--[[ 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 ( short and #comps == 3 and comps[2] == '' ) or (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