XOOPS 2.5.6  Final
 All Classes Namespaces Files Functions Variables Pages
module.textsanitizer.php
Go to the documentation of this file.
1 <?php
29 {
30  var $instance;
31  var $ts;
32  var $config;
34 
40  function __construct(&$ts)
41  {
42  $this->ts = $ts;
43  $this->image_path = XOOPS_URL . '/images/form';
44  }
45 
53  {
54  $this->__construct($ts);
55  }
56 
63  function loadConfig($path = null)
64  {
66  $path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
67  if (false === strpos($path, '/')) {
68  if (is_dir($ts->path_basic . '/' . $path)) {
69  $path = $ts->path_basic . '/' . $path;
70  } else {
71  if (is_dir($ts->path_plugin . '/' . $path)) {
72  $path = $ts->path_plugin . '/' . $path;
73  }
74 
75  }
76  }
77  $config_default = array();
78  $config_custom = array();
79  if (file_exists($path . '/config.php')) {
80  $config_default = include $path . '/config.php';
81  }
82  if (file_exists($path . '/config.custom.php')) {
83  $config_custom = include $path . '/config.custom.php';
84  }
85  return $this->mergeConfig($config_default, $config_custom);
86  }
87 
95  function mergeConfig($config_default, $config_custom)
96  {
97  if (is_array($config_custom)) {
98  foreach ($config_custom as $key => $val) {
99  if (is_array($config_default[$key])) {
100  $config_default[$key] = $this->mergeConfig($config_default[$key], $config_custom[$key]);
101  } else {
102  $config_default[$key] = $val;
103  }
104  }
105  }
106  return $config_default;
107  }
108 
114  function encode()
115  {
116  return array();
117  }
118 
124  function decode()
125  {
126  return null;
127  }
128 }
129 
143 {
148  var $smileys = array();
149 
153 
158  var $text = "";
159  var $patterns = array();
160  var $replacements = array();
161 
164 
165  var $config;
166 
167  function __construct()
168  {
169  $this->path_basic = XOOPS_ROOT_PATH . '/class/textsanitizer';
170  $this->path_plugin = XOOPS_ROOT_PATH . '/Frameworks/textsanitizer';
171  $this->config = $this->loadConfig();
172  }
173 
184  function MyTextSanitizer()
185  {
186  $this->__construct();
187  }
188 
195  function loadConfig($name = null)
196  {
197  if (!empty($name)) {
199  }
200  $config_default = include $this->path_basic . '/config.php';
201  $config_custom = array();
202  if (file_exists($file = $this->path_basic . '/config.custom.php')) {
203  $config_custom = include $file;
204  }
205  return $this->mergeConfig($config_default, $config_custom);
206  }
207 
215  function mergeConfig($config_default, $config_custom)
216  {
217  if (is_array($config_custom)) {
218  foreach ($config_custom as $key => $val) {
219  if (isset($config_default[$key]) && is_array($config_default[$key])) {
220  $config_default[$key] = $this->mergeConfig($config_default[$key], $config_custom[$key]);
221  } else {
222  $config_default[$key] = $val;
223  }
224  }
225  }
226  return $config_default;
227  }
228 
236  static function getInstance()
237  {
238  static $instance;
239  if (!isset($instance)) {
240  $instance = new MyTextSanitizer();
241  }
242  return $instance;
243  }
244 
251  function getSmileys($isAll = true)
252  {
253  if (count($this->smileys) == 0) {
255  if ($getsmiles = $xoopsDB->query('SELECT * FROM ' . $xoopsDB->prefix('smiles'))) {
256  while ($smiles = $xoopsDB->fetchArray($getsmiles)) {
257  array_push($this->smileys, $smiles);
258  }
259  }
260  }
261  if ($isAll) {
262  return $this->smileys;
263  }
264 
265  $smileys = array();
266  foreach($this->smileys as $smile) {
267  if (empty($smile['display'])) {
268  continue;
269  }
270  $smileys[] = $smile;
271  }
272  return $smileys;
273  }
274 
281  function smiley($message)
282  {
283  $smileys = $this->getSmileys();
284  foreach($smileys as $smile) {
285  $message = str_replace($smile['code'], '<img class="imgsmile" src="' . XOOPS_UPLOAD_URL . '/' . htmlspecialchars($smile['smile_url']) . '" alt="" />', $message);
286  }
287  return $message;
288  }
289 
296  function makeClickable(&$text) {
297  $valid_chars = "a-z0-9\/\-_+=.~!%@?#&;:$\|";
298  $end_chars = "a-z0-9\/\-_+=~!%@?#&;:$\|";
299 
300  $patterns = array();
301  $replacements = array();
302 
303  $patterns[] = "/(^|[^]_a-z0-9-=\"'\/])([a-z]+?):\/\/([{$valid_chars}]+[{$end_chars}])/ei";
304  $replacements[] = "'\\1<a href=\"\\2://\\3\" title=\"\\2://\\3\" rel=\"external\">\\2://'.MyTextSanitizer::truncate( '\\3' ).'</a>'";
305 
306  $patterns[] = "/(^|[^]_a-z0-9-=\"'\/:\.])www\.((([a-zA-Z0-9\-]*\.){1,}){1}([a-zA-Z]{2,6}){1})((\/([a-zA-Z0-9\-\._\?\,\'\/\\+&%\$#\=~])*)*)/ei";
307  $replacements[] = "'\\1<a href=\"http://www.\\2\\6\" title=\"www.\\2\\6\" rel=\"external\">'.MyTextSanitizer::truncate( 'www.\\2\\6' ).'</a>'";
308 
309  $patterns[] = "/(^|[^]_a-z0-9-=\"'\/])ftp\.([a-z0-9\-]+)\.([{$valid_chars}]+[{$end_chars}])/ei";
310  $replacements[] = "'\\1<a href=\"ftp://ftp.\\2.\\3\" title=\"ftp.\\2.\\3\" rel=\"external\">'.MyTextSanitizer::truncate( 'ftp.\\2.\\3' ).'</a>'";
311 
312  $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";
313  $replacements[] = "'\\1<a href=\"mailto:\\2@\\3\" title=\"\\2@\\3\">'.MyTextSanitizer::truncate( '\\2@\\3' ).'</a>'";
314 
315  $text = preg_replace($patterns, $replacements, $text);
316  return $text;
317  }
318 
325  function truncate($text)
326  {
327  $instance =& MyTextSanitizer::getInstance();
328  if (empty($text) || empty($instance->config['truncate_length']) || strlen($text) < $instance->config['truncate_length']) {
329  return $text;
330  }
331  $len = floor($instance->config['truncate_length'] / 2);
332  $ret = substr($text, 0, $len) . ' ... ' . substr($text, 5 - $len);
333  return $ret;
334  }
335 
344  function &xoopsCodeDecode(&$text, $allowimage = 1)
345  {
346  $patterns = array();
347  $replacements = array();
348  $patterns[] = "/\[siteurl=(['\"]?)([^\"'<>]*)\\1](.*)\[\/siteurl\]/sU";
349  $replacements[] = '<a href="' . XOOPS_URL . '/\\2" title="">\\3</a>';
350  $patterns[] = "/\[url=(['\"]?)(http[s]?:\/\/[^\"'<>]*)\\1](.*)\[\/url\]/sU";
351  $replacements[] = '<a href="\\2" rel="external" title="">\\3</a>';
352  $patterns[] = "/\[url=(['\"]?)(ftp?:\/\/[^\"'<>]*)\\1](.*)\[\/url\]/sU";
353  $replacements[] = '<a href="\\2" rel="external" title="">\\3</a>';
354  $patterns[] = "/\[url=(['\"]?)([^'\"<>]*)\\1](.*)\[\/url\]/sU";
355  $replacements[] = '<a href="http://\\2" rel="external" title="">\\3</a>';
356  $patterns[] = "/\[color=(['\"]?)([a-zA-Z0-9]*)\\1](.*)\[\/color\]/sU";
357  $replacements[] = '<span style="color: #\\2;">\\3</span>';
358  $patterns[] = "/\[size=(['\"]?)([a-z0-9-]*)\\1](.*)\[\/size\]/sU";
359  $replacements[] = '<span style="font-size: \\2;">\\3</span>';
360  $patterns[] = "/\[font=(['\"]?)([^;<>\*\(\)\"']*)\\1](.*)\[\/font\]/sU";
361  $replacements[] = '<span style="font-family: \\2;">\\3</span>';
362  $patterns[] = "/\[email]([^;<>\*\(\)\"']*)\[\/email\]/sU";
363  $replacements[] = '<a href="mailto:\\1" title="">\\1</a>';
364 
365  $patterns[] = "/\[b](.*)\[\/b\]/sU";
366  $replacements[] = '<strong>\\1</strong>';
367  $patterns[] = "/\[i](.*)\[\/i\]/sU";
368  $replacements[] = '<em>\\1</em>';
369  $patterns[] = "/\[u](.*)\[\/u\]/sU";
370  $replacements[] = '<u>\\1</u>';
371  $patterns[] = "/\[d](.*)\[\/d\]/sU";
372  $replacements[] = '<del>\\1</del>';
373  $patterns[] = "/\[center](.*)\[\/center\]/sU";
374  $replacements[] = '<div style="text-align: center;">\\1</div>';
375  $patterns[] = "/\[left](.*)\[\/left\]/sU";
376  $replacements[] = '<div style="text-align: left;">\\1</div>';
377  $patterns[] = "/\[right](.*)\[\/right\]/sU";
378  $replacements[] = '<div style="text-align: right;">\\1</div>';
379 
380  $this->text = $text;
381  $this->patterns = $patterns;
382  $this->replacements = $replacements;
383 
384  $this->config['allowimage'] = $allowimage;
385  $this->executeExtensions();
386 
387  $text = preg_replace($this->patterns, $this->replacements, $this->text);
388  $text = $this->quoteConv($text);
389  return $text;
390  }
391 
398  function quoteConv($text)
399  {
400  //look for both open and closing tags in the correct order
401  $pattern = "/\[quote](.*)\[\/quote\]/sU";
402  $replacement = _QUOTEC . '<div class="xoopsQuote"><blockquote>\\1</blockquote></div>';
403 
404  $text = preg_replace($pattern, $replacement, $text, -1, $count);
405  //no more matches, return now
406  if (!$count) {
407  return $text;
408  }
409  //new matches could have been created, keep doing it until we have no matches
410  return $this->quoteConv($text);
411  }
412 
418  function filterXss($text)
419  {
420  $patterns = array();
421  $replacements = array();
422  $text = str_replace("\x00", "", $text);
423  $c = "[\x01-\x1f]*";
424  $patterns[] = "/\bj{$c}a{$c}v{$c}a{$c}s{$c}c{$c}r{$c}i{$c}p{$c}t{$c}[\s]*:/si";
425  $replacements[] = "javascript;";
426  $patterns[] = "/\ba{$c}b{$c}o{$c}u{$c}t{$c}[\s]*:/si";
427  $replacements[] = "about;";
428  $patterns[] = "/\bx{$c}s{$c}s{$c}[\s]*:/si";
429  $replacements[] = "xss;";
430  $text = preg_replace($patterns, $replacements, $text);
431  return $text;
432  }
433 
440  function nl2Br($text)
441  {
442  return preg_replace('/(\015\012)|(\015)|(\012)/', '<br />', $text);
443  }
444 
451  function addSlashes($text)
452  {
453  if (!get_magic_quotes_gpc()) {
454  $text = addslashes($text);
455  }
456  return $text;
457  }
458 
466  {
467  if (get_magic_quotes_gpc()) {
468  $text = stripslashes($text);
469  }
470  return $text;
471  }
472 
482  function htmlSpecialChars($text, $quote_style = ENT_QUOTES, $charset = null, $double_encode = true)
483  {
484  if (version_compare(phpversion(), '5.2.3', '>=')) {
485  $text = htmlspecialchars($text, $quote_style, $charset ? $charset : (defined('_CHARSET') ? _CHARSET : 'UTF-8'), $double_encode);
486  } else {
487  $text = htmlspecialchars($text, $quote_style);
488  }
489  return preg_replace(array('/&amp;/i' , '/&nbsp;/i'), array('&' , '&amp;nbsp;'), $text);
490  }
491 
499  {
500  return preg_replace(array('/&gt;/i' , '/&lt;/i' , '/&quot;/i' , '/&#039;/i' , '/&amp;nbsp;/i'), array('>' , '<' , '"' , '\'' , "&nbsp;"), $text);
501  }
502 
514  function &displayTarea($text, $html = 0, $smiley = 1, $xcode = 1, $image = 1, $br = 1)
515  {
516  $charset = (defined('_CHARSET') ? _CHARSET : 'UTF-8');
517  $text = mb_convert_encoding($text, $charset, mb_detect_encoding($text,$charset.', ISO-8859-1', true));
518  if ($html != 1) {
519  // html not allowed
520  $text = $this->htmlSpecialChars($text,ENT_COMPAT,$charset);
521  }
522  $text = $this->codePreConv($text, $xcode); // Ryuji_edit(2003-11-18)
523  if ($smiley != 0) {
524  // process smiley
525  $text = $this->smiley($text);
526  }
527  if ($xcode != 0) {
528  // decode xcode
529  if ($image != 0) {
530  // image allowed
531  $text = $this->xoopsCodeDecode($text);
532  } else {
533  // image not allowed
534  $text = $this->xoopsCodeDecode($text, 0);
535  }
536  }
537  if ($br != 0) {
538  $text = $this->nl2Br($text);
539  }
540  $text = $this->codeConv($text, $xcode);
541  $text = $this->makeClickable($text);
542  if (!empty($this->config['filterxss_on_display'])) {
543  $text = $this->filterXss($text);
544  }
545  return $text;
546  }
547 
559  function &previewTarea($text, $html = 0, $smiley = 1, $xcode = 1, $image = 1, $br = 1)
560  {
561  $text = $this->stripSlashesGPC($text);
562  $text = $this->displayTarea($text, $html, $smiley, $xcode, $image, $br);
563  return $text;
564  }
565 
573  function &censorString(&$text)
574  {
575  $ret = $this->executeExtension('censor', $text);
576  if ($ret === false) {
577  return $text;
578  }
579  return $ret;
580  }
581 
589  function codePreConv($text, $xcode = 1)
590  {
591  if ($xcode != 0) {
592  $patterns = "/\[code([^\]]*?)\](.*)\[\/code\]/esU";
593  $replacements = "'[code\\1]'.base64_encode('\\2').'[/code]'";
594  $text = preg_replace($patterns, $replacements, $text);
595  }
596  return $text;
597  }
598 
606  function codeConv($text, $xcode = 1)
607  {
608  if (empty($xcode)) {
609  return $text;
610  }
611  $patterns = "/\[code([^\]]*?)\](.*)\[\/code\]/esU";
612  $replacements = "'<div class=\"xoopsCode\">'.\$this->executeExtension('syntaxhighlight', str_replace('\\\"', '\"', base64_decode('$2')), '$1').'</div>'";
613  $text = preg_replace($patterns, $replacements, $text);
614  return $text;
615  }
616 
622  function executeExtensions()
623  {
624  $extensions = array_filter($this->config['extensions']);
625  if (empty($extensions)) {
626  return true;
627  }
628  foreach (array_keys($extensions) as $extension) {
629  $this->executeExtension($extension);
630  }
631  }
632 
639  function loadExtension($name)
640  {
641  if (file_exists($file = $this->path_basic . '/' . $name . '/' . $name . '.php')) {
642  include_once $file;
643  } else if (file_exists($file = $this->path_plugin . '/' . $name . '/' . $name . '.php')) {
644  include_once $file;
645  } else {
646  return false;
647  }
648  $class = 'Myts' . ucfirst($name);
649  if (!class_exists($class)) {
650  trigger_error("Extension '{$name}' does not exist", E_USER_WARNING);
651  return false;
652  }
653  $extension = null;
654  $extension = new $class($this);
655  return $extension;
656  }
657 
664  function executeExtension($name)
665  {
666  $extension = $this->loadExtension($name);
667  $args = array_slice(func_get_args(), 1);
668  return call_user_func_array(array($extension , 'load'), array_merge(array(&$this), $args));
669  }
670 
679  function textFilter($text, $force = false)
680  {
681  $ret = $this->executeExtension('textfilter', $text, $force);
682  if ($ret === false) {
683  return $text;
684  }
685  return $ret;
686  }
687  // #################### Deprecated Methods ######################
701  function codeSanitizer($str, $image = 1)
702  {
703  $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . "::" . __FUNCTION__ . ' is deprecated');
704  $str = $this->htmlSpecialChars(str_replace('\"', '"', base64_decode($str)));
705  $str = $this->xoopsCodeDecode($str, $image);
706  return $str;
707  }
708 
718  function sanitizeForDisplay($text, $allowhtml = 0, $smiley = 1, $bbcode = 1)
719  {
720  $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . "::" . __FUNCTION__ . ' is deprecated');
721  if ($allowhtml == 0) {
722  $text = $this->htmlSpecialChars($text);
723  } else {
724  // $config =& $GLOBALS['xoopsConfig'];
725  // $allowed = $config['allowed_html'];
726  // $text = strip_tags($text, $allowed);
727  $text = $this->makeClickable($text);
728  }
729  if ($smiley == 1) {
730  $text = $this->smiley($text);
731  }
732  if ($bbcode == 1) {
733  $text = $this->xoopsCodeDecode($text);
734  }
735  $text = $this->nl2Br($text);
736  return $text;
737  }
738 
748  function sanitizeForPreview($text, $allowhtml = 0, $smiley = 1, $bbcode = 1)
749  {
750  $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . "::" . __FUNCTION__ . ' is deprecated');
751  $text = $this->oopsStripSlashesGPC($text);
752  if ($allowhtml == 0) {
753  $text = $this->htmlSpecialChars($text);
754  } else {
755  // $config =& $GLOBALS['xoopsConfig'];
756  // $allowed = $config['allowed_html'];
757  // $text = strip_tags($text, $allowed);
758  $text = $this->makeClickable($text);
759  }
760  if ($smiley == 1) {
761  $text = $this->smiley($text);
762  }
763  if ($bbcode == 1) {
764  $text = $this->xoopsCodeDecode($text);
765  }
766  $text = $this->nl2Br($text);
767  return $text;
768  }
769 
777  {
778  $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . "::" . __FUNCTION__ . ' is deprecated');
779  // $text = $this->undoHtmlSpecialChars($text);
780  return $this->addSlashes($text);
781  }
782 
790  function makeTboxData4Show($text, $smiley = 0)
791  {
792  $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . "::" . __FUNCTION__ . ' is deprecated');
793  $text = $this->htmlSpecialChars($text);
794  return $text;
795  }
796 
804  {
805  $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . "::" . __FUNCTION__ . ' is deprecated');
806  return $this->htmlSpecialChars($text);
807  }
808 
816  function makeTboxData4Preview($text, $smiley = 0)
817  {
818  $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . "::" . __FUNCTION__ . ' is deprecated');
819  $text = $this->stripSlashesGPC($text);
820  $text = $this->htmlSpecialChars($text);
821  return $text;
822  }
823 
831  {
832  $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . "::" . __FUNCTION__ . ' is deprecated');
833  $text = $this->stripSlashesGPC($text);
834  return $this->htmlSpecialChars($text);
835  }
836 
844  {
845  $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . "::" . __FUNCTION__ . ' is deprecated');
846  return $this->addSlashes($text);
847  }
848 
858  function &makeTareaData4Show(&$text, $html = 1, $smiley = 1, $xcode = 1)
859  {
860  $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . "::" . __FUNCTION__ . ' is deprecated');
861  $text = $this->displayTarea($text, $html, $smiley, $xcode);
862  return $text;
863  }
864 
872  {
873  $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . "::" . __FUNCTION__ . ' is deprecated');
874  return $this->htmlSpecialChars($text);
875  }
876 
886  function &makeTareaData4Preview(&$text, $html = 1, $smiley = 1, $xcode = 1)
887  {
888  $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . "::" . __FUNCTION__ . ' is deprecated');
889  $text = $this->previewTarea($text, $html, $smiley, $xcode);
890  return $text;
891  }
892 
900  {
901  $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . "::" . __FUNCTION__ . ' is deprecated');
902  // if magic_quotes_gpc is on, do stipslashes
903  $text = $this->stripSlashesGPC($text);
904  return $this->htmlSpecialChars($text);
905  }
906 
914  {
915  $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . "::" . __FUNCTION__ . ' is deprecated');
916  return $this->htmlSpecialChars($text);
917  }
918 
926  {
927  $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . "::" . __FUNCTION__ . ' is deprecated');
928  return $this->stripSlashesGPC($text);
929  }
930 
938  {
939  $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . "::" . __FUNCTION__ . ' is deprecated');
940  if (get_magic_quotes_runtime()) {
941  $text = stripslashes($text);
942  }
943  return $text;
944  }
945 
953  {
954  $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . "::" . __FUNCTION__ . ' is deprecated');
955  return $this->addSlashes($text);
956  }
957 
965  {
966  $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . "::" . __FUNCTION__ . ' is deprecated');
967  return $this->htmlSpecialChars($text);
968  }
969 
976  function oopsNl2Br($text)
977  {
978  $GLOBALS['xoopsLogger']->addDeprecated(__CLASS__ . "::" . __FUNCTION__ . ' is deprecated');
979  return $this->nl2br($text);
980  }
981 }
982 
983 ?>