Commit 61263119 authored by Côme Chilliet's avatar Côme Chilliet
Browse files

feat(ldap) Improve code and documentation

issue #1
parent e326d919
Pipeline #8928 failed with stages
in 1 minute and 8 seconds
......@@ -11,5 +11,11 @@
"require": {},
"autoload": {
"psr-4": {"FusionDirectory\\Ldap\\": "src/FusionDirectory/Ldap"}
},
"require-dev": {
"phpstan/phpstan": "^0.12.56",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan-strict-rules": "^0.12.5",
"pepakriz/phpstan-exception-rules": "^0.11.2"
}
}
......@@ -65,7 +65,7 @@ class Acl
public function __construct (string $acl)
{
if (preg_match('/^{(\d+)}/', $acl, $m)) {
if (preg_match('/^{(\d+)}/', $acl, $m) !== 1) {
$this->index = (int)($m[1]);
$acl = substr($acl, strlen($m[0]));
}
......
......@@ -21,20 +21,20 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*! \class LdapGeneralizedTime
\brief LdapGeneralizedTime allows you to convert from and to LDAP GeneralizedTime format PHP DateTime objects
This class provides function to convert from LDAP GeneralizedTime to DateTime and the other way.
Please note that leap seconds will be lost as PHP has no support for it (see https://bugs.php.net/bug.php?id=70335). 01:60 will become 02:00.
Also, this class does not support fraction of hours or fraction of minutes (fraction of seconds are supported).
*/
declare(strict_types = 1);
namespace FusionDirectory\Ldap;
use DateTime, DateTimeZone;
/**
* LdapGeneralizedTime allows you to convert from and to LDAP GeneralizedTime format PHP DateTime objects
*
* This class provides function to convert from LDAP GeneralizedTime to DateTime and the other way.
* Please note that leap seconds will be lost as PHP has no support for it (see https://bugs.php.net/bug.php?id=70335).
* 01:60 will become 02:00.
* Also, this class does not support fraction of hours or fraction of minutes (fraction of seconds are supported).
*/
class GeneralizedTime
{
/**
......@@ -78,14 +78,14 @@ class GeneralizedTime
$timezone.
'$/';
if (preg_match($pattern, $string, $m)) {
if (empty($m['minute'])) {
if (preg_match($pattern, $string, $m) !== 1) {
if (!isset($m['minute']) || ($m['minute'] === '')) {
$m['minute'] = '00';
}
if (empty($m['second'])) {
if (!isset($m['second']) || ($m['second'] === '')) {
$m['second'] = '00';
}
if (empty($m['fraction'])) {
if (!isset($m['fraction']) || ($m['fraction'] === '')) {
$m['fraction'] = '0';
}
$date = new DateTime($m['year'].'-'.$m['month'].'-'.$m['day'].'T'.$m['hour'].':'.$m['minute'].':'.$m['second'].'.'.$m['fraction'].$m['timezone']);
......@@ -106,9 +106,9 @@ class GeneralizedTime
if ($setToUTC) {
$date->setTimezone(new DateTimeZone('UTC'));
}
$fraction = preg_replace('/0+$/', '', $date->format('u'));
$fraction = (preg_replace('/0+$/', '', $date->format('u')) ?? '');
$string = $date->format('YmdHis');
if (empty($fraction)) {
if ($fraction === '') {
return preg_replace('/(00){1,2}$/', '', $string).'Z';
} else {
return $string.'.'.$fraction.'Z';
......
......@@ -25,6 +25,9 @@ declare(strict_types = 1);
namespace FusionDirectory\Ldap;
/**
* This class handles an LDAP connection towards an LDAP server.
*/
class Link
{
/**
......@@ -40,17 +43,27 @@ class Link
*/
protected $tls;
/**
* Link constructor. Does not open the connection.
*
* @param string $hostname LDAP URI to use for ldap_connect
* @param bool $tls wether to use TLS
*/
public function __construct (string $hostname, bool $tls = FALSE)
{
$this->hostname = $hostname;
$this->tls = $tls;
}
/**
* Actually open the connection and bind to the LDAP server.
* Uses EXTERNAL for the bind.
*/
public function bind (): void
{
$cid = ldap_connect($this->hostname);
if (!$cid) {
if ($cid === FALSE) {
throw new Exception('Invalid URI: '.$this->hostname);
}
......@@ -67,8 +80,13 @@ class Link
}
/**
* @param array<string> $attrs
* @param array<array> $controls
* Perform an LDAP search
*
* @param string $basedn Base to search in
* @param string $filter Filter to use for the search
* @param array<string> $attrs Which attributes to fetch
* @param string $scope One of 'base','one' or 'subtree'
* @param array<array> $controls Controls to pass along with the search
*/
public function search (string $basedn, string $filter, array $attrs = [], string $scope = 'subtree', array $controls = NULL): Result
{
......@@ -89,8 +107,11 @@ class Link
}
/**
* @param array<string> $attrs
* @param array<array> $controls
* Add values to attributes on an existing entry. Adds attributes if needed.
*
* @param string $dn The LDAP node to modify
* @param array<string,string|array<string>> $attrs The attributes values to add
* @param array<array> $controls Controls to send along with the request
*/
public function mod_add (string $dn, array $attrs, array $controls = []): Result
{
......@@ -103,8 +124,11 @@ class Link
}
/**
* @param array<string> $attrs
* @param array<array> $controls
* Replaces values of attributes on an existing entry. Adds attributes if needed.
*
* @param string $dn The LDAP node to modify
* @param array<string,string|array<string>> $attrs The attributes values to replace
* @param array<array> $controls Controls to send along with the request
*/
public function mod_replace (string $dn, array $attrs, array $controls = []): Result
{
......@@ -117,8 +141,11 @@ class Link
}
/**
* @param array<string> $attrs
* @param array<array> $controls
* Delete values of attributes on an existing entry. Deletes attributes if needed.
*
* @param string $dn The LDAP node to modify
* @param array<string,string|array<string>> $attrs The attributes values to delete
* @param array<array> $controls Controls to send along with the request
*/
public function mod_del (string $dn, array $attrs, array $controls = []): Result
{
......@@ -131,7 +158,10 @@ class Link
}
/**
* @param array<array> $controls
* Delete an LDAP entry
*
* @param string $dn The LDAP node to delete
* @param array<array> $controls Controls to send along with the request
*/
public function delete (string $dn, array $controls = []): Result
{
......@@ -203,7 +233,7 @@ class Link
case 'MAY':
if ($name != '') {
$v = static::value2container($value);
if (in_array($name, ['MUST','MAY'])) {
if (in_array($name, ['MUST','MAY'], TRUE)) {
if ($v === TRUE) {
$v = [];
} else if (!is_array($v)) {
......@@ -229,7 +259,7 @@ class Link
protected static function value2container (string $value)
{
/* Set empty values to "TRUE" only */
if (preg_match('/^\s*$/', $value)) {
if (preg_match('/^\s*$/', $value) === 1) {
return TRUE;
}
......@@ -239,7 +269,7 @@ class Link
$value = rtrim($value);
/* Convert to array if $ is inside... */
if (preg_match('/\$/', $value)) {
if (preg_match('/\$/', $value) === 1) {
$container = preg_split('/\s*\$\s*/', $value);
if ($container === FALSE) {
throw new Exception('Failed to split value');
......
......@@ -81,7 +81,7 @@ class Result implements \Iterator,\Countable
{
if ($this->errcode != 0) {
$errmsg = $this->errmsg.' ('.$this->errcode.')';
if (!empty($this->matcheddn)) {
if (isset($this->matcheddn) && (strlen($this->matcheddn) > 0)) {
$errmsg .= '(matched dn: '.$this->matcheddn.')';
}
throw new Exception($errmsg);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment