| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410 | 
							- <?php
 
- /*
 
- @name Connexion AD (LDAP)
 
- @author Valentin CARRUESCO <valentin.carruesco@sys1.fr>
 
- @link http://www.sys1.fr
 
- @licence Copyright Sys1
 
- @version 1.0.0
 
- @description Plugin pour l'identification sur Active Directory (LDAP)
 
- */
 
- //Recuperation d'un instance ldap avec les configuraiton serveur
 
- function ldap_instance($ssl = false){
 
- 	require_once(__DIR__.SLASH.'ActiveDirectory.class.php');
 
- 	global $conf;
 
- 	$ldap = new ActiveDirectory();
 
- 	$ldap->server = ($ssl ? 'ldaps://':'' ).$conf->get('activedirectory_server');
 
- 	$ldap->port = $ssl ? $conf->get('activedirectory_ssl_port'):  $conf->get('activedirectory_port');
 
- 	$ldap->userRoot = $conf->get('activedirectory_users_root');
 
- 	$ldap->groupRoot = $conf->get('activedirectory_groups_root');
 
- 	$ldap->domain = $conf->get('activedirectory_domain');
 
- 	$ldap->protocolVersion = 3;
 
- 	return $ldap;
 
- }
 
- //Récuperation de l'ensemble des utilisateurs en LDAP (appellé par User::getAll)
 
- function ldap_plugin_all_users(&$users, $loadRights=false){
 
- 	require_once(__DIR__.SLASH.'ActiveDirectory.class.php');
 
- 	global $conf;
 
- 	try{
 
- 		$ldap = ldap_instance();
 
- 		$ldap->connect($conf->get('activedirectory_reader_login'),$conf->get('activedirectory_reader_password'));
 
- 		$attributes = ActiveDirectory::USER_SEARCH_DEFAULT_ATTRIBUTES;
 
- 		foreach(activedirectory_meta_data() as $data)
 
- 			$attributes .= ','.$data['adslug'];
 
- 		$infos = $ldap->search($conf->get('activedirectory_users_root'), null, $attributes);
 
- 		if(empty($infos)) return $ldap->disconnect();
 
- 		$allUsers = array();
 
- 		$authentificationAttribute = ActiveDirectory::authentification_attribute($conf->get('activedirectory_authentification'));
 
- 		foreach($infos as $info){
 
- 			if(isset($info[$authentificationAttribute][0]) && trim($info[$authentificationAttribute][0])!=''){
 
- 				$newUser = new User();
 
- 				ldap_user_fill($ldap,$newUser,$info,true,false);
 
- 				if($loadRights) user_rank_firm_by_group($newUser);
 
- 				$manager = new User();
 
- 				if(isset($info['manager'][0])){
 
- 					foreach($infos as $info2){
 
- 						if($info2['dn'] != $info['manager'][0]) continue;
 
- 						ldap_user_fill($ldap,$manager,$info2,false,false);
 
- 					}
 
- 				}
 
- 				$newUser->manager = $manager;
 
- 				$allUsers[] = $newUser;
 
- 			}
 
- 		}
 
- 		$users = $allUsers;
 
- 	}catch(Exception $e){
 
- 		$ldap->disconnect();
 
- 		//Décommenter la ligne qui suit pour avoir un message d'erreur si pb de connexion à l'AD
 
- 		//throw new Exception("Une erreur est survenue lors de la connexion à l'AD");
 
- 	}
 
- }
 
- //Récuperation d'un utilisateur précis en LDAP (appellé par User::check)
 
