<?php
# ************** LICENCE ****************
/**
	Copyright (c) PORTANEO.

	This file is part of POSH (Portaneo Open Source Homepage) http://sourceforge.net/projects/posh/.

	POSH is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version

	POSH is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with Posh.  If not, see <http://www.gnu.org/licenses/>.
**/
/**

    Acl class
    
    A group must created for each user

**/
class acl {
    
    var $userid; //integer
    var $rights; //hash
    var $json;  //string
    /**
            datas inside json structure must be simple quoted only
    
            $default
            
                auo = ACL_USER_OBJ 
                    user id
                
                ago = ACL_GROUP_OBJ
                        user group id given to object
                
                ag =  ACL_GROUP
                        users in any  groupid added in this array
                
                au =  ACL_USER
                        any given user id added in this array
                
                ao =  ACL_OTHER
                        world
                
                am = ACL_MASK
                        default
    **/
    var $default_json = '{"auo":0,"ago":0,"ag":[],"au":[],"ao":0,"am":0}';
    var $default_rights; //hash
    var $long_rights = array(
                'ACL_USER_OBJ' => 'auo',
                'ACL_GROUP_OBJ' => 'ago',
                'ACL_GROUP'     => 'ag',
                'ACL_USER'      => 'au',
                'ACL_OTHER'     => 'ao',
                'ACL_MASK'      => 'am'
            );
    var $use_long_rights = false;
    
    /**
            new object acl
    
    **/
    function acl () {
    }
    /**
           \fn addDefaultRights
            
            add acl hash

    **/
    function addDefaultRights ($rights) {
        $this->rights = $rights;
        
    }
    
    function getRights () {
        return $this->rights;
    }
    
    function useLongRights () {
        $this->use_long_rights = true;
    }
    /**
    
            getJSON
            
            return json string decoded from hash $this->rights
    **/
    function getJSON () {
        return $this->decodeJson();
    }
    /**
                 \fn decodeJson
                 
                 @param $string
                 
                    transforms  string into  a hash ($this->rights)
    **/
    function decodeJson ($string) {
        $this->rights = $this->json_decode($string);
        return $this->rights;
    }
    /**
    
                \fn encodeJson
                
                complete : $this->json
                
                transforms  hash  ($this->rights) in string
    **/
    function encodeJson () {
        $this->json = $this->json_encode($this->rights);
        return $this->json;
    }
    /**
            Function: addRight
            
            @param $datas array to modify (reference to array, see  decodeJson)
            @param $action : read/write/anything
            @param $type: auo (private access) / ago (access group) / ao (world access)
            @param $userid  send if user_id is different from session user_id
            
    **/
    function addRight (&$datas,$action,$type,$userid) {
        $value = $userid;
        if (!$userid) {
            $value = $_SESSION['user_id'];
        }
        if ($type == 'ao') {
            $value = 1;
        }
        if ($this->use_long_rights) {
            $datas[$action][$this->long_rights[$type]] = $value;
        } else {
            $datas[$action][$type] = $value;
        }
    }
    /**
    
                removeRight
                
                 unauthorized rights on world, group or user

                @param &$datas reference to array of rights
                @param $action read or write or any action allowed on an object
                @param type  auo (rights for user, ago (rights for group), ao (rights for world)
    **/
    function removeRight (&$datas,$action,$type) {
        if ($this->use_long_rights) {
            $datas[$action][$this->long_rights[$type]] = 0;
        } else {
            $datas[$action][$type] = 0;
        }
    }
    /**
    
                addGroup
                
                add group of an array of rights
                
                @param &$datas reference to array of rights
                @param $action read or write or any action allowed on an object
                @param $groupid  id of group
    **/       
    function addGroup (&$datas,$action,$groupid) {
        $mapping = array();
        foreach ($datas[$action]['ag'] as $cle) {
            $mapping[$cle] = 1;
        }
        $mapping[$groupid] = 1;
        $datas[$action]['ag'] = array();
        foreach ($mapping as $c => $v ) {
            array_push($datas[$action]['ag'],$c);
        }
    }
    /**
    
                removeGroup
                
                remove group of an array of rights
                
                @param &$datas reference to array of rights
                @param $action read or write or any action allowed on an object
                @param $groupid  id of group
    **/       
    function removeGroup (&$datas,$action,$groupid) {
        $mapping = array();
        foreach ($datas[$action]['ag'] as $cle) {
            $mapping[$cle] = 1;
        }
        unset($mapping[$groupid]); 
        $datas[$action]['ag'] = array();
        foreach ($mapping as $c => $v ) {
            array_push($datas[$action]['ag'],$c);
        }        
    }
    /**
    
                addUser
                
                add user of an array of rights
                
                @param &$datas reference to array of rights
                @param $action read or write or any action allowed on an object
                @param $userid  id of user
    **/    
    function addUser (&$datas,$action,$userid) {
        $mapping = array();
        foreach ($datas[$action]['au'] as $cle) {
            $mapping[$cle] = 1;
        }
        $mapping[$userid] = 1;
        $datas[$action]['au'] = array();
        foreach ($mapping as $c => $v ) {
            array_push($datas[$action]['au'],$c);
        }
    }
    /**
                \fn getUserId
                
                @param $action (read or write or any thing)
                
                return id of user in rights object
                
    
    **/
    function getUserId ($action) {
        $rights = $this->rights();
        return $rights[$action]['auo'];
    }
    
    
    
