Issues (299)

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/Utility.php (2 issues)

1
<?php declare(strict_types=1);
2
3
namespace XoopsModules\Smartfaq;
4
5
use XoopsModules\Smartfaq;
6
7
/**
8
 * Class Utility
9
 */
10
class Utility extends Common\SysUtility
11
{
12
    //--------------- Custom module methods -----------------------------
13
    /**
14
     * @return mixed|null
15
     */
16
    public static function getModuleInfo()
17
    {
18
        static $smartModule;
19
        if (null === $smartModule) {
20
            global $xoopsModule;
21
            if (null !== $xoopsModule && \is_object($xoopsModule) && 'smartfaq' === $xoopsModule->getVar('dirname')) {
22
                $smartModule = $xoopsModule;
23
            } else {
24
                $moduleHandler = \xoops_getHandler('module');
25
                $smartModule   = $moduleHandler->getByDirname('smartfaq');
26
            }
27
        }
28
29
        return $smartModule;
30
    }
31
32
    /**
33
     * @return mixed
34
     */
35
    public static function getModuleConfig()
36
    {
37
        static $smartConfig;
38
        if (!$smartConfig) {
39
            global $xoopsModule;
40
            if (null !== $xoopsModule && \is_object($xoopsModule) && 'smartfaq' === $xoopsModule->getVar('dirname')) {
41
                global $xoopsModuleConfig;
42
                $smartConfig = $xoopsModuleConfig;
43
            } else {
44
                $smartModule = self::getModuleInfo();
45
                /** @var \XoopsConfigHandler $configHandler */
46
                $configHandler  = \xoops_getHandler('config');
47
                $smartConfig = $configHandler->getConfigsByCat(0, $smartModule->getVar('mid'));
48
            }
49
        }
50
51
        return $smartConfig;
52
    }
53
54
    /**
55
     * @return string
56
     */
57
    public static function getHelpPath()
58
    {
59
        $smartConfig = self::getModuleConfig();
60
        switch ($smartConfig['helppath_select']) {
61
            case 'docs.xoops.org':
62
                return 'https://docs.xoops.org/help/sfaqh/index.htm';
63
            case 'inside':
64
                return XOOPS_URL . '/modules/smartfaq/doc/';
65
            case 'custom':
66
                return $smartConfig['helppath_custom'];
67
        }
68
    }
69
70
    /**
71
     * @param array $errors
72
     * @return string
73
     */
74
    public static function formatErrors($errors = [])
75
    {
76
        $ret = '';
77
        foreach ($errors as $key => $value) {
78
            $ret .= '<br> - ' . $value;
79
        }
80
81
        return $ret;
82
    }
83
84
    /**
85
     * @param         $categoryObj
86
     * @param int     $selectedid
87
     * @param int     $level
88
     * @param string  $ret
89
     * @return string
90
     */
91
    public static function addCategoryOption($categoryObj, $selectedid = 0, $level = 0, $ret = '')
92
    {
93
        // Creating the category handler object
94
        /** @var Smartfaq\CategoryHandler $categoryHandler */
95
        $categoryHandler = Smartfaq\Helper::getInstance()->getHandler('Category');
96
97
        $spaces = '';
98
        for ($j = 0; $j < $level; ++$j) {
99
            $spaces .= '--';
100
        }
101
102
        $ret .= "<option value='" . $categoryObj->categoryid() . "'";
103
        if ($selectedid == $categoryObj->categoryid()) {
104
            $ret .= ' selected';
105
        }
106
        $ret .= '>' . $spaces . $categoryObj->name() . "</option>\n";
107
108
        $subCategoriesObj = &$categoryHandler->getCategories(0, 0, $categoryObj->categoryid());
109
        if (\count($subCategoriesObj) > 0) {
110
            ++$level;
111
            foreach ($subCategoriesObj as $catID => $subCategoryObj) {
112
                $ret .= self::addCategoryOption($subCategoryObj, $selectedid, $level);
113
            }
114
        }
115
116
        return $ret;
117
    }
118
119
    /**
120
     * @param int  $selectedid
121
     * @param int  $parentcategory
122
     * @param bool $allCatOption
123
     * @return string
124
     */
125
    public static function createCategorySelect($selectedid = 0, $parentcategory = 0, $allCatOption = true)
126
    {
127
        $ret = \_MB_SF_SELECTCAT . "&nbsp;<select name='options[]'>";
128
        if ($allCatOption) {
129
            $ret .= "<option value='0'";
130
            $ret .= '>' . \_MB_SF_ALLCAT . "</option>\n";
131
        }
132
133
        // Creating the category handler object
134
        $categoryHandler = Smartfaq\Helper::getInstance()->getHandler('Category');
135
136
        // Creating category objects
137
        $categoriesObj = $categoryHandler->getCategories(0, 0, $parentcategory);
138
139
        if (\count($categoriesObj) > 0) {
140
            foreach ($categoriesObj as $catID => $categoryObj) {
141
                $ret .= self::addCategoryOption($categoryObj, $selectedid);
142
            }
143
        }
144
        $ret .= "</select>\n";
145
146
        return $ret;
147
    }
148
149
    /**
150
     * @return array
151
     */
152
    public static function getStatusArray()
153
    {
154
        $result = [
155
            1 => \_AM_SF_STATUS1,
156
            2 => \_AM_SF_STATUS2,
157
            3 => \_AM_SF_STATUS3,
158
            4 => \_AM_SF_STATUS4,
159
            5 => \_AM_SF_STATUS5,
160
            6 => \_AM_SF_STATUS6,
161
            7 => \_AM_SF_STATUS7,
162
            8 => \_AM_SF_STATUS8,
163
        ];
164
165
        return $result;
166
    }
167
168
    /**
169
     * @return bool
170
     */
171
    public static function hasModerator()
172
    {
173
        global $xoopsUser;
174
175
        if ($xoopsUser) {
176
            /** @var Smartfaq\PermissionHandler $smartPermHandler */
177
            $smartPermHandler = Smartfaq\Helper::getInstance()->getHandler('Permission');
178
179
            $categories = $smartPermHandler->getPermissions('moderation');
180
            if (0 == \count($categories)) {
181
                $result = false;
182
            } else {
183
                $result = true;
184
            }
185
        } else {
186
            $result = false;
187
        }
188
189
        return $result;
190
    }
191
192
    /**
193
     * @return string
194
     */
195
    public static function modFooter()
196
    {
197
        $smartModule = self::getModuleInfo();
198
199
        $modfootertxt = 'Module ' . $smartModule->getInfo('name') . ' - Version ' . $smartModule->getInfo('version');
200
201
        $modfooter = "<a href='" . $smartModule->getInfo('support_site_url') . "' target='_blank'><img src='" . XOOPS_URL . "/modules/smartfaq/assets/images/sfcssbutton.gif' title='" . $modfootertxt . "' alt='" . $modfootertxt . "'></a>";
202
203
        return $modfooter;
204
    }
205
206
    /**
207
     * Checks if a user is admin of Smartfaq
208
     *
209
     * self::userIsAdmin()
210
     *
211
     * @return bool array with userids and uname
212
     */
213
    public static function userIsAdmin()
214
    {
215
        global $xoopsUser;
216
217
        $result = false;
218
219
        $smartModule = self::getModuleInfo();
220
        $module_id   = $smartModule->getVar('mid');
221
222
        if (!empty($xoopsUser)) {
223
            $groups = &$xoopsUser->getGroups();
224
            $result = \in_array(XOOPS_GROUP_ADMIN, $groups, true) || $xoopsUser->isAdmin($module_id);
225
        }
226
227
        return $result;
228
    }
229
230
    /**
231
     * Checks if a user has access to a selected faq. If no item permissions are
232
     * set, access permission is denied. The user needs to have necessary category
233
     * permission as well.
234
     *
235
     * self::faqAccessGranted()
236
     *
237
     * @param $faqObj
238
     * @return int -1 if no access, 0 if partialview and 1 if full access
239
     * @internal param int $faqid faqid on which we are setting permissions
240
     * @internal param int $categoryid categoryid of the faq
241
     */
242
243
    // TODO : Move this function to Smartfaq\Faq class
244
    public static function faqAccessGranted($faqObj)
245
    {
246
        global $xoopsUser;
247
248
        if (self::userIsAdmin()) {
249
            $result = 1;
250
        } else {
251
            $result = -1;
252
253
            $groups = $xoopsUser ? $xoopsUser->getGroups() : XOOPS_GROUP_ANONYMOUS;
254
            /** @var \XoopsGroupPermHandler $grouppermHandler */
255
            $grouppermHandler = \xoops_getHandler('groupperm');
256
            $smartModule      = self::getModuleInfo();
257
            $module_id        = $smartModule->getVar('mid');
258
259
            // Do we have access to the parent category
260
            if ($grouppermHandler->checkRight('category_read', $faqObj->categoryid(), $groups, $module_id)) {
261
                // Do we have access to the faq?
262
                if ($grouppermHandler->checkRight('item_read', $faqObj->faqid(), $groups, $module_id)) {
263
                    $result = 1;
264
                } else { // No we don't !
265
                    // Check to see if we have partial view access
266
                    if (!\is_object($xoopsUser) && $faqObj->partialView()) {
267
                        return 0;
268
                    }
269
                }
270
            } else { // No we don't !
271
                $result = false;
272
            }
273
        }
274
275
        return $result;
276
    }
277
278
    /**
279
     * Override FAQs permissions of a category by the category read permissions
280
     *
281
     *   self::overrideFaqsPermissions()
282
     *
283
     * @param array $groups     group with granted permission
284
     * @param int   $categoryid
285
     * @return bool|array TRUE if the no errors occurred
286
     */
287
    public static function overrideFaqsPermissions($groups, $categoryid)
288
    {
289
        global $xoopsDB;
290
291
        $result      = true;
0 ignored issues
show
The assignment to $result is dead and can be removed.
Loading history...
292
        $smartModule = self::getModuleInfo();
293
        $module_id   = $smartModule->getVar('mid');
294
295
        $grouppermHandler = \xoops_getHandler('groupperm');
296
297
        $sql    = 'SELECT faqid FROM ' . $xoopsDB->prefix('smartfaq_faq') . " WHERE categoryid = '$categoryid' ";
298
        $result = $xoopsDB->queryF($sql);
299
300
        if ($GLOBALS['xoopsDB']->getRowsNum($result) > 0) {
301
            while ([$faqid] = $xoopsDB->fetchRow($result)) {
302
                // First, if the permissions are already there, delete them
303
                $grouppermHandler->deleteByModule($module_id, 'item_read', $faqid);
304
                // Save the new permissions
305
                if (\count($groups) > 0) {
306
                    foreach ($groups as $group_id) {
307
                        $grouppermHandler->addRight('item_read', $faqid, $group_id, $module_id);
308
                    }
309
                }
310
            }
311
        }
312
313
        return $result;
314
    }
315
316
    /**
317
     * Saves permissions for the selected faq
318
     *
319
     *   self::saveItemPermissions()
320
     *
321
     * @param array $groups group with granted permission
322
     * @param int   $itemID faqid on which we are setting permissions
323
     * @return bool TRUE if the no errors occurred
324
     */
325
    public static function saveItemPermissions($groups, $itemID)
326
    {
327
        $result      = true;
328
        $smartModule = self::getModuleInfo();
329
        $module_id   = $smartModule->getVar('mid');
330
331
        $grouppermHandler = \xoops_getHandler('groupperm');
332
        // First, if the permissions are already there, delete them
333
        $grouppermHandler->deleteByModule($module_id, 'item_read', $itemID);
334
        // Save the new permissions
335
        if (\count($groups) > 0) {
336
            foreach ($groups as $group_id) {
337
                $grouppermHandler->addRight('item_read', $itemID, $group_id, $module_id);
338
            }
339
        }
340
341
        return $result;
342
    }
343
344
    /**
345
     * Saves permissions for the selected category
346
     *
347
     *   self::saveCategoryPermissions()
348
     *
349
     * @param array  $groups      group with granted permission
350
     * @param int    $categoryid  categoryid on which we are setting permissions
351
     * @param string $perm_name   name of the permission
352
     * @return bool  TRUE if the no errors occurred
353
     */
354
    public static function saveCategoryPermissions($groups, $categoryid, $perm_name)
355
    {
356
        $result      = true;
357
        $smartModule = self::getModuleInfo();
358
        $module_id   = $smartModule->getVar('mid');
359
360
        $grouppermHandler = \xoops_getHandler('groupperm');
361
        // First, if the permissions are already there, delete them
362
        $grouppermHandler->deleteByModule($module_id, $perm_name, $categoryid);
363
        // Save the new permissions
364
        if (\count($groups) > 0) {
365
            foreach ($groups as $group_id) {
366
                $grouppermHandler->addRight($perm_name, $categoryid, $group_id, $module_id);
367
            }
368
        }
369
370
        return $result;
371
    }
372
373
    /**
374
     * Saves permissions for the selected category
375
     *
376
     *   self::saveModerators()
377
     *
378
     * @param array $moderators moderators uids
379
     * @param int   $categoryid categoryid on which we are setting permissions
380
     * @return bool TRUE if the no errors occurred
381
     */
382
    public static function saveModerators($moderators, $categoryid)
383
    {
384
        $result      = true;
385
        $smartModule = self::getModuleInfo();
386
        $module_id   = $smartModule->getVar('mid');
387
388
        $grouppermHandler = \xoops_getHandler('groupperm');
389
        // First, if the permissions are already there, delete them
390
        $grouppermHandler->deleteByModule($module_id, 'category_moderation', $categoryid);
391
        // Save the new permissions
392
        if (\count($moderators) > 0) {
393
            foreach ($moderators as $uid) {
394
                $grouppermHandler->addRight('category_moderation', $categoryid, $uid, $module_id);
395
            }
396
        }
397
398
        return $result;
399
    }
400
401
    /**
402
     * @param int $faqid
403
     * @return array
404
     */
405
    public static function retrieveFaqByID($faqid = 0)
406
    {
407
        $ret = [];
0 ignored issues
show
The assignment to $ret is dead and can be removed.
Loading history...
408
        global $xoopsDB;
409
410
        $result = $xoopsDB->queryF('SELECT * FROM ' . $xoopsDB->prefix('smartfaq_faq') . " WHERE faqid = '$faqid'");
411
        $ret    = $xoopsDB->fetchArray($result);
412
413
        return $ret;
414
    }
415
416
    /**
417
     * self::getAdminLinks()
418
     *
419
     * @param int  $faqid
420
     * @param bool $open
421
     * @return string
422
     */
423
424
    // TODO : Move this to the Smartfaq\Faq class
425
    public static function getAdminLinks($faqid = 0, $open = false)
426
    {
427
        global $xoopsUser, $xoopsModule, $xoopsConfig;
428
        /** @var Smartfaq\Helper $helper */
429
        $helper = Smartfaq\Helper::getInstance();
430
431
        $adminLinks = '';
432
        $modulePath = XOOPS_URL . '/modules/' . $xoopsModule->dirname() . '/';
433
        $page       = $open ? 'question.php' : 'faq.php';
434
        if ($xoopsUser && $xoopsUser->isAdmin($xoopsModule->getVar('mid'))) {
435
            // Edit button
436
            $adminLinks .= "<a href='" . $modulePath . "admin/$page?op=mod&amp;faqid=" . $faqid . "'><img src='" . $modulePath . "assets/images/links/edit.gif'" . " title='" . \_MD_SF_EDIT . "' alt='" . \_MD_SF_EDIT . "'></a>";
437
            $adminLinks .= ' ';
438
            // Delete button
439
            $adminLinks .= "<a href='" . $modulePath . "admin/$page?op=del&amp;faqid=" . $faqid . "'><img src='" . $modulePath . "assets/images/links/delete.gif'" . " title='" . \_MD_SF_DELETE . "' alt='" . \_MD_SF_DELETE . "'></a>";
440
            $adminLinks .= ' ';
441
        }
442
        // Print button
443
        $adminLinks .= "<a href='" . $modulePath . 'print.php?faqid=' . $faqid . "'><img src='" . $modulePath . "assets/images/links/print.gif' title='" . \_MD_SF_PRINT . "' alt='" . \_MD_SF_PRINT . "'></a>";
444
        $adminLinks .= ' ';
445
        // Email button
446
        $maillink   = 'mailto:?subject=' . \sprintf(\_MD_SF_INTARTICLE, $xoopsConfig['sitename']) . '&amp;body=' . \sprintf(\_MD_SF_INTARTFOUND, $xoopsConfig['sitename']) . ':  ' . $modulePath . 'faq.php?faqid=' . $faqid;
447
        $adminLinks .= '<a href="' . $maillink . "\"><img src='" . $modulePath . "assets/images/links/friend.gif' title='" . \_MD_SF_MAIL . "' alt='" . \_MD_SF_MAIL . "'></a>";
448
        $adminLinks .= ' ';
449
        // Submit New Answer button
450
        if ($helper->getConfig('allownewanswer') && (\is_object($xoopsUser) || $helper->getConfig('anonpost'))) {
451
            $adminLinks .= "<a href='" . $modulePath . 'answer.php?faqid=' . $faqid . "'><img src='" . $modulePath . "assets/images/links/newanswer.gif' title='" . \_MD_SF_SUBMITANSWER . "' alt='" . \_MD_SF_SUBMITANSWER . "'></a>";
452
            $adminLinks .= ' ';
453
        }
454
455
        return $adminLinks;
456
    }
457
458
    /**
459
     * self::getLinkedUnameFromId()
460
     *
461
     * @param int   $userid Userid of poster etc
462
     * @param int   $name   :  0 Use Usenamer 1 Use realname
463
     * @param array $users
464
     * @return string
465
     */
466
    public static function getLinkedUnameFromId($userid = 0, $name = 0, $users = [])
467
    {
468
        if (!\is_numeric($userid)) {
469
            return $userid;
470
        }
471
472
        $userid = (int)$userid;
473
        if ($userid > 0) {
474
            if ($users == []) {
475
                //fetching users
476
                /** @var \XoopsMemberHandler $memberHandler */
477
                $memberHandler = \xoops_getHandler('member');
478
                $user          = $memberHandler->getUser($userid);
479
            } else {
480
                if (!isset($users[$userid])) {
481
                    return $GLOBALS['xoopsConfig']['anonymous'];
482
                }
483
                $user = &$users[$userid];
484
            }
485
486
            if (\is_object($user)) {
487
                $ts       = \MyTextSanitizer::getInstance();
488
                $username = $user->getVar('uname');
489
                $fullname = '';
490
491
                $fullname2 = $user->getVar('name');
492
493
                if ($name && !empty($fullname2)) {
494
                    $fullname = $user->getVar('name');
495
                }
496
                if (!empty($fullname)) {
497
                    $linkeduser = "$fullname [<a href='" . XOOPS_URL . '/userinfo.php?uid=' . $userid . "'>" . $ts->htmlSpecialChars($username) . '</a>]';
498
                } else {
499
                    $linkeduser = "<a href='" . XOOPS_URL . '/userinfo.php?uid=' . $userid . "'>" . \ucwords($ts->htmlSpecialChars($username)) . '</a>';
500
                }
501
502
                return $linkeduser;
503
            }
504
        }
505
506
        return $GLOBALS['xoopsConfig']['anonymous'];
507
    }
508
509
    /**
510
     * @param string $url
511
     * @return mixed|string
512
     */
513
    public static function getXoopslink($url = '')
514
    {
515
        $xurl = $url;
516
        if ('' !== $xurl) {
517
            $xurl[0] = '/';
518
            if ($xurl[0]) {
519
                $xurl = \str_replace('/', '', $xurl);
520
            }
521
            $xurl = \str_replace('{SITE_URL}', XOOPS_URL, $xurl);
522
        }
523
524
        //        $xurl = $url;
525
526
        return $xurl;
527
    }
528
529
    /**
530
     * @param string $tablename
531
     * @param string $iconname
532
     */
533
    public static function collapsableBar($tablename = '', $iconname = ''): void
534
    {
535
        ?>
536
        <script type="text/javascript"><!--
537
            function goto_URL(object) {
538
                window.location.href = object.options[object.selectedIndex].value;
539
            }
540
541
            function toggle(id) {
542
                if (document.getElementById) {
543
                    obj = document.getElementById(id);
544
                }
545
                if (document.all) {
546
                    obj = document.all[id];
547
                }
548
                if (document.layers) {
549
                    obj = document.layers[id];
550
                }
551
                if (obj) {
552
                    if (obj.style.display === "none") {
553
                        obj.style.display = "";
554
                    } else {
555
                        obj.style.display = "none";
556
                    }
557
                }
558
559
                return false;
560
            }
561
562
            var iconClose = new Image();
563
            iconClose.src = '../assets/images/icon/close12.gif';
564
            var iconOpen = new Image();
565
            iconOpen.src = '../assets/images/icon/open12.gif';
566
567
            function toggleIcon(iconName) {
568
                if (document.images[iconName].src == window.iconOpen.src) {
569
                    document.images[iconName].src = window.iconClose.src;
570
                }
571
                elseif(document.images[iconName].src == window.iconClose.src)
572
                {
573
                    document.images[iconName].src = window.iconOpen.src;
574
                }
575
576
                return;
577
            }
578
579
            //-->
580
        </script>
581
        <?php
582
        echo "<h3 style=\"color: #2F5376; margin: 6px 0 0 0; \"><a href='#' onClick=\"toggle('" . $tablename . "'); toggleIcon('" . $iconname . "');\">";
583
    }
584
}
585