8000 feature #17560 [Ldap] Improving the LDAP component (csarrazi) · symfony/symfony@7848a46 · GitHub
[go: up one dir, main page]

Skip to content

Commit 7848a46

Browse files
committed
feature #17560 [Ldap] Improving the LDAP component (csarrazi)
This PR was merged into the 3.1-dev branch. Discussion ---------- [Ldap] Improving the LDAP component | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | BC breaks? | yes | Deprecations? | no | Tests pass? | no | Fixed tickets | #14602 | License | MIT | Doc PR | not yet This PR will address a few issues mentioned in #14602. * [x] Integrate the Config component in order to simplify the client's configuration * [x] Separate Connection handling from the Client * [x] Support for multiple drivers * [x] Add functional tests * [x] Update Security component Commits ------- 34d3c85 Added compatibility layer for previous version of the Security component 81cb79b Improved the Ldap Component
2 parents 2d75718 + 34d3c85 commit 7848a46

37 files changed

+1394
-191
lines changed

.travis.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ addons:
66
apt_packages:
77
- parallel
88
- language-pack-fr-base
9+
- ldap-utils
10+
- slapd
911

1012
env:
1113
global:
@@ -48,6 +50,11 @@ before_install:
4850
- if [[ $deps != skip ]]; then composer self-update; fi;
4951
- if [[ $deps != skip ]]; then ./phpunit install; fi;
5052
- export PHPUNIT=$(readlink -f ./phpunit)
53+
- mkdir /tmp/slapd
54+
- slapd -f src/Symfony/Component/Ldap/Tests/Fixtures/conf/slapd.conf -h ldap://localhost:3389 &
55+
- sleep 3
56+
- ldapadd -h localhost:3389 -D cn=admin,dc=symfony,dc=com -w symfony -f src/Symfony/Component/Ldap/Tests/Fixtures/data/base.ldif
57+
- ldapadd -h localhost:3389 -D cn=admin,dc=symfony,dc=com -w symfony -f src/Symfony/Component/Ldap/Tests/Fixtures/data/fixtures.ldif
5158

5259
install:
5360
- if [[ $deps != skip ]]; then COMPONENTS=$(find src/Symfony -mindepth 3 -type f -name phpunit.xml.dist -printf '%h\n'); fi;

