<?php

/*
 @nom: ldap
 @auteur: Valentin CARRUESCO (valentincarruesco@yahoo.fr)
 @date de cr�ation: 31/05/2013 02:47:27
 @description: Gestion des connexions aux annuaires ldap 
 */

class ActiveDirectory
{
	public $server,$port,$login,$password,$userRoot,$groupRoot,$domain,$datasource,$protocolVersion;
		

	/**
	 * Se connecte a l'annuaire ldap en mode authentifi� si login et mdp sont pr�cis�s,
	 * en mode anonyme le cas �ch�ant, possibilit� d'activer le mode debug pour obtenir 
	 * des echo etapes par etapes.
	 * @param <String> login [=false]
	 * @param <String> mot de passe [=false]
	 * @param <String> mode debug [=false] (true or false)
	 * @return <Boolean> true si la connexion a reussie, false dans le cas contraire
	 */
	
	public function connect($login=false,$password=false){
		putenv('LDAPTLS_REQCERT=never');
		if($this->server==null || $this->port==null || $this->userRoot==null) throw new Exception('Param�tres de connexion manquants',400);
		$this->datasource = ldap_connect($this->server,$this->port);
		if(!$this->datasource) throw new Exception('Connexion �chou�e', 400);	
		ldap_set_option($this->datasource,LDAP_OPT_PROTOCOL_VERSION,$this->protocolVersion);
		ldap_set_option($this->datasource, LDAP_OPT_REFERRALS, 0);
		if(@ldap_bind($this->datasource,$login,$password) == false) throw new Exception('Identifiant ou mot de passe incorrect', 401);
	}
	

	/**
	* R�cupere un samaccountname depuis un CN (conrtion des liaisons ad en liasons erp)
	* @param <Strong> CN complet de la personne recherch�e
	**/
    public function userFromCn($cn){
		$entries= $this->search($this->userRoot,"(distinguishedname=$cn)");
		return $entries;
	}

	/**
	* R�cupere un CN depuis le login
	* @param <String> Login
	**/
	public function cnFromLogin($login){
		$entries= $this->search($this->userRoot,'(samAccountName='.$login.')');
		return (isset($entries[0])) ? $entries[0]['dn'] : false;
	}

	/**
	 * R�cupere les groupes ancetres du groupe cibl�s recusrivement et les ajoute a la liste pass�e en argument
	 * @param <String> liste des groupes � alimenter
	 * @param <String> CN du groupe concern�
	 * @return <void>
	 */
	function recursiveGroups(&$groups,$groupCN){
		$entries = $this->search($this->groupRoot,"(member=".$groupCN.")");
		if(count($entries)!=0 && $entries['count']!=0) {
			if(isset($entries[0])){
				$groups[] = $entries[0]['name'][0];
				$parentCN = $entries[0]['distinguishedname'][0];
				$this->recursiveGroups($groups,$parentCN);
			}
		}
	}


	
	/**
	 * Recherche des valeurs dans la base de donn�es en fonction du filter
	 * @param <String> Racine contexte de la recherche
	 * @param <String> Filtre contenant les �l�ments a rechercher
	 * @return <Array> tableau contenant les objets correspondants a la recherche
	 */
	public function search($dn,$filter="(objectClass=user)"){
		$roots = (substr_count($dn, ';') > 0) ? explode(';', $dn) : array($dn);
		$infos = array('count' => 0);
		foreach ($roots as $root) {
			if(empty($root)) continue;
			$sr = ldap_search($this->datasource, $root, $filter); // retourne un identifiant de recherche
			if(!$sr) throw new Exception("Erreur lors de la recherche. V�rifiez que les racines existent");
			$info = ldap_get_entries($this->datasource, $sr);

			if($info['count'] == 0) continue;

			$infos['count'] += $info['count'];
			for($i=0;$i<$info['count'];$i++){
				array_push($infos, $info[$i]);
			}
		}
		$infos = array_unique($infos,SORT_REGULAR);
		return $infos;
	}
	
	/**
	 * R�cupere tous les utilisateurs du LDAP
	 * @param <String> Racine contexte de la recherche
	 */
	public function populate($dn){
		return $this->search($dn,"(&(samAccountName=*)(objectClass=user))");
	}

	public function get_domain_name($login){
		$user = $this->search($this->userRoot,'(samAccountName='.$login.')');
		return $user[0]['dn'];
	}

	public function set($dn,$entry,$value){
		putenv('LDAPTLS_REQCERT=never');
		if($value != ''){
			$attributes[$entry][0] = $value;
			return ldap_modify($this->datasource,$dn,$attributes);
		}else{
			$attributes[$entry] = array();
			return ldap_mod_del($this->datasource,$dn,$attributes);
		}
	}

	public function change_password( $userDn , $newPassword ) {
		if (!ldap_mod_replace($this->datasource, $userDn ,  self::encrypt_password($newPassword))) throw new Exception("Impossible de modifier le mot de passe : ".ldap_error($this->datasource));
	}

	public static function encrypt_password( $newPassword ) {
		$newPassword = "\"" . $newPassword . "\"";
		$len = strlen( $newPassword );
		$newPassw = "";
		for ( $i = 0; $i < $len; $i++ ){
			$newPassw .= "{$newPassword{$i}}\000";
		}
		return array("unicodePwd" => $newPassw);
	}
	

	/**
	 * Deconnexion du LDAP
	 */
	public function disconnect(){
		if($this->datasource!=null){
			@ldap_close($this->datasource);
		}
	}
	
	
}
?>