diff options
Diffstat (limited to 'acf/model/net.lua')
-rw-r--r-- | acf/model/net.lua | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/acf/model/net.lua b/acf/model/net.lua new file mode 100644 index 0000000..725c543 --- /dev/null +++ b/acf/model/net.lua @@ -0,0 +1,88 @@ +--[[ +Copyright (c) 2012-2013 Kaarle Ritvanen +See LICENSE file for license details +--]] + +module(..., package.seeall) + +local raise = require('acf.error').raise +local Union = require('acf.model.combination').Union + +local fld = require('acf.model.field') +local String = fld.String + +local object = require('acf.object') +local class = object.class +local super = object.super + +local update = require('acf.util').update + + +require 'stringy' + + +IPv4Address = class(String) + +function IPv4Address:validate(context, value) + super(self, IPv4Address):validate(context, value) + local function test(...) + if #arg ~= 4 then return true end + for _, octet in ipairs(arg) do + if tonumber(octet) > 255 then return true end + end + end + if test(string.match(value, '^(%d+)%.(%d+)%.(%d+)%.(%d+)$')) then + raise(context.path, 'Invalid IPv4 address') + end +end + + +IPv6Address = class(String) + +function IPv6Address:validate(context, value) + super(self, IPv6Address):validate(context, value) + + local function invalid() raise(context.path, 'Invalid IPv6 address') end + + if value == '' then invalid() end + + local comps = stringy.split(value, ':') + if #comps < 3 then invalid() end + + local function collapse(i, ofs) + if comps[i] > '' then return end + if comps[i + ofs] > '' then invalid() end + table.remove(comps, i) + end + collapse(1, 1) + collapse(#comps, -1) + if #comps > 8 then invalid() end + + local short = false + for _, comp in ipairs(comps) do + if comp == '' then + if short then invalid() end + short = true + elseif not string.match(comp, '^%x%x?%x?%x?$') then invalid() end + end + if not short and #comps < 8 then invalid() end +end + + +IPAddress = class(Union) + +function IPAddress:init(params) + super(self, IPAddress):init( + update( + params, {types={IPv4Address, IPv6Address}, error='Invalid IP address'} + ) + ) +end + + +Port = class(fld.Integer) + +function Port:validate(context, value) + super(self, Port):validate(context, value) + if value < 0 or value > 65535 then raise(context.path, 'Invalid port') end +end |