-- From -- Via
-- Descriptions-- en: -- de:
-- Test : -- Wikidata:
--[=[ URLutil 2014-09-20 Utilities for URL etc. on www. * getAuthority * getFragment * getHost * getLocation * getPath * getPort * getQuery * getQueryTable * getRelativePath * getScheme * getTLD * getTop2domain * getTop3domain * isAuthority * isDomain * isDomainExample * isDomainInt * isHost * isIP * isIPlocal * isIPv4 * isIPv6 * isMailAddress * isMailLink * isProtocolDialog * isProtocolWiki * isResourceURL * isSuspiciousURL * isUnescapedURL * isWebURL * wikiEscapeURL Only [[dotted decimal]] notation for IPv4 supported.Does not support dotted hexadecimal, dotted octal, or single-number formats.IPv6 URL (bracketed) not yet implemented; might need Wikintax escaping anyway.]=]
-- table for exportlocal URLutil =
URLutil.getURIScheme = function (uri) if type(uri)
1 and #prot >= 2 then return prot:lower elseif #slashes
0 then return "//" end end return falseend -- getURIScheme
local getTopDomain = function (url, mode) local r = URLutil.getHost(url) if r then local pattern = "[%w%%]+%.%a[%w-]*%a)$" if mode
URLutil.getAuthority = function (url) local r if type(url)
":" then if port:find("^[1-9]") then r = (host .. ":" .. port) end elseif #port
URLutil.getFragment = function (url, decode) local r if type(url)
"string" then local encoding = mw.text.trim(decode) local launch if encoding
"WIKI" then r = r:gsub("%.(%x%x)", "%%%1") :gsub("_", " ") launch = true end if launch then r = mw.uri.decode(r, "PATH") end end else r = false end else r = nil end return rend -- URLutil.getFragment
URLutil.getHost = function (url) local r = URLutil.getAuthority(url) if r then r = mw.ustring.match(r, "^([%w%.%%-]+):?[%d]*$") end return rend -- URLutil.getHost
URLutil.getLocation = function (url) local r if type(url)
"" then r = false else local i r = mw.text.decode(r) i = r:find("#", 1, true) if i then if i
URLutil.getPath = function (url) local r = URLutil.getRelativePath(url) if r then local s = r:match("^([^%?]*)%?") if s then r = s end s = r:match("^([^#]*)#") if s then r = s end end return rend -- URLutil.getPath
URLutil.getPort = function (url) local r = URLutil.getAuthority(url) if r then r = r:match(":([1-9][0-9]*)$") if r then r = tonumber(r) else r = false end end return rend -- URLutil.getPort
URLutil.getQuery = function (url, key, separator) local r = URLutil.getLocation(url) if r then r = r:match("^[^%?]*%?(.+)$") if r then if type(key)
"string" then s = mw.text.trim(separator) if s:match("^[&;,/]$") then sep = s end end s = string.format("%s%s%s", sep, r, sep) scan = string.format("%s%s=([^%s]*)%s", sep, key, sep, sep) r = s:match(scan) end end if not r then r = false end end return rend -- URLutil.getQuery
URLutil.getQueryTable = function (url, separator) local r = URLutil.getQuery(url) if r then local sep = "&" local n, pairs, s, set if type(separator)
URLutil.getRelativePath = function (url) local r if type(url)
"/" then s = s:match("/[^/]+(/.*)$") end end if s then r = mw.text.trim(s) elseif URLutil.isResourceURL(url) then r = "/" else r = false end else r = nil end return rend -- URLutil.getRelativePath
URLutil.getScheme = function (url) local r if type(url)
"//" then if colon
0 then r = "//" end end else r = nil end return rend -- URLutil.getScheme
URLutil.getTLD = function (url) local r = URLutil.getHost(url) if r then r = mw.ustring.match(r, "[%w]+%.(%a[%w-]*%a)$") if not r then r = false end end return rend -- URLutil.getTLD
URLutil.getTop2domain = function (url) return getTopDomain(url, 2)end -- URLutil.getTop2domain
URLutil.getTop3domain = function (url) return getTopDomain(url, 3)end -- URLutil.getTop3domain
URLutil.isAuthority = function (s) local r if type(s)
":" then port = port:match("^[1-9][0-9]*$") if type(port) ~= "string" then r = false end elseif port ~= "" then r = false end r = URLutil.isHost(host) else r = nil end return rend -- URLutil.isAuthority
URLutil.isDomain = function (s) local r if type(s)
"string" then if mw.ustring.find(s, "^%w") then if mw.ustring.find(s, "..", 1, true) then r = false else r = true end end end else r = nil end return rend -- URLutil.isDomain
URLutil.isDomainExample = function (url) -- RFC 2606: example.com example.net example.org example.edu local r = getTopDomain(url, 2) if r then local s = r:lower:match("^example%.([a-z][a-z][a-z])$") if s then r = (s
"edu" or s
"org") else r = false end end return rend -- URLutil.isDomainExample
URLutil.isDomainInt = function (url) -- Internationalized Domain Name (Punycode) local r = URLutil.getHost(url) if r then if r:match("^[!-~]+$") then local s = "." .. r if s:find(".xn--", 1, true) then r = true else r = false end else r = true end end return rend -- URLutil.isDomainInt
URLutil.isHost = function (s) return URLutil.isDomain(s) or URLutil.isIP(s)end -- URLutil.isHost
URLutil.isIP = function (s) return URLutil.isIPv4(s) and 4 or URLutil.isIPv6(s) and 6end -- URLutil.isIP
URLutil.isIPlocal = function (s) -- IPv4 according to RFC 1918, RFC 1122; even any 0.0.0.0 (RFC 5735) local r = false local num = s:match("^ *([01][0-9]*)%.") if num then num = tonumber(num) if num
10 or num
169 then -- 169.254.*.* elseif num
192 then -- 192.168.*.* num = s:match("^ *0*192%.([0-9]+)%.") if num then num = tonumber(num) if num
URLutil.isIPv4 = function (s) local function legal(n) return (tonumber(n) < 256) end local r = false if type(s)
URLutil.isIPv6 = function (s) local dcolon, groups if type(s) ~= "string" or s:len
1 and groups < 8) or (dcolon
8)) and (s:len
1 and s
URLutil.isMailAddress = function (s) if type(s)
URLutil.isMailLink = function (s) if type(s)
"string" then if s:lower
local function isProtocolAccepted(prot, supplied) if type(prot)
"" then if colon ~= ":" and slashes
":" or slashes
"string" then return true end end end end return falseend -- isProtocolAccepted
URLutil.isProtocolMW = function (prot) return isProtocolAccepted(prot, " http https ftp ftps ssh sftp irc ircs xmpp sip sips gopher telnet nntp worldwind mailto tel sms news svn git mms bitcoin magnet urn geo ")end -- URLutil.isProtocolMW
URLutil.isProtocolDialog = function (prot) return isProtocolAccepted(prot, " mailto irc ircs ssh telnet ")end -- URLutil.isProtocolDialog
URLutil.isProtocolWiki = function (prot) return isProtocolAccepted(prot, " ftp ftps git http https nntp sftp svn worldwind ")end -- URLutil.isProtocolWiki
URLutil.isResourceURL = function (url) local scheme = URLutil.getScheme(url) if scheme then local s = " // http:// https:// ftp:// sftp:// " s = s:find(string.format(" %s ", scheme)) if s then if URLutil.getAuthority(url) then if not url:match("%S%s+%S") then return true end end end end return falseend -- URLutil.isResourceURL
URLutil.isSuspiciousURL = function (url) if URLutil.isResourceURL(url) then local s = URLutil.getAuthority(url) local pat = "[%[|%]" .. mw.ustring.char(8201, 45, 8207, 8234, 45, 8239, 8288) .. "]" if s:find("@") or url:find("") or url:find(pat) or url:find("[%.,]$") then return true end -- TODO zero width character ?? return false end return trueend -- URLutil.isSuspiciousURL
URLutil.isUnescapedURL = function (url, trailing) if type(trailing) ~= "string" then if URLutil.isWebURL(url) then if url:match("[%[|%]]") then return true end end end return falseend -- URLutil.isUnescapedURL
URLutil.isWebURL = function (url) if URLutil.getScheme(url) and URLutil.getAuthority(url) then if not url:match("%S%s+%S") then return true end end return falseend -- URLutil.isWebURL
URLutil.wikiEscapeURL = function (url) if url:find("[%[|%]]") then local n url, n = url:gsub("%[", "[") :gsub("|", "|") :gsub("%]", "]") end return urlend -- URLutil.wikiEscapeURL
-- Provide template access and expose URLutil table to require
local p =
function p.getURIScheme(frame) return URLutil.getURIScheme(frame.args[1 ]) or ""endfunction p.getAuthority(frame) return URLutil.getAuthority(frame.args[1 ]) or ""endfunction p.getFragment(frame) local r = URLutil.getFragment(frame.args[1 ], frame.args[2 ]) if r then r = "#" .. r else r = "" end return rendfunction p.getHost(frame) return URLutil.getHost(frame.args[1 ]) or ""endfunction p.getLocation(frame) return URLutil.getLocation(frame.args[1 ]) or ""endfunction p.getPath(frame) return URLutil.getPath(frame.args[1 ]) or ""endfunction p.getPort(frame) return URLutil.getPort(frame.args[1 ]) or ""endfunction p.getQuery(frame) local r local key = frame.args[2 ] if key then key = mw.text.trim(key) if key
return p