From 2a6db3772ba8dd77cbc11e750765f4dea2c075f3 Mon Sep 17 00:00:00 2001
From: Daniel Winzen <d@winzen4.de>
Date: Mon, 17 Aug 2015 18:59:23 +0200
Subject: [PATCH] Version 1.12

---
 CHANGELOG   |   8 +
 chat.php    | 933 ++++++++++++++++++++++++++++++++--------------------
 lang_de.php |  26 +-
 lang_en.php |  28 +-
 4 files changed, 621 insertions(+), 374 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 7a11378..1d7c617 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,11 @@
+Version 1.12 - Aug. 17, 2015
+Almost all settings moved to setup
+Backup/restore for super admin
+Moderate and extreme captcha are more readable
+Simplified font styling
+Linkfilter to modify text of a link
+More simplifications and fixes
+
 Version 1.11.2 - Jul. 29, 2015
 Fix security vulnerability
 More simplifications
diff --git a/chat.php b/chat.php
index e705e2e..25c19cf 100755
--- a/chat.php
+++ b/chat.php
@@ -58,7 +58,7 @@ if(!isSet($_REQUEST['action'])){
 }elseif($_REQUEST['action']=='post'){
 	check_session();
 	if(isSet($_REQUEST['kick']) && isSet($_REQUEST['sendto']) && valid_nick($_REQUEST['sendto'])){
-		if($U['status']>=5 || ($C['memkick'] && $countmods==0 && $U['status']>=3)){
+		if($U['status']>=5 || (get_setting('memkick') && $countmods==0 && $U['status']>=3)){
 			if(isSet($_REQUEST['what']) && $_REQUEST['what']=='purge') kick_chatter(array($_REQUEST['sendto']), $_REQUEST['message'], true);
 			else kick_chatter(array($_REQUEST['sendto']), $_REQUEST['message'], false);
 		}
@@ -146,24 +146,31 @@ if(!isSet($_REQUEST['action'])){
 	}elseif($_REQUEST['do']=='filter'){
 		manage_filter();
 		send_filter();
+	}elseif($_REQUEST['do']=='linkfilter'){
+		manage_linkfilter();
+		send_linkfilter();
 	}
 	send_admin();
 }elseif($_REQUEST['action']=='setup'){
 	if(check_init()<7) send_init();
 	update_db();
 	if(!valid_admin()) send_alogin();
+	$settings=array('guestaccess', 'englobalpass', 'globalpass', 'msgenter', 'msgexit', 'msgmemreg', 'msgsureg', 'msgkick', 'msgmultikick', 'msgallkick', 'msgclean', 'dateformat', 'captcha', 'colbg', 'coltxt', 'css', 'memberexpire', 'guestexpire', 'kickpenalty', 'entrywait', 'captchatime', 'messageexpire', 'messagelimit', 'maxmessage', 'maxname', 'minpass', 'defaultrefresh', 'dismemcaptcha', 'suguests', 'imgembed', 'timestamps', 'trackip', 'captchachars', 'memkick', 'forceredirect', 'redirect', 'incognito', 'rulestxt');
 	if(!isSet($_REQUEST['do'])){
+	}elseif($_REQUEST['do']=='backup' && $U['status']==8){
+		send_backup();
+	}elseif($_REQUEST['do']=='restore' && $U['status']==8){
+		restore_backup();
+		send_backup();
 	}elseif($_REQUEST['do']=='save'){
-		$settings=array('guestaccess', 'englobalpass', 'globalpass', 'msgenter', 'msgexit', 'msgmemreg', 'msgsureg', 'msgkick', 'msgmultikick', 'msgallkick', 'msgclean', 'dateformat', 'captcha', 'css', 'memberexpire', 'guestexpire', 'kickpenalty', 'entrywait', 'captchatime', 'messageexpire', 'messagelimit', 'maxmessage');
+		$_REQUEST['rulestxt']=preg_replace("/(\r?\n|\r\n?)/", '<br>', $_REQUEST['rulestxt']);
+		if($_REQUEST['memberexpire']<5) $_REQUEST['memberexpire']=5;
+		if($_REQUEST['captchatime']<30) $_REQUEST['memberexpire']=30;
+		if($_REQUEST['defaultrefresh']<5) $_REQUEST['defaultrefresh']=5;
+		if($_REQUEST['defaultrefresh']>150) $_REQUEST['defaultrefresh']=150;
 		foreach($settings as $setting){
 			if(isSet($_REQUEST[$setting])) update_setting($setting, $_REQUEST[$setting]);
 		}
-		if(isSet($_REQUEST['rulestxt'])){
-			$_REQUEST['rulestxt']=preg_replace("/\r\n/", '<br>', $_REQUEST['rulestxt']);
-			$_REQUEST['rulestxt']=preg_replace("/\n/", '<br>', $_REQUEST['rulestxt']);
-			$_REQUEST['rulestxt']=preg_replace("/\r/", '<br>', $_REQUEST['rulestxt']);
-			update_setting('rulestxt', $_REQUEST['rulestxt']);
-		}
 	}
 	send_setup();
 }elseif($_REQUEST['action']=='init'){
@@ -176,9 +183,10 @@ exit;
 
 //  html output subs
 function print_stylesheet(){
-	global $C;
 	$css=get_setting('css');
-	echo "<style type=\"text/css\">body{background-color:#$C[colbg];color:#$C[coltxt];} $css</style>";
+	$colbg=get_setting('colbg');
+	$coltxt=get_setting('coltxt');
+	echo "<style type=\"text/css\">body{background-color:#$colbg;color:#$coltxt;} $css</style>";
 }
 
 function print_end(){
@@ -222,13 +230,13 @@ function thr(){
 }
 
 function print_start($class='',  $ref=0, $url=''){
-	global $C, $H;
+	global $H;
 	header('Content-Type: text/html; charset=UTF-8'); header('Pragma: no-cache'); header('Cache-Control: no-cache'); header('Expires: 0');
 	if(!empty($url)) header("Refresh: $ref; URL=$url");
 	echo "<!DOCTYPE html><html><head>$H[meta_html]";
 	if(!empty($url)) echo "<meta http-equiv=\"Refresh\" content=\"$ref; URL=$url\">";
 	if($class=='init'){
-		echo "<style type=\"text/css\">body{background-color:#$C[colbg];color:#$C[coltxt];} a:visited{color:#B33CB4;} a:active{color:#FF0033;} a:link{color:#0000FF;} input,select,textarea{color:#FFFFFF;background-color:#000000;} a img{width:15%} a:hover img{width:35%} .error{color:#FF0033;} .delbutton{background-color:#660000;} .backbutton{background-color:#004400;} #exitbutton{background-color:#AA0000;}</style>";
+		echo "<style type=\"text/css\">body{background-color:#000000;color:#FFFFFF;} a:visited{color:#B33CB4;} a:active{color:#FF0033;} a:link{color:#0000FF;} input,select,textarea{color:#FFFFFF;background-color:#000000;} a img{width:15%} a:hover img{width:35%} .error{color:#FF0033;} .delbutton{background-color:#660000;} .backbutton{background-color:#004400;} #exitbutton{background-color:#AA0000;}</style>";
 	}else{
 		print_stylesheet();
 	}
@@ -253,10 +261,11 @@ function send_captcha(){
 	global $C, $I, $memcached, $mysqli;
 	$difficulty=get_setting('captcha');
 	if($difficulty==0) return;
-	$length=strlen($C['captchachars'])-1;
+	$captchachars=get_setting('captchachars');
+	$length=strlen($captchachars)-1;
 	$code='';
 	for($i=0;$i<5;++$i){
-		$code.=$C['captchachars'][rand(0, $length)];
+		$code.=$captchachars[rand(0, $length)];
 	}
 	$randid=rand(0, 99999999);
 	$time=time();
@@ -281,8 +290,8 @@ function send_captcha(){
 		$bg=imagecolorallocate($im, 0, 0, 0);
 		$fg=imagecolorallocate($im, 255, 255, 255);
 		imagefill($im, 0, 0, $bg);
-		$line=imagecolorallocate($im, 200, 200, 200);
-		for($i=0;$i<4;++$i){
+		$line=imagecolorallocate($im, 100, 100, 100);
+		for($i=0;$i<3;++$i){
 			imageline($im, 0, rand(0, 24), 55, rand(0, 24), $line);
 		}
 		$dots=imagecolorallocate($im, 200, 200, 200);
@@ -296,27 +305,62 @@ function send_captcha(){
 		$bg=imagecolorallocate($im, 0, 0, 0);
 		$fg=imagecolorallocate($im, 255, 255, 255);
 		imagefill($im, 0, 0, $bg);
-		$line=imagecolorallocate($im, 200, 200, 200);
-		for($i=0;$i<10;++$i){
+		$line=imagecolorallocate($im, 100, 100, 100);
+		for($i=0;$i<5;++$i){
 			imageline($im, 0, rand(0, 200), 150, rand(0, 200), $line);
 		}
 		$dots=imagecolorallocate($im, 200, 200, 200);
 		for($i=0;$i<1000;++$i){
 			imagesetpixel($im, rand(0, 150), rand(0, 200), $dots);
 		}
+		$chars=array();
 		for($i=0;$i<5;++$i){
-			imagechar($im, 5, rand(10, 140), rand(10, 180), $C['captchachars'][rand(0, $length)], $fg);
+			$found=false;
+			while(!$found){
+				$x=rand(10, 140);
+				$y=rand(10, 180);
+				$found=true;
+				foreach($chars as $char){
+					if($char['x']>=$x && ($char['x']-$x)<25) $found=false;
+					elseif($char['x']<$x && ($x-$char['x'])<25) $found=false;
+					if(!$found){
+						if($char['y']>=$y && ($char['y']-$y)<25) break;
+						elseif($char['y']<$y && ($y-$char['y'])<25) break;
+						else $found=true;
+					}
+				}
+			}
+			$chars[]=array('x', 'y');
+			$chars[$i]['x']=$x;
+			$chars[$i]['y']=$y;
+			imagechar($im, 5, $chars[$i]['x'], $chars[$i]['y'], $captchachars[rand(0, $length)], $fg);
 		}
 		$x=$y=array();
-		$follow=imagecolorallocate($im, 200, 0, 0);
-		for($i=0;$i<5;++$i){
-			$x[]=rand(10, 140);
-			$y[]=rand(10, 180);
-			imagechar($im, 5, $x[$i], $y[$i], $code[$i], $fg);
+		for($i=5;$i<10;++$i){
+			$found=false;
+			while(!$found){
+				$x=rand(10, 140);
+				$y=rand(10, 180);
+				$found=true;
+				foreach($chars as $char){
+					if($char['x']>=$x && ($char['x']-$x)<25) $found=false;
+					elseif($char['x']<$x && ($x-$char['x'])<25) $found=false;
+					if(!$found){
+						if($char['y']>=$y && ($char['y']-$y)<25) break;
+						elseif($char['y']<$y && ($y-$char['y'])<25) break;
+						else $found=true;
+					}
+				}
+			}
+			$chars[]=array('x', 'y');
+			$chars[$i]['x']=$x;
+			$chars[$i]['y']=$y;
+			imagechar($im, 5, $chars[$i]['x'], $chars[$i]['y'], $code[$i-5], $fg);
 		}
-		imagearc($im, $x[0]+4, $y[0]+8, 16, 16, 0, 360, $follow);
-		for($i=0;$i<4;++$i){
-			imageline($im, $x[$i]+4, $y[$i]+8, $x[$i+1]+4, $y[$i+1]+8, $follow);
+		$follow=imagecolorallocate($im, 200, 0, 0);
+		imagearc($im, $chars[5]['x']+4, $chars[5]['y']+8, 16, 16, 0, 360, $follow);
+		for($i=5;$i<9;++$i){
+			imageline($im, $chars[$i]['x']+4, $chars[$i]['y']+8, $chars[$i+1]['x']+4, $chars[$i+1]['y']+8, $follow);
 		}
 		echo '<img width="150" height="200" src="data:image/gif;base64,';
 	}
@@ -357,26 +401,36 @@ function send_setup(){
 	echo "<tr><td>&nbsp;$I[msgenter]</td><td>&nbsp;<input type=\"text\" name=\"msgenter\" value=\"".get_setting('msgenter').'"></td></tr>';
 	echo "<tr><td>&nbsp;$I[msgexit]</td><td>&nbsp;<input type=\"text\" name=\"msgexit\" value=\"".get_setting('msgexit').'"></td></tr>';
 	echo "<tr><td>&nbsp;$I[msgmemreg]</td><td>&nbsp;<input type=\"text\" name=\"msgmemreg\" value=\"".get_setting('msgmemreg').'"></td></tr>';
-	if($C['suguests']) echo "<tr><td>&nbsp;$I[msgsureg]</td><td>&nbsp;<input type=\"text\" name=\"msgsureg\" value=\"".get_setting('msgsureg').'"></td></tr>';
+	if(get_setting('suguests')) echo "<tr><td>&nbsp;$I[msgsureg]</td><td>&nbsp;<input type=\"text\" name=\"msgsureg\" value=\"".get_setting('msgsureg').'"></td></tr>';
 	echo "<tr><td>&nbsp;$I[msgkick]</td><td>&nbsp;<input type=\"text\" name=\"msgkick\" value=\"".get_setting('msgkick').'"></td></tr>';
 	echo "<tr><td>&nbsp;$I[msgmultikick]</td><td>&nbsp;<input type=\"text\" name=\"msgmultikick\" value=\"".get_setting('msgmultikick').'"></td></tr>';
 	echo "<tr><td>&nbsp;$I[msgallkick]</td><td>&nbsp;<input type=\"text\" name=\"msgallkick\" value=\"".get_setting('msgallkick').'"></td></tr>';
 	echo "<tr><td>&nbsp;$I[msgclean]</td><td>&nbsp;<input type=\"text\" name=\"msgclean\" value=\"".get_setting('msgclean').'"></td></tr>';
 	echo '</table></td></tr></table></td></tr>';
-	thr();
-	echo "<tr><td><table cellspacing=\"0\" width=\"100%\"><tr><td align=\"left\"><b>$I[rules]</b></td><td align=\"right\">";
-	echo '<table cellspacing="0">';
-	echo '<tr><td colspan="2"><textarea name="rulestxt" rows="4" cols="60">'.htmlspecialchars(get_setting('rulestxt')).'</textarea></td></tr>';
-	echo '</table></td></tr></table></td></tr>';
-	thr();
-	echo "<tr><td><table cellspacing=\"0\" width=\"100%\"><tr><td align=\"left\"><b>$I[dateformat]</b></td><td align=\"right\">";
-	echo '<table cellspacing="0">';
-	echo '<tr><td><input type="text" name="dateformat" value="'.htmlspecialchars(get_setting('dateformat')).'"></td></tr>';
-	echo '</table></td></tr></table></td></tr>';
+	$text_settings=array('dateformat', 'captchachars', 'redirect');
+	foreach($text_settings as $setting){
+		thr();
+		echo '<tr><td><table cellspacing="0" width="100%"><tr><td align="left"><b>'.$I[$setting].'</b></td><td align="right">';
+		echo '<table cellspacing="0">';
+		echo "<tr><td><input type=\"text\" name=\"$setting\" value=\"".htmlspecialchars(get_setting($setting)).'"></td></tr>';
+		echo '</table></td></tr></table></td></tr>';
+	}
+	$colour_settings=array('colbg', 'coltxt');
+	foreach($colour_settings as $setting){
+		thr();
+		echo '<tr><td><table cellspacing="0" width="100%"><tr><td align="left"><b>'.$I[$setting].'</b></td><td align="right">';
+		echo '<table cellspacing="0">';
+		echo "<tr><td><input type=\"text\" name=\"$setting\" size=\"6\" maxlength=\"6\" pattern=\"[a-fA-F0-9]{6}\" value=\"".htmlspecialchars(get_setting($setting)).'"></td></tr>';
+		echo '</table></td></tr></table></td></tr>';
+	}
 	thr();
 	echo "<tr><td><table cellspacing=\"0\" width=\"100%\"><tr><td align=\"left\"><b>$I[captcha]</b></td><td align=\"right\">";
 	echo '<table cellspacing="0">';
-	echo '<tr><td><select name="captcha">';
+	echo '<tr><td><select name="dismemcaptcha">';
+	$dismemcaptcha=get_setting('dismemcaptcha');
+	echo '<option value="0"'; if($dismemcaptcha==0) echo ' selected'; echo ">$I[enabled]</option>";
+	echo '<option value="1"'; if($dismemcaptcha==1) echo ' selected'; echo ">$I[onlyguests]</option>";
+	echo '</select></td><td><select name="captcha">';
 	$captcha=get_setting('captcha');
 	echo '<option value="0"'; if($captcha==0) echo ' selected'; echo ">$I[disabled]</option>";
 	echo '<option value="1"'; if($captcha==1) echo ' selected'; echo ">$I[simple]</option>";
@@ -384,12 +438,15 @@ function send_setup(){
 	echo '<option value="3"'; if($captcha==3) echo ' selected'; echo ">$I[extreme]</option>";
 	echo '</select></td></tr>';
 	echo '</table></td></tr></table></td></tr>';
-	thr();
-	echo "<tr><td><table cellspacing=\"0\" width=\"100%\"><tr><td align=\"left\"><b>$I[css]</b></td><td align=\"right\">";
-	echo '<table cellspacing="0">';
-	echo '<tr><td colspan="2"><textarea name="css" rows="4" cols="60">'.htmlspecialchars(get_setting('css')).'</textarea></td></tr>';
-	echo '</table></td></tr></table></td></tr>';
-	$number_settings=array('memberexpire', 'guestexpire', 'kickpenalty', 'entrywait', 'captchatime', 'messageexpire', 'messagelimit', 'maxmessage');
+	$textarea_settings=array('rulestxt', 'css');
+	foreach($textarea_settings as $setting){
+		thr();
+		echo '<tr><td><table cellspacing="0" width="100%"><tr><td align="left"><b>'.$I[$setting].'</b></td><td align="right">';
+		echo '<table cellspacing="0">';
+		echo "<tr><td colspan=\"2\"><textarea name=\"$setting\" rows=\"4\" cols=\"60\">".htmlspecialchars(get_setting($setting)).'</textarea></td></tr>';
+		echo '</table></td></tr></table></td></tr>';
+	}
+	$number_settings=array('memberexpire', 'guestexpire', 'kickpenalty', 'entrywait', 'captchatime', 'messageexpire', 'messagelimit', 'maxmessage', 'maxname', 'minpass', 'defaultrefresh');
 	foreach($number_settings as $setting){
 		thr();
 		echo '<tr><td><table cellspacing="0" width="100%"><tr><td align="left"><b>'.$I[$setting].'</b></td><td align="right">';
@@ -397,8 +454,121 @@ function send_setup(){
 		echo "<tr><td colspan=\"2\"><input type=\"number\" name=\"$setting\" value=\"".htmlspecialchars(get_setting($setting)).'"></td></tr>';
 		echo '</table></td></tr></table></td></tr>';
 	}
+	$bool_settings=array('suguests', 'imgembed', 'timestamps', 'trackip', 'memkick', 'forceredirect', 'incognito');
+	foreach($bool_settings as $setting){
+		thr();
+		echo '<tr><td><table cellspacing="0" width="100%"><tr><td align="left"><b>'.$I[$setting].'</b></td><td align="right">';
+		echo '<table cellspacing="0">';
+		echo "<tr><td colspan=\"2\"><select name=\"$setting\">";
+		$value=get_setting($setting);
+		echo '<option value="0"'; if($value==0) echo ' selected'; echo ">$I[disabled]</option>";
+		echo '<option value="1"'; if($value==1) echo ' selected'; echo ">$I[enabled]</option>";
+		echo '</select></td></tr></table></td></tr></table></td></tr>';
+	}
 	thr();
-	echo '<tr align="center"><td>'.submit($I['apply'])."</td></tr></table></form><br><$H[form]>".hidden('action', 'logout').hidden('session', $U['session']).hidden('lang', $C['lang']).submit($I['logout'])."</form></tr>$H[credit]";
+	echo '<tr align="center"><td>'.submit($I['apply']).'</td></tr></table></form><br>';
+	echo '<table><tr>';
+	if($U['status']==8) echo "<td><$H[form]>".hidden('action', 'setup').hidden('do', 'backup').hidden('session', $U['session']).hidden('lang', $C['lang']).submit($I['backuprestore'])."</form></td>";
+	echo "<td><$H[form]>".hidden('action', 'logout').hidden('session', $U['session']).hidden('lang', $C['lang']).submit($I['logout'], 'id="exitbutton"')."</form></td></tr></table>$H[credit]</center>";
+	print_end();
+}
+
+function restore_backup(){
+	global $C, $mysqli, $settings;
+	$code=json_decode($_REQUEST['restore'], true);
+	if(isSet($_REQUEST['settings'])){
+		foreach($settings as $setting){
+			if(isSet($code['settings'][$setting])) update_setting($setting, $code['settings'][$setting]);
+		}
+	}
+	if(isSet($_REQUEST['filter']) && (isSet($code['filters']) || isSet($code['linkfilters']))){
+		mysqli_query($mysqli, "DELETE FROM `$C[prefix]filter`");
+		mysqli_query($mysqli, "DELETE FROM `$C[prefix]linkfilter`");
+		$stmt=mysqli_prepare($mysqli, "INSERT INTO `$C[prefix]filter` (`match`, `replace`, `allowinpm`, `regex`, `kick`) VALUES (?, ?, ?, ?, ?)");
+		foreach($code['filters'] as $filter){
+			mysqli_stmt_bind_param($stmt, 'ssiii', $filter['match'], $filter['replace'], $filter['allowinpm'], $filter['regex'], $filter['kick']);
+			mysqli_stmt_execute($stmt);
+		}
+		mysqli_stmt_close($stmt);
+		$stmt=mysqli_prepare($mysqli, "INSERT INTO `$C[prefix]linkfilter` (`match`, `replace`, `regex`) VALUES (?, ?, ?)");
+		foreach($code['linkfilters'] as $filter){
+			mysqli_stmt_bind_param($stmt, 'ssi', $filter['match'], $filter['replace'], $filter['regex']);
+			mysqli_stmt_execute($stmt);
+		}
+		mysqli_stmt_close($stmt);
+		if($C['memcached']) $memcached->delete("$C[dbname]-$C[prefix]filter");
+		if($C['memcached']) $memcached->delete("$C[dbname]-$C[prefix]linkfilter");
+	}
+	if(isSet($_REQUEST['members']) && isSet($code['members'])){
+		mysqli_query($mysqli, "DELETE FROM `$C[prefix]members`");
+		$stmt=mysqli_prepare($mysqli, "INSERT INTO `$C[prefix]members` (`nickname`, `passhash`, `status`, `refresh`, `bgcolour`, `boxwidth`, `boxheight`, `notesboxwidth`, `notesboxheight`, `regedby`, `lastlogin`, `timestamps`, `embed`, `incognito`, `style`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
+		foreach($code['members'] as $member){
+			mysqli_stmt_bind_param($stmt, 'ssiisiiiisiiiis', $member['nickname'], $member['passhash'], $member['status'], $member['refresh'], $member['bgcolour'], $member['boxwidth'], $member['boxheight'], $member['notesboxwidth'], $member['notesboxheight'], $member['regedby'], $member['lastlogin'], $member['timestamps'], $member['embed'], $member['incognito'], $member['style']);
+			mysqli_stmt_execute($stmt);
+		}
+		mysqli_stmt_close($stmt);
+		if($C['memcached']) $memcached->delete("$C[dbname]-$C[prefix]members");
+	}
+	if(isSet($_REQUEST['notes']) && isSet($code['notes'])){
+		mysqli_query($mysqli, "DELETE FROM `$C[prefix]notes`");
+		$stmt=mysqli_prepare($mysqli, "INSERT INTO `$C[prefix]notes` (`type`, `lastedited`, `editedby`, `text`) VALUES (?, ?, ?, ?)");
+		foreach($code['notes'] as $note){
+			mysqli_stmt_bind_param($stmt, 'siss', $note['type'], $note['lastedited'], $note['editedby'], $note['text']);
+			mysqli_stmt_execute($stmt);
+		}
+		mysqli_stmt_close($stmt);
+	}
+}
+
+function send_backup(){
+	global $C, $H, $I, $U, $mysqli, $settings;
+	$code=array();
+	if($_REQUEST['do']=='backup'){
+		if(isSet($_REQUEST['settings'])) foreach($settings as $setting) $code['settings'][$setting]=get_setting($setting);
+		if(isSet($_REQUEST['filter'])){
+			$result=mysqli_query($mysqli, "SELECT `match`, `replace`, `allowinpm`, `regex`, `kick` FROM `$C[prefix]filter`");
+			while($filter=mysqli_fetch_array($result, MYSQLI_ASSOC)) $code['filters'][]=$filter;
+			$result=mysqli_query($mysqli, "SELECT `match`, `replace`, `regex` FROM `$C[prefix]linkfilter`");
+			while($filter=mysqli_fetch_array($result, MYSQLI_ASSOC)) $code['linkfilters'][]=$filter;
+		}
+		if(isSet($_REQUEST['members'])){
+			$result=mysqli_query($mysqli, "SELECT `nickname`, `passhash`, `status`, `refresh`, `bgcolour`, `boxwidth`, `boxheight`, `notesboxwidth`, `notesboxheight`, `regedby`, `lastlogin`, `timestamps`, `embed`, `incognito`, `style` FROM `$C[prefix]members`");
+			while($member=mysqli_fetch_array($result, MYSQLI_ASSOC)) $code['members'][]=$member;
+		}
+		if(isSet($_REQUEST['notes'])){
+			$result=mysqli_query($mysqli, "SELECT `type`, `lastedited`, `editedby`, `text` FROM `$C[prefix]notes` WHERE `type`='admin' ORDER BY `id` DESC LIMIT 1");
+			$code['notes'][]=mysqli_fetch_array($result, MYSQLI_ASSOC);
+			$result=mysqli_query($mysqli, "SELECT `type`, `lastedited`, `editedby`, `text` FROM `$C[prefix]notes` WHERE `type`='staff' ORDER BY `id` DESC LIMIT 1");
+			$code['notes'][]=mysqli_fetch_array($result, MYSQLI_ASSOC);
+		}
+	}
+	if(isSet($_REQUEST['settings'])) $chksettings=' checked'; else $chksettings='';
+	if(isSet($_REQUEST['filter'])) $chkfilters=' checked'; else $chkfilters='';
+	if(isSet($_REQUEST['members'])) $chkmembers=' checked'; else $chkmembers='';
+	if(isSet($_REQUEST['notes'])) $chknotes=' checked'; else $chknotes='';
+	print_start('backup');
+	echo "<center><h2>$I[backuprestore]</h2><table cellspacing=\"0\">";
+	thr();
+	echo "<tr><td><$H[form]>".hidden('action', 'setup').hidden('do', 'backup').hidden('session', $U['session']).hidden('lang', $C['lang']);
+	echo '<table width="100%" cellspacing="0"><tr><td>';
+	echo "<input type=\"checkbox\" name=\"settings\" id=\"backupsettings\" value=\"1\"$chksettings><label for=\"backupsettings\">$I[settings]</label>";
+	echo "<input type=\"checkbox\" name=\"filter\" id=\"backupfilter\" value=\"1\"$chkfilters><label for=\"backupfilter\">$I[filter]</label>";
+	echo "<input type=\"checkbox\" name=\"members\" id=\"backupmembers\" value=\"1\"$chkmembers><label for=\"backupmembers\">$I[members]</label>";
+	echo "<input type=\"checkbox\" name=\"notes\" id=\"backupnotes\" value=\"1\"$chknotes><label for=\"backupnotes\">$I[notes]</label>";
+	echo '</td><td>'.submit($I['backup']).'</td></tr></table></form></td></tr>';
+	thr();
+	echo "<tr align=\"right\"><td><$H[form]>".hidden('action', 'setup').hidden('do', 'restore').hidden('session', $U['session']).hidden('lang', $C['lang']);
+	echo '<table cellspacing="0">';
+	echo "<tr><td colspan=\"2\"><textarea name=\"restore\" rows=\"4\" cols=\"60\">".htmlspecialchars(json_encode($code)).'</textarea></td></tr>';
+	echo "<tr><td><input type=\"checkbox\" name=\"settings\" id=\"restoresettings\" value=\"1\"$chksettings><label for=\"restoresettings\">$I[settings]</label>";
+	echo "<input type=\"checkbox\" name=\"filter\" id=\"restorefilter\" value=\"1\"$chkfilters><label for=\"restorefilter\">$I[filter]</label>";
+	echo "<input type=\"checkbox\" name=\"members\" id=\"restoremembers\" value=\"1\"$chkmembers><label for=\"restoremembers\">$I[members]</label>";
+	echo "<input type=\"checkbox\" name=\"notes\" id=\"restorenotes\" value=\"1\"$chknotes><label for=\"restorenotes\">$I[notes]</label></td><td>";
+	echo submit($I['restore']).'</td></tr></table>';
+	echo '</form></td></tr>';
+	thr();
+	echo "<tr align=\"center\"><td><$H[form]>".hidden('action', 'setup').hidden('session', $U['session']).hidden('lang', $C['lang']).submit($I['initgosetup'], 'class="backbutton"')."</form></tr></td></center>";
+	echo '</table>';
 	print_end();
 }
 
@@ -443,14 +613,20 @@ function send_alogin(){
 }
 
 function send_admin($arg=''){
-	global $C, $H, $I, $P, $U;
+	global $C, $H, $I, $U;
 	$ga=get_setting('guestaccess');
 	print_start('admin');
+	$lines=parse_sessions();
+	foreach($lines as $temp){
+		if($temp['entry']!=0 && $temp['status']!=0){
+			$Present[$temp['nickname']]=[$temp['nickname'], $temp['status'], $temp['style']];
+		}
+	}
 	$chlist="<select name=\"name[]\" size=\"5\" multiple><option value=\"\">$I[choose]</option>";
 	$chlist.="<option value=\"&\">$I[allguests]</option>";
-	array_multisort(array_map('strtolower', array_keys($P)), SORT_ASC, SORT_STRING, $P);
-	foreach($P as $user){
-		if($user[1]>0 && $user[1]<$U['status']) $chlist.="<option value=\"$user[0]\" style=\"$user[2]\">$user[0]</option>";
+	array_multisort(array_map('strtolower', array_keys($Present)), SORT_ASC, SORT_STRING, $Present);
+	foreach($Present as $user){
+		if($user[1]<$U['status']) $chlist.="<option value=\"$user[0]\" style=\"$user[2]\">$user[0]</option>";
 	}
 	$chlist.='</select>';
 	echo "<center><h2>$I[admfunc]</h2><i>$arg</i><table cellspacing=\"0\">";
@@ -475,12 +651,12 @@ function send_admin($arg=''){
 	echo "<tr><td><table cellspacing=\"0\" width=\"100%\"><tr><td align=\"left\"><b>$I[logoutinact]</b></td><td align=\"right\">";
 	echo frmadm('logout')."<table cellspacing=\"0\"><tr><td align=\"right\">$chlist</td><td align=\"right\">";
 	echo submit($I['logout']).'</td></tr></table></form></td></tr></table></td></tr>';
+	$views=array('sessions', 'filter', 'linkfilter');
+	foreach($views as $view){
 	thr();
-	echo "<tr><td><table cellspacing=\"0\" width=\"100%\"><tr><td align=\"left\"><b>$I[viewsess]</b></td><td align=\"right\">";
-	echo frmadm('sessions').'<table cellspacing="0"><tr><td align="right">'.submit($I['view']).'</td></tr></table></form></td></tr></table></td></tr>';
-	thr();
-	echo "<tr><td><table cellspacing=\"0\" width=\"100%\"><tr><td align=\"left\"><b>$I[filter]</b></td><td align=\"right\">";
-	echo frmadm('filter').'<table cellspacing="0"><tr><td align="right">'.submit($I['view']).'</td></tr></table></form></td></tr></table></td></tr>';
+		echo '<tr><td><table cellspacing="0" width="100%"><tr><td align="left"><b>'.$I[$view].'</b></td><td align="right">';
+		echo frmadm($view).'<table cellspacing="0"><tr><td align="right">'.submit($I['view']).'</td></tr></table></form></td></tr></table></td></tr>';
+	}
 	thr();
 	echo "<tr><td><table cellspacing=\"0\" width=\"100%\"><tr><td align=\"left\"><b>$I[guestacc]</b></td><td align=\"right\">";
 	echo frmadm('guestaccess').'<table cellspacing="0">';
@@ -491,10 +667,10 @@ function send_admin($arg=''){
 	echo '<option value="0"'; if($ga==0) echo ' selected'; echo ">$I[guestdisallow]</option>";
 	echo '</select></td><td align="right">'.submit($I['change']).'</td></tr></table></form></td></tr></table></td></tr>';
 	thr();
-	if($C['suguests']){
+	if(get_setting('suguests')){
 		echo "<tr><td><table cellspacing=\"0\" width=\"100%\"><tr><td align=\"left\"><b>$I[addsuguest]</b></td><td align=\"right\">";
 		echo frmadm('superguest')."<table cellspacing=\"0\"><tr><td valign=\"bottom\"><select name=\"name\" size=\"1\"><option value=\"\">$I[choose]</option>";
-		foreach($P as $user){
+		foreach($Present as $user){
 			if($user[1]==1) echo "<option value=\"$user[0]\" style=\"$user[2]\">$user[0]</option>";
 		}
 		echo '</select></td><td valign="bottom">'.submit($I['register']).'</td></tr></table></form></td></tr></table></td></tr>';
@@ -505,7 +681,7 @@ function send_admin($arg=''){
 		echo frmadm('status')."<table cellspacing=\"0\"><td valign=\"bottom\" align=\"right\"><select name=\"name\" size=\"1\"><option value=\"\">$I[choose]</option>";
 		print_memberslist();
 		echo "</select><select name=\"set\" size=\"1\"><option value=\"\">$I[choose]</option><option value=\"-\">$I[memdel]</option><option value=\"0\">$I[memdeny]</option>";
-		if($C['suguests']) echo "<option value=\"2\">$I[memsuguest]</option>";
+		if(get_setting('suguests')) echo "<option value=\"2\">$I[memsuguest]</option>";
 		echo "<option value=\"3\">$I[memreg]</option>";
 		echo "<option value=\"5\">$I[memmod]</option>";
 		echo "<option value=\"6\">$I[memsumod]</option>";
@@ -514,7 +690,7 @@ function send_admin($arg=''){
 		thr();
 		echo "<tr><td><table cellspacing=\"0\" width=\"100%\"><tr><td align=\"left\"><b>$I[regguest]</b></td><td align=\"right\">";
 		echo frmadm('register')."<table cellspacing=\"0\"><tr><td valign=\"bottom\"><select name=\"name\" size=\"1\"><option value=\"\">$I[choose]</option>";
-		foreach($P as $user){
+		foreach($Present as $user){
 			if($user[1]==1) echo "<option value=\"$user[0]\" style=\"$user[2]\">$user[0]</option>";
 		}
 		echo '</select></td><td valign="bottom">'.submit($I['register']).'</td></tr></table></form></td></tr></table></td></tr>';
@@ -530,12 +706,13 @@ function send_admin($arg=''){
 }
 
 function send_sessions(){
-	global $C, $H, $I, $U;
+	global $H, $I, $U;
 	$lines=parse_sessions();
 	print_start('sessions');
 	echo "<center><h1>$I[sessact]</h1><table border=\"0\" cellpadding=\"5\">";
 	echo "<thead valign=\"middle\"><tr><th><b>$I[sessnick]</b></th><th><b>$I[sesstimeout]</b></th><th><b>$I[sessua]</b></th>";
-	if($C['trackip']) echo "<th><b>$I[sesip]</b></th>";
+	$trackip=get_setting('trackip');
+	if($trackip) echo "<th><b>$I[sesip]</b></th>";
 	echo "<th><b>$I[actions]</b></th></tr></thead><tbody valign=\"middle\">";
 	foreach($lines as $temp){
 		if($temp['status']!=0 && $temp['entry']!=0 && (!$temp['incognito'] || $temp['status']<$U['status'])){
@@ -545,14 +722,14 @@ function send_sessions(){
 			elseif($temp['status']==6) $s='&nbsp;(SM)';
 			elseif($temp['status']==7) $s='&nbsp;(A)';
 			elseif($temp['status']==8) $s='&nbsp;(SA)';
-			echo '<tr><td align="left">'.style_this($temp['nickname'].$s, $temp['fontinfo']).'</td><td>'.get_timeout($temp['lastpost'], $temp['status']).'</td>';
+			echo '<tr><td align="left">'.style_this($temp['nickname'].$s, $temp['style']).'</td><td>'.get_timeout($temp['lastpost'], $temp['status']).'</td>';
 			if($U['status']>$temp['status'] || $U['session']==$temp['session']){
 				echo "<td align=\"left\">$temp[useragent]</td>";
-				if($C['trackip']) echo "<td align=\"left\">$temp[ip]</td>";
+				if($trackip) echo "<td align=\"left\">$temp[ip]</td>";
 				echo "<td align=\"left\">".frmadm('sessions').hidden('nick', $temp['nickname']).submit($I['kick']).'</form></td></tr>';
 			}else{
 				echo '<td align="left">-</td>';
-				if($C['trackip']) echo '<td align="left">-</td>';
+				if($trackip) echo '<td align="left">-</td>';
 				echo '<td align="left">-</td></tr>';
 			}
 		}
@@ -600,6 +777,41 @@ function manage_filter(){
 	}
 }
 
+function manage_linkfilter(){
+	global $C, $I, $memcached, $mysqli;
+	if(isSet($_REQUEST['id'])){
+		$_REQUEST['match']=htmlspecialchars($_REQUEST['match']);
+		if(isSet($_REQUEST['regex']) && $_REQUEST['regex']==1){
+			if(!is_int(@preg_match("/$_REQUEST[match]/", ''))) send_linkfilter($I['incorregex']);
+			$reg=1;
+		}else{
+			$_REQUEST['match']=preg_replace('/([^\w\d])/', "\\\\$1", $_REQUEST['match']);
+			$reg=0;
+		}
+		if(preg_match('/^[0-9]*$/', $_REQUEST['id'])){
+			if(empty($_REQUEST['match'])){
+				$stmt=mysqli_prepare($mysqli, "DELETE FROM `$C[prefix]linkfilter` WHERE `id`=?");
+				mysqli_stmt_bind_param($stmt, 'i', $_REQUEST['id']);
+				mysqli_stmt_execute($stmt);
+				mysqli_stmt_close($stmt);
+				if($C['memcached']) $memcached->delete("$C[dbname]-$C[prefix]linkfilter");
+			}else{
+				$stmt=mysqli_prepare($mysqli, "UPDATE `$C[prefix]linkfilter` SET `match`=?, `replace`=?, `regex`=? WHERE `id`=?");
+				mysqli_stmt_bind_param($stmt, 'ssii', $_REQUEST['match'], $_REQUEST['replace'], $reg, $_REQUEST['id']);
+				mysqli_stmt_execute($stmt);
+				mysqli_stmt_close($stmt);
+				if($C['memcached']) $memcached->delete("$C[dbname]-$C[prefix]linkfilter");
+			}
+		}elseif(preg_match('/^\+$/', $_REQUEST['id'])){
+			$stmt=mysqli_prepare($mysqli, "INSERT INTO `$C[prefix]linkfilter` (`match`, `replace`, `regex`) VALUES (?, ?, ?)");
+			mysqli_stmt_bind_param($stmt, 'ssi', $_REQUEST['match'], $_REQUEST['replace'], $reg);
+			mysqli_stmt_execute($stmt);
+			mysqli_stmt_close($stmt);
+			if($C['memcached']) $memcached->delete("$C[dbname]-$C[prefix]linkfilter");
+		}
+	}
+}
+
 function send_filter($arg=''){
 	global $C, $H, $I, $U, $memcached, $mysqli;
 	print_start('filter');
@@ -648,6 +860,44 @@ function send_filter($arg=''){
 	print_end();
 }
 
+function send_linkfilter($arg=''){
+	global $C, $H, $I, $U, $memcached, $mysqli;
+	print_start('linkfilter');
+	echo "<center><h2>$I[linkfilter]</h2><i>$arg</i><table cellspacing=\"0\">";
+	thr();
+	echo "<tr><th><table cellspacing=\"0\" width=\"100%\"><tr><td style=\"width:8em\"><center><b>$I[fid]</b></center></td>";
+	echo "<td style=\"width:12em\"><center><b>$I[match]</b></center></td>";
+	echo "<td style=\"width:12em\"><center><b>$I[replace]</b></center></td>";
+	echo "<td style=\"width:5em\"><center><b>$I[regex]</b></center></td>";
+	echo "<td style=\"width:5em\"><center><b>$I[apply]</b></center></td></tr></table></th></tr>";
+	if($C['memcached']) $filters=$memcached->get("$C[dbname]-$C[prefix]linkfilter");
+	if(!$C['memcached'] || $memcached->getResultCode()!=Memcached::RES_SUCCESS){
+		$filters=array();
+		$result=mysqli_query($mysqli, "SELECT * FROM `$C[prefix]linkfilter`");
+		while($filter=mysqli_fetch_array($result, MYSQLI_ASSOC)) $filters[]=$filter;
+		if($C['memcached']) $memcached->set("$C[dbname]-$C[prefix]linkfilter", $filters);
+	}
+	foreach($filters as $filter){
+		if($filter['regex']==1) $checked=' checked';
+		else $checked='';
+		if($filter['regex']==0) $filter['match']=preg_replace('/(\\\\(.))/', "$2", $filter['match']);
+		echo '<tr><td>'.frmadm('linkfilter').hidden('id', $filter['id']);
+		echo "<table cellspacing=\"0\" width=\"100%\"><tr><td style=\"width:8em\"><b>$I[filter] $filter[id]:</b></td>";
+		echo "<td style=\"width:12em\"><input type=\"text\" name=\"match\" value=\"$filter[match]\" size=\"20\" style=\"$U[style]\"></td>";
+		echo '<td style="width:12em"><input type="text" name="replace" value="'.htmlspecialchars($filter['replace'])."\" size=\"20\" style=\"$U[style]\"></td>";
+		echo "<td style=\"width:5em\"><input type=\"checkbox\" name=\"regex\" id=\"regex-$filter[id]\" value=\"1\"$checked><label for=\"regex-$filter[id]\">$I[regex]</label></td>";
+		echo '<td align="right" style="width:5em">'.submit($I['change']).'</td></tr></table></form></td></tr>';
+	}
+	echo '<tr><td>'.frmadm('linkfilter').hidden('id', '+');
+	echo "<table cellspacing=\"0\" width=\"100%\"><tr><td align=\"left\" style=\"width:8em\"><b>$I[newfilter]</b></td>";
+	echo "<td style=\"width:12em\"><input type=\"text\" name=\"match\" value=\"\" size=\"20\" style=\"$U[style]\"></td>";
+	echo "<td style=\"width:12em\"><input type=\"text\" name=\"replace\" value=\"\" size=\"20\" style=\"$U[style]\"></td>";
+	echo "<td style=\"width:5em\"><input type=\"checkbox\" name=\"regex\" id=\"regex\" value=\"1\"><label for=\"regex\">$I[regex]</label></td>";
+	echo '<td align="right" style="width:5em">'.submit($I['add']).'</td></tr></table></form></td></tr>';
+	echo "</table><br>$H[backtochat]</center>";
+	print_end();
+}
+
 function send_frameset(){
 	global $C, $H, $I, $U, $mysqli;
 	header('Content-Type: text/html; charset=UTF-8'); header('Pragma: no-cache'); header('Cache-Control: no-cache'); header('Expires: 0');
@@ -670,11 +920,11 @@ function send_messages(){
 		$url="$_SERVER[SCRIPT_NAME]?action=view&session=$U[session]&lang=$C[lang]";
 	}
 	print_start('messages', $U['refresh'], $url);
-	echo '<a name="top"></a>';
+	echo '<a id="top"></a>';
 	print_chatters();
-	echo "<table cellspacing=\"0\" width=\"100%\"><tr><td valign=\"top\" align=\"right\"><a href=\"#bottom\">$I[bottom]</a></td></tr></table>";
+	echo "<a style=\"position:fixed; top:0.5em; right:0.5em\" href=\"#bottom\">$I[bottom]</a>";
 	print_messages();
-	echo "<a name=\"bottom\"></a><table cellspacing=\"0\" width=\"100%\"><tr><td align=\"right\"><a href=\"#top\">$I[top]</a></td></tr></table>";
+	echo "<a id=\"bottom\"></a><a style=\"position:fixed; bottom:0.5em; right:0.5em\" href=\"#top\">$I[top]</a>";
 	print_end();
 }
 
@@ -723,7 +973,7 @@ function send_approve_waiting(){
 		echo frmadm('approve').'<table cellpadding="5">';
 		echo "<thead align=\"left\"><tr><th><b>$I[sessnick]</b></th><th><b>$I[sessua]</b></th></tr></thead><tbody align=\"left\" valign=\"middle\">";
 		while($temp=mysqli_fetch_array($result, MYSQLI_ASSOC)){
-			echo '<tr>'.hidden('alls[]', $temp['nickname'])."<td><input type=\"checkbox\" name=\"csid[]\" id=\"$temp[nickname]]\" value=\"$temp[nickname]\"><label for=\"$temp[nickname]\">&nbsp;$temp[displayname]</label></td><td>$temp[useragent]</td></tr>";
+			echo '<tr>'.hidden('alls[]', $temp['nickname'])."<td><input type=\"checkbox\" name=\"csid[]\" id=\"$temp[nickname]]\" value=\"$temp[nickname]\"><label for=\"$temp[nickname]\"> ".style_this($temp['nickname'], $temp['style'])."</label></td><td>$temp[useragent]</td></tr>";
 		}
 		echo "</tbody></table><br><table><tr><td><input type=\"radio\" name=\"what\" value=\"allowchecked\" id=\"allowchecked\" checked></td><td><label for=\"allowchecked\">$I[allowchecked]</label></td>";
 		echo "<td><input type=\"radio\" name=\"what\" value=\"allowall\" id=\"allowall\"></td><td><label for=\"allowall\">$I[allowall]</label></td>";
@@ -762,17 +1012,18 @@ function send_waiting_room(){
 	}elseif(!$wait && $U['entry']!=0){
 		send_frameset();
 	}else{
+		$refresh=get_setting('defaultrefresh');
 		if(isSet($_COOKIE['test'])){
-			header("Refresh: $C[defaultrefresh]; URL=$_SERVER[SCRIPT_NAME]?action=wait");
-			print_start('waitingroom', $C['defaultrefresh'], "$_SERVER[SCRIPT_NAME]?action=wait");
+			header("Refresh: $refresh; URL=$_SERVER[SCRIPT_NAME]?action=wait");
+			print_start('waitingroom', $refresh, "$_SERVER[SCRIPT_NAME]?action=wait");
 		}else{
-			header("Refresh: $C[defaultrefresh]; URL=$_SERVER[SCRIPT_NAME]?action=wait&session=$U[session]");
-			print_start('waitingroom', $C['defaultrefresh'], "$_SERVER[SCRIPT_NAME]?action=wait&session=$U[session]&lang=$C[lang]");
+			header("Refresh: $refresh; URL=$_SERVER[SCRIPT_NAME]?action=wait&session=$U[session]");
+			print_start('waitingroom', $refresh, "$_SERVER[SCRIPT_NAME]?action=wait&session=$U[session]&lang=$C[lang]");
 		}
 		if($wait){
-			echo "<center><h2>$I[waitingroom]</h2><p>".sprintf($I['waittext'], $U['displayname'], $timeleft).'</p><br><p>'.sprintf($I['waitreload'], $C['defaultrefresh']).'</p><br><br>';
+			echo "<center><h2>$I[waitingroom]</h2><p>".sprintf($I['waittext'], style_this($U['nickname'], $U['style']), $timeleft).'</p><br><p>'.sprintf($I['waitreload'], $refresh).'</p><br><br>';
 		}else{
-			echo "<center><h2>$I[waitingroom]</h2><p>".sprintf($I['admwaittext'], $U['displayname']).'</p><br><p>'.sprintf($I['waitreload'], $C['defaultrefresh']).'</p><br><br>';
+			echo "<center><h2>$I[waitingroom]</h2><p>".sprintf($I['admwaittext'], style_this($U['nickname'], $U['style'])).'</p><br><p>'.sprintf($I['waitreload'], $refresh).'</p><br><br>';
 		}
 		echo "<hr><form action=\"$_SERVER[SCRIPT_NAME]\" method=\"post\">".hidden('action', 'wait').hidden('session', $U['session']).hidden('lang', $C['lang']).submit($I['reload']).'</form><br>';
 		$rulestxt=get_setting('rulestxt');
@@ -803,13 +1054,13 @@ function send_del_confirm(){
 }
 
 function send_post(){
-	global $C, $I, $P, $U, $countmods;
+	global $I, $P, $U, $countmods;
 	$U['postid']=substr(time(), -6);
 	print_start('post');
 	if(!isSet($_REQUEST['multi'])) $_REQUEST['multi']='';
 	if(!isSet($_REQUEST['sendto'])) $_REQUEST['sendto']='';
 	echo '<center><table cellspacing="0"><tr><td align="center">'.frmpst('post').hidden('postid', $U['postid']).hidden('multi', $_REQUEST['multi']);
-	echo "<table cellspacing=\"0\"><tr><td valign=\"top\">$U[displayname]</td><td valign=\"top\">:</td>";
+	echo '<table cellspacing="0"><tr><td valign="top">'.style_this($U['nickname'], $U['style']).'</td><td valign="top">:</td>';
 	if(!isSet($U['rejected'])) $U['rejected']='';
 	if(isSet($_REQUEST['multi']) && $_REQUEST['multi']=='on'){
 		echo "<td valign=\"top\"><textarea name=\"message\" wrap=\"virtual\" rows=\"$U[boxheight]\" cols=\"$U[boxwidth]\" maxlength=\"".get_setting('maxmessage')."\" style=\"$U[style]\" autofocus>$U[rejected]</textarea></td>";
@@ -844,11 +1095,11 @@ function send_post(){
 		if($U['nickname']!==$user[0] && !in_array($user[0], $ignored)){
 			echo '<option ';
 			if(isSet($_REQUEST['sendto']) && $_REQUEST['sendto']==$user[0]) echo 'selected ';
-			echo "value=\"$user[0]\" style=\"$user[2]\">$user[0]</option>";
+			echo "value=\"$user[0]\" style=\"$user[1]\">$user[0]</option>";
 		}
 	}
 	echo '</select>';
-	if($U['status']>=5 || ($C['memkick'] && $countmods==0 && $U['status']>=3)){
+	if($U['status']>=5 || (get_setting('memkick') && $countmods==0 && $U['status']>=3)){
 		echo "<input type=\"checkbox\" name=\"kick\" id=\"kick\" value=\"kick\"><label for=\"kick\">&nbsp;$I[kick]</label>";
 		echo "<input type=\"checkbox\" name=\"what\" id=\"what\" value=\"purge\" checked><label for=\"what\">&nbsp;$I[alsopurge]</label>";
 	}
@@ -867,12 +1118,12 @@ function send_post(){
 }
 
 function send_help(){
-	global $C, $H, $I, $U;
+	global $H, $I, $U;
 	print_start('help');
 	$rulestxt=get_setting('rulestxt');
 	if(!empty($rulestxt)) echo "<h2>$I[rules]</h2>$rulestxt<br><br><hr>";
 	echo "<h2>$I[help]</h2>$I[helpguest]";
-	if($C['imgembed']) echo "<br>$I[helpembed]";
+	if(get_setting('imgembed')) echo "<br>$I[helpembed]";
 	if($U['status']>=3){
 		echo "<br>$I[helpmem]<br>";
 		if($U['status']>=5){
@@ -880,7 +1131,7 @@ function send_help(){
 			if($U['status']>=7) echo "<br>$I[helpadm]<br>";
 		}
 	}
-	echo "<br><hr><center>$H[backtochat]$H[credit]";
+	echo "<br><hr><center>$H[backtochat]$H[credit]</center>";
 	print_end();
 }
 
@@ -902,7 +1153,7 @@ function send_profile($arg=''){
 			$style='';
 			foreach($P as $user){
 				if($ign==$user[0]){
-					$style=" style=\"$user[2]\"";
+					$style=" style=\"$user[1]\"";
 					break;
 				}
 			}
@@ -916,7 +1167,7 @@ function send_profile($arg=''){
 		echo "<tr><td>&nbsp;</td><td><select name=\"ignore\" size=\"1\"><option value=\"\">$I[choose]</option>";
 		foreach($P as $user){
 			if($U['nickname']!==$user[0] && !in_array($user[0], $ignored)){
-				echo "<option value=\"$user[0]\" style=\"$user[2]\">$user[0]</option>";
+				echo "<option value=\"$user[0]\" style=\"$user[1]\">$user[0]</option>";
 			}
 		}
 		echo '</select></td></tr></table></td></tr></table></td></tr>';
@@ -926,6 +1177,8 @@ function send_profile($arg=''){
 	echo "<tr><td>&nbsp;</td><td><input type=\"number\" name=\"refresh\" size=\"3\" maxlength=\"3\" min=\"5\" max=\"150\" value=\"$U[refresh]\"></td></tr></table></td></tr></table></td></tr>";
 	thr();
 	if(!isSet($_COOKIE[$C['cookiename']])) $session='&session=$U[session]'; else $session='';
+	preg_match('/#([0-9a-f]{6})/i', $U['style'], $matches);
+	$U['colour']=$matches[1];
 	echo "<tr><td><table cellspacing=\"0\" width=\"100%\"><tr><td align=\"left\"><b>$I[fontcolour]</b> (<a href=\"$_SERVER[SCRIPT_NAME]?action=colours$session\" target=\"view\">$I[viewexample]</a>)</td><td align=\"right\"><table cellspacing=\"0\">";
 	echo "<tr><td>&nbsp;</td><td><input type=\"text\" size=\"6\" maxlength=\"6\" pattern=\"[a-fA-F0-9]{6}\" value=\"$U[colour]\" name=\"colour\"></td></tr></table></td></tr></table></td></tr>";
 	thr();
@@ -936,32 +1189,32 @@ function send_profile($arg=''){
 		echo "<tr><td><table cellspacing=\"0\" width=\"100%\"><tr><td align=\"left\"><b>$I[fontface]</b></td><td align=\"right\"><table cellspacing=\"0\">";
 		echo "<tr><td>&nbsp;</td><td><select name=\"font\" size=\"1\"><option value=\"\">* $I[roomdefault] *</option>";
 		foreach($F as $name=>$font){
-			echo '<option style="'.get_style($font).'" ';
-			if(preg_match("/$font/", $U['fontinfo'])) echo 'selected ';
+			echo "<option style=\"$font\" ";
+			if(preg_match("/$font/", $U['style'])) echo 'selected ';
 			echo "value=\"$name\">$name</option>";
 		}
 		echo '</select></td><td>&nbsp;</td><td><input type="checkbox" name="bold" id="bold" value="on"';
-		if(preg_match('/<i?bi?>/', $U['fontinfo'])) echo ' checked';
+		if(preg_match('/font-weight:bold;/', $U['style'])) echo ' checked';
 		echo "></td><td><label for=\"bold\"><b>$I[bold]</b></label></td><td>&nbsp;</td><td><input type=\"checkbox\" name=\"italic\" id=\"italic\" value=\"on\"";
-		if(preg_match('/<b?ib?>/', $U['fontinfo'])) echo ' checked';
+		if(preg_match('/font-style:italic;/', $U['style'])) echo ' checked';
 		echo "></td><td><label for=\"italic\"><i>$I[italic]</i></label></td></tr></table></td></tr></table></td></tr>";
 		thr();
 	}
-	echo "<tr><td align=\"center\">$U[displayname]&nbsp;: ".style_this($I['fontexample'], $U['fontinfo']).'</td></tr>';
+	echo '<tr><td align="center">'.style_this("$U[nickname] : $I[fontexample]", $U['style']).'</td></tr>';
 	thr();
 	echo "<tr><td><table cellspacing=\"0\" width=\"100%\"><tr><td align=\"left\"><b>$I[timestamps]</b></td><td align=\"right\"><table cellspacing=\"0\">";
 	echo '<tr><td>&nbsp;</td><td><input type="checkbox" name="timestamps" id="timestamps" value="on"';
 	if($U['timestamps']) echo ' checked';
 	echo "></td><td><label for=\"timestamps\"><b>$I[enabled]</b></label></td></tr></table></td></tr></table></td></tr>";
 	thr();
-	if($C['imgembed']){
+	if(get_setting('imgembed')){
 		echo "<tr><td><table cellspacing=\"0\" width=\"100%\"><tr><td align=\"left\"><b>$I[embed]</b></td><td align=\"right\"><table cellspacing=\"0\">";
 		echo '<tr><td>&nbsp;</td><td><input type="checkbox" name="embed" id="embed" value="on"';
 		if($U['embed'] && isSet($_COOKIE[$C['cookiename']])) echo ' checked';
 		echo "></td><td><label for=\"embed\"><b>$I[enabled]</b></label></td></tr></table></td></tr></table></td></tr>";
 		thr();
 	}
-	if($U['status']>=5 && $C['incognito']){
+	if($U['status']>=5 && get_setting('incognito')){
 		echo "<tr><td><table cellspacing=\"0\" width=\"100%\"><tr><td align=\"left\"><b>$I[incognito]</b></td><td align=\"right\"><table cellspacing=\"0\">";
 		echo '<tr><td>&nbsp;</td><td><input type="checkbox" name="incognito" id="incognito" value="on"';
 		if($U['incognito']) echo ' checked';
@@ -1010,7 +1263,7 @@ function send_controls(){
 function send_logout(){
 	global $H, $I, $U;
 	print_start('logout');
-	echo '<center><h1>'.sprintf($I['bye'], $U['displayname'])."</h1>$H[backtologin]</center>";
+	echo '<center><h1>'.sprintf($I['bye'], style_this($U['nickname'], $U['style']))."</h1>$H[backtologin]</center>";
 	print_end();
 }
 
@@ -1038,7 +1291,8 @@ function send_login(){
 	print_start('login');
 	$ga=get_setting('guestaccess');
 	$englobal=get_setting('englobalpass');
-	echo "<center><h1>$C[chatname]</h1><$H[form] target=\"_parent\">".hidden('action', 'login').hidden('lang', $C['lang']);
+	echo "<center><h1>$C[chatname]</h1>";
+	echo "<$H[form] target=\"_parent\">".hidden('action', 'login').hidden('lang', $C['lang']);
 	if($englobal==1 && isSet($_POST['globalpass'])) echo hidden('globalpass', $_POST['globalpass']);
 	echo '<table border="2" width="1" rules="none">';
 	if($englobal!=1 || (isSet($_POST['globalpass']) && $_POST['globalpass']==get_setting('globalpass'))){
@@ -1066,7 +1320,7 @@ function send_login(){
 	foreach($L as $lang=>$name){
 		echo " <a href=\"$_SERVER[SCRIPT_NAME]?lang=$lang\">$name</a>";
 	}
-	echo "</p>$H[credit]";
+	echo "</p>$H[credit]</center>";
 	print_end();
 }
 
@@ -1086,10 +1340,10 @@ function print_chatters(){
 		if($temp[0]>0) echo '<td valign="top">'.frmadm('approve').submit(sprintf($I['approveguests'], $temp[0])).'</form></td><td>&nbsp;</td>';
 	}
 	if(!empty($M)){
-		echo "<td valign=\"top\"><b>$I[members]</b></td><td>&nbsp;</td><td valign=\"top\">".implode(' &nbsp; ', $M).'</td>';
+		echo "<td valign=\"top\"><b>$I[members]:</b></td><td>&nbsp;</td><td valign=\"top\">".implode(' &nbsp; ', $M).'</td>';
 		if(!empty($G)) echo '<td>&nbsp;&nbsp;</td>';
 	}
-	if(!empty($G)) echo "<td valign=\"top\"><b>$I[guests]</b></td><td>&nbsp;</td><td valign=\"top\">".implode(' &nbsp; ', $G).'</td>';
+	if(!empty($G)) echo "<td valign=\"top\"><b>$I[guests]:</b></td><td>&nbsp;</td><td valign=\"top\">".implode(' &nbsp; ', $G).'</td>';
 	echo '</tr></table>';
 }
 
@@ -1113,15 +1367,14 @@ function print_memberslist(){
 
 function create_session($setup){
 	global $C, $I, $U, $memcached, $mysqli;
-	$U['nickname']=cleanup_nick($_REQUEST['nick']);
+	$U['nickname']=preg_replace('/\s+/', '', $_REQUEST['nick']);
 	$U['passhash']=md5(sha1(md5($U['nickname'].$_REQUEST['pass'])));
-	if(isSet($_REQUEST['colour'])) $U['colour']=$_REQUEST['colour'];
-	else $U['colour']=$C['coltxt'];
+	if(isSet($_REQUEST['colour'])) $U['colour']=$_REQUEST['colour']; else $U['colour']='';
 	$U['status']=1;
 	check_member();
 	add_user_defaults();
 	if($setup) $U['incognito']=true;
-	if(get_setting('captcha')>0 && ($U['status']==1 || !$C['dismemcaptcha'])){
+	if(get_setting('captcha')>0 && ($U['status']==1 || get_setting('dismemcaptcha')==0)){
 		if(!isSet($_REQUEST['challenge'])) send_error($I['wrongcaptcha']);
 		if(!$C['memcached']){
 			$stmt=mysqli_prepare($mysqli, "SELECT `code` FROM `$C[prefix]captcha` WHERE `id`=?");
@@ -1131,7 +1384,7 @@ function create_session($setup){
 			if(!mysqli_stmt_fetch($stmt)) send_error($I['captchaexpire']);
 			mysqli_stmt_close($stmt);
 		}else{
-			if(!$code=$memcached->get("$C[dbname]-$C[prefix]captcha-$_REQUEST[challenge]")) send_error($I['captchexpire']);
+			if(!$code=$memcached->get("$C[dbname]-$C[prefix]captcha-$_REQUEST[challenge]")) send_error($I['captchaexpire']);
 			$memcached->delete("$C[dbname]-$C[prefix]captcha-$_REQUEST[challenge]");
 		}
 		if($_REQUEST['captcha']!=$code) send_error($I['wrongcaptcha']);
@@ -1142,8 +1395,8 @@ function create_session($setup){
 		mysqli_stmt_close($stmt);
 	}
 	if($U['status']==1){
-		if(!valid_nick($U['nickname'])) send_error(sprintf($I['invalnick'], $C['maxname']));
-		if(!valid_pass($_REQUEST['pass'])) send_error(sprintf($I['invalpass'], $C['minpass']));
+		if(!valid_nick($U['nickname'])) send_error(sprintf($I['invalnick'], get_setting('maxname')));
+		if(!valid_pass($_REQUEST['pass'])) send_error(sprintf($I['invalpass'], get_setting('minpass')));
 		if(get_setting('guestaccess')==0) send_error($I['noguests']);
 		if(get_setting('englobalpass')!=0 && isSet($_REQUEST['globalpass']) && $_REQUEST['globalpass']!=get_setting('globalpass')) send_error($I['wrongglobalpass']);
 	}
@@ -1151,44 +1404,41 @@ function create_session($setup){
 }
 
 function write_new_session(){
-	global $C, $I, $U, $mysqli;
+	global $C, $H, $I, $U, $mysqli;
 	// read and update current sessions
 	$lines=parse_sessions();
-	$sids; $inuse=false; $reentry=false;
+	$sids; $reentry=false;
 	foreach($lines as $temp){
 		$sids[$temp['session']]=true;// collect all existing ids
 		if($temp['nickname']==$U['nickname']){// nick already here?
 			if($U['passhash']==$temp['passhash']){
 				$U=$temp;
-				add_user_defaults();
+				if($U['status']==0){
+					setcookie($C['cookiename'], false);
+					send_error("$I[kicked]<br>$U[kickmessage]");
+				}
 				setcookie($C['cookiename'], $U['session']);
+				$H['begin_body']="body style=\"background-color:#$U[bgcolour];\"";
 				$reentry=true;
 				break;
 			}else{
-				$inuse=true;
-				break;
+				send_error($I['wrongpass']);
 			}
 		}
 	}
 	// create new session:
-	if(!$inuse && !$reentry){
+	if(!$reentry){
 		do{
 			$U['session']=md5(time().rand().$U['nickname']);
 		}while(isSet($sids[$U['session']]));// check for hash collision
 		if(isSet($_SERVER['HTTP_USER_AGENT'])) $useragent=htmlspecialchars($_SERVER['HTTP_USER_AGENT']);
 		else $useragent='';
-		$ip=$_SERVER['REMOTE_ADDR'];
-		$stmt=mysqli_prepare($mysqli, "INSERT INTO `$C[prefix]sessions` (`session`, `nickname`, `displayname`, `status`, `refresh`, `fontinfo`, `style`, `lastpost`, `passhash`, `postid`, `boxwidth`, `boxheight`, `useragent`, `bgcolour`, `notesboxwidth`, `notesboxheight`, `entry`, `timestamps`, `embed`, `incognito`, `ip`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
-		mysqli_stmt_bind_param($stmt, 'sssiissisiiissiiiiiis', $U['session'], $U['nickname'], $U['displayname'], $U['status'], $U['refresh'], $U['fontinfo'], $U['style'], $U['lastpost'], $U['passhash'], $U['postid'], $U['boxwidth'], $U['boxheight'], $useragent, $U['bgcolour'], $U['notesboxwidth'], $U['notesboxheight'], $U['entry'], $U['timestamps'], $U['embed'], $U['incognito'], $ip);
+		$stmt=mysqli_prepare($mysqli, "INSERT INTO `$C[prefix]sessions` (`session`, `nickname`, `status`, `refresh`, `style`, `lastpost`, `passhash`, `postid`, `boxwidth`, `boxheight`, `useragent`, `bgcolour`, `notesboxwidth`, `notesboxheight`, `entry`, `timestamps`, `embed`, `incognito`, `ip`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
+		mysqli_stmt_bind_param($stmt, 'ssiisisiiissiiiiiis', $U['session'], $U['nickname'], $U['status'], $U['refresh'], $U['style'], $U['lastpost'], $U['passhash'], $U['postid'], $U['boxwidth'], $U['boxheight'], $useragent, $U['bgcolour'], $U['notesboxwidth'], $U['notesboxheight'], $U['entry'], $U['timestamps'], $U['embed'], $U['incognito'], $_SERVER['REMOTE_ADDR']);
 		mysqli_stmt_execute($stmt);
 		mysqli_stmt_close($stmt);
 		setcookie($C['cookiename'], $U['session']);
-		if($U['status']>=3 && !$U['incognito']) add_system_message(sprintf(get_setting('msgenter'), $U['displayname']));
-	}elseif($inuse){
-		send_error($I['wrongpass']);
-	}elseif($U['status']==0){
-		setcookie($C['cookiename'], false);
-		send_error("$I[kicked]<br>$U[kickmessage]");
+		if($U['status']>=3 && !$U['incognito']) add_system_message(sprintf(get_setting('msgenter'), style_this($U['nickname'], $U['style'])));
 	}
 }
 
@@ -1231,10 +1481,10 @@ function check_login(){
 	global $C, $I, $U, $mysqli;
 	$ga=get_setting('guestaccess');
 	if(isSet($_POST['session'])){
-		$stmt=mysqli_prepare($mysqli, "SELECT `session`, `nickname`, `displayname`, `status`, `refresh`, `fontinfo`, `style`, `lastpost`, `passhash`, `postid`, `boxwidth`, `boxheight`, `kickmessage`, `bgcolour`, `notesboxheight`, `notesboxwidth`, `entry`, `timestamps`, `embed`, `incognito` FROM `$C[prefix]sessions` WHERE `session`=?");
+		$stmt=mysqli_prepare($mysqli, "SELECT `session`, `nickname`, `status`, `refresh`, `style`, `lastpost`, `passhash`, `postid`, `boxwidth`, `boxheight`, `kickmessage`, `bgcolour`, `notesboxheight`, `notesboxwidth`, `entry`, `timestamps`, `embed`, `incognito` FROM `$C[prefix]sessions` WHERE `session`=?");
 		mysqli_stmt_bind_param($stmt, 's', $_POST['session']);
 		mysqli_stmt_execute($stmt);
-		mysqli_stmt_bind_result($stmt, $U['session'], $U['nickname'], $U['displayname'], $U['status'], $U['refresh'], $U['fontinfo'], $U['style'], $U['lastpost'], $U['passhash'], $U['postid'], $U['boxwidth'], $U['boxheight'], $U['kickmessage'], $U['bgcolour'], $U['notesboxheight'], $U['notesboxwidth'], $U['entry'], $U['timestamps'], $U['embed'], $U['incognito']);
+		mysqli_stmt_bind_result($stmt, $U['session'], $U['nickname'], $U['status'], $U['refresh'], $U['style'], $U['lastpost'], $U['passhash'], $U['postid'], $U['boxwidth'], $U['boxheight'], $U['kickmessage'], $U['bgcolour'], $U['notesboxheight'], $U['notesboxwidth'], $U['entry'], $U['timestamps'], $U['embed'], $U['incognito']);
 		if(mysqli_stmt_fetch($stmt)){
 			mysqli_stmt_close($stmt);
 			if($U['status']==0){
@@ -1293,7 +1543,7 @@ function kill_session(){
 		mysqli_stmt_close($stmt);
 		if($C['memcached']) $memcached->delete("$C[dbname]-$C[prefix]ignored");
 	}
-	elseif($U['status']>=3 && !$U['incognito']) add_system_message(sprintf(get_setting('msgexit'), $U['displayname']));
+	elseif($U['status']>=3 && !$U['incognito']) add_system_message(sprintf(get_setting('msgexit'), style_this($U['nickname'], $U['style'])));
 }
 
 function kick_chatter($names, $mes, $purge){
@@ -1308,7 +1558,7 @@ function kick_chatter($names, $mes, $purge){
 				mysqli_stmt_bind_param($stmt, 'ss', $mes, $temp['session']);
 				mysqli_stmt_execute($stmt);
 				if($purge) del_all_messages($temp['nickname'], 10, 0);
-				$lonick.="$temp[displayname], ";
+				$lonick.=style_this($temp['nickname'], $temp['style']).', ';
 				++$i;
 				unset($P[$name]);
 			}
@@ -1362,23 +1612,6 @@ function logout_chatter($names){
 	mysqli_stmt_close($stmt3);
 }
 
-function update_session(){
-	global $C, $U, $mysqli;
-	if($U['postid']==$_REQUEST['postid']){// ignore double post=reload from browser or proxy
-		$_REQUEST['message']='';
-	}elseif(time()-$U['lastpost']<=1){// time between posts too short, reject!
-		$U['rejected']=$_REQUEST['message'];
-		$_REQUEST['message']='';
-	}else{// valid post
-		$U['postid']=substr($_REQUEST['postid'], 0, 6);
-		$U['lastpost']=time();
-		$stmt=mysqli_prepare($mysqli, "UPDATE `$C[prefix]sessions` SET `lastpost`=?, `postid`=? WHERE `session`=?");
-		mysqli_stmt_bind_param($stmt, 'iis', $U['lastpost'], $U['postid'], $U['session']);
-		mysqli_stmt_execute($stmt);
-		mysqli_stmt_close($stmt);
-	}
-}
-
 function check_session(){
 	global $C, $I, $U;
 	parse_sessions();
@@ -1402,7 +1635,7 @@ function get_nowchatting(){
 }
 
 function parse_sessions(){
-	global $C, $G, $M, $P, $U, $countmods, $memcached, $mysqli;
+	global $C, $G, $H, $M, $P, $U, $countmods, $memcached, $mysqli;
 	$result=mysqli_query($mysqli, "SELECT `nickname`, `status`, `session` FROM `$C[prefix]sessions` WHERE (`lastpost`<'".(time()-60*get_setting('guestexpire'))."' AND `status`<='2') OR (`lastpost`<'".(time()-60*get_setting('memberexpire'))."' AND `status`>'2')");
 	if(mysqli_num_rows($result)>0){
 		$stmt=mysqli_prepare($mysqli, "DELETE FROM `$C[prefix]sessions` WHERE `nickname`=?");
@@ -1434,7 +1667,7 @@ function parse_sessions(){
 		foreach($lines as $temp){
 			if($temp['session']==$_REQUEST['session']){
 				$U=$temp;
-				add_user_defaults();
+				$H['begin_body']="body style=\"background-color:#$U[bgcolour];\"";
 				break;
 			}
 		}
@@ -1446,12 +1679,12 @@ function parse_sessions(){
 	foreach($lines as $temp){
 		if($temp['entry']!=0){
 			if($temp['status']==1 || $temp['status']==2){
-				$P[$temp['nickname']]=[$temp['nickname'], $temp['status'], $temp['style']];
-				$G[]=$temp['displayname'];
+				$P[$temp['nickname']]=[$temp['nickname'], $temp['style']];
+				$G[]=style_this($temp['nickname'], $temp['style']);
 			}elseif($temp['status']>2){
 				if(!$temp['incognito']){
-					$P[$temp['nickname']]=[$temp['nickname'], $temp['status'], $temp['style']];
-					$M[]=$temp['displayname'];
+					$P[$temp['nickname']]=[$temp['nickname'], $temp['style']];
+					$M[]=style_this($temp['nickname'], $temp['style']);
 				}
 				if($temp['status']>=5) ++$countmods;
 			}
@@ -1464,10 +1697,10 @@ function parse_sessions(){
 
 function check_member(){
 	global $C, $I, $U, $mysqli;
-	$stmt=mysqli_prepare($mysqli, "SELECT `nickname`, `passhash`, `status`, `refresh`, `colour`, `bgcolour`, `fontface`, `fonttags`, `boxwidth`, `boxheight`, `notesboxwidth`, `notesboxheight`, `lastlogin`, `timestamps`, `embed`, `incognito` FROM `$C[prefix]members` WHERE `nickname`=?");
+	$stmt=mysqli_prepare($mysqli, "SELECT `nickname`, `passhash`, `status`, `refresh`, `bgcolour`, `boxwidth`, `boxheight`, `notesboxwidth`, `notesboxheight`, `lastlogin`, `timestamps`, `embed`, `incognito`, `style` FROM `$C[prefix]members` WHERE `nickname`=?");
 	mysqli_stmt_bind_param($stmt, 's', $U['nickname']);
 	mysqli_stmt_execute($stmt);
-	mysqli_stmt_bind_result($stmt, $temp['nickname'], $temp['passhash'], $temp['status'], $temp['refresh'], $temp['colour'], $temp['bgcolour'], $temp['fontface'], $temp['fonttags'], $temp['boxwidth'], $temp['boxheight'], $temp['notesboxwidth'], $temp['notesboxheight'], $temp['lastlogin'], $temp['timestamps'], $temp['embed'], $temp['incognito']);
+	mysqli_stmt_bind_result($stmt, $temp['nickname'], $temp['passhash'], $temp['status'], $temp['refresh'], $temp['bgcolour'], $temp['boxwidth'], $temp['boxheight'], $temp['notesboxwidth'], $temp['notesboxheight'], $temp['lastlogin'], $temp['timestamps'], $temp['embed'], $temp['incognito'], $temp['style']);
 	if(mysqli_stmt_fetch($stmt)){
 		if($temp['passhash']==$U['passhash']){
 			mysqli_stmt_close($stmt);
@@ -1485,14 +1718,14 @@ function check_member(){
 }
 
 function read_members(){
-	global $A, $C, $F, $memcached, $mysqli;
+	global $A, $C, $memcached, $mysqli;
 	if($C['memcached']) $A=$memcached->get("$C[dbname]-$C[prefix]members");
 	if(!$C['memcached'] || $memcached->getResultCode()!=Memcached::RES_SUCCESS){
 		$result=mysqli_query($mysqli, "SELECT * FROM `$C[prefix]members`");
 		while($temp=mysqli_fetch_array($result, MYSQLI_ASSOC)){
 			$A[$temp['nickname']][0]=$temp['nickname'];
 			$A[$temp['nickname']][1]=$temp['status'];
-			$A[$temp['nickname']][2]=@get_style("#$temp[colour] {$F[$temp['fontface']]} <$temp[fonttags]>");
+			$A[$temp['nickname']][2]=$temp['style'];
 		}
 		if($C['memcached']) $memcached->set("$C[dbname]-$C[prefix]members", $A);
 	}
@@ -1504,15 +1737,15 @@ function register_guest($status){
 	if(!isSet($P[$_REQUEST['name']])) send_admin(sprintf($I['cantreg'], $_REQUEST['name']));
 	read_members();
 	if(isSet($A[$_REQUEST['name']])) send_admin(sprintf($I['alreadyreged'], $_REQUEST['name']));
-	$stmt=mysqli_prepare($mysqli, "SELECT `session`, `nickname`, `displayname`, `passhash`, `refresh`, `fontinfo`, `bgcolour`, `boxwidth`, `boxheight`, `notesboxwidth`, `notesboxheight`, `timestamps`, `embed`, `incognito` FROM `$C[prefix]sessions` WHERE `nickname`=? AND `status`='1'");
+	$stmt=mysqli_prepare($mysqli, "SELECT `session`, `nickname`, ``passhash`, `refresh`, `bgcolour`, `boxwidth`, `boxheight`, `notesboxwidth`, `notesboxheight`, `timestamps`, `embed`, `incognito` FROM `$C[prefix]sessions` WHERE `nickname`=? AND `status`='1'");
 	mysqli_stmt_bind_param($stmt, 's', $_REQUEST['name']);
 	mysqli_stmt_execute($stmt);
-	mysqli_stmt_bind_result($stmt, $reg['session'], $reg['nickname'], $reg['displayname'], $reg['passhash'], $reg['refresh'], $reg['fontinfo'], $reg['bgcolour'], $reg['boxwidth'], $reg['boxheight'], $reg['notesboxwidth'], $reg['notesboxheight'], $reg['timestamps'], $reg['embed'], $reg['incognito']);
+	mysqli_stmt_bind_result($stmt, $reg['session'], $reg['nickname'], $reg['passhash'], $reg['refresh'], $reg['bgcolour'], $reg['boxwidth'], $reg['boxheight'], $reg['notesboxwidth'], $reg['notesboxheight'], $reg['timestamps'], $reg['embed'], $reg['incognito']);
 	if(mysqli_stmt_fetch($stmt)){
 		mysqli_stmt_close($stmt);
 		$reg['status']=$status;
-		if(preg_match('/#([a-f0-9]{6})/i', $reg['fontinfo'], $match)) $reg['colour']=$match[1];
-		else $reg['colour']=$C['coltxt'];
+		if(preg_match('/#([a-f0-9]{6})/i', $reg['style'], $match)) $reg['colour']=$match[1];
+		else $reg['colour']=get_setting('coltxt');
 		$stmt=mysqli_prepare($mysqli, "UPDATE `$C[prefix]sessions` SET `status`=? WHERE `session`=?");
 		mysqli_stmt_bind_param($stmt, 'is', $reg['status'], $reg['session']);
 		mysqli_stmt_execute($stmt);
@@ -1526,37 +1759,37 @@ function register_guest($status){
 	mysqli_stmt_execute($stmt);
 	mysqli_stmt_close($stmt);
 	if($C['memcached']) $memcached->delete("$C[dbname]-$C[prefix]members");
-	if($reg['status']==3) add_system_message(sprintf(get_setting('msgmemreg'), $reg['displayname']));
-	else add_system_message(sprintf(get_setting('msgsureg'), $reg['displayname']));
+	if($reg['status']==3) add_system_message(sprintf(get_setting('msgmemreg'), style_this($reg['nickname'], $reg['style'])));
+	else add_system_message(sprintf(get_setting('msgsureg'), style_this($reg['nickname'], $reg['style'])));
 }
 
 function register_new(){
 	global $A, $C, $I, $P, $U, $memcached, $mysqli;
-	$_REQUEST['name']=cleanup_nick($_REQUEST['name']);
+	$_REQUEST['name']=preg_replace('/\s+/', '', $_REQUEST['name']);
 	if(empty($_REQUEST['name'])) send_admin();
 	if(isSet($P[$_REQUEST['name']])) send_admin(sprintf($I['cantreg'], $_REQUEST['name']));
-	if(!valid_nick($_REQUEST['name'])) send_admin(sprintf($I['invalnick'], $C['maxname']));
-	if(!valid_pass($_REQUEST['pass'])) send_admin(sprintf($I['invalpass'], $C['minpass']));
+	if(!valid_nick($_REQUEST['name'])) send_admin(sprintf($I['invalnick'], get_setting('maxname')));
+	if(!valid_pass($_REQUEST['pass'])) send_admin(sprintf($I['invalpass'], get_setting('minpass')));
 	read_members();
 	if(isSet($A[$_REQUEST['name']])) send_admin(sprintf($I['alreadyreged'], $_REQUEST['name']));
 	$reg=array(
 		'nickname'	=>$_REQUEST['name'],
 		'passhash'	=>md5(sha1(md5($_REQUEST['name'].$_REQUEST['pass']))),
 		'status'	=>3,
-		'refresh'	=>$C['defaultrefresh'],
-		'colour'	=>$C['coltxt'],
-		'bgcolour'	=>$C['colbg'],
+		'refresh'	=>get_setting('defaultrefresh'),
+		'bgcolour'	=>get_setting('colbg'),
 		'boxwidth'	=>40,
 		'boxheight'	=>3,
 		'notesboxwidth'	=>80,
 		'notesboxheight'=>30,
 		'regedby'	=>$U['nickname'],
-		'timestamps'	=>$C['timestamps'],
-		'embed'		=>$C['embed'],
-		'incognito'	=>false
+		'timestamps'	=>get_setting('timestamps'),
+		'embed'		=>true,
+		'incognito'	=>false,
+		'style'		=>'color:#'.get_setting('coltxt').';'
 	);
-	$stmt=mysqli_prepare($mysqli, "INSERT INTO `$C[prefix]members` (`nickname`, `passhash`, `status`, `refresh`, `colour`, `bgcolour`, `boxwidth`, `boxheight`,`notesboxwidth`, `notesboxheight`, `regedby`, `timestamps`, `embed`, `incognito`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
-	mysqli_stmt_bind_param($stmt, 'ssiissiiiisiii', $reg['nickname'], $reg['passhash'], $reg['status'], $reg['refresh'], $reg['colour'], $reg['bgcolour'], $reg['boxwidth'], $reg['boxheight'], $reg['notesboxwidth'], $reg['notesboxheight'], $reg['regedby'], $reg['timestamps'], $reg['embed'], $reg['incognito']);
+	$stmt=mysqli_prepare($mysqli, "INSERT INTO `$C[prefix]members` (`nickname`, `passhash`, `status`, `refresh`, `bgcolour`, `boxwidth`, `boxheight`,`notesboxwidth`, `notesboxheight`, `regedby`, `timestamps`, `embed`, `incognito`, `style`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
+	mysqli_stmt_bind_param($stmt, 'ssiisiiiisiiis', $reg['nickname'], $reg['passhash'], $reg['status'], $reg['refresh'], $reg['bgcolour'], $reg['boxwidth'], $reg['boxheight'], $reg['notesboxwidth'], $reg['notesboxheight'], $reg['regedby'], $reg['timestamps'], $reg['embed'], $reg['incognito'], $reg['style']);
 	mysqli_stmt_execute($stmt);
 	mysqli_stmt_close($stmt);
 	if($C['memcached']) $memcached->delete("$C[dbname]-$C[prefix]members");
@@ -1605,37 +1838,31 @@ function change_status(){
 }
 
 function amend_profile(){
-	global $C, $F, $U;
+	global $F, $U;
 	if(isSet($_REQUEST['refresh'])) $U['refresh']=$_REQUEST['refresh'];
-	else $U['refresh']=$C['defaultrefresh'];
 	if($U['refresh']<5) $U['refresh']=5;
 	elseif($U['refresh']>150) $U['refresh']=150;
 	if(preg_match('/^[a-f0-9]{6}$/i', $_REQUEST['colour'])) $U['colour']=$_REQUEST['colour'];
-	else $U['colour']=$C['coltxt'];
+	else{
+		preg_match('/#([0-9a-f]{6})/i', $U['style'], $matches);
+		$U['colour']=$matches[1];
+	}
 	if(preg_match('/^[a-f0-9]{6}$/i', $_REQUEST['bgcolour'])) $U['bgcolour']=$_REQUEST['bgcolour'];
-	else $U['bgcolour']=$C['colbg'];
-	$U['fonttags']='';
-	if($U['status']>=3 && isSet($_REQUEST['bold'])) $U['fonttags'].='b';
-	if($U['status']>=3 && isSet($_REQUEST['italic'])) $U['fonttags'].='i';
-	if($U['status']>=3 && isSet($F[$_REQUEST['font']])) $U['fontface']=$_REQUEST['font'];
-	@$U['fontinfo']="#$U[colour] {$F[$U['fontface']]} <$U[fonttags]>";
-	if(!isSet($U['fontinfo'])) $U['fontinfo']='';
-	$U['style']=get_style($U['fontinfo']);
-	$U['displayname']=style_this($U['nickname'], $U['fontinfo']);
-	if($_REQUEST['boxwidth']>0) $U['boxwidth']=$_REQUEST['boxwidth'];
-	if($_REQUEST['boxheight']>0) $U['boxheight']=$_REQUEST['boxheight'];
-	if(isSet($_REQUEST['notesboxwidth']) && $_REQUEST['notesboxwidth']>0) $U['notesboxwidth']=$_REQUEST['notesboxwidth'];
-	if(isSet($_REQUEST['notesboxheight']) && $_REQUEST['notesboxheight']>0) $U['notesboxheight']=$_REQUEST['notesboxheight'];
+	$fonttags='';
+	if($U['status']>=3 && isSet($_REQUEST['bold'])) $fonttags.='b';
+	if($U['status']>=3 && isSet($_REQUEST['italic'])) $fonttags.='i';
+	if($U['status']>=3 && isSet($F[$_REQUEST['font']])) $fontface=$F[$_REQUEST['font']]; else $fontface='';
+	$U['style']=get_style("#$U[colour] $fontface <$fonttags>");
+	if($_REQUEST['boxwidth']>0 && $_REQUEST['boxwidth']<1000) $U['boxwidth']=$_REQUEST['boxwidth'];
+	if($_REQUEST['boxheight']>0 && $_REQUEST['boxheight']<1000) $U['boxheight']=$_REQUEST['boxheight'];
+	if(isSet($_REQUEST['notesboxwidth']) && $_REQUEST['notesboxwidth']>0 && $_REQUEST['notesboxwidth']<1000) $U['notesboxwidth']=$_REQUEST['notesboxwidth'];
+	if(isSet($_REQUEST['notesboxheight']) && $_REQUEST['notesboxheight']>0 && $_REQUEST['notesboxheight']<1000) $U['notesboxheight']=$_REQUEST['notesboxheight'];
 	if(isSet($_REQUEST['timestamps'])) $U['timestamps']=true;
 	else $U['timestamps']=false;
 	if(isSet($_REQUEST['embed'])) $U['embed']=true;
 	else $U['embed']=false;
-	if($U['status']>=5 && isSet($_REQUEST['incognito']) && $C['incognito']) $U['incognito']=true;
+	if($U['status']>=5 && isSet($_REQUEST['incognito']) && get_setting('incognito')) $U['incognito']=true;
 	else $U['incognito']=false;
-	if($U['boxwidth']>=1000) $U['boxwidth']=40;
-	if($U['boxheight']>=1000) $U['boxheight']=3;
-	if($U['notesboxwidth']>=1000) $U['notesboxwidth']=80;
-	if($U['notesboxheight']>=1000) $U['notesboxheight']=30;
 }
 
 function save_profile(){
@@ -1654,13 +1881,13 @@ function save_profile(){
 	if($U['passhash']!==$U['oldhash']) send_profile($I['wrongpass']);
 	$U['passhash']=$U['newhash'];
 	amend_profile();
-	$stmt=mysqli_prepare($mysqli, "UPDATE `$C[prefix]sessions` SET `refresh`=?, `displayname`=?, `fontinfo`=?, `style`=?, `passhash`=?, `boxwidth`=?, `boxheight`=?, `bgcolour`=?, `notesboxwidth`=?, `notesboxheight`=?, `timestamps`=?, `embed`=?, `incognito`=? WHERE `session`=?");
-	mysqli_stmt_bind_param($stmt, 'issssiisiiiiis', $U['refresh'], $U['displayname'], $U['fontinfo'], $U['style'], $U['passhash'], $U['boxwidth'], $U['boxheight'], $U['bgcolour'], $U['notesboxwidth'], $U['notesboxheight'], $U['timestamps'], $U['embed'], $U['incognito'], $U['session']);
+	$stmt=mysqli_prepare($mysqli, "UPDATE `$C[prefix]sessions` SET `refresh`=?, `style`=?, `passhash`=?, `boxwidth`=?, `boxheight`=?, `bgcolour`=?, `notesboxwidth`=?, `notesboxheight`=?, `timestamps`=?, `embed`=?, `incognito`=? WHERE `session`=?");
+	mysqli_stmt_bind_param($stmt, 'issiisiiiiis', $U['refresh'], $U['style'], $U['passhash'], $U['boxwidth'], $U['boxheight'], $U['bgcolour'], $U['notesboxwidth'], $U['notesboxheight'], $U['timestamps'], $U['embed'], $U['incognito'], $U['session']);
 	mysqli_stmt_execute($stmt);
 	mysqli_stmt_close($stmt);
 	if($U['status']>=2){
-		$stmt=mysqli_prepare($mysqli, "UPDATE `$C[prefix]members` SET `passhash`=?, `refresh`=?, `colour`=?, `bgcolour`=?, `fontface`=?, `fonttags`=?, `boxwidth`=?, `boxheight`=?, `notesboxwidth`=?, `notesboxheight`=?, `timestamps`=?, `embed`=?, `incognito`=? WHERE `nickname`=?");
-		mysqli_stmt_bind_param($stmt, 'sissssiiiiiiis', $U['passhash'], $U['refresh'], $U['colour'], $U['bgcolour'], $U['fontface'], $U['fonttags'], $U['boxwidth'], $U['boxheight'], $U['notesboxwidth'], $U['notesboxheight'], $U['timestamps'], $U['embed'], $U['incognito'], $U['nickname']);
+		$stmt=mysqli_prepare($mysqli, "UPDATE `$C[prefix]members` SET `passhash`=?, `refresh`=?, `bgcolour`=?, `boxwidth`=?, `boxheight`=?, `notesboxwidth`=?, `notesboxheight`=?, `timestamps`=?, `embed`=?, `incognito`=?, `style`=? WHERE `nickname`=?");
+		mysqli_stmt_bind_param($stmt, 'sisiiiiiiiss', $U['passhash'], $U['refresh'], $U['bgcolour'], $U['boxwidth'], $U['boxheight'], $U['notesboxwidth'], $U['notesboxheight'], $U['timestamps'], $U['embed'], $U['incognito'], $U['style'], $U['nickname']);
 		mysqli_stmt_execute($stmt);
 		mysqli_stmt_close($stmt);
 		if($C['memcached']) $memcached->delete("$C[dbname]-$C[prefix]members");
@@ -1683,59 +1910,50 @@ function save_profile(){
 }
 
 function add_user_defaults(){
-	global $C, $F, $H, $U;
-	if(!isSet($U['refresh'])) $U['refresh']=$C['defaultrefresh'];
-	if($U['refresh']<5) $U['refresh']=5;
-	elseif($U['refresh']>150) $U['refresh']=150;
-	if(!isSet($U['fontinfo'])){
-		if(!preg_match('/^[a-f0-9]{6}$/i', $U['colour'])){
-			$U['colour']=$C['coltxt'];
-			do{
-				$U['colour']=sprintf('%02X', rand(0, 256)).sprintf('%02X', rand(0, 256)).sprintf('%02X', rand(0, 256));
-			}while(abs(greyval($U['colour'])-greyval($C['colbg']))<75);
-		}
-		$U['fontinfo']="#$U[colour]";
-		@$U['fontinfo'].=" {$F[$U['fontface']]} <$U[fonttags]>";
-	}
-	if(!isSet($U['bgcolour'])) $U['bgcolour']=$C['colbg'];
+	global $H, $U;
+	if(!isSet($U['refresh'])) $U['refresh']=get_setting('defaultrefresh');
+	if(!isSet($U['bgcolour'])) $U['bgcolour']=get_setting('colbg');
 	$H['begin_body']="body style=\"background-color:#$U[bgcolour];\"";
-	if(!isSet($U['colour'])){
-		preg_match('/([0-9a-f]{6})/i', $U['fontinfo'], $matches);
-		$U['colour']=$matches[0];
+	if(!isSet($U['style']) && !preg_match('/^[a-f0-9]{6}$/i', $U['colour'])){
+		do{
+			$U['colour']=sprintf('%02X', rand(0, 256)).sprintf('%02X', rand(0, 256)).sprintf('%02X', rand(0, 256));
+		}while(abs(greyval($U['colour'])-greyval(get_setting('colbg')))<75);
 	}
-	if(!isSet($U['style'])) $U['style']=get_style($U['fontinfo']);
+	if(!isSet($U['style'])) $U['style']=get_style("#$U[colour]");
 	if(!isSet($U['boxwidth'])) $U['boxwidth']=40;
 	if(!isSet($U['boxheight'])) $U['boxheight']=3;
 	if(!isSet($U['notesboxwidth'])) $U['notesboxwidth']=80;
 	if(!isSet($U['notesboxheight'])) $U['notesboxheight']=30;
-	if(!isSet($U['timestamps'])) $U['timestamps']=$C['timestamps'];
-	if(!isSet($U['embed'])) $U['embed']=$C['embed'];
+	if(!isSet($U['timestamps'])) $U['timestamps']=get_setting('timestamps');
+	if(!isSet($U['embed'])) $U['embed']=true;
 	if(!isSet($U['incognito'])) $U['incognito']=false;
-	if(!isSet($U['lastpost'])) $U['lastpost']=time();
-	if(!isSet($U['entry'])) $U['entry']=$U['lastpost'];
-	if(!isSet($U['postid'])) $U['postid']='OOOOOO';
-	if(!isSet($U['displayname'])) $U['displayname']=style_this($U['nickname'], $U['fontinfo']);
+	$U['entry']=$U['lastpost']=time();
+	$U['postid']='OOOOOO';
 }
 
 // message handling
 
 function validate_input(){
-	global $P, $U;
+	global $C, $P, $U, $mysqli;
 	$maxmessage=get_setting('maxmessage');
 	$U['message']=substr($_REQUEST['message'], 0, $maxmessage);
 	$U['rejected']=substr($_REQUEST['message'], $maxmessage);
+	if($U['postid']==$_REQUEST['postid']){// ignore double post=reload from browser or proxy
+		$_REQUEST['message']='';
+	}elseif((time()-$U['lastpost'])<=1){// time between posts too short, reject!
+		$U['rejected']=$_REQUEST['message'];
+		$_REQUEST['message']='';
+	}
 	if(preg_match('/&[^;]{0,8}$/', $U['message']) && preg_match('/^([^;]{0,8};)/', $U['rejected'], $match)){
 		$U['message'].=$match[0];
 		$U['rejected']=preg_replace("/^$match[0]", '', $U['rejected']);
 	}
-	if($U['rejected']){
+	if(!empty($U['rejected'])){
 		$U['rejected']=trim($U['rejected']);
 		$U['rejected']=htmlspecialchars($U['rejected']);
 	}
 	$U['message']=htmlspecialchars($U['message']);
-	$U['message']=preg_replace("/\r\n/", '<br>', $U['message']);
-	$U['message']=preg_replace("/\n/", '<br>', $U['message']);
-	$U['message']=preg_replace("/\r/", '<br>', $U['message']);
+	$U['message']=preg_replace("/(\r?\n|\r\n?)/", '<br>', $U['message']);
 	if(isSet($_REQUEST['multi']) && $_REQUEST['multi']=='on'){
 		$U['message']=preg_replace('/\s*<br>/', '<br>', $U['message']);
 		$U['message']=preg_replace('/<br>(<br>)+/', '<br><br>', $U['message']);
@@ -1750,16 +1968,16 @@ function validate_input(){
 	$U['recipient']='';
 	if($_REQUEST['sendto']=='*'){
 		$U['poststatus']='1';
-		$U['displaysend']="$U[displayname] - ";
+		$U['displaysend']=style_this($U['nickname'], $U['style']).' - ';
 	}elseif($_REQUEST['sendto']=='?' && $U['status']>=3){
 		$U['poststatus']='3';
-		$U['displaysend']="[M] $U[displayname] - ";
+		$U['displaysend']='[M] '.style_this($U['nickname'], $U['style']).' - ';
 	}elseif($_REQUEST['sendto']=='#' && $U['status']>=5){
 		$U['poststatus']='5';
-		$U['displaysend']="[Staff] $U[displayname] - ";
+		$U['displaysend']='[Staff] '.style_this($U['nickname'], $U['style']).' - ';
 	}elseif($_REQUEST['sendto']=='&' && $U['status']>=6){
 		$U['poststatus']='6';
-		$U['displaysend']="[Admin] $U[displayname] - ";
+		$U['displaysend']='[Admin] '.style_this($U['nickname'], $U['style']).' - ';
 	}else{// known nick in room?
 		$ignored=get_ignored();
 		$ignore=false;
@@ -1773,7 +1991,7 @@ function validate_input(){
 			foreach($P as $chatter){
 				if($_REQUEST['sendto']==$chatter[0]){
 					$U['recipient']=$chatter[0];
-					$U['displayrecp']=style_this($chatter[0], $chatter[2]);
+					$U['displayrecp']=style_this($chatter[0], $chatter[1]);
 					break;
 				}
 			}
@@ -1781,7 +1999,7 @@ function validate_input(){
 		if(!empty($U['recipient'])){
 			$U['poststatus']='9';
 			$U['delstatus']='9';
-			$U['displaysend']="[$U[displayname] to $U[displayrecp]] - ";
+			$U['displaysend']='['.style_this($U['nickname'], $U['style'])." to $U[displayrecp]] - ";
 		}else{// nick left already or ignores us
 			$U['message']='';
 			$U['rejected']='';
@@ -1790,7 +2008,15 @@ function validate_input(){
 	if(isSet($U['poststatus'])){
 		apply_filter();
 		create_hotlinks();
-		if(add_message()) update_session();
+		apply_linkfilter();
+		if(add_message()){
+			$U['lastpost']=time();
+			$stmt=mysqli_prepare($mysqli, "UPDATE `$C[prefix]sessions` SET `lastpost`=?, `postid`=? WHERE `session`=?");
+			mysqli_stmt_bind_param($stmt, 'iis', $U['lastpost'], $_REQUEST['postid'], $U['session']);
+			mysqli_stmt_execute($stmt);
+			mysqli_stmt_close($stmt);
+		}
+
 	}
 }
 
@@ -1800,7 +2026,7 @@ function apply_filter(){
 		$U['displaysend']=substr($U['displaysend'], 0, -3);
 		$U['message']=preg_replace("~^/me~i", '', $U['message']);
 	}
-	$U['message']=preg_replace_callback("/\@([a-z0-9]{1,$C[maxname]})/i", function ($matched){ global $P; if(isSet($P[$matched[1]])) return style_this($matched[0], $P[$matched[1]][2]); else return "$matched[0]";}, $U['message']);
+	$U['message']=preg_replace_callback('/\@([a-z0-9]{1,})/i', function ($matched){ global $P; if(isSet($P[$matched[1]])) return style_this($matched[0], $P[$matched[1]][1]); else return "$matched[0]";}, $U['message']);
 	if($C['memcached']) $filters=$memcached->get("$C[dbname]-$C[prefix]filter");
 	if(!$C['memcached'] || $memcached->getResultCode()!=Memcached::RES_SUCCESS){
 		$filters=array();
@@ -1818,8 +2044,34 @@ function apply_filter(){
 	}
 }
 
+function apply_linkfilter(){
+	global $C, $U, $memcached, $mysqli;
+	if(get_setting('imgembed')) $U['message']=preg_replace_callback('/\[img\]\s?<a href="(.*?(?="))" target="_blank">(.*?(?=<\/a>))<\/a>/i', function ($matched){ return str_ireplace('[/img]', '', "<br><a href=\"$matched[1]\" target=\"_blank\"><img src=\"$matched[1]\"></a><br>");}, $U['message']);
+	if($C['memcached']) $filters=$memcached->get("$C[dbname]-$C[prefix]linkfilter");
+	if(!$C['memcached'] || $memcached->getResultCode()!=Memcached::RES_SUCCESS){
+		$filters=array();
+		$result=mysqli_query($mysqli, "SELECT * FROM `$C[prefix]linkfilter`");
+		while($filter=mysqli_fetch_array($result, MYSQLI_ASSOC)) $filters[]=$filter;
+		if($C['memcached']) $memcached->set("$C[dbname]-$C[prefix]linkfilter", $filters);
+	}
+	foreach($filters as $filter){
+		$U['message']=preg_replace_callback("/<a href=\"(.*?(?=\"))\" target=\"_blank\">(.*?(?=<\/a>))<\/a>/i", function ($matched) use(&$filter){ return "<a href=\"$matched[1]\" target=\"_blank\">".preg_replace("/$filter[match]/i", $filter['replace'], $matched[2]).'</a>';}, $U['message']);
+	}
+	$redirect=get_setting('redirect');
+	if(empty($redirect)) $redirect="$_SERVER[SCRIPT_NAME]?action=redirect&url=";
+	if(get_setting('forceredirect')) $U['message']=preg_replace_callback('/<a href="(.*?(?="))" target="_blank">(.*?(?=<\/a>))<\/a>/', function ($matched){ global $C; return "<a href=\"$redirect".urlencode($matched[1])."\" target=\"_blank\">$matched[2]</a>";}, $U['message']);
+	elseif(preg_match_all('/<a href="(.*?(?="))" target="_blank">(.*?(?=<\/a>))<\/a>/', $U['message'], $matches)){
+		foreach($matches[1] as $match){
+			if(!preg_match('~^http(s)?://~', $match)){
+				$U['message']=preg_replace_callback('/<a href="(.*?(?="))" target="_blank">(.*?(?=<\/a>))<\/a>/', function ($matched){ global $C; return "<a href=\"$redirect".urlencode($matched[1])."\" target=\"_blank\">$matched[2]</a>";}, $U['message']);
+				break;
+			}
+		}
+	}
+}
+
 function create_hotlinks(){
-	global $C, $U;
+	global $U;
 	//Make hotlinks for URLs, redirect through dereferrer script to prevent session leakage
 	// 1. all explicit schemes with whatever xxx://yyyyyyy
 	$U['message']=preg_replace('~(\w*://[^\s<>]+)~i', "<<$1>>", $U['message']);
@@ -1832,16 +2084,6 @@ function create_hotlinks(){
 	$U['message']=preg_replace('~([a-z0-9\-]+(?:\.[a-z0-9\-]+)+(?:\.(?!rar|zip|exe|gz|7z|bat|doc)[a-z]{2,}))(?=[^a-z0-9\-\.]|$)(?![^<>]*>)~i', "<<$1>>", $U['message']);// xxx.yyy.zzz
 	// Convert every <<....>> into proper links:
 	$U['message']=preg_replace_callback('/<<([^<>]+)>>/', function ($matches){if(strpos($matches[1], '://')==false){ return "<a href=\"http://$matches[1]\" target=\"_blank\">$matches[1]</a>";}else{ return "<a href=\"$matches[1]\" target=\"_blank\">$matches[1]</a>"; }}, $U['message']);
-	if($C['imgembed']) $U['message']=preg_replace_callback('/\[img\]\s?<a href="(.*?(?="))" target="_blank">(.*?(?=<\/a>))<\/a>/i', function ($matched){ return str_ireplace('[/img]', '', "<br><a href=\"$matched[1]\" target=\"_blank\"><img src=\"$matched[1]\"></a><br>");}, $U['message']);
-	if($C['forceredirect']) $U['message']=preg_replace_callback('/<a href="(.*?(?="))" target="_blank">(.*?(?=<\/a>))<\/a>/', function ($matched){ global $C; return "<a href=\"$C[redirect]".urlencode($matched[1])."\" target=\"_blank\">$matched[2]</a>";}, $U['message']);
-	elseif(preg_match_all('/<a href="(.*?(?="))" target="_blank">(.*?(?=<\/a>))<\/a>/', $U['message'], $matches)){
-		foreach($matches[1] as $match){
-			if(!preg_match('~^http(s)?://~', $match)){
-				$U['message']=preg_replace_callback('/<a href="(.*?(?="))" target="_blank">(.*?(?=<\/a>))<\/a>/', function ($matched){ global $C; return "<a href=\"$C[redirect]".urlencode($matched[1])."\" target=\"_blank\">$matched[2]</a>";}, $U['message']);
-				break;
-			}
-		}
-	}
 }
 
 function add_message(){
@@ -1852,7 +2094,7 @@ function add_message(){
 		'poststatus'	=>$U['poststatus'],
 		'poster'	=>$U['nickname'],
 		'recipient'	=>$U['recipient'],
-		'text'		=>$U['displaysend'].style_this($U['message'], $U['fontinfo']),
+		'text'		=>$U['displaysend'].style_this($U['message'], $U['style']),
 		'delstatus'	=>$U['delstatus']
 	);
 	write_message($newmessage);
@@ -1887,7 +2129,7 @@ function write_message($message){
 	if($C['sendmail'] && $message['poststatus']<9){
 		$subject='New Chat message';
 		$headers="From: $C[mailsender]\r\nX-Mailer: PHP/".phpversion()."\r\nContent-Type: text/html; charset=UTF-8\r\n";
-		$body="<html><body stlye=\"background-color:#$C[colbg];color:#$C[coltxt];\">$message[text]</body></html>";
+		$body='<html><body style="background-color:#'.get_setting('colbg').';color:#'.get_setting('coltxt').";\">$message[text]</body></html>";
 		mail($C['mailreceiver'], $subject, $body, $headers);
 	}
 }
@@ -1944,9 +2186,13 @@ function print_messages($delstatus=''){
 	global $C, $U, $mysqli;
 	$dateformat=get_setting('dateformat');
 	$messagelimit=get_setting('messagelimit');
-	if(!isSet($_COOKIE[$C['cookiename']]) && !$C['forceredirect']) $injectRedirect=true; else $injectRedirect=false;
-	if($C['imgembed'] && (!$U['embed'] || !isSet($_COOKIE[$C['cookiename']]))) $removeEmbed=true; else $removeEmbed=false;
-	mysqli_query($mysqli, "DELETE FROM `$C[prefix]messages` WHERE `postdate`<='".(time()-60*get_setting('messageexpire'))."'");
+	if(!isSet($_COOKIE[$C['cookiename']]) && get_setting('forceredirect')==0){
+		$injectRedirect=true;
+		$redirect=get_setting('redirect');
+		if(empty($redirect)) $redirect="$_SERVER[SCRIPT_NAME]?action=redirect&url=";
+	}else $injectRedirect=false;
+	if(get_setting('imgembed') && (!$U['embed'] || !isSet($_COOKIE[$C['cookiename']]))) $removeEmbed=true; else $removeEmbed=false;
+	mysqli_query($mysqli, "DELETE FROM `$C[prefix]messages` WHERE `postdate`<='".(time()-60*get_setting('messageexpire'))."' OR (`poster`='' AND `recipient`='' AND `poststatus`='9')");
 	if(!empty($delstatus)){
 		$stmt=mysqli_prepare($mysqli, "SELECT `postdate`, `id`, `text` FROM `$C[prefix]messages` WHERE ".
 		"`id` IN (SELECT * FROM (SELECT `id` FROM `$C[prefix]messages` WHERE `poststatus`='1' ORDER BY `id` DESC LIMIT ?) AS t) ".
@@ -1957,7 +2203,7 @@ function print_messages($delstatus=''){
 		while(mysqli_stmt_fetch($stmt)){
 			if($C['msgencrypted']) $message['text']=openssl_decrypt($message['text'], 'aes-256-cbc', $C['encryptkey'], 0, '1234567890123456');
 			if($injectRedirect){
-				$message['text']=preg_replace_callback('/<a href="(.*?(?="))" target="_blank">(.*?(?=<\/a>))<\/a>/', function ($matched){ global $C; return "<a href=\"$C[redirect]".urlencode($matched[1])."\" target=\"_blank\">$matched[2]</a>";}, $message['text']);
+				$message['text']=preg_replace_callback('/<a href="(.*?(?="))" target="_blank">(.*?(?=<\/a>))<\/a>/', function ($matched){ global $C; return "<a href=\"$redirect".urlencode($matched[1])."\" target=\"_blank\">$matched[2]</a>";}, $message['text']);
 			}
 			if($removeEmbed){
 				$message['text']=preg_replace_callback('/<img src="(.*?(?="))">/', function ($matched){ return $matched[1];}, $message['text']);
@@ -1978,7 +2224,7 @@ function print_messages($delstatus=''){
 		while(mysqli_stmt_fetch($stmt)){
 			if($C['msgencrypted']) $message['text']=openssl_decrypt($message['text'], 'aes-256-cbc', $C['encryptkey'], 0, '1234567890123456');
 			if($injectRedirect){
-				$message['text']=preg_replace_callback('/<a href="(.*?(?="))" target="_blank">(.*?(?=<\/a>))<\/a>/', function ($matched){ global $C; return "<a href=\"$C[redirect]".urlencode($matched[1])."\" target=\"_blank\">$matched[2]</a>";}, $message['text']);
+				$message['text']=preg_replace_callback('/<a href="(.*?(?="))" target="_blank">(.*?(?=<\/a>))<\/a>/', function ($matched){ global $C; return "<a href=\"$redirect".urlencode($matched[1])."\" target=\"_blank\">$matched[2]</a>";}, $message['text']);
 			}
 			if($removeEmbed){
 				$message['text']=preg_replace_callback('/<img src="(.*?(?="))">/', function ($matched){ return $matched[1];}, $message['text']);
@@ -2019,18 +2265,11 @@ function valid_admin(){
 }
 
 function valid_nick($nick){
-	global $C;
-	return preg_match("/^[a-z0-9]{1,$C[maxname]}$/i", $nick);
+	return preg_match('/^[a-z0-9]{1,'.get_setting('maxname').'}$/i', $nick);
 }
 
 function valid_pass($pass){
-	global $C;
-	return preg_match('/^.{'.$C['minpass'].',}$/', $pass);
-}
-
-function cleanup_nick($nick){
-	$nick=preg_replace('/\s+/', '', $nick);
-	return $nick;
+	return preg_match('/^.{'.get_setting('minpass').',}$/', $pass);
 }
 
 function get_timeout($lastpost, $status){ // lastpost, status
@@ -2048,11 +2287,11 @@ function get_timeout($lastpost, $status){ // lastpost, status
 }
 
 function print_colours(){
-	global $C, $I;
+	global $I;
 	// Prints a short list with selected named HTML colours and filters out illegible text colours for the given background.
 	// It's a simple comparison of weighted grey values. This is not very accurate but gets the job done well enough.
 	$colours=array('Beige'=>'F5F5DC', 'Black'=>'000000', 'Blue'=>'0000FF', 'BlueViolet'=>'8A2BE2', 'Brown'=>'A52A2A', 'Cyan'=>'00FFFF', 'DarkBlue'=>'00008B', 'DarkGreen'=>'006400', 'DarkRed'=>'8B0000', 'DarkViolet'=>'9400D3', 'DeepSkyBlue'=>'00BFFF', 'Gold'=>'FFD700', 'Grey'=>'808080', 'Green'=>'008000', 'HotPink'=>'FF69B4', 'Indigo'=>'4B0082', 'LightBlue'=>'ADD8E6', 'LightGreen'=>'90EE90', 'LimeGreen'=>'32CD32', 'Magenta'=>'FF00FF', 'Olive'=>'808000', 'Orange'=>'FFA500', 'OrangeRed'=>'FF4500', 'Purple'=>'800080', 'Red'=>'FF0000', 'RoyalBlue'=>'4169E1', 'SeaGreen'=>'2E8B57', 'Sienna'=>'A0522D', 'Silver'=>'C0C0C0', 'Tan'=>'D2B48C', 'Teal'=>'008080', 'Violet'=>'EE82EE', 'White'=>'FFFFFF', 'Yellow'=>'FFFF00', 'YellowGreen'=>'9ACD32');
-	$greybg=greyval($C['colbg']);
+	$greybg=greyval(get_setting('colbg'));
 	foreach($colours as $name=>$colour){
 		if(abs($greybg-greyval($colour))>75) echo "<option value=\"$colour\" style=\"color:#$colour\">$I[$name]</option>";
 	}
@@ -2065,22 +2304,11 @@ function greyval($colour){
 function get_style($styleinfo){
 	$fbold=preg_match('/(<i?bi?>|:bold)/', $styleinfo);
 	$fitalic=preg_match('/(<b?ib?>|:italic)/', $styleinfo);
-	$fsmall=preg_match('/(size="-1"|:smaller)/', $styleinfo);
-	preg_match('/(#.{6})/', $styleinfo, $match);
+	$fsmall=preg_match('/:smaller/', $styleinfo);
+	preg_match('/(#.{6})/i', $styleinfo, $match);
 	if(isSet($match[0])) $fcolour=$match[0];
-	preg_match('/face=\'([^"]+)\'/', $styleinfo, $match);
-	if(isSet($match[1])) $fface=$match[1];
 	preg_match('/font-family:([^;]+);/', $styleinfo, $match);
 	if(isSet($match[1])) $sface=$match[1];
-	if(isSet($fface)){
-		$sface=$fface;
-		$sface=preg_replace('/^/', "'", $sface);
-		$sface=preg_replace('/$/', "'", $sface);
-		$sface=preg_replace('/,/', "','", $sface);
-	}elseif(isSet($sface)){
-		$fface=$sface;
-		$fface=preg_replace("/'/", '', $fface);
-	}
 	$fstyle='';
 	if(isSet($fcolour)) $fstyle.="color:$fcolour;";
 	if(isSet($sface)) $fstyle.="font-family:$sface;";
@@ -2091,43 +2319,7 @@ function get_style($styleinfo){
 }
 
 function style_this($text, $styleinfo){
-	$fbold=preg_match('/(<i?bi?>|:bold)/', $styleinfo);
-	$fitalic=preg_match('/(<b?ib?>|:italic)/', $styleinfo);
-	$fsmall=preg_match('/(size="-1"|:smaller)/', $styleinfo);
-	preg_match('/(#.{6})/', $styleinfo, $match);
-	if(isSet($match[0])) $fcolour=$match[0];
-	preg_match('/face=\'([^"]+)\'/', $styleinfo, $match);
-	if(isSet($match[1])) $fface=$match[1];
-	preg_match('/font-family:([^;]+);/', $styleinfo, $match);
-	if(isSet($match[1])) $sface=$match[1];
-	if(isSet($fface)){
-		$sface=$fface;
-		$sface=preg_replace('/^/', "'", $sface);
-		$sface=preg_replace('/$/', "'", $sface);
-		$sface=preg_replace('/,/', "','", $sface);
-	}elseif(isSet($sface)){
-		$fface=$sface;
-		$fface=preg_replace("/'/", '', $fface);
-	}
-	$fstyle='';
-	if(isSet($fcolour)) $fstyle.="color:$fcolour;";
-	if(isSet($sface)) $fstyle.="font-family:$sface;";
-	if($fsmall) $fstyle.='font-size:smaller;';
-	if($fitalic) $fstyle.='font-style:italic;';
-	if($fbold) $fstyle.='font-weight:bold;';
-	$fstart='<font';
-	if(!isSet($fcolour)) $fstart.=" color=\"$fcolour\"";
-	if(isSet($fface)) $fstart.=" face=\"$fface\"";
-	if($fsmall) $fstart.=" size=\"-1\"";
-	if(!empty($fstyle)) $fstart.=" style=\"$fstyle\"";
-	$fstart.='>';
-	if($fbold) $fstart.='<b>';
-	if($fitalic) $fstart.='<i>';
-	$fend='';
-	if($fitalic) $fend.='</i>';
-	if($fbold) $fend.='</b>';
-	$fend.='</font>';
-	return "$fstart$text$fend";
+	return "<font style=\"$styleinfo\">$text</font>";
 }
 
 function check_init(){
@@ -2153,24 +2345,26 @@ function init_chat(){
 		if(mysqli_num_rows($result)>0){
 			$suwrite=$I['initsuexist'];
 		}
-	}elseif(!valid_nick($_REQUEST['sunick'])){
-		$suwrite=sprintf($I['invalnick'], $C['maxname']);
-	}elseif(!valid_pass($_REQUEST['supass'])){
-		$suwrite=sprintf($I['invalpass'], $C['minpass']);
+	}elseif(!preg_match('/^[a-z0-9]{1,20}$/i', $_REQUEST['sunick'])){
+		$suwrite=sprintf($I['invalnick'], 20);
+	}elseif(!preg_match('/^.{5,}$/', $_REQUEST['supass'])){
+		$suwrite=sprintf($I['invalpass'], 5);
 	}elseif($_REQUEST['supass']!==$_REQUEST['supassc']){
 		$suwrite=$I['noconfirm'];
 	}else{
-		mysqli_multi_query($mysqli, 	"CREATE TABLE IF NOT EXISTS `$C[prefix]captcha` (`id` int(10) unsigned NOT NULL, `time` int(10) unsigned NOT NULL, `code` tinytext NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8; ".
-						"CREATE TABLE IF NOT EXISTS `$C[prefix]filter` (`id` tinyint(3) unsigned NOT NULL, `match` tinytext NOT NULL, `replace` text NOT NULL, `allowinpm` tinyint(1) unsigned NOT NULL, `regex` tinyint(1) unsigned NOT NULL, `kick` tinyint(1) unsigned NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8; ".
-						"CREATE TABLE IF NOT EXISTS `$C[prefix]ignored` (`id` int(10) unsigned NOT NULL, `ignored` tinytext NOT NULL, `by` tinytext NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8; ".
-						"CREATE TABLE IF NOT EXISTS `$C[prefix]members` (`id` tinyint(3) unsigned NOT NULL, `nickname` tinytext CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, `passhash` tinytext NOT NULL, `status` tinyint(3) unsigned NOT NULL, `refresh` tinyint(3) unsigned NOT NULL, `colour` tinytext NOT NULL, `bgcolour` tinytext NOT NULL, `fontface` tinytext NOT NULL, `fonttags` tinytext NOT NULL, `boxwidth` tinyint(3) unsigned NOT NULL, `boxheight` tinyint(3) unsigned NOT NULL, `notesboxheight` tinyint(3) unsigned NOT NULL, `notesboxwidth` tinyint(3) unsigned NOT NULL, `regedby` tinytext CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, `lastlogin` int(10) unsigned NOT NULL, `timestamps` tinyint(1) unsigned NOT NULL, `embed` tinyint(1) unsigned NOT NULL, `incognito` tinyint(1) unsigned NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8; ".
-						"CREATE TABLE IF NOT EXISTS `$C[prefix]messages` (`id` int(10) unsigned NOT NULL, `postdate` int(10) unsigned NOT NULL, `poststatus` tinyint(3) unsigned NOT NULL, `poster` tinytext CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, `recipient` tinytext CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, `text` text NOT NULL, `delstatus` tinyint(3) unsigned NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8; ".
-						"CREATE TABLE IF NOT EXISTS `$C[prefix]notes` (`id` int(10) unsigned NOT NULL, `type` tinytext NOT NULL, `lastedited` int(10) unsigned NOT NULL, `editedby` tinytext CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, `text` text NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8; ".
-						"CREATE TABLE IF NOT EXISTS `$C[prefix]sessions` (`id` int(10) unsigned NOT NULL, `session` tinytext NOT NULL, `nickname` tinytext CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, `displayname` text NOT NULL, `status` tinyint(3) unsigned NOT NULL, `refresh` tinyint(3) unsigned NOT NULL, `fontinfo` tinytext NOT NULL, `style` text NOT NULL, `lastpost` int(10) unsigned NOT NULL, `passhash` tinytext NOT NULL, `postid` int(10) unsigned NOT NULL, `boxwidth` tinyint(3) unsigned NOT NULL, `boxheight` tinyint(3) unsigned NOT NULL, `useragent` text NOT NULL, `kickmessage` text NOT NULL, `bgcolour` tinytext NOT NULL, `notesboxheight` tinyint(3) unsigned NOT NULL, `notesboxwidth` tinyint(3) unsigned NOT NULL, `entry` int(10) unsigned NOT NULL, `timestamps` tinyint(1) unsigned NOT NULL, `embed` tinyint(1) unsigned NOT NULL, `incognito` tinyint(1) unsigned NOT NULL, `ip` tinytext NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8; ".
-						"CREATE TABLE IF NOT EXISTS `$C[prefix]settings` (`id` tinyint(3) unsigned NOT NULL, `setting` tinytext NOT NULL, `value` text NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8; ".
+		mysqli_multi_query($mysqli, 	"CREATE TABLE IF NOT EXISTS `$C[prefix]captcha` (`id` int(10) unsigned NOT NULL, `time` int(10) unsigned NOT NULL, `code` tinytext NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; ".
+						"CREATE TABLE IF NOT EXISTS `$C[prefix]filter` (`id` tinyint(3) unsigned NOT NULL, `match` tinytext NOT NULL, `replace` text NOT NULL, `allowinpm` tinyint(1) unsigned NOT NULL, `regex` tinyint(1) unsigned NOT NULL, `kick` tinyint(1) unsigned NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; ".
+						"CREATE TABLE IF NOT EXISTS `$C[prefix]ignored` (`id` int(10) unsigned NOT NULL, `ignored` tinytext NOT NULL, `by` tinytext NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; ".
+						"CREATE TABLE IF NOT EXISTS `$C[prefix]linkfilter` (`id` int(10) unsigned NOT NULL, `match` tinytext NOT NULL, `replace` tinytext NOT NULL, `regex` tinyint(1) unsigned NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; ".
+						"CREATE TABLE IF NOT EXISTS `$C[prefix]members` (`id` tinyint(3) unsigned NOT NULL, `nickname` tinytext NOT NULL, `passhash` tinytext NOT NULL, `status` tinyint(3) unsigned NOT NULL, `refresh` tinyint(3) unsigned NOT NULL, `bgcolour` tinytext NOT NULL, `boxwidth` tinyint(3) unsigned NOT NULL, `boxheight` tinyint(3) unsigned NOT NULL, `notesboxheight` tinyint(3) unsigned NOT NULL, `notesboxwidth` tinyint(3) unsigned NOT NULL, `regedby` tinytext NOT NULL, `lastlogin` int(10) unsigned NOT NULL, `timestamps` tinyint(1) unsigned NOT NULL, `embed` tinyint(1) unsigned NOT NULL, `incognito` tinyint(1) unsigned NOT NULL, `style` text NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; ".
+						"CREATE TABLE IF NOT EXISTS `$C[prefix]messages` (`id` int(10) unsigned NOT NULL, `postdate` int(10) unsigned NOT NULL, `poststatus` tinyint(3) unsigned NOT NULL, `poster` tinytext NOT NULL, `recipient` tinytext NOT NULL, `text` text NOT NULL, `delstatus` tinyint(3) unsigned NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; ".
+						"CREATE TABLE IF NOT EXISTS `$C[prefix]notes` (`id` int(10) unsigned NOT NULL, `type` tinytext NOT NULL, `lastedited` int(10) unsigned NOT NULL, `editedby` tinytext NOT NULL, `text` text NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; ".
+						"CREATE TABLE IF NOT EXISTS `$C[prefix]sessions` (`id` int(10) unsigned NOT NULL, `session` tinytext NOT NULL, `nickname` tinytext NOT NULL, `status` tinyint(3) unsigned NOT NULL, `refresh` tinyint(3) unsigned NOT NULL, `style` text NOT NULL, `lastpost` int(10) unsigned NOT NULL, `passhash` tinytext NOT NULL, `postid` int(10) unsigned NOT NULL, `boxwidth` tinyint(3) unsigned NOT NULL, `boxheight` tinyint(3) unsigned NOT NULL, `useragent` text NOT NULL, `kickmessage` text NOT NULL, `bgcolour` tinytext NOT NULL, `notesboxheight` tinyint(3) unsigned NOT NULL, `notesboxwidth` tinyint(3) unsigned NOT NULL, `entry` int(10) unsigned NOT NULL, `timestamps` tinyint(1) unsigned NOT NULL, `embed` tinyint(1) unsigned NOT NULL, `incognito` tinyint(1) unsigned NOT NULL, `ip` tinytext NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; ".
+						"CREATE TABLE IF NOT EXISTS `$C[prefix]settings` (`id` tinyint(3) unsigned NOT NULL, `setting` tinytext NOT NULL, `value` text NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; ".
 						"ALTER TABLE `$C[prefix]captcha` ADD UNIQUE KEY `id` (`id`); ".
 						"ALTER TABLE `$C[prefix]filter` ADD PRIMARY KEY (`id`); ".
 						"ALTER TABLE `$C[prefix]ignored` ADD PRIMARY KEY (`id`); ".
+						"ALTER TABLE `$C[prefix]linkfilter` ADD PRIMARY KEY (`id`); ".
 						"ALTER TABLE `$C[prefix]members` ADD PRIMARY KEY (`id`); ".
 						"ALTER TABLE `$C[prefix]messages` ADD PRIMARY KEY (`id`); ".
 						"ALTER TABLE `$C[prefix]notes` ADD PRIMARY KEY (`id`); ".
@@ -2178,42 +2372,43 @@ function init_chat(){
 						"ALTER TABLE `$C[prefix]settings` ADD PRIMARY KEY (`id`); ".
 						"ALTER TABLE `$C[prefix]filter` MODIFY `id` tinyint(3) unsigned NOT NULL AUTO_INCREMENT; ".
 						"ALTER TABLE `$C[prefix]ignored` MODIFY `id` int(10) unsigned NOT NULL AUTO_INCREMENT; ".
+						"ALTER TABLE `$C[prefix]linkfilter` MODIFY `id` int(10) unsigned NOT NULL AUTO_INCREMENT; ".
 						"ALTER TABLE `$C[prefix]members` MODIFY `id` tinyint(3) unsigned NOT NULL AUTO_INCREMENT; ".
 						"ALTER TABLE `$C[prefix]messages` MODIFY `id` int(10) unsigned NOT NULL AUTO_INCREMENT; ".
 						"ALTER TABLE `$C[prefix]notes` MODIFY `id` int(10) unsigned NOT NULL AUTO_INCREMENT; ".
 						"ALTER TABLE `$C[prefix]sessions` MODIFY `id` int(10) unsigned NOT NULL AUTO_INCREMENT; ".
 						"ALTER TABLE `$C[prefix]settings` MODIFY `id` tinyint(3) unsigned NOT NULL AUTO_INCREMENT; ".
-						"INSERT INTO `$C[prefix]settings` (`setting`,`value`) VALUES ('guestaccess','0'), ('globalpass',''), ('englobalpass','0'), ('captcha','0'), ('dateformat','m-d H:i:s'), ('rulestxt', ''), ('msgencrypted','0'), ('msgenter','%s entered the chat.'), ('msgexit','%s left the chat.'), ('msgmemreg','%s is now a registered member.'), ('msgsureg','%s is now a registered applicant.'), ('msgkick','%s has been kicked.'), ('msgmultikick','%s have been kicked.'), ('msgallkick','All chatters have been kicked.'), ('msgclean','%s has been cleaned.'), ('dbversion','$C[dbversion]'), ('css','a:visited{color:#B33CB4;} a:active{color:#FF0033;} a:link{color:#0000FF;} input,select,textarea{color:#FFFFFF;background-color:#000000;} a img{width:15%} a:hover img{width:35%} .error{color:#FF0033;} .delbutton{background-color:#660000;} .backbutton{background-color:#004400;} #exitbutton{background-color:#AA0000;}'), ('memberexpire','60'), ('guestexpire', '15'), ('kickpenalty', '10'), ('entrywait', '120'), ('messageexpire', '14400'), ('messagelimit', '150'), ('maxmessage', 2000), ('captchatime', '600');");
+						"INSERT INTO `$C[prefix]settings` (`setting`,`value`) VALUES ('guestaccess', '0'), ('globalpass', ''), ('englobalpass', '0'), ('captcha', '0'), ('dateformat', 'm-d H:i:s'), ('rulestxt', ''), ('msgencrypted', '0'), ('msgenter', '%s entered the chat.'), ('msgexit', '%s left the chat.'), ('msgmemreg', '%s is now a registered member.'), ('msgsureg', '%s is now a registered applicant.'), ('msgkick', '%s has been kicked.'), ('msgmultikick', '%s have been kicked.'), ('msgallkick', 'All chatters have been kicked.'), ('msgclean', '%s has been cleaned.'), ('dbversion', '$C[dbversion]'), ('css', 'a:visited{color:#B33CB4;} a:active{color:#FF0033;} a:link{color:#0000FF;} input,select,textarea{color:#FFFFFF;background-color:#000000;} a img{width:15%} a:hover img{width:35%} .error{color:#FF0033;} .delbutton{background-color:#660000;} .backbutton{background-color:#004400;} #exitbutton{background-color:#AA0000;}'), ('memberexpire', '60'), ('guestexpire', '15'), ('kickpenalty', '10'), ('entrywait', '120'), ('messageexpire', '14400'), ('messagelimit', '150'), ('maxmessage', 2000), ('captchatime', '600'), ('colbg', '000000'), ('coltxt', 'FFFFFF'), ('maxname', '20'), ('minpass', '5'), ('defaultrefresh', '20'), ('dismemcaptcha', '0'), ('suguests', '0'), ('imgembed', '1'), ('timestamps', '1'), ('trackip', '1'), ('captchachars', '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'), ('memkick', '1'), ('forceredirect', '0'), ('redirect', ''), ('incognito', '1');");
 		while(mysqli_more_results($mysqli)) mysqli_next_result($mysqli);
 		$reg=array(
 			'nickname'	=>$_REQUEST['sunick'],
 			'passhash'	=>md5(sha1(md5($_REQUEST['sunick'].$_REQUEST['supass']))),
 			'status'	=>8,
-			'refresh'	=>$C['defaultrefresh'],
-			'colour'	=>$C['coltxt'],
-			'bgcolour'	=>$C['colbg'],
+			'refresh'	=>20,
+			'bgcolour'	=>'000000',
 			'boxwidth'	=>40,
 			'boxheight'	=>3,
 			'notesboxwidth'	=>80,
 			'notesboxheight'=>30,
-			'timestamps'	=>$C['timestamps'],
-			'embed'		=>$C['embed'],
-			'incognito'	=>false
+			'timestamps'	=>true,
+			'embed'		=>true,
+			'incognito'	=>false,
+			'style'		=>'color:#FFFFFF;'
 		);
-		$stmt=mysqli_prepare($mysqli, "INSERT INTO `$C[prefix]members` (`nickname`, `passhash`, `status`, `refresh`, `colour`, `bgcolour`, `boxwidth`, `boxheight`, `notesboxwidth`, `notesboxheight`, `timestamps`, `embed`, `incognito`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
-		mysqli_stmt_bind_param($stmt, 'ssiissiiiiiii', $reg['nickname'], $reg['passhash'], $reg['status'], $reg['refresh'], $reg['colour'], $reg['bgcolour'], $reg['boxwidth'], $reg['boxheight'], $reg['notesboxwidth'], $reg['notesboxheight'], $reg['timestamps'], $reg['embed'], $reg['incognito']);
+		$stmt=mysqli_prepare($mysqli, "INSERT INTO `$C[prefix]members` (`nickname`, `passhash`, `status`, `refresh`, `bgcolour`, `boxwidth`, `boxheight`, `notesboxwidth`, `notesboxheight`, `timestamps`, `embed`, `incognito`, `style`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
+		mysqli_stmt_bind_param($stmt, 'ssiisiiiiiiis', $reg['nickname'], $reg['passhash'], $reg['status'], $reg['refresh'], $reg['bgcolour'], $reg['boxwidth'], $reg['boxheight'], $reg['notesboxwidth'], $reg['notesboxheight'], $reg['timestamps'], $reg['embed'], $reg['incognito'], $reg['style']);
 		mysqli_stmt_execute($stmt);
 		mysqli_stmt_close($stmt);
 		$suwrite=$I['susuccess'];
 	}
 	print_start('init');
 	echo "<center><h2>$I[init]</h2><br><h3>$I[sulogin]</h3>$suwrite<br><br><br>";
-	echo "<$H[form]>".hidden('action', 'setup').hidden('lang', $C['lang']).submit($I['initgosetup'])."</form>$H[credit]";
+	echo "<$H[form]>".hidden('action', 'setup').hidden('lang', $C['lang']).submit($I['initgosetup'])."</form>$H[credit]</center>";
 	print_end();
 }
 
 function update_db(){
-	global $C, $mysqli;
+	global $C, $F, $mysqli;
 	$dbversion=get_setting('dbversion');
 	if($dbversion<$C['dbversion'] || get_setting('msgencrypted')!=$C['msgencrypted']){
 		if($dbversion<2){
@@ -2253,11 +2448,35 @@ function update_db(){
 			mysqli_query($mysqli, "ALTER TABLE `$C[prefix]settings` CHANGE `value` `value` text NOT NULL");
 			mysqli_query($mysqli, "ALTER TABLE `$C[prefix]messages` DROP `postid`");
 		}
-
 		if($dbversion<10){
 			mysqli_query($mysqli, "INSERT INTO `$C[prefix]settings` (`setting`, `value`) VALUES ('css', 'a:visited{color:#B33CB4;} a:active{color:#FF0033;} a:link{color:#0000FF;} input,select,textarea{color:#FFFFFF;background-color:#000000;} a img{width:15%} a:hover img{width:35%} .error{color:#FF0033;} .delbutton{background-color:#660000;} .backbutton{background-color:#004400;} #exitbutton{background-color:#AA0000;}'), ('memberexpire', '60'), ('guestexpire', '15'), ('kickpenalty', '10'), ('entrywait', '120'), ('messageexpire', '14400'), ('messagelimit', '150'), ('maxmessage', 2000), ('captchatime', '600')");
 			mysqli_query($mysqli, "ALTER TABLE `$C[prefix]sessions` ADD `ip` TINYTEXT NOT NULL");
 		}
+		if($dbversion<11){
+			mysqli_query($mysqli, "ALTER TABLE `$C[prefix]captcha` CHARACTER SET utf8 COLLATE utf8_bin");
+			mysqli_query($mysqli, "ALTER TABLE `$C[prefix]filter` CHARACTER SET utf8 COLLATE utf8_bin");
+			mysqli_query($mysqli, "ALTER TABLE `$C[prefix]ignored` CHARACTER SET utf8 COLLATE utf8_bin");
+			mysqli_query($mysqli, "ALTER TABLE `$C[prefix]members` CHARACTER SET utf8 COLLATE utf8_bin");
+			mysqli_query($mysqli, "ALTER TABLE `$C[prefix]messages` CHARACTER SET utf8 COLLATE utf8_bin");
+			mysqli_query($mysqli, "ALTER TABLE `$C[prefix]notes` CHARACTER SET utf8 COLLATE utf8_bin");
+			mysqli_query($mysqli, "ALTER TABLE `$C[prefix]sessions` CHARACTER SET utf8 COLLATE utf8_bin");
+			mysqli_query($mysqli, "ALTER TABLE `$C[prefix]settings` CHARACTER SET utf8 COLLATE utf8_bin");
+			mysqli_query($mysqli, "CREATE TABLE IF NOT EXISTS `$C[prefix]linkfilter` (`id` int(10) unsigned NOT NULL, `match` tinytext NOT NULL, `replace` tinytext NOT NULL, `regex` tinyint(1) unsigned NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin");
+			mysqli_query($mysqli, "ALTER TABLE `$C[prefix]linkfilter` ADD PRIMARY KEY (`id`)");
+			mysqli_query($mysqli, "ALTER TABLE `$C[prefix]linkfilter` MODIFY `id` int(10) unsigned NOT NULL AUTO_INCREMENT");
+			mysqli_query($mysqli, "ALTER TABLE `$C[prefix]sessions` DROP `fontinfo`, DROP `displayname`");
+			mysqli_query($mysqli, "ALTER TABLE `members` ADD `style` TEXT NOT NULL");
+			$result=mysqli_query($mysqli, "SELECT * FROM `$C[prefix]members`");
+			$stmt=mysqli_prepare($mysqli, "UPDATE `$C[prefix]members` SET `style`=? WHERE `id`=?");
+			while($temp=mysqli_fetch_array($result, MYSQLI_ASSOC)){
+				$style=@get_style("#$temp[colour] {$F[$temp['fontface']]} <$temp[fonttags]>");
+				mysqli_stmt_bind_param($stmt, 'si', $style, $temp['id']);
+				mysqli_stmt_execute($stmt);
+			}
+			mysqli_stmt_close($stmt);
+			mysqli_query($mysqli, "ALTER TABLE `members` DROP `colour`, DROP `fontface`, DROP `fonttags`;");
+			mysqli_query($mysqli, "INSERT INTO `$C[prefix]settings` (`setting`, `value`) VALUES ('colbg', '000000'), ('coltxt', 'FFFFFF'), ('maxname', '20'), ('minpass', '5'), ('defaultrefresh', '20'), ('dismemcaptcha', '0'), ('suguests', '0'), ('imgembed', '1'), ('timestamps', '1'), ('trackip', '1'), ('captchachars', '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'), ('memkick', '1'), ('forceredirect', '0'), ('redirect', ''), ('incognito', '1')");
+		}
 		if(get_setting('msgencrypted')!=$C['msgencrypted']){
 			$result=mysqli_query($mysqli, "SELECT `id`, `text` FROM `$C[prefix]messages`");
 			$stmt=mysqli_prepare($mysqli, "UPDATE `$C[prefix]messages` SET `text`=? WHERE `id`=?");
@@ -2312,20 +2531,20 @@ function update_setting($setting, $value){
 function load_fonts(){
 	global $F;
 	$F=array(
-		'Arial'			=>" face='Arial,Helvetica,sans-serif'",
-		'Book Antiqua'		=>" face='Book Antiqua,MS Gothic'",
-		'Comic'			=>" face='Comic Sans MS,Papyrus'",
-		'Comic small'		=>" face='Comic Sans MS,Papyrus' size=\"-1\"",
-		'Courier'		=>" face='Courier New,Courier,monospace'",
-		'Cursive'		=>" face='Cursive,Papyrus'",
-		'Fantasy'		=>" face='Fantasy,Futura,Papyrus'",
-		'Garamond'		=>" face='Garamond,Palatino,serif'",
-		'Georgia'		=>" face='Georgia,Times New Roman,Times,serif'",
-		'Serif'			=>" face='MS Serif,New York,serif'",
-		'System'		=>" face='System,Chicago,sans-serif'",
-		'Times New Roman'	=>" face='Times New Roman,Times,serif'",
-		'Verdana'		=>" face='Verdana,Geneva,Arial,Helvetica,sans-serif'",
-		'Verdana small'		=>" face='Verdana,Geneva,Arial,Helvetica,sans-serif' size=\"-1\""
+		'Arial'			=>"font-family:'Arial','Helvetica','sans-serif';",
+		'Book Antiqua'		=>"font-family:'Book Antiqua','MS Gothic';",
+		'Comic'			=>"font-family:'Comic Sans MS','Papyrus';",
+		'Comic small'		=>"font-family:'Comic Sans MS','Papyrus';font-size:smaller;",
+		'Courier'		=>"font-family:'Courier New','Courier','monospace';",
+		'Cursive'		=>"font-family:'Cursive','Papyrus';",
+		'Fantasy'		=>"font-family:'Fantasy','Futura','Papyrus';",
+		'Garamond'		=>"font-family:'Garamond','Palatino','serif';",
+		'Georgia'		=>"font-family:'Georgia','Times New Roman','Times','serif';",
+		'Serif'			=>"font-family:'MS Serif','New York','serif';",
+		'System'		=>"font-family:'System','Chicago','sans-serif';",
+		'Times New Roman'	=>"font-family:'Times New Roman','Times','serif';",
+		'Verdana'		=>"font-family:'Verdana','Geneva','Arial','Helvetica','sans-serif';",
+		'Verdana small'		=>"font-family:'Verdana','Geneva','Arial','Helvetica','sans-serif';font-size:smaller;"
 	);
 }
 
@@ -2335,7 +2554,7 @@ function load_html(){
 		'begin_body'	=>"body",
 		'form'		=>"form action=\"$_SERVER[SCRIPT_NAME]\" method=\"post\" style=\"margin:0;padding:0;\"",
 		'meta_html'	=>"<title>$C[chatname]</title><meta name=\"robots\" content=\"noindex,nofollow\"><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"><meta http-equiv=\"Pragma\" content=\"no-cache\"><meta http-equiv=\"Cache-Control\" content=\"no-cache\"><meta http-equiv=\"expires\" content=\"0\">",
-		'credit'	=>"<small><br><br><a target=\"_blank\" href=\"https://github.com/DanWin/le-chat-php\">LE CHAT-PHP - $C[version]</a></small></center>"
+		'credit'	=>"<small><br><br><a target=\"_blank\" href=\"https://github.com/DanWin/le-chat-php\">LE CHAT-PHP - $C[version]</a></small>"
 	);
 	$H=$H+array(
 		'backtologin'	=>"<$H[form] target=\"_parent\">".hidden('lang', $C['lang']).submit($I['backtologin'], 'class="backbutton"').'</form>',
@@ -2378,17 +2597,12 @@ function load_lang(){
 function load_config(){
 	global $C;
 	$C=array(
-		'version'	=>'1.11.2', // Script version
-		'dbversion'	=>10, // Database version
-		'colbg'		=>'000000', // Background colour
-		'coltxt'	=>'FFFFFF', // Default text colour
+		'version'	=>'1.12', // Script version
+		'dbversion'	=>11, // Database version
 		'chatname'	=>'My Chat', // Chat Name
 		'keeplimit'	=>3, // Amount of messages to keep in the database (multiplied with max messages displayed) - increase if you have many private messages
-		'defaultrefresh'=>30, // Seconds to refresh the messages
 		'msgencrypted'	=>false, // Store messages encrypted in the database to prevent other database users from reading them - true/false - visit the setup page after editing!
 		'encryptkey'	=>'MY_KEY', // Encryption key for messages
-		'maxname'	=>20, // Longest number of chatacters for a name
-		'minpass'	=>5, // Shortest number of chatacters for a password
 		'dbhost'	=>'p:localhost', // Database host
 		'dbuser'	=>'www-data', // Database user
 		'dbpass'	=>'YOUR_DB_PASS', // Database password
@@ -2397,21 +2611,10 @@ function load_config(){
 		'memcached'	=>false, // Enable/disable memcached caching true/false - needs php5-memcached and a memcached server.
 		'memcachedhost'	=>'localhost', // Memcached server
 		'memcachedport'	=>'11211', // Memcached server
-		'captchachars'	=>'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', // Characters used for captcha generation
-		'dismemcaptcha'	=>false, // Disable captcha for members? true/false
-		'embed'		=>true, // Default for displaying embedded imgs or turning them into links true/false
-		'imgembed'	=>true, // Allow image embedding in chat using [img] tag? true/false
-		'suguests'	=>false, // Adds option to add applicants. They will have a reserved nick protected with a password, but don't count as member true/false
-		'timestamps'	=>true, // Display timestamps in front of the messages by default true/false
-		'incognito'	=>true, // Allow mods and admins to be invisable true/false
-		'forceredirect'	=>false, // Force redirect script or only use when no cookies available? true/false
-		'memkick'	=>true, // Let a member kick guests if no mod is present
 		'sendmail'	=>false, // Send mail on new message - only activate on low traffic chat or your inbox will fill up very fast!
 		'mailsender'	=>'www-data <www-data@localhost>', // Send mail using this e-Mail address
 		'mailreceiver'	=>'Webmaster <webmaster@localhost>', // Send mail to this e-Mail address
-		'redirect'	=>"$_SERVER[SCRIPT_NAME]?action=redirect&url=", // Redirect script default: "$_SERVER[SCRIPT_NAME]?action=redirect&url="
-		'lang'		=>'en', // Default language
-		'trackip'	=>true // Display IP-Address in session overview - true/false
+		'lang'		=>'en' // Default language
 	);
 	$C=$C+array(
 		'cookiename'	=>"$C[prefix]chat_session" // Cookie name storing the session information
diff --git a/lang_de.php b/lang_de.php
index 6e350a7..98d2c00 100644
--- a/lang_de.php
+++ b/lang_de.php
@@ -77,7 +77,7 @@ $I=array(
 	'kick' => 'Rausschmeißen',
 	'logoutinact' => 'Inaktive Teilnehmer abmelden',
 	'logout' => 'Abmelden',
-	'viewsess' => 'Aktive Sitzungen anzeigen',
+	'sessions' => 'Aktive Sitzungen anzeigen',
 	'view' => 'Anzeigen',
 	'filter' => 'Filter',
 	'guestacc' => 'Gastzugriff ändern',
@@ -180,8 +180,8 @@ $I=array(
 	'randomcol' => 'Zufällige Farbe',
 	'enter' => 'Chat beitreten',
 	'error' => 'Fehler:',
-	'members' => 'Mitglieder:',
-	'guests' => 'Gäste:',
+	'members' => 'Mitglieder',
+	'guests' => 'Gäste',
 	'approveguests' => '%d neue Gäste zum Hereinlassen',
 	'allowchecked' => 'Ausgewählte erlauben',
 	'allowall' => 'Alle erlauben',
@@ -256,6 +256,24 @@ $I=array(
 	'maxmessage' => 'Maximale Nachrichenlänge',
 	'confirm' => 'Bist du sicher?',
 	'yes' => 'Ja',
-	'no' => 'Nein'
+	'no' => 'Nein',
+	'colbg' => 'Hintergrundfarbe',
+	'coltxt' => 'Schriftfarbe',
+	'maxname' => 'Maximale Benutzernamen-Länge',
+	'minpass' => 'Minimale Passwortlänge',
+	'defaultrefresh' => 'Standardzeit zum Neuladen der Nachrichten (Sekunden)',
+	'suguests' => 'Anwerber aktivieren',
+	'rulestxt' => 'Regeln (html)',
+	'imgembed' => 'Bilder einbetten',
+	'trackip' => 'Sitzungs-IP anzeigen',
+	'captchachars' => 'Im Captcha benutzte Zeichen',
+	'memkick' => 'Mitglieder dürfen Rasusschmeißen, wenn kein Moderator da ist',
+	'forceredirect' => 'Umleitung erzwingen',
+	'redirect' => 'Benutzerdefinierte Umleitungsadresse',
+	'backuprestore' => 'Sichern und wiederherstellen',
+	'backup' => 'Sichern',
+	'restore' => 'Wiederherstellen',
+	'settings' => 'Einstellungen',
+	'linkfilter' => 'Linkfilter'
 );
 ?>
diff --git a/lang_en.php b/lang_en.php
index b7f3a14..8bfc955 100644
--- a/lang_en.php
+++ b/lang_en.php
@@ -78,7 +78,7 @@ $I=array(
 	'kick' => 'Kick',
 	'logoutinact' => 'Logout inactive Chatter',
 	'logout' => 'Logout',
-	'viewsess' => 'View active sessions',
+	'sessions' => 'View active sessions',
 	'view' => 'View',
 	'filter' => 'Filter',
 	'guestacc' => 'Change Guestaccess',
@@ -181,8 +181,8 @@ $I=array(
 	'randomcol' => 'Random Colour',
 	'enter' => 'Enter Chat',
 	'error' => 'Error:',
-	'members' => 'Members:',
-	'guests' => 'Guests:',
+	'members' => 'Members',
+	'guests' => 'Guests',
 	'approveguests' => '%d new guests to approve',
 	'allowchecked' => 'Allow checked',
 	'allowall' => 'Allow all',
@@ -254,9 +254,27 @@ $I=array(
 	'captchatime' => 'Captcha timeout (seconds)',
 	'messageexpire' => 'Message timeout (minutes)',
 	'messagelimit' => 'Message limit (public)',
-	'maxmessage' => 'Maximum message length',
+	'maxmessage' => 'Maximal message length',
 	'confirm' => 'Are you sure?',
 	'yes' => 'Yes',
-	'no' => 'No'
+	'no' => 'No',
+	'colbg' => 'Background colour',
+	'coltxt' => 'Text colour',
+	'maxname' => 'Maximal user name length',
+	'minpass' => 'Minimal password length',
+	'defaultrefresh' => 'Default message reload time (seconds)',
+	'suguests' => 'Enable applicants',
+	'rulestxt' => 'Rules (html)',
+	'imgembed' => 'Embed images',
+	'trackip' => 'Show session-IP',
+	'captchachars' => 'Characters used in Captcha',
+	'memkick' => 'Members can kick, if no moderator is present',
+	'forceredirect' => 'Force redirection',
+	'redirect' => 'Custom redirection script',
+	'backuprestore' => 'Backup and restore',
+	'backup' => 'Backup',
+	'restore' => 'Restore',
+	'settings' => 'Settings',
+	'linkfilter' => 'Linkfilter'
 );
 ?>