- function ldap_plugin_identification(&$user,$login,$password,$loadRight,$loadManager=true,$noPassword=false){
 
- 	global $_,$conf;
 
- 	require_once(__DIR__.SLASH.'ActiveDirectory.class.php');
 
- 	if($user != false) return;
 
- 	$ldap = ldap_instance();
 
- 	try{
 
- 		if($noPassword)
 
- 			$ldap->connect($conf->get('activedirectory_reader_login'), $conf->get('activedirectory_reader_password'));
 
- 		else
 
- 			$ldap->connect($login.$ldap->domain, $password);
 
- 		$attributes = ActiveDirectory::USER_SEARCH_DEFAULT_ATTRIBUTES;
 
- 		foreach(activedirectory_meta_data() as $data)
 
- 			$attributes .= ','.$data['adslug'];
 
- 		$infos = $ldap->search($conf->get('activedirectory_users_root'), $ldap->authentification_filter($login, $conf->get('activedirectory_authentification')), $attributes);
 
- 		if(!empty($infos)){
 
- 			$user = new User();
 
- 			ldap_user_fill($ldap,$user,$infos[0],$loadRight,$loadManager);
 
- 			user_rank_firm_by_group($user);
 
- 			foreach($user->firms as $firm){
 
- 				if($firm->has_plugin('fr.sys1.activedirectory')){
 
- 					$firmHasPlugin = true;
 
- 					break;
 
- 				}
 
- 			}
 
- 		}
 
- 		// if(!isset($firmHasPlugin)) throw new Exception("Ce compte n'est actif sur aucun établissement",403);
 
- 		$avatarPath = __ROOT__.FILE_PATH.AVATAR_PATH.$user->login.'.jpg';
 
- 		if(isset($user->meta['ldap_avatar'])){
 
- 			if(!file_exists(__ROOT__.FILE_PATH.AVATAR_PATH)) mkdir(__ROOT__.FILE_PATH.AVATAR_PATH,0755,true);
 
- 			file_put_contents($avatarPath,base64_decode($user->meta['ldap_avatar']));
 
- 		}
 
- 	}catch(Exception $e){
 
- 		switch ($e->getCode()) {
 
- 			case 403:
 
- 				// throw new Exception($e->getMessage(), 403);
 
- 			break;
 
- 			default:
 
- 			break;
 
- 		}
 
- 	}
 
- 	$ldap->disconnect();
 
- }
 
- //Remplissage d'une classe User en fonction des atttributs LDAPS
 
