MyTextSanitizer   F
last analyzed

Complexity

Total Complexity 102

Size/Duplication

Total Lines 1000
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 296
c 2
b 0
f 0
dl 0
loc 1000
rs 2
wmc 102

49 Methods

Rating   Name   Duplication   Size   Complexity  
A codeConvCallback() 0 3 1
A executeExtensions() 0 10 3
A censorString() 0 8 2
A codePreConv() 0 17 2
A codeConv() 0 9 2
A previewTarea() 0 6 1
F displayTarea() 0 42 12
A nl2Br() 0 3 1
A htmlSpecialChars() 0 13 5
A xoopsCodeDecode() 0 54 2
A makeTboxData4Preview() 0 7 1
A oopsAddSlashes() 0 5 1
A makeTboxData4Edit() 0 5 1
A oopsNl2Br() 0 5 1
A makeTboxData4Show() 0 6 1
A loadExtension() 0 16 4
A smiley() 0 8 2
A codeSanitizer() 0 7 1
A makeTareaData4Show() 0 6 1
A makeTareaData4PreviewInForm() 0 7 1
A quoteConv() 0 14 2
A makeClickableCallback03() 0 3 1
A oopsStripSlashesRT() 0 8 2
A makeClickableCallback01() 0 3 1
B getSmileys() 0 24 7
A makeClickableCallback04() 0 3 1
A makeClickable() 0 40 1
A sanitizeForDisplay() 0 20 4
A executeExtension() 0 7 1
A makeTareaData4Preview() 0 6 1
A getInstance() 0 8 2
A makeTareaData4InsideQuotes() 0 5 1
A undoHtmlSpecialChars() 0 3 1
A truncate() 0 10 4
A makeTboxData4PreviewInForm() 0 6 1
A makeTareaData4Save() 0 5 1
A makeClickableCallback02() 0 3 1
A oopsStripSlashesGPC() 0 5 1
A addSlashes() 0 7 2
A makeTareaData4Edit() 0 5 1
A oopsHtmlSpecialChars() 0 5 1
A mergeConfig() 0 13 5
A makeTboxData4Save() 0 6 1
A sanitizeForPreview() 0 21 4
A filterXss() 0 15 1
A loadConfig() 0 17 4
A __construct() 0 6 1
A textFilter() 0 8 2
A stripSlashesGPC() 0 7 2

How to fix   Complexity   

Complex Class

Complex classes like MyTextSanitizer often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use MyTextSanitizer, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * XOOPS TextSanitizer extension
4
 *
5
 * You may not change or alter any portion of this comment or credits
6
 * of supporting developers from this source code or any supporting source code
7
 * which is considered copyrighted (c) material of the original comment or credit authors.
8
 * This program is distributed in the hope that it will be useful,
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11
 *
