/class.xuser.inc
PHP | 894 lines | 749 code | 62 blank | 83 comment | 202 complexity | f98181b0bfa2b3006a46cdcdf1d89dba MD5 | raw file
Possible License(s): LGPL-2.0, LGPL-2.1, GPL-3.0, Apache-2.0, BSD-3-Clause
- <?php
- /// classe representant un utilisateur authentifie
- class XUser {
- const DB_SESSION_CACHE_PREFIX='cache::';
- public $table='USERS';
- public $_cur=NULL;
- public $_curoid=NULL;
- public $_debug=false;
- public $admin=false;
- static $_cacheml=array();
- static $_C81=array();
- static $_C82=array();
- static $_C8OID = array();
- static $_C8OIDS = array();
- static $_cache_sGroup=array();
- static $_cache_listObjectAccess=array();
- // creation d'un utilisateur ou d'un object utilisateur a partir d'un alias, d'un uid, d'un ar avec UID
- function __construct($ar=NULL) {
- if(is_string($ar)) {
- if(Kernel::isAKoid($ar)) $this->_curoid=$ar;
- else {
- $uid=selectQueryGetOne('SELECT KOID FROM USERS WHERE alias="'.$ar.'" LIMIT 1');
- if(!empty($uid)) $this->_curoid=$uid['KOID'];
- }
- }
- if(empty($this->_curoid)) {
- $p = new XParam($ar, array('UID'=>TZR_USERID_NOBODY));
- $this->_curoid=$p->get('UID');
- }
- if($this->_curoid!=TZR_USERID_NOBODY) $this->load();
- else{
- $this->_cur['ldata']='';
- $this->_cur['luser']='';
- }
- }
- static function clearCache() {
- XUser::$_cacheml = array();
- XUser::$_C81 = array();
- XUser::$_C82 = array();
- XUser::$_cache_sGroup = array();
- XUser::$_cache_listObjectAccess=array();
- XUser::clearDbSessionDataAndRightCache();
- }
- static public function authentified() {
- $uid=getSessionVar('UID');
- if(!empty($uid) && ($uid!='USERS:0')) return true;
- return false;
- }
- static function get_current_user_uid() {
- $uid= getSessionVar('UID');
- if(empty($uid)) $uid=TZR_USERID_NOBODY;
- return $uid;
- }
- static function isNobody() {
- $uid= getSessionVar('UID');
- if(empty($uid)) return true;
- if($uid==TZR_USERID_NOBODY) return true;
- return false;
- }
- public static function &get_user() {
- return $GLOBALS['XUSER'];
- }
- function uid() {
- return $this->_curoid;
- }
- function isRoot() { return(!empty($this->_cur['grp']) && in_array(TZR_GROUPID_ROOT,$this->_cur['grp'])); }
- /// rend le nom en clair de l'utilisateur authentifie
- function fullname() {
- return $this->_cur['fullnam'];
- }
- /// rend le home du backoffice de l'utilisateur
- function bohome() {
- if(!empty($this->_cur['bohome']) && Kernel::objectExists($this->_cur['bohome']))
- return $this->_cur['bohome'];
- else
- return 'home';
- }
- /// rend le top du menu backoffice de l'utilisateur
- function botop() {
- if(!empty($this->_cur['bohome']) && Kernel::objectExists($this->_cur['bohome']))
- return $this->_cur['bohome'];
- else
- return 'top';
- }
- /// rend l'email en clair de l'utilisateur authentifie
- function email() {
- return $this->_cur['email'];
- }
- /// rend la date de derniere connexion en clair de l'utilisateur authentifie
- function lastconnection() {
- return $this->_cur['lastcon'];
- }
- function language($ar=NULL) {
- return array(@$this->_cur['ldata'],@$this->_cur['luser']);
- }
- function load() {
- $this->_cur = selectQuery('SELECT * FROM '.$this->table .' WHERE KOID="'.$this->_curoid.'"')->fetch(PDO::FETCH_ASSOC);
- $this->_cur['grp'] = explode('||', $this->_cur['GRP']);
- if(empty($this->_cur['luser']))
- $this->_cur['luser'] = TZR_DEFAULT_LANG;
- if(XShell::admini_mode() && !XUser::isNobody()) {
- if(!in_array(TZR_GROUPID_AUTH,$this->_cur['grp']))
- $this->_cur['grp'][]=TZR_GROUPID_AUTH;
- }
- elseif(!in_array(TZR_GROUPID_NOBODY,$this->_cur['grp']))
- $this->_cur['grp'][]=TZR_GROUPID_NOBODY;
- }
- function getUserList($myselfIncluded = true) {
- $LANG_USER = XShell::getLangUser();
- $liste = array();
- $cond='';
- if ( !$myselfIncluded ) {
- $cond.=' KOID != "'.$this->_curoid.'" ';
- }
- $requete = 'select * from USERS '.$cond.' order by fullnam';
- $rs=selectQuery($requete);
- $liste=array();
- $ors=array();
- while($rs && ($ors=$rs->fetch())) {
- $fullnam=$ors['fullnam'];
- $alias=$ors['alias'];
- $liste[$ors['KOID']]="$fullnam [$alias]";
- }
- return $liste;
- }
- function groups($refresh=false) {
- if(!$refresh && !empty($this->_cur['groups'])) return $this->_cur['groups'];
- $limits=array();
- $limits['USERS']=array('GRP');
- $limits['GRP']=array('GRPS');
- $g1=Kernel::followLinks(array($this->_curoid),$limits);
- // Si l'utilisateur est authentifié, il fait parti du groupe "Utilisateurs authentifié" automatiquement
- if(!XUser::isNobody() && !in_array(TZR_GROUPID_AUTH, $g1)) $g1[]=TZR_GROUPID_AUTH;
- // Si l'utilisateur fait parti du groupe "Utilisateurs authentifiés", il ne fera pas parti du groupe "Tout le monde"
- if(!in_array(TZR_GROUPID_AUTH, $g1) && !in_array(TZR_GROUPID_NOBODY, $g1)) $g1[]=TZR_GROUPID_NOBODY;
- $this->_cur['groups']=$g1;
- return $g1;
- }
- static function sGroups($uoid) {
- if(!is_array($uoid)) $uoid=array($uoid);
- $idx=implode('-',$uoid);
- if(empty(XUser::$_cache_sGroup[$idx])){
- $limits=array();
- $limits['USERS']=array('GRP');
- $limits['GRP']=array('GRPS');
- $g1=Kernel::followLinks($uoid,$limits);
- if(!XUser::isNobody() && !in_array(TZR_GROUPID_AUTH, $g1)) $g1[]=TZR_GROUPID_AUTH;
- if(!in_array(TZR_GROUPID_AUTH, $g1) && !in_array(TZR_GROUPID_NOBODY, $g1)) $g1[]=TZR_GROUPID_NOBODY;
- XUser::$_cache_sGroup[$idx]=array_unique($g1);
- }
- return XUser::$_cache_sGroup[$idx];
- }
- // Rend vrai si l'utiliser uid est dans les groupes $grps (attention si $parents==true, en ajoute dans grps les groupes parents et surtout GRP:0 ou GRP:2 selon si authentifié ou pas)
- function inGroups($grps,$parents=true) {
- if(!is_array($grps)) $grps=array($grps);
- $mygroups = $this->groups();
- if($parents) $otgroups = XUser::sGroups($grps);
- else $otgroups = $grps;
- $r1=array_intersect($mygroups, $otgroups);
- if(empty($r1)) {
- return false;
- }
- return true;
- }
- /// Compare 2 niveaux de sécurité pour une classe donnée
- static public function compareSecLevels($class,$lvl1,$lvl2,$op){
- if(is_numeric($class)){
- $mod=XModule::objectFactory($class);
- $class=get_class($mod);
- }
- $secs=call_user_func(array($class,'secList'),NULL);
- $res1=array_search($lvl1,$secs);
- $res2=array_search($lvl2,$secs);
- return eval('return '.$res1.$op.$res2.';');
- }
- /// Vérifie si l'utilisateur courant peut attribuer un droit spécifique à un objet
- static public function isAuthorizedToSetAccess($class,$moid,$lang,$oid,$lvl){
- if($lvl=='default') return true;
- $actlvl=XUser::secure8maxlevel($moid,$oid,null,$lang);
- return XUser::compareSecLevels($moid,$lvl,$actlvl,'<=');
- }
- /// Positionnement du niveau d'accés dans la base de donnéees
- public function setUserAccess($class,$moid,$lang,$oid,$level,$uoid=NULL,$cache=false,$force=true,$comment='') {
- if(empty($uoid)) $uoid=$this->_curoid;
- if(!$force && !$cache && !XShell::isRoot()){
- if(!XUser::isAuthorizedToSetAccess($class,$moid,$lang,$oid,$level)) return false;
- }
- $table=($cache?'ACL4_CACHE':'ACL4');
- $aoid=substr(md5(uniqid('')),0,40);
- if(!empty($moid)) {
- $q='DELETE FROM '.$table.' where AMOID="'.$moid.'" and ALANG="'.$lang.'" and AKOID="'.$oid.'" and AGRP="'.$uoid.'"';
- $q2='INSERT INTO '.$table.'(AOID,UPD,AGRP,AFUNCTION,ALANG,AMOID,AKOID,OK,ACOMMENT) '.
- 'values ("'.$aoid.'",NULL,"'.$uoid.'","'.$level.'","'.$lang.'","'.$moid.'","'.$oid.'",1,"'.$comment.'")';
- $q3='DELETE FROM ACL4_CACHE where AMOID="'.$moid.'" and ALANG="'.$lang.'"';
- if(!$cache) XLogs::update('security', $uoid, 'Delete security rules for moid='.$moid.' oid='.$oid.' user='.$uoid.' lang='.$lang);
- } else {
- $q='DELETE FROM '.$table.' where ACLASS="'.$class.'" and ALANG="'.$lang.'" and AKOID="'.$oid.'" and AGRP="'.$uoid.'"';
- $q2='INSERT INTO '.$table.'(AOID,UPD,AGRP,AFUNCTION,ACLASS,ALANG,AKOID,OK,ACOMMENT) '.
- 'values ("'.$aoid.'",NULL,"'.$uoid.'","'.$level.'","'.$class.'","'.$lang.'","'.$oid.'",1,"")';
- $q3='DELETE FROM ACL4_CACHE where ACLASS="'.$class.'" and ALANG="'.$lang.'"';
- if(!$cache) XLogs::update('security', $uoid, 'Delete security rules for class='.$class.' oid='.$oid.' user='.$uoid.' lang='.$lang);
- }
- if($lang=='all'){
- $q=str_replace('and ALANG="all"','',$q);
- $q3=str_replace('and ALANG="all"','',$q3);
- }
- // On efface d'eventuels drois deja presents
- updateQuery($q);
- // On efface le cache du module
- if(!$cache) updateQuery($q3);
- if($level!='default') {
- if($lang=='all'){
- foreach($GLOBALS['TZR_LANGUAGES'] as $lg=>$locale){
- updateQuery(str_replace('"all"','"'.$lg.'"',$q2));
- $this->_cacheml[$class.$moid.$lg.$uoid.$oid]=$level;
- }
- }else{
- updateQuery($q2);
- $this->_cacheml[$class.$moid.$lang.$uoid.$oid]=$level;
- }
- if(!$cache) XLogs::update('security', $uoid, "New security rules for '$uoid',1,'$level','$class','$lang','$moid','$oid',1");
- }else{
- unset($this->_cacheml[$class.$moid.$lang.$uoid.$oid]);
- }
- return true;
- }
-
- /// Copie des acces sur un oid vers un autre oid
- public function copyUserAccess($oidsrc, $oiddst, $moid) {
- $rs=selectQuery('select * FROM ACL4 where AMOID="'.$moid.'" and AKOID="'.$oidsrc.'"');
- while($ors=$rs->fetch()) {
- // on verifie que l'acl n'existe pas
- $n=countSelectQuery('select count(*) from ACL4 where AGRP="'.$ors['AGRP'].'" and AFUNCTION="'.$ors['AFUNCTION'].'" and ACLASS="'.$ors['ACLASS'].'" '.
- 'and ALANG="'.$ors['ALANG'].'" and AMOID="'.$ors['AMOID'].'" and AKOID="'.$oiddst.'" and OK="'.$ors['OK'].'"');
- if(!$n){
- $aoid=substr(md5(uniqid("")),0,40);
- updateQuery('INSERT INTO ACL4(AOID,AGRP,AFUNCTION,ACLASS,ALANG,AMOID,AKOID,OK) values ("'.
- $aoid.'","'.$ors['AGRP'].'","'.$ors['AFUNCTION'].'","'.$ors['ACLASS'].'","'.$ors['ALANG'].
- '","'.$ors['AMOID'].'","'.$oiddst.'","'.$ors['OK'].'")');
- }
- }
- $rs->closeCursor();
- XLogs::update('security',$oiddst,'Copy security rules from '.$oidsrc.' to '.$oiddst.' on '.$moid);
- }
- /// Copie tous les droits d'un utilisateur/groupe vers un autre
- function copyAllUserAccess($suid,$duid){
- $rs=selectQuery('select * FROM ACL4 where AGRP="'.$suid.'"');
- while($ors=$rs->fetch()) {
- $aoid=md5(uniqid(''));
- updateQuery('INSERT INTO ACL4(AOID,AGRP,AFUNCTION,ACLASS,ALANG,AMOID,AKOID,OK) values ("'.$aoid.'","'.$duid.'","'.$ors['AFUNCTION'].'",'.
- '"'.$ors['ACLASS'].'","'.$ors['ALANG'].'","'.$ors['AMOID'].'","'.$ors['AKOID'].'","'.$ors['OK'].'")');
- }
- $rs->closeCursor();
- XLogs::update('security',$duid,'Copy all security rules from '.$suid);
- }
-
- /// Effaccement des droits correspondant a un module, une langue, un oid, des utilisateurs donnes
- public function clearUserAccess($class, $moid, $lang, $oid, $uoid=NULL) {
- if(!empty($uoid)) $AGRP=' and AGRP="'.$uoid.'"';
- else $AGRP='';
- updateQuery('DELETE FROM ACL4 where ACLASS="'.$class.'" and AMOID="'.$moid.'" and ALANG="'.$lang.'" and AKOID="'.$oid.'"'.$AGRP);
- XLogs::update('security',$oid,'Clear security rules for '.$class.','.$moid.','.$lang.','.$oid.' on '.$AGRP);
- }
-
- /// Rend la liste des droits pour un moid/oid
- public function getObjectAccess($mod, $lang, $oid=NULL, $grp=NULL) {
- if(!$mod) return array();
- if(is_numeric($mod)) $mod=XModule::objectFactory($mod);
- if(!$mod) return array(array(),array());
- $seclistfull = $seclist = $mod->secList();
- $level=self::secure8maxlevel($mod,$oid,$grp,$lang);
- $cnt=count($seclist);
- $i=$cnt-1;
- while($i>=0) {
- if(!($level==$seclist[$i])) {
- unset($seclist[$i]);
- $i--;
- } else break;
- }
- if(count($seclist)<=0) $seclist=array("none");
- return array($seclist,$seclistfull);
- }
- /// Alias de getObjectAccess
- public function getUserAccess($class, $moid, $lang=NULL, $oid=NULL, $grp=NULL) {
- return $this->getObjectAccess($moid, $lang, $oid, $grp);
- }
- /// recherche des acces pour tous les utilsiateurs sur module donne. si $oid, alors sur objet
- static function getModuleAccess(XModule &$mod,$all=true) {
- global $TZR_LANGUAGES;
- list($users, $groups) = XUser::getUsersAndGroups(true,$all);
- $x1=self::get_user();
- foreach($users['lines_oid'] as $i=>$uoid) {
- $users['lines_nsec'][$i]=count($users['lines_sec'][$i][TZR_DEFAULT_LANG][0]);
- $users['lines_sec'][$i]=array();
- foreach($TZR_LANGUAGES as $lang=>$v){
- $users['lines_sec'][$i][$lang]=$x1->getUserAccess(get_class($mod), $mod->_moid, $lang, NULL, $uoid);
- }
- }
- foreach($groups['lines_oid'] as $i=>$uoid) {
- $groups['lines_nsec'][$i]=count($groups['lines_sec'][$i][TZR_DEFAULT_LANG][0]);
- $groups['lines_sec'][$i]=array();
- foreach($TZR_LANGUAGES as $lang=>$v){
- $groups['lines_sec'][$i][$lang]=$x1->getUserAccess(get_class($mod), $mod->_moid, $lang, NULL, $uoid);
- }
- }
-
- return array($users, $groups);
- }
- public function getObjectsAccess($mod, $lang, &$oids) {
- $l=$this->getObjectAccess($mod, $lang);
- $l=array_flip($l[0]);
- if(empty($mod->object_sec)) {
- $levs = array();
- foreach($oids as $i => $oid) {
- $levs[$i]=$l;
- }
- } else {
- $hasrules=XUser::getObjectsWithSec($mod,XUser::get_current_user_uid());
- $hasrules=array_flip($hasrules);
- $levs = array();
- foreach($oids as $i => $oid) {
- if(array_key_exists($oid,$hasrules)){
- $l2 = $this->getObjectAccess($mod, $lang, $oid);
- $l2=array_flip($l2[0]);
- $levs[$i]=$l2;
- }else{
- $levs[$i]=$l;
- }
- }
- }
- return $levs;
- }
- /// Pour un user/group donné, retourne les oids pour lesquels des droits spécifique ont été posé
- static function &getObjectsWithSec($mod,$uid){
- $uids=XUser::sGroups($uid);
- $hasrules=selectQueryGetColumn('(select AKOID from ACL4 where AGRP in ("'.implode('","',$uids).'") and AMOID="'.$mod->_moid.'" and AKOID!="" AND AKOID NOT LIKE "_field%") UNION DISTINCT '.
- '(select AKOID from ACL4_CACHE where AGRP in ("'.implode('","',$uids).'") and AMOID="'.$mod->_moid.'" and AKOID!="" and ACOMMENT="'.XSession::CS8_EMPTY_CHECK.'")');
- return $hasrules;
- }
- public function listObjectAccess(XModule &$mod, $lang, $oid, $details=false) {
- $lang_cond="";
- if(!empty($lang)) $lang_cond = "and ALANG='$lang'";
- $rs=selectQuery("select * from ACL4 where AMOID='".$mod->_moid."' ".$lang_cond." and AKOID='$oid' order by AGRP,ALANG");
- $r=array();
- $k = new Kernel();
- $ors=array();
- while( $ors=$rs->fetch()) {
- if($details) {
- $d1=&XUser::$_cache_listObjectAccess[$ors['AGRP']];
- if(!$d1) $d1=XDataSource::objectDisplayHelper($ors['AGRP']);
- if(is_array($d1)) {
- if($d1['ofullnam']->raw) $names[]='B-'.$d1['ofullnam']->raw;
- else $names[]='A-'.$d1['oGRP']->raw;
- $r['acl_uid'][]=$ors['AGRP'];
- $r['acl_own'][]=$d1;
- $r['acl_level'][]=$ors['AFUNCTION'];
- $r['acl_lang'][]=$ors['ALANG'];
- $r['acl_longlevel'][]=XLabels::getSysLabel('security',$ors['AFUNCTION']);
- } else {
- updateQuery('delete from ACL4 where AGRP = "'.$ors['AGRP'].'"');
- }
- } else $r['acl_uid'][]=$ors['AGRP'];
- }
- if($details) array_multisort($names,$r['acl_uid'],$r['acl_own'],$r['acl_level'],$r['acl_lang'],$r['acl_longlevel']);
- $r["oid"]=$oid;
- if(XShell::admini_mode() && ($lang==TZR_DEFAULT_LANG)) {
- if(!$oid){
- $r['title']=XLabels::getSysLabel('general','module','text').' '.$mod->modulename;
- }elseif((substr($oid,0,7)!='_field-') && Kernel::objectExists($oid)){
- $otab=XDataSource::objectFactoryHelper8('BCLASS=XDSTable&SPECS='.$oid);
- $ro = $otab->display(array("_publishedonly"=>true,"tplentry"=>TZR_RETURN_DATA,"oid"=>$oid, '_archive'=>''));
- $r["title"]=$ro['link'];
- }else{
- $r['title']=$mod->xset->desc[substr($oid,7)]->label;
- }
- }
- $r["lang"]=$lang;
- $r["moid"]=$mod->_moid;
- $r["classname"]=get_class($mod);
- return $r;
- }
- public function editObjectAccess(XModule &$mod, $lang, $oid) {
- $rs=selectQuery("select * from ACL4 where AMOID='".$mod->_moid."' and ALANG='$lang' and AKOID='$oid'");
- $r=array();
- $k = new Kernel();
- $ls = $this->getObjectAccess($mod,$lang,$oid);
- $ors=array();
- while( $ors=$rs->fetch()) {
- $d1=$k->data_display(array("tplentry"=>TZR_RETURN_DATA, "oid"=>$ors['AGRP'],
- '_options'=>array('error'=>'return')));
- if(is_array($d1)) {
- $r['acl_uid'][]=$ors['AGRP'];
- $r['acl_own'][]=$d1;
- $r['acl_level'][]=$ors['AFUNCTION'];
- $r['acl_longlevel'][]=XLabels::getSysLabel('security',$ors['AFUNCTION']);
- } else {
- updateQuery('delete from ACL4 where AGRP = "'.$ors['AGRP'].'"');
- }
- }
- $rs->closeCursor();
- return $r;
- }
- /// envoi d'un mail a l'utilisateur, ou a $mail si $mail est renseigné
- /// $mail peut etre : une adresse, un tableau d'adresses, un tableau de la forme (mail=>mail,name=>nom), un tableau de tableau mail/nom
- public function sendMail2User($subject,$message,$email=NULL,$from=NULL,$archive=true,$filename=NULL,$filetitle=NULL,$stringattachment=NULL,$mime=NULL,$params=array()) {
- if(!XUser::isNobody() && empty($email)) {
- $rs=selectQuery('select * from USERS where KOID="'.$this->_curoid.'"');
- if($rs && $ors=$rs->fetch()) {
- $email = $ors['email'];
- }
- }
- if(empty($email)) return;
- if(empty($from)) $from=TZR_SENDER_ADDRESS;
- $xmail=new XMail();
- $xmail->setTZRSubject($subject);
- $xmail->logActive=$archive;
- @$xmail->_modid=$params['moid'];
- @$xmail->_mtype=$params['mtype'];
- if(is_array($from)){
- $xmail->From=$from[0];
- $xmail->FromName=$from[1];
- }else{
- $xmail->From=$from;
- $xmail->FromName="";
- }
- if(preg_match("/(^<html>)/",$message)) {
- $xmail->IsHTML(true);
- if(!empty($params['sign'])) $xmail->setTZRBody($message);
- else $xmail->Body=$message;
- } else {
- $xmail->IsHTML(false);
- if(!array_key_exists('sign',$params) || !empty($params['sign'])) $xmail->setTZRBody(wordwrap($message, 65));
- else $xmail->Body=wordwrap($message, 65);
- }
- if(!empty($filename)){
- if(!is_array($filename)) $filename=array($filename);
- if(!is_array($filetitle)) $filetitle=array($filetitle);
- foreach($filename as $i=>$fn){
- $xmail->AddAttachment($filename[$i], $filetitle[$i]);
- }
- }
- if(!empty($stringattachment)) $xmail->AddStringAttachment($stringattachment, $filetitle, "base64", $mime);
- if(!is_array($email)) $email=array($email);
- elseif(array_key_exists('mail',$email)) $email=array($email);
- foreach($email as $i=>$mail){
- $xmail->ClearAllRecipients();
- if(is_array($mail)) $xmail->AddAddress($mail['mail'],$mail['name']);
- else $xmail->AddAddress($mail);
- $xmail->Send();
- if($archive) XLogs::update("mail sent", '',"To: $mail\nSubject: $subject\n".$xmail->Body);
- }
- }
-
- // creation d'un nouvel utilisateur
- // fonction non autorisée depuis internet
- //
- function newUser($ar=NULL) {
- $p = new XParam($ar,array());
- $tplentry=$p->get("tplentry");
- $login = $p->get("login");
- $passwd = $p->get("passwd");
- $thenlog = $p->get("_thenlog");
- $login=preg_replace('/([^[A-Za-z0-9]]+)/','',$login);
- $status=false;
- if(empty($login) && ($login!="root")) {
- $message=XLabels::getSysLabel("xmoduser.aliasnotaccepted");
- } else {
- $cnt=countSelectQuery("select COUNT(*) from USERS where alias='$login'");
- if($cnt>0) {
- $status=false;
- $message=XLabels::getSysLabel("xmoduser.existing_user");
- } else {
- $xuser=XDataSource::objectFactoryHelper8('BCLASS=XDSTable&SPECS='.'USERS');
- $ar["alias"]=$login;
- $ar["passwd"]=$passwd;
- $ar["GRP"]=$p->get("GRP","local");
- $xuser->procInput($ar);
- if($thenlog) {
- $xsession=new XSession();
- $xsession->procAuth(array("login"=>$login, "password"=>$passwd));
- $status=true;
- }
- }
- }
- $r=array("status"=>$status, "message"=>$message);
- if($tplentry==TZR_RETURN_DATA) {
- return $r;
- }
- return XShell::toScreen1($tplentry, $r);
- }
- function &getUserName($user) {
- static $names=array();
- if(!empty($names[$user])) return $names[$user];
- $rs=selectQuery("SELECT * FROM USERS WHERE KOID='$user'");
- if($ors=$rs->fetch()) {
- $names[$user]=array(1=>$ors['fullnam'],2=>$user);
- } else {
- $names[$user]=array(1=>'',2=>'');
- }
- $rs->closeCursor();
- return $names[$user];
- }
- /// recherche de la liste des utilisateurs et groupes
- static function &getUsersAndGroups($valid=false,$all=true,$directory=NULL) {
- if(empty($directory)) {
- $xuser = XDataSource::objectFactoryHelper8('BCLASS=XDSTable&SPECS=USERS');
- $cond=array();
- if(!$all || $all==='groups') $cond['GRP']=array('!=','');
- if($valid){
- if($xuser->fieldExists('DATEF') && $xuser->fieldExists('DATET')) {
- $cond['DATET']=array('>=',date('Y-m-d'));
- $cond['DATEF']=array('<=',date('Y-m-d'));
- }
- if($xuser->fieldExists('PUBLISH')) {
- $cond['PUBLISH']=array('=',1);
- }
- }
- $select=(!empty($cond)?$xuser->select_query(array('cond'=>$cond)):'');;
- $acl_user=$xuser->browse(array('tplentry'=>TZR_RETURN_DATA,'order'=>'fullnam','select'=>$select,'pagesize'=>'9999','selectedfields'=>array('fullnam','GRP','alias')));
- } else {
- $xuser = XModule::objectFactory($directory);
- if(empty($xuser)) return array();
- $select='';
- if($valid && $xuser->xset->fieldExists('DATEF') && $xuser->xset->fieldExists('DATET')) {
- $select = 'DATET >= "'.date('Y-m-d').'"';
- $select .= 'AND DATEF <= "'.date('Y-m-d').'"';
- }
- $acl_user=$xuser->browse(array('_local'=>1, 'select'=>$select, 'pagesize'=>9999, 'order'=>'fullnam', 'selectedfields'=>array('fullnam','GRP','alias')));
- }
- // On récupère tous les groupes et sous-groupes des utilisateurs actifs
- $grps = self::sGroups($acl_user['lines_oid']);
- // Si le paramètre "all" est activé, on ajoute les groupes "Tout le monde" et "Utilisateurs authentifiés" à la liste
- if($all && $all!=='users') $grps = array_merge($grps, array('GRP:*','GRP:2'));
- $grps=array_unique($grps);
- $xgrp=XDataSource::objectFactoryHelper8('BCLASS=XDSTable&SPECS=GRP');
- $select=$xgrp->select_query(array('cond'=>array('KOID'=>array('=',$grps))));
- $acl_grp=$xgrp->browse(array('tplentry'=>TZR_RETURN_DATA, 'order'=>'GRP','pagesize'=>'1000','select'=>$select));
- $ar=array(&$acl_user,&$acl_grp);
- return $ar;
- }
- /// Vérifie le niveau de droit d'une fonction sur un module pour un ensemble d'oid
- /// $function : nom de la fonction à tester
- /// $mod : module à tester
- /// $oid : oid ou tableau d'oid à tester
- /// $user : uid du user à tester
- /// $lang : langue à tester
- /// @return : [ fonction accessible (bool), nb de regle parcourue (int), niveau max de droit (string) ]
- static function secure8($function, $mod, $oid=null, $user=null, $lang=null, $checkparent=true) {
- // Recherche de la liste des groupes/users a tester
- if(!$user) $user=XUser::get_current_user_uid();
- elseif(is_object($user)) $user=$user->_curoid;
- $g1 = XUser::sGroups($user);
- // Si on est dans le groupe des administrateurs on a tous les droits
- if(in_array(TZR_GROUPID_ROOT, $g1)) return array(true,1,'admin');
- $g1=array_unique($g1);
- // Récupération du module et nettoyage des oids
- if(is_numeric($mod)) $mod=XModule::objectFactory($mod);
- if(!$lang) $lang=TZR_DEFAULT_LANG;
- if(!$mod->objectSecurityEnabled() || !$oid){
- $oids=array('');
- }elseif(!is_array($oid)){
- $oids=array($oid);
- }else{
- $oids=array_unique($oid,SORT_REGULAR);
- }
- $ooids=$oids;
- // Liste des droits necessaires pour l'execution de la fonction
- $needed = $mod->secGroups($function);
- if(!is_array($needed)) return false;
- list($minlvl)=$needed;
- if($minlvl=='none') return array(true,1,'none');
- // Condition SQL
- $cond='"'.implode('","',$g1).'"';
- // Vérifie le cache statique
- $idx=$cond.$minlvl.$mod->_moid.implode('',$oids).$lang;
- if(isset(XUser::$_C81[$idx])){
- return XUser::$_C81[$idx];
- }
- // Nombre de requete effectuée pour trouver un droit. Si à la fin du while celui ci vaut 0, c'est qu'aucune regle n'a été trouvé en base et qu'il faut donc faire jouer l'heritage
- $found=false;
- $rqs=0;
- $maxlvl=null;
- $maxlvluid='';
- $cache=true;
- $nboids=count($oids);
- $firstoid=$oids[0];
- // Si on ne demande le droit que d'un oid sur un user, on vérifié le cache SQL
- // Ce cas étant le plus courant, c'est le seul cache SQL disponible pour l'instant
- $cacheenabled=($mod->rightCacheEnabled() && $nboids==1 && self::oidIsUser($user));
- while(($oid=array_shift($oids))!==null){
- // Vérifie si l'objet est locké ou pas
- if(!empty($GLOBALS['XLOCK']) && !empty($oid) && !in_array('ro',$needed)) {
- $locked=$GLOBALS['XLOCK']->locked($oid, $lang);
- if(!empty($locked) && $user!=$locked['OWN']){
- return array(false,1,'none');
- }
- }
- // Cache SQL
- if($cacheenabled){
- XAudit::plusplus('secure8-cachesql');
- $cache=selectQueryGetOne('select OK,AMAX from ACL4_CACHE where AFUNCTION="'.$function.'" AND AGRP="'.$user.'" and ALANG="'.$lang.'" and AMOID="'.$mod->_moid.'" AND AKOID="'.$oid.'"');
- if($cache){
- XAudit::plusplus('secure8-cachesql-ok');
- $rqs++;
- $found=(bool)$cache['OK'];
- list($maxlvl,$maxlvluid)=explode(';',$cache['AMAX']);
- break;
- }
- }
- // On recupere toutes les regles en base ou dans le cache statique
- $idx2=$cond.$mod->_moid.$oid.$lang;
- if(!isset(XUser::$_C82[$idx2])){
- XAudit::plusplus('secure8-query');
- XUser::$_C82[$idx2]=selectQueryGetAll('SELECT * FROM ACL4 WHERE AGRP IN ('.$cond.') AND AKOID="'.$oid.'" AND AMOID="'.$mod->_moid.'" AND ALANG="'.$lang.'" /* secure8 */');
- }
- $rs=&XUser::$_C82[$idx2];
- foreach($rs as &$acl){
- $rqs++;
- $lvl=array_search($acl['AFUNCTION'], $needed);
- // Si on trouve une regle sur le user, elle a la priorité, on recupere le resultat et on stoppe la boucle
- if(self::oidIsUser($acl['AGRP'])){
- $maxlvl=$lvl;
- $found=($lvl!==false);
- break;
- }
- if($lvl!==false) {
- $found=true;
- }
- // Si le niveau detecté est supérieur ou qu'il est egal sur la personne demandée (cette derniere condition est necessaire pour etre sur qu'il s'agit d'un heritage ou pas)
- if($lvl>$maxlvl || $maxlvl===null || ($lvl==$maxlvl && $acl['AGRP']==$user)){
- $maxlvl=$lvl;
- $maxlvluid=$acl['AGRP'];
- }
- }
- // Si une regle positive a été trouvée, pas la peine de passer à l'oid suivant
- if($found) break;
- }
-
- // Si aucune règle n'a été trouvé en base et si on est pas déjà au niveau du module (oid vide), on va tester d'enventuels parents
- if($checkparent && !$rqs && !empty($firstoid) && $mod->objectSecurityEnabled()){
- $parents=$mod->getParentsOids($ooids);
- if(!empty($parents)){
- $res=self::secure8($function,$mod,$parents,$user,$lang);
- $found=$res[0];
- $rqs+=$res[1];
- $maxlvl=$res[2];
- $maxlvluid=$res[3];
- }
- }
- // Recupere le niveau max de droit
- if(is_numeric($maxlvl)) $maxlvl=$needed[$maxlvl];
- elseif($maxlvl===NULL) $maxlvl='none';
- // Si la personne avec les droits les plus élevé est celle demandée à l'origine, on retourne une chaine vide pour siginifier que ce n'est pas de l'heritage
- if($maxlvluid==$user) $maxlvluid='';
- // Si on ne demande le droit que d'un oid sur un user, on met le résultat en cache SQL
- // Va de paire avec le select ACL4_CACHE quelques lignes au dessus
- if($cacheenabled && !$cache){
- XUser::setCache($user, $function, $lang, $mod->_moid, $firstoid, $found, 'secure8', $maxlvl, $maxlvluid);
- }
- XUser::$_C81[$idx]=array($found,$rqs,$maxlvl,$maxlvluid);
- return XUser::$_C81[$idx];
- }
- static function setCache($user=null, $function, $lang=null, $moid, $oid, $ok, $comment, $maxlevel, $maxleveluid) {
- if (empty($user))
- $user = XUser::get_current_user_uid();
- if (empty($lang))
- $lang = TZR_DEFAULT_LANG;
- $aoid=substr(md5(uniqid('')),0,40);
- updateQuery('insert into ACL4_CACHE(AOID,ACOMMENT,AGRP,AFUNCTION,ALANG,AMOID,AKOID,OK,AMAX) '.
- 'values("'.$aoid.'","'.$comment.'","'.$user.'","'.$function.'","'.$lang.'",'.$moid.',"'.$oid.'",'.(int)$ok.',"'.$maxlevel.';'.$maxleveluid.'")');
- }
-
- /// retourne les oids pour lesquels des droits sont positionnées et ceux du module(clef vide)
- static function secure8oids($mod, $user=null, $lang=TZR_DEFAULT_LANG) {
- if (!$lang)
- $lang = TZR_DEFAULT_LANG;
- // Recherche de la liste des groupes/users a tester
- if (!$user) $user=XUser::get_current_user_uid();
- elseif (is_object($user)) $user=$user->_curoid;
- $g1 = XUser::sGroups($user);
- if (is_object($mod))
- $mod = $mod->_moid;
- $idx = "$user-$mod-$lang";
- //
- if (!isset(XUser::$_C8OIDS[$idx])) {
- $cond='"'.implode('","',$g1).'"';
- $acls = selectQuery('SELECT AKOID, AFUNCTION, AGRP FROM ACL4 WHERE AGRP IN ('.$cond.') AND AMOID="'.$mod.'" AND ALANG="'.$lang.'" order by AGRP desc /* secure8oids */')->fetchAll(PDO::FETCH_GROUP); // users before group
- XUser::$_C8OIDS[$idx] = $acls;
- }
- return XUser::$_C8OIDS[$idx];
- }
-
- /// Vérifie les droits sur un module/oid/user
- static function secure8oid($function, $mod, $oid=null, $user=null, $lang=TZR_DEFAULT_LANG, $checkparent=false) {
- if (!$lang)
- $lang = TZR_DEFAULT_LANG;
- if (XShell::isRoot())
- return true;
- if (is_numeric($mod))
- $mod = XModule::objectFactory($mod);
- $needed = $mod->secGroups($function);
- if (!is_array($needed))
- return false;
- list($minlvl) = $needed;
- if ($minlvl=='none')
- return true;
- // Vérifie si l'objet est locké ou pas
- if(!empty($GLOBALS['XLOCK']) && !empty($oid) && !in_array('ro', $needed)) {
- $locked=$GLOBALS['XLOCK']->locked($oid, $lang);
- if(!empty($locked) && $user!=$locked['OWN']){
- return false;
- }
- }
- $idx = "$function-".$mod->_moid."-$oid-$user-$lang-$checkparent";
- if (isset(XUser::$_C8OID[$idx]))
- return XUser::$_C8OID[$idx];
- $acls = XUser::secure8oids($mod, $user, $lang);
- // les règles utilisateur viennent avant celle des groupes
- foreach ($acls[$oid] as $acl) {
- $level = $acl['AFUNCTION'];
- if (in_array($level, $needed))
- return XUser::$_C8OID[$idx] = true;
- // si une règle est positionné sur l'utilisateur, elle a priorité
- if ($acl['AGRP'] == $user)
- break;
- }
- if (!isset($acls[$oid]) && $checkparent) {
- $parents = $mod->getParentsOids(array($oid));
- foreach ($parents as $parentOid) {
- if (XUser::secure8oid($function, $mod, $parentOid, $user, $lang, $checkparent)) {
- return XUser::$_C8OID[$idx] = true;
- }
- }
- }
- // default le module
- foreach ($acls[''] as $acl) {
- $level = $acl['AFUNCTION'];
- if (in_array($level, $needed))
- return XUser::$_C8OID[$idx] = true;
- if ($acl['AGRP'] == $user)
- break;
- }
- return XUser::$_C8OID[$idx] = false;
- }
- /// Vérifie si une methode sur une classe est accessible. Cela n'est possible que si la methode est acessible par tout le monde
- static function secure8class($class, $function){
- if(XShell::isRoot()) return true;
- $secs=call_user_func(array($class,"secGroups"),$function);
- return in_array('none',$secs);
- }
- /// Retourne le niveau max d'accès pour un module/oid
- static function secure8maxlevel($mod, $oid='', $user=NULL, $lang=TZR_DEFAULT_LANG) {
- $sec=self::secure8(':list', $mod, $oid, $user, $lang);
- return $sec[2];
- }
- /// Vérifie si un oid représente un user
- static function oidIsUser($oid){
- return (strpos($oid,'USERS:')===0);
- }
- /// Teste si le user USERS:self existe
- static function selfExists() {
- static $done=false;
- static $exists=false;
- if(!$done) {
- $exists=countSelectQuery('SELECT COUNT(KOID) FROM USERS WHERE KOID="'.TZR_SELF_USER.'"');
- $done=true;
- }
- return $exists;
- }
- /// Récupere une variable de session en base de données
- static function getDbSessionData($varname){
- static $cache=array();
- $sessid=session_id();
- if(!$sessid) return null;
- if(!array_key_exists($varname,$cache)){
- $row=selectQueryGetOne('select value from _VARS where sessid="'.$sessid.'" and name="'.$varname.'"');
- if($row) $cache[$varname]=unserialize($row['value']);
- else return null;
- }
- return $cache[$varname];
- }
- /// Récupere une variable de cache en base de données
- static function getDbCacheData($varname){
- return self::getDBSessionData(self::DB_SESSION_CACHE_PREFIX.$varname);
- }
- /// Ajoute/modifie une variable de session en base de données
- static function setDbSessionData($varname,$value){
- $sessid=session_id();
- if(!$sessid) return null;
- updateQuery('replace into _VARS (sessid,user,name,value) values ("'.$sessid.'","'.XUser::get_current_user_uid().'","'.$varname.'",'.$GLOBALS['TZR_DB']->quote(serialize($value)).')');
- }
- /// Ajoute/modifie une variable de cache en base de données
- static function setDbCacheData($varname,$value){
- return self::setDbSessionData(self::DB_SESSION_CACHE_PREFIX.$varname,$value);
- }
- /// Efface une variable de session en base de données
- static function deleteDbSessionDataUPD($varname){
- $sessid=session_id();
- if(!$sessid) return null;
- updateQuery('delete from _VARS where sessid="'.$sessid.'" and name="'.$varname.'"');
- }
- /// Efface une variable de cache en base de données
- static function deleteDbCacheDataUPD($varname){
- return self::deleteDbSessionDataUPD(self::DB_SESSION_CACHE_PREFIX.$varname);
- }
- /// Met à jour l'upd d'une variable de session en base de données
- static function updateDbSessionDataUPD($varname){
- $sessid=session_id();
- if(!$sessid) return null;
- updateQuery('update ignore _VARS set UPD=NOW() where sessid="'.$sessid.'" and name="'.$varname.'"');
- }
- /// Met à jour l'upd d'une variable de cache en base de données
- static function updateDbCacheDataUPD($varname){
- return self::updateDbSessionDataUPD(self::DB_SESSION_CACHE_PREFIX.$varname);
- }
- /// Efface toutes les données d'une session en base de données
- static function clearDbSessionDataAndRightCache(){
- $sessid=session_id();
- if(!$sessid) return null;
- updateQuery('delete from _VARS where sessid="'.$sessid.'"');
- updateQuery('delete from ACL4_CACHE where AGRP="'.XUser::get_current_user_uid().'"');
- }
- /// Efface toutes les données de session/cache périmées en base de données
- static function clearOldDbSessionDataAndRightCache(){
- // Efface le cache
- updateQuery('delete from _VARS where sessid is not null and name like "'.self::DB_SESSION_CACHE_PREFIX.'%" and UPD<="'.date('Y-m-d H:i:s',strtotime('-10 minutes')).'"');
-
- // Efface les sessions
- $rs=selectQuery('select sessid from _VARS where name="last_activity" and UPD<="'.date('Y-m-d H:i:s',strtotime('-'.TZR_SESSION_DURATION.' seconds')).'"');
- while($rs && $ors=$rs->fetch()){
- updateQuery('delete from _VARS where sessid="'.$ors['sessid'].'"');
- }
- // Efface le cache des droits des users qui n'ont plus de session actives
- $rs=selectQuery('select distinct(AGRP) as AGRP from ACL4_CACHE');
- while($rs && $ors=$rs->fetch()){
- $nb=countSelectQuery('select count(*) from _VARS where name="last_activity" and user="'.$ors['AGRP'].'"');
- if(!$nb) updateQuery('delete from ACL4_CACHE where AGRP="'.$ors['AGRP'].'"');
- }
- }
- }
- ?>