From 169efa09b9e4e68b90278244b4bad7b54dced982 Mon Sep 17 00:00:00 2001 From: Nick Liu Date: Sun, 6 Feb 2022 16:49:56 +0100 Subject: [PATCH] `e_parse::toAttributes()`: New API to concatenate HTML attributes `e_parse::toAttributes()` is an expansion of the formerly private method `e_form::attributes()`. Now, all client code can use `e_parse::toAttributes()` to make it easy to concatenate variable-length HTML attributes. Values are guaranteed to be encoded so that they cannot escape an HTML attribute value. All client code usages are encouraged to build HTML tags with this new method to prevent cross-site scripting (XSS) attacks and prevent breaking the HTML validity due to improperly escaped HTML attributes. This new method is an extension to `e_parse::toAttribute()`, which escaped one single HTML attribute value. --- e107_handlers/e_parse_class.php | 1424 ++++---- e107_handlers/form_handler.php | 90 +- e107_tests/tests/unit/e_parseTest.php | 4794 +++++++++++++------------ 3 files changed, 3220 insertions(+), 3088 deletions(-) diff --git a/e107_handlers/e_parse_class.php b/e107_handlers/e_parse_class.php index 77e177b0f..2aba8bf6b 100644 --- a/e107_handlers/e_parse_class.php +++ b/e107_handlers/e_parse_class.php @@ -10,7 +10,7 @@ * */ -if(!defined('e107_INIT')) +if (!defined('e107_INIT')) { exit(); } @@ -97,19 +97,19 @@ class e_parse 'link_replace' => true, // Parse shortcodes - TRUE enables parsing - 'parse_sc' => false, + 'parse_sc' => false, // remove HTML tags. - 'no_tags' => false, + 'no_tags' => false, // Restore entity form of quotes and such to single characters - TRUE disables - 'value' => false, + 'value' => false, // Line break compression - TRUE removes newline characters - 'nobreak' => false, + 'nobreak' => false, // Retain newlines - wraps to \n instead of
if TRUE (for non-HTML email text etc) - 'retain_nl' => false + 'retain_nl' => false ); // Super modifiers override default option values @@ -178,10 +178,10 @@ class e_parse array( 'nobreak' => true, 'retain_nl' => true, 'link_click' => false, 'emotes' => false, 'hook' => false, 'no_tags' => true ), - 'NODEFAULT' => - array ('context' => false, 'fromadmin' => false, 'emotes' => false, 'defs' => false, 'constants' => false, 'hook' => false, - 'scripts' => false, 'link_click' => false, 'link_replace' => false, 'parse_sc' => false, 'no_tags' => false, 'value' => false, - 'nobreak' => false, 'retain_nl' => false + 'NODEFAULT' => + array('context' => false, 'fromadmin' => false, 'emotes' => false, 'defs' => false, 'constants' => false, 'hook' => false, + 'scripts' => false, 'link_click' => false, 'link_replace' => false, 'parse_sc' => false, 'no_tags' => false, 'value' => false, + 'nobreak' => false, 'retain_nl' => false ) ); @@ -251,11 +251,11 @@ class e_parse private $bootstrap; private $fontawesome; - private $removedList = array(); - private $nodesToDelete = array(); - private $nodesToConvert = array(); + private $removedList = array(); + private $nodesToDelete = array(); + private $nodesToConvert = array(); private $nodesToDisableSC = array(); - private $pathList = array(); + private $pathList = array(); private $allowedAttributes = array(); @@ -265,7 +265,7 @@ class e_parse private $replaceAttrValues = array(); private $allowedTags = array(); - private $scriptTags = array(); + private $scriptTags = array(); private $scriptAttributes = array(); @@ -290,7 +290,7 @@ class e_parse public function getModifierList($type = '') { - if($type === 'super') + if ($type === 'super') { return $this->e_SuperMods; } @@ -310,13 +310,14 @@ class e_parse public function setMultibyte($bool) { - if($bool === false) + if ($bool === false) { $this->multibyte = false; + return null; } - if(extension_loaded('mbstring')) + if (extension_loaded('mbstring')) { $this->multibyte = true; mb_internal_encoding('UTF-8'); @@ -333,14 +334,14 @@ class e_parse */ public function ustrlen($str) { - if($this->multibyte) + if ($this->multibyte) { return mb_strlen($str); } return strlen($str); - // return strlen(utf8_decode($str)); + // return strlen(utf8_decode($str)); } @@ -353,7 +354,7 @@ class e_parse */ public function ustrtolower($str) { - if($this->multibyte) + if ($this->multibyte) { return mb_strtolower($str); } @@ -372,7 +373,7 @@ class e_parse public function ustrtoupper($str) { - if($this->multibyte) + if ($this->multibyte) { return mb_strtoupper($str); } @@ -389,16 +390,16 @@ class e_parse * 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. + * @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) { - if($this->multibyte) + if ($this->multibyte) { return mb_strpos($haystack, $needle, $offset); } @@ -413,15 +414,15 @@ class e_parse * 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. + * @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) { - if($this->multibyte) + if ($this->multibyte) { return mb_strrpos($haystack, $needle, $offset); } @@ -434,15 +435,15 @@ class e_parse * Returns all of haystack starting from and including the first occurrence of needle to the end. * Unicode (UTF-8) analogue of standard @link http://php.net/stristr stristr PHP function. * - * @param string $haystack The UTF-8 encoded string to search in. - * @param mixed $needle If needle is not a string, it is converted to an integer and applied as the ordinal value of a character. - * @param bool $before_needle [optional] (PHP 5.3+) If TRUE, returns the part of the haystack before the first occurrence of the needle (excluding needle). + * @param string $haystack The UTF-8 encoded string to search in. + * @param mixed $needle If needle is not a string, it is converted to an integer and applied as the ordinal value of a character. + * @param bool $before_needle [optional] (PHP 5.3+) If TRUE, returns the part of the haystack before the first occurrence of the needle (excluding needle). * @return string Returns the matched substring. If needle is not found, returns FALSE. */ public function ustristr($haystack, $needle, $before_needle = false) { - if($this->multibyte) + if ($this->multibyte) { return mb_stristr($haystack, $needle, $before_needle); } @@ -458,17 +459,17 @@ class e_parse * 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 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. + * (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) { - if($this->multibyte) + if ($this->multibyte) { return ($length === null) ? mb_substr($str, $start) : mb_substr($str, $start, $length); } @@ -480,14 +481,14 @@ class e_parse /** * Converts the supplied text (presumed to be from user input) to a format suitable for storing in a database table. * - * @param mixed $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|string $mod [optional] model = admin-ui usage. 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 mixed $parm [optional] + * @param mixed $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|string $mod [optional] model = admin-ui usage. 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 mixed $parm [optional] * @return mixed * @todo complete the documentation of this essential method */ @@ -496,16 +497,16 @@ class e_parse $variableType = gettype($data); - if(($variableType !== 'string' && $variableType !== 'array') || $data === '0') + if (($variableType !== 'string' && $variableType !== 'array') || $data === '0') { return $data; } - if($variableType === 'array') + if ($variableType === 'array') { $ret = array(); - foreach($data as $key => $var) + foreach ($data as $key => $var) { //Fix - sanitize keys as well $key = str_replace(['"', "'"], ['"', '''], $key); @@ -516,20 +517,20 @@ class e_parse } - if(MAGIC_QUOTES_GPC === true && $nostrip === false) + if (MAGIC_QUOTES_GPC === true && $nostrip === false) { $data = stripslashes($data); } $core_pref = e107::getConfig(); - if($mod !== 'pReFs') //XXX We're not saving prefs. + if ($mod !== 'pReFs') //XXX We're not saving prefs. { $data = $this->preFilter($data); // used by bb_xxx.php toDB() functions. bb_code.php toDB() allows us to properly bypass HTML cleaning below. $data = $this->cleanHtml($data); // clean it regardless of if it is text or html. (html could have missing closing tags) - if(($this->isHtml($data)) && strpos($mod, 'no_html') === false) + if (($this->isHtml($data)) && strpos($mod, 'no_html') === false) { $this->isHtml = true; // $data = $this->cleanHtml($data); // sanitize all html. (moved above to include everything) @@ -546,7 +547,7 @@ class e_parse } - if(!check_class($core_pref->get('post_html', e_UC_MAINADMIN))) + if (!check_class($core_pref->get('post_html', e_UC_MAINADMIN))) { $data = strip_tags($data); // remove tags from cleaned html. $data = str_replace(array('[html]', '[/html]'), '', $data); @@ -556,17 +557,17 @@ class e_parse } - if(check_class($core_pref->get('post_html'))) /*$core_pref->is('post_html') && XXX preformecd by cleanHtml() */ + if (check_class($core_pref->get('post_html'))) /*$core_pref->is('post_html') && XXX preformecd by cleanHtml() */ { $no_encode = true; } - if($parm !== null && is_numeric($parm) && !check_class($core_pref->get('post_html'), '', $parm)) + if ($parm !== null && is_numeric($parm) && !check_class($core_pref->get('post_html'), '', $parm)) { $no_encode = false; } - if($no_encode === true && strpos($mod, 'no_html') === false) + if ($no_encode === true && strpos($mod, 'no_html') === false) { $search = array('$', '"', "'", '\\', 'get('php_bbcode'))) + if ((strpos($mod, 'no_php') !== false) || !check_class($core_pref->get('php_bbcode'))) { $ret = preg_replace("#\[(php)#i", "[\\1", $ret); } // Don't allow hooks to mess with prefs. - if($mod !== 'model') + if ($mod !== 'model') { return $ret; } @@ -602,7 +603,7 @@ class e_parse * e_parse hook */ $eParseList = $core_pref->get('e_parse_list'); - if(!empty($eParseList)) + if (!empty($eParseList)) { $opts = array( @@ -612,10 +613,10 @@ class e_parse 'field' => $parm['field'] ); - foreach($eParseList as $plugin) + foreach ($eParseList as $plugin) { $hookObj = e107::getAddon($plugin, 'e_parse'); - if($tmp = e107::callMethod($hookObj, 'toDB', $ret, $opts)) + if ($tmp = e107::callMethod($hookObj, 'toDB', $ret, $opts)) { $ret = $tmp; } @@ -632,6 +633,7 @@ class e_parse /** * Check for umatched 'dangerous' HTML tags * (these can destroy page layout where users are able to post HTML) + * * @param string $data * @param string $tagList - if empty, uses default list of input tags. Otherwise a CSV list of tags to check (any type) * @@ -672,7 +674,7 @@ class e_parse public function preFilter($data) { - if(!$this->isBBcode($data)) + if (!$this->isBBcode($data)) { return $data; } @@ -684,6 +686,7 @@ class e_parse /** * Takes a multi-dimensional array and converts the keys to a list of routing paths. * paths are the key and value are the top most key. + * * @param array $array * @return array */ @@ -692,24 +695,24 @@ class e_parse $res = $this->_processRoute($array); $tmp = explode("_#_", $res); $ret = []; - foreach($tmp as $v) + foreach ($tmp as $v) { - list($k) = explode('/',$v); + list($k) = explode('/', $v); $ret[$v] = $k; } return $ret; } - private function _processRoute($array, $prefix='') + private function _processRoute($array, $prefix = '') { $text = []; - if(is_array($array)) + if (is_array($array)) { - foreach($array as $key=>$val) + foreach ($array as $key => $val) { - if($tag = $this->_processRoute($val, $key.'/')) + if ($tag = $this->_processRoute($val, $key . '/')) { $add = $tag; } @@ -718,27 +721,25 @@ class e_parse $add = $key; } - $text[] = $prefix.$add; + $text[] = $prefix . $add; } } - return implode('_#_',$text); + return implode('_#_', $text); } - - public function toForm($text) { - if(empty($text)) // fix - handle proper 0, Space etc values. + if (empty($text)) // fix - handle proper 0, Space etc values. { return $text; } - if(is_string($text) && strpos($text, '[html]') === 0) + if (is_string($text) && strpos($text, '[html]') === 0) { // $text = $this->toHTML($text,true); $search = array('"', ''', '\', '&',); // '&' must be last. @@ -758,7 +759,7 @@ class e_parse $replace = array('$', '"', '<', '>', '%2B'); $text = str_replace($search, $replace, $text); - if(is_string($text) && e107::wysiwyg() !== true) + if (is_string($text) && e107::wysiwyg() !== true) { // fix for utf-8 issue with html_entity_decode(); ??? $text = urldecode($text); @@ -775,10 +776,10 @@ class e_parse public function post_toForm($text) { - if(is_array($text)) + if (is_array($text)) { $arr = array(); - foreach($text as $key => $value) + foreach ($text as $key => $value) { $key = $this->post_toForm($key); $arr[$key] = $this->post_toForm($value); @@ -789,7 +790,7 @@ class e_parse $text = (string) $text; - if(MAGIC_QUOTES_GPC == true) + if (MAGIC_QUOTES_GPC == true) { $text = stripslashes($text); } @@ -807,16 +808,16 @@ class e_parse } /** - * @param $text - template to parse. - * @param boolean $parseSCFiles - parse core 'single' shortcodes - * @param object|array $extraCodes - shortcode class containing sc_xxxxx methods or an array of key/value pairs or legacy shortcode content (eg. content within .sc) - * @param object $eVars - XXX more info needed. + * @param $text - template to parse. + * @param boolean $parseSCFiles - parse core 'single' shortcodes + * @param object|array $extraCodes - shortcode class containing sc_xxxxx methods or an array of key/value pairs or legacy shortcode content (eg. content within .sc) + * @param object $eVars - XXX more info needed. * @return string */ public function parseTemplate($text, $parseSCFiles = true, $extraCodes = null, $eVars = null) { - if(!is_bool($parseSCFiles)) + if (!is_bool($parseSCFiles)) { trigger_error('$parseSCFiles in parseTemplate() was given incorrect data'); } @@ -826,10 +827,10 @@ class e_parse /** * @experimental - * @param string $text - * @param bool $parseSCFiles + * @param string $text + * @param bool $parseSCFiles * @param object|array $extraCodes - * @param object $eVars + * @param object $eVars * @return string */ public function parseSchemaTemplate($text, $parseSCFiles = true, $extraCodes = null, $eVars = null) @@ -839,6 +840,7 @@ class e_parse $text = e107::getScParser()->parseCodes($text, $parseSCFiles, $extraCodes, $eVars); $text = str_replace(''; - $homeIcon = ($this->_fontawesome) ? e107::getParser()->toGlyph('fa-home.glyph') : $fallbackIcon; + $homeIcon = ($this->_fontawesome) ? $this->tp->toGlyph('fa-home.glyph') : $fallbackIcon; } @@ -3812,7 +3810,7 @@ var_dump($select_options);*/ 'target' => '_blank', 'title' => LAN_EDIT, 'href' => $url, - ]) . ">" . e107::getParser()->toGlyph('fa-edit') . ''; + ]) . ">" . $this->tp->toGlyph('fa-edit') . ''; } return ''; @@ -4037,22 +4035,7 @@ var_dump($select_options);*/ */ private function attributes($attributes) { - $stringifiedAttributes = []; - - foreach ($attributes as $key => $value) - { - - if ($value === true && (strpos($key,'data-') !== 0)) - { - $value = $key; - } - if (!empty($value) || is_numeric($value) || $key === "value" || strpos($key,'data-') === 0) - { - $stringifiedAttributes[] = $key . "='" . htmlspecialchars((string) $value, ENT_QUOTES) . "'"; - } - } - - return count($stringifiedAttributes) > 0 ? " ".implode(" ", $stringifiedAttributes) : ""; + return $this->tp->toAttributes($attributes, true); } public function get_attributes($options, $name = '', $value = '') @@ -4454,7 +4437,6 @@ var_dump($select_options);*/ public function thead($fieldarray, $columnPref = array(), $querypattern = '', $requeststr = '') { - $tp = e107::getParser(); $text = ''; $querypattern = strip_tags($querypattern); @@ -4631,7 +4613,7 @@ var_dump($select_options);*/ - $tp = e107::getParser(); + $tp = $this->tp; $types = explode(',',$parm['types']); $list = array(); @@ -4857,7 +4839,7 @@ var_dump($select_options);*/ } } - $source = e107::getParser()->toJSON($jsonArray, true); + $source = $this->tp->toJSON($jsonArray, true); $mode = preg_replace('/[\W]/', '', vartrue($_GET['mode'])); @@ -4946,7 +4928,7 @@ var_dump($select_options);*/ } elseif (!empty($model)) // old way. { - $tp = e107::getParser(); + $tp = $this->tp; $data = $model->getData(); @@ -4994,7 +4976,7 @@ var_dump($select_options);*/ private function renderOptions($parms, $id, $attributes) { - $tp = e107::getParser(); + $tp = $this->tp; $cls = false; $editIconDefault = deftrue('ADMIN_EDIT_ICON', $tp->toGlyph('fa-edit')); @@ -5134,7 +5116,7 @@ var_dump($select_options);*/ } // @see custom fields in cpage which accept json params. - if(!empty($attributes['writeParms']) && $tmpOpt = e107::getParser()->isJSON($attributes['writeParms'])) + if(!empty($attributes['writeParms']) && $tmpOpt = $this->tp->isJSON($attributes['writeParms'])) { $attributes['writeParms'] = $tmpOpt; unset($tmpOpt); @@ -5158,7 +5140,7 @@ var_dump($select_options);*/ $this->renderValueTrigger($field, $value, $parms, $id); - $tp = e107::getParser(); + $tp = $this->tp; switch($field) // special fields { case 'options': @@ -5602,7 +5584,7 @@ var_dump($select_options);*/ } else { - $url = e107::getParser()->replaceConstants($value, 'full'); + $url = $this->tp->replaceConstants($value, 'full'); } $name = basename($value); $value = ''.$name.''; @@ -5640,7 +5622,7 @@ var_dump($select_options);*/ $vparm = array('thumb'=>'tag','w'=> vartrue($parms['thumb_aw'],'80')); - if($video = e107::getParser()->toVideo($value,$vparm)) + if($video = $tp->toVideo($value,$vparm)) { return $video; } @@ -5653,7 +5635,7 @@ var_dump($select_options);*/ $icon = '{e_IMAGE}filemanager/zip_32.png'; $src = $tp->replaceConstants(vartrue($parms['pre']).$icon, 'abs'); // return $value; - return e107::getParser()->toGlyph('fa-file','size=2x'); + return $tp->toGlyph('fa-file','size=2x'); // return ''.$value.''; } @@ -6275,7 +6257,7 @@ var_dump($select_options);*/ $value = html_entity_decode($value, ENT_QUOTES); } - $tp = e107::getParser(); + $tp = $this->tp; $ret = ''; $parms = vartrue($attributes['writeParms'], array()); @@ -6498,7 +6480,7 @@ var_dump($select_options);*/ if(!empty($parms['maxlength']) && empty($parms['post'])) { - $charMsg = e107::getParser()->lanVars(defset('LAN_X_CHARS_REMAINING', '[x] chars remaining'), "" . $parms['maxlength'] . ""); + $charMsg = $tp->lanVars(defset('LAN_X_CHARS_REMAINING', '[x] chars remaining'), "" . $parms['maxlength'] . ""); $parms['post'] = "attributes([ 'id' => $this->name2id($key) . "-char-count", 'class' => 'text-muted', @@ -6928,7 +6910,7 @@ var_dump($select_options);*/ case 'upload': //TODO - from method // TODO uploadfile SC is now processing uploads as well (add it to admin UI), write/readParms have to be added (see uploadfile.php parms) $disbut = varset($parms['disable_button'], '0'); - $ret = $tp->parseTemplate('{UPLOADFILE=' .(vartrue($parms['path']) ? e107::getParser()->replaceConstants($parms['path']) : e_UPLOAD)."|nowarn&trigger=etrigger_uploadfiles&disable_button={$disbut}}"); + $ret = $tp->parseTemplate('{UPLOADFILE=' .(vartrue($parms['path']) ? $tp->replaceConstants($parms['path']) : e_UPLOAD)."|nowarn&trigger=etrigger_uploadfiles&disable_button={$disbut}}"); break; case 'hidden': @@ -7014,7 +6996,7 @@ var_dump($select_options);*/ foreach($parms['optArray'] as $key=>$val) { - $thumbnail = e107::getParser()->toImage($val['thumbnail'], $parms); + $thumbnail = $this->tp->toImage($val['thumbnail'], $parms); $active = ($key === $value) ? ' active' : ''; $text .= "
@@ -7055,7 +7037,7 @@ var_dump($select_options);*/ foreach($parms['optArray'] as $key=>$val) { - $thumbnail = e107::getParser()->toImage($val,$parms); + $thumbnail = $this->tp->toImage($val,$parms); $text .= "
attributes([ @@ -7122,7 +7104,7 @@ var_dump($select_options);*/ */ public function renderListForm($form_options, $tree_models, $nocontainer = false) { - $tp = e107::getParser(); + $tp = $this->tp; $text = ''; $formPre = ''; $formPost = ''; @@ -7294,7 +7276,7 @@ var_dump($select_options);*/ */ public function renderGridForm($form_options, $tree_models, $nocontainer = false) { - $tp = e107::getParser(); + $tp = $this->tp; $text = ''; @@ -7516,7 +7498,7 @@ var_dump($select_options);*/ } $query = isset($form['query']) ? $form['query'] : e_QUERY ; - $url = (isset($form['url']) ? e107::getParser()->replaceConstants($form['url'], 'abs') : e_SELF).($query ? '?'.$query : ''); + $url = (isset($form['url']) ? $this->tp->replaceConstants($form['url'], 'abs') : e_SELF).($query ? '?'.$query : ''); $curTab = (string) varset($_GET['tab'], '0'); $text .= " @@ -7902,7 +7884,7 @@ var_dump($select_options);*/ foreach ($forms as $fid => $form) { $query = isset($form['query']) ? $form['query'] : e_QUERY ; - $url = (isset($form['url']) ? e107::getParser()->replaceConstants($form['url'], 'abs') : e_SELF).($query ? '?'.$query : ''); + $url = (isset($form['url']) ? $this->tp->replaceConstants($form['url'], 'abs') : e_SELF).($query ? '?'.$query : ''); $text .= ' ' .vartrue($form['form_pre'])." diff --git a/e107_tests/tests/unit/e_parseTest.php b/e107_tests/tests/unit/e_parseTest.php index c265a9a63..65cec4ebb 100644 --- a/e107_tests/tests/unit/e_parseTest.php +++ b/e107_tests/tests/unit/e_parseTest.php @@ -1,112 +1,111 @@ tp = $this->make('e_parse'); + } + catch (Exception $e) + { + $this->assertTrue(false, "Couldn't load e_parser object"); + } + + $this->tp->__construct(); + } + + public function testInit() + { + $this->tp->init(); + } + + public function testToRoute() + { + + $posted = array( + 'myfield' => array( + 'computer' => array( + 'apple' => array('imac' => '1') + ), + 'os' => array( + 'microsoft' => array('windows' => 'xp') + ) + ), + 'myfield2' => array( + 'house' => array('car' => 'red') + ), + 'myfield3' => 'string', + + ); + + $expected = array( + 'myfield/computer/apple/imac' => 'myfield', + 'myfield/os/microsoft/windows' => 'myfield', + 'myfield2/house/car' => 'myfield2', + 'myfield3' => 'myfield3', + ); + + $result = $this->tp->toRoute($posted); + $this->assertSame($expected, $result); + + } + + + public function testStripBlockTags() + { + $tests = array( + 0 => array( + 'text' => '

Paragraph 1

Paragraph 2
Line 3

', + 'expected' => "Paragraph 1Paragraph 2
Line 3
", + ), + + + ); + + foreach ($tests as $var) + { + $result = $this->tp->stripBlockTags($var['text']); + + if (empty($var['expected'])) { - $this->tp = $this->make('e_parse'); - } - catch (Exception $e) - { - $this->assertTrue(false, "Couldn't load e_parser object"); + echo $result . "\n\n"; + continue; } - $this->tp->__construct(); - } - - public function testInit() - { - $this->tp->init(); - } - - public function testToRoute() - { - - $posted = array( - 'myfield' => array( - 'computer' => array( - 'apple' => array('imac' => '1') - ), - 'os' => array( - 'microsoft' => array('windows' => 'xp') - ) - ), - 'myfield2' => array( - 'house' => array('car' => 'red') - ), - 'myfield3' => 'string', - - ); - - $expected = array ( - 'myfield/computer/apple/imac' => 'myfield', - 'myfield/os/microsoft/windows' => 'myfield', - 'myfield2/house/car' => 'myfield2', - 'myfield3' => 'myfield3', - ); - - $result = $this->tp->toRoute($posted); - $this->assertSame($expected, $result); - + $this->assertEquals($var['expected'], $result); } - public function testStripBlockTags() - { - $tests = array( - 0 => array( - 'text' => '

Paragraph 1

Paragraph 2
Line 3

', - 'expected' => "Paragraph 1Paragraph 2
Line 3
", - ), + } - - ); - - foreach($tests as $var) + /* + public function testHtmlAbuseFilter() { - $result = $this->tp->stripBlockTags($var['text']); - if(empty($var['expected'])) - { - echo $result."\n\n"; - continue; - } - - $this->assertEquals($var['expected'], $result); } + public function testE_highlight() + { + }*/ - } - -/* - public function testHtmlAbuseFilter() - { - - } - - public function testE_highlight() - { - - }*/ - - public function testToHTML() - { - $src = <<tp->toHTML($src,true); + $actual = $this->tp->toHTML($src, true); - $this->assertEquals($expected,$actual, "BBcode parsing failed"); + $this->assertEquals($expected, $actual, "BBcode parsing failed"); $src = "[center][img]{e_IMAGE}generic/blank_avatar.jpg[/img][/center]"; - - $actual = $this->tp->toHTML($src,true); - $expected = "
Blank Avatar
"; + $actual = $this->tp->toHTML($src, true); + + $expected = "
Blank Avatar
"; $this->assertEquals($expected, $actual, "BBcode parsing failed on [img]"); @@ -147,7 +146,7 @@ src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> [/center] SRC; - $expected = <<
EXPECTED; - $actual = $this->tp->toHTML($src,true); - $this->assertEquals($expected,$actual); + $actual = $this->tp->toHTML($src, true); + $this->assertEquals($expected, $actual); -/* -$src = "[html] -
$sql = e107::getDb();
-$sql->select('tablename', 'field1, field2', 'field_id = 1');
-while($row = $sql->fetch())
-{
-    echo $row['field1'];
-}
-[/html]"; + /* + $src = "[html] +
$sql = e107::getDb();
+		$sql->select('tablename', 'field1, field2', 'field_id = 1');
+		while($row = $sql->fetch())
+		{
+			echo $row['field1'];
+		}
+ [/html]"; - $actual = $this->tp->toHTML($src,true); - $expected = ''; + $actual = $this->tp->toHTML($src,true); + $expected = ''; - $this->assertEquals($expected, $actual, "BBcode parsing failed on
");*/
+				$this->assertEquals($expected, $actual, "BBcode parsing failed on 
");*/
 
 
-		}
-/*
-		public function testUstrpos()
-		{
+	}
 
-		}
-*/
-		public function testThumbUrlDecode()
-		{
-			$tests = array(
-				0   => array(
-					'input' => '/media/img/a400xa500/myimage.jpg',
-					'expected' => array (
-					  'src' => 'e_MEDIA_IMAGE/myimage.jpg',
-					  'aw' => '400',
-					  'ah' => '500',
-					)
-				),
-				1   => array(
-					'input' => '/media/img/400x500/myimage2.jpg',
-					'expected' => array (
-					  'src' => 'e_MEDIA_IMAGE/myimage2.jpg',
-					  'w' => '400',
-					  'h' => '500',
-					)
-				),
-				2   => array(
-					'input' => '/theme/img/a400xa500/mytheme/myimage.jpg',
-					'expected' => array (
-					  'src' => 'e_THEME/mytheme/myimage.jpg',
-					  'aw' => '400',
-					  'ah' => '500',
-					)
-				),
-				3   => array(
-					'input' => '/theme/img/400x500/mytheme/myimage2.jpg',
-					'expected' => array (
-					  'src' => 'e_THEME/mytheme/myimage2.jpg',
-					  'w' => '400',
-					  'h' => '500',
-					)
-				),
-
-			);
-
-			foreach($tests as $var)
+	/*
+			public function testUstrpos()
 			{
-				$result = $this->tp->thumbUrlDecode($var['input']);
-				$this->assertSame($var['expected'], $result);
+
 			}
+	*/
+	public function testThumbUrlDecode()
+	{
+		$tests = array(
+			0 => array(
+				'input'    => '/media/img/a400xa500/myimage.jpg',
+				'expected' => array(
+					'src' => 'e_MEDIA_IMAGE/myimage.jpg',
+					'aw'  => '400',
+					'ah'  => '500',
+				)
+			),
+			1 => array(
+				'input'    => '/media/img/400x500/myimage2.jpg',
+				'expected' => array(
+					'src' => 'e_MEDIA_IMAGE/myimage2.jpg',
+					'w'   => '400',
+					'h'   => '500',
+				)
+			),
+			2 => array(
+				'input'    => '/theme/img/a400xa500/mytheme/myimage.jpg',
+				'expected' => array(
+					'src' => 'e_THEME/mytheme/myimage.jpg',
+					'aw'  => '400',
+					'ah'  => '500',
+				)
+			),
+			3 => array(
+				'input'    => '/theme/img/400x500/mytheme/myimage2.jpg',
+				'expected' => array(
+					'src' => 'e_THEME/mytheme/myimage2.jpg',
+					'w'   => '400',
+					'h'   => '500',
+				)
+			),
 
+		);
 
+		foreach ($tests as $var)
+		{
+			$result = $this->tp->thumbUrlDecode($var['input']);
+			$this->assertSame($var['expected'], $result);
 		}
 
 
-		function testToHTMLModifiers()
-		{
+	}
+
+
+	function testToHTMLModifiers()
+	{
 		//	e107::getConfig()->set('make_clickable', 0)->save(false, true);
 
-			$list = $this->tp->getModifierList();
+		$list = $this->tp->getModifierList();
 
-			$tests = array (
-				'emotes_off'        =>
-					array(
-						'input'    => ":-)",
-						'expected' => ':-)',
-					),
-				'emotes_on'         =>
-					array(
-						'input'    => ":-)",
-						'expected' => 'smile',
-					),
-				'no_hook'           =>
-					array(
-						'input'    => "",
-						'expected' => '',
-					),
-				'do_hook'           =>
-					array(
-						'input'    => "",
-						'expected' => '',
-					),
-				'scripts_off'       =>
-					array(
-						'input'    => "",
-						'expected' => '',
-					),
-				'scripts_on'        =>
-					array(
-						'input'    => "",
-						'expected' => '',
-					),
-				'no_make_clickable' =>
-					array(
-						'input'    => "www.somewhere.com mailto:myemail@somewhere.com",
-						'expected' => 'www.somewhere.com mailto:myemail@somewhere.com',
-					),
-				'make_clickable'    =>
-					array(
-						'input'    => "www.somewhere.com mailto:myemail@somewhere.com",
-						'expected' => '', // random obfiscation
-					),
-				'no_replace'        =>
-					array(
-						'input'    => "www.somewhere.com",
-						'expected' => '',
-					),
-				'replace'           =>
-					array(
-						'input'    => "www.somewhere.com",
-						'expected' => '',
-					),
-				'consts_off'        =>
-					array(
-						'input'    => "{e_PLUGIN}",
-						'expected' => '{e_PLUGIN}',
-					),
-				'consts_rel'        =>
-					array(
-						'input'    => "{e_PLUGIN}",
-						'expected' => 'e107_plugins/',
-					),
-				'consts_abs'        =>
-					array(
-						'input'    => "{e_PLUGIN}",
-						'expected' => '/e107_plugins/',
-					),
-				'consts_full'       =>
-					array(
-						'input'    => "{e_PLUGIN}",
-						'expected' => 'https://localhost/e107/e107_plugins/',
-					),
-				'scparse_off'       =>
-					array(
-						'input'    => "{SITENAME}",
-						'expected' => '{SITENAME}',
-					),
-				'scparse_on'        =>
-					array(
-						'input'    => "{SITENAME}",
-						'expected' => 'e107',
-					),
-				'no_tags'           =>
-					array(
-						'input'    => "bold",
-						'expected' => 'bold',
-					),
-				'do_tags'           =>
-					array(
-						'input'    => "bold",
-						'expected' => 'bold',
-					),
-				'fromadmin'         =>
-					array(
-						'input'    => "My Text {SITENAME} {e_PLUGIN} www.somewhere.com \nNew line :-)",
-						'expected' => '',
-					),
-				'notadmin'          =>
-					array(
-						'input'    => "My Text {SITENAME} {e_PLUGIN} www.somewhere.com \nNew line :-)",
-						'expected' => '',
-					),
-				'er_off'            =>
-					array(
-						'input'    => "My Text {SITENAME} {e_PLUGIN} www.somewhere.com \nNew line :-)",
-						'expected' => '',
-					),
-				'er_on'             =>
-					array(
-						'input'    => "My Text {SITENAME} {e_PLUGIN} www.somewhere.com \nNew line :-)",
-						'expected' => '',
-					),
-				'defs_off'          =>
-					array(
-						'input'    => "LAN_THANK_YOU",
-						'expected' => 'LAN_THANK_YOU',
-					),
-				'defs_on'           =>
-					array(
-						'input'    => "LAN_THANK_YOU",
-						'expected' => 'Thank you',
-					),
-				'dobreak'           =>
-					array(
-						'input'    => "Line 1\nLine 2\nLine 3",
-						'expected' => 'Line 1
Line 2
Line 3', - ), - 'nobreak' => - array( - 'input' => "Line 1\nLine 2\nLine 3", - 'expected' => "Line 1\nLine 2\nLine 3", - ), - 'lb_nl' => - array( - 'input' => "Line 1\nLine 2\nLine 3", - 'expected' => "Line 1\nLine 2\nLine 3", - ), - 'lb_br' => - array( - 'input' => "Line 1\nLine 2\nLine 3", - 'expected' => 'Line 1
Line 2
Line 3', - ), - 'retain_nl' => - array( - 'input' => "Line 1\nLine 2\nLine 3", - 'expected' => "Line 1\nLine 2\nLine 3", - ), - 'defs' => - array( - 'input' => "LAN_THANK_YOU", - 'expected' => 'Thank you', - ), - 'parse_sc' => - array( - 'input' => "{SITENAME}", - 'expected' => 'e107', - ), - 'constants' => - array( - 'input' => "{e_PLUGIN}", - 'expected' => 'e107_plugins/', - ), - 'value' => - array( - 'input' => "", - 'expected' => '', - ), - 'wysiwyg' => - array( - 'input' => "", - 'expected' => '', - ), - ); + $tests = array( + 'emotes_off' => + array( + 'input' => ":-)", + 'expected' => ':-)', + ), + 'emotes_on' => + array( + 'input' => ":-)", + 'expected' => 'smile', + ), + 'no_hook' => + array( + 'input' => "", + 'expected' => '', + ), + 'do_hook' => + array( + 'input' => "", + 'expected' => '', + ), + 'scripts_off' => + array( + 'input' => "", + 'expected' => '', + ), + 'scripts_on' => + array( + 'input' => "", + 'expected' => '', + ), + 'no_make_clickable' => + array( + 'input' => "www.somewhere.com mailto:myemail@somewhere.com", + 'expected' => 'www.somewhere.com mailto:myemail@somewhere.com', + ), + 'make_clickable' => + array( + 'input' => "www.somewhere.com mailto:myemail@somewhere.com", + 'expected' => '', // random obfiscation + ), + 'no_replace' => + array( + 'input' => "www.somewhere.com", + 'expected' => '', + ), + 'replace' => + array( + 'input' => "www.somewhere.com", + 'expected' => '', + ), + 'consts_off' => + array( + 'input' => "{e_PLUGIN}", + 'expected' => '{e_PLUGIN}', + ), + 'consts_rel' => + array( + 'input' => "{e_PLUGIN}", + 'expected' => 'e107_plugins/', + ), + 'consts_abs' => + array( + 'input' => "{e_PLUGIN}", + 'expected' => '/e107_plugins/', + ), + 'consts_full' => + array( + 'input' => "{e_PLUGIN}", + 'expected' => 'https://localhost/e107/e107_plugins/', + ), + 'scparse_off' => + array( + 'input' => "{SITENAME}", + 'expected' => '{SITENAME}', + ), + 'scparse_on' => + array( + 'input' => "{SITENAME}", + 'expected' => 'e107', + ), + 'no_tags' => + array( + 'input' => "bold", + 'expected' => 'bold', + ), + 'do_tags' => + array( + 'input' => "bold", + 'expected' => 'bold', + ), + 'fromadmin' => + array( + 'input' => "My Text {SITENAME} {e_PLUGIN} www.somewhere.com \nNew line :-)", + 'expected' => '', + ), + 'notadmin' => + array( + 'input' => "My Text {SITENAME} {e_PLUGIN} www.somewhere.com \nNew line :-)", + 'expected' => '', + ), + 'er_off' => + array( + 'input' => "My Text {SITENAME} {e_PLUGIN} www.somewhere.com \nNew line :-)", + 'expected' => '', + ), + 'er_on' => + array( + 'input' => "My Text {SITENAME} {e_PLUGIN} www.somewhere.com \nNew line :-)", + 'expected' => '', + ), + 'defs_off' => + array( + 'input' => "LAN_THANK_YOU", + 'expected' => 'LAN_THANK_YOU', + ), + 'defs_on' => + array( + 'input' => "LAN_THANK_YOU", + 'expected' => 'Thank you', + ), + 'dobreak' => + array( + 'input' => "Line 1\nLine 2\nLine 3", + 'expected' => 'Line 1
Line 2
Line 3', + ), + 'nobreak' => + array( + 'input' => "Line 1\nLine 2\nLine 3", + 'expected' => "Line 1\nLine 2\nLine 3", + ), + 'lb_nl' => + array( + 'input' => "Line 1\nLine 2\nLine 3", + 'expected' => "Line 1\nLine 2\nLine 3", + ), + 'lb_br' => + array( + 'input' => "Line 1\nLine 2\nLine 3", + 'expected' => 'Line 1
Line 2
Line 3', + ), + 'retain_nl' => + array( + 'input' => "Line 1\nLine 2\nLine 3", + 'expected' => "Line 1\nLine 2\nLine 3", + ), + 'defs' => + array( + 'input' => "LAN_THANK_YOU", + 'expected' => 'Thank you', + ), + 'parse_sc' => + array( + 'input' => "{SITENAME}", + 'expected' => 'e107', + ), + 'constants' => + array( + 'input' => "{e_PLUGIN}", + 'expected' => 'e107_plugins/', + ), + 'value' => + array( + 'input' => "", + 'expected' => '', + ), + 'wysiwyg' => + array( + 'input' => "", + 'expected' => '', + ), + ); - - $ret = []; - foreach($list as $mod => $val) + $ret = []; + foreach ($list as $mod => $val) + { + if (empty($tests[$mod]['expected'])) { - if(empty($tests[$mod]['expected'])) - { - continue; - } + continue; + } - $result = $this->tp->toHTML($tests[$mod]['input'], false, 'defaults_off,'.$mod); - $this->assertSame($tests[$mod]['expected'], $result, $mod." didn't match the expected result."); + $result = $this->tp->toHTML($tests[$mod]['input'], false, 'defaults_off,' . $mod); + $this->assertSame($tests[$mod]['expected'], $result, $mod . " didn't match the expected result."); // $ret[$mod] = $result; - } + } // e107::getConfig()->set('make_clickable', 0)->save(false, true); // var_export($ret); - } + } + function testToHTMLWithBBcode() + { + $tests = array( + 0 => array( + 'text' => '[code]$something = "something";[/code]', + 'expected' => "
\$something = "something";
", + ), + 1 => array( + 'text' => '[b]Title[/b][code]$something = "something"; [b]Not parsed[/b][/code]', + 'expected' => "Title
\$something = "something"; [b]Not parsed[/b]
", + ), + 2 => array( + 'text' => '[php] "", + ), + 3 => array( + 'text' => "[table][tr]\n[td]cell[/td]\n[/tr][/table]", + 'expected' => "\n\n
cell
", + ), - function testToHTMLWithBBcode() + 4 => array( + 'text' => "Test\n[b]first line[/b][b]\nsecond line[/b]", + 'expected' => "Test
first line
second line
", + ), + + 5 => array( + 'text' => "Test\n[code]1st [b]line[/b] of code[/code]\n[code]2nd line of code[/code]", + 'expected' => "Test
1st [b]line[/b] of code
2nd line of code
", + ), + + + ); + + foreach ($tests as $index => $var) { - $tests = array( - 0 => array( - 'text' => '[code]$something = "something";[/code]', - 'expected' => "
\$something = "something";
", - ), - 1 => array( - 'text' => '[b]Title[/b][code]$something = "something"; [b]Not parsed[/b][/code]', - 'expected' => "Title
\$something = "something"; [b]Not parsed[/b]
", - ), - 2 => array( - 'text' => '[php] "", - ), - 3 => array( - 'text' => "[table][tr]\n[td]cell[/td]\n[/tr][/table]", - 'expected' => "\n\n
cell
", - ), + $result = $this->tp->toHTML($var['text'], true); - 4 => array( - 'text' => "Test\n[b]first line[/b][b]\nsecond line[/b]", - 'expected' => "Test
first line
second line
", - ), - - 5 => array( - 'text' => "Test\n[code]1st [b]line[/b] of code[/code]\n[code]2nd line of code[/code]", - 'expected' => "Test
1st [b]line[/b] of code
2nd line of code
", - ), - - - ); - - foreach($tests as $index => $var) + if (!isset($var['expected'])) { - $result = $this->tp->toHTML($var['text'], true); - - if(!isset($var['expected'])) - { - echo $result."\n\n"; - continue; - } - - $this->assertEquals($var['expected'], $result, 'Test #'.$index.' failed.'); + echo $result . "\n\n"; + continue; } - - + $this->assertEquals($var['expected'], $result, 'Test #' . $index . ' failed.'); } - public function testParseTemplateWithEnabledCoreShortcodes() - { - $needle = '