Issues (340)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  Header Injection
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

class/PermissionHandler.php (5 issues)

1
<?php declare(strict_types=1);
2
3
namespace XoopsModules\Newbb;
4
5
/**
6
 * NewBB,  the forum module for XOOPS project
7
 *
8
 * @copyright      XOOPS Project (https://xoops.org)
9
 * @license        GNU GPL 2.0 or later (https://www.gnu.org/licenses/gpl-2.0.html)
10
 * @author         Taiwen Jiang (phppp or D.J.) <[email protected]>
11
 * @since          4.00
12
 */
13
14
use Xmf\Module\Helper\Cache;
15
16
/** @var Cache $cacheHelper */
17
18
\defined('NEWBB_FUNCTIONS_INI') || require $GLOBALS['xoops']->path('modules/newbb/include/functions.ini.php');
19
\define('NEWBB_HANDLER_PERMISSION', 1);
20
21
// Initializing XoopsGroupPermHandler if not loaded yet
22
if (!\class_exists('XoopsGroupPermHandler')) {
23
    require_once $GLOBALS['xoops']->path('kernel/groupperm.php');
24
}
25
26
/**
27
 * Class PermissionHandler
28
 */
29
class PermissionHandler extends \XoopsGroupPermHandler
30
{
31
    protected Cache $cacheHelper;
32
    /** @var array|null */
33
    private array $_handler;
34
    
35
    /** @var Helper|null $helper
36
     * @readonly */
37
    private ?Helper $helper;
38
39
    /**
40
     * @param \XoopsDatabase|null $db
41
     * @param Helper|null         $helper
42
     */
43
    public function __construct(\XoopsDatabase $db = null, Helper $helper = null)
44
    {
45
        $this->cacheHelper = new Cache('newbb');
46
        if (null === $helper) {
47
            $helper = Helper::getInstance();
48
        }
49
        $this->helper = $helper;
50
51
        $this->db = $db;
52
        parent::__construct($db);
0 ignored issues
show
It seems like $db can also be of type null; however, parameter $db of XoopsGroupPermHandler::__construct() does only seem to accept XoopsDatabase, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

52
        parent::__construct(/** @scrutinizer ignore-type */ $db);
Loading history...
53
    }
54
55
    /**
56
     * @param string $name
57
     * @return mixed
58
     */
59
    public function loadHandler(string $name)
60
    {
61
        if (!isset($this->_handler[$name])) {
62
            //            $className             = '\\XoopsModules\\Newbb\\Permission' . \ucfirst($name) . 'Handler';
63
            //            $this->_handler[$name] = new $className($this->db);
64
            $this->_handler[$name] = $this->helper->getHandler('Permission' . \ucfirst($name));
0 ignored issues
show
The method getHandler() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

64
            /** @scrutinizer ignore-call */ 
65
            $this->_handler[$name] = $this->helper->getHandler('Permission' . \ucfirst($name));

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
65
        }
66
67
        return $this->_handler[$name];
68
    }
69
70
    /**
71
     * @param bool $fullname
72
     * @return array
73
     */
74
    public function getValidForumPerms(bool $fullname = false): array
75
    {
76
        /** @var PermissionForumHandler $handler */
77
        $handler = $this->loadHandler('Forum');
78
79
        return $handler->getValidPerms($fullname);
80
    }
81
82
    /**
83
     * @param int|Forum  $forum
84
     * @param bool $topic_locked
85
     * @param bool $isAdmin
86
     * @return array
87
     */
88
    public function getPermissionTable($forum = 0, bool $topic_locked = false, bool $isAdmin = false): array
89
    {
90
        /** @var PermissionForumHandler $handler */
91
        $handler = $this->loadHandler('Forum');
92
        $perm    = $handler->getPermissionTable($forum, $topic_locked, $isAdmin);
93
94
        return $perm;
95
    }
96
97
    /**
98
     * @param int $forum_id
99
     * @return bool
100
     */
101
    public function deleteByForum(int $forum_id): bool
102
    {
103
        $this->cacheHelper->delete('permission_forum');
104
        /** @var PermissionForumHandler $handler */
105
        $handler = $this->loadHandler('Forum');
106
107
        return $handler->deleteByForum($forum_id);
108
    }
109
110
    /**
111
     * @param int $cat_id
112
     * @return bool
113
     */
114
    public function deleteByCategory(int $cat_id):bool
115
    {
116
        $this->cacheHelper->delete('permission_category');
117
        /** @var PermissionCategoryHandler $handler */
118
        $handler = $this->loadHandler('Category');
119
120
        return $handler->deleteByCategory($cat_id);
121
    }
122
123
    /**
124
     * @param int $category
125
     * @param array  $groups
126
     * @return bool
127
     */
128
    public function setCategoryPermission(int $category, array $groups = []): bool
129
    {
130
        $this->cacheHelper->delete('permission_category');
131
        /** @var PermissionCategoryHandler $handler */
132
        $handler = $this->loadHandler('Category');
133
134
        return $handler->setCategoryPermission($category, $groups);
135
    }
136
137
    /**
138
     * @param string $type
139
     * @param string $gperm_name
140
     * @param int    $id
141
     * @return bool
142
     */
143
    public function getPermission(string $type, string $gperm_name = 'access', int $id = 0): bool
144
    {
145
        global $xoopsModule;
146
        $ret = false;
147
        if ($GLOBALS['xoopsUserIsAdmin'] && 'newbb' === $xoopsModule->getVar('dirname')) {
148
            $ret = true;
149
        }
150
151
        $groups = \is_object($GLOBALS['xoopsUser']) ? $GLOBALS['xoopsUser']->getGroups() : [XOOPS_GROUP_ANONYMOUS];
152
        if (!$groups) {
153
            $ret = false;
154
        }
155
        if (!$allowed_groups = $this->getGroups("{$type}_{$gperm_name}", $id)) {
156
            $ret = false;
157
        }
158
159
        if (\count(\array_intersect($allowed_groups, $groups)) > 0) {
160
            $ret = true;
161
        }
162
163
        return $ret;
164
    }
165
166
    /**
167
     * @param string $permName
168
     * @return array
169
     */
170
    public function &getCategories(string $permName = 'access'): array
171
    {
172
        $ret = $this->getAllowedItems('category', "category_{$permName}");
173
174
        return $ret;
175
    }
176
177
    /**
178
     * @param string $permName
179
     * @return array
180
     */
181
    public function getForums(string $permName = 'access'): array
182
    {
183
        $ret = $this->getAllowedItems('forum', "forum_{$permName}");
184
185
        return $ret;
186
    }
187
188
    /**
189
     * @param string $type
190
     * @param string $permName
191
     * @return array
192
     */
193
    public function getAllowedItems(string $type, string $permName): array
0 ignored issues
show
The parameter $type is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

193
    public function getAllowedItems(/** @scrutinizer ignore-unused */ string $type, string $permName): array

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
194
    {
195
        $ret = [];
196
197
        $groups = \is_object($GLOBALS['xoopsUser']) ? $GLOBALS['xoopsUser']->getGroups() : [XOOPS_GROUP_ANONYMOUS];
198
        if ((is_countable($groups) ? \count($groups) : 0) < 1) {
199
            return $ret;
200
        }
201
202
        if (!$_cachedPerms = $this->loadPermData($permName)) {
203
            return $ret;
204
        }
205
206
        $allowed_items = [];
207
        foreach ($_cachedPerms as $id => $allowed_groups) {
208
            if (0 == $id || empty($allowed_groups)) {
209
                continue;
210
            }
211
212
            if (\array_intersect($groups, $allowed_groups)) {
213
                $allowed_items[$id] = 1;
214
            }
215
        }
216
        unset($_cachedPerms);
217
        $ret = \array_keys($allowed_items);
218
219
        return $ret;
220
    }
221
222
    /**
223
     * @param string $gperm_name
224
     * @param int    $id
225
     * @return array
226
     */
227
    public function getGroups(string $gperm_name, int $id = 0): array
228
    {
229
        $_cachedPerms = $this->loadPermData($gperm_name);
230
        $groups       = empty($_cachedPerms[$id]) ? [] : \array_unique($_cachedPerms[$id]);
231
        unset($_cachedPerms);
232
233
        return $groups;
234
    }
235
236
    /**
237
     * @param string $permName
238
     * @return array
239
     */
240
    public function createPermData(string $permName = 'forum_all'): array
241
    {
242
        global $xoopsModule;
243
        /** @var \XoopsModuleHandler $moduleHandler */
244
        $perms = [];
245
246
        if (\is_object($xoopsModule) && 'newbb' === $xoopsModule->getVar('dirname')) {
247
            $modid = $xoopsModule->getVar('mid');
248
        } else {
249
            /** @var \XoopsModuleHandler $moduleHandler */
250
            $moduleHandler = \xoops_getHandler('module');
251
            $module        = $moduleHandler->getByDirname('newbb');
252
            $modid         = $module->getVar('mid');
253
            unset($module);
254
        }
255
256
        if (\in_array($permName, ['forum_all', 'category_all'], true)) {
257
            /** @var \XoopsMemberHandler $memberHandler */
258
            $memberHandler = \xoops_getHandler('member');
259
            $groups        = \array_keys($memberHandler->getGroupList());
260
261
            $type = ('category_all' === $permName) ? 'Category' : 'Forum';
262
            /** @var \XoopsPersistableObjectHandler $objectHandler */
263
            $objectHandler = Helper::getInstance()->getHandler($type);
264
            $object_ids    = $objectHandler->getIds();
265
            foreach ($object_ids as $item_id) {
266
                $perms[$permName][$item_id] = $groups;
267
            }
268
        } else {
269
            $grouppermHandler = \xoops_getHandler('groupperm');
0 ignored issues
show
The assignment to $grouppermHandler is dead and can be removed.
Loading history...
270
            $criteria         = new \CriteriaCompo(new \Criteria('gperm_modid', $modid));
271
            if (!empty($permName) && 'forum_all' !== $permName && 'category_all' !== $permName) {
272
                $criteria->add(new \Criteria('gperm_name', $permName));
273
            }
274
            $permissions = $this->getObjects($criteria);
275
276
            foreach ($permissions as $gperm) {
277
                $item_id                                         = $gperm->getVar('gperm_itemid');
278
                $group_id                                        = (int)$gperm->getVar('gperm_groupid');
279
                $perms[$gperm->getVar('gperm_name')][$item_id][] = $group_id;
280
            }
281
        }
282
        if (\count($perms) > 0) {
283
            foreach (\array_keys($perms) as $perm) {
284
                $this->cacheHelper->write("permission_{$perm}", $perms[$perm]);
285
            }
286
        }
287
        $ret = (!empty($permName) && !empty($perms)) ? @$perms[$permName] : $perms;
288
289
        return $ret;
290
    }
291
292
    /**
293
     * @param string $permName
294
     * @return array
295
     */
296
    public function &loadPermData(string $permName = 'forum_access'): array
297
    {
298
        if (!$perms = $this->cacheHelper->read("permission_{$permName}")) {
299
            $perms = $this->createPermData($permName);
300
        }
301
302
        return $perms;
303
    }
304
305
    /**
306
     * @param string   $perm
307
     * @param int      $itemid
308
     * @param int      $groupid
309
     * @param int|null $mid
310
     * @return bool
311
     */
312
    public function validateRight(string $perm, int $itemid, int $groupid, ?int $mid = null): bool
313
    {
314
        if (empty($mid)) {
315
            if (\is_object($GLOBALS['xoopsModule']) && 'newbb' === $GLOBALS['xoopsModule']->getVar('dirname')) {
316
                $mid = $GLOBALS['xoopsModule']->getVar('mid');
317
            } else {
318
                /** @var \XoopsModuleHandler $moduleHandler */
319
                $moduleHandler = \xoops_getHandler('module');
320
                $mod           = $moduleHandler->getByDirname('newbb');
321
                $mid           = $mod->getVar('mid');
322
                unset($mod);
323
            }
324
        }
325
        if ($this->myCheckRight($perm, $itemid, $groupid, $mid)) {
326
            return true;
327
        }
328
        $this->cacheHelper->delete('permission');
329
        $this->addRight($perm, $itemid, $groupid, $mid);
330
331
        return true;
332
    }
333
334
    /**
335
     * Check permission (directly)
336
     *
337
     * @param string    $gperm_name    Name of permission
338
     * @param int       $gperm_itemid  ID of an item
339
     * @param int|array $gperm_groupid A group ID or an array of group IDs
340
     * @param int       $gperm_modid   ID of a module
341
     *
342
     * @return bool TRUE if permission is enabled
343
     */
344
    public function myCheckRight(string $gperm_name, int $gperm_itemid, $gperm_groupid, int $gperm_modid = 1): bool
345
    {
346
        $ret      = false;
347
        $criteria = new \CriteriaCompo(new \Criteria('gperm_modid', $gperm_modid));
348
        $criteria->add(new \Criteria('gperm_name', $gperm_name));
349
        $gperm_itemid = (int)$gperm_itemid;
350
        if ($gperm_itemid > 0) {
351
            $criteria->add(new \Criteria('gperm_itemid', $gperm_itemid));
352
        }
353
        if (\is_array($gperm_groupid)) {
354
            $criteria2 = new \CriteriaCompo();
355
            foreach ($gperm_groupid as $gid) {
356
                $criteria2->add(new \Criteria('gperm_groupid', $gid), 'OR');
357
            }
358
            $criteria->add($criteria2);
359
        } else {
360
            $criteria->add(new \Criteria('gperm_groupid', $gperm_groupid));
361
        }
362
        if ($this->getCount($criteria) > 0) {
363
            $ret = true;
364
        }
365
366
        return $ret;
367
    }
368
369
    /**
370
     * @param string   $perm
371
     * @param int      $itemid
372
     * @param int      $groupid
373
     * @param int|null $mid
374
     * @return bool
375
     */
376
    public function deleteRight(string $perm, int $itemid, int $groupid, ?int $mid = null): bool
377
    {
378
        $this->cacheHelper->delete('permission');
379
        if (null === $mid) {
380
            if (\is_object($GLOBALS['xoopsModule']) && 'newbb' === $GLOBALS['xoopsModule']->getVar('dirname')) {
381
                $mid = $GLOBALS['xoopsModule']->getVar('mid');
382
            } else {
383
                /** @var \XoopsModuleHandler $moduleHandler */
384
                $moduleHandler = \xoops_getHandler('module');
385
                $mod           = $moduleHandler->getByDirname('newbb');
386
                $mid           = $mod->getVar('mid');
387
                unset($mod);
388
            }
389
        }
390
        if (\is_callable('parent::deleteRight')) {
391
            return self::deleteRight($perm, $itemid, $groupid, $mid);
0 ignored issues
show
Bug Best Practice introduced by
The method XoopsModules\Newbb\Permi...nHandler::deleteRight() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

391
            return self::/** @scrutinizer ignore-call */ deleteRight($perm, $itemid, $groupid, $mid);
Loading history...
392
        }
393
        $criteria = new \CriteriaCompo(new \Criteria('gperm_name', $perm));
394
        $criteria->add(new \Criteria('gperm_groupid', $groupid));
395
        $criteria->add(new \Criteria('gperm_itemid', $itemid));
396
        $criteria->add(new \Criteria('gperm_modid', $mid));
397
        $permsObject = $this->getObjects($criteria);
398
        if (!empty($permsObject)) {
399
            foreach ($permsObject as $permObject) {
400
                $this->delete($permObject);
401
            }
402
        }
403
        unset($criteria, $permsObject);
404
405
        return true;
406
    }
407
408
    /**
409
     * @param int $forum
410
     * @param int $mid
411
     * @return bool
412
     */
413
    public function applyTemplate(int $forum, int $mid = 0): bool
414
    {
415
        $this->cacheHelper->delete('permission_forum');
416
        /** @var PermissionForumHandler $handler */
417
        $handler = $this->loadHandler('Forum');
418
419
        return $handler->applyTemplate($forum, $mid);
420
    }
421
422
    /**
423
     * @return array
424
     */
425
    public function getTemplate(): array
426
    {
427
        /** @var PermissionForumHandler $handler */
428
        $handler  = $this->loadHandler('Forum');
429
        $template = $handler->getTemplate();
430
431
        return $template;
432
    }
433
434
    /**
435
     * @param array $perms
436
     * @param int   $groupid
437
     * @return bool|int
438
     */
439
    public function setTemplate(array $perms, int $groupid = 0)
440
    {
441
        /** @var PermissionForumHandler $handler */
442
        $handler = $this->loadHandler('Forum');
443
444
        return $handler->setTemplate($perms, $groupid);
445
    }
446
}
447