    /**
    
                removeUser
                
                remove user of an array of rights
                
                @param &$datas reference to array of rights
                @param $action read or write or any action allowed on an object
                @param $userid  id of user
    **/
    function removeUser (&$datas,$action,$userid) {
        $mapping = array();
        foreach ($datas[$action]['au'] as $cle) {
            $mapping[$cle] = 1;
        }
        unset($mapping[$userid]); 
        $datas[$action]['au'] = array();
        foreach ($mapping as $c => $v ) {
            array_push($datas[$action]['au'],$c);
        }
    } 
    /**
                \fn checkRights
                
                check if user has rights to access current object
                
                @param $userdatas hash
                    
                            $userdatas = new array( 
                                                            'userid' => $_SESSION['user_id'],
                                                            'groupid' => $_SESSION['user_id'],
                                                            'currentAction' => 'write'
                                                        );
    
    **/
    function checkRights ($userdatas) {
        $acl = $this->rights;
        $userid = $datas['userid'];
        $groupid = $datas['groupid'];
        if ( !$this->checkRightsbyUser($acl,$userdatas) ) {
            if (!$this->checkRightByAnyUser($acl,$userdatas)) {
                if (!$this->checkRightsByGroup($acl,$userdatas)) {
                    if (!$this->checkRightsByAnyGroup($acl,$userdatas)) {
                        if (!$this->checkWorldAccess($acl,$userdatas)) {
                            return false;
                        }
                    }
                }
            }
        }
        return true;
    }
    /**
            \fn checkWorldAccess
            
            @see checkRights
            
    **/
    function checkWorldAccess ($acl,$userdatas) {
        $currentAction = $userdatas['currentAction']; 
        if ($acl[$currentAction]['ao'] == 1) {
            return true;
        }
        return false;
    }
    /**
                \fn checkRightsByAnyGroup
                
                            @see checkRights
    **/
    function checkRightsByAnyGroup ($acl,$userdatas) {
        $userid = $userdatas['userid'];
        $groupid = $userdatas['groupid'];
        $currentAction = $userdatas['currentAction']; 
        $mapping = array();
        foreach ($acl[$currentAction]['ag'] as $cle) {
            $mapping[$cle] = 1;
        }            
        foreach ($_SESSION['usergroups'] as $gid) {
            if ($mapping[$gid] ) {
                return true;
            }
        }
        return false;
    }
    /**
    
                \fn checkRightsByGroup
                
               @see checkRights
    **/
    function checkRightsByGroup ($acl,$userdatas) {
        $userid = $userdatas['userid'];
        $groupid = $userdatas['groupid'];
        $currentAction = $userdatas['currentAction']; 
        foreach ($_SESSION['usergroups'] as $gid) {
            if ($acl[$currentAction]['ago'] == $gid ) {
                return true;
            }
        }
        return false;
    }
    /**
                \fn checkRightByAnyUser
                
                @see checkRights
    **/
    function checkRightByAnyUser ($acl,$userdatas) {
        $userid = $userdatas['userid'];
        $groupid = $userdatas['groupid'];
        $currentAction = $userdatas['currentAction'];
        $mapping = array();
        foreach ($acl[$currentAction]['au'] as $cle) {
            $mapping[$cle] = 1;
        }        
        if ($_SESSION['user_id'] != $userid ) {
            if ($mapping[$userid] == 1) {
                return true;
            } else {
                return false;
            }
        }
    }
    /**
                \fn  checkRightsbyUser
                
                @see checkRights
    **/
    function checkRightsbyUser ($acl,$userdatas) {
        $currentAction = $userdatas['currentAction'];
        if ($_SESSION['user_id'] == $userid ) {
            if ( $acl[$currentAction]['auo'] ==  $_SESSION['user_id'] ) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }    
    }
    /**
            \fn json_decode
            
              transforms php array in json string
              
              @param $array
    
    **/
    function json_encode ($array) {
        $string = '{';
        foreach ($array as $action => $types_array) {
            $string .= "\"$action\":{";
            foreach ($types_array as $type => $droits) {
                $string .= "\"$type\":";
                if (is_array($droits)) {
                    $string .= "[";
                    foreach ($droits as $id) {
                        $string .= "$id,";
                    }
                    $string = preg_replace("/,$/m",'',$string);
                    $string .= "],";
                } else {
                    $string .= "$droits,";
                }
                
            }
            $string = preg_replace("/,$/m",'',$string);
            $string .= '},';
        }
        $string = preg_replace("/\,$/m",'',$string);
        $string .= '}';
        return $string;
    }
    /**
    
            \fn json_encode 
            
             transforms json string in php array
             
             @param $string
    
    **/
    function json_decode ($string) {
        $acl = array();
        $types = array(
                    'auo'   => array ('type'=>'int','rex' => '(\d+)'),
                    'ago'   => array('type'=>'int','rex' => '(\d+)'),
                    'ag'    => array('type'=>'array','rex' => '\[([^\]]*?)\]') ,
                    'au'    => array('type'=>'array','rex' => '\[([^\]]*?)\]'),
                    'ao'    => array('type'=>'int','rex' => '(\d+)'),
                    'am'    => array('type'=>'int','rex' => '(\d+)')
                   );
                    
        preg_match_all(
                        "/
                            \"([^\"]+)\"\:\{(.+?)\}
                        /xmsi",
                        $string,
                        $actions,
                        PREG_SET_ORDER
                        );
        foreach ($actions as $entry) {
            $action = $entry[1];
            $detail_action = $entry[2];
            foreach ($types as $type => $regex) {
                $thisregex = $regex['rex'];
                preg_match_all(
                            "/
                                \"($type)\":$thisregex
                            /xmsi",
                            $detail_action,
                            $res,
                            PREG_SET_ORDER
                        );
                        
                foreach ($res as $value) {
                    $res = $value[2];
                    if ($regex['type'] == 'int') {
                        $acl[$action][$type] = $res;
                    }  
                    if ($regex['type'] == 'array') {
                        if ($value[2]) {
                           $ids = split(',',$value[2]);
                           $acl[$action][$type] = $ids;
                        } else {
                            $acl[$action][$type] = array();
                        }
                    }
                }
            }
        }
        return $acl;
    }
    
}

?>