Modul:URLutil: Unterschied zwischen den Versionen
2022-04-05
ICON (Diskussion | Beiträge) (Die Seite wurde neu angelegt: „local URLutil = { suite = "URLutil", serial = "2018-01-24", item = 10859193 } --[=[ Utilities for URL etc. on www. * get…“) |
(2022-04-05) |
||
Zeile 1: | Zeile 1: | ||
local URLutil = { suite = "URLutil", | local URLutil = { suite = "URLutil", | ||
serial = " | serial = "2022-04-05", | ||
item = 10859193 } | item = 10859193 } | ||
--[=[ | --[=[ | ||
Utilities for URL etc. on www. | Utilities for URL etc. on www. | ||
* decode() | |||
* encode() | |||
* getAuthority() | * getAuthority() | ||
* getFragment() | * getFragment() | ||
Zeile 24: | Zeile 26: | ||
* isDomainInt() | * isDomainInt() | ||
* isHost() | * isHost() | ||
* isHostPathResource() | |||
* isIP() | * isIP() | ||
* isIPlocal() | * isIPlocal() | ||
Zeile 37: | Zeile 40: | ||
* isWebURL() | * isWebURL() | ||
* wikiEscapeURL() | * wikiEscapeURL() | ||
* failsafe() | |||
Only [[dotted decimal]] notation for IPv4 expected. | Only [[dotted decimal]] notation for IPv4 expected. | ||
Does not support dotted hexadecimal, dotted octal, or single-number formats. | Does not support dotted hexadecimal, dotted octal, or single-number formats. | ||
IPv6 URL (bracketed) not yet implemented; might need Wikintax escaping anyway. | IPv6 URL (bracketed) not yet implemented; might need Wikintax escaping anyway. | ||
]=] | ]=] | ||
local Failsafe = URLutil | |||
Zeile 46: | Zeile 51: | ||
local decodeComponentProtect = { F = "\"#%<>[\]^`{|}", | local decodeComponentProtect = { F = "\"#%<>[\]^`{|}", | ||
P = "\"#%<>[\]^`{|}/?", | P = "\"#%<>[\]^`{|}/?", | ||
Q = "\"#%<>[\]^`{|}&=+;", | Q = "\"#%<>[\]^`{|}&=+;,", | ||
X = "\"#%<>[\]^`{|}&=+;/?" } | X = "\"#%<>[\]^`{|}&=+;,/?" } | ||
Zeile 123: | Zeile 128: | ||
end | end | ||
n = ( ask:byte( j, j ) - 48 ) * 16 + n | n = ( ask:byte( j, j ) - 48 ) * 16 + n | ||
if decodeComponentEscape( averse, n ) then | if n == 39 and | ||
ask:sub( i + 3, i + 5 ) == "%27" then | |||
j = i + 6 | |||
while ( ask:sub( j, j + 2 ) == "%27" ) do | |||
j = j + 3 | |||
end -- while "%27" | |||
elseif decodeComponentEscape( averse, n ) then | |||
if m then | if m then | ||
ask = string.format( "%s%c%s", | ask = string.format( "%s%c%s", | ||
Zeile 189: | Zeile 200: | ||
return r | return r | ||
end -- getHash() | end -- getHash() | ||
URLutil.decode = function ( url, enctype ) | |||
local r, s | |||
if type( enctype ) == "string" then | |||
s = mw.text.trim( enctype ) | |||
if s == "" then | |||
s = false | |||
else | |||
s = s:upper() | |||
end | |||
end | |||
r = mw.text.encode( mw.uri.decode( url, s ) ) | |||
if r:find( "[%[|%]]" ) then | |||
local k | |||
r, k = r:gsub( "%[", "[" ) | |||
:gsub( "|", "|" ) | |||
:gsub( "%]", "]" ) | |||
end | |||
return r | |||
end -- URLutil.decode() | |||
URLutil.encode = function ( url, enctype ) | |||
local k, r, s | |||
if type( enctype ) == "string" then | |||
s = mw.text.trim( enctype ) | |||
if s == "" then | |||
s = false | |||
else | |||
s = s:upper() | |||
end | |||
end | |||
r = mw.uri.encode( url, s ) | |||
k = r:byte( 1, 1 ) | |||
if -- k == 35 or -- # | |||
k == 42 or -- * | |||
k == 58 or -- : | |||
k == 59 then -- ; | |||
r = string.format( "%%%X%s", k, r:sub( 2 ) ) | |||
end | |||
if r:find( "[%[|%]]" ) then | |||
r, k = r:gsub( "%[", "%5B" ) | |||
:gsub( "|", "%7C" ) | |||
:gsub( "%]", "%5D" ) | |||
end | |||
return r | |||
end -- URLutil.encode() | |||
Zeile 601: | Zeile 662: | ||
local r | local r | ||
if type( s ) == "string" then | if type( s ) == "string" then | ||
local scan = "^%s*([%w%.%%_-] | local scan = "^%s*([%w%.%%_-]*%w)%.(%a[%w-]*%a)%s*$" | ||
local scope | local scope | ||
s, scope = mw.ustring.match( s, scan ) | s, scope = mw.ustring.match( s, scan ) | ||
Zeile 663: | Zeile 724: | ||
return URLutil.isDomain( s ) or URLutil.isIP( s ) | return URLutil.isDomain( s ) or URLutil.isIP( s ) | ||
end -- URLutil.isHost() | end -- URLutil.isHost() | ||
URLutil.isHostPathResource = function ( s ) | |||
local r = URLutil.isResourceURL( s ) | |||
if not r and s then | |||
r = URLutil.isResourceURL( "//" .. mw.text.trim( s ) ) | |||
end | |||
return r | |||
end -- URLutil.isHostPathResource() | |||
Zeile 842: | Zeile 913: | ||
local s = URLutil.getAuthority( url ) | local s = URLutil.getAuthority( url ) | ||
local pat = "[%[|%]" .. | local pat = "[%[|%]" .. | ||
mw.ustring.char( 8201, 45, 8207, | mw.ustring.char( 34, | ||
8201, 45, 8207, | |||
8234, 45, 8239, | 8234, 45, 8239, | ||
8288 ) | 8288 ) | ||
Zeile 875: | Zeile 947: | ||
URLutil.isWebURL = function ( url ) | URLutil.isWebURL = function ( url ) | ||
if URLutil.getScheme( url ) and URLutil.getAuthority( url ) then | if URLutil.getScheme( url ) and URLutil.getAuthority( url ) then | ||
if not url: | if not url:find( "%S%s+%S" ) and | ||
not url:find( "''", 1, true ) then | |||
return true | return true | ||
end | end | ||
Zeile 896: | Zeile 969: | ||
Failsafe.failsafe = function ( atleast ) | |||
-- Retrieve versioning and check for compliance | -- Retrieve versioning and check for compliance | ||
-- Precondition: | -- Precondition: | ||
-- | -- atleast -- string, with required version | ||
-- | -- or wikidata|item|~|@ or false | ||
-- Postcondition: | -- Postcondition: | ||
-- Returns string with | -- Returns string -- with queried version/item, also if problem | ||
local since = | -- false -- if appropriate | ||
-- 2020-08-17 | |||
local since = atleast | |||
local last = ( since == "~" ) | |||
local linked = ( since == "@" ) | |||
local link = ( since == "item" ) | |||
local r | local r | ||
if since == "wikidata" then | if last or link or linked or since == "wikidata" then | ||
local item = | local item = Failsafe.item | ||
since = false | since = false | ||
if type( item ) == "number" and item > 0 then | if type( item ) == "number" and item > 0 then | ||
local | local suited = string.format( "Q%d", item ) | ||
if link then | |||
r = suited | |||
else | |||
local entity = mw.wikibase.getEntity( suited ) | |||
if type( entity ) == "table" then | |||
local seek = Failsafe.serialProperty or "P348" | |||
local vsn = entity:formatPropertyValues( seek ) | |||
if type( vsn ) == "table" and | |||
type( vsn.value ) == "string" and | |||
vsn.value ~= "" then | |||
if last and vsn.value == Failsafe.serial then | |||
r = false | |||
elseif linked then | |||
if mw.title.getCurrentTitle().prefixedText | |||
== mw.wikibase.getSitelink( suited ) then | |||
r = false | |||
else | |||
r = suited | |||
end | |||
else | |||
r = vsn.value | |||
end | |||
end | |||
end | end | ||
end | end | ||
end | end | ||
end | end | ||
if | if type( r ) == "nil" then | ||
if not since or since <= | if not since or since <= Failsafe.serial then | ||
r = | r = Failsafe.serial | ||
else | else | ||
r = false | r = false | ||
Zeile 929: | Zeile 1.023: | ||
end | end | ||
return r | return r | ||
end -- | end -- Failsafe.failsafe() | ||
local function Template( frame, action, amount ) | |||
-- Run actual code from template transclusion | |||
-- Precondition: | |||
-- frame -- object | |||
-- action -- string, with function name | |||
-- amount -- number, of args if > 1 | |||
-- Postcondition: | |||
-- Return string or not | |||
local n = amount or 1 | |||
local v = { } | |||
local r, s | |||
for i = 1, n do | |||
s = frame.args[ i ] | |||
if s then | |||
s = mw.text.trim( s ) | |||
if s ~= "" then | |||
v[ i ] = s | |||
end | |||
end | |||
end -- for i | |||
if v[ 1 ] then | |||
r = URLutil[ action ]( v[ 1 ], v[ 2 ], v[ 3 ] ) | |||
end | |||
return r | |||
end -- Template() | |||
local p = {} | local p = {} | ||
function p.decode( frame ) | |||
return Template( frame, "decode", 2 ) or "" | |||
end | |||
function p.encode( frame ) | |||
return Template( frame, "encode", 2 ) or "" | |||
end | |||
function p.getAuthority( frame ) | function p.getAuthority( frame ) | ||
return | return Template( frame, "getAuthority" ) or "" | ||
end | end | ||
function p.getFragment( frame ) | function p.getFragment( frame ) | ||
local r = | local r = Template( frame, "getFragment", 2 ) | ||
if r then | if r then | ||
r = "#" .. r | r = "#" .. r | ||
Zeile 950: | Zeile 1.076: | ||
end | end | ||
function p.getHost( frame ) | function p.getHost( frame ) | ||
return | return Template( frame, "getHost" ) or "" | ||
end | end | ||
function p.getLocation( frame ) | function p.getLocation( frame ) | ||
return | return Template( frame, "getLocation" ) or "" | ||
end | end | ||
function p.getNormalized( frame ) | function p.getNormalized( frame ) | ||
return | return Template( frame, "getNormalized" ) or "" | ||
end | end | ||
function p.getPath( frame ) | function p.getPath( frame ) | ||
return | return Template( frame, "getPath" ) or "" | ||
end | end | ||
function p.getPort( frame ) | function p.getPort( frame ) | ||
return | return Template( frame, "getPort" ) or "" | ||
end | end | ||
function p.getQuery( frame ) | function p.getQuery( frame ) | ||
local r | local r = Template( frame, "getQuery", 3 ) | ||
local key = frame.args[ 2 ] | if r then | ||
local key = frame.args[ 2 ] | |||
if key then | |||
key = mw.text.trim( key ) | |||
if key == "" then | |||
key = nil | |||
end | |||
end | end | ||
if not key then | if not key then | ||
r = "?" .. r | r = "?" .. r | ||
Zeile 984: | Zeile 1.109: | ||
end | end | ||
function p.getRelativePath( frame ) | function p.getRelativePath( frame ) | ||
return | return Template( frame, "getRelativePath" ) or "" | ||
end | end | ||
function p.getScheme( frame ) | function p.getScheme( frame ) | ||
return | return Template( frame, "getScheme" ) or "" | ||
end | end | ||
function p.getSortkey( frame ) | function p.getSortkey( frame ) | ||
return | return Template( frame, "getSortkey" ) or "" | ||
end | end | ||
function p.getTLD( frame ) | function p.getTLD( frame ) | ||
return | return Template( frame, "getTLD" ) or "" | ||
end | end | ||
function p.getTop2domain( frame ) | function p.getTop2domain( frame ) | ||
return | return Template( frame, "getTop2domain" ) or "" | ||
end | end | ||
function p.getTop3domain( frame ) | function p.getTop3domain( frame ) | ||
return | return Template( frame, "getTop3domain" ) or "" | ||
end | end | ||
function p.isAuthority( frame ) | function p.isAuthority( frame ) | ||
return | return Template( frame, "isAuthority" ) and "1" or "" | ||
end | end | ||
function p.isDomain( frame ) | function p.isDomain( frame ) | ||
return | return Template( frame, "isDomain" ) and "1" or "" | ||
end | end | ||
function p.isDomainExample( frame ) | function p.isDomainExample( frame ) | ||
return | return Template( frame, "isDomainExample" ) and "1" or "" | ||
end | end | ||
function p.isDomainInt( frame ) | function p.isDomainInt( frame ) | ||
return | return Template( frame, "isDomainInt" ) and "1" or "" | ||
end | end | ||
function p.isHost( frame ) | function p.isHost( frame ) | ||
return | return Template( frame, "isHost" ) and "1" or "" | ||
end | |||
function p.isHostPathResource( frame ) | |||
return Template( frame, "isHostPathResource" ) and "1" or "" | |||
end | end | ||
function p.isIP( frame ) | function p.isIP( frame ) | ||
return | return Template( frame, "isIP" ) or "" | ||
end | end | ||
function p.isIPlocal( frame ) | function p.isIPlocal( frame ) | ||
return | return Template( frame, "isIPlocal" ) and "1" or "" | ||
end | end | ||
function p.isIPv4( frame ) | function p.isIPv4( frame ) | ||
return | return Template( frame, "isIPv4" ) and "1" or "" | ||
end | end | ||
function p.isIPv6( frame ) | function p.isIPv6( frame ) | ||
return | return Template( frame, "isIPv6" ) and "1" or "" | ||
end | end | ||
function p.isMailAddress( frame ) | function p.isMailAddress( frame ) | ||
return | return Template( frame, "isMailAddress" ) and "1" or "" | ||
end | end | ||
function p.isMailLink( frame ) | function p.isMailLink( frame ) | ||
return | return Template( frame, "isMailLink" ) and "1" or "" | ||
end | end | ||
function p.isProtocolDialog( frame ) | function p.isProtocolDialog( frame ) | ||
return | return Template( frame, "isProtocolDialog" ) and "1" or "" | ||
end | end | ||
function p.isProtocolWiki( frame ) | function p.isProtocolWiki( frame ) | ||
return | return Template( frame, "isProtocolWiki" ) and "1" or "" | ||
end | end | ||
function p.isResourceURL( frame ) | function p.isResourceURL( frame ) | ||
return | return Template( frame, "isResourceURL" ) and "1" or "" | ||
end | end | ||
function p.isSuspiciousURL( frame ) | function p.isSuspiciousURL( frame ) | ||
return | return Template( frame, "isSuspiciousURL" ) and "1" or "" | ||
end | end | ||
function p.isUnescapedURL( frame ) | function p.isUnescapedURL( frame ) | ||
return | return Template( frame, "isUnescapedURL", 2 ) and "1" or "" | ||
end | end | ||
function p.isWebURL( frame ) | function p.isWebURL( frame ) | ||
return | return Template( frame, "isWebURL" ) and "1" or "" | ||
end | end | ||
function p.wikiEscapeURL( frame ) | function p.wikiEscapeURL( frame ) | ||
return | return Template( frame, "wikiEscapeURL" ) | ||
end | end | ||
p.failsafe = function ( frame ) | p.failsafe = function ( frame ) | ||
Zeile 1.069: | Zeile 1.197: | ||
end | end | ||
end | end | ||
return | return Failsafe.failsafe( since ) or "" | ||
end | end | ||
function p.URLutil() | function p.URLutil() |