<?php
/*
@name Connexion AD (LDAP)
@author Valentin CARRUESCO <valentin.carruesco@idleman.fr>
@link http://www.idleman.fr
@licence Copyright IdleCorp
@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(){
	require_once(__DIR__.SLASH.'ActiveDirectory.class.php');
	global $conf;
	$ldap = new ActiveDirectory();
	$ldap->server = $conf->get('plugin_activedirectory_server');
	$ldap->port = $conf->get('plugin_activedirectory_port');
	$ldap->userRoot = $conf->get('plugin_activedirectory_user_root');
	$ldap->groupRoot = $conf->get('plugin_activedirectory_group_root');
	$ldap->domain = $conf->get('plugin_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;

	if(empty($conf->get('plugin_activedirectory_reader_login')) || empty($conf->get('plugin_activedirectory_reader_password')) || empty($conf->get('plugin_activedirectory_user_root')) ) return;

	try{
		$ldap = ldap_instance();
		$ldap->connect($conf->get('plugin_activedirectory_reader_login'),$conf->get('plugin_activedirectory_reader_password'));	
		$infos = $ldap->populate($conf->get('plugin_activedirectory_user_root'));
		if($infos["count"] == 0) return $ldap->disconnect();
		$allUsers = array();
		foreach($infos as $info){
			if( isset($info['userprincipalname'][0]) && trim($info['userprincipalname'][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(!isset($info2['distinguishedname'][0]) || $info2['distinguishedname'][0] != $info['manager'][0]) continue;		
						ldap_user_fill($ldap,$manager,$info2,false,false);
					}
				}
				$newUser->manager = $manager;
				$allUsers[] = $newUser;
				
			}
		}

		$users = $allUsers;
	}catch(Exception $e){
		$ldap->disconnect();
		throw $e;
	}

	
}

//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('plugin_activedirectory_reader_login'), $conf->get('plugin_activedirectory_reader_password'));
		}else{
			$ldap->connect($login.$ldap->domain, $password);
		}
		$infos = $ldap->search($conf->get('plugin_activedirectory_user_root'),"(userprincipalname=".$login.$ldap->domain.")");
		
		if($infos["count"]>0){
			$user = new User();
			ldap_user_fill($ldap,$user,$infos[0],$loadRight,$loadManager);
			user_rank_firm_by_group($user);
		}
		$avatarPath = __ROOT__.FILE_PATH.AVATAR_PATH.$user->login.'.jpg';
        if(!file_exists($avatarPath) && 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){
		//nothing to do
	}
	$ldap->disconnect();
}


//Remplissage d'une classe User en fonction des atttributs LDAPS
function ldap_user_fill($ldap,&$user,$infos,$loadRight=false,$loadManager = false){
	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;
    }

	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['samaccountname'][0])) $user->login = mb_strtolower($infos['samaccountname'][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]);
	
	global $conf;
	$metafields = explode(PHP_EOL,$conf->get('plugin_activedirectory_metafields'));
	foreach ($metafields as $line) {
		$metaInfos = explode(':',$line);
		if(count($metaInfos)<4) continue;
		list($label,$type,$adslug,$slug) = $metaInfos;
		if(isset($infos[$adslug][0])) $user->meta[$slug] = $infos[$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($managerEntry['count'] > 0 ){
				$manager = new User();
				ldap_user_fill($ldap,$manager,$managerEntry[0],$loadRight,false);
				if(isset($infos['sn'][0])) $manager->setName($managerEntry[0]['sn'][0]);
				if(isset($infos['givenname'][0])) $manager->setFirstName($managerEntry[0]['givenname'][0]);
				if(isset($infos['mail'][0])) $manager->setMail($managerEntry[0]['mail'][0]);
				if(isset($infos['telephonenumber'][0])) $manager->setPhone($managerEntry[0]['telephonenumber'][0]);
				if(isset($infos['mobile'][0])) $manager->setMobile($managerEntry[0]['mobile'][0]);
				if(isset($infos['title'][0])) $manager->function = $managerEntry[0]['title'][0];
				if(isset($infos['samaccountname'][0])) $manager->login = mb_strtolower($managerEntry[0]['samaccountname'][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");
	
	if(json_encode($userForm->meta) != json_encode($user->meta)) throw new Exception("Cette fonctionnalité n'est pas disponible pour des utilisateurs active directory");
	

	global $_,$conf;
	require_once(__DIR__.SLASH.'ActiveDirectory.class.php');


	$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/>';

    $ldap = ldap_instance();
    if($conf->get('plugin_activedirectory_admin_login')=='') throw new Exception("Le compte AD admin n'est pas configuré, veuillez contacter un administrateur");
	$ldap->connect($conf->get('plugin_activedirectory_admin_login'),$conf->get('plugin_activedirectory_admin_password'));	
	$cn = $ldap->cnFromLogin($user->login);
	if(!$cn) throw new Exception("Impossible de trouver l'utilsateur dans la base AD");

	$user->phone = $userForm->phone;
	$user->mobile = $userForm->mobile;




	$ldap->set($cn,'telephoneNumber',$userForm->phone);
	$ldap->set($cn,'mobile',$userForm->mobile);
	

	$ldap->disconnect();
}

function user_rank_firm_by_group(&$user){
	require_once(__DIR__.SLASH.'ActiveDirectoryGroup.class.php');
	global $conf, $myFirm;
	$firms = array();
	$ranks = array();

	$groups = ActiveDirectoryGroup::loadAll(array(), null,  null, array('*'),1);
	if(empty($groups)) throw new Exception("Etablissements et accès non paramétrés, veuillez contacter un administrateur");
	
	if(!isset($user->groups)) $user->groups = array();
	foreach($groups as $group){
		if(!in_array($group->adgroup,$user->groups)) continue;
		$firm = $group->join('firm');
		$rank = $group->join('rank');
		$firms[$firm->id] = $firm;
		if(!isset($ranks[$firm->id])) $ranks[$firm->id] = array();
		$ranks[$firm->id][] = $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.idleman.activedirectory') return;
	Entity::install(__DIR__);
}

function activedirectory_plugin_uninstall($id){
	if($id != 'fr.idleman.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>';
	}
}

function activedirectory_account_global(){
	global $myUser,$conf;
	$metafields = explode(PHP_EOL,$conf->get('plugin_activedirectory_metafields'));
	?>
	<div class="row">
	<?php
	foreach ($metafields as $line) :
		$metaInfos = explode(':',$line);
		if(count($metaInfos)<4) continue;
		list($label,$type,$adslug,$slug) = $metaInfos;
	?>
	
		<div class="col-md-6">
			<label for="<?php echo $slug; ?>"><?php echo $label ?>:</label>
			<input id="<?php echo $slug; ?>" name="<?php echo $slug; ?>" class="form-control-plaintext" readonly="readonly" type="text" value="<?php echo isset($myUser->meta[$slug])?$myUser->meta[$slug]:''; ?>">
		</div>
	
	<?php
	endforeach;
	?>
	</div>
	<?php
}


Plugin::addJs('/js/main.js?v=1.0');
Plugin::addCss('/css/main.css?v=1.0');

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");   
?>