Editing
Module:Sensitive IP addresses/list/validate
From Thetacola Wiki
Jump to navigation
Jump to search
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
-- This module validates the data in [[Module:Sensitive IP addresses/list]]. -- Load modules local mSIPA_API = require('Module:Sensitive IP addresses/API') local Subnet = require('Module:IP').Subnet -- Constants local DATA_MODULE = 'Module:Sensitive IP addresses/list' local p = {} local function makeErrorLogger() -- Return an object for formatting errors. return { errors = {}, addError = function (self, msg, ...) table.insert(self.errors, string.format(msg, ...)) end, addEntryTypeError = function (self, entryIdx, field, actual, expected) self:addError( 'The %s field in data entry #%d was type %s (should be string or nil)', field, entryIdx, actual, expected ) end, hasErrors = function (self) return #self.errors > 0 end, makeReport = function (self) if #self.errors < 1 then return 'No errors found' else local ret = {'Found the following errors:'} for i, msg in ipairs(self.errors) do ret[#ret + 1] = string.format('* <strong class="error">%s</strong>', msg) end return table.concat(ret, '\n') end end, } end local function loadData(logger) -- Load the data table, logging any errors in the process. -- Check whether the data module can be successfully loaded. local success, data = pcall(mw.loadData, DATA_MODULE) if not success then logger:addError('%s could not be parsed by mw.loadData; check for [[mw:LUAREF#mw.loadData|invalid data]]', DATA_MODULE) return nil end -- Check that the data table is a table. if type(data) ~= 'table' then logger:addError('%s returned a %s; table expected', DATA_MODULE, type(data)) end return data end local function checkDataStructure(logger, data) -- Check the structure of the individual entries in the data table. for dataIndex, subtable in ipairs(data) do -- Check that subtables are tables. if type(subtable) ~= 'table' then logger:addError('Data entry #%d is not a table', dataIndex) end -- Check that we have required string fields. for _, field in ipairs{'name', 'id', 'description'} do if type(subtable[field]) ~= 'string' then logger:addError( "Missing field '%s' in data entry #%d", field, dataIndex ) elseif subtable[field] == '' then logger:addError( "Blank field '%s' in data entry #%d", field, dataIndex ) end end -- Check that optional string fields are strings if they are present. for _, field in ipairs{'notes'} do local val = subtable[field] if val ~= nil and type(val) ~= 'string' then logger:addEntryTypeError(dataIndex, field, type(val), 'string or nil') end end -- Check that the reason is valid if it is present. if subtable.reason ~= nil then if type(subtable.reason) ~= 'string' then logger:addEntryTypeError( dataIndex, 'reason', type(subtable.reason), 'string or nil' ) elseif not mSIPA_API._isValidSensitivityReason(subtable.reason) then logger:addError( "The reason field in data entry #%d was invalid (should be '%s')", dataIndex, mSIPA_API._getSensitivityReasons("', '", "', or '") ) end end -- Check IP range tables. for i, field in ipairs{'ipv4Ranges', 'ipv6Ranges'} do local ranges = subtable[field] if ranges ~= nil then if type(ranges) ~= 'table' then logger:addEntryTypeError(dataIndex, field, type(ranges), 'table or nil') else for j, range in ipairs(ranges) do if type(range) ~= 'string' then logger:addError( 'Range #%d in the %s field of entry #%d was type %s (expected string)', j, field, type(range) ) elseif range == '' then logger:addError( 'Range #%d in the %s field of entry #%d was a blank string', j, field ) end end end end end end end local function makeSubnet(cidr) -- Make a subnet object from a CIDR string. Returns a subnet object, or nil -- if there were any errors. local success, obj = pcall(Subnet.new, cidr) if success then return obj end end local function checkDuplicateIds(logger, data) -- Check that there are no duplicate IDs in the data. local ids = {} for dataIndex, subtable in ipairs(data) do if ids[subtable.id] then logger:addError( "Data entry #%d (%s) and data entry #%d (%s) have duplicate ID '%s'", ids[subtable.id], data[ids[subtable.id]].name, dataIndex, subtable.name, subtable.id ) else ids[subtable.id] = dataIndex end end end local function checkRanges(logger, data) -- Check the ranges in the data table to make sure they are all valid and -- that they don't overlap with each other. This function assumes that the -- structure of the data table is valid. -- Make an array of subnet data for easy comparison local ranges = { ipv4 = {}, ipv6 = {}, } for dataIndex, subtable in ipairs(data) do for i, field in ipairs{'ipv4Ranges', 'ipv6Ranges'} do local cidrs = subtable[field] if cidrs then for j, cidr in ipairs(cidrs) do local subnet = makeSubnet(cidr) if subnet then local ipVersion = field == 'ipv4Ranges' and 'IPv4' or 'IPv6' local rangeKey = ipVersion:lower() if ipVersion == subnet:getVersion() then table.insert(ranges[rangeKey], { dataIndex = dataIndex, field = field, rangeIndex = j, subnet = subnet, name = subtable.name, }) else logger:addError( "Found %s CIDR string '%s' in range #%d in the %s field of entry #%d (%s); should be %s", subnet:getVersion(), cidr, j, field, dataIndex, subtable.name, ipVersion ) end else logger:addError( "Invalid CIDR string '%s' in range #%d in the %s field of entry #%d (%s)", cidr, j, field, dataIndex, subtable.name ) end end end end end -- Check for overlapping subnets local nComparisons = 0 for ipVersion, versionData in pairs(ranges) do local lim = #versionData for i = 1, lim - 1 do local subnetData1 = versionData[i] for j = i + 1, lim do local subnetData2 = versionData[j] nComparisons = nComparisons + 1 if subnetData1.subnet:overlapsSubnet(subnetData2.subnet) then logger:addError( "%s range #%d '%s' in data entry #%d (%s) overlaps range #%d '%s' in data entry #%d (%s)", ipVersion == 'ipv4' and 'IPv4' or 'IPv6', subnetData1.rangeIndex, subnetData1.subnet:getCIDR(), subnetData1.dataIndex, subnetData1.name, subnetData2.rangeIndex, subnetData2.subnet:getCIDR(), subnetData2.dataIndex, subnetData2.name ) end end end end mw.log(nComparisons .. ' subnet comparisons performed') end function p.main() local logger = makeErrorLogger() local data = loadData(logger) if logger:hasErrors() then return logger:makeReport() end checkDataStructure(logger, data) if logger:hasErrors() then return logger:makeReport() end checkDuplicateIds(logger, data) checkRanges(logger, data) return logger:makeReport() end return p
Summary:
Please note that all contributions to Thetacola Wiki may be edited, altered, or removed by other contributors. If you do not want your writing to be edited mercilessly, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource (see
Project:Copyrights
for details).
Do not submit copyrighted work without permission!
Cancel
Editing help
(opens in new window)
Template used on this page:
Module:Sensitive IP addresses/list/validate/doc
(
edit
)
Navigation menu
Page actions
Module
Discussion
Read
Edit source
History
Page actions
Module
Discussion
More
Tools
Personal tools
Not logged in
Talk
Contributions
Create account
Log in
Navigation
Main page
Recent changes
Random page
Help about MediaWiki
Search
Tools
What links here
Related changes
Special pages
Page information