Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local component = require("component")
- local event = require("event")
- local internet = require("internet")
- local term = require("term")
- local unicode = require("unicode")
- local gpu = component.gpu
- local hasColor = gpu.getDepth() > 1
- local function bootUpScreen()
- term.clear()
- local logo = [[
- :::::::: :::::::: ::: ::: :::::::::: :::::::::
- :+: :+: :+: :+: :+: :+: :+: :+:
- +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+
- +#+ +:+ +#++:++#++: +#++:++#++ +#++:++#+
- +#+ +#+ +#+ +#+ +#+ +#+
- #+# #+# #+# #+# #+# #+#
- ######## ### ### ### ###
- ]]
- term.setCursor(1, 1)
- term.write(logo)
- term.setCursor(1, select(2, term.getCursor()) + 1)
- term.write("Loading...")
- term.setCursor(1, select(2, term.getCursor()) + 2)
- term.write("OC-WEB: A Web Browser For OpenComputers Coded by nonogamer9")
- os.sleep(3)
- end
- local function resolveURL(base, relative)
- if not base or not relative then return nil end
- if relative:match("^https?://") then return relative end
- if relative:sub(1, 1) == "/" then
- return base:match("^(https?://[^/]+)") .. relative
- else
- local baseMatch = base:match("^(https?://.*/)") or base:match("^(https?://[^/]+)")
- if baseMatch then
- if baseMatch:sub(-1) ~= "/" then
- baseMatch = baseMatch .. "/"
- end
- return baseMatch .. relative
- else
- return nil
- end
- end
- end
- local function handleJavaScript(html, currentBaseURL)
- local redirectUrl = html:match("window%.location%s*=%s*['\"](.-)['\"]")
- if redirectUrl then
- return resolveURL(currentBaseURL, redirectUrl)
- end
- return nil
- end
- local function fetch(url, visited)
- visited = visited or {}
- if visited[url] then
- return false, "Redirect loop detected"
- end
- visited[url] = true
- local handle, err = internet.request(url)
- if not handle then
- return false, "Failed to connect to " .. url .. ": " .. (err or "unknown error")
- end
- local data = ""
- for chunk in handle do
- if chunk then
- data = data .. chunk
- end
- end
- local redirectUrl = handleJavaScript(data, url)
- if redirectUrl then
- return fetch(redirectUrl, visited)
- end
- return true, data
- end
- local function parseCSS(css)
- local styles = {}
- for selector, rules in css:gmatch("([^{]+){([^}]+)}") do
- styles[selector:gsub("%s+", "")] = {}
- for property, value in rules:gmatch("([^:]+):([^;]+);") do
- styles[selector:gsub("%s+", "")][property:gsub("%s+", "")] = value:gsub("%s+", "")
- end
- end
- return styles
- end
- local function applyCSS(html, styles)
- for selector, rules in pairs(styles) do
- local pattern = "<" .. selector .. ">(.-)</" .. selector .. ">"
- html = html:gsub(pattern, function(content)
- local styled = content
- for property, value in pairs(rules) do
- if property == "color" then
- styled = "[COLOR=" .. value .. "]" .. styled .. "[/COLOR]"
- end
- -- Add more property handlers here as needed
- end
- return styled
- end)
- end
- return html
- end
- local function executeJavaScript(script)
- -- This is a placeholder. Implementing a full JS engine is beyond the scope of this project.
- print("Executing JavaScript:", script:sub(1, 50) .. "...")
- end
- local function parseHTML(html, baseURL)
- local links = {}
- local styles = {}
- -- Extract and parse CSS
- html = html:gsub("<style>(.-)</style>", function(css)
- local parsedStyles = parseCSS(css)
- for k, v in pairs(parsedStyles) do
- styles[k] = v
- end
- return ""
- end)
- -- Extract and execute JavaScript
- html = html:gsub("<script>(.-)</script>", function(js)
- executeJavaScript(js)
- return ""
- end)
- -- Parse HTML elements
- html = html:gsub("<b>(.-)</b>", function(content) return "[B]" .. content .. "[/B]" end)
- html = html:gsub("<strong>(.-)</strong>", function(content) return "[B]" .. content .. "[/B]" end)
- html = html:gsub("<i>(.-)</i>", function(content) return "[I]" .. content .. "[/I]" end)
- html = html:gsub("<em>(.-)</em>", function(content) return "[I]" .. content .. "[/I]" end)
- html = html:gsub("<u>(.-)</u>", function(content) return "[U]" .. content .. "[/U]" end)
- html = html:gsub('<a href="(.-)">(.-)</a>', function(href, content)
- local fullURL = resolveURL(baseURL, href)
- table.insert(links, {href = fullURL, content = content})
- return content .. " [" .. #links .. "]"
- end)
- html = html:gsub("<h[1-6]>(.-)</h[1-6]>", function(content) return "[H]" .. content .. "[/H]" end)
- html = html:gsub("<li>(.-)</li>", function(content) return " * " .. content end)
- html = html:gsub("<br>", "\n")
- html = html:gsub("<p>", "\n\n")
- html = html:gsub("</p>", "\n\n")
- html = html:gsub("<div>(.-)</div>", function(content) return content .. "\n" end)
- html = html:gsub("<.->", "")
- html = html:gsub("<", "<")
- html = html:gsub(">", ">")
- html = html:gsub("&", "&")
- html = html:gsub(""", "\"")
- html = html:gsub("'", "'")
- -- Apply CSS
- html = applyCSS(html, styles)
- return html, links
- end
- local function display(baseURL, data, links)
- local lines = {}
- for line in data:gmatch("[^\r\n]+") do
- table.insert(lines, line)
- end
- local offset = 0
- local screenWidth, screenHeight = gpu.getResolution()
- local contentHeight = screenHeight - 1
- local function redraw()
- term.setCursor(1, 1)
- for i = 1, contentHeight do
- local line = lines[i + offset] or ""
- term.setCursor(1, i)
- term.clearLine()
- -- Handle color tags
- line = line:gsub("%[COLOR=(%w+)%](.-)%[/COLOR%]", function(color, text)
- if hasColor then
- gpu.setForeground(tonumber(color, 16) or 0xFFFFFF)
- end
- return text
- end)
- term.write(unicode.sub(line, 1, screenWidth))
- if hasColor then
- gpu.setForeground(0xFFFFFF) -- Reset color
- end
- end
- term.setCursor(1, screenHeight)
- gpu.setBackground(0x333333)
- term.clearLine()
- term.write("URL: " .. (baseURL or "N/A") .. " | Use Arrow Keys to Scroll, Q to Quit, U to Change URL")
- gpu.setBackground(0x000000)
- end
- redraw()
- while true do
- local eventType, _, _, y, _, scrollDirection = event.pull()
- local needsRedraw = false
- if eventType == "key_down" then
- if y == 200 then -- Up arrow
- offset = math.max(0, offset - 1)
- needsRedraw = true
- elseif y == 208 then -- Down arrow
- offset = math.min(#lines - contentHeight, offset + 1)
- needsRedraw = true
- elseif y
- == 16 then -- Q key
- break
- elseif y == 22 then -- U key
- return false
- end
- elseif eventType == "scroll" then
- if scrollDirection == 1 then
- offset = math.max(0, offset - 1)
- needsRedraw = true
- elseif scrollDirection == -1 then
- offset = math.min(#lines - contentHeight, offset + 1)
- needsRedraw = true
- end
- elseif eventType == "touch" then
- local lineIndex = y + offset
- if lineIndex <= #lines then
- local line = lines[lineIndex]
- local linkIndex = line:match("%[(%d+)%]$")
- if linkIndex then
- local link = links[tonumber(linkIndex)]
- if link and link.href then
- local resolvedURL = resolveURL(baseURL, link.href)
- if resolvedURL then
- print("Opening link: " .. resolvedURL)
- local success, newData = fetch(resolvedURL)
- if success then
- local newParsedData, newLinks = parseHTML(newData, resolvedURL)
- display(resolvedURL, newParsedData, newLinks)
- else
- print("Error fetching URL: " .. newData)
- end
- else
- print("Invalid URL: " .. tostring(link.href))
- end
- else
- print("Invalid link at index: " .. linkIndex)
- end
- end
- end
- end
- if needsRedraw then
- redraw()
- end
- end
- end
- function main(showBootScreen)
- if showBootScreen then
- bootUpScreen()
- end
- term.clear()
- print("Enter a URL:")
- local url = io.read()
- if not url:match("^https?://") then
- print("Invalid URL. Please include http:// or https://")
- else
- local success, data = fetch(url)
- if success then
- local parsedData, links = parseHTML(data, url)
- if display(url, parsedData, links) == false then
- main(false)
- end
- else
- print("Error fetching URL: " .. data)
- end
- end
- end
- main(true)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement