xurfer/xurfer/ext/xrfragments/url.lua

145 lines
5 KiB
Lua
Raw Normal View History

2026-06-08 11:04:52 +02:00
-- Copyright 2026 Leon van Kammen / coderofsalvation. All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without modification, are
-- permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice, this list of
-- conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright notice, this list
-- of conditions and the following disclaimer in the documentation and/or other materials
-- provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED BY AS IS'' AND ANY EXPRESS OR IMPLIED
-- WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-- FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR
-- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-- ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--
-- The views and conclusions contained in the software and documentation are those of the
-- authors and should not be interpreted as representing official policies, either expressed
-- or implied, of
-- below is a lua adaptation of Godot's URI.gd
2026-06-06 12:35:31 +02:00
-- https://gist.github.com/coderofsalvation/b2b111a2631fbdc8e76d6cab3bea8f17
local url = {}
-- Helper function to split a string by a delimiter
local function split(str, delimiter)
local result = {}
if delimiter == "" then return {str} end
local pattern = string.format("([^%s]+)", delimiter)
for match in string.gmatch(str, pattern) do
table.insert(result, match)
end
return result
end
-- Helper for guess_type (converts numbers/booleans from strings)
local function guess_type(val)
if tonumber(val) then return tonumber(val) end
if val == "true" then return true end
if val == "false" then return false end
return val
end
-- Helper to parse query parameters and fragments
local function parseArgs(fragment)
local ARG = {}
if not fragment or fragment == "" then return ARG end
local items = split(fragment, "&")
for _, item in ipairs(items) do
local key_value = split(item, "=")
if #key_value > 1 then
ARG[key_value[1]] = guess_type(key_value[2])
elseif #key_value == 1 then
ARG[key_value[1]] = ""
end
end
return ARG
end
-- Main URL Parser function attached to the module object
function url.parse(url_string)
-- Setup initial URI table structure
local URI = {
domain = "",
fragment = {},
file = "",
extension = "",
string = url_string,
protocol = "",
path = "",
query = {},
hash = "",
URN = "",
isLocal = false
}
local remaining = url_string
local protocol = string.match(remaining, "^(%w+://)") -- protocol
if protocol then
URI.protocol = protocol:gsub("://", "")
remaining = remaining:sub(#protocol + 1)
end
local hash = string.match(remaining, "(#.*)$") -- fragment
if hash then
URI.hash = hash
remaining = remaining:sub(1, #remaining - #hash)
end
local query = string.match(remaining, "(%?[^#]+)$")
if query then
URI.query = query
remaining = remaining:sub(1, #remaining - #query)
end
URI.path = remaining
-- Process Path, Domain, and File
if URI.path and URI.path ~= "" then
local pathParts = split(URI.path, "/")
if #pathParts > 1 then
local firstPart = pathParts[1]
-- Check if the first part looks like a domain (contains '.' or ':')
if string.find(firstPart, "%.") or string.find(firstPart, ":") then
URI.domain = table.remove(pathParts, 1)
end
end
-- Reconstruct path
URI.path = table.concat(pathParts, "/")
-- Extract file if present
if #pathParts > 0 then
local lastPart = pathParts[#pathParts]
if string.find(lastPart, "%.") then
URI.file = lastPart
URI.extension = URI.file:match("%.([^%.]+)$"):upper()
end
end
end
if URI.hash and URI.hash ~= "" then
URI.fragment = parseArgs(URI.hash:sub(2)) -- sub(2) skips the '#'
else
URI.fragment = {}
end
if URI.query and type(URI.query) == "string" and URI.query ~= "" then
URI.query = parseArgs(URI.query:sub(2)) -- sub(2) skips the '?'
else
URI.query = {}
end
if URI.domain ~= "" then
URI.URN = URI.string:gsub("%?.*", "")
else
URI.URN = ""
end
URI.isLocal = (URI.domain == "")
return URI
end
-- Return the module table so it can be assigned via require()
return url