1<?php
2/**
3 * The Horde_Perms_Base class provides the Horde permissions system.
4 *
5 * Copyright 2001-2017 Horde LLC (http://www.horde.org/)
6 *
7 * See the enclosed file COPYING for license information (LGPL). If you
8 * did not receive this file, see http://www.horde.org/licenses/lgpl21.
9 *
10 * @author   Chuck Hagenbuch <chuck@horde.org>
11 * @author   Jan Schneider <jan@horde.org>
12 * @category Horde
13 * @package  Perms
14 * @todo     Remove $GLOBALS references here and in Sql backend for Horde 6.
15 */
16abstract class Horde_Perms_Base
17{
18    /**
19     * Cache object.
20     *
21     * @var Horde_Cache
22     */
23    protected $_cache;
24
25    /**
26     * Logger.
27     *
28     * @var Horde_Log_Logger
29     */
30    protected $_logger;
31
32    /**
33     * Constructor.
34     *
35     * @param array $params  Configuration parameters:
36     * <pre>
37     * 'cache' - (Horde_Cache) The object to use to cache perms.
38     * 'logger' - (Horde_Log_Logger) A logger object.
39     * </pre>
40     *
41     * @throws Horde_Perms_Exception
42     */
43    public function __construct($params = array())
44    {
45        if (isset($params['cache'])) {
46            $this->_cache = $params['cache'];
47        }
48
49        if (isset($params['logger'])) {
50            $this->_logger = $params['logger'];
51        }
52    }
53
54    /**
55     * Returns the short name of an object, the last portion of the full name.
56     *
57     * @param string $name  The name of the object.
58     *
59     * @return string  The object's short name.
60     */
61    public function getShortName($name)
62    {
63        /* If there are several components to the name, explode and
64         * get the last one, otherwise just return the name. */
65        if (strpos($name, ':') !== false) {
66            $tmp = explode(':', $name);
67            return array_pop($tmp);
68        }
69
70        return $name;
71    }
72
73    /**
74     * Returns a new permissions object.
75     *
76     * @param string $name   The permission's name.
77     * @param string $type   The permission type.
78     * @param array $params  The permission parameters.
79     *
80     * @return Horde_Perms_Permission  A new permissions object.
81     * @throws Horde_Perms_Exception
82     */
83    abstract public function newPermission($name, $type = 'matrix', $params = null);
84
85    /**
86     * Returns an object corresponding to the named permission, with the users
87     * and other data retrieved appropriately.
88     *
89     * @param string $name  The name of the permission to retrieve.
90     *
91     * @return Horde_Perms_Permission  A permissions object.
92     * @throws Horde_Perms_Exception
93     */
94    abstract public function getPermission($name);
95
96    /**
97     * Returns an object corresponding to the given unique ID, with the users
98     * and other data retrieved appropriately.
99     *
100     * @param integer $cid  The unique ID of the permission to retrieve.
101     *
102     * @return Horde_Perms_Permission  A permissions object.
103     * @throws Horde_Perms_Exception
104     */
105    abstract public function getPermissionById($cid);
106
107    /**
108     * Adds a permission to the permissions system. The permission must first
109     * be created with newPermission(), and have any initial users added to
110     * it, before this function is called.
111     *
112     * @param Horde_Perms_Permission $perm  The permissions object.
113     *
114     * @throws Horde_Perms_Exception
115     */
116    abstract public function addPermission(Horde_Perms_Permission $perm);
117
118    /**
119     * Removes a permission from the permissions system permanently.
120     *
121     * @param Horde_Perms_Permission $perm  The permission to remove.
122     * @param boolean $force                Force to remove every child.
123     *
124     * @throws Horde_Perms_Exception
125     */
126    abstract public function removePermission(Horde_Perms_Permission $perm,
127                                              $force = false);
128
129    /**
130     * Finds out what rights the given user has to this object.
131     *
132     * @param mixed $permission  The full permission name of the object to
133     *                           check the permissions of, or the
134     *                           Horde_Permissions object.
135     * @param string $user       The user to check for.
136     * @param string $creator    The user who created the event.
137     *
138     * @return mixed  A bitmask of permissions the user has, false if there
139     *                are none.
140     */
141    public function getPermissions($permission, $user, $creator = null)
142    {
143        if (is_string($permission)) {
144            try {
145                $permission = $this->getPermission($permission);
146            } catch (Horde_Perms_Exception $e) {
147                /* Ignore not exists errors. */
148                if ($this->_logger &&
149                    ($e->getCode() != Horde_Perms_Exception::NOT_EXIST)) {
150                    $this->_logger->log($e, 'DEBUG');
151                }
152                return false;
153            }
154        }
155
156        // If this is a guest user, only check guest permissions.
157        if (empty($user)) {
158            return $permission->getGuestPermissions();
159        }
160
161        // Combine all other applicable permissions.
162        $type = $permission->get('type');
163        $composite_perm = ($type == 'matrix') ? 0 : array();
164
165        // If $creator was specified, check creator permissions.
166        // If the user is the creator of the event see if there are creator
167        // permissions.
168        if (!is_null($creator) &&
169            strlen($user) &&
170            ($user === $creator) &&
171            (($perms = $permission->getCreatorPermissions()) !== null)) {
172            if ($type == 'matrix') {
173                $composite_perm |= $perms;
174            } else {
175                $composite_perm[] = $perms;
176            }
177        }
178
179        // Check user-level permissions.
180        $userperms = $permission->getUserPermissions();
181        if (isset($userperms[$user])) {
182            if ($type == 'matrix') {
183                $composite_perm |= $userperms[$user];
184            } else {
185                $composite_perm[] = $userperms[$user];
186            }
187        }
188
189        // If no user permissions are found, try group permissions.
190        if (isset($permission->data['groups']) &&
191            is_array($permission->data['groups']) &&
192            count($permission->data['groups'])) {
193            $groups = $GLOBALS['injector']
194                ->getInstance('Horde_Group')
195                ->listGroups($user);
196
197            foreach ($permission->data['groups'] as $group => $perms) {
198                if (isset($groups[$group])) {
199                    if ($type == 'matrix') {
200                        $composite_perm |= $perms;
201                    } else {
202                        $composite_perm[] = $perms;
203                    }
204                }
205            }
206        }
207
208        // If there are default permissions, return them.
209        if (($perms = $permission->getDefaultPermissions()) !== null) {
210            if ($type == 'matrix') {
211                $composite_perm |= $perms;
212            } else {
213                $composite_perm[] = $perms;
214            }
215        }
216
217        // Return composed permissions.
218        if ($composite_perm) {
219            return $composite_perm;
220        }
221
222        // Otherwise, deny all permissions to the object.
223        return false;
224    }
225
226    /**
227     * Returns the unique identifier of this permission.
228     *
229     * @param Horde_Perms_Permission $permission  The permission object to get
230     *                                            the ID of.
231     *
232     * @return integer  The unique id.
233     * @throws Horde_Perms_Exception
234     */
235    abstract public function getPermissionId($permission);
236
237    /**
238     * Finds out if the user has the specified rights to the given object.
239     *
240     * @param string $permission  The permission to check.
241     * @param string $user        The user to check for.
242     * @param integer $perm       The permission level that needs to be checked
243     *                            for.
244     * @param string $creator     The creator of the event
245     *
246     * @return boolean  Whether the user has the specified permissions.
247     */
248    public function hasPermission($permission, $user, $perm, $creator = null)
249    {
250        return (bool)($this->getPermissions($permission, $user, $creator) & $perm);
251    }
252
253    /**
254     * Checks if a permission exists in the system.
255     *
256     * @param string $permission  The permission to check.
257     *
258     * @return boolean  True if the permission exists.
259     */
260    abstract public function exists($permission);
261
262    /**
263     * Returns a list of parent permissions.
264     *
265     * @param string $child  The name of the child to retrieve parents for.
266     *
267     * @return array  A hash with all parents in a tree format.
268     * @throws Horde_Perms_Exception
269     */
270    abstract public function getParents($child);
271
272    /**
273     * Returns all permissions of the system in a tree format.
274     *
275     * @return array  A hash with all permissions in a tree format.
276     */
277    abstract public function getTree();
278}
279