- function ldap_user_fill($ldap,&$user,$infos,$loadRight=false,$loadManager = false){
 
- 	global $conf;
 
- 	require_once(__DIR__.SLASH.'ActiveDirectory.class.php');
 
- 	//Vérifie que le compte n'est pas expiré (nb : 0 et 9223372036854775807 sont les deux valeurs possibles pour un n'expire jamais (allez comprendre la logique microsoft...))
 
- 	if(isset($infos['accountexpires'][0]) && $infos['accountexpires'][0]!=0 && $infos['accountexpires'][0]!=9223372036854775807){
 
- 		//Convertion en seconds
 
- 		$seconds = (float)($infos['accountexpires'][0] / 10000000);
 
- 		//Convertion d'un timestamp AD en timestamp UNIX
 
- 		$timestamp = round($seconds - (((1970-1601) * 365.242190) * 86400));
 
- 	    if($timestamp <= time()) return;
 
-     }
 
-     // récupération du login en fonction de l'attribut AD que l'on va contrôler
 
-     $attribute = ActiveDirectory::authentification_attribute($conf->get('activedirectory_authentification'));
 
-     if(isset($infos[$attribute][0])) $user->login = $ldap->attribute_to_login(mb_strtolower($infos[$attribute][0]));
 
- 	if(isset($infos['sn'][0])) $user->setName($infos['sn'][0]);
 
- 	if(isset($infos['givenname'][0])) $user->setFirstName($infos['givenname'][0]);
 
- 	if(isset($infos['mail'][0])) $user->setMail($infos['mail'][0]);
 
- 	if(isset($infos['telephonenumber'][0])) $user->setPhone($infos['telephonenumber'][0]);
 
- 	if(isset($infos['mobile'][0])) $user->setMobile($infos['mobile'][0]);
 
- 	if(isset($infos['title'][0])) $user->setFunction($infos['title'][0]);
 
- 	if(isset($infos['department'][0])) $user->service = $infos['department'][0];
 
- 	if(isset($infos['thumbnailphoto'][0])) $user->meta['ldap_avatar'] = base64_encode($infos['thumbnailphoto'][0]);
 
- 	if(isset($infos['jpegphoto'][0])) $user->meta['ldap_avatar'] = base64_encode($infos['jpegphoto'][0]);
 
- 	foreach(activedirectory_meta_data() as $data)
 
- 		if(isset($infos[$data['adslug']][0])) $user->meta[$data['slug']] = $infos[$data['adslug']][0];
 
- 	if(isset($infos['whencreated'][0]) && strlen($infos['whencreated'][0])>=12 ){
 
- 		$created = substr($infos['whencreated'][0],0,8).' '.substr($infos['whencreated'][0],8,2).':'.substr($infos['whencreated'][0],10,2);
 
- 		$user->created = strtotime($created);
 
- 	}
 
- 	if(isset($infos['manager'][0])){
 
- 		$user->manager = $infos['manager'][0];
 
- 		if($loadManager){
 
- 			$managerEntry = $ldap->userFromCn($infos['manager'][0]);
 
- 			if(isset($managerEntry) && !empty($managerEntry)){
 
- 				$manager = new User();
 
- 				ldap_user_fill($ldap,$manager,$managerEntry[0],$loadRight,false);
 
- 				if(isset($managerEntry['sn'][0])) $manager->setName($managerEntry[0]['sn'][0]);
 
- 				if(isset($managerEntry['givenname'][0])) $manager->setFirstName($managerEntry[0]['givenname'][0]);
 
- 				if(isset($managerEntry['mail'][0])) $manager->setMail($managerEntry[0]['mail'][0]);
 
- 				if(isset($managerEntry['telephonenumber'][0])) $manager->setPhone($managerEntry[0]['telephonenumber'][0]);
 
- 				if(isset($managerEntry['mobile'][0])) $manager->setMobile($managerEntry[0]['mobile'][0]);
 
- 				if(isset($managerEntry['title'][0])) $manager->function = $managerEntry[0]['title'][0];
 
- 				if(isset($managerEntry[$attribute][0])) $manager->login = $ldap->attribute_to_login(mb_strtolower($managerEntry[0][$attribute][0]));
 
- 				$user->manager = $manager;
 
- 			}
 
- 		}
 
- 	}
 
- 	$user->origin = 'active_directory';
 
- 	if($loadRight){
 
- 		$groups = array();
 
- 		if(isset($infos['memberof'])){
 
- 			for($i=0; $i<count($infos['memberof'])-1; ++$i){
 
- 				$groupCN = $infos['memberof'][$i];
 
- 				list($group,$root) = explode(',',$groupCN);
 
- 				list($entity,$group) = explode('=',$group);
 
- 				//TODO decommenter une fois les pb de perf résolus
 
- 				//$ldap->recursiveGroups($groups,$groupCN);
 
- 				$groups[] = $group;
 
- 			}
 
- 		}
 
- 		$user->groups = $groups;
 
- 	}
 
- }
 