12
 * @copyright       (c) 2000-2021 XOOPS Project (https://xoops.org)
13
 * @license             GNU GPL 2 (https://www.gnu.org/licenses/gpl-2.0.html)
14
 * @package             class
15
 * @since               2.0.0
16
 * @author              Kazumi Ono (http://www.myweb.ne.jp/, http://jp.xoops.org/)
17
 * @author              Goghs Cheng (http://www.eqiao.com, http://www.devbeez.com/)
18
 * @author              Taiwen Jiang <[email protected]>
19
 */
20
21
/**
22
 * Abstract class for extensions
23
 *
24
 * @author              Taiwen Jiang <[email protected]>
25
 * @copyright       (c) 2000-2021 XOOPS Project (https://xoops.org)
26
 */
27
class MyTextSanitizerExtension
28
{
29
    public $instance;
30
    public $ts;
31
    public $config;
32
    public $image_path;
33
34
    /**
35
     * Constructor
36
     *
37
     * @param MyTextSanitizer $ts
38
     */
39
    public function __construct(MyTextSanitizer $ts)
40
    {
41
        $this->ts         = $ts;
42
        $this->image_path = XOOPS_URL . '/images/form';
43
    }
44
45
    /**
46
     * loadConfig
47
     *
48
     * @param  string $path
49
     * @return string|array
50
     */
51
    public static function loadConfig($path = null)
52
    {
53
        $ts   = MyTextSanitizer::getInstance();
54
        $extensionName = (null === $path) ? '' : basename($path);
55
        $pathDist = $ts->path_basic;
56
        $pathConfig = $ts->path_config;
57
58
        if ('' !== $extensionName) {
59
            $configFileName = $pathConfig . '/config.' . $extensionName . '.php';
60
            $distFileName = $pathDist . '/' . $extensionName . '/config.' . $extensionName . '.dist.php';
61
        } else {
62
            $configFileName = $pathConfig . '/config.php';
63
            $distFileName = $pathDist . '/config.dist.php';
64
        }
65
        if (!file_exists($configFileName)) {
66
            if (false === copy($distFileName, $configFileName)) {
67
                trigger_error('Could not create textsanitizer config file ' . basename($configFileName));
68
                return $a = array();
0 ignored issues
show
Unused Code introduced by geekwright
The assignment to $a is dead and can be removed.
Loading history...
69
            }
70
        }
71
        $configs = include $configFileName;
72
        return $configs;
73
    }
74
75
    /**
76
     * Merge Config
77
     *
78
     * @param  array $config_default
79
     * @param  array $config_custom
80
     * @return array
81
     */
82
    public static function mergeConfig($config_default, $config_custom)
83
    {
84
        if (is_array($config_custom)) {
0 ignored issues
show
introduced by beckmi
The condition is_array($config_custom) is always true.
Loading history...
85
            foreach ($config_custom as $key => $val) {
86
                if (is_array($config_default[$key])) {
87
                    $config_default[$key] = self::mergeConfig($config_default[$key], $config_custom[$key]);
88
                } else {
89
                    $config_default[$key] = $val;
90
                }
91
            }
92
        }
93
94
        return $config_default;
95
    }
96
97
    /**
98
     * encode
99
     *
100
     * @param string $textarea_id id attribute of text area
101
     *
102
     * @return array
103
     */
104
    public function encode($textarea_id)
0 ignored issues
show
Unused Code introduced by geekwright
The parameter $textarea_id 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

104
    public function encode(/** @scrutinizer ignore-unused */ $textarea_id)

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...
105
    {
106
        return array();
107
    }
108
109
    /**
110
     * decode
111
     *
112
     * @param string $url
113
     * @param string|integer $width
114
     * @param string|integer $height
115
     *
116
     * @return Null
117
     */
118
    public static function decode($url, $width, $height)
0 ignored issues
show
Unused Code introduced by geekwright
The parameter $height 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

118
    public static function decode($url, $width, /** @scrutinizer ignore-unused */ $height)

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...
Unused Code introduced by geekwright
The parameter $width 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

118
    public static function decode($url, /** @scrutinizer ignore-unused */ $width, $height)

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...
119
    {
120
        return null;
121
    }
122
}
123
124
/**
125
 * Class to "clean up" text for various uses
126
 *
127
 * <strong>Singleton</strong>
128
 *
129
 * @package       kernel
130
 * @subpackage    core
131
 * @author        Kazumi Ono <[email protected]>
132
 * @author        Taiwen Jiang <[email protected]>
133
 * @author        Goghs Cheng
134
 * @copyright (c) 2000-2021 XOOPS Project (https://xoops.org)
135
 */
136
class MyTextSanitizer
137
{
138
    /**
139
     *
140
     * @var array
141
     */
142
    public $smileys = array();
143
144
    /**
145
     */
146
    public $censorConf;
147
148
    /**
149
     *
150
     * @var string holding reference to text
151
     */
152
    public $text         = '';
153
    public $patterns     = array();
154
    public $replacements = array();
155
156
    //mb------------------------------
157
    public $callbackPatterns = array();
158
    public $callbacks        = array();
159
    //mb------------------------------
160
161
    public $path_basic;
162
    public $path_config;
163
    public $path_plugin;
164
165
    public $config;
166
167
    /**
168
     * Constructor of this class
169
     *
170
     * Gets allowed html tags from admin config settings
171
     * <br> should not be allowed since nl2br will be used
172
     * when storing data.
173
     *
174
     * @access private
175
     */
176
177
    public function __construct()
178
    {
179
        $this->path_basic  = XOOPS_ROOT_PATH . '/class/textsanitizer';
180
        $this->path_config = XOOPS_VAR_PATH . '/configs/textsanitizer';
181
        $this->path_plugin = XOOPS_ROOT_PATH . '/Frameworks/textsanitizer';
182
        $this->config      = $this->loadConfig();
183
    }
184
185
    /**
186
     * Enter description here...
187
     *
188
     * @param  string $name
189
     * @return array|string
190
     */
191
    public function loadConfig($name = null)
192
    {
193
        // NB: sending a null name results in an infinite loop
194
        if (!empty($name)) {
195
            return MyTextSanitizerExtension::loadConfig($name);
196
        }
197
198
        $configFileName = $this->path_config . '/config.php';
199
        $distFileName = $this->path_basic . '/config.dist.php';
200
201
        if (!file_exists($configFileName)) {
202
            if (false===copy($distFileName, $configFileName)) {
203
                trigger_error('Could not create textsanitizer config file ' . basename($configFileName));
204
                return array();
205
            }
206
        }
207
        return include $configFileName;
208
    }
209
210
    /**
211
     * Enter description here...
212
     *
213
     * @param  array $config_default
214
     * @param  array $config_custom
215
     * @return mixed
216
     */
217
    public function mergeConfig($config_default, $config_custom)
218
    {
219
        if (is_array($config_custom)) {
0 ignored issues
show
introduced by beckmi
The condition is_array($config_custom) is always true.
Loading history...
220
            foreach ($config_custom as $key => $val) {
221
                if (isset($config_default[$key]) && is_array($config_default[$key])) {
222
                    $config_default[$key] = $this->mergeConfig($config_default[$key], $config_custom[$key]);
223
                } else {
224
                    $config_default[$key] = $val;
225
                }
226
            }
227
        }
228
229
        return $config_default;
230
    }
231
232
    /**
233
     * Access the only instance of this class
234
     *
235
     * @return MyTextSanitizer
236
     */
237
    public static function getInstance()
238
    {
239
        static $instance;
240
        if (!isset($instance)) {
241
            $instance = new MyTextSanitizer();
242
        }
243
244
        return $instance;
245
    }
246
247
    /**
248
     * Get the smileys
249
     *
250
     * @param bool $isAll TRUE for all smileys, FALSE for smileys with display = 1
251
     *
252
     * @return array
253
     */
254
    public function getSmileys($isAll = true)
255
    {
256
        if (count($this->smileys) == 0) {
257
            /* @var XoopsMySQLDatabase $xoopsDB */
258
            $xoopsDB = XoopsDatabaseFactory::getDatabaseConnection();
259
            if ($getsmiles = $xoopsDB->query('SELECT * FROM ' . $xoopsDB->prefix('smiles'))) {
260
                while (false !== ($smiles = $xoopsDB->fetchArray($getsmiles))) {
0 ignored issues
show
Bug introduced by mambax7
It seems like $getsmiles can also be of type true; however, parameter $result of XoopsMySQLDatabase::fetchArray() does only seem to accept mysqli_result, 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

260
                while (false !== ($smiles = $xoopsDB->fetchArray(/** @scrutinizer ignore-type */ $getsmiles))) {
Loading history...
261
                    $this->smileys[] = $smiles;
262
                }
263
            }
264
        }
265
        if ($isAll) {
266
            return $this->smileys;
267
        }
268
269
        $smileys = array();
270
        foreach ($this->smileys as $smile) {
271
            if (empty($smile['display'])) {
272
                continue;
273
            }
274
            $smileys[] = $smile;
275
        }
276
277
        return $smileys;
278
    }
279
280
    /**
281
     * Replace emoticons in the message with smiley images
282
     *
283
     * @param  string $message
284
     * @return string
285
     */
286
    public function smiley($message)
287
    {
288
        $smileys = $this->getSmileys();
289
        foreach ($smileys as $smile) {
290
            $message = str_replace($smile['code'], '<img class="imgsmile" src="' . XOOPS_UPLOAD_URL . '/' . htmlspecialchars($smile['smile_url']) . '" alt="" />', $message);
291
        }
292
293
        return $message;
294
    }
295
296
    /**
297
     * @param $match
298
     *
299
     * @return string
300
     */
301
    public function makeClickableCallback01($match)
302
    {
303
        return $match[1] . "<a href=\"$match[2]://$match[3]\" title=\"$match[2]://$match[3]\" rel=\"noopener external\">$match[2]://" . $this->truncate($match[3]) . '</a>';
304
    }
305
306
    /**
307
     * @param $match
308
     *
309
     * @return string
310
     */
311
    public function makeClickableCallback02($match)
312
    {
313
        return $match[1] . "<a href=\"http://www.$match[2]$match[6]\" title=\"www.$match[2]$match[6]\" rel=\"noopener external\">" . $this->truncate('www.' . $match[2] . $match[6]) . '</a>';
314
    }
315
316
    /**
317
     * @param $match
318
     *
319
     * @return string
320
     */
321
    public function makeClickableCallback03($match)
322
    {
323
        return $match[1] . "<a href=\"ftp://ftp.$match[2].$match[3]\" title=\"ftp.$match[2].$match[3]\" rel=\"external\">" . $this->truncate('ftp.' . $match[2] . $match[3]) . '</a>';
324
    }
325
326
    /**
327
     * @param $match
328
     *
329
     * @return string
330
     */
331
    public function makeClickableCallback04($match)
332
    {
333
        return $match[1] . "<a href=\"mailto:$match[2]@$match[3]\" title=\"$match[2]@$match[3]\">" . $this->truncate($match[2] . '@' . $match[3]) . '</a>';
334
    }
335
336
    /**
337
     * Make links in the text clickable
338
     *
339
     * @param  string $text
340
     * @return string
341
     */
342
    public function makeClickable(&$text)
343
    {
344
        $text1 = $text;
345
346
        $valid_chars = "a-z0-9\/\-_+=.~!%@?#&;:$\|";
347
        $end_chars   = "a-z0-9\/\-_+=~!%@?#&;:$\|";
348
349
        //        $patterns   = array();
350
        //        $replacements   = array();
351
        //
352
        //        $patterns[]     = "/(^|[^]_a-z0-9-=\"'\/])([a-z]+?):\/\/([{$valid_chars}]+[{$end_chars}])/ei";
353
        //        $replacements[] = "'\\1<a href=\"\\2://\\3\" title=\"\\2://\\3\" rel=\"external\">\\2://'.MyTextSanitizer::truncate( '\\3' ).'</a>'";
354
        //
355
        //
356
        //        $patterns[]     = "/(^|[^]_a-z0-9-=\"'\/:\.])www\.((([a-zA-Z0-9\-]*\.){1,}){1}([a-zA-Z]{2,6}){1})((\/([a-zA-Z0-9\-\._\?\,\'\/\\+&%\$#\=~])*)*)/ei";
357
        //        $replacements[] = "'\\1<a href=\"http://www.\\2\\6\" title=\"www.\\2\\6\" rel=\"external\">'.MyTextSanitizer::truncate( 'www.\\2\\6' ).'</a>'";
358
        //
359
        //        $patterns[]     = "/(^|[^]_a-z0-9-=\"'\/])ftp\.([a-z0-9\-]+)\.([{$valid_chars}]+[{$end_chars}])/ei";
360
        //        $replacements[] = "'\\1<a href=\"ftp://ftp.\\2.\\3\" title=\"ftp.\\2.\\3\" rel=\"external\">'.MyTextSanitizer::truncate( 'ftp.\\2.\\3' ).'</a>'";
361
        //
362
        //        $patterns[]     = "/(^|[^]_a-z0-9-=\"'\/:\.])([-_a-z0-9\'+*$^&%=~!?{}]++(?:\.[-_a-z0-9\'+*$^&%=~!?{}]+)*+)@((?:(?![-.])[-a-z0-9.]+(?<![-.])\.[a-z]{2,6}|\d{1,3}(?:\.\d{1,3}){3})(?::\d++)?)/ei";
363
        //        $replacements[] = "'\\1<a href=\"mailto:\\[email protected]\\3\" title=\"\\[email protected]\\3\">'.MyTextSanitizer::truncate( '\\[email protected]\\3' ).'</a>'";
364
        //
365
        //        $text = preg_replace($patterns, $replacements, $text);
366
        //
367
        //----------------------------------------------------------------------------------
368
369
        $pattern = "/(^|[^]_a-z0-9-=\"'\/])([a-z]+?):\/\/([{$valid_chars}]+[{$end_chars}])/i";
370
        $text1   = preg_replace_callback($pattern, 'self::makeClickableCallback01', $text1);
371
372
        $pattern = "/(^|[^]_a-z0-9-=\"'\/:\.])www\.((([a-zA-Z0-9\-]*\.){1,}){1}([a-zA-Z]{2,6}){1})((\/([a-zA-Z0-9\-\._\?\,\'\/\\+&%\$#\=~])*)*)/i";
373
        $text1   = preg_replace_callback($pattern, 'self::makeClickableCallback02', $text1);
374
375
        $pattern = "/(^|[^]_a-z0-9-=\"'\/])ftp\.([a-z0-9\-]+)\.([{$valid_chars}]+[{$end_chars}])/i";
376
        $text1   = preg_replace_callback($pattern, 'self::makeClickableCallback03', $text1);
377
378
        $pattern = "/(^|[^]_a-z0-9-=\"'\/:\.])([-_a-z0-9\'+*$^&%=~!?{}]++(?:\.[-_a-z0-9\'+*$^&%=~!?{}]+)*+)@((?:(?![-.])[-a-z0-9.]+(?<![-.])\.[a-z]{2,6}|\d{1,3}(?:\.\d{1,3}){3})(?::\d++)?)/i";
379
        $text1   = preg_replace_callback($pattern, 'self::makeClickableCallback04', $text1);
380
381
        return $text1;
382
    }
383
384
    /**
385
     * MyTextSanitizer::truncate()
386
     *
387
     * @param  mixed $text
388
     * @return mixed|string
389
     */
390
    public function truncate($text)
391
    {
392
        $instance = MyTextSanitizer::getInstance();
393
        if (empty($text) || empty($instance->config['truncate_length']) || strlen($text) < $instance->config['truncate_length']) {
394
            return $text;
395
        }
396
        $len = floor($instance->config['truncate_length'] / 2);
397
        $ret = substr($text, 0, $len) . ' ... ' . substr($text, 5 - $len);
0 ignored issues
show
Bug introduced by beckmi
$len of type double is incompatible with the type integer|null expected by parameter $length of substr(). ( Ignorable by Annotation )

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

397
        $ret = substr($text, 0, /** @scrutinizer ignore-type */ $len) . ' ... ' . substr($text, 5 - $len);
Loading history...
Bug introduced by beckmi
5 - $len of type double is incompatible with the type integer expected by parameter $offset of substr(). ( Ignorable by Annotation )

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

397
        $ret = substr($text, 0, $len) . ' ... ' . substr($text, /** @scrutinizer ignore-type */ 5 - $len);
Loading history...
398
399
        return $ret;
400
    }
401
402
    /**
403
     * Replace XoopsCodes with their equivalent HTML formatting
404
     *
405
     * @param  string   $text
406
     * @param  bool|int $allowimage Allow images in the text?
407
     *                              On FALSE, uses links to images.
408
     * @return string
409
     */
410
    public function &xoopsCodeDecode(&$text, $allowimage = 1)
411
    {
412
        $patterns       = array();
413
        $replacements   = array();
414
        $patterns[]     = "/\[siteurl=(['\"]?)([^\"'<>]*)\\1](.*)\[\/siteurl\]/sU";
415
        $replacements[] = '<a href="' . XOOPS_URL . '/\\2" title="">\\3</a>';
416
        $patterns[]     = "/\[url=(['\"]?)(http[s]?:\/\/[^\"'<>]*)\\1](.*)\[\/url\]/sU";
417
        $replacements[] = '<a href="\\2" rel="noopener external" title="">\\3</a>';
418
        $patterns[]     = "/\[url=(['\"]?)(ftp?:\/\/[^\"'<>]*)\\1](.*)\[\/url\]/sU";
419
        $replacements[] = '<a href="\\2" rel="external" title="">\\3</a>';
420
        $patterns[]     = "/\[url=(['\"]?)([^'\"<>]*)\\1](.*)\[\/url\]/sU";
421
        $replacements[] = '<a href="http://\\2" rel="noopener external" title="">\\3</a>';
422
        $patterns[]     = "/\[color=(['\"]?)([a-zA-Z0-9]*)\\1](.*)\[\/color\]/sU";
423
        $replacements[] = '<span style="color: #\\2;">\\3</span>';
424
        $patterns[]     = "/\[size=(['\"]?)([a-z0-9-]*)\\1](.*)\[\/size\]/sU";
425
        $replacements[] = '<span style="font-size: \\2;">\\3</span>';
426
        $patterns[]     = "/\[font=(['\"]?)([^;<>\*\(\)\"']*)\\1](.*)\[\/font\]/sU";
427
        $replacements[] = '<span style="font-family: \\2;">\\3</span>';
428
        $patterns[]     = "/\[email]([^;<>\*\(\)\"']*)\[\/email\]/sU";
429
        $replacements[] = '<a href="mailto:\\1" title="">\\1</a>';
430
431
        $patterns[]     = "/\[b](.*)\[\/b\]/sU";
432
        $replacements[] = '<strong>\\1</strong>';
433
        $patterns[]     = "/\[i](.*)\[\/i\]/sU";
434
        $replacements[] = '<em>\\1</em>';
435
        $patterns[]     = "/\[u](.*)\[\/u\]/sU";
436
        $replacements[] = '<span style="text-decoration: underline;">\\1</span>';
437
        $patterns[]     = "/\[d](.*)\[\/d\]/sU";
438
        $replacements[] = '<del>\\1</del>';
439
        $patterns[]     = "/\[center](.*)\[\/center\]/sU";
440
        $replacements[] = '<div style="text-align: center;">\\1</div>';
441
        $patterns[]     = "/\[left](.*)\[\/left\]/sU";
442
        $replacements[] = '<div style="text-align: left;">\\1</div>';
443
        $patterns[]     = "/\[right](.*)\[\/right\]/sU";
444
        $replacements[] = '<div style="text-align: right;">\\1</div>';
445
446
        $this->text         = $text;
447
        $this->patterns     = $patterns;
448
        $this->replacements = $replacements;
449
450
        $this->config['allowimage'] = $allowimage;
451
        $this->executeExtensions();
452
453
        $text = preg_replace($this->patterns, $this->replacements, $this->text);
454
        //-------------------------------------------------------------------------------
455
        $count = count($this->callbackPatterns);
456
457
        for ($i = 0; $i < $count; ++$i) {
458
            $text = preg_replace_callback($this->callbackPatterns[$i], $this->callbacks[$i], $text);
459
        }
460
        //------------------------------------------------------------------------------
461
        $text = $this->quoteConv($text);
462
463
        return $text;
464
    }
465
466
    /**
467
     * Convert quote tags
468
     *
469
     * @param  string $text
470
     * @return string
471
     */
472
    public function quoteConv($text)
473
    {
474
        //look for both open and closing tags in the correct order
475
        $pattern     = "/\[quote](.*)\[\/quote\]/sU";
476
        $replacement = _QUOTEC . '<div class="xoopsQuote"><blockquote>\\1</blockquote></div>';
477
478
        $text = preg_replace($pattern, $replacement, $text, -1, $count);
479
        //no more matches, return now
480
        if (!$count) {
481
            return $text;
482
        }
483
484
        //new matches could have been created, keep doing it until we have no matches
485
        return $this->quoteConv($text);
486
    }
487
488
    /**
489
     * A quick solution for filtering XSS scripts
490
     *
491
     * @TODO : To be improved
492
     * @param $text
493
     * @return mixed
494
     */
495
    public function filterXss($text)
496
    {
497
        $patterns       = array();
498
        $replacements   = array();
499
        $text           = str_replace("\x00", '', $text);
500
        $c              = "[\x01-\x1f]*";
501
        $patterns[]     = "/\bj{$c}a{$c}v{$c}a{$c}s{$c}c{$c}r{$c}i{$c}p{$c}t{$c}[\s]*:/si";
502
        $replacements[] = 'javascript;';
503
        $patterns[]     = "/\ba{$c}b{$c}o{$c}u{$c}t{$c}[\s]*:/si";
504
        $replacements[] = 'about;';
505
        $patterns[]     = "/\bx{$c}s{$c}s{$c}[\s]*:/si";
506
        $replacements[] = 'xss;';
507
        $text           = preg_replace($patterns, $replacements, $text);
508
509
        return $text;
510
    }
511
512
    /**
513
     * Convert linebreaks to <br> tags
514
     *
515
     * @param  string $text
516
     * @return string
517
     */
518
    public function nl2Br($text)
519
    {
520
        return preg_replace('/(\015\012)|(\015)|(\012)/', '<br>', $text);
521
    }
522
523
    /**
524
     * Add slashes to the text if magic_quotes_gpc is turned off.
525
     *
526
     * @param  string $text
527
     * @return string
528
     */
529
    public function addSlashes($text)
530
    {
531
        if ([email protected]_magic_quotes_gpc()) {
532
            $text = addslashes($text);
533
        }
534
535
        return $text;
536
    }
537
538
    /**
539
     * Convert special characters to HTML entities
540
     *
541
     * @param  string $text    string being converted
542
     * @param  int|null    $quote_style
543
     * @param  string $charset character set used in conversion
544
     * @param  bool   $double_encode
545
     * @return string
546
     */
547
    public function htmlSpecialChars($text, $quote_style = NULL, $charset = null, $double_encode = true)
548
    {
549
        if ($quote_style === NULL) {
550
            $quote_style = ENT_QUOTES;
551
        }
552
553
        if (version_compare(phpversion(), '5.2.3', '>=')) {
554
            $text = htmlspecialchars($text, $quote_style, $charset ?: (defined('_CHARSET') ? _CHARSET : 'UTF-8'), $double_encode);
555
        } else {
556
            $text = htmlspecialchars($text, $quote_style);
557
        }
558
559
        return preg_replace(array('/&amp;/i', '/&nbsp;/i'), array('&', '&amp;nbsp;'), $text);
560
    }
561
562
    /**
563
     * Reverses {@link htmlSpecialChars()}
564
     *
565
     * @param  string $text
566
     * @return string
567
     */
568
    public function undoHtmlSpecialChars($text)
569
    {
570
        return preg_replace(array('/&gt;/i', '/&lt;/i', '/&quot;/i', '/&#039;/i', '/&amp;nbsp;/i'), array('>', '<', '"', '\'', '&nbsp;'), $text);
571
    }
572
573
    /**
574
     * Filters textarea form data in DB for display
575
     *
576
     * @param  string   $text
577
     * @param  bool|int $html   allow html?
578
     * @param  bool|int $smiley allow smileys?
579
     * @param  bool|int $xcode  allow xoopscode?
580
     * @param  bool|int $image  allow inline images?
581
     * @param  bool|int $br     convert linebreaks?
582
     * @return string
583
     */
584
    public function &displayTarea($text, $html = 0, $smiley = 1, $xcode = 1, $image = 1, $br = 1)
585
    {
586
        $charset = (defined('_CHARSET') ? _CHARSET : 'UTF-8');
587
        if (function_exists('mb_convert_encoding')) {
588
            $text = mb_convert_encoding($text, $charset, mb_detect_encoding($text, mb_detect_order(), true));
0 ignored issues
show
Bug introduced by geekwright
It seems like mb_detect_order() can also be of type true; however, parameter $encodings of mb_detect_encoding() does only seem to accept array|null|string, 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

588
            $text = mb_convert_encoding($text, $charset, mb_detect_encoding($text, /** @scrutinizer ignore-type */ mb_detect_order(), true));
Loading history...
589
        }
590
        if ($html && $br) {
591
            $testText = strip_tags($text);
0 ignored issues
show
Bug introduced by geekwright
It seems like $text can also be of type array; however, parameter $string of strip_tags() does only seem to accept string, 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

591
            $testText = strip_tags(/** @scrutinizer ignore-type */ $text);
Loading history...
592
            if (mb_strlen($text) != mb_strlen($testText)) {
0 ignored issues
show
Bug introduced by geekwright
It seems like $text can also be of type array; however, parameter $string of mb_strlen() does only seem to accept string, 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

592
            if (mb_strlen(/** @scrutinizer ignore-type */ $text) != mb_strlen($testText)) {
Loading history...
593
                $br = 0;
594
            }
595
            unset($testText);
596
        }
597
        if ($html != 1) {
598
            // html not allowed
599
            $text = $this->htmlSpecialChars($text, ENT_COMPAT, $charset);
0 ignored issues
show
Bug introduced by mambax7
It seems like $text can also be of type array; however, parameter $text of MyTextSanitizer::htmlSpecialChars() does only seem to accept string, 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

599
            $text = $this->htmlSpecialChars(/** @scrutinizer ignore-type */ $text, ENT_COMPAT, $charset);
Loading history...
600
        }
601
        $text = $this->codePreConv($text, $xcode); // Ryuji_edit(2003-11-18)
602
        if ($smiley != 0) {
603
            // process smiley
604
            $text = $this->smiley($text);
0 ignored issues
show
Bug introduced by beckmi
It seems like $text can also be of type array; however, parameter $message of MyTextSanitizer::smiley() does only seem to accept string, 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

604
            $text = $this->smiley(/** @scrutinizer ignore-type */ $text);
Loading history...
605
        }
606
        if ($xcode != 0) {
607
            // decode xcode
608
            if ($image != 0) {
609
                // image allowed
610
                $text =& $this->xoopsCodeDecode($text);
0 ignored issues
show
Bug introduced by mambax7
It seems like $text can also be of type array; however, parameter $text of MyTextSanitizer::xoopsCodeDecode() does only seem to accept string, 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

610
                $text =& $this->xoopsCodeDecode(/** @scrutinizer ignore-type */ $text);
Loading history...
611
            } else {
612
                // image not allowed
613
                $text =& $this->xoopsCodeDecode($text, 0);
614
            }
615
        }
616
        if ($br != 0) {
617
            $text = $this->nl2Br($text);
0 ignored issues
show
Bug introduced by beckmi
It seems like $text can also be of type array; however, parameter $text of MyTextSanitizer::nl2Br() does only seem to accept string, 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

617
            $text = $this->nl2Br(/** @scrutinizer ignore-type */ $text);
Loading history...
618
        }
619
        $text = $this->codeConv($text, $xcode);
620
        $text = $this->makeClickable($text);
0 ignored issues
show
Bug introduced by beckmi
It seems like $text can also be of type array; however, parameter $text of MyTextSanitizer::makeClickable() does only seem to accept string, 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

620
        $text = $this->makeClickable(/** @scrutinizer ignore-type */ $text);
Loading history...
621
        if (!empty($this->config['filterxss_on_display'])) {
622
            $text = $this->filterXss($text);
623
        }
624
625
        return $text;
626
    }
627
628
    /**
629
     * Filters textarea form data submitted for preview
630
     *
631
     * @param  string   $text
632
     * @param  bool|int $html   allow html?
633
     * @param  bool|int $smiley allow smileys?
634
     * @param  bool|int $xcode  allow xoopscode?
635
     * @param  bool|int $image  allow inline images?
636
     * @param  bool|int $br     convert linebreaks?
637
     * @return string
638
     */
639
    public function &previewTarea($text, $html = 0, $smiley = 1, $xcode = 1, $image = 1, $br = 1)
640
    {
641
        $text = $this->stripSlashesGPC($text);
0 ignored issues
show
Deprecated Code introduced by beckmi
The function MyTextSanitizer::stripSlashesGPC() has been deprecated: as of XOOPS 2.5.11 and will be removed in next XOOPS version ( Ignorable by Annotation )

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

641
        $text = /** @scrutinizer ignore-deprecated */ $this->stripSlashesGPC($text);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
642
        $text =& $this->displayTarea($text, $html, $smiley, $xcode, $image, $br);
643
644
        return $text;
645
    }
646
647
    /**
648
     * Replaces banned words in a string with their replacements
649
     *
650
     * @param  string $text
651
     * @return string
652
     * @deprecated
653
     */
654
    public function &censorString(&$text)
655
    {
656
        $ret = $this->executeExtension('censor', $text);
657
        if ($ret === false) {
658
            return $text;
659
        }
660
661
        return $ret;
662
    }
663
664
    /**
665
     * MyTextSanitizer::codePreConv()
666
     *
667
     * @param  mixed $text
668
     * @param  mixed $xcode
669
     * @return mixed
670
     */
671
    public function codePreConv($text, $xcode = 1)
672
    {
673
        if ($xcode != 0) {
674
            //            $patterns = "/\[code([^\]]*?)\](.*)\[\/code\]/esU";
675
            //            $replacements = "'[code\\1]'.base64_encode('\\2').'[/code]'";
676
677
            $patterns = "/\[code([^\]]*?)\](.*)\[\/code\]/sU";
678
            $text = preg_replace_callback(
679
                $patterns,
680
                function ($matches) {
681
                    return '[code'. $matches[1] . ']' . base64_encode($matches[2]) . '[/code]';
682
                },
683
                $text
684
            );
685
        }
686
687
        return $text;
688
    }
689
690
    /**
691
     * @param $match
692
     *
693
     * @return string
694
     */
695
    public function codeConvCallback($match)
696
    {
697
        return '<div class="xoopsCode">' . $this->executeExtension('syntaxhighlight', str_replace('\\\"', '\"', base64_decode($match[2])), $match[1]) . '</div>';
698
    }
699
700
    /**
701
     * MyTextSanitizer::codeConv()
702
     *
703
     * @param  mixed $text
704
     * @param  mixed $xcode
705
     * @return mixed
706
     */
707
    public function codeConv($text, $xcode = 1)
708
    {
709
        if (empty($xcode)) {
710
            return $text;
711
        }
712
        $patterns = "/\[code([^\]]*?)\](.*)\[\/code\]/sU";
713
        $text1    = preg_replace_callback($patterns, array($this, 'codeConvCallback'), $text);
714
715
        return $text1;
716
    }
717
718
    /**
719
     * MyTextSanitizer::executeExtensions()
720
     *
721
     * @return bool
722
     */
723
    public function executeExtensions()
724
    {
725
        $extensions = array_filter($this->config['extensions']);
726
        if (empty($extensions)) {
727
            return true;
728
        }
729
        foreach (array_keys($extensions) as $extension) {
730
            $this->executeExtension($extension);
731
        }
732
        return null;
733
    }
734
735
    /**
736
     * MyTextSanitizer::loadExtension()
737
     *
738
     * @param  mixed $name
739
     * @return MyTextSanitizerExtension|false
740
     */
741
    public function loadExtension($name)
742
    {
743
        if (file_exists($file = $this->path_basic . '/' . $name . '/' . $name . '.php')) {
744
            include_once $file;
745
        } elseif (file_exists($file = $this->path_plugin . '/' . $name . '/' . $name . '.php')) {
746
            include_once $file;
747
        } else {
748
            return false;
749
        }
750
        $class = 'Myts' . ucfirst($name);
751
        if (!class_exists($class)) {
752
            trigger_error("Extension '{$name}' does not exist", E_USER_WARNING);
753
754
            return false;
755
        }
756
        return new $class($this);
757
    }
758
759
    /**
760
     * MyTextSanitizer::executeExtension()
761
     *
762
     * @param  mixed $name
763
     * @return mixed
764
     */
765
    public function executeExtension($name)
766
    {
767
        $extension = $this->loadExtension($name);
768
        $args      = array_slice(func_get_args(), 1);
769
        array_unshift($args, $this);
770
771
        return call_user_func_array(array($extension, 'load'), $args);
772
    }
773
774
    /**
775
     * Filter out possible malicious text
776
     * kses project at SF could be a good solution to check
777
     *
778
     * @param  string $text  text to filter
779
     * @param  bool   $force force filtering
780
     * @return string filtered text
781
     */
782
    public function textFilter($text, $force = false)
783
    {
784
        $ret = $this->executeExtension('textfilter', $text, $force);
785
        if ($ret === false) {
786
            return $text;
787
        }
788
789
        return $ret;
790
    }
791
792
    // #################### Deprecated Methods ######################
793
794
    /**
795
     * if magic_quotes_gpc is on, strip back slashes
796
     *
797
     * @param  string $text
798
     * @return string
799
     * @deprecated as of XOOPS 2.5.11 and will be removed in next XOOPS version
800
     *
801
     * This remains here until we officially drop support for PHP 5.3 in next release
802
     */
803
    public function stripSlashesGPC($text)
804
    {
805
        if (@get_magic_quotes_gpc()) {
806
            $text = stripslashes($text);
807
        }
808
809
        return $text;
810
    }
811
812
    /**
813
     * MyTextSanitizer::codeSanitizer()
814
     *
815
     * @param  mixed $str
816
     * @param  mixed $image
817
     * @return mixed|string
818
     * @deprecated will be removed in next XOOPS version
819
     */
820
    public function codeSanitizer($str, $image = 1)
821
    {
822
        $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated');
823
        $str = $this->htmlSpecialChars(str_replace('\"', '"', base64_decode($str)));
824
        $str =& $this->xoopsCodeDecode($str, $image);
825
826
        return $str;
827
    }
828
829
    /**
830
     * MyTextSanitizer::sanitizeForDisplay()
831
     *
832
     * @param  mixed   $text
833
     * @param  integer $allowhtml
834
     * @param  integer $smiley
835
     * @param  mixed   $bbcode
836
     * @return mixed|string
837
     * @deprecated will be removed in next XOOPS version
838
     */
839
    public function sanitizeForDisplay($text, $allowhtml = 0, $smiley = 1, $bbcode = 1)
840
    {
841
        $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated');
842
        if ($allowhtml == 0) {
843
            $text = $this->htmlSpecialChars($text);
844
        } else {
845
            // $config =& $GLOBALS['xoopsConfig'];
846
            // $allowed = $config['allowed_html'];
847
            // $text = strip_tags($text, $allowed);
848
            $text = $this->makeClickable($text);
849
        }
850
        if ($smiley == 1) {
851
            $text = $this->smiley($text);
852
        }
853
        if ($bbcode == 1) {
854
            $text =& $this->xoopsCodeDecode($text);
855
        }
856
        $text = $this->nl2Br($text);
857
858
        return $text;
859
    }
860
861
    /**
862
     * MyTextSanitizer::sanitizeForPreview()
863
     *
864
     * @param  mixed   $text
865
     * @param  integer $allowhtml
866
     * @param  integer $smiley
867
     * @param  mixed   $bbcode
868
     * @return mixed|string
869
     * @deprecated will be removed in next XOOPS version
870
     */
871
    public function sanitizeForPreview($text, $allowhtml = 0, $smiley = 1, $bbcode = 1)
872
    {
873
        $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated');
874
        $text = $this->oopsStripSlashesGPC($text);
0 ignored issues
show
Deprecated Code introduced by beckmi
The function MyTextSanitizer::oopsStripSlashesGPC() has been deprecated: will be removed in next XOOPS version ( Ignorable by Annotation )

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

874
        $text = /** @scrutinizer ignore-deprecated */ $this->oopsStripSlashesGPC($text);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
875
        if ($allowhtml == 0) {
876
            $text = $this->htmlSpecialChars($text);
877
        } else {
878
            // $config =& $GLOBALS['xoopsConfig'];
879
            // $allowed = $config['allowed_html'];
880
            // $text = strip_tags($text, $allowed);
881
            $text = $this->makeClickable($text);
882
        }
883
        if ($smiley == 1) {
884
            $text = $this->smiley($text);
885
        }
886
        if ($bbcode == 1) {
887
            $text =& $this->xoopsCodeDecode($text);
888
        }
889
        $text = $this->nl2Br($text);
890
891
        return $text;
892
    }
893
894
    /**
895
     * MyTextSanitizer::makeTboxData4Save()
896
     *
897
     * @param  mixed $text
898
     * @return string
899
     * @deprecated will be removed in next XOOPS version
900
     */
901
    public function makeTboxData4Save($text)
902
    {
903
        $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated');
904
905
        // $text = $this->undoHtmlSpecialChars($text);
906
        return $this->addSlashes($text);
907
    }
908
909
    /**
910
     * MyTextSanitizer::makeTboxData4Show()
911
     *
912
     * @param  mixed $text
913
     * @param  mixed $smiley
914
     * @return mixed|string
915
     * @deprecated will be removed in next XOOPS version
916
     */
917
    public function makeTboxData4Show($text, $smiley = 0)
0 ignored issues
show
Unused Code introduced by mambax7
The parameter $smiley 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

917
    public function makeTboxData4Show($text, /** @scrutinizer ignore-unused */ $smiley = 0)

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...
918
    {
919
        $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated');
920
        $text = $this->htmlSpecialChars($text);
921
922
        return $text;
923
    }
924
925
    /**
926
     * MyTextSanitizer::makeTboxData4Edit()
927
     *
928
     * @param  mixed $text
929
     * @return string
930
     * @deprecated will be removed in next XOOPS version
931
     */
932
    public function makeTboxData4Edit($text)
933
    {
934
        $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated');
935
936
        return $this->htmlSpecialChars($text);
937
    }
938
939
    /**
940
     * MyTextSanitizer::makeTboxData4Preview()
941
     *
942
     * @param  mixed $text
943
     * @param  mixed $smiley
944
     * @return mixed|string
945
     * @deprecated will be removed in next XOOPS version
946
     */
947
    public function makeTboxData4Preview($text, $smiley = 0)
0 ignored issues
show
Unused Code introduced by mambax7
The parameter $smiley 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

947
    public function makeTboxData4Preview($text, /** @scrutinizer ignore-unused */ $smiley = 0)

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...
948
    {
949
        $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated');
950
        $text = $this->stripSlashesGPC($text);
0 ignored issues
show
Deprecated Code introduced by beckmi
The function MyTextSanitizer::stripSlashesGPC() has been deprecated: as of XOOPS 2.5.11 and will be removed in next XOOPS version ( Ignorable by Annotation )

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

950
        $text = /** @scrutinizer ignore-deprecated */ $this->stripSlashesGPC($text);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
951
        $text = $this->htmlSpecialChars($text);
952
953
        return $text;
954
    }
955
956
    /**
957
     * MyTextSanitizer::makeTboxData4PreviewInForm()
958
     *
959
     * @param  mixed $text
960
     * @return string
961
     * @deprecated will be removed in next XOOPS version
962
     */
963
    public function makeTboxData4PreviewInForm($text)
964
    {
965
        $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated');
966
        $text = $this->stripSlashesGPC($text);
0 ignored issues
show
Deprecated Code introduced by beckmi