-- -- Firewolf Website Browser -- Made by GravityScore and 1lann -- License found here: https://raw.github.com/1lann/Firewolf/master/LICENSE -- -- Original Concept From RednetExplorer 2.4.1 -- RednetExplorer Made by ComputerCraftFan11 -- -- -------- Variables -- Version local version = "2.5" local build = 36 local browserAgent = "Firewolf " .. version local tArgs = {...} -- Server Identification local serverID = "other" local serverList = {experimental = "Experimental", other = "Other"} -- Updating local autoupdate = "true" local noInternet = false -- Resources local graphics = {} local files = {} local w, h = term.getSize() -- Debugging local debugFile = nil -- Environment local oldEnv = {} local env = {} local api = {} local override = {} local antivirus = {} -- Themes local theme = {} -- Databases local blacklist = {} local whitelist = {} local dnsDatabase = {{}, {}} -- Website Loading local pages = {} local errorPages = {} local website = "" local homepage = "" local timeout = 0.2 local loadingRate, loadingClock = 0, nil local openAddressBar, clickableAddressBar = true, true local menuBarOpen = false local offsetclick = true local websiteerror = nil -- Tabs local tabs = {} local filters = {} local currentTab = 1 -- Protocols local curProtocol = {} local protocols = {} -- History local addressBarHistory = {} -- Events local event_load = "firewolf_websiteLoadEvent" local event_redirect = "firewolf_redirectEvent" local event_error = "firewolf_siteErrorEvent" local event_exit = "firewolf_exitEvent" -- Download URLs local firewolfURL = "https://raw.github.com/1lann/Firewolf/master/entities/other.lua" local serverURL = "https://raw.github.com/1lann/Firewolf/master/server/server-release.lua" local buildURL = "https://raw.github.com/1lann/Firewolf/master/build" -- Data Locations local rootFolder = "/.Firewolf_Data" local cacheFolder = rootFolder .. "/cache" local serverFolder = rootFolder .. "/servers" local websiteDataFolder = rootFolder .. "/website_data" local themeLocation = rootFolder .. "/theme" local serverLocation = rootFolder .. "/server_software" local settingsLocation = rootFolder .. "/settings" local debugLogLocation = "/firewolf-log" local firewolfLocation = "/" .. shell.getRunningProgram() local userBlacklist = rootFolder .. "/user_blacklist" local userWhitelist = rootFolder .. "/user_whitelist" local function isAdvanced() return term.isColor and term.isColor() end local function modemPresent() if curProtocol == protocols.rdnt then for _, v in pairs(rs.getSides()) do if peripheral.getType(v) == "modem" then rednet.open(v) return true end end else return true end return false end -- -------- Utilities local function debugLog(n, ...) local lArgs = {...} if debugFile then if not n then return end debugFile:write("\n" .. tostring(n) .. " : ") for k, v in pairs(lArgs) do if type(v) == "string" or type(v) == "number" or not type(v) or type(v) == "boolean" then debugFile:write(tostring(v) .. ", ") else debugFile:write("type-" .. type(v) .. ", ") end end end end local function clear(site, background, drawmenu) local titles = { ["firewolf"] = "Firewolf", ["server/rdnt"] = "Server Management", ["server/http"] = "Server Management", ["help"] = "Help", ["settings"] = "Settings", ["credits"] = "Credits", ["crash"] = "Crashed!", ["overspeed"] = "Too Fast!" } local title = titles[site] or "" term.setBackgroundColor(background or colors.black) term.setTextColor(colors[theme["address-bar-text"]]) if drawmenu ~= true then term.clear() end if not menuBarOpen then term.setBackgroundColor(colors[theme["address-bar-background"]]) term.setCursorPos(2, 1) term.clearLine() if site:len() > w - 10 then site = site:sub(1, 38) .. "..." end if curProtocol == protocols.http then write("http://" .. site) else write("rdnt://" .. site) end term.setCursorPos(w - title:len() - 1, 1) write(title) if isAdvanced() then term.setCursorPos(w, 1) term.setBackgroundColor(colors[theme["top-box"]]) term.setTextColor(colors[theme["text-color"]]) write("<") end term.setBackgroundColor(background or colors.black) term.setTextColor(colors.white) else term.setCursorPos(1, 1) term.setBackgroundColor(colors[theme["top-box"]]) term.setTextColor(colors[theme["text-color"]]) term.clearLine() write("> [- Exit Firewolf -] ") end print("") end local function modRead(properties) local w, h = term.getSize() local defaults = {replaceChar = nil, history = nil, visibleLength = nil, textLength = nil, liveUpdates = nil, exitOnKey = nil} if not properties then properties = {} end for k, v in pairs(defaults) do if not properties[k] then properties[k] = v end end if properties.replaceChar then properties.replaceChar = properties.replaceChar:sub(1, 1) end if not properties.visibleLength then properties.visibleLength = w end local sx, sy = term.getCursorPos() local line = "" local pos = 0 local historyPos = nil local function redraw(repl) local scroll = 0 if properties.visibleLength and sx + pos > properties.visibleLength + 1 then scroll = (sx + pos) - (properties.visibleLength + 1) end term.setCursorPos(sx, sy) local a = repl or properties.replaceChar if a then term.write(string.rep(a, line:len() - scroll)) else term.write(line:sub(scroll + 1, -1)) end term.setCursorPos(sx + pos - scroll, sy) end local function sendLiveUpdates(event, ...) if type(properties.liveUpdates) == "function" then local ox, oy = term.getCursorPos() local a, data = properties.liveUpdates(line, event, ...) if a == true and not data then term.setCursorBlink(false) return line elseif a == true and data then term.setCursorBlink(false) return data end term.setCursorPos(ox, oy) end end local a = sendLiveUpdates("delete") if a then return a end term.setCursorBlink(true) while true do local e, but, x, y, p4, p5 = os.pullEvent() if e == "char" then local s = false if properties.textLength and line:len() < properties.textLength then s = true elseif not properties.textLength then s = true end local canType = true if not properties.grantPrint and properties.refusePrint then local canTypeKeys = {} if type(properties.refusePrint) == "table" then for _, v in pairs(properties.refusePrint) do table.insert(canTypeKeys, tostring(v):sub(1, 1)) end elseif type(properties.refusePrint) == "string" then for char in properties.refusePrint:gmatch(".") do table.insert(canTypeKeys, char) end end for _, v in pairs(canTypeKeys) do if but == v then canType = false end end elseif properties.grantPrint then canType = false local canTypeKeys = {} if type(properties.grantPrint) == "table" then for _, v in pairs(properties.grantPrint) do table.insert(canTypeKeys, tostring(v):sub(1, 1)) end elseif type(properties.grantPrint) == "string" then for char in properties.grantPrint:gmatch(".") do table.insert(canTypeKeys, char) end end for _, v in pairs(canTypeKeys) do if but == v then canType = true end end end if s and canType then line = line:sub(1, pos) .. but .. line:sub(pos + 1, -1) pos = pos + 1 redraw() end elseif e == "key" then if but == keys.enter then break elseif but == keys.left then if pos > 0 then pos = pos - 1 redraw() end elseif but == keys.right then if pos < line:len() then pos = pos + 1 redraw() end elseif (but == keys.up or but == keys.down) and properties.history and #properties.history > 0 then redraw(" ") if but == keys.up then if not historyPos and #properties.history > 0 then historyPos = #properties.history elseif historyPos > 1 then historyPos = historyPos - 1 end elseif but == keys.down then if historyPos == #properties.history then historyPos = nil elseif historyPos then historyPos = historyPos + 1 end end if properties.history and historyPos then line = properties.history[historyPos] pos = line:len() else line = "" pos = 0 end redraw() local a = sendLiveUpdates("history") if a then return a end elseif but == keys.backspace and pos > 0 then redraw(" ") line = line:sub(1, pos - 1) .. line:sub(pos + 1, -1) pos = pos - 1 redraw() local a = sendLiveUpdates("delete") if a then return a end elseif but == keys.home then pos = 0 redraw() elseif but == keys.delete and pos < line:len() then redraw(" ") line = line:sub(1, pos) .. line:sub(pos + 2, -1) redraw() local a = sendLiveUpdates("delete") if a then return a end elseif but == keys["end"] then pos = line:len() redraw() elseif properties.exitOnKey then if but == properties.exitOnKey or (properties.exitOnKey == "control" and (but == 29 or but == 157)) then term.setCursorBlink(false) return nil end end end local a = sendLiveUpdates(e, but, x, y, p4, p5) if a then return a end end term.setCursorBlink(false) if line then line = line:gsub("^%s*(.-)%s*$", "%1") end return line end -- -------- API -- Drawing local function printWithType(t, func) if type(t) == "table" then for _, v in pairs(t) do env.pcall(function() printWithType(v, func) end) end else func(tostring(t)) end end api.centerWrite = function(text) printWithType(text, function(t) local x, y = term.getCursorPos() term.setCursorPos(math.ceil((w + 1)/2 - t:len()/2), y) write(t) end) end api.centerPrint = function(text) printWithType(text, function(t) local x, y = term.getCursorPos() term.setCursorPos(math.ceil((w + 2)/2 - t:len()/2), y) print(t) end) end api.leftWrite = function(text) printWithType(text, function(t) local x, y = term.getCursorPos() term.setCursorPos(1, y) write(t) end) end api.leftPrint = function(text) printWithType(text, function(t) local x, y = term.getCursorPos() term.setCursorPos(1, y) print(t) end) end api.rightWrite = function(text) printWithType(text, function(t) local x, y = term.getCursorPos() term.setCursorPos(w - t:len() + 1, y) write(t) end) end api.rightPrint = function(text) printWithType(text, function(t) local x, y = term.getCursorPos() term.setCursorPos(w - t:len() + 1, y) print(t) end) end api.clearArea = function() term.clear() term.setCursorPos(1, 1) end api.cPrint = function(text) api.centerPrint(text) end api.cWrite = function(text) api.centerWrite(text) end api.lPrint = function(text) api.leftPrint(text) end api.lWrite = function(text) api.leftWrite(text) end api.rPrint = function(text) api.rightPrint(text) end api.rWrite = function(text) api.rightWrite(text) end -- Server Interation api.loadFileFromServer = function(path) if type(path) ~= "string" then error("expected string", 2) end sleep(0.05) if path:sub(1, 1) == "/" then path = path:sub(2, -1) end local id, content = curProtocol.getWebsite(website .. "/" .. path) if id then return content end return nil end api.ioReadFileFromServer = function(path) local content = api.loadFileFromServer(path) if content then local f = env.io.open(rootFolder .. "/temp_file", "w") f:write(content) f:close() return env.io.open(rootFolder .. "/temp_file", "r") end return nil end api.loadImageFromServer = function(path) local content = api.loadFileFromServer(path) if content then local f = env.io.open(rootFolder .. "/temp_file", "w") f:write(content) f:close() local image = paintutils.loadImage(rootFolder .. "/temp_file") env.fs.delete("/temp_file") return image end return nil end api.writeDataFile = function(path, content) if type(path) ~= "string" or type(content) ~= "string" then error("expected string, string", 2) end if path:sub(1, 1) == "/" then path = path:sub(2, -1) end local dataPath = websiteDataFolder .. "/" .. path:gsub("/", "$slazh$") if env.fs.isReadOnly(dataPath) then return false end if env.fs.exists(dataPath) then env.fs.delete(dataPath) end local f = env.io.open(dataPath, "w") if not f then return false end f:write(content) f:close() return true end api.readDataFile = function(path) if type(path) ~= "string" then error("readDataFile: expected string") end if path:sub(1, 1) == "/" then path = path:sub(2, -1) end local dataPath = websiteDataFolder .. "/" .. path:gsub("/", "$slazh$") if env.fs.isDir(dataPath) then env.fs.delete(dataPath) end if env.fs.exists(dataPath) then local f = env.io.open(dataPath, "r") local cont = f:read("*a") f:close() return cont end return nil end api.saveFileToUserComputer = function(content) if type(content) ~= "string" then error("expected string", 2) end local oldback, oldtext = override.term.getBackgroundColor(), override.term.getTextColor() local ox, oy = term.getCursorPos() term.setTextColor(colors[theme["text-color"]]) term.setBackgroundColor(colors[theme["background"]]) term.clear() term.setCursorPos(1, 1) term.setBackgroundColor(colors[theme["top-box"]]) print("") leftPrint(string.rep(" ", 20)) leftPrint(" Save File Request ") leftPrint(string.rep(" ", 20)) print("") term.setBackgroundColor(colors[theme["bottom-box"]]) for i = 1, 11 do rightPrint(string.rep(" ", 36)) end term.setCursorPos(1, 7) rightPrint("The website: ") rightPrint(website .. " ") rightPrint("Is requesting to save a file ") rightPrint("to your computer. ") local ret = nil local opt = prompt({{"Save File", w - 16, 12}, {"Cancel", w - 13, 13}}, "vertical") if opt == "Save File" then while not ret do term.setCursorPos(1, 15) rightWrite(string.rep(" ", 36)) term.setCursorPos(w - 34, 15) write("Path: /") local p = read() term.setCursorPos(1, 15) rightWrite(string.rep(" ", 36)) if p == "" then rightWrite("Cancelled ") break elseif fs.exists("/" .. p) then rightWrite("File Already Exists! ") else rightWrite("File Saved! ") ret = "/" .. p local f = env.io.open(ret, "w") f:write(content) f:close() end openAddressBar = false sleep(1.3) openAddressBar = true end elseif opt == "Cancel" then term.setCursorPos(1, 15) rightWrite("Saving Cancelled! ") end openAddressBar = false sleep(1.3) openAddressBar = true term.setBackgroundColor(oldback or colors.black) term.setTextColor(oldtext or colors.white) term.clear() term.setCursorPos(ox, oy) return ret end api.urlDownload = function(url) if type(url) ~= "string" then error("expected string", 2) end local source = nil http.request(url) local a = os.startTimer(10) while true do local e, surl, handle = os.pullEvent() if e == "http_success" then source = handle.readAll() break elseif e == "http_failure" or (e == "timer" and surl == a) then break end end if type(source) == "string" then return api.saveFileToUserComputer(source) else return nil end end api.pastebinDownload = function(code) return api.urlDownload("http://pastebin.com/raw.php?i=" .. tostring(code)) end -- Redirection api.redirect = function(url) if type(url) ~= "string" then url = "home" end os.queueEvent(event_redirect, url:gsub("rdnt://"):gsub("http://")) error() end -- Theme api.themeColor = function(tag) if type(tag) ~= "string" then error("themeColor: expected string") end return colors[theme[tag] or defaultTheme[tag] or "white"] end api.themeColour = function(tag) return api.themeColor(tag) end -- Prompt api.prompt = function(list, dir) if isAdvanced() then for _, v in pairs(list) do if v.bg then term.setBackgroundColor(v.bg) end if v.tc then term.setTextColor(v.tc) end if v[2] == -1 then v[2] = math.ceil((w + 1)/2 - (v[1]:len() + 6)/2) end term.setCursorPos(v[2], v[3]) write("[- " .. v[1]) term.setCursorPos(v[2] + v[1]:len() + 3, v[3]) write(" -]") end while true do local e, but, x, y = os.pullEvent() if e == "mouse_click" then for _, v in pairs(list) do if x >= v[2] and x <= v[2] + v[1]:len() + 5 and y + (v.coffset or 0) == v[3] then return v[1] end end end end else for _, v in pairs(list) do term.setBackgroundColor(colors.black) term.setTextColor(colors.white) if v[2] == -1 then v[2] = math.ceil((w + 1)/2 - (v[1]:len() + 4)/2) end term.setCursorPos(v[2], v[3]) write(" " .. v[1]) term.setCursorPos(v[2] + v[1]:len() + 2, v[3]) write(" ") end local key1 = dir == "horizontal" and 203 or 200 local key2 = dir == "horizontal" and 205 or 208 local curSel = 1 term.setCursorPos(list[curSel][2], list[curSel][3]) write("[") term.setCursorPos(list[curSel][2] + list[curSel][1]:len() + 3, list[curSel][3]) write("]") while true do local e, key = os.pullEvent("key") term.setCursorPos(list[curSel][2], list[curSel][3]) write(" ") term.setCursorPos(list[curSel][2] + list[curSel][1]:len() + 3, list[curSel][3]) write(" ") if key == key1 and curSel > 1 then curSel = curSel - 1 elseif key == key2 and curSel < #list then curSel = curSel + 1 elseif key == 28 then return list[curSel][1] end term.setCursorPos(list[curSel][2], list[curSel][3]) write("[") term.setCursorPos(list[curSel][2] + list[curSel][1]:len() + 3, list[curSel][3]) write("]") end end end api.scrollingPrompt = function(list, x, y, len, width, coffset) local wid = width if not wid then wid = w - 3 end local function updateDisplayList(items, loc, len) local ret = {} for i = 1, len do local item = items[i + loc - 1] if item then table.insert(ret, item) end end return ret end if isAdvanced() then local function draw(a) for i, v in ipairs(a) do term.setCursorPos(x, y + i - 1) write(string.rep(" ", wid)) term.setCursorPos(x, y + i - 1) write("[ " .. v:sub(1, wid - 5)) term.setCursorPos(wid + x - 2, y + i - 1) write(" ]") end end local loc = 1 local disList = updateDisplayList(list, loc, len) draw(disList) while true do local e, but, clx, cly = os.pullEvent() if e == "key" and but == 200 and loc > 1 then loc = loc - 1 disList = updateDisplayList(list, loc, len) draw(disList) elseif e == "key" and but == 208 and loc + len - 1 < #list then loc = loc + 1 disList = updateDisplayList(list, loc, len) draw(disList) elseif e == "mouse_scroll" and but > 0 and loc + len - 1 < #list then loc = loc + but disList = updateDisplayList(list, loc, len) draw(disList) elseif e == "mouse_scroll" and but < 0 and loc > 1 then loc = loc + but disList = updateDisplayList(list, loc, len) draw(disList) elseif e == "mouse_click" then for i, v in ipairs(disList) do if clx >= x and clx <= x + wid and cly + coffset == i + y - 1 then return v end end end end else local function draw(a) for i, v in ipairs(a) do term.setCursorPos(x, y + i - 1) write(string.rep(" ", wid)) term.setCursorPos(x, y + i - 1) write("[ ] " .. v:sub(1, wid - 5)) end end local loc = 1 local curSel = 1 local disList = updateDisplayList(list, loc, len) draw(disList) term.setCursorPos(x + 1, y + curSel - 1) write("x") while true do local e, key = os.pullEvent() term.setCursorPos(x + 1, y + curSel - 1) write(" ") if e == "key" and key == 200 then if curSel > 1 then curSel = curSel - 1 elseif loc > 1 then loc = loc - 1 disList = updateDisplayList(list, loc, len) draw(disList) end elseif e == "key" and key == 208 then if curSel < #disList then curSel = curSel + 1 elseif loc + len - 1 < #list then loc = loc + 1 disList = updateDisplayList(list, loc, len) draw(disList) end elseif e == "key" and key == 28 then return list[curSel + loc - 1] end term.setCursorPos(x + 1, y + curSel - 1) write("x") end end end -- Set Environment for k, v in pairs(getfenv(0)) do env[k] = v end for k, v in pairs(getfenv(1)) do env[k] = v end for k, v in pairs(env) do oldEnv[k] = v end for k, v in pairs(api) do env[k] = v end -- -------- Override for k, v in pairs(env) do override[k] = v end local curtext, curbackground = colors.white, colors.black override.term = {} for k, v in pairs(env.term) do override.term[k] = v end override.os = {} for k, v in pairs(env.os) do override.os[k] = v end override.term.getSize = function() local a, b = env.term.getSize() return a, b - 2 end override.term.setCursorPos = function(x, y) if y < 1 then return env.term.setCursorPos(x, 2) else return env.term.setCursorPos(x, y + 1) end end override.term.getCursorPos = function() local x, y = env.term.getCursorPos() return x, y - 1 end override.term.getBackgroundColor = function() return curbackground end override.term.getBackgroundColour = function() return override.term.getBackgroundColor() end override.term.setBackgroundColor = function(col) curbackground = col return env.term.setBackgroundColor(col) end override.term.setBackgroundColour = function(col) return override.term.setBackgroundColor(col) end override.term.getTextColor = function() return curtext end override.term.getTextColour = function() return override.term.getTextColor() end override.term.setTextColor = function(col) curtext = col return env.term.setTextColor(col) end override.term.setTextColour = function(col) return override.term.setTextColor(col) end override.term.clear = function() local x, y = term.getCursorPos() local oldbackground = override.term.getBackgroundColor() local oldtext = override.term.getTextColor() clear(website, curbackground) term.setBackgroundColor(oldbackground) term.setTextColor(oldtext) term.setCursorPos(x, y) end override.term.scroll = function(n) local x, y = term.getCursorPos() local oldbackground = override.term.getBackgroundColor() local oldtext = override.term.getTextColor() env.term.scroll(n) clear(website, curbackground, true) term.setBackgroundColor(oldbackground) term.setTextColor(oldtext) term.setCursorPos(x, y) end override.term.isColor = function() return isAdvanced() end override.term.isColour = function() return override.term.isColor() end override.os.queueEvent = function(event, ...) if event == "terminate" or event == event_exit then return end if event == event_error and not websiteerror then return end env.os.queueEvent(event, ...) end override.prompt = function(list, dir) local a = {} for k, v in pairs(list) do table.insert(a, {v[1], v[2], v[3] + 1, tc = v.tc or curtext, bg = v.bg or curbackground, coffset = 1}) end return env.prompt(a, dir) end override.scrollingPrompt = function(list, x, y, len, width) return env.scrollingPrompt(list, x, y + 1, len, width, 1) end local barTerm = {} for k, v in pairs(override.term) do barTerm[k] = v end barTerm.clear = override.term.clear barTerm.scroll = override.term.scroll local safeTerm = {} for k, v in pairs(term) do safeTerm[k] = v end override.showBar = function() offsetclick, clickableAddressBar = true, true return os.pullEvent, barTerm end override.hideBar = function() offsetclick, clickableAddressBar = false, false return os.pullEvent, safeTerm end setfenv(api.saveFileToUserComputer, override) -- -------- Antivirus local antivirusOverrides = { ["Run Files"] = {"shell.run", "os.run"}, ["Modify System"] = {"shell.setAlias", "shell.clearAlias", "os.setComputerLabel", "shell.setDir", "shell.setPath"}, ["Modify Files"] = {"fs.makeDir", "fs.move", "fs.copy", "fs.delete", "fs.open", "io.open", "io.write", "io.read", "io.close"}, ["Shutdown Computer"] = {"os.shutdown", "os.reboot", "shell.exit"} } local antivirusDestroy = { "rawset", "rawget", "setfenv", "loadfile", "loadstring", "dofile", "getfenv" } local function triggerAntivirus(offence, onlyCancel) local oldback, oldtext = curbackground, curtext local ox, oy = term.getCursorPos() openAddressBar = false term.setBackgroundColor(colors[theme["address-bar-background"]]) term.setTextColor(colors[theme["address-bar-text"]]) term.setCursorPos(2, 1) term.clearLine() write("Request: " .. offence) term.setCursorPos(w - 8, 1) write("[C]ancel") if not onlyCancel then term.setCursorPos(w - 16, 1) write("[A]llow") end offsetclick = false local stat = "" while true do local e, but, x, y = env.os.pullEvent() if e == "mouse_click" and y == 1 then if x >= w - 8 and x <= w - 1 then stat = "cancel" elseif not onlyCancel and x >= w - 16 and x <= w - 9 then stat = "allow" end elseif e == "char" and but == "c" then stat = "cancel" elseif e == "char" and not onlyCancel and but == "a" then stat = "allow" end if stat ~= "" then break end end offsetclick = true clear(website, nil, true) term.setTextColor(colors.white) term.setBackgroundColor(colors.black) term.setCursorPos(ox, oy) term.setBackgroundColor(oldback) term.setTextColor(oldtext) if not onlyCancel and stat == "allow" then -- To prevent the menu bar from opening os.queueEvent("firewolf_requiredEvent") os.pullEvent() openAddressBar = true return true elseif stat == "cancel" then openAddressBar = true redirect("home") end end for k, v in pairs(override) do antivirus[k] = v end antivirus.shell = {} for k, v in pairs(override.shell) do antivirus.shell[k] = v end antivirus.os = {} for k, v in pairs(override.os) do antivirus.os[k] = v end antivirus.fs = {} for k, v in pairs(override.fs) do antivirus.fs[k] = v end antivirus.io = {} for k, v in pairs(override.io) do antivirus.io[k] = v end for warning, v in pairs(antivirusOverrides) do for k, func in pairs(v) do if func:find(".", 1, true) then -- Functions in another table local table = func:sub(1, func:find(".", 1, true) - 1) local funcname = func:sub(func:find(".", 1, true) + 1, -1) antivirus[table][funcname] = function(...) env.setfenv(triggerAntivirus, env) if triggerAntivirus(warning) then return override[table][funcname](...) end end else -- Plain functions antivirus[func] = function(...) env.setfenv(triggerAntivirus, env) if triggerAntivirus(warning) then return override[func](...) end end end end end for k, v in pairs(antivirusDestroy) do antivirus[v] = function(...) env.setfenv(triggerAntivirus, env) triggerAntivirus("Destory your System! D:", true) return nil end end antivirus.pcall = function(...) local suc, err = env.pcall(...) if err:lower():find("terminate") then error("terminate") end return suc, err end -- -------- Themes local defaultTheme = { ["address-bar-text"] = "white", ["address-bar-background"] = "gray", ["address-bar-base"] = "lightGray", ["top-box"] = "red", ["bottom-box"] = "orange", ["text-color"] = "white", ["background"] = "gray" } local originalTheme = { ["address-bar-text"] = "white", ["address-bar-background"] = "black", ["address-bar-base"] = "black", ["top-box"] = "black", ["bottom-box"] = "black", ["text-color"] = "white", ["background"] = "black" } local function loadTheme(path) if fs.exists(path) and not fs.isDir(path) then local a = {} local f = io.open(path, "r") local l = f:read("*l") while l do l = l:gsub("^%s*(.-)%s*$", "%1") if l and l ~= "" and l ~= "\n" and l:sub(1, 2) ~= "--" then local k, v = string.match(l, "^(%a+)=(%a+)") if k and v then a[k] = v else return nil end end l = f:read("*l") end f:close() return a end return nil end -- -------- Filesystem local function download(url, path) for i = 1, 3 do local response = http.get(url) if response then local data = response.readAll() response.close() if path then local f = io.open(path, "w") f:write(data) f:close() end return true end end return false end local function updateClient() local skipNormal = false if serverID ~= "experimental" then http.request(buildURL) local a = os.startTimer(10) while true do local e, url, handle = os.pullEvent() if e == "http_success" then local b = handle.readAll():gsub("^%s*(.-)%s*$", "%1") if not tonumber(b) or tonumber(b) > build then break else return false end elseif e == "http_failure" or (e == "timer" and url == a) then skipNormal = true break end end end local source = nil if not skipNormal then local _, y = term.getCursorPos() term.setCursorPos(1, y - 2) rightWrite(string.rep(" ", 32)) rightWrite("Updating Firewolf... ") http.request(firewolfURL) local a = os.startTimer(10) while true do local e, url, handle = os.pullEvent() if e == "http_success" then source = handle break elseif e == "http_failure" or (e == "timer" and url == a) then break end end end if not source then if isAdvanced() then term.setTextColor(colors[theme["text-color"]]) term.setBackgroundColor(colors[theme["background"]]) term.clear() if not fs.exists(rootFolder) then fs.makeDir(rootFolder) end local f = io.open(rootFolder .. "/temp_file", "w") f:write(graphics.githubImage) f:close() local a = paintutils.loadImage(rootFolder .. "/temp_file") paintutils.drawImage(a, 5, 5) sleep(0.2) fs.delete(rootFolder .. "/temp_file") term.setCursorPos(19, 4) term.setBackgroundColor(colors[theme["top-box"]]) write(string.rep(" ", 32)) term.setCursorPos(19, 5) write(" Could Not Connect to GitHub! ") term.setCursorPos(19, 6) write(string.rep(" ", 32)) term.setBackgroundColor(colors[theme["bottom-box"]]) term.setCursorPos(19, 8) write(string.rep(" ", 32)) term.setCursorPos(19, 9) write(" Sorry, Firewolf could not ") term.setCursorPos(19, 10) write(" connect to GitHub to download ") term.setCursorPos(19, 11) write(" necessary files. Please check: ") term.setCursorPos(19, 12) write(" http://status.github.com ") term.setCursorPos(19, 13) write(string.rep(" ", 32)) term.setCursorPos(19, 14) write(" Click to exit... ") term.setCursorPos(19, 15) write(string.rep(" ", 32)) else term.clear() term.setCursorPos(1, 1) term.setBackgroundColor(colors.black) term.setTextColor(colors.white) print("\n") centerPrint("Could not connect to GitHub!") print("") centerPrint("Sorry, Firewolf could not connect to") centerPrint("GitHub to download necessary files.") centerPrint("Please check:") centerPrint("http://status.github.com") print("") centerPrint("Press any key to exit...") end while true do local e = os.pullEvent() if e == "mouse_click" or e == "key" then break end end return false elseif source and autoupdate == "true" then local b = io.open(firewolfLocation, "r") local new = source.readAll() local cur = b:read("*a") source.close() b:close() if cur ~= new then fs.delete(firewolfLocation) local f = io.open(firewolfLocation, "w") f:write(new) f:close() return true else return false end end end local function resetFilesystem() -- Migrate fs.delete(rootFolder .. "/available_themes") fs.delete(rootFolder .. "/default_theme") -- Reset if not fs.exists(rootFolder) then fs.makeDir(rootFolder) elseif not fs.isDir(rootFolder) then fs.move(rootFolder, "/Firewolf_Data.old") end for _, v in pairs({serverFolder, cacheFolder, websiteDataFolder}) do if not fs.isDir(v) then fs.delete(v) end if not fs.exists(v) then fs.makeDir(v) end end if fs.isDir(settingsLocation) then fs.delete(settingsLocation) end if fs.isDir(serverLocation) then fs.delete(serverLocation) end if not fs.exists(settingsLocation) then local f = io.open(settingsLocation, "w") f:write(textutils.serialize({auto = "true", incog = "false", home = "firewolf"})) f:close() end if not fs.exists(serverLocation) then download(serverURL, serverLocation) end fs.delete(rootFolder .. "/temp_file") for _, v in pairs({userWhitelist, userBlacklist}) do if fs.isDir(v) then fs.delete(v) end if not fs.exists(v) then local f = io.open(v, "w") f:write("") f:close() end end end local function checkForModem(display) while true do local present = false for _, v in pairs(rs.getSides()) do if peripheral.getType(v) == "modem" then rednet.open(v) present = true break end end if not present and type(display) == "function" then display() os.pullEvent("peripheral") else return true end end end -- -------- Databases local function loadDatabases() if fs.exists(userBlacklist) and not fs.isDir(userBlacklist) then local bf = io.open(userBlacklist, "r") local l = bf:read("*l") while l do if l and l ~= "" and l ~= "\n" then l = l:gsub("^%s*(.-)%s*$", "%1") table.insert(blacklist, l) end l = bf:read("*l") end bf:close() end if fs.exists(userWhitelist) and not fs.isDir(userWhitelist) then local wf = io.open(userWhitelist, "r") local l = wf:read("*l") while l do if l and l ~= "" and l ~= "\n" then l = l:gsub("^%s*(.-)%s*$", "%1") local a, b = l:find("| |") table.insert(whitelist, {l:sub(1, a - 1), l:sub(b + 1, -1)}) end l = wf:read("*l") end wf:close() end end local function verifyBlacklist(id) for _, v in pairs(blacklist) do if tostring(id) == v then return true end end return false end local function verifyWhitelist(id, url) for _, v in pairs(whitelist) do if v[2] == tostring(id) and v[1] == tostring(url) then return true end end return false end -- -------- Graphics and Files graphics.githubImage = [[ f f fffffffff fffffffff f4244424f f4444444f fffffefffe fffe e fffff e ff f fe e e e ]] graphics.nomodem = function() term.setTextColor(colors[theme["text-color"]]) term.setBackgroundColor(colors[theme["background"]]) term.clear() term.setCursorPos(1, 1) print("\n") term.setBackgroundColor(colors[theme["top-box"]]) api.leftPrint(string.rep(" ", 24)) api.leftPrint(" No Modem Attached! D: ") api.leftPrint(string.rep(" ", 24)) print("\n") term.setBackgroundColor(colors[theme["bottom-box"]]) api.rightPrint(string.rep(" ", 40)) api.rightPrint(" No wireless modem was found on this ") api.rightPrint(" computer, and Firewolf cannot use the ") api.rightPrint(" RDNT protocol without one! ") api.rightPrint(string.rep(" ", 40)) api.rightPrint(" Waiting for a modem to be attached... ") api.rightPrint(string.rep(" ", 40)) end graphics.nonexistantwebpage = function() term.setBackgroundColor(colors[theme["background"]]) term.clear() term.setCursorPos(1, 2) term.setTextColor(colors[theme["text-color"]]) term.setBackgroundColor(colors[theme["top-box"]]) leftPrint(string.rep(" ", 11)) leftPrint(" Oh Noes! ") leftPrint(string.rep(" ", 11)) print("\n") term.setBackgroundColor(colors[theme["bottom-box"]]) rightPrint(string.rep(" ", 43)) rightPrint([[ ______ __ ]]) rightPrint([[ / ____/_____ _____ ____ _____ / / ]]) rightPrint([[ / __/ / ___// ___// __ \ / ___// / ]]) rightPrint([[ / /___ / / / / / /_/ // / /_/ ]]) rightPrint([[ /_____//_/ /_/ \____//_/ (_) ]]) rightPrint(string.rep(" ", 43)) rightPrint(" Could not connect to the website! It may ") rightPrint(" be down, or not exist! ") rightPrint(string.rep(" ", 43)) end graphics.nosearchresults = function() term.setBackgroundColor(colors[theme["background"]]) term.clear() term.setCursorPos(1, 5) term.setTextColor(colors[theme["text-color"]]) term.setBackgroundColor(colors[theme["top-box"]]) centerPrint(string.rep(" ", 40)) centerPrint(" No Websites are Currently Online! D: ") centerPrint(string.rep(" ", 40)) centerPrint(" Why not make one yourself? ") centerPrint(" Visit rdnt://server! ") centerPrint(string.rep(" ", 40)) end files.availableThemes = [[ https://raw.github.com/1lann/firewolf/master/themes/default.txt| |Fire (default) https://raw.github.com/1lann/firewolf/master/themes/ice.txt| |Ice https://raw.github.com/1lann/firewolf/master/themes/carbon.txt| |Carbon https://raw.github.com/1lann/firewolf/master/themes/christmas.txt| |Christmas https://raw.github.com/1lann/firewolf/master/themes/original.txt| |Original https://raw.github.com/1lann/firewolf/master/themes/ocean.txt| |Ocean https://raw.github.com/1lann/firewolf/master/themes/forest.txt| |Forest https://raw.github.com/1lann/firewolf/master/themes/pinky.txt| |Pinky https://raw.github.com/1lann/firewolf/master/themes/azhftech.txt| |AzhfTech ]] files.newTheme = [[ -- Address bar text color address-bar-text= -- Address bar background color address-bar-background= -- Color of separator bar on live search dropdown address-bar-base= -- Top box background color top-box= -- Bottom box background color bottom-box= -- Main background color background= -- Main text color text-color= ]] -- -------- Protocols protocols.rdnt = {} protocols.http = {} protocols.rdnt.getSearchResults = function() dnsDatabase = {[1] = {}, [2] = {}} local resultIDs = {} local conflict = {} rednet.broadcast("firewolf.broadcast.dns.list") local startClock = os.clock() while os.clock() - startClock < timeout do local id, i = rednet.receive(timeout) if id then if i:sub(1, 14) == "firewolf-site:" then i = i:sub(15, -1) local bl, wl = verifyBlacklist(id), verifyWhitelist(id, i) if not i:find(" ") and i:len() < 40 and (not bl or (bl and wl)) then if not resultIDs[tostring(id)] then resultIDs[tostring(id)] = 1 else resultIDs[tostring(id)] = resultIDs[tostring(id)] + 1 end if not i:find("rdnt://") then i = ("rdnt://" .. i) end local x = false if conflict[i] then x = true table.insert(conflict[i], id) else for m, n in pairs(dnsDatabase[1]) do if n:lower() == i:lower() then x = true table.remove(dnsDatabase[1], m) table.remove(dnsDatabase[2], m) if conflict[i] then table.insert(conflict[i], id) else conflict[i] = {} table.insert(conflict[i], id) end break end end end if not x and resultIDs[tostring(id)] <= 3 then table.insert(dnsDatabase[1], i) table.insert(dnsDatabase[2], id) end end end else break end end for k, v in pairs(conflict) do table.sort(v) table.insert(dnsDatabase[1], k) table.insert(dnsDatabase[2], v[1]) end end protocols.rdnt.getWebsite = function(site) local id, content, status = nil, nil, nil local clock = os.clock() local websiteID = nil for k, v in pairs(dnsDatabase[1]) do local web = site:gsub("rdnt://", "") if web:find("/") then web = web:sub(1, web:find("/") - 1) end if web == v:gsub("rdnt://", "") then websiteID = dnsDatabase[2][k] break end end if not websiteID then return nil, nil, nil end sleep(timeout) rednet.send(websiteID, site) clock = os.clock() while os.clock() - clock < timeout do id, content = rednet.receive(timeout) if id and id == websiteID then local bl, wl = verifyBlacklist(id), verifyWhitelist(id, site) status = nil if (bl and not wl) or site == "" or site == "." or site == ".." then -- Ignore elseif wl then status = "whitelist" break else status = "safe" break end end end return id, content, status end protocols.http.getSearchResults = function() dnsDatabase = {[1] = {}, [2] = {}} end protocols.http.getWebsite = function(site) return nil, nil, nil end -- -------- Homepage pages["firewolf"] = function() term.setBackgroundColor(colors[theme["background"]]) term.clear() term.setTextColor(colors[theme["text-color"]]) term.setBackgroundColor(colors[theme["top-box"]]) print("") leftPrint(string.rep(" ", 42)) leftPrint([[ _,-='"-.__ /\_/\ ]]) leftPrint([[ -.} =._,.-==-._., @ @._, ]]) leftPrint([[ -.__ __,-. ) _,.-' ]]) leftPrint([[ Firewolf ]] .. version .. string.rep(" ", 8 - version:len()) .. [[" G..m-"^m m' ]]) leftPrint(string.rep(" ", 42)) print("\n") term.setBackgroundColor(colors[theme["bottom-box"]]) rightPrint(string.rep(" ", 42)) if isAdvanced() then rightPrint(" News: [- Sites -] ") else rightPrint(" News: ") end rightPrint(" Firewolf 2.5 is out! It rewrites the ") rightPrint(" whole Firewolf's internals (again :P) ") rightPrint(string.rep(" ", 42)) rightPrint(" Firewolf 3.0 will be out soon! It will ") rightPrint(" bring the long awaited HTTP support! ") rightPrint(string.rep(" ", 42)) while true do local e, but, x, y = os.pullEvent() if e == "mouse_click" and x >= 40 and x <= 50 and y == 11 then redirect("sites") end end end pages["sites"] = function() term.setBackgroundColor(colors[theme["background"]]) term.clear() term.setTextColor(colors[theme["text-color"]]) term.setBackgroundColor(colors[theme["top-box"]]) print("\n") leftPrint(string.rep(" ", 17)) leftPrint(" Built-In Sites ") leftPrint(string.rep(" ", 17)) local sx = 8 term.setBackgroundColor(colors[theme["bottom-box"]]) term.setCursorPos(1, sx) rightPrint(string.rep(" ", 40)) rightPrint(" rdnt://firewolf Homepage ") rightPrint(" rdnt://sites Sites ") rightPrint(" rdnt://server Server Management ") rightPrint(" rdnt://help Help Page ") rightPrint(" rdnt://settings Settings ") rightPrint(" rdnt://credits Credits ") rightPrint(" rdnt://exit Exit ") rightPrint(string.rep(" ", 40)) local a = {"firewolf", "sites", "server", "help", "settings", "credits", "exit"} while true do local e, but, x, y = os.pullEvent() if e == "mouse_click" and x >= 14 and x <= 50 then for i, v in ipairs(a) do if y == sx + i and v ~= "exit" then redirect(v) end end end end end -- -------- Server Management local function manageServers(site, protocol, functionList, startServerName) local servers = functionList["reload servers"]() local sy = 7 if not startServerName then startServerName = "Start" end if isAdvanced() then local function draw(l, sel) term.setBackgroundColor(colors[theme["bottom-box"]]) term.setCursorPos(4, sy) write("[- New Server -]") for i, v in ipairs(l) do term.setCursorPos(3, i + sy) write(string.rep(" ", 24)) term.setCursorPos(4, i + sy) local nv = v if nv:len() > 18 then nv = nv:sub(1, 15) .. "..." end if i == sel then write("[ " .. nv .. " ]") else write(" " .. nv) end end if #l < 1 then term.setCursorPos(4, sy + 2) write("A website is literally") term.setCursorPos(4, sy + 3) write("just a lua script!") term.setCursorPos(4, sy + 4) write("Go ahead and make one!") term.setCursorPos(4, sy + 6) write("Also, be sure to check") term.setCursorPos(4, sy + 7) write("out Firewolf's APIs to") term.setCursorPos(4, sy + 8) write("help you make your") term.setCursorPos(4, sy + 9) write("site, at rdnt://help") end term.setCursorPos(30, sy) write(string.rep(" ", 19)) term.setCursorPos(30, sy) if l[sel] then local nl = l[sel] if nl:len() > 19 then nl = nl:sub(1, 16) .. "..." end write(nl) else write("No Server Selected!") end term.setCursorPos(30, sy + 2) write("[- " .. startServerName .. " -]") term.setCursorPos(30, sy + 4) write("[- Edit -]") term.setCursorPos(30, sy + 6) if functionList["run on boot"] then write("[- Run on Boot -]") end term.setCursorPos(30, sy + 8) write("[- Delete -]") end local function updateDisplayList(items, loc, len) local ret = {} for i = 1, len do if items[i + loc - 1] then table.insert(ret, items[i + loc - 1]) end end return ret end while true do term.setBackgroundColor(colors[theme["background"]]) term.clear() term.setCursorPos(1, 1) term.setTextColor(colors[theme["text-color"]]) term.setBackgroundColor(colors[theme["top-box"]]) print("") leftPrint(string.rep(" ", 27)) leftPrint(" Server Management - " .. protocol:upper() .. " ") leftPrint(string.rep(" ", 27)) print("") term.setBackgroundColor(colors[theme["bottom-box"]]) for i = 1, 12 do term.setCursorPos(3, i + sy - 2) write(string.rep(" ", 24)) term.setCursorPos(29, i + sy - 2) write(string.rep(" ", 21)) end local sel, loc, len = 1, 1, 10 local disList = updateDisplayList(servers, loc, len) draw(disList, sel) while true do local e, but, x, y = os.pullEvent() if e == "key" and but == 200 and #servers > 0 and loc > 1 then loc = loc - 1 disList = updateDisplayList(servers, loc, len) draw(disList, sel) elseif e == "key" and but == 208 and #servers > 0 and loc + len - 1 < #servers then loc = loc + 1 disList = updateDisplayList(servers, loc, len) draw(disList, sel) elseif e == "mouse_click" then if x >= 4 and x <= 25 then if y == 7 then functionList["new server"]() servers = functionList["reload servers"]() break elseif #servers > 0 then for i, v in ipairs(disList) do if y == i + 7 then sel = i draw(disList, sel) end end end elseif x >= 30 and x <= 40 and y == 9 and #servers > 0 then functionList["start"](disList[sel]) servers = functionList["reload servers"]() break elseif x >= 30 and x <= 39 and y == 11 and #servers > 0 then functionList["edit"](disList[sel]) servers = functionList["reload servers"]() break elseif x >= 30 and x <= 46 and y == 13 and #servers > 0 and functionList["run on boot"] then functionList["run on boot"](disList[sel]) term.setBackgroundColor(colors[theme["bottom-box"]]) term.setCursorPos(32, 15) write("Will Run on Boot!") openAddressBar = false sleep(1.3) openAddressBar = true term.setCursorPos(32, 15) write(string.rep(" ", 18)) break elseif x >= 30 and x <= 41 and y == 15 and #servers > 0 then functionList["delete"](disList[sel]) servers = functionList["reload servers"]() break end end end end else while true do term.setBackgroundColor(colors[theme["background"]]) term.clear() term.setCursorPos(1, 1) term.setTextColor(colors[theme["text-color"]]) term.setBackgroundColor(colors[theme["top-box"]]) print("") centerPrint(string.rep(" ", 27)) centerPrint(" Server Management - " .. protocol:upper() .. " ") centerPrint(string.rep(" ", 27)) print("") local a = {"New Server"} for _, v in pairs(servers) do table.insert(a, v) end local server = scrollingPrompt(a, 4, 7, 10) if server == "New Server" then functionList["new server"]() servers = functionList["reload servers"]() else term.setCursorPos(30, 8) write(server) local a = {{"Start", 30, 9}, {"Edit", 30, 11}, {"Run on Boot", 30, 12}, {"Delete", 30, 13}, {"Back", 30, 15}} if not functionList["run on boot"] then a = {{"Start", 30, 9}, {"Edit", 30, 11}, {"Delete", 30, 13}, {"Back", 30, 15}} end local opt = prompt(a, "vertical") if opt == "Start" then functionList["start"](server) servers = functionList["reload servers"]() elseif opt == "Edit" then functionList["edit"](server) servers = functionList["reload servers"](server) elseif opt == "Run on Boot" and functionList["run on boot"] then functionList["run on boot"](server) term.setCursorPos(32, 16) write("Will Run on Boot!") openAddressBar = false sleep(1.3) openAddressBar = true elseif opt == "Delete" then functionList["delete"](server) servers = functionList["reload servers"]() end end end end end local function editPages(dir) local oldLoc = shell.dir() local commandHis = {} term.setBackgroundColor(colors.black) term.setTextColor(colors.white) term.clear() term.setCursorPos(1, 1) print("") print(" Server Shell Editing") print(" Type 'exit' to return to Firewolf.") print(" The 'home' file is the index of your site.") print("") local allowed = {"move", "mv", "cp", "copy", "drive", "delete", "rm", "edit", "eject", "exit", "help", "id", "monitor", "rename", "alias", "clear", "paint", "lua", "redstone", "rs", "redprobe", "redpulse", "programs", "redset", "reboot", "hello", "label", "list", "ls", "easter", "pastebin", "dir"} while true do shell.setDir(dir) term.setBackgroundColor(colors.black) if isAdvanced() then term.setTextColor(colors.yellow) else term.setTextColor(colors.white) end write("> ") term.setTextColor(colors.white) local line = read(nil, commandHis) table.insert(commandHis, line) local words = {} for m in string.gmatch(line, "[^ \t]+") do local a = m:gsub("^%s*(.-)%s*$", "%1") table.insert(words, a) end local com = words[1] if com == "exit" then break elseif com then local a = false for _, v in pairs(allowed) do if com == v then a = true break end end if a then term.setBackgroundColor(colors.black) term.setTextColor(colors.white) shell.run(com, unpack(words, 2)) else term.setTextColor(colors.red) print("Program Not Allowed!") end end end shell.setDir(oldLoc) end local function newServer(onCreate) term.setBackgroundColor(colors[theme["background"]]) for i = 1, 12 do term.setCursorPos(3, i + 5) term.clearLine() end term.setBackgroundColor(colors[theme["bottom-box"]]) term.setCursorPos(1, 7) for i = 1, 8 do centerPrint(string.rep(" ", 47)) end term.setCursorPos(5, 8) write("Name: ") local name = modRead({refusePrint = "`", visibleLength = w - 4, textLength = 200}) term.setCursorPos(5, 10) write("URL:") term.setCursorPos(8, 11) write("rdnt://") local url = modRead({grantPrint = "abcdefghijklmnopqrstuvwxyz1234567890-_.+", visibleLength = w - 4, textLength = 200}) url = url:gsub(" ", "") if name == "" or url == "" then term.setCursorPos(5, 13) write("URL or Name is Empty!") openAddressBar = false sleep(1.3) openAddressBar = true else local c = onCreate(name, url) term.setCursorPos(5, 13) if c and c == "true" then write("Successfully Created Server!") elseif c == "false" or not c then write("Server Creation Failed!") else write(c) end openAddressBar = false sleep(1.3) openAddressBar = true end end pages["server/rdnt"] = function(site) manageServers(site, "rdnt", {["reload servers"] = function() local servers = {} for _, v in pairs(fs.list(serverFolder)) do if fs.isDir(serverFolder .. "/" .. v) then table.insert(servers, v) end end return servers end, ["new server"] = function() newServer(function(name, url) if fs.exists(serverFolder .. "/" .. url) then return "Server Already Exists!" end fs.makeDir(serverFolder .. "/" .. url) local f = io.open(serverFolder .. "/" .. url .. "/home", "w") f:write("print(\"\")\ncenterPrint(\"Welcome To " .. name .. "!\")\n\n") f:close() return "true" end) end, ["start"] = function(server) term.clear() term.setCursorPos(1, 1) term.setBackgroundColor(colors.black) term.setTextColor(colors.white) openAddressBar, offsetclick = false, false setfenv(1, oldEnv) shell.run(serverLocation, server, serverFolder .. "/" .. server) setfenv(1, override) openAddressBar, offsetclick = true, true checkForModem() end, ["edit"] = function(server) openAddressBar, offsetclick = false, false editPages(serverFolder .. "/" .. server) openAddressBar, offsetclick = true, true if not fs.exists(serverFolder .. "/" .. server .. "/home") then local f = io.open(serverFolder .. "/" .. server .. "/home", "w") f:write("print(\"\")\ncenterPrint(\"Welcome To " .. server .. "!\")\n\n") f:close() end end, ["run on boot"] = function(server) fs.delete("/old-startup") if fs.exists("/startup") then fs.move("/startup", "/old-startup") end local f = io.open("/startup", "w") f:write("shell.run(\"" .. serverLocation .. "\", \"" .. server .. "\", \"" .. serverFolder .. "/" .. server .. "\")") f:close() end, ["delete"] = function(server) fs.delete(serverFolder .. "/" .. server) end}) end pages["server/http"] = function() term.setTextColor(colors[theme["text-color"]]) term.setBackgroundColor(colors[theme["background"]]) term.clear() print("\n\n") term.setBackgroundColor(colors[theme["top-box"]]) centerPrint(string.rep(" ", 17)) centerPrint(" Comming Soon! ") centerPrint(string.rep(" ", 17)) end pages["server"] = function() setfenv(manageServers, override) setfenv(newServer, override) setfenv(editPages, env) if curProtocol == protocols.rdnt then redirect("server/rdnt") elseif curProtocol == protocols.http then redirect("server/http") end end -- -------- Help pages["help"] = function() term.setBackgroundColor(colors[theme["background"]]) term.clear() term.setTextColor(colors[theme["text-color"]]) term.setBackgroundColor(colors[theme["top-box"]]) print("") leftPrint(string.rep(" ", 16)) leftPrint(" Firewolf Help ") leftPrint(string.rep(" ", 16)) print("\n") term.setBackgroundColor(colors[theme["bottom-box"]]) for i = 1, 11 do rightPrint(string.rep(" ", 41)) end term.setCursorPos(1, 15) rightPrint(" View the full documentation at: ") rightPrint(" https://github.com/1lann/Firewolf/wiki ") local opt = prompt({{"Getting Started", w - 21, 8}, {"Making a Theme", w - 20, 10}, {"API Documentation", w - 23, 12}}, "vertical") local pages = {} if opt == "Getting Started" then pages[1] = {title = "Getting Started - Intoduction", content = { "Hey there!", "", "Firewolf is an app that allows you to create", "and visit websites! Each site has an address", "(the URL) which you can type into the address", "bar above, and then visit the site.", "", "You can open the address bar by clicking on", "it, or by pressing control." }} pages[2] = {title = "Getting Started - Searching", content = { "The address bar can be also be used to", "search for sites, by simply typing in the", "search term.", "", "To view all sites, just open it and hit", "enter (leave the field blank)." }} pages[3] = {title = "Getting Started - Built-In Websites", content = { "Firewolf has a set of built-in websites", "available for use:", "", "rdnt://firewolf Normal hompage", "rdnt://sites Built-In Site", "rdnt://server Create websites", "rdnt://help Help and documentation" }} pages[4] = {title = "Getting Started - Built-In Websites", content = { "More built-in websites:", "", "rdnt://settings Firewolf settings", "rdnt://credits View the credits", "rdnt://exit Exit the app" }} elseif opt == "Making a Theme" then pages[1] = {title = "Making a Theme - Introduction", content = { "Firewolf themes are files that tell Firewolf", "to color which things what.", "Several themes can already be downloaded for", "Firewolf from rdnt://settings/themes.", "", "You can also make your own theme, use it in", "your copy of Firewolf.Your theme can also be", "submitted it to the themes list!" }} pages[2] = {title = "Making a Theme - Example", content = { "A theme file consists of several lines of", "text. Here is the default theme file:", "address-bar-text=white", "address-bar-background=gray", "address-bar-base=lightGray", "top-box=red", "bottom-box=orange", "background=gray", "text-color=white" }} pages[3] = {title = "Making a Theme - Explanation", content = { "On each line of the example, something is", "given a color, like on the last line, the", "text of the page is told to be white.", "", "The color specified after the = is the same", "as when you call colors.[color name].", "For example, specifying 'red' after the =", "colors that object red." }} pages[4] = {title = "Making a Theme - Have a Go", content = { "Themes can be made at rdnt://settings/themes,", "click on 'Change Theme' button, and click on", "'New Theme'.", "", "Enter a theme name, then exit Firewolf and", "edit the newly created file", "Specify the colors for each of the keys,", "and return to the themes section of the", "downloads center. Click 'Load Theme'." }} pages[5] = {title = "Making a Theme - Submitting", content = { "To submit a theme to the theme list,", "send GravityScore a message on the CCForums", "that contains your theme file and name.", "", "He will message you back saying whether your", "theme has been added, or if anything needs to", "be changed before it is added." }} elseif opt == "API Documentation" then pages[1] = {title = "API Documentation - 1", content = { "The Firewolf API is a bunch of global", "functions that aim to simplify your life when", "designing and coding websites.", "", "For a full documentation on these functions,", "visit the Firewolf Wiki Page here:", "https://github.com/1lann/Firewolf/wiki" }} pages[2] = {title = "API Documentation - 2", content = { "centerPrint(string text)", "cPrint(string text)", "centerWrite(string text)", "cWrite(string text)", "", "leftPrint(string text)", "lPrint(string text)", }} pages[3] = {title = "API Documentation - 3", content = { "leftWrite(string text)", "lWrite(string text)", "", "rightPrint(string text)", "rPrint(string text)", "rightWrite(string text)", "rWrite(string text)" }} pages[4] = {title = "API Documentation - 4", content = { "prompt(table list, string direction)", "scrollingPrompt(table list, integer x,", " integer y, integer length[,", " integer width])", "", "urlDownload(string url)", "pastebinDownload(string code)", "redirect(string site)", }} pages[5] = {title = "API Documentation - 5", content = { "loadImageFromServer(string imagePath)", "ioReadFileFromServer(string filePath)", "fileFileFromServer(string filePath)", "saveFileToUserComputer(string content)", "", "writeDataFile(string path, string contents)", "readDataFile(string path)" }} pages[6] = {title = "API Documentation - 6", content = { "themeColor(string tag)", "themeColour(string tag)" }} end local function drawPage(page) term.setBackgroundColor(colors[theme["background"]]) term.clear() term.setCursorPos(1, 1) term.setTextColor(colors[theme["text-color"]]) term.setBackgroundColor(colors[theme["top-box"]]) print("") leftPrint(string.rep(" ", page.title:len() + 3)) leftPrint(" " .. page.title .. " ") leftPrint(string.rep(" ", page.title:len() + 3)) print("") term.setBackgroundColor(colors[theme["bottom-box"]]) for i = 1, 12 do print(string.rep(" ", w)) end for i, v in ipairs(page.content) do term.setCursorPos(4, i + 6) write(v) end end local curPage = 1 local a = {{"Prev", 26, 17}, {"Next", 38, 17}, {"Back", 14, 17}} drawPage(pages[curPage]) while true do local b = {a[3]} if curPage == 1 then table.insert(b, a[2]) elseif curPage == #pages then table.insert(b, a[1]) else table.insert(b, a[1]) table.insert(b, a[2]) end local opt = prompt(b, "horizontal") if opt == "Prev" then curPage = curPage - 1 elseif opt == "Next" then curPage = curPage + 1 elseif opt == "Back" then break end drawPage(pages[curPage]) end redirect("help") end -- -------- Settings pages["settings/themes"] = function() term.setBackgroundColor(colors[theme["background"]]) term.clear() term.setTextColor(colors[theme["text-color"]]) term.setBackgroundColor(colors[theme["top-box"]]) print("") leftPrint(string.rep(" ", 17)) leftPrint(" Theme Settings ") leftPrint(string.rep(" ", 17)) print("") if isAdvanced() then term.setBackgroundColor(colors[theme["bottom-box"]]) for i = 1, 12 do rightPrint(string.rep(" ", 36)) end local themes = {} local themenames = {"Back", "New Theme", "Load Theme"} local f = io.open(rootFolder .. "/temp_file", "w") f:write(files.availableThemes) f:close() local f = io.open(rootFolder .. "/temp_file", "r") local l = f:read("*l") while l do l = l:gsub("^%s*(.-)%s*$", "%1") local a, b = l:find("| |") table.insert(themenames, l:sub(b + 1, -1)) table.insert(themes, {name = l:sub(b + 1, -1), url = l:sub(1, a - 1)}) l = f:read("*l") end f:close() fs.delete(rootFolder .. "/temp_file") local t = scrollingPrompt(themenames, w - 33, 7, 10, 32) if t == "Back" then redirect("settings") elseif t == "New Theme" then term.setCursorPos(w - 33, 17) write("Path: /") local n = modRead({visibleLength = w - 2, textLength = 100}) if n ~= "" and n then n = "/" .. n local f = io.open(n, "w") f:write(files.newTheme) f:close() term.setCursorPos(1, 17) rightWrite(string.rep(" ", 36)) term.setCursorPos(1, 17) rightWrite("File Created! ") openAddressBar = false sleep(1.1) openAddressBar = true redirect("settings/themes") end elseif t == "Load Theme" then term.setCursorPos(w - 33, 17) write("Path: /") local n = modRead({visibleLength = w - 2, textLength = 100}) if n ~= "" and n then n = "/" .. n term.setCursorPos(1, 17) rightWrite(string.rep(" ", 36)) term.setCursorPos(1, 17) if fs.exists(n) and not fs.isDir(n) then local a = loadTheme(n) if a then fs.delete(themeLocation) fs.copy(n, themeLocation) theme = a rightWrite("Theme File Loaded! :D ") else rightWrite("Theme File is Corrupt! D: ") end elseif not fs.exists(n) then rightWrite("File does not exist! ") elseif fs.isDir(n) then rightWrite("File is a directory! ") end openAddressBar = false sleep(1.1) openAddressBar = true redirect("settings/themes") end else local url = "" for _, v in pairs(themes) do if v.name == t then url = v.url break end end term.setBackgroundColor(colors[theme["top-box"]]) term.setCursorPos(1, 3) leftWrite(string.rep(" ", 17)) leftWrite(" Downloading... ") fs.delete(rootFolder .. "/temp_file") download(url, rootFolder .. "/temp_file") local th = loadTheme(rootFolder .. "/temp_file") if not th then term.setCursorPos(1, 3) leftWrite(string.rep(" ", 17)) leftWrite(" Theme Corrupt! ") openAddressBar = false sleep(1.3) openAddressBar = true fs.delete(rootFolder .. "/temp_file") redirect("settings/themes") else term.setCursorPos(1, 3) leftWrite(string.rep(" ", 17)) leftWrite(" Theme Loaded! ") openAddressBar = false sleep(1.3) openAddressBar = true fs.delete(themeLocation) fs.move(rootFolder .. "/temp_file", themeLocation) theme = th redirect("home") end end else print("") rightPrint(string.rep(" ", 30)) rightPrint(" Themes are not available on ") rightPrint(" normal computers! :( ") rightPrint(string.rep(" ", 30)) end end pages["settings"] = function() term.setBackgroundColor(colors[theme["background"]]) term.clear() term.setTextColor(colors[theme["text-color"]]) term.setBackgroundColor(colors[theme["top-box"]]) print("") leftPrint(string.rep(" ", 17 + serverList[serverID]:len())) leftPrint(" Firewolf Settings " .. string.rep(" ", serverList[serverID]:len() - 3)) leftPrint(" Designed For: " .. serverList[serverID] .. " ") leftPrint(string.rep(" ", 17 + serverList[serverID]:len())) print("\n") local a = "Automatic Updating - On" if autoupdate == "false" then a = "Automatic Updating - Off" end local b = "Home - rdnt://" .. homepage if b:len() >= 28 then b = b:sub(1, 24) .. "..." end term.setBackgroundColor(colors[theme["bottom-box"]]) for i = 1, 9 do rightPrint(string.rep(" ", 36)) end local c = {{a, w - a:len() - 6, 9}, {"Change Theme", w - 18, 11}, {b, w - b:len() - 6, 13}, {"Reset Firewolf", w - 20, 15}} if not isAdvanced() then c = {{a, w - a:len(), 9}, {b, w - b:len(), 11}, {"Reset Firewolf", w - 14, 13}} end local opt = prompt(c, "vertical") if opt == a then if autoupdate == "true" then autoupdate = "false" elseif autoupdate == "false" then autoupdate = "true" end elseif opt == "Change Theme" and isAdvanced() then redirect("settings/themes") elseif opt == b then if isAdvanced() then term.setCursorPos(w - 30, 14) else term.setCursorPos(w - 30, 12) end write("rdnt://") local a = read() if a ~= "" then homepage = a end elseif opt == "Reset Firewolf" then term.setBackgroundColor(colors[theme["background"]]) term.clear() term.setCursorPos(1, 1) term.setTextColor(colors[theme["text-color"]]) term.setBackgroundColor(colors[theme["top-box"]]) print("") leftPrint(string.rep(" ", 17)) leftPrint(" Reset Firewolf ") leftPrint(string.rep(" ", 17)) print("\n") term.setBackgroundColor(colors[theme["bottom-box"]]) for i = 1, 11 do rightPrint(string.rep(" ", 26)) end local opt = prompt({{"Reset History", w - 19, 8}, {"Reset Servers", w - 19, 9}, {"Reset Theme", w - 17, 10}, {"Reset Cache", w - 17, 11}, {"Reset Databases", w - 21, 12}, {"Reset Settings", w - 20, 13}, {"Back", w - 10, 14}, {"Reset All", w - 15, 16}}, "vertical") openAddressBar = false if opt == "Reset All" then fs.delete(rootFolder) elseif opt == "Reset History" then fs.delete(historyLocation) elseif opt == "Reset Servers" then fs.delete(serverFolder) fs.delete(serverLocation) elseif opt == "Reset Cache" then fs.delete(cacheFolder) elseif opt == "Reset Databases" then fs.delete(userWhitelist) fs.delete(userBlacklist) elseif opt == "Reset Settings" then fs.delete(settingsLocation) elseif opt == "Reset Theme" then fs.delete(themeLocation) elseif opt == "Back" then openAddressBar = true redirect("settings") end term.setBackgroundColor(colors[theme["background"]]) term.clear() term.setCursorPos(1, 1) term.setBackgroundColor(colors[theme["top-box"]]) print("\n\n") leftPrint(string.rep(" ", 17)) leftPrint(" Reset Firewolf ") leftPrint(string.rep(" ", 17)) print("") term.setCursorPos(1, 10) term.setBackgroundColor(colors[theme["bottom-box"]]) rightPrint(string.rep(" ", 27)) rightPrint(" Firewolf has been reset! ") rightWrite(string.rep(" ", 27)) if isAdvanced() then rightPrint(" Click to exit... ") else rightPrint(" Press any key to exit... ") end rightPrint(string.rep(" ", 27)) while true do local e = os.pullEvent() if e == "mouse_click" or e == "key" then return true end end end -- Save local f = io.open(settingsLocation, "w") f:write(textutils.serialize({auto = autoupdate, incog = incognito, home = homepage})) f:close() redirect("settings") end -- -------- Credits pages["credits"] = function() term.setTextColor(colors[theme["text-color"]]) term.setBackgroundColor(colors[theme["background"]]) term.clear() print("\n") term.setBackgroundColor(colors[theme["top-box"]]) leftPrint(string.rep(" ", 19)) leftPrint(" Firewolf Credits ") leftPrint(string.rep(" ", 19)) print("\n") term.setBackgroundColor(colors[theme["bottom-box"]]) rightPrint(string.rep(" ", 38)) rightPrint(" Coded by: GravityScore ") rightPrint(" and 1lann ") rightPrint(string.rep(" ", 38)) rightPrint(" Based off: RednetExplorer 2.4.1 ") rightPrint(" Made by ComputerCraftFan11 ") rightPrint(string.rep(" ", 38)) end -- -------- Error Pages errorPages["overspeed"] = function() clear("overspeed", colors[theme["background"]]) print("") term.setTextColor(colors[theme["text-color"]]) term.setBackgroundColor(colors[theme["top-box"]]) leftPrint(string.rep(" ", 14)) leftPrint(" Warning! D: ") leftPrint(string.rep(" ", 14)) print("") term.setBackgroundColor(colors[theme["bottom-box"]]) rightPrint(string.rep(" ", 40)) rightPrint(" Website browsing sleep limit reached! ") rightPrint(string.rep(" ", 40)) rightPrint(" To prevent Firewolf from spamming ") rightPrint(" rednet, Firewolf has stopped loading ") rightPrint(" the page. ") for i = 1, 3 do rightPrint(string.rep(" ", 40)) end openAddressBar = false for i = 1, 5 do term.setCursorPos(1, 14) rightWrite(string.rep(" ", 43)) if 6 - i == 1 then rightWrite(" Please wait 1 second... ") else rightWrite(" Please wait " .. tostring(6 - i) .. " seconds... ") end sleep(1) end openAddressBar = true term.setCursorPos(1, 14) rightWrite(string.rep(" ", 43)) rightWrite(" You may now browse normally ") end errorPages["crash"] = function(error) clear("crash", colors[theme["background"]]) print("") term.setTextColor(colors[theme["text-color"]]) term.setBackgroundColor(colors[theme["top-box"]]) leftPrint(string.rep(" ", 30)) leftPrint(" The Website Has Crashed! D: ") leftPrint(string.rep(" ", 30)) print("") term.setBackgroundColor(colors[theme["bottom-box"]]) rightPrint(string.rep(" ", 31)) rightPrint(" The website has crashed! ") rightPrint(" Report this to the operator: ") rightPrint(string.rep(" ", 31)) term.setBackgroundColor(colors[theme["background"]]) print("") print(" " .. tostring(error)) print("") term.setBackgroundColor(colors[theme["bottom-box"]]) rightPrint(string.rep(" ", 31)) rightPrint(" You may now browse normally ") rightPrint(string.rep(" ", 31)) end -- -------- External local function validateexternal(site) -- Modem if not modemPresent() then return "modem" end -- Website local id, content, status = curProtocol.getWebsite(site) if id and status then return "exists", id, content, status end -- Cache local cacheLoc = cacheFolder .. "/" .. site:gsub("/", "$slazh$") if fs.exists(cacheLoc) and not fs.isDir(cacheLoc) then return "cache" end -- Search results local res = {} if site ~= "" then for _, v in pairs(dnsDatabase[1]) do if v:find(site:lower(), 1, true) then table.insert(res, v) end end else for _, v in pairs(dnsDatabase[1]) do table.insert(res, v) end end table.sort(res) table.sort(res, function(a, b) local _, ac = a:gsub("rdnt://", ""):gsub("http://", ""):gsub(site:lower(), "") local _, bc = b:gsub("rdnt://", ""):gsub("http://", ""):gsub(site:lower(), "") return ac > bc end) if #res > 0 then return "search", res elseif site == "" then return "search", res end -- Doesn't exist return "false" end local function loadexternal(site) local a, res, content, status = validateexternal(site) local func = nil if a == "exists" then local cacheLoc = cacheFolder .. "/" .. site:gsub("/", "$slazh$") local f = io.open(cacheLoc, "w") f:write(content) f:close() local fn, err = loadfile(cacheLoc) if not err then setfenv(fn, antivirus) if status == "whitelist" then setfenv(fn, override) end func = function() local _, err = pcall(fn) if err then websiteerror = err os.queueEvent(event_error) end end else func = function() local errf = errorPages["crash"] setfenv(errf, override) pcall(function() errf(err) end) end end elseif a == "modem" then func = function() checkForModem(graphics.nomodem) end elseif a == "search" then if #res > 0 then func = function() term.setBackgroundColor(colors[theme["background"]]) term.clear() term.setCursorPos(1, 2) term.setTextColor(colors[theme["text-color"]]) term.setBackgroundColor(colors[theme["top-box"]]) local t = "1 Search Result" if #res > 1 then t = #res .. " Search Results" end leftPrint(string.rep(" ", t:len() + 3)) leftPrint(" " .. t .. " ") leftPrint(string.rep(" ", t:len() + 3)) print("") term.setBackgroundColor(colors[theme["bottom-box"]]) for i = 1, 12 do rightPrint(string.rep(" ", 42)) end local opt = scrollingPrompt(res, w - 39, 7, 10, 38) if opt then redirect(opt:gsub("rdnt://", ""):gsub("http://", "")) end end else func = graphics.nosearchresults end elseif a == "false" or a == "cache" then func = graphics.nonexistantwebpage end term.setBackgroundColor(colors.black) term.setTextColor(colors.white) term.clear() term.setCursorPos(1, 1) local a = override a["browserAgent"] = browserAgent setfenv(func, a) curtext, curbackground = colors.white, colors.black tabs[currentTab] = coroutine.create(func) end -- -------- Website local function loadinternal(site) if pages[site] then local func = pages[site] setfenv(func, override) tabs[currentTab] = coroutine.create(function() local _, err = pcall(function() func() end) if err then websiteerror = err os.queueEvent(event_error) end end) return true else return false end end local function loadsite(site) w, h = term.getSize() clear(site) term.setBackgroundColor(colors.black) term.setTextColor(colors.white) fs.delete(websiteDataFolder) fs.makeDir(websiteDataFolder) if site ~= "exit" and site ~= addressBarHistory[#addressBarHistory] then table.insert(addressBarHistory, site) end checkForModem() if os.clock() - loadingClock > 5 then loadingRate, loadingClock = 0, os.clock() end if loadingRate >= 8 then local overspeedFunc = errorPages["overspeed"] setfenv(overspeedFunc, override) overspeedFunc() loadingRate, loadingClock = 0, os.clock() end -- Load os.queueEvent(event_load) website = site setfenv(loadinternal, override) setfenv(loadexternal, override) if not loadinternal(site) then loadexternal(site) end if tabs[currentTab] then _, filters[currentTab] = coroutine.resume(tabs[currentTab]) end end -- -------- Address Bar local function addressbarread() local len, list = 4, {} local function draw(l) local ox, oy = term.getCursorPos() for i = 1, len do term.setTextColor(colors[theme["address-bar-text"]]) term.setBackgroundColor(colors[theme["address-bar-background"]]) term.setCursorPos(1, i + 1) write(string.rep(" ", w)) end term.setBackgroundColor(colors[theme["address-bar-base"] or theme["bottom-box"]]) term.setCursorPos(1, len + 2) write(string.rep(" ", w)) term.setBackgroundColor(colors[theme["address-bar-background"]]) for i, v in ipairs(l) do term.setCursorPos(2, i + 1) write(v) end term.setCursorPos(ox, oy) end local function update(line, event, ...) local params = {...} local y = params[3] if event == "char" or event == "history" or event == "delete" then list = {} for _, v in pairs(dnsDatabase[1]) do if #list < len and v:gsub("rdnt://", ""):gsub("http://", ""):find(line:lower(), 1, true) then table.insert(list, v) end end table.sort(list) table.sort(list, function(a, b) local _, ac = a:gsub("rdnt://", ""):gsub("http://", ""):gsub(line:lower(), "") local _, bc = b:gsub("rdnt://", ""):gsub("http://", ""):gsub(line:lower(), "") return ac > bc end) draw(list) return false elseif event == "mouse_click" then for i = 1, #list do if y == i + 1 then return true, list[i]:gsub("rdnt://", ""):gsub("http://", "") end end end end if isAdvanced() and modemPresent() then return modRead({history = addressBarHistory, visibleLength = w - 2, textLength = 300, liveUpdates = update, exitOnKey = "control"}) else return modRead({history = addressBarHistory, visibleLength = w - 2, textLength = 300, exitOnKey = "control"}) end end -- -------- Main local function searchresults() if modemPresent() then curProtocol.getSearchResults() end local lastCheck = os.clock() while true do local e = os.pullEvent() if e == event_load and modemPresent() and os.clock() - lastCheck > 5 then curProtocol.getSearchResults() lastCheck = os.clock() end end end local function run() loadingClock = os.clock() loadsite(homepage) while true do local e, but, x, y, p4, p5 = os.pullEvent() if ((e == "mouse_click" and y == 1 and clickableAddressBar) or (e == "key" and (but == 29 or but == 157))) and openAddressBar then if e == "key" then x = -1 end if not menuBarOpen and x == w then -- Open menu bar menuBarOpen = true term.setBackgroundColor(colors[theme["top-box"]]) term.setTextColor(colors[theme["address-bar-text"]]) term.setCursorPos(1, 1) write("> [- Exit Firewolf -] ") elseif menuBarOpen and (x == 1 or (but == 29 or but == 157)) then -- Close menu bar menuBarOpen = false clear(website, nil, true) elseif menuBarOpen and x > 2 and x < 22 then return elseif not menuBarOpen then -- Stop if tabs[currentTab] then tabs[currentTab] = nil end -- Clear term.setBackgroundColor(colors[theme["address-bar-background"]]) term.setTextColor(colors[theme["address-bar-text"]]) term.setCursorPos(2, 1) term.clearLine() if curProtocol == protocols.rdnt then write("rdnt://") elseif curProtocol == protocols.http then write("http://") end -- Read local osite = website local site = addressbarread() if not site then site = osite elseif site == "home" or site == "homepage" then site = homepage elseif site == "exit" then return end -- Load loadsite(site) end elseif e == event_error and websiteerror then -- Display if tabs[currentTab] then tabs[currentTab] = nil end local errf = errorPages["crash"] setfenv(errf, override) errf(websiteerror) websiteerror = nil elseif e == event_redirect and openAddressBar then -- Stop if tabs[currentTab] then tabs[currentTab] = nil end -- Load if not but or but == "exit" then but = website elseif but == "home" or but == "homepage" then but = homepage end loadsite(but) elseif tabs[currentTab] then if coroutine.status(tabs[currentTab]) == "suspended" then if e == "mouse_click" and offsetclick then y = y - 1 end if (filters[currentTab] or e) == e then _, filters[currentTab] = coroutine.resume(tabs[currentTab], e, but, x, y, p4, p5) end end for i = 1, #tabs do if tabs[i] and coroutine.status(tabs[i]) == "dead" then tabs[i] = nil end end end end end -- -------- Startup local function main() -- Logo term.setBackgroundColor(colors[theme["background"]]) term.setTextColor(colors[theme["text-color"]]) term.clear() term.setCursorPos(1, 2) term.setBackgroundColor(colors[theme["top-box"]]) leftPrint(string.rep(" ", 47)) leftPrint([[ ______ ____ ____ ______ ]]) leftPrint([[ ------- / ____// _// __ \ / ____/ ]]) leftPrint([[ ------ / /_ / / / /_/ // __/ ]]) leftPrint([[ ----- / __/ _/ / / _ _// /___ ]]) leftPrint([[ ---- / / /___//_/ |_|/_____/ ]]) leftPrint([[ --- / / _ __ ____ __ ______ ]]) leftPrint([[ -- /_/ | | / // __ \ / / / ____/ ]]) leftPrint([[ | | /| / // / / // / / /_ ]]) leftPrint([[ | |/ |/ // /_/ // /___ / __/ ]]) leftPrint([[ |__/|__/ \____//_____//_/ ]]) leftPrint(string.rep(" ", 47)) print("\n") term.setBackgroundColor(colors[theme["bottom-box"]]) -- Load Settings if fs.exists(settingsLocation) and not fs.isDir(settingsLocation) then local f = io.open(settingsLocation, "r") local a = textutils.unserialize(f:read("*l")) if type(a) == "table" then autoupdate, incognito, homepage = a.auto, a.incog, a.home end f:close() else autoupdate, incognito, homepage = "true", "false", "firewolf" end curProtocol = protocols.rdnt -- Update rightPrint(string.rep(" ", 32)) rightPrint(" Checking for Updates... ") rightPrint(string.rep(" ", 32)) setfenv(updateClient, env) if not noInternet then if updateClient() then if debugFile then debugFile:close() end shell.run(firewolfLocation) error() end end -- Download Files local x, y = term.getCursorPos() term.setCursorPos(1, y - 2) rightWrite(string.rep(" ", 32)) rightWrite(" Downloading Required Files... ") if not noInternet then resetFilesystem() end loadDatabases() checkForModem() -- Run setfenv(run, env) parallel.waitForAny(run, searchresults) end local function startup() -- HTTP if not http and not noInternet then term.setTextColor(colors[theme["text-color"]]) term.setBackgroundColor(colors[theme["background"]]) term.clear() term.setCursorPos(1, 2) term.setBackgroundColor(colors[theme["top-box"]]) api.leftPrint(string.rep(" ", 24)) api.leftPrint(" HTTP API Not Enabled! ") api.leftPrint(string.rep(" ", 24)) print("") term.setBackgroundColor(colors[theme["bottom-box"]]) api.rightPrint(string.rep(" ", 36)) api.rightPrint(" Firewolf is unable to run without ") api.rightPrint(" the HTTP API Enabled! Please ") api.rightPrint(" enable it in your ComputerCraft ") api.rightPrint(" Config! ") api.rightPrint(string.rep(" ", 36)) if isAdvanced() then api.rightPrint(" Click to exit... ") else api.rightPrint(" Press any key to exit... ") end api.rightPrint(string.rep(" ", 36)) while true do local e, but, x, y = os.pullEvent() if e == "mouse_click" or e == "key" then break end end return false end -- Turtle if turtle then term.clear() term.setCursorPos(1, 2) api.centerPrint("Advanced computer Required!") print("\n") api.centerPrint(" This version of Firewolf requires ") api.centerPrint(" an Advanced computer to run! ") print("") api.centerPrint(" Turtles may not be used to run ") api.centerPrint(" Firewolf! :( ") print("") api.centerPrint("Press any key to exit...") os.pullEvent("key") return false end -- Run setfenv(main, env) local _, err = pcall(main) if err and not err:lower():find("terminated") then term.setTextColor(colors[theme["text-color"]]) term.setBackgroundColor(colors[theme["background"]]) term.clear() term.setCursorPos(1, 2) term.setCursorBlink(false) term.setBackgroundColor(colors[theme["top-box"]]) api.leftPrint(string.rep(" ", 27)) api.leftPrint(" Firewolf has Crashed! D: ") api.leftPrint(string.rep(" ", 27)) print("") term.setBackgroundColor(colors[theme["background"]]) print("") print(" " .. err) print("") term.setBackgroundColor(colors[theme["bottom-box"]]) api.rightPrint(string.rep(" ", 41)) if autoupdate == "true" then api.rightPrint(" Please report this error to 1lann or ") api.rightPrint(" GravityScore so we are able to fix it! ") api.rightPrint(" If this problem persists, try deleting ") api.rightPrint(" " .. rootFolder .. " ") else api.rightPrint(" Automatic updating is off! A new ") api.rightPrint(" version may have have been released ") api.rightPrint(" that may fix this error! ") api.rightPrint(" If you didn't turn auto updating ") api.rightPrint(" off, delete " .. rootFolder .. " ") end api.rightPrint(string.rep(" ", 41)) if isAdvanced() then api.rightPrint(" Click to exit... ") else api.rightPrint(" Press any key to exit... ") end api.rightPrint(string.rep(" ", 41)) while true do local e, but, x, y = os.pullEvent() if e == "mouse_click" or e == "key" then break end end return false end end -- Check If Read Only if fs.isReadOnly(firewolfLocation) or fs.isReadOnly(rootFolder) then print("Firewolf cannot modify itself or its root folder!") print("") print("This cold be caused by Firewolf being placed in") print("the rom folder, or another program may be") print("preventing the modification of Firewolf.") error() end -- Theme if not isAdvanced() then theme = originalTheme else theme = loadTheme(themeLocation) or defaultTheme end -- Debug File if #tArgs > 0 and tArgs[1] == "debug" then print("Debug Mode Enabled") if fs.exists(debugLogLocation) then debugFile = io.open(debugLogLocation, "a") else debugFile = io.open(debugLogLocation, "w") end debugFile:write("\n-- [" .. textutils.formatTime(os.time()) .. "] New Log --") sleep(1) end -- Start startup() -- Exit Message term.setBackgroundColor(colors.black) term.setTextColor(colors.white) term.setCursorBlink(false) term.clear() term.setCursorPos(1, 1) api.centerPrint("Thank You for Using Firewolf " .. version) api.centerPrint("Made by 1lann and GravityScore") -- Close for _, v in pairs(rs.getSides()) do if peripheral.getType(v) == "modem" then rednet.close(v) end end if debugFile then debugFile:close() end