- function activedirectory_user_save(&$user,$userForm,&$response){
 
- 	if($user->origin != 'active_directory') return;
 
- 	if($user->login != $userForm->login) throw new Exception("L'identifiant n'est pas modifiable");
 
- 	global $_,$conf;
 
- 	require_once(__DIR__.SLASH.'ActiveDirectory.class.php');
 
- 	//Régles de définition de mot de passe
 
- 	if(!empty($userForm->password)){
 
- 		if(strlen($userForm->password)<7) throw new Exception("Le mot de passe doit être supérieur à 7 caractères");
 
- 		if(!preg_match('|[0-9]|i', $userForm->password)) throw new Exception("Le mot de passe doit contenir au moins un chiffre");
 
- 		if(!preg_match('|[a-z]|i', $userForm->password)) throw new Exception("Le mot de passe doit contenir au moins une lettre");
 
- 		if(!preg_match('|[a-z]|', $userForm->password)) throw new Exception("Le mot de passe doit contenir au moins une lettre Minuscule");
 
- 		if(!preg_match('|[A-Z]|', $userForm->password)) throw new Exception("Le mot de passe doit contenir au moins une lettre Majuscule");
 
- 	}
 
-     $ldap = ldap_instance(true);
 
-     if($conf->get('activedirectory_admin_login')=='') throw new Exception("Le compte AD admin n'est pas configuré, veuillez contacter un administrateur");
 
- 	$ldap->connect($conf->get('activedirectory_admin_login'),$conf->get('activedirectory_admin_password'));
 
- 	$cn = $ldap->cnFromLogin($user->login, $conf->get('activedirectory_authentification'));
 
- 	if(!$cn) throw new Exception("Impossible de trouver l'utilisateur dans la base active directory");
 
- 	$user->phone = $userForm->phone;
 
- 	$user->mobile = $userForm->mobile;
 
- 	$infos = $ldap->search($conf->get('activedirectory_users_root'),$ldap->authentification_filter($user->login, $conf->get('activedirectory_authentification')));
 
- 	
 
- 	$ldap->set($cn,'telephonenumber',$userForm->phone);
 
- 	$ldap->set($cn,'mobile',$userForm->mobile);
 
- 	
 
- 	$avatarPath = glob(__ROOT__.FILE_PATH.AVATAR_PATH.$user->login.'.*');
 
- 	if(!empty($avatarPath)){
 
- 		$avatarPath = $avatarPath[0];
 
- 		$temp = File::temp().rand(0,10000).basename($avatarPath);
 
- 		copy($avatarPath,$temp);
 
- 		Image::toJpg($temp);
 
- 		$temp = explode('.', $temp);
 
- 		array_pop($temp);
 
- 		$temp = implode('.',$temp).'.jpg';
 
- 		$ldap->set($cn,'jpegphoto',file_get_contents($temp));
 
- 		unlink($temp);
 
- 	}
 
- 	if(!empty($userForm->password)){
 
- 		$ldap->change_password($cn,$userForm->password);
 
- 		$user->preference('passwordTime',time());
 
- 	}
 
- 	$response['warning'] = 'Vous êtes sur un compte de société, seules les informations suivantes ont été modifiées :<br/>
 
- 		- Téléphone<br/>
 
- 		- Mobile<br/>
 
- 		- Mot de passe (7 caracteres minimum : Majuscules, minucules et chiffres)<br/>
 
- 		- Avatar (JPG uniquement)<br/>';
 
- 	$ldap->disconnect();
 
- }
 
- function user_rank_firm_by_group(&$user){
 
- 	require_once(__DIR__.SLASH.'ActiveDirectoryGroup.class.php');
 
- 	global $conf, $myFirm;
 
- 	$firms = array();
 
- 	$ranks = array();
 
- 	if(!isset($user->groups)) $user->groups = array();
 
- 	foreach(ActiveDirectoryGroup::loadAll(array(), null,  null, array('*'),1) as $group){
 
- 		if(!in_array($group->adgroup,$user->groups)) continue;
 
- 		$firm = $group->join('firm');
 
- 		$rank = $group->join('rank');
 
- 		if(is_null($firm->id)) continue;
 
- 		$firms[$firm->id] = $firm;
 
- 		if(!isset($ranks[$firm->id])) $ranks[$firm->id] = array();
 
- 		$ranks[$firm->id][$rank->id] = $rank;
 
- 	}
 
- 	if(empty($ranks) && $conf->get('activedirectory_default_rank')!=''){
 
- 		foreach(Firm::loadAll() as $firm){
 
- 			if(!$firm->has_plugin('fr.sys1.activedirectory')) continue;
 
- 			$firms[$firm->id] = $firm;
 
- 			$ranks[$firm->id][$conf->get('activedirectory_default_rank')] = Rank::getById($conf->get('activedirectory_default_rank'));
 
- 		}
 
- 	}
 
- 	if(!empty($ranks)) {
 
- 		$user->setFirms($firms);
 
- 		$defaultFirm = !empty($user->preference('default_firm')) ? $user->preferences['default_firm'] : key($firms);
 
- 		$myFirm = $firms[$defaultFirm];
 
- 	}
 
- 	$user->ranks = $ranks;
 
- 	$user->loadRights();
 
- }
 
- function activedirectory_action(){
 
- 	global $_;
 
- 	require_once(__DIR__.SLASH.'action.php');
 
- }
 
- function activedirectory_plugin_menu(&$settingMenu){
 
- 	global $_, $myUser;
 
- 	if($myUser->can('activedirectory','configure'))
 
- 		$settingMenu[]= array(
 
- 			'sort' =>1,
 
- 			'url' => 'setting.php?section=activedirectory',
 
- 			'icon' => 'fas fa-angle-right',
 
- 			'label' => 'Active Directory'
 
- 		);
 
- }
 
