mirror of
https://github.com/lucaspalomodevelop/core.git
synced 2026-03-13 08:09:41 +00:00
MVC: Add IPPortField type (#7134)
Useful for Netflow and plugins. Tests included.
This commit is contained in:
parent
587375aaed
commit
8846037d93
2
plist
2
plist
@ -531,6 +531,7 @@
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Base/FieldTypes/DescriptionField.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Base/FieldTypes/EmailField.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Base/FieldTypes/HostnameField.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Base/FieldTypes/IPPortField.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Base/FieldTypes/IntegerField.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Base/FieldTypes/InterfaceField.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Base/FieldTypes/JsonKeyValueStoreField.php
|
||||
@ -845,6 +846,7 @@
|
||||
/usr/local/opnsense/mvc/tests/app/models/OPNsense/Base/FieldTypes/CertificateFieldTest/config.xml
|
||||
/usr/local/opnsense/mvc/tests/app/models/OPNsense/Base/FieldTypes/CountryFieldTest.php
|
||||
/usr/local/opnsense/mvc/tests/app/models/OPNsense/Base/FieldTypes/Field_Framework_TestCase.php
|
||||
/usr/local/opnsense/mvc/tests/app/models/OPNsense/Base/FieldTypes/IPPortFieldTest.php
|
||||
/usr/local/opnsense/mvc/tests/app/models/OPNsense/Base/FieldTypes/IntegerFieldTest.php
|
||||
/usr/local/opnsense/mvc/tests/app/models/OPNsense/Base/FieldTypes/InterfaceFieldTest.php
|
||||
/usr/local/opnsense/mvc/tests/app/models/OPNsense/Base/FieldTypes/InterfaceFieldTest/config.xml
|
||||
|
||||
@ -0,0 +1,149 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2024 Deciso B.V.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
namespace OPNsense\Base\FieldTypes;
|
||||
|
||||
use OPNsense\Base\Validators\CallbackValidator;
|
||||
use OPNsense\Firewall\Util;
|
||||
|
||||
/**
|
||||
* Class IPPortField
|
||||
* @package OPNsense\Base\FieldTypes
|
||||
*/
|
||||
class IPPortField extends BaseField
|
||||
{
|
||||
/**
|
||||
* @var bool marks if this is a data node or a container
|
||||
*/
|
||||
protected $internalIsContainer = false;
|
||||
|
||||
/**
|
||||
* @var string when multiple values could be provided at once, specify the split character
|
||||
*/
|
||||
protected $internalFieldSeparator = ',';
|
||||
|
||||
/**
|
||||
* @var bool when set, results are returned as list (with all options enabled)
|
||||
*/
|
||||
protected $internalAsList = false;
|
||||
|
||||
/**
|
||||
* @var string Network family (ipv4, ipv6)
|
||||
*/
|
||||
protected $internalAddressFamily = null;
|
||||
|
||||
/**
|
||||
* trim IP-Port combination
|
||||
* @param string $value
|
||||
*/
|
||||
public function setValue($value)
|
||||
{
|
||||
parent::setValue(trim($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* get valid options, descriptions and selected value
|
||||
* @return array
|
||||
*/
|
||||
public function getNodeData()
|
||||
{
|
||||
if ($this->internalAsList) {
|
||||
// return result as list
|
||||
$result = array();
|
||||
foreach (explode($this->internalFieldSeparator, $this->internalValue) as $address) {
|
||||
$result[$address] = array("value" => $address, "selected" => 1);
|
||||
}
|
||||
return $result;
|
||||
} else {
|
||||
// normal, single field response
|
||||
return $this->internalValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* setter for address family
|
||||
* @param $value address family [ipv4, ipv6, empty for all]
|
||||
*/
|
||||
public function setAddressFamily($value)
|
||||
{
|
||||
$this->internalAddressFamily = trim(strtolower($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* select if multiple IP-Port combinations may be selected at once
|
||||
* @param $value string value Y/N
|
||||
*/
|
||||
public function setAsList($value)
|
||||
{
|
||||
$this->internalAsList = trim(strtoupper($value)) == "Y";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function defaultValidationMessage()
|
||||
{
|
||||
return gettext('Invalid IP-port combination.');
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve field validators for this field type
|
||||
* @return array returns validators
|
||||
*/
|
||||
public function getValidators()
|
||||
{
|
||||
$validators = parent::getValidators();
|
||||
if ($this->internalValue != null) {
|
||||
$validators[] = new CallbackValidator(["callback" => function ($data) {
|
||||
foreach ($this->internalAsList ? explode($this->internalFieldSeparator, $data) : [$data] as $value) {
|
||||
if ($this->internalAddressFamily == 'ipv4' || $this->internalAddressFamily == null) {
|
||||
$parts = explode(':', $value);
|
||||
if (count($parts) == 2 && Util::isIpv4Address($parts[0]) && Util::isPort($parts[1])) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->internalAddressFamily == 'ipv6' || $this->internalAddressFamily == null) {
|
||||
$parts = preg_split('/\[([^\]]+)\]/', $value, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
|
||||
if (count($parts) == 2 &&
|
||||
Util::isIpv6Address($parts[0]) &&
|
||||
str_contains($parts[1], ':') &&
|
||||
Util::isPort(trim($parts[1], ': '))) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return ["\"" . $value . "\" is invalid. " . $this->getValidationMessage()];
|
||||
}
|
||||
}]);
|
||||
}
|
||||
|
||||
return $validators;
|
||||
}
|
||||
}
|
||||
@ -24,10 +24,9 @@
|
||||
<v9>v9</v9>
|
||||
</OptionValues>
|
||||
</version>
|
||||
<targets type="CSVListField">
|
||||
<Mask>/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?):(6553[0-5]|655[0-2][0-9]|65[0-4]\d{2}|6[0-4]\d{3}|[1-5]\d{4}|[1-9]\d{0,3})$/u</Mask>
|
||||
<ValidationMessage>Please enter valid targets (e.g. 192.168.0.1:2055).</ValidationMessage>
|
||||
<MaskPerItem>Y</MaskPerItem>
|
||||
<targets type="IPPortField">
|
||||
<AsList>Y</AsList>
|
||||
<AddressFamily>ipv4</AddressFamily>
|
||||
</targets>
|
||||
</capture>
|
||||
<collect>
|
||||
|
||||
@ -0,0 +1,152 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2024 Deciso B.V.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace tests\OPNsense\Base\FieldTypes;
|
||||
|
||||
// @CodingStandardsIgnoreStart
|
||||
require_once 'Field_Framework_TestCase.php';
|
||||
// @CodingStandardsIgnoreEnd
|
||||
|
||||
use OPNsense\Base\FieldTypes\IPPortField;
|
||||
|
||||
class IPPortFieldTest extends Field_Framework_TestCase
|
||||
{
|
||||
public function testCanBeCreated()
|
||||
{
|
||||
$this->assertInstanceOf('\OPNsense\Base\FieldTypes\IPPortField', new IPPortField());
|
||||
}
|
||||
|
||||
public function testRequiredEmpty()
|
||||
{
|
||||
$this->expectException(\Phalcon\Filter\Validation\Exception::class);
|
||||
$this->expectExceptionMessage("PresenceOf");
|
||||
$field = new IPPortField();
|
||||
$field->setRequired("Y");
|
||||
$field->setValue("");
|
||||
$this->validateThrow($field);
|
||||
}
|
||||
|
||||
public function testNotRequiredEmpty()
|
||||
{
|
||||
$field = new IPPortField();
|
||||
$field->setValue("");
|
||||
$this->assertEmpty($this->validate($field));
|
||||
}
|
||||
|
||||
public function testRequiredNotEmpty()
|
||||
{
|
||||
$field = new IPPortField();
|
||||
$field->setRequired("Y");
|
||||
$field->setValue("127.0.0.1:2056");
|
||||
$this->assertEmpty($this->validate($field));
|
||||
}
|
||||
|
||||
public function testValidValueIpv4()
|
||||
{
|
||||
$field = new IPPortField();
|
||||
$field->setValue("127.0.0.1:2056");
|
||||
$this->assertEmpty($this->validate($field));
|
||||
}
|
||||
|
||||
public function testValidValueAsListIpv4()
|
||||
{
|
||||
$field = new IPPortField();
|
||||
$field->setAsList("Y");
|
||||
$field->setValue("127.0.0.1:2056,192.168.1.1:1111");
|
||||
$this->assertEmpty($this->validate($field));
|
||||
}
|
||||
|
||||
public function testValidValueIpv6()
|
||||
{
|
||||
$field = new IPPortField();
|
||||
$field->setValue("[::1]:2056");
|
||||
$this->assertEmpty($this->validate($field));
|
||||
}
|
||||
|
||||
public function testValidValueAsListIpv6()
|
||||
{
|
||||
$field = new IPPortField();
|
||||
$field->setAsList("Y");
|
||||
$field->setValue("[::1]:2056,[fe80::]:1111");
|
||||
$this->assertEmpty($this->validate($field));
|
||||
}
|
||||
|
||||
public function testInvalidValueIpv4()
|
||||
{
|
||||
$this->expectException(\Phalcon\Filter\Validation\Exception::class);
|
||||
$field = new IPPortField();
|
||||
$field->setValue("abcdefg");
|
||||
$this->validateThrow($field);
|
||||
}
|
||||
|
||||
public function testInvalidValueAsListIpv4()
|
||||
{
|
||||
$this->expectException(\Phalcon\Filter\Validation\Exception::class);
|
||||
$field = new IPPortField();
|
||||
$field->setAsList("Y");
|
||||
$field->setValue("127.0.0.1:2056,abcdefg");
|
||||
$this->validateThrow($field);
|
||||
}
|
||||
|
||||
public function testInvalidValueIpv6()
|
||||
{
|
||||
$this->expectException(\Phalcon\Filter\Validation\Exception::class);
|
||||
$field = new IPPortField();
|
||||
$field->setValue("[::1]");
|
||||
$this->validateThrow($field);
|
||||
}
|
||||
|
||||
public function testInvalidValueAsListIpv6()
|
||||
{
|
||||
$this->expectException(\Phalcon\Filter\Validation\Exception::class);
|
||||
$field = new IPPortField();
|
||||
$field->setAsList("Y");
|
||||
$field->setValue("[::1]:2056,[fe80::]");
|
||||
$this->validateThrow($field);
|
||||
}
|
||||
|
||||
public function testAddressFamilyIpv4()
|
||||
{
|
||||
$this->expectException(\Phalcon\Filter\Validation\Exception::class);
|
||||
$field = new IPPortField();
|
||||
$field->setAddressFamily("ipv4");
|
||||
$field->setValue("[::1]:2056");
|
||||
$this->validateThrow($field);
|
||||
}
|
||||
|
||||
public function testAddressFamilyIpv6()
|
||||
{
|
||||
$this->expectException(\Phalcon\Filter\Validation\Exception::class);
|
||||
$field = new IPPortField();
|
||||
$field->setAddressFamily("ipv6");
|
||||
$field->setValue("192.168.1.1:1111");
|
||||
$this->validateThrow($field);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user