From 0afbe3d13b67d439177ae23a4f60028b91cc7687 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Wed, 5 Jun 2019 20:52:37 +0200 Subject: [PATCH] add validation tests Signed-off-by: Michael Kaufmann --- lib/Froxlor/Database/Database.php | 15 +++++ lib/Froxlor/Validate/Validate.php | 105 ++++++++++++------------------ tests/Froxlor/ValidateTest.php | 99 ++++++++++++++++++++++++++++ 3 files changed, 157 insertions(+), 62 deletions(-) diff --git a/lib/Froxlor/Database/Database.php b/lib/Froxlor/Database/Database.php index 466a948e..ccf5ad3b 100644 --- a/lib/Froxlor/Database/Database.php +++ b/lib/Froxlor/Database/Database.php @@ -183,6 +183,21 @@ class Database return $return; } + /** + * return number of characters that are allowed to use as username + * + * @return int + */ + public static function getSqlUsernameLength() + { + // MySQL user names can be up to 32 characters long (16 characters before MySQL 5.7.8). + $mysql_max = 32; + if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '5.7.8', '<')) { + $mysql_max -= 16; + } + return $mysql_max; + } + /** * let's us interact with the PDO-Object by using static * call like "Database::function()" diff --git a/lib/Froxlor/Validate/Validate.php b/lib/Froxlor/Validate/Validate.php index 2a767fe6..3e77b595 100644 --- a/lib/Froxlor/Validate/Validate.php +++ b/lib/Froxlor/Validate/Validate.php @@ -124,10 +124,8 @@ class Validate * * @param string $url * URL to be tested + * * @return bool - * @author Christian Hoffmann - * @author Froxlor team (2010-) - * */ public static function validateUrl($url) { @@ -148,31 +146,7 @@ class Validate return true; } - // not an fqdn - if (strtolower(substr($url, 0, 7)) == "http://" || strtolower(substr($url, 0, 8)) == "https://") { - if (strtolower(substr($url, 0, 7)) == "http://") { - $ip = strtolower(substr($url, 7)); - } - - if (strtolower(substr($url, 0, 8)) == "https://") { - $ip = strtolower(substr($url, 8)); - } - - $ip = substr($ip, 0, strpos($ip, '/')); - // possible : in IP (when a port is given), #1173 - // but only if there actually IS ONE - if (strpos($ip, ':') !== false) { - $ip = substr($ip, 0, strpos($ip, ':')); - } - - if (\Froxlor\Validate\Validate::validate_ip2($ip, true) !== false) { - return true; - } else { - return false; - } - } else { - return false; - } + return false; } /** @@ -210,7 +184,7 @@ class Validate */ public static function validateLocalHostname($hostname) { - $pattern = '/^([a-zA-Z0-9\-])+$/i'; + $pattern = '/^[a-z0-9][a-z0-9\-]{0,62}$/i'; if (preg_match($pattern, $hostname)) { return $hostname; } @@ -233,52 +207,59 @@ class Validate /** * Returns if an username is in correct format or not. * - * @param - * string The username to check - * @return bool Correct or not - * @author Michael Duergner - * + * @param string $username + * The username to check + * @param bool $unix_names + * optional, default true, checks whether it must be UNIX compatible + * @param int $mysql_max + * optional, number of max mysql username characters, default empty + * + * @return bool */ public static function validateUsername($username, $unix_names = 1, $mysql_max = '') { + if (empty($mysql_max) || ! is_numeric($mysql_max) || $mysql_max <= 0) { + $mysql_max = \Froxlor\Database\Database::getSqlUsernameLength() - 1; + } else { + $mysql_max --; + } if ($unix_names == 0) { if (strpos($username, '--') === false) { - return (preg_match('/^[a-z][a-z0-9\-_]{0,' . (int) ($mysql_max - 1) . '}[a-z0-9]{1}$/Di', $username) != false); - } else { - return false; + return (preg_match('/^[a-z][a-z0-9\-_]{0,' . $mysql_max . '}[a-z0-9]{1}$/Di', $username) != false); } - } else { - return (preg_match('/^[a-z][a-z0-9]{0,' . $mysql_max . '}$/Di', $username) != false); + return false; } + return (preg_match('/^[a-z][a-z0-9]{0,' . $mysql_max . '}$/Di', $username) != false); } + /** + * validate sql interval string + * + * @param string $interval + * + * @return boolean + */ public static function validateSqlInterval($interval = null) { - if (! $interval === null || $interval != '') { - if (strstr($interval, ' ') !== false) { - /* - * [0] = ([0-9]+) - * [1] = valid SQL-Interval expression - */ - $valid_expr = array( - 'SECOND', - 'MINUTE', - 'HOUR', - 'DAY', - 'WEEK', - 'MONTH', - 'YEAR' - ); + if (! empty($interval) && strstr($interval, ' ') !== false) { + /* + * [0] = ([0-9]+) + * [1] = valid SQL-Interval expression + */ + $valid_expr = array( + 'SECOND', + 'MINUTE', + 'HOUR', + 'DAY', + 'WEEK', + 'MONTH', + 'YEAR' + ); - $interval_parts = explode(' ', $interval); + $interval_parts = explode(' ', $interval); - if (is_array($interval_parts) && isset($interval_parts[0]) && isset($interval_parts[1])) { - if (preg_match('/([0-9]+)/i', $interval_parts[0])) { - if (in_array(strtoupper($interval_parts[1]), $valid_expr)) { - return true; - } - } - } + if (count($interval_parts) == 2 && preg_match('/[0-9]+/', $interval_parts[0]) && in_array(strtoupper($interval_parts[1]), $valid_expr)) { + return true; } } return false; diff --git a/tests/Froxlor/ValidateTest.php b/tests/Froxlor/ValidateTest.php index 0c7edb15..a47dba82 100644 --- a/tests/Froxlor/ValidateTest.php +++ b/tests/Froxlor/ValidateTest.php @@ -8,6 +8,7 @@ use Froxlor\Validate\Validate; * @covers \Froxlor\Validate\Validate * @covers \Froxlor\UI\Response * @covers \Froxlor\FroxlorLogger + * @covers \Froxlor\Idna\IdnaWrapper */ class ValidateTest extends TestCase { @@ -97,4 +98,102 @@ class ValidateTest extends TestCase $this->expectExceptionCode(400); Validate::validate_ip2("127.0.0.2", false, 'invalidip', true, false, false, true); } + + public function testValidateUrl() + { + $result = Validate::validateUrl("https://froxlor.org/"); + $this->assertTrue($result); + $result = Validate::validateUrl("http://forum.froxlor.org/"); + $this->assertTrue($result); + $result = Validate::validateUrl("https://api.froxlor.org/doc/0.10.0/index.php"); + $this->assertTrue($result); + $result = Validate::validateUrl("#froxlor"); + $this->assertFalse($result); + $result = Validate::validateUrl("https://82.149.225.211/"); + $this->assertTrue($result); + $result = Validate::validateUrl("https://82.149.225.300"); + $this->assertFalse($result); + $result = Validate::validateUrl("82.149.225.211:443"); + $this->assertTrue($result); + } + + public function testValidateDomain() + { + $result = Validate::validateDomain('froxlor.org'); + $this->assertEquals('froxlor.org', $result); + $result = Validate::validateDomain('_dmarc.froxlor.org'); + $this->assertFalse($result); + $result = Validate::validateDomain('_dmarc.froxlor.org', true); + $this->assertEquals('_dmarc.froxlor.org', $result); + $result = Validate::validateDomain('test._dmarc.froxlor.org', true); + $this->assertEquals('test._dmarc.froxlor.org', $result); + $result = Validate::validateDomain('0815'); + $this->assertFalse($result); + $result = Validate::validateDomain('abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz'); + $this->assertFalse($result); + } + + public function testValidateHostname() + { + $result = Validate::validateLocalHostname('localhost'); + $this->assertEquals('localhost', $result); + $result = Validate::validateLocalHostname('froxlor-srv02'); + $this->assertEquals('froxlor-srv02', $result); + $result = Validate::validateLocalHostname('froxlor_org'); + $this->assertFalse($result); + $result = Validate::validateLocalHostname('froxlor.org'); + $this->assertFalse($result); + $result = Validate::validateLocalHostname('a--------------------------------------------------------------'); + $this->assertEquals('a--------------------------------------------------------------', $result); + $result = Validate::validateLocalHostname('-hostname'); + $this->assertFalse($result); + $result = Validate::validateLocalHostname('a-----------------------------------------------------------------'); + $this->assertFalse($result); + } + + public function testValidateEmail() + { + $result = Validate::validateEmail('team@froxlor.org'); + $this->assertEquals('team@froxlor.org', $result); + $result = Validate::validateEmail('team.froxlor.org'); + $this->assertFalse($result); + } + + public function testValidateUsername() + { + $result = Validate::validateUsername('web123sql2'); + $this->assertTrue($result); + $mysql_max = \Froxlor\Database\Database::getSqlUsernameLength() - strlen(\Froxlor\Settings::Get('customer.mysqlprefix')); + $result = Validate::validateUsername('web123sql2', true, $mysql_max); + $this->assertTrue($result); + // too long + $result = Validate::validateUsername('myperfectsuperduperwebuser123sql2', true, $mysql_max); + $this->assertFalse($result); + // not unix-conform + $result = Validate::validateUsername('web123-sql2', true, $mysql_max); + $this->assertFalse($result); + // non-unix-conform + $result = Validate::validateUsername('web123-sql2', false, $mysql_max); + $this->assertTrue($result); + $result = Validate::validateUsername('web123--sql2', false, $mysql_max); + $this->assertFalse($result); + $result = Validate::validateUsername('-web123sql2', false, $mysql_max); + $this->assertFalse($result); + $result = Validate::validateUsername('web123sql2-', false, $mysql_max); + $this->assertFalse($result); + } + + public function testValidateSqlInterval() + { + $result = Validate::validateSqlInterval('60 HOUR'); + $this->assertTrue($result); + $result = Validate::validateSqlInterval('2 MONTH'); + $this->assertTrue($result); + $result = Validate::validateSqlInterval(); + $this->assertFalse($result); + $result = Validate::validateSqlInterval('2 QUARTER'); + $this->assertFalse($result); + $result = Validate::validateSqlInterval('1DAY'); + $this->assertFalse($result); + } }