Completed
Pull Request — master (#133)
by Goffy
16:45
created

MyTextSanitizer::codePreConv()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 9
nc 2
nop 2
dl 0
loc 18
rs 9.4285
c 0
b 0
f 0
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-2016 XOOPS Project (www.xoops.org)
13
 * @license             GNU GPL 2 (http://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-2016 XOOPS Project (www.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
0 ignored issues
show
Documentation introduced by
Should the return type not be array?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
50
     */
51
    public static function loadConfig($path = null)
52
    {
53
        $ts   = MyTextSanitizer::getInstance();
54
        $path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
55
        if (false === strpos($path, '/')) {
56
            if (is_dir($ts->path_basic . '/' . $path)) {
57
                $path = $ts->path_basic . '/' . $path;
58
            } else {
59
                if (is_dir($ts->path_plugin . '/' . $path)) {
60
                    $path = $ts->path_plugin . '/' . $path;
61
                }
62
            }
63
        }
64
        $config_default = array();
65
        $config_custom  = array();
66
        if (file_exists($path . '/config.php')) {
67
            $config_default = include $path . '/config.php';
68
        }
69
        if (file_exists($path . '/config.custom.php')) {
70
            $config_custom = include $path . '/config.custom.php';
71
        }
72
73
        return self::mergeConfig($config_default, $config_custom);
74
    }
75
76
    /**
77
     * Merge Config
78
     *
79
     * @param  array $config_default
80
     * @param  array $config_custom
81
     * @return array
82
     */
83
    public static function mergeConfig($config_default, $config_custom)
84
    {
85
        if (is_array($config_custom)) {
86
            foreach ($config_custom as $key => $val) {
87
                if (is_array($config_default[$key])) {
88
                    $config_default[$key] = self::mergeConfig($config_default[$key], $config_custom[$key]);
89
                } else {
90
                    $config_default[$key] = $val;
91
                }
92
            }
93
        }
94
95
        return $config_default;
96
    }
97
98
    /**
99
     * encode
100
     *
101
     * @param string $textarea_id id attribute of text area
102
     *
103
     * @return array
104
     */
105
    public function encode($textarea_id)
106
    {
107
        return array();
108
    }
109
110
    /**
111
     * decode
112
     *
113
     * @return Null
114
     */
115
    public static function decode($url, $width, $height)
116
    {
117
        return null;
118
    }
119
}
120
121
/**
122
 * Class to "clean up" text for various uses
123
 *
124
 * <strong>Singleton</strong>
125
 *
126
 * @package       kernel
127
 * @subpackage    core
128
 * @author        Kazumi Ono <[email protected]>
129
 * @author        Taiwen Jiang <[email protected]>
130
 * @author        Goghs Cheng
131
 * @copyright (c) 2000-2016 XOOPS Project - www.xoops.org
132
 */
133
class MyTextSanitizer
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
134
{
135
    /**
136
     *
137
     * @var array
138
     */
139
    public $smileys = array();
140
141
    /**
142
     */
143
    public $censorConf;
144
145
    /**
146
     *
147
     * @var holding reference to text
148
     */
149
    public $text         = '';
150
    public $patterns     = array();
151
    public $replacements = array();
152
153
    //mb------------------------------
154
    public $callbackPatterns = array();
155
    public $callbacks        = array();
156
    //mb------------------------------
157
158
    public $path_basic;
159
    public $path_plugin;
160
161
    public $config;
162
163
    /**
164
     * Constructor of this class
165
     *
166
     * Gets allowed html tags from admin config settings
167
     * <br> should not be allowed since nl2br will be used
168
     * when storing data.
169
     *
170
     * @access private
171
     */
172
173
    public function __construct()
174
    {
175
        $this->path_basic  = XOOPS_ROOT_PATH . '/class/textsanitizer';
176
        $this->path_plugin = XOOPS_ROOT_PATH . '/Frameworks/textsanitizer';
177
        $this->config      = $this->loadConfig();
178
    }
179
180
    /**
181
     * Enter description here...
182
     *
183
     * @param  string $name
184
     * @return array
185
     */
186
    public function loadConfig($name = null)
187
    {
188
        if (!empty($name)) {
189
            return MyTextSanitizerExtension::loadConfig($name);
190
        }
191
        $config_default = include $this->path_basic . '/config.php';
192
        $config_custom  = array();
193
        if (file_exists($file = $this->path_basic . '/config.custom.php')) {
194
            $config_custom = include $file;
195
        }
196
197
        return $this->mergeConfig($config_default, $config_custom);
198
    }
199
200
    /**
201
     * Enter description here...
202
     *
203
     * @param  array $config_default
204
     * @param  array $config_custom
205
     * @return unknown
0 ignored issues
show
Documentation introduced by
Should the return type not be array?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
206
     */
207
    public function mergeConfig($config_default, $config_custom)
208
    {
209
        if (is_array($config_custom)) {
210
            foreach ($config_custom as $key => $val) {
211
                if (isset($config_default[$key]) && is_array($config_default[$key])) {
212
                    $config_default[$key] = $this->mergeConfig($config_default[$key], $config_custom[$key]);
213
                } else {
214
                    $config_default[$key] = $val;
215
                }
216
            }
217
        }
218
219
        return $config_default;
220
    }
221
222
    /**
223
     * Access the only instance of this class
224
     *
225
     * @return object
226
     * @static
227
     * @staticvar object
228
     */
229
    public static function getInstance()
230
    {
231
        static $instance;
232
        if (!isset($instance)) {
233
            $instance = new MyTextSanitizer();
234
        }
235
236
        return $instance;
237
    }
238
239
    /**
240
     * Get the smileys
241
     *
242
     * @param bool $isAll TRUE for all smileys, FALSE for smileys with display = 1
243
     *
244
     * @return array
245
     */
246
    public function getSmileys($isAll = true)
247
    {
248
        if (count($this->smileys) == 0) {
249
            $xoopsDB = XoopsDatabaseFactory::getDatabaseConnection();
250
            if ($getsmiles = $xoopsDB->query('SELECT * FROM ' . $xoopsDB->prefix('smiles'))) {
251
                while ($smiles = $xoopsDB->fetchArray($getsmiles)) {
252
                    $this->smileys[] = $smiles;
253
                }
254
            }
255
        }
256
        if ($isAll) {
257
            return $this->smileys;
258
        }
259
260
        $smileys = array();
261
        foreach ($this->smileys as $smile) {
262
            if (empty($smile['display'])) {
263
                continue;
264
            }
265
            $smileys[] = $smile;
266
        }
267
268
        return $smileys;
269
    }
270
271
    /**
272
     * Replace emoticons in the message with smiley images
273
     *
274
     * @param  string $message
275
     * @return string
276
     */
277
    public function smiley($message)
278
    {
279
        $smileys = $this->getSmileys();
280
        foreach ($smileys as $smile) {
281
            $message = str_replace($smile['code'], '<img class="imgsmile" src="' . XOOPS_UPLOAD_URL . '/' . htmlspecialchars($smile['smile_url']) . '" alt="" />', $message);
282
        }
283
284
        return $message;
285
    }
286
287
    /**
288
     * @param $match
289
     *
290
     * @return string
291
     */
292
    public function makeClickableCallback01($match)
293
    {
294
        return $match[1] . "<a href=\"$match[2]://$match[3]\" title=\"$match[2]://$match[3]\" rel=\"external\">$match[2]://" . $this->truncate($match[3]) . '</a>';
295
    }
296
297
    /**
298
     * @param $match
299
     *
300
     * @return string
301
     */
302
    public function makeClickableCallback02($match)
303
    {
304
        return $match[1] . "<a href=\"http://www.$match[2]$match[6]\" title=\"www.$match[2]$match[6]\" rel=\"external\">" . $this->truncate('www.' . $match[2] . $match[6]) . '</a>';
305
    }
306
307
    /**
308
     * @param $match
309
     *
310
     * @return string
311
     */
312
    public function makeClickableCallback03($match)
313
    {
314
        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>';
315
    }
316
317
    /**
318
     * @param $match
319
     *
320
     * @return string
321
     */
322
    public function makeClickableCallback04($match)
323
    {
324
        return $match[1] . "<a href=\"mailto:$match[2]@$match[3]\" title=\"$match[2]@$match[3]\">" . $this->truncate($match[2] . '@' . $match[3]) . '</a>';
325
    }
326
327
    /**
328
     * Make links in the text clickable
329
     *
330
     * @param  string $text
331
     * @return string
332
     */
333
    public function makeClickable(&$text)
334
    {
335
        $text1 = $text;
336
337
        $valid_chars = "a-z0-9\/\-_+=.~!%@?#&;:$\|";
338
        $end_chars   = "a-z0-9\/\-_+=~!%@?#&;:$\|";
339
340
        //        $patterns   = array();
341
        //        $replacements   = array();
342
        //
343
        //        $patterns[]     = "/(^|[^]_a-z0-9-=\"'\/])([a-z]+?):\/\/([{$valid_chars}]+[{$end_chars}])/ei";
344
        //        $replacements[] = "'\\1<a href=\"\\2://\\3\" title=\"\\2://\\3\" rel=\"external\">\\2://'.MyTextSanitizer::truncate( '\\3' ).'</a>'";
345
        //
346
        //
347
        //        $patterns[]     = "/(^|[^]_a-z0-9-=\"'\/:\.])www\.((([a-zA-Z0-9\-]*\.){1,}){1}([a-zA-Z]{2,6}){1})((\/([a-zA-Z0-9\-\._\?\,\'\/\\+&%\$#\=~])*)*)/ei";
348
        //        $replacements[] = "'\\1<a href=\"http://www.\\2\\6\" title=\"www.\\2\\6\" rel=\"external\">'.MyTextSanitizer::truncate( 'www.\\2\\6' ).'</a>'";
349
        //
350
        //        $patterns[]     = "/(^|[^]_a-z0-9-=\"'\/])ftp\.([a-z0-9\-]+)\.([{$valid_chars}]+[{$end_chars}])/ei";
351
        //        $replacements[] = "'\\1<a href=\"ftp://ftp.\\2.\\3\" title=\"ftp.\\2.\\3\" rel=\"external\">'.MyTextSanitizer::truncate( 'ftp.\\2.\\3' ).'</a>'";
352
        //
353
        //        $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";
354
        //        $replacements[] = "'\\1<a href=\"mailto:\\2@\\3\" title=\"\\2@\\3\">'.MyTextSanitizer::truncate( '\\2@\\3' ).'</a>'";
355
        //
356
        //        $text = preg_replace($patterns, $replacements, $text);
357
        //
358
        //----------------------------------------------------------------------------------
359
360
        $pattern = "/(^|[^]_a-z0-9-=\"'\/])([a-z]+?):\/\/([{$valid_chars}]+[{$end_chars}])/i";
361
        $text1   = preg_replace_callback($pattern, 'self::makeClickableCallback01', $text1);
362
363
        $pattern = "/(^|[^]_a-z0-9-=\"'\/:\.])www\.((([a-zA-Z0-9\-]*\.){1,}){1}([a-zA-Z]{2,6}){1})((\/([a-zA-Z0-9\-\._\?\,\'\/\\+&%\$#\=~])*)*)/i";
364
        $text1   = preg_replace_callback($pattern, 'self::makeClickableCallback02', $text1);
365
366
        $pattern = "/(^|[^]_a-z0-9-=\"'\/])ftp\.([a-z0-9\-]+)\.([{$valid_chars}]+[{$end_chars}])/i";
367
        $text1   = preg_replace_callback($pattern, 'self::makeClickableCallback03', $text1);
368
369
        $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";
370
        $text1   = preg_replace_callback($pattern, 'self::makeClickableCallback04', $text1);
371
372
        return $text1;
373
    }
374
375
    /**
376
     * MyTextSanitizer::truncate()
377
     *
378
     * @param  mixed $text
379
     * @return mixed|string
380
     */
381
    public function truncate($text)
382
    {
383
        $instance = MyTextSanitizer::getInstance();
0 ignored issues
show
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
384
        if (empty($text) || empty($instance->config['truncate_length']) || strlen($text) < $instance->config['truncate_length']) {
385
            return $text;
386
        }
387
        $len = floor($instance->config['truncate_length'] / 2);
388
        $ret = substr($text, 0, $len) . ' ... ' . substr($text, 5 - $len);
389
390
        return $ret;
391
    }
392
393
    /**
394
     * Replace XoopsCodes with their equivalent HTML formatting
395
     *
396
     * @param  string   $text
397
     * @param  bool|int $allowimage Allow images in the text?
398
     *                              On FALSE, uses links to images.
399
     * @return string
400
     */
401
    public function &xoopsCodeDecode(&$text, $allowimage = 1)
402
    {
403
        $patterns       = array();
404
        $replacements   = array();
405
        $patterns[]     = "/\[siteurl=(['\"]?)([^\"'<>]*)\\1](.*)\[\/siteurl\]/sU";
406
        $replacements[] = '<a href="' . XOOPS_URL . '/\\2" title="">\\3</a>';
407
        $patterns[]     = "/\[url=(['\"]?)(http[s]?:\/\/[^\"'<>]*)\\1](.*)\[\/url\]/sU";
408
        $replacements[] = '<a href="\\2" rel="external" title="">\\3</a>';
409
        $patterns[]     = "/\[url=(['\"]?)(ftp?:\/\/[^\"'<>]*)\\1](.*)\[\/url\]/sU";
410
        $replacements[] = '<a href="\\2" rel="external" title="">\\3</a>';
411
        $patterns[]     = "/\[url=(['\"]?)([^'\"<>]*)\\1](.*)\[\/url\]/sU";
412
        $replacements[] = '<a href="http://\\2" rel="external" title="">\\3</a>';
413
        $patterns[]     = "/\[color=(['\"]?)([a-zA-Z0-9]*)\\1](.*)\[\/color\]/sU";
414
        $replacements[] = '<span style="color: #\\2;">\\3</span>';
415
        $patterns[]     = "/\[size=(['\"]?)([a-z0-9-]*)\\1](.*)\[\/size\]/sU";
416
        $replacements[] = '<span style="font-size: \\2;">\\3</span>';
417
        $patterns[]     = "/\[font=(['\"]?)([^;<>\*\(\)\"']*)\\1](.*)\[\/font\]/sU";
418
        $replacements[] = '<span style="font-family: \\2;">\\3</span>';
419
        $patterns[]     = "/\[email]([^;<>\*\(\)\"']*)\[\/email\]/sU";
420
        $replacements[] = '<a href="mailto:\\1" title="">\\1</a>';
421
422
        $patterns[]     = "/\[b](.*)\[\/b\]/sU";
423
        $replacements[] = '<strong>\\1</strong>';
424
        $patterns[]     = "/\[i](.*)\[\/i\]/sU";
425
        $replacements[] = '<em>\\1</em>';
426
        $patterns[]     = "/\[u](.*)\[\/u\]/sU";
427
        $replacements[] = '<span style="text-decoration: underline;">\\1</span>';
428
        $patterns[]     = "/\[d](.*)\[\/d\]/sU";
429
        $replacements[] = '<del>\\1</del>';
430
        $patterns[]     = "/\[center](.*)\[\/center\]/sU";
431
        $replacements[] = '<div style="text-align: center;">\\1</div>';
432
        $patterns[]     = "/\[left](.*)\[\/left\]/sU";
433
        $replacements[] = '<div style="text-align: left;">\\1</div>';
434
        $patterns[]     = "/\[right](.*)\[\/right\]/sU";
435
        $replacements[] = '<div style="text-align: right;">\\1</div>';
436
437
        $this->text         = $text;
0 ignored issues
show
Documentation Bug introduced by
It seems like $text of type string is incompatible with the declared type object<holding> of property $text.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
438
        $this->patterns     = $patterns;
439
        $this->replacements = $replacements;
440
441
        $this->config['allowimage'] = $allowimage;
442
        $this->executeExtensions();
443
444
        $text = preg_replace($this->patterns, $this->replacements, $this->text);
445
        //-------------------------------------------------------------------------------
446
        $count = count($this->callbackPatterns);
447
448
        for ($i = 0; $i < $count; ++$i) {
449
            $text = preg_replace_callback($this->callbackPatterns[$i], $this->callbacks[$i], $text);
450
        }
451
        //------------------------------------------------------------------------------
452
        $text = $this->quoteConv($text);
453
454
        return $text;
455
    }
456
457
    /**
458
     * Convert quote tags
459
     *
460
     * @param  string $text
461
     * @return string
462
     */
463
    public function quoteConv($text)
464
    {
465
        //look for both open and closing tags in the correct order
466
        $pattern     = "/\[quote](.*)\[\/quote\]/sU";
467
        $replacement = _QUOTEC . '<div class="xoopsQuote"><blockquote>\\1</blockquote></div>';
468
469
        $text = preg_replace($pattern, $replacement, $text, -1, $count);
470
        //no more matches, return now
471
        if (!$count) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $count of type integer|null is loosely compared to false; this is ambiguous if the integer can be zero. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
472
            return $text;
473
        }
474
475
        //new matches could have been created, keep doing it until we have no matches
476
        return $this->quoteConv($text);
477
    }
478
479
    /**
480
     * A quick solution for filtering XSS scripts
481
     *
482
     * @TODO : To be improved
483
     * @param $text
484
     * @return mixed
485
     */
486
    public function filterXss($text)
487
    {
488
        $patterns       = array();
489
        $replacements   = array();
490
        $text           = str_replace("\x00", '', $text);
491
        $c              = "[\x01-\x1f]*";
492
        $patterns[]     = "/\bj{$c}a{$c}v{$c}a{$c}s{$c}c{$c}r{$c}i{$c}p{$c}t{$c}[\s]*:/si";
493
        $replacements[] = 'javascript;';
494
        $patterns[]     = "/\ba{$c}b{$c}o{$c}u{$c}t{$c}[\s]*:/si";
495
        $replacements[] = 'about;';
496
        $patterns[]     = "/\bx{$c}s{$c}s{$c}[\s]*:/si";
497
        $replacements[] = 'xss;';
498
        $text           = preg_replace($patterns, $replacements, $text);
499
500
        return $text;
501
    }
502
503
    /**
504
     * Convert linebreaks to <br> tags
505
     *
506
     * @param  string $text
507
     * @return string
508
     */
509
    public function nl2Br($text)
510
    {
511
        return preg_replace('/(\015\012)|(\015)|(\012)/', '<br>', $text);
512
    }
513
514
    /**
515
     * Add slashes to the text if magic_quotes_gpc is turned off.
516
     *
517
     * @param  string $text
518
     * @return string
519
     */
520
    public function addSlashes($text)
521
    {
522
        if (!get_magic_quotes_gpc()) {
523
            $text = addslashes($text);
524
        }
525
526
        return $text;
527
    }
528
529
    /**
530
     * if magic_quotes_gpc is on, stirip back slashes
531
     *
532
     * @param  string $text
533
     * @return string
534
     */
535
    public function stripSlashesGPC($text)
536
    {
537
        if (get_magic_quotes_gpc()) {
538
            $text = stripslashes($text);
539
        }
540
541
        return $text;
542
    }
543
544
    /**
545
     * Convert special characters to HTML entities
546
     *
547
     * @param  string $text    string being converted
548
     * @param  int    $quote_style
549
     * @param  string $charset character set used in conversion
550
     * @param  bool   $double_encode
551
     * @return string
552
     */
553
    public function htmlSpecialChars($text, $quote_style = ENT_QUOTES, $charset = null, $double_encode = true)
554
    {
555
        if (version_compare(phpversion(), '5.2.3', '>=')) {
556
            $text = htmlspecialchars($text, $quote_style, $charset ?: (defined('_CHARSET') ? _CHARSET : 'UTF-8'), $double_encode);
557
        } else {
558
            $text = htmlspecialchars($text, $quote_style);
559
        }
560
561
        return preg_replace(array('/&amp;/i', '/&nbsp;/i'), array('&', '&amp;nbsp;'), $text);
562
    }
563
564
    /**
565
     * Reverses {@link htmlSpecialChars()}
566
     *
567
     * @param  string $text
568
     * @return string
569
     */
570
    public function undoHtmlSpecialChars($text)
571
    {
572
        return preg_replace(array('/&gt;/i', '/&lt;/i', '/&quot;/i', '/&#039;/i', '/&amp;nbsp;/i'), array('>', '<', '"', '\'', '&nbsp;'), $text);
573
    }
574
575
    /**
576
     * Filters textarea form data in DB for display
577
     *
578
     * @param  string   $text
579
     * @param  bool|int $html   allow html?
580
     * @param  bool|int $smiley allow smileys?
581
     * @param  bool|int $xcode  allow xoopscode?
582
     * @param  bool|int $image  allow inline images?
583
     * @param  bool|int $br     convert linebreaks?
584
     * @return string
585
     */
586
    public function &displayTarea($text, $html = 0, $smiley = 1, $xcode = 1, $image = 1, $br = 1)
587
    {
588
        $charset = (defined('_CHARSET') ? _CHARSET : 'UTF-8');
589
        if (function_exists('mb_convert_encoding')) {
590
            $text = mb_convert_encoding($text, $charset, mb_detect_encoding($text, mb_detect_order(), true));
591
        }
592
        if ($html != 1) {
593
            // html not allowed
594
            $text = $this->htmlSpecialChars($text, ENT_COMPAT, $charset);
595
        }
596
        $text = $this->codePreConv($text, $xcode); // Ryuji_edit(2003-11-18)
597
        if ($smiley != 0) {
598
            // process smiley
599
            $text = $this->smiley($text);
600
        }
601
        if ($xcode != 0) {
602
            // decode xcode
603
            if ($image != 0) {
604
                // image allowed
605
                $text =& $this->xoopsCodeDecode($text);
606
            } else {
607
                // image not allowed
608
                $text =& $this->xoopsCodeDecode($text, 0);
609
            }
610
        }
611
        if ($br != 0) {
612
            $text = $this->nl2Br($text);
613
        }
614
        $text = $this->codeConv($text, $xcode);
615
        $text = $this->makeClickable($text);
616
        if (!empty($this->config['filterxss_on_display'])) {
617
            $text = $this->filterXss($text);
618
        }
619
620
        return $text;
621
    }
622
623
    /**
624
     * Filters textarea form data submitted for preview
625
     *
626
     * @param  string   $text
627
     * @param  bool|int $html   allow html?
628
     * @param  bool|int $smiley allow smileys?
629
     * @param  bool|int $xcode  allow xoopscode?
630
     * @param  bool|int $image  allow inline images?
631
     * @param  bool|int $br     convert linebreaks?
632
     * @return string
633
     */
634
    public function &previewTarea($text, $html = 0, $smiley = 1, $xcode = 1, $image = 1, $br = 1)
635
    {
636
        $text = $this->stripSlashesGPC($text);
637
        $text =& $this->displayTarea($text, $html, $smiley, $xcode, $image, $br);
638
639
        return $text;
640
    }
641
642
    /**
643
     * Replaces banned words in a string with their replacements
644
     *
645
     * @param  string $text
646
     * @return string
647
     * @deprecated
648
     */
649
    public function &censorString(&$text)
650
    {
651
        $ret = $this->executeExtension('censor', $text);
652
        if ($ret === false) {
653
            return $text;
654
        }
655
656
        return $ret;
657
    }
658
659
    /**
660
     * MyTextSanitizer::codePreConv()
661
     *
662
     * @param  mixed $text
663
     * @param  mixed $xcode
664
     * @return mixed
665
     */
666
    public function codePreConv($text, $xcode = 1)
667
    {
668
        if ($xcode != 0) {
669
            //            $patterns = "/\[code([^\]]*?)\](.*)\[\/code\]/esU";
670
            //            $replacements = "'[code\\1]'.base64_encode('\\2').'[/code]'";
671
672
            $patterns = "/\[code([^\]]*?)\](.*)\[\/code\]/sU";
673
            $text = preg_replace_callback(
674
                $patterns,
675
                function ($matches) {
676
                    return '[code'. $matches[1] . ']' . base64_encode($matches[2]) . '[/code]';
677
                },
678
                $text
679
            );
680
        }
681
682
        return $text;
683
    }
684
685
    /**
686
     * @param $match
687
     *
688
     * @return string
689
     */
690
    public function codeConvCallback($match)
691
    {
692
        return '<div class="xoopsCode">' . $this->executeExtension('syntaxhighlight', str_replace('\\\"', '\"', base64_decode($match[2])), $match[1]) . '</div>';
693
    }
694
695
    /**
696
     * MyTextSanitizer::codeConv()
697
     *
698
     * @param  mixed $text
699
     * @param  mixed $xcode
700
     * @return mixed
701
     */
702
    public function codeConv($text, $xcode = 1)
703
    {
704
        if (empty($xcode)) {
705
            return $text;
706
        }
707
        $patterns = "/\[code([^\]]*?)\](.*)\[\/code\]/sU";
708
        $text1    = preg_replace_callback($patterns, array($this, 'codeConvCallback'), $text);
709
710
        return $text1;
711
    }
712
713
    /**
714
     * MyTextSanitizer::executeExtensions()
715
     *
716
     * @return bool
0 ignored issues
show
Documentation introduced by
Should the return type not be boolean|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
717
     */
718
    public function executeExtensions()
719
    {
720
        $extensions = array_filter($this->config['extensions']);
721
        if (empty($extensions)) {
722
            return true;
723
        }
724
        foreach (array_keys($extensions) as $extension) {
725
            $this->executeExtension($extension);
726
        }
727
        return null;
728
    }
729
730
    /**
731
     * MyTextSanitizer::loadExtension()
732
     *
733
     * @param  mixed $name
734
     * @return bool|null
0 ignored issues
show
Documentation introduced by
Should the return type not be false|object?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
735
     */
736
    public function loadExtension($name)
737
    {
738
        if (file_exists($file = $this->path_basic . '/' . $name . '/' . $name . '.php')) {
739
            include_once $file;
740 View Code Duplication
        } elseif (file_exists($file = $this->path_plugin . '/' . $name . '/' . $name . '.php')) {
741
            include_once $file;
742
        } else {
743
            return false;
744
        }
745
        $class = 'Myts' . ucfirst($name);
746
        if (!class_exists($class)) {
747
            trigger_error("Extension '{$name}' does not exist", E_USER_WARNING);
748
749
            return false;
750
        }
751
        $extension = null;
0 ignored issues
show
Unused Code introduced by
$extension is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
752
        $extension = new $class($this);
753
754
        return $extension;
755
    }
756
757
    /**
758
     * MyTextSanitizer::executeExtension()
759
     *
760
     * @param  mixed $name
761
     * @return mixed
762
     */
763
    public function executeExtension($name)
764
    {
765
        $extension = $this->loadExtension($name);
766
        $args      = array_slice(func_get_args(), 1);
767
768
        return call_user_func_array(array($extension, 'load'), array_merge(array(&$this), $args));
769
    }
770
771
    /**
772
     * Filter out possible malicious text
773
     * kses project at SF could be a good solution to check
774
     *
775
     * @param  string $text  text to filter
776
     * @param  bool   $force force filtering
777
     * @return string filtered text
778
     */
779
    public function textFilter($text, $force = false)
780
    {
781
        $ret = $this->executeExtension('textfilter', $text, $force);
782
        if ($ret === false) {
783
            return $text;
784
        }
785
786
        return $ret;
787
    }
788
789
    // #################### Deprecated Methods ######################
790
    /**
791
     * *#@+
792
     *
793
     * @deprecated
794
     */
795
796
    /**
797
     * MyTextSanitizer::codeSanitizer()
798
     *
799
     * @param  mixed $str
800
     * @param  mixed $image
801
     * @return mixed|string
802
     */
803
    public function codeSanitizer($str, $image = 1)
804
    {
805
        $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated');
806
        $str = $this->htmlSpecialChars(str_replace('\"', '"', base64_decode($str)));
807
        $str =& $this->xoopsCodeDecode($str, $image);
808
809
        return $str;
810
    }
811
812
    /**
813
     * MyTextSanitizer::sanitizeForDisplay()
814
     *
815
     * @param  mixed   $text
816
     * @param  integer $allowhtml
817
     * @param  integer $smiley
818
     * @param  mixed   $bbcode
819
     * @return mixed|string
820
     */
821 View Code Duplication
    public function sanitizeForDisplay($text, $allowhtml = 0, $smiley = 1, $bbcode = 1)
822
    {
823
        $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated');
824
        if ($allowhtml == 0) {
825
            $text = $this->htmlSpecialChars($text);
826
        } else {
827
            // $config =& $GLOBALS['xoopsConfig'];
828
            // $allowed = $config['allowed_html'];
829
            // $text = strip_tags($text, $allowed);
830
            $text = $this->makeClickable($text);
831
        }
832
        if ($smiley == 1) {
833
            $text = $this->smiley($text);
834
        }
835
        if ($bbcode == 1) {
836
            $text =& $this->xoopsCodeDecode($text);
837
        }
838
        $text = $this->nl2Br($text);
839
840
        return $text;
841
    }
842
843
    /**
844
     * MyTextSanitizer::sanitizeForPreview()
845
     *
846
     * @param  mixed   $text
847
     * @param  integer $allowhtml
848
     * @param  integer $smiley
849
     * @param  mixed   $bbcode
850
     * @return mixed|string
851
     */
852 View Code Duplication
    public function sanitizeForPreview($text, $allowhtml = 0, $smiley = 1, $bbcode = 1)
853
    {
854
        $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated');
855
        $text = $this->oopsStripSlashesGPC($text);
856
        if ($allowhtml == 0) {
857
            $text = $this->htmlSpecialChars($text);
858
        } else {
859
            // $config =& $GLOBALS['xoopsConfig'];
860
            // $allowed = $config['allowed_html'];
861
            // $text = strip_tags($text, $allowed);
862
            $text = $this->makeClickable($text);
863
        }
864
        if ($smiley == 1) {
865
            $text = $this->smiley($text);
866
        }
867
        if ($bbcode == 1) {
868
            $text =& $this->xoopsCodeDecode($text);
869
        }
870
        $text = $this->nl2Br($text);
871
872
        return $text;
873
    }
874
875
    /**
876
     * MyTextSanitizer::makeTboxData4Save()
877
     *
878
     * @param  mixed $text
879
     * @return string
880
     */
881
    public function makeTboxData4Save($text)
882
    {
883
        $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated');
884
885
        // $text = $this->undoHtmlSpecialChars($text);
886
        return $this->addSlashes($text);
887
    }
888
889
    /**
890
     * MyTextSanitizer::makeTboxData4Show()
891
     *
892
     * @param  mixed $text
893
     * @param  mixed $smiley
894
     * @return mixed|string
895
     */
896 View Code Duplication
    public function makeTboxData4Show($text, $smiley = 0)
0 ignored issues
show
Unused Code introduced by
The parameter $smiley is not used and could be removed.

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

Loading history...
897
    {
898
        $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated');
899
        $text = $this->htmlSpecialChars($text);
900
901
        return $text;
902
    }
903
904
    /**
905
     * MyTextSanitizer::makeTboxData4Edit()
906
     *
907
     * @param  mixed $text
908
     * @return string
909
     */
910
    public function makeTboxData4Edit($text)
911
    {
912
        $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated');
913
914
        return $this->htmlSpecialChars($text);
915
    }
916
917
    /**
918
     * MyTextSanitizer::makeTboxData4Preview()
919
     *
920
     * @param  mixed $text
921
     * @param  mixed $smiley
922
     * @return mixed|string
923
     */
924 View Code Duplication
    public function makeTboxData4Preview($text, $smiley = 0)
0 ignored issues
show
Unused Code introduced by
The parameter $smiley is not used and could be removed.

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

Loading history...
925
    {
926
        $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated');
927
        $text = $this->stripSlashesGPC($text);
928
        $text = $this->htmlSpecialChars($text);
929
930
        return $text;
931
    }
932
933
    /**
934
     * MyTextSanitizer::makeTboxData4PreviewInForm()
935
     *
936
     * @param  mixed $text
937
     * @return string
938
     */
939 View Code Duplication
    public function makeTboxData4PreviewInForm($text)
940
    {
941
        $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated');
942
        $text = $this->stripSlashesGPC($text);
943
944
        return $this->htmlSpecialChars($text);
945
    }
946
947
    /**
948
     * MyTextSanitizer::makeTareaData4Save()
949
     *
950
     * @param  mixed $text
951
     * @return string
952
     */
953
    public function makeTareaData4Save($text)
954
    {
955
        $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated');
956
957
        return $this->addSlashes($text);
958
    }
959
960
    /**
961
     * MyTextSanitizer::makeTareaData4Show()
962
     *
963
     * @param  mixed   $text
964
     * @param  integer $html
965
     * @param  integer $smiley
966
     * @param  mixed   $xcode
967
     * @return mixed|string
968
     */
969 View Code Duplication
    public function &makeTareaData4Show(&$text, $html = 1, $smiley = 1, $xcode = 1)
970
    {
971
        $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated');
972
        $text =& $this->displayTarea($text, $html, $smiley, $xcode);
973
974
        return $text;
975
    }
976
977
    /**
978
     * MyTextSanitizer::makeTareaData4Edit()
979
     *
980
     * @param  mixed $text
981
     * @return string
982
     */
983
    public function makeTareaData4Edit($text)
984
    {
985
        $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated');
986
987
        return $this->htmlSpecialChars($text);
988
    }
989
990
    /**
991
     * MyTextSanitizer::makeTareaData4Preview()
992
     *
993
     * @param  mixed   $text
994
     * @param  integer $html
995
     * @param  integer $smiley
996
     * @param  mixed   $xcode
997
     * @return mixed|string
998
     */
999 View Code Duplication
    public function &makeTareaData4Preview(&$text, $html = 1, $smiley = 1, $xcode = 1)
1000
    {
1001
        $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated');
1002
        $text =& $this->previewTarea($text, $html, $smiley, $xcode);
1003
1004
        return $text;
1005
    }
1006
1007
    /**
1008
     * MyTextSanitizer::makeTareaData4PreviewInForm()
1009
     *
1010
     * @param  mixed $text
1011
     * @return string
1012
     */
1013 View Code Duplication
    public function makeTareaData4PreviewInForm($text)
1014
    {
1015
        $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated');
1016
        // if magic_quotes_gpc is on, do stipslashes
1017
        $text = $this->stripSlashesGPC($text);
1018
1019
        return $this->htmlSpecialChars($text);
1020
    }
1021
1022
    /**
1023
     * MyTextSanitizer::makeTareaData4InsideQuotes()
1024
     *
1025
     * @param  mixed $text
1026
     * @return string
1027
     */
1028
    public function makeTareaData4InsideQuotes($text)
1029
    {
1030
        $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated');
1031
1032
        return $this->htmlSpecialChars($text);
1033
    }
1034
1035
    /**
1036
     * MyTextSanitizer::oopsStripSlashesGPC()
1037
     *
1038
     * @param  mixed $text
1039
     * @return string
1040
     */
1041
    public function oopsStripSlashesGPC($text)
1042
    {
1043
        $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated');
1044
1045
        return $this->stripSlashesGPC($text);
1046
    }
1047
1048
    /**
1049
     * MyTextSanitizer::oopsStripSlashesRT()
1050
     *
1051
     * @param  mixed $text
1052
     * @return mixed|string
1053
     */
1054
    public function oopsStripSlashesRT($text)
1055
    {
1056
        $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated');
1057
        if (get_magic_quotes_runtime()) {
1058
            $text = stripslashes($text);
1059
        }
1060
1061
        return $text;
1062
    }
1063
1064
    /**
1065
     * MyTextSanitizer::oopsAddSlashes()
1066
     *
1067
     * @param  mixed $text
1068
     * @return string
1069
     */
1070
    public function oopsAddSlashes($text)
1071
    {
1072
        $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated');
1073
1074
        return $this->addSlashes($text);
1075
    }
1076
1077
    /**
1078
     * MyTextSanitizer::oopsHtmlSpecialChars()
1079
     *
1080
     * @param  mixed $text
1081
     * @return string
1082
     */
1083
    public function oopsHtmlSpecialChars($text)
1084
    {
1085
        $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated');
1086
1087
        return $this->htmlSpecialChars($text);
1088
    }
1089
1090
    /**
1091
     * MyTextSanitizer::oopsNl2Br()
1092
     *
1093
     * @param  mixed $text
1094
     * @return string
1095
     */
1096
    public function oopsNl2Br($text)
1097
    {
1098
        $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated');
1099
1100
        return $this->nl2Br($text);
1101
    }
1102
}
1103