diff --git a/conf/data/configs/application.ini b/conf/data/configs/application.ini index e533665..7651599 100644 --- a/conf/data/configs/application.ini +++ b/conf/data/configs/application.ini @@ -138,7 +138,7 @@ sign_me_auto = "DefaultOff" enable = On ; List of enabled plugins -enabled_list = "ynh-login-mapping" +enabled_list = "ynh-login-mapping,ynh-ldap-addressbooks" [defaults] ; Editor mode used by default (Plain, Html, HtmlForced or PlainForced) diff --git a/scripts/install b/scripts/install index 8d4feb1..db11b47 100644 --- a/scripts/install +++ b/scripts/install @@ -82,8 +82,8 @@ sudo cp ../conf/data/domains/disabled $rainloop_path/data/_data_/_default_/domai # now install ynh plugins: sudo mkdir -p $rainloop_path/data/_data_/_default_/plugins -sudo cp -rf ../sources/plugins/ynh-login-mapping $rainloop_path/data/_data_/_default_/plugins/. - +sudo cp -rf ../sources/plugins/ynh-login-mapping $rainloop_path/data/_data_/_default_/plugins/. +sudo cp -rf ../sources/plugins/ynh-ldap-addressbooks $rainloop_path/data/_data_/_default_/plugins/. # Hooks for domains are not implemented yet, so new domains will not be added automatically diff --git a/scripts/upgrade b/scripts/upgrade index d62d07b..e5c8335 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -32,7 +32,8 @@ sudo cp ../sources/patch/index_auto_version.php $rainloop_path/index.php # update ynh plugins: sudo mkdir -p $rainloop_path/data/_data_/_default_/plugins -sudo cp -rf ../sources/plugins/ynh-login-mapping $rainloop_path/data/_data_/_default_/plugins/. +sudo cp -rf ../sources/plugins/ynh-login-mapping $rainloop_path/data/_data_/_default_/plugins/. +sudo cp -rf ../sources/plugins/ynh-ldap-addressbooks $rainloop_path/data/_data_/_default_/plugins/. # update SSO and auto version if [ $final_path == $rainloop_path ] diff --git a/sources/plugins/ynh-ldap-addressbooks/README b/sources/plugins/ynh-ldap-addressbooks/README new file mode 100644 index 0000000..b6fece7 --- /dev/null +++ b/sources/plugins/ynh-ldap-addressbooks/README @@ -0,0 +1 @@ +Plugin which allows to suggess email from ynh ldap diff --git a/sources/plugins/ynh-ldap-addressbooks/VERSION b/sources/plugins/ynh-ldap-addressbooks/VERSION new file mode 100644 index 0000000..49d5957 --- /dev/null +++ b/sources/plugins/ynh-ldap-addressbooks/VERSION @@ -0,0 +1 @@ +0.1 diff --git a/sources/plugins/ynh-ldap-addressbooks/YnhLdapAddressbooks.php b/sources/plugins/ynh-ldap-addressbooks/YnhLdapAddressbooks.php new file mode 100644 index 0000000..314efee --- /dev/null +++ b/sources/plugins/ynh-ldap-addressbooks/YnhLdapAddressbooks.php @@ -0,0 +1,150 @@ +ldapSearch ( $oAccount, $sQuery, $iLimit ); + + $aResult = \RainLoop\Utils::RemoveSuggestionDuplicates($aResult); + if ($iLimit < \count($aResult)) { + $aResult = \array_slice($aResult, 0, $iLimit); + } + + return $aResult; + } + + /** + * + * OK search in ldap. + * match email or displayName... + * + * @param \RainLoop\Model\Account $oAccount + * @param string $sQuery + * + * @return array + */ + private function ldapSearch($oAccount, $sQuery, $iLimit) { + $sSearchEscaped = $this->escape($sQuery); + + $aResult = array(); + $oCon = @\ldap_connect(); + if (! $oCon) { + $this->oLogger->Write('YnhLdapAddressbooks: Could not connect to LDAP server', \MailSo\Log\Enumerations\Type::ERROR ); + return $aResult; + } + + @\ldap_set_option($oCon, LDAP_OPT_PROTOCOL_VERSION, 3 ); + + if (!ldap_bind($oCon)) { + // bizard... ca renvoie false.... mais ca marche.... + // $this->logLdapError ( $oCon, 'ldap_bind' ); + // $this->Manager()->Actions()->Logger()->Write('YnhLdapAdressbooks: Could not bind to LDAP server', \MailSo\Log\Enumerations\Type::ERROR); + // return $aResult; + } + + $this->oLogger->Write('YnhLdapAddressbooks: connected to LDAP', \MailSo\Log\Enumerations\Type::INFO, 'LDAP' ); + + $sSearchDn='dc=yunohost,dc=org'; + + // on veut chercher parmis mail et nom utilisateur... + $sFilter = '(&(objectClass=inetOrgPerson)'; + $sFilter .= '(|'; + $sFilter .= '(mail=*' . $sSearchEscaped . '*)'; + $sFilter .= '(displayName=*' . $sSearchEscaped . '*)'; + $sFilter .= '))'; + + $aItems = array ( 'mail', 'displayName'); + + $this->oLogger->Write('YnhLdapAddressbooks: ldap_search : '.$sSearchDn.' / '.$sFilter, \MailSo\Log\Enumerations\Type::INFO, 'LDAP' ); + + $oS = @\ldap_search($oCon, $sSearchDn, $sFilter, $aItems, 0, $iLimit, $iLimit); + if ($oS) { + $aEntries = @\ldap_get_entries($oCon, $oS); + $this->oLogger->Write('YnhLdapAddressbooks: ldap_search => '.var_export($aEntries), \MailSo\Log\Enumerations\Type::INFO, 'LDAP'); + if (is_array($aEntries)) { + if (isset ( $aEntries ['count'] )) { unset ( $aEntries ['count'] ); } + + foreach ( $aEntries as $aItem ) { + if ($aItem) { + $sEmail = \trim($aItem['mail'] [0] ); + $sName = \trim($aItem['displayname'] [0] ); + + if (!empty($sEmail)) { + $aResult[] = array($sEmail, $sName); + } + } + } + } else { + $this->logLdapError($oCon, 'ldap_get_entries'); + } + } else { + $this->logLdapError($oCon, 'ldap_search'); + } + + return $aResult; + } + + /** + * + * @param string $sStr + * + * @return string + */ + private function escape($sStr) { + $aNewChars = array (); + $aChars = array ('\\', '*',' (', ')', \chr(0)); + + foreach ( $aChars as $iIndex => $sValue ) { + $aNewChars [$iIndex] = '\\' . \str_pad ( \dechex ( \ord ( $sValue ) ), 2, '0' ); + } + return \str_replace($aChars, $aNewChars, $sStr); + } + + /** + * + * @param mixed $oCon + * @param string $sCmd + * + * @return string + */ + private function logLdapError($oCon, $sCmd) { + if ($this->oLogger) { + $sError = $oCon ? @\ldap_error($oCon) : ''; + $iErrno = $oCon ? @\ldap_errno($oCon) : 0; + + $this->oLogger->Write($sCmd.' error: '.$sError.' ('. $iErrno.')', \MailSo\Log\Enumerations\Type::WARNING, 'LDAP' ); + } + } + + /** + * + * @param \MailSo\Log\Logger $oLogger + * + * @return \LdapContactsSuggestions + */ + /** + * + * @param \MailSo\Log\Logger $oLogger + */ + public function SetLogger($oLogger) { + $this->oLogger = $oLogger instanceof \MailSo\Log\Logger ? $oLogger : null; + } + +} diff --git a/sources/plugins/ynh-ldap-addressbooks/index.php b/sources/plugins/ynh-ldap-addressbooks/index.php new file mode 100644 index 0000000..60daf42 --- /dev/null +++ b/sources/plugins/ynh-ldap-addressbooks/index.php @@ -0,0 +1,36 @@ +addHook ( 'main.fabrica', 'MainFabrica' ); + } + + /** + * test if ldap is supported (but with ynh it nead ;) ) + * @return string + */ + public function Supported() { + if (! \function_exists ( 'ldap_connect' )) { + return 'The LDAP PHP exention must be installed to use this plugin'; + } + return ''; + } + + /** + * @param string $sName + * @param mixed $mResult + */ + public function MainFabrica($sName, &$mResult) { + if ($sName === 'suggestions') { + include_once __DIR__ . '/YnhLdapAddressbooks.php'; + + if (! \is_array ( $mResult )) { + $mResult = array (); + } + + $oProvider = new YnhLdapAddressbooks (); + $mResult [] = $oProvider; + } + } + +} diff --git a/sources/plugins/ynh-login-mapping/index.php b/sources/plugins/ynh-login-mapping/index.php index d22ec61..f228e83 100644 --- a/sources/plugins/ynh-login-mapping/index.php +++ b/sources/plugins/ynh-login-mapping/index.php @@ -1,23 +1,10 @@ addHook('filter.login-credentials.step-1', 'FilterLoginСredentials1'); - // $this->addHook('filter.login-credentials.step-2', 'FilterLoginСredentials2'); $this->addHook ( 'filter.login-credentials', 'FilterLoginСredentials' ); } - /* // ca ne semble pas marcher... - * public function FilterLoginCredentials1(&$sEmail, &$sPassword) { - * $this->Manager()->Actions()->Logger()->Write('LdapLoginMappingPlugin::FilterLoginСredentials_S1:'); - * } - */ - - /* // ca non plus... - * public function FilterLoginCredentials2(&$sEmail, &$sPassword) { - * $this->Manager()->Actions()->Logger()->Write('LdapLoginMappingPlugin::FilterLoginСredentials_S2:'); - * } - */ - /** * * @param string $sEmail @@ -27,13 +14,13 @@ class YnhLoginMappingPlugin extends \RainLoop\Plugins\AbstractPlugin { * @throws \RainLoop\Exceptions\ClientException */ public function FilterLoginСredentials(&$sEmail, &$sLogin, &$sPassword) { - $this->Manager()->Actions()->Logger()->Write('LdapLoginMappingPlugin::FilterLoginСredentials IN => '.$sEmail.'/'.$sLogin, \MailSo\Log\Enumerations\Type::INFO); + $this->Manager()->Actions()->Logger()->Write('YnhLoginMappingPlugin::FilterLoginСredentials IN => '.$sEmail.'/'.$sLogin, \MailSo\Log\Enumerations\Type::INFO); // connection au ldap ynh... en local $cnx = ldap_connect (); // single connection if (! $cnx) { - $this->Manager()->Actions()->Logger()->Write('LdapLoginMappingPlugin: Could not connect to LDAP server', \MailSo\Log\Enumerations\Type::ERROR ); + $this->Manager()->Actions()->Logger()->Write('YnhLoginMappingPlugin: Could not connect to LDAP server', \MailSo\Log\Enumerations\Type::ERROR ); return; } @@ -52,7 +39,7 @@ class YnhLoginMappingPlugin extends \RainLoop\Plugins\AbstractPlugin { // OK un petit recherche $sr = ldap_search ( $cnx, $dn, $filter, $justthese ); if (!$sr) { - $this->Manager()->Actions()->Logger()->Write('LdapLoginMappingPlugin: search on LDAP server', \MailSo\Log\Enumerations\Type::ERROR ); + $this->Manager()->Actions()->Logger()->Write('YnhLoginMappingPlugin: search on LDAP server', \MailSo\Log\Enumerations\Type::ERROR ); return; } $result = ldap_get_entries ( $cnx, $sr ); @@ -61,22 +48,10 @@ class YnhLoginMappingPlugin extends \RainLoop\Plugins\AbstractPlugin { if (($result['count'] > 0) && ($result[0]['uid']['count'] > 0)) { $sLogin = $result[0]['uid'][0]; } else { - $this->Manager()->Actions()->Logger()->Write('LdapLoginMappingPlugin: user not found', \MailSo\Log\Enumerations\Type::ERROR ); + $this->Manager()->Actions()->Logger()->Write('YnhLoginMappingPlugin: user not found', \MailSo\Log\Enumerations\Type::ERROR ); } - $this->Manager()->Actions()->Logger()->Write('LdapLoginMappingPlugin::FilterLoginСredentials OUT => '. $sEmail.'/'.$sLogin, \MailSo\Log\Enumerations\Type::INFO ); + $this->Manager()->Actions()->Logger()->Write('YnhLoginMappingPlugin::FilterLoginСredentials OUT => '. $sEmail.'/'.$sLogin, \MailSo\Log\Enumerations\Type::INFO ); } - /* - * // pas encore de configuration... - * public function configMapping() - * { - * return array( - * \RainLoop\Plugins\Property::NewInstance('mapping')->SetLabel('Mapping') - * ->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING_TEXT) - * ->SetDescription('email:login mapping') - * ->SetDefaultValue("user@domain.com:user.bob\nadmin@domain.com:user.john2") - * ); - * } - */ }