<?php
//v1.0.4 www.bcoos.net 2006/10 GPL
//v1.3 www.exoops.info 2006/03 
// $Id: module.textsanitizer.php,v 1.21 2003/08/17 18:31:15 half-dead Exp $
// ------------------------------------------------------------------------- //
//               E-Xoops: Content Management for the Masses                  //
//                       < http://www.e-xoops.com >                          //
// ------------------------------------------------------------------------- //
// Original Author: Kazumi Ono, Goghs Cheng
// Author Website : http://www.mywebaddons.com/ , http://www.eqiao.com
// License Type   : GPL: See /manual/LICENSES/GPL.txt
// ------------------------------------------------------------------------- //
if (!defined("XOOPS_MYTEXTSANITIZER_INCLUDED")) {
	define("XOOPS_MYTEXTSANITIZER_INCLUDED", 1);
//---------------------------------------------------------------------------------------//
/**
* Description
*/
class MyTextSanitizer {
	var $smileys      = array();
	var $allowImage   = false;
	var $allowLibrary = false;
	var $clickable    = true;
	var $type         = 'user';
//---------------------------------------------------------------------------------------//
/**
* 0: Off, 1: Local Only, 2: Local & Distant
*
* @param type $var description
* @return type description
*/
function setAllowImage($value=0) {
	$this->allowImage = intval($value);
}
//---------------------------------------------------------------------------------------//
/**
* 0: Off, 1: Local Only, 2: Local & Distant
*
* @param type $var description
* @return type description
*/
function setAllowLibrary($value=0) {
	$this->allowLibrary = intval($value);
}
//---------------------------------------------------------------------------------------//
/**
* Description
*
* @param type $var description
* @return type description
*/
function setClickable($value=true) {
	$this->clickable = (bool)$value;
}
//---------------------------------------------------------------------------------------//
/**
* Description
*
* @param type $var description
* @return type description
*/
function setType($value='user') {
	$this->type = $value;
}
//---------------------------------------------------------------------------------------//
/**
* Description
*
* @param type $var description
* @return type description
*/
function smiley($message) {
global $db;
if (count($this->smileys) == 0) {
	if ( $getsmiles = $db->query("SELECT code, smile_url FROM ".$db->prefix("smiles")) ) {
		while ($smiles = $db->fetchArray($getsmiles)) {
			$message = str_replace($smiles['code'], '<img src="'.formatURL(XOOPS_URL.'/images/smilies/', $smiles['smile_url']).'" alt="'.$smiles['code'].'" />', $message);
			array_push($this->smileys, $smiles);
		}
	}
	} else {
		foreach ($this->smileys as $smiles) {
			$message = str_replace($smiles['code'], '<img src="'.formatURL(XOOPS_URL.'/images/smilies/', $smiles['smile_url']).'" alt="'.$smiles['code'].'" />', $message);
		}
	}
return $message;
}
//---------------------------------------------------------------------------------------//
/**
* Description
*
* @param type $var description
* @return type description
*/
function desmile($message) {
global $db;
if (count($this->smileys) == 0) {
	if ( $getsmiles = $db->query("SELECT * FROM ".$db->prefix("smiles")) ) {
		while ($smiles = $db->fetchArray($getsmiles)) {
			$message = str_replace("<img src='".formatURL(XOOPS_URL.'/images/smilies/', $smiles['smile_url'])."' />", $smiles['code'], $message);
			array_push($this->smileys, $smiles);
		}
	}
	} else {
		foreach ($this->smileys as $smiles) {
			$message = str_replace("<img src='".formatURL(XOOPS_URL.'/images/smilies/', $smiles['smile_url'])."' />", $smiles['code'], $message);
		}
	}
return $message;
}
//---------------------------------------------------------------------------------------//
/**
* Description
*
* @param type $var description
* @return type description
*/
function makeClickable($text) {
$find    = array();
$replace = array();
$text    = " ".$text;
$find[]    = "/([\n ])([a-z0-9]+?):\/\/([^, \n\r]+)/i";
$replace[] = "\\1<a href=\"\\2://\\3\" >\\2://\\3</a>";
$find[]    = "/([\n ])www\.([a-z0-9\-]+)\.([a-z0-9\-.~]+)((?:\/[^, \n\r]*)?)/i";
$replace[] = "\\1<a href=\"http://www.\\2.\\3\\4\" >www.\\2.\\3\\4</a>";
$find[]    = "/([\n ])ftp\.([a-z0-9\-]+)\.([a-z0-9\-.~]+)((?:\/[^, \n\r]*)?)/i";
$replace[] = "\\1<a href=\"ftp://ftp.\\2.\\3\\4\" >ftp.\\2.\\3\\4</a>";
$find[]    = "/([\n ])([a-z0-9\-_.]+?)@([^, \n\r]+)/i";
$replace[] = "\\1<a href=\"mailto:\\2@\\3\">\\2@\\3</a>";
$text = preg_replace($find, $replace, $text);
return trim($text);
}
//---------------------------------------------------------------------------------------//
/**
* Description
*
* @param type $var description
* @return type description
*/
function xoopsCodeDecode($text, $allow_html=0) {
$patterns     = array();
$replacements = array();
$replacement  = "'"._CODEC."<div class=\"xoopsCode\"><pre width=\"80\">'.";
if ($allow_html == 1) {
	$patterns[]     = "/\[enc_code](.*)\[\/enc_code\]/esU";
	$replacement   .= "htmlspecialchars(base64_decode('\\1'), ENT_QUOTES)";
	} else {
		$patterns[]     = "/\[enc_code](.*)\[\/enc_code\]/esU";
		$replacement   .= "base64_decode('\\1')";
	}
$replacement   .= ".'</pre></div>'";
$replacements[] = $replacement;
$patterns[]     = "/\[quote](.*)\[\/quote\]/sU";
$replacements[] = _QUOTEC.'<div class="xoopsQuote">\\1</div>';
$patterns[]     = "/\[url=(['\"]?)(http[s]?:\/\/[^\"']*)\\1](.*)\[\/url\]/sU";
$replacements[] = '<a href="\\2" >\\3</a>';
$patterns[]     = "/\[url=(['\"]?)([^\"']*)\\1](.*)\[\/url\]/sU";
$replacements[] = '<a href="http://\\2" >\\3</a>';
$patterns[]     = "/\[color=(['\"]?)([^\"']*)\\1](.*)\[\/color\]/sU";
$replacements[] = '<span style="color: #\\2;">\\3</span>';
$patterns[]     = "/\[size=(['\"]?)([^\"']*)\\1](.*)\[\/size\]/sU";
$replacements[] = '<span style="font-size: \\2;">\\3</span>';
$patterns[]     = "/\[font=(['\"]?)([^\"']*)\\1](.*)\[\/font\]/sU";
$replacements[] = '<span style="font-family: \\2;">\\3</span>';
$patterns[]     = "/\[email]([^\"']*)\[\/email\]/sU";
$replacements[] = '<a href="mailto:\\1">\\1</a>';
$patterns[]     = "/\[b](.*)\[\/b\]/sU";
$replacements[] = '<b>\\1</b>';
$patterns[]     = "/\[i](.*)\[\/i\]/sU";
$replacements[] = '<i>\\1</i>';
$patterns[]     = "/\[u](.*)\[\/u\]/sU";
$replacements[] = '<u>\\1</u>';
if ( $this->allowImage == true || ($this->type == 'admin') ) {
	$patterns[] = "/\[img align=(['\"]?)(left|right)\\1]([^\"\(\)\?\&']*)\[\/img\]/sU";
	$replacements[] = '<img src="\\3" align="\\2" alt="" />';
	$patterns[] = "/\[img]([^\"\(\)\?\&']*)\[\/img\]/sU";
	$replacements[] = '<img src="\\1" alt="" />';
	} else {
		$patterns[]     = "/\[img align=(['\"]?)(left|right)\\1]([^\"\(\)\?\&']*)\[\/img\]/esU";
		$replacements[] = "'<a href=\"\\3\">'.basename('\\3').'</a>'";
		$patterns[]     = "/\[img]([^\"\(\)\?\&']*)\[\/img\]/esU";
		$replacements[] = "'<a href=\"\\1\">'.basename('\\1').'</a>'";
	}
if ( ($this->allowLibrary == true) || ($this->type == 'admin') ) {
	$patterns[]     = "/\[lib align=(['\"]?)(left|right)\\1]([^\"\(\)\?\&']*)\[\/lib\]/esU";
	$replacements[] = "'<img src=\"'.formatURL(XOOPS_URL.'/images/library/', '\\3').'\" align=\"\\2\" alt=\"\" border=\"0\" />'";
	$patterns[]     = "/\[lib]([^\"\(\)\?\&']*)\[\/lib\]/esU";
	$replacements[] = "'<img src=\"'.formatURL(XOOPS_URL.'/images/library/', '\\1').'\" alt=\"\" border=\"0\" />'";
}
$text = preg_replace($patterns, $replacements, $text);
return $text;
}
//---------------------------------------------------------------------------------------//
/**
* Replaces banned words in a string with their replacements
*/
function censorString($text='') {
global $xoopsBadWords;
return $text;
if ( !empty($text) && is_array($xoopsBadWords) && !empty($xoopsBadWords) ) {
	foreach ($xoopsBadWords as $pattern) {
		$words = @explode('[split]', $pattern);
		$find  = trim($words[0]);
		if ( !empty($find) ) {
			$text = preg_replace($find, $words[1], $text);
			if ($text) {
				return $text;
			}
		}
	}
}
return $text;
}
//---------------------------------------------------------------------------------------//
/**
* Filters both textbox and textarea form data before display
* For internal use
*/
function sanitizeForDisplay($text, $allow_html=0, $allow_smileys=1, $allow_bbcode=1) {
$text = $this->oopsStripSlashesRT($text);
if ($allow_html == 0) {
	$text = $this->oopsHtmlSpecialChars($text);
	if ($allow_bbcode == 1) {
		$search[]  = "/\[code](.*)\[\/code\]/esU";
		$replace[] = "'[enc_code]'.base64_encode(stripslashes('\\1')).'[/enc_code]'";
	}
	$search[]  = "/&amp;/i";
	$replace[] = "&";
	$text      = preg_replace($search, $replace, $text);
	} else {
		if ($allow_bbcode == 1) {
			$search[]  = "/\[code](.*)\[\/code\]/esU";
			$replace[] = "'[enc_code]'.base64_encode(stripslashes('\\1')).'[/enc_code]'";
			$text      = preg_replace($search, $replace, $text);
		}
		$text = $this->escapeTags($text, $this->type);
	}
if ($this->clickable) {
	$text = $this->makeClickable($text);
}
if ($allow_smileys == 1) {
	$text = $this->smiley($text);
}
if ($allow_bbcode == 1) {
	$text = $this->xoopsCodeDecode($text, $allow_html);
}
if ($allow_html != 2) {
	$text = $this->oopsNl2Br($text);
}
$text = $this->censorString($text);
$this->setType('user');
return $text;
}
//---------------------------------------------------------------------------------------//
/**
* Filters both textbox and textarea form data before preview
* For internal use
*/
function sanitizeForPreview($text, $allow_html=0, $allow_smileys=1, $allow_bbcode=1) {
global $bcoosConfig, $xoopsUser;
$text = $this->oopsStripSlashesGPC($text);
if ($allow_html == 0) {
	$text = $this->oopsHtmlSpecialChars($text);
	if ($allow_bbcode == 1) {
		$search[]  = "/\[code](.*)\[\/code\]/esU";
		$replace[] = "'[enc_code]'.base64_encode(stripslashes('\\1')).'[/enc_code]'";
	}
	$search[]  = "/&amp;/i";
	$replace[] = "&";
	$text      = preg_replace($search, $replace, $text);
	} else {
		if ($allow_bbcode == 1) {
			$search[]  = "/\[code](.*)\[\/code\]/esU";
			$replace[] = "'[enc_code]'.base64_encode(stripslashes('\\1')).'[/enc_code]'";
			$text      = preg_replace($search, $replace, $text);
		}
		$text      = $this->escapeTags($text, $this->type);
	}
if ($this->clickable) {
	$text = $this->makeClickable($text);
}
if ($allow_smileys == 1) {
	$text = $this->smiley($text);
}
if ($allow_bbcode == 1) {
	$text = $this->xoopsCodeDecode($text, $allow_html);
}
if ($allow_html != 2) {
	$text = $this->oopsNl2Br($text);
}
$this->setType('user');
return $text;
}
//---------------------------------------------------------------------------------------//
/**
* Called before displaying textarea form data from DB
*/
function makeTareaData4Show($text, $allow_html=1, $allow_smileys=0, $allow_bbcode=0) {
$text = $this->sanitizeForDisplay($text, $allow_html, $allow_smileys, $allow_bbcode);
return $text;
}
//---------------------------------------------------------------------------------------//
/**
*  Used for displaying textbox form data from DB.
*  Smilies can also be used.
*/
function makeTboxData4Show($text, $allow_smileys=0) {
$this->setClickable(false);
$text = $this->sanitizeForDisplay($text, 0, $allow_smileys, 0);
$this->setClickable(true);
return $text;
}
//---------------------------------------------------------------------------------------//
/**
* Called when previewing textarea data which was submitted via an html form
*/
function makeTareaData4Preview($text, $allow_html=1, $allow_smileys=0, $allow_bbcode=0) {
$text = $this->sanitizeForPreview($text, $allow_html, $allow_smileys, $allow_bbcode);
return $text;
}
//---------------------------------------------------------------------------------------//
/**
*  Called when previewing textbox form data submitted from a form.
*  Smilies can be used if needed
*  Use makeTboxData4PreviewInForm when textbox data is to be previewed in textbox again
*/
function makeTboxData4Preview($text, $allow_smileys=0) {
$this->setClickable(false);
$text = $this->sanitizeForPreview($text, 0, $allow_smileys, 0);
$this->setClickable(true);
return $text;
}
//---------------------------------------------------------------------------------------//
/**
*  Called when previewing textarea data whih was submitted via an html form.
*  This time, text area data is inserted into textarea again
*/
function makeTboxData4PreviewInForm($text) {
$text = $this->oopsStripSlashesGPC($text);
$text = $this->oopsHtmlSpecialChars($text);
return $text;
}
/**
* Depracted (Reason: double entry)
* Use: makeTboxData4PreviewInForm();
*/
function makeTareaData4PreviewInForm($text) {
$text = $this->makeTboxData4PreviewInForm($text);
return $text;
}
//---------------------------------------------------------------------------------------//
/**
*  Called before saving first-time or editted textarea
*  data into DB
*  Used for saving textbox form data.
*  Adds slashes if magic_quotes_gpc is off.
*/
function makeTboxData4Save($text) {
$text = $this->oopsAddSlashesGPC($text);
return $text;
}
/**
* Depracted (Reason: double entry)
* Use: makeTboxData4Save();
*/
function makeTareaData4Save($text) {
$text = $this->makeTboxData4Save($text);
return $text;
}
//---------------------------------------------------------------------------------------//
/**
*  Use this function when you need to output textarea value inside
*  quotes. For example, meta keywords are saved as textarea value
*  but it is displayed inside <meta> tag keywords attribute with
*  quotes around it. This can be also used for textbox values.
*  Called when textarea data in DB is to be editted in html form
*  Used when textbox data in DB is to be editted in html form.
*  "&amp;" must be converted back to "&" to maintain the correct
*  ISO encoding values, which is needed for some multi-bytes chars.
*/
function makeTboxData4Edit($text) {
$text = $this->oopsHtmlSpecialChars($text);
return $text;
}
/**
* Depracted (Reason: double entry)
* Use: makeTboxData4Edit();
*/
function makeTareaData4InsideQuotes($text) {
$text = $this->makeTboxData4Edit($text);
return $text;
}
/**
* Depracted (Reason: double entry)
* Use: makeTboxData4Edit();
*/
function makeTareaData4Edit($text) {
$text = $this->makeTboxData4Edit($text);
return $text;
}
//---------------------------------------------------------------------------------------//
/**
* if magic_quotes_gpc is off, add back slashes
*/
function oopsAddSlashesGPC($text) {
if ( !get_magic_quotes_gpc() ) {
	$text = addslashes($text);
}
return $text;
}
/**
* Depracted (Reason: Misleading because no GPC in name)
* Use: oopsAddSlashesGPC() / oopsAddSlashesRT depending on need
*/
function oopsAddSlashes($text) {
$text = $this->addslashesGPC($text);
return $text;
}
//---------------------------------------------------------------------------------------//
/**
* if magic_quotes_gpc is on, strip back slashes
*/
function oopsStripSlashesGPC($text) {
if ( get_magic_quotes_gpc() ) {
	$text = stripslashes($text);
}
return $text;
}
//---------------------------------------------------------------------------------------//
/**
* If magic_quotes_runtime is on, strip back slashes
* This is pretty much a php legacy feature
*/
function oopsStripSlashesRT($text) {
if ( get_magic_quotes_runtime() ) {
	$text = stripslashes($text);
}
return $text;
}
//---------------------------------------------------------------------------------------//
/**
* If magic_quotes_runtime is off, add back slashes
* This is pretty much a php legacy feature,
* But can be usefull when copying data from 1 db table to another
*/
function oopsAddSlashesRT($text) {
if ( !get_magic_quotes_runtime() ) {
	$text = addslashes($text);
}
return $text;
}
//---------------------------------------------------------------------------------------//
/**
* Converts newlines to br's
*
* @param type $var description
* @return type description
*/
function oopsNl2Br($text) {
$find[]    = "/(\015\012)|(\015)|(\012)/";
$replace[] = "<br />";
$text      = preg_replace($find, $replace, $text);
return $text;
}
//---------------------------------------------------------------------------------------//
/**
* Takes a string, and does the reverse of the PHP standard function
* HtmlSpecialChars().
* Original Name : undo_htmlspecialchars
*/
function undoHtmlSpecialChars($text) {
$text = preg_replace("/&amp;/i" , "&", $text);
$text = preg_replace("/&gt;/i"  , ">", $text);
$text = preg_replace("/&lt;/i"  , "<", $text);
$text = preg_replace("/&quot;/i", '"', $text);
$text = str_replace("&#039;"    , "'", $text);
return $text;
}
//---------------------------------------------------------------------------------------//
/**
*  htmlspecialchars will not convert single quotes by default,
*  so i made this function.
*/
function oopsHtmlSpecialChars($text) {
$text = htmlspecialchars($text, ENT_QUOTES);
return $text;
}
//---------------------------------------------------------------------------------------//
/**
* Escapes non-allowed html tags
*
* @param string $text Text to be processed
* @param string $type Which types of tags to allow
* @return string Escaped text
*/
function escapeTags($text, $type='user') {
global $bcoosConfig;
if ($type == 'admin') {
	$html_tags = $bcoosConfig['admin_html'];
	} else {
		$html_tags = $bcoosConfig['user_html'];
	}
$search[]  = "'(<)+(/?\S+>?)'U";
$replace[] = "&lt;\\2";
if ( !empty($html_tags) ) {
	$search[]  = "'(&lt;)+(/?\b(($html_tags){1})\b>?)'i";
	$replace[] = "<\\2";
}
$text = preg_replace($search, $replace, $text);
return $text;
}
//---------------------------------------------------------------------------------------//
} // END TEXTSANTISIZER
//---------------------------------------------------------------------------------------//
}
?>