- function activedirectory_plugin_page(){
 
- 	global $_;
 
- 	if(in_array($_['section'],array('activedirectory')) && file_exists(__DIR__.SLASH.'setting.'.$_['section'].'.php'))
 
- 		require_once(__DIR__.SLASH.'setting.'.$_['section'].'.php');
 
- }
 
- function activedirectory_plugin_section(&$sections){
 
- 	$sections['activedirectory'] = 'Gestion des droits sur les échanges avec l\'AD';
 
- }
 
- function activedirectory_plugin_install($id){
 
- 	if($id != 'fr.sys1.activedirectory') return;
 
- 	Entity::install(__DIR__);
 
- }
 
- function activedirectory_plugin_uninstall($id){
 
- 	if($id != 'fr.sys1.activedirectory') return;
 
- 	Entity::uninstall(__DIR__);
 
- }
 
- function activedirectory_directory_list(&$usermapping){
 
- 	foreach ($usermapping as $login => $infos) {
 
- 		$user = $infos['object'];
 
- 		//todo à dynamiser en fct de plugin_activedirectory_metafields
 
- 		if(isset($user->meta['personalPhone'])) $usermapping[$login]['values']['Portable (perso)'] = '<a href="tel: '.$user->meta['personalPhone'].'">'.$user->meta['personalPhone'].'</a>';
 
- 		// if(isset($user->meta['jobstart'])) $usermapping[$login]['values']['Date début contrat'] = $user->meta['jobstart'];
 
- 	}
 
- }
 
- function activedirectory_account_global(){
 
- 	global $myUser; ?>
 
- 	<div class="row">
 
- 	<?php foreach(activedirectory_meta_data() as $data): ?>
 
- 		<div class="col-md-6">
 
- 			<label for="<?php echo $data['slug']; ?>"><?php echo $data['label'] ?> :</label>
 
- 			<input id="<?php echo $data['slug']; ?>" name="<?php echo $data['slug']; ?>" class="form-control-plaintext" readonly="readonly" type="text" value="<?php echo isset($myUser->meta[$data['slug']])?$myUser->meta[$data['slug']]:''; ?>">
 
- 		</div>
 
- 	<?php endforeach; ?>
 
- 	</div>
 
- 	<?php
 
- }
 
- function activedirectory_meta_data(){
 
- 	global $conf;
 
- 	$data = array();
 
- 	$metaFields = preg_split('/('.PHP_EOL.'|\n|\r)/',$conf->get('activedirectory_metafields'),-1, PREG_SPLIT_NO_EMPTY);
 
- 	$metas = array('label','type','adslug','slug');
 
- 	foreach($metaFields as $line){
 
- 		$metaInfos = explode(':',$line);
 
- 		if(count($metaInfos)<4) continue;
 
- 		$lineData = array_combine($metas,$metaInfos);
 
- 		$data[] = $lineData;
 
- 	}
 
- 	return $data;
 
- }
 
- //Déclaration des settings de base
 
- //Types possibles : text,select ( + "values"=> array('1'=>'Val 1'),password,checkbox. Un simple string définit une catégorie.
 
