Commit f5652245 authored by bmortier's avatar bmortier

Merge branch '1.0.19-fixes'

parents 1d55ee80 03802b90
......@@ -203,3 +203,6 @@ documentation and additional help.
* Martin Hamant <mh@ow2.org>
Adding DSA accounts into groups
* Mathias Soupault <mathias.soupault@inalco.fr>
Making supannAliasLogin usage possible in password recovery
FusionDirectory changelog
=========================
* FusionDirectory 1.0.20
[Fix] Bugs #5282: Documentation for Password Policy Plugin
[Fix] Bugs #5362: PHP errors related to ogroup
[Fix] FusionDirectory plugins - Bugs #5370: webservice doesn't provide a way to logout
[Feature] Bugs #5397: User is able to lock their own account
[Fix] Bugs #5410: edit conflict warning screen : "read only" button make the same page to reload
[Fix] Bugs #5422: There seems to be a problem with TimeAttribute
[Fix] Bugs #5426: Problems with PHP CAS on centos 7
[Feature] FusionDirectory plugins - Bugs #5437: argonaut-ldap2zone should be able to get data from a branch
[Feature] FusionDirectory plugins - Bugs #5438: we should add the directive check-names into the argonaut-dns service
[Fix] FusionDirectory plugins - Bugs #5442: Document fopen activation for argonaut plugin
[Feature] FusionDirectory plugins - Bugs #5443: argonaut ldap2zone should be able to create config for dns slave also, but not create the data
[Feature] FusionDirectory plugins - Bugs #5444: dropdown in systems on the dns tab
[Fix] FusionDirectory plugins - Bugs #5445: reorganize the argonaut dns plugin service
[Fix] FusionDirectory plugins - Bugs #5446: Error message when trying to update System name in the systems page
[Fix] Bugs #5448: Foreign keys from Services does not work
[Fix] FusionDirectory plugins - Bugs #5452: Error when reloading dhcp service through FD
[Fix] FusionDirectory plugins - Bugs #5457: Error modifynig DNS settings in the system's DNS tab
[Feature] Wishlist #5424: Mail alternatif pour la récupération de mot de passe quand supann est activé
[Feature] Wishlist #5425: Utiliser le supannAliasLogin dans les messages et les vues de récupération de mot de passe
[Feature] Wishlist #5456: Fine grain ACL control
* FusionDirectory 1.0.19
[Fix] Bugs #5303: When clicking on login from user selection we end up in user edition
......
......@@ -1472,7 +1472,7 @@ sub migrate_dhcp {
);
$result->code && die "Migration of DHCP configuration entry failed, LDAP error: ".$result->error."\n";
my $configDn = "$rdn,$dhcprdn,$entrybase";
my $configDn = "$rdn-$systemcn,$dhcprdn,$entrybase";
# Add DHCP service on server
$mesg = $ldap->search(
......
This diff is collapsed.
......@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "FUSIONDIRECTORY-INSERT-SCHEMA 1"
.TH FUSIONDIRECTORY-INSERT-SCHEMA 1 "2017-01-19" "FusionDirectory 1.0.19" "FusionDirectory Documentation"
.TH FUSIONDIRECTORY-INSERT-SCHEMA 1 "2017-01-23" "FusionDirectory 1.0.20" "FusionDirectory Documentation"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
......
......@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "FUSIONDIRECTORY-SETUP 1"
.TH FUSIONDIRECTORY-SETUP 1 "2017-01-19" "FusionDirectory 1.0.19" "FusionDirectory Documentation"
.TH FUSIONDIRECTORY-SETUP 1 "2017-03-29" "FusionDirectory 1.0.20" "FusionDirectory Documentation"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
......
......@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "FUSIONDIRECTORY.CONF 1"
.TH FUSIONDIRECTORY.CONF 1 "2016-11-02" "FusionDirectory 1.0.19" "FusionDirectory Documentation"
.TH FUSIONDIRECTORY.CONF 1 "2017-03-29" "FusionDirectory 1.0.20" "FusionDirectory Documentation"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
......
......@@ -580,6 +580,12 @@ attributetype ( 1.3.6.1.4.1.38414.8.110.9 NAME 'fdPasswordRecoveryUseAlternate'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.38414.8.110.10 NAME 'fdPasswordRecoveryLoginAttribute'
DESC 'Fusion Directory - Password recovery login attribute (usually uid)'
EQUALITY caseExactIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
SINGLE-VALUE )
# Object Class
objectclass ( 1.3.6.1.4.1.38414.8.2.1 NAME 'fusionDirectoryConf'
......@@ -627,7 +633,7 @@ objectclass ( 1.3.6.1.4.1.38414.8.2.3 NAME 'fdPasswordRecoveryConf'
fdPasswordRecoveryMailSubject $ fdPasswordRecoveryMailBody $
fdPasswordRecoveryMail2Subject $ fdPasswordRecoveryMail2Body $
fdPasswordRecoveryValidity $ fdPasswordRecoverySalt $
fdPasswordRecoveryUseAlternate
fdPasswordRecoveryUseAlternate $ fdPasswordRecoveryLoginAttribute
) )
# Dashboard Object Class
......
......@@ -5,8 +5,8 @@
# Attributes
attributetype ( 1.3.6.1.4.1.38414.38.1.1 NAME 'fdTemplateField'
DESC 'FusionDirectory - template field'
EQUALITY caseExactMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
EQUALITY octetStringMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.40)
# Objectclasses
objectclass (1.3.6.1.4.1.38414.38.2.1 NAME 'fdTemplate'
......
......@@ -237,7 +237,8 @@ class standAlonePage {
}
class passwordRecovery extends standAlonePage {
var $uid;
protected $loginAttribute;
protected $login;
var $message = array();
var $email_address;
......@@ -266,19 +267,19 @@ class passwordRecovery extends standAlonePage {
{
parent::__construct($interactive);
if (isset($_GET['email_address']) && $_GET['email_address'] != "") {
if (isset($_GET['email_address']) && ($_GET['email_address'] != '')) {
$this->email_address = validate($_GET['email_address']);
} elseif (isset($_POST['email_address'])) {
$this->email_address = validate($_POST['email_address']);
}
/* Check for selected user... */
if (isset($_GET['uid']) && $_GET['uid'] != "") {
$this->uid = validate($_GET['uid']);
} elseif (isset($_POST['uid'])) {
$this->uid = validate($_POST['uid']);
if (isset($_GET['login']) && $_GET['login'] != '') {
$this->login = validate($_GET['login']);
} elseif (isset($_POST['login'])) {
$this->login = validate($_POST['login']);
} else {
$this->uid = '';
$this->login = '';
}
}
......@@ -289,7 +290,7 @@ class passwordRecovery extends standAlonePage {
}
/* Got a formular answer, validate and try to log in */
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if (session::global_is_set('_LAST_PAGE_REQUEST')) {
session::global_set('_LAST_PAGE_REQUEST', time());
}
......@@ -307,7 +308,7 @@ class passwordRecovery extends standAlonePage {
$this->step3();
}
}
} elseif ($_SERVER["REQUEST_METHOD"] == "GET") {
} elseif ($_SERVER['REQUEST_METHOD'] == 'GET') {
if (isset($_GET['uniq'])) {
$this->step4();
}
......@@ -373,6 +374,8 @@ class passwordRecovery extends standAlonePage {
$this->usealternates = $config->get_cfg_value('passwordRecoveryUseAlternate');
$this->loginAttribute = $config->get_cfg_value('passwordRecoveryLoginAttribute', 'uid');
@DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $config->get_cfg_value('passwordRecoveryActivated'), "passwordRecoveryActivated");
return ($config->get_cfg_value('passwordRecoveryActivated') == "TRUE");
}
......@@ -400,16 +403,16 @@ class passwordRecovery extends standAlonePage {
fusiondirectory_log("Created token branch ".$token);
}
$dn = "ou=".$this->uid.",$token";
$dn = 'ou='.$this->login.','.$token;
$ldap->cat($dn, array('dn'));
$add = ($ldap->count() == 0);
/* We store the token and its validity due date */
$attrs = array(
'objectClass' => array('organizationalUnit'),
'ou' => $this->uid,
'userPassword' => $sha1_temp_password,
'description' => time() + $this->delay_allowed * 60,
);
'objectClass' => array('organizationalUnit'),
'ou' => $this->login,
'userPassword' => $sha1_temp_password,
'description' => time() + $this->delay_allowed * 60,
);
$ldap->cd($dn);
if ($add) {
$ldap->add($attrs);
......@@ -435,7 +438,7 @@ class passwordRecovery extends standAlonePage {
$ldap = $config->get_ldap_link();
$token = get_ou('recoveryTokenRDN').get_ou('fusiondirectoryRDN').$config->current['BASE'];
$dn = "ou=".$this->uid.",$token";
$dn = 'ou='.$this->login.','.$token;
$ldap->cat($dn);
$attrs = $ldap->fetch();
......@@ -460,15 +463,15 @@ class passwordRecovery extends standAlonePage {
if (class_available('supannAccount') && ($config->get_cfg_value('supannPasswordRecovery', 'TRUE') == 'TRUE')) {
$objectClasses[] = 'supannPerson';
}
$filter = '(&(|(objectClass='.join(')(objectClass=', $objectClasses).'))(uid='.$this->uid.'))';
$filter = '(&(|(objectClass='.join(')(objectClass=', $objectClasses).'))('.$this->loginAttribute.'='.ldap_escape_f($this->login).'))';
$ldap->cd($config->current['BASE']);
$ldap->search($filter, array('dn'));
if ($ldap->count() < 1) {
$this->message[] = sprintf(_('Did not find an account with login "%s"'), $this->uid);
$this->message[] = sprintf(_('Did not find an account with login "%s"'), $this->login);
return;
} elseif ($ldap->count() > 1) {
$this->message[] = sprintf(_('Found multiple accounts with login "%s"'), $this->uid);
$this->message[] = sprintf(_('Found multiple accounts with login "%s"'), $this->login);
return;
}
......@@ -477,28 +480,29 @@ class passwordRecovery extends standAlonePage {
return $attrs['dn'];
}
/* find the uid of for the given email address */
/* Find the login of for the given email address */
function step2()
{
global $config;
/* Search uid corresponding to the mail */
/* Search login corresponding to the mail */
$address_escaped = ldap_escape_f($this->email_address);
if ($this->usealternates) {
$filter = '(&(objectClass=gosaMailAccount)(|(mail='.$this->email_address.')(gosaMailAlternateAddress='.$this->email_address.')))';
$filter = '(&(objectClass=gosaMailAccount)(|(mail='.$address_escaped.')(gosaMailAlternateAddress='.$address_escaped.')))';
} else {
$filter = '(&(objectClass=gosaMailAccount)(mail='.$this->email_address.'))';
$filter = '(&(objectClass=gosaMailAccount)(mail='.$address_escaped.'))';
}
if (class_available('personalInfo') && ($config->get_cfg_value('privateEmailPasswordRecovery', 'FALSE') == 'TRUE')) {
$filter = '(|'.$filter.'(&(objectClass=fdPersonalInfo)(fdPrivateMail='.$this->email_address.')))';
$filter = '(|'.$filter.'(&(objectClass=fdPersonalInfo)(fdPrivateMail='.$address_escaped.')))';
}
if (class_available('supannAccount') && ($config->get_cfg_value('supannPasswordRecovery', 'TRUE') == 'TRUE')) {
$filter = '(|'.$filter.'(&(objectClass=supannPerson)(supannMailPerso='.$this->email_address.')))';
$filter = '(|'.$filter.'(&(objectClass=supannPerson)(supannMailPerso='.$address_escaped.')))';
}
$ldap = $config->get_ldap_link();
$ldap->cd($config->current['BASE']);
$ldap->search($filter, array('dn', 'userPassword', 'uid'));
$ldap->search($filter, array('dn', 'userPassword', $this->loginAttribute));
/* Only one uid should be found */
/* Only one ldap node should be found */
if ($ldap->count() < 1) {
$this->message[] = sprintf(_('There is no account using email "%s"'), $this->email_address);
return;
......@@ -514,15 +518,15 @@ class passwordRecovery extends standAlonePage {
$this->message[] = sprintf(_('The user using email "%s" is locked. Please contact your administrator.'), $this->email_address);
return;
}
$this->uid = $attrs['uid'][0];
$this->login = $attrs[$this->loginAttribute][0];
$this->step = 2;
if ($this->interactive) {
$smarty = get_smarty();
$smarty->assign('uid', $this->uid);
$smarty->assign('login', $this->login);
$smarty->assign('email_address', $this->email_address);
$params = $this->encodeParams(array('uid', 'directory', 'email_address'));
$params = $this->encodeParams(array('login', 'directory', 'email_address'));
$smarty->assign('params', $params);
}
......@@ -554,14 +558,14 @@ class passwordRecovery extends standAlonePage {
}
$reinit_link = $this->getPageURL();
$reinit_link .= "?uniq=".urlencode($token);
$reinit_link .= "&uid=".urlencode($this->uid);
$reinit_link .= "&email_address=".urlencode($this->email_address);
$reinit_link .= '?uniq='.urlencode($token);
$reinit_link .= '&login='.urlencode($this->login);
$reinit_link .= '&email_address='.urlencode($this->email_address);
@DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $reinit_link, "Setting link to");
@DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $reinit_link, 'Setting link to');
/* Send the mail */
$mail_body = sprintf($this->mail_body, $this->uid, $reinit_link);
$mail_body = sprintf($this->mail_body, $this->login, $reinit_link);
if (mail_utf8($this->email_address, FALSE, $this->from_mail, $this->mail_subject, $mail_body)) {
$this->step = 3;
......@@ -570,7 +574,7 @@ class passwordRecovery extends standAlonePage {
}
$smarty = get_smarty();
$smarty->assign('uid', $this->uid);
$smarty->assign('login', $this->login);
}
/* check if the given token is the good one */
......@@ -588,8 +592,8 @@ class passwordRecovery extends standAlonePage {
$smarty->assign('uniq', $uniq_id_from_mail);
$this->uniq = $uniq_id_from_mail;
$this->step = 4;
$smarty->assign('uid', $this->uid);
$params = $this->encodeParams(array('uid', 'directory', 'email_address', 'uniq'));
$smarty->assign('login', $this->login);
$params = $this->encodeParams(array('login', 'directory', 'email_address', 'uniq'));
$smarty->assign('params', $params);
if (isset($_POST['change'])) {
......@@ -623,7 +627,7 @@ class passwordRecovery extends standAlonePage {
$userTabs->save_object();
$userTabs->save();
fusiondirectory_log('User '.$this->uid.' password has been changed');
fusiondirectory_log('User '.$this->login.' password has been changed');
return TRUE;
}
......@@ -637,7 +641,7 @@ class passwordRecovery extends standAlonePage {
}
/* Send the mail */
$mail_body = sprintf($this->mail2_body, $this->uid);
$mail_body = sprintf($this->mail2_body, $this->login);
if (mail_utf8($this->email_address, FALSE, $this->from_mail, $this->mail2_subject, $mail_body)) {
$smarty = get_smarty();
......
......@@ -113,9 +113,9 @@ if (isset($_REQUEST['signout']) && $_REQUEST['signout']) {
$config = session::global_get('config');
if ($config->get_cfg_value('casActivated') == 'TRUE') {
require_once('CAS.php');
/* Move CAS autoload before FD autoload */
spl_autoload_unregister('CAS_autoload');
spl_autoload_register('CAS_autoload', TRUE, TRUE);
/* Move FD autoload after CAS autoload */
spl_autoload_unregister('__fusiondirectory_autoload');
spl_autoload_register('__fusiondirectory_autoload');
phpCAS::client(
CAS_VERSION_2_0,
$config->get_cfg_value('casHost', 'localhost'),
......@@ -582,9 +582,9 @@ if ($config->get_cfg_value('httpAuthActivated') == 'TRUE') {
Index::authLoginProcess();
} elseif ($config->get_cfg_value('casActivated') == 'TRUE') {
require_once('CAS.php');
/* Move CAS autoload before FD autoload */
spl_autoload_unregister('CAS_autoload');
spl_autoload_register('CAS_autoload', TRUE, TRUE);
/* Move FD autoload after CAS autoload */
spl_autoload_unregister('__fusiondirectory_autoload');
spl_autoload_register('__fusiondirectory_autoload');
Index::casLoginProcess();
} elseif ($config->get_cfg_value('httpHeaderAuthActivated') == 'TRUE') {
Index::headerAuthLoginProcess();
......
......@@ -591,7 +591,7 @@ border-color: #ffd324;
color: #412701;
}
.success {
background: ##f3f4f4;
background: #f3f4f4;
color: #264409;
border-color: #f3f4f4;
}
......
......@@ -19,7 +19,7 @@
</div>
<div id="header-right">
<a><span class="optional">{t}Signed in:{/t} </span><b>{$username}</b></a>
{if ($sessionLifetime > 0)}
{if ($sessionLifetime >= 1)}
<div class="logout-label">
<canvas id="sTimeout" width="22" height="22" title="{$sessionLifetime}|{t}Session expires in %d!{/t}"></canvas>
</div>
......@@ -67,7 +67,7 @@
}
{/literal}
{if ($sessionLifetime > 0)}
{if ($sessionLifetime >= 1)}
logout.delay({$sessionLifetime});
{/if}
......
......@@ -12,7 +12,7 @@
background-image:url(images/opacity_black.png);">
{else}
{if $s_Trace != "" && $i_TraceCnt != 0}
{if $s_Trace != "" && $i_TraceCnt >= 1}
<div id="trace_{$i_ID}"
style="
display:none;
......@@ -49,7 +49,7 @@
{$s_Message}
</div>
<div class="plugbottom">
{if $s_Trace != "" && $i_TraceCnt != 0}
{if $s_Trace != "" && $i_TraceCnt >= 1}
<input type="button" id="Trace" name="Trace"
onClick="$('trace_{$i_ID}').toggle();" value="{t}Trace{/t}"/>
{/if}
......
......@@ -29,7 +29,7 @@
{if $step==3}
<p class="infotext">
{t 1=$uid 2=$email_address}Information to reset password for %1 has been sent to email address %2{/t}<br/>
{t 1=$login 2=$email_address}Information to reset password for %1 has been sent to email address %2{/t}<br/>
<span class="warning">{t 1=$delay_allowed}Warning : this email is only valid for %1 minutes.{/t}</span>
</p>
</div>
......@@ -52,9 +52,9 @@
</tr>
{/if}
<tr>
<td><label for="uid">{t}Login{/t}</label></td>
<td><label for="login">{t}Login{/t}</label></td>
<td>
<i>{$uid}</i>
<i>{$login}</i>
</td>
</tr>
<tr>
......@@ -138,7 +138,7 @@
<!-- Place cursor in email field -->
<script type="text/javascript">
<!-- // First input field on page
focus_field('error_accept','uid','directory','username','current_password','email_address');
focus_field('error_accept','login','directory','username','current_password','email_address');
next_msg_dialog();
-->
</script>
......
......@@ -142,7 +142,7 @@ class baseSelector {
{
global $config;
if (!isset($this->base) || ($this->base == "")) {
if (!isset($this->base) || ($this->base == '')) {
$this->lastState = FALSE;
return FALSE;
}
......@@ -179,7 +179,6 @@ class baseSelector {
}
}
}
}
/* Skip if there's no change */
......
......@@ -147,7 +147,7 @@ class management
function execute()
{
// Ensure that html posts and gets are kept even if we see a 'Entry islocked' dialog.
$vars = array('/^act$/','/^listing/','/^PID$/','/^FILTER_PID$/');
$vars = array('/^act$/','/^listing/','/^PID$/');
session::set('LOCK_VARS_TO_USE', $vars);
/* Display the copy & paste dialog, if it is currently open */
......
......@@ -22,9 +22,9 @@
class objects
{
/*!
* \brief Get list of object of objectType $type in $ou
* \brief Get list of object of objectTypes from $types in $ou
*
* \param string $type the objectType to list
* \param array $types the objectTypes to list
* \param mixed $attrs The attributes to fetch.
* If this is a single value, the resulting associative array will have for each dn the value of this attribute.
* If this is an array, the keys must be the wanted attributes, and the values can be either 1, '*' or 'raw'
......@@ -32,14 +32,36 @@ class objects
* Other values are considered to be 1.
* \param string $ou the LDAP branch to search in, base will be used if it is NULL
* \param string $filter an additional filter to use in the LDAP search.
* \param boolean $checkAcl should ACL be ignored or checked? Defaults to FALSE.
*
* \return The list of objects as an associative array (keys are dns)
*/
static function ls ($type, $attrs = NULL, $ou = NULL, $filter = '')
static function ls ($types, $attrs = NULL, $ou = NULL, $filter = '', $checkAcl = FALSE)
{
global $ui;
if (!is_array($types)) {
$types = array($types);
}
if ($checkAcl) {
if (count($types) > 1) {
throw new FusionDirectoryException('Cannot evaluate ACL for several types');
}
$infos = static::infos(reset($types));
$acl = $infos['aclCategory'].'/'.$infos['mainTab'];
}
if ($attrs === NULL) {
$infos = static::infos($type);
$attrs = $infos['mainAttr'];
$attrs = array();
foreach ($types as $type) {
$infos = static::infos($type);
$attrs[] = $infos['mainAttr'];
}
$attrs = array_unique($attrs);
if (count($attrs) == 1) {
$attrs = $attrs[0];
}
}
if (is_array($attrs)) {
......@@ -48,13 +70,16 @@ class objects
$search_attrs = array($attrs);
}
try {
$ldap = static::search($type, $search_attrs, $ou, $filter);
$ldap = static::search($types, $search_attrs, $ou, $filter);
} catch (NonExistingBranchException $e) {
return array();
}
$result = array();
while ($fetched_attrs = $ldap->fetch()) {
$key = $fetched_attrs['dn'];
if ($checkAcl && !preg_match('/r/', $ui->get_permissions($key, $acl))) {
continue;
}
if (is_array($attrs)) {
$result[$key] = array();
foreach ($attrs as $attr => $mode) {
......@@ -79,18 +104,18 @@ class objects
}
/*!
* \brief Get count of objects of objectType $type in $ou
* \brief Get count of objects of objectTypes from $types in $ou
*
* \param string $type the objectType to list
* \param array $types the objectTypes to list
* \param string $ou the LDAP branch to search in, base will be used if it is NULL
* \param string $filter an additional filter to use in the LDAP search.
*
* \return The number of objects of type $type in $ou
*/
static function count ($type, $ou = NULL, $filter = '')
static function count ($types, $ou = NULL, $filter = '')
{
try {
$ldap = static::search($type, array('dn'), $ou, $filter);
$ldap = static::search($types, array('dn'), $ou, $filter);
} catch (EmptyFilterException $e) {
return 0;
} catch (NonExistingBranchException $e) {
......@@ -99,16 +124,28 @@ class objects
return $ldap->count();
}
private static function search ($type, $search_attrs, $ou = NULL, $filter = '')
private static function search ($types, $search_attrs, $ou = NULL, $filter = '')
{
global $config;
if (!is_array($types)) {
$types = array($types);
}
if ($ou === NULL) {
$ou = $config->current['BASE'];
}
$infos = static::infos($type);
if ($infos['filter'] == '') {
$typeFilters = array();
foreach ($types as $type) {
$infos = static::infos($type);
if ($infos['filter'] == '') {
continue;
}
$typeFilters[] = $infos['filter'];
}
if (empty($typeFilters)) {
throw new EmptyFilterException();
}
......@@ -117,12 +154,12 @@ class objects
throw new NonExistingBranchException();
}
if (empty($filter)) {
$filter = $infos['filter'];
$filter = '(|'.implode($typeFilters).')';
} else {
if (!preg_match('/^\(.*\)$/', $filter)) {
$filter = '('.$filter.')';
}
$filter = '(&'.$filter.$infos['filter'].')';
$filter = '(&'.$filter.'(|'.implode($typeFilters).'))';
}
$ldap->cd($ou);
$ldap->search($filter, $search_attrs);
......
......@@ -252,6 +252,12 @@ class plugin
}
}
/* Used by prepare_save and template::apply */
public function mergeObjectClasses(array $oc)
{
return array_merge_unique($oc, $this->objectclasses);
}
protected function templateLoadAttrs($template_attrs)
{
$this->is_template = TRUE;
......@@ -459,7 +465,7 @@ class plugin
$is_new = empty($oc);
/* Load (minimum) attributes, add missing ones */
$this->attrs['objectClass'] = array_merge_unique($oc, $this->objectclasses);
$this->attrs['objectClass'] = $this->mergeObjectClasses($oc);
/* Copy standard attributes */
foreach ($this->attributes as $val) {
......@@ -924,6 +930,10 @@ class plugin
*/
static function tpl_parse_string($string, $attrs, $escapeMethod = NULL)
{
if (preg_match('/^%%/', $string)) {
/* Special case: %% at beginning of string means do not touch it. Used by binary attributes. */
return preg_replace('/^%%/', '', $string);
}
$offset = 0;
while (preg_match('/%([^%]+)%/', $string, $m, PREG_OFFSET_CAPTURE, $offset)) {
$replace = static::tpl_parse_mask($m[1][0], $attrs);
......@@ -1206,7 +1216,12 @@ class plugin
$ofield = $ref[1];
$filter = $ref[2];
$cinfos = pluglist::pluginInfos($class);
foreach ($cinfos['plObjectType'] as $key => $objectType) {
if (is_subclass_of($class, 'simpleService')) {
$objectTypes = array('server');
} else {
$objectTypes = $cinfos['plObjectType'];
}
foreach ($objectTypes as $key => $objectType) {
if (!is_numeric($key)) {
$objectType = $key;
}
......@@ -1275,11 +1290,12 @@ class plugin
// For each tab concerned
foreach ($tabRefs['refs'] as $tab => $fieldRefs) {
// If the tab is activated on this object