From 3f5d3786b2f2d556946f661285ca2d19ca7b5965 Mon Sep 17 00:00:00 2001
From: Cameron <e107inc@gmail.com>
Date: Thu, 7 Jan 2021 13:24:55 -0800
Subject: [PATCH] PHP8 fixes and shortcode tests for forum, gallery, hero and
 login_menu. admin-shortcode time fix.

---
 .../shortcodes/batch/admin_shortcodes.php     |   27 +-
 e107_core/shortcodes/single/user_extended.php |    8 +-
 e107_handlers/e107_class.php                  |    9 +-
 e107_handlers/shortcode_handler.php           |    4 +-
 e107_plugins/forum/forum_class.php            |    5 +
 .../shortcodes/batch/view_shortcodes.php      | 2146 +++++++++--------
 e107_plugins/gallery/e_shortcode.php          |    4 +-
 e107_plugins/hero/hero_shortcodes.php         |   13 +-
 .../login_menu/login_menu_shortcodes.php      |   53 +-
 .../tests/unit/e_parse_shortcodeTest.php      |  253 +-
 10 files changed, 1442 insertions(+), 1080 deletions(-)

diff --git a/e107_core/shortcodes/batch/admin_shortcodes.php b/e107_core/shortcodes/batch/admin_shortcodes.php
index 49ee61621..987a948f0 100644
--- a/e107_core/shortcodes/batch/admin_shortcodes.php
+++ b/e107_core/shortcodes/batch/admin_shortcodes.php
@@ -108,7 +108,9 @@ class admin_shortcodes
 	function sc_admin_docs()
 	{
 		if (!ADMIN) { return ''; }
-		global $ns;
+
+		$helplist = array();
+
 		$i=1;
 		if (!$handle=opendir(e_DOCS.e_LANGUAGE.'/'))
 		{
@@ -125,6 +127,7 @@ class admin_shortcodes
 		closedir($handle);
 
 		unset($e107_var);
+		$e107_var = array();
 		foreach ($helplist as $key => $value)
 		{
 			$e107_var['x'.$key]['text'] = str_replace('_', ' ', $value);
@@ -136,7 +139,7 @@ class admin_shortcodes
 		if(function_exists('show_admin_menu'))
 		{
 			$text = show_admin_menu(FOOTLAN_14, $act, $e107_var, FALSE, TRUE, TRUE);
-			return $ns -> tablerender(FOOTLAN_14,$text, array('id' => 'admin_docs', 'style' => 'button_menu'), TRUE);
+			return e107::getRender()->tablerender(FOOTLAN_14,$text, array('id' => 'admin_docs', 'style' => 'button_menu'), TRUE);
 		}
 	}
 
@@ -1009,6 +1012,7 @@ class admin_shortcodes
 			$xml->filter = array('@attributes' => FALSE, 'administration' => FALSE);	// .. and they're all going to need the same filter
 
 			$nav_sql = new db;
+			$tmp = array();
 			if ($nav_sql ->select('plugin', '*', 'plugin_installflag=1'))
 			{
 				$tmp = array();
@@ -1038,9 +1042,9 @@ class admin_shortcodes
 					}
 
 					// Links Plugins
-					if ($eplug_conffile)
+					if(!empty($eplug_conffile))
 					{
-						$tmp['plug_'.$plugin_id]['text'] = $eplug_caption;
+						$tmp['plug_'.$plugin_id]['text'] = varset($eplug_caption);
 						$tmp['plug_'.$plugin_id]['link'] = e_PLUGIN.$plugin_path.'/'.$eplug_conffile;
 						$tmp['plug_'.$plugin_id]['perm'] = 'P'.$plugin_id;
 					}
@@ -1171,16 +1175,20 @@ class admin_shortcodes
 
 	function sc_admin_siteinfo($parm='')
 	{
-		if($parm == 'creditsonly' && e_PAGE != "credits.php"  && e_PAGE != "phpinfo.php" && e_PAGE != 'e107_update.php')
+		if($parm == 'creditsonly' && e_PAGE !== "credits.php"  && e_PAGE !== "phpinfo.php" && e_PAGE !== 'e107_update.php')
 		{
 			return null;
 		}	
 		
 		
-		if (ADMIN)
+		if (!ADMIN)
 		{
-			global $ns, $pref, $themename, $themeversion, $themeauthor, $themedate, $themeinfo, $mySQLdefaultdb;
+			return null;
+		}
+			global $themename, $themeversion, $themeauthor, $themedate, $themeinfo, $mySQLdefaultdb;
 
+			$pref = e107::getPref();
+			$ns = e107::getRender();
 		//	if (file_exists(e_ADMIN.'ver.php'))
 			{
 			//	include(e_ADMIN.'ver.php');
@@ -1191,8 +1199,7 @@ class admin_shortcodes
 				return e_VERSION;
 			}
 
-			$obj = e107::getDateConvert();
-			$install_date = $obj->convert_date($pref['install_date'], 'long');
+			$install_date = e107::getDate()->convert_date($pref['install_date'], '%A %d %B %Y - %H:%M');
 			
 			if(is_readable(THEME."theme.xml"))
 			{
@@ -1267,7 +1274,7 @@ class admin_shortcodes
 			"<br />";
 
 			return e107::getRender()->tablerender(FOOTLAN_13, $text, '', TRUE);
-		}
+
 	}
 
 	private function getLastGitUpdate()
diff --git a/e107_core/shortcodes/single/user_extended.php b/e107_core/shortcodes/single/user_extended.php
index de69e6f39..3e06012ce 100644
--- a/e107_core/shortcodes/single/user_extended.php
+++ b/e107_core/shortcodes/single/user_extended.php
@@ -143,9 +143,15 @@
 			return FALSE;
 		}
 
-		if ($parms[1] == 'value')
+		if ($parms[1] === 'value')
 		{
 			$uVal = isset($parms[0]) && isset($udata['user_'.$parms[0]]) ?  str_replace(chr(1), '', $udata['user_'.$parms[0]]) : '';
+
+			if(!isset($parms[0]) || !isset($ueStruct["user_".$parms[0]]) || !isset($ueStruct["user_".$parms[0]]['user_extended_struct_type']))
+			{
+				return null;
+			}
+
 			switch ($ueStruct["user_".$parms[0]]['user_extended_struct_type'])
 			{
 
diff --git a/e107_handlers/e107_class.php b/e107_handlers/e107_class.php
index bd7f5ced6..4a6bef9ab 100644
--- a/e107_handlers/e107_class.php
+++ b/e107_handlers/e107_class.php
@@ -1744,7 +1744,7 @@ class e107
 
 	/**
 	 * Retrieve date handler singleton object
-	 *
+	 * @deprecated Use e107::getDate();
 	 * @return convert
 	 */
 	public static function getDateConvert()
@@ -3495,6 +3495,9 @@ class e107
 	 * 	// import defeinitions from /e107_plugins/myplug/languages/[CurrentLanguage]_admin.php
 	 * 	e107::plugLan('myplug', true);
 	 *
+	 * // import defeinitions from /e107_plugins/myplug/languages/[CurrentLanguage].php // FOR BC only.
+	 * 	e107::plugLan('myplug', null);
+	 *
 	 * 	// import defeinitions from /e107_plugins/myplug/languages/[CurrentLanguage]/[CurrentLanguage]_front.php
 	 * 	e107::plugLan('myplug', 'front', true);
 	 *
@@ -3530,6 +3533,10 @@ class e107
 			//$fname = "admin/".e_LANGUAGE;
 			 $fname = e_LANGUAGE."_admin";
 		}
+		elseif($fname === null)
+		{
+			$fname = e_LANGUAGE;
+		}
 		else
 		{
 			// $fname = e_LANGUAGE;
diff --git a/e107_handlers/shortcode_handler.php b/e107_handlers/shortcode_handler.php
index 47b88ac7a..920aef23e 100644
--- a/e107_handlers/shortcode_handler.php
+++ b/e107_handlers/shortcode_handler.php
@@ -1449,7 +1449,8 @@ class e_parse_shortcode
 	 */
 	private function makeWrapper($ret, $code, $fullShortcodeKey, $sc_mode)
 	{
-		$pre = $post = '';
+		$pre = '';
+		$post = '';
 
 		if(!empty($fullShortcodeKey) && !empty($this->wrappers[$fullShortcodeKey]) ) // eg: $NEWS_WRAPPER['view']['item']['NEWSIMAGE: item=1']
 		{
@@ -1505,6 +1506,7 @@ class e_parse_shortcode
 			$this->nowrap = false;
 		}
 
+
 		return $pre.$ret.$post;
 
 	}
diff --git a/e107_plugins/forum/forum_class.php b/e107_plugins/forum/forum_class.php
index 550696aa4..3c171b580 100644
--- a/e107_plugins/forum/forum_class.php
+++ b/e107_plugins/forum/forum_class.php
@@ -1942,6 +1942,11 @@ class e107forum
 
 	function forumGetAllowed($type='view')
 	{
+		if(empty($this->permList[$type]))
+		{
+			return array();
+		}
+
 		$sql = e107::getDb();
 		$forumList = implode(',', $this->permList[$type]);
 		$qry = "
diff --git a/e107_plugins/forum/shortcodes/batch/view_shortcodes.php b/e107_plugins/forum/shortcodes/batch/view_shortcodes.php
index 814cffe3a..1183ec49e 100644
--- a/e107_plugins/forum/shortcodes/batch/view_shortcodes.php
+++ b/e107_plugins/forum/shortcodes/batch/view_shortcodes.php
@@ -1,800 +1,866 @@
 <?php
-	/*
-	 * Copyright e107 Inc e107.org, Licensed under GNU GPL (http://www.gnu.org/licenses/gpl.txt)
-	 *
-	 * Forum plugin - view shortcodess
-	 *
-	*/
+/*
+ * Copyright e107 Inc e107.org, Licensed under GNU GPL (http://www.gnu.org/licenses/gpl.txt)
+ *
+ * Forum plugin - view shortcodess
+ *
+*/
 
-	if(!defined('e107_INIT'))
+if(!defined('e107_INIT'))
+{
+	exit;
+}
+
+
+class plugin_forum_view_shortcodes extends e_shortcode
+{
+
+	protected $e107;
+	protected $defaultImgAttachSize = false;
+	public $pref;
+	public $param;
+
+	// $param is sent from nfp menu.
+
+	function __construct()
 	{
-		exit;
+
+		parent::__construct();
+		$this->e107 = e107::getInstance();
+		require_once(e_PLUGIN . "forum/forum_class.php");
+		$this->forum = new e107forum();
+
+		$this->pref = (array) e107::pref('forum');
+
+		$this->defaultImgAttachSize = e107::pref('forum', 'maxwidth', false); // don't resize here if set to 0.
 	}
 
 
-	class plugin_forum_view_shortcodes extends e_shortcode
-	{
-
-		protected $e107;
-		protected $defaultImgAttachSize = false;
-		public $pref;
-		// $param is sent from nfp menu.
-
-		function __construct()
-		{
-			parent::__construct();
-			$this->e107 = e107::getInstance();
-			$this->forum = new e107forum();
-			$this->pref = e107::pref('forum');
-
-			$this->defaultImgAttachSize = e107::pref('forum', 'maxwidth', false); // don't resize here if set to 0.
-		}
-
-
-		/**
-		 * v2.1.5 - Start of Shortcode rewrite rewrite for use throughout all of the forum plugin..
-		 * return 1 piece of data. (ie. no combining of titles and urls unless absolutely required)
-		 * @param $this->var - table data.
-		 * @param $this->param - dynamic control of shortcode via menu configuration.
-		 * Only by nfp menu at this time.
-		*/
+	/**
+	 * v2.1.5 - Start of Shortcode rewrite rewrite for use throughout all of the forum plugin..
+	 * return 1 piece of data. (ie. no combining of titles and urls unless absolutely required)
+	 * @param $this- >var - table data.
+	 * @param $this- >param - dynamic control of shortcode via menu configuration.
+	 * Only by nfp menu at this time.
+	 */
 
 	// @todo new post shortcodes
 
-		function sc_post_url($parm=null)
-		{
-				$url = e107::url('forum', 'topic', $this->var, array(
-					'query'    => array(
-						'f' => 'post',
-						'id'    => intval($this->var['post_id']) // proper page number
-					),
-				));
+	function sc_post_url($parm = null)
+	{
 
-				return $url;
-		}
+		$url = e107::url('forum', 'topic', $this->var, array(
+			'query' => array(
+				'f'  => 'post',
+				'id' => intval($this->var['post_id']) // proper page number
+			),
+		));
 
-		function sc_post_datestamp($parm=null)
-		{
-			return $this->sc_threaddatestamp('relative');
-		}
+		return $url;
+	}
 
-		function sc_post_topic($parm=null)
-		{
-			return $this->sc_threadname($parm);
-		}
+	function sc_post_datestamp($parm = null)
+	{
 
-		function sc_post_content($parm=null)
-		{
-			$tp = e107::getParser();
-			$pref = e107::getPref();
-			$post = strip_tags($tp->toHTML($this->var['post_entry'], true, 'emotes_off, no_make_clickable', '', $pref['menu_wordwrap']));
-			$post = $tp->text_truncate($post, varset($this->param['nfp_characters'],120), varset($this->param['nfp_postfix'],'...'));
+		return $this->sc_threaddatestamp('relative');
+	}
 
-			return $post;
-		}
+	function sc_post_topic($parm = null)
+	{
 
-		function sc_post_author_name($parm=null)
-		{
-			return $this->sc_poster();
-		}
+		return $this->sc_threadname($parm);
+	}
 
-		function sc_post_author_avatar($parm=null)
-		{
-			return e107::getParser()->toAvatar($this->postInfo, $parm);
+	function sc_post_content($parm = null)
+	{
+
+		$tp = e107::getParser();
+		$pref = e107::getPref();
+		$post = strip_tags($tp->toHTML($this->var['post_entry'], true, 'emotes_off, no_make_clickable', '', $pref['menu_wordwrap']));
+		$post = $tp->text_truncate($post, varset($this->param['nfp_characters'], 120), varset($this->param['nfp_postfix'], '...'));
+
+		return $post;
+	}
+
+	function sc_post_author_name($parm = null)
+	{
+
+		return $this->sc_poster();
+	}
+
+	function sc_post_author_avatar($parm = null)
+	{
+
+		return e107::getParser()->toAvatar($this->postInfo, $parm);
 		//	return $this->sc_avatar($parm);
-		}
+	}
 
 	// @todo new thread/topic shortcodes
 
-		function sc_topic_name($parm=null)
+	function sc_topic_name($parm = null)
+	{
+
+		return $this->sc_threadname($parm);
+	}
+
+
+	function sc_topic_author_name($parm = null)
+	{
+
+		if(!empty($this->var['thread_user_username']))
 		{
-			return $this->sc_threadname($parm);
+			return "<a href='" . e107::getUrl()->create('user/profile/view', array('name' => $this->postInfo['thread_user_username'], 'id' => $this->postInfo['thread_user'])) . "'>{$this->postInfo['thread_user_username']}</a>";
+		}
+		elseif(!empty($this->postInfo['thread_user_anon']))
+		{
+			return '<b>' . e107::getParser()->toHTML($this->postInfo['thread_user_anon']) . '</b>';
+		}
+	}
+
+
+	function sc_topic_author_url($parm = null)
+	{
+
+		if(empty($this->var['thread_user_username']) || empty($this->var['thread_user']))
+		{
+			return '';
+		}
+
+		return e107::getUrl()->create('user/profile/view', array('name' => $this->var['thread_user_username'], 'id' => $this->var['thread_user']));
+	}
+
+
+	function sc_topic_author_avatar($parm = null)
+	{
+
+		$arr = array(
+			'user_id'           => $this->var['thread_user'],           // standardized field names.
+			'user_name'         => varset($this->var['thread_user_username']),
+			'user_image'        => varset($this->var['thread_user_userimage']),
+			'user_currentvisit' => varset($this->var['thread_user_usercurrentvisit'])
+		);
+
+		return e107::getParser()->toAvatar($arr, $parm);
+		//	return $this->sc_avatar($parm);
+	}
+
+
+	function sc_topic_url($parm = null)
+	{
+
+		return e107::url('forum', 'topic', $this->var);
+	}
+
+	function sc_topic_views($parm = null)
+	{
+
+		$val = ($this->var['thread_views']) ? $this->var['thread_views'] : '0';
+
+		return e107::getParser()->toBadge($val);
+	}
+
+
+	function sc_topic_replies($parm = null)
+	{
+
+		$val = ($this->var['thread_total_replies']) ? $this->var['thread_total_replies'] : '0';
+
+		return e107::getParser()->toBadge($val);
+	}
+
+	/**
+	 * @param string $parm ['format'] short|long|forum|relative
+	 * @return string HTML
+	 * @example {TOPIC_DATESTAMP: format=relative}
+	 */
+	function sc_topic_datestamp($parm = null)
+	{
+
+		$mode = empty($parm['format']) ? 'forum' : $parm['format'];
+
+		return e107::getParser()->toDate($this->var['thread_datestamp'], $mode);
+	}
+
+
+	/**
+	 * @param string $parm ['format'] short|long|forum|relative
+	 * @return string
+	 * @example {TOPIC_LASTPOST_DATE: format=relative}
+	 */
+	function sc_topic_lastpost_date($parm = null)
+	{
+
+		if(empty($this->var['thread_total_replies']))
+		{
+			return '';
 		}
 
 
-		function sc_topic_author_name($parm=null)
+		$mode = empty($parm['format']) ? 'forum' : $parm['format'];
+
+		return e107::getParser()->toDate($this->var['thread_lastpost'], $mode);
+	}
+
+
+	function sc_topic_lastpost_author($parm = null)
+	{
+
+		if($this->var['thread_views'] && !empty($this->var['thread_total_replies']))
 		{
-			if($this->var['thread_user_username'])
+
+			if(!empty($this->var['thread_lastuser_username']))
 			{
-				return "<a href='" . e107::getUrl()->create('user/profile/view', array('name' => $this->postInfo['thread_user_username'], 'id' => $this->postInfo['thread_user'])) . "'>{$this->postInfo['thread_user_username']}</a>";
+				$url = e107::getUrl()->create('user/profile/view', "name={$this->var['thread_lastuser_username']}&id={$this->var['thread_lastuser']}");
+
+				return "<a href='{$url}'>" . $this->var['thread_lastuser_username'] . "</a>";
+			}
+			elseif($this->var['thread_lastuser_anon'])
+			{
+				return e107::getParser()->toHTML($this->var['thread_lastuser_anon']);
 			}
 			else
 			{
-				return '<b>' . e107::getParser()->toHTML($this->postInfo['thread_user_anon']) . '</b>';
+				return LAN_FORUM_1015;
+
 			}
 		}
 
+		return ' - ';
 
-		function sc_topic_author_url($parm=null)
+	}
+
+
+	function sc_topic_icon($parm = null)
+	{
+
+		$newflag = (USER && defined('USERLV') && ($this->var['thread_lastpost'] > USERLV) && !in_array($this->var['thread_id'], $this->forum->threadGetUserViewed()));
+
+		$ICON = ($newflag ? defset('IMAGE_new') : defset('IMAGE_nonew'));
+
+		if($this->var['thread_total_replies'] >= vartrue($this->pref['popular'], 10))
 		{
-			if(empty($this->var['thread_user_username']) || empty($this->var['thread_user']))
-			{
-				return '';
-			}
-
-			return e107::getUrl()->create('user/profile/view', array('name' => $this->var['thread_user_username'], 'id' => $this->var['thread_user']));
+			$ICON = ($newflag ? defset('IMAGE_new_popular') : defset('IMAGE_nonew_popular'));
+		}
+		elseif(empty($this->var['thread_total_replies']) && defined('IMAGE_noreplies'))
+		{
+			$ICON = defset('IMAGE_noreplies');
 		}
 
-
-		function sc_topic_author_avatar($parm=null)
+		if($this->var['thread_sticky'] == 1)
 		{
-			$arr = array(
-				'user_id'           => $this->var['thread_user'],           // standardized field names.
-				'user_name'         => $this->var['thread_user_username'],
-				'user_image'        => $this->var['thread_user_userimage'],
-				'user_currentvisit' => $this->var['thread_user_usercurrentvisit']
-			);
-
-			return e107::getParser()->toAvatar($arr, $parm);
-		//	return $this->sc_avatar($parm);
+			$ICON = ($this->var['thread_active'] ? defset('IMAGE_sticky') : defset('IMAGE_stickyclosed'));
+		}
+		elseif($this->var['thread_sticky'] == 2)
+		{
+			$ICON = defset('IMAGE_announce');
+		}
+		elseif(!$this->var['thread_active'])
+		{
+			$ICON = defset('IMAGE_closed');
 		}
 
-
-
-
-		function sc_topic_url($parm=null)
-		{
-			return e107::url('forum', 'topic', $this->var);
-		}
-
-		function sc_topic_views($parm=null)
-		{
-			$val = ($this->var['thread_views']) ? $this->var['thread_views'] : '0' ;
-			return e107::getParser()->toBadge($val);
-		}
-
-
-		function sc_topic_replies($parm=null)
-		{
-			$val = ($this->var['thread_total_replies']) ? $this->var['thread_total_replies'] : '0';
-			return e107::getParser()->toBadge($val);
-		}
-
-		/**
-		 * @example {TOPIC_DATESTAMP: format=relative}
-		 * @param string $parm['format'] short|long|forum|relative
-		 * @return string HTML
-		 */
-		function sc_topic_datestamp($parm=null)
-		{
-			$mode = empty($parm['format']) ? 'forum' : $parm['format'];
-			return e107::getParser()->toDate($this->var['thread_datestamp'], $mode);
-		}
-
-
-		/**
-		 * @example {TOPIC_LASTPOST_DATE: format=relative}
-		 * @param string $parm['format'] short|long|forum|relative
-		 * @return string
-		 */
-		function sc_topic_lastpost_date($parm=null)
-		{
-			if(empty($this->var['thread_total_replies']))
-			{
-				return '';
-			}
-			
-		
-			$mode = empty($parm['format']) ? 'forum' : $parm['format'];
-			return e107::getParser()->toDate($this->var['thread_lastpost'], $mode);
-		}
-
-
-		function sc_topic_lastpost_author($parm=null)
-		{
-
-			if($this->var['thread_views'] && !empty($this->var['thread_total_replies']))
-			{
-
-				if($this->var['thread_lastuser_username'])
-				{
-					$url = e107::getUrl()->create('user/profile/view', "name={$this->var['thread_lastuser_username']}&id={$this->var['thread_lastuser']}");
-					return "<a href='{$url}'>" . $this->var['thread_lastuser_username'] . "</a>";
-				}
-				elseif($this->var['thread_lastuser_anon'])
-				{
-					return e107::getParser()->toHTML($this->var['thread_lastuser_anon']);
-				}
-				else
-				{
-					return LAN_FORUM_1015;
-
-				}
-			}
-
-			return ' - ';
-
-		}
-
-
-		function sc_topic_icon($parm=null)
-		{
-
-			$newflag = (USER && $this->var['thread_lastpost'] > USERLV && !in_array($this->var['thread_id'], $this->forum->threadGetUserViewed()));
-
-			$ICON = ($newflag ? IMAGE_new : IMAGE_nonew);
-
-			if($this->var['thread_total_replies'] >= vartrue($this->pref['popular'], 10))
-			{
-				$ICON = ($newflag ? IMAGE_new_popular : IMAGE_nonew_popular);
-			}
-			elseif(empty($this->var['thread_total_replies']) && defined('IMAGE_noreplies'))
-			{
-				$ICON = IMAGE_noreplies;
-			}
-
-			if($this->var['thread_sticky'] == 1)
-			{
-				$ICON = ($this->var['thread_active'] ? IMAGE_sticky : IMAGE_stickyclosed);
-			}
-			elseif($this->var['thread_sticky'] == 2)
-			{
-				$ICON = IMAGE_announce;
-			}
-			elseif(!$this->var['thread_active'])
-			{
-				$ICON = IMAGE_closed;
-			}
-
-			return $ICON;
-		}
+		return $ICON;
+	}
 
 
 	// @todo new forum shortcodes
 
-		function sc_forum_name($parm=null)
+	function sc_forum_name($parm = null)
+	{
+
+		if(substr($this->var['forum_name'], 0, 1) === '*')
 		{
-			if(substr($this->var['forum_name'], 0, 1) === '*')
-			{
-				$this->var['forum_name'] = substr($this->var['forum_name'], 1);
-			}
-
-			$this->var['forum_name'] = e107::getParser()->toHTML($this->var['forum_name'], true, 'no_hook');
-
-			return $this->var['forum_name'];
+			$this->var['forum_name'] = substr($this->var['forum_name'], 1);
 		}
 
-		function sc_forum_url($parm=null)
-		{
-			return e107::url('forum', 'forum', $this->var);
-		}
+		$this->var['forum_name'] = e107::getParser()->toHTML($this->var['forum_name'], true, 'no_hook');
+
+		return $this->var['forum_name'];
+	}
+
+	function sc_forum_url($parm = null)
+	{
+
+		return e107::url('forum', 'forum', $this->var);
+	}
 
 
-		// More sc_topic_xxxxx and sc_forum_xxxx in the same format.
+	// More sc_topic_xxxxx and sc_forum_xxxx in the same format.
 
 	// ---------------------------------------
 
 
+	function sc_breadcrumb()
+	{
+
+		return !empty($this->var['breadcrumb']) ? $this->var['breadcrumb'] : '';
+	}
+
+	function sc_backlink()
+	{
+
+		return !empty($this->var['breadcrumb']) ? $this->var['breadcrumb'] : '';
+	}
+
+	function sc_top($parm = '')
+	{
+
+		$text = ($parm === 'caret') ? "<span class='caret'></span>" : LAN_FORUM_2030;
+
+		return "<a href='" . e_SELF . '?' . e_QUERY . "#top' onclick=\"window.scrollTo(0,0);\">" . $text . '</a>';
+	}
 
 
+	/**
+	 * @example {JOINED: dateformat=relative} - long|short|relative
+	 */
+	function sc_joined($parm = null)
+	{
 
-
-
-
-
-
-
-
-		function sc_breadcrumb()
+		$gen = e107::getDate();
+		if(!empty($this->postInfo['post_user']))
 		{
-			return $this->var['breadcrumb'];
-		}
 
-		function sc_backlink()
-		{
-			return $this->var['breadcrumb'];
-		}
-
-		function sc_top($parm = '')
-		{
-			$text = ($parm == 'caret') ? "<span class='caret'></span>" : LAN_FORUM_2030;
-
-			return "<a href='" . e_SELF . '?' . e_QUERY . "#top' onclick=\"window.scrollTo(0,0);\">" . $text . '</a>';
-		}
-
-		
-		/**
-			* @example {JOINED: dateformat=relative} - long|short|relative
-		*/
-		function sc_joined($parm = null)
-		{
-			$gen = e107::getDate();
-			if($this->postInfo['post_user'])
+			if(empty($parm['dateformat']))
 			{
-
-				if(empty($parm['dateformat']))
-				{
-					return LAN_FORUM_2031 . ': ' . $gen->convert_date($this->postInfo['user_join'], 'forum') . '<br />';
-				}
-				else
-				{
-					return LAN_FORUM_2031 . ': ' . $gen->convert_date($this->postInfo['user_join'], $parm['dateformat']) . '<br />';
-				}
-			}
-		}
-
-
-		function sc_threaddatestamp($parm = '')
-		{
-			$gen = e107::getDateConvert(); // XXX _URL_ check if all required info is there
-
-			if($parm == 'relative')
-			{
-				return $gen->computeLapse($this->postInfo['post_datestamp'], time(), false, true, 'short');
-			}
-
-			// XXX what is this line meant to do?
-			// $text = "<a id='post_{$this->postInfo['post_id']}' href='".$this->e107->url->create('forum/thread/post', array('name' => $this->postInfo['thread_name'], 'thread' => $this->postInfo['post_thread'], 'id' => $this->postInfo['post_id']))."'>".IMAGE_post."</a> ";
-			return $gen->convert_date($this->postInfo['post_datestamp'], 'forum');
-		}
-
-		function sc_postid()
-		{
-			return $this->postInfo['post_id'];
-		}
-
-		/* Preferred - as {POST} may conflict with other shortcodes */
-		function sc_thread_text($parm=null)
-		{
-			return $this->sc_post($parm=null);
-		}
-
-		/**
-		 * @DEPRECATED - use {THREAD_TEXT}
-		 */
-		function sc_post($parm)
-		{
-			//	return print_a($this->postInfo['post_entry'],true);
-			$emote = (isset($this->postInfo['post_options']['no_emote']) ? ',emotes_off' : '');
-
-			$uclass = (!empty($this->postInfo['user_class'])) ? $this->postInfo['user_class'] : 0;
-
-			return e107::getParser()->toHTML($this->postInfo['post_entry'], true, 'USER_BODY' . $emote, 'class:' . $uclass);
-		}
-
-		function sc_postdeleted()
-		{
-			if($this->postInfo['post_status'])
-			{
-				$info = unserialize($this->postInfo['post_options']);
-
-				return "
-			" . LAN_FORUM_2037 . ": {$info['deldate']}<br />
-			" . LAN_FORUM_2038 . ": {$info['delreason']}
-			";
-				//	$ret = '<pre>'.print_r($info, true).'</pre>';
-			}
-		}
-
-
-		function sc_attachments($parm = array())
-		{
-			$tp = e107::getParser();
-
-			if($this->postInfo['post_attachments'])
-			{
-				$baseDir = $this->forum->getAttachmentPath($this->postInfo['post_user']);
-
-				$images = array();
-				$txt = '';
-
-				$attachArray = e107::unserialize($this->postInfo['post_attachments']);
-
-				$thumbAtt = (!empty($this->defaultImgAttachSize)) ? array('w' => $this->defaultImgAttachSize, 'x' => 1) : null;
-
-				//print_a($attachArray);
-
-				foreach($attachArray as $type => $vals)
-				{
-					foreach($vals as $key => $file)
-					{
-						if(is_array($file))
-						{
-
-							$name = !empty($file['name']) ? $file['name'] : $file['file'];
-
-							$file = $file['file'];
-						}
-						else
-						{
-							list($date, $user, $name) = explode("_", $file, 3);
-						}
-
-						switch($type)
-						{
-							case "file":
-
-								$url = e_REQUEST_SELF . "?id=" . $this->postInfo['post_id'] . "&amp;dl=" . $key;
-
-								$saveicon = (deftrue('FONTAWESOME')) ? 'fa-save' : 'icon-save.glyph';
-                				$saveicon = e107::getParser()->toGlyph($saveicon,false);
-								
-								if(defset("BOOTSTRAP"))
-								{
-									$txt .= "<a class='forum-attachment-file btn btn-sm btn-default' href='" . $url . "'>" . $saveicon . " {$name}</a><br />";
-								}
-								else
-								{
-									$txt .= IMAGE_attachment . " <a href='" . $url . "'>{$name}</a><br />";
-								}
-
-								break;
-
-							case 'img': //Always use thumb to hide the hash.
-
-
-								//	return $baseDir.$file;
-								if(file_exists($baseDir . $file))
-								{
-									$thumb = $tp->thumbUrl($baseDir . $file, $thumbAtt, true);
-									$full = $tp->thumbUrl($baseDir . $file, 'w=0&x=1', true);
-
-									//TODO Use jQuery zoom instead.
-
-									$caption = $name;
-
-									$inc = (vartrue($parm['modal'])) ? "data-modal-caption=\"" . $caption . "\" data-target='#uiModal' " : "";
-									$images[] = "<a  {$inc} rel='external' href='{$full}' class='forum-attachment-image e-modal' ><img class='thumbnail' src='{$thumb}' alt='' /></a>";
-								}
-								elseif(ADMIN)
-								{
-									$images[] = "Missing File: " . $baseDir . $file;
-								}
-
-
-								break;
-						}
-
-					}
-
-				}
-
-				if(count($images))
-				{
-					if(deftrue('BOOTSTRAP'))
-					{
-
-						return "<ul class='thumbnails list-unstyled list-inline'><li>" . implode("</li><li>", $images) . "</li></ul>" . vartrue($txt);
-					}
-					else
-					{
-						return implode("<br />", $images) . "<br />" . vartrue($txt);
-					}
-				}
-
-				return $txt;
-			}
-
-		}
-
-		function sc_privmessage()
-		{
-			if(e107::isInstalled('pm') && ($this->postInfo['post_user'] > 0))
-			{
-				return e107::getParser()->parseTemplate("{SENDPM={$this->postInfo['post_user']}}");
-			}
-		}
-
-		function sc_avatar($opts)
-		{
-			return e107::getParser()->toAvatar($this->postInfo, $opts);
-			// return $tp->parseTemplate("{USER_AVATAR=".$this->postInfo['user_image']."}", true);
-		}
-
-		function sc_anon_ip()
-		{
-			if($this->postInfo['post_user_anon'] && (ADMIN || MODERATOR))
-			{
-				return e107::getIPHandler()->ipDecode($this->postInfo['post_ip']);
-			}
-		}
-
-		function sc_ip()
-		{
-			if((ADMIN || MODERATOR) && !$this->postInfo['user_admin'])
-			{
-				return e107::getIPHandler()->ipDecode($this->postInfo['post_ip']);
-			}
-
-		}
-
-		function sc_poster()
-		{
-			if($this->postInfo['user_name'])
-			{
-				return "<a href='" . e107::getUrl()->create('user/profile/view', array('name' => $this->postInfo['user_name'], 'id' => $this->postInfo['post_user'])) . "'>{$this->postInfo['user_name']}</a>";
+				return LAN_FORUM_2031 . ': ' . $gen->convert_date($this->postInfo['user_join'], 'forum') . '<br />';
 			}
 			else
 			{
-				return '<b>' . e107::getParser()->toHTML($this->postInfo['post_user_anon']) . '</b>';
-			}
-
-		}
-
-		function sc_emailimg()
-		{
-			if($this->postInfo['user_name'])
-			{
-				return (!$this->postInfo['user_hideemail'] ? e107::getParser()->parseTemplate("{EMAILTO={$this->postInfo['user_email']}}") : '');
-			}
-
-			return '';
-
-		}
-
-		function sc_emailitem()
-		{
-			if($this->postInfo['thread_start'])
-			{
-				return e107::getParser()->parseTemplate("{EMAIL_ITEM=" . LAN_FORUM_2044 . "^plugin:forum.{$this->postInfo['post_thread']}}");
+				return LAN_FORUM_2031 . ': ' . $gen->convert_date($this->postInfo['user_join'], $parm['dateformat']) . '<br />';
 			}
 		}
+	}
 
-		function sc_printitem()
+
+	function sc_threaddatestamp($parm = '')
+	{
+
+
+		if(empty($this->postInfo['post_datestamp']))
 		{
-			if($this->postInfo['thread_start'])
-			{
-				return e107::getParser()->parseTemplate("{PRINT_ITEM=" . LAN_FORUM_2045 . "^plugin:forum.{$this->postInfo['post_thread']}}");
-			}
+			return null;
 		}
 
-		function sc_signature($parm = '')
+		$gen = e107::getDate();
+
+		if($parm === 'relative')
 		{
-			if(!USER)
+			return $gen->computeLapse($this->postInfo['post_datestamp'], time(), false, true, 'short');
+		}
+
+		// XXX what is this line meant to do?
+		// $text = "<a id='post_{$this->postInfo['post_id']}' href='".$this->e107->url->create('forum/thread/post', array('name' => $this->postInfo['thread_name'], 'thread' => $this->postInfo['post_thread'], 'id' => $this->postInfo['post_id']))."'>".IMAGE_post."</a> ";
+		return $gen->convert_date($this->postInfo['post_datestamp'], 'forum');
+	}
+
+	function sc_postid()
+	{
+
+		return !empty($this->postInfo['post_id']) ? $this->postInfo['post_id'] : null;
+	}
+
+	/* Preferred - as {POST} may conflict with other shortcodes */
+	function sc_thread_text($parm = null)
+	{
+
+		return $this->sc_post($parm = null);
+	}
+
+	/**
+	 * @deprecated - use {THREAD_TEXT}
+	 */
+	function sc_post($parm = null)
+	{
+
+		if(empty($this->postInfo['post_entry']))
+		{
+			return null;
+		}
+
+		//	return print_a($this->postInfo['post_entry'],true);
+		$emote = (isset($this->postInfo['post_options']['no_emote']) ? ',emotes_off' : '');
+
+		$uclass = (!empty($this->postInfo['user_class'])) ? $this->postInfo['user_class'] : 0;
+
+		return e107::getParser()->toHTML($this->postInfo['post_entry'], true, 'USER_BODY' . $emote, 'class:' . $uclass);
+	}
+
+	function sc_postdeleted()
+	{
+
+		if(!empty($this->postInfo['post_status']))
+		{
+			$info = unserialize($this->postInfo['post_options']);
+
+			return "
+			" . LAN_FORUM_2037 . ": {$info['deldate']}<br />
+			" . LAN_FORUM_2038 . ": {$info['delreason']}
+			";
+			//	$ret = '<pre>'.print_r($info, true).'</pre>';
+		}
+	}
+
+
+	function sc_attachments($parm = array())
+	{
+
+		$tp = e107::getParser();
+
+		if(!empty($this->postInfo['post_attachments']))
+		{
+			$baseDir = $this->forum->getAttachmentPath($this->postInfo['post_user']);
+
+			$images = array();
+			$txt = '';
+
+			$attachArray = e107::unserialize($this->postInfo['post_attachments']);
+
+			$thumbAtt = (!empty($this->defaultImgAttachSize)) ? array('w' => $this->defaultImgAttachSize, 'x' => 1) : null;
+
+			//print_a($attachArray);
+
+			foreach($attachArray as $type => $vals)
 			{
-				return '';
-			}
-			global $forum;
-			$tp = e107::getParser();
-			static $forum_sig_shown;
-			if($forum->prefs->get('sig_once'))
-			{
-				$_tmp = 'forum_sig_shown_' . $this->postInfo['post_user'];
-				if(e107::getRegistry($_tmp))
+				foreach($vals as $key => $file)
 				{
-					return '';
+					if(is_array($file))
+					{
+
+						$name = !empty($file['name']) ? $file['name'] : $file['file'];
+
+						$file = $file['file'];
+					}
+					else
+					{
+						list($date, $user, $name) = explode("_", $file, 3);
+					}
+
+					switch($type)
+					{
+						case "file":
+
+							$url = e_REQUEST_SELF . "?id=" . $this->postInfo['post_id'] . "&amp;dl=" . $key;
+
+							$saveicon = (deftrue('FONTAWESOME')) ? 'fa-save' : 'icon-save.glyph';
+							$saveicon = e107::getParser()->toGlyph($saveicon, false);
+
+							if(defset("BOOTSTRAP"))
+							{
+								$txt .= "<a class='forum-attachment-file btn btn-sm btn-default' href='" . $url . "'>" . $saveicon . " {$name}</a><br />";
+							}
+							else
+							{
+								$txt .= IMAGE_attachment . " <a href='" . $url . "'>{$name}</a><br />";
+							}
+
+							break;
+
+						case 'img': //Always use thumb to hide the hash.
+
+
+							//	return $baseDir.$file;
+							if(file_exists($baseDir . $file))
+							{
+								$thumb = $tp->thumbUrl($baseDir . $file, $thumbAtt, true);
+								$full = $tp->thumbUrl($baseDir . $file, 'w=0&x=1', true);
+
+								//TODO Use jQuery zoom instead.
+
+								$caption = $name;
+
+								$inc = (vartrue($parm['modal'])) ? "data-modal-caption=\"" . $caption . "\" data-target='#uiModal' " : "";
+								$images[] = "<a  {$inc} rel='external' href='{$full}' class='forum-attachment-image e-modal' ><img class='thumbnail' src='{$thumb}' alt='' /></a>";
+							}
+							elseif(ADMIN)
+							{
+								$images[] = "Missing File: " . $baseDir . $file;
+							}
+
+
+							break;
+					}
+
 				}
-				e107::setRegistry($_tmp, 1);
+
 			}
 
-			if($parm == 'clean')
+			if(count($images))
 			{
-				return ($this->postInfo['user_signature'] ? trim($tp->toHTML($this->postInfo['user_signature'], true)) : "");
-			}
-
-
-			return ($this->postInfo['user_signature'] ? "<br /><hr style='width:15%; text-align:left' /><span class='smalltext'>" . trim($tp->toHTML($this->postInfo['user_signature'], true)) . '</span>' : '');
-		}
-
-		function sc_profileimg()
-		{
-			if(USER && $this->postInfo['user_name'])
-			{
-				return e107::getParser()->parseTemplate("{PROFILE={$this->postInfo['post_user']}}");
-			}
-		}
-
-		function sc_posts()
-		{
-			if($this->postInfo['post_user'])
-			{
-				return LAN_FORUM_2032 . ': ' . (int) $this->postInfo['user_plugin_forum_posts'] . '<br />';
-			}
-		}
-
-		function sc_visits()
-		{
-			if($this->postInfo['user_name'])
-			{
-				return LAN_FORUM_2033 . ': ' . $this->postInfo['user_visits'] . '<br />';
-			}
-		}
-
-		function sc_customtitle()
-		{
-			if($this->postInfo['user_customtitle'])
-			{
-				return e107::getParser()->toHTML($this->postInfo['user_customtitle']) . '<br />';
-			}
-		}
-
-		function sc_website()
-		{
-			if(!empty($this->postInfo['user_homepage']))
-			{
-				return LAN_FORUM_2034 . ': ' . $this->postInfo['user_homepage'] . '<br />';
-			}
-		}
-
-		function sc_websiteimg()
-		{
-			if($this->postInfo['user_homepage'] && $this->postInfo['user_homepage'] != 'http://')
-			{
-				return "<a href='{$this->postInfo['user_homepage']}'>" . IMAGE_website . '</a>';
-			}
-		}
-
-		function sc_editimg()
-		{
-			if(USER && $this->postInfo['post_user'] == USERID && $this->thread->threadInfo['thread_active'])
-			{
-				$qry = array('f' => 'edit', 'id' => $this->postInfo['post_thread'], 'post' => $this->postInfo['post_id']);
-				$editURL = e107::url('forum', 'post', null, array('query' => $qry));
-
-				return "<a class='e-tip' href='" . $editURL . "' title=\"" . LAN_EDIT . "\">" . IMAGE_edit . '</a> ';
-			}
-		}
-
-		function sc_quoteimg()
-		{
-			if($this->forum->checkperm($this->postInfo['post_forum'], 'post'))
-			{
-				$qry = array('f' => 'quote', 'id' => $this->postInfo['post_thread'], 'post' => $this->postInfo['post_id']);
-				$quoteURL = e107::url('forum', 'post', null, array('query' => $qry));
-
-				return "<a class='e-tip' href='" . $quoteURL . "' title=\"" . LAN_FORUM_2041 . "\">" . IMAGE_quote . '</a> ';
-			}
-		}
-
-		function sc_reportimg()
-		{
-			if(USER)
-			{
-				$qry = array('f' => 'report', 'id' => $this->postInfo['post_thread'], 'post' => $this->postInfo['post_id']);
-				$reportURL = e107::url('forum', 'post', null, array('query' => $qry));
-
-				return "<a class='e-tip' href='" . $reportURL . "' title=\"" . LAN_FORUM_2046 . "\">" . IMAGE_report . '</a> ';
-			}
-		}
-
-		function sc_rpg()
-		{
-			return rpg($this->postInfo['user_join'], $this->postInfo['user_plugin_forum_posts']);
-		}
-
-		function sc_memberid()
-		{
-			if(!$this->postInfo['post_user'])
-			{
-				return false;
-			}
-
-			return "<span class='smalltext'>" . LAN_FORUM_2035 . ' #' . $this->postInfo['post_user'] . '</span>';
-		}
-
-		function sc_level($parm)
-		{
-
-			if(isset($this->pref['ranks']) && empty($this->pref['ranks']))
-			{
-				return false;
-			}
-
-
-			if(!$this->postInfo['post_user'])
-			{
-				return '';
-			}
-
-			$rankInfo = e107::getRank()->getRanks($this->postInfo['post_user']);
-			// FIXME - level handler!!!
-
-			//	print_a($rankInfo);
-			
-
-			if($parm == 'badge')
-			{
-				if(!empty($rankInfo['name']))
+				if(deftrue('BOOTSTRAP'))
 				{
-					return "<span class='label label-info'>" . $rankInfo['name'] . "</span>";
+
+					return "<ul class='thumbnails list-unstyled list-inline'><li>" . implode("</li><li>", $images) . "</li></ul>" . vartrue($txt);
+				}
+				else
+				{
+					return implode("<br />", $images) . "<br />" . vartrue($txt);
 				}
 			}
 
-			if(!$parm)
-			{
-				$parm = 'name';
-			}
-
-
-			switch($parm)
-			{
-
-				case 'userid' :
-					return $this->sc_memberid();
-					break;
-
-				case 'special':
-					if(isset($rankInfo['special']))
-					{
-						return $rankInfo['special'];
-					}
-					if($this->forum->isModerator($this->postInfo['post_user']))
-					{
-						return "<div class='spacer'>" . IMAGE_rank_moderator_image . '</div>';
-					}
-
-					return '';
-					break;
-
-				case 'glyph':
-					$text = "";
-					$tp = e107::getParser();
-					for($i = 0; $i < $rankInfo['value']; $i++)
-					{
-						$text .= $tp->toGlyph('fa-star');
-					}
-
-					return $text;
-					break;
-
-				default:
-					return varset($rankInfo[$parm], '');
-					break;
-			}
+			return $txt;
 		}
 
-		function sc_modoptions()
+	}
+
+	function sc_privmessage()
+	{
+
+		if(e107::isInstalled('pm') && ($this->postInfo['post_user'] > 0))
 		{
-			if(MODERATOR)
-			{
-				return showmodoptions();
-			}
+			return e107::getParser()->parseTemplate("{SENDPM={$this->postInfo['post_user']}}");
+		}
+	}
+
+	function sc_avatar($opts = null)
+	{
+
+		return e107::getParser()->toAvatar($this->postInfo, $opts);
+		// return $tp->parseTemplate("{USER_AVATAR=".$this->postInfo['user_image']."}", true);
+	}
+
+	function sc_anon_ip()
+	{
+
+		if(!empty($this->postInfo['post_user_anon']) && (ADMIN || deftrue('MODERATOR')))
+		{
+			return e107::getIPHandler()->ipDecode($this->postInfo['post_ip']);
+		}
+	}
+
+	function sc_ip()
+	{
+
+		if((ADMIN || deftrue('MODERATOR')) && empty($this->postInfo['user_admin']) && !empty($this->postInfo['post_ip']))
+		{
+			return e107::getIPHandler()->ipDecode($this->postInfo['post_ip']);
 		}
 
-		function sc_lastedit()
+	}
+
+	function sc_poster()
+	{
+
+		if(!empty($this->postInfo['user_name']))
 		{
-			$gen = e107::getDate();
-			if($this->postInfo['post_edit_datestamp'])
-			{
-				return $gen->convert_date($this->postInfo['post_edit_datestamp'], 'forum');
-			}
+			return "<a href='" . e107::getUrl()->create('user/profile/view', array('name' => $this->postInfo['user_name'], 'id' => $this->postInfo['post_user'])) . "'>{$this->postInfo['user_name']}</a>";
+		}
+		elseif(!empty($this->postInfo['post_user_anon']))
+		{
+			return '<b>' . e107::getParser()->toHTML($this->postInfo['post_user_anon']) . '</b>';
 		}
 
-		function sc_lasteditby($parm = '')
+	}
+
+	function sc_emailimg()
+	{
+
+		if(!empty($this->postInfo['user_name']))
 		{
-			if(isset($this->postInfo['edit_name']))
-			{
-				if($parm == 'link')
-				{
-					$url = e107::getUrl()->create('user/profile/view', array('name' => $this->postInfo['edit_name'], 'id' => $this->postInfo['post_edit_user']));
-
-					return "<a href='{$url}'>{$this->postInfo['edit_name']}</a>";
-				}
-
-				return $this->postInfo['edit_name'];
-			}
+			return (!$this->postInfo['user_hideemail'] ? e107::getParser()->parseTemplate("{EMAILTO={$this->postInfo['user_email']}}") : '');
 		}
 
-		function sc_poll()
-		{
-			if($this->postInfo['thread_start'] == 1)
-			{
-				global $pollstr;
+		return '';
 
-				return $pollstr;
-			}
+	}
+
+	function sc_emailitem()
+	{
+
+		if(!empty($this->postInfo['thread_start']))
+		{
+			return e107::getParser()->parseTemplate("{EMAIL_ITEM=" . LAN_FORUM_2044 . "^plugin:forum.{$this->postInfo['post_thread']}}");
 		}
+	}
 
-		function sc_newflag()
+	function sc_printitem()
+	{
+
+		if(!empty($this->postInfo['thread_start']))
+		{
+			return e107::getParser()->parseTemplate("{PRINT_ITEM=" . LAN_FORUM_2045 . "^plugin:forum.{$this->postInfo['post_thread']}}");
+		}
+	}
+
+	function sc_signature($parm = '')
+	{
+
+		if(!USER)
 		{
-			// Defined in case an indicator is required
 			return '';
 		}
 
-		function sc_usercombo()
+		static $forum_sig_shown;
+		if(!empty($this->pref['sig_once']))
+		{
+			$_tmp = 'forum_sig_shown_' . $this->postInfo['post_user'];
+			if(e107::getRegistry($_tmp))
+			{
+				return '';
+			}
+			e107::setRegistry($_tmp, 1);
+		}
+
+		$tp = e107::getParser();
+
+		if($parm == 'clean')
+		{
+			return ($this->postInfo['user_signature'] ? trim($tp->toHTML($this->postInfo['user_signature'], true)) : "");
+		}
+
+
+		return (!empty($this->postInfo['user_signature']) ? "<br /><hr style='width:15%; text-align:left' /><span class='smalltext'>" . trim($tp->toHTML($this->postInfo['user_signature'], true)) . '</span>' : '');
+	}
+
+	function sc_profileimg()
+	{
+
+		if(USER && !empty($this->postInfo['user_name']))
+		{
+			return e107::getParser()->parseTemplate("{PROFILE={$this->postInfo['post_user']}}");
+		}
+	}
+
+	function sc_posts()
+	{
+
+		if(!empty($this->postInfo['post_user']))
+		{
+			return LAN_FORUM_2032 . ': ' . (int) $this->postInfo['user_plugin_forum_posts'] . '<br />';
+		}
+	}
+
+	function sc_visits()
+	{
+
+		if(!empty($this->postInfo['user_name']))
+		{
+			return LAN_FORUM_2033 . ': ' . varset($this->postInfo['user_visits']) . '<br />';
+		}
+	}
+
+	function sc_customtitle()
+	{
+
+		if(!empty($this->postInfo['user_customtitle']))
+		{
+			return e107::getParser()->toHTML($this->postInfo['user_customtitle']) . '<br />';
+		}
+	}
+
+	function sc_website()
+	{
+
+		if(!empty($this->postInfo['user_homepage']))
+		{
+			return LAN_FORUM_2034 . ': ' . $this->postInfo['user_homepage'] . '<br />';
+		}
+	}
+
+	function sc_websiteimg()
+	{
+
+		if(!empty($this->postInfo['user_homepage']) && $this->postInfo['user_homepage'] !== 'http://')
+		{
+			return "<a href='{$this->postInfo['user_homepage']}'>" . defset('IMAGE_website') . '</a>';
+		}
+	}
+
+	function sc_editimg()
+	{
+
+		if(USER && !empty($this->postInfo['post_user']) && $this->postInfo['post_user'] == USERID && $this->thread->threadInfo['thread_active'])
+		{
+			$qry = array('f' => 'edit', 'id' => $this->postInfo['post_thread'], 'post' => $this->postInfo['post_id']);
+			$editURL = e107::url('forum', 'post', null, array('query' => $qry));
+
+			return "<a class='e-tip' href='" . $editURL . "' title=\"" . LAN_EDIT . "\">" . IMAGE_edit . '</a> ';
+		}
+	}
+
+	function sc_quoteimg()
+	{
+
+		if(isset($this->postInfo['post_forum']) && $this->forum->checkperm($this->postInfo['post_forum'], 'post'))
+		{
+			$qry = array('f' => 'quote', 'id' => $this->postInfo['post_thread'], 'post' => $this->postInfo['post_id']);
+			$quoteURL = e107::url('forum', 'post', null, array('query' => $qry));
+
+			return "<a class='e-tip' href='" . $quoteURL . "' title=\"" . LAN_FORUM_2041 . "\">" . IMAGE_quote . '</a> ';
+		}
+	}
+
+	function sc_reportimg()
+	{
+
+		if(USER && !empty($this->postInfo['post_thread']))
+		{
+			$qry = array('f' => 'report', 'id' => $this->postInfo['post_thread'], 'post' => $this->postInfo['post_id']);
+			$reportURL = e107::url('forum', 'post', null, array('query' => $qry));
+
+			return "<a class='e-tip' href='" . $reportURL . "' title=\"" . LAN_FORUM_2046 . "\">" . IMAGE_report . '</a> ';
+		}
+	}
+
+	function sc_rpg()
+	{
+
+		if(!function_exists('rpg'))
+		{
+			return null;
+		}
+
+		return rpg($this->postInfo['user_join'], $this->postInfo['user_plugin_forum_posts']);
+	}
+
+	function sc_memberid()
+	{
+
+		if(empty($this->postInfo['post_user']))
+		{
+			return false;
+		}
+
+		return "<span class='smalltext'>" . LAN_FORUM_2035 . ' #' . $this->postInfo['post_user'] . '</span>';
+	}
+
+	function sc_level($parm = null)
+	{
+
+		if(isset($this->pref['ranks']) && empty($this->pref['ranks']))
+		{
+			return false;
+		}
+
+
+		if(empty($this->postInfo['post_user']))
+		{
+			return '';
+		}
+
+		$rankInfo = e107::getRank()->getRanks($this->postInfo['post_user']);
+		// FIXME - level handler!!!
+
+		//	print_a($rankInfo);
+
+
+		if($parm == 'badge')
+		{
+			if(!empty($rankInfo['name']))
+			{
+				return "<span class='label label-info'>" . $rankInfo['name'] . "</span>";
+			}
+		}
+
+		if(!$parm)
+		{
+			$parm = 'name';
+		}
+
+
+		switch($parm)
 		{
 
-			$tp = e107::getParser();
+			case 'userid' :
+				return $this->sc_memberid();
+				break;
 
-			//	$text2 = $this->sc_level('special');
-			//	$text .= $this->sc_level('pic');
+			case 'special':
+				if(isset($rankInfo['special']))
+				{
+					return $rankInfo['special'];
+				}
+				if($this->forum->isModerator($this->postInfo['post_user']))
+				{
+					return "<div class='spacer'>" . IMAGE_rank_moderator_image . '</div>';
+				}
 
-			$ue = $tp->parseTemplate("{USER_EXTENDED=location.text_value}", true);
-			$username = (empty($this->postInfo['user_name'])) ? LAN_ANONYMOUS : $this->postInfo['user_name'];
+				return '';
+				break;
 
-			$userUrl = empty($this->postInfo['post_user']) ? '#' : e107::getUrl()->create('user/profile/view', array('user_id' => $this->postInfo['post_user'], 'user_name' => $username));
-			// e_HTTP.'user.php?id.'.$this->postInfo['post_user']
-			$text = '<div class="btn-group ">
+			case 'glyph':
+				$text = "";
+				$tp = e107::getParser();
+				for($i = 0; $i < $rankInfo['value']; $i++)
+				{
+					$text .= $tp->toGlyph('fa-star');
+				}
+
+				return $text;
+				break;
+
+			default:
+				return varset($rankInfo[$parm], '');
+				break;
+		}
+	}
+
+	function sc_modoptions()
+	{
+
+		if(deftrue('MODERATOR'))
+		{
+			return showmodoptions();
+		}
+	}
+
+	function sc_lastedit()
+	{
+
+		if(!empty($this->postInfo['post_edit_datestamp']))
+		{
+			return e107::getDate()->convert_date($this->postInfo['post_edit_datestamp'], 'forum');
+		}
+	}
+
+	function sc_lasteditby($parm = '')
+	{
+
+		if(isset($this->postInfo['edit_name']))
+		{
+			if($parm == 'link')
+			{
+				$url = e107::getUrl()->create('user/profile/view', array('name' => $this->postInfo['edit_name'], 'id' => $this->postInfo['post_edit_user']));
+
+				return "<a href='{$url}'>{$this->postInfo['edit_name']}</a>";
+			}
+
+			return $this->postInfo['edit_name'];
+		}
+	}
+
+	function sc_poll()
+	{
+
+		if(isset($this->postInfo['thread_start']) && ($this->postInfo['thread_start'] == 1))
+		{
+			global $pollstr;
+
+			return $pollstr;
+		}
+	}
+
+	function sc_newflag()
+	{
+
+		// Defined in case an indicator is required
+		return '';
+	}
+
+	function sc_usercombo()
+	{
+
+		$tp = e107::getParser();
+
+		//	$text2 = $this->sc_level('special');
+		//	$text .= $this->sc_level('pic');
+
+		$ue = $tp->parseTemplate("{USER_EXTENDED=location.text_value}", true);
+		$username = (empty($this->postInfo['user_name'])) ? LAN_ANONYMOUS : $this->postInfo['user_name'];
+
+		$userUrl = empty($this->postInfo['post_user']) ? '#' : e107::getUrl()->create('user/profile/view', array('user_id' => $this->postInfo['post_user'], 'user_name' => $username));
+		// e_HTTP.'user.php?id.'.$this->postInfo['post_user']
+		$text = '<div class="btn-group ">
 
     <a class="btn btn-default btn-secondary btn-sm btn-small" href="' . $userUrl . '">' . $username . '</a>
     <button class="btn btn-default btn-secondary btn-sm btn-small dropdown-toggle" data-toggle="dropdown">
@@ -803,436 +869,470 @@
     <ul class="dropdown-menu left">
     ';
 
-			$text .= "<li><a href='#'>" . $this->sc_level('userid') . "</a></li>";
-			$text .= "<li><a href='#'>" . $this->sc_joined() . "</a></li>";
-			if($ue)
+		$text .= "<li><a href='#'>" . $this->sc_level('userid') . "</a></li>";
+		$text .= "<li><a href='#'>" . $this->sc_joined() . "</a></li>";
+		if($ue)
+		{
+			$text .= "<li><a hre='#'>" . $ue . "</a></li>";
+		}
+		$text .= "<li><a href='#'>" . $this->sc_posts() . "</a></li>";
+
+
+		if(e107::isInstalled('pm') && ($this->postInfo['post_user'] > 0))
+		{
+			if($pmButton = $tp->parseTemplate("{SENDPM: user=" . $this->postInfo['post_user'] . "&glyph=envelope&class=pm-send}", true))
 			{
-				$text .= "<li><a hre='#'>" . $ue . "</a></li>";
-			}
-			$text .= "<li><a href='#'>" . $this->sc_posts() . "</a></li>";
-
-
-			if(e107::isInstalled('pm') && ($this->postInfo['post_user'] > 0))
-			{
-				if($pmButton = $tp->parseTemplate("{SENDPM: user=" . $this->postInfo['post_user'] . "&glyph=envelope&class=pm-send}", true))
-				{
-					$text .= "<li class='divider'></li>";
-					$text .= "<li>" . $pmButton . "</li>";
-				}
-
-				// $text .= "<li><a href='".e_PLUGIN_ABS."pm/pm.php?send.{$this->postInfo['post_user']}'>".$tp->toGlyph('envelope')." ".LAN_FORUM_2036." </a></li>";
+				$text .= "<li class='divider'></li>";
+				$text .= "<li>" . $pmButton . "</li>";
 			}
 
-			if($website = $this->sc_website())
-			{
-				$text .= "<li>" . $website . "</li>";
-			}
+			// $text .= "<li><a href='".e_PLUGIN_ABS."pm/pm.php?send.{$this->postInfo['post_user']}'>".$tp->toGlyph('envelope')." ".LAN_FORUM_2036." </a></li>";
+		}
+
+		if($website = $this->sc_website())
+		{
+			$text .= "<li>" . $website . "</li>";
+		}
 
 //	{EMAILIMG}
 //	{WEBSITEIMG}
 
-			$text .= "</ul>
+		$text .= "</ul>
 	</div>";
 
 
-			return $text;
+		return $text;
+	}
+
+
+	function sc_postoptions()
+	{
+
+		$tp = e107::getParser();
+		$threadID = !empty($this->postInfo['post_thread']) ? $this->postInfo['post_thread'] : 0;
+		$postID = !empty($this->postInfo['post_id']) ? $this->postInfo['post_id'] : 0;
+		// {EMAILITEM} {PRINTITEM} {REPORTIMG}{EDITIMG}{QUOTEIMG}
+
+		$text = '<div class="btn-group pull-right float-right">
+    		<button class="btn btn-default btn-secondary btn-sm btn-small dropdown-toggle" data-toggle="dropdown">
+    		' . LAN_FORUM_8013 . '
+    	    ';
+
+		if(defined('BOOTSTRAP') && BOOTSTRAP !== 4)
+		{
+			$text .= '<span class="caret"></span>';
+		}
+
+		$text .= '
+    		</button>
+    		<ul class="dropdown-menu pull-right float-right text-right">';
+
+
+		$text .= "<li class='text-right float-right float-right'><a href='" . e_HTTP . "email.php?plugin:forum." . $threadID . "'>" . LAN_FORUM_2044 . " " . $tp->toGlyph('fa-envelope') . "</a></li>";
+		$text .= "<li class='text-right float-right'><a href='" . e_HTTP . "print.php?plugin:forum." . $threadID . "'>" . LAN_FORUM_2045 . " " . $tp->toGlyph('fa-print') . "</a></li>"; // FIXME
+
+		if(USER) // Report
+		{
+			$urlReport = e107::url('forum', 'post') . "?f=report&amp;id=" . $threadID . "&amp;post=" . $postID;
+			//	$urlReport = $this->e107->url->create('forum/thread/report', "id={$threadID}&post={$postID}");
+			$text .= "<li class='text-right float-right'><a href='" . $urlReport . "'>" . LAN_FORUM_2046 . " " . $tp->toGlyph('fa-flag') . "</a></li>";
+		}
+
+		// Edit
+		if((USER && isset($this->postInfo['post_user']) && $this->postInfo['post_user'] == USERID && $this->thread->threadInfo['thread_active']))
+		{
+
+
+			$url = e107::url('forum', 'post') . "?f=edit&amp;id=" . $threadID . "&amp;post=" . $postID;
+			//$url = e107::getUrl()->create('forum/thread/edit', array('id' => $threadID, 'post'=>$postID));
+			$text .= "<li class='text-right float-right'><a href='" . $url . "'>" . LAN_EDIT . " " . $tp->toGlyph('fa-edit') . "</a></li>";
+
+		}
+
+		// Delete own post, if it is the last in the thread
+		if($this->thisIsTheLastPost && USER && $this->thread->threadInfo['thread_lastuser'] == USERID)
+		{
+			/* only show delete button when post is not the initial post of the topic
+			 * AND if this post is the last post in the thread */
+			if($this->thread->threadInfo['thread_active'] && empty($this->postInfo['thread_start']))
+			{
+				$text .= "<li class='text-right float-right'><a href='" . e_REQUEST_URI . "' data-forum-action='deletepost'  data-confirm='" . LAN_JSCONFIRM . "' data-forum-post='" . $postID . "'>" . LAN_DELETE . " " . $tp->toGlyph('fa-trash') . "</a></li>";
+			}
+		}
+
+		if(isset($this->postInfo['post_forum']) && $this->forum->checkperm($this->postInfo['post_forum'], 'post'))
+		{
+			$url = e107::url('forum', 'post') . "?f=quote&amp;id=" . $threadID . "&amp;post=" . $postID;
+			//$url = e107::getUrl()->create('forum/thread/quote', array('id' => $threadID, 'post'=>$postID));
+			$text .= "<li class='text-right float-right'><a href='" . $url . "'>" . LAN_FORUM_2041 . " " . $tp->toGlyph('fa-share-alt') . "</a></li>";
+
+			//	$text .= "<li class='text-right float-right'><a href='".e107::getUrl()->create('forum/thread/quote', array('id' => $postID))."'>".LAN_FORUM_2041." ".$tp->toGlyph('share-alt')."</a></li>";
 		}
 
 
-		function sc_postoptions()
+		if(defset('MODERATOR'))
 		{
-			$tp = e107::getParser();
-			// {EMAILITEM} {PRINTITEM} {REPORTIMG}{EDITIMG}{QUOTEIMG}
+			$text .= "<li role='presentation' class='divider'> </li>";
+			$type = ($this->postInfo['thread_start']) ? 'thread' : 'Post';
 
-			$text = '<div class="btn-group pull-right float-right">
-    	<button class="btn btn-default btn-secondary btn-sm btn-small dropdown-toggle" data-toggle="dropdown">
-    	' . LAN_FORUM_8013 . '
-    	';
-    	if(defined('BOOTSTRAP') && BOOTSTRAP !== 4)
-    	{
-    		$text .= '<span class="caret"></span>';
-    	}
-    	$text .= '
-    	</button>
-    	<ul class="dropdown-menu pull-right float-right text-right">';
+			//	print_a($this->postInfo);
 
-
-			$text .= "<li class='text-right float-right float-right'><a href='" . e_HTTP . "email.php?plugin:forum." . $this->postInfo['post_thread'] . "'>" . LAN_FORUM_2044 . " " . $tp->toGlyph('fa-envelope') . "</a></li>";
-			$text .= "<li class='text-right float-right'><a href='" . e_HTTP . "print.php?plugin:forum." . $this->postInfo['post_thread'] . "'>" . LAN_FORUM_2045 . " " . $tp->toGlyph('fa-print') . "</a></li>"; // FIXME
-
-			if(USER) // Report
-			{
-				$urlReport = e107::url('forum', 'post') . "?f=report&amp;id=" . $this->postInfo['post_thread'] . "&amp;post=" . $this->postInfo['post_id'];
-				//	$urlReport = $this->e107->url->create('forum/thread/report', "id={$this->postInfo['post_thread']}&post={$this->postInfo['post_id']}");
-				$text .= "<li class='text-right float-right'><a href='" . $urlReport . "'>" . LAN_FORUM_2046 . " " . $tp->toGlyph('fa-flag') . "</a></li>";
-			}
-
-			// Edit
-			if((USER && $this->postInfo['post_user'] == USERID && $this->thread->threadInfo['thread_active']))
+			if((USER && isset($this->postInfo['post_user']) && $this->postInfo['post_user'] != USERID && $this->thread->threadInfo['thread_active']))
 			{
 
+				$url = e107::url('forum', 'post') . "?f=edit&amp;id=" . $threadID . "&amp;post=" . $postID;
+				// $url = e107::getUrl()->create('forum/thread/edit', array('id' => $threadID, 'post'=>$postID));
 
-				$url = e107::url('forum', 'post') . "?f=edit&amp;id=" . $this->postInfo['post_thread'] . "&amp;post=" . $this->postInfo['post_id'];
-				//$url = e107::getUrl()->create('forum/thread/edit', array('id' => $this->postInfo['post_thread'], 'post'=>$this->postInfo['post_id']));
 				$text .= "<li class='text-right float-right'><a href='" . $url . "'>" . LAN_EDIT . " " . $tp->toGlyph('fa-edit') . "</a></li>";
-
 			}
 
-			// Delete own post, if it is the last in the thread
-			if($this->thisIsTheLastPost && USER && $this->thread->threadInfo['thread_lastuser'] == USERID)
+			// only show delete button when post is not the initial post of the topic
+			//	if(!$this->forum->threadDetermineInitialPost($postID))
+			if(empty($this->postInfo['thread_start']))
 			{
-				/* only show delete button when post is not the initial post of the topic
-				 * AND if this post is the last post in the thread */
-				if($this->thread->threadInfo['thread_active'] && empty($this->postInfo['thread_start']) )
-				{
-					$text .= "<li class='text-right float-right'><a href='" . e_REQUEST_URI . "' data-forum-action='deletepost'  data-confirm='".LAN_JSCONFIRM."' data-forum-post='" . $this->postInfo['post_id'] . "'>" . LAN_DELETE . " " . $tp->toGlyph('fa-trash') . "</a></li>";
-				}
+				$text .= "<li class='text-right float-right'><a href='" . e_REQUEST_URI . "' data-forum-action='deletepost' data-confirm='" . LAN_JSCONFIRM . "'  data-forum-post='" . $postID . "'>" . LAN_DELETE . " " . $tp->toGlyph('fa-trash') . "</a></li>";
 			}
 
-			if($this->forum->checkperm($this->postInfo['post_forum'], 'post'))
+			if($type == 'thread')
 			{
-				$url = e107::url('forum', 'post') . "?f=quote&amp;id=" . $this->postInfo['post_thread'] . "&amp;post=" . $this->postInfo['post_id'];
-				//$url = e107::getUrl()->create('forum/thread/quote', array('id' => $this->postInfo['post_thread'], 'post'=>$this->postInfo['post_id']));
-				$text .= "<li class='text-right float-right'><a href='" . $url . "'>" . LAN_FORUM_2041 . " " . $tp->toGlyph('fa-share-alt') . "</a></li>";
-
-				//	$text .= "<li class='text-right float-right'><a href='".e107::getUrl()->create('forum/thread/quote', array('id' => $this->postInfo['post_id']))."'>".LAN_FORUM_2041." ".$tp->toGlyph('share-alt')."</a></li>";
+				$url = e107::url('forum', 'move', array('thread_id' => $threadID));
+				$text .= "<li class='text-right float-right'><a href='" . $url . "'>" . LAN_FORUM_2042 . " " . $tp->toGlyph('fa-arrows') . "</a></li>";
 			}
-
-
-			if(MODERATOR)
+			elseif(e_DEVELOPER === true) //TODO
 			{
-				$text .= "<li role='presentation' class='divider'> </li>";
-				$type = ($this->postInfo['thread_start']) ? 'thread' : 'Post';
+				$text .= "<li class='text-right float-right'><a href='" . e107::url('forum', 'split', array('thread_id' => $threadID, 'post_id' => $postID)) . "'>" . LAN_FORUM_2043 . " " . $tp->toGlyph('fa-cut') . "</a></li>";
 
-				//	print_a($this->postInfo);
-
-				if((USER && $this->postInfo['post_user'] != USERID && $this->thread->threadInfo['thread_active']))
-				{
-
-					$url = e107::url('forum', 'post') . "?f=edit&amp;id=" . $this->postInfo['post_thread'] . "&amp;post=" . $this->postInfo['post_id'];
-					// $url = e107::getUrl()->create('forum/thread/edit', array('id' => $this->postInfo['post_thread'], 'post'=>$this->postInfo['post_id']));
-
-					$text .= "<li class='text-right float-right'><a href='" . $url . "'>" . LAN_EDIT . " " . $tp->toGlyph('fa-edit') . "</a></li>";
-				}
-
-				// only show delete button when post is not the initial post of the topic
-				//	if(!$this->forum->threadDetermineInitialPost($this->postInfo['post_id']))
-				if(empty($this->postInfo['thread_start']))
-				{
-					$text .= "<li class='text-right float-right'><a href='" . e_REQUEST_URI . "' data-forum-action='deletepost' data-confirm='".LAN_JSCONFIRM."'  data-forum-post='" . $this->postInfo['post_id'] . "'>" . LAN_DELETE . " " . $tp->toGlyph('fa-trash') . "</a></li>";
-				}
-
-				if($type == 'thread')
-				{
-					$url = e107::url('forum', 'move', array('thread_id' => $this->postInfo['post_thread']));
-					$text .= "<li class='text-right float-right'><a href='" . $url . "'>" . LAN_FORUM_2042 . " " . $tp->toGlyph('fa-arrows') . "</a></li>";
-				}
-				elseif(e_DEVELOPER === true) //TODO
-				{
-					$text .= "<li class='text-right float-right'><a href='" . e107::url('forum', 'split', array('thread_id' => $this->postInfo['post_thread'], 'post_id' => $this->postInfo['post_id'])) . "'>" . LAN_FORUM_2043 . " " . $tp->toGlyph('fa-cut') . "</a></li>";
-
-				}
 			}
+		}
 
 
-			$text .= '
+		$text .= '
 		</ul>
 		</div>';
 
-			return $text;
+		return $text;
 
 
-		}
+	}
 
 //---- SHORTCODES CONVERTED FROM $tVars....
-		function sc_threadname($parm=null)
+	function sc_threadname($parm = null)
+	{
+
+		return e107::getParser()->toHTML($this->var['thread_name'], true, 'no_hook, emotes_off');
+	}
+
+	function sc_nextprev()
+	{
+
+		global $thread;
+
+		if(!is_object($thread))
 		{
-			return e107::getParser()->toHTML($this->var['thread_name'], true, 'no_hook, emotes_off');
+			return null;
 		}
 
-		function sc_nextprev()
+		$prev = $this->forum->threadGetNextPrev('prev', $thread->threadId, $this->var['forum_id'], $this->var['thread_lastpost']);
+		$next = $this->forum->threadGetNextPrev('next', $thread->threadId, $this->var['forum_id'], $this->var['thread_lastpost']);
+
+		$options = array();
+
+		if($prev !== false)
 		{
-			global $forum, $thread;
-			$prev = $forum->threadGetNextPrev('prev', $thread->threadId, $this->var['forum_id'], $this->var['thread_lastpost']);
-			$next = $forum->threadGetNextPrev('next', $thread->threadId, $this->var['forum_id'], $this->var['thread_lastpost']);
-
-			$options = array();
-
-			if($prev !== false)
-			{
-				$options[] = "<a class='btn btn-default btn-secondary btn-sm btn-small' href='" . e107::url('forum', 'topic', $prev) . "'>&laquo; " . LAN_FORUM_2001 . "</a>";
-			}
-			if($next !== false)
-			{
-				$options[] = "<a class='btn btn-default btn-secondary btn-sm btn-small' href='" . e107::url('forum', 'topic', $next) . "'>" . LAN_FORUM_2002 . " &raquo;</a>";
-			}
+			$options[] = "<a class='btn btn-default btn-secondary btn-sm btn-small' href='" . e107::url('forum', 'topic', $prev) . "'>&laquo; " . LAN_FORUM_2001 . "</a>";
+		}
+		if($next !== false)
+		{
+			$options[] = "<a class='btn btn-default btn-secondary btn-sm btn-small' href='" . e107::url('forum', 'topic', $next) . "'>" . LAN_FORUM_2002 . " &raquo;</a>";
+		}
 
 //----	$tVars->NEXTPREV = implode(" | ", $options);
-			return implode(" | ", $options);
-		}
+		return implode(" | ", $options);
+	}
 
 
-		function sc_track()
+	function sc_track()
+	{
+
+		global $forum;
+		if(!empty($this->pref['track']) && USER)
 		{
-			global $forum;
-			if($forum->prefs->get('track') && USER)
+			// BC Fix for old template.
+			if(!defined('IMAGE_track'))
 			{
-				// BC Fix for old template.
-				if(!defined('IMAGE_track'))
-				{
-					define('IMAGE_track', '<img src="' . img_path('track.png') . '" alt="' . LAN_FORUM_4009 . '" title="' . LAN_FORUM_4009 . '" class="icon S16 action" />');
-				}
+				define('IMAGE_track', '<img src="' . img_path('track.png') . '" alt="' . LAN_FORUM_4009 . '" title="' . LAN_FORUM_4009 . '" class="icon S16 action" />');
+			}
 
-				if(!defined('IMAGE_untrack'))
-				{
-					define('IMAGE_untrack', '<img src="' . img_path('untrack.png') . '" alt="' . LAN_FORUM_4010 . '" title="' . LAN_FORUM_4010 . '" class="icon S16 action" />');
-				}
+			if(!defined('IMAGE_untrack'))
+			{
+				define('IMAGE_untrack', '<img src="' . img_path('untrack.png') . '" alt="' . LAN_FORUM_4010 . '" title="' . LAN_FORUM_4010 . '" class="icon S16 action" />');
+			}
 
 
-				$img = ($this->var['track_userid'] ? IMAGE_track : IMAGE_untrack);
+			$img = (!empty($this->var['track_userid']) ? defset('IMAGE_track') : defset('IMAGE_untrack'));
 
 
-				/*
-					$url = $e107->url->create('forum/thread/view', array('id' => $thread->threadId), 'encode=0'); // encoding could break AJAX call
+			/*
+				$url = $e107->url->create('forum/thread/view', array('id' => $thread->threadId), 'encode=0'); // encoding could break AJAX call
 
-					$url = e107::url('forum','index');
+				$url = e107::url('forum','index');
 
-					$tVars->TRACK .= "
-							<span id='forum-track-trigger-container'>
-							<a class='btn btn-default btn-sm btn-small e-ajax' data-target='forum-track-trigger' href='{$url}' id='forum-track-trigger'>{$img}</a>
-							</span>
-							<script type='text/javascript'>
-							e107.runOnLoad(function(){
-								$('forum-track-trigger').observe('click', function(e) {
-									e.stop();
-									new e107Ajax.Updater('forum-track-trigger-container', '{$url}', {
-										method: 'post',
-										parameters: { //send query parameters here
-											'track_toggle': 1
-										},
-										overlayPage: $(document.body)
-									});
+				$tVars->TRACK .= "
+						<span id='forum-track-trigger-container'>
+						<a class='btn btn-default btn-sm btn-small e-ajax' data-target='forum-track-trigger' href='{$url}' id='forum-track-trigger'>{$img}</a>
+						</span>
+						<script type='text/javascript'>
+						e107.runOnLoad(function(){
+							$('forum-track-trigger').observe('click', function(e) {
+								e.stop();
+								new e107Ajax.Updater('forum-track-trigger-container', '{$url}', {
+									method: 'post',
+									parameters: { //send query parameters here
+										'track_toggle': 1
+									},
+									overlayPage: $(document.body)
 								});
-							}, document, true);
-							</script>
-					";*/
+							});
+						}, document, true);
+						</script>
+				";*/
 
 
-				$trackDiz = ($forum->prefs->get('trackemail', true)) ? LAN_FORUM_3040 : LAN_FORUM_3041;
+			$trackDiz = (varset($this->pref['track'], true)) ? LAN_FORUM_3040 : LAN_FORUM_3041;
 
 //	$tVars->TRACK = "<a id='forum-track-button' href='#' title=\"".$trackDiz."\" data-token='".deftrue('e_TOKEN','')."' data-forum-insert='forum-track-button'  data-forum-post='".$thread->threadInfo['thread_forum_id']."' data-forum-thread='".$thread->threadInfo['thread_id']."' data-forum-action='track' name='track' class='e-tip btn btn-default' >".$img."</a>";
-				return "<a id='forum-track-button' href='#' title=\"" . $trackDiz . "\" data-token='" . deftrue('e_TOKEN', '') . "' data-forum-insert='forum-track-button'  data-forum-post='" . $this->var['thread_forum_id'] . "' data-forum-thread='" . $this->var['thread_id'] . "' data-forum-action='track' name='track' class='e-tip btn btn-default' >" . $img . "</a>";
+			return "<a id='forum-track-button' href='#' title=\"" . $trackDiz . "\" data-token='" . deftrue('e_TOKEN', '') . "' data-forum-insert='forum-track-button'  data-forum-post='" . $this->var['thread_forum_id'] . "' data-forum-thread='" . $this->var['thread_id'] . "' data-forum-action='track' name='track' class='e-tip btn btn-default' >" . $img . "</a>";
 
-			}
-
-			return '';
 		}
 
-		function sc_moderators()
+		return '';
+	}
+
+	function sc_moderators()
+	{
+
+		$modUser = array();
+		foreach($this->forum->modArray as $user)
 		{
-			$modUser = array();
-			foreach($this->forum->modArray as $user)
+			$modUser[] = "<a href='" . e107::getUrl()->create('user/profile/view', $user) . "'>" . $user['user_name'] . "</a>";
+		}
+
+
+		return LAN_FORUM_2003 . ": " . implode(', ', $modUser);
+
+	}
+
+	function sc_threadstatus()
+	{
+
+		return (!$this->var['thread_active'] ? LAN_FORUM_2004 : '');
+	}
+
+
+	function sc_gotopages()
+	{
+
+		global $thread;
+
+		if(!is_object($thread))
+		{
+			e107::getDebug()->log('$thread was empty');
+
+			return null;
+		}
+
+
+		if($thread->pages > 1)
+		{
+			if(!$thread->page)
 			{
-				$modUser[] = "<a href='" . e107::getUrl()->create('user/profile/view', $user) . "'>" . $user['user_name'] . "</a>";
+				$thread->page = 1;
 			}
 
+			// issue #3171 old method produced an invalid url: /forum/subforum/35/forum-topic/&p=2
+			// moved additional parameter p= to the options/query array
+			$url = e107::url('forum', 'topic', $this->var, array('query' => array('p' => '--FROM--'))); // . "&amp;p=[FROM]";
 
-			return LAN_FORUM_2003 . ": " . implode(', ', $modUser);
+			$parms = "total={$thread->pages}&type=page&current={$thread->page}&url=" . urlencode($url) . "&caption=off&tmpl=default&navcount=4&glyphs=1";
 
+			return e107::getParser()->parseTemplate("{NEXTPREV={$parms}}");
 		}
-
-		function sc_threadstatus()
-		{
-			return (!$this->var['thread_active'] ? LAN_FORUM_2004 : '');
-		}
+	}
 
 
-		function sc_gotopages()
-		{
-			global $thread;
-			if($thread->pages > 1)
-			{
-				if(!$thread->page)
-				{
-					$thread->page = 1;
-				}
+	function sc_buttons()
+	{
 
-				// issue #3171 old method produced an invalid url: /forum/subforum/35/forum-topic/&p=2
-				// moved additional parameter p= to the options/query array
-				$url = e107::url('forum', 'topic', $this->var, array('query' => array('p' => '--FROM--'))); // . "&amp;p=[FROM]";
-
-				$parms = "total={$thread->pages}&type=page&current={$thread->page}&url=" . urlencode($url) . "&caption=off&tmpl=default&navcount=4&glyphs=1";
-
-				return e107::getParser()->parseTemplate("{NEXTPREV={$parms}}");
-			}
-		}
-
-
-		function sc_buttons()
-		{
-			global $forum, $thread;
+		global $thread;
 //----$tVars->BUTTONS = '';
-			if($forum->checkPerm($this->var['thread_forum_id'], 'post') && $this->var['thread_active'])
-			{
-				// print_a($thread->threadInfo);
-				$url = e107::url('forum', 'post') . "?f=rp&amp;id=" . $this->var['thread_id'] . "&amp;post=" . $thread->threadId;
+		if($this->forum->checkPerm($this->var['thread_forum_id'], 'post') && $this->var['thread_active'])
+		{
+			// print_a($thread->threadInfo);
+			$url = e107::url('forum', 'post') . "?f=rp&amp;id=" . $this->var['thread_id'] . "&amp;post=" . $thread->threadId;
 
 //	$url = $e107->url->create('forum/thread/reply', array('id' => $thread->threadId));
-				return "<a href='" . $url . "'>" . IMAGE_reply . "</a>";
-			}
-			if($forum->checkPerm($this->var['thread_forum_id'], 'thread'))
-			{
-				$ntUrl = e107::url('forum', 'post') . "?f=nt&amp;id=" . $this->var['thread_forum_id'];
+			return "<a href='" . $url . "'>" . IMAGE_reply . "</a>";
+		}
+		if($this->forum->checkPerm($this->var['thread_forum_id'], 'thread'))
+		{
+			$ntUrl = e107::url('forum', 'post') . "?f=nt&amp;id=" . $this->var['thread_forum_id'];
 
 //	$ntUrl = $e107->url->create('forum/thread/new', array('id' => $thread->threadInfo['thread_forum_id']));
-				return "<a href='" . $ntUrl . "'>" . IMAGE_newthread . "</a>";
-			}
-
-			return '';
+			return "<a href='" . $ntUrl . "'>" . IMAGE_newthread . "</a>";
 		}
 
+		return '';
+	}
+
 //$tVars->BUTTONSX = forumbuttons($thread);
 
-		function sc_buttonsx()
-		{
-			global $forum, $thread;
+	function sc_buttonsx()
+	{
 
-			if($forum->checkPerm($this->var['thread_forum_id'], 'post') && $this->var['thread_active'])
-			{
-				$url = e107::url('forum', 'post') . "?f=rp&amp;id=" . $this->var['thread_id'] . "&amp;post=" . $thread->threadId;
-				//	$url = e107::getUrl()->create('forum/thread/reply', array('id' => $thread->threadId));
-			}
-			$replyUrl = "<a class='btn btn-primary" . ($url ? "" : " disabled") . "' "
-				. ($url ? "" : " data-toggle='tooltip' title='" . LAN_FORUM_0046 . "'
+		global $thread;
+
+		if(!is_object($thread))
+		{
+			e107::getDebug()->log('$thread object is missing');
+			return null;
+		}
+
+		$url = '';
+
+		if($this->forum->checkPerm($this->var['thread_forum_id'], 'post') && $this->var['thread_active'])
+		{
+			$url = e107::url('forum', 'post') . "?f=rp&amp;id=" . $this->var['thread_id'] . "&amp;post=" . $thread->threadId;
+		}
+
+		$replyUrl = "<a class='btn btn-primary" . ($url ? "" : " disabled") . "' "
+			. ($url ? "" : " data-toggle='tooltip' title='" . LAN_FORUM_0046 . "'
 	style='cursor: not-allowed; pointer-events: all !important;'") . " href='" . ($url ?: "#") . "'>" . LAN_FORUM_2006 . "</a>" . ($url ? "" : "<span>&nbsp;</span>");
 
-			if($forum->checkPerm($this->var['thread_forum_id'], 'post'))
-			{
-				$ntUrl = e107::url('forum', 'post') . "?f=nt&amp;id=" . $this->var['thread_forum_id'];
-				//	$ntUrl = e107::getUrl()->create('forum/thread/new', array('id' => $thread->threadInfo['thread_forum_id']));
-				$options[] = " <a  href='" . $ntUrl . "'>" . LAN_FORUM_2005 . "</a>";
-			}
+		if($this->forum->checkPerm($this->var['thread_forum_id'], 'post'))
+		{
+			$ntUrl = e107::url('forum', 'post') . "?f=nt&amp;id=" . $this->var['thread_forum_id'];
+			//	$ntUrl = e107::getUrl()->create('forum/thread/new', array('id' => $thread->threadInfo['thread_forum_id']));
+			$options[] = " <a  href='" . $ntUrl . "'>" . LAN_FORUM_2005 . "</a>";
+		}
 
 //	$options[] = "<a href='" . e107::getUrl()->create('forum/thread/prev', array('id' => $thread->threadId)) . "'>".LAN_FORUM_1017." ".LAN_FORUM_2001."</a>";
 //	$options[] = "<a href='" . e107::getUrl()->create('forum/thread/prev', array('id' => $thread->threadId)) . "'>".LAN_FORUM_1017." ".LAN_FORUM_2002."</a>";
 
 //---- SIMILAR CODE AS SC_NEXTPREV!!!!!!!
-			$prev = $forum->threadGetNextPrev('prev', $thread->threadId, $this->var['forum_id'], $this->var['thread_lastpost']);
-			$next = $forum->threadGetNextPrev('next', $thread->threadId, $this->var['forum_id'], $this->var['thread_lastpost']);
+		$prev = $this->forum->threadGetNextPrev('prev', $thread->threadId, $this->var['forum_id'], $this->var['thread_lastpost']);
+		$next = $this->forum->threadGetNextPrev('next', $thread->threadId, $this->var['forum_id'], $this->var['thread_lastpost']);
 
-			if($prev !== false)
-			{
-				$options[] = "<a href='" . e107::url('forum', 'topic', $prev) . "'>" . LAN_FORUM_1017 . " " . LAN_FORUM_2001 . "</a>";
-			}
-			if($next !== false)
-			{
-				$options[] = "<a href='" . e107::url('forum', 'topic', $next) . "'>" . LAN_FORUM_1017 . " " . LAN_FORUM_2002 . "</a>";
-			}
+		if($prev !== false)
+		{
+			$options[] = "<a href='" . e107::url('forum', 'topic', $prev) . "'>" . LAN_FORUM_1017 . " " . LAN_FORUM_2001 . "</a>";
+		}
+		if($next !== false)
+		{
+			$options[] = "<a href='" . e107::url('forum', 'topic', $next) . "'>" . LAN_FORUM_1017 . " " . LAN_FORUM_2002 . "</a>";
+		}
 
 
-			/*
-			$text = '<div class="btn-group">
-			   '.($replyUrl?:"").'
-				<button class="btn btn-primary dropdown-toggle" data-toggle="dropdown">
-				'.($replyUrl?"":LAN_FORUM_1003." ".LAN_FORUM_8013).'<span class="caret"></span>
-				<span class="sr-only">Toggle Dropdown</span>
-				</button>
-				<ul class="dropdown-menu pull-right">
-				';
-			*/
-			$text = '<div class="btn-group">
-   ' . $replyUrl . '
-    <button class="btn btn-primary dropdown-toggle" data-toggle="dropdown">
-    ';
-	if(defined('BOOTSTRAP') && BOOTSTRAP !== 4)
-	{
-    	$text .= '<span class="caret"></span>';
-    }
-    $text .= '
-    <span class="sr-only">Toggle Dropdown</span>
-    </button>
-    <ul class="dropdown-menu pull-right float-right">
-    ';
+		$text = '<div class="btn-group">
+	   	' . $replyUrl . '
+	    <button class="btn btn-primary dropdown-toggle" data-toggle="dropdown">
+	    ';
 
-			foreach($options as $key => $val)
-			{
-				$text .= '<li>' . $val . '</li>';
-			}
+		if(defined('BOOTSTRAP') && BOOTSTRAP !== 4)
+		{
+			$text .= '<span class="caret"></span>';
+		}
 
-			$jumpList = $forum->forumGetAllowed();
+		$text .= '
+    	<span class="sr-only">Toggle Dropdown</span>
+    	</button>
+    	<ul class="dropdown-menu pull-right float-right">
+    	';
 
-			$text .= "<li class='divider'></li>";
+		foreach($options as $key => $val)
+		{
+			$text .= '<li>' . $val . '</li>';
+		}
 
-			foreach($jumpList as $key => $val)
-			{
-				$text .= '<li><a href ="' . e107::url('forum', 'forum', $val) . '">' . LAN_FORUM_1017 . " " . $val['forum_name'] . '</a></li>';
-			}
+		$jumpList = $this->forum->forumGetAllowed();
 
-			$text .= '
+		$text .= "<li class='divider'></li>";
+
+		foreach($jumpList as $key => $val)
+		{
+			$text .= '<li><a href ="' . e107::url('forum', 'forum', $val) . '">' . LAN_FORUM_1017 . " " . $val['forum_name'] . '</a></li>';
+		}
+
+		$text .= '
     </ul>
     </div>';
 
 
-			return $text;
-		}
+		return $text;
+	}
 
-		/*---- Function redeclared, this one came directly from forum_viewtopic.php.....
-		function sc_poll()
-		{
-			global $pollstr;
-		return vartrue($pollstr);
-		}
-		----*/
-		function sc_forumjump()
-		{
-			global $forum;
-			$jumpList = $forum->forumGetAllowed();
-			$text = "<form method='post' action='" . e_SELF . "'><p>" . LAN_FORUM_1017 . ": <select name='forumjump' class='tbox'>";
+	/*---- Function redeclared, this one came directly from forum_viewtopic.php.....
+	function sc_poll()
+	{
+		global $pollstr;
+	return vartrue($pollstr);
+	}
+	----*/
+	function sc_forumjump()
+	{
+		$jumpList = $this->forum->forumGetAllowed();
+		$text = "<form method='post' action='" . e_SELF . "'><p>" . LAN_FORUM_1017 . ": <select name='forumjump' class='tbox'>";
 //--	foreach ($jumpList as $key => $val)
-			foreach($jumpList as $val)
-			{
-				$text .= "\n<option value='" . e107::url('forum', 'forum', $val) . "'>" . $val['forum_name'] . "</option>";
-			}
-			$text .= "</select> <input class='btn btn-default btn-secondary button' type='submit' name='fjsubmit' value='" . LAN_GO . "' /></p></form>";
+		foreach($jumpList as $val)
+		{
+			$text .= "\n<option value='" . e107::url('forum', 'forum', $val) . "'>" . $val['forum_name'] . "</option>";
+		}
+		$text .= "</select> <input class='btn btn-default btn-secondary button' type='submit' name='fjsubmit' value='" . LAN_GO . "' /></p></form>";
 
-			return $text;
+		return $text;
+	}
+
+	function sc_message()
+	{
+
+		global $thread;
+
+		if(!is_object($thread))
+		{
+			return null;
 		}
 
-		function sc_message()
-		{
-			global $thread;
+		return $thread->message;
+	}
 
-			return $thread->message;
+	function sc_quickreply()
+	{
+
+		global $forum, $forum_quickreply, $thread;
+
+		// Define which tinymce4 template should be used, depending if the current user is registered or a guest
+		if(!deftrue('e_TINYMCE_TEMPLATE'))
+		{
+			define('e_TINYMCE_TEMPLATE', (USER ? 'member' : 'public')); // allow images / videos.
 		}
 
-		function sc_quickreply()
+		if($this->forum->checkPerm($this->var['thread_forum_id'], 'post') && $this->var['thread_active'])
 		{
-			global $forum, $forum_quickreply, $thread;
-
-			// Define which tinymce4 template should be used, depending if the current user is registered or a guest
-			if (!deftrue('e_TINYMCE_TEMPLATE'))
+			//XXX Show only on the last page??
+			if(!vartrue($forum_quickreply))
 			{
-				define('e_TINYMCE_TEMPLATE', (USER ? 'member' : 'public')); // allow images / videos.
-			}
-			
-			if($forum->checkPerm($this->var['thread_forum_id'], 'post') && $this->var['thread_active'])
-			{
-				//XXX Show only on the last page??
-				if(!vartrue($forum_quickreply))
-				{
-					$ajaxInsert = ($thread->pages == $thread->page || $thread->pages == 0) ? 1 : 0;
-					//	$ajaxInsert = 1;
-					//	echo "AJAX-INSERT=".$ajaxInsert ."(".$thread->pages." vs ".$thread->page.")";
+				$ajaxInsert = ($thread->pages == $thread->page || $thread->pages == 0) ? 1 : 0;
+				//	$ajaxInsert = 1;
+				//	echo "AJAX-INSERT=".$ajaxInsert ."(".$thread->pages." vs ".$thread->page.")";
 //Orphan $frm variable????		$frm = e107::getForm();
 
-					$urlParms = array('f' => 'rp', 'id' => $this->var['thread_id'], 'post' => $this->var['thread_id']);
-					$url = e107::url('forum', 'post', null, array('query' => $urlParms));; // ."?f=rp&amp;id=".$thread->threadInfo['thread_id']."&amp;post=".$thread->threadInfo['thread_id'];
+				$urlParms = array('f' => 'rp', 'id' => $this->var['thread_id'], 'post' => $this->var['thread_id']);
+				$url = e107::url('forum', 'post', null, array('query' => $urlParms));; // ."?f=rp&amp;id=".$thread->threadInfo['thread_id']."&amp;post=".$thread->threadInfo['thread_id'];
 
-					$qr = e107::getPlugPref('forum', 'quickreply', 'default');
-					if ($qr == 'default')
-					{
+				$qr = e107::getPlugPref('forum', 'quickreply', 'default');
+				if($qr == 'default')
+				{
 
-						return "
+					return "
 						<form action='" . $url . "' method='post'>
 						<div class='form-group'>
 							<textarea cols='80' placeholder='" . LAN_FORUM_2007 . "' rows='4' id='forum-quickreply-text' class='tbox input-xxlarge form-control' name='post' onselect='storeCaret(this);' onclick='storeCaret(this);' onkeyup='storeCaret(this);'></textarea>
@@ -1243,16 +1343,16 @@
 						</div>
 	
 						</form>";
-					}
-					else
-					{
-						$editor = $this->forum->prefs->get('editor');
-						$editor = is_null($editor) ? 'default' : $editor;
-						$text = "
+				}
+				else
+				{
+					$editor = varset($this->pref['editor'], null);
+					$editor = is_null($editor) ? 'default' : $editor;
+					$text = "
 						<form action='" . $url . "' method='post'>
 						<div class='form-group'>" .
 //						e107::getForm()->bbarea('post','','forum', '_common', 'small', array('id' => 'forum-quickreply-text', 'wysiwyg' => $editor)) .
-						e107::getForm()->bbarea('post','','forum', 'forum', 'medium', array('id' => 'forum-quickreply-text', 'wysiwyg' => $editor)) .
+						e107::getForm()->bbarea('post', '', 'forum', 'forum', 'medium', array('id' => 'forum-quickreply-text', 'wysiwyg' => $editor)) .
 						"</div>
 						<div class='center text-center form-group'>
 							<input type='submit' data-token='" . e_TOKEN . "' data-forum-insert='" . $ajaxInsert . "' data-forum-post='" . $this->var['thread_forum_id'] . "' data-forum-thread='" . $this->var['thread_id'] . "' data-forum-action='quickreply' name='reply' value='" . LAN_FORUM_2006 . "' class='btn btn-success button' />
@@ -1261,19 +1361,19 @@
 	
 						</form>";
 
-						return $text;
-					}
-
-					// Preview should be reserved for the full 'Post reply' page. <input type='submit' name='fpreview' value='" . Preview . "' /> &nbsp;
+					return $text;
 				}
+
+				// Preview should be reserved for the full 'Post reply' page. <input type='submit' name='fpreview' value='" . Preview . "' /> &nbsp;
+			}
 //----	else
 //----	{
-				return $forum_quickreply;
+			return $forum_quickreply;
 //----	}
-			}
 		}
-
 	}
 
+}
+
 
 
diff --git a/e107_plugins/gallery/e_shortcode.php b/e107_plugins/gallery/e_shortcode.php
index f304190db..b010b45bd 100644
--- a/e107_plugins/gallery/e_shortcode.php
+++ b/e107_plugins/gallery/e_shortcode.php
@@ -312,7 +312,7 @@ class gallery_shortcodes extends e_shortcode
 	 * limit - (optional) total limit of pcitures to be shown
 	 * template - (optional) template - name of template to be used for parsing the slideshow item
 	 */
-	function sc_gallery_slides($parm)
+	function sc_gallery_slides($parm=null)
 	{
 		$plugPrefs = e107::getPlugConfig('gallery')->getPref();
 		$orderBy = varset($plugPrefs['orderby'], 'media_id DESC');
@@ -359,7 +359,7 @@ class gallery_shortcodes extends e_shortcode
 	}
 
 
-	function sc_gallery_jumper($parm)
+	function sc_gallery_jumper($parm=null)
 	{
 		// echo "SlideCount=".$this->slideCount; 
 		if($this->slideCount == 1 && deftrue('E107_DBG_BASIC'))
diff --git a/e107_plugins/hero/hero_shortcodes.php b/e107_plugins/hero/hero_shortcodes.php
index 1e0b7a513..59774eff9 100644
--- a/e107_plugins/hero/hero_shortcodes.php
+++ b/e107_plugins/hero/hero_shortcodes.php
@@ -7,7 +7,7 @@ if (!defined('e107_INIT')) { exit; }
 
 class plugin_hero_hero_shortcodes extends e_shortcode
 {
-	public $count;
+	public $count =0;
 
 	/**
 	* {hero_ID}
@@ -52,7 +52,7 @@ class plugin_hero_hero_shortcodes extends e_shortcode
 	{
 		$target = !empty($parm['target']) ? $parm['target'] : 'carousel-hero';
 		$class = !empty($parm['class']) ? $parm['class'] : '';
-		$total = (int) $this->var['hero_total_slides'];
+		$total = (int) vartrue($this->var['hero_total_slides'], 0);
 
 		if(empty($total))
 		{
@@ -81,7 +81,7 @@ class plugin_hero_hero_shortcodes extends e_shortcode
 
 	public function sc_hero_slide_active($parm=null)
 	{
-		return $this->var['hero_slide_active'];
+		return varset($this->var['hero_slide_active']);
 	}
 
 	public function sc_hero_slide_interval($parm=null)
@@ -135,7 +135,8 @@ class plugin_hero_hero_shortcodes extends e_shortcode
 
 	public function sc_hero_text()
 	{
-		return e107::getParser()->toHTML($this->var['hero_bullets'][$this->count]['text'],true,'BODY');
+		$count = (int) $this->count;
+		return e107::getParser()->toHTML($this->var['hero_bullets'][$count]['text'],true,'BODY');
 	}
 
 
@@ -209,12 +210,12 @@ class plugin_hero_hero_shortcodes extends e_shortcode
 
 	/**
 	* {HERO_BULLETS}
-	*/
+	*//*
 	public function sc_hero_bullets($parm=null)
 	{
 		return $this->var['hero_bullets'];
 	}
-	
+	*/
 
 	/**
 	* {hero_BUTTON1_xxxx}
diff --git a/e107_plugins/login_menu/login_menu_shortcodes.php b/e107_plugins/login_menu/login_menu_shortcodes.php
index 7a89a378a..12ed9606f 100755
--- a/e107_plugins/login_menu/login_menu_shortcodes.php
+++ b/e107_plugins/login_menu/login_menu_shortcodes.php
@@ -17,6 +17,7 @@
 if (!defined('e107_INIT')) { exit(); }
 global $tp;
 
+e107::plugLan('login_menu', null);
 
 // BC LAN Fix.
 
@@ -190,7 +191,7 @@ e107::getLanguage()->bcDefs($bcDefs);
 				if($parm == "hidden"){
 					return "<input type='hidden' name='autologin' id='autologin' value='1' />";
 				}
-				if($pref['user_tracking'] != "session")
+				if(varset($pref['user_tracking']) !== "session")
 				{
 					return "<label for='autologin'><input type='checkbox' name='autologin' id='autologin' value='1' checked='checked' />".($parm ? $parm : "".LAN_LOGINMENU_6."</label>");
 				}
@@ -252,8 +253,10 @@ e107::getLanguage()->bcDefs($bcDefs);
 			{
 				if(ADMIN)
 				{
-					$data = e107::getRegistry('login_menu_data');
-					return $parm == 'src' ? $data['link_bullet_src'] : $data['link_bullet'];
+					if($data = e107::getRegistry('login_menu_data'))
+					{
+						return $parm == 'src' ? $data['link_bullet_src'] : $data['link_bullet'];
+					}
 				}
 				return '';
 			}
@@ -276,8 +279,12 @@ e107::getLanguage()->bcDefs($bcDefs);
 
 			function sc_lm_bullet($parm='')
 			{
-			$data = e107::getRegistry('login_menu_data');
-			return $parm == 'src' ? $data['link_bullet_src'] : $data['link_bullet'];
+				if(!$data = e107::getRegistry('login_menu_data'))
+				{
+					return null;
+				}
+
+				return $parm == 'src' ? $data['link_bullet_src'] : $data['link_bullet'];
 			}
 
 			function sc_lm_usersettings($parm='')
@@ -323,6 +330,7 @@ e107::getLanguage()->bcDefs($bcDefs);
 				global $menu_pref, $login_menu_shortcodes, $LOGIN_MENU_EXTERNAL_LINK;
 
 				$tp = e107::getParser();
+				require_once(e_PLUGIN."login_menu/login_menu_class.php");
 				$lmc = new login_menu_class;
 
 				if(!vartrue($menu_pref['login_menu']['external_links']))
@@ -361,6 +369,12 @@ e107::getLanguage()->bcDefs($bcDefs);
 			function sc_lm_external_link($parm='')
 			{
 				$lbox_item = e107::getRegistry('login_menu_linkdata');
+
+				if(empty($lbox_item['link_url']))
+				{
+					return null;
+				}
+
 				return $parm == 'href' ? $lbox_item['link_url'] : '<a href="'.$lbox_item['link_url'].'" class="login_menu_link external" id="login_menu_link_external_'.$lbox_item['link_id'].'">'.vartrue($lbox_item['link_label'], '['.LAN_LOGINMENU_44.']').'</a>';
 			}
 
@@ -372,11 +386,17 @@ e107::getLanguage()->bcDefs($bcDefs);
 
 			function sc_lm_stats($parm='')
 			{
+
 				$tp = e107::getParser();
 				global $LOGIN_MENU_STATS;
 				$data = e107::getRegistry('login_menu_data');
-				if(!$data['enable_stats']) return '';
-				return $tp -> parseTemplate($LOGIN_MENU_STATS, true, $this);
+
+				if(empty($data['enable_stats']) || empty($LOGIN_MENU_STATS))
+				{
+					return '';
+				}
+
+				return $tp->parseTemplate($LOGIN_MENU_STATS, true, $this);
 			}
 
 			function sc_lm_new_news($parm='')
@@ -439,7 +459,7 @@ e107::getLanguage()->bcDefs($bcDefs);
 				global $tp, $menu_pref, $new_total, $LOGIN_MENU_STATITEM, $LM_STATITEM_SEPARATOR;
 
 				if(!vartrue($menu_pref['login_menu']['external_stats'])) return '';
-
+				require_once(e_PLUGIN."login_menu/login_menu_class.php");
 				$lm = new login_menu_class;
 
 				$lbox_infos = $lm->parse_external_list(true, false);
@@ -483,11 +503,20 @@ e107::getLanguage()->bcDefs($bcDefs);
 			}
 
 
-			function sc_lm_listnew_link($parm='')
+			function sc_lm_listnew_link($parm = '')
 			{
-				$data = e107::getRegistry('login_menu_data');
-				if($parm == 'href') return $data['listnew_link'];
-				return $data['listnew_link'] ? '<a href="'.$data['listnew_link'].'" class="login_menu_link listnew" id="login_menu_link_listnew">'.LAN_LOGINMENU_24.'</a>' : '';
+
+				if(!$data = e107::getRegistry('login_menu_data'))
+				{
+					return null;
+				}
+
+				if($parm === 'href')
+				{
+					return $data['listnew_link'];
+				}
+
+				return $data['listnew_link'] ? '<a href="' . $data['listnew_link'] . '" class="login_menu_link listnew" id="login_menu_link_listnew">' . LAN_LOGINMENU_24 . '</a>' : '';
 			}
 
 
diff --git a/e107_tests/tests/unit/e_parse_shortcodeTest.php b/e107_tests/tests/unit/e_parse_shortcodeTest.php
index f0850fa2a..e880b2d59 100644
--- a/e107_tests/tests/unit/e_parse_shortcodeTest.php
+++ b/e107_tests/tests/unit/e_parse_shortcodeTest.php
@@ -741,7 +741,7 @@ class e_parse_shortcodeTest extends \Codeception\Test\Unit
 
     }
 
-      public function testFaqsShortcodes()
+    public function testFaqsShortcodes()
     {
         require_once(e_PLUGIN."faqs/faqs_shortcodes.php");
 
@@ -907,31 +907,236 @@ class e_parse_shortcodeTest extends \Codeception\Test\Unit
     }
 
 
+      public function testForumViewShortcodes()
+    {
+        require_once(e_PLUGIN."forum/shortcodes/batch/view_shortcodes.php");
+
+        try
+		{
+			/** @var plugin_forum_view_shortcodes $sc */
+			$sc = $this->make('plugin_forum_view_shortcodes');
+		}
+		catch (Exception $e)
+		{
+			$this->fail($e->getMessage());
+		}
+
+		$vars = array(
+			'forum_id'                 => '2',
+			'forum_name'               => 'Parent Number Two',
+			'forum_description'        => 'Forum Description',
+			'forum_parent'             => '0',
+			'forum_sub'                => '0',
+			'forum_datestamp'          => '1367304545',
+			'forum_moderators'         => '248',
+			'forum_threads'            => '0',
+			'forum_replies'            => '0',
+			'forum_lastpost_user'      => '0',
+			'forum_lastpost_user_anon' => NULL,
+			'forum_lastpost_info'      => '',
+			'forum_class'              => '253',
+			'forum_order'              => '300',
+			'forum_postclass'          => '253',
+			'forum_threadclass'        => '0',
+			'forum_options'            => '',
+			'forum_sef'                => 'parent-number-two',
+			'forum_image'              => NULL,
+			'forum_icon'               => NULL,
+			'thread_id' => '1',
+			'thread_name' => '3 Duis tempus enim vitae magna placerat vel dapibus tellus feugiat.',
+			'thread_forum_id' => '4',
+			'thread_views' => '53',
+			'thread_active' => '1',
+			'thread_lastpost' => '1434584999',
+			'thread_sticky' => '0',
+			'thread_datestamp' => '1367307189',
+			'thread_user' => '2',
+			'thread_user_anon' => NULL,
+			'thread_lastuser' => '1',
+			'thread_lastuser_anon' => NULL,
+			'thread_total_replies' => '7',
+			'thread_options' => NULL,
+			'post_id' => '1',
+			'post_entry' => '4 Morbi eleifend auctor quam, ac consequat ipsum dictum vitae. Curabitur egestas lacinia mi, in venenatis mi euismod eu.',
+			'post_thread' => '1',
+			'post_forum' => '4',
+			'post_status' => '0',
+			'post_datestamp' => '1367307189',
+			'post_user' => '2',
+			'post_edit_datestamp' => NULL,
+			'post_edit_user' => NULL,
+			'post_ip' => NULL,
+			'post_user_anon' => NULL,
+			'post_attachments' => NULL,
+			'post_options' => NULL
+
+
+		);
+
+		$sc->__construct();
+
+		$sc->setVars($vars);
+
+        $this->processShortcodeMethods($sc);
+
+    }
+
+
+    public function testGalleryShortcodes()
+    {
+        require_once(e_PLUGIN."gallery/e_shortcode.php");
+
+        try
+		{
+			/** @var gallery_shortcodes $sc */
+			$sc = $this->make('gallery_shortcodes');
+		}
+		catch (Exception $e)
+		{
+			$this->fail($e->getMessage());
+		}
+
+		$vars = array(
+			'media_id'           => '227',
+			'media_type'         => 'image/jpeg',
+			'media_name'         => 'gasmask.jpg',
+			'media_caption'      => 'gasmask.jpg',
+			'media_description'  => '',
+			'media_category'     => '_common_image',
+			'media_datestamp'    => '1464646050',
+			'media_author'       => '1',
+			'media_url'          => '{e_THEME}voux/install/gasmask.jpg',
+			'media_size'         => '91054',
+			'media_dimensions'   => '1200 x 830',
+			'media_userclass'    => '0',
+			'media_usedby'       => '',
+			'media_tags'         => '',
+			'media_cat_id'       => '1',
+			'media_cat_owner'    => '_common',
+			'media_cat_category' => '_common_image',
+			'media_cat_title'    => '(Common Images)',
+			'media_cat_sef'      => '',
+			'media_cat_diz'      => 'Media in this category will be available in all areas of admin.',
+			'media_cat_class'    => '253',
+			'media_cat_image'    => '',
+			'media_cat_order'    => '0'
+		);
+
+
+
+		$sc->setVars($vars);
+		$exclude = array('sc_gallery_slides'); // uses a counter.
+        $this->processShortcodeMethods($sc, $exclude);
+
+    }
+
+
+    public function testHeroShortcodes()
+    {
+        require_once(e_PLUGIN."hero/hero_shortcodes.php");
+
+        try
+		{
+			/** @var plugin_hero_hero_shortcodes $sc */
+			$sc = $this->make('plugin_hero_hero_shortcodes');
+		}
+		catch (Exception $e)
+		{
+			$this->fail($e->getMessage());
+		}
+
+		$vars =  array(
+				'hero_id' => '1',
+				'hero_title' => 'A [powerful] &amp; [free] hero area',
+				'hero_description' => '[Easy] to Use',
+				'hero_bg' => '{e_MEDIA_IMAGE}2020-12/4.sm.webp',
+				'hero_media' => '{e_MEDIA_IMAGE}2020-12/horse.jpg',
+				'hero_bullets' => e107::unserialize('[
+		    {
+		        "icon": "fa-sun-o.glyph",
+		        "icon_style": "warning",
+		        "text": "Add some bullet text",
+		        "animation": "fadeInRight",
+		        "animation_delay": "15"
+		    },
+		    {
+		        "icon": "fa-font-awesome.glyph",
+		        "icon_style": "success",
+		        "text": "Select an Icon from FontAwesome or others",
+		        "animation": "fadeInRight",
+		        "animation_delay": "25"
+		    },
+		    {
+		        "icon": "fa-adjust.glyph",
+		        "icon_style": "danger",
+		        "text": "Choose a Style from Bootstrap",
+		        "animation": "fadeInRight",
+		        "animation_delay": "35"
+		    },
+		    {
+		        "icon": "",
+		        "icon_style": "",
+		        "text": "",
+		        "animation": "",
+		        "animation_delay": "0"
+		    },
+		    {
+		        "icon": "",
+		        "icon_style": "",
+		        "text": "",
+		        "animation": "",
+		        "animation_delay": "0"
+		    }
+		]'),
+		'hero_button1' => e107::unserialize('{
+		    "icon": "fa-",
+		    "label": "",
+		    "url": "",
+		    "class": ""
+		}'),
+		'hero_button2' => e107::unserialize('{
+		    "icon": "fa-",
+		    "label": "",
+		    "url": "",
+		    "class": ""
+		}'),
+		'hero_order' => '1',
+		'hero_class' => '0'
+		);
+
+
+
+		$sc->setVars($vars);
+	//	$exclude = array('sc_gallery_slides'); // uses a counter.
+        $this->processShortcodeMethods($sc);
+
+    }
+
+
+    public function testLoginMenuShortcodes()
+    {
+        require_once(e_PLUGIN."login_menu/login_menu_shortcodes.php");
+
+        try
+		{
+			/** @var login_menu_shortcodes $sc */
+			$sc = $this->make('login_menu_shortcodes');
+		}
+		catch (Exception $e)
+		{
+			$this->fail($e->getMessage());
+		}
+
+
+
+        $this->processShortcodeMethods($sc);
+
+    }
+
+
 	/*
 
-            e107_plugins\faqs/
-                faqs_shortcodes.php  (1 usage found)
-                    1 <?php
-            e107_plugins\forum\shortcodes\batch  (4 usages found)
-                forum_shortcodes.php  (1 usage found)
-                    1 <?php
-                post_shortcodes.php  (1 usage found)
-                    1 <?php
-                view_shortcodes.php  (1 usage found)
-                    1 <?php
-                viewforum_shortcodes.php  (1 usage found)
-                    1 <?php
-            e107_plugins\forum\todelete  (2 usages found)
-                forum_post_shortcodes.php  (1 usage found)
-                    1 <?php
-                forum_shortcodes.php  (1 usage found)
-                    1 <?php
-            e107_plugins\gallery\shortcodes\batch  (1 usage found)
-                gallery_shortcodes.php  (1 usage found)
-                    1 <?php
-            e107_plugins\hero  (1 usage found)
-                hero_shortcodes.php  (1 usage found)
-                    1 <?php
+
             e107_plugins\links_page  (1 usage found)
                 links_page_shortcodes.php  (1 usage found)
                     1 <?php