- Configuration::setting('activedirectory',array(
 
-     "Configuration de l'AD",
 
-     'activedirectory_server' => array("label"=>"Serveur","type"=>"text","legend"=>"L'adresse IP du serveur AD","placeholder"=>"192.168.XXX.XXX"),
 
-     'activedirectory_port' => array("label"=>"Port","type"=>"number","legend"=>"Le port sur lequel attaquer le serveur AD","placeholder"=>"389"),
 
-     'activedirectory_ssl_port' => array("label"=>"Port SSL","type"=>"number","legend"=>"Le port SSL sur lequel attaquer le serveur AD","placeholder"=>"636"),
 
-     'activedirectory_domain' => array("label"=>"Domaine","type"=>"text","legend"=>"Le domaine sur lequel se base l'AD","placeholder"=>"@EXAMPLE.LOCAL"),
 
-     'activedirectory_users_root' => array("label"=>'Racine des utilisateurs <small title="Cliquez pour ajouter une racine utilisateur supplémentaire" class="text-primary no-select right pointer" onclick="activedirectory_activedirectory_add_roots(this);"><i class="fas fa-plus"></i> Ajouter une racine supplémentaire</small>',"type"=>"text","legend"=>"La racine où chercher les users","placeholder"=>"OU=SYS1,OU=UTILISATEURS,OU=sys1.fr,DC=SYS1,DC=LOCAL","parameters"=>array("data-root"=>"users")),
 
-     'activedirectory_groups_root' => array("label"=>'Racine des groupes <small title="Cliquez pour ajouter une racine groupe supplémentaire" class="text-primary no-select right pointer" onclick="activedirectory_activedirectory_add_roots(this);"><i class="fas fa-plus"></i> Ajouter une racine supplémentaire</small>',"type"=>"text","legend"=>"La racine où chercher les groupes","placeholder"=>"OU=SYS1,OU=UTILISATEURS,OU=sys1.fr,DC=SYS1,DC=LOCAL","parameters"=>array("data-root"=>"groups")),
 
-     "Compte Lecture seule",
 
-     'activedirectory_reader_login' => array("label"=>"CN","type"=>"text","legend"=>"Le Common Name du compte de lecture seule","placeholder"=>"CN=reader_account,OU=EXAMPLE,OU=APPLICATIONS,OU=example.fr,..."),
 
-     'activedirectory_reader_password' => array("label"=>"Mot de passe","type"=>"password","legend"=>"Le mot de passe du compte de lecture seule","placeholder"=>""),
 
-     "Compte Administrateur",
 
-     'activedirectory_admin_login' => array("label"=>"CN","type"=>"text","legend"=>"Le Common Name du compte administrateur","placeholder"=>"CN=administrator_account,OU=EXAMPLE,OU=APPLICATIONS,OU=example.fr,..."),
 
-     'activedirectory_admin_password' => array("label"=>"Mot de passe","type"=>"password","legend"=>"Le mot de passe du compte administrateur","placeholder"=>""),
 
-     "Champs de méta informations",
 
-     'activedirectory_metafields' => array("label"=>"Méta informations","type"=>"textarea","legend"=>"Vous pouvez remplir des méta champs pour les utilisateurs (un champ par ligne).<br>
 
-     Ces métas champs sont requis par certains plugins et peuvent être renseignés depuis l'AD via la syntaxe : <code>Libellé:Type:nom-champ-ad:nom-meta</code>","placeholder"=>"Date début contrat:date:description:jobstart","parameters"=>array("cols"=>"100")),
 
-     "Authentification",
 
-     'activedirectory_authentification' => array("label"=>"Authentification via l'attribut","type"=>"select","values"=>array("userprincipalname"=>"userPrincipalName","samaccountname"=>"sAMAccountName"),"default"=>"userprincipalname"),
 
-     "Utilisateurs de l'AD",
 
-     'activedirectory_default_rank' => array("label"=>"Rang par défaut","legend"=>"Utilisé si aucun groupe AD n'a été défini pour le rang \"Utilisateur\" standard","type"=>"rank")
 
- ));
 
- Plugin::addJs('/js/main.js');
 
- Plugin::addCss('/css/main.css');
 
- Plugin::addHook('directory_list',"activedirectory_directory_list");
 
- Plugin::addHook("account_global", "activedirectory_account_global");
 
- Plugin::addHook("install", "activedirectory_plugin_install");
 
- Plugin::addHook("uninstall", "activedirectory_plugin_uninstall");
 
- Plugin::addHook("user_login", "ldap_plugin_identification");
 
- Plugin::addHook("user_load", "ldap_plugin_all_users");
 
- Plugin::addHook("user_save","activedirectory_user_save");
 
- Plugin::addHook("user_rank_firm", "user_rank_firm_by_group");
 
- Plugin::addHook("section", "activedirectory_plugin_section");
 
- Plugin::addHook("action", "activedirectory_action");
 
- Plugin::addHook("menu_setting", "activedirectory_plugin_menu");
 
- Plugin::addHook("content_setting", "activedirectory_plugin_page");
 
- ?>
 
 
  |