appveyor.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ install:
4343
- IF %PHP%==1 echo extension=php_mbstring.dll >> php.ini-max
4444
- IF %PHP%==1 echo extension=php_fileinfo.dll >> php.ini-max
4545
- IF %PHP%==1 echo extension=php_pdo_sqlite.dll >> php.ini-max
46-
- IF %PHP%==1 echo extension=php_ldap.dll >> php.ini-max
4746
- appveyor DownloadFile https://getcomposer.org/composer.phar
4847
- copy /Y php.ini-max php.ini
4948
- cd c:\projects\symfony
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Ldap\Adapter;
13+
14+
use Symfony\Component\OptionsResolver\Options;
15+
use Symfony\Component\OptionsResolver\OptionsResolver;
16+
17+
/**
18+
* @author Charles Sarrazin <charles@sarraz.in>
19+
*/
20+
abstract class AbstractConnection implements ConnectionInterface
21+
{
22+
protected $config;
23+
24+
public function __construct(array $config = array())
25+
{
26+
$resolver = new OptionsResolver();
27+
$resolver->setDefaults(array(
28+
'host' => null,
29+
'port' => 389,
30+
'version' => 3,
31+
'useSsl' => false,
32+
'useStartTls' => false,
33+
'optReferrals' => false,
34+
));
35+
$resolver->setNormalizer('host', function (Options $options, $value) {
36+
if ($value && $options['useSsl']) {
37+
return 'ldaps://'.$value;
38+
}
39+
40+
return $value;
41+
});
42+
43+
$this->config = $resolver->resolve($config);
44+
}
45+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Ldap\Adapter;
13+
14+
use Symfony\Component\OptionsResolver\Options;
15+
use Symfony\Component\OptionsResolver\OptionsResolver;
16+
17+
/**
18+
* @author Charles Sarrazin <charles@sarraz.in>
19+
*/
20+
abstract class AbstractQuery implements QueryInterface
21+
{
22+
protected $connection;
23+
protected $dn;
24+
protected $query;
25+
protected $options;
26+
27+
public function __construct(ConnectionInterface $connection, $dn, $query, array $options = array())
28+
{
29+
$resolver = new OptionsResolver();
30+
$resolver->setDefaults(array(
31+
'filter' => '*',
32+
'maxItems' => 0,
33+
'sizeLimit' => 0,
34+
'timeout' => 0,
35+
'deref' => static::DEREF_NEVER,
36+
'attrsOnly' => 0,
37+
));
38+
$resolver->setAllowedValues('deref', array(static::DEREF_ALWAYS, static::DEREF_NEVER, static::DEREF_FINDING, static::DEREF_SEARCHING));
39+
$resolver->setNormalizer('filter', function (Options $options, $value) {
40+
return is_array($value) ? $value : array($value);
41+
});
42+
43+
$this->connection = $connection;
44+
$this->dn = $dn;
45+
$this->query = $query;
46+
$this->options = $resolver->resolve($options);
47+
}
48+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Ldap\Adapter;
13+
14+
/**
15+
* @author Charles Sarrazin <charles@sarraz.in>
16+
*/
17+
interface AdapterInterface
18+
{
19+
/**
20+
* Returns the current connection.
21+
*
22+
* @return ConnectionInterface
23+
*/
24+
public function getConnection();
25+
26+
/**
27+
* Creates a new Query.
28+
*
29+
* @param $dn
30+
* @param $query
31+
* @param array $options
32+
*
33+
* @return QueryInterface
34+
*/
35+
public function createQuery($dn, $query, array $options = array());
36+
37+
/**
38+
* Escape a string for use in an LDAP filter or DN.
39+
*
40+
* @param string $subject
41+
* @param string $ignore
42+
* @param int $flags
43+
*
44+
* @return string
45+
*/
46+
public function escape($subject, $ignore = '', $flags = 0);
47+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Ldap\Adapter;
13+
14+
use Symfony\Component\Ldap\Entry;
15+
16+
/**
17+
* @author Charles Sarrazin <charles@sarraz.in>
18+
*/
19+
interface CollectionInterface extends \Countable, \IteratorAggregate, \ArrayAccess
20+
{
21+
/**
22+
* @return Entry[]
23+
*/
24+
public function toArray();
25+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Ldap\Adapter;
13+
14+
/**
15+
* @author Charles Sarrazin <charles@sarraz.in>
16+
*/
17+
interface ConnectionInterface
18+
{
19+
/**
20+
* Checks whether the connection was already bound or not.
21+
*
22+
* @return bool
23+
*/
24+
public function isBound();
25+
26+
/**
27+
* Binds the connection against a DN and password.
28+
*
29+
* @param string $dn The user's DN
30+
* @param string $password The associated password
31+
*/
32+
public function bind($dn = null, $password = null);
33+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Ldap\Adapter\ExtLdap;
13+
14+
use Symfony\Component\Ldap\Adapter\AdapterInterface;
15+
use Symfony\Component\Ldap\Exception\LdapException;
16+
17+
/**
18+
* @author Charles Sarrazin <charles@sarraz.in>
19+
*/
20+
class Adapter implements AdapterInterface
21+
{
22+
private $config;
23+
private $connection;
24+
25+
public function __construct(array $config = array())
26+
{
27+
if (!extension_loaded('ldap')) {
28+
throw new LdapException('The LDAP PHP extension is not enabled.');
29+
}
30+
31+
$this->config = $config;
32+
}
33+
34+
/**
35+
* {@inheritdoc}
36+
*/
37+
public function getConnection()
38+
{
39+
if (null === $this->connection) {
40+
$this->connection = new Connection($this->config);
41+
}
42+
43+
return $this->connection;
44+
}
45+
46+
/**
47+
* {@inheritdoc}
48+
*/
49+
public function createQuery($dn, $query, array $options = array())
50+
{
51+
return new Query($this->getConnection(), $dn, $query, $options);
52+
}
53+
54+
/**
55+
* {@inheritdoc}
56+
*/
57+
public function escape($subject, $ignore = '', $flags = 0)
58+
{
59+
$value = ldap_escape($subject, $ignore, $flags);
60+
61+
// Per RFC 4514, leading/trailing spaces should be encoded in DNs, as well as carriage returns.
62+
if ((int) $flags & LDAP_ESCAPE_DN) {
63+
if (!empty($value) && $value[0] === ' ') {
64+
$value = '\\20'.substr($value, 1);
65+
}
66+
if (!empty($value) && $value[strlen($value) - 1] === ' ') {
67+
$value = substr($value, 0, -1).'\\20';
68+
}
69+
$value = str_replace("\r", '\0d', $value);
70+
}
71+
72+
return $value;
73+
}
74+
}

0 commit comments

Comments
 (0)
0