universe

Universe
git clone https://git.dasho.dev/universe.git
Log | Files | Refs | Submodules | README

index.php (264827B)


      1 <?php
      2 
      3 // Turn off error reporting and display
      4 error_reporting(0);
      5 ini_set('display_errors', 0);
      6 ini_set('display_startup_errors', 0);
      7 ini_set('log_errors', 1);
      8 ini_set('html_errors', 0);
      9 
     10 /*
     11 * status codes
     12 * 0 - Kicked/Banned
     13 * 1 - Guest
     14 * 2 - Applicant
     15 * 3 - Member
     16 * 4 - System message
     17 * 5 - Moderator
     18 * 6 - Super-Moderator
     19 * 7 - Admin
     20 * 8 - Super-Admin
     21 * 9 - Private messages
     22 */
     23 
     24 // Dasho (https://dasho.dev)
     25 
     26 send_headers();
     27 // initialize and load variables/configuration
     28 $I = []; // Translations
     29 $L = []; // Languages
     30 $U = []; // This user data
     31 $db; // Database connection
     32 $memcached; // Memcached connection
     33 $language; // user selected language
     34 load_config();
     35 // set session variable to cookie if cookies are enabled
     36 if (!isset($_REQUEST['session']) && isset($_COOKIE[COOKIENAME])) {
     37 
     38 //Modification that prevents users from doing unwanted things (for example unintentionally deleting their account), if someone else posts a malicious link.
     39 // MODIFICATION added logout to list of unwanted things
     40 // MODIFICATION fixed: allow setup actions when they're legitimate POST requests or have 'do' parameter (admin operations)
     41 if (isset($_REQUEST['action']) && ($_REQUEST['action'] === 'profile' || $_REQUEST['action'] === 'post' || $_REQUEST['action'] === 'admin' || $_REQUEST['action'] === 'logout')) {
     42 	$_REQUEST['action'] = 'login';
     43 } elseif (isset($_REQUEST['action']) && $_REQUEST['action'] === 'setup' && !isset($_REQUEST['do']) && $_SERVER['REQUEST_METHOD'] !== 'POST') {
     44 	$_REQUEST['action'] = 'login';
     45 }
     46 $_REQUEST['session'] = $_COOKIE[COOKIENAME];
     47 }
     48 $_REQUEST['session'] = preg_replace('/[^0-9a-zA-Z]/', '', $_REQUEST['session'] ?? '');
     49 load_lang();
     50 check_db();
     51 cron();
     52 route();
     53 
     54 //  main program: decide what to do based on queries
     55 function route()
     56 {
     57 global $U;
     58 if (!isset($_REQUEST['action'])) {
     59 	send_login();
     60 } elseif ($_REQUEST['action'] === 'view') {
     61 	check_session();
     62 	//Modification chat rooms
     63 	if (isset($_REQUEST['room'])) {
     64 		change_room();
     65 		check_session();
     66 	}
     67 	// show_rooms('true');
     68 	send_messages();
     69 } elseif ($_REQUEST['action'] === 'redirect' && !empty($_REQUEST['url'])) {
     70 	send_redirect($_REQUEST['url']);
     71 } elseif ($_REQUEST['action'] === 'rooms') {
     72 	check_session();
     73 	rooms();
     74 } elseif ($_REQUEST['action'] === 'wait') {
     75 	parse_sessions();
     76 	send_waiting_room();
     77 } elseif ($_REQUEST['action'] === 'post') {
     78 	check_session();
     79 	if (isset($_REQUEST['kick']) && isset($_REQUEST['sendto']) && $_REQUEST['sendto'] !== ('s 48' || 's 56' || 's 65')) {
     80 		//Modification to allow members to kick guests, if memdel (DEL-Buttons) enabled
     81 		if ($U['status'] >= 5 || ($U['status'] >= 3 && get_count_mods() == 0 && get_setting('memkick')) || ($U['status'] >= 3 && (int)get_setting('memdel') === 2)) {
     82 			if (isset($_REQUEST['what']) && $_REQUEST['what'] === 'purge') {
     83 				kick_chatter([$_REQUEST['sendto']], $_REQUEST['message'], true);
     84 			} else {
     85 				kick_chatter([$_REQUEST['sendto']], $_REQUEST['message'], false);
     86 			}
     87 		}
     88 	} elseif (isset($_REQUEST['message']) && isset($_REQUEST['sendto'])) {
     89 		send_post(validate_input());
     90 	}
     91 	send_post();
     92 } elseif ($_REQUEST['action'] === 'login') {
     93 	check_login();
     94 	send_frameset();
     95 } elseif ($_REQUEST['action'] === 'controls') {
     96 	check_session();
     97 	send_controls();
     98 } elseif ($_REQUEST['action'] === 'greeting') {
     99 	check_session();
    100 	send_greeting();
    101 } elseif ($_REQUEST['action'] === 'delete') {
    102 	check_session();
    103 	if ($_REQUEST['what'] === 'all') {
    104 		if (isset($_REQUEST['confirm'])) {
    105 			del_all_messages($U['nickname'], $U['status'] == 1 ? $U['entry'] : 0);
    106 		} else {
    107 			send_del_confirm();
    108 		}
    109 	} elseif ($_REQUEST['what'] === 'last') {
    110 		del_last_message();
    111 	}
    112 	send_post();
    113 } elseif ($_REQUEST['action'] === 'profile') {
    114 	check_session();
    115 	$arg = '';
    116 	if (!isset($_REQUEST['do'])) {
    117 	} elseif ($_REQUEST['do'] === 'save') {
    118 		$arg = save_profile();
    119 	} elseif ($_REQUEST['do'] === 'delete') {
    120 		if (isset($_REQUEST['confirm'])) {
    121 			delete_account();
    122 		} else {
    123 			send_delete_account();
    124 		}
    125 	}
    126 	send_profile($arg);
    127 } elseif ($_REQUEST['action'] === 'logout') {
    128 	kill_session();
    129 	send_logout();
    130 } elseif ($_REQUEST['action'] === 'colours') {
    131 	check_session();
    132 	send_colours();
    133 } elseif ($_REQUEST['action'] === 'notes') {
    134 	check_session();
    135 	$sparenotesaccess = (int) get_setting('sparenotesaccess');
    136 	if (isset($_REQUEST['do']) && $_REQUEST['do'] === 'admin' && $U['status'] > 6) {
    137 		send_notes(0);
    138 	} elseif (isset($_REQUEST['do']) && $_REQUEST['do'] === 'staff' && $U['status'] >= 5) {
    139 		send_notes(1);
    140 		// Modification Spare Notes
    141 	} elseif (isset($_REQUEST['do']) && $_REQUEST['do'] === 'spare' && $U['status'] >= $sparenotesaccess) {
    142 		send_notes(3);
    143 	}
    144 	if ($U['status'] < 3 || !get_setting('personalnotes')) {
    145 		send_access_denied();
    146 	}
    147 	send_notes(2);
    148 } elseif ($_REQUEST['action'] === 'help') {
    149 	check_session();
    150 	send_help();
    151 } elseif ($_REQUEST['action'] === 'inbox') {
    152 	check_session();
    153 	if (isset($_REQUEST['do'])) {
    154 		clean_inbox_selected();
    155 	}
    156 	send_inbox();
    157 } elseif ($_REQUEST['action'] === 'download') {
    158 	send_download();
    159 } elseif ($_REQUEST['action'] === 'admin') {
    160 	check_session();
    161 	send_admin(route_admin());
    162 	//MODIFICATION DEL-BUTTONS 3 Lines added to enable delete buttons in front of each message.
    163 } elseif ($_REQUEST['action'] === 'admin_clean_message') {
    164 	check_session();
    165 
    166 	//These lines allows members to use the DEL-buttons according to the memdel setting (0 = not allowed , 2 =  allowed, 1 = allowed if not mod is present and if DEL-Buttons are activated for members.)
    167 	$memdel = (int)get_setting('memdel');
    168 	if (($U['status'] >= 5) || ($U['status'] >= 3 && $memdel === 2) || ($U['status'] >= 3 && get_count_mods() == 0 && $memdel === 1)) {
    169 		clean_selected($U['status'], $U['nickname']);
    170 	}
    171 	send_messages();
    172 
    173 	//MODIFICATION gallery
    174 } elseif ($_REQUEST['action'] === 'gallery') {
    175 	check_session(); //to get $U['status']
    176 	if (!isset($_REQUEST['do'])) {
    177 		send_gallery();
    178 	} else {
    179 		send_gallery($_REQUEST['do']);
    180 	}
    181 	//MODIFICATION links page
    182 } elseif ($_REQUEST['action'] === 'links') {
    183 	check_session(); //to allow links page only for logged in users.
    184 	send_links_page();
    185 
    186 	//Forum Button was moved to the post box (function send_post)
    187 	/*
    188    }elseif($_REQUEST['action']==='forum'){
    189  		check_session(); //to allow link to form only for logged in users.
    190  		send_to_forum();	
    191 */
    192 } elseif ($_REQUEST['action'] === 'setup') {
    193 	route_setup();
    194 } else {
    195 	send_login();
    196 }
    197 }
    198 
    199 function route_admin()
    200 {
    201 global $U, $db;
    202 
    203 if ($U['status'] < 5) {
    204 	send_access_denied();
    205 }
    206 //Modification chat rooms
    207 $roomcreateaccess = (int) get_setting('roomcreateaccess');
    208 if (!isset($_REQUEST['do'])) {
    209 } elseif ($_REQUEST['do'] === 'clean') {
    210 	if ($_REQUEST['what'] === 'choose') {
    211 		send_choose_messages();
    212 	} elseif ($_REQUEST['what'] === 'selected') {
    213 		clean_selected($U['status'], $U['nickname']);
    214 	} elseif ($_REQUEST['what'] === 'chat') {
    215 		clean_chat();
    216 	} elseif ($_REQUEST['what'] === 'room') {
    217 		clean_room();
    218 	} elseif ($_REQUEST['what'] === 'nick') {
    219 		$stmt = $db->prepare('SELECT null FROM ' . PREFIX . 'members WHERE nickname=? AND status>=?;');
    220 		$stmt->execute([$_REQUEST['nickname'], $U['status']]);
    221 		if (!$stmt->fetch(PDO::FETCH_ASSOC)) {
    222 			del_all_messages($_REQUEST['nickname'], 0);
    223 		}
    224 	}
    225 } elseif ($_REQUEST['do'] === 'kick') {
    226 	if (isset($_REQUEST['name'])) {
    227 		if (isset($_REQUEST['what']) && $_REQUEST['what'] === 'purge') {
    228 			kick_chatter($_REQUEST['name'], $_REQUEST['kickmessage'], true);
    229 		} else {
    230 			kick_chatter($_REQUEST['name'], $_REQUEST['kickmessage'], false);
    231 		}
    232 	}
    233 } elseif ($_REQUEST['do'] === 'logout') {
    234 	if (isset($_REQUEST['name'])) {
    235 		logout_chatter($_REQUEST['name']);
    236 	}
    237 } elseif ($_REQUEST['do'] === 'sessions') {
    238 	if (isset($_REQUEST['kick']) && isset($_REQUEST['nick'])) {
    239 		kick_chatter([$_REQUEST['nick']], '', false);
    240 	} elseif (isset($_REQUEST['logout']) && isset($_REQUEST['nick'])) {
    241 		logout_chatter([$_REQUEST['nick']], '', false);
    242 	}
    243 	send_sessions();
    244 	// MODIFICATION only admins can register to member
    245 } elseif ($_REQUEST['do'] === 'register' && $U['status'] > 6) {
    246 	return register_guest(3, $_REQUEST['name']);
    247 } elseif ($_REQUEST['do'] === 'superguest') {
    248 	return register_guest(2, $_REQUEST['name']);
    249 	// MODIFICATION only admins can change status
    250 } elseif ($_REQUEST['do'] === 'status' && $U['status'] > 6) {
    251 	return change_status($_REQUEST['name'], $_REQUEST['set']);
    252 	// MODIFICATION only admins can register new members
    253 } elseif ($_REQUEST['do'] === 'regnew' && $U['status'] > 6) {
    254 	return register_new($_REQUEST['name'], $_REQUEST['pass']);
    255 } elseif ($_REQUEST['do'] === 'approve') {
    256 	approve_session();
    257 	send_approve_waiting();
    258 } elseif ($_REQUEST['do'] === 'guestaccess') {
    259 	if (isset($_REQUEST['guestaccess']) && preg_match('/^[0123]$/', $_REQUEST['guestaccess'])) {
    260 		update_setting('guestaccess', $_REQUEST['guestaccess']);
    261 	}
    262 	//MODIFICATION 2019-08-28 line changed. only smods (status = 6) with name Jonie , admins and above can view or change filters.
    263 } elseif (($_REQUEST['do'] === 'filter' && $U['status'] >= 7) || ($_REQUEST['do'] === 'filter' && $U['status'] >= 6 && $U['nickname'] === 'Jonie')) {
    264 	send_filter(manage_filter());
    265 	//MODIFICATION 2019-08-28 line changed. only smods (status = 6) with name Jonie , admins and above can view or change linkfilters.
    266 } elseif (($_REQUEST['do'] === 'linkfilter' && $U['status'] >= 7) || ($_REQUEST['do'] === 'linkfilter' && $U['status'] >= 6 && $U['nickname'] === 'Jonie')) {
    267 	send_linkfilter(manage_linkfilter());
    268 } elseif ($_REQUEST['do'] === 'lastlogin' && $U['status'] >= 7) {
    269 	send_lastlogin();
    270 } elseif ($_REQUEST['do'] === 'topic') {
    271 	//Modification "topic with html-code" (2 Lines)
    272 	if (isset($_REQUEST['topic']) && $U['status'] >= 7) {
    273 		update_setting('topic', $_REQUEST['topic']);
    274 	}
    275 	// MODIFICATION only admins can reset passwords
    276 } elseif ($_REQUEST['do'] === 'passreset' && $U['status'] > 6) {
    277 	return passreset($_REQUEST['name'], $_REQUEST['pass']);
    278 	//Modification chat rooms
    279 } elseif ($_REQUEST['do'] === 'rooms' && $U['status'] >= $roomcreateaccess) {
    280 	send_rooms(manage_rooms());
    281 }
    282 }
    283 
    284 function route_setup()
    285 {
    286 global $U;
    287 if (!valid_admin()) {
    288 	send_alogin();
    289 }
    290 //MODIFICATION incognito setting only for super admin
    291 $C['bool_settings'] = ['suguests', 'imgembed', 'timestamps', 'trackip', 'memkick', 'forceredirect', 'sendmail', 'modfallback', 'disablepm', 'eninbox', 'enablegreeting', 'sortupdown', 'hidechatters', 'personalnotes', 'filtermodkick'];
    292 $C['colour_settings'] = ['colbg', 'coltxt'];
    293 $C['msg_settings'] = ['msgenter', 'msgexit', 'msgmemreg', 'msgsureg', 'msgkick', 'msgmultikick', 'msgallkick', 'msgclean', 'msgsendall', 'msgsendmem', 'msgsendmod', 'msgsendadm', 'msgsendprv', 'msgattache'];
    294 $C['number_settings'] = ['memberexpire', 'guestexpire', 'kickpenalty', 'entrywait', 'captchatime', 'messageexpire', 'messagelimit', 'maxmessage', 'maxname', 'minpass', 'defaultrefresh', 'numnotes', 'maxuploadsize', 'enfileupload'];
    295 $C['textarea_settings'] = ['rulestxt', 'css', 'disabletext'];
    296 $C['text_settings'] = ['dateformat', 'captchachars', 'redirect', 'chatname', 'mailsender', 'mailreceiver', 'nickregex', 'passregex', 'externalcss'];
    297 
    298 //MODIFICATION for links page. setting links and linksenabled added.
    299 //MODIFICATION for DEL-Buttons: setting memdel added.
    300 //MODIFICATION for galleryaccess: setting galleryaccess added.
    301 //MODIFICATION for forumbtnaccess: setting forumbtnaccess added.
    302 //MODIFICATION for forumbtnlink: setting forumbtnlink added.
    303 //MODIFICATION for frontpagetext: setting frontpagetext added.
    304 //MODIFICATION for adminjoinleavemsg: setting adminjoinleavemsg
    305 //MODIFICATION for clickablne nicknames: setting clickablenicknamesglobal
    306 //MODIFICATION for spare notes: setting sparenotesname, setting sparenotesaccess
    307 //MODIFICATION for chat rooms: setting roomcreateaccess, setting roomexpire, setting channelvisinroom
    308 $C['settings'] = array_merge(['guestaccess', 'englobalpass', 'globalpass', 'captcha', 'dismemcaptcha', 'topic', 'guestreg', 'defaulttz', 'links', 'linksenabled', 'memdel', 'galleryaccess', 'forumbtnaccess', 'forumbtnlink', 'frontpagetext', 'adminjoinleavemsg', 'clickablenicknamesglobal', 'sparenotesname', 'sparenotesaccess', 'roomcreateaccess', 'roomexpire', 'channelvisinroom'], $C['bool_settings'], $C['colour_settings'], $C['msg_settings'], $C['number_settings'], $C['textarea_settings'], $C['text_settings']); // All settings in the database
    309 
    310 
    311 //Modification Super Admin settings
    312 //MODIFICATION for modsdeladminmsg: Super Admin setting modsdeladminmsg added
    313 $C_SAdmin = $C;
    314 $C_SAdmin['settings'] = array_merge($C['settings'], ['modsdeladminmsg', 'incognito']);
    315 
    316 
    317 //Modificatoin Super Admin settings
    318 if (!isset($_REQUEST['do'])) {
    319 } elseif ($_REQUEST['do'] === 'save' && $U['status'] == 8) {
    320 	save_setup($C_SAdmin);
    321 } elseif ($_REQUEST['do'] === 'save') {
    322 	save_setup($C);
    323 } elseif ($_REQUEST['do'] === 'backup' && $U['status'] == 8) {
    324 	send_backup($C);
    325 } elseif ($_REQUEST['do'] === 'restore' && $U['status'] == 8) {
    326 	restore_backup($C);
    327 	send_backup($C);
    328 } elseif ($_REQUEST['do'] === 'destroy' && $U['status'] == 8) {
    329 	if (isset($_REQUEST['confirm'])) {
    330 		destroy_chat($C);
    331 	} else {
    332 		send_destroy_chat();
    333 	}
    334 }
    335 send_setup($C);
    336 }
    337 
    338 //  html output subs
    339 function print_stylesheet($init = false)
    340 {
    341 global $U;
    342 //default css
    343 echo '<style type="text/css">';
    344 echo 'body{background-color:#000000;color:#FFFFFF;font-size:14px;text-align:center;} body .rooms {background-color: transparent !important;}';
    345 echo 'a:visited{color:#B33CB4;} a:active{color:#FF0033;} a:link{color:#0000FF;} #messages{word-wrap:break-word;} ';
    346 echo 'input,select,textarea{color:#FFFFFF;background-color:#000000;} .messages a img{width:15%} .messages a:hover img{width:35%} ';
    347 echo '.error{color:#FF0033;text-align:left;} .delbutton{background-color:#660000;} .backbutton{background-color:#004400;} #exitbutton{background-color:#AA0000;} ';
    348 echo '.setup table table,.admin table table,.profile table table{width:100%;text-align:left} ';
    349 echo '.alogin table,.init table,.destroy_chat table,.delete_account table,.sessions table,.filter table,.linkfilter table,.notes table,.approve_waiting table,.del_confirm table,.profile table,.admin table,.backup table,.setup table{margin-left:auto;margin-right:auto;} ';
    350 echo '.setup table table table,.admin table table table,.profile table table table{border-spacing:0px;margin-left:auto;margin-right:unset;width:unset;} ';
    351 echo '.setup table table td,.backup #restoresubmit,.backup #backupsubmit,.admin table table td,.profile table table td,.login td+td,.alogin td+td{text-align:right;} ';
    352 echo '.init td,.backup #restorecheck td,.admin #clean td,.admin #regnew td,.session td,.messages,.inbox,.approve_waiting td,.choose_messages,.greeting,.help,.login td,.alogin td{text-align:left;} ';
    353 echo '.messages #chatters{max-height:100px;overflow-y:auto;} .messages #chatters a{text-decoration-line:none;} .messages #chatters table{border-spacing:0px;} ';
    354 echo '.messages #chatters th,.messages #chatters td,.post #firstline{vertical-align:top;} ';
    355 echo '.approve_waiting #action td:only-child,.help #backcredit,.login td:only-child,.alogin td:only-child,.init td:only-child{text-align:center;} .sessions td,.sessions th,.approve_waiting td,.approve_waiting th{padding: 5px;} ';
    356 echo '.sessions td td{padding: 1px;} .messages #bottom_link{position:fixed;top:0.5em;right:0.5em;} .messages #top_link{position:fixed;bottom:0.5em;right:0.5em;} ';
    357 echo '.post table,.controls table,.login table{border-spacing:0px;margin-left:auto;margin-right:auto;} .login table{border:2px solid;} .controls{overflow-y:none;} ';
    358 echo '#manualrefresh{display:block;position:fixed;text-align:center;left:25%;width:50%;top:-200%;animation:timeout_messages ';
    359 if (isset($U['refresh'])) {
    360 	echo $U['refresh'] + 20;
    361 } else {
    362 	echo '160';
    363 }
    364 echo 's forwards;z-index:2;background-color:#500000;border:2px solid #ff0000;} ';
    365 echo '@keyframes timeout_messages{0%{top:-200%;} 99%{top:-200%;} 100%{top:0%;}} ';
    366 echo '.notes textarea{height:80vh;width:80%;}iframe{width:100%;height:100%;margin:0;padding:0;border:none}';
    367 echo '@import url("style.css");';
    368 echo '</style>';
    369 if ($init) {
    370 	return;
    371 }
    372 $css = get_setting('css');
    373 $coltxt = get_setting('coltxt');
    374 if (!empty($U['bgcolour'])) {
    375 	$colbg = $U['bgcolour'];
    376 } else {
    377 	$colbg = get_setting('colbg');
    378 }
    379 echo "<link rel=\"shortcut icon\" href=\"https://cdn.sokka.dev/global/images/favicon.svg\">";
    380 //overwrite with custom css
    381 echo "<style type=\"text/css\">body{background-color:#$colbg;color:#$coltxt;} $css</style>";
    382 echo "<link rel=\"preload\" href=\"style.css\" as=\"style\"><link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">";
    383 }
    384 
    385 function print_end()
    386 {
    387 echo '</body></html>';
    388 exit;
    389 }
    390 
    391 function credit()
    392 {
    393 return '<small><br><br><a target="_blank" style="color:var(--accent); text-decoration: underline dotted var(--accent)" href="https://4-0-4.io">Project 404</a></small>';
    394 }
    395 
    396 function meta_html()
    397 {
    398 return '<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, no-store, must-revalidate, max-age=0"><meta http-equiv="expires" content="0"><meta name="referrer" content="no-referrer">';
    399 }
    400 
    401 function form($action, $do = '')
    402 {
    403 global $language;
    404 $form = "<form action=\"\" enctype=\"multipart/form-data\" method=\"post\">" . hidden('lang', $language) . hidden('nc', substr(time(), -6)) . hidden('action', $action);
    405 if (!empty($_REQUEST['session'])) {
    406 	$form .= hidden('session', $_REQUEST['session']);
    407 }
    408 if ($do !== '') {
    409 	$form .= hidden('do', $do);
    410 }
    411 return $form;
    412 }
    413 
    414 function form_target($target, $action, $do = '')
    415 {
    416 global $language;
    417 $form = "<form action=\"\" enctype=\"multipart/form-data\" method=\"post\" target=\"$target\">" . hidden('lang', $language) . hidden('nc', substr(time(), -6)) . hidden('action', $action);
    418 if (!empty($_REQUEST['session'])) {
    419 	$form .= hidden('session', $_REQUEST['session']);
    420 }
    421 if ($do !== '') {
    422 	$form .= hidden('do', $do);
    423 }
    424 return $form;
    425 }
    426 
    427 function hidden($arg1 = '', $arg2 = '')
    428 {
    429 return "<input type=\"hidden\" name=\"$arg1\" value=\"$arg2\">";
    430 }
    431 
    432 function submit($arg1 = '', $arg2 = '')
    433 {
    434 return "<input type=\"submit\" value=\"$arg1\" $arg2>";
    435 }
    436 
    437 function thr()
    438 {
    439 echo '<tr><td><hr></td></tr>';
    440 }
    441 
    442 function print_start($class = '', $ref = 0, $url = '')
    443 {
    444 global $I;
    445 if (!empty($url)) {
    446 	$url = str_replace('&amp;', '&', $url); // Don't escape "&" in URLs here, it breaks some (older) browsers and js refresh!
    447 	header("Refresh: $ref; URL=$url");
    448 }
    449 echo '<!DOCTYPE html><html><head>' . meta_html();
    450 if (!empty($url)) {
    451 	echo "<meta http-equiv=\"Refresh\" content=\"$ref; URL=$url\">";
    452 	$ref += 5; //only use js if browser refresh stopped working
    453 	$ref *= 1000; //js uses milliseconds
    454 
    455 	// MODIFICATION removed window refresh js
    456 	/* echo "<script type=\"text/javascript\">setTimeout(function(){window.location.replace(\"$url\");}, $ref);</script>";*/
    457 }
    458 if ($class === 'init') {
    459 	echo "<title>$I[init]</title>";
    460 	print_stylesheet(true);
    461 } else {
    462 	echo '<title>' . get_setting('chatname') . '</title>';
    463 	print_stylesheet();
    464 }
    465 if ($class !== 'init' && ($externalcss = get_setting('externalcss')) != '') {
    466 	//external css - in body to make it non-renderblocking
    467 }
    468 echo "<link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">";
    469 echo '<meta http-equiv="onion-location" content="http://cboxkuuxrtulkkxhod2pxo3la25tztcp4cdjmc75wc5airqqliq2srad.onion" />';
    470 echo "</head><body class=\"$class\">";
    471 }
    472 
    473 function send_redirect($url)
    474 {
    475 global $I;
    476 $url = trim(htmlspecialchars_decode(rawurldecode($url)));
    477 preg_match('~^(.*)://~u', $url, $match);
    478 $url = preg_replace('~^(.*)://~u', '', $url);
    479 $escaped = htmlspecialchars($url);
    480 if (isset($match[1]) && ($match[1] === 'http' || $match[1] === 'https')) {
    481 	print_start('redirect', 0, $match[0] . $escaped);
    482 	echo "<p>$I[redirectto] <a href=\"$match[0]$escaped\">$match[0]$escaped</a>.</p>";
    483 } else {
    484 	print_start('redirect');
    485 	if (!isset($match[0])) {
    486 		$match[0] = '';
    487 	}
    488 	if (preg_match('~^(javascript|blob|data):~', $url)) {
    489 		echo "<p>$I[dangerousnonhttp] $match[0]$escaped</p>";
    490 	} else {
    491 		echo "<p>$I[nonhttp] <a href=\"$match[0]$escaped\">$match[0]$escaped</a>.</p>";
    492 	}
    493 	echo "<p>$I[httpredir] <a href=\"http://$escaped\">http://$escaped</a>.</p>";
    494 }
    495 print_end();
    496 }
    497 
    498 function send_access_denied()
    499 {
    500 global $I, $U;
    501 header('HTTP/1.1 403 Forbidden');
    502 print_start('access_denied');
    503 echo "<h1>$I[accessdenied]</h1>" . sprintf($I['loggedinas'], style_this(htmlspecialchars($U['nickname']), $U['style'])) . '<br>';
    504 echo form('logout');
    505 if (!isset($_REQUEST['session'])) {
    506 	echo hidden('session', $U['session']);
    507 }
    508 echo submit($I['logout'], 'id="exitbutton"') . "</form>";
    509 print_end();
    510 }
    511 
    512 function send_captcha()
    513 {
    514 global $I, $db, $memcached;
    515 $difficulty = (int) get_setting('captcha');
    516 if ($difficulty === 0 || !extension_loaded('gd')) {
    517 	return;
    518 }
    519 $captchachars = get_setting('captchachars');
    520 $length = strlen($captchachars) - 1;
    521 $code = '';
    522 for ($i = 0; $i < 5; ++$i) {
    523 	$code .= $captchachars[mt_rand(0, $length)];
    524 }
    525 $randid = mt_rand();
    526 $time = time();
    527 if (MEMCACHED) {
    528 	$memcached->set(DBNAME . '-' . PREFIX . "captcha-$randid", $code, get_setting('captchatime'));
    529 } else {
    530 	$stmt = $db->prepare('INSERT INTO ' . PREFIX . 'captcha (id, time, code) VALUES (?, ?, ?);');
    531 	$stmt->execute([$randid, $time, $code]);
    532 }
    533 echo "<tr id=\"captcha\"><td><span class=\"centerWrap sprite-decaptcha-logo-night\"></span> ";
    534 if ($difficulty === 1) {
    535 	$im = imagecreatetruecolor(55, 24);
    536 	$bg = imagecolorallocatealpha($im, 0, 0, 0, 127);
    537 	$fg = imagecolorallocate($im, 255, 255, 255);
    538 	imagefill($im, 0, 0, $bg);
    539 	imagestring($im, 5, 5, 5, $code, $fg);
    540 	imagesavealpha($im, true);
    541 	echo '<img class="captchalogincbox" width="55" height="24" src="data:image/gif;base64,';
    542 } elseif ($difficulty === 2) {
    543 	$im = imagecreatetruecolor(55, 24);
    544 	$bg = imagecolorallocatealpha($im, 0, 0, 0, 0);
    545 	$fg = imagecolorallocate($im, 255, 255, 255);
    546 	imagefill($im, 0, 0, $bg);
    547 	imagestring($im, 5, 5, 5, $code, $fg);
    548 	$line = imagecolorallocate($im, 255, 255, 255);
    549 	for ($i = 0; $i < 2; ++$i) {
    550 		imageline($im, 0, mt_rand(0, 24), 55, mt_rand(0, 24), $line);
    551 	}
    552 	$dots = imagecolorallocate($im, 255, 255, 255);
    553 	for ($i = 0; $i < 100; ++$i) {
    554 		imagesetpixel($im, mt_rand(0, 55), mt_rand(0, 24), $dots);
    555 	}
    556 	echo '<img class="captchalogincbox" width="55" height="24" src="data:image/gif;base64,';
    557 } else {
    558 	$im = imagecreatetruecolor(150, 200);
    559 	$bg = imagecolorallocatealpha($im, 0, 0, 0, 0);
    560 	$fg = imagecolorallocate($im, 255, 255, 255);
    561 	imagefill($im, 0, 0, $bg);
    562 	$chars = [];
    563 	for ($i = 0; $i < 10; ++$i) {
    564 		$found = false;
    565 		while (!$found) {
    566 			$x = mt_rand(10, 140);
    567 			$y = mt_rand(10, 180);
    568 			$found = true;
    569 			foreach ($chars as $char) {
    570 				if ($char['x'] >= $x && ($char['x'] - $x) < 25) {
    571 					$found = false;
    572 				} elseif ($char['x'] < $x && ($x - $char['x']) < 25) {
    573 					$found = false;
    574 				}
    575 				if (!$found) {
    576 					if ($char['y'] >= $y && ($char['y'] - $y) < 25) {
    577 						break;
    578 					} elseif ($char['y'] < $y && ($y - $char['y']) < 25) {
    579 						break;
    580 					} else {
    581 						$found = true;
    582 					}
    583 				}
    584 			}
    585 		}
    586 		$chars[] = ['x', 'y'];
    587 		$chars[$i]['x'] = $x;
    588 		$chars[$i]['y'] = $y;
    589 		if ($i < 5) {
    590 			imagechar($im, 5, $chars[$i]['x'], $chars[$i]['y'], $captchachars[mt_rand(0, $length)], $fg);
    591 		} else {
    592 			imagechar($im, 5, $chars[$i]['x'], $chars[$i]['y'], $code[$i - 5], $fg);
    593 		}
    594 	}
    595 	$follow = imagecolorallocate($im, 200, 0, 0);
    596 	imagearc($im, $chars[5]['x'] + 4, $chars[5]['y'] + 8, 16, 16, 0, 360, $follow);
    597 	for ($i = 5; $i < 9; ++$i) {
    598 		imageline($im, $chars[$i]['x'] + 4, $chars[$i]['y'] + 8, $chars[$i + 1]['x'] + 4, $chars[$i + 1]['y'] + 8, $follow);
    599 	}
    600 	$line = imagecolorallocate($im, 255, 255, 255);
    601 	for ($i = 0; $i < 5; ++$i) {
    602 		imageline($im, 0, mt_rand(0, 200), 150, mt_rand(0, 200), $line);
    603 	}
    604 	$dots = imagecolorallocate($im, 255, 255, 255);
    605 	for ($i = 0; $i < 1000; ++$i) {
    606 		imagesetpixel($im, mt_rand(0, 150), mt_rand(0, 200), $dots);
    607 	}
    608 	echo '<img class="captchalogincbox" width="150" height="200" src="data:image/gif;base64,';
    609 }
    610 ob_start();
    611 imagegif($im);
    612 imagedestroy($im);
    613 echo base64_encode(ob_get_clean()) . '">';
    614 echo '</td><td>' . hidden('challenge', $randid) . '<input type="text" name="captcha" size="15" autocomplete="off"></td></tr>';
    615 }
    616 
    617 function send_setup($C)
    618 {
    619 global $I, $U;
    620 print_start('setup');
    621 echo "<h2>$I[setup]</h2>" . form('setup', 'save');
    622 if (!isset($_REQUEST['session'])) {
    623 	echo hidden('session', $U['session']);
    624 }
    625 echo '<table id="guestaccess">';
    626 thr();
    627 $ga = (int) get_setting('guestaccess');
    628 echo "<tr><td><table><tr><th>$I[guestacc]</th><td>";
    629 echo '<select name="guestaccess">';
    630 echo '<option value="1"';
    631 if ($ga === 1) {
    632 	echo ' selected';
    633 }
    634 echo ">$I[guestallow]</option>";
    635 echo '<option value="2"';
    636 if ($ga === 2) {
    637 	echo ' selected';
    638 }
    639 echo ">$I[guestwait]</option>";
    640 echo '<option value="3"';
    641 if ($ga === 3) {
    642 	echo ' selected';
    643 }
    644 echo ">$I[adminallow]</option>";
    645 echo '<option value="0"';
    646 if ($ga === 0) {
    647 	echo ' selected';
    648 }
    649 echo ">$I[guestdisallow]</option>";
    650 echo '<option value="4"';
    651 if ($ga === 4) {
    652 	echo ' selected';
    653 }
    654 echo ">$I[disablechat]</option>";
    655 echo '</select></td></tr></table></td></tr>';
    656 thr();
    657 $englobal = (int) get_setting('englobalpass');
    658 echo "<tr><td><table id=\"globalpass\"><tr><th>$I[globalloginpass]</th><td>";
    659 echo '<table>';
    660 echo '<tr><td><select name="englobalpass">';
    661 echo '<option value="0"';
    662 if ($englobal === 0) {
    663 	echo ' selected';
    664 }
    665 echo ">$I[disabled]</option>";
    666 echo '<option value="1"';
    667 if ($englobal === 1) {
    668 	echo ' selected';
    669 }
    670 echo ">$I[enabled]</option>";
    671 echo '<option value="2"';
    672 if ($englobal === 2) {
    673 	echo ' selected';
    674 }
    675 echo ">$I[onlyguests]</option>";
    676 echo '</select></td><td>&nbsp;</td>';
    677 echo '<td><input type="text" name="globalpass" value="' . htmlspecialchars(get_setting('globalpass')) . '"></td></tr>';
    678 echo '</table></td></tr></table></td></tr>';
    679 thr();
    680 $ga = (int) get_setting('guestreg');
    681 echo "<tr><td><table id=\"guestreg\"><tr><th>$I[guestreg]</th><td>";
    682 echo '<select name="guestreg">';
    683 echo '<option value="0"';
    684 if ($ga === 0) {
    685 	echo ' selected';
    686 }
    687 echo ">$I[disabled]</option>";
    688 echo '<option value="1"';
    689 if ($ga === 1) {
    690 	echo ' selected';
    691 }
    692 echo ">$I[assuguest]</option>";
    693 echo '<option value="2"';
    694 if ($ga === 2) {
    695 	echo ' selected';
    696 }
    697 echo ">$I[asmember]</option>";
    698 echo '</select></td></tr></table></td></tr>';
    699 thr();
    700 echo "<tr><td><table id=\"sysmessages\"><tr><th>$I[sysmessages]</th><td>";
    701 echo '<table>';
    702 foreach ($C['msg_settings'] as $setting) {
    703 	echo "<tr><td>&nbsp;$I[$setting]</td><td>&nbsp;<input type=\"text\" name=\"$setting\" value=\"" . get_setting($setting) . '"></td></tr>';
    704 }
    705 echo '</table></td></tr></table></td></tr>';
    706 foreach ($C['text_settings'] as $setting) {
    707 	thr();
    708 	echo "<tr><td><table id=\"$setting\"><tr><th>" . $I[$setting] . '</th><td>';
    709 	echo "<input type=\"text\" name=\"$setting\" value=\"" . htmlspecialchars(get_setting($setting)) . '">';
    710 	echo '</td></tr></table></td></tr>';
    711 }
    712 foreach ($C['colour_settings'] as $setting) {
    713 	thr();
    714 	echo "<tr><td><table id=\"$setting\"><tr><th>" . $I[$setting] . '</th><td>';
    715 	echo "<input type=\"color\" name=\"$setting\" value=\"#" . htmlspecialchars(get_setting($setting)) . '">';
    716 	echo '</td></tr></table></td></tr>';
    717 }
    718 thr();
    719 echo "<tr><td><table id=\"captcha\"><tr><th>$I[captcha]</th><td>";
    720 echo '<table>';
    721 if (!extension_loaded('gd')) {
    722 	echo "<tr><td>$I[gdextrequired]</td></tr>";
    723 } else {
    724 	echo '<tr><td><select name="dismemcaptcha">';
    725 	$dismemcaptcha = (bool) get_setting('dismemcaptcha');
    726 	echo '<option value="0"';
    727 	if (!$dismemcaptcha) {
    728 		echo ' selected';
    729 	}
    730 	echo ">$I[enabled]</option>";
    731 	echo '<option value="1"';
    732 	if ($dismemcaptcha) {
    733 		echo ' selected';
    734 	}
    735 	echo ">$I[onlyguests]</option>";
    736 	echo '</select></td><td><select name="captcha">';
    737 	$captcha = (int) get_setting('captcha');
    738 	echo '<option value="0"';
    739 	if ($captcha === 0) {
    740 		echo ' selected';
    741 	}
    742 	echo ">$I[disabled]</option>";
    743 	echo '<option value="1"';
    744 	if ($captcha === 1) {
    745 		echo ' selected';
    746 	}
    747 	echo ">$I[simple]</option>";
    748 	echo '<option value="2"';
    749 	if ($captcha === 2) {
    750 		echo ' selected';
    751 	}
    752 	echo ">$I[moderate]</option>";
    753 	echo '<option value="3"';
    754 	if ($captcha === 3) {
    755 		echo ' selected';
    756 	}
    757 	echo ">$I[extreme]</option>";
    758 	echo '</select></td></tr>';
    759 }
    760 echo '</table></td></tr></table></td></tr>';
    761 thr();
    762 echo "<tr><td><table id=\"defaulttz\"><tr><th>$I[defaulttz]</th><td>";
    763 echo "<select name=\"defaulttz\">";
    764 $tzs = timezone_identifiers_list();
    765 $defaulttz = get_setting('defaulttz');
    766 foreach ($tzs as $tz) {
    767 	echo "<option value=\"$tz\"";
    768 	if ($defaulttz == $tz) {
    769 		echo ' selected';
    770 	}
    771 	echo ">$tz</option>";
    772 }
    773 echo '</select>';
    774 echo '</td></tr></table></td></tr>';
    775 foreach ($C['textarea_settings'] as $setting) {
    776 	thr();
    777 	echo "<tr><td><table id=\"$setting\"><tr><th>" . $I[$setting] . '</th><td>';
    778 	echo "<textarea name=\"$setting\" rows=\"4\" cols=\"60\">" . htmlspecialchars(get_setting($setting)) . '</textarea>';
    779 	echo '</td></tr></table></td></tr>';
    780 }
    781 //MODIFICATION textarea to edit links page
    782 thr();
    783 echo "<tr><td><table id=\"links\"><tr><th>Links Page (html)</th><td>";
    784 echo "<textarea name=\"links\" rows=\"4\" cols=\"60\">" . htmlspecialchars(get_setting('links')) . '</textarea>';
    785 echo '</td></tr></table></td></tr>';
    786 //End of Modification
    787 
    788 //MODIFICATION frontpagetext: textarea to edit front page
    789 thr();
    790 echo "<tr><td><table id=\"frontpagetext\"><tr><th>Text on front page (html)</th><td>";
    791 echo "<textarea name=\"frontpagetext\" rows=\"4\" cols=\"60\">" . htmlspecialchars(get_setting('frontpagetext')) . '</textarea>';
    792 echo '</td></tr></table></td></tr>';
    793 //End of Modification
    794 
    795 foreach ($C['number_settings'] as $setting) {
    796 	thr();
    797 	echo "<tr><td><table id=\"$setting\"><tr><th>" . $I[$setting] . '</th><td>';
    798 	echo "<input type=\"number\" name=\"$setting\" value=\"" . htmlspecialchars(get_setting($setting)) . '">';
    799 	echo '</td></tr></table></td></tr>';
    800 }
    801 foreach ($C['bool_settings'] as $setting) {
    802 	thr();
    803 	echo "<tr><td><table id=\"$setting\"><tr><th>" . $I[$setting] . '</th><td>';
    804 	echo "<select name=\"$setting\">";
    805 	$value = (bool) get_setting($setting);
    806 	echo '<option value="0"';
    807 	if (!$value) {
    808 		echo ' selected';
    809 	}
    810 	echo ">$I[disabled]</option>";
    811 	echo '<option value="1"';
    812 	if ($value) {
    813 		echo ' selected';
    814 	}
    815 	echo ">$I[enabled]</option>";
    816 	echo '</select></td></tr>';
    817 	echo '</table></td></tr>';
    818 }
    819 //thr();
    820 
    821 //MODIFICATION to enable links page 
    822 thr();
    823 echo "<tr><td><table id=\"linksenabled\"><tr><th>Links Page</th><td>";
    824 echo "<select name=\"linksenabled\">";
    825 $value = (bool) get_setting('linksenabled');
    826 echo '<option value="0"';
    827 if (!$value) {
    828 	echo ' selected';
    829 }
    830 echo ">$I[disabled]</option>";
    831 echo '<option value="1"';
    832 if ($value) {
    833 	echo ' selected';
    834 }
    835 echo ">$I[enabled]</option>";
    836 echo '</select></td></tr>';
    837 echo '</table></td></tr>';
    838 thr();
    839 //End of Modification
    840 
    841 //MODIFICATION to enable DEL-Buttons for members (2 = always, 1 =  if no mod is present.)
    842 //thr();
    843 echo "<tr><td><table id=\"memdel\"><tr><th>Members can delete messages (DEL) and can kick</th><td>";
    844 echo "<select name=\"memdel\">";
    845 $value = (int) get_setting('memdel');
    846 echo '<option value="0"';
    847 if ($value == 0) {
    848 	echo ' selected';
    849 }
    850 echo ">$I[disabled]</option>";
    851 
    852 echo '<option value="1"';
    853 if ($value == 1) {
    854 	echo ' selected';
    855 }
    856 echo ">DEL-Buttons enabled, if no mod is present</option>";
    857 
    858 /*
    859 echo '</select></td></tr>';
    860    echo '</table></td></tr>';
    861    */
    862 
    863 echo '<option value="2"';
    864 if ($value == 2) {
    865 	echo ' selected';
    866 }
    867 echo ">$I[enabled]</option>";
    868 echo '</select></td></tr>';
    869 echo '</table></td></tr>';
    870 
    871 thr();
    872 //End of Modification
    873 
    874 //Modification gallery access
    875 echo "<tr><td><table id=\"galleryaccess\"><tr><th>Gallery access</th><td>";
    876 echo "<select name=\"galleryaccess\">";
    877 $value = (int) get_setting('galleryaccess');
    878 
    879 $options = array(1, 2, 3, 5, 6, 7, 10);
    880 
    881 foreach ($options as $option) {
    882 	echo "<option value=\"$option\"";
    883 
    884 	if ($value == $option) {
    885 		echo ' selected';
    886 	}
    887 
    888 	if ($option == 1) echo ">All</option>";
    889 	elseif ($option == 2) echo ">Registered guests</option>";
    890 	elseif ($option == 3) echo ">Members</option>";
    891 	elseif ($option == 5) echo ">Moderators</option>";
    892 	elseif ($option == 6) echo ">Super Moderators</option>";
    893 	elseif ($option == 7) echo ">Admins</option>";
    894 	elseif ($option == 10) echo ">Disabled</option>";
    895 }
    896 
    897 echo '</select></td></tr>';
    898 echo '</table></td></tr>';
    899 thr();
    900 //End of modification
    901 
    902 //Modification forum button visibility
    903 echo "<tr><td><table id=\"forumbtnaccess\"><tr><th>Forum Button visibility</th><td>";
    904 echo "<select name=\"forumbtnaccess\">";
    905 $value = (int) get_setting('forumbtnaccess');
    906 
    907 $options = array(1, 2, 3, 5, 6, 7, 10);
    908 
    909 foreach ($options as $option) {
    910 	echo "<option value=\"$option\"";
    911 
    912 	if ($value == $option) {
    913 		echo ' selected';
    914 	}
    915 
    916 	if ($option == 1) echo ">All</option>";
    917 	elseif ($option == 2) echo ">Registered guests</option>";
    918 	elseif ($option == 3) echo ">Members</option>";
    919 	elseif ($option == 5) echo ">Moderators</option>";
    920 	elseif ($option == 6) echo ">Super Moderators</option>";
    921 	elseif ($option == 7) echo ">Admins</option>";
    922 	elseif ($option == 10) echo ">Disabled</option>";
    923 }
    924 
    925 echo '</select></td></tr>';
    926 echo '</table></td></tr>';
    927 thr();
    928 //End of modification
    929 
    930 //Modification forum button link
    931 
    932 echo "<tr><td><table id=\"forumbtnlink\"><tr><th>Forum Button link</th><td>";
    933 echo "<input type=\"text\" name=\"forumbtnlink\" value=\"" . htmlspecialchars(get_setting('forumbtnlink')) . '">';
    934 echo '</td></tr></table></td></tr>';
    935 thr();
    936 //End of modification
    937 
    938 //MODIFICATION adminjoinleavemsg to not create a system message if an admins arrives or leaves the chat
    939 echo "<tr><td><table id=\"adminjoinleavemsg\"><tr><th>Show system message if an admin joined or left the chat</th><td>";
    940 echo "<select name=\"adminjoinleavemsg\">";
    941 $value = (bool) get_setting('adminjoinleavemsg');
    942 echo '<option value="0"';
    943 if (!$value) {
    944 	echo ' selected';
    945 }
    946 echo ">$I[disabled]</option>";
    947 echo '<option value="1"';
    948 if ($value) {
    949 	echo ' selected';
    950 }
    951 echo ">$I[enabled]</option>";
    952 echo '</select></td></tr>';
    953 echo '</table></td></tr>';
    954 thr();
    955 //End of Modification
    956 
    957 //MODIFICATION clickablenicknamesglobal to enable/disable clickablenicknames, e. g. in case of errors
    958 echo "<tr><td><table id=\"clickablenicknamesglobal\"><tr><th>Clickable nicknames</th><td>";
    959 echo "<select name=\"clickablenicknamesglobal\">";
    960 $value = (bool) get_setting('clickablenicknamesglobal');
    961 echo '<option value="0"';
    962 if (!$value) {
    963 	echo ' selected';
    964 }
    965 echo ">$I[disabled]</option>";
    966 echo '<option value="1"';
    967 if ($value) {
    968 	echo ' selected';
    969 }
    970 echo ">$I[enabled]</option>";
    971 echo '</select></td></tr>';
    972 echo '</table></td></tr>';
    973 thr();
    974 //End of Modification
    975 
    976 // Modification Spare Notes.
    977 // Spare Notes name
    978 echo '<tr><td><table id="sparenotesname"><tr><th>Spare Notes Name</th><td>';
    979 echo '<input type="text" name="sparenotesname" value="' . htmlspecialchars(get_setting('sparenotesname')) . '">';
    980 echo '</td></tr></table></td></tr>';
    981 thr();
    982 // Spare Notes Access
    983 echo "<tr><td><table id=\"sparenotesaccess\"><tr><th>Spare Notes Access</th><td>";
    984 echo "<select name=\"sparenotesaccess\">";
    985 $value = (int) get_setting('sparenotesaccess');
    986 
    987 $options = array(3, 5, 6, 7, 10);
    988 
    989 foreach ($options as $option) {
    990 	echo "<option value=\"$option\"";
    991 
    992 	if ($value == $option) {
    993 		echo ' selected';
    994 	}
    995 
    996 	if ($option == 3) echo ">Members</option>";
    997 	elseif ($option == 5) echo ">Moderators</option>";
    998 	elseif ($option == 6) echo ">Super Moderators</option>";
    999 	elseif ($option == 7) echo ">Admins</option>";
   1000 	elseif ($option == 10) echo ">Disabled</option>";
   1001 }
   1002 // End of Modification
   1003 echo '</select></td></tr>';
   1004 echo '</table></td></tr>';
   1005 thr();
   1006 
   1007 // Modificatin create chat rooms
   1008 echo "<tr><td><table id=\"roomcreateaccess\"><tr><th>Rooms can be created by:</th><td>";
   1009 echo "<select name=\"roomcreateaccess\">";
   1010 $value = (int) get_setting('roomcreateaccess');
   1011 
   1012 $options = array(5, 6, 7);
   1013 
   1014 foreach ($options as $option) {
   1015 	echo "<option value=\"$option\"";
   1016 
   1017 	if ($value == $option) {
   1018 		echo ' selected';
   1019 	}
   1020 
   1021 	if ($option == 5) echo ">Moderators</option>";
   1022 	elseif ($option == 6) echo ">Super Moderators</option>";
   1023 	elseif ($option == 7) echo ">Admins</option>";
   1024 }
   1025 echo '</select></td></tr>';
   1026 echo '</table></td></tr>';
   1027 thr();
   1028 echo "<tr><td><table id=\"roomexpire\"><tr><th>Room Timeout (minutes)</th><td>";
   1029 echo "<input type=\"number\" name=\"roomexpire\" value=\"" . get_setting('roomexpire') . '">';
   1030 echo '</td></tr></table></td></tr>';
   1031 thr();
   1032 
   1033 echo "<tr><td><table id=\"channelvisinroom\"><tr><th>Channels visible in all rooms</th><td>";
   1034 echo "<select name=\"channelvisinroom\">";
   1035 $value = (int) get_setting('channelvisinroom');
   1036 $options = array(2, 3, 5, 6, 7, 9);
   1037 
   1038 foreach ($options as $option) {
   1039 	echo "<option value=\"$option\"";
   1040 
   1041 	if ($value == $option) {
   1042 		echo ' selected';
   1043 	}
   1044 
   1045 	if ($option == 2) echo ">All Channels</option>";
   1046 	elseif ($option == 3) echo ">Member Channels</option>";
   1047 	elseif ($option == 5) echo ">Staff Channels</option>";
   1048 	elseif ($option == 6) echo ">SMod Channels</option>";
   1049 	elseif ($option == 7) echo ">Admin Channel</option>";
   1050 	elseif ($option == 9) echo ">No channels</option>";
   1051 }
   1052 echo '</select></td></tr>';
   1053 echo '</table></td></tr>';
   1054 thr();
   1055 // End of Modification
   1056 
   1057 
   1058 
   1059 
   1060 
   1061 /*****************************************
   1062  *SETTINGS ONLY FOR SUPER ADMIN ARE BELOW
   1063  ******************************************/
   1064 if ($U['status'] == 8) {
   1065 
   1066 	echo '<tr><td><table>';
   1067 	echo "<font color='red'>↓ Setting(s) below can only be viewed and edited by Super Admin  ↓</font>";
   1068 	echo '</td></tr></table>';
   1069 
   1070 	thr();
   1071 	//MODIFICATION modsdeladminmsg to allow mods deleting admin messages
   1072 	echo "<tr><td><table id=\"modsdeladminmsg\"><tr><th>Staff members can delete messages of higher ranked staff members</th><td>";
   1073 	echo "<select name=\"modsdeladminmsg\">";
   1074 	$value = (bool) get_setting('modsdeladminmsg');
   1075 	echo '<option value="0"';
   1076 	if (!$value) {
   1077 		echo ' selected';
   1078 	}
   1079 	echo ">$I[disabled]</option>";
   1080 	echo '<option value="1"';
   1081 	if ($value) {
   1082 		echo ' selected';
   1083 	}
   1084 	echo ">$I[enabled]</option>";
   1085 	echo '</select></td></tr>';
   1086 	echo '</table></td></tr>';
   1087 	thr();
   1088 	//End of Modification
   1089 
   1090 	//MODIFICATION incognitomode setting only for super admin.
   1091 	echo "<tr><td><table id=\"incognito\"><tr><th>" . $I['incognito'] . "</th><td>";
   1092 	echo "<select name=\"incognito\">";
   1093 	$value = (bool) get_setting('incognito');
   1094 	echo '<option value="0"';
   1095 	if (!$value) {
   1096 		echo ' selected';
   1097 	}
   1098 	echo ">$I[disabled]</option>";
   1099 	echo '<option value="1"';
   1100 	if ($value) {
   1101 		echo ' selected';
   1102 	}
   1103 	echo ">$I[enabled]</option>";
   1104 	echo '</select></td></tr>';
   1105 	echo '</table></td></tr>';
   1106 	thr();
   1107 	//End of Modification
   1108 
   1109 	echo '<tr><td><table>';
   1110 	echo "<font color='red'> ↑ Setting(s) above can only be viewed and edited by Super Admin ↑</font>";
   1111 	echo '</td></tr></table>';
   1112 	thr();
   1113 } //End if
   1114 
   1115 /*****************************************
   1116  *SETTINGS ONLY FOR SUPER ADMIN ARE ABOVE
   1117  ******************************************/
   1118 
   1119 echo '<tr><td>' . submit($I['apply']) . '</td></tr></table></form><br>';
   1120 if ($U['status'] == 8) {
   1121 	echo '<table id="actions"><tr><td>';
   1122 	echo form('setup', 'backup');
   1123 	if (!isset($_REQUEST['session'])) {
   1124 		echo hidden('session', $U['session']);
   1125 	}
   1126 	echo submit($I['backuprestore']) . '</form></td><td>';
   1127 	echo form('setup', 'destroy');
   1128 	if (!isset($_REQUEST['session'])) {
   1129 		echo hidden('session', $U['session']);
   1130 	}
   1131 	echo submit($I['destroy'], 'class="delbutton"') . '</form></td></tr></table><br>';
   1132 }
   1133 echo form_target('_parent', 'logout');
   1134 if (!isset($_REQUEST['session'])) {
   1135 	echo hidden('session', $U['session']);
   1136 }
   1137 echo submit($I['logout'], 'id="exitbutton"') . '</form>' . credit();
   1138 print_end();
   1139 }
   1140 
   1141 function restore_backup($C)
   1142 {
   1143 global $db, $memcached;
   1144 if (!extension_loaded('json')) {
   1145 	return;
   1146 }
   1147 $code = json_decode($_REQUEST['restore'], true);
   1148 if (isset($_REQUEST['settings'])) {
   1149 	foreach ($C['settings'] as $setting) {
   1150 		if (isset($code['settings'][$setting])) {
   1151 			update_setting($setting, $code['settings'][$setting]);
   1152 		}
   1153 	}
   1154 }
   1155 if (isset($_REQUEST['filter']) && (isset($code['filters']) || isset($code['linkfilters']))) {
   1156 	$db->exec('DELETE FROM ' . PREFIX . 'filter;');
   1157 	$db->exec('DELETE FROM ' . PREFIX . 'linkfilter;');
   1158 	$stmt = $db->prepare('INSERT INTO ' . PREFIX . 'filter (filtermatch, filterreplace, allowinpm, regex, kick, cs) VALUES (?, ?, ?, ?, ?, ?);');
   1159 	foreach ($code['filters'] as $filter) {
   1160 		if (!isset($filter['cs'])) {
   1161 			$filter['cs'] = 0;
   1162 		}
   1163 		$stmt->execute([$filter['match'], $filter['replace'], $filter['allowinpm'], $filter['regex'], $filter['kick'], $filter['cs']]);
   1164 	}
   1165 	$stmt = $db->prepare('INSERT INTO ' . PREFIX . 'linkfilter (filtermatch, filterreplace, regex) VALUES (?, ?, ?);');
   1166 	foreach ($code['linkfilters'] as $filter) {
   1167 		$stmt->execute([$filter['match'], $filter['replace'], $filter['regex']]);
   1168 	}
   1169 	if (MEMCACHED) {
   1170 		$memcached->delete(DBNAME . '-' . PREFIX . 'filter');
   1171 		$memcached->delete(DBNAME . '-' . PREFIX . 'linkfilter');
   1172 	}
   1173 }
   1174 if (isset($_REQUEST['members']) && isset($code['members'])) {
   1175 	$db->exec('DELETE FROM ' . PREFIX . 'inbox;');
   1176 	$db->exec('DELETE FROM ' . PREFIX . 'members;');
   1177 	$stmt = $db->prepare('INSERT INTO ' . PREFIX . 'members (nickname, passhash, status, refresh, bgcolour, regedby, lastlogin, timestamps, embed, incognito, style, nocache, tz, eninbox, sortupdown, hidechatters, nocache_old) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);');
   1178 	foreach ($code['members'] as $member) {
   1179 		$new_settings = ['nocache', 'tz', 'eninbox', 'sortupdown', 'hidechatters', 'nocache_old'];
   1180 		foreach ($new_settings as $setting) {
   1181 			if (!isset($member[$setting])) {
   1182 				$member[$setting] = 0;
   1183 			}
   1184 		}
   1185 		$stmt->execute([$member['nickname'], $member['passhash'], $member['status'], $member['refresh'], $member['bgcolour'], $member['regedby'], $member['lastlogin'], $member['timestamps'], $member['embed'], $member['incognito'], $member['style'], $member['nocache'], $member['tz'], $member['eninbox'], $member['sortupdown'], $member['hidechatters'], $member['nocache_old']]);
   1186 	}
   1187 }
   1188 if (isset($_REQUEST['notes']) && isset($code['notes'])) {
   1189 	$db->exec('DELETE FROM ' . PREFIX . 'notes;');
   1190 	$stmt = $db->prepare('INSERT INTO ' . PREFIX . 'notes (type, lastedited, editedby, text) VALUES (?, ?, ?, ?);');
   1191 	foreach ($code['notes'] as $note) {
   1192 		if ($note['type'] === 'admin') {
   1193 			$note['type'] = 0;
   1194 		} elseif ($note['type'] === 'staff') {
   1195 			$note['type'] = 1;
   1196 		}
   1197 		if (MSGENCRYPTED) {
   1198 			$note['text'] = base64_encode(sodium_crypto_aead_aes256gcm_encrypt($note['text'], '', AES_IV, ENCRYPTKEY));
   1199 		}
   1200 		$stmt->execute([$note['type'], $note['lastedited'], $note['editedby'], $note['text']]);
   1201 	}
   1202 }
   1203 }
   1204 
   1205 function send_backup($C)
   1206 {
   1207 global $I, $db;
   1208 $code = [];
   1209 if ($_REQUEST['do'] === 'backup') {
   1210 	if (isset($_REQUEST['settings'])) {
   1211 		foreach ($C['settings'] as $setting) {
   1212 			$code['settings'][$setting] = get_setting($setting);
   1213 		}
   1214 	}
   1215 	if (isset($_REQUEST['filter'])) {
   1216 		$result = $db->query('SELECT * FROM ' . PREFIX . 'filter;');
   1217 		while ($filter = $result->fetch(PDO::FETCH_ASSOC)) {
   1218 			$code['filters'][] = ['match' => $filter['filtermatch'], 'replace' => $filter['filterreplace'], 'allowinpm' => $filter['allowinpm'], 'regex' => $filter['regex'], 'kick' => $filter['kick'], 'cs' => $filter['cs']];
   1219 		}
   1220 		$result = $db->query('SELECT * FROM ' . PREFIX . 'linkfilter;');
   1221 		while ($filter = $result->fetch(PDO::FETCH_ASSOC)) {
   1222 			$code['linkfilters'][] = ['match' => $filter['filtermatch'], 'replace' => $filter['filterreplace'], 'regex' => $filter['regex']];
   1223 		}
   1224 	}
   1225 	if (isset($_REQUEST['members'])) {
   1226 		$result = $db->query('SELECT * FROM ' . PREFIX . 'members;');
   1227 		while ($member = $result->fetch(PDO::FETCH_ASSOC)) {
   1228 			$code['members'][] = $member;
   1229 		}
   1230 	}
   1231 	if (isset($_REQUEST['notes'])) {
   1232 		$result = $db->query('SELECT * FROM ' . PREFIX . "notes;");
   1233 		while ($note = $result->fetch(PDO::FETCH_ASSOC)) {
   1234 			if (MSGENCRYPTED) {
   1235 				$note['text'] = sodium_crypto_aead_aes256gcm_decrypt(base64_decode($note['text']), null, AES_IV, ENCRYPTKEY);
   1236 			}
   1237 			$code['notes'][] = $note;
   1238 		}
   1239 	}
   1240 }
   1241 if (isset($_REQUEST['settings'])) {
   1242 	$chksettings = ' checked';
   1243 } else {
   1244 	$chksettings = '';
   1245 }
   1246 if (isset($_REQUEST['filter'])) {
   1247 	$chkfilters = ' checked';
   1248 } else {
   1249 	$chkfilters = '';
   1250 }
   1251 if (isset($_REQUEST['members'])) {
   1252 	$chkmembers = ' checked';
   1253 } else {
   1254 	$chkmembers = '';
   1255 }
   1256 if (isset($_REQUEST['notes'])) {
   1257 	$chknotes = ' checked';
   1258 } else {
   1259 	$chknotes = '';
   1260 }
   1261 print_start('backup');
   1262 echo "<h2>$I[backuprestore]</h2><table>";
   1263 thr();
   1264 if (!extension_loaded('json')) {
   1265 	echo "<tr><td>$I[jsonextrequired]</td></tr>";
   1266 } else {
   1267 	echo '<tr><td>' . form('setup', 'backup');
   1268 	echo '<table id="backup"><tr><td id="backupcheck">';
   1269 	echo "<label><input type=\"checkbox\" name=\"settings\" id=\"backupsettings\" value=\"1\"$chksettings>$I[settings]</label>";
   1270 	echo "<label><input type=\"checkbox\" name=\"filter\" id=\"backupfilter\" value=\"1\"$chkfilters>$I[filter]</label>";
   1271 	echo "<label><input type=\"checkbox\" name=\"members\" id=\"backupmembers\" value=\"1\"$chkmembers>$I[members]</label>";
   1272 	echo "<label><input type=\"checkbox\" name=\"notes\" id=\"backupnotes\" value=\"1\"$chknotes>$I[notes]</label>";
   1273 	echo '</td><td id="backupsubmit">' . submit($I['backup']) . '</td></tr></table></form></td></tr>';
   1274 	thr();
   1275 	echo '<tr><td>' . form('setup', 'restore');
   1276 	echo '<table id="restore">';
   1277 	echo "<tr><td colspan=\"2\"><textarea name=\"restore\" rows=\"4\" cols=\"60\">" . htmlspecialchars(json_encode($code)) . '</textarea></td></tr>';
   1278 	echo "<tr><td id=\"restorecheck\"><label><input type=\"checkbox\" name=\"settings\" id=\"restoresettings\" value=\"1\"$chksettings>$I[settings]</label>";
   1279 	echo "<label><input type=\"checkbox\" name=\"filter\" id=\"restorefilter\" value=\"1\"$chkfilters>$I[filter]</label>";
   1280 	echo "<label><input type=\"checkbox\" name=\"members\" id=\"restoremembers\" value=\"1\"$chkmembers>$I[members]</label>";
   1281 	echo "<label><input type=\"checkbox\" name=\"notes\" id=\"restorenotes\" value=\"1\"$chknotes>$I[notes]</label>";
   1282 	echo '</td><td id="restoresubmit">' . submit($I['restore']) . '</td></tr></table>';
   1283 	echo '</form></td></tr>';
   1284 }
   1285 thr();
   1286 echo '<tr><td>' . form('setup') . submit($I['initgosetup'], 'class="backbutton"') . "</form></tr></td>";
   1287 echo '</table>';
   1288 print_end();
   1289 }
   1290 
   1291 function send_destroy_chat()
   1292 {
   1293 global $I;
   1294 print_start('destroy_chat');
   1295 echo "<table><tr><td colspan=\"2\">$I[confirm]</td></tr><tr><td>";
   1296 echo form_target('_parent', 'setup', 'destroy') . hidden('confirm', 'yes') . submit($I['yes'], 'class="delbutton"') . '</form></td><td>';
   1297 echo form('setup') . submit($I['no'], 'class="backbutton"') . '</form></td><tr></table>';
   1298 print_end();
   1299 }
   1300 
   1301 function send_delete_account()
   1302 {
   1303 global $I;
   1304 print_start('delete_account');
   1305 echo "<table><tr><td colspan=\"2\">$I[confirm]</td></tr><tr><td>";
   1306 echo form('profile', 'delete') . hidden('confirm', 'yes') . submit($I['yes'], 'class="delbutton"') . '</form></td><td>';
   1307 echo form('profile') . submit($I['no'], 'class="backbutton"') . '</form></td><tr></table>';
   1308 print_end();
   1309 }
   1310 
   1311 function send_init()
   1312 {
   1313 global $I, $L;
   1314 print_start('init');
   1315 echo "<h2>$I[init]</h2>";
   1316 echo form('init') . "<table><tr><td><h3>$I[sulogin]</h3><table>";
   1317 echo "<tr><td>$I[sunick]</td><td><input type=\"text\" name=\"sunick\" size=\"15\"></td></tr>";
   1318 echo "<tr><td>$I[supass]</td><td><input type=\"password\" name=\"supass\" size=\"15\"></td></tr>";
   1319 echo "<tr><td>$I[suconfirm]</td><td><input type=\"password\" name=\"supassc\" size=\"15\"></td></tr>";
   1320 echo '</table></td></tr><tr><td><br>' . submit($I['initbtn']) . '</td></tr></table></form>';
   1321 echo "<p id=\"changelang\">$I[changelang]";
   1322 foreach ($L as $lang => $name) {
   1323 	echo " <a href=\"?action=setup&amp;lang=$lang\">$name</a>";
   1324 }
   1325 echo '</p>' . credit();
   1326 print_end();
   1327 }
   1328 
   1329 function send_update($msg)
   1330 {
   1331 global $I;
   1332 print_start('update');
   1333 echo "<h2>$I[dbupdate]</h2><br>" . form('setup') . submit($I['initgosetup']) . "</form>$msg<br>" . credit();
   1334 print_end();
   1335 }
   1336 
   1337 function send_alogin()
   1338 {
   1339 global $I, $L;
   1340 print_start('alogin');
   1341 echo form('setup') . '<table>';
   1342 echo "<tr><td>$I[nick]</td><td><input type=\"text\" name=\"nick\" size=\"15\" autofocus></td></tr>";
   1343 echo "<tr><td>$I[pass]</td><td><input type=\"password\" name=\"pass\" size=\"15\"></td></tr>";
   1344 send_captcha();
   1345 echo '<tr><td colspan="2">' . submit($I['login']) . '</td></tr></table></form>';
   1346 echo "<p id=\"changelang\">$I[changelang]";
   1347 foreach ($L as $lang => $name) {
   1348 	echo " <a href=\"?action=setup&amp;lang=$lang\">$name</a>";
   1349 }
   1350 echo '</p>' . credit();
   1351 print_end();
   1352 }
   1353 
   1354 function send_admin($arg = '')
   1355 {
   1356 global $I, $U, $db;
   1357 $ga = (int) get_setting('guestaccess');
   1358 print_start('admin');
   1359 $chlist = "<select name=\"name[]\" size=\"5\" multiple><option value=\"\">$I[choose]</option>";
   1360 $chlist .= "<option value=\"s &amp;\">$I[allguests]</option>";
   1361 $users = [];
   1362 $stmt = $db->query('SELECT nickname, style, status FROM ' . PREFIX . 'sessions WHERE entry!=0 AND status>0 ORDER BY LOWER(nickname);');
   1363 while ($user = $stmt->fetch(PDO::FETCH_NUM)) {
   1364 	$users[] = [htmlspecialchars($user[0]), $user[1], $user[2]];
   1365 }
   1366 foreach ($users as $user) {
   1367 	if ($user[2] < $U['status']) {
   1368 		$chlist .= "<option value=\"$user[0]\" style=\"$user[1]\">$user[0]</option>";
   1369 	}
   1370 }
   1371 $chlist .= '</select>';
   1372 echo "<h2>$I[admfunc]</h2><i>$arg</i><table>";
   1373 if ($U['status'] >= 7) {
   1374 	thr();
   1375 	echo '<tr><td>' . form_target('view', 'setup') . submit($I['initgosetup']) . '</form></td></tr>';
   1376 }
   1377 thr();
   1378 echo "<tr><td><table id=\"clean\"><tr><th>$I[cleanmsgs]</th><td>";
   1379 echo form('admin', 'clean');
   1380 echo '<table><tr><td><label><input type="radio" name="what" id="room" value="chat">';
   1381 echo $I['chat'] . "</label></td><td>&nbsp;</td><td><label><input type=\"radio\" name=\"what\" id=\"choose\" value=\"room\" checked>";
   1382 echo $I['room'] . "</label></td><td>&nbsp;</td><td></tr><tr><td colspan=\"3\"><label><input type=\"radio\" name=\"what\" id=\"choose\" value=\"choose\" checked>";
   1383 echo $I['selection'] . "</label></td><td>&nbsp;</td></tr><tr><td colspan=\"3\"><label><input type=\"radio\" name=\"what\" id=\"nick\" value=\"nick\">";
   1384 echo $I['cleannick'] . "</label> <select name=\"nickname\" size=\"1\"><option value=\"\">$I[choose]</option>";
   1385 $stmt = $db->prepare('SELECT poster FROM ' . PREFIX . "messages WHERE delstatus<? AND poster!='' GROUP BY poster;");
   1386 $stmt->execute([$U['status']]);
   1387 while ($nick = $stmt->fetch(PDO::FETCH_NUM)) {
   1388 	echo '<option value="' . htmlspecialchars($nick[0]) . '">' . htmlspecialchars($nick[0]) . '</option>';
   1389 }
   1390 echo '</select></td><td>';
   1391 echo submit($I['clean'], 'class="delbutton"') . '</td></tr></table></form></td></tr></table></td></tr>';
   1392 thr();
   1393 echo '<tr><td><table id="kick"><tr><th>' . sprintf($I['kickchat'], get_setting('kickpenalty')) . '</th></tr><tr><td>';
   1394 echo form('admin', 'kick');
   1395 echo "<table><tr><td>$I[kickreason]</td><td><input type=\"text\" name=\"kickmessage\" size=\"30\"></td><td>&nbsp;</td></tr>";
   1396 echo "<tr><td><label><input type=\"checkbox\" name=\"what\" value=\"purge\" id=\"purge\">$I[kickpurge]</label></td><td>$chlist</td><td>";
   1397 echo submit($I['kick']) . '</td></tr></table></form></td></tr></table></td></tr>';
   1398 thr();
   1399 echo "<tr><td><table id=\"logout\"><tr><th>$I[logoutinact]</th><td>";
   1400 echo form('admin', 'logout');
   1401 echo "<table><tr><td>$chlist</td><td>";
   1402 echo submit($I['logout']) . '</td></tr></table></form></td></tr></table></td></tr>';
   1403 
   1404 //MODIFICATION 2019-09-06 last-login table (show when members logged in the last time.
   1405 $view_lastlogin = 'lastlogin';
   1406 if ($U['status'] >= 7) {
   1407 	thr();
   1408 	echo "<tr><td><table id=\"$view_lastlogin\"><tr><th>" . "Last logins" . '</th><td>';
   1409 	echo form('admin', $view_lastlogin);
   1410 	echo submit($I['view']) . '</form></td></tr></table></td></tr>';
   1411 }
   1412 //MODIFICATION 2019-08-28 one line replaced with 6 lines of code
   1413 //filter button and linkfilter button will only be shown to smod 'Jonie' (status = 6), admins and higher.
   1414 if (($U['status'] >= 7) || ($U['status'] >= 6 && $U['nickname'] == 'Jonie')) {
   1415 	$views = ['sessions', 'filter', 'linkfilter'];
   1416 } else {
   1417 	$views = ['sessions'];
   1418 }
   1419 
   1420 foreach ($views as $view) {
   1421 	thr();
   1422 	echo "<tr><td><table id=\"$view\"><tr><th>" . $I[$view] . '</th><td>';
   1423 	echo form('admin', $view);
   1424 	echo submit($I['view']) . '</form></td></tr></table></td></tr>';
   1425 }
   1426 thr();
   1427 //Modification chat rooms.
   1428 $roomcreateaccess = (int) get_setting('roomcreateaccess');
   1429 if ($U['status'] >= $roomcreateaccess) {
   1430 	echo "<tr><td><table id=\"chatrooms\"><tr><th>" . 'Chat Rooms</th><td>';
   1431 	echo form('admin', 'rooms');
   1432 	echo submit($I['view']) . '</form></td></tr></table></td></tr>';
   1433 	thr();
   1434 }
   1435 
   1436 //Modification "html topic" (Topic can only be set by admins)
   1437 if ($U['status'] >= 7) {
   1438 
   1439 	echo "<tr><td><table id=\"topic\"><tr><th>$I[topic]</th><td>";
   1440 	echo form('admin', 'topic');
   1441 	echo '<table><tr><td><input type="text" name="topic" size="20" value="' . htmlspecialchars(get_setting('topic')) . '"></td><td>';
   1442 	echo submit($I['change']) . '</td></tr></table></form></td></tr></table></td></tr>';
   1443 	thr();
   1444 }
   1445 
   1446 echo "<tr><td><table id=\"guestaccess\"><tr><th>$I[guestacc]</th><td>";
   1447 echo form('admin', 'guestaccess');
   1448 echo '<table>';
   1449 echo '<tr><td><select name="guestaccess">';
   1450 echo '<option value="1"';
   1451 if ($ga === 1) {
   1452 	echo ' selected';
   1453 }
   1454 echo ">$I[guestallow]</option>";
   1455 echo '<option value="2"';
   1456 if ($ga === 2) {
   1457 	echo ' selected';
   1458 }
   1459 echo ">$I[guestwait]</option>";
   1460 echo '<option value="3"';
   1461 if ($ga === 3) {
   1462 	echo ' selected';
   1463 }
   1464 echo ">$I[adminallow]</option>";
   1465 echo '<option value="0"';
   1466 if ($ga === 0) {
   1467 	echo ' selected';
   1468 }
   1469 echo ">$I[guestdisallow]</option>";
   1470 if ($ga === 4) {
   1471 	echo '<option value="4" selected';
   1472 	echo ">$I[disablechat]</option>";
   1473 }
   1474 echo '</select></td><td>' . submit($I['change']) . '</td></tr></table></form></td></tr></table></td></tr>';
   1475 thr();
   1476 if (get_setting('suguests')) {
   1477 	echo "<tr><td><table id=\"suguests\"><tr><th>$I[addsuguest]</th><td>";
   1478 	echo form('admin', 'superguest');
   1479 	echo "<table><tr><td><select name=\"name\" size=\"1\"><option value=\"\">$I[choose]</option>";
   1480 	foreach ($users as $user) {
   1481 		if ($user[2] == 1) {
   1482 			echo "<option value=\"$user[0]\" style=\"$user[1]\">$user[0]</option>";
   1483 		}
   1484 	}
   1485 	echo '</select></td><td>' . submit($I['register']) . '</td></tr></table></form></td></tr></table></td></tr>';
   1486 	thr();
   1487 }
   1488 if ($U['status'] >= 7) {
   1489 	echo "<tr><td><table id=\"status\"><tr><th>$I[admmembers]</th><td>";
   1490 	echo form('admin', 'status');
   1491 	echo "<table><td><select name=\"name\" size=\"1\"><option value=\"\">$I[choose]</option>";
   1492 	$members = [];
   1493 	$result = $db->query('SELECT nickname, style, status FROM ' . PREFIX . 'members ORDER BY LOWER(nickname);');
   1494 	while ($temp = $result->fetch(PDO::FETCH_NUM)) {
   1495 		$members[] = [htmlspecialchars($temp[0]), $temp[1], $temp[2]];
   1496 	}
   1497 	foreach ($members as $member) {
   1498 		echo "<option value=\"$member[0]\" style=\"$member[1]\">$member[0]";
   1499 		if ($member[2] == 0) {
   1500 			echo ' (!)';
   1501 		} elseif ($member[2] == 2) {
   1502 			echo ' (G)';
   1503 		} elseif ($member[2] == 3) {
   1504 		} elseif ($member[2] == 5) {
   1505 			echo ' (M)';
   1506 		} elseif ($member[2] == 6) {
   1507 			echo ' (SM)';
   1508 		} elseif ($member[2] == 7) {
   1509 			echo ' (A)';
   1510 		} else {
   1511 			echo ' (SA)';
   1512 		}
   1513 		echo '</option>';
   1514 	}
   1515 	echo "</select><select name=\"set\" size=\"1\"><option value=\"\">$I[choose]</option><option value=\"-\">$I[memdel]</option><option value=\"0\">$I[memdeny]</option>";
   1516 	if (get_setting('suguests')) {
   1517 		echo "<option value=\"2\">$I[memsuguest]</option>";
   1518 	}
   1519 	echo "<option value=\"3\">$I[memreg]</option>";
   1520 	echo "<option value=\"5\">$I[memmod]</option>";
   1521 	echo "<option value=\"6\">$I[memsumod]</option>";
   1522 	if ($U['status'] >= 8) {
   1523 		echo "<option value=\"7\">$I[memadm]</option>";
   1524 	}
   1525 	echo '</select></td><td>' . submit($I['change']) . '</td></tr></table></form></td></tr></table></td></tr>';
   1526 	thr();
   1527 	echo "<tr><td><table id=\"passreset\"><tr><th>$I[passreset]</th><td>";
   1528 	echo form('admin', 'passreset');
   1529 	echo "<table><td><select name=\"name\" size=\"1\"><option value=\"\">$I[choose]</option>";
   1530 	foreach ($members as $member) {
   1531 		echo "<option value=\"$member[0]\" style=\"$member[1]\">$member[0]</option>";
   1532 	}
   1533 	echo '</select></td><td><input type="password" name="pass"></td><td>' . submit($I['change']) . '</td></tr></table></form></td></tr></table></td></tr>';
   1534 	thr();
   1535 	echo "<tr><td><table id=\"register\"><tr><th>$I[regguest]</th><td>";
   1536 	echo form('admin', 'register');
   1537 	echo "<table><tr><td><select name=\"name\" size=\"1\"><option value=\"\">$I[choose]</option>";
   1538 	foreach ($users as $user) {
   1539 		if ($user[2] == 1) {
   1540 			echo "<option value=\"$user[0]\" style=\"$user[1]\">$user[0]</option>";
   1541 		}
   1542 	}
   1543 	echo '</select></td><td>' . submit($I['register']) . '</td></tr></table></form></td></tr></table></td></tr>';
   1544 	thr();
   1545 	////Modification Register new Applicant
   1546 	echo "<tr><td><table id=\"regnew\"><tr><th>" . (get_setting('suguests') ? "Register new Applicant" : $I['regmem']) . "</th></tr><tr><td>";
   1547 	echo form('admin', 'regnew');
   1548 	echo "<table><tr><td>$I[nick]</td><td>&nbsp;</td><td><input type=\"text\" name=\"name\" size=\"20\"></td><td>&nbsp;</td></tr>";
   1549 	echo "<tr><td>$I[pass]</td><td>&nbsp;</td><td><input type=\"password\" name=\"pass\" size=\"20\"></td><td>";
   1550 	echo submit($I['register']) . '</td></tr></table></form></td></tr></table></td></tr>';
   1551 	thr();
   1552 }
   1553 echo "</table><br>";
   1554 echo form('admin') . submit($I['reload']) . '</form>';
   1555 print_end();
   1556 }
   1557 
   1558 function send_sessions()
   1559 {
   1560 global $I, $U, $db;
   1561 $stmt = $db->prepare('SELECT nickname, style, lastpost, status, useragent, ip FROM ' . PREFIX . 'sessions WHERE entry!=0 AND (incognito=0 OR status<? OR nickname=?) ORDER BY status DESC, lastpost DESC;');
   1562 $stmt->execute([$U['status'], $U['nickname']]);
   1563 if (!$lines = $stmt->fetchAll(PDO::FETCH_ASSOC)) {
   1564 	$lines = [];
   1565 }
   1566 print_start('sessions');
   1567 echo "<h1>$I[sessact]</h1><table>";
   1568 echo "<tr><th>$I[sessnick]</th><th>$I[sesstimeout]</th><th>$I[sessua]</th>";
   1569 $trackip = (bool) get_setting('trackip');
   1570 $memexpire = (int) get_setting('memberexpire');
   1571 $guestexpire = (int) get_setting('guestexpire');
   1572 if ($trackip) echo "<th>$I[sesip]</th>";
   1573 echo "<th>$I[actions]</th></tr>";
   1574 foreach ($lines as $temp) {
   1575 	if ($temp['status'] == 0) {
   1576 		$s = ' (K)';
   1577 	} elseif ($temp['status'] <= 2) {
   1578 		$s = ' (G)';
   1579 	} elseif ($temp['status'] == 3) {
   1580 		$s = '';
   1581 	} elseif ($temp['status'] == 5) {
   1582 		$s = ' (M)';
   1583 	} elseif ($temp['status'] == 6) {
   1584 		$s = ' (SM)';
   1585 	} elseif ($temp['status'] == 7) {
   1586 		$s = ' (A)';
   1587 	} else {
   1588 		$s = ' (SA)';
   1589 	}
   1590 	echo '<tr><td class="nickname">' . style_this(htmlspecialchars($temp['nickname']) . $s, $temp['style']) . '</td><td class="timeout">';
   1591 	if ($temp['status'] > 2) {
   1592 		echo get_timeout($temp['lastpost'], $memexpire);
   1593 	} else {
   1594 		echo get_timeout($temp['lastpost'], $guestexpire);
   1595 	}
   1596 	echo '</td>';
   1597 	if ($U['status'] > $temp['status'] || $U['nickname'] === $temp['nickname']) {
   1598 		echo "<td class=\"ua\">$temp[useragent]</td>";
   1599 		if ($trackip) {
   1600 			echo "<td class=\"ip\">$temp[ip]</td>";
   1601 		}
   1602 		echo '<td class="action">';
   1603 		if ($temp['nickname'] !== $U['nickname']) {
   1604 			echo '<table><tr>';
   1605 			if ($temp['status'] != 0) {
   1606 				echo '<td>';
   1607 				echo form('admin', 'sessions');
   1608 				echo hidden('kick', '1') . hidden('nick', htmlspecialchars($temp['nickname'])) . submit($I['kick']) . '</form>';
   1609 				echo '</td>';
   1610 			}
   1611 			echo '<td>';
   1612 			echo form('admin', 'sessions');
   1613 			echo hidden('logout', '1') . hidden('nick', htmlspecialchars($temp['nickname'])) . submit($temp['status'] == 0 ? $I['unban'] : $I['logout']) . '</form>';
   1614 			echo '</td></tr></table>';
   1615 		} else {
   1616 			echo '-';
   1617 		}
   1618 		echo '</td></tr>';
   1619 	} else {
   1620 		echo '<td class="ua">-</td>';
   1621 		if ($trackip) {
   1622 			echo '<td class="ip">-</td>';
   1623 		}
   1624 		echo '<td class="action">-</td></tr>';
   1625 	}
   1626 }
   1627 echo "</table><br>";
   1628 echo form('admin', 'sessions') . submit($I['reload']) . '</form>';
   1629 print_end();
   1630 }
   1631 
   1632 //MODIFICATION 2019-09-06 Featrue: last login table. function send_lastlogin() added.
   1633 function send_lastlogin()
   1634 {
   1635 global $I, $U, $db;
   1636 
   1637 if ($U['status'] >= 7) {
   1638 	$stmt = $db->prepare('SELECT nickname, status, lastlogin, style FROM ' . PREFIX . 'members ORDER BY status DESC, lastlogin DESC');
   1639 	$stmt->execute();
   1640 
   1641 	if (!$lines = $stmt->fetchAll(PDO::FETCH_ASSOC)) {
   1642 		$lines = [];
   1643 	}
   1644 	print_start('lastlogin');
   1645 	echo "<h1>Last logins</h1><table id=table_lastlogins>";
   1646 
   1647 	echo "<tr><th>Nickname</th><th>Last login</th>";
   1648 
   1649 	foreach ($lines as $temp) {
   1650 
   1651 		if ($temp['status'] == 0) {
   1652 			$s = ' (K)';
   1653 		} elseif ($temp['status'] <= 2) {
   1654 			$s = ' (G)';
   1655 		} elseif ($temp['status'] == 3) {
   1656 			$s = '';
   1657 		} elseif ($temp['status'] == 5) {
   1658 			$s = ' (M)';
   1659 		} elseif ($temp['status'] == 6) {
   1660 			$s = ' (SM)';
   1661 		} elseif ($temp['status'] == 7) {
   1662 			$s = ' (A)';
   1663 		} else {
   1664 			$s = ' (SA)';
   1665 		}
   1666 
   1667 		echo '<tr><td class="nickname">' . style_this(htmlspecialchars($temp['nickname']) . $s, $temp['style'] . '</td>');
   1668 		if ($temp['lastlogin'] === '0') {
   1669 			echo '<td class="lastlogin">unknown</td>';
   1670 		} else {
   1671 			echo '<td class="lastlogin">' . date('l jS \of F Y h:i:s A', $temp['lastlogin']) . '</td>';
   1672 		}
   1673 	}
   1674 	echo "</table><br>";
   1675 	echo form('admin', 'lastlogin') . submit($I['reload']) . '</form>';
   1676 	print_end();
   1677 }
   1678 }
   1679 
   1680 function send_gallery($site = 1)
   1681 {
   1682 global $I, $U, $db;
   1683 
   1684 //gallery version v0.9.3
   1685 
   1686 $link = '';
   1687 $links = [];
   1688 $reallinks = [];
   1689 $tempmessage = '';
   1690 $gallery_reload_button = 0;
   1691 
   1692 //Use the following patterns, if "force redirection" is enabled in the chat setup.
   1693 //pattern to find the hyperlinks. you can add the allowed file extensions here.
   1694 $pattern = 'url=http.*\.(jpg|jpeg|png|gif|bmp)';
   1695 
   1696 //pattern to find just the url (within the hyperlinks). Finds http and https links.
   1697 $pattern2 = 'https?\%3A\%2F\%2F.*\.(jpg|jpeg|png|gif|bmp)';
   1698 
   1699 
   1700 $GalleryAdminStatus = '5';
   1701 
   1702 print_start('gallery');
   1703 echo "<h1>The 404 Gallery</h1>";
   1704 
   1705 if ($U['status'] < (int)get_setting('galleryaccess')) {
   1706 
   1707 	echo "You are not allowed to view the gallery";
   1708 }
   1709 
   1710 
   1711 if (!get_setting('forceredirect')) {
   1712 
   1713 	echo "Please enable \"force redirect\" in the chat setup. The gallery  won't work otherwise.";
   1714 } elseif ($U['status'] >= (int)get_setting('galleryaccess')) {
   1715 
   1716 
   1717 	// Modification chat rooms so that images in channels not visible to the chatter are not shown
   1718 	$stmt = $db->prepare('SELECT id, text FROM ' . PREFIX . 'messages WHERE poststatus<=? AND (roomid= ANY (SELECT id FROM ' . PREFIX . 'rooms WHERE access<=?) OR roomid IS NULL OR poststatus>1)  ORDER BY id DESC;');
   1719 	$stmt->execute([$U['status'], $U['status']]);
   1720 
   1721 
   1722 	//START OF LINKS DETECTION Here we start to detect the links in the messages 
   1723 	/*************************/
   1724 
   1725 	$matches =  [];
   1726 	$number_of_matches = 0;
   1727 
   1728 	while ($message = $stmt->fetch(PDO::FETCH_ASSOC)) {
   1729 
   1730 		prepare_message_print($message, true); //decrypt message if encrypted.
   1731 
   1732 		$tempmessage = $message['text'];
   1733 
   1734 
   1735 
   1736 		//Debug
   1737 		//echo "Debug. ".htmlspecialchars($message['text'])."<br><br>";
   1738 
   1739 		//Description: Finds all picture-hyperlinks wihtin one message 
   1740 		preg_match('/' . $pattern . '/i', $tempmessage, $matches);
   1741 		if (!empty($matches['0'])) {
   1742 
   1743 			$tempmatch = $matches['0'];;
   1744 
   1745 			//Description: Finds all urls within one message
   1746 			preg_match('/' . $pattern2 . '/i', $tempmatch, $matches);
   1747 			if (!empty($matches['0'])) {
   1748 				$link = $matches['0'];
   1749 			}
   1750 
   1751 
   1752 			$token = strtok($link, " ");
   1753 
   1754 			while ($token !== false) {
   1755 
   1756 				$links[] = $token;
   1757 				$token = strtok(" ");
   1758 			}
   1759 
   1760 			$number_of_matches++;
   1761 		}
   1762 	}
   1763 
   1764 	$arrlength = count($links);
   1765 	for ($x = 0; $x < $arrlength; $x++) {
   1766 		preg_match('/' . $pattern2 . '/i', $links[$x], $matches);
   1767 		if (!empty($matches['0'])) {
   1768 			$reallinks[] = $matches['0'];
   1769 		}
   1770 	}
   1771 
   1772 
   1773 	//END OF LINKS DETECTION. Now we can build the gallery with the detected links.
   1774 
   1775 
   1776 
   1777 	//START OF PRINTING GALLERY
   1778 	/**************************/
   1779 	$posts_per_site = 12; //default value is 12. Change this value to set the number of pictures per gallery site.
   1780 	$start = ($site - 1) * $posts_per_site;
   1781 
   1782 
   1783 	//Hyperlinks and embedded images
   1784 	//count number of links
   1785 	$number_of_links = count($reallinks);
   1786 
   1787 
   1788 	//PAGINATION CONTROLS TO NAVIGATRE THROUGH GALLERY
   1789 	//Calculate the number of sites
   1790 	$number_of_sites = ceil($number_of_links / floatval($posts_per_site));
   1791 
   1792 	//Print links to the different sites
   1793 	//---------------------------------------------
   1794 	echo "<p></p><div id='pagination_controls'>";
   1795 	echo "<table id='pagination_controls_table'><tr>";
   1796 	if (($site > 1) && ($site <= $number_of_sites)) {
   1797 		echo '<td>' . form('gallery', $site - 1) . submit('Previous') . '</form>&nbsp;&nbsp;&nbsp;&nbsp</td>';
   1798 	}
   1799 
   1800 	for ($a = 1; $a <= $number_of_sites; $a++) {
   1801 
   1802 		//If user is on _this_ site, do not print a link		
   1803 		if ($site == $a) {
   1804 			echo '<td>' . form('gallery', $a) . submit($a, "id='current_site_button'") . '</form>&nbsp;&nbsp</td>';
   1805 			$gallery_reload_button = $a;
   1806 		} else {
   1807 			//user is not on _this_ site, so print a link.
   1808 			echo '<td>' . form('gallery', $a) . submit(' ' . $a . ' ') . '</form>&nbsp;&nbsp</td>';
   1809 		}
   1810 	}
   1811 
   1812 	if (($site >= 1) && ($site < $number_of_sites)) {
   1813 		echo '<td>' . form('gallery', $site + 1) . submit('Next') . '</form>&nbsp;&nbsp;&nbsp;&nbsp</td>';
   1814 	}
   1815 	echo '</tr></table>';
   1816 	echo "</div>";
   1817 	//END OF PAGNINATION CONTROLS
   1818 
   1819 	echo "<div id='live_gallery_div'><table id='live_gallery_table' width='1000' cellpadding='10'><tbody><tr>";
   1820 	if (($start + $posts_per_site) < $number_of_links) {
   1821 
   1822 		$arrlength2 = $start + $posts_per_site;
   1823 	} else {
   1824 		$arrlength2 = $number_of_links;
   1825 	}
   1826 	$column_number = 0;
   1827 
   1828 
   1829 	for ($x = $start; $x < $arrlength2; $x++) {
   1830 
   1831 		$y = $x + 1;
   1832 
   1833 		echo "<td align='center'><a href='#imgdiv" . $y . "'><img id='img" . $y . "' class='img' src='" . urldecode($reallinks[$x]) . "' height='100'></a><br>";
   1834 
   1835 		//echo "<br>";
   1836 		$column_number++;
   1837 		if ($column_number === 6) { //default value is 6. change this value to show more pictures in one row
   1838 			echo "</tr><tr>";
   1839 			$column_number = 0;
   1840 		}
   1841 	}
   1842 
   1843 	echo "</tbody></table></div>";
   1844 
   1845 	//gallery reload button
   1846 	//debug
   1847 	//echo "gallery reload button value: ".$gallery_reload_button;
   1848 
   1849 	echo "<table id='gallery_navigation_table'><tr><td>";
   1850 	if ($gallery_reload_button >= 1) {
   1851 		echo "<br>" . form('gallery', $gallery_reload_button) . submit($I['reload']) . '</form>';
   1852 	} else {
   1853 		echo "<br>" . form('gallery') . submit($I['reload']) . '</form>';
   1854 	}
   1855 
   1856 	echo "</td><td>";
   1857 	echo form_target('view', 'view') . submit('Back to chat') . '</form>';
   1858 	echo "</td></tr></table>";
   1859 
   1860 
   1861 
   1862 
   1863 	echo "<br>";
   1864 	//the variables use here are define avove pagination controls  in the code. see above.
   1865 	//Print a div for each image. Each of them must be hided through css. A div that becomes target must be displayed (with css).
   1866 	for ($x = $start; $x < $arrlength2; $x++) {
   1867 
   1868 		$y = $x + 1;
   1869 		echo "<a href='#live_gallery_table'><div id='imgdiv" . $y . "' class='imgdiv'><img class='galleryimg' src='" . urldecode($reallinks[$x]) . "'></a><br>" . apply_linkfilter(create_hotlinks(urldecode($reallinks[$x]))) . "</div>";
   1870 	}
   1871 	//END OF PRINTING GALLERY
   1872 
   1873 }
   1874 print_end();
   1875 }
   1876 
   1877 //MODIFICATION links page
   1878 function send_links_page()
   1879 {
   1880 
   1881 global $I;
   1882 
   1883 if (get_setting('linksenabled') === '1') {
   1884 	$links = get_setting('links');
   1885 
   1886 	print_start('links');
   1887 	$links = get_setting('links');
   1888 	if (!empty($links)) {
   1889 		echo "<div id=\"links\"><h2>The Underground Links</h2><br>$links<br>" . form_target('view', 'view') . submit('Back to chat') . "</form></div>";
   1890 	}
   1891 } else {
   1892 	return;
   1893 }
   1894 }
   1895 
   1896 // Modification change chat rooms
   1897 function change_room()
   1898 {
   1899 global $U, $db;
   1900 if ($_REQUEST['room'] === '*') {
   1901 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'sessions SET roomid=NULL WHERE id=?;');
   1902 	$stmt->execute([$U['id']]);
   1903 } else {
   1904 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'sessions SET roomid=(SELECT id FROM ' . PREFIX . 'rooms WHERE id=? AND access<=?) WHERE id=?;');
   1905 	$stmt->execute([$_REQUEST['room'], $U['status'], $U['id']]);
   1906 }
   1907 // Set session flag to indicate room change for post box reload
   1908 $_SESSION['room_changed'] = true;
   1909 }
   1910 
   1911 // Modification select chat rooms
   1912 function print_rooms()
   1913 {
   1914 global $db, $U;
   1915 echo '<div id="roomblock">';
   1916 echo '<div class="room-header">';
   1917 echo '<span class="room-label">💬 Switch Room</span>';
   1918 echo '</div>';
   1919 echo '<div class="room-selector">';
   1920 echo form_target('view', 'view');
   1921 echo "<select name=\"room\" id=\"room\">";
   1922 echo '<option value="*">[Main Chat]</option>';
   1923 $stmt = $db->prepare('SELECT id, name FROM ' . PREFIX . 'rooms WHERE access<=? ORDER BY id ASC;');
   1924 $stmt->execute([$U['status']]);
   1925 if (!$rooms = $stmt->fetchAll(PDO::FETCH_ASSOC)) {
   1926 	$rooms = [];
   1927 }
   1928 foreach ($rooms as $room) {
   1929 	$stmt = $db->prepare('SELECT id FROM ' . PREFIX . 'sessions WHERE roomid=?;');
   1930 	$stmt->execute([$room['id']]);
   1931 	$num = count($stmt->fetchAll());
   1932 	echo "<option value=\"$room[id]\"";
   1933 	if ($U['roomid'] === $room['id']) {
   1934 		echo ' selected';
   1935 	}
   1936 	echo ">$room[name] ($num)</option>";
   1937 }
   1938 echo '</select>';
   1939 echo submit('Switch');
   1940 echo '</form>';
   1941 echo '</div>';
   1942 echo '</div>';
   1943 }
   1944 
   1945 // Modification rooms in admin page
   1946 function send_rooms($arg = '')
   1947 {
   1948 global $I, $U, $db;
   1949 print_start('linkfilter');
   1950 echo "<h2>Chat Rooms</h2><i>$arg</i><table>";
   1951 thr();
   1952 echo '<tr><th><table style="width:100%;"><tr>';
   1953 echo "<td style=\"width:8em;\">Room ID:</td>";
   1954 echo "<td style=\"width:12em;\">Name</td>";
   1955 echo "<td style=\"width:12em;\">Access</td>";
   1956 if ($U['status'] > 6) {
   1957 	echo "<td style=\"width:10em;\">Permanent</td>";
   1958 }
   1959 echo "<td style=\"width:5em;\">$I[apply]</td>";
   1960 echo "<td style=\"width:8em;\">Expires in</td>";
   1961 echo '</tr></table></th></tr>';
   1962 $stmt = $db->prepare('SELECT * FROM ' . PREFIX . 'rooms WHERE access<=? ORDER BY id ASC;');
   1963 $stmt->execute([$U['status']]);
   1964 if (!$rooms = $stmt->fetchAll(PDO::FETCH_ASSOC)) {
   1965 	$rooms = [];
   1966 }
   1967 foreach ($rooms as $room) {
   1968 	if ($room['permanent'] && $U['status'] <= 6) {
   1969 		continue;
   1970 	}
   1971 	if ($room['permanent']) {
   1972 		$checkedpm = ' checked';
   1973 	} else {
   1974 		$checkedpm = '';
   1975 	}
   1976 	echo '<tr><td>';
   1977 	echo form('admin', 'rooms') . hidden('id', $room['id']);
   1978 	echo "<table style=\"width:100%;\"><tr><th style=\"width:8em;\">Room $room[id]:</th>";
   1979 	echo "<td style=\"width:12em;\"><input type=\"text\" name=\"name\" value=\"$room[name]\" size=\"20\" style=\"$U[style]\"></td>";
   1980 	echo '<td style="width:12em;">';
   1981 	echo "<select name=\"access\">";
   1982 
   1983 	$options = array(1, 2, 3, 5, 6, 7, 8, 10);
   1984 
   1985 	foreach ($options as $option) {
   1986 		if ($U['status'] < $option) {
   1987 			break;
   1988 		}
   1989 		echo "<option value=\"$option\"";
   1990 
   1991 		if ($room['access'] == $option) {
   1992 			echo ' selected';
   1993 		}
   1994 
   1995 		if ($option == 1) echo ">All</option>";
   1996 		elseif ($option == 2) echo ">Registered guests</option>";
   1997 		elseif ($option == 3) echo ">Members</option>";
   1998 		elseif ($option == 5) echo ">Moderators</option>";
   1999 		elseif ($option == 6) echo ">Super Moderators</option>";
   2000 		elseif ($option == 7) echo ">Admins</option>";
   2001 		elseif ($option == 8) echo ">Super Admins</option>";
   2002 		elseif ($option == 10) echo ">Disabled</option>";
   2003 	}
   2004 
   2005 	echo '</select></td>';
   2006 	if ($U['status'] > 6) {
   2007 		echo "<td style=\"width:10em;\"><label><input type=\"checkbox\" name=\"permanent\" value=\"1\"$checkedpm>Permanent</label></td>";
   2008 	}
   2009 	echo '<td class="roomsubmit" style="width:5em;">' . submit($I['change']) . '</td>';
   2010 	$stmt = $db->prepare('SELECT null FROM ' . PREFIX . 'sessions WHERE roomid=?;');
   2011 	$stmt->execute([$room['id']]);
   2012 	if ($stmt->fetch(PDO::FETCH_NUM) || $room['permanent']) {
   2013 		echo "<th style=\"width:8em;\">--:--</th>";
   2014 	} else {
   2015 		$expire = (int) get_setting('roomexpire');
   2016 		echo "<th style=\"width:8em;\">" . get_timeout($room['time'], $expire) . '</th>';
   2017 	}
   2018 	echo "</tr></table></form></td></tr>";
   2019 }
   2020 echo '<tr><td>';
   2021 echo form('admin', 'rooms') . hidden('id', '+');
   2022 echo "<table style=\"width:100%;\"><tr><th style=\"width:8em;\">New Room</th>";
   2023 echo "<td style=\"width:12em;\"><input type=\"text\" name=\"name\" value=\"\" size=\"20\" style=\"$U[style]\"></td>";
   2024 echo '<td style="width:12em;">';
   2025 echo "<select name=\"access\">";
   2026 
   2027 $options = array(1, 2, 3, 5, 6, 7, 8, 10);
   2028 
   2029 foreach ($options as $option) {
   2030 	if ($U['status'] < $option) {
   2031 		break;
   2032 	}
   2033 	echo "<option value=\"$option\"";
   2034 
   2035 	if ($option == 1) echo ">All</option>";
   2036 	elseif ($option == 2) echo ">Registered guests</option>";
   2037 	elseif ($option == 3) echo ">Members</option>";
   2038 	elseif ($option == 5) echo ">Moderators</option>";
   2039 	elseif ($option == 6) echo ">Super Moderators</option>";
   2040 	elseif ($option == 7) echo ">Admins</option>";
   2041 	elseif ($option == 8) echo ">Super Admins</option>";
   2042 	elseif ($option == 10) echo ">Disabled</option>";
   2043 }
   2044 
   2045 echo '</select></td>';
   2046 if ($U['status'] > 6) {
   2047 	echo "<td style=\"width:10em;\"><label><input type=\"checkbox\" name=\"permanent\" value=\"1\">Permanent</label></td>";
   2048 }
   2049 echo '<td class="roomsubmit" style="width:5em;">' . submit($I['add']) . '</td>';
   2050 echo "<th style=\"width:8em;\"></th>";
   2051 echo "</tr></table></form></td></tr></table><br>";
   2052 echo form('admin', 'rooms') . submit($I['reload']) . '</form>';
   2053 print_end();
   2054 }
   2055 
   2056 //Forum Link was moved to the post box (function send_post)
   2057 /*
   2058 function send_to_forum(){
   2059 
   2060    echo "Add redirect to forum here";
   2061 
   2062 }
   2063 */
   2064 
   2065 // Modification chat rooms.
   2066 function manage_rooms()
   2067 {
   2068 global $U, $db;
   2069 if (!isset($_REQUEST['id']) || !isset($_REQUEST['access']) || !isset($_REQUEST['name']) || $U['status'] < $_REQUEST['access']) {
   2070 	return;
   2071 }
   2072 if (!preg_match('/^[A-Za-z0-9\-]{0,50}$/', $_REQUEST['name'])) {
   2073 	return "Invalid Name.";
   2074 }
   2075 if (isset($_REQUEST['permanent']) && $_REQUEST['permanent'] && $U['status'] > 6) {
   2076 	$permanent = 1;
   2077 } else {
   2078 	$permanent = 0;
   2079 }
   2080 if ($_REQUEST['id'] === '+' && $_REQUEST['name'] !== '') {
   2081 	$stmt = $db->prepare('SELECT null FROM ' . PREFIX . 'rooms WHERE name=?');
   2082 	$stmt->execute([$_REQUEST['name']]);
   2083 	if ($stmt->fetch(PDO::FETCH_NUM)) {
   2084 		return;
   2085 	}
   2086 	$stmt = $db->prepare('INSERT INTO ' . PREFIX . 'rooms (name, access, time, permanent) VALUES (?, ?, ?, ?);');
   2087 	$stmt->execute([$_REQUEST['name'], $_REQUEST['access'], time(), $permanent]);
   2088 } elseif ($_REQUEST['name'] !== '') {
   2089 	$stmt = $db->prepare('SELECT null FROM ' . PREFIX . 'rooms WHERE name=? AND id!=?;');
   2090 	$stmt->execute([$_REQUEST['name'], $_REQUEST['id']]);
   2091 	if ($stmt->fetch(PDO::FETCH_NUM)) {
   2092 		return;
   2093 	}
   2094 	if ($U['status'] < 7) {
   2095 		$stmt = $db->prepare('SELECT null FROM ' . PREFIX . 'rooms WHERE id=? AND permanent=1;');
   2096 		$stmt->execute([$_REQUEST['id']]);
   2097 		if ($stmt->fetch(PDO::FETCH_NUM)) {
   2098 			return;
   2099 		}
   2100 	}
   2101 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'rooms SET name=?, access=?, permanent=? WHERE id=? AND access<=?;');
   2102 	$stmt->execute([$_REQUEST['name'], $_REQUEST['access'], $permanent, $_REQUEST['id'], $U['status']]);
   2103 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'sessions SET roomid=NULL WHERE roomid=? AND status<?;');
   2104 	$stmt->execute([$_REQUEST['id'], $_REQUEST['access']]);
   2105 } else {
   2106 	remove_room(false, $_REQUEST['id'], $U['status']);
   2107 }
   2108 }
   2109 
   2110 function remove_room($all = false, $id = '', $status = 10)
   2111 {
   2112 global $db;
   2113 if ($all) {
   2114 	//placeholder
   2115 } else {
   2116 	$stmt = $db->prepare('SELECT id FROM ' . PREFIX . "rooms WHERE id=? AND access<=?;");
   2117 	$stmt->execute([$id, $status]);
   2118 	if ($room = $stmt->fetch(PDO::FETCH_ASSOC)) {
   2119 		$name = $stmt->fetch(PDO::FETCH_NUM);
   2120 		$stmt = $db->prepare('DELETE FROM ' . PREFIX . 'rooms WHERE id=?;');
   2121 		$stmt->execute([$room['id']]);
   2122 		$stmt = $db->prepare('DELETE FROM ' . PREFIX . 'messages WHERE roomid=?;');
   2123 		$stmt->execute([$room['id']]);
   2124 		$stmt = $db->prepare('UPDATE ' . PREFIX . 'sessions SET roomid=NULL WHERE roomid=?;');
   2125 		$stmt->execute([$room['id']]);
   2126 	}
   2127 }
   2128 }
   2129 
   2130 
   2131 function check_filter_match(&$reg)
   2132 {
   2133 global $I;
   2134 $_REQUEST['match'] = htmlspecialchars($_REQUEST['match']);
   2135 if (isset($_REQUEST['regex']) && $_REQUEST['regex'] == 1) {
   2136 	if (!valid_regex($_REQUEST['match'])) {
   2137 		return "$I[incorregex]<br>$I[prevmatch]: $_REQUEST[match]";
   2138 	}
   2139 	$reg = 1;
   2140 } else {
   2141 	$_REQUEST['match'] = preg_replace('/([^\w\d])/u', "\\\\$1", $_REQUEST['match']);
   2142 	$reg = 0;
   2143 }
   2144 if (mb_strlen($_REQUEST['match']) > 255) {
   2145 	return "$I[matchtoolong]<br>$I[prevmatch]: $_REQUEST[match]";
   2146 }
   2147 return false;
   2148 }
   2149 
   2150 function manage_filter()
   2151 {
   2152 global $db, $memcached;
   2153 if (isset($_REQUEST['id'])) {
   2154 	$reg = 0;
   2155 	if ($tmp = check_filter_match($reg)) {
   2156 		return $tmp;
   2157 	}
   2158 	if (isset($_REQUEST['allowinpm']) && $_REQUEST['allowinpm'] == 1) {
   2159 		$pm = 1;
   2160 	} else {
   2161 		$pm = 0;
   2162 	}
   2163 	if (isset($_REQUEST['kick']) && $_REQUEST['kick'] == 1) {
   2164 		$kick = 1;
   2165 	} else {
   2166 		$kick = 0;
   2167 	}
   2168 	if (isset($_REQUEST['cs']) && $_REQUEST['cs'] == 1) {
   2169 		$cs = 1;
   2170 	} else {
   2171 		$cs = 0;
   2172 	}
   2173 	if (preg_match('/^[0-9]+$/', $_REQUEST['id'])) {
   2174 		if (empty($_REQUEST['match'])) {
   2175 			$stmt = $db->prepare('DELETE FROM ' . PREFIX . 'filter WHERE id=?;');
   2176 			$stmt->execute([$_REQUEST['id']]);
   2177 		} else {
   2178 			$stmt = $db->prepare('UPDATE ' . PREFIX . 'filter SET filtermatch=?, filterreplace=?, allowinpm=?, regex=?, kick=?, cs=? WHERE id=?;');
   2179 			$stmt->execute([$_REQUEST['match'], $_REQUEST['replace'], $pm, $reg, $kick, $cs, $_REQUEST['id']]);
   2180 		}
   2181 	} elseif ($_REQUEST['id'] === '+') {
   2182 		$stmt = $db->prepare('INSERT INTO ' . PREFIX . 'filter (filtermatch, filterreplace, allowinpm, regex, kick, cs) VALUES (?, ?, ?, ?, ?, ?);');
   2183 		$stmt->execute([$_REQUEST['match'], $_REQUEST['replace'], $pm, $reg, $kick, $cs]);
   2184 	}
   2185 	if (MEMCACHED) {
   2186 		$memcached->delete(DBNAME . '-' . PREFIX . 'filter');
   2187 	}
   2188 }
   2189 }
   2190 
   2191 function manage_linkfilter()
   2192 {
   2193 global $db, $memcached;
   2194 if (isset($_REQUEST['id'])) {
   2195 	$reg = 0;
   2196 	if ($tmp = check_filter_match($reg)) {
   2197 		return $tmp;
   2198 	}
   2199 	if (preg_match('/^[0-9]+$/', $_REQUEST['id'])) {
   2200 		if (empty($_REQUEST['match'])) {
   2201 			$stmt = $db->prepare('DELETE FROM ' . PREFIX . 'linkfilter WHERE id=?;');
   2202 			$stmt->execute([$_REQUEST['id']]);
   2203 		} else {
   2204 			$stmt = $db->prepare('UPDATE ' . PREFIX . 'linkfilter SET filtermatch=?, filterreplace=?, regex=? WHERE id=?;');
   2205 			$stmt->execute([$_REQUEST['match'], $_REQUEST['replace'], $reg, $_REQUEST['id']]);
   2206 		}
   2207 	} elseif ($_REQUEST['id'] === '+') {
   2208 		$stmt = $db->prepare('INSERT INTO ' . PREFIX . 'linkfilter (filtermatch, filterreplace, regex) VALUES (?, ?, ?);');
   2209 		$stmt->execute([$_REQUEST['match'], $_REQUEST['replace'], $reg]);
   2210 	}
   2211 	if (MEMCACHED) {
   2212 		$memcached->delete(DBNAME . '-' . PREFIX . 'linkfilter');
   2213 	}
   2214 }
   2215 }
   2216 
   2217 function get_filters()
   2218 {
   2219 global $db, $memcached;
   2220 if (MEMCACHED) {
   2221 	$filters = $memcached->get(DBNAME . '-' . PREFIX . 'filter');
   2222 }
   2223 if (!MEMCACHED || $memcached->getResultCode() !== Memcached::RES_SUCCESS) {
   2224 	$filters = [];
   2225 	$result = $db->query('SELECT id, filtermatch, filterreplace, allowinpm, regex, kick, cs FROM ' . PREFIX . 'filter;');
   2226 	while ($filter = $result->fetch(PDO::FETCH_ASSOC)) {
   2227 		$filters[] = ['id' => $filter['id'], 'match' => $filter['filtermatch'], 'replace' => $filter['filterreplace'], 'allowinpm' => $filter['allowinpm'], 'regex' => $filter['regex'], 'kick' => $filter['kick'], 'cs' => $filter['cs']];
   2228 	}
   2229 	if (MEMCACHED) {
   2230 		$memcached->set(DBNAME . '-' . PREFIX . 'filter', $filters);
   2231 	}
   2232 }
   2233 return $filters;
   2234 }
   2235 
   2236 function get_linkfilters()
   2237 {
   2238 global $db, $memcached;
   2239 if (MEMCACHED) {
   2240 	$filters = $memcached->get(DBNAME . '-' . PREFIX . 'linkfilter');
   2241 }
   2242 if (!MEMCACHED || $memcached->getResultCode() !== Memcached::RES_SUCCESS) {
   2243 	$filters = [];
   2244 	$result = $db->query('SELECT id, filtermatch, filterreplace, regex FROM ' . PREFIX . 'linkfilter;');
   2245 	while ($filter = $result->fetch(PDO::FETCH_ASSOC)) {
   2246 		$filters[] = ['id' => $filter['id'], 'match' => $filter['filtermatch'], 'replace' => $filter['filterreplace'], 'regex' => $filter['regex']];
   2247 	}
   2248 	if (MEMCACHED) {
   2249 		$memcached->set(DBNAME . '-' . PREFIX . 'linkfilter', $filters);
   2250 	}
   2251 }
   2252 return $filters;
   2253 }
   2254 
   2255 function send_filter($arg = '')
   2256 {
   2257 global $I, $U;
   2258 print_start('filter');
   2259 echo "<h2>$I[filter]</h2><i>$arg</i><table>";
   2260 thr();
   2261 echo '<tr><th><table style="width:100%;"><tr>';
   2262 echo "<td style=\"width:8em;\">$I[fid]</td>";
   2263 echo "<td style=\"width:12em;\">$I[match]</td>";
   2264 echo "<td style=\"width:12em;\">$I[replace]</td>";
   2265 echo "<td style=\"width:9em;\">$I[allowpm]</td>";
   2266 echo "<td style=\"width:5em;\">$I[regex]</td>";
   2267 echo "<td style=\"width:5em;\">$I[kick]</td>";
   2268 echo "<td style=\"width:5em;\">$I[cs]</td>";
   2269 echo "<td style=\"width:5em;\">$I[apply]</td>";
   2270 echo '</tr></table></th></tr>';
   2271 $filters = get_filters();
   2272 foreach ($filters as $filter) {
   2273 	if ($filter['allowinpm'] == 1) {
   2274 		$check = ' checked';
   2275 	} else {
   2276 		$check = '';
   2277 	}
   2278 	if ($filter['regex'] == 1) {
   2279 		$checked = ' checked';
   2280 	} else {
   2281 		$checked = '';
   2282 		$filter['match'] = preg_replace('/(\\\\(.))/u', "$2", $filter['match']);
   2283 	}
   2284 	if ($filter['kick'] == 1) {
   2285 		$checkedk = ' checked';
   2286 	} else {
   2287 		$checkedk = '';
   2288 	}
   2289 	if ($filter['cs'] == 1) {
   2290 		$checkedcs = ' checked';
   2291 	} else {
   2292 		$checkedcs = '';
   2293 	}
   2294 	echo '<tr><td>';
   2295 	echo form('admin', 'filter') . hidden('id', $filter['id']);
   2296 	echo "<table style=\"width:100%;\"><tr><th style=\"width:8em;\">$I[filter] $filter[id]:</th>";
   2297 	echo "<td style=\"width:12em;\"><input type=\"text\" name=\"match\" value=\"$filter[match]\" size=\"20\" style=\"$U[style]\"></td>";
   2298 	echo '<td style="width:12em;"><input type="text" name="replace" value="' . htmlspecialchars($filter['replace']) . "\" size=\"20\" style=\"$U[style]\"></td>";
   2299 	echo "<td style=\"width:9em;\"><label><input type=\"checkbox\" name=\"allowinpm\" value=\"1\"$check>$I[allowpm]</label></td>";
   2300 	echo "<td style=\"width:5em;\"><label><input type=\"checkbox\" name=\"regex\" value=\"1\"$checked>$I[regex]</label></td>";
   2301 	echo "<td style=\"width:5em;\"><label><input type=\"checkbox\" name=\"kick\" value=\"1\"$checkedk>$I[kick]</label></td>";
   2302 	echo "<td style=\"width:5em;\"><label><input type=\"checkbox\" name=\"cs\" value=\"1\"$checkedcs>$I[cs]</label></td>";
   2303 	echo '<td class="filtersubmit" style="width:5em;">' . submit($I['change']) . '</td></tr></table></form></td></tr>';
   2304 }
   2305 echo '<tr><td>';
   2306 echo form('admin', 'filter') . hidden('id', '+');
   2307 echo "<table style=\"width:100%;\"><tr><th style=\"width:8em\">$I[newfilter]</th>";
   2308 echo "<td style=\"width:12em;\"><input type=\"text\" name=\"match\" value=\"\" size=\"20\" style=\"$U[style]\"></td>";
   2309 echo "<td style=\"width:12em;\"><input type=\"text\" name=\"replace\" value=\"\" size=\"20\" style=\"$U[style]\"></td>";
   2310 echo "<td style=\"width:9em;\"><label><input type=\"checkbox\" name=\"allowinpm\" id=\"allowinpm\" value=\"1\">$I[allowpm]</label></td>";
   2311 echo "<td style=\"width:5em;\"><label><input type=\"checkbox\" name=\"regex\" id=\"regex\" value=\"1\">$I[regex]</label></td>";
   2312 echo "<td style=\"width:5em;\"><label><input type=\"checkbox\" name=\"kick\" id=\"kick\" value=\"1\">$I[kick]</label></td>";
   2313 echo "<td style=\"width:5em;\"><label><input type=\"checkbox\" name=\"cs\" id=\"cs\" value=\"1\">$I[cs]</label></td>";
   2314 echo '<td class="filtersubmit" style="width:5em;">' . submit($I['add']) . '</td></tr></table></form></td></tr>';
   2315 echo "</table><br>";
   2316 echo form('admin', 'filter') . submit($I['reload']) . '</form>';
   2317 print_end();
   2318 }
   2319 
   2320 function send_linkfilter($arg = '')
   2321 {
   2322 global $I, $U;
   2323 print_start('linkfilter');
   2324 echo "<h2>$I[linkfilter]</h2><i>$arg</i><table>";
   2325 thr();
   2326 echo '<tr><th><table style="width:100%;"><tr>';
   2327 echo "<td style=\"width:8em;\">$I[fid]</td>";
   2328 echo "<td style=\"width:12em;\">$I[match]</td>";
   2329 echo "<td style=\"width:12em;\">$I[replace]</td>";
   2330 echo "<td style=\"width:5em;\">$I[regex]</td>";
   2331 echo "<td style=\"width:5em;\">$I[apply]</td>";
   2332 echo '</tr></table></th></tr>';
   2333 $filters = get_linkfilters();
   2334 foreach ($filters as $filter) {
   2335 	if ($filter['regex'] == 1) {
   2336 		$checked = ' checked';
   2337 	} else {
   2338 		$checked = '';
   2339 		$filter['match'] = preg_replace('/(\\\\(.))/u', "$2", $filter['match']);
   2340 	}
   2341 	echo '<tr><td>';
   2342 	echo form('admin', 'linkfilter') . hidden('id', $filter['id']);
   2343 	echo "<table style=\"width:100%;\"><tr><th style=\"width:8em;\">$I[filter] $filter[id]:</th>";
   2344 	echo "<td style=\"width:12em;\"><input type=\"text\" name=\"match\" value=\"$filter[match]\" size=\"20\" style=\"$U[style]\"></td>";
   2345 	echo '<td style="width:12em;"><input type="text" name="replace" value="' . htmlspecialchars($filter['replace']) . "\" size=\"20\" style=\"$U[style]\"></td>";
   2346 	echo "<td style=\"width:5em;\"><label><input type=\"checkbox\" name=\"regex\" value=\"1\"$checked>$I[regex]</label></td>";
   2347 	echo '<td class="filtersubmit" style="width:5em;">' . submit($I['change']) . '</td></tr></table></form></td></tr>';
   2348 }
   2349 echo '<tr><td>';
   2350 echo form('admin', 'linkfilter') . hidden('id', '+');
   2351 echo "<table style=\"width:100%;\"><tr><th style=\"width:8em;\">$I[newfilter]</th>";
   2352 echo "<td style=\"width:12em;\"><input type=\"text\" name=\"match\" value=\"\" size=\"20\" style=\"$U[style]\"></td>";
   2353 echo "<td style=\"width:12em;\"><input type=\"text\" name=\"replace\" value=\"\" size=\"20\" style=\"$U[style]\"></td>";
   2354 echo "<td style=\"width:5em;\"><label><input type=\"checkbox\" name=\"regex\" value=\"1\">$I[regex]</label></td>";
   2355 echo '<td class="filtersubmit" style="width:5em;">' . submit($I['add']) . '</td></tr></table></form></td></tr>';
   2356 echo "</table><br>";
   2357 echo form('admin', 'linkfilter') . submit($I['reload']) . '</form>';
   2358 print_end();
   2359 }
   2360 
   2361 function send_frameset()
   2362 {
   2363 global $I, $U, $db, $language;
   2364 echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd"><html><head>' . meta_html();
   2365 echo '<title>' . get_setting('chatname') . '</title>';
   2366 print_stylesheet();
   2367 echo '</head><body>';
   2368 if (isset($_REQUEST['sort'])) {
   2369 	if ($_REQUEST['sort'] == 1) {
   2370 		$U['sortupdown'] = 1;
   2371 		$tmp = $U['nocache'];
   2372 		$U['nocache'] = $U['nocache_old'];
   2373 		$U['nocache_old'] = $tmp;
   2374 	} else {
   2375 		$U['sortupdown'] = 0;
   2376 		$tmp = $U['nocache'];
   2377 		$U['nocache'] = $U['nocache_old'];
   2378 		$U['nocache_old'] = $tmp;
   2379 	}
   2380 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'sessions SET sortupdown=?, nocache=?, nocache_old=? WHERE nickname=?;');
   2381 	$stmt->execute([$U['sortupdown'], $U['nocache'], $U['nocache_old'], $U['nickname']]);
   2382 	if ($U['status'] > 1) {
   2383 		$stmt = $db->prepare('UPDATE ' . PREFIX . 'members SET sortupdown=?, nocache=?, nocache_old=? WHERE nickname=?;');
   2384 		$stmt->execute([$U['sortupdown'], $U['nocache'], $U['nocache_old'], $U['nickname']]);
   2385 	}
   2386 }
   2387 if (($U['status'] >= 5 || ($U['status'] > 2 && get_count_mods() == 0)) && get_setting('enfileupload') > 0 && get_setting('enfileupload') <= $U['status']) {
   2388 	$postheight = '120px';
   2389 } else {
   2390 	$postheight = '100px';
   2391 }
   2392 $bottom = '';
   2393 if (get_setting('enablegreeting')) {
   2394 	$action_mid = 'greeting';
   2395 } else {
   2396 	if ($U['sortupdown']) {
   2397 		$bottom = '#bottom';
   2398 	}
   2399 	$action_mid = 'view';
   2400 }
   2401 if ((!isset($_REQUEST['sort']) && !$U['sortupdown']) || (isset($_REQUEST['sort']) && $_REQUEST['sort'] == 0)) {
   2402 	$action_top = 'post';
   2403 	$action_bot = 'controls';
   2404 	$sort_bot = '&sort=1';
   2405 	$frameset_mid_style = "position:fixed;top:$postheight;bottom:45px;left:0;right:0;margin:0;padding:0;overflow:hidden;";
   2406 	$frameset_top_style = "position:fixed;top:0;left:0;right:0;height:$postheight;margin:0;padding:0;overflow:hidden;border-bottom: 1px solid;";
   2407 	$frameset_bot_style = "position:fixed;bottom:0;left:0;right:0;height:45px;margin:0;padding:0;overflow:hidden;border-top:1px solid;";
   2408 	$noscroll_bot = "scrolling=\"yes\" style=\"overflow-y:hidden !important;\"";
   2409 	$noscroll_top = "";
   2410 } else {
   2411 	$action_top = 'controls';
   2412 	$action_bot = 'post';
   2413 	$sort_bot = '';
   2414 	$frameset_mid_style = "position:fixed;top:45px;bottom:$postheight;left:0;right:0;margin:0;padding:0;overflow:hidden;";
   2415 	$frameset_top_style = "position:fixed;top:0;left:0;right:0;height:45px;margin:0;padding:0;overflow:hidden;border-bottom:1px solid;";
   2416 	$frameset_bot_style = "position:fixed;bottom:0;left:0;right:0;height:$postheight;margin:0;padding:0;overflow:hidden;border-top:1px solid;";
   2417 	$noscroll_top = "scrolling=\"yes\" style=\"overflow-y:hidden !important;\"";
   2418 	$noscroll_bot = "";
   2419 }
   2420 echo "<div id=\"frameset-mid\" style=\"$frameset_mid_style\"><iframe name=\"view\" src=\"?action=$action_mid&session=$U[session]&lang=$language$bottom\">" . noframe_html() . "</iframe></div>";
   2421 echo "<div id=\"frameset-top\" style=\"$frameset_top_style\"><iframe $noscroll_top name=\"$action_top\" src=\"?action=$action_top&session=$U[session]&lang=$language\">" . noframe_html() . "</iframe></div>";
   2422 echo "<div id=\"frameset-bot\" style=\"$frameset_bot_style\"><iframe $noscroll_bot name=\"$action_bot\" src=\"?action=$action_bot&session=$U[session]&lang=$language$sort_bot\">" . noframe_html() . "</iframe></div>";
   2423 echo '</body></html>';
   2424 exit;
   2425 }
   2426 
   2427 function rooms()
   2428 {
   2429 print_start('rooms');
   2430 // if(show_rooms()){
   2431 print_rooms();
   2432 //}
   2433 print_end();
   2434 }
   2435 
   2436 function show_rooms($true = "false")
   2437 {
   2438 $handle = curl_init();
   2439 curl_setopt_array($handle, array(
   2440 	CURLOPT_URL => $url,
   2441 	CURLOPT_RETURNTRANSFER => 0,
   2442 	CURLOPT_POST => true,
   2443 	CURLOPT_POSTFIELDS => $postData,
   2444 ));
   2445 curl_exec($handle);
   2446 if ($true) {
   2447 	return true;
   2448 } else {
   2449 	return false;
   2450 }
   2451 }
   2452 function noframe_html(): string
   2453 {
   2454 global $I;
   2455 return "$I[noframes]" . form_target('_parent', '') . submit($I['backtologin'], 'class="backbutton"') . '</form>';
   2456 }
   2457 
   2458 function send_messages()
   2459 {
   2460 global $I, $U, $language;
   2461 if ($U['nocache']) {
   2462 	$nocache = '&nc=' . substr(time(), -6);
   2463 } else {
   2464 	$nocache = '';
   2465 }
   2466 if ($U['sortupdown']) {
   2467 	$sort = '#bottom';
   2468 } else {
   2469 	$sort = '';
   2470 }
   2471 $modroom = "";
   2472 if (isset($_REQUEST['modroom']) && $_REQUEST['modroom']) {
   2473 	$modroom = '&modroom=1';
   2474 }
   2475 print_start('messages', $U['refresh'], "?action=view&session=$U[session]&lang=$language$nocache$sort$modroom" . uniqid('?r='));
   2476 echo '<a id="top"></a>';
   2477 echo "<a id=\"bottom_link\" href=\"#bottom\">$I[bottom]</a>";
   2478 //MODIFICATION We don't like the manual refresh box.
   2479 //echo "<div id=\"manualrefresh\"><br>$I[manualrefresh]<br>".form('view').submit($I['reload']).'</form><br></div>';
   2480 //Modification for mod room for rooms
   2481 /*if(isset($_REQUEST['modroom']) && $_REQUEST['modroom']=1 && $U['status']>=5){
   2482 	echo '<div id="modroomreload">';
   2483 	echo form('view').hidden('modroom','1').submit($I['reload']).'</form>';
   2484 	echo '</div>';
   2485 	print_messages(0,1);
   2486 	
   2487 }else{*/
   2488 if (!$U['sortupdown']) {
   2489 	echo '<div id="topic">';
   2490 	echo get_setting('topic');
   2491 	echo '</div>';
   2492 	print_chatters();
   2493 	print_notifications();
   2494 	print_messages();
   2495 } else {
   2496 	print_messages();
   2497 	print_notifications();
   2498 	print_chatters();
   2499 	echo '<div id="topic">';
   2500 	echo get_setting('topic');
   2501 	echo '</div>';
   2502 }
   2503 //}
   2504 echo "<a id=\"bottom\"></a><a id=\"top_link\" href=\"#top\">$I[top]</a>";
   2505 print_end();
   2506 }
   2507 
   2508 function send_inbox()
   2509 {
   2510 global $I, $U, $db;
   2511 print_start('inbox');
   2512 echo form('inbox', 'clean') . submit($I['delselmes'], 'class="delbutton"') . '<br><br>';
   2513 $dateformat = get_setting('dateformat');
   2514 if (!$U['embed'] && get_setting('imgembed')) {
   2515 	$removeEmbed = true;
   2516 } else {
   2517 	$removeEmbed = false;
   2518 }
   2519 if ($U['timestamps'] && !empty($dateformat)) {
   2520 	$timestamps = true;
   2521 } else {
   2522 	$timestamps = false;
   2523 }
   2524 if ($U['sortupdown']) {
   2525 	$direction = 'ASC';
   2526 } else {
   2527 	$direction = 'DESC';
   2528 }
   2529 $stmt = $db->prepare('SELECT id, postdate, text FROM ' . PREFIX . "inbox WHERE recipient=? ORDER BY id $direction;");
   2530 $stmt->execute([$U['nickname']]);
   2531 while ($message = $stmt->fetch(PDO::FETCH_ASSOC)) {
   2532 	prepare_message_print($message, $removeEmbed);
   2533 	echo "<div class=\"msg\"><label><input type=\"checkbox\" name=\"mid[]\" value=\"$message[id]\">";
   2534 	if ($timestamps) {
   2535 		echo ' <small>' . date($dateformat, $message['postdate']) . ' - </small>';
   2536 	}
   2537 	echo " $message[text]</label></div>";
   2538 }
   2539 echo '</form><br>' . form('view') . submit($I['backtochat'], 'class="backbutton"') . '</form>';
   2540 print_end();
   2541 }
   2542 
   2543 // Modification type 3 is spare notes
   2544 
   2545 function send_notes($type)
   2546 {
   2547 global $I, $U, $db;
   2548 print_start('notes');
   2549 $personalnotes = (bool) get_setting('personalnotes');
   2550 $sparenotesaccess = (int) get_setting('sparenotesaccess');
   2551 // Modification Spare notes
   2552 if (($U['status'] >= 5 && ($personalnotes || $U['status'] > 6)) || ($personalnotes && $U['status'] >= $sparenotesaccess)) {
   2553 	echo '<table><tr>';
   2554 	if ($U['status'] > 6) {
   2555 		echo '<td>' . form_target('view', 'notes', 'admin') . submit($I['admnotes']) . '</form></td>';
   2556 	}
   2557 	if ($U['status'] >= 5) {
   2558 		echo '<td>' . form_target('view', 'notes', 'staff') . submit($I['staffnotes']) . '</form></td>';
   2559 	}
   2560 	if ($personalnotes) {
   2561 		echo '<td>' . form_target('view', 'notes') . submit($I['personalnotes']) . '</form></td>';
   2562 	}
   2563 	if ($U['status'] >= $sparenotesaccess) {
   2564 		echo '<td>' . form_target('view', 'notes', 'spare') . submit(get_setting('sparenotesname')) . '</form></td>';
   2565 	}
   2566 	echo '</tr></table>';
   2567 }
   2568 if ($type === 1) {
   2569 	echo "<h2>$I[staffnotes]</h2><p>";
   2570 	$hiddendo = hidden('do', 'staff');
   2571 } elseif ($type === 0) {
   2572 	echo "<h2>$I[adminnotes]</h2><p>";
   2573 	$hiddendo = hidden('do', 'admin');
   2574 	// Modification spare notes
   2575 } elseif ($type === 3) {
   2576 	echo '<h2>' . get_setting('sparenotesname') . '</h2><p>';
   2577 	$hiddendo = hidden('do', 'spare');
   2578 } else {
   2579 	echo "<h2>$I[personalnotes]</h2><p>";
   2580 	$hiddendo = '';
   2581 }
   2582 if (isset($_REQUEST['text'])) {
   2583 	if (MSGENCRYPTED) {
   2584 		$_REQUEST['text'] = base64_encode(sodium_crypto_aead_aes256gcm_encrypt($_REQUEST['text'], '', AES_IV, ENCRYPTKEY));
   2585 	}
   2586 	$time = time();
   2587 	$stmt = $db->prepare('INSERT INTO ' . PREFIX . 'notes (type, lastedited, editedby, text) VALUES (?, ?, ?, ?);');
   2588 	$stmt->execute([$type, $time, $U['nickname'], $_REQUEST['text']]);
   2589 	echo "<b>$I[notessaved]</b> ";
   2590 }
   2591 $dateformat = get_setting('dateformat');
   2592 if ($type !== 2) {
   2593 	$stmt = $db->prepare('SELECT COUNT(*) FROM ' . PREFIX . 'notes WHERE type=?;');
   2594 	$stmt->execute([$type]);
   2595 } else {
   2596 	$stmt = $db->prepare('SELECT COUNT(*) FROM ' . PREFIX . 'notes WHERE type=? AND editedby=?;');
   2597 	$stmt->execute([$type, $U['nickname']]);
   2598 }
   2599 $num = $stmt->fetch(PDO::FETCH_NUM);
   2600 if (!empty($_REQUEST['revision'])) {
   2601 	$revision = intval($_REQUEST['revision']);
   2602 } else {
   2603 	$revision = 0;
   2604 }
   2605 if ($type !== 2) {
   2606 	$stmt = $db->prepare('SELECT * FROM ' . PREFIX . "notes WHERE type=? ORDER BY id DESC LIMIT 1 OFFSET $revision;");
   2607 	$stmt->execute([$type]);
   2608 } else {
   2609 	$stmt = $db->prepare('SELECT * FROM ' . PREFIX . "notes WHERE type=? AND editedby=? ORDER BY id DESC LIMIT 1 OFFSET $revision;");
   2610 	$stmt->execute([$type, $U['nickname']]);
   2611 }
   2612 if ($note = $stmt->fetch(PDO::FETCH_ASSOC)) {
   2613 	printf($I['lastedited'], htmlspecialchars($note['editedby']), date($dateformat, $note['lastedited']));
   2614 } else {
   2615 	$note['text'] = '';
   2616 }
   2617 if (MSGENCRYPTED) {
   2618 	$note['text'] = sodium_crypto_aead_aes256gcm_decrypt(base64_decode($note['text']), null, AES_IV, ENCRYPTKEY);
   2619 }
   2620 echo "</p>" . form('notes');
   2621 echo "$hiddendo<textarea name=\"text\">" . htmlspecialchars($note['text']) . '</textarea><br>';
   2622 echo submit($I['savenotes']) . '</form><br>';
   2623 if ($num[0] > 1) {
   2624 	echo "<br><table><tr><td>$I[revisions]</td>";
   2625 	if ($revision < $num[0] - 1) {
   2626 		echo '<td>' . form('notes') . hidden('revision', $revision + 1);
   2627 		echo $hiddendo . submit($I['older']) . '</form></td>';
   2628 	}
   2629 	if ($revision > 0) {
   2630 		echo '<td>' . form('notes') . hidden('revision', $revision - 1);
   2631 		echo $hiddendo . submit($I['newer']) . '</form></td>';
   2632 	}
   2633 	echo '</tr></table>';
   2634 }
   2635 print_end();
   2636 }
   2637 
   2638 function send_approve_waiting()
   2639 {
   2640 global $I, $db;
   2641 print_start('approve_waiting');
   2642 echo "<h2>$I[waitingroom]</h2>";
   2643 $result = $db->query('SELECT * FROM ' . PREFIX . 'sessions WHERE entry=0 AND status=1 ORDER BY id LIMIT 100;');
   2644 if ($tmp = $result->fetchAll(PDO::FETCH_ASSOC)) {
   2645 	echo form('admin', 'approve');
   2646 	echo '<table>';
   2647 	echo "<tr><th>$I[sessnick]</th><th>$I[sessua]</th></tr>";
   2648 	foreach ($tmp as $temp) {
   2649 		echo '<tr>' . hidden('alls[]', htmlspecialchars($temp['nickname']));
   2650 		echo '<td><label><input type="checkbox" name="csid[]" value="' . htmlspecialchars($temp['nickname']) . '">';
   2651 		echo style_this(htmlspecialchars($temp['nickname']), $temp['style']) . '</label></td>';
   2652 		echo "<td>$temp[useragent]</td></tr>";
   2653 	}
   2654 	echo "</table><br><table id=\"action\"><tr><td><label><input type=\"radio\" name=\"what\" value=\"allowchecked\" id=\"allowchecked\" checked>$I[allowchecked]</label></td>";
   2655 	echo "<td><label><input type=\"radio\" name=\"what\" value=\"allowall\" id=\"allowall\">$I[allowall]</label></td>";
   2656 	echo "<td><label><input type=\"radio\" name=\"what\" value=\"denychecked\" id=\"denychecked\">$I[denychecked]</label></td>";
   2657 	echo "<td><label><input type=\"radio\" name=\"what\" value=\"denyall\" id=\"denyall\">$I[denyall]</label></td></tr><tr><td colspan=\"8\">$I[denymessage] <input type=\"text\" name=\"kickmessage\" size=\"45\"></td>";
   2658 	echo '</tr><tr><td colspan="8">' . submit($I['butallowdeny']) . '</td></tr></table></form>';
   2659 } else {
   2660 	echo "$I[waitempty]<br>";
   2661 }
   2662 echo '<br>' . form('admin', 'approve');
   2663 echo submit($I['reload']) . '</form>';
   2664 echo '<br>' . form('view') . submit($I['backtochat'], 'class="backbutton"') . '</form>';
   2665 print_end();
   2666 }
   2667 
   2668 function send_waiting_room()
   2669 {
   2670 global $I, $U, $db, $language;
   2671 $ga = (int) get_setting('guestaccess');
   2672 if ($ga === 3 && (get_count_mods() > 0 || !get_setting('modfallback'))) {
   2673 	$wait = false;
   2674 } else {
   2675 	$wait = true;
   2676 }
   2677 check_expired();
   2678 check_kicked();
   2679 $timeleft = get_setting('entrywait') - (time() - $U['lastpost']);
   2680 if ($wait && ($timeleft <= 0 || $ga === 1)) {
   2681 	$U['entry'] = $U['lastpost'];
   2682 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'sessions SET entry=lastpost WHERE session=?;');
   2683 	$stmt->execute([$U['session']]);
   2684 	send_frameset();
   2685 } elseif (!$wait && $U['entry'] != 0) {
   2686 	send_frameset();
   2687 } else {
   2688 	$refresh = (int) get_setting('defaultrefresh');
   2689 	print_start('waitingroom', $refresh, "?action=wait&session=$U[session]&lang=$language&nc=" . substr(time(), -6));
   2690 	echo "<h2>$I[waitingroom]</h2><p>";
   2691 	if ($wait) {
   2692 		printf($I['waittext'], style_this(htmlspecialchars($U['nickname']), $U['style']), $timeleft);
   2693 	} else {
   2694 		printf($I['admwaittext'], style_this(htmlspecialchars($U['nickname']), $U['style']));
   2695 	}
   2696 	echo '</p><br><p>';
   2697 	printf($I['waitreload'], $refresh);
   2698 	echo '</p><br><br>';
   2699 	echo '<hr>' . form('wait');
   2700 	if (!isset($_REQUEST['session'])) {
   2701 		echo hidden('session', $U['session']);
   2702 	}
   2703 	echo submit($I['reload']) . '</form><br>';
   2704 	echo form('logout');
   2705 	if (!isset($_REQUEST['session'])) {
   2706 		echo hidden('session', $U['session']);
   2707 	}
   2708 	echo submit($I['exit'], 'id="exitbutton"') . '</form>';
   2709 	$rulestxt = get_setting('rulestxt');
   2710 	if (!empty($rulestxt)) {
   2711 		echo "<div id=\"rules\"><h2>$I[rules]</h2><b>$rulestxt</b></div>";
   2712 	}
   2713 	print_end();
   2714 }
   2715 }
   2716 
   2717 function send_choose_messages()
   2718 {
   2719 global $I, $U;
   2720 print_start('choose_messages');
   2721 echo form('admin', 'clean');
   2722 echo hidden('what', 'selected') . submit($I['delselmes'], 'class="delbutton"') . '<br><br>';
   2723 print_messages($U['status']);
   2724 echo '<br>' . submit($I['delselmes'], 'class="delbutton"') . "</form>";
   2725 print_end();
   2726 }
   2727 
   2728 function send_del_confirm()
   2729 {
   2730 global $I;
   2731 print_start('del_confirm');
   2732 echo "<table><tr><td colspan=\"2\">$I[confirm]</td></tr><tr><td>" . form('delete');
   2733 if (isset($_REQUEST['multi'])) {
   2734 	echo hidden('multi', 'on');
   2735 }
   2736 if (isset($_REQUEST['sendto'])) {
   2737 	echo hidden('sendto', $_REQUEST['sendto']);
   2738 }
   2739 echo hidden('confirm', 'yes') . hidden('what', $_REQUEST['what']) . submit($I['yes'], 'class="delbutton"') . '</form></td><td>' . form('post');
   2740 if (isset($_REQUEST['multi'])) {
   2741 	echo hidden('multi', 'on');
   2742 }
   2743 if (isset($_REQUEST['sendto'])) {
   2744 	echo hidden('sendto', $_REQUEST['sendto']);
   2745 }
   2746 echo submit($I['no'], 'class="backbutton"') . '</form></td><tr></table>';
   2747 print_end();
   2748 }
   2749 
   2750 
   2751 
   2752 function send_post($rejected = '')
   2753 {
   2754 global $I, $U, $db;
   2755 print_start('post');
   2756 
   2757 if (!isset($_REQUEST['sendto'])) {
   2758 	$_REQUEST['sendto'] = '';
   2759 }
   2760 echo '<table><tr><td>' . form('post');
   2761 echo hidden('postid', substr(time(), -6));
   2762 if (isset($_REQUEST['multi'])) {
   2763 	echo hidden('multi', 'on');
   2764 }
   2765 echo '<table><tr><td><table><tr id="firstline"><td>' . style_this(htmlspecialchars($U['nickname']), $U['style']) . '</td><td>:</td>';
   2766 if (isset($_REQUEST['multi'])) {
   2767 	echo "<td><textarea name=\"message\" rows=\"3\" cols=\"40\" style=\"$U[style]\" autofocus>$rejected</textarea></td>";
   2768 } else {
   2769 	//some lines changed for clickable nicknames that select username in the text box
   2770 	if (($rejected === '') && (!empty($_REQUEST['nickname']))) {
   2771 		echo "<td><input type=\"text\" name=\"message\" value=\"" . $_REQUEST['nickname'] . "\" size=\"40\" style=\"$U[style]\" autofocus></td>";
   2772 	} else {
   2773 		echo "<td><input type=\"text\" name=\"message\" value=\"$rejected\" size=\"40\" style=\"$U[style]\" autofocus></td>";
   2774 	}
   2775 }
   2776 echo '<td>' . submit($I['talkto']) . '</td><td><select name="sendto" size="1">';
   2777 echo '<option ';
   2778 if ($_REQUEST['sendto'] === 's 17') {
   2779 	echo 'selected ';
   2780 }
   2781 
   2782 echo "value=\"s 17\">- All Chatters -</option>";
   2783 
   2784 //Modification added an option to send to all rooms.
   2785 if ($U['status'] >= 5) {
   2786 	echo '<option ';
   2787 	if ($_REQUEST['sendto'] === 'r @') {
   2788 		echo 'selected ';
   2789 	}
   2790 	echo "value=\"r @\">- All Rooms -</option>";
   2791 }
   2792 
   2793 //MODIFICATION 7 lines added for the RG channel (option to write to registered guests)
   2794 if ($U['status'] >= 2) {
   2795 	echo '<option ';
   2796 	if ($_REQUEST['sendto'] === 's 24') {
   2797 		echo 'selected ';
   2798 	}
   2799 	echo "value=\"s 24\">- Junior Members -</option>";
   2800 }
   2801 
   2802 if ($U['status'] >= 3) {
   2803 	echo '<option ';
   2804 	if ($_REQUEST['sendto'] === 's 31') {
   2805 		echo 'selected ';
   2806 	}
   2807 	echo "value=\"s 31\">- Senior Members -</option>";
   2808 }
   2809 if ($U['status'] >= 5) {
   2810 	echo '<option ';
   2811 	if ($_REQUEST['sendto'] === 's 48') {
   2812 		echo 'selected ';
   2813 	}
   2814 	echo "value=\"s 48\">- Staff -</option>";
   2815 }
   2816 //MODICATION description of item in dropdown menu changed to SMods only
   2817 if ($U['status'] >= 6) {
   2818 	echo '<option ';
   2819 	if ($_REQUEST['sendto'] === 's 56') {
   2820 		echo 'selected ';
   2821 	}
   2822 	echo "value=\"s 56\">- Admins -</option>";
   2823 }
   2824 
   2825 //MODIFICATION 7 lines added for the new admin channel (option to admins only)
   2826 if ($U['status'] >= 7) {
   2827 	echo '<option ';
   2828 	if ($_REQUEST['sendto'] === 's 65') {
   2829 		echo 'selected ';
   2830 	}
   2831 	echo "value=\"s 65\">- Gods -</option>";
   2832 }
   2833 $disablepm = (bool) get_setting('disablepm');
   2834 if (!$disablepm) {
   2835 	$users = [];
   2836 	$stmt = $db->prepare('SELECT * FROM (SELECT nickname, style, 0 AS offline FROM ' . PREFIX . 'sessions WHERE entry!=0 AND status>0 AND incognito=0 UNION SELECT nickname, style, 1 AS offline FROM ' . PREFIX . 'members WHERE eninbox!=0 AND eninbox<=? AND nickname NOT IN (SELECT nickname FROM ' . PREFIX . 'sessions WHERE incognito=0)) AS t WHERE nickname NOT IN (SELECT ign FROM ' . PREFIX . 'ignored WHERE ignby=? UNION SELECT ignby FROM ' . PREFIX . 'ignored WHERE ign=?) ORDER BY LOWER(nickname);');
   2837 	$stmt->execute([$U['status'], $U['nickname'], $U['nickname']]);
   2838 	while ($tmp = $stmt->fetch(PDO::FETCH_ASSOC)) {
   2839 		if ($tmp['offline']) {
   2840 			$users[] = ["$tmp[nickname] $I[offline]", $tmp['style'], $tmp['nickname']];
   2841 		} else {
   2842 			$users[] = [$tmp['nickname'], $tmp['style'], $tmp['nickname']];
   2843 		}
   2844 	}
   2845 	foreach ($users as $user) {
   2846 		if ($U['nickname'] !== $user[2]) {
   2847 			echo '<option ';
   2848 			if ($_REQUEST['sendto'] == $user[2]) {
   2849 				echo 'selected ';
   2850 			}
   2851 			echo 'value="' . htmlspecialchars($user[2]) . "\" style=\"$user[1]\">" . htmlspecialchars($user[0]) . '</option>';
   2852 		}
   2853 	}
   2854 }
   2855 echo '</select></td>';
   2856 if (get_setting('enfileupload') > 0 && get_setting('enfileupload') <= $U['status']) {
   2857 	if (!$disablepm && ($U['status'] >= 5 || ($U['status'] >= 3 && get_count_mods() == 0 && get_setting('memkick')))) {
   2858 		echo '</tr></table><table><tr id="secondline">';
   2859 	}
   2860 	printf("<td><input type=\"file\" name=\"file\"><small>$I[maxsize]</small></td>", get_setting('maxuploadsize'));
   2861 }
   2862 
   2863 //Modification to enable kick function, if memdel hast value 2
   2864 if (!$disablepm && ($U['status'] >= 5 || ($U['status'] >= 3 && get_count_mods() == 0 && get_setting('memkick')) || ($U['status'] >= 3  && (int)get_setting('memdel') === 2))) {
   2865 	echo "<td><label><input type=\"checkbox\" name=\"kick\" id=\"kick\" value=\"kick\">$I[kick]</label></td>";
   2866 	echo "<td><label><input type=\"checkbox\" name=\"what\" id=\"what\" value=\"purge\" checked>$I[alsopurge]</label></td>";
   2867 }
   2868 echo '</tr></table></td></tr></table></form></td></tr><tr><td><table><tr id="thirdline"><td>' . form('delete');
   2869 if (isset($_REQUEST['multi'])) {
   2870 	echo hidden('multi', 'on');
   2871 }
   2872 echo hidden('sendto', $_REQUEST['sendto']) . hidden('what', 'last');
   2873 echo submit($I['dellast'], 'class="delbutton"') . '</form></td><td>' . form('delete');
   2874 if (isset($_REQUEST['multi'])) {
   2875 	echo hidden('multi', 'on');
   2876 }
   2877 echo hidden('sendto', $_REQUEST['sendto']) . hidden('what', 'all');
   2878 echo submit($I['delall'], 'class="delbutton"') . '</form></td><td style="width:10px;"></td><td>' . form('post');
   2879 if (isset($_REQUEST['multi'])) {
   2880 	echo submit($I['switchsingle']);
   2881 } else {
   2882 	echo hidden('multi', 'on') . submit($I['switchmulti']);
   2883 }
   2884 echo hidden('sendto', $_REQUEST['sendto']) . '</form></td>';
   2885 echo '</tr></table></td></tr></table>';
   2886 
   2887 //External Links section start
   2888 //div left for links section
   2889 echo "<div align='left'>";
   2890 //one line added (emoji-link with id for css)
   2891 echo "<a id='emoji_link' target='view' rel='noopener noreferrer' href='emojis.html'>Emojis</a>";
   2892 echo "&nbsp";
   2893 
   2894 
   2895 //modification forum button 
   2896 if ($U['status'] >= (int)get_setting('forumbtnaccess')) {
   2897 	echo "<a id='forum_link' target='_blank' href='" . get_setting('forumbtnlink') . "'>Forum</a>";
   2898 }
   2899 echo "<div style=\"position: absolute; bottom: 10%; right: 4%; width: 220px; height: auto; overflow-y: hidden\">";
   2900 print_rooms();
   2901 echo "</div>";
   2902 //echo "</div>";
   2903 //External Links section end
   2904 
   2905 print_end();
   2906 }
   2907 
   2908 function send_greeting()
   2909 {
   2910 global $I, $U, $language;
   2911 print_start('greeting', $U['refresh'], "?action=view&session=$U[session]&lang=$language");
   2912 printf("<h1>$I[greetingmsg]</h1>", style_this(htmlspecialchars($U['nickname']), $U['style']));
   2913 printf("<hr><small>$I[entryhelp]</small>", $U['refresh']);
   2914 $rulestxt = get_setting('rulestxt');
   2915 if (!empty($rulestxt)) {
   2916 	echo "<hr><div id=\"rules\"><h2>$I[rules]</h2>$rulestxt</div>";
   2917 }
   2918 print_end();
   2919 }
   2920 
   2921 function send_help()
   2922 {
   2923 global $I, $U;
   2924 print_start('help');
   2925 $rulestxt = get_setting('rulestxt');
   2926 if (!empty($rulestxt)) {
   2927 	echo "<div id=\"rules\"><h2>$I[rules]</h2>$rulestxt<br></div><hr>";
   2928 }
   2929 echo "<h2>$I[help]</h2>$I[helpguest]";
   2930 if (get_setting('imgembed')) {
   2931 	echo "<br>$I[helpembed]";
   2932 }
   2933 if ($U['status'] >= 3) {
   2934 	echo "<br><br>$I[helpmem]<br><br>";
   2935 	if ($U['status'] >= 5) {
   2936 		echo "<br>$I[helpmod]<br><br>";
   2937 		if ($U['status'] >= 7) {
   2938 			echo "<br>$I[helpadm]<br><br>";
   2939 		}
   2940 	}
   2941 }
   2942 // MODIFICATION removed script version.
   2943 echo '<br><hr><div id="backcredit">' . form('view') . submit($I['backtochat'], 'class="backbutton"') . '</form>'/*.credit()*/ . '</div>';
   2944 print_end();
   2945 }
   2946 
   2947 function send_profile($arg = '')
   2948 {
   2949 global $I, $L, $U, $db, $language;
   2950 print_start('profile');
   2951 echo form('profile', 'save') . "<h2>$I[profile]</h2><i>$arg</i><table>";
   2952 thr();
   2953 $ignored = [];
   2954 $stmt = $db->prepare('SELECT ign FROM ' . PREFIX . 'ignored WHERE ignby=? ORDER BY LOWER(ign);');
   2955 $stmt->execute([$U['nickname']]);
   2956 while ($tmp = $stmt->fetch(PDO::FETCH_ASSOC)) {
   2957 	$ignored[] = htmlspecialchars($tmp['ign']);
   2958 }
   2959 if (count($ignored) > 0) {
   2960 	echo "<tr><td><table id=\"unignore\"><tr><th>$I[unignore]</th><td>";
   2961 	echo "<select name=\"unignore\" size=\"1\"><option value=\"\">$I[choose]</option>";
   2962 	foreach ($ignored as $ign) {
   2963 		echo "<option value=\"$ign\">$ign</option>";
   2964 	}
   2965 	echo '</select></td></tr></table></td></tr>';
   2966 	thr();
   2967 }
   2968 echo "<tr><td><table id=\"ignore\"><tr><th>$I[ignore]</th><td>";
   2969 echo "<select name=\"ignore\" size=\"1\"><option value=\"\">$I[choose]</option>";
   2970 $stmt = $db->prepare('SELECT poster, style FROM ' . PREFIX . 'messages INNER JOIN (SELECT nickname, style FROM ' . PREFIX . 'sessions UNION SELECT nickname, style FROM ' . PREFIX . 'members) AS t ON (' .  PREFIX . 'messages.poster=t.nickname) WHERE poster!=? AND poster NOT IN (SELECT ign FROM ' . PREFIX . 'ignored WHERE ignby=?) GROUP BY poster ORDER BY LOWER(poster);');
   2971 $stmt->execute([$U['nickname'], $U['nickname']]);
   2972 while ($nick = $stmt->fetch(PDO::FETCH_NUM)) {
   2973 	echo '<option value="' . htmlspecialchars($nick[0]) . "\" style=\"$nick[1]\">" . htmlspecialchars($nick[0]) . '</option>';
   2974 }
   2975 echo '</select></td></tr></table></td></tr>';
   2976 thr();
   2977 echo "<tr><td><table id=\"refresh\"><tr><th>$I[refreshrate]</th><td>";
   2978 echo "<input type=\"number\" name=\"refresh\" size=\"3\" maxlength=\"3\" min=\"5\" max=\"150\" value=\"$U[refresh]\"></td></tr></table></td></tr>";
   2979 thr();
   2980 preg_match('/#([0-9a-f]{6})/i', $U['style'], $matches);
   2981 echo "<tr><td><table id=\"colour\"><tr><th>$I[fontcolour] (<a href=\"?action=colours&amp;session=$U[session]&amp;lang=$language\" target=\"view\">$I[viewexample]</a>)</th><td>";
   2982 echo "<input type=\"color\" value=\"#$matches[1]\" name=\"colour\"></td></tr></table></td></tr>";
   2983 thr();
   2984 echo "<tr><td><table id=\"bgcolour\"><tr><th>$I[bgcolour] (<a href=\"?action=colours&amp;session=$U[session]&amp;lang=$language\" target=\"view\">$I[viewexample]</a>)</th><td>";
   2985 echo "<input type=\"color\" value=\"#$U[bgcolour]\" name=\"bgcolour\"></td></tr></table></td></tr>";
   2986 thr();
   2987 if ($U['status'] >= 3) {
   2988 	echo "<tr><td><table id=\"font\"><tr><th>$I[fontface]</th><td><table>";
   2989 	echo "<tr><td>&nbsp;</td><td><select name=\"font\" size=\"1\"><option value=\"\">* $I[roomdefault] *</option>";
   2990 	$F = load_fonts();
   2991 	foreach ($F as $name => $font) {
   2992 		echo "<option style=\"$font\" ";
   2993 		if (strpos($U['style'], $font) !== false) {
   2994 			echo 'selected ';
   2995 		}
   2996 		echo "value=\"$name\">$name</option>";
   2997 	}
   2998 	echo '</select></td><td>&nbsp;</td><td><label><input type="checkbox" name="bold" id="bold" value="on"';
   2999 	if (strpos($U['style'], 'font-weight:bold;') !== false) {
   3000 		echo ' checked';
   3001 	}
   3002 	echo "><b>$I[bold]</b></label></td><td>&nbsp;</td><td><label><input type=\"checkbox\" name=\"italic\" id=\"italic\" value=\"on\"";
   3003 	if (strpos($U['style'], 'font-style:italic;') !== false) {
   3004 		echo ' checked';
   3005 	}
   3006 	echo "><i>$I[italic]</i></label></td><td>&nbsp;</td><td><label><input type=\"checkbox\" name=\"small\" id=\"small\" value=\"on\"";
   3007 	if (strpos($U['style'], 'font-size:smaller;') !== false) {
   3008 		echo ' checked';
   3009 	}
   3010 	echo "><small>$I[small]</small></label></td></tr></table></td></tr></table></td></tr>";
   3011 	thr();
   3012 }
   3013 echo '<tr><td>' . style_this(htmlspecialchars($U['nickname']) . " : $I[fontexample]", $U['style']) . '</td></tr>';
   3014 thr();
   3015 $bool_settings = ['timestamps', 'nocache', 'sortupdown', 'hidechatters'];
   3016 if (get_setting('imgembed')) {
   3017 	$bool_settings[] = 'embed';
   3018 }
   3019 if ($U['status'] >= 5 && get_setting('incognito')) {
   3020 	$bool_settings[] = 'incognito';
   3021 }
   3022 foreach ($bool_settings as $setting) {
   3023 	echo "<tr><td><table id=\"$setting\"><tr><th>" . $I[$setting] . '</th><td>';
   3024 	echo "<label><input type=\"checkbox\" name=\"$setting\" value=\"on\"";
   3025 	if ($U[$setting]) {
   3026 		echo ' checked';
   3027 	}
   3028 	echo "><b>$I[enabled]</b></label></td></tr></table></td></tr>";
   3029 	thr();
   3030 }
   3031 if ($U['status'] >= 2 && get_setting('eninbox')) {
   3032 	echo "<tr><td><table id=\"eninbox\"><tr><th>$I[eninbox]</th><td>";
   3033 	echo "<select name=\"eninbox\" id=\"eninbox\">";
   3034 	echo '<option value="0"';
   3035 	if ($U['eninbox'] == 0) {
   3036 		echo ' selected';
   3037 	}
   3038 	echo ">$I[disabled]</option>";
   3039 	echo '<option value="1"';
   3040 	if ($U['eninbox'] == 1) {
   3041 		echo ' selected';
   3042 	}
   3043 	echo ">$I[eninall]</option>";
   3044 	echo '<option value="3"';
   3045 	if ($U['eninbox'] == 3) {
   3046 		echo ' selected';
   3047 	}
   3048 	echo ">$I[eninmem]</option>";
   3049 	echo '<option value="5"';
   3050 	if ($U['eninbox'] == 5) {
   3051 		echo ' selected';
   3052 	}
   3053 	echo ">$I[eninstaff]</option>";
   3054 	echo '</select></td></tr></table></td></tr>';
   3055 	thr();
   3056 }
   3057 echo "<tr><td><table id=\"tz\"><tr><th>$I[tz]</th><td>";
   3058 echo "<select name=\"tz\">";
   3059 $tzs = timezone_identifiers_list();
   3060 foreach ($tzs as $tz) {
   3061 	echo "<option value=\"$tz\"";
   3062 	if ($U['tz'] == $tz) {
   3063 		echo ' selected';
   3064 	}
   3065 	echo ">$tz</option>";
   3066 }
   3067 echo '</select></td></tr></table></td></tr>';
   3068 
   3069 //MODIFICATION nicklinks setting (setting for clickable nicknames in the message frame
   3070 //REMOVE LATER (Remove 18 LINES (Modification no longer needed)
   3071 /*
   3072    thr();
   3073 echo "<tr><td><table id=\"clickablenicknames\"><tr><th>Clickable nicknames</th><td>";
   3074 echo "<select name=\"clickablenicknames\">";
   3075 
   3076 
   3077 $options = array(0, 1, 2);
   3078 foreach($options as $option){
   3079 	echo "<option value=\"$option\"";
   3080 	
   3081 	if($U['clickablenicknames']==$option){
   3082 		echo ' selected';
   3083 	}
   3084 	
   3085 	if ($option == 0) echo ">Disabled</option>";
   3086 	elseif($option == 1) echo ">Select nickname from dropdown menu</option>";
   3087 	elseif($option == 2) echo ">Copy nickname to post box</option>";
   3088 }
   3089 echo '</select></td></tr></table></td></tr>';	
   3090 */
   3091 
   3092 thr();
   3093 if ($U['status'] >= 2) {
   3094 	echo "<tr><td><table id=\"changepass\"><tr><th>$I[changepass]</th></tr>";
   3095 	echo '<tr><td><table>';
   3096 	echo "<tr><td>&nbsp;</td><td>$I[oldpass]</td><td><input type=\"password\" name=\"oldpass\" size=\"20\"></td></tr>";
   3097 	echo "<tr><td>&nbsp;</td><td>$I[newpass]</td><td><input type=\"password\" name=\"newpass\" size=\"20\"></td></tr>";
   3098 	echo "<tr><td>&nbsp;</td><td>$I[confirmpass]</td><td><input type=\"password\" name=\"confirmpass\" size=\"20\"></td></tr>";
   3099 	echo '</table></td></tr></table></td></tr>';
   3100 	thr();
   3101 	echo "<tr><td><table id=\"changenick\"><tr><th>$I[changenick]</th><td><table>";
   3102 	echo "<tr><td>&nbsp;</td><td>$I[newnickname]</td><td><input type=\"text\" name=\"newnickname\" size=\"20\">";
   3103 	echo '</table></td></tr></table></td></tr>';
   3104 	thr();
   3105 }
   3106 echo '<tr><td>' . submit($I['savechanges']) . '</td></tr></table></form>';
   3107 if ($U['status'] > 1 && $U['status'] < 8) {
   3108 	echo '<br>' . form('profile', 'delete') . submit($I['deleteacc'], 'class="delbutton"') . '</form>';
   3109 }
   3110 echo "<br><p id=\"changelang\">$I[changelang]";
   3111 foreach ($L as $lang => $name) {
   3112 	echo " <a href=\"?lang=$lang&amp;session=$U[session]&amp;action=controls\" target=\"controls\">$name</a>";
   3113 }
   3114 echo '</p><br>' . form('view') . submit($I['backtochat'], 'class="backbutton"') . '</form>';
   3115 print_end();
   3116 }
   3117 
   3118 function send_controls()
   3119 {
   3120 global $I, $U;
   3121 print_start('controls');
   3122 $personalnotes = (bool) get_setting('personalnotes');
   3123 echo '<table><tr>';
   3124 echo '<td>' . form_target('post', 'post') . submit($I['reloadpb']) . '</form></td>';
   3125 echo '<td>' . form_target('view', 'view') . submit($I['reloadmsgs']) . '</form></td>';
   3126 echo '<td>' . form_target('view', 'profile') . submit($I['chgprofile']) . '</form></td>';
   3127 //MODIFICATION Links Page
   3128 if (get_setting('linksenabled') === '1') {
   3129 	echo '<td>' . form_target('view', 'links') . submit('Links') . '</form></td>';
   3130 }
   3131 
   3132 //Forum Button was moved to the postbox (function send_post) 
   3133 /*
   3134 if($U['status']>= (int)get_setting('forumbtnaccess')){
   3135         echo '<td>'.form_target('_blank', 'forum').submit('Forum').'</form></td>';
   3136 }
   3137 //ToDo handle forum request in function validate_input (redirect to forum page)
   3138 */
   3139 
   3140 //MODIFICATION for feature gallery
   3141 if ($U['status'] >= (int)get_setting('galleryaccess')) {
   3142 	echo '<td>' . form_target('view', 'gallery') . submit('Gallery') . '</form></td>';
   3143 }
   3144 
   3145 if ($U['status'] >= 5) {
   3146 	echo '<td>' . form_target('view', 'view') . hidden('modroom', '1') . submit('Mod Rooms') . '</form></td>';
   3147 }
   3148 
   3149 
   3150 if ($U['status'] >= 5) {
   3151 	echo '<td>' . form_target('view', 'admin') . submit($I['adminbtn']) . '</form></td>';
   3152 	//MODIFICATION for feature gallery. one line changed.
   3153 	//echo '<td>'.form_target('_blank', 'gallery').submit('Gallery').'</form></td>';
   3154 	if (!$personalnotes) {
   3155 		echo '<td>' . form_target('view', 'notes', 'staff') . submit($I['notes']) . '</form></td>';
   3156 	}
   3157 }
   3158 // Modification spare notes
   3159 $sparenotesaccess = (int) get_setting('sparenotesaccess');
   3160 if ($U['status'] >= 3) {
   3161 	if ($personalnotes) {
   3162 		echo '<td>' . form_target('view', 'notes') . submit($I['notes']) . '</form></td>';
   3163 	} elseif ($U['status'] >= $sparenotesaccess && $U['status'] === 3) {
   3164 		echo '<td>' . form_target('view', 'notes', 'spare') . submit($I['notes']) . '</form></td>';
   3165 	}
   3166 	echo '<td>' . form_target('_blank', 'login') . submit($I['clone']) . '</form></td>';
   3167 }
   3168 if (!isset($_REQUEST['sort'])) {
   3169 	$sort = 0;
   3170 } else {
   3171 	$sort = $_REQUEST['sort'];
   3172 }
   3173 echo '<td>' . form_target('_parent', 'login') . hidden('sort', $sort) . submit($I['sortframe']) . '</form></td>';
   3174 echo '<td>' . form_target('view', 'help') . submit($I['randh']) . '</form></td>';
   3175 echo '<td>' . form_target('_parent', 'logout') . submit($I['exit'], 'id="exitbutton"') . '</form></td>';
   3176 echo '</tr></table>';
   3177 print_end();
   3178 }
   3179 
   3180 function send_download()
   3181 {
   3182 global $I, $db;
   3183 if (isset($_REQUEST['id'])) {
   3184 	$stmt = $db->prepare('SELECT filename, type, data FROM ' . PREFIX . 'files WHERE hash=?;');
   3185 	$stmt->execute([$_REQUEST['id']]);
   3186 	if ($data = $stmt->fetch(PDO::FETCH_ASSOC)) {
   3187 		header("Content-Type: $data[type]");
   3188 		header("Content-Disposition: filename=\"$data[filename]\"");
   3189 		header('Pragma: no-cache');
   3190 		header('Cache-Control: no-cache, no-store, must-revalidate, max-age=0, private');
   3191 		header('Expires: 0');
   3192 		echo base64_decode($data['data']);
   3193 	} else {
   3194 		send_error($I['filenotfound']);
   3195 	}
   3196 } else {
   3197 	send_error($I['filenotfound']);
   3198 }
   3199 }
   3200 
   3201 function send_logout()
   3202 {
   3203 global $I, $U;
   3204 print_start('logout');
   3205 echo '<h1>' . sprintf($I['bye'], style_this(htmlspecialchars($U['nickname']), $U['style'])) . '</h1>' . form_target('_parent', '') . submit($I['backtologin'], 'class="backbutton"') . '</form>';
   3206 print_end();
   3207 }
   3208 
   3209 function send_colours()
   3210 {
   3211 global $I;
   3212 print_start('colours');
   3213 echo "<h2>$I[colourtable]</h2><kbd><b>";
   3214 for ($red = 0x00; $red <= 0xFF; $red += 0x33) {
   3215 	for ($green = 0x00; $green <= 0xFF; $green += 0x33) {
   3216 		for ($blue = 0x00; $blue <= 0xFF; $blue += 0x33) {
   3217 			$hcol = sprintf('%02X%02X%02X', $red, $green, $blue);
   3218 			echo "<span style=\"color:#$hcol\">$hcol</span> ";
   3219 		}
   3220 		echo '<br>';
   3221 	}
   3222 	echo '<br>';
   3223 }
   3224 echo '</b></kbd>' . form('profile') . submit($I['backtoprofile'], ' class="backbutton"') . '</form>';
   3225 print_end();
   3226 }
   3227 
   3228 function nav()
   3229 {
   3230 echo '
   3231 <div class="navbartitle"><a href="#" style="text-decoration: none; color: #fff;">404 Chatroom Not Found</a></div>
   3232 <nav class="topnav">
   3233 <ul class="topnav">
   3234 <li><a href="#ABOUT" target="_self">About</a></li>
   3235 <li><a href="https://github.com/d-a-s-h-o/universe" target="_blank">Source</a></li>
   3236 <li><a href="/" target="_blank">Homepage</a></li>
   3237 <a class="wgbtn" href="#logincbox">Login</a>
   3238 </ul> </nav>';
   3239 }
   3240 
   3241 function send_login()
   3242 {
   3243 global $I, $L;
   3244 $ga = (int) get_setting('guestaccess');
   3245 if ($ga === 4) {
   3246 	send_chat_disabled();
   3247 }
   3248 print_start('login');
   3249 nav();
   3250 $englobal = (int) get_setting('englobalpass');
   3251 //MODIFICATION frontpagetext
   3252 //Frontpage text added
   3253 /* $frontpagetext=get_setting('frontpagetext');
   3254 	if(!empty($frontpagetext)){
   3255 		echo "<span id=\"\">$frontpagetext</span>";
   3256 	} */
   3257 //MODIFICATION Javascript check.
   3258 //ToDo (Maybe later)
   3259 
   3260 //MODIFICATION Topic on Frontpage disabled
   3261 //echo '<h1 id="chatname">'.get_setting('chatname').'</h1>';
   3262 echo '<div id="logincbox" class="overlaycbx"><div class="popupcbx"><h2>Login</h2><a class="closecbx" href="#">&times;</a><div class="contentcbx">';
   3263 echo form_target('_parent', 'login') . '<table>';
   3264 if ($englobal === 1 && isset($_REQUEST['globalpass'])) {
   3265 	echo hidden('globalpass', $_REQUEST['globalpass']);
   3266 }
   3267 if ($englobal !== 1 || (isset($_REQUEST['globalpass']) && $_REQUEST['globalpass'] == get_setting('globalpass'))) {
   3268 	echo "<tr><td>$I[nick]</td><td><input type=\"text\" name=\"nick\" size=\"15\" autofocus></td></tr>";
   3269 	echo "<tr><td>$I[pass]</td><td><input type=\"password\" name=\"pass\" size=\"15\"></td></tr>";
   3270 	send_captcha();
   3271 	if ($ga !== 0) {
   3272 		if (get_setting('guestreg') != 0) {
   3273 			echo "<tr><td>$I[regpass]</td><td><input type=\"password\" name=\"regpass\" size=\"15\" placeholder=\"$I[optional]\"></td></tr>";
   3274 		}
   3275 		if ($englobal === 2) {
   3276 			echo "<tr><td>$I[globalloginpass]</td><td><input type=\"password\" name=\"globalpass\" size=\"15\"></td></tr>";
   3277 		}
   3278 		echo "<tr><td colspan=\"2\">$I[choosecol]<br><select name=\"colour\"><option value=\"\">* $I[randomcol] *</option>";
   3279 		print_colours();
   3280 		echo '</select></td></tr>';
   3281 	} else {
   3282 		echo "<tr><td colspan=\"2\">$I[noguests]</td></tr>";
   3283 	}
   3284 	echo '<tr><td colspan="2">' . submit($I['enter']) . '</td></tr></table></form>';
   3285 	echo '<br>';
   3286 	get_nowchatting();
   3287 	// echo '<br><div id="topic">';
   3288 	//MODIFICATION Topic on Frontpage disabled. 1 lines "removed"
   3289 	//echo get_setting('topic');
   3290 	// echo '</div>';
   3291 	$rulestxt = get_setting('rulestxt');
   3292 
   3293 	//MODIFICATION Rules on Frontpage disabled. 3 lines "removed"
   3294 	/*
   3295 	if(!empty($rulestxt)){
   3296 		echo "<div id=\"rules\"><h2>$I[rules]</h2><b>$rulestxt</b></div>";
   3297 	}
   3298 	*/
   3299 } else {
   3300 	echo "<tr><td>$I[globalloginpass]</td><td><input type=\"password\" name=\"globalpass\" size=\"15\" autofocus></td></tr>";
   3301 	if ($ga === 0) {
   3302 		echo "<tr><td colspan=\"2\">$I[noguests]</td></tr>";
   3303 	}
   3304 	echo '<tr><td colspan="2">' . submit($I['enter']) . '</td></tr></table></form>';
   3305 }
   3306 /*echo "<p id=\"changelang\">$I[changelang]";
   3307 foreach($L as $lang=>$name){
   3308 	echo " <a href=\"$_SERVER[SCRIPT_NAME]?lang=$lang\">$name</a>";
   3309 }*/
   3310 
   3311 //MODIFICATION we hide our script version for security reasons and because it was modificated. 1 line replaced.
   3312 //echo '</p>'.credit();
   3313 //echo '</p>'; 
   3314 echo '</table>';
   3315 $link4o4 = 'https://4-0-4.io';
   3316 $class = 'clearnet';
   3317 
   3318 echo '</div></div></div>';
   3319 echo "<div class=\"odiv\"><div class=\"splash\"><h2><strong>Welcome to the 404 Chatroom</strong></h2><div class=\"splashcard\"><br>
   3320 <h3><ins>Shocking News</ins>: New Updates! We're online!</h3><br>
   3321 <strong>Welcome to the 404 Chatroom - <em>The most over-compensating chat on tor</em>.</strong>
   3322 <br>Are you looking for a fun - stress free, user friendly - totally secret awesome badass cool darkweb chat? That's such a coincidence, because that's what this is. All you have to do is press the <strong>Login</strong> button in the top right hand corner, enter your credentials, and start chatting. If you want to chat anonymously, just enter any nickname press <strong>Enter Chat</strong> straight away and get at it. We hope you have fun!
   3323 <br><br>
   3324 <div class=\"callout alert\" style=\"background: none; border: 2px; border-style: solid; border-color: #ffff80; border-radius: 0.5em; padding: 1em; color: white; margin-left: 10%; margin-right: 10%;\">  <p style=\"color: white; text-align: center\"><center>The <span style=\"color: #404 Chatroomffff80;\">404 Chatroom</span> Rules</center></p><hr><ol>  <li><span style=\"color: #ffff80;\">Nothing gross or illegal.</span></li>  <li>Freedom of speech is welcomed, but be nice.</li>  <li>Please <span style=\"color: #ffff80;\">be respectful</span> to other chatters</li>  <li>Please <span style=\"color: #ffff80;\">use meaningful</span> and <span style=\"color: #ffff80;\">non-offensive nicknames</span>. No pedo nicks.</li>  <li>Please <span style=\"color: #ffff80;\">use English</span> in the Main Chat please.</li>  <li>Please <span style=\"color: #ffff80;\">no advertising</span> with out staff approval .</li>  <li>No drug or gun endorsements, or endorsements of other illegal markets.</li></ol> <hr /></div>
   3325 <br><br>
   3326 </div><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
   3327 <a href=\"http://4o4o4hn4hsujpnbsso7tqigujuokafxys62thulbk2k3mf46vq22qfqd.onion/\"><div class=\"tip\" style=\"position: fixed; bottom : 0; width: 100%\"><h4 style=\"color:white;\">~ Part of the 404 Project ~</h4></div>
   3328 </a>
   3329 <div class=\"idiv\" id=\"ABOUT\"><div class=\"idivs1\">&nbsp;</div>
   3330        
   3331        <div class=\"idivc\">
   3332        
   3333        <div style=\"text-align:center\"><h3><a name=\"Links\">About The Chat</a></h3></div>
   3334        <br><br>
   3335 <div class=\"insb\">Spread the word</div>
   3336 <br>
   3337 If you are passionate about promoting this chat, why not put a link to the site/chat in your regular forum profile signature? Go to your signature edit box and use something like this:<br><br>
   3338 <div class=\"scrollbox\"><div class=\"sbc\"><pre><code>[b][size=100][bgcolor=#121525][color=#166FA6][/color][color=#F7F7F7]the 404 Chatroom:[/color][color=#166FA6] [/color][/bgcolor][/size] [size=100][bgcolor=#C13B5B][color=#F7F7F7]The dopest chat of darkweb.[/color][color=#C13B5B][/color][/bgcolor][/size][/b]</code></pre></div></div> <br>
   3339 
   3340 <div class=\"insb\">Ideas and to-do's that need your input</div>
   3341 <br>
   3342 If you have theme ideas for the chat - or other improvements you'd like to see implemented, just contact a member of staff. Your feedback is highly appreciated.<br><br>
   3343        </div><div class=\"idivs2\">&nbsp;</div><br>
   3344 </div></div>";
   3345 print_end();
   3346 }
   3347 
   3348 function send_chat_disabled()
   3349 {
   3350 print_start('disabled');
   3351 echo get_setting('disabletext');
   3352 print_end();
   3353 }
   3354 
   3355 function send_error($err)
   3356 {
   3357 global $I;
   3358 print_start('error');
   3359 echo "<h2>$I[error]: $err</h2>" . form_target('_parent', '') . submit($I['backtologin'], 'class="backbutton"') . '</form>';
   3360 print_end();
   3361 }
   3362 
   3363 function send_fatal_error($err)
   3364 {
   3365 global $I;
   3366 echo '<!DOCTYPE html><html><head>' . meta_html();
   3367 echo "<title>$I[fatalerror]</title>";
   3368 echo "<style type=\"text/css\">body{background-color:#000000;color:#FF0033;}</style>";
   3369 echo '</head><body>';
   3370 echo "<h2>$I[fatalerror]: $err</h2>";
   3371 print_end();
   3372 }
   3373 
   3374 function print_notifications()
   3375 {
   3376 global $I, $U, $db;
   3377 echo '<span id="notifications">';
   3378 if ($U['status'] >= 2 && $U['eninbox'] != 0) {
   3379 	$stmt = $db->prepare('SELECT COUNT(*) FROM ' . PREFIX . 'inbox WHERE recipient=?;');
   3380 	$stmt->execute([$U['nickname']]);
   3381 	$tmp = $stmt->fetch(PDO::FETCH_NUM);
   3382 	if ($tmp[0] > 0) {
   3383 		echo '<p>' . form('inbox') . submit(sprintf($I['inboxmsgs'], $tmp[0])) . '</form></p>';
   3384 	}
   3385 }
   3386 if ($U['status'] >= 5 && get_setting('guestaccess') == 3) {
   3387 	$result = $db->query('SELECT COUNT(*) FROM ' . PREFIX . 'sessions WHERE entry=0 AND status=1;');
   3388 	$temp = $result->fetch(PDO::FETCH_NUM);
   3389 	if ($temp[0] > 0) {
   3390 		echo '<p>';
   3391 		echo form('admin', 'approve');
   3392 		echo submit(sprintf($I['approveguests'], $temp[0])) . '</form></p>';
   3393 	}
   3394 }
   3395 echo '</span>';
   3396 }
   3397 function print_chatters()
   3398 {
   3399 global $I, $U, $db, $language;
   3400 
   3401 $icon_star_red = "<img border='0' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4wgIACgc4JxSRwAAARBJREFUKM99kL1KA1EQhb/Z6+4GJQQbDQi+Q7CPYMBGKxtrVyRsaSkEg4iCBGxMuQQ2kGewzxtYiW+gpSD5u94dq4hsLp5u5jtnhhnwaJ6mu4tOZ93H1nxNJpNjrDXAUxkF+HWi1p75wErAjkZGnGsBDdvtbpa5zNN0X6bTDQBVFTFmT527ARCRnqqORaQgCNA4nsq83d5mNnsGGvyvFyqVI1lWiyS5UufufU4Jw9soy64B5C9YJMmlOvdYMneiLLvzHq3OHZSnq7VN75e+h8MAaAGIMRcShueAAofu7TVYCRTjcRP4kmq1Hg0GWZRlA6nVdoAP99A7XQmoMXGc51tRv//xu78o3uM8r2sYfi5bP+VcXsOKMjGVAAAAAElFTkSuQmCC'/>";
   3402 
   3403 $icon_star_gold = "<img border='0' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAABKElEQVQoz32QvUoDQRSFz53ZjfEnMTFgkkYQrOyCragYsdFCLAIpRXwASyEIIoog2PgQiUbRTsXON4i1D7AKmhUk2d3MzLWKhOzgKb9vhnvvASwJb2dnOo+LYzbnWGHkbUr9JQFcDjsBa3ibdLhjM7EP7deaBKsymbDUeV7LDnvq3RSXhfoZBzFgiFjIBaH8IwAwcuKcmF5AbAiAdlJdipqFvFT+A5mghH/CItnSTnqD+qB3NXUgVfsU4Nhj42aOnYp/CAA0KFQjsy+0fzHItJuruZXPE+vRxMFqrBXdWbK25LXOBHGvDBIwTnZPu5O7gGTicP0p4Hj96jq3ouuJj+79XL7Pgrv5oq4nPN1IV2MTtEyOyGo0Pbr19v63IkJPVqOCclLfffYLGXVpfXSgIhUAAAAASUVORK5CYII='/>";
   3404 
   3405 $icon_star_silver = "<img border='0' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA8ElEQVQoz42STSuEURiGr/tgw8pOTfkPk61GIQorG6uz0CRri1moSUmklF8gm/PuZI1m5x/MrPwEH8VGQym3zVHT6yw8y/ujnufqgcKklGaHt/OTJS+URNsb1y+77X8XgE3b2/8qvA26Y8AS0Bz2lqfrvlJKC8BUXkWS5mwfAkg6s30v6TvnP8aBB9s3QDOXRm/pAJ2s9SWta4TMvu2T0t6SjmKMBwCq4dyzfV4Ld2OMx8WjbS8WELeKlB77pyHTQdKOpDZgYOXu0+FPoTdotID3EMJMjPEixng58fXaAJ6er6qt0jus1rWqqpS9tV/tB1UBYQLU/vuEAAAAAElFTkSuQmCC'/>";
   3406 
   3407 $icon_star_bronze = "<img border='0' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAABEElEQVQoz42QL0hDYRTFf/d7s2jSYhN8w2YZVpmgsoGaDL5ZBBl2hRVhCCoMYWw2g8UijIF9yprYZQOjrymaBiLTsPddgz7Bx4fspnvPuX/OPeCIesGf6l/Pj7o44wIHka6dXTwXhx4A1q3V7aEGet2yp7AEZPrt5fEkL/WCvxBZHQNQRURkTlUPAUSoqnIrggXBM3xILfAnI6stIMP/0fGMrEpcVTf8fVWtOHUbOS41wwMALwbbD7273OzEG5BPNJdLzfDI+bSqLia3W6tZp0svnRPDtzuIyI4xUgQUyN186m9fKk4uK+dZ4H0kZab3Go+vAFe7M63waXDf3UoHQOPP6Vrg55NyTjfT8sOtxNgX5ehXBVg4i6sAAAAASUVORK5CYII='/>";
   3408 
   3409 $icon_heart_red = "<img border='0' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAABs0lEQVQoz22Ry2sTURSHv3vvPNLMTBLTiiVIFSsuxFCIuBJEKi58LN3730k0BRcVBVEpXSloN1IrrYJSHyQTZ5pn03nc6yJpF+K3/J3v/BbnCIDnNqeWa9WrjuN4xlJbF3Z+7gNsX1pccjPdyI3u7+13P9zP6InXc1SvXDy/UQn8upSSLM97nU7nzmGaumdrtXVHWb7BEPf6W+8/f1+1Fqqle+XAr9u2DYBlWWW3OPfCEYHrFQoFYwwAlVLQOHcmuGVpaEgpOUYbw+nqfNkYw7EMoKREIlZkotlO9HRghABAGIMUApSCWWa0xlFqR/7pDzZ+t8NxNhojkgSpNUJMPZFmiMkEMRqQxPFwPBi+lXdH5steO3zZ7Ubo8RjybNYqwOSQpiSDEV/b4bOVOP2mAKzEtBZ1+jAwVHzHBrcASkKuSQ4GfOzGnxrR0SqABHjgCx1m+vpubxiFYYzp9WFyRBYdsBvFnR+T9OZm2REnF3hcVAA0PevyZqVgftUqJlpaMO/mPb0e2MsAT2bOCS1/+oeWZ197U3IOX5XcYdOz6wBPA4f/sjZbahbV7UdFdQNg7R/5Lza2vZnfg8j9AAAAAElFTkSuQmCC'/>";
   3410 
   3411 //Color was changed from blue to light blue
   3412 $icon_heart_blue = "<img border='0' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAABqUlEQVQoz2WQu2tTYRiHn/c7JyeXJpbopnAU9yJEHFSUEHUoTiIOXQTXtouLf4K46RBHVxcLHQwIIhKdXOwi6iISW/Ba06QnObmc7/teB220+My/Gz8BaNz9WK2W8yejiDkR2Xh4/fAWwNKDrdgGpmas3/2a+Ncvbh7ty8X7nYNHyrl2qWgWAq9YY/r9JFu0nvyhueBxaCgDJBPd6HRtI6wUgsulolmIAIwQoPNRaJ5EkM+HUuAPpaLUqgeCCyFQC7yCEQCcCpVCMC8o/xJ4JXT+hHEqb60xM/EeRkBE9plE5L1JJ7bdS2w6yhTUIyiB/E53XnFeGakwmPjBKNNX5tnKsQ/bY/t0J1MmVlH9O8UrTB2Mpo7toW+1luOOAfjSD64mvazTszBB9uoBmFrPTuLetZbjJQADcOd27MehOTsY2O7uwJJ6yJwynCrd1H9Plfpi85PMDKk3tFfjzyPkXG8MvcTyc+j4NnI6VDnzfCX+cePWcQWY3fConOPaIKNxr3MqDMxL47wbh+Z0ezV+s16JuJJM+Y+1cg6AenPzUr25eR5grRLt0/wCkH7H2hCmE9kAAAAASUVORK5CYII='/>";
   3413 
   3414 
   3415 if (!$U['hidechatters']) {
   3416 	echo '<div id="chatters">';
   3417 	if ($U['status'] >= 5) {
   3418 		$stmt = $db->prepare('SELECT nickname, style, status, roomid FROM ' . PREFIX . 'sessions WHERE entry!=0 AND status>0 AND incognito=0 AND nickname NOT IN (SELECT ign FROM ' . PREFIX . 'ignored WHERE ignby=? UNION SELECT ignby FROM ' . PREFIX . 'ignored WHERE ign=?) ORDER BY status DESC, lastpost DESC;');
   3419 	} else {
   3420 		$stmt = $db->prepare('SELECT nickname, style, status, roomid FROM ' . PREFIX . 'sessions WHERE entry!=0 AND status>0 AND incognito=0 AND nickname NOT IN (SELECT ign FROM ' . PREFIX . 'ignored WHERE ignby=? UNION SELECT ignby FROM ' . PREFIX . 'ignored WHERE ign=?) ORDER BY lastpost DESC;');
   3421 	}
   3422 	$stmt->execute([$U['nickname'], $U['nickname']]);
   3423 	$nc = substr(time(), -6);
   3424 	$G = $RG = $M = $S = [];
   3425 	while ($user = $stmt->fetch(PDO::FETCH_BOTH)) {
   3426 		//MODIFICATION chat rooms
   3427 		$roomclass = 'notinroom';
   3428 		if ($U['roomid'] === $user['roomid']) {
   3429 			$roomclass = 'inroom';
   3430 		}
   3431 		$stmt1 = $db->prepare('SELECT name FROM ' . PREFIX . 'rooms WHERE id=? AND access<=? ;');
   3432 		$stmt1->execute([$user['roomid'], $U['status']]);
   3433 		if ($room = $stmt1->fetch(PDO::FETCH_NUM)) {
   3434 			$roomname = $room[0];
   3435 		} else {
   3436 			$roomname = " ";
   3437 			if ($user['roomid'] === null) {
   3438 				$roomname = "[Main Chat]";
   3439 			}
   3440 		}
   3441 		$roomprefix = "<span class=\"$roomclass\" title=\"$roomname\">";
   3442 		$roompostfix = '</span>';
   3443 
   3444 		$link = "<a style=\"text-decoration: none;\" href=\"?action=post&amp;session=$U[session]&amp;lang=$language&amp;nc=$nc&amp;sendto=" . htmlspecialchars($user[0]) . '" target="post">' . style_this(htmlspecialchars($user[0]), $user[1]) . '</a>';
   3445 
   3446 		//staff can see the different rank icons of the staff people
   3447 		if ($U['status'] >= 5) {    //if logged in user is moderator or higher            
   3448 
   3449 			if ($user[2] >= 8) {
   3450 				$link = "<nobr>" . rank_this($user[2]) . $roomprefix . $link . $roompostfix . "</nobr>"; //adds red star icon in front of the nick.
   3451 				$S[] = $link;
   3452 			} elseif ($user[2] == 7) {
   3453 				$link = "<nobr>" . rank_this($user[2]) . $roomprefix . $link . $roompostfix . "</nobr>"; //adds gold star icon in front of the nick.
   3454 				$S[] = $link;
   3455 			} elseif ($user[2] == 6) {
   3456 				$link = "<nobr>" . rank_this($user[2]) . $roomprefix . $link . $roompostfix . "</nobr>"; //adds silver star icon in front of the nick.
   3457 				$S[] = $link;
   3458 			} elseif ($user[2] == 5) {
   3459 				$link = "<nobr>" . rank_this($user[2]) . $roomprefix . $link . $roompostfix . "</nobr>"; //adds bronze star icon in front of the nick.
   3460 				$S[] = $link;
   3461 			} elseif ($user[2] == 3) {
   3462 				$link = "<nobr>" . rank_this($user[2]) . $roomprefix . $link . $roompostfix . "</nobr>"; //adds "heart icon red" in front of the nick.
   3463 				$M[] = $link;
   3464 			} elseif ($user[2] == 2) {
   3465 				$link = "<nobr>" . rank_this($user[2]) . $roomprefix . $link . $roompostfix . "</nobr>"; //adds "heart icon pink" in front of the nick.
   3466 				$RG[] = $link;
   3467 			} else {
   3468 				$G[] = $roomprefix . $link . $roompostfix;
   3469 			}
   3470 
   3471 			//guests and members can't see the different rank icons of the staff
   3472 		} else {
   3473 			if ($user[2] >= 5) {
   3474 				$link = "<nobr>" . rank_this('5') . $roomprefix . $link . $roompostfix . "</nobr>"; //adds star icon in front of the nick. No break tags (deprecated) to prevent line break between icon and nickname.
   3475 				$M[] = $link;
   3476 			} elseif ($user[2] == 3) {
   3477 				$link = "<nobr>" . rank_this('3') . $roomprefix . $link . $roompostfix . "</nobr>"; //adds "heart icon red" in front of the nick.
   3478 				$M[] = $link;
   3479 			} elseif ($user[2] == 2) {
   3480 				$link = "<nobr>" . rank_this('2') . $roomprefix . $link . $roompostfix . "</nobr>"; //adds "heart icon" pink in front of the nick.
   3481 				$RG[] = $link;
   3482 			} else {
   3483 				$G[] = $roomprefix . $link . $roompostfix;
   3484 			}
   3485 		} //end if
   3486 
   3487 	} //end while
   3488 	if ($U['status'] >= 5) {
   3489 		$chanlinks = "<a style=\"color:#fff; text-decoration: none\" href=\"?action=post&amp;session=$U[session]&amp;lang=$language&amp;nc=$nc&amp;sendto=s 48\" target=\"post\">$I[staff]</a>";
   3490 		$chanlinkm = "<a style=\"color:#fff; text-decoration: none\" href=\"?action=post&amp;session=$U[session]&amp;lang=$language&amp;nc=$nc&amp;sendto=s 31\" target=\"post\">$I[members2]</a>";
   3491 		$chanlinkrg = "<a style=\"color:#fff; text-decoration: none\" href=\"?action=post&amp;session=$U[session]&amp;lang=$language&amp;nc=$nc&amp;sendto=s 24\" target=\"post\">$I[regguests]</a>";
   3492 		$chanlinkg = "<a style=\"color:#fff; text-decoration: none\" href=\"?action=post&amp;session=$U[session]&amp;lang=$language&amp;nc=$nc&amp;sendto=s 17\" target=\"post\">$I[guests]</a>";
   3493 	} elseif ($U['status'] == 3) {
   3494 		$chanlinks = "$I[staff]";
   3495 		$chanlinkm = "<a style=\"color:#fff; text-decoration: none\" href=\"?action=post&amp;session=$U[session]&amp;lang=$language&amp;nc=$nc&amp;sendto=s 31\"  target=\"post\">$I[members2]</a>";
   3496 		$chanlinkrg = "<a style=\"color:#fff; text-decoration: none\" href=\"?action=post&amp;session=$U[session]&amp;lang=$language&amp;nc=$nc&amp;sendto=s 24\" target=\"post\">$I[regguests]</a>";
   3497 		$chanlinkg = "<a style=\"color:#fff; text-decoration: none\" href=\"?action=post&amp;session=$U[session]&amp;lang=$language&amp;nc=$nc&amp;sendto=s 17\" target=\"post\">$I[guests]</a>";
   3498 	} elseif ($U['status'] == 2) {
   3499 		$chanlinks = "$I[staff]";
   3500 		$chanlinkm = "$I[members2]";
   3501 		$chanlinkrg = "<a style=\"color:#fff; text-decoration: none\" href=\"?action=post&amp;session=$U[session]&amp;lang=$language&amp;nc=$nc&amp;sendto=s 24\" target=\"post\">$I[regguests]</a>";
   3502 		$chanlinkg = "<a style=\"color:#fff; text-decoration: none\" href=\"?action=post&amp;session=$U[session]&amp;lang=$language&amp;nc=$nc&amp;sendto=s 17\" target=\"post\">$I[guests]</a>";
   3503 	} else {
   3504 		$chanlinks = "$I[staff]";
   3505 		$chanlinkm = "$I[members2]";
   3506 		$chanlinkrg = "$I[regguests]";
   3507 		$chanlinkg = "<a style=\"color:#fff; text-decoration: none\" href=\"?action=post&amp;session=$U[session]&amp;lang=$language&amp;nc=$nc&amp;sendto=s 17\" target=\"post\">$I[guests]</a>";
   3508 	}
   3509 	if (!empty($S)) {
   3510 		echo "<span class='group'>" . $chanlinks . " (" . count($S) . ")</span><div>" . implode('</span><br><span>', $S) . '</div>';
   3511 		if (!empty($M) || !empty($R) || !empty($G)) {
   3512 			echo '<div>&nbsp;&nbsp;</div>';
   3513 		}
   3514 	}
   3515 	if (!empty($M)) {
   3516 		echo "<span class='group'>" . $chanlinkm . " (" . count($M) . ")</span><div>" . implode('</span><br><span>', $M) . '</div>';
   3517 		if (!empty($R) || !empty($G)) {
   3518 			echo '<div>&nbsp;&nbsp;</div>';
   3519 		}
   3520 	}
   3521 	if (!empty($RG)) {
   3522 		echo "<span class='group'>" . $chanlinkrg . " (" . count($RG) . ")</span><div>" . implode('</span><br><span>', $RG) . '</div>';
   3523 		if (!empty($G)) {
   3524 			echo '<div>&nbsp;&nbsp;</div>';
   3525 		}
   3526 	}
   3527 	if (!empty($G)) {
   3528 		echo "<span class='group'>" . $chanlinkg . " (" . count($G) . ")</span><div>" . implode('</span><br><span>', $G) . '</div>';
   3529 	}
   3530 	echo '</div>';
   3531 } //end if
   3532 } //end function print_chatters
   3533 
   3534 //  session management
   3535 
   3536 function create_session($setup, $nickname, $password)
   3537 {
   3538 global $I, $U;
   3539 $U['nickname'] = preg_replace('/\s/', '', $nickname);
   3540 if (check_member($password)) {
   3541 	if ($setup && $U['status'] >= 7) {
   3542 		$U['incognito'] = 1;
   3543 	}
   3544 	$U['entry'] = $U['lastpost'] = time();
   3545 } else {
   3546 	add_user_defaults($password);
   3547 	check_captcha(isset($_REQUEST['challenge']) ? $_REQUEST['challenge'] : '', isset($_REQUEST['captcha']) ? $_REQUEST['captcha'] : '');
   3548 	$ga = (int) get_setting('guestaccess');
   3549 	if (!valid_nick($U['nickname'])) {
   3550 		send_error(sprintf($I['invalnick'], get_setting('maxname'), get_setting('nickregex')));
   3551 	}
   3552 	if (!valid_pass($password)) {
   3553 		send_error(sprintf($I['invalpass'], get_setting('minpass'), get_setting('passregex')));
   3554 	}
   3555 	if ($ga === 0) {
   3556 		send_error($I['noguests']);
   3557 	} elseif ($ga === 3) {
   3558 		$U['entry'] = 0;
   3559 	}
   3560 	if (get_setting('englobalpass') != 0 && isset($_REQUEST['globalpass']) && $_REQUEST['globalpass'] != get_setting('globalpass')) {
   3561 		send_error($I['wrongglobalpass']);
   3562 	}
   3563 }
   3564 write_new_session($password);
   3565 }
   3566 
   3567 function rank_this($status)
   3568 {
   3569 
   3570 /*
   3571 1 .rank.g { background-image: url('green-1.png'); }
   3572 2 .rank.ra { background-image: url('green-2.png'); }
   3573 3 .rank.m { background-image: url('blue-1.png'); }
   3574 5 .rank.mod { background-image: url('red-1.png'); }
   3575 6 .rank.sm { background-image: url('red-2.png'); }
   3576 7 .rank.a { background-image: url('red-3.png'); }
   3577 8 .rank.sa { background-image: url('yellow-1.png'); }
   3578 */
   3579 
   3580 $rank = "";
   3581 
   3582 switch ($status) {
   3583 	case 1:
   3584 		$rank = "g";
   3585 		break;
   3586 	case 2:
   3587 		$rank = "ra";
   3588 		break;
   3589 	case 3:
   3590 		$rank = "m";
   3591 		break;
   3592 	case 5:
   3593 		$rank = "mod";
   3594 		break;
   3595 	case 6:
   3596 		$rank = "sm";
   3597 		break;
   3598 	case 7:
   3599 		$rank = "a";
   3600 		break;
   3601 	case 8:
   3602 		$rank = "sa";
   3603 		break;
   3604 	case 9:
   3605 		$rank = "sa";
   3606 		break;
   3607 	default:
   3608 		$rank = "";
   3609 }
   3610 
   3611 if (strlen($rank)) {
   3612 	return sprintf("<span class=\"rank %s\"></span><bdi class=\"spacer\"></bdi>", $rank);
   3613 }
   3614 return '';
   3615 }
   3616 
   3617 function check_captcha($challenge, $captcha_code)
   3618 {
   3619 global $I, $db, $memcached;
   3620 $captcha = (int) get_setting('captcha');
   3621 if ($captcha !== 0) {
   3622 	if (empty($challenge)) {
   3623 		send_error($I['wrongcaptcha']);
   3624 	}
   3625 	if (MEMCACHED) {
   3626 		if (!$code = $memcached->get(DBNAME . '-' . PREFIX . "captcha-$_REQUEST[challenge]")) {
   3627 			send_error($I['captchaexpire']);
   3628 		}
   3629 		$memcached->delete(DBNAME . '-' . PREFIX . "captcha-$_REQUEST[challenge]");
   3630 	} else {
   3631 		$stmt = $db->prepare('SELECT code FROM ' . PREFIX . 'captcha WHERE id=?;');
   3632 		$stmt->execute([$challenge]);
   3633 		$stmt->bindColumn(1, $code);
   3634 		if (!$stmt->fetch(PDO::FETCH_BOUND)) {
   3635 			send_error($I['captchaexpire']);
   3636 		}
   3637 		$time = time();
   3638 		$stmt = $db->prepare('DELETE FROM ' . PREFIX . 'captcha WHERE id=? OR time<(?-(SELECT value FROM ' . PREFIX . "settings WHERE setting='captchatime'));");
   3639 		$stmt->execute([$challenge, $time]);
   3640 	}
   3641 	if ($captcha_code !== $code) {
   3642 		if ($captcha !== 3 || strrev($captcha_code) !== $code) {
   3643 			send_error($I['wrongcaptcha']);
   3644 		}
   3645 	}
   3646 }
   3647 }
   3648 
   3649 function is_definitely_ssl()
   3650 {
   3651 if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') {
   3652 	return true;
   3653 }
   3654 if (isset($_SERVER['SERVER_PORT']) && ('443' == $_SERVER['SERVER_PORT'])) {
   3655 	return true;
   3656 }
   3657 if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && ('https' == $_SERVER['HTTP_X_FORWARDED_PROTO'])) {
   3658 	return true;
   3659 }
   3660 return false;
   3661 }
   3662 
   3663 function set_secure_cookie($name, $value)
   3664 {
   3665 if (version_compare(PHP_VERSION, '7.3.0') >= 0) {
   3666 	setcookie($name, $value, ['expires' => 0, 'path' => '/', 'domain' => '', 'secure' => is_definitely_ssl(), 'httponly' => true, 'samesite' => 'Strict']);
   3667 } else {
   3668 	setcookie($name, $value, 0, '/', '', is_definitely_ssl(), true);
   3669 }
   3670 }
   3671 
   3672 function write_new_session($password)
   3673 {
   3674 global $I, $U, $db;
   3675 $stmt = $db->prepare('SELECT * FROM ' . PREFIX . 'sessions WHERE nickname=?;');
   3676 $stmt->execute([$U['nickname']]);
   3677 if ($temp = $stmt->fetch(PDO::FETCH_ASSOC)) {
   3678 	// check whether alrady logged in
   3679 	if (password_verify($password, $temp['passhash'])) {
   3680 		$U = $temp;
   3681 		check_kicked();
   3682 		set_secure_cookie(COOKIENAME, $U['session']);
   3683 	} else {
   3684 		send_error("$I[userloggedin]<br>$I[wrongpass]");
   3685 	}
   3686 } else {
   3687 	// create new session
   3688 	$stmt = $db->prepare('SELECT null FROM ' . PREFIX . 'sessions WHERE session=?;');
   3689 	do {
   3690 		if (function_exists('random_bytes')) {
   3691 			$U['session'] = bin2hex(random_bytes(16));
   3692 		} else {
   3693 			$U['session'] = md5(uniqid($U['nickname'], true) . mt_rand());
   3694 		}
   3695 		$stmt->execute([$U['session']]);
   3696 	} while ($stmt->fetch(PDO::FETCH_NUM)); // check for hash collision
   3697 	if (isset($_SERVER['HTTP_USER_AGENT'])) {
   3698 		$useragent = htmlspecialchars($_SERVER['HTTP_USER_AGENT']);
   3699 	} else {
   3700 		$useragent = '';
   3701 	}
   3702 	if (get_setting('trackip')) {
   3703 		$ip = $_SERVER['REMOTE_ADDR'];
   3704 	} else {
   3705 		$ip = '';
   3706 	}
   3707 	$stmt = $db->prepare('INSERT INTO ' . PREFIX . 'sessions (session, nickname, status, refresh, style, lastpost, passhash, useragent, bgcolour, entry, timestamps, embed, incognito, ip, nocache, tz, eninbox, sortupdown, hidechatters, nocache_old) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);');
   3708 	$stmt = $db->prepare('INSERT INTO ' . PREFIX . 'sessions (session, nickname, status, refresh, style, lastpost, passhash, useragent, bgcolour, entry, timestamps, embed, incognito, ip, nocache, tz, eninbox, sortupdown, hidechatters, nocache_old) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);');
   3709 	$stmt->execute([$U['session'], $U['nickname'], $U['status'], $U['refresh'], $U['style'], $U['lastpost'], $U['passhash'], $useragent, $U['bgcolour'], $U['entry'], $U['timestamps'], $U['embed'], $U['incognito'], $ip, $U['nocache'], $U['tz'], $U['eninbox'], $U['sortupdown'], $U['hidechatters'], $U['nocache_old']]);
   3710 	set_secure_cookie(COOKIENAME, $U['session']);
   3711 
   3712 	//MDIFICATION for clickable nicknames setting. (clickablenicknames value added)
   3713 	/* REMVOE LATER
   3714 	$stmt=$db->prepare('INSERT INTO ' . PREFIX . 'sessions (session, nickname, status, refresh, style, lastpost, passhash, useragent, bgcolour, entry, timestamps, embed, incognito, ip, nocache, tz, eninbox, sortupdown, hidechatters, nocache_old, clickablenicknames) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);');
   3715 	$stmt->execute([$U['session'], $U['nickname'], $U['status'], $U['refresh'], $U['style'], $U['lastpost'], $U['passhash'], $useragent, $U['bgcolour'], $U['entry'], $U['timestamps'], $U['embed'], $U['incognito'], $ip, $U['nocache'], $U['tz'], $U['eninbox'], $U['sortupdown'], $U['hidechatters'], $U['nocache_old'],$U['clickablenicknames'] ]);
   3716 	setcookie(COOKIENAME, $U['session']);
   3717 	*/
   3718 
   3719 	//MODIFICATION adminjoinleavemsg setting for join/leave message for admins
   3720 	if (($U['status'] >= 3 && $U['status'] <= 6 && !$U['incognito']) || ($U['status'] >= 7 && !$U['incognito'] && (bool) get_setting('adminjoinleavemsg'))) {
   3721 		add_system_message(sprintf(get_setting('msgenter'), style_this_clickable(htmlspecialchars($U['nickname']), $U['style'])));
   3722 	}
   3723 }
   3724 }
   3725 
   3726 function approve_session()
   3727 {
   3728 global $db;
   3729 if (isset($_REQUEST['what'])) {
   3730 	if ($_REQUEST['what'] === 'allowchecked' && isset($_REQUEST['csid'])) {
   3731 		$stmt = $db->prepare('UPDATE ' . PREFIX . 'sessions SET entry=lastpost WHERE nickname=?;');
   3732 		foreach ($_REQUEST['csid'] as $nick) {
   3733 			$stmt->execute([$nick]);
   3734 		}
   3735 	} elseif ($_REQUEST['what'] === 'allowall' && isset($_REQUEST['alls'])) {
   3736 		$stmt = $db->prepare('UPDATE ' . PREFIX . 'sessions SET entry=lastpost WHERE nickname=?;');
   3737 		foreach ($_REQUEST['alls'] as $nick) {
   3738 			$stmt->execute([$nick]);
   3739 		}
   3740 	} elseif ($_REQUEST['what'] === 'denychecked' && isset($_REQUEST['csid'])) {
   3741 		$time = 60 * (get_setting('kickpenalty') - get_setting('guestexpire')) + time();
   3742 		$stmt = $db->prepare('UPDATE ' . PREFIX . 'sessions SET lastpost=?, status=0, kickmessage=? WHERE nickname=? AND status=1;');
   3743 		foreach ($_REQUEST['csid'] as $nick) {
   3744 			$stmt->execute([$time, $_REQUEST['kickmessage'], $nick]);
   3745 		}
   3746 	} elseif ($_REQUEST['what'] === 'denyall' && isset($_REQUEST['alls'])) {
   3747 		$time = 60 * (get_setting('kickpenalty') - get_setting('guestexpire')) + time();
   3748 		$stmt = $db->prepare('UPDATE ' . PREFIX . 'sessions SET lastpost=?, status=0, kickmessage=? WHERE nickname=? AND status=1;');
   3749 		foreach ($_REQUEST['alls'] as $nick) {
   3750 			$stmt->execute([$time, $_REQUEST['kickmessage'], $nick]);
   3751 		}
   3752 	}
   3753 }
   3754 }
   3755 
   3756 function check_login()
   3757 {
   3758 global $I, $U, $db;
   3759 $ga = (int) get_setting('guestaccess');
   3760 if (isset($_REQUEST['session'])) {
   3761 	parse_sessions();
   3762 }
   3763 if (isset($U['session'])) {
   3764 	check_kicked();
   3765 } elseif (get_setting('englobalpass') == 1 && (!isset($_REQUEST['globalpass']) || $_REQUEST['globalpass'] != get_setting('globalpass'))) {
   3766 	send_error($I['wrongglobalpass']);
   3767 } elseif (!isset($_REQUEST['nick']) || !isset($_REQUEST['pass'])) {
   3768 	send_login();
   3769 } else {
   3770 	if ($ga === 4) {
   3771 		send_chat_disabled();
   3772 	}
   3773 	if (!empty($_REQUEST['regpass']) && $_REQUEST['regpass'] !== $_REQUEST['pass']) {
   3774 		send_error($I['noconfirm']);
   3775 	}
   3776 	create_session(false, $_REQUEST['nick'], $_REQUEST['pass']);
   3777 	if (!empty($_REQUEST['regpass'])) {
   3778 		$guestreg = (int) get_setting('guestreg');
   3779 		if ($guestreg === 1) {
   3780 			register_guest(2, $_REQUEST['nick']);
   3781 			$U['status'] = 2;
   3782 		} elseif ($guestreg === 2) {
   3783 			register_guest(3, $_REQUEST['nick']);
   3784 			$U['status'] = 3;
   3785 		}
   3786 	}
   3787 }
   3788 if ($U['status'] == 1) {
   3789 	if ($ga === 2 || $ga === 3) {
   3790 		$stmt = $db->prepare('UPDATE ' . PREFIX . 'sessions SET entry=0 WHERE session=?;');
   3791 		$stmt->execute([$U['session']]);
   3792 		send_waiting_room();
   3793 	}
   3794 }
   3795 }
   3796 
   3797 function kill_session()
   3798 {
   3799 global $U, $db;
   3800 parse_sessions();
   3801 check_expired();
   3802 check_kicked();
   3803 setcookie(COOKIENAME, false);
   3804 $_REQUEST['session'] = '';
   3805 $stmt = $db->prepare('DELETE FROM ' . PREFIX . 'sessions WHERE session=?;');
   3806 $stmt->execute([$U['session']]);
   3807 
   3808 //Modification adminjoinleavemsg
   3809 if (($U['status'] >= 3 && $U['status'] <= 6 && !$U['incognito']) || ($U['status'] >= 7 && !$U['incognito'] && (bool) get_setting('adminjoinleavemsg'))) {
   3810 	//MODIFICATION for clickablenicknames stlye_this_clickable instead of style_this
   3811 	add_system_message(sprintf(get_setting('msgexit'), style_this_clickable(htmlspecialchars($U['nickname']), $U['style'])));
   3812 }
   3813 }
   3814 
   3815 function kick_chatter($names, $mes, $purge)
   3816 {
   3817 global $U, $db;
   3818 $lonick = '';
   3819 $time = 60 * (get_setting('kickpenalty') - get_setting('guestexpire')) + time();
   3820 $check = $db->prepare('SELECT style, entry FROM ' . PREFIX . 'sessions WHERE nickname=? AND status!=0 AND (status<? OR nickname=?);');
   3821 $stmt = $db->prepare('UPDATE ' . PREFIX . 'sessions SET lastpost=?, status=0, kickmessage=? WHERE nickname=?;');
   3822 $all = false;
   3823 if ($names[0] === 's &') {
   3824 	$tmp = $db->query('SELECT nickname FROM ' . PREFIX . 'sessions WHERE status=1;');
   3825 	$names = [];
   3826 	while ($name = $tmp->fetch(PDO::FETCH_NUM)) {
   3827 		$names[] = $name[0];
   3828 	}
   3829 	$all = true;
   3830 }
   3831 $i = 0;
   3832 foreach ($names as $name) {
   3833 	$check->execute([$name, $U['status'], $U['nickname']]);
   3834 	if ($temp = $check->fetch(PDO::FETCH_ASSOC)) {
   3835 		$stmt->execute([$time, $mes, $name]);
   3836 		if ($purge) {
   3837 			del_all_messages($name, $temp['entry']);
   3838 		}
   3839 		//MODIFICATION style_thins replaced with style_this_clickable
   3840 		$lonick .= style_this_clickable(htmlspecialchars($name), $temp['style']) . ', ';
   3841 		++$i;
   3842 	}
   3843 }
   3844 if ($i > 0) {
   3845 	if ($all) {
   3846 		add_system_message(get_setting('msgallkick'));
   3847 	} else {
   3848 		$lonick = substr($lonick, 0, -2);
   3849 		if ($i > 1) {
   3850 			add_system_message(sprintf(get_setting('msgmultikick'), $lonick));
   3851 		} else {
   3852 			add_system_message(sprintf(get_setting('msgkick'), $lonick));
   3853 		}
   3854 	}
   3855 	return true;
   3856 }
   3857 return false;
   3858 }
   3859 
   3860 function logout_chatter($names)
   3861 {
   3862 global $U, $db;
   3863 $stmt = $db->prepare('DELETE FROM ' . PREFIX . 'sessions WHERE nickname=? AND status<?;');
   3864 if ($names[0] === 's &') {
   3865 	$tmp = $db->query('SELECT nickname FROM ' . PREFIX . 'sessions WHERE status=1;');
   3866 	$names = [];
   3867 	while ($name = $tmp->fetch(PDO::FETCH_NUM)) {
   3868 		$names[] = $name[0];
   3869 	}
   3870 }
   3871 foreach ($names as $name) {
   3872 	$stmt->execute([$name, $U['status']]);
   3873 }
   3874 }
   3875 
   3876 function check_session()
   3877 {
   3878 global $U;
   3879 parse_sessions();
   3880 check_expired();
   3881 check_kicked();
   3882 if ($U['entry'] == 0) {
   3883 	send_waiting_room();
   3884 }
   3885 }
   3886 
   3887 function check_expired()
   3888 {
   3889 global $I, $U;
   3890 if (!isset($U['session'])) {
   3891 	setcookie(COOKIENAME, false);
   3892 	$_REQUEST['session'] = '';
   3893 	send_error($I['expire']);
   3894 }
   3895 }
   3896 
   3897 function get_count_mods()
   3898 {
   3899 global $db;
   3900 $c = $db->query('SELECT COUNT(*) FROM ' . PREFIX . 'sessions WHERE status>=5')->fetch(PDO::FETCH_NUM);
   3901 return $c[0];
   3902 }
   3903 
   3904 function check_kicked()
   3905 {
   3906 global $I, $U;
   3907 if ($U['status'] == 0) {
   3908 	setcookie(COOKIENAME, false);
   3909 	$_REQUEST['session'] = '';
   3910 	send_error("$I[kicked]<br>$U[kickmessage]");
   3911 }
   3912 }
   3913 
   3914 function get_nowchatting()
   3915 {
   3916 global $I, $db;
   3917 parse_sessions();
   3918 $stmt = $db->query('SELECT COUNT(*) FROM ' . PREFIX . 'sessions WHERE entry!=0 AND status>0 AND incognito=0;');
   3919 $count = $stmt->fetch(PDO::FETCH_NUM);
   3920 echo '<div id="chatters">' . sprintf($I['curchat'], $count[0]) . '<br>';
   3921 if (!get_setting('hidechatters')) {
   3922 
   3923 	//MODIFICATION hidden ranks on frontpage. Some lines changed and some lines added.
   3924 	$stmt = $db->query('SELECT nickname, style FROM ' . PREFIX . 'sessions WHERE entry!=0 AND status>=3 AND incognito=0 ORDER BY lastpost DESC;');
   3925 	while ($user = $stmt->fetch(PDO::FETCH_NUM)) {
   3926 		echo style_this(htmlspecialchars($user[0]), $user[1]) . ' &nbsp; ';
   3927 	}
   3928 
   3929 	$stmt = $db->query('SELECT nickname, style FROM ' . PREFIX . 'sessions WHERE entry!=0 AND status>0 AND status<3 AND incognito=0 ORDER BY status DESC, lastpost DESC;');
   3930 	while ($user = $stmt->fetch(PDO::FETCH_NUM)) {
   3931 		echo style_this(htmlspecialchars($user[0]), $user[1]) . ' &nbsp; ';
   3932 	}
   3933 }
   3934 
   3935 echo '</div>';
   3936 }
   3937 
   3938 function parse_sessions()
   3939 {
   3940 global $U, $db;
   3941 // look for our session
   3942 if (isset($_REQUEST['session'])) {
   3943 	$stmt = $db->prepare('SELECT * FROM ' . PREFIX . 'sessions WHERE session=?;');
   3944 	$stmt->execute([$_REQUEST['session']]);
   3945 	if ($tmp = $stmt->fetch(PDO::FETCH_ASSOC)) {
   3946 		$U = $tmp;
   3947 	}
   3948 }
   3949 set_default_tz();
   3950 }
   3951 
   3952 //  member handling
   3953 
   3954 function check_member($password)
   3955 {
   3956 global $I, $U, $db;
   3957 $stmt = $db->prepare('SELECT * FROM ' . PREFIX . 'members WHERE nickname=?;');
   3958 $stmt->execute([$U['nickname']]);
   3959 if ($temp = $stmt->fetch(PDO::FETCH_ASSOC)) {
   3960 	if (get_setting('dismemcaptcha') == 0) {
   3961 		check_captcha(isset($_REQUEST['challenge']) ? $_REQUEST['challenge'] : '', isset($_REQUEST['captcha']) ? $_REQUEST['captcha'] : '');
   3962 	}
   3963 	if ($temp['passhash'] === md5(sha1(md5($U['nickname'] . $password)))) {
   3964 		// old hashing method, update on the fly
   3965 		$temp['passhash'] = password_hash($password, PASSWORD_DEFAULT);
   3966 		$stmt = $db->prepare('UPDATE ' . PREFIX . 'members SET passhash=? WHERE nickname=?;');
   3967 		$stmt->execute([$temp['passhash'], $U['nickname']]);
   3968 	}
   3969 	if (password_verify($password, $temp['passhash'])) {
   3970 		$U = $temp;
   3971 		$stmt = $db->prepare('UPDATE ' . PREFIX . 'members SET lastlogin=? WHERE nickname=?;');
   3972 		$stmt->execute([time(), $U['nickname']]);
   3973 		return true;
   3974 	} else {
   3975 		send_error("$I[regednick]<br>$I[wrongpass]");
   3976 	}
   3977 }
   3978 return false;
   3979 }
   3980 
   3981 function delete_account()
   3982 {
   3983 global $U, $db;
   3984 if ($U['status'] < 8) {
   3985 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'sessions SET status=1, incognito=0 WHERE nickname=?;');
   3986 	$stmt->execute([$U['nickname']]);
   3987 	$stmt = $db->prepare('DELETE FROM ' . PREFIX . 'members WHERE nickname=?;');
   3988 	$stmt->execute([$U['nickname']]);
   3989 	$stmt = $db->prepare('DELETE FROM ' . PREFIX . 'inbox WHERE recipient=?;');
   3990 	$stmt->execute([$U['nickname']]);
   3991 	$stmt = $db->prepare('DELETE FROM ' . PREFIX . 'notes WHERE type=2 AND editedby=?;');
   3992 	$stmt->execute([$U['nickname']]);
   3993 	$U['status'] = 1;
   3994 }
   3995 }
   3996 
   3997 function register_guest($status, $nick)
   3998 {
   3999 global $I, $U, $db;
   4000 $stmt = $db->prepare('SELECT style FROM ' . PREFIX . 'members WHERE nickname=?');
   4001 $stmt->execute([$nick]);
   4002 if ($tmp = $stmt->fetch(PDO::FETCH_NUM)) {
   4003 	return sprintf($I['alreadyreged'], style_this(htmlspecialchars($nick), $tmp[0]));
   4004 }
   4005 $stmt = $db->prepare('SELECT * FROM ' . PREFIX . 'sessions WHERE nickname=? AND status=1;');
   4006 $stmt->execute([$nick]);
   4007 if ($reg = $stmt->fetch(PDO::FETCH_ASSOC)) {
   4008 	$reg['status'] = $status;
   4009 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'sessions SET status=? WHERE session=?;');
   4010 	$stmt->execute([$reg['status'], $reg['session']]);
   4011 } else {
   4012 	return sprintf($I['cantreg'], htmlspecialchars($nick));
   4013 }
   4014 
   4015 $stmt = $db->prepare('INSERT INTO ' . PREFIX . 'members (nickname, passhash, status, refresh, bgcolour, regedby, timestamps, embed, style, incognito, nocache, tz, eninbox, sortupdown, hidechatters, nocache_old) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);');
   4016 
   4017 //MODIFICATION for clickable nicknames
   4018 /* REMOVE LATER
   4019 $stmt=$db->prepare('INSERT INTO ' . PREFIX . 'members (nickname, passhash, status, refresh, bgcolour, regedby, timestamps, embed, style, incognito, nocache, tz, eninbox, sortupdown, hidechatters, clickablenicknames, nocache_old) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);');
   4020 */
   4021 
   4022 //MODIFICATION for clickable nicknames
   4023 /* REMOVE LATER
   4024 $stmt->execute([$reg['nickname'], $reg['passhash'], $reg['status'], $reg['refresh'], $reg['bgcolour'], $U['nickname'], $reg['timestamps'], $reg['embed'], $reg['style'], $reg['incognito'], $reg['nocache'], $reg['tz'], $reg['eninbox'], $reg['sortupdown'], $reg['hidechatters'], $reg['clickablenicknames'], $reg['nocache_old']]);
   4025 */
   4026 $stmt->execute([$reg['nickname'], $reg['passhash'], $reg['status'], $reg['refresh'], $reg['bgcolour'], $U['nickname'], $reg['timestamps'], $reg['embed'], $reg['style'], $reg['incognito'], $reg['nocache'], $reg['tz'], $reg['eninbox'], $reg['sortupdown'], $reg['hidechatters'], $reg['nocache_old']]);
   4027 if ($reg['status'] == 3) {
   4028 	//MODIFICATION stlye_this_clickable instead of style_this
   4029 	add_system_message(sprintf(get_setting('msgmemreg'), style_this_clickable(htmlspecialchars($reg['nickname']), $reg['style'])));
   4030 } else {
   4031 	//MODIFICATION stlye_this_clickable instead of style_this
   4032 	add_system_message(sprintf(get_setting('msgsureg'), style_this_clickable(htmlspecialchars($reg['nickname']), $reg['style'])));
   4033 }
   4034 return sprintf($I['successreg'], style_this(htmlspecialchars($reg['nickname']), $reg['style']));
   4035 }
   4036 
   4037 function register_new($nick, $pass)
   4038 {
   4039 global $I, $U, $db;
   4040 $nick = preg_replace('/\s/', '', $nick);
   4041 if (empty($nick)) {
   4042 	return '';
   4043 }
   4044 $stmt = $db->prepare('SELECT null FROM ' . PREFIX . 'sessions WHERE nickname=?');
   4045 $stmt->execute([$nick]);
   4046 if ($stmt->fetch(PDO::FETCH_NUM)) {
   4047 	return sprintf($I['cantreg'], htmlspecialchars($nick));
   4048 }
   4049 if (!valid_nick($nick)) {
   4050 	return sprintf($I['invalnick'], get_setting('maxname'), get_setting('nickregex'));
   4051 }
   4052 if (!valid_pass($pass)) {
   4053 	return sprintf($I['invalpass'], get_setting('minpass'), get_setting('passregex'));
   4054 }
   4055 $stmt = $db->prepare('SELECT null FROM ' . PREFIX . 'members WHERE nickname=?');
   4056 $stmt->execute([$nick]);
   4057 if ($stmt->fetch(PDO::FETCH_NUM)) {
   4058 	return sprintf($I['alreadyreged'], htmlspecialchars($nick));
   4059 }
   4060 
   4061 $reg = [
   4062 	'nickname'	=> $nick,
   4063 	'passhash'	=> password_hash($pass, PASSWORD_DEFAULT),
   4064 	//Modification Register new Applicant
   4065 	'status'	=> (get_setting('suguests') ? 2 : 3),
   4066 
   4067 	'refresh'	=> get_setting('defaultrefresh'),
   4068 	'bgcolour'	=> get_setting('colbg'),
   4069 	'regedby'	=> $U['nickname'],
   4070 	'timestamps'	=> get_setting('timestamps'),
   4071 	'style'		=> 'color:#' . get_setting('coltxt') . ';',
   4072 	'embed'		=> 1,
   4073 	'incognito'	=> 0,
   4074 	'nocache'	=> 0,
   4075 	'nocache_old'	=> 1,
   4076 	'tz'		=> get_setting('defaulttz'),
   4077 	'eninbox'	=> 0,
   4078 	'sortupdown'	=> get_setting('sortupdown'),
   4079 	'hidechatters'	=> get_setting('hidechatters'),
   4080 
   4081 	//MODIFICATION clickable nicknames
   4082 	/* REMOVE LATER
   4083 	'clickablenicknames'	=>0,
   4084 	*/
   4085 ];
   4086 /*REMOVE LATER
   4087    $stmt=$db->prepare('INSERT INTO ' . PREFIX . 'members (nickname, passhash, status, refresh, bgcolour, regedby, timestamps, style, embed, incognito, nocache, tz, eninbox, sortupdown, hidechatters, clickablenicknames, nocache_old) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);');
   4088 */
   4089 $stmt = $db->prepare('INSERT INTO ' . PREFIX . 'members (nickname, passhash, status, refresh, bgcolour, regedby, timestamps, style, embed, incognito, nocache, tz, eninbox, sortupdown, hidechatters, nocache_old) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);');
   4090 $stmt->execute([$reg['nickname'], $reg['passhash'], $reg['status'], $reg['refresh'], $reg['bgcolour'], $reg['regedby'], $reg['timestamps'], $reg['style'], $reg['embed'], $reg['incognito'], $reg['nocache'], $reg['tz'], $reg['eninbox'], $reg['sortupdown'], $reg['hidechatters'], $reg['nocache_old']]);
   4091 return sprintf($I['successreg'], htmlspecialchars($reg['nickname']));
   4092 }
   4093 
   4094 function change_status($nick, $status)
   4095 {
   4096 global $I, $U, $db;
   4097 if (empty($nick)) {
   4098 	return '';
   4099 } elseif ($U['status'] <= $status || !preg_match('/^[023567\-]$/', $status)) {
   4100 	return sprintf($I['cantchgstat'], htmlspecialchars($nick));
   4101 }
   4102 $stmt = $db->prepare('SELECT incognito, style FROM ' . PREFIX . 'members WHERE nickname=? AND status<?;');
   4103 $stmt->execute([$nick, $U['status']]);
   4104 if (!$old = $stmt->fetch(PDO::FETCH_NUM)) {
   4105 	return sprintf($I['cantchgstat'], htmlspecialchars($nick));
   4106 }
   4107 if ($_REQUEST['set'] === '-') {
   4108 	$stmt = $db->prepare('DELETE FROM ' . PREFIX . 'members WHERE nickname=?;');
   4109 	$stmt->execute([$nick]);
   4110 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'sessions SET status=1, incognito=0 WHERE nickname=?;');
   4111 	$stmt->execute([$nick]);
   4112 	return sprintf($I['succdel'], style_this(htmlspecialchars($nick), $old[1]));
   4113 } else {
   4114 	if ($status < 5) {
   4115 		$old[0] = 0;
   4116 	}
   4117 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'members SET status=?, incognito=? WHERE nickname=?;');
   4118 	$stmt->execute([$status, $old[0], $nick]);
   4119 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'sessions SET status=?, incognito=? WHERE nickname=?;');
   4120 	$stmt->execute([$status, $old[0], $nick]);
   4121 	return sprintf($I['succchg'], style_this(htmlspecialchars($nick), $old[1]));
   4122 }
   4123 }
   4124 
   4125 function passreset($nick, $pass)
   4126 {
   4127 global $I, $U, $db;
   4128 if (empty($nick)) {
   4129 	return '';
   4130 }
   4131 $stmt = $db->prepare('SELECT null FROM ' . PREFIX . 'members WHERE nickname=? AND status<?;');
   4132 $stmt->execute([$nick, $U['status']]);
   4133 if ($stmt->fetch(PDO::FETCH_ASSOC)) {
   4134 	$passhash = password_hash($pass, PASSWORD_DEFAULT);
   4135 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'members SET passhash=? WHERE nickname=?;');
   4136 	$stmt->execute([$passhash, $nick]);
   4137 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'sessions SET passhash=? WHERE nickname=?;');
   4138 	$stmt->execute([$passhash, $nick]);
   4139 	return sprintf($I['succpassreset'], htmlspecialchars($nick));
   4140 } else {
   4141 	return sprintf($I['cantresetpass'], htmlspecialchars($nick));
   4142 }
   4143 }
   4144 
   4145 function amend_profile()
   4146 {
   4147 global $U;
   4148 if (isset($_REQUEST['refresh'])) {
   4149 	$U['refresh'] = $_REQUEST['refresh'];
   4150 }
   4151 if ($U['refresh'] < 5) {
   4152 	$U['refresh'] = 5;
   4153 } elseif ($U['refresh'] > 150) {
   4154 	$U['refresh'] = 150;
   4155 }
   4156 if (preg_match('/^#([a-f0-9]{6})$/i', $_REQUEST['colour'], $match)) {
   4157 	$colour = $match[1];
   4158 } else {
   4159 	preg_match('/#([0-9a-f]{6})/i', $U['style'], $matches);
   4160 	$colour = $matches[1];
   4161 }
   4162 if (preg_match('/^#([a-f0-9]{6})$/i', $_REQUEST['bgcolour'], $match)) {
   4163 	$U['bgcolour'] = $match[1];
   4164 }
   4165 $U['style'] = "color:#$colour;";
   4166 if ($U['status'] >= 3) {
   4167 	$F = load_fonts();
   4168 	if (isset($F[$_REQUEST['font']])) {
   4169 		$U['style'] .= $F[$_REQUEST['font']];
   4170 	}
   4171 	if (isset($_REQUEST['small'])) {
   4172 		$U['style'] .= 'font-size:smaller;';
   4173 	}
   4174 	if (isset($_REQUEST['italic'])) {
   4175 		$U['style'] .= 'font-style:italic;';
   4176 	}
   4177 	if (isset($_REQUEST['bold'])) {
   4178 		$U['style'] .= 'font-weight:bold;';
   4179 	}
   4180 }
   4181 if ($U['status'] >= 5 && isset($_REQUEST['incognito']) && get_setting('incognito')) {
   4182 	$U['incognito'] = 1;
   4183 } else {
   4184 	$U['incognito'] = 0;
   4185 }
   4186 if (isset($_REQUEST['tz'])) {
   4187 	$tzs = timezone_identifiers_list();
   4188 	if (in_array($_REQUEST['tz'], $tzs)) {
   4189 		$U['tz'] = $_REQUEST['tz'];
   4190 	}
   4191 }
   4192 
   4193 //MODIFICATION for clicable nicknames setting
   4194 /* REMOVE LATER
   4195 $clickablelinks_allowedvalues = array(0, 1, 2);
   4196 if(isset($_REQUEST['clickablenicknames']) && in_array($_REQUEST['clickablenicknames'], $clickablelinks_allowedvalues)){
   4197 		$U['clickablenicknames'] = (int) $_REQUEST['clickablenicknames'];
   4198    }
   4199 */
   4200 
   4201 if (isset($_REQUEST['eninbox']) && $_REQUEST['eninbox'] >= 0 && $_REQUEST['eninbox'] <= 5) {
   4202 	$U['eninbox'] = $_REQUEST['eninbox'];
   4203 }
   4204 $bool_settings = ['timestamps', 'embed', 'nocache', 'sortupdown', 'hidechatters'];
   4205 foreach ($bool_settings as $setting) {
   4206 	if (isset($_REQUEST[$setting])) {
   4207 		$U[$setting] = 1;
   4208 	} else {
   4209 		$U[$setting] = 0;
   4210 	}
   4211 }
   4212 }
   4213 
   4214 function save_profile()
   4215 {
   4216 global $I, $U, $db;
   4217 amend_profile();
   4218 //MODIFICATION for clickable nicknames setting
   4219 /* REMOVE LATER
   4220 $stmt=$db->prepare('UPDATE ' . PREFIX . 'sessions SET refresh=?, style=?, bgcolour=?, timestamps=?, embed=?, incognito=?, nocache=?, tz=?, eninbox=?, sortupdown=?, hidechatters=?, clickablenicknames=? WHERE session=?;');
   4221 */
   4222 $stmt = $db->prepare('UPDATE ' . PREFIX . 'sessions SET refresh=?, style=?, bgcolour=?, timestamps=?, embed=?, incognito=?, nocache=?, tz=?, eninbox=?, sortupdown=?, hidechatters=? WHERE session=?;');
   4223 
   4224 //MODIFICATION for clickable nicknames (clickablenicknames)
   4225 /* REMOVE LATER
   4226 $stmt->execute([$U['refresh'], $U['style'], $U['bgcolour'], $U['timestamps'], $U['embed'], $U['incognito'], $U['nocache'], $U['tz'], $U['eninbox'], $U['sortupdown'], $U['hidechatters'], $U['clickablenicknames'], $U['session']]);
   4227 */
   4228 $stmt->execute([$U['refresh'], $U['style'], $U['bgcolour'], $U['timestamps'], $U['embed'], $U['incognito'], $U['nocache'], $U['tz'], $U['eninbox'], $U['sortupdown'], $U['hidechatters'], $U['session']]);
   4229 
   4230 if ($U['status'] >= 2) {
   4231 	/* REMOVE LATER
   4232 	$stmt=$db->prepare('UPDATE ' . PREFIX . 'members SET refresh=?, bgcolour=?, timestamps=?, embed=?, incognito=?, style=?, nocache=?, tz=?, eninbox=?, sortupdown=?, hidechatters=?, clickablenicknames=? WHERE nickname=?;');
   4233 	$stmt->execute([$U['refresh'], $U['bgcolour'], $U['timestamps'], $U['embed'], $U['incognito'], $U['style'], $U['nocache'], $U['tz'], $U['eninbox'], $U['sortupdown'], $U['hidechatters'], $U['clickablenicknames'], $U['nickname']]);
   4234    */
   4235 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'members SET refresh=?, bgcolour=?, timestamps=?, embed=?, incognito=?, style=?, nocache=?, tz=?, eninbox=?, sortupdown=?, hidechatters=? WHERE nickname=?;');
   4236 	$stmt->execute([$U['refresh'], $U['bgcolour'], $U['timestamps'], $U['embed'], $U['incognito'], $U['style'], $U['nocache'], $U['tz'], $U['eninbox'], $U['sortupdown'], $U['hidechatters'], $U['nickname']]);
   4237 }
   4238 if (!empty($_REQUEST['unignore'])) {
   4239 	$stmt = $db->prepare('DELETE FROM ' . PREFIX . 'ignored WHERE ign=? AND ignby=?;');
   4240 	$stmt->execute([$_REQUEST['unignore'], $U['nickname']]);
   4241 }
   4242 if (!empty($_REQUEST['ignore'])) {
   4243 	$stmt = $db->prepare('SELECT null FROM ' . PREFIX . 'messages WHERE poster=? AND poster NOT IN (SELECT ign FROM ' . PREFIX . 'ignored WHERE ignby=?);');
   4244 	$stmt->execute([$_REQUEST['ignore'], $U['nickname']]);
   4245 	if ($U['nickname'] !== $_REQUEST['ignore'] && $stmt->fetch(PDO::FETCH_NUM)) {
   4246 		$stmt = $db->prepare('INSERT INTO ' . PREFIX . 'ignored (ign, ignby) VALUES (?, ?);');
   4247 		$stmt->execute([$_REQUEST['ignore'], $U['nickname']]);
   4248 	}
   4249 }
   4250 if ($U['status'] > 1 && !empty($_REQUEST['newpass'])) {
   4251 	if (!valid_pass($_REQUEST['newpass'])) {
   4252 		return sprintf($I['invalpass'], get_setting('minpass'), get_setting('passregex'));
   4253 	}
   4254 	if (!isset($_REQUEST['oldpass'])) {
   4255 		$_REQUEST['oldpass'] = '';
   4256 	}
   4257 	if (!isset($_REQUEST['confirmpass'])) {
   4258 		$_REQUEST['confirmpass'] = '';
   4259 	}
   4260 	if ($_REQUEST['newpass'] !== $_REQUEST['confirmpass']) {
   4261 		return $I['noconfirm'];
   4262 	} else {
   4263 		$U['newhash'] = password_hash($_REQUEST['newpass'], PASSWORD_DEFAULT);
   4264 	}
   4265 	if (!password_verify($_REQUEST['oldpass'], $U['passhash'])) {
   4266 		return $I['wrongpass'];
   4267 	}
   4268 	$U['passhash'] = $U['newhash'];
   4269 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'sessions SET passhash=? WHERE session=?;');
   4270 	$stmt->execute([$U['passhash'], $U['session']]);
   4271 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'members SET passhash=? WHERE nickname=?;');
   4272 	$stmt->execute([$U['passhash'], $U['nickname']]);
   4273 }
   4274 if ($U['status'] > 1 && !empty($_REQUEST['newnickname'])) {
   4275 	$msg = set_new_nickname();
   4276 	if ($msg !== '') {
   4277 		return $msg;
   4278 	}
   4279 }
   4280 return $I['succprofile'];
   4281 }
   4282 
   4283 function set_new_nickname()
   4284 {
   4285 global $I, $U, $db;
   4286 $_REQUEST['newnickname'] = preg_replace('/\s/', '', $_REQUEST['newnickname']);
   4287 if (!valid_nick($_REQUEST['newnickname'])) {
   4288 	return sprintf($I['invalnick'], get_setting('maxname'), get_setting('nickregex'));
   4289 }
   4290 $stmt = $db->prepare('SELECT id FROM ' . PREFIX . 'sessions WHERE nickname=? UNION SELECT id FROM ' . PREFIX . 'members WHERE nickname=?;');
   4291 $stmt->execute([$_REQUEST['newnickname'], $_REQUEST['newnickname']]);
   4292 if ($stmt->fetch(PDO::FETCH_NUM)) {
   4293 	return $I['nicknametaken'];
   4294 } else {
   4295 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'members SET nickname=? WHERE nickname=?;');
   4296 	$stmt->execute([$_REQUEST['newnickname'], $U['nickname']]);
   4297 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'sessions SET nickname=? WHERE nickname=?;');
   4298 	$stmt->execute([$_REQUEST['newnickname'], $U['nickname']]);
   4299 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'messages SET poster=? WHERE poster=?;');
   4300 	$stmt->execute([$_REQUEST['newnickname'], $U['nickname']]);
   4301 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'messages SET recipient=? WHERE recipient=?;');
   4302 	$stmt->execute([$_REQUEST['newnickname'], $U['nickname']]);
   4303 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'ignored SET ignby=? WHERE ignby=?;');
   4304 	$stmt->execute([$_REQUEST['newnickname'], $U['nickname']]);
   4305 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'ignored SET ign=? WHERE ign=?;');
   4306 	$stmt->execute([$_REQUEST['newnickname'], $U['nickname']]);
   4307 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'inbox SET poster=? WHERE poster=?;');
   4308 	$stmt->execute([$_REQUEST['newnickname'], $U['nickname']]);
   4309 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'notes SET editedby=? WHERE editedby=?;');
   4310 	$stmt->execute([$_REQUEST['newnickname'], $U['nickname']]);
   4311 	$U['nickname'] = $_REQUEST['newnickname'];
   4312 }
   4313 return '';
   4314 }
   4315 
   4316 //sets default settings for guests
   4317 function add_user_defaults($password)
   4318 {
   4319 global $U;
   4320 $U['refresh'] = get_setting('defaultrefresh');
   4321 $U['bgcolour'] = get_setting('colbg');
   4322 if (!isset($_REQUEST['colour']) || !preg_match('/^[a-f0-9]{6}$/i', $_REQUEST['colour']) || abs(greyval($_REQUEST['colour']) - greyval(get_setting('colbg'))) < 75) {
   4323 	do {
   4324 		$colour = sprintf('%06X', mt_rand(0, 16581375));
   4325 	} while (abs(greyval($colour) - greyval(get_setting('colbg'))) < 75);
   4326 } else {
   4327 	$colour = $_REQUEST['colour'];
   4328 }
   4329 $U['style'] = "color:#$colour;";
   4330 $U['timestamps'] = get_setting('timestamps');
   4331 $U['embed'] = 1;
   4332 $U['incognito'] = 0;
   4333 $U['status'] = 1;
   4334 $U['nocache'] = get_setting('sortupdown');
   4335 if ($U['nocache']) {
   4336 	$U['nocache_old'] = 0;
   4337 } else {
   4338 	$U['nocache_old'] = 1;
   4339 }
   4340 $U['tz'] = get_setting('defaulttz');
   4341 $U['eninbox'] = 1;
   4342 $U['sortupdown'] = get_setting('sortupdown');
   4343 $U['hidechatters'] = get_setting('hidechatters');
   4344 $U['passhash'] = password_hash($password, PASSWORD_DEFAULT);
   4345 $U['entry'] = $U['lastpost'] = time();
   4346 
   4347 //MODIFICATION for clickable nicknames
   4348 /* REMOVE LATER
   4349 $U['clickablenicknames']=0;
   4350 */
   4351 }
   4352 
   4353 // message handling
   4354 
   4355 function validate_input()
   4356 {
   4357 //global $U, $db;
   4358 global $U, $db, $language;
   4359 
   4360 $inbox = false;
   4361 $maxmessage = get_setting('maxmessage');
   4362 $message = mb_substr($_REQUEST['message'], 0, $maxmessage);
   4363 $rejected = mb_substr($_REQUEST['message'], $maxmessage);
   4364 if ($U['postid'] === $_REQUEST['postid']) { // ignore double post=reload from browser or proxy
   4365 	$message = '';
   4366 } elseif ((time() - $U['lastpost']) <= 1) { // time between posts too short, reject!
   4367 	$rejected = $_REQUEST['message'];
   4368 	$message = '';
   4369 }
   4370 if (!empty($rejected)) {
   4371 	$rejected = trim($rejected);
   4372 	$rejected = htmlspecialchars($rejected);
   4373 }
   4374 $message = htmlspecialchars($message);
   4375 $message = preg_replace("/(\r?\n|\r\n?)/u", '<br>', $message);
   4376 if (isset($_REQUEST['multi'])) {
   4377 	$message = preg_replace('/\s*<br>/u', '<br>', $message);
   4378 	$message = preg_replace('/<br>(<br>)+/u', '<br><br>', $message);
   4379 	$message = preg_replace('/<br><br>\s*$/u', '<br>', $message);
   4380 	$message = preg_replace('/^<br>\s*$/u', '', $message);
   4381 } else {
   4382 	$message = str_replace('<br>', ' ', $message);
   4383 }
   4384 $message = trim($message);
   4385 $message = preg_replace('/\s+/u', ' ', $message);
   4386 $recipient = '';
   4387 
   4388 //This ist the the place where the username is added to $displaysend (and later to the message).
   4389 
   4390 /*
   4391 	'r @'
   4392        's 17'
   4393        's 24'
   4394        's 31'
   4395        's 48'
   4396        's 56'
   4397        's 65'
   4398 */
   4399 
   4400 if ($_REQUEST['sendto'] === 's 17') {
   4401 	$poststatus = 1;
   4402 	//MODIFICATION for clickablenicknames stlye_this_clickable instead of style_this
   4403 	$displaysend = sprintf(get_setting('msgsendall'), style_this_clickable(htmlspecialchars($U['nickname']), $U['style']));
   4404 	//MODIFICATION 3 lines added for the RG channel
   4405 } elseif ($_REQUEST['sendto'] === 's 24' && $U['status'] >= 2) {
   4406 	$poststatus = 2;
   4407 	//MODIFICATION for clickablenicknames stlye_this_clickable instead of style_this
   4408 	$displaysend = sprintf('[RG] %s - ', style_this_clickable(htmlspecialchars($U['nickname']), $U['style']));
   4409 } elseif ($_REQUEST['sendto'] === 's 31' && $U['status'] >= 3) {
   4410 	$poststatus = 3;
   4411 	//MODIFICATION for clickablenicknames stlye_this_clickable instead of style_this
   4412 	$displaysend = sprintf(get_setting('msgsendmem'), style_this_clickable(htmlspecialchars($U['nickname']), $U['style']));
   4413 } elseif ($_REQUEST['sendto'] === 's 48' && $U['status'] >= 5) {
   4414 	$poststatus = 5;
   4415 	//MODIFICATION for clickablenicknames stlye_this_clickable instead of style_this
   4416 	$displaysend = sprintf(get_setting('msgsendmod'), style_this_clickable(htmlspecialchars($U['nickname']), $U['style']));
   4417 	// Modifcation added all rooms channel
   4418 } elseif ($_REQUEST['sendto'] === 'r @' && $U['status'] >= 5) {
   4419 	$poststatus = 1;
   4420 	$displaysend = sprintf('[All Rooms] %s - ', style_this_clickable(htmlspecialchars($U['nickname']), $U['style']));
   4421 	//MODIFICATION 1 line replaced for the new SMod channel ([SMods] in front of the line.
   4422 } elseif ($_REQUEST['sendto'] === 's 56' && $U['status'] >= 6) {
   4423 	$poststatus = 6;
   4424 	//MODIFICATION for clickablenicknames stlye_this_clickable instead of style_this
   4425 	$displaysend = sprintf('[SMods] %s - ', style_this_clickable(htmlspecialchars($U['nickname']), $U['style']));
   4426 
   4427 	//MODIFICATION 3 lines added for the new admin channel (admins only, no smods)
   4428 } elseif ($_REQUEST['sendto'] === 's 65' && $U['status'] >= 7) {
   4429 	$poststatus = 7;
   4430 	//MODIFICATION for clickablenicknames stlye_this_clickable instead of style_this
   4431 	$displaysend = sprintf(get_setting('msgsendadm'), style_this_clickable(htmlspecialchars($U['nickname']), $U['style']));
   4432 } else { // known nick in room?
   4433 	if (get_setting('disablepm')) {
   4434 		//PMs disabled
   4435 		return;
   4436 	}
   4437 	$stmt = $db->prepare('SELECT null FROM ' . PREFIX . 'ignored WHERE (ignby=? AND ign=?) OR (ign=? AND ignby=?);');
   4438 	$stmt->execute([$_REQUEST['sendto'], $U['nickname'], $_REQUEST['sendto'], $U['nickname']]);
   4439 	if ($stmt->fetch(PDO::FETCH_NUM)) {
   4440 		//ignored
   4441 		return;
   4442 	}
   4443 	$tmp = false;
   4444 	$stmt = $db->prepare('SELECT s.style, 0 AS inbox FROM ' . PREFIX . 'sessions AS s LEFT JOIN ' . PREFIX . 'members AS m ON (m.nickname=s.nickname) WHERE s.nickname=? AND (s.incognito=0 OR (m.eninbox!=0 AND m.eninbox<=?));');
   4445 	$stmt->execute([$_REQUEST['sendto'], $U['status']]);
   4446 	if (!$tmp = $stmt->fetch(PDO::FETCH_ASSOC)) {
   4447 		$stmt = $db->prepare('SELECT style, 1 AS inbox FROM ' . PREFIX . 'members WHERE nickname=? AND eninbox!=0 AND eninbox<=?;');
   4448 		$stmt->execute([$_REQUEST['sendto'], $U['status']]);
   4449 		if (!$tmp = $stmt->fetch(PDO::FETCH_ASSOC)) {
   4450 			//nickname left or disabled offline inbox for us
   4451 			return;
   4452 		}
   4453 	}
   4454 	$recipient = $_REQUEST['sendto'];
   4455 	$poststatus = 9;
   4456 
   4457 	$displaysend = sprintf(get_setting('msgsendprv'), style_this_clickable(htmlspecialchars($U['nickname']), $U['style']), style_this_clickable(htmlspecialchars($recipient), $tmp['style']));
   4458 	$inbox = $tmp['inbox'];
   4459 }
   4460 if ($poststatus !== 9 && preg_match('~^/me~iu', $message)) {
   4461 	$displaysend = style_this(htmlspecialchars("$U[nickname] "), $U['style']);
   4462 	$message = preg_replace("~^/me\s?~iu", '', $message);
   4463 }
   4464 $message = apply_filter($message, $poststatus, $U['nickname']);
   4465 $message = create_hotlinks($message);
   4466 $message = apply_linkfilter($message);
   4467 if (isset($_FILES['file']) && get_setting('enfileupload') > 0 && get_setting('enfileupload') <= $U['status']) {
   4468 	if ($_FILES['file']['error'] === UPLOAD_ERR_OK && $_FILES['file']['size'] <= (1024 * get_setting('maxuploadsize'))) {
   4469 		$hash = sha1_file($_FILES['file']['tmp_name']);
   4470 		$name = htmlspecialchars($_FILES['file']['name']);
   4471 		$message = sprintf(get_setting('msgattache'), "<a class=\"attachement\" href=\"?action=download&amp;id=$hash\" target=\"_blank\">$name</a>", $message);
   4472 	}
   4473 }
   4474 if (add_message($message, $recipient, $U['nickname'], $U['status'], $poststatus, $displaysend, $U['style'])) {
   4475 	$U['lastpost'] = time();
   4476 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'sessions SET lastpost=?, postid=? WHERE session=?;');
   4477 	$stmt->execute([$U['lastpost'], $_REQUEST['postid'], $U['session']]);
   4478 	$stmt = $db->prepare('SELECT id FROM ' . PREFIX . 'messages WHERE poster=? ORDER BY id DESC LIMIT 1;');
   4479 	$stmt->execute([$U['nickname']]);
   4480 	$id = $stmt->fetch(PDO::FETCH_NUM);
   4481 	if ($inbox && $id) {
   4482 		$newmessage = [
   4483 			'postdate'	=> time(),
   4484 			'poster'	=> $U['nickname'],
   4485 			'recipient'	=> $recipient,
   4486 
   4487 			'text'		=> "<span class=\"usermsg\">$displaysend" . style_this($message, $U['style']) . '</span>'
   4488 		];
   4489 		if (MSGENCRYPTED) {
   4490 			$newmessage['text'] = base64_encode(sodium_crypto_aead_aes256gcm_encrypt($newmessage['text'], '', AES_IV, ENCRYPTKEY));
   4491 		}
   4492 		$stmt = $db->prepare('INSERT INTO ' . PREFIX . 'inbox (postdate, postid, poster, recipient, text) VALUES(?, ?, ?, ?, ?)');
   4493 		$stmt->execute([$newmessage['postdate'], $id[0], $newmessage['poster'], $newmessage['recipient'], $newmessage['text']]);
   4494 	}
   4495 	if (isset($hash) && $id) {
   4496 		if (!empty($_FILES['file']['type']) && preg_match('~^[a-z0-9/\-\.\+]*$~i', $_FILES['file']['type'])) {
   4497 			$type = $_FILES['file']['type'];
   4498 		} else {
   4499 			$type = 'application/octet-stream';
   4500 		}
   4501 		$stmt = $db->prepare('INSERT INTO ' . PREFIX . 'files (postid, hash, filename, type, data) VALUES (?, ?, ?, ?, ?);');
   4502 		$stmt->execute([$id[0], $hash, str_replace('"', '\"', $_FILES['file']['name']), $type, base64_encode(file_get_contents($_FILES['file']['tmp_name']))]);
   4503 		unlink($_FILES['file']['tmp_name']);
   4504 	}
   4505 }
   4506 return $rejected;
   4507 }
   4508 
   4509 function apply_filter($message, $poststatus, $nickname)
   4510 {
   4511 global $I, $U;
   4512 $message = str_replace('<br>', "\n", $message);
   4513 $message = apply_mention($message);
   4514 $filters = get_filters();
   4515 foreach ($filters as $filter) {
   4516 	//MODIFICATION line changed (! removed)
   4517 	if ($poststatus !== 9 || $filter['allowinpm']) {
   4518 		if ($filter['cs']) {
   4519 			$message = preg_replace("/$filter[match]/u", $filter['replace'], $message, -1, $count);
   4520 		} else {
   4521 			$message = preg_replace("/$filter[match]/iu", $filter['replace'], $message, -1, $count);
   4522 		}
   4523 	}
   4524 	if (isset($count) && $count > 0 && $filter['kick'] && ($U['status'] < 5 || get_setting('filtermodkick'))) {
   4525 		kick_chatter([$nickname], $filter['replace'], false);
   4526 		setcookie(COOKIENAME, false);
   4527 		$_REQUEST['session'] = '';
   4528 		send_error("$I[kicked]<br>$filter[replace]");
   4529 	}
   4530 }
   4531 $message = str_replace("\n", '<br>', $message);
   4532 return $message;
   4533 }
   4534 
   4535 function apply_linkfilter($message)
   4536 {
   4537 $filters = get_linkfilters();
   4538 foreach ($filters as $filter) {
   4539 	$message = preg_replace_callback(
   4540 		"/<a href=\"([^\"]+)\" target=\"_blank\"( rel=\"noreferrer noopener\")?>(.*?(?=<\/a>))<\/a>/iu",
   4541 		function ($matched) use (&$filter) {
   4542 			return "<a href=\"$matched[1]\" target=\"_blank\"$matched[2]>" . preg_replace("/$filter[match]/iu", $filter['replace'], $matched[3]) . '</a>';
   4543 		},
   4544 		$message
   4545 	);
   4546 }
   4547 $redirect = get_setting('redirect');
   4548 if (get_setting('imgembed')) {
   4549 	$message = preg_replace_callback(
   4550 		'/\[img\]\s?<a href="([^"]+)" target="_blank"( rel=\"noreferrer noopener\")?>(.*?(?=<\/a>))<\/a>/iu',
   4551 		function ($matched) {
   4552 			return str_ireplace('[/img]', '', "<br><a href=\"$matched[1]\" target=\"_blank\"$matched[2]><img src=\"$matched[1]\"></a><br>");
   4553 		},
   4554 		$message
   4555 	);
   4556 }
   4557 if (empty($redirect)) {
   4558 	$redirect = "?action=redirect&amp;url=";
   4559 }
   4560 if (get_setting('forceredirect')) {
   4561 	$message = preg_replace_callback(
   4562 		'/<a href="([^"]+)" target="_blank"( rel=\"noreferrer noopener\")?>(.*?(?=<\/a>))<\/a>/u',
   4563 		function ($matched) use ($redirect) {
   4564 			return "<a href=\"$redirect" . rawurlencode($matched[1]) . "\" target=\"_blank\"$matched[2]>$matched[3]</a>";
   4565 		},
   4566 		$message
   4567 	);
   4568 } elseif (preg_match_all('/<a href="([^"]+)" target="_blank"( rel=\"noreferrer noopener\")?>(.*?(?=<\/a>))<\/a>/u', $message, $matches)) {
   4569 	foreach ($matches[1] as $match) {
   4570 		if (!preg_match('~^http(s)?://~u', $match)) {
   4571 			$message = preg_replace_callback(
   4572 				'/<a href="(' . preg_quote($match, '/') . ')\" target=\"_blank\"( rel=\"noreferrer noopener\")?>(.*?(?=<\/a>))<\/a>/u',
   4573 				function ($matched) use ($redirect) {
   4574 					return "<a href=\"$redirect" . rawurlencode($matched[1]) . "\" target=\"_blank\"$matched[2]>$matched[3]</a>";
   4575 				},
   4576 				$message
   4577 			);
   4578 		}
   4579 	}
   4580 }
   4581 return $message;
   4582 }
   4583 
   4584 function create_hotlinks($message)
   4585 {
   4586 //Make hotlinks for URLs, redirect through dereferrer script to prevent session leakage
   4587 // 1. all explicit schemes with whatever xxx://yyyyyyy
   4588 $message = preg_replace('~(^|[^\w"])(\w+://[^\s<>]+)~iu', "$1<<$2>>", $message);
   4589 // 2. valid URLs without scheme:
   4590 $message = preg_replace('~((?:[^\s<>]*:[^\s<>]*@)?[a-z0-9\-]+(?:\.[a-z0-9\-]+)+(?::\d*)?/[^\s<>]*)(?![^<>]*>)~iu', "<<$1>>", $message); // server/path given
   4591 $message = preg_replace('~((?:[^\s<>]*:[^\s<>]*@)?[a-z0-9\-]+(?:\.[a-z0-9\-]+)+:\d+)(?![^<>]*>)~iu', "<<$1>>", $message); // server:port given
   4592 $message = preg_replace('~([^\s<>]*:[^\s<>]*@[a-z0-9\-]+(?:\.[a-z0-9\-]+)+(?::\d+)?)(?![^<>]*>)~iu', "<<$1>>", $message); // au:th@server given
   4593 // 3. likely servers without any hints but not filenames like *.rar zip exe etc.
   4594 $message = preg_replace('~((?:[a-z0-9\-]+\.)*(?:[a-z2-7]{55}d|[a-z2-7]{16})\.onion)(?![^<>]*>)~iu', "<<$1>>", $message); // *.onion
   4595 $message = preg_replace('~([a-z0-9\-]+(?:\.[a-z0-9\-]+)+(?:\.(?!rar|zip|exe|gz|7z|bat|doc)[a-z]{2,}))(?=[^a-z0-9\-\.]|$)(?![^<>]*>)~iu', "<<$1>>", $message); // xxx.yyy.zzz
   4596 // Convert every <<....>> into proper links:
   4597 $message = preg_replace_callback(
   4598 	'/<<([^<>]+)>>/u',
   4599 	function ($matches) {
   4600 		if (strpos($matches[1], '://') === false) {
   4601 			return "<a href=\"http://$matches[1]\" target=\"_blank\" rel=\"noreferrer noopener\">$matches[1]</a>";
   4602 		} else {
   4603 			return "<a href=\"$matches[1]\" target=\"_blank\" rel=\"noreferrer noopener\">$matches[1]</a>";
   4604 		}
   4605 	},
   4606 	$message
   4607 );
   4608 return $message;
   4609 }
   4610 
   4611 function apply_mention($message)
   4612 {
   4613 return preg_replace_callback('/\@([^\s]+)/iu', function ($matched) {
   4614 	global $db;
   4615 	$nick = htmlspecialchars_decode($matched[1]);
   4616 	$rest = '';
   4617 	for ($i = 0; $i <= 3; ++$i) {
   4618 		//match case-sensitive present nicknames
   4619 		$stmt = $db->prepare('SELECT style FROM ' . PREFIX . 'sessions WHERE nickname=?;');
   4620 		$stmt->execute([$nick]);
   4621 		if ($tmp = $stmt->fetch(PDO::FETCH_NUM)) {
   4622 			return style_this(htmlspecialchars("@$nick"), $tmp[0]) . $rest;
   4623 		}
   4624 		//match case-insensitive present nicknames
   4625 		$stmt = $db->prepare('SELECT style FROM ' . PREFIX . 'sessions WHERE LOWER(nickname)=LOWER(?);');
   4626 		$stmt->execute([$nick]);
   4627 		if ($tmp = $stmt->fetch(PDO::FETCH_NUM)) {
   4628 			return style_this(htmlspecialchars("@$nick"), $tmp[0]) . $rest;
   4629 		}
   4630 		//match case-sensitive members
   4631 		$stmt = $db->prepare('SELECT style FROM ' . PREFIX . 'members WHERE nickname=?;');
   4632 		$stmt->execute([$nick]);
   4633 		if ($tmp = $stmt->fetch(PDO::FETCH_NUM)) {
   4634 			return style_this(htmlspecialchars("@$nick"), $tmp[0]) . $rest;
   4635 		}
   4636 		//match case-insensitive members
   4637 		$stmt = $db->prepare('SELECT style FROM ' . PREFIX . 'members WHERE LOWER(nickname)=LOWER(?);');
   4638 		$stmt->execute([$nick]);
   4639 		if ($tmp = $stmt->fetch(PDO::FETCH_NUM)) {
   4640 			return style_this(htmlspecialchars("@$nick"), $tmp[0]) . $rest;
   4641 		}
   4642 		if (strlen($nick) === 1) {
   4643 			break;
   4644 		}
   4645 		$rest = mb_substr($nick, -1) . $rest;
   4646 		$nick = mb_substr($nick, 0, -1);
   4647 	}
   4648 	return $matched[0];
   4649 }, $message);
   4650 }
   4651 
   4652 function add_message($message, $recipient, $poster, $delstatus, $poststatus, $displaysend, $style)
   4653 {
   4654 global $db, $U;
   4655 if ($message === '') {
   4656 	return false;
   4657 }
   4658 //Modifications for chat rooms
   4659 $roomid = $U['roomid'];
   4660 if (isset($_REQUEST['sendto']) && $_REQUEST['sendto'] === 'r @' && $U['status'] >= 5) {
   4661 	$allrooms = 1;
   4662 	$roomid = null;
   4663 } else {
   4664 	$allrooms = 0;
   4665 }
   4666 $newmessage = [
   4667 	'postdate'	=> time(),
   4668 	'poststatus'	=> $poststatus,
   4669 	'poster'	=> $poster,
   4670 	'recipient'	=> $recipient,
   4671 	'text'		=> "<span class=\"usermsg\">$displaysend" . style_this($message, $style) . '</span>',
   4672 	'delstatus'	=> $delstatus,
   4673 	'roomid'	=> $roomid,
   4674 	'allrooms'	=> $allrooms
   4675 ];
   4676 //Modifcation chat rooms
   4677 if ($newmessage['roomid'] === NULL) {
   4678 	//prevent posting the same message twice, if no other message was posted in-between.
   4679 	$stmt = $db->prepare('SELECT id FROM ' . PREFIX . 'messages WHERE poststatus=? AND poster=? AND recipient=? AND text=? AND roomid IS NULL AND id IN (SELECT * FROM (SELECT id FROM ' . PREFIX . 'messages ORDER BY id DESC LIMIT 1) AS t);');
   4680 	$stmt->execute([$newmessage['poststatus'], $newmessage['poster'], $newmessage['recipient'], $newmessage['text']]);
   4681 } else {
   4682 	$stmt = $db->prepare('SELECT id FROM ' . PREFIX . 'messages WHERE poststatus=? AND poster=? AND recipient=? AND text=? AND roomid=? AND id IN (SELECT * FROM (SELECT id FROM ' . PREFIX . 'messages ORDER BY id DESC LIMIT 1) AS t);');
   4683 	$stmt->execute([$newmessage['poststatus'], $newmessage['poster'], $newmessage['recipient'], $newmessage['text'], $newmessage['roomid']]);
   4684 }
   4685 if ($stmt->fetch(PDO::FETCH_NUM)) {
   4686 	return false;
   4687 }
   4688 write_message($newmessage);
   4689 return true;
   4690 }
   4691 //Modification chat rooms
   4692 function add_system_message($mes, $roomid = NULL)
   4693 {
   4694 if ($mes === '') {
   4695 	return;
   4696 }
   4697 $sysmessage = [
   4698 	'postdate'	=> time(),
   4699 	'poststatus'	=> 1,
   4700 	'poster'	=> '',
   4701 	'recipient'	=> '',
   4702 	'text'		=> "<span class=\"sysmsg\">$mes</span>",
   4703 	'delstatus'	=> 4,
   4704 	'roomid'    => $roomid,
   4705 	'allrooms'	=> 0
   4706 ];
   4707 write_message($sysmessage);
   4708 }
   4709 
   4710 function write_message($message)
   4711 {
   4712 global $db;
   4713 if (MSGENCRYPTED) {
   4714 	$message['text'] = base64_encode(sodium_crypto_aead_aes256gcm_encrypt($message['text'], '', AES_IV, ENCRYPTKEY));
   4715 }
   4716 $stmt = $db->prepare('INSERT INTO ' . PREFIX . 'messages (postdate, poststatus, poster, recipient, text, delstatus, roomid, allrooms) VALUES (?, ?, ?, ?, ?, ?, ?, ?);');
   4717 $stmt->execute([$message['postdate'], $message['poststatus'], $message['poster'], $message['recipient'], $message['text'], $message['delstatus'], $message['roomid'], $message['allrooms']]);
   4718 if ($message['poststatus'] < 9 && get_setting('sendmail')) {
   4719 	$subject = 'New Chat message';
   4720 	$headers = 'From: ' . get_setting('mailsender') . "\r\nX-Mailer: PHP/" . phpversion() . "\r\nContent-Type: text/html; charset=UTF-8\r\n";
   4721 	$body = '<html><body style="background-color:#' . get_setting('colbg') . ';color:#' . get_setting('coltxt') . ";\">$message[text]</body></html>";
   4722 	mail(get_setting('mailreceiver'), $subject, $body, $headers);
   4723 }
   4724 }
   4725 
   4726 //Modified
   4727 function clean_chat()
   4728 {
   4729 global $db;
   4730 $db->query('DELETE FROM ' . PREFIX . 'messages;');
   4731 add_system_message(sprintf(get_setting('msgclean'), get_setting('chatname')));
   4732 }
   4733 //Modified
   4734 function clean_room()
   4735 {
   4736 global $db, $U;
   4737 $stmt = $db->prepare('DELETE FROM ' . PREFIX . 'messages where roomid=?;');
   4738 $stmt->execute([$U['roomid']]);
   4739 }
   4740 
   4741 function clean_selected($status, $nick)
   4742 {
   4743 global $db;
   4744 if (isset($_REQUEST['mid'])) {
   4745 
   4746 	//Modification modsdeladminmsg - moderators can delete admin messages (but he can only delete the messages he is able to read.)
   4747 	if ((get_setting('modsdeladminmsg') == 1) && ($status >= 5)) {
   4748 
   4749 		$stmt = $db->prepare('DELETE FROM ' . PREFIX . 'messages WHERE id=? AND (poster=? OR recipient=? OR (poststatus<= ' . $status . ' AND delstatus<9));');
   4750 		foreach ($_REQUEST['mid'] as $mid) {
   4751 			$stmt->execute([$mid, $nick, $nick]);
   4752 		}
   4753 	} else {
   4754 		$stmt = $db->prepare('DELETE FROM ' . PREFIX . 'messages WHERE id=? AND (poster=? OR recipient=? OR (poststatus<? AND delstatus<?));');
   4755 		foreach ($_REQUEST['mid'] as $mid) {
   4756 			$stmt->execute([$mid, $nick, $nick, $status, $status]);
   4757 		}
   4758 	}
   4759 }
   4760 }
   4761 
   4762 function clean_inbox_selected()
   4763 {
   4764 global $U, $db;
   4765 if (isset($_REQUEST['mid'])) {
   4766 	$stmt = $db->prepare('DELETE FROM ' . PREFIX . 'inbox WHERE id=? AND recipient=?;');
   4767 	foreach ($_REQUEST['mid'] as $mid) {
   4768 		$stmt->execute([$mid, $U['nickname']]);
   4769 	}
   4770 }
   4771 }
   4772 
   4773 function del_all_messages($nick, $entry)
   4774 {
   4775 global $db;
   4776 if ($nick == '') {
   4777 	return;
   4778 }
   4779 $stmt = $db->prepare('DELETE FROM ' . PREFIX . 'messages WHERE poster=? AND postdate>=?;');
   4780 $stmt->execute([$nick, $entry]);
   4781 $stmt = $db->prepare('DELETE FROM ' . PREFIX . 'inbox WHERE poster=? AND postdate>=?;');
   4782 $stmt->execute([$nick, $entry]);
   4783 }
   4784 
   4785 function del_last_message()
   4786 {
   4787 
   4788 global $U, $db;
   4789 if ($U['status'] > 1) {
   4790 	$entry = 0;
   4791 } else {
   4792 	$entry = $U['entry'];
   4793 }
   4794 $stmt = $db->prepare('SELECT id FROM ' . PREFIX . 'messages WHERE poster=? AND postdate>=? ORDER BY id DESC LIMIT 1;');
   4795 $stmt->execute([$U['nickname'], $entry]);
   4796 if ($id = $stmt->fetch(PDO::FETCH_NUM)) {
   4797 	$stmt = $db->prepare('DELETE FROM ' . PREFIX . 'messages WHERE id=?;');
   4798 	$stmt->execute($id);
   4799 	$stmt = $db->prepare('DELETE FROM ' . PREFIX . 'inbox WHERE postid=?;');
   4800 	$stmt->execute($id);
   4801 }
   4802 }
   4803 
   4804 function print_messages($delstatus = 0, $modroom = 0)
   4805 {
   4806 //line changed
   4807 global $U, $I, $db, $language;
   4808 
   4809 
   4810 $dateformat = get_setting('dateformat');
   4811 if (!$U['embed'] && get_setting('imgembed')) {
   4812 	$removeEmbed = true;
   4813 } else {
   4814 	$removeEmbed = false;
   4815 }
   4816 if ($U['timestamps'] && !empty($dateformat)) {
   4817 	$timestamps = true;
   4818 } else {
   4819 	$timestamps = false;
   4820 }
   4821 if ($U['sortupdown']) {
   4822 	$direction = 'ASC';
   4823 } else {
   4824 	$direction = 'DESC';
   4825 }
   4826 if ($U['status'] > 1) {
   4827 	$entry = 0;
   4828 } else {
   4829 	$entry = $U['entry'];
   4830 }
   4831 if (isset($_REQUEST['modroom']) && $_REQUEST['modroom'] && $U['status'] >= 5) {
   4832 	$modroom = 1;
   4833 } else {
   4834 	$modroom = 0;
   4835 }
   4836 
   4837 //MODIFCATION chat rooms to only show messages of the all rooms
   4838 
   4839 //MODIFICATION DEL-BUTTONS some lines added to enable delete buttons in front of messages for mods and above.
   4840 // look at function send_choose_messages for better understanding 
   4841 $modmode = false;
   4842 
   4843 
   4844 
   4845 
   4846 
   4847 //modmode (DEL-Buttons) for mods. and for members (according to the memdel setting (always OR if no mod is present and if memkick setting enabled.)
   4848 $memdel = (int)get_setting('memdel');
   4849 if (($delstatus === 0 && $U['status'] >= 5) || ($U['status'] >= 3 && $memdel == 2) || ($U['status'] >= 3 && get_count_mods() == 0 && $memdel == 1)) {
   4850 	$modmode = true;
   4851 	$delstatus = $U['status'];
   4852 	//debug 
   4853 	//echo "modmode active";
   4854 }
   4855 
   4856 
   4857 //Modification for visibility of channels in all roooms
   4858 $channelvisinroom = (int) get_setting('channelvisinroom');
   4859 if ($channelvisinroom == 0) {
   4860 	$channelvisinroom = 2;
   4861 }
   4862 
   4863 
   4864 echo '<div id="messages">';
   4865 
   4866 if ($modmode === true) {
   4867 	echo form('admin_clean_message', 'clean');
   4868 	echo hidden('what', 'selected');
   4869 	echo hidden('modroom', $modroom); // so that deleting a message does not cause exiting modroom
   4870 
   4871 	$stmt = $db->prepare('SELECT id, postdate, text, poststatus, delstatus, poster, recipient, roomid, allrooms FROM ' . PREFIX . 'messages WHERE (poststatus<=? OR ' .
   4872 		'(poststatus=9 AND ( (poster=? AND recipient NOT IN (SELECT ign FROM ' . PREFIX . 'ignored WHERE ignby=?) ) OR recipient=?) AND postdate>=?)' .
   4873 		') AND poster NOT IN (SELECT ign FROM ' . PREFIX . "ignored WHERE ignby=?) ORDER BY id $direction;");
   4874 	$stmt->execute([$U['status'], $U['nickname'], $U['nickname'], $U['nickname'], $entry, $U['nickname']]);
   4875 
   4876 
   4877 	while ($message = $stmt->fetch(PDO::FETCH_ASSOC)) {
   4878 
   4879 		//Modification for chat rooms
   4880 		if ($message['poststatus'] < $channelvisinroom && $message['roomid'] !== $U['roomid'] && !$message['allrooms'] && !$modroom) {
   4881 			continue;
   4882 		}
   4883 
   4884 		//Modification for modrooms in chat rooms
   4885 		$roomname = "";
   4886 		if ($modroom && !$message['allrooms']) {
   4887 			$roomname = 'Main Chat';
   4888 			if ($message['roomid'] != null) {
   4889 				$stmt1 = $db->prepare('SELECT name FROM ' . PREFIX . 'rooms WHERE id=? AND access<=?');
   4890 				$stmt1->execute([$message['roomid'], $U['status']]);
   4891 				if (!$name = $stmt1->fetch(PDO::FETCH_NUM)) {
   4892 					continue;
   4893 				}
   4894 				$roomname = $name[0];
   4895 			}
   4896 			$roomname = '[' . $roomname . ']';
   4897 		}
   4898 
   4899 		prepare_message_print($message, $removeEmbed);
   4900 		//MODIFICATION modsdeladminmsg (mods can delete admins messages)
   4901 		if (get_setting('modsdeladminmsg') == 1 && $U['status'] >= 5) {
   4902 			if (($message['poststatus'] <= $U['status'] &&  $message['delstatus'] < 9) || ($message['poster'] === $U['nickname'] || ($message['recipient'] === $U['nickname']) && $message['postdate'] >= $entry)) {
   4903 				echo "<div class=\"msg\"><button title = \"Delete message\" class = \"delbutton_inline_removable\" name=\"mid[]\" type=\"submit\" value=\"$message[id]\">DEL</button>";
   4904 			}
   4905 		} elseif (($message['poststatus'] < $U['status'] &&  $message['delstatus'] < $U['status']) || ($message['poster'] === $U['nickname'] || ($message['recipient'] === $U['nickname']) && $message['postdate'] >= $entry)) {
   4906 			echo "<div class=\"msg\"><button title = \"Delete message\" class = \"delbutton_inline_removable\" name=\"mid[]\" type=\"submit\" value=\"$message[id]\">DEL</button>";
   4907 		} else {
   4908 			//next line is for debug output (to check if permissions to delete messages are correct. test passed! (everything okay)
   4909 			//echo "<div class=\"msg\"><button class = \"delbutton_inline_unremovable\" name=\"mid[]\" type=\"submit\" value=\"$message[id]\">-----</button>";
   4910 			echo "<div class=\"msg\">&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp";
   4911 		}
   4912 
   4913 
   4914 
   4915 		//if((int)$U['clickablenicknames']>0){   //REMOVE LINE LATER
   4916 		if ((bool) get_setting('clickablenicknamesglobal')) {
   4917 
   4918 			$message_new = make_nicknames_clickable($message['text']);
   4919 		} else {
   4920 
   4921 			$message_new = $message['text'];
   4922 		}
   4923 
   4924 		if ($timestamps) {
   4925 			echo ' <small>' . date($dateformat, $message['postdate']) . ' - </small>';
   4926 		}
   4927 
   4928 		if ($modroom) {
   4929 			echo "<span class=\"modroom\">$roomname</span>";
   4930 		}
   4931 		echo " $message_new</div>";
   4932 	}
   4933 	echo "</form>";
   4934 } elseif ($delstatus > 0) {
   4935 	//Modification modsdeladminmsg
   4936 
   4937 	if (get_setting('modsdeladminmsg') == 1) {
   4938 		$stmt = $db->prepare('SELECT postdate, id, poststatus, roomid, allrooms text FROM ' . PREFIX . 'messages WHERE ' .
   4939 			"(poststatus<=? AND delstatus<9) OR ((poster=? OR recipient=?) AND postdate>=?) ORDER BY id $direction;");
   4940 		$stmt->execute([$U['status'], $U['nickname'], $U['nickname'], $entry]);
   4941 		while ($message = $stmt->fetch(PDO::FETCH_ASSOC)) {
   4942 			//Modification for chat rooms
   4943 			if ($message['poststatus'] < $channelvisinroom && $message['roomid'] !== $U['roomid'] && !$message['allrooms']) {
   4944 				continue;
   4945 			}
   4946 
   4947 			prepare_message_print($message, $removeEmbed);
   4948 			echo "<div class=\"msg\"><label><input type=\"checkbox\" name=\"mid[]\" value=\"$message[id]\">";
   4949 			if ($timestamps) {
   4950 				echo ' <small>' . date($dateformat, $message['postdate']) . ' - </small>';
   4951 			}
   4952 			echo " $message[text]</label></div>";
   4953 		}
   4954 	} else {
   4955 		$stmt = $db->prepare('SELECT postdate, id, text, poststatus, roomid, allrooms FROM ' . PREFIX . 'messages WHERE ' .
   4956 			"(poststatus<? AND delstatus<?) OR ((poster=? OR recipient=?) AND postdate>=?) ORDER BY id $direction;");
   4957 		$stmt->execute([$U['status'], $delstatus, $U['nickname'], $U['nickname'], $entry]);
   4958 		while ($message = $stmt->fetch(PDO::FETCH_ASSOC)) {
   4959 			//Modification for chat rooms
   4960 			if ($message['poststatus'] < $channelvisinroom && $message['roomid'] !== $U['roomid'] && !$message['allrooms']) {
   4961 				continue;
   4962 			}
   4963 			prepare_message_print($message, $removeEmbed);
   4964 			echo "<div class=\"msg\"><label><input type=\"checkbox\" name=\"mid[]\" value=\"$message[id]\">";
   4965 			if ($timestamps) {
   4966 				echo ' <small>' . date($dateformat, $message['postdate']) . ' - </small>';
   4967 			}
   4968 			echo " $message[text]</label></div>";
   4969 		}
   4970 	}
   4971 } else {
   4972 	$stmt = $db->prepare('SELECT id, postdate, text, roomid, allrooms, poststatus FROM ' . PREFIX . 'messages WHERE (poststatus<=? OR ' .
   4973 		'(poststatus=9 AND ( (poster=? AND recipient NOT IN (SELECT ign FROM ' . PREFIX . 'ignored WHERE ignby=?) ) OR recipient=?) AND postdate>=?)' .
   4974 		') AND poster NOT IN (SELECT ign FROM ' . PREFIX . "ignored WHERE ignby=?) ORDER BY id $direction;");
   4975 	$stmt->execute([$U['status'], $U['nickname'], $U['nickname'], $U['nickname'], $entry, $U['nickname']]);
   4976 	while ($message = $stmt->fetch(PDO::FETCH_ASSOC)) {
   4977 		//Modification for chat rooms
   4978 		if ($message['poststatus'] < $channelvisinroom && $message['roomid'] !== $U['roomid'] && !$message['allrooms']) {
   4979 			continue;
   4980 		}
   4981 
   4982 		prepare_message_print($message, $removeEmbed);
   4983 		echo '<div class="msg">';
   4984 
   4985 		//MODIFICATION to make nicknames clickable //REMOVE LINE LATER
   4986 		//if((int)$U['clickablenicknames']>0){//REMOVE LINE LATER
   4987 		//MODIFICATION to make nicknames clickable (global setting
   4988 		if ((bool) get_setting('clickablenicknamesglobal')) {
   4989 			$message_new = make_nicknames_clickable($message['text']);
   4990 		} else {
   4991 
   4992 			$message_new = $message['text'];
   4993 		}
   4994 
   4995 
   4996 
   4997 		if ($timestamps) {
   4998 			echo '<small>' . date($dateformat, $message['postdate']) . ' - </small>';
   4999 		}
   5000 		echo "$message_new</div>";
   5001 	}
   5002 }
   5003 echo '</div>';
   5004 }
   5005 
   5006 //MODIFICATION for clickable nicknames
   5007 function make_nicknames_clickable($message)
   5008 {
   5009 
   5010 global $U, $language;
   5011 $nc = substr(time(), -6);
   5012 
   5013 $channel = "";
   5014 $sender = "";
   5015 $recipient = "";
   5016 $pm = false;
   5017 
   5018 $channel_encoded = "";
   5019 
   5020 //pattern for default system message settings in chat setup. If system messages are changed in the setup, this pattern has to be changed as well. 
   5021 $pattern_channel_detect = "(\[RG\]\ |\[M\]\ |\[Staff\]\ |\[SMods\]\ |\[Admin\]\ )";
   5022 
   5023 $pattern_pm_detect = "\[(\<span\ style\=\"[^\"]{1,}\"\><span\ class\=\"clickablenickname\"\>[A-Za-z0-9]{1,}\<\/span\>\<\/span\>)\ to\ ((?1))\]";
   5024 
   5025 $pattern = "(\<span\ style\=\"[^\"]{1,}\"\>\<span\ class\=\"clickablenickname\"\>([A-Za-z0-9]{1,})\<\/span\>)";
   5026 
   5027 
   5028 preg_match('/' . $pattern_pm_detect . '/i', $message, $matches);
   5029 if (!empty($matches['0'])) {
   5030 	$pm = true;
   5031 }
   5032 
   5033 preg_match('/' . $pattern_channel_detect . '/i', $message, $matches);
   5034 if (!empty($matches['0'])) {
   5035 	if ($matches['0'] === "[RG] ") {
   5036 		$channel = "s 24";
   5037 	} elseif ($matches['0'] === "[M] ") {
   5038 		$channel = "s 31";
   5039 	} elseif ($matches['0'] === "[Staff] ") {
   5040 		$channel = "s 48";
   5041 	} elseif ($matches['0'] === "[Admins] ") {
   5042 		$channel = "s 56";
   5043 	} elseif ($matches['0'] === "[Gods] ") {
   5044 		$channel = "s 65";
   5045 	}
   5046 } else {
   5047 	$channel = "s 17"; // send to all 
   5048 }
   5049 
   5050 //channel must be encoded because of special character + and & and space
   5051 $channel_encoded = urlencode($channel);
   5052 
   5053 /* REMOVE LATER
   5054    //option 1
   5055    if($pm || ((int)$U['clickablenicknames']===1)){
   5056          $replacement = "<a class=\"nicklink\" href=\"?action=post&amp;session=$U[session]&amp;lang=$language&amp;nc=$nc&amp;sendto=".htmlspecialchars('$2').'" target="post">'.'$1'.'</a>';    
   5057    }
   5058 
   5059    //option 2
   5060    if(!$pm && ((int)$U['clickablenicknames']===2)){
   5061    $replacement = "<a class=\"nicklink\" href=\"?action=post&amp;session=$U[session]&amp;lang=$language&amp;nc=$nc&amp;sendto=".$channel_encoded."&amp;nickname=@".htmlspecialchars('$2').'&nbsp" target="post">'.'$1'.'</a>';
   5062    }
   5063    */
   5064 
   5065 if ($pm) { //IF PM DETECTED
   5066 	$replacement = "<a class=\"nicklink\" href=\"?action=post&amp;session=$U[session]&amp;lang=$language&amp;nc=$nc&amp;sendto=" . htmlspecialchars('$2') . '" target="post">' . '$1' . '</a>';
   5067 } else { //Message to all or to one of the channels
   5068 	$replacement = "<a class=\"nicklink\" href=\"?action=post&amp;session=$U[session]&amp;lang=$language&amp;nc=$nc&amp;sendto=" . $channel_encoded . "&amp;nickname=@" . htmlspecialchars('$2') . '&nbsp" target="post">' . '$1' . '</a>';
   5069 }
   5070 
   5071 //regex for option 1 and option 2 and PM
   5072 $message = preg_replace("/$pattern/", $replacement, $message);
   5073 
   5074 return $message;
   5075 }
   5076 
   5077 
   5078 function prepare_message_print(&$message, $removeEmbed)
   5079 {
   5080 if (MSGENCRYPTED) {
   5081 	$message['text'] = sodium_crypto_aead_aes256gcm_decrypt(base64_decode($message['text']), null, AES_IV, ENCRYPTKEY);
   5082 }
   5083 if ($removeEmbed) {
   5084 	$message['text'] = preg_replace_callback(
   5085 		'/<img src="([^"]+)"><\/a>/u',
   5086 		function ($matched) {
   5087 			return "$matched[1]</a>";
   5088 		},
   5089 		$message['text']
   5090 	);
   5091 }
   5092 }
   5093 
   5094 // this and that
   5095 
   5096 function send_headers()
   5097 {
   5098 header('Content-Type: text/html; charset=UTF-8');
   5099 header('Pragma: no-cache');
   5100 header('Cache-Control: no-cache, no-store, must-revalidate, max-age=0');
   5101 header('Expires: 0');
   5102 header('Referrer-Policy: no-referrer');
   5103 header("Content-Security-Policy: default-src 'self'; img-src * data:; media-src * data:; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'");
   5104 header('X-Content-Type-Options: nosniff');
   5105 header('X-Frame-Options: sameorigin');
   5106 header('X-XSS-Protection: 1; mode=block');
   5107 if ($_SERVER['REQUEST_METHOD'] === 'HEAD') {
   5108 	exit; // headers sent, no further processing needed
   5109 }
   5110 }
   5111 
   5112 function save_setup($C)
   5113 {
   5114 global $db;
   5115 //sanity checks and escaping
   5116 foreach ($C['msg_settings'] as $setting) {
   5117 	$_REQUEST[$setting] = htmlspecialchars($_REQUEST[$setting]);
   5118 }
   5119 foreach ($C['number_settings'] as $setting) {
   5120 	settype($_REQUEST[$setting], 'int');
   5121 }
   5122 foreach ($C['colour_settings'] as $setting) {
   5123 	if (preg_match('/^#([a-f0-9]{6})$/i', $_REQUEST[$setting], $match)) {
   5124 		$_REQUEST[$setting] = $match[1];
   5125 	} else {
   5126 		unset($_REQUEST[$setting]);
   5127 	}
   5128 }
   5129 settype($_REQUEST['guestaccess'], 'int');
   5130 if (!preg_match('/^[01234]$/', $_REQUEST['guestaccess'])) {
   5131 	unset($_REQUEST['guestaccess']);
   5132 } elseif ($_REQUEST['guestaccess'] == 4) {
   5133 	$db->exec('DELETE FROM ' . PREFIX . 'sessions WHERE status<7;');
   5134 }
   5135 settype($_REQUEST['englobalpass'], 'int');
   5136 settype($_REQUEST['captcha'], 'int');
   5137 settype($_REQUEST['dismemcaptcha'], 'int');
   5138 settype($_REQUEST['guestreg'], 'int');
   5139 if (isset($_REQUEST['defaulttz'])) {
   5140 	$tzs = timezone_identifiers_list();
   5141 	if (!in_array($_REQUEST['defaulttz'], $tzs)) {
   5142 		unset($_REQUEST['defualttz']);
   5143 	}
   5144 }
   5145 $_REQUEST['rulestxt'] = preg_replace("/(\r?\n|\r\n?)/u", '<br>', $_REQUEST['rulestxt']);
   5146 $_REQUEST['chatname'] = htmlspecialchars($_REQUEST['chatname']);
   5147 $_REQUEST['redirect'] = htmlspecialchars($_REQUEST['redirect']);
   5148 if ($_REQUEST['memberexpire'] < 5) {
   5149 	$_REQUEST['memberexpire'] = 5;
   5150 }
   5151 if ($_REQUEST['captchatime'] < 30) {
   5152 	$_REQUEST['memberexpire'] = 30;
   5153 }
   5154 if ($_REQUEST['defaultrefresh'] < 5) {
   5155 	$_REQUEST['defaultrefresh'] = 5;
   5156 } elseif ($_REQUEST['defaultrefresh'] > 150) {
   5157 	$_REQUEST['defaultrefresh'] = 150;
   5158 }
   5159 if ($_REQUEST['maxname'] < 1) {
   5160 	$_REQUEST['maxname'] = 1;
   5161 } elseif ($_REQUEST['maxname'] > 50) {
   5162 	$_REQUEST['maxname'] = 50;
   5163 }
   5164 if ($_REQUEST['maxmessage'] < 1) {
   5165 	$_REQUEST['maxmessage'] = 1;
   5166 } elseif ($_REQUEST['maxmessage'] > 16000) {
   5167 	$_REQUEST['maxmessage'] = 16000;
   5168 }
   5169 if ($_REQUEST['numnotes'] < 1) {
   5170 	$_REQUEST['numnotes'] = 1;
   5171 }
   5172 if (!valid_regex($_REQUEST['nickregex'])) {
   5173 	unset($_REQUEST['nickregex']);
   5174 }
   5175 if (!valid_regex($_REQUEST['passregex'])) {
   5176 	unset($_REQUEST['passregex']);
   5177 }
   5178 // Modification spare notes
   5179 if (!preg_match('/^[3567]$/', $_REQUEST['sparenotesaccess'])) {
   5180 	$_REQUEST['sparenotesaccess'] = '10';
   5181 }
   5182 $_REQUEST['sparenotesname'] = htmlspecialchars($_REQUEST['sparenotesname']);
   5183 // End modification
   5184 // Modification chat rooms
   5185 if (!preg_match('/^[567]$/', $_REQUEST['roomcreateaccess'])) {
   5186 	unset($_REQUEST['roomcreateaccess']);
   5187 }
   5188 settype($_REQUEST['roomexpire'], 'int');
   5189 if (!preg_match('/^[235679]$/', $_REQUEST['channelvisinroom'])) {
   5190 	unset($_REQUEST['channelvisinroom']);
   5191 }
   5192 // End modification
   5193 
   5194 //save values
   5195 foreach ($C['settings'] as $setting) {
   5196 	if (isset($_REQUEST[$setting])) {
   5197 		update_setting($setting, $_REQUEST[$setting]);
   5198 	}
   5199 }
   5200 }
   5201 
   5202 function set_default_tz()
   5203 {
   5204 global $U;
   5205 if (isset($U['tz'])) {
   5206 	date_default_timezone_set($U['tz']);
   5207 } else {
   5208 	date_default_timezone_set(get_setting('defaulttz'));
   5209 }
   5210 }
   5211 
   5212 function valid_admin()
   5213 {
   5214 global $U;
   5215 if (isset($_REQUEST['session'])) {
   5216 	parse_sessions();
   5217 }
   5218 if (!isset($U['session']) && isset($_REQUEST['nick']) && isset($_REQUEST['pass'])) {
   5219 	create_session(true, $_REQUEST['nick'], $_REQUEST['pass']);
   5220 }
   5221 if (isset($U['status'])) {
   5222 	if ($U['status'] >= 7) {
   5223 		return true;
   5224 	}
   5225 	send_access_denied();
   5226 }
   5227 return false;
   5228 }
   5229 
   5230 function valid_nick($nick)
   5231 {
   5232 $len = mb_strlen($nick);
   5233 if ($len < 1 || $len > get_setting('maxname')) {
   5234 	return false;
   5235 }
   5236 return preg_match('/' . get_setting('nickregex') . '/u', $nick);
   5237 }
   5238 
   5239 function valid_pass($pass)
   5240 {
   5241 if (mb_strlen($pass) < get_setting('minpass')) {
   5242 	return false;
   5243 }
   5244 return preg_match('/' . get_setting('passregex') . '/u', $pass);
   5245 }
   5246 
   5247 function valid_regex(&$regex)
   5248 {
   5249 $regex = preg_replace('~(^|[^\\\\])/~', "$1\/u", $regex); // Escape "/" if not yet escaped
   5250 return (@preg_match("/$_REQUEST[match]/u", '') !== false);
   5251 }
   5252 
   5253 function get_timeout($lastpost, $expire)
   5254 {
   5255 $s = ($lastpost + 60 * $expire) - time();
   5256 $m = floor($s / 60);
   5257 $s %= 60;
   5258 if ($s < 10) {
   5259 	$s = "0$s";
   5260 }
   5261 if ($m > 60) {
   5262 	$h = floor($m / 60);
   5263 	$m %= 60;
   5264 	if ($m < 10) {
   5265 		$m = "0$m";
   5266 	}
   5267 	return "$h:$m:$s";
   5268 } else {
   5269 	return "$m:$s";
   5270 }
   5271 }
   5272 
   5273 function print_colours()
   5274 {
   5275 global $I;
   5276 // Prints a short list with selected named HTML colours and filters out illegible text colours for the given background.
   5277 // It's a simple comparison of weighted grey values. This is not very accurate but gets the job done well enough.
   5278 // name=>[colour, greyval(colour)]
   5279 $colours = ['Beige' => ['F5F5DC', 242.25], 'Black' => ['000000', 0], 'Blue' => ['0000FF', 28.05], 'BlueViolet' => ['8A2BE2', 91.63], 'Brown' => ['A52A2A', 78.9], 'Cyan' => ['00FFFF', 178.5], 'DarkBlue' => ['00008B', 15.29], 'DarkGreen' => ['006400', 59], 'DarkRed' => ['8B0000', 41.7], 'DarkViolet' => ['9400D3', 67.61], 'DeepSkyBlue' => ['00BFFF', 140.74], 'Gold' => ['FFD700', 203.35], 'Grey' => ['808080', 128], 'Green' => ['008000', 75.52], 'HotPink' => ['FF69B4', 158.25], 'Indigo' => ['4B0082', 36.8], 'LightBlue' => ['ADD8E6', 204.64], 'LightGreen' => ['90EE90', 199.46], 'LimeGreen' => ['32CD32', 141.45], 'Magenta' => ['FF00FF', 104.55], 'Olive' => ['808000', 113.92], 'Orange' => ['FFA500', 173.85], 'OrangeRed' => ['FF4500', 117.21], 'Purple' => ['800080', 52.48], 'Red' => ['FF0000', 76.5], 'RoyalBlue' => ['4169E1', 106.2], 'SeaGreen' => ['2E8B57', 105.38], 'Sienna' => ['A0522D', 101.33], 'Silver' => ['C0C0C0', 192], 'Tan' => ['D2B48C', 184.6], 'Teal' => ['008080', 89.6], 'Violet' => ['EE82EE', 174.28], 'White' => ['FFFFFF', 255], 'Yellow' => ['FFFF00', 226.95], 'YellowGreen' => ['9ACD32', 172.65]];
   5280 $greybg = greyval(get_setting('colbg'));
   5281 foreach ($colours as $name => $colour) {
   5282 	if (abs($greybg - $colour[1]) > 75) {
   5283 		echo "<option value=\"$colour[0]\" style=\"color:#$colour[0];\">$I[$name]</option>";
   5284 	}
   5285 }
   5286 }
   5287 
   5288 function greyval($colour)
   5289 {
   5290 return hexdec(substr($colour, 0, 2)) * .3 + hexdec(substr($colour, 2, 2)) * .59 + hexdec(substr($colour, 4, 2)) * .11;
   5291 }
   5292 
   5293 function style_this($text, $styleinfo)
   5294 {
   5295 return "<span style=\"$styleinfo\">$text</span>";
   5296 }
   5297 
   5298 //new function for clickablenicknames
   5299 function style_this_clickable($text, $styleinfo)
   5300 {
   5301 return "<span style=\"$styleinfo\"><span class=\"clickablenickname\">$text</span></span>";
   5302 }
   5303 
   5304 function check_init()
   5305 {
   5306 global $db;
   5307 return @$db->query('SELECT null FROM ' . PREFIX . 'settings LIMIT 1;');
   5308 }
   5309 
   5310 // run every minute doing various database cleanup task
   5311 function cron()
   5312 {
   5313 global $db;
   5314 $time = time();
   5315 if (get_setting('nextcron') > $time) {
   5316 	return;
   5317 }
   5318 update_setting('nextcron', $time + 10);
   5319 // delete old sessions
   5320 $stmt = $db->prepare('DELETE FROM ' . PREFIX . 'sessions WHERE (status<=2 AND lastpost<(?-60*(SELECT value FROM ' . PREFIX . "settings WHERE setting='guestexpire'))) OR (status>2 AND lastpost<(?-60*(SELECT value FROM " . PREFIX . "settings WHERE setting='memberexpire')));");
   5321 $stmt->execute([$time, $time]);
   5322 // delete old messages
   5323 $limit = get_setting('messagelimit');
   5324 $stmt = $db->query('SELECT id FROM ' . PREFIX . "messages WHERE poststatus=1 AND roomid IS NULL ORDER BY id DESC LIMIT 1 OFFSET $limit;");
   5325 if ($id = $stmt->fetch(PDO::FETCH_NUM)) {
   5326 	$stmt = $db->prepare('DELETE FROM ' . PREFIX . 'messages WHERE id<=?;');
   5327 	$stmt->execute($id);
   5328 }
   5329 $stmt = $db->prepare('DELETE FROM ' . PREFIX . 'messages WHERE id IN (SELECT * FROM (SELECT id FROM ' . PREFIX . 'messages WHERE postdate<(?-60*(SELECT value FROM ' . PREFIX . "settings WHERE setting='messageexpire'))) AS t);");
   5330 $stmt->execute([$time]);
   5331 // delete expired ignored people
   5332 $result = $db->query('SELECT id FROM ' . PREFIX . 'ignored WHERE ign NOT IN (SELECT nickname FROM ' . PREFIX . 'sessions UNION SELECT nickname FROM ' . PREFIX . 'members UNION SELECT poster FROM ' . PREFIX . 'messages) OR ignby NOT IN (SELECT nickname FROM ' . PREFIX . 'sessions UNION SELECT nickname FROM ' . PREFIX . 'members UNION SELECT poster FROM ' . PREFIX . 'messages);');
   5333 $stmt = $db->prepare('DELETE FROM ' . PREFIX . 'ignored WHERE id=?;');
   5334 while ($tmp = $result->fetch(PDO::FETCH_NUM)) {
   5335 	$stmt->execute($tmp);
   5336 }
   5337 // delete files that do not belong to any message
   5338 $result = $db->query('SELECT id FROM ' . PREFIX . 'files WHERE postid NOT IN (SELECT id FROM ' . PREFIX . 'messages UNION SELECT postid FROM ' . PREFIX . 'inbox);');
   5339 $stmt = $db->prepare('DELETE FROM ' . PREFIX . 'files WHERE id=?;');
   5340 while ($tmp = $result->fetch(PDO::FETCH_NUM)) {
   5341 	$stmt->execute($tmp);
   5342 }
   5343 // delete old notes
   5344 $limit = get_setting('numnotes');
   5345 // Modification for spare notes
   5346 $db->exec('DELETE FROM ' . PREFIX . 'notes WHERE type!=2 AND id NOT IN (SELECT * FROM ( (SELECT id FROM ' . PREFIX . "notes WHERE type=0 ORDER BY id DESC LIMIT $limit) UNION (SELECT id FROM " . PREFIX . "notes WHERE type=3 ORDER BY id DESC LIMIT $limit)UNION (SELECT id FROM " . PREFIX . "notes WHERE type=1 ORDER BY id DESC LIMIT $limit) ) AS t);");
   5347 $result = $db->query('SELECT editedby, COUNT(*) AS cnt FROM ' . PREFIX . "notes WHERE type=2 GROUP BY editedby HAVING cnt>$limit;");
   5348 $stmt = $db->prepare('DELETE FROM ' . PREFIX . 'notes WHERE type=2 AND editedby=? AND id NOT IN (SELECT * FROM (SELECT id FROM ' . PREFIX . "notes WHERE type=2 AND editedby=? ORDER BY id DESC LIMIT $limit) AS t);");
   5349 while ($tmp = $result->fetch(PDO::FETCH_NUM)) {
   5350 	$stmt->execute([$tmp[0], $tmp[0]]);
   5351 }
   5352 // delete old captchas
   5353 $stmt = $db->prepare('DELETE FROM ' . PREFIX . 'captcha WHERE time<(?-(SELECT value FROM ' . PREFIX . "settings WHERE setting='captchatime'));");
   5354 $stmt->execute([$time]);
   5355 
   5356 // modification expire rooms
   5357 $result = $db->query('SELECT DISTINCT roomid FROM ' . PREFIX . 'sessions where roomid is not null;');
   5358 while ($active = $result->fetch(PDO::FETCH_ASSOC)) {
   5359 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'rooms SET time=? WHERE id=?');
   5360 	$stmt->execute([$time, $active['roomid']]);
   5361 }
   5362 $expire = (int) get_setting('roomexpire') * 60;
   5363 $stmt = $db->prepare('SELECT id FROM ' . PREFIX . 'rooms WHERE time<=? AND permanent=0');
   5364 $stmt->execute([$time - $expire]);
   5365 if (!$rooms = $stmt->fetchAll(PDO::FETCH_ASSOC)) {
   5366 	$rooms = [];
   5367 }
   5368 foreach ($rooms as $room) {
   5369 	remove_room(false, $room['id']);
   5370 }
   5371 
   5372 // End modifications for rooms
   5373 }
   5374 
   5375 function destroy_chat($C)
   5376 {
   5377 global $I, $db, $memcached;
   5378 setcookie(COOKIENAME, false);
   5379 $_REQUEST['session'] = '';
   5380 print_start('destory');
   5381 $db->exec('DROP TABLE ' . PREFIX . 'captcha;');
   5382 $db->exec('DROP TABLE ' . PREFIX . 'files;');
   5383 $db->exec('DROP TABLE ' . PREFIX . 'filter;');
   5384 $db->exec('DROP TABLE ' . PREFIX . 'ignored;');
   5385 $db->exec('DROP TABLE ' . PREFIX . 'inbox;');
   5386 $db->exec('DROP TABLE ' . PREFIX . 'linkfilter;');
   5387 $db->exec('DROP TABLE ' . PREFIX . 'members;');
   5388 $db->exec('DROP TABLE ' . PREFIX . 'messages;');
   5389 $db->exec('DROP TABLE ' . PREFIX . 'notes;');
   5390 $db->exec('DROP TABLE ' . PREFIX . 'sessions;');
   5391 $db->exec('DROP TABLE ' . PREFIX . 'settings;');
   5392 if (MEMCACHED) {
   5393 	$memcached->delete(DBNAME . '-' . PREFIX . 'filter');
   5394 	$memcached->delete(DBANEM . '-' . PREFIX . 'linkfilter');
   5395 	foreach ($C['settings'] as $setting) {
   5396 		$memcached->delete(DBNAME . '-' . PREFIX . "settings-$setting");
   5397 	}
   5398 	$memcached->delete(DBNAME . '-' . PREFIX . 'settings-dbversion');
   5399 	$memcached->delete(DBNAME . '-' . PREFIX . 'settings-msgencrypted');
   5400 	$memcached->delete(DBNAME . '-' . PREFIX . 'settings-nextcron');
   5401 }
   5402 echo "<h2>$I[destroyed]</h2><br><br><br>";
   5403 echo form('setup') . submit($I['init']) . '</form>' . credit();
   5404 print_end();
   5405 }
   5406 
   5407 function init_chat()
   5408 {
   5409 global $I, $db;
   5410 $suwrite = '';
   5411 if (check_init()) {
   5412 	$suwrite = $I['initdbexist'];
   5413 	$result = $db->query('SELECT null FROM ' . PREFIX . 'members WHERE status=8;');
   5414 	if ($result->fetch(PDO::FETCH_NUM)) {
   5415 		$suwrite = $I['initsuexist'];
   5416 	}
   5417 } elseif (!preg_match('/^[a-z0-9]{1,20}$/i', $_REQUEST['sunick'])) {
   5418 	$suwrite = sprintf($I['invalnick'], 20, '^[A-Za-z1-9]*$');
   5419 } elseif (mb_strlen($_REQUEST['supass']) < 5) {
   5420 	$suwrite = sprintf($I['invalpass'], 5, '.*');
   5421 } elseif ($_REQUEST['supass'] !== $_REQUEST['supassc']) {
   5422 	$suwrite = $I['noconfirm'];
   5423 } else {
   5424 	ignore_user_abort(true);
   5425 	set_time_limit(0);
   5426 	if (DBDRIVER === 0) { //MySQL
   5427 		$memengine = ' ENGINE=MEMORY';
   5428 		$diskengine = ' ENGINE=InnoDB';
   5429 		$charset = ' DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin';
   5430 		$primary = 'integer PRIMARY KEY AUTO_INCREMENT';
   5431 		$longtext = 'longtext';
   5432 	} elseif (DBDRIVER === 1) { //PostgreSQL
   5433 		$memengine = '';
   5434 		$diskengine = '';
   5435 		$charset = '';
   5436 		$primary = 'serial PRIMARY KEY';
   5437 		$longtext = 'text';
   5438 	} else { //SQLite
   5439 		$memengine = '';
   5440 		$diskengine = '';
   5441 		$charset = '';
   5442 		$primary = 'integer PRIMARY KEY';
   5443 		$longtext = 'text';
   5444 	}
   5445 	$db->exec('CREATE TABLE ' . PREFIX . "captcha (id $primary, time integer NOT NULL, code char(5) NOT NULL)$memengine$charset;");
   5446 	$db->exec('CREATE TABLE ' . PREFIX . "files (id $primary, postid integer NOT NULL UNIQUE, filename varchar(255) NOT NULL, hash char(40) NOT NULL, type varchar(255) NOT NULL, data $longtext NOT NULL)$diskengine$charset;");
   5447 	$db->exec('CREATE INDEX ' . PREFIX . 'files_hash ON ' . PREFIX . 'files(hash);');
   5448 	$db->exec('CREATE TABLE ' . PREFIX . "filter (id $primary, filtermatch varchar(255) NOT NULL, filterreplace text NOT NULL, allowinpm smallint NOT NULL, regex smallint NOT NULL, kick smallint NOT NULL, cs smallint NOT NULL)$diskengine$charset;");
   5449 	$db->exec('CREATE TABLE ' . PREFIX . "ignored (id $primary, ign varchar(50) NOT NULL, ignby varchar(50) NOT NULL)$diskengine$charset;");
   5450 	$db->exec('CREATE INDEX ' . PREFIX . 'ign ON ' . PREFIX . 'ignored(ign);');
   5451 	$db->exec('CREATE INDEX ' . PREFIX . 'ignby ON ' . PREFIX . 'ignored(ignby);');
   5452 	$db->exec('CREATE TABLE ' . PREFIX . "inbox (id $primary, postdate integer NOT NULL, postid integer NOT NULL UNIQUE, poster varchar(50) NOT NULL, recipient varchar(50) NOT NULL, text text NOT NULL)$diskengine$charset;");
   5453 	$db->exec('CREATE INDEX ' . PREFIX . 'inbox_poster ON ' . PREFIX . 'inbox(poster);');
   5454 	$db->exec('CREATE INDEX ' . PREFIX . 'inbox_recipient ON ' . PREFIX . 'inbox(recipient);');
   5455 	$db->exec('CREATE TABLE ' . PREFIX . "linkfilter (id $primary, filtermatch varchar(255) NOT NULL, filterreplace varchar(255) NOT NULL, regex smallint NOT NULL)$diskengine$charset;");
   5456 
   5457 	//MODIFICATION clickable nicknames
   5458 	/*REMOVE LATER
   5459 	$db->exec('CREATE TABLE ' . PREFIX . "members (id $primary, nickname varchar(50) NOT NULL UNIQUE, passhash varchar(255) NOT NULL, status smallint NOT NULL, refresh smallint NOT NULL, bgcolour char(6) NOT NULL, regedby varchar(50) DEFAULT '', lastlogin integer DEFAULT 0, timestamps smallint NOT NULL, embed smallint NOT NULL, incognito smallint NOT NULL, style varchar(255) NOT NULL, nocache smallint NOT NULL, tz varchar(255) NOT NULL, eninbox smallint NOT NULL, sortupdown smallint NOT NULL, hidechatters smallint NOT NULL, nocache_old smallint NOT NULL, clickablenicknames smallint NOT NULL DEFAULT 0)$diskengine$charset;");
   5460 	*/
   5461 	$db->exec('CREATE TABLE ' . PREFIX . "members (id $primary, nickname varchar(50) NOT NULL UNIQUE, passhash varchar(255) NOT NULL, status smallint NOT NULL, refresh smallint NOT NULL, bgcolour char(6) NOT NULL, regedby varchar(50) DEFAULT '', lastlogin integer DEFAULT 0, timestamps smallint NOT NULL, embed smallint NOT NULL, incognito smallint NOT NULL, style varchar(255) NOT NULL, nocache smallint NOT NULL, tz varchar(255) NOT NULL, eninbox smallint NOT NULL, sortupdown smallint NOT NULL, hidechatters smallint NOT NULL, nocache_old smallint NOT NULL)$diskengine$charset;");
   5462 
   5463 
   5464 	$db->exec('ALTER TABLE ' . PREFIX . 'inbox ADD FOREIGN KEY (recipient) REFERENCES ' . PREFIX . 'members(nickname) ON DELETE CASCADE ON UPDATE CASCADE;');
   5465 	$db->exec('CREATE TABLE ' . PREFIX . "messages (id $primary, postdate integer NOT NULL, poststatus smallint NOT NULL, poster varchar(50) NOT NULL, recipient varchar(50) NOT NULL, text text NOT NULL, delstatus smallint NOT NULL)$diskengine$charset;");
   5466 	$db->exec('CREATE INDEX ' . PREFIX . 'poster ON ' . PREFIX . 'messages (poster);');
   5467 	$db->exec('CREATE INDEX ' . PREFIX . 'recipient ON ' . PREFIX . 'messages(recipient);');
   5468 	$db->exec('CREATE INDEX ' . PREFIX . 'postdate ON ' . PREFIX . 'messages(postdate);');
   5469 	$db->exec('CREATE INDEX ' . PREFIX . 'poststatus ON ' . PREFIX . 'messages(poststatus);');
   5470 	$db->exec('CREATE TABLE ' . PREFIX . "notes (id $primary, type smallint NOT NULL, lastedited integer NOT NULL, editedby varchar(50) NOT NULL, text text NOT NULL)$diskengine$charset;");
   5471 	$db->exec('CREATE INDEX ' . PREFIX . 'notes_type ON ' . PREFIX . 'notes(type);');
   5472 	$db->exec('CREATE INDEX ' . PREFIX . 'notes_editedby ON ' . PREFIX . 'notes(editedby);');
   5473 
   5474 	//MODIFICATION clickable nicknames
   5475 	/* REMOVE LATER
   5476 	$db->exec('CREATE TABLE ' . PREFIX . "sessions (id $primary, session char(32) NOT NULL UNIQUE, nickname varchar(50) NOT NULL UNIQUE, status smallint NOT NULL, refresh smallint NOT NULL, style varchar(255) NOT NULL, lastpost integer NOT NULL, passhash varchar(255) NOT NULL, postid char(6) NOT NULL DEFAULT '000000', useragent varchar(255) NOT NULL, kickmessage varchar(255) DEFAULT '', bgcolour char(6) NOT NULL, entry integer NOT NULL, timestamps smallint NOT NULL, embed smallint NOT NULL, incognito smallint NOT NULL, ip varchar(45) NOT NULL, nocache smallint NOT NULL, tz varchar(255) NOT NULL, eninbox smallint NOT NULL, sortupdown smallint NOT NULL, hidechatters smallint NOT NULL, nocache_old smallint NOT NULL, clickablenicknames smallint NOT NULL DEFAULT 0)$memengine$charset;");
   5477 	*/
   5478 	$db->exec('CREATE TABLE ' . PREFIX . "sessions (id $primary, session char(32) NOT NULL UNIQUE, nickname varchar(50) NOT NULL UNIQUE, status smallint NOT NULL, refresh smallint NOT NULL, style varchar(255) NOT NULL, lastpost integer NOT NULL, passhash varchar(255) NOT NULL, postid char(6) NOT NULL DEFAULT '000000', useragent varchar(255) NOT NULL, kickmessage varchar(255) DEFAULT '', bgcolour char(6) NOT NULL, entry integer NOT NULL, timestamps smallint NOT NULL, embed smallint NOT NULL, incognito smallint NOT NULL, ip varchar(45) NOT NULL, nocache smallint NOT NULL, tz varchar(255) NOT NULL, eninbox smallint NOT NULL, sortupdown smallint NOT NULL, hidechatters smallint NOT NULL, nocache_old smallint NOT NULL)$memengine$charset;");
   5479 
   5480 	$db->exec('CREATE INDEX ' . PREFIX . 'status ON ' . PREFIX . 'sessions(status);');
   5481 	$db->exec('CREATE INDEX ' . PREFIX . 'lastpost ON ' . PREFIX . 'sessions(lastpost);');
   5482 	$db->exec('CREATE INDEX ' . PREFIX . 'incognito ON ' . PREFIX . 'sessions(incognito);');
   5483 	$db->exec('CREATE TABLE ' . PREFIX . "settings (setting varchar(50) NOT NULL PRIMARY KEY, value text NOT NULL)$diskengine$charset;");
   5484 
   5485 	// Modification for chat rooms
   5486 	$db->exec('CREATE TABLE ' . PREFIX . "rooms (id $primary, name varchar(50) NOT NULL UNIQUE, access smallint NOT NULL, time integer NOT NULL, permanent smallint NOT NULL DEFAULT(0))$diskengine$charset;");
   5487 	$db->exec('ALTER TABLE ' . PREFIX . 'sessions ADD COLUMN roomid integer;');
   5488 	$db->exec('ALTER TABLE ' . PREFIX . 'messages ADD COLUMN roomid integer;');
   5489 	$db->exec('CREATE INDEX ' . PREFIX . 'sroomid ON ' . PREFIX . 'sessions(roomid);');
   5490 	$db->exec('CREATE INDEX ' . PREFIX . 'mroomid ON ' . PREFIX . 'messages(roomid);');
   5491 	$db->exec('ALTER TABLE ' . PREFIX . 'messages ADD COLUMN allrooms smallint NOT NULL DEFAULT(0);');
   5492 
   5493 
   5494 	$settings = [
   5495 		['guestaccess', '0'],
   5496 		['globalpass', ''],
   5497 		['englobalpass', '0'],
   5498 		['captcha', '0'],
   5499 		['dateformat', 'm-d H:i:s'],
   5500 		['rulestxt', ''],
   5501 		['msgencrypted', '0'],
   5502 		['dbversion', DBVERSION],
   5503 		['css', ''],
   5504 		['memberexpire', '60'],
   5505 		['guestexpire', '15'],
   5506 		['kickpenalty', '10'],
   5507 		['entrywait', '120'],
   5508 		['messageexpire', '14400'],
   5509 		['messagelimit', '150'],
   5510 		['maxmessage', 2000],
   5511 		['captchatime', '600'],
   5512 		['colbg', '000000'],
   5513 		['coltxt', 'FFFFFF'],
   5514 		['maxname', '20'],
   5515 		['minpass', '5'],
   5516 		['defaultrefresh', '20'],
   5517 		['dismemcaptcha', '0'],
   5518 		['suguests', '0'],
   5519 		['imgembed', '1'],
   5520 		['timestamps', '1'],
   5521 		['trackip', '0'],
   5522 		['captchachars', '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'],
   5523 		['memkick', '1'],
   5524 		['forceredirect', '0'],
   5525 		['redirect', ''],
   5526 		['incognito', '1'],
   5527 		['chatname', 'My Chat'],
   5528 		['topic', ''],
   5529 		['msgsendall', $I['sendallmsg']],
   5530 		['msgsendmem', $I['sendmemmsg']],
   5531 		['msgsendmod', $I['sendmodmsg']],
   5532 		['msgsendadm', $I['sendadmmsg']],
   5533 		['msgsendprv', $I['sendprvmsg']],
   5534 		['msgenter', $I['entermsg']],
   5535 		['msgexit', $I['exitmsg']],
   5536 		['msgmemreg', $I['memregmsg']],
   5537 		['msgsureg', $I['suregmsg']],
   5538 		['msgkick', $I['kickmsg']],
   5539 		['msgmultikick', $I['multikickmsg']],
   5540 		['msgallkick', $I['allkickmsg']],
   5541 		['msgclean', $I['cleanmsg']],
   5542 		['numnotes', '3'],
   5543 		['mailsender', 'www-data <www-data@localhost>'],
   5544 		['mailreceiver', 'Webmaster <webmaster@localhost>'],
   5545 		['sendmail', '0'],
   5546 		['modfallback', '1'],
   5547 		['guestreg', '0'],
   5548 		['disablepm', '0'],
   5549 		['disabletext', "<h1>$I[disabledtext]</h1>"],
   5550 		['defaulttz', 'UTC'],
   5551 		['eninbox', '0'],
   5552 		['passregex', '.*'],
   5553 		['nickregex', '^[A-Za-z0-9]*$'],
   5554 		['externalcss', ''],
   5555 		['enablegreeting', '0'],
   5556 		['sortupdown', '0'],
   5557 		['hidechatters', '0'],
   5558 		['enfileupload', '0'],
   5559 		['msgattache', '%2$s [%1$s]'],
   5560 		['maxuploadsize', '1024'],
   5561 		['nextcron', '0'],
   5562 		['personalnotes', '1'],
   5563 		['filtermodkick', '0'],
   5564 
   5565 		//MODIFICATION Text field for links in settings and option to enable or disable links page.
   5566 		['links', ''],
   5567 		['linksenabled', '0'],
   5568 
   5569 		//MODIFICATION option to enable or disable DEL-Buttons for members, if no mod is present. (DEL Buttons can bes used to delete messages within the message frame)
   5570 		['memdel', '0'],
   5571 
   5572 		//MODIFICATION option to set galleryaccess for users depending on their rank(status).
   5573 		['galleryaccess', '10'],
   5574 
   5575 		//MODIFICATION option to set forum button visibility for users depending on their rank(status).
   5576 		['forumbtnaccess', '10'],
   5577 
   5578 		//MODIFICATION option to set link for the forum button 
   5579 		['forumbtnlink', 'forum/index.php'],
   5580 
   5581 		//MODIFICATION frontpagetext (text for front page)
   5582 		['frontpagetext', ''],
   5583 
   5584 		//MODIFICATION adminjoinleavemsg (admin join leave messages can be hidden)
   5585 		['adminjoinleavemsg', '1'],
   5586 
   5587 		//MODIFICATION modsdeladminmsg (mods can delete admin messages)
   5588 		['modsdeladminmsg', '0'],
   5589 
   5590 		//MODIFICATION clickablenicknamesglobal (nicknames at beginning of messages are clickable)
   5591 		['clickablenicknamesglobal', '1'],
   5592 
   5593 		//MODIFICATION spare notes.
   5594 		['sparenotesname', ''],
   5595 		['sparenotesaccess', '10'],
   5596 
   5597 		//MODIFICATION rooms
   5598 		['roomcreateaccess', '7'],
   5599 		['roomexpire', '10'],
   5600 		['channelvisinroom', '2']
   5601 	];
   5602 	$stmt = $db->prepare('INSERT INTO ' . PREFIX . 'settings (setting, value) VALUES (?, ?);');
   5603 	foreach ($settings as $pair) {
   5604 		$stmt->execute($pair);
   5605 	}
   5606 	$reg = [
   5607 		'nickname'	=> $_REQUEST['sunick'],
   5608 		'passhash'	=> password_hash($_REQUEST['supass'], PASSWORD_DEFAULT),
   5609 		'status'	=> 8,
   5610 		'refresh'	=> 20,
   5611 		'bgcolour'	=> '000000',
   5612 		'timestamps'	=> 1,
   5613 		'style'		=> 'color:#FFFFFF;',
   5614 		'embed'		=> 1,
   5615 		'incognito'	=> 0,
   5616 		'nocache'	=> 0,
   5617 		'nocache_old'	=> 1,
   5618 		'tz'		=> 'UTC',
   5619 		'eninbox'	=> 0,
   5620 		'sortupdown'	=> 0,
   5621 		'hidechatters'	=> 0,
   5622 	];
   5623 	$stmt = $db->prepare('INSERT INTO ' . PREFIX . 'members (nickname, passhash, status, refresh, bgcolour, timestamps, style, embed, incognito, nocache, tz, eninbox, sortupdown, hidechatters, nocache_old) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);');
   5624 	$stmt->execute([$reg['nickname'], $reg['passhash'], $reg['status'], $reg['refresh'], $reg['bgcolour'], $reg['timestamps'], $reg['style'], $reg['embed'], $reg['incognito'], $reg['nocache'], $reg['tz'], $reg['eninbox'], $reg['sortupdown'], $reg['hidechatters'], $reg['nocache_old']]);
   5625 	$suwrite = $I['susuccess'];
   5626 }
   5627 print_start('init');
   5628 echo "<h2>$I[init]</h2><br><h3>$I[sulogin]</h3>$suwrite<br><br><br>";
   5629 echo form('setup') . submit($I['initgosetup']) . '</form>' . credit();
   5630 print_end();
   5631 }
   5632 
   5633 function update_db()
   5634 {
   5635 global $I, $db, $memcached;
   5636 $dbversion = (int) get_setting('dbversion');
   5637 $msgencrypted = (bool) get_setting('msgencrypted');
   5638 if ($dbversion >= DBVERSION && $msgencrypted === MSGENCRYPTED) {
   5639 	return;
   5640 }
   5641 ignore_user_abort(true);
   5642 set_time_limit(0);
   5643 if (DBDRIVER === 0) { //MySQL
   5644 	$memengine = ' ENGINE=MEMORY';
   5645 	$diskengine = ' ENGINE=InnoDB';
   5646 	$charset = ' DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin';
   5647 	$primary = 'integer PRIMARY KEY AUTO_INCREMENT';
   5648 	$longtext = 'longtext';
   5649 } elseif (DBDRIVER === 1) { //PostgreSQL
   5650 	$memengine = '';
   5651 	$diskengine = '';
   5652 	$charset = '';
   5653 	$primary = 'serial PRIMARY KEY';
   5654 	$longtext = 'text';
   5655 } else { //SQLite
   5656 	$memengine = '';
   5657 	$diskengine = '';
   5658 	$charset = '';
   5659 	$primary = 'integer PRIMARY KEY';
   5660 	$longtext = 'text';
   5661 }
   5662 $msg = '';
   5663 if ($dbversion < 2) {
   5664 	$db->exec('CREATE TABLE IF NOT EXISTS ' . PREFIX . "ignored (id integer unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT, ignored varchar(50) NOT NULL, `by` varchar(50) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8;");
   5665 }
   5666 if ($dbversion < 3) {
   5667 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('rulestxt', '');");
   5668 }
   5669 if ($dbversion < 4) {
   5670 	$db->exec('ALTER TABLE ' . PREFIX . 'members ADD incognito smallint NOT NULL;');
   5671 }
   5672 if ($dbversion < 5) {
   5673 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('globalpass', '');");
   5674 }
   5675 if ($dbversion < 6) {
   5676 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('dateformat', 'm-d H:i:s');");
   5677 }
   5678 if ($dbversion < 7) {
   5679 	$db->exec('ALTER TABLE ' . PREFIX . 'captcha ADD code char(5) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;');
   5680 }
   5681 if ($dbversion < 8) {
   5682 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('captcha', '0'), ('englobalpass', '0');");
   5683 	$ga = (int) get_setting('guestaccess');
   5684 	if ($ga === -1) {
   5685 		update_setting('guestaccess', 0);
   5686 		update_setting('englobalpass', 1);
   5687 	} elseif ($ga === 4) {
   5688 		update_setting('guestaccess', 1);
   5689 		update_setting('englobalpass', 2);
   5690 	}
   5691 }
   5692 if ($dbversion < 9) {
   5693 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting,value) VALUES ('msgencrypted', '0');");
   5694 	$db->exec('ALTER TABLE ' . PREFIX . 'settings MODIFY value varchar(20000) NOT NULL;');
   5695 	$db->exec('ALTER TABLE ' . PREFIX . 'messages DROP postid;');
   5696 }
   5697 if ($dbversion < 10) {
   5698 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('css', ''), ('memberexpire', '60'), ('guestexpire', '15'), ('kickpenalty', '10'), ('entrywait', '120'), ('messageexpire', '14400'), ('messagelimit', '150'), ('maxmessage', 2000), ('captchatime', '600');");
   5699 }
   5700 if ($dbversion < 11) {
   5701 	$db->exec('ALTER TABLE ', PREFIX . 'captcha CHARACTER SET utf8 COLLATE utf8_bin;');
   5702 	$db->exec('ALTER TABLE ' . PREFIX . 'filter CHARACTER SET utf8 COLLATE utf8_bin;');
   5703 	$db->exec('ALTER TABLE ' . PREFIX . 'ignored CHARACTER SET utf8 COLLATE utf8_bin;');
   5704 	$db->exec('ALTER TABLE ' . PREFIX . 'messages CHARACTER SET utf8 COLLATE utf8_bin;');
   5705 	$db->exec('ALTER TABLE ' . PREFIX . 'notes CHARACTER SET utf8 COLLATE utf8_bin;');
   5706 	$db->exec('ALTER TABLE ' . PREFIX . 'settings CHARACTER SET utf8 COLLATE utf8_bin;');
   5707 	$db->exec('CREATE TABLE ' . PREFIX . "linkfilter (id integer unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT, `match` varchar(255) NOT NULL, `replace` varchar(255) NOT NULL, regex smallint NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;");
   5708 	$db->exec('ALTER TABLE ' . PREFIX . 'members ADD style varchar(255) NOT NULL;');
   5709 	$result = $db->query('SELECT * FROM ' . PREFIX . 'members;');
   5710 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'members SET style=? WHERE id=?;');
   5711 	$F = load_fonts();
   5712 	while ($temp = $result->fetch(PDO::FETCH_ASSOC)) {
   5713 		$style = "color:#$temp[colour];";
   5714 		if (isset($F[$temp['fontface']])) {
   5715 			$style .= $F[$temp['fontface']];
   5716 		}
   5717 		if (strpos($temp['fonttags'], 'i') !== false) {
   5718 			$style .= 'font-style:italic;';
   5719 		}
   5720 		if (strpos($temp['fonttags'], 'b') !== false) {
   5721 			$style .= 'font-weight:bold;';
   5722 		}
   5723 		$stmt->execute([$style, $temp['id']]);
   5724 	}
   5725 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('colbg', '000000'), ('coltxt', 'FFFFFF'), ('maxname', '20'), ('minpass', '5'), ('defaultrefresh', '20'), ('dismemcaptcha', '0'), ('suguests', '0'), ('imgembed', '1'), ('timestamps', '1'), ('trackip', '0'), ('captchachars', '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'), ('memkick', '1'), ('forceredirect', '0'), ('redirect', ''), ('incognito', '1');");
   5726 }
   5727 if ($dbversion < 12) {
   5728 	$db->exec('ALTER TABLE ' . PREFIX . 'captcha MODIFY code char(5) NOT NULL, DROP INDEX id, ADD PRIMARY KEY (id) USING BTREE;');
   5729 	$db->exec('ALTER TABLE ' . PREFIX . 'captcha ENGINE=MEMORY;');
   5730 	$db->exec('ALTER TABLE ' . PREFIX . 'filter MODIFY id integer unsigned NOT NULL AUTO_INCREMENT, MODIFY `match` varchar(255) NOT NULL, MODIFY replace varchar(20000) NOT NULL;');
   5731 	$db->exec('ALTER TABLE ' . PREFIX . 'ignored MODIFY ignored varchar(50) NOT NULL, MODIFY `by` varchar(50) NOT NULL, ADD INDEX(ignored), ADD INDEX(`by`);');
   5732 	$db->exec('ALTER TABLE ' . PREFIX . 'linkfilter MODIFY match varchar(255) NOT NULL, MODIFY replace varchar(255) NOT NULL;');
   5733 	$db->exec('ALTER TABLE ' . PREFIX . 'messages MODIFY poster varchar(50) NOT NULL, MODIFY recipient varchar(50) NOT NULL, MODIFY text varchar(20000) NOT NULL, ADD INDEX(poster), ADD INDEX(recipient), ADD INDEX(postdate), ADD INDEX(poststatus);');
   5734 	$db->exec('ALTER TABLE ' . PREFIX . 'notes MODIFY type char(5) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL, MODIFY editedby varchar(50) NOT NULL, MODIFY text varchar(20000) NOT NULL;');
   5735 	$db->exec('ALTER TABLE ' . PREFIX . 'settings MODIFY id integer unsigned NOT NULL, MODIFY setting varchar(50) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL, MODIFY value varchar(20000) NOT NULL;');
   5736 	$db->exec('ALTER TABLE ' . PREFIX . 'settings DROP PRIMARY KEY, DROP id, ADD PRIMARY KEY(setting);');
   5737 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('chatname', 'My Chat'), ('topic', ''), ('msgsendall', '$I[sendallmsg]'), ('msgsendmem', '$I[sendmemmsg]'), ('msgsendmod', '$I[sendmodmsg]'), ('msgsendadm', '$I[sendadmmsg]'), ('msgsendprv', '$I[sendprvmsg]'), ('numnotes', '3');");
   5738 }
   5739 if ($dbversion < 13) {
   5740 	$db->exec('ALTER TABLE ' . PREFIX . 'filter CHANGE `match` filtermatch varchar(255) NOT NULL, CHANGE `replace` filterreplace varchar(20000) NOT NULL;');
   5741 	$db->exec('ALTER TABLE ' . PREFIX . 'ignored CHANGE ignored ign varchar(50) NOT NULL, CHANGE `by` ignby varchar(50) NOT NULL;');
   5742 	$db->exec('ALTER TABLE ' . PREFIX . 'linkfilter CHANGE `match` filtermatch varchar(255) NOT NULL, CHANGE `replace` filterreplace varchar(255) NOT NULL;');
   5743 }
   5744 if ($dbversion < 14) {
   5745 	if (MEMCACHED) {
   5746 		$memcached->delete(DBNAME . '-' . PREFIX . 'members');
   5747 		$memcached->delete(DBNAME . '-' . PREFIX . 'ignored');
   5748 	}
   5749 	if (DBDRIVER === 0) { //MySQL - previously had a wrong SQL syntax and the captcha table was not created.
   5750 		$db->exec('CREATE TABLE IF NOT EXISTS ' . PREFIX . 'captcha (id integer unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT, time integer unsigned NOT NULL, code char(5) NOT NULL) ENGINE=MEMORY DEFAULT CHARSET=utf8 COLLATE=utf8_bin;');
   5751 	}
   5752 }
   5753 if ($dbversion < 15) {
   5754 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('mailsender', 'www-data <www-data@localhost>'), ('mailreceiver', 'Webmaster <webmaster@localhost>'), ('sendmail', '0'), ('modfallback', '1'), ('guestreg', '0');");
   5755 }
   5756 if ($dbversion < 17) {
   5757 	$db->exec('ALTER TABLE ' . PREFIX . 'members ADD COLUMN nocache smallint NOT NULL DEFAULT 0;');
   5758 }
   5759 if ($dbversion < 18) {
   5760 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('disablepm', '0');");
   5761 }
   5762 if ($dbversion < 19) {
   5763 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('disabletext', '<h1>$I[disabledtext]</h1>');");
   5764 }
   5765 if ($dbversion < 20) {
   5766 	$db->exec('ALTER TABLE ' . PREFIX . 'members ADD COLUMN tz smallint NOT NULL DEFAULT 0;');
   5767 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('defaulttz', 'UTC');");
   5768 }
   5769 if ($dbversion < 21) {
   5770 	$db->exec('ALTER TABLE ' . PREFIX . 'members ADD COLUMN eninbox smallint NOT NULL DEFAULT 0;');
   5771 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('eninbox', '0');");
   5772 	if (DBDRIVER === 0) {
   5773 		$db->exec('CREATE TABLE ' . PREFIX . "inbox (id integer unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT, postid integer unsigned NOT NULL, postdate integer unsigned NOT NULL, poster varchar(50) NOT NULL, recipient varchar(50) NOT NULL, text varchar(20000) NOT NULL, INDEX(postid), INDEX(poster), INDEX(recipient)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;");
   5774 	} else {
   5775 		$db->exec('CREATE TABLE ' . PREFIX . "inbox (id $primary, postdate integer NOT NULL, postid integer NOT NULL, poster varchar(50) NOT NULL, recipient varchar(50) NOT NULL, text varchar(20000) NOT NULL);");
   5776 		$db->exec('CREATE INDEX ' . PREFIX . 'inbox_postid ON ' . PREFIX . 'inbox(postid);');
   5777 		$db->exec('CREATE INDEX ' . PREFIX . 'inbox_poster ON ' . PREFIX . 'inbox(poster);');
   5778 		$db->exec('CREATE INDEX ' . PREFIX . 'inbox_recipient ON ' . PREFIX . 'inbox(recipient);');
   5779 	}
   5780 }
   5781 if ($dbversion < 23) {
   5782 	$db->exec('DELETE FROM ' . PREFIX . "settings WHERE setting='enablejs';");
   5783 }
   5784 if ($dbversion < 25) {
   5785 	$db->exec('DELETE FROM ' . PREFIX . "settings WHERE setting='keeplimit';");
   5786 }
   5787 if ($dbversion < 26) {
   5788 	$db->exec('INSERT INTO ' . PREFIX . 'settings (setting, value) VALUES (\'passregex\', \'.*\'), (\'nickregex\', \'^[A-Za-z0-9]*$\');');
   5789 }
   5790 if ($dbversion < 27) {
   5791 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('externalcss', '');");
   5792 }
   5793 if ($dbversion < 28) {
   5794 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('enablegreeting', '0');");
   5795 }
   5796 if ($dbversion < 29) {
   5797 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('sortupdown', '0');");
   5798 	$db->exec('ALTER TABLE ' . PREFIX . 'members ADD COLUMN sortupdown smallint NOT NULL DEFAULT 0;');
   5799 }
   5800 if ($dbversion < 30) {
   5801 	$db->exec('ALTER TABLE ' . PREFIX . 'filter ADD COLUMN cs smallint NOT NULL DEFAULT 0;');
   5802 	if (MEMCACHED) {
   5803 		$memcached->delete(DBNAME . '-' . PREFIX . "filter");
   5804 	}
   5805 }
   5806 if ($dbversion < 31) {
   5807 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('hidechatters', '0');");
   5808 	$db->exec('ALTER TABLE ' . PREFIX . 'members ADD COLUMN hidechatters smallint NOT NULL DEFAULT 0;');
   5809 }
   5810 if ($dbversion < 32 && DBDRIVER === 0) {
   5811 	//recreate db in utf8mb4
   5812 	try {
   5813 		$olddb = new PDO('mysql:host=' . DBHOST . ';dbname=' . DBNAME, DBUSER, DBPASS, [PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING, PDO::ATTR_PERSISTENT => PERSISTENT]);
   5814 	} catch (PDOException $e) {
   5815 		send_fatal_error($I['nodb']);
   5816 	}
   5817 	$db->exec('DROP TABLE ' . PREFIX . 'captcha;');
   5818 	$db->exec('CREATE TABLE ' . PREFIX . "captcha (id integer PRIMARY KEY AUTO_INCREMENT, time integer NOT NULL, code char(5) NOT NULL) ENGINE=MEMORY DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;");
   5819 	$result = $olddb->query('SELECT filtermatch, filterreplace, allowinpm, regex, kick, cs FROM ' . PREFIX . 'filter;');
   5820 	$data = $result->fetchAll(PDO::FETCH_NUM);
   5821 	$db->exec('DROP TABLE ' . PREFIX . 'filter;');
   5822 	$db->exec('CREATE TABLE ' . PREFIX . "filter (id integer PRIMARY KEY AUTO_INCREMENT, filtermatch varchar(255) NOT NULL, filterreplace text NOT NULL, allowinpm smallint NOT NULL, regex smallint NOT NULL, kick smallint NOT NULL, cs smallint NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;");
   5823 	$stmt = $db->prepare('INSERT INTO ' . PREFIX . 'filter (filtermatch, filterreplace, allowinpm, regex, kick, cs) VALUES(?, ?, ?, ?, ?, ?);');
   5824 	foreach ($data as $tmp) {
   5825 		$stmt->execute($tmp);
   5826 	}
   5827 	$result = $olddb->query('SELECT ign, ignby FROM ' . PREFIX . 'ignored;');
   5828 	$data = $result->fetchAll(PDO::FETCH_NUM);
   5829 	$db->exec('DROP TABLE ' . PREFIX . 'ignored;');
   5830 	$db->exec('CREATE TABLE ' . PREFIX . "ignored (id integer PRIMARY KEY AUTO_INCREMENT, ign varchar(50) NOT NULL, ignby varchar(50) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;");
   5831 	$stmt = $db->prepare('INSERT INTO ' . PREFIX . 'ignored (ign, ignby) VALUES(?, ?);');
   5832 	foreach ($data as $tmp) {
   5833 		$stmt->execute($tmp);
   5834 	}
   5835 	$db->exec('CREATE INDEX ' . PREFIX . 'ign ON ' . PREFIX . 'ignored(ign);');
   5836 	$db->exec('CREATE INDEX ' . PREFIX . 'ignby ON ' . PREFIX . 'ignored(ignby);');
   5837 	$result = $olddb->query('SELECT postdate, postid, poster, recipient, text FROM ' . PREFIX . 'inbox;');
   5838 	$data = $result->fetchAll(PDO::FETCH_NUM);
   5839 	$db->exec('DROP TABLE ' . PREFIX . 'inbox;');
   5840 	$db->exec('CREATE TABLE ' . PREFIX . "inbox (id integer PRIMARY KEY AUTO_INCREMENT, postdate integer NOT NULL, postid integer NOT NULL UNIQUE, poster varchar(50) NOT NULL, recipient varchar(50) NOT NULL, text text NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;");
   5841 	$stmt = $db->prepare('INSERT INTO ' . PREFIX . 'inbox (postdate, postid, poster, recipient, text) VALUES(?, ?, ?, ?, ?);');
   5842 	foreach ($data as $tmp) {
   5843 		$stmt->execute($tmp);
   5844 	}
   5845 	$db->exec('CREATE INDEX ' . PREFIX . 'inbox_poster ON ' . PREFIX . 'inbox(poster);');
   5846 	$db->exec('CREATE INDEX ' . PREFIX . 'inbox_recipient ON ' . PREFIX . 'inbox(recipient);');
   5847 	$result = $olddb->query('SELECT filtermatch, filterreplace, regex FROM ' . PREFIX . 'linkfilter;');
   5848 	$data = $result->fetchAll(PDO::FETCH_NUM);
   5849 	$db->exec('DROP TABLE ' . PREFIX . 'linkfilter;');
   5850 	$db->exec('CREATE TABLE ' . PREFIX . "linkfilter (id integer PRIMARY KEY AUTO_INCREMENT, filtermatch varchar(255) NOT NULL, filterreplace varchar(255) NOT NULL, regex smallint NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;");
   5851 	$stmt = $db->prepare('INSERT INTO ' . PREFIX . 'linkfilter (filtermatch, filterreplace, regex) VALUES(?, ?, ?);');
   5852 	foreach ($data as $tmp) {
   5853 		$stmt->execute($tmp);
   5854 	}
   5855 	$result = $olddb->query('SELECT nickname, passhash, status, refresh, bgcolour, regedby, lastlogin, timestamps, embed, incognito, style, nocache, tz, eninbox, sortupdown, hidechatters FROM ' . PREFIX . 'members;');
   5856 	$data = $result->fetchAll(PDO::FETCH_NUM);
   5857 	$db->exec('DROP TABLE ' . PREFIX . 'members;');
   5858 	$db->exec('CREATE TABLE ' . PREFIX . "members (id integer PRIMARY KEY AUTO_INCREMENT, nickname varchar(50) NOT NULL UNIQUE, passhash char(32) NOT NULL, status smallint NOT NULL, refresh smallint NOT NULL, bgcolour char(6) NOT NULL, regedby varchar(50) DEFAULT '', lastlogin integer DEFAULT 0, timestamps smallint NOT NULL, embed smallint NOT NULL, incognito smallint NOT NULL, style varchar(255) NOT NULL, nocache smallint NOT NULL, tz smallint NOT NULL, eninbox smallint NOT NULL, sortupdown smallint NOT NULL, hidechatters smallint NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;");
   5859 	$stmt = $db->prepare('INSERT INTO ' . PREFIX . 'members (nickname, passhash, status, refresh, bgcolour, regedby, lastlogin, timestamps, embed, incognito, style, nocache, tz, eninbox, sortupdown, hidechatters) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);');
   5860 	foreach ($data as $tmp) {
   5861 		$stmt->execute($tmp);
   5862 	}
   5863 	$result = $olddb->query('SELECT postdate, poststatus, poster, recipient, text, delstatus FROM ' . PREFIX . 'messages;');
   5864 	$data = $result->fetchAll(PDO::FETCH_NUM);
   5865 	$db->exec('DROP TABLE ' . PREFIX . 'messages;');
   5866 	$db->exec('CREATE TABLE ' . PREFIX . "messages (id integer PRIMARY KEY AUTO_INCREMENT, postdate integer NOT NULL, poststatus smallint NOT NULL, poster varchar(50) NOT NULL, recipient varchar(50) NOT NULL, text text NOT NULL, delstatus smallint NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;");
   5867 	$stmt = $db->prepare('INSERT INTO ' . PREFIX . 'messages (postdate, poststatus, poster, recipient, text, delstatus) VALUES(?, ?, ?, ?, ?, ?);');
   5868 	foreach ($data as $tmp) {
   5869 		$stmt->execute($tmp);
   5870 	}
   5871 	$db->exec('CREATE INDEX ' . PREFIX . 'poster ON ' . PREFIX . 'messages (poster);');
   5872 	$db->exec('CREATE INDEX ' . PREFIX . 'recipient ON ' . PREFIX . 'messages(recipient);');
   5873 	$db->exec('CREATE INDEX ' . PREFIX . 'postdate ON ' . PREFIX . 'messages(postdate);');
   5874 	$db->exec('CREATE INDEX ' . PREFIX . 'poststatus ON ' . PREFIX . 'messages(poststatus);');
   5875 	$result = $olddb->query('SELECT type, lastedited, editedby, text FROM ' . PREFIX . 'notes;');
   5876 	$data = $result->fetchAll(PDO::FETCH_NUM);
   5877 	$db->exec('DROP TABLE ' . PREFIX . 'notes;');
   5878 	$db->exec('CREATE TABLE ' . PREFIX . "notes (id integer PRIMARY KEY AUTO_INCREMENT, type char(5) NOT NULL, lastedited integer NOT NULL, editedby varchar(50) NOT NULL, text text NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;");
   5879 	$stmt = $db->prepare('INSERT INTO ' . PREFIX . 'notes (type, lastedited, editedby, text) VALUES(?, ?, ?, ?);');
   5880 	foreach ($data as $tmp) {
   5881 		$stmt->execute($tmp);
   5882 	}
   5883 	$result = $olddb->query('SELECT setting, value FROM ' . PREFIX . 'settings;');
   5884 	$data = $result->fetchAll(PDO::FETCH_NUM);
   5885 	$db->exec('DROP TABLE ' . PREFIX . 'settings;');
   5886 	$db->exec('CREATE TABLE ' . PREFIX . "settings (setting varchar(50) NOT NULL PRIMARY KEY, value text NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;");
   5887 	$stmt = $db->prepare('INSERT INTO ' . PREFIX . 'settings (setting, value) VALUES(?, ?);');
   5888 	foreach ($data as $tmp) {
   5889 		$stmt->execute($tmp);
   5890 	}
   5891 }
   5892 if ($dbversion < 33) {
   5893 	$db->exec('CREATE TABLE ' . PREFIX . "files (id $primary, postid integer NOT NULL UNIQUE, filename varchar(255) NOT NULL, hash char(40) NOT NULL, type varchar(255) NOT NULL, data $longtext NOT NULL)$diskengine$charset;");
   5894 	$db->exec('CREATE INDEX ' . PREFIX . 'files_hash ON ' . PREFIX . 'files(hash);');
   5895 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('enfileupload', '0'), ('msgattache', '%2\$s [%1\$s]'), ('maxuploadsize', '1024');");
   5896 }
   5897 if ($dbversion < 34) {
   5898 	$msg .= "<br>$I[cssupdate]";
   5899 	$db->exec('ALTER TABLE ' . PREFIX . 'members ADD COLUMN nocache_old smallint NOT NULL DEFAULT 0;');
   5900 }
   5901 if ($dbversion < 37) {
   5902 	$db->exec('ALTER TABLE ' . PREFIX . 'members MODIFY tz varchar(255) NOT NULL;');
   5903 	$db->exec('UPDATE ' . PREFIX . "members SET tz='UTC';");
   5904 	$db->exec('UPDATE ' . PREFIX . "settings SET value='UTC' WHERE setting='defaulttz';");
   5905 }
   5906 if ($dbversion < 38) {
   5907 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('nextcron', '0');");
   5908 	$db->exec('DELETE FROM ' . PREFIX . 'inbox WHERE recipient NOT IN (SELECT nickname FROM ' . PREFIX . 'members);'); // delete inbox of members who deleted themselves
   5909 }
   5910 if ($dbversion < 39) {
   5911 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('personalnotes', '1');");
   5912 	$result = $db->query('SELECT type, id FROM ' . PREFIX . 'notes;');
   5913 	while ($tmp = $result->fetch(PDO::FETCH_NUM)) {
   5914 		if ($tmp[0] === 'admin') {
   5915 			$tmp[0] = 0;
   5916 		} else {
   5917 			$tmp[0] = 1;
   5918 		}
   5919 		$data[] = $tmp;
   5920 	}
   5921 	$db->exec('ALTER TABLE ' . PREFIX . 'notes MODIFY type smallint NOT NULL;');
   5922 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'notes SET type=? WHERE id=?;');
   5923 	foreach ($data as $tmp) {
   5924 		$stmt->execute($tmp);
   5925 	}
   5926 	$db->exec('CREATE INDEX ' . PREFIX . 'notes_type ON ' . PREFIX . 'notes(type);');
   5927 	$db->exec('CREATE INDEX ' . PREFIX . 'notes_editedby ON ' . PREFIX . 'notes(editedby);');
   5928 }
   5929 if ($dbversion < 41) {
   5930 	$db->exec('DROP TABLE ' . PREFIX . 'sessions;');
   5931 	$db->exec('CREATE TABLE ' . PREFIX . "sessions (id $primary, session char(32) NOT NULL UNIQUE, nickname varchar(50) NOT NULL UNIQUE, status smallint NOT NULL, refresh smallint NOT NULL, style varchar(255) NOT NULL, lastpost integer NOT NULL, passhash varchar(255) NOT NULL, postid char(6) NOT NULL DEFAULT '000000', useragent varchar(255) NOT NULL, kickmessage varchar(255) DEFAULT '', bgcolour char(6) NOT NULL, entry integer NOT NULL, timestamps smallint NOT NULL, embed smallint NOT NULL, incognito smallint NOT NULL, ip varchar(45) NOT NULL, nocache smallint NOT NULL, tz varchar(255) NOT NULL, eninbox smallint NOT NULL, sortupdown smallint NOT NULL, hidechatters smallint NOT NULL, nocache_old smallint NOT NULL)$memengine$charset;");
   5932 	$db->exec('CREATE INDEX ' . PREFIX . 'status ON ' . PREFIX . 'sessions(status);');
   5933 	$db->exec('CREATE INDEX ' . PREFIX . 'lastpost ON ' . PREFIX . 'sessions(lastpost);');
   5934 	$db->exec('CREATE INDEX ' . PREFIX . 'incognito ON ' . PREFIX . 'sessions(incognito);');
   5935 	$result = $db->query('SELECT nickname, passhash, status, refresh, bgcolour, regedby, lastlogin, timestamps, embed, incognito, style, nocache, nocache_old, tz, eninbox, sortupdown, hidechatters FROM ' . PREFIX . 'members;');
   5936 	$members = $result->fetchAll(PDO::FETCH_NUM);
   5937 	$result = $db->query('SELECT postdate, postid, poster, recipient, text FROM ' . PREFIX . 'inbox;');
   5938 	$inbox = $result->fetchAll(PDO::FETCH_NUM);
   5939 	$db->exec('DROP TABLE ' . PREFIX . 'inbox;');
   5940 	$db->exec('DROP TABLE ' . PREFIX . 'members;');
   5941 	$db->exec('CREATE TABLE ' . PREFIX . "members (id $primary, nickname varchar(50) NOT NULL UNIQUE, passhash varchar(255) NOT NULL, status smallint NOT NULL, refresh smallint NOT NULL, bgcolour char(6) NOT NULL, regedby varchar(50) DEFAULT '', lastlogin integer DEFAULT 0, timestamps smallint NOT NULL, embed smallint NOT NULL, incognito smallint NOT NULL, style varchar(255) NOT NULL, nocache smallint NOT NULL, nocache_old smallint NOT NULL, tz varchar(255) NOT NULL, eninbox smallint NOT NULL, sortupdown smallint NOT NULL, hidechatters smallint NOT NULL)$diskengine$charset");
   5942 	$stmt = $db->prepare('INSERT INTO ' . PREFIX . 'members (nickname, passhash, status, refresh, bgcolour, regedby, lastlogin, timestamps, embed, incognito, style, nocache, nocache_old, tz, eninbox, sortupdown, hidechatters) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);');
   5943 	foreach ($members as $tmp) {
   5944 		$stmt->execute($tmp);
   5945 	}
   5946 	$db->exec('CREATE TABLE ' . PREFIX . "inbox (id $primary, postdate integer NOT NULL, postid integer NOT NULL UNIQUE, poster varchar(50) NOT NULL, recipient varchar(50) NOT NULL, text text NOT NULL)$diskengine$charset;");
   5947 	$stmt = $db->prepare('INSERT INTO ' . PREFIX . 'inbox (postdate, postid, poster, recipient, text) VALUES(?, ?, ?, ?, ?);');
   5948 	foreach ($inbox as $tmp) {
   5949 		$stmt->execute($tmp);
   5950 	}
   5951 	$db->exec('CREATE INDEX ' . PREFIX . 'inbox_poster ON ' . PREFIX . 'inbox(poster);');
   5952 	$db->exec('CREATE INDEX ' . PREFIX . 'inbox_recipient ON ' . PREFIX . 'inbox(recipient);');
   5953 	$db->exec('ALTER TABLE ' . PREFIX . 'inbox ADD FOREIGN KEY (recipient) REFERENCES ' . PREFIX . 'members(nickname) ON DELETE CASCADE ON UPDATE CASCADE;');
   5954 }
   5955 if ($dbversion < 42) {
   5956 	$db->exec('INSERT IGNORE INTO ' . PREFIX . "settings (setting, value) VALUES ('filtermodkick', '1');");
   5957 }
   5958 //MODIFICATION Text field for links in settings and option to enable or disable links page.
   5959 if ($dbversion < 1142) {
   5960 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('links', '');");
   5961 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('linksenabled', '0');");
   5962 }
   5963 //MODIFICATION option to enable or disable DEL-Buttons for members, if no mod is present. (DEL Buttons can bes used to delete messages within the message frame)
   5964 if ($dbversion < 1242) {
   5965 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('memdel', '0');");
   5966 }
   5967 
   5968 //MODIFICATION clickable nicknames
   5969 /* REMOVE LATER
   5970  if($dbversion<1243){
   5971     $db->exec('ALTER TABLE ' . PREFIX . 'sessions ADD COLUMN clickablenicknames smallint NOT NULL DEFAULT 0;');
   5972     $db->exec('ALTER TABLE ' . PREFIX . 'members ADD COLUMN clickablenicknames smallint NOT NULL DEFAULT 0;');
   5973    }
   5974    */
   5975 
   5976 //MODIFICATION option to set galleryaccess and forum button visibility for users depending on their rank(status).
   5977 if ($dbversion < 1342) {
   5978 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('galleryaccess', '10');");
   5979 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('forumbtnaccess', '10');");
   5980 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('forumbtnlink', 'forum/index.php');");
   5981 }
   5982 //MODIFICATION fontpgagetext - Text field for text on front page of the chat.
   5983 if ($dbversion < 1442) {
   5984 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('frontpagetext', '');");
   5985 }
   5986 //MODIFICATION modsdeladminmsg - mods can delete admin messages. To be more precise: Staff members can delete messages of higher ranked staff members, bot only those messages that the lower ranked staff member can read (where status <= poststatus).
   5987 if ($dbversion < 1542) {
   5988 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('modsdeladminmsg', '0');");
   5989 }
   5990 //MODIFICATION adminjoinleavemsg to not create a system message if an admins arrives or leaves the chat
   5991 if ($dbversion < 1642) {
   5992 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('adminjoinleavemsg', '1');");
   5993 }
   5994 
   5995 //MODIFICATION clickablenicknamesglobal (nicknames at beginning of messages are clickable)
   5996 if ($dbversion < 1742) {
   5997 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('clickablenicknamesglobal', '1');");
   5998 }
   5999 // Modification spare notes
   6000 if ($dbversion < 2100) {
   6001 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('sparenotesaccess', '10');");
   6002 	$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('sparenotesname', '');");
   6003 }
   6004 // Modification for rooms
   6005 if ($dbversion < 2101) {
   6006 	$db->exec('INSERT IGNORE INTO ' . PREFIX . "settings (setting, value) VALUES ('roomcreateaccess', '7');");
   6007 	$db->exec('CREATE TABLE ' . PREFIX . "rooms (id $primary, name varchar(50) NOT NULL UNIQUE, access smallint NOT NULL, time integer NOT NULL)$diskengine$charset");
   6008 	$db->exec('ALTER TABLE ' . PREFIX . 'sessions ADD COLUMN roomid integer;');
   6009 	$db->exec('ALTER TABLE ' . PREFIX . 'messages ADD COLUMN roomid integer;');
   6010 	$db->exec('CREATE INDEX ' . PREFIX . 'sroomid ON ' . PREFIX . 'sessions(roomid);');
   6011 	$db->exec('CREATE INDEX ' . PREFIX . 'mroomid ON ' . PREFIX . 'messages(roomid);');
   6012 	$db->exec('INSERT IGNORE INTO ' . PREFIX . "settings (setting, value) VALUES ('roomexpire', '10');");
   6013 }
   6014 // Modification for rooms
   6015 if ($dbversion < 2102) {
   6016 	$db->exec('ALTER TABLE ' . PREFIX . 'rooms ADD COLUMN permanent smallint NOT NULL DEFAULT(0);');
   6017 	$db->exec('ALTER TABLE ' . PREFIX . 'messages ADD COLUMN allrooms smallint NOT NULL DEFAULT(0);');
   6018 }
   6019 // Modification for rooms
   6020 if ($dbversion < 2103) {
   6021 	$db->exec('INSERT IGNORE INTO ' . PREFIX . "settings (setting, value) VALUES ('channelvisinroom', '2');");
   6022 }
   6023 update_setting('dbversion', DBVERSION);
   6024 if ($msgencrypted !== MSGENCRYPTED) {
   6025 	if (!extension_loaded('sodium')) {
   6026 		send_fatal_error($I['sodiumextrequired']);
   6027 	}
   6028 	$result = $db->query('SELECT id, text FROM ' . PREFIX . 'messages;');
   6029 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'messages SET text=? WHERE id=?;');
   6030 	while ($message = $result->fetch(PDO::FETCH_ASSOC)) {
   6031 		if (MSGENCRYPTED) {
   6032 			$message['text'] = base64_encode(sodium_crypto_aead_aes256gcm_encrypt($message['text'], '', AES_IV, ENCRYPTKEY));
   6033 		} else {
   6034 			$message['text'] = sodium_crypto_aead_aes256gcm_decrypt(base64_decode($message['text']), null, AES_IV, ENCRYPTKEY);
   6035 		}
   6036 		$stmt->execute([$message['text'], $message['id']]);
   6037 	}
   6038 	$result = $db->query('SELECT id, text FROM ' . PREFIX . 'notes;');
   6039 	$stmt = $db->prepare('UPDATE ' . PREFIX . 'notes SET text=? WHERE id=?;');
   6040 	while ($message = $result->fetch(PDO::FETCH_ASSOC)) {
   6041 		if (MSGENCRYPTED) {
   6042 			$message['text'] = base64_encode(sodium_crypto_aead_aes256gcm_encrypt($message['text'], '', AES_IV, ENCRYPTKEY));
   6043 		} else {
   6044 			$message['text'] = sodium_crypto_aead_aes256gcm_decrypt(base64_decode($message['text']), null, AES_IV, ENCRYPTKEY);
   6045 		}
   6046 		$stmt->execute([$message['text'], $message['id']]);
   6047 	}
   6048 	update_setting('msgencrypted', (int) MSGENCRYPTED);
   6049 }
   6050 send_update($msg);
   6051 }
   6052 
   6053 function get_setting($setting)
   6054 {
   6055 global $db, $memcached;
   6056 if (!MEMCACHED || !$value = $memcached->get(DBNAME . '-' . PREFIX . "settings-$setting")) {
   6057 	$stmt = $db->prepare('SELECT value FROM ' . PREFIX . 'settings WHERE setting=?;');
   6058 	$stmt->execute([$setting]);
   6059 	$stmt->bindColumn(1, $value);
   6060 	$stmt->fetch(PDO::FETCH_BOUND);
   6061 	if (MEMCACHED) {
   6062 		$memcached->set(DBNAME . '-' . PREFIX . "settings-$setting", $value);
   6063 	}
   6064 }
   6065 return $value;
   6066 }
   6067 
   6068 function update_setting($setting, $value)
   6069 {
   6070 global $db, $memcached;
   6071 $stmt = $db->prepare('UPDATE ' . PREFIX . 'settings SET value=? WHERE setting=?;');
   6072 $stmt->execute([$value, $setting]);
   6073 if (MEMCACHED) {
   6074 	$memcached->set(DBNAME . '-' . PREFIX . "settings-$setting", $value);
   6075 }
   6076 }
   6077 
   6078 // configuration, defaults and internals
   6079 
   6080 function check_db()
   6081 {
   6082 global $I, $db, $memcached;
   6083 $options = [PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING, PDO::ATTR_PERSISTENT => PERSISTENT];
   6084 try {
   6085 	if (DBDRIVER === 0) {
   6086 		if (!extension_loaded('pdo_mysql')) {
   6087 			send_fatal_error($I['pdo_mysqlextrequired']);
   6088 		}
   6089 		$db = new PDO('mysql:host=' . DBHOST . ';dbname=' . DBNAME . ';charset=utf8mb4', DBUSER, DBPASS, $options);
   6090 	} elseif (DBDRIVER === 1) {
   6091 		if (!extension_loaded('pdo_pgsql')) {
   6092 			send_fatal_error($I['pdo_pgsqlextrequired']);
   6093 		}
   6094 		$db = new PDO('pgsql:host=' . DBHOST . ';dbname=' . DBNAME, DBUSER, DBPASS, $options);
   6095 	} else {
   6096 		if (!extension_loaded('pdo_sqlite')) {
   6097 			send_fatal_error($I['pdo_sqliteextrequired']);
   6098 		}
   6099 		$db = new PDO('sqlite:' . SQLITEDBFILE, NULL, NULL, $options);
   6100 	}
   6101 } catch (PDOException $e) {
   6102 	try {
   6103 		//Attempt to create database
   6104 		if (DBDRIVER === 0) {
   6105 			$db = new PDO('mysql:host=' . DBHOST, DBUSER, DBPASS, $options);
   6106 			if (false !== $db->exec('CREATE DATABASE ' . DBNAME)) {
   6107 				$db = new PDO('mysql:host=' . DBHOST . ';dbname=' . DBNAME . ';charset=utf8mb4', DBUSER, DBPASS, $options);
   6108 			} else {
   6109 				send_fatal_error($I['nodbsetup']);
   6110 			}
   6111 		} elseif (DBDRIVER === 1) {
   6112 			$db = new PDO('pgsql:host=' . DBHOST, DBUSER, DBPASS, $options);
   6113 			if (false !== $db->exec('CREATE DATABASE ' . DBNAME)) {
   6114 				$db = new PDO('pgsql:host=' . DBHOST . ';dbname=' . DBNAME, DBUSER, DBPASS, $options);
   6115 			} else {
   6116 				send_fatal_error($I['nodbsetup']);
   6117 			}
   6118 		} else {
   6119 			if (isset($_REQUEST['action']) && $_REQUEST['action'] === 'setup') {
   6120 				send_fatal_error($I['nodbsetup']);
   6121 			} else {
   6122 				send_fatal_error($I['nodb']);
   6123 			}
   6124 		}
   6125 	} catch (PDOException $e) {
   6126 		if (isset($_REQUEST['action']) && $_REQUEST['action'] === 'setup') {
   6127 			send_fatal_error($I['nodbsetup']);
   6128 		} else {
   6129 			send_fatal_error($I['nodb']);
   6130 		}
   6131 	}
   6132 }
   6133 if (MEMCACHED) {
   6134 	if (!extension_loaded('memcached')) {
   6135 		send_fatal_error($I['memcachedextrequired']);
   6136 	}
   6137 	$memcached = new Memcached();
   6138 	$memcached->addServer(MEMCACHEDHOST, MEMCACHEDPORT);
   6139 }
   6140 if (!isset($_REQUEST['action']) || $_REQUEST['action'] === 'setup') {
   6141 	if (!check_init()) {
   6142 		send_init();
   6143 	}
   6144 	update_db();
   6145 } elseif ($_REQUEST['action'] === 'init') {
   6146 	init_chat();
   6147 }
   6148 }
   6149 
   6150 function load_fonts()
   6151 {
   6152 return [
   6153 	'Arial'			=> "font-family:'Arial','Helvetica','sans-serif';",
   6154 	'Book Antiqua'		=> "font-family:'Book Antiqua','MS Gothic';",
   6155 	'Comic'			=> "font-family:'Comic Sans MS','Papyrus';",
   6156 	'Courier'		=> "font-family:'Courier New','Courier','monospace';",
   6157 	'Cursive'		=> "font-family:'Cursive','Papyrus';",
   6158 	'Fantasy'		=> "font-family:'Fantasy','Futura','Papyrus';",
   6159 	'Garamond'		=> "font-family:'Garamond','Palatino','serif';",
   6160 	'Georgia'		=> "font-family:'Georgia','Times New Roman','Times','serif';",
   6161 	'Serif'			=> "font-family:'MS Serif','New York','serif';",
   6162 	'System'		=> "font-family:'System','Chicago','sans-serif';",
   6163 	'Times New Roman'	=> "font-family:'Times New Roman','Times','serif';",
   6164 	'Verdana'		=> "font-family:'Verdana','Geneva','Arial','Helvetica','sans-serif';",
   6165 ];
   6166 }
   6167 
   6168 function load_lang()
   6169 {
   6170 global $I, $L, $language;
   6171 $L = [
   6172 	'bg'	=> 'Български',
   6173 	'cz'	=> 'čeština',
   6174 	'de'	=> 'Deutsch',
   6175 	'en'	=> 'English',
   6176 	'es'	=> 'Español',
   6177 	'fr'	=> 'Français',
   6178 	'id'	=> 'Bahasa Indonesia',
   6179 	'it'	=> 'Italiano',
   6180 	'ru'	=> 'Русский',
   6181 	'tr'	=> 'Türkçe',
   6182 	'uk'	=> 'Українська',
   6183 	'zh_CN'	=> '简体中文',
   6184 ];
   6185 if (isset($_REQUEST['lang']) && isset($L[$_REQUEST['lang']])) {
   6186 	$language = $_REQUEST['lang'];
   6187 	if (!isset($_COOKIE['language']) || $_COOKIE['language'] !== $language) {
   6188 		set_secure_cookie('language', $language);
   6189 	}
   6190 } elseif (isset($_COOKIE['language']) && isset($L[$_COOKIE['language']])) {
   6191 	$language = $_COOKIE['language'];
   6192 } else {
   6193 	$language = LANG;
   6194 	set_secure_cookie('language', $language);
   6195 }
   6196 include('lang_en.php'); //always include English
   6197 if ($language !== 'en') {
   6198 	$T = [];
   6199 	include("lang_$language.php"); //replace with translation if available
   6200 	foreach ($T as $name => $translation) {
   6201 		$I[$name] = $translation;
   6202 	}
   6203 }
   6204 }
   6205 
   6206 function load_config()
   6207 {
   6208 mb_internal_encoding('UTF-8');
   6209 define('VERSION', '2.2.2'); // Script version
   6210 //See changelog
   6211 
   6212 define('DBVERSION', 10); // Database layout version
   6213 //Paste other config below this line: 
   6214 define('MSGENCRYPTED', false); // Store messages encrypted in the database to prevent other database users from reading them - true/false - visit the setup page after editing!
   6215 define('ENCRYPTKEY_PASS', 'MY_SECRET_KEY'); // Recommended length: 32. Encryption key for messages
   6216 define('AES_IV_PASS', '012345678912'); // Recommended length: 12. AES Encryption IV
   6217 define('DBHOST', 'dbhost'); // Database host
   6218 define('DBUSER', 'dbuser'); // Database user
   6219 define('DBPASS', 'dbpass'); // Database password
   6220 define('DBNAME', 'dbname'); // Database
   6221 define('PERSISTENT', true); // Use persistent database conection true/false
   6222 define('PREFIX', ''); // Prefix - Set this to a unique value for every chat, if you have more than 1 chats on the same database or domain - use only alpha-numeric values (A-Z, a-z, 0-9, or _) other symbols might break the queries
   6223 define('MEMCACHED', false); // Enable/disable memcached caching true/false - needs memcached extension and a memcached server.
   6224 if (MEMCACHED) {
   6225 	define('MEMCACHEDHOST', 'localhost'); // Memcached host
   6226 	define('MEMCACHEDPORT', '11211'); // Memcached port
   6227 }
   6228 define('DBDRIVER', 2); // Selects the database driver to use - 0=MySQL, 1=PostgreSQL, 2=sqlite
   6229 if (DBDRIVER === 2) {
   6230 	define('SQLITEDBFILE', $_ENV['SQLITE_DB_PATH'] ?? getenv('SQLITE_DB_PATH') ?? 'super_chat.sqlite'); // Filepath of the sqlite database, if sqlite is used - make sure it is writable for the webserver user
   6231 }
   6232 define('COOKIENAME', PREFIX . 'chat_session'); // Cookie name storing the session information
   6233 define('LANG', 'en'); // Default language
   6234 if (MSGENCRYPTED) {
   6235 	if (version_compare(PHP_VERSION, '7.2.0') < 0) {
   6236 		die("You need at least PHP >= 7.2.x");
   6237 	}
   6238 	//Do not touch: Compute real keys needed by encryption functions
   6239 	if (strlen(ENCRYPTKEY_PASS) !== SODIUM_CRYPTO_AEAD_AES256GCM_KEYBYTES) {
   6240 		define('ENCRYPTKEY', substr(hash("sha512/256", ENCRYPTKEY_PASS), 0, SODIUM_CRYPTO_AEAD_AES256GCM_KEYBYTES));
   6241 	} else {
   6242 		define('ENCRYPTKEY', ENCRYPTKEY_PASS);
   6243 	}
   6244 	if (strlen(AES_IV_PASS) !== SODIUM_CRYPTO_AEAD_AES256GCM_NPUBBYTES) {
   6245 		define('AES_IV', substr(hash("sha512/256", AES_IV_PASS), 0, SODIUM_CRYPTO_AEAD_AES256GCM_NPUBBYTES));
   6246 	} else {
   6247 		define('AES_IV', AES_IV_PASS);
   6248 	}
   6249 }
   6250 }