rror', '>', '"', ' & ');
// Set to TRUE or FALSE once it has been calculated
var $e_highlighting;
// Highlight query
var $e_query;
// Set up the defaults
var $e_optDefault = array(
// default context: reflects legacy settings (many items enabled)
'context' => 'OLDDEFAULT',
//
'fromadmin' => FALSE,
// Enable emote display
'emotes' => TRUE,
// Convert defines(constants) within text.
'defs' => FALSE,
// replace all {e_XXX} constants with their e107 value - 'rel' or 'abs'
'constants' => FALSE,
// Enable hooked parsers
'hook' => TRUE,
// Allow scripts through (new for 0.8)
'scripts' => TRUE,
// Make links clickable
'link_click' => TRUE,
// Substitute on clickable links (only if link_click == TRUE)
'link_replace' => TRUE,
// Parse shortcodes - TRUE enables parsing
'parse_sc' => FALSE,
// remove HTML tags.
'no_tags' => FALSE,
// Restore entity form of quotes and such to single characters - TRUE disables
'value' => FALSE,
// Line break compression - TRUE removes newline characters
'nobreak' => FALSE,
// Retain newlines - wraps to \n instead of
if TRUE (for non-HTML email text etc)
'retain_nl' => FALSE
);
// Super modifiers override default option values
var $e_SuperMods = array(
//text is part of a title (e.g. news title)
'TITLE' =>
array(
'nobreak'=>TRUE, 'retain_nl'=>TRUE, 'link_click' => FALSE, 'emotes'=>FALSE, 'defs'=>TRUE, 'parse_sc'=>TRUE
),
//text is user-entered (i.e. untrusted) and part of a title (e.g. forum title)
'USER_TITLE' =>
array(
'nobreak'=>TRUE, 'retain_nl'=>TRUE, 'link_click' => FALSE, 'scripts' => FALSE, 'emotes'=>FALSE, 'hook'=>FALSE
),
// text is 'body' of email or similar - being sent 'off-site' so don't rely on server availability
'E_TITLE' =>
array(
'nobreak'=>TRUE, 'retain_nl'=>TRUE, 'defs'=>TRUE, 'parse_sc'=>TRUE, 'emotes'=>FALSE, 'scripts' => FALSE, 'link_click' => FALSE
),
// text is part of the summary of a longer item (e.g. content summary)
'SUMMARY' =>
array(
'defs'=>TRUE, 'constants'=>'full', 'parse_sc'=>TRUE
),
// text is the description of an item (e.g. download, link)
'DESCRIPTION' =>
array(
'defs'=>TRUE, 'constants'=>'full', 'parse_sc'=>TRUE
),
// text is 'body' or 'bulk' text (e.g. custom page body, content body)
'BODY' =>
array(
'defs'=>TRUE, 'constants'=>'full', 'parse_sc'=>TRUE
),
'WYSIWYG' =>
array(
'defs'=>FALSE, 'constants'=>'full', 'parse_sc'=>FALSE, 'wysiwyg'=>TRUE
),
// text is user-entered (i.e. untrusted)'body' or 'bulk' text (e.g. custom page body, content body)
'USER_BODY' =>
array(
'constants'=>'full', 'scripts' => FALSE
),
// text is 'body' of email or similar - being sent 'off-site' so don't rely on server availability
'E_BODY' =>
array(
'defs'=>TRUE, 'constants'=>'full', 'parse_sc'=>TRUE, 'emotes'=>FALSE, 'scripts' => FALSE, 'link_click' => FALSE
),
// text is text-only 'body' of email or similar - being sent 'off-site' so don't rely on server availability
'E_BODY_PLAIN' =>
array(
'defs'=>TRUE, 'constants'=>'full', 'parse_sc'=>TRUE, 'emotes'=>FALSE, 'scripts' => FALSE, 'link_click' => FALSE, 'retain_nl' => TRUE, 'no_tags' => TRUE
),
// text is the 'content' of a link (A tag, etc)
'LINKTEXT' =>
array(
'nobreak'=>TRUE, 'retain_nl'=>TRUE, 'link_click' => FALSE, 'emotes'=>FALSE, 'hook'=>FALSE, 'defs'=>TRUE, 'parse_sc'=>TRUE
),
// text is used (for admin edit) without fancy conversions or html.
'RAWTEXT' =>
array(
'nobreak'=>TRUE, 'retain_nl'=>TRUE, 'link_click' => FALSE, 'emotes'=>FALSE, 'hook'=>FALSE, 'no_tags'=>TRUE
)
);
// Individual modifiers change the current context
var $e_Modifiers = array(
'emotes_off' => array('emotes' => FALSE),
'emotes_on' => array('emotes' => TRUE),
'no_hook' => array('hook' => FALSE),
'do_hook' => array('hook' => TRUE),
// New for 0.8
'scripts_off' => array('scripts' => FALSE),
// New for 0.8
'scripts_on' => array('scripts' => TRUE),
'no_make_clickable' => array('link_click' => FALSE),
'make_clickable' => array('link_click' => TRUE),
'no_replace' => array('link_replace' => FALSE),
// Replace text of clickable links (only if make_clickable option set)
'replace' => array('link_replace' => TRUE),
// No path replacement
'consts_off' => array('constants' => FALSE),
// Relative path replacement
'consts_rel' => array('constants' => 'rel'),
// Absolute path replacement
'consts_abs' => array('constants' => 'abs'),
// Full path replacement
'consts_full' => array('constants' => 'full'),
// No shortcode parsing
'scparse_off' => array('parse_sc' => FALSE),
'scparse_on' => array('parse_sc' => TRUE),
// Strip tags
'no_tags' => array('no_tags' => TRUE),
// Leave tags
'do_tags' => array('no_tags' => FALSE),
'fromadmin' => array('fromadmin' => TRUE),
'notadmin' => array('fromadmin' => FALSE),
// entity replacement
'er_off' => array('value' => FALSE),
'er_on' => array('value' => TRUE),
// Decode constant if exists
'defs_off' => array('defs' => FALSE),
'defs_on' => array('defs' => TRUE),
'dobreak' => array('nobreak' => FALSE),
'nobreak' => array('nobreak' => TRUE),
// Line break using \n
'lb_nl' => array('retain_nl' => TRUE),
// Line break using
'lb_br' => array('retain_nl' => FALSE),
// Legacy option names below here - discontinue later
'retain_nl' => array('retain_nl' => TRUE),
'defs' => array('defs' => TRUE),
'parse_sc' => array('parse_sc' => TRUE),
'constants' => array('constants' => 'rel'),
'value' => array('value' => TRUE),
'wysiwyg' => array('wysiwyg'=>TRUE)
);
/**
* Constructor - keep it public for backward compatibility
still some new e_parse() in the core
*
* @return void
*/
public function __construct()
{
// initialise the type of UTF-8 processing methods depending on PHP version and mb string extension
$this->initCharset();
// Preprocess the supermods to be useful default arrays with all values
foreach ($this->e_SuperMods as $key => $val)
{
// precalculate super defaults
$this->e_SuperMods[$key] = array_merge($this->e_optDefault , $this->e_SuperMods[$key]);
$this->e_SuperMods[$key]['context'] = $key;
}
}
/**
* Initialise the type of UTF-8 processing methods depending on PHP version and mb string extension.
*
* NOTE: can't be called until CHARSET is known
but we all know that it is UTF-8 now
*
* @return void
*/
private function initCharset()
{
// Start by working out what, if anything, we do about utf-8 handling.
// 'Do nothing' is the simple option
$this->utfAction = 0;
// CHARSET is utf-8
// if(strtolower(CHARSET) == 'utf-8')
// {
$this->isutf8 = TRUE;
if(version_compare(PHP_VERSION, '6.0.0') < 1)
{
// Need to do something here
if(extension_loaded('mbstring'))
{
// Check for function overloading
$temp = ini_get('mbstring.func_overload');
// Just check the string functions - will be non-zero if overloaded
if(($temp & MB_OVERLOAD_STRING) == 0)
{
// Can use the mb_string routines
$this->utfAction = 1;
}
// Set the default encoding, so we don't have to specify every time
mb_internal_encoding('UTF-8');
}
else
{
// Must use emulation - will probably be slow!
$this->utfAction = 2;
require (E_UTF8_PACK.'utils/unicode.php');
// Always load the core routines - bound to need some of them!
require (E_UTF8_PACK.'native/core.php');
}
}
// }
}
/**
* Unicode (UTF-8) analogue of standard @link http://php.net/strlen strlen PHP function.
* Returns the length of the given string.
*
* @param string $str The UTF-8 encoded string being measured for length.
* @return integer The length (amount of UTF-8 characters) of the string on success, and 0 if the string is empty.
*/
public function ustrlen($str)
{
switch($this->utfAction)
{
case 0:
return strlen($str);
case 1:
return mb_strlen($str);
}
// Default case shouldn't happen often
// Save a call - invoke the function directly
return strlen(utf8_decode($str));
}
/**
* Unicode (UTF-8) analogue of standard @link http://php.net/strtolower strtolower PHP function.
* Make a string lowercase.
*
* @param string $str The UTF-8 encoded string to be lowercased.
* @return string Specified string with all alphabetic characters converted to lowercase.
*/
public function ustrtolower($str)
{
switch($this->utfAction)
{
case 0:
return strtolower($str);
case 1:
return mb_strtolower($str);
}
// Default case shouldn't happen often
return utf8_strtolower($str);
}
/**
* Unicode (UTF-8) analogue of standard @link http://php.net/strtoupper strtoupper PHP function.
* Make a string uppercase.
*
* @param string $str The UTF-8 encoded string to be uppercased.
* @return string Specified string with all alphabetic characters converted to uppercase.
*/
public function ustrtoupper($str)
{
switch($this->utfAction)
{
case 0:
return strtoupper($str);
case 1:
return mb_strtoupper($str);
}
// Default case shouldn't happen often
return utf8_strtoupper($str);
}
/**
* Unicode (UTF-8) analogue of standard @link http://php.net/strpos strpos PHP function.
* Find the position of the first occurrence of a case-sensitive UTF-8 encoded string.
* Returns the numeric position (offset in amount of UTF-8 characters)
* of the first occurrence of needle in the haystack string.
*
* @param string $haystack The UTF-8 encoded string being searched in.
* @param integer $needle The UTF-8 encoded string being searched for.
* @param integer $offset [optional] The optional offset parameter allows you to specify which character in haystack to start searching.
* The position returned is still relative to the beginning of haystack.
* @return integer|boolean Returns the position as an integer. If needle is not found, the function will return boolean FALSE.
*/
public function ustrpos($haystack, $needle, $offset = 0)
{
switch($this->utfAction)
{
case 0:
return strpos($haystack, $needle, $offset);
case 1:
return mb_strpos($haystack, $needle, $offset);
}
return utf8_strpos($haystack, $needle, $offset);
}
/**
* Unicode (UTF-8) analogue of standard @link http://php.net/strrpos strrpos PHP function.
* Find the position of the last occurrence of a case-sensitive UTF-8 encoded string.
* Returns the numeric position (offset in amount of UTF-8 characters)
* of the last occurrence of needle in the haystack string.
*
* @param string $haystack The UTF-8 encoded string being searched in.
* @param integer $needle The UTF-8 encoded string being searched for.
* @param integer $offset [optional] - The optional offset parameter allows you to specify which character in haystack to start searching.
* The position returned is still relative to the beginning of haystack.
* @return integer|boolean Returns the position as an integer. If needle is not found, the function will return boolean FALSE.
*/
public function ustrrpos($haystack, $needle, $offset = 0)
{
switch($this->utfAction)
{
case 0:
return strrpos($haystack, $needle, $offset);
case 1:
return mb_strrpos($haystack, $needle, $offset);
}
return utf8_strrpos($haystack, $needle, $offset);
}
/**
* Unicode (UTF-8) analogue of standard @link http://php.net/substr substr PHP function.
* Returns the portion of string specified by the start and length parameters.
*
* NOTE: May be subtle differences in return values dependent on which routine is used.
* Native substr() routine can return FALSE. mb_substr() and utf8_substr() just return an empty string.
*
* @param string $str The UTF-8 encoded string.
* @param integer $start Start of portion to be returned. Position is counted in amount of UTF-8 characters from the beginning of str.
* First character's position is 0. Second character position is 1, and so on.
* @param integer $length [optional] If length is given, the string returned will contain at most length characters beginning from start
* (depending on the length of string). If length is omitted, the rest of string from start will be returned.
* @return string The extracted UTF-8 encoded part of input string.
*/
public function usubstr($str, $start, $length = NULL)
{
switch($this->utfAction)
{
case 0:
return substr($str, $start, $length);
case 1:
if(is_null($length))
{
return mb_substr($str, $start);
}
else
{
return mb_substr($str, $start, $length);
}
}
return utf8_substr($str, $start, $length);
}
/**
* Converts the supplied text (presumed to be from user input) to a format suitable for storing in a database table.
*
* @param string $data
* @param boolean $nostrip [optional] Assumes all data is GPC ($_GET, $_POST, $_COOKIE) unless indicate otherwise by setting this var to TRUE.
* If magic quotes is enabled on the server and you do not tell toDB() that the data is non GPC then slashes will be stripped when they should not be.
* @param boolean $no_encode [optional] This parameter should nearly always be FALSE. It is used by the save_prefs() function to preserve HTML content within prefs even when
* the save_prefs() function has been called by a non admin user / user without html posting permissions.
* @param boolean $mod [optional] The 'no_html' and 'no_php' modifiers blanket prevent HTML and PHP posting regardless of posting permissions. (used in logging)
* The 'pReFs' value is for internal use only, when saving prefs, to prevent sanitisation of HTML.
* @param boolean $original_author [optional]
* @return string
* @todo complete the documentation of this essential method
*/
public function toDB($data, $nostrip = FALSE, $no_encode = FALSE, $mod = FALSE, $original_author = FALSE)
{
$core_pref = e107::getConfig();
if (is_array($data))
{
foreach ($data as $key => $var)
{
//Fix - sanitize keys as well
$ret[$this->toDB($key, $nostrip, $no_encode, $mod, $original_author)] = $this->toDB($var, $nostrip, $no_encode, $mod, $original_author);
}
return $ret;
}
if (MAGIC_QUOTES_GPC == TRUE && $nostrip == FALSE)
{
$data = stripslashes($data);
}
if ($mod != 'pReFs')
{
$data = $this->preFilter($data);
if (!check_class($core_pref->get('post_html', e_UC_MAINADMIN)) || !check_class($core_pref->get('post_script', e_UC_MAINADMIN)))
{
$data = $this->dataFilter($data);
}
}
if (/*$core_pref->is('post_html') && */check_class($core_pref->get('post_html')))
{
$no_encode = TRUE;
}
if ($core_pref->get('html_abuse'))
{
if ($this->htmlAbuseFilter($data)) $no_encode = FALSE;
}
if (is_numeric($original_author) && !check_class($core_pref->get('post_html'), '', $original_author))
{
$no_encode = FALSE;
}
if ($no_encode === TRUE && strpos($mod, 'no_html') === FALSE)
{
$search = array('$', '"', "'", '\\', '');
$replace = array('$', '"', ''', '\', '<?');
$ret = str_replace($search, $replace, $data);
}
else
{
$data = htmlspecialchars($data, ENT_QUOTES, 'UTF-8');
$data = str_replace('\\', '\', $data);
$ret = preg_replace("/&#(\d*?);/", "\\1;", $data);
}
// XXX - php_bbcode pref missing?
if ((strpos($mod, 'no_php') !== FALSE) || !check_class($core_pref->get('php_bbcode')))
{
$ret = preg_replace("#\[(php)#i", "[\\1", $ret);
}
return $ret;
}
/**
* Check for HTML closing tag for input elements, without corresponding opening tag
*
* @param string $data
* @param string $tagList - if empty, uses default list of input tags. Otherwise a CSV list of tags to check (any type)
*
* @return boolean TRUE if an unopened closing tag found
* FALSE if nothing found
*/
function htmlAbuseFilter($data, $tagList = '')
{
if ($tagList == '')
{
$checkTags = array('textarea', 'input', 'td', 'tr', 'table');
}
else
{
$checkTags = explode(',', $tagList);
}
$data = strtolower(preg_replace('#\[code.*?\[\/code\]#i', '', $data)); // Ignore code blocks. All lower case simplifies subsequent processing
foreach ($checkTags as $tag)
{
$aCount = substr_count($data, '<'.$tag); // Count opening tags
$bCount = substr_count($data, ''.$tag); // Count closing tags
if ($aCount != $bCount)
{
return TRUE; // Potentially abusive HTML found - tags don't balance
}
}
return FALSE; // Nothing detected
}
/**
* Checks a string for potentially dangerous HTML tags, including malformed tags
*
*/
public function dataFilter($data, $mode='bbcode')
{
$ans = '';
$vetWords = array('