Issues (62)

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/Common/SysUtility.php (1 issue)

1
<?php declare(strict_types=1);
2
3
namespace XoopsModules\Xhttperror\Common;
4
5
/*
6
 Utility Class Definition
7
8
 You may not change or alter any portion of this comment or credits of
9
 supporting developers from this source code or any supporting source code
10
 which is considered copyrighted (c) material of the original comment or credit
11
 authors.
12
13
 This program is distributed in the hope that it will be useful, but
14
 WITHOUT ANY WARRANTY; without even the implied warranty of
15
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
 */
17
18
/**
19
 * @license      https://www.fsf.org/copyleft/gpl.html GNU public license
20
 * @copyright    https://xoops.org 2000-2020 &copy; XOOPS Project
21
 * @author       ZySpec <[email protected]>
22
 * @author       Mamba <[email protected]>
23
 */
24
25
use Xmf\Request;
26
use MyTextSanitizer;
27
use XoopsFormDhtmlTextArea;
28
use XoopsFormTextArea;
29
use XoopsModules\Xhttperror\{
30
    Helper
31
};
32
33
34
/**
35
 * Class SysUtility
36
 */
37
class SysUtility
38
{
39
    use VersionChecks; //checkVerXoops, checkVerPhp Traits
0 ignored issues
show
The trait XoopsModules\Xhttperror\Common\VersionChecks requires some properties which are not provided by XoopsModules\Xhttperror\Common\SysUtility: $tag_name, $prerelease
Loading history...
40
    use ServerStats; // getServerStats Trait
41
    use FilesManagement; // Files Management Trait
42
43
    //--------------- Common module methods -----------------------------
44
45
    /**
46
     * Access the only instance of this class
47
     *
48
     * @return SysUtility
49
     *
50
     */
51
    public static function getInstance()
52
    {
53
        static $instance;
54
        if (null === $instance) {
55
            $instance = new static();
56
        }
57
58
        return $instance;
59
    }
60
61
    /**
62
     * @param $text
63
     * @param $form_sort
64
     * @return string
65
     */
66
    public static function selectSorting($text, $form_sort)
67
    {
68
        global $start, $order, $file_cat, $sort, $xoopsModule;
69
70
        $select_view   = '';
71
        $moduleDirName = basename(dirname(__DIR__));
72
        /** @var Helper $helper */
73
        $helper = Helper::getInstance();
74
75
        //$pathModIcon16 = XOOPS_URL . '/modules/' . $moduleDirName . '/' . $helper->getConfig('modicons16');
76
        $pathModIcon16 = $helper->url($helper->getModule()->getInfo('modicons16'));
77
78
        $select_view = '<form name="form_switch" id="form_switch" action="' . Request::getString('REQUEST_URI', '', 'SERVER') . '" method="post"><span style="font-weight: bold;">' . $text . '</span>';
79
        //$sorts =  $sort ==  'asc' ? 'desc' : 'asc';
80
        if ($form_sort == $sort) {
81
            $sel1 = 'asc' === $order ? 'selasc.png' : 'asc.png';
82
            $sel2 = 'desc' === $order ? 'seldesc.png' : 'desc.png';
83
        } else {
84
            $sel1 = 'asc.png';
85
            $sel2 = 'desc.png';
86
        }
87
        $select_view .= '  <a href="' . Request::getString('SCRIPT_NAME', '', 'SERVER') . '?start=' . $start . '&sort=' . $form_sort . '&order=asc"><img src="' . $pathModIcon16 . '/' . $sel1 . '" title="ASC" alt="ASC"></a>';
88
        $select_view .= '<a href="' . Request::getString('SCRIPT_NAME', '', 'SERVER') . '?start=' . $start . '&sort=' . $form_sort . '&order=desc"><img src="' . $pathModIcon16 . '/' . $sel2 . '" title="DESC" alt="DESC"></a>';
89
        $select_view .= '</form>';
90
91
        return $select_view;
92
    }
93
94
    /***************Blocks***************/
95
    /**
96
     * @param array $cats
97
     * @return string
98
     */
99
    public static function blockAddCatSelect($cats)
100
    {
101
        $cat_sql = '';
102
        if (is_array($cats) && !empty($cats)) {
103
            $cat_sql = '(' . current($cats);
104
            array_shift($cats);
105
            foreach ($cats as $cat) {
106
                $cat_sql .= ',' . $cat;
107
            }
108
            $cat_sql .= ')';
109
        }
110
111
        return $cat_sql;
112
    }
113
114
    /**
115
     * @param $content
116
     */
117
    public static function metaKeywords($content)
118
    {
119
        global $xoopsTpl, $xoTheme;
120
        $myts    = \MyTextSanitizer::getInstance();
121
        $content = $myts->undoHtmlSpecialChars($myts->displayTarea($content));
122
        if (null !== $xoTheme && is_object($xoTheme)) {
123
            $xoTheme->addMeta('meta', 'keywords', strip_tags($content));
124
        } else {    // Compatibility for old Xoops versions
125
            $xoopsTpl->assign('xoops_metaKeywords', strip_tags($content));
126
        }
127
    }
128
129
    /**
130
     * @param $content
131
     */
132
    public static function metaDescription($content)
133
    {
134
        global $xoopsTpl, $xoTheme;
135
        $myts    = \MyTextSanitizer::getInstance();
136
        $content = $myts->undoHtmlSpecialChars($myts->displayTarea($content));
137
        if (null !== $xoTheme && is_object($xoTheme)) {
138
            $xoTheme->addMeta('meta', 'description', strip_tags($content));
139
        } else {    // Compatibility for old Xoops versions
140
            $xoopsTpl->assign('xoops_metaDescription', strip_tags($content));
141
        }
142
    }
143
144
    /**
145
     * @param $tableName
146
     * @param $columnName
147
     *
148
     * @return array
149
     */
150
    public static function enumerate($tableName, $columnName)
151
    {
152
        $table = $GLOBALS['xoopsDB']->prefix($tableName);
153
154
        //    $result = $GLOBALS['xoopsDB']->query("SELECT COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS
155
        //        WHERE TABLE_NAME = '" . $table . "' AND COLUMN_NAME = '" . $columnName . "'")
156
        //    || exit ($GLOBALS['xoopsDB']->error());
157
158
        $sql    = 'SELECT COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = "' . $table . '" AND COLUMN_NAME = "' . $columnName . '"';
159
        $result = $GLOBALS['xoopsDB']->query($sql);
160
        if (!$result) {
161
            exit($GLOBALS['xoopsDB']->error());
162
        }
163
164
        $row      = $GLOBALS['xoopsDB']->fetchBoth($result);
165
        $enumList = explode(',', str_replace("'", '', substr($row['COLUMN_TYPE'], 5, - 6)));
166
        return $enumList;
167
    }
168
169
170
    /**
171
     * @param array|string $tableName
172
     * @param int          $id_field
173
     * @param int          $id
174
     *
175
     * @return mixed
176
     */
177
    public static function cloneRecord($tableName, $id_field, $id)
178
    {
179
        $new_id = false;
180
        $table  = $GLOBALS['xoopsDB']->prefix($tableName);
181
        // copy content of the record you wish to clone
182
        $sql = "SELECT * FROM $table WHERE $id_field='$id' ";
183
        $tempTable = $GLOBALS['xoopsDB']->fetchArray($GLOBALS['xoopsDB']->query($sql), MYSQLI_ASSOC);
184
        if (!$tempTable) {
185
            exit($GLOBALS['xoopsDB']->error());
186
        }
187
        // set the auto-incremented id's value to blank.
188
        unset($tempTable[$id_field]);
189
        // insert cloned copy of the original  record
190
        $sql    = "INSERT INTO $table (" . implode(', ', array_keys($tempTable)) . ") VALUES ('" . implode("', '", array_values($tempTable)) . "')";
191
        $result = $GLOBALS['xoopsDB']->queryF($sql);
192
        if (!$result) {
193
            exit($GLOBALS['xoopsDB']->error());
194
        }
195
        // Return the new id
196
        $new_id = $GLOBALS['xoopsDB']->getInsertId();
197
198
        return $new_id;
199
    }
200
    /**
201
     * truncateHtml can truncate a string up to a number of characters while preserving whole words and HTML tags
202
     * www.gsdesign.ro/blog/cut-html-string-without-breaking-the-tags
203
     * www.cakephp.org
204
     *
205
     * @param string $text         String to truncate.
206
     * @param int    $length       Length of returned string, including ellipsis.
207
     * @param string $ending       Ending to be appended to the trimmed string.
208
     * @param bool   $exact        If false, $text will not be cut mid-word
209
     * @param bool   $considerHtml If true, HTML tags would be handled correctly
210
     *
211
     * @return string Trimmed string.
212
     */
213
    public static function truncateHtml($text, $length = 100, $ending = '...', $exact = false, $considerHtml = true)
214
    {
215
        $openTags = [];
216
        if ($considerHtml) {
217
            // if the plain text is shorter than the maximum length, return the whole text
218
            if (strlen(preg_replace('/<.*?' . '>/', '', $text)) <= $length) {
219
                return $text;
220
            }
221
            // splits all html-tags to scanable lines
222
            preg_match_all('/(<.+?' . '>)?([^<>]*)/s', $text, $lines, PREG_SET_ORDER);
223
            $total_length = strlen($ending);
224
            //$openTags    = [];
225
            $truncate     = '';
226
            foreach ($lines as $line_matchings) {
227
                // if there is any html-tag in this line, handle it and add it (uncounted) to the output
228
                if (!empty($line_matchings[1])) {
229
                    // if it's an "empty element" with or without xhtml-conform closing slash
230
                    if (preg_match('/^<(\s*.+?\/\s*|\s*(img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param)(\s.+?)?)>$/is', $line_matchings[1])) {
231
                        // do nothing
232
                        // if tag is a closing tag
233
                    } elseif (preg_match('/^<\s*\/([^\s]+?)\s*>$/s', $line_matchings[1], $tag_matchings)) {
234
                        // delete tag from $openTags list
235
                        $pos = array_search($tag_matchings[1], $openTags);
236
                        if (false !== $pos) {
237
                            unset($openTags[$pos]);
238
                        }
239
                        // if tag is an opening tag
240
                    } elseif (preg_match('/^<\s*([^\s>!]+).*?' . '>$/s', $line_matchings[1], $tag_matchings)) {
241
                        // add tag to the beginning of $openTags list
242
                        array_unshift($openTags, strtolower($tag_matchings[1]));
243
                    }
244
                    // add html-tag to $truncate'd text
245
                    $truncate .= $line_matchings[1];
246
                }
247
                // calculate the length of the plain text part of the line; handle entities as one character
248
                $content_length = strlen(preg_replace('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|[0-9a-f]{1,6};/i', ' ', $line_matchings[2]));
249
                if ($total_length + $content_length > $length) {
250
                    // the number of characters which are left
251
                    $left            = $length - $total_length;
252
                    $entities_length = 0;
253
                    // search for html entities
254
                    if (preg_match_all('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|[0-9a-f]{1,6};/i', $line_matchings[2], $entities, PREG_OFFSET_CAPTURE)) {
255
                        // calculate the real length of all entities in the legal range
256
                        foreach ($entities[0] as $entity) {
257
                            if ($entity[1] + 1 - $entities_length <= $left) {
258
                                $left--;
259
                                $entities_length += strlen($entity[0]);
260
                            } else {
261
                                // no more characters left
262
                                break;
263
                            }
264
                        }
265
                    }
266
                    $truncate .= substr($line_matchings[2], 0, $left + $entities_length);
267
                    // maximum lenght is reached, so get off the loop
268
                    break;
269
                } else {
270
                $truncate     .= $line_matchings[2];
271
                $total_length += $content_length;
272
                }
273
                // if the maximum length is reached, get off the loop
274
                if ($total_length >= $length) {
275
                    break;
276
                }
277
            }
278
        } elseif (strlen($text) <= $length) {
279
                return $text;
280
            } else {
281
                $truncate = substr($text, 0, $length - strlen($ending));
282
            }
283
284
        // if the words shouldn't be cut in the middle...
285
        if (!$exact) {
286
            // ...search the last occurance of a space...
287
            $spacepos = mb_strrpos($truncate, ' ');
288
            if (isset($spacepos)) {
289
                // ...and cut the text in this position
290
                $truncate = substr($truncate, 0, $spacepos);
291
            }
292
        }
293
        // add the defined ending to the text
294
        $truncate .= $ending;
295
        if ($considerHtml) {
296
            // close all unclosed html-tags
297
            foreach ($openTags as $tag) {
298
                $truncate .= '</' . $tag . '>';
299
            }
300
        }
301
302
        return $truncate;
303
    }
304
305
    /**
306
     * @param \Xmf\Module\Helper $helper
307
     * @param array|null         $options
308
     * @return \XoopsFormDhtmlTextArea|\XoopsFormEditor
309
     */
310
    public static function getEditor($helper = null, $options = null)
311
    {
312
        /** @var Helper $helper */
313
        if (null === $options) {
314
            $options           = [];
315
            $options['name']   = 'Editor';
316
            $options['value']  = 'Editor';
317
            $options['rows']   = 10;
318
            $options['cols']   = '100%';
319
            $options['width']  = '100%';
320
            $options['height'] = '400px';
321
        }
322
323
        if (null === $helper) {
324
            $helper = Helper::getInstance();
325
        }
326
327
        $isAdmin = $helper->isUserAdmin();
328
329
        if (class_exists('XoopsFormEditor')) {
330
            if ($isAdmin) {
331
                $descEditor = new \XoopsFormEditor(ucfirst($options['name']), $helper->getConfig('editorAdmin'), $options, $nohtml = false, $onfailure = 'textarea');
332
            } else {
333
                $descEditor = new \XoopsFormEditor(ucfirst($options['name']), $helper->getConfig('editorUser'), $options, $nohtml = false, $onfailure = 'textarea');
334
            }
335
        } else {
336
            $descEditor = new \XoopsFormDhtmlTextArea(ucfirst($options['name']), $options['name'], $options['value'], '100%', '100%');
337
        }
338
339
        //        $form->addElement($descEditor);
340
341
        return $descEditor;
342
    }
343
344
    /**
345
     * @param string $fieldname
346
     * @param string $table
347
     *
348
     * @return bool
349
     */
350
    public static function fieldExists($fieldname, $table)
351
    {
352
        global $xoopsDB;
353
        $result = $xoopsDB->queryF("SHOW COLUMNS FROM   $table LIKE '$fieldname'");
354
355
        return ($xoopsDB->getRowsNum($result) > 0);
356
    }
357
358
    /**
359
     * Function responsible for checking if a directory exists, we can also write in and create an index.html file
360
     *
361
     * @param string $folder The full path of the directory to check
362
     */
363
    public static function prepareFolder($folder)
364
    {
365
        try {
366
            if (!@mkdir($folder) && !is_dir($folder)) {
367
                throw new \RuntimeException(sprintf('Unable to create the %s directory', $folder));
368
            }
369
            file_put_contents($folder . '/index.html', '<script>history.go(-1);</script>');
370
        } catch (\Exception $e) {
371
            echo 'Caught exception: ', $e->getMessage(), "\n", '<br>';
372
        }
373
    }
374
375
    /**
376
     * @param string $tablename
377
     *
378
     * @return bool
379
     */
380
   public static function tableExists($tablename)
381
    {
382
        $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
383
        trigger_error(__FUNCTION__ . " is deprecated, called from {$trace[0]['file']} line {$trace[0]['line']}");
384
        $GLOBALS['xoopsLogger']->addDeprecated(
385
            basename(dirname(dirname(__DIR__))) .  ' Module: ' . __FUNCTION__ . " function is deprecated, please use Xmf\Database\Tables method(s) instead." . " Called from {$trace[0]['file']}line {$trace[0]['line']}"
386
        );
387
        $result = $GLOBALS['xoopsDB']->queryF("SHOW TABLES LIKE '$tablename'");
388
389
        return ($GLOBALS['xoopsDB']->getRowsNum($result) > 0) ? true : false;
390
    }
391
392
    /**
393
     * Add a field to a mysql table
394
     *
395
     * @param $field
396
     * @param $table
397
     * @return bool|\mysqli_result
398
     */
399
    public static function addField($field, $table)
400
    {
401
        global $xoopsDB;
402
        $result = $xoopsDB->queryF('ALTER TABLE ' . $table . " ADD $field;");
403
404
        return $result;
405
    }
406
}
407