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 <phppp@users.sourceforge.net> 19 */ 20 21/** 22 * Abstract class for extensions 23 * 24 * @author Taiwen Jiang <phppp@users.sourceforge.net> 25 * @copyright (c) 2000-2016 XOOPS Project (www.xoops.org) 26 */ 27class 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 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 <onokazu@xoops.org> 129 * @author Taiwen Jiang <phppp@users.sourceforge.net> 130 * @author Goghs Cheng 131 * @copyright (c) 2000-2016 XOOPS Project - www.xoops.org 132 */ 133class MyTextSanitizer 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 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 /* @var XoopsMySQLDatabase $xoopsDB */ 250 $xoopsDB = XoopsDatabaseFactory::getDatabaseConnection(); 251 if ($getsmiles = $xoopsDB->query('SELECT * FROM ' . $xoopsDB->prefix('smiles'))) { 252 while (false !== ($smiles = $xoopsDB->fetchArray($getsmiles))) { 253 $this->smileys[] = $smiles; 254 } 255 } 256 } 257 if ($isAll) { 258 return $this->smileys; 259 } 260 261 $smileys = array(); 262 foreach ($this->smileys as $smile) { 263 if (empty($smile['display'])) { 264 continue; 265 } 266 $smileys[] = $smile; 267 } 268 269 return $smileys; 270 } 271 272 /** 273 * Replace emoticons in the message with smiley images 274 * 275 * @param string $message 276 * @return string 277 */ 278 public function smiley($message) 279 { 280 $smileys = $this->getSmileys(); 281 foreach ($smileys as $smile) { 282 $message = str_replace($smile['code'], '<img class="imgsmile" src="' . XOOPS_UPLOAD_URL . '/' . htmlspecialchars($smile['smile_url']) . '" alt="" />', $message); 283 } 284 285 return $message; 286 } 287 288 /** 289 * @param $match 290 * 291 * @return string 292 */ 293 public function makeClickableCallback01($match) 294 { 295 return $match[1] . "<a href=\"$match[2]://$match[3]\" title=\"$match[2]://$match[3]\" rel=\"external\">$match[2]://" . $this->truncate($match[3]) . '</a>'; 296 } 297 298 /** 299 * @param $match 300 * 301 * @return string 302 */ 303 public function makeClickableCallback02($match) 304 { 305 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>'; 306 } 307 308 /** 309 * @param $match 310 * 311 * @return string 312 */ 313 public function makeClickableCallback03($match) 314 { 315 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>'; 316 } 317 318 /** 319 * @param $match 320 * 321 * @return string 322 */ 323 public function makeClickableCallback04($match) 324 { 325 return $match[1] . "<a href=\"mailto:$match[2]@$match[3]\" title=\"$match[2]@$match[3]\">" . $this->truncate($match[2] . '@' . $match[3]) . '</a>'; 326 } 327 328 /** 329 * Make links in the text clickable 330 * 331 * @param string $text 332 * @return string 333 */ 334 public function makeClickable(&$text) 335 { 336 $text1 = $text; 337 338 $valid_chars = "a-z0-9\/\-_+=.~!%@?#&;:$\|"; 339 $end_chars = "a-z0-9\/\-_+=~!%@?#&;:$\|"; 340 341 // $patterns = array(); 342 // $replacements = array(); 343 // 344 // $patterns[] = "/(^|[^]_a-z0-9-=\"'\/])([a-z]+?):\/\/([{$valid_chars}]+[{$end_chars}])/ei"; 345 // $replacements[] = "'\\1<a href=\"\\2://\\3\" title=\"\\2://\\3\" rel=\"external\">\\2://'.MyTextSanitizer::truncate( '\\3' ).'</a>'"; 346 // 347 // 348 // $patterns[] = "/(^|[^]_a-z0-9-=\"'\/:\.])www\.((([a-zA-Z0-9\-]*\.){1,}){1}([a-zA-Z]{2,6}){1})((\/([a-zA-Z0-9\-\._\?\,\'\/\\+&%\$#\=~])*)*)/ei"; 349 // $replacements[] = "'\\1<a href=\"http://www.\\2\\6\" title=\"www.\\2\\6\" rel=\"external\">'.MyTextSanitizer::truncate( 'www.\\2\\6' ).'</a>'"; 350 // 351 // $patterns[] = "/(^|[^]_a-z0-9-=\"'\/])ftp\.([a-z0-9\-]+)\.([{$valid_chars}]+[{$end_chars}])/ei"; 352 // $replacements[] = "'\\1<a href=\"ftp://ftp.\\2.\\3\" title=\"ftp.\\2.\\3\" rel=\"external\">'.MyTextSanitizer::truncate( 'ftp.\\2.\\3' ).'</a>'"; 353 // 354 // $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"; 355 // $replacements[] = "'\\1<a href=\"mailto:\\2@\\3\" title=\"\\2@\\3\">'.MyTextSanitizer::truncate( '\\2@\\3' ).'</a>'"; 356 // 357 // $text = preg_replace($patterns, $replacements, $text); 358 // 359 //---------------------------------------------------------------------------------- 360 361 $pattern = "/(^|[^]_a-z0-9-=\"'\/])([a-z]+?):\/\/([{$valid_chars}]+[{$end_chars}])/i"; 362 $text1 = preg_replace_callback($pattern, 'self::makeClickableCallback01', $text1); 363 364 $pattern = "/(^|[^]_a-z0-9-=\"'\/:\.])www\.((([a-zA-Z0-9\-]*\.){1,}){1}([a-zA-Z]{2,6}){1})((\/([a-zA-Z0-9\-\._\?\,\'\/\\+&%\$#\=~])*)*)/i"; 365 $text1 = preg_replace_callback($pattern, 'self::makeClickableCallback02', $text1); 366 367 $pattern = "/(^|[^]_a-z0-9-=\"'\/])ftp\.([a-z0-9\-]+)\.([{$valid_chars}]+[{$end_chars}])/i"; 368 $text1 = preg_replace_callback($pattern, 'self::makeClickableCallback03', $text1); 369 370 $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"; 371 $text1 = preg_replace_callback($pattern, 'self::makeClickableCallback04', $text1); 372 373 return $text1; 374 } 375 376 /** 377 * MyTextSanitizer::truncate() 378 * 379 * @param mixed $text 380 * @return mixed|string 381 */ 382 public function truncate($text) 383 { 384 $instance = MyTextSanitizer::getInstance(); 385 if (empty($text) || empty($instance->config['truncate_length']) || strlen($text) < $instance->config['truncate_length']) { 386 return $text; 387 } 388 $len = floor($instance->config['truncate_length'] / 2); 389 $ret = substr($text, 0, $len) . ' ... ' . substr($text, 5 - $len); 390 391 return $ret; 392 } 393 394 /** 395 * Replace XoopsCodes with their equivalent HTML formatting 396 * 397 * @param string $text 398 * @param bool|int $allowimage Allow images in the text? 399 * On FALSE, uses links to images. 400 * @return string 401 */ 402 public function &xoopsCodeDecode(&$text, $allowimage = 1) 403 { 404 $patterns = array(); 405 $replacements = array(); 406 $patterns[] = "/\[siteurl=(['\"]?)([^\"'<>]*)\\1](.*)\[\/siteurl\]/sU"; 407 $replacements[] = '<a href="' . XOOPS_URL . '/\\2" title="">\\3</a>'; 408 $patterns[] = "/\[url=(['\"]?)(http[s]?:\/\/[^\"'<>]*)\\1](.*)\[\/url\]/sU"; 409 $replacements[] = '<a href="\\2" rel="external" title="">\\3</a>'; 410 $patterns[] = "/\[url=(['\"]?)(ftp?:\/\/[^\"'<>]*)\\1](.*)\[\/url\]/sU"; 411 $replacements[] = '<a href="\\2" rel="external" title="">\\3</a>'; 412 $patterns[] = "/\[url=(['\"]?)([^'\"<>]*)\\1](.*)\[\/url\]/sU"; 413 $replacements[] = '<a href="http://\\2" rel="external" title="">\\3</a>'; 414 $patterns[] = "/\[color=(['\"]?)([a-zA-Z0-9]*)\\1](.*)\[\/color\]/sU"; 415 $replacements[] = '<span style="color: #\\2;">\\3</span>'; 416 $patterns[] = "/\[size=(['\"]?)([a-z0-9-]*)\\1](.*)\[\/size\]/sU"; 417 $replacements[] = '<span style="font-size: \\2;">\\3</span>'; 418 $patterns[] = "/\[font=(['\"]?)([^;<>\*\(\)\"']*)\\1](.*)\[\/font\]/sU"; 419 $replacements[] = '<span style="font-family: \\2;">\\3</span>'; 420 $patterns[] = "/\[email]([^;<>\*\(\)\"']*)\[\/email\]/sU"; 421 $replacements[] = '<a href="mailto:\\1" title="">\\1</a>'; 422 423 $patterns[] = "/\[b](.*)\[\/b\]/sU"; 424 $replacements[] = '<strong>\\1</strong>'; 425 $patterns[] = "/\[i](.*)\[\/i\]/sU"; 426 $replacements[] = '<em>\\1</em>'; 427 $patterns[] = "/\[u](.*)\[\/u\]/sU"; 428 $replacements[] = '<span style="text-decoration: underline;">\\1</span>'; 429 $patterns[] = "/\[d](.*)\[\/d\]/sU"; 430 $replacements[] = '<del>\\1</del>'; 431 $patterns[] = "/\[center](.*)\[\/center\]/sU"; 432 $replacements[] = '<div style="text-align: center;">\\1</div>'; 433 $patterns[] = "/\[left](.*)\[\/left\]/sU"; 434 $replacements[] = '<div style="text-align: left;">\\1</div>'; 435 $patterns[] = "/\[right](.*)\[\/right\]/sU"; 436 $replacements[] = '<div style="text-align: right;">\\1</div>'; 437 438 $this->text = $text; 439 $this->patterns = $patterns; 440 $this->replacements = $replacements; 441 442 $this->config['allowimage'] = $allowimage; 443 $this->executeExtensions(); 444 445 $text = preg_replace($this->patterns, $this->replacements, $this->text); 446 //------------------------------------------------------------------------------- 447 $count = count($this->callbackPatterns); 448 449 for ($i = 0; $i < $count; ++$i) { 450 $text = preg_replace_callback($this->callbackPatterns[$i], $this->callbacks[$i], $text); 451 } 452 //------------------------------------------------------------------------------ 453 $text = $this->quoteConv($text); 454 455 return $text; 456 } 457 458 /** 459 * Convert quote tags 460 * 461 * @param string $text 462 * @return string 463 */ 464 public function quoteConv($text) 465 { 466 //look for both open and closing tags in the correct order 467 $pattern = "/\[quote](.*)\[\/quote\]/sU"; 468 $replacement = _QUOTEC . '<div class="xoopsQuote"><blockquote>\\1</blockquote></div>'; 469 470 $text = preg_replace($pattern, $replacement, $text, -1, $count); 471 //no more matches, return now 472 if (!$count) { 473 return $text; 474 } 475 476 //new matches could have been created, keep doing it until we have no matches 477 return $this->quoteConv($text); 478 } 479 480 /** 481 * A quick solution for filtering XSS scripts 482 * 483 * @TODO : To be improved 484 * @param $text 485 * @return mixed 486 */ 487 public function filterXss($text) 488 { 489 $patterns = array(); 490 $replacements = array(); 491 $text = str_replace("\x00", '', $text); 492 $c = "[\x01-\x1f]*"; 493 $patterns[] = "/\bj{$c}a{$c}v{$c}a{$c}s{$c}c{$c}r{$c}i{$c}p{$c}t{$c}[\s]*:/si"; 494 $replacements[] = 'javascript;'; 495 $patterns[] = "/\ba{$c}b{$c}o{$c}u{$c}t{$c}[\s]*:/si"; 496 $replacements[] = 'about;'; 497 $patterns[] = "/\bx{$c}s{$c}s{$c}[\s]*:/si"; 498 $replacements[] = 'xss;'; 499 $text = preg_replace($patterns, $replacements, $text); 500 501 return $text; 502 } 503 504 /** 505 * Convert linebreaks to <br> tags 506 * 507 * @param string $text 508 * @return string 509 */ 510 public function nl2Br($text) 511 { 512 return preg_replace('/(\015\012)|(\015)|(\012)/', '<br>', $text); 513 } 514 515 /** 516 * Add slashes to the text if magic_quotes_gpc is turned off. 517 * 518 * @param string $text 519 * @return string 520 */ 521 public function addSlashes($text) 522 { 523 if (!get_magic_quotes_gpc()) { 524 $text = addslashes($text); 525 } 526 527 return $text; 528 } 529 530 /** 531 * if magic_quotes_gpc is on, stirip back slashes 532 * 533 * @param string $text 534 * @return string 535 */ 536 public function stripSlashesGPC($text) 537 { 538 if (get_magic_quotes_gpc()) { 539 $text = stripslashes($text); 540 } 541 542 return $text; 543 } 544 545 /** 546 * Convert special characters to HTML entities 547 * 548 * @param string $text string being converted 549 * @param int|null $quote_style 550 * @param string $charset character set used in conversion 551 * @param bool $double_encode 552 * @return string 553 */ 554 public function htmlSpecialChars($text, $quote_style = NULL, $charset = null, $double_encode = true) 555 { 556 if ($quote_style === NULL) { 557 $quote_style = ENT_QUOTES; 558 } 559 560 if (version_compare(phpversion(), '5.2.3', '>=')) { 561 $text = htmlspecialchars($text, $quote_style, $charset ?: (defined('_CHARSET') ? _CHARSET : 'UTF-8'), $double_encode); 562 } else { 563 $text = htmlspecialchars($text, $quote_style); 564 } 565 566 return preg_replace(array('/&/i', '/ /i'), array('&', '&nbsp;'), $text); 567 } 568 569 /** 570 * Reverses {@link htmlSpecialChars()} 571 * 572 * @param string $text 573 * @return string 574 */ 575 public function undoHtmlSpecialChars($text) 576 { 577 return preg_replace(array('/>/i', '/</i', '/"/i', '/'/i', '/&nbsp;/i'), array('>', '<', '"', '\'', ' '), $text); 578 } 579 580 /** 581 * Filters textarea form data in DB for display 582 * 583 * @param string $text 584 * @param bool|int $html allow html? 585 * @param bool|int $smiley allow smileys? 586 * @param bool|int $xcode allow xoopscode? 587 * @param bool|int $image allow inline images? 588 * @param bool|int $br convert linebreaks? 589 * @return string 590 */ 591 public function &displayTarea($text, $html = 0, $smiley = 1, $xcode = 1, $image = 1, $br = 1) 592 { 593 $charset = (defined('_CHARSET') ? _CHARSET : 'UTF-8'); 594 if (function_exists('mb_convert_encoding')) { 595 $text = mb_convert_encoding($text, $charset, mb_detect_encoding($text, mb_detect_order(), true)); 596 } 597 if ($html != 1) { 598 // html not allowed 599 $text = $this->htmlSpecialChars($text, ENT_COMPAT, $charset); 600 } 601 $text = $this->codePreConv($text, $xcode); // Ryuji_edit(2003-11-18) 602 if ($smiley != 0) { 603 // process smiley 604 $text = $this->smiley($text); 605 } 606 if ($xcode != 0) { 607 // decode xcode 608 if ($image != 0) { 609 // image allowed 610 $text =& $this->xoopsCodeDecode($text); 611 } else { 612 // image not allowed 613 $text =& $this->xoopsCodeDecode($text, 0); 614 } 615 } 616 if ($br != 0) { 617 $text = $this->nl2Br($text); 618 } 619 $text = $this->codeConv($text, $xcode); 620 $text = $this->makeClickable($text); 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); 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 bool|null 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 $extension = null; 757 $extension = new $class($this); 758 759 return $extension; 760 } 761 762 /** 763 * MyTextSanitizer::executeExtension() 764 * 765 * @param mixed $name 766 * @return mixed 767 */ 768 public function executeExtension($name) 769 { 770 $extension = $this->loadExtension($name); 771 $args = array_slice(func_get_args(), 1); 772 array_unshift($args, $this); 773 774 return call_user_func_array(array($extension, 'load'), $args); 775 } 776 777 /** 778 * Filter out possible malicious text 779 * kses project at SF could be a good solution to check 780 * 781 * @param string $text text to filter 782 * @param bool $force force filtering 783 * @return string filtered text 784 */ 785 public function textFilter($text, $force = false) 786 { 787 $ret = $this->executeExtension('textfilter', $text, $force); 788 if ($ret === false) { 789 return $text; 790 } 791 792 return $ret; 793 } 794 795 // #################### Deprecated Methods ###################### 796 /** 797 * *#@+ 798 * 799 * @deprecated 800 */ 801 802 /** 803 * MyTextSanitizer::codeSanitizer() 804 * 805 * @param mixed $str 806 * @param mixed $image 807 * @return mixed|string 808 */ 809 public function codeSanitizer($str, $image = 1) 810 { 811 $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated'); 812 $str = $this->htmlSpecialChars(str_replace('\"', '"', base64_decode($str))); 813 $str =& $this->xoopsCodeDecode($str, $image); 814 815 return $str; 816 } 817 818 /** 819 * MyTextSanitizer::sanitizeForDisplay() 820 * 821 * @param mixed $text 822 * @param integer $allowhtml 823 * @param integer $smiley 824 * @param mixed $bbcode 825 * @return mixed|string 826 */ 827 public function sanitizeForDisplay($text, $allowhtml = 0, $smiley = 1, $bbcode = 1) 828 { 829 $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated'); 830 if ($allowhtml == 0) { 831 $text = $this->htmlSpecialChars($text); 832 } else { 833 // $config =& $GLOBALS['xoopsConfig']; 834 // $allowed = $config['allowed_html']; 835 // $text = strip_tags($text, $allowed); 836 $text = $this->makeClickable($text); 837 } 838 if ($smiley == 1) { 839 $text = $this->smiley($text); 840 } 841 if ($bbcode == 1) { 842 $text =& $this->xoopsCodeDecode($text); 843 } 844 $text = $this->nl2Br($text); 845 846 return $text; 847 } 848 849 /** 850 * MyTextSanitizer::sanitizeForPreview() 851 * 852 * @param mixed $text 853 * @param integer $allowhtml 854 * @param integer $smiley 855 * @param mixed $bbcode 856 * @return mixed|string 857 */ 858 public function sanitizeForPreview($text, $allowhtml = 0, $smiley = 1, $bbcode = 1) 859 { 860 $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated'); 861 $text = $this->oopsStripSlashesGPC($text); 862 if ($allowhtml == 0) { 863 $text = $this->htmlSpecialChars($text); 864 } else { 865 // $config =& $GLOBALS['xoopsConfig']; 866 // $allowed = $config['allowed_html']; 867 // $text = strip_tags($text, $allowed); 868 $text = $this->makeClickable($text); 869 } 870 if ($smiley == 1) { 871 $text = $this->smiley($text); 872 } 873 if ($bbcode == 1) { 874 $text =& $this->xoopsCodeDecode($text); 875 } 876 $text = $this->nl2Br($text); 877 878 return $text; 879 } 880 881 /** 882 * MyTextSanitizer::makeTboxData4Save() 883 * 884 * @param mixed $text 885 * @return string 886 */ 887 public function makeTboxData4Save($text) 888 { 889 $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated'); 890 891 // $text = $this->undoHtmlSpecialChars($text); 892 return $this->addSlashes($text); 893 } 894 895 /** 896 * MyTextSanitizer::makeTboxData4Show() 897 * 898 * @param mixed $text 899 * @param mixed $smiley 900 * @return mixed|string 901 */ 902 public function makeTboxData4Show($text, $smiley = 0) 903 { 904 $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated'); 905 $text = $this->htmlSpecialChars($text); 906 907 return $text; 908 } 909 910 /** 911 * MyTextSanitizer::makeTboxData4Edit() 912 * 913 * @param mixed $text 914 * @return string 915 */ 916 public function makeTboxData4Edit($text) 917 { 918 $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated'); 919 920 return $this->htmlSpecialChars($text); 921 } 922 923 /** 924 * MyTextSanitizer::makeTboxData4Preview() 925 * 926 * @param mixed $text 927 * @param mixed $smiley 928 * @return mixed|string 929 */ 930 public function makeTboxData4Preview($text, $smiley = 0) 931 { 932 $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated'); 933 $text = $this->stripSlashesGPC($text); 934 $text = $this->htmlSpecialChars($text); 935 936 return $text; 937 } 938 939 /** 940 * MyTextSanitizer::makeTboxData4PreviewInForm() 941 * 942 * @param mixed $text 943 * @return string 944 */ 945 public function makeTboxData4PreviewInForm($text) 946 { 947 $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated'); 948 $text = $this->stripSlashesGPC($text); 949 950 return $this->htmlSpecialChars($text); 951 } 952 953 /** 954 * MyTextSanitizer::makeTareaData4Save() 955 * 956 * @param mixed $text 957 * @return string 958 */ 959 public function makeTareaData4Save($text) 960 { 961 $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated'); 962 963 return $this->addSlashes($text); 964 } 965 966 /** 967 * MyTextSanitizer::makeTareaData4Show() 968 * 969 * @param mixed $text 970 * @param integer $html 971 * @param integer $smiley 972 * @param mixed $xcode 973 * @return mixed|string 974 */ 975 public function &makeTareaData4Show(&$text, $html = 1, $smiley = 1, $xcode = 1) 976 { 977 $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated'); 978 $text =& $this->displayTarea($text, $html, $smiley, $xcode); 979 980 return $text; 981 } 982 983 /** 984 * MyTextSanitizer::makeTareaData4Edit() 985 * 986 * @param mixed $text 987 * @return string 988 */ 989 public function makeTareaData4Edit($text) 990 { 991 $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated'); 992 993 return $this->htmlSpecialChars($text); 994 } 995 996 /** 997 * MyTextSanitizer::makeTareaData4Preview() 998 * 999 * @param mixed $text 1000 * @param integer $html 1001 * @param integer $smiley 1002 * @param mixed $xcode 1003 * @return mixed|string 1004 */ 1005 public function &makeTareaData4Preview(&$text, $html = 1, $smiley = 1, $xcode = 1) 1006 { 1007 $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated'); 1008 $text =& $this->previewTarea($text, $html, $smiley, $xcode); 1009 1010 return $text; 1011 } 1012 1013 /** 1014 * MyTextSanitizer::makeTareaData4PreviewInForm() 1015 * 1016 * @param mixed $text 1017 * @return string 1018 */ 1019 public function makeTareaData4PreviewInForm($text) 1020 { 1021 $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated'); 1022 // if magic_quotes_gpc is on, do stipslashes 1023 $text = $this->stripSlashesGPC($text); 1024 1025 return $this->htmlSpecialChars($text); 1026 } 1027 1028 /** 1029 * MyTextSanitizer::makeTareaData4InsideQuotes() 1030 * 1031 * @param mixed $text 1032 * @return string 1033 */ 1034 public function makeTareaData4InsideQuotes($text) 1035 { 1036 $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated'); 1037 1038 return $this->htmlSpecialChars($text); 1039 } 1040 1041 /** 1042 * MyTextSanitizer::oopsStripSlashesGPC() 1043 * 1044 * @param mixed $text 1045 * @return string 1046 */ 1047 public function oopsStripSlashesGPC($text) 1048 { 1049 $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated'); 1050 1051 return $this->stripSlashesGPC($text); 1052 } 1053 1054 /** 1055 * MyTextSanitizer::oopsStripSlashesRT() 1056 * 1057 * @param mixed $text 1058 * @return mixed|string 1059 */ 1060 public function oopsStripSlashesRT($text) 1061 { 1062 $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated'); 1063 if (get_magic_quotes_runtime()) { 1064 $text = stripslashes($text); 1065 } 1066 1067 return $text; 1068 } 1069 1070 /** 1071 * MyTextSanitizer::oopsAddSlashes() 1072 * 1073 * @param mixed $text 1074 * @return string 1075 */ 1076 public function oopsAddSlashes($text) 1077 { 1078 $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated'); 1079 1080 return $this->addSlashes($text); 1081 } 1082 1083 /** 1084 * MyTextSanitizer::oopsHtmlSpecialChars() 1085 * 1086 * @param mixed $text 1087 * @return string 1088 */ 1089 public function oopsHtmlSpecialChars($text) 1090 { 1091 $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated'); 1092 1093 return $this->htmlSpecialChars($text); 1094 } 1095 1096 /** 1097 * MyTextSanitizer::oopsNl2Br() 1098 * 1099 * @param mixed $text 1100 * @return string 1101 */ 1102 public function oopsNl2Br($text) 1103 { 1104 $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . '::' . __FUNCTION__ . ' is deprecated'); 1105 1106 return $this->nl2Br($text); 1107 } 1108} 1109