· 6 years ago · Sep 03, 2019, 10:52 AM
1CHAT.PHP
2
3<?php
4/*
5* LE CHAT-PHP - a PHP Chat based on LE CHAT - Main program
6*
7* Copyright (C) 2015-2018 Daniel Winzen <d@winzen4.de>
8*
9* This program is free software: you can redistribute it and/or modify
10* it under the terms of the GNU General Public License as published by
11* the Free Software Foundation, either version 3 of the License, or
12* (at your option) any later version.
13*
14* This program is distributed in the hope that it will be useful,
15* but WITHOUT ANY WARRANTY; without even the implied warranty of
16* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17* GNU General Public License for more details.
18*
19* You should have received a copy of the GNU General Public License
20* along with this program. If not, see <http://www.gnu.org/licenses/>.
21*/
22
23/*
24* status codes
25* 0 - Kicked/Banned
26* 1 - Guest
27* 2 - Applicant
28* 3 - Member
29* 4 - System message
30* 5 - Moderator
31* 6 - Super-Moderator
32* 7 - Admin
33* 8 - Super-Admin
34* 9 - Private messages
35*/
36
37include "site_config.php";
38
39send_headers();
40// initialize and load variables/configuration
41$I=[];// Translations
42$L=[];// Languages
43$U=[];// This user data
44$db;// Database connection
45$memcached;// Memcached connection
46$language;// user selected language
47load_config();
48// set session variable to cookie if cookies are enabled
49if(!isset($_REQUEST['session']) && isset($_COOKIE[COOKIENAME])){
50 $_REQUEST['session']=$_COOKIE[COOKIENAME];
51}
52load_lang();
53check_db();
54cron();
55route();
56
57// main program: decide what to do based on queries
58function route(){
59 global $U;
60 if(!isset($_REQUEST['action'])){
61 send_login();
62 }elseif($_REQUEST['action']==='view'){
63 check_session();
64 send_messages();
65 }elseif($_REQUEST['action']==='redirect' && !empty($_REQUEST['url'])){
66 send_redirect($_REQUEST['url']);
67 }elseif($_REQUEST['action']==='wait'){
68 parse_sessions();
69 send_waiting_room();
70 }elseif($_REQUEST['action']==='post'){
71 check_session();
72 if(isset($_REQUEST['kick']) && isset($_REQUEST['sendto']) && $_REQUEST['sendto']!=='s &'){
73 if($U['status']>=5 || ($U['status']>=3 && get_count_mods()==0 && get_setting('memkick'))){
74 if(isset($_REQUEST['what']) && $_REQUEST['what']==='purge'){
75 kick_chatter([$_REQUEST['sendto']], $_REQUEST['message'], true);
76 }else{
77 kick_chatter([$_REQUEST['sendto']], $_REQUEST['message'], false);
78 }
79 }
80 }elseif(isset($_REQUEST['message']) && isset($_REQUEST['sendto'])){
81 send_post(validate_input());
82 return; // debbie added this, think it was missing because if validate_input returns a rejection failure, it is never shown
83 }
84 send_post();
85 }elseif($_REQUEST['action']==='msglink'){
86 // debbies add-on to enable links from message frame to populate text box in post box with @personsname
87 check_session();
88 if(isset($_REQUEST['refname']))
89 {
90 send_post("@".$_REQUEST['refname']." ");
91 }
92 else
93 {
94 send_post();
95 }
96 }elseif($_REQUEST['action']==='login'){
97 check_login();
98 send_frameset();
99 }elseif($_REQUEST['action']==='controls'){
100 check_session();
101 send_controls();
102 }elseif($_REQUEST['action']==='greeting'){
103 check_session();
104 send_greeting();
105 }elseif($_REQUEST['action']==='delete'){
106 check_session();
107 if($_REQUEST['what']==='all'){
108 if(isset($_REQUEST['confirm'])){
109 del_all_messages($U['nickname'], $U['status']==1 ? $U['entry'] : 0);
110 }else{
111 send_del_confirm();
112 }
113 }elseif($_REQUEST['what']==='last'){
114 del_last_message();
115 }
116 send_post();
117 }elseif($_REQUEST['action']==='profile'){
118 check_session();
119 $arg='';
120 if(!isset($_REQUEST['do'])){
121 }elseif($_REQUEST['do']==='save'){
122 $arg=save_profile();
123 }elseif($_REQUEST['do']==='delete'){
124 if(isset($_REQUEST['confirm'])){
125 delete_account();
126 }else{
127 send_delete_account();
128 }
129 }
130 send_profile($arg);
131 }elseif($_REQUEST['action']==='logout'){
132 kill_session();
133 send_logout();
134 }elseif($_REQUEST['action']==='colours'){
135 check_session();
136 send_colours();
137 }elseif($_REQUEST['action']==='notes'){
138 check_session();
139 if(isset($_REQUEST['do']) && $_REQUEST['do']==='admin' && $U['status']>6){
140 send_notes(0);
141 }elseif(isset($_REQUEST['do']) && $_REQUEST['do']==='staff' && $U['status']>=5){
142 send_notes(1);
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 }elseif($_REQUEST['action']==='setup'){
163 route_setup();
164 }else{
165 send_login();
166 }
167}
168function route_admin(){
169 global $U, $db;
170 if($U['status']<5){
171 send_access_denied();
172 }
173 if(!isset($_REQUEST['do'])){
174 }elseif($_REQUEST['do']==='clean'){
175 if($_REQUEST['what']==='choose'){
176 send_choose_messages();
177 }elseif($_REQUEST['what']==='selected'){
178 clean_selected($U['status'], $U['nickname']);
179 }elseif($_REQUEST['what']==='room'){
180 clean_room();
181 }elseif($_REQUEST['what']==='nick'){
182 $stmt=$db->prepare('SELECT null FROM ' . PREFIX . 'members WHERE nickname=? AND status>=?;');
183 $stmt->execute([$_REQUEST['nickname'], $U['status']]);
184 if(!$stmt->fetch(PDO::FETCH_ASSOC)){
185 del_all_messages($_REQUEST['nickname'], 0);
186 }
187 }
188 }elseif($_REQUEST['do']==='kick'){
189 if(isset($_REQUEST['name'])){
190 if(isset($_REQUEST['what']) && $_REQUEST['what']==='purge'){
191 kick_chatter($_REQUEST['name'], $_REQUEST['kickmessage'], true);
192 }else{
193 kick_chatter($_REQUEST['name'], $_REQUEST['kickmessage'], false);
194 }
195 }
196 }elseif($_REQUEST['do']==='logout'){
197 if(isset($_REQUEST['name'])){
198 logout_chatter($_REQUEST['name']);
199 }
200 }elseif($_REQUEST['do']==='sessions'){
201 if(isset($_REQUEST['kick']) && isset($_REQUEST['nick'])){
202 kick_chatter([$_REQUEST['nick']], '', false);
203 }elseif(isset($_REQUEST['logout']) && isset($_REQUEST['nick'])){
204 logout_chatter([$_REQUEST['nick']], '', false);
205 }
206 send_sessions();
207 }elseif($_REQUEST['do']==='register'){
208 return register_guest(3, $_REQUEST['name']);
209 }elseif($_REQUEST['do']==='superguest'){
210 return register_guest(2, $_REQUEST['name']);
211 }elseif($_REQUEST['do']==='status'){
212 return change_status($_REQUEST['name'], $_REQUEST['set']);
213 }elseif($_REQUEST['do']==='regnew'){
214 return register_new($_REQUEST['name'], $_REQUEST['pass']);
215 }elseif($_REQUEST['do']==='approve'){
216 approve_session();
217 send_approve_waiting();
218 }elseif($_REQUEST['do']==='guestaccess'){
219 if(isset($_REQUEST['guestaccess']) && preg_match('/^[0123]$/', $_REQUEST['guestaccess'])){
220 update_setting('guestaccess', $_REQUEST['guestaccess']);
221 }
222 }elseif($_REQUEST['do']==='filter'){
223 send_filter(manage_filter());
224 }elseif($_REQUEST['do']==='linkfilter'){
225 send_linkfilter(manage_linkfilter());
226 }elseif($_REQUEST['do']==='topic'){
227 if(isset($_REQUEST['topic'])){
228 update_setting('topic', htmlspecialchars($_REQUEST['topic']));
229 }
230 }elseif($_REQUEST['do']==='passreset'){
231 return passreset($_REQUEST['name'], $_REQUEST['pass']);
232 }elseif($_REQUEST['do']==='MultiKick'){
233 send_debbies_multikick();
234 }
235
236}
237
238function route_setup(){
239 global $U;
240 if(!valid_admin()){
241 send_alogin();
242 }
243 $C['bool_settings']=['suguests', 'imgembed', 'timestamps', 'trackip', 'memkick', 'forceredirect', 'incognito', 'sendmail', 'modfallback', 'disablepm', 'eninbox', 'enablegreeting', 'sortupdown', 'hidechatters', 'enfileupload', 'personalnotes', 'filtermodkick'];
244 $C['colour_settings']=['colbg', 'coltxt'];
245 $C['msg_settings']=['msgenter', 'msgexit', 'msgmemreg', 'msgsureg', 'msgkick', 'msgmultikick', 'msgallkick', 'msgclean', 'msgsendall', 'msgsendmem', 'msgsendmod', 'msgsendadm', 'msgsendprv', 'msgattache'];
246 $C['number_settings']=['memberexpire', 'guestexpire', 'kickpenalty', 'entrywait', 'captchatime', 'messageexpire', 'messagelimit', 'maxmessage', 'maxname', 'minpass', 'defaultrefresh', 'numnotes', 'maxuploadsize'];
247 $C['textarea_settings']=['rulestxt', 'css', 'disabletext'];
248 $C['text_settings']=['dateformat', 'captchachars', 'redirect', 'chatname', 'mailsender', 'mailreceiver', 'nickregex', 'passregex', 'externalcss'];
249 $C['settings']=array_merge(['guestaccess', 'englobalpass', 'globalpass', 'captcha', 'dismemcaptcha', 'topic', 'guestreg', 'defaulttz'], $C['bool_settings'], $C['colour_settings'], $C['msg_settings'], $C['number_settings'], $C['textarea_settings'], $C['text_settings']); // All settings in the database
250 if(!isset($_REQUEST['do'])){
251 }elseif($_REQUEST['do']==='save'){
252 save_setup($C);
253 }elseif($_REQUEST['do']==='backup' && $U['status']==8){
254 send_backup($C);
255 }elseif($_REQUEST['do']==='restore' && $U['status']==8){
256 restore_backup($C);
257 send_backup($C);
258 }elseif($_REQUEST['do']==='destroy' && $U['status']==8){
259 if(isset($_REQUEST['confirm'])){
260 destroy_chat($C);
261 }else{
262 send_destroy_chat();
263 }
264 }
265 send_setup($C);
266}
267
268// html output subs
269function print_stylesheet($init=false){
270 global $U;
271 //default css
272 echo '<style type="text/css">';
273 echo 'body{background-color:#000000;color:#FFFFFF;font-size:14px;text-align:center;} ';
274 echo 'a:visited{color:#B33CB4;} a:active{color:#FF0033;} a:link{color:#0000FF;} #messages{word-wrap:break-word;} ';
275 // debbie removed "a:hover" in line below as it messed with members badge formatting echo 'input,select,textarea{color:#FFFFFF;background-color:#000000;} .messages a img{width:15%} .messages a:hover img{width:35%} ';
276 echo 'input,select,textarea{color:#FFFFFF;background-color:#000000;} .messages a img{width:15%} ';
277 echo '.error{color:#FF0033;text-align:left;} .delbutton{background-color:#660000;} .backbutton{background-color:#004400;} #exitbutton{background-color:#AA0000;} ';
278 // To fix width of rankbadges
279 echo ' #rankbadgeswidth{ width: 15px; } ';
280 echo '.setup table table,.admin table table,.profile table table{width:100%;text-align:left} ';
281 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;} ';
282 echo '.setup table table table,.admin table table table,.profile table table table{border-spacing:0px;margin-left:auto;margin-right:unset;width:unset;} ';
283 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;} ';
284 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;} ';
285 echo '.messages #chatters{max-height:100px;overflow-y:auto;} .messages #chatters a{text-decoration-line:none;} .messages #chatters table{border-spacing:0px;} ';
286 echo '.messages #chatters th,.messages #chatters td,.post #firstline{vertical-align:top;} ';
287 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;} ';
288 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;} ';
289 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;} ';
290 echo '#manualrefresh{display:block;position:fixed;text-align:center;left:25%;width:50%;top:-200%;animation:timeout_messages ';
291 if(isset($U['refresh'])){
292 echo $U['refresh']+20;
293 }else{
294 echo '160';
295 }
296 echo 's forwards;z-index:2;background-color:#500000;border:2px solid #ff0000;} ';
297 echo '@keyframes timeout_messages{0%{top:-200%;} 99%{top:-200%;} 100%{top:0%;}} ';
298 echo '.notes textarea{height:80vh;width:80%;}';
299 echo '</style>';
300 if($init){
301 return;
302 }
303 $css=get_setting('css');
304 $coltxt=get_setting('coltxt');
305 if(!empty($U['bgcolour'])){
306 $colbg=$U['bgcolour'];
307 }else{
308 $colbg=get_setting('colbg');
309 }
310 //overwrite with custom css
311 echo "<style type=\"text/css\">body{background-color:#$colbg;color:#$coltxt;} $css</style>";
312}
313
314function print_end(){
315 echo '</body></html>';
316 exit;
317}
318
319function credit(){
320// removed reference to Topics and replaced with danwin's github
321 return '<small><br><br><a target="_blank" href="https://github.com/DanWin/le-chat-php/"></a> ' . VERSION . '</a></small>';
322}
323
324function meta_html(){
325 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">';
326}
327
328function form($action, $do=''){
329 global $language;
330 $form="<form action=\"$_SERVER[SCRIPT_NAME]\" enctype=\"multipart/form-data\" method=\"post\">".hidden('lang', $language).hidden('nc', substr(time(), -6)).hidden('action', $action);
331 if(!empty($_REQUEST['session'])){
332 $form.=hidden('session', $_REQUEST['session']);
333 }
334 if($do!==''){
335 $form.=hidden('do', $do);
336 }
337 return $form;
338}
339
340function form_target($target, $action, $do=''){
341 global $language;
342 $form="<form action=\"$_SERVER[SCRIPT_NAME]\" enctype=\"multipart/form-data\" method=\"post\" target=\"$target\">".hidden('lang', $language).hidden('nc', substr(time(), -6)).hidden('action', $action);
343 if(!empty($_REQUEST['session'])){
344 $form.=hidden('session', $_REQUEST['session']);
345 }
346 if($do!==''){
347 $form.=hidden('do', $do);
348 }
349 return $form;
350}
351
352function hidden($arg1='', $arg2=''){
353 return "<input type=\"hidden\" name=\"$arg1\" value=\"$arg2\">";
354}
355
356function submit($arg1='', $arg2=''){
357 return "<input type=\"submit\" value=\"$arg1\" $arg2>";
358}
359
360function thr(){
361 echo '<tr><td><hr></td></tr>';
362}
363
364function print_start($class='', $ref=0, $url=''){
365 global $I;
366 if(!empty($url)){
367 $url=str_replace('&', '&', $url);// Don't escape "&" in URLs here, it breaks some (older) browsers and js refresh!
368 header("Refresh: $ref; URL=$url");
369 }
370 echo '<!DOCTYPE html><html><head>'.meta_html();
371 if(!empty($url)){
372 echo "<meta http-equiv=\"Refresh\" content=\"$ref; URL=$url\">";
373 $ref+=5;//only use js if browser refresh stopped working
374 $ref*=1000;//js uses milliseconds
375 echo "<script type=\"text/javascript\">setTimeout(function(){window.location.replace(\"$url\");}, $ref);</script>";
376 }
377 if($class==='init'){
378 echo "<title>$I[init]</title>";
379 print_stylesheet(true);
380 }else{
381 echo '<title>'.get_setting('chatname').'</title>';
382 print_stylesheet();
383 }
384 echo "</head><body class=\"$class\">";
385 if($class!=='init' && ($externalcss=get_setting('externalcss'))!=''){
386 //external css - in body to make it non-renderblocking
387 echo "<link rel=\"stylesheet\" type=\"text/css\" href=\"$externalcss\">";
388 }
389}
390
391function send_redirect($url){
392 global $I;
393 $url=htmlspecialchars_decode(rawurldecode($url));
394 preg_match('~^(.*)://~u', $url, $match);
395 $url=preg_replace('~^(.*)://~u', '', $url);
396 $escaped=htmlspecialchars($url);
397 if(isset($match[1]) && ($match[1]==='http' || $match[1]==='https')){
398 print_start('redirect', 0, $match[0].$escaped);
399 echo "<p>$I[redirectto] <a href=\"$match[0]$escaped\">$match[0]$escaped</a>.</p>";
400 }else{
401 print_start('redirect');
402 if(!isset($match[0])){
403 $match[0]='';
404 }
405 echo "<p>$I[nonhttp] <a href=\"$match[0]$escaped\">$match[0]$escaped</a>.</p>";
406 echo "<p>$I[httpredir] <a href=\"http://$escaped\">http://$escaped</a>.</p>";
407 }
408 print_end();
409}
410
411function send_access_denied(){
412 global $I, $U;
413 header('HTTP/1.1 403 Forbidden');
414 print_start('access_denied');
415 echo "<h1>$I[accessdenied]</h1>".sprintf($I['loggedinas'], style_this(htmlspecialchars($U['nickname']), $U['style'])).'<br>';
416 echo form('logout');
417 if(!isset($_REQUEST['session'])){
418 echo hidden('session', $U['session']);
419 }
420 echo submit($I['logout'], 'id="exitbutton"')."</form>";
421 print_end();
422}
423
424function send_captcha(){
425 global $I, $db, $memcached;
426 $difficulty=(int) get_setting('captcha');
427 if($difficulty===0 || !extension_loaded('gd')){
428 return;
429 }
430 $captchachars=get_setting('captchachars');
431 $length=strlen($captchachars)-1;
432 $code='';
433 for($i=0;$i<5;++$i){
434 $code.=$captchachars[mt_rand(0, $length)];
435 }
436 $randid=mt_rand();
437 $time=time();
438 if(MEMCACHED){
439 $memcached->set(DBNAME . '-' . PREFIX . "captcha-$randid", $code, get_setting('captchatime'));
440 }else{
441 $stmt=$db->prepare('INSERT INTO ' . PREFIX . 'captcha (id, time, code) VALUES (?, ?, ?);');
442 $stmt->execute([$randid, $time, $code]);
443 }
444 echo "<tr id=\"captcha\"><td>$I[copy]<br>";
445 if($difficulty===1){
446 $im=imagecreatetruecolor(55, 24);
447 $bg=imagecolorallocate($im, 0, 0, 0);
448 $fg=imagecolorallocate($im, 255, 255, 255);
449 imagefill($im, 0, 0, $bg);
450 imagestring($im, 5, 5, 5, $code, $fg);
451 echo '<img width="55" height="24" src="data:image/gif;base64,';
452 }elseif($difficulty===2){
453 $im=imagecreatetruecolor(55, 24);
454 $bg=imagecolorallocate($im, 0, 0, 0);
455 $fg=imagecolorallocate($im, 255, 255, 255);
456 imagefill($im, 0, 0, $bg);
457 imagestring($im, 5, 5, 5, $code, $fg);
458 $line=imagecolorallocate($im, 255, 255, 255);
459 for($i=0;$i<2;++$i){
460 imageline($im, 0, mt_rand(0, 24), 55, mt_rand(0, 24), $line);
461 }
462 $dots=imagecolorallocate($im, 255, 255, 255);
463 for($i=0;$i<100;++$i){
464 imagesetpixel($im, mt_rand(0, 55), mt_rand(0, 24), $dots);
465 }
466 echo '<img width="55" height="24" src="data:image/gif;base64,';
467 }else{
468 $im=imagecreatetruecolor(150, 200);
469 $bg=imagecolorallocate($im, 0, 0, 0);
470 $fg=imagecolorallocate($im, 255, 255, 255);
471 imagefill($im, 0, 0, $bg);
472 $chars=[];
473 for($i=0;$i<10;++$i){
474 $found=false;
475 while(!$found){
476 $x=mt_rand(10, 140);
477 $y=mt_rand(10, 180);
478 $found=true;
479 foreach($chars as $char){
480 if($char['x']>=$x && ($char['x']-$x)<25){
481 $found=false;
482 }elseif($char['x']<$x && ($x-$char['x'])<25){
483 $found=false;
484 }
485 if(!$found){
486 if($char['y']>=$y && ($char['y']-$y)<25){
487 break;
488 }elseif($char['y']<$y && ($y-$char['y'])<25){
489 break;
490 }else{
491 $found=true;
492 }
493 }
494 }
495 }
496 $chars[]=['x', 'y'];
497 $chars[$i]['x']=$x;
498 $chars[$i]['y']=$y;
499 if($i<5){
500 imagechar($im, 5, $chars[$i]['x'], $chars[$i]['y'], $captchachars[mt_rand(0, $length)], $fg);
501 }else{
502 imagechar($im, 5, $chars[$i]['x'], $chars[$i]['y'], $code[$i-5], $fg);
503 }
504 }
505 $follow=imagecolorallocate($im, 200, 0, 0);
506 imagearc($im, $chars[5]['x']+4, $chars[5]['y']+8, 16, 16, 0, 360, $follow);
507 for($i=5;$i<9;++$i){
508 imageline($im, $chars[$i]['x']+4, $chars[$i]['y']+8, $chars[$i+1]['x']+4, $chars[$i+1]['y']+8, $follow);
509 }
510 $line=imagecolorallocate($im, 255, 255, 255);
511 for($i=0;$i<5;++$i){
512 imageline($im, 0, mt_rand(0, 200), 150, mt_rand(0, 200), $line);
513 }
514 $dots=imagecolorallocate($im, 255, 255, 255);
515 for($i=0;$i<1000;++$i){
516 imagesetpixel($im, mt_rand(0, 150), mt_rand(0, 200), $dots);
517 }
518 echo '<img width="150" height="200" src="data:image/gif;base64,';
519 }
520 ob_start();
521 imagegif($im);
522 imagedestroy($im);
523 echo base64_encode(ob_get_clean()).'">';
524 echo '</td><td>'.hidden('challenge', $randid).'<input type="text" name="captcha" size="15" autocomplete="off"></td></tr>';
525}
526
527function send_setup($C){
528 global $I, $U;
529 print_start('setup');
530 echo "<h2>$I[setup]</h2>".form('setup', 'save');
531 if(!isset($_REQUEST['session'])){
532 echo hidden('session', $U['session']);
533 }
534 echo '<table id="guestaccess">';
535 thr();
536 $ga=(int) get_setting('guestaccess');
537 echo "<tr><td><table><tr><th>$I[guestacc]</th><td>";
538 echo '<select name="guestaccess">';
539 echo '<option value="1"';
540 if($ga===1){
541 echo ' selected';
542 }
543 echo ">$I[guestallow]</option>";
544 echo '<option value="2"';
545 if($ga===2){
546 echo ' selected';
547 }
548 echo ">$I[guestwait]</option>";
549 echo '<option value="3"';
550 if($ga===3){
551 echo ' selected';
552 }
553 echo ">$I[adminallow]</option>";
554 echo '<option value="0"';
555 if($ga===0){
556 echo ' selected';
557 }
558 echo ">$I[guestdisallow]</option>";
559 echo '<option value="4"';
560 if($ga===4){
561 echo ' selected';
562 }
563 echo ">$I[disablechat]</option>";
564 echo '</select></td></tr></table></td></tr>';
565 thr();
566 $englobal=(int) get_setting('englobalpass');
567 echo "<tr><td><table id=\"globalpass\"><tr><th>$I[globalloginpass]</th><td>";
568 echo '<table>';
569 echo '<tr><td><select name="englobalpass">';
570 echo '<option value="0"';
571 if($englobal===0){
572 echo ' selected';
573 }
574 echo ">$I[disabled]</option>";
575 echo '<option value="1"';
576 if($englobal===1){
577 echo ' selected';
578 }
579 echo ">$I[enabled]</option>";
580 echo '<option value="2"';
581 if($englobal===2){
582 echo ' selected';
583 }
584 echo ">$I[onlyguests]</option>";
585 echo '</select></td><td> </td>';
586 echo '<td><input type="text" name="globalpass" value="'.htmlspecialchars(get_setting('globalpass')).'"></td></tr>';
587 echo '</table></td></tr></table></td></tr>';
588 thr();
589 $ga=(int) get_setting('guestreg');
590 echo "<tr><td><table id=\"guestreg\"><tr><th>$I[guestreg]</th><td>";
591 echo '<select name="guestreg">';
592 echo '<option value="0"';
593 if($ga===0){
594 echo ' selected';
595 }
596 echo ">$I[disabled]</option>";
597 echo '<option value="1"';
598 if($ga===1){
599 echo ' selected';
600 }
601 echo ">$I[assuguest]</option>";
602 echo '<option value="2"';
603 if($ga===2){
604 echo ' selected';
605 }
606 echo ">$I[asmember]</option>";
607 echo '</select></td></tr></table></td></tr>';
608 thr();
609 echo "<tr><td><table id=\"sysmessages\"><tr><th>$I[sysmessages]</th><td>";
610 echo '<table>';
611 foreach($C['msg_settings'] as $setting){
612 echo "<tr><td> $I[$setting]</td><td> <input type=\"text\" name=\"$setting\" value=\"".get_setting($setting).'"></td></tr>';
613 }
614 echo '</table></td></tr></table></td></tr>';
615 foreach($C['text_settings'] as $setting){
616 thr();
617 echo "<tr><td><table id=\"$setting\"><tr><th>".$I[$setting].'</th><td>';
618 echo "<input type=\"text\" name=\"$setting\" value=\"".htmlspecialchars(get_setting($setting)).'">';
619 echo '</td></tr></table></td></tr>';
620 }
621 foreach($C['colour_settings'] as $setting){
622 thr();
623 echo "<tr><td><table id=\"$setting\"><tr><th>".$I[$setting].'</th><td>';
624 echo "<input type=\"color\" name=\"$setting\" value=\"#".htmlspecialchars(get_setting($setting)).'">';
625 echo '</td></tr></table></td></tr>';
626 }
627 thr();
628 echo "<tr><td><table id=\"captcha\"><tr><th>$I[captcha]</th><td>";
629 echo '<table>';
630 if(!extension_loaded('gd')){
631 echo "<tr><td>$I[gdextrequired]</td></tr>";
632 }else{
633 echo '<tr><td><select name="dismemcaptcha">';
634 $dismemcaptcha=(bool) get_setting('dismemcaptcha');
635 echo '<option value="0"';
636 if(!$dismemcaptcha){
637 echo ' selected';
638 }
639 echo ">$I[enabled]</option>";
640 echo '<option value="1"';
641 if($dismemcaptcha){
642 echo ' selected';
643 }
644 echo ">$I[onlyguests]</option>";
645 echo '</select></td><td><select name="captcha">';
646 $captcha=(int) get_setting('captcha');
647 echo '<option value="0"';
648 if($captcha===0){
649 echo ' selected';
650 }
651 echo ">$I[disabled]</option>";
652 echo '<option value="1"';
653 if($captcha===1){
654 echo ' selected';
655 }
656 echo ">$I[simple]</option>";
657 echo '<option value="2"';
658 if($captcha===2){
659 echo ' selected';
660 }
661 echo ">$I[moderate]</option>";
662 echo '<option value="3"';
663 if($captcha===3){
664 echo ' selected';
665 }
666 echo ">$I[extreme]</option>";
667 echo '</select></td></tr>';
668 }
669 echo '</table></td></tr></table></td></tr>';
670 thr();
671 echo "<tr><td><table id=\"defaulttz\"><tr><th>$I[defaulttz]</th><td>";
672 echo "<select name=\"defaulttz\">";
673 $tzs=timezone_identifiers_list();
674 $defaulttz=get_setting('defaulttz');
675 foreach($tzs as $tz){
676 echo "<option value=\"$tz\"";
677 if($defaulttz==$tz){
678 echo ' selected';
679 }
680 echo ">$tz</option>";
681 }
682 echo '</select>';
683 echo '</td></tr></table></td></tr>';
684 foreach($C['textarea_settings'] as $setting){
685 thr();
686 echo "<tr><td><table id=\"$setting\"><tr><th>".$I[$setting].'</th><td>';
687 echo "<textarea name=\"$setting\" rows=\"4\" cols=\"60\">".htmlspecialchars(get_setting($setting)).'</textarea>';
688 echo '</td></tr></table></td></tr>';
689 }
690 foreach($C['number_settings'] as $setting){
691 thr();
692 echo "<tr><td><table id=\"$setting\"><tr><th>".$I[$setting].'</th><td>';
693 echo "<input type=\"number\" name=\"$setting\" value=\"".htmlspecialchars(get_setting($setting)).'">';
694 echo '</td></tr></table></td></tr>';
695 }
696 foreach($C['bool_settings'] as $setting){
697 thr();
698 echo "<tr><td><table id=\"$setting\"><tr><th>".$I[$setting].'</th><td>';
699 echo "<select name=\"$setting\">";
700 $value=(bool) get_setting($setting);
701 echo '<option value="0"';
702 if(!$value){
703 echo ' selected';
704 }
705 echo ">$I[disabled]</option>";
706 echo '<option value="1"';
707 if($value){
708 echo ' selected';
709 }
710 echo ">$I[enabled]</option>";
711 echo '</select></td></tr>';
712 echo '</table></td></tr>';
713 }
714 thr();
715 echo '<tr><td>'.submit($I['apply']).'</td></tr></table></form><br>';
716 if($U['status']==8){
717 echo '<table id="actions"><tr><td>';
718 echo form('setup', 'backup');
719 if(!isset($_REQUEST['session'])){
720 echo hidden('session', $U['session']);
721 }
722 echo submit($I['backuprestore']).'</form></td><td>';
723 echo form('setup', 'destroy');
724 if(!isset($_REQUEST['session'])){
725 echo hidden('session', $U['session']);
726 }
727 echo submit($I['destroy'], 'class="delbutton"').'</form></td></tr></table><br>';
728 }
729 echo form_target('_parent', 'logout');
730 if(!isset($_REQUEST['session'])){
731 echo hidden('session', $U['session']);
732 }
733 echo submit($I['logout'], 'id="exitbutton"').'</form>'.credit();
734 print_end();
735}
736
737function restore_backup($C){
738 global $db, $memcached;
739 if(!extension_loaded('json')){
740 return;
741 }
742 $code=json_decode($_REQUEST['restore'], true);
743 if(isset($_REQUEST['settings'])){
744 foreach($C['settings'] as $setting){
745 if(isset($code['settings'][$setting])){
746 update_setting($setting, $code['settings'][$setting]);
747 }
748 }
749 }
750 if(isset($_REQUEST['filter']) && (isset($code['filters']) || isset($code['linkfilters']))){
751 $db->exec('DELETE FROM ' . PREFIX . 'filter;');
752 $db->exec('DELETE FROM ' . PREFIX . 'linkfilter;');
753 $stmt=$db->prepare('INSERT INTO ' . PREFIX . 'filter (filtermatch, filterreplace, allowinpm, regex, kick, cs) VALUES (?, ?, ?, ?, ?, ?);');
754 foreach($code['filters'] as $filter){
755 if(!isset($filter['cs'])){
756 $filter['cs']=0;
757 }
758 $stmt->execute([$filter['match'], $filter['replace'], $filter['allowinpm'], $filter['regex'], $filter['kick'], $filter['cs']]);
759 }
760 $stmt=$db->prepare('INSERT INTO ' . PREFIX . 'linkfilter (filtermatch, filterreplace, regex) VALUES (?, ?, ?);');
761 foreach($code['linkfilters'] as $filter){
762 $stmt->execute([$filter['match'], $filter['replace'], $filter['regex']]);
763 }
764 if(MEMCACHED){
765 $memcached->delete(DBNAME . '-' . PREFIX . 'filter');
766 $memcached->delete(DBNAME . '-' . PREFIX . 'linkfilter');
767 }
768 }
769 if(isset($_REQUEST['members']) && isset($code['members'])){
770 $db->exec('DELETE FROM ' . PREFIX . 'inbox;');
771 $db->exec('DELETE FROM ' . PREFIX . 'members;');
772 $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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);');
773 foreach($code['members'] as $member){
774 $new_settings=['nocache', 'tz', 'eninbox', 'sortupdown', 'hidechatters', 'nocache_old'];
775 foreach($new_settings as $setting){
776 if(!isset($member[$setting])){
777 $member[$setting]=0;
778 }
779 }
780 $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']]);
781 }
782 }
783 if(isset($_REQUEST['notes']) && isset($code['notes'])){
784 $db->exec('DELETE FROM ' . PREFIX . 'notes;');
785 $stmt=$db->prepare('INSERT INTO ' . PREFIX . 'notes (type, lastedited, editedby, text) VALUES (?, ?, ?, ?);');
786 foreach($code['notes'] as $note){
787 if($note['type']==='admin'){
788 $note['type']=0;
789 }elseif($note['type']==='staff'){
790 $note['type']=1;
791 }
792 if(MSGENCRYPTED){
793 $note['text']=openssl_encrypt($note['text'], 'aes-256-cbc', ENCRYPTKEY, 0, '1234567890123456');
794 }
795 $stmt->execute([$note['type'], $note['lastedited'], $note['editedby'], $note['text']]);
796 }
797 }
798}
799
800function send_backup($C){
801 global $I, $db;
802 $code=[];
803 if($_REQUEST['do']==='backup'){
804 if(isset($_REQUEST['settings'])){
805 foreach($C['settings'] as $setting){
806 $code['settings'][$setting]=get_setting($setting);
807 }
808 }
809 if(isset($_REQUEST['filter'])){
810 $result=$db->query('SELECT * FROM ' . PREFIX . 'filter;');
811 while($filter=$result->fetch(PDO::FETCH_ASSOC)){
812 $code['filters'][]=['match'=>$filter['filtermatch'], 'replace'=>$filter['filterreplace'], 'allowinpm'=>$filter['allowinpm'], 'regex'=>$filter['regex'], 'kick'=>$filter['kick'], 'cs'=>$filter['cs']];
813 }
814 $result=$db->query('SELECT * FROM ' . PREFIX . 'linkfilter;');
815 while($filter=$result->fetch(PDO::FETCH_ASSOC)){
816 $code['linkfilters'][]=['match'=>$filter['filtermatch'], 'replace'=>$filter['filterreplace'], 'regex'=>$filter['regex']];
817 }
818 }
819 if(isset($_REQUEST['members'])){
820 $result=$db->query('SELECT * FROM ' . PREFIX . 'members;');
821 while($member=$result->fetch(PDO::FETCH_ASSOC)){
822 $code['members'][]=$member;
823 }
824 }
825 if(isset($_REQUEST['notes'])){
826 $result=$db->query('SELECT * FROM ' . PREFIX . "notes;");
827 while($note=$result->fetch(PDO::FETCH_ASSOC)){
828 if(MSGENCRYPTED){
829 $note['text']=openssl_decrypt($note['text'], 'aes-256-cbc', ENCRYPTKEY, 0, '1234567890123456');
830 }
831 $code['notes'][]=$note;
832 }
833 }
834 }
835 if(isset($_REQUEST['settings'])){
836 $chksettings=' checked';
837 }else{
838 $chksettings='';
839 }
840 if(isset($_REQUEST['filter'])){
841 $chkfilters=' checked';
842 }else{
843 $chkfilters='';
844 }
845 if(isset($_REQUEST['members'])){
846 $chkmembers=' checked';
847 }else{
848 $chkmembers='';
849 }
850 if(isset($_REQUEST['notes'])){
851 $chknotes=' checked';
852 }else{
853 $chknotes='';
854 }
855 print_start('backup');
856 echo "<h2>$I[backuprestore]</h2><table>";
857 thr();
858 if(!extension_loaded('json')){
859 echo "<tr><td>$I[jsonextrequired]</td></tr>";
860 }else{
861 echo '<tr><td>'.form('setup', 'backup');
862 echo '<table id="backup"><tr><td id="backupcheck">';
863 echo "<label><input type=\"checkbox\" name=\"settings\" id=\"backupsettings\" value=\"1\"$chksettings>$I[settings]</label>";
864 echo "<label><input type=\"checkbox\" name=\"filter\" id=\"backupfilter\" value=\"1\"$chkfilters>$I[filter]</label>";
865 echo "<label><input type=\"checkbox\" name=\"members\" id=\"backupmembers\" value=\"1\"$chkmembers>$I[members]</label>";
866 echo "<label><input type=\"checkbox\" name=\"notes\" id=\"backupnotes\" value=\"1\"$chknotes>$I[notes]</label>";
867 echo '</td><td id="backupsubmit">'.submit($I['backup']).'</td></tr></table></form></td></tr>';
868 thr();
869 echo '<tr><td>'.form('setup', 'restore');
870 echo '<table id="restore">';
871 echo "<tr><td colspan=\"2\"><textarea name=\"restore\" rows=\"4\" cols=\"60\">".htmlspecialchars(json_encode($code)).'</textarea></td></tr>';
872 echo "<tr><td id=\"restorecheck\"><label><input type=\"checkbox\" name=\"settings\" id=\"restoresettings\" value=\"1\"$chksettings>$I[settings]</label>";
873 echo "<label><input type=\"checkbox\" name=\"filter\" id=\"restorefilter\" value=\"1\"$chkfilters>$I[filter]</label>";
874 echo "<label><input type=\"checkbox\" name=\"members\" id=\"restoremembers\" value=\"1\"$chkmembers>$I[members]</label>";
875 echo "<label><input type=\"checkbox\" name=\"notes\" id=\"restorenotes\" value=\"1\"$chknotes>$I[notes]</label>";
876 echo '</td><td id="restoresubmit">'.submit($I['restore']).'</td></tr></table>';
877 echo '</form></td></tr>';
878 }
879 thr();
880 echo '<tr><td>'.form('setup').submit($I['initgosetup'], 'class="backbutton"')."</form></tr></td>";
881 echo '</table>';
882 print_end();
883}
884
885function send_destroy_chat(){
886 global $I;
887 print_start('destroy_chat');
888 echo "<table><tr><td colspan=\"2\">$I[confirm]</td></tr><tr><td>";
889 echo form_target('_parent', 'setup', 'destroy').hidden('confirm', 'yes').submit($I['yes'], 'class="delbutton"').'</form></td><td>';
890 echo form('setup').submit($I['no'], 'class="backbutton"').'</form></td><tr></table>';
891 print_end();
892}
893
894function send_delete_account(){
895 global $I;
896 print_start('delete_account');
897 echo "<table><tr><td colspan=\"2\">$I[confirm]</td></tr><tr><td>";
898 echo form('profile', 'delete').hidden('confirm', 'yes').submit($I['yes'], 'class="delbutton"').'</form></td><td>';
899 echo form('profile').submit($I['no'], 'class="backbutton"').'</form></td><tr></table>';
900 print_end();
901}
902
903function send_init(){
904 global $I, $L;
905 print_start('init');
906 echo "<h2>$I[init]</h2>";
907 echo form('init')."<table><tr><td><h3>$I[sulogin]</h3><table>";
908 echo "<tr><td>$I[sunick]</td><td><input type=\"text\" name=\"sunick\" size=\"15\"></td></tr>";
909 echo "<tr><td>$I[supass]</td><td><input type=\"password\" name=\"supass\" size=\"15\"></td></tr>";
910 echo "<tr><td>$I[suconfirm]</td><td><input type=\"password\" name=\"supassc\" size=\"15\"></td></tr>";
911 echo '</table></td></tr><tr><td><br>'.submit($I['initbtn']).'</td></tr></table></form>';
912 echo "<p id=\"changelang\">$I[changelang]";
913 foreach($L as $lang=>$name){
914 echo " <a href=\"$_SERVER[SCRIPT_NAME]?action=setup&lang=$lang\">$name</a>";
915 }
916 echo '</p>'.credit();
917 print_end();
918}
919
920function send_update($msg){
921 global $I;
922 print_start('update');
923 echo "<h2>$I[dbupdate]</h2><br>".form('setup').submit($I['initgosetup'])."</form>$msg<br>".credit();
924 print_end();
925}
926
927function send_alogin(){
928 global $I, $L;
929 print_start('alogin');
930 echo form('setup').'<table>';
931 echo "<tr><td>$I[nick]</td><td><input type=\"text\" name=\"nick\" size=\"15\" autofocus></td></tr>";
932 echo "<tr><td>$I[pass]</td><td><input type=\"password\" name=\"pass\" size=\"15\"></td></tr>";
933 send_captcha();
934 echo '<tr><td colspan="2">'.submit($I['login']).'</td></tr></table></form>';
935 echo "<p id=\"changelang\">$I[changelang]";
936 foreach($L as $lang=>$name){
937 echo " <a href=\"$_SERVER[SCRIPT_NAME]?action=setup&lang=$lang\">$name</a>";
938 }
939 echo '</p>'.credit();
940 print_end();
941}
942
943function send_admin($arg=''){
944 global $I, $U, $db;
945 $ga=(int) get_setting('guestaccess');
946 print_start('admin');
947 $chlist="<select name=\"name[]\" size=\"5\" multiple><option value=\"\">$I[choose]</option>";
948 $chlist.="<option value=\"s &\">$I[allguests]</option>";
949 $users=[];
950 $stmt=$db->query('SELECT nickname, style, status FROM ' . PREFIX . 'sessions WHERE entry!=0 AND status>0 ORDER BY LOWER(nickname);');
951 while($user=$stmt->fetch(PDO::FETCH_NUM)){
952 $users[]=[htmlspecialchars($user[0]), $user[1], $user[2]];
953 }
954 foreach($users as $user){
955 if($user[2]<$U['status']){
956 $chlist.="<option value=\"$user[0]\" style=\"$user[1]\">$user[0]</option>";
957 }
958 }
959 $chlist.='</select>';
960 echo "<h2>$I[admfunc]</h2><i>$arg</i><table>";
961 if($U['status']>=7){
962 thr();
963 echo '<tr><td>'.form_target('view', 'setup').submit($I['initgosetup']).'</form></td></tr>';
964 }
965 thr();
966 // Don't care who built the multi-kick function
967 echo "<tr><td><table id=\"DebbiesKick\"><tr><th>".'Troll Multi-Kick'.'</th><td>';
968 echo form('admin', 'MultiKick');
969 echo submit('Multi Kick').'</form></td></tr></table></td></tr>';
970 thr();
971 echo "<tr><td><table id=\"clean\"><tr><th>$I[cleanmsgs]</th><td>";
972 echo form('admin', 'clean');
973 echo '<table><tr><td><label><input type="radio" name="what" id="room" value="room">';
974 echo "$I[room]</label></td><td> </td><td><label><input type=\"radio\" name=\"what\" id=\"choose\" value=\"choose\" checked>";
975 echo "$I[selection]</label></td><td> </td></tr><tr><td colspan=\"3\"><label><input type=\"radio\" name=\"what\" id=\"nick\" value=\"nick\">";
976 echo "$I[cleannick]</label> <select name=\"nickname\" size=\"1\"><option value=\"\">$I[choose]</option>";
977 $stmt=$db->prepare('SELECT poster FROM ' . PREFIX . "messages WHERE delstatus<? AND poster!='' GROUP BY poster;");
978 $stmt->execute([$U['status']]);
979 while($nick=$stmt->fetch(PDO::FETCH_NUM)){
980 echo '<option value="'.htmlspecialchars($nick[0]).'">'.htmlspecialchars($nick[0]).'</option>';
981 }
982 echo '</select></td><td>';
983 echo submit($I['clean'], 'class="delbutton"').'</td></tr></table></form></td></tr></table></td></tr>';
984 thr();
985 echo '<tr><td><table id="kick"><tr><th>'.sprintf($I['kickchat'], get_setting('kickpenalty')).'</th></tr><tr><td>';
986 echo form('admin', 'kick');
987 echo "<table><tr><td>$I[kickreason]</td><td><input type=\"text\" name=\"kickmessage\" size=\"30\"></td><td> </td></tr>";
988 echo "<tr><td><label><input type=\"checkbox\" name=\"what\" value=\"purge\" id=\"purge\">$I[kickpurge]</label></td><td>$chlist</td><td>";
989 echo submit($I['kick']).'</td></tr></table></form></td></tr></table></td></tr>';
990 thr();
991 echo "<tr><td><table id=\"logout\"><tr><th>$I[logoutinact]</th><td>";
992 echo form('admin', 'logout');
993 echo "<table><tr><td>$chlist</td><td>";
994 echo submit($I['logout']).'</td></tr></table></form></td></tr></table></td></tr>';
995 $views=['sessions', 'filter', 'linkfilter'];
996 foreach($views as $view){
997 thr();
998 echo "<tr><td><table id=\"$view\"><tr><th>".$I[$view].'</th><td>';
999 echo form('admin', $view);
1000 echo submit($I['view']).'</form></td></tr></table></td></tr>';
1001 }
1002 thr();
1003 echo "<tr><td><table id=\"topic\"><tr><th>$I[topic]</th><td>";
1004 echo form('admin', 'topic');
1005 echo '<table><tr><td><input type="text" name="topic" size="20" value="'.get_setting('topic').'"></td><td>';
1006 echo submit($I['change']).'</td></tr></table></form></td></tr></table></td></tr>';
1007 thr();
1008 echo "<tr><td><table id=\"guestaccess\"><tr><th>$I[guestacc]</th><td>";
1009 echo form('admin', 'guestaccess');
1010 echo '<table>';
1011 echo '<tr><td><select name="guestaccess">';
1012 echo '<option value="1"';
1013 if($ga===1){
1014 echo ' selected';
1015 }
1016 echo ">$I[guestallow]</option>";
1017 echo '<option value="2"';
1018 if($ga===2){
1019 echo ' selected';
1020 }
1021 echo ">$I[guestwait]</option>";
1022 echo '<option value="3"';
1023 if($ga===3){
1024 echo ' selected';
1025 }
1026 echo ">$I[adminallow]</option>";
1027 echo '<option value="0"';
1028 if($ga===0){
1029 echo ' selected';
1030 }
1031 echo ">$I[guestdisallow]</option>";
1032 if($ga===4){
1033 echo '<option value="4" selected';
1034 echo ">$I[disablechat]</option>";
1035 }
1036 echo '</select></td><td>'.submit($I['change']).'</td></tr></table></form></td></tr></table></td></tr>';
1037 thr();
1038 if(get_setting('suguests')){
1039 echo "<tr><td><table id=\"suguests\"><tr><th>$I[addsuguest]</th><td>";
1040 echo form('admin', 'superguest');
1041 echo "<table><tr><td><select name=\"name\" size=\"1\"><option value=\"\">$I[choose]</option>";
1042 foreach($users as $user){
1043 if($user[2]==1){
1044 echo "<option value=\"$user[0]\" style=\"$user[1]\">$user[0]</option>";
1045 }
1046 }
1047 echo '</select></td><td>'.submit($I['register']).'</td></tr></table></form></td></tr></table></td></tr>';
1048 thr();
1049 }
1050 if($U['status']>=7){
1051 echo "<tr><td><table id=\"status\"><tr><th>$I[admmembers]</th><td>";
1052 echo form('admin', 'status');
1053 echo "<table><td><select name=\"name\" size=\"1\"><option value=\"\">$I[choose]</option>";
1054 $members=[];
1055 $result=$db->query('SELECT nickname, style, status FROM ' . PREFIX . 'members ORDER BY LOWER(nickname);');
1056 while($temp=$result->fetch(PDO::FETCH_NUM)){
1057 $members[]=[htmlspecialchars($temp[0]), $temp[1], $temp[2]];
1058 }
1059 foreach($members as $member){
1060 echo "<option value=\"$member[0]\" style=\"$member[1]\">$member[0]";
1061 if($member[2]==0){
1062 echo ' (!)';
1063 }elseif($member[2]==2){
1064 echo ' (G)';
1065 }elseif($member[2]==3){
1066 }elseif($member[2]==5){
1067 echo ' (M)';
1068 }elseif($member[2]==6){
1069 echo ' (SM)';
1070 }elseif($member[2]==7){
1071 echo ' (A)';
1072 }else{
1073 echo ' (SA)';
1074 }
1075 echo '</option>';
1076 }
1077 echo "</select><select name=\"set\" size=\"1\"><option value=\"\">$I[choose]</option><option value=\"-\">$I[memdel]</option><option value=\"0\">$I[memdeny]</option>";
1078 if(get_setting('suguests')){
1079 echo "<option value=\"2\">$I[memsuguest]</option>";
1080 }
1081 echo "<option value=\"3\">$I[memreg]</option>";
1082 echo "<option value=\"5\">$I[memmod]</option>";
1083 echo "<option value=\"6\">$I[memsumod]</option>";
1084 if($U['status']>=8){
1085 echo "<option value=\"7\">$I[memadm]</option>";
1086 }
1087 echo '</select></td><td>'.submit($I['change']).'</td></tr></table></form></td></tr></table></td></tr>';
1088 thr();
1089 echo "<tr><td><table id=\"passreset\"><tr><th>$I[passreset]</th><td>";
1090 echo form('admin', 'passreset');
1091 echo "<table><td><select name=\"name\" size=\"1\"><option value=\"\">$I[choose]</option>";
1092 foreach($members as $member){
1093 echo "<option value=\"$member[0]\" style=\"$member[1]\">$member[0]</option>";
1094 }
1095 echo '</select></td><td><input type="password" name="pass"></td><td>'.submit($I['change']).'</td></tr></table></form></td></tr></table></td></tr>';
1096 thr();
1097 echo "<tr><td><table id=\"register\"><tr><th>$I[regguest]</th><td>";
1098 echo form('admin', 'register');
1099 echo "<table><tr><td><select name=\"name\" size=\"1\"><option value=\"\">$I[choose]</option>";
1100 foreach($users as $user){
1101 if($user[2]==1){
1102 echo "<option value=\"$user[0]\" style=\"$user[1]\">$user[0]</option>";
1103 }
1104 }
1105 echo '</select></td><td>'.submit($I['register']).'</td></tr></table></form></td></tr></table></td></tr>';
1106 thr();
1107 echo "<tr><td><table id=\"regnew\"><tr><th>$I[regmem]</th></tr><tr><td>";
1108 echo form('admin', 'regnew');
1109 echo "<table><tr><td>$I[nick]</td><td> </td><td><input type=\"text\" name=\"name\" size=\"20\"></td><td> </td></tr>";
1110 echo "<tr><td>$I[pass]</td><td> </td><td><input type=\"password\" name=\"pass\" size=\"20\"></td><td>";
1111 echo submit($I['register']).'</td></tr></table></form></td></tr></table></td></tr>';
1112 thr();
1113 }
1114 echo "</table><br>";
1115 echo form('admin').submit($I['reload']).'</form>';
1116 print_end();
1117}
1118
1119function send_sessions(){
1120 global $I, $U, $db;
1121 $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;');
1122 $stmt->execute([$U['status'], $U['nickname']]);
1123 if(!$lines=$stmt->fetchAll(PDO::FETCH_ASSOC)){
1124 $lines=[];
1125 }
1126 print_start('sessions');
1127 echo "<h1>$I[sessact]</h1><table>";
1128 echo "<tr><th>$I[sessnick]</th><th>$I[sesstimeout]</th><th>$I[sessua]</th>";
1129 $trackip=(bool) get_setting('trackip');
1130 $memexpire=(int) get_setting('memberexpire');
1131 $guestexpire=(int) get_setting('guestexpire');
1132 if($trackip) echo "<th>$I[sesip]</th>";
1133 echo "<th>$I[actions]</th></tr>";
1134 foreach($lines as $temp){
1135 if($temp['status']==0){
1136 $s=' (K)';
1137 }elseif($temp['status']<=2){
1138 $s=' (G)';
1139 }elseif($temp['status']==3){
1140 $s='';
1141 }elseif($temp['status']==5){
1142 $s=' (M)';
1143 }elseif($temp['status']==6){
1144 $s=' (SM)';
1145 }elseif($temp['status']==7){
1146 $s=' (A)';
1147 }else{
1148 $s=' (SA)';
1149 }
1150 echo '<tr><td class="nickname">'.style_this(htmlspecialchars($temp['nickname']).$s, $temp['style']).'</td><td class="timeout">';
1151 if($temp['status']>2){
1152 get_timeout($temp['lastpost'], $memexpire);
1153 }else{
1154 get_timeout($temp['lastpost'], $guestexpire);
1155 }
1156 echo '</td>';
1157 if($U['status']>$temp['status'] || $U['nickname']===$temp['nickname']){
1158 echo "<td class=\"ua\">$temp[useragent]</td>";
1159 if($trackip){
1160 echo "<td class=\"ip\">$temp[ip]</td>";
1161 }
1162 echo '<td class="action">';
1163 if($temp['nickname']!==$U['nickname']){
1164 echo '<table><tr>';
1165 if($temp['status']!=0){
1166 echo '<td>';
1167 echo form('admin', 'sessions');
1168 echo hidden('kick', '1').hidden('nick', htmlspecialchars($temp['nickname'])).submit($I['kick']).'</form>';
1169 echo '</td>';
1170 }
1171 echo '<td>';
1172 echo form('admin', 'sessions');
1173 echo hidden('logout', '1').hidden('nick', htmlspecialchars($temp['nickname'])).submit($temp['status']==0 ? $I['unban'] : $I['logout']).'</form>';
1174 echo '</td></tr></table>';
1175 }else{
1176 echo '-';
1177 }
1178 echo '</td></tr>';
1179 }else{
1180 echo '<td class="ua">-</td>';
1181 if($trackip){
1182 echo '<td class="ip">-</td>';
1183 }
1184 echo '<td class="action">-</td></tr>';
1185 }
1186 }
1187 echo "</table><br>";
1188 echo form('admin', 'sessions').submit($I['reload']).'</form>';
1189 print_end();
1190}
1191
1192function check_filter_match(&$reg){
1193 global $I;
1194 $_REQUEST['match']=htmlspecialchars($_REQUEST['match']);
1195 if(isset($_REQUEST['regex']) && $_REQUEST['regex']==1){
1196 if(!valid_regex($_REQUEST['match'])){
1197 return "$I[incorregex]<br>$I[prevmatch]: $_REQUEST[match]";
1198 }
1199 $reg=1;
1200 }else{
1201 $_REQUEST['match']=preg_replace('/([^\w\d])/u', "\\\\$1", $_REQUEST['match']);
1202 $reg=0;
1203 }
1204 if(mb_strlen($_REQUEST['match'])>255){
1205 return "$I[matchtoolong]<br>$I[prevmatch]: $_REQUEST[match]";
1206 }
1207 return false;
1208}
1209
1210function manage_filter(){
1211 global $db, $memcached;
1212 if(isset($_REQUEST['id'])){
1213 $reg=0;
1214 if($tmp=check_filter_match($reg)){
1215 return $tmp;
1216 }
1217 if(isset($_REQUEST['allowinpm']) && $_REQUEST['allowinpm']==1){
1218 $pm=1;
1219 }else{
1220 $pm=0;
1221 }
1222 if(isset($_REQUEST['kick']) && $_REQUEST['kick']==1){
1223 $kick=1;
1224 }else{
1225 $kick=0;
1226 }
1227 if(isset($_REQUEST['cs']) && $_REQUEST['cs']==1){
1228 $cs=1;
1229 }else{
1230 $cs=0;
1231 }
1232 if(preg_match('/^[0-9]+$/', $_REQUEST['id'])){
1233 if(empty($_REQUEST['match'])){
1234 $stmt=$db->prepare('DELETE FROM ' . PREFIX . 'filter WHERE id=?;');
1235 $stmt->execute([$_REQUEST['id']]);
1236 }else{
1237 $stmt=$db->prepare('UPDATE ' . PREFIX . 'filter SET filtermatch=?, filterreplace=?, allowinpm=?, regex=?, kick=?, cs=? WHERE id=?;');
1238 $stmt->execute([$_REQUEST['match'], $_REQUEST['replace'], $pm, $reg, $kick, $cs, $_REQUEST['id']]);
1239 }
1240 }elseif($_REQUEST['id']==='+'){
1241 $stmt=$db->prepare('INSERT INTO ' . PREFIX . 'filter (filtermatch, filterreplace, allowinpm, regex, kick, cs) VALUES (?, ?, ?, ?, ?, ?);');
1242 $stmt->execute([$_REQUEST['match'], $_REQUEST['replace'], $pm, $reg, $kick, $cs]);
1243 }
1244 if(MEMCACHED){
1245 $memcached->delete(DBNAME . '-' . PREFIX . 'filter');
1246 }
1247 }
1248}
1249
1250function manage_linkfilter(){
1251 global $db, $memcached;
1252 if(isset($_REQUEST['id'])){
1253 $reg=0;
1254 if($tmp=check_filter_match($reg)){
1255 return $tmp;
1256 }
1257 if(preg_match('/^[0-9]+$/', $_REQUEST['id'])){
1258 if(empty($_REQUEST['match'])){
1259 $stmt=$db->prepare('DELETE FROM ' . PREFIX . 'linkfilter WHERE id=?;');
1260 $stmt->execute([$_REQUEST['id']]);
1261 }else{
1262 $stmt=$db->prepare('UPDATE ' . PREFIX . 'linkfilter SET filtermatch=?, filterreplace=?, regex=? WHERE id=?;');
1263 $stmt->execute([$_REQUEST['match'], $_REQUEST['replace'], $reg, $_REQUEST['id']]);
1264 }
1265 }elseif($_REQUEST['id']==='+'){
1266 $stmt=$db->prepare('INSERT INTO ' . PREFIX . 'linkfilter (filtermatch, filterreplace, regex) VALUES (?, ?, ?);');
1267 $stmt->execute([$_REQUEST['match'], $_REQUEST['replace'], $reg]);
1268 }
1269 if(MEMCACHED){
1270 $memcached->delete(DBNAME . '-' . PREFIX . 'linkfilter');
1271 }
1272 }
1273}
1274
1275function get_filters(){
1276 global $db, $memcached;
1277 if(MEMCACHED){
1278 $filters=$memcached->get(DBNAME . '-' . PREFIX . 'filter');
1279 }
1280 if(!MEMCACHED || $memcached->getResultCode()!==Memcached::RES_SUCCESS){
1281 $filters=[];
1282 $result=$db->query('SELECT id, filtermatch, filterreplace, allowinpm, regex, kick, cs FROM ' . PREFIX . 'filter;');
1283 while($filter=$result->fetch(PDO::FETCH_ASSOC)){
1284 $filters[]=['id'=>$filter['id'], 'match'=>$filter['filtermatch'], 'replace'=>$filter['filterreplace'], 'allowinpm'=>$filter['allowinpm'], 'regex'=>$filter['regex'], 'kick'=>$filter['kick'], 'cs'=>$filter['cs']];
1285 }
1286 if(MEMCACHED){
1287 $memcached->set(DBNAME . '-' . PREFIX . 'filter', $filters);
1288 }
1289 }
1290 return $filters;
1291}
1292
1293function get_linkfilters(){
1294 global $db, $memcached;
1295 if(MEMCACHED){
1296 $filters=$memcached->get(DBNAME . '-' . PREFIX . 'linkfilter');
1297 }
1298 if(!MEMCACHED || $memcached->getResultCode()!==Memcached::RES_SUCCESS){
1299 $filters=[];
1300 $result=$db->query('SELECT id, filtermatch, filterreplace, regex FROM ' . PREFIX . 'linkfilter;');
1301 while($filter=$result->fetch(PDO::FETCH_ASSOC)){
1302 $filters[]=['id'=>$filter['id'], 'match'=>$filter['filtermatch'], 'replace'=>$filter['filterreplace'], 'regex'=>$filter['regex']];
1303 }
1304 if(MEMCACHED){
1305 $memcached->set(DBNAME . '-' . PREFIX . 'linkfilter', $filters);
1306 }
1307 }
1308 return $filters;
1309}
1310
1311function send_filter($arg=''){
1312 global $I, $U;
1313 print_start('filter');
1314 echo "<h2>$I[filter]</h2><i>$arg</i><table>";
1315 thr();
1316 echo '<tr><th><table style="width:100%;"><tr>';
1317 echo "<td style=\"width:8em;\">$I[fid]</td>";
1318 echo "<td style=\"width:12em;\">$I[match]</td>";
1319 echo "<td style=\"width:12em;\">$I[replace]</td>";
1320 echo "<td style=\"width:9em;\">$I[allowpm]</td>";
1321 echo "<td style=\"width:5em;\">$I[regex]</td>";
1322 echo "<td style=\"width:5em;\">$I[kick]</td>";
1323 echo "<td style=\"width:5em;\">$I[cs]</td>";
1324 echo "<td style=\"width:5em;\">$I[apply]</td>";
1325 echo '</tr></table></th></tr>';
1326 $filters=get_filters();
1327 foreach($filters as $filter){
1328 if($filter['allowinpm']==1){
1329 $check=' checked';
1330 }else{
1331 $check='';
1332 }
1333 if($filter['regex']==1){
1334 $checked=' checked';
1335 }else{
1336 $checked='';
1337 $filter['match']=preg_replace('/(\\\\(.))/u', "$2", $filter['match']);
1338 }
1339 if($filter['kick']==1){
1340 $checkedk=' checked';
1341 }else{
1342 $checkedk='';
1343 }
1344 if($filter['cs']==1){
1345 $checkedcs=' checked';
1346 }else{
1347 $checkedcs='';
1348 }
1349 echo '<tr><td>';
1350 echo form('admin', 'filter').hidden('id', $filter['id']);
1351 echo "<table style=\"width:100%;\"><tr><th style=\"width:8em;\">$I[filter] $filter[id]:</th>";
1352 echo "<td style=\"width:12em;\"><input type=\"text\" name=\"match\" value=\"$filter[match]\" size=\"20\" style=\"$U[style]\"></td>";
1353 echo '<td style="width:12em;"><input type="text" name="replace" value="'.htmlspecialchars($filter['replace'])."\" size=\"20\" style=\"$U[style]\"></td>";
1354 echo "<td style=\"width:9em;\"><label><input type=\"checkbox\" name=\"allowinpm\" value=\"1\"$check>$I[allowpm]</label></td>";
1355 echo "<td style=\"width:5em;\"><label><input type=\"checkbox\" name=\"regex\" value=\"1\"$checked>$I[regex]</label></td>";
1356 echo "<td style=\"width:5em;\"><label><input type=\"checkbox\" name=\"kick\" value=\"1\"$checkedk>$I[kick]</label></td>";
1357 echo "<td style=\"width:5em;\"><label><input type=\"checkbox\" name=\"cs\" value=\"1\"$checkedcs>$I[cs]</label></td>";
1358 echo '<td class="filtersubmit" style="width:5em;">'.submit($I['change']).'</td></tr></table></form></td></tr>';
1359 }
1360 echo '<tr><td>';
1361 echo form('admin', 'filter').hidden('id', '+');
1362 echo "<table style=\"width:100%;\"><tr><th style=\"width:8em\">$I[newfilter]</th>";
1363 echo "<td style=\"width:12em;\"><input type=\"text\" name=\"match\" value=\"\" size=\"20\" style=\"$U[style]\"></td>";
1364 echo "<td style=\"width:12em;\"><input type=\"text\" name=\"replace\" value=\"\" size=\"20\" style=\"$U[style]\"></td>";
1365 echo "<td style=\"width:9em;\"><label><input type=\"checkbox\" name=\"allowinpm\" id=\"allowinpm\" value=\"1\">$I[allowpm]</label></td>";
1366 echo "<td style=\"width:5em;\"><label><input type=\"checkbox\" name=\"regex\" id=\"regex\" value=\"1\">$I[regex]</label></td>";
1367 echo "<td style=\"width:5em;\"><label><input type=\"checkbox\" name=\"kick\" id=\"kick\" value=\"1\">$I[kick]</label></td>";
1368 echo "<td style=\"width:5em;\"><label><input type=\"checkbox\" name=\"cs\" id=\"cs\" value=\"1\">$I[cs]</label></td>";
1369 echo '<td class="filtersubmit" style="width:5em;">'.submit($I['add']).'</td></tr></table></form></td></tr>';
1370 echo "</table><br>";
1371 echo form('admin', 'filter').submit($I['reload']).'</form>';
1372 print_end();
1373}
1374
1375function send_linkfilter($arg=''){
1376 global $I, $U;
1377 print_start('linkfilter');
1378 echo "<h2>$I[linkfilter]</h2><i>$arg</i><table>";
1379 thr();
1380 echo '<tr><th><table style="width:100%;"><tr>';
1381 echo "<td style=\"width:8em;\">$I[fid]</td>";
1382 echo "<td style=\"width:12em;\">$I[match]</td>";
1383 echo "<td style=\"width:12em;\">$I[replace]</td>";
1384 echo "<td style=\"width:5em;\">$I[regex]</td>";
1385 echo "<td style=\"width:5em;\">$I[apply]</td>";
1386 echo '</tr></table></th></tr>';
1387 $filters=get_linkfilters();
1388 foreach($filters as $filter){
1389 if($filter['regex']==1){
1390 $checked=' checked';
1391 }else{
1392 $checked='';
1393 $filter['match']=preg_replace('/(\\\\(.))/u', "$2", $filter['match']);
1394 }
1395 echo '<tr><td>';
1396 echo form('admin', 'linkfilter').hidden('id', $filter['id']);
1397 echo "<table style=\"width:100%;\"><tr><th style=\"width:8em;\">$I[filter] $filter[id]:</th>";
1398 echo "<td style=\"width:12em;\"><input type=\"text\" name=\"match\" value=\"$filter[match]\" size=\"20\" style=\"$U[style]\"></td>";
1399 echo '<td style="width:12em;"><input type="text" name="replace" value="'.htmlspecialchars($filter['replace'])."\" size=\"20\" style=\"$U[style]\"></td>";
1400 echo "<td style=\"width:5em;\"><label><input type=\"checkbox\" name=\"regex\" value=\"1\"$checked>$I[regex]</label></td>";
1401 echo '<td class="filtersubmit" style="width:5em;">'.submit($I['change']).'</td></tr></table></form></td></tr>';
1402 }
1403 echo '<tr><td>';
1404 echo form('admin', 'linkfilter').hidden('id', '+');
1405 echo "<table style=\"width:100%;\"><tr><th style=\"width:8em;\">$I[newfilter]</th>";
1406 echo "<td style=\"width:12em;\"><input type=\"text\" name=\"match\" value=\"\" size=\"20\" style=\"$U[style]\"></td>";
1407 echo "<td style=\"width:12em;\"><input type=\"text\" name=\"replace\" value=\"\" size=\"20\" style=\"$U[style]\"></td>";
1408 echo "<td style=\"width:5em;\"><label><input type=\"checkbox\" name=\"regex\" value=\"1\">$I[regex]</label></td>";
1409 echo '<td class="filtersubmit" style="width:5em;">'.submit($I['add']).'</td></tr></table></form></td></tr>';
1410 echo "</table><br>";
1411 echo form('admin', 'linkfilter').submit($I['reload']).'</form>';
1412 print_end();
1413}
1414
1415function send_frameset(){
1416 global $I, $U, $db, $language;
1417 echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd"><html><head>'.meta_html();
1418 echo '<title>'.get_setting('chatname').'</title>';
1419 print_stylesheet();
1420 echo '</head>';
1421 if(isset($_REQUEST['sort'])){
1422 if($_REQUEST['sort']==1){
1423 $U['sortupdown']=1;
1424 $tmp=$U['nocache'];
1425 $U['nocache']=$U['nocache_old'];
1426 $U['nocache_old']=$tmp;
1427 }else{
1428 $U['sortupdown']=0;
1429 $tmp=$U['nocache'];
1430 $U['nocache']=$U['nocache_old'];
1431 $U['nocache_old']=$tmp;
1432 }
1433 $stmt=$db->prepare('UPDATE ' . PREFIX . 'sessions SET sortupdown=?, nocache=?, nocache_old=? WHERE nickname=?;');
1434 $stmt->execute([$U['sortupdown'], $U['nocache'], $U['nocache_old'], $U['nickname']]);
1435 if($U['status']>1){
1436 $stmt=$db->prepare('UPDATE ' . PREFIX . 'members SET sortupdown=?, nocache=?, nocache_old=? WHERE nickname=?;');
1437 $stmt->execute([$U['sortupdown'], $U['nocache'], $U['nocache_old'], $U['nickname']]);
1438 }
1439 }
1440 if($U['sortupdown']){
1441 $bottom='#bottom';
1442 }else{
1443 $bottom='';
1444 }
1445 if(($U['status']>=5 || ($U['status']>2 && get_count_mods()==0)) && get_setting('enfileupload')){
1446 $postheight=120;
1447 }else{
1448 $postheight=100;
1449 }
1450 if((!isset($_REQUEST['sort']) && !$U['sortupdown']) || (isset($_REQUEST['sort']) && $_REQUEST['sort']==0)){
1451 echo "<frameset rows=\"$postheight,*,45\" border=\"3\" frameborder=\"3\" framespacing=\"3\">";
1452 echo "<frame name=\"post\" src=\"$_SERVER[SCRIPT_NAME]?action=post&session=$U[session]&lang=$language\">";
1453 if(get_setting('enablegreeting')){
1454 echo "<frame name=\"view\" src=\"$_SERVER[SCRIPT_NAME]?action=greeting&session=$U[session]&lang=$language\">";
1455 }else{
1456 echo "<frame name=\"view\" src=\"$_SERVER[SCRIPT_NAME]?action=view&session=$U[session]&lang=$language$bottom\">";
1457 }
1458 echo "<frame name=\"controls\" src=\"$_SERVER[SCRIPT_NAME]?action=controls&session=$U[session]&lang=$language&sort=1\">";
1459 }else{
1460 echo "<frameset rows=\"45,*,$postheight\" border=\"3\" frameborder=\"3\" framespacing=\"3\">";
1461 echo "<frame name=\"controls\" src=\"$_SERVER[SCRIPT_NAME]?action=controls&session=$U[session]&lang=$language&sort=0\">";
1462 if(get_setting('enablegreeting')){
1463 echo "<frame name=\"view\" src=\"$_SERVER[SCRIPT_NAME]?action=greeting&session=$U[session]&lang=$language\">";
1464 }else{
1465 echo "<frame name=\"view\" src=\"$_SERVER[SCRIPT_NAME]?action=view&session=$U[session]&lang=$language$bottom\">";
1466 }
1467 echo "<frame name=\"post\" src=\"$_SERVER[SCRIPT_NAME]?action=post&session=$U[session]&lang=$language\">";
1468 }
1469 echo "<noframes><body>$I[noframes]".form_target('_parent', '').submit($I['backtologin'], 'class="backbutton"').'</form></body></noframes></frameset></html>';
1470 exit;
1471}
1472
1473function send_messages(){
1474 global $I, $U, $language;
1475 if($U['nocache']){
1476 $nocache='&nc='.substr(time(), -6);
1477 }else{
1478 $nocache='';
1479 }
1480 if($U['sortupdown']){
1481 $sort='#bottom';
1482 }else{
1483 $sort='';
1484 }
1485 print_start('messages', $U['refresh'], "$_SERVER[SCRIPT_NAME]?action=view&session=$U[session]&lang=$language$nocache$sort");
1486 echo '<a id="top"></a>';
1487 echo "<a id=\"bottom_link\" href=\"#bottom\">$I[bottom]</a>";
1488 echo "<div id=\"manualrefresh\"><br>$I[manualrefresh]<br>".form('view').submit($I['reload']).'</form><br></div>';
1489 if(!$U['sortupdown']){
1490 echo '<div id="topic">';
1491 echo get_setting('topic');
1492 echo '</div>';
1493 print_chatters();
1494 print_notifications();
1495 print_messages();
1496 }else{
1497 print_messages();
1498 print_notifications();
1499 print_chatters();
1500 echo '<div id="topic">';
1501 echo get_setting('topic');
1502 echo '</div>';
1503 }
1504 echo "<a id=\"bottom\"></a><a id=\"top_link\" href=\"#top\">$I[top]</a>";
1505 print_end();
1506}
1507
1508function send_inbox(){
1509 global $I, $U, $db;
1510 print_start('inbox');
1511 echo form('inbox', 'clean').submit($I['delselmes'], 'class="delbutton"').'<br><br>';
1512 $dateformat=get_setting('dateformat');
1513 if(!$U['embed'] && get_setting('imgembed')){
1514 $removeEmbed=true;
1515 }else{
1516 $removeEmbed=false;
1517 }
1518 if($U['timestamps'] && !empty($dateformat)){
1519 $timestamps=true;
1520 }else{
1521 $timestamps=false;
1522 }
1523 if($U['sortupdown']){
1524 $direction='ASC';
1525 }else{
1526 $direction='DESC';
1527 }
1528 $stmt=$db->prepare('SELECT id, postdate, text FROM ' . PREFIX . "inbox WHERE recipient=? ORDER BY id $direction;");
1529 $stmt->execute([$U['nickname']]);
1530 while($message=$stmt->fetch(PDO::FETCH_ASSOC)){
1531 prepare_message_print($message, $removeEmbed);
1532 echo "<div class=\"msg\"><label><input type=\"checkbox\" name=\"mid[]\" value=\"$message[id]\">";
1533 if($timestamps){
1534 echo ' <small>'.date($dateformat, $message['postdate']).' - </small>';
1535 }
1536 echo " $message[text]</label></div>";
1537 }
1538 echo '</form><br>'.form('view').submit($I['backtochat'], 'class="backbutton"').'</form>';
1539 print_end();
1540}
1541
1542function send_notes($type){
1543 global $I, $U, $db;
1544 print_start('notes');
1545 $personalnotes=(bool) get_setting('personalnotes');
1546 if($U['status']>=5 && ($personalnotes || $U['status']>6)){
1547 echo '<table><tr>';
1548 if($U['status']>6){
1549 echo '<td>'.form_target('view', 'notes', 'admin').submit($I['admnotes']).'</form></td>';
1550 }
1551 echo '<td>'.form_target('view', 'notes', 'staff').submit($I['staffnotes']).'</form></td>';
1552 if($personalnotes){
1553 echo '<td>'.form_target('view', 'notes').submit($I['personalnotes']).'</form></td>';
1554 }
1555 echo '</tr></table>';
1556 }
1557 if($type===1){
1558 echo "<h2>$I[staffnotes]</h2><p>";
1559 $hiddendo=hidden('do', 'staff');
1560 }elseif($type===0){
1561 echo "<h2>$I[adminnotes]</h2><p>";
1562 $hiddendo=hidden('do', 'admin');
1563 }else{
1564 echo "<h2>$I[personalnotes]</h2><p>";
1565 $hiddendo='';
1566 }
1567 if(isset($_REQUEST['text'])){
1568 if(MSGENCRYPTED){
1569 $_REQUEST['text']=openssl_encrypt($_REQUEST['text'], 'aes-256-cbc', ENCRYPTKEY, 0, '1234567890123456');
1570 }
1571 $time=time();
1572 $stmt=$db->prepare('INSERT INTO ' . PREFIX . 'notes (type, lastedited, editedby, text) VALUES (?, ?, ?, ?);');
1573 $stmt->execute([$type, $time, $U['nickname'], $_REQUEST['text']]);
1574 echo "<b>$I[notessaved]</b> ";
1575 }
1576 $dateformat=get_setting('dateformat');
1577 if($type!==2){
1578 $stmt=$db->prepare('SELECT COUNT(*) FROM ' . PREFIX . 'notes WHERE type=?;');
1579 $stmt->execute([$type]);
1580 }else{
1581 $stmt=$db->prepare('SELECT COUNT(*) FROM ' . PREFIX . 'notes WHERE type=? AND editedby=?;');
1582 $stmt->execute([$type, $U['nickname']]);
1583 }
1584 $num=$stmt->fetch(PDO::FETCH_NUM);
1585 if(!empty($_REQUEST['revision'])){
1586 $revision=intval($_REQUEST['revision']);
1587 }else{
1588 $revision=0;
1589 }
1590 if($type!==2){
1591 $stmt=$db->prepare('SELECT * FROM ' . PREFIX . "notes WHERE type=? ORDER BY id DESC LIMIT 1 OFFSET $revision;");
1592 $stmt->execute([$type]);
1593 }else{
1594 $stmt=$db->prepare('SELECT * FROM ' . PREFIX . "notes WHERE type=? AND editedby=? ORDER BY id DESC LIMIT 1 OFFSET $revision;");
1595 $stmt->execute([$type, $U['nickname']]);
1596 }
1597 if($note=$stmt->fetch(PDO::FETCH_ASSOC)){
1598 printf($I['lastedited'], htmlspecialchars($note['editedby']), date($dateformat, $note['lastedited']));
1599 }else{
1600 $note['text']='';
1601 }
1602 if(MSGENCRYPTED){
1603 $note['text']=openssl_decrypt($note['text'], 'aes-256-cbc', ENCRYPTKEY, 0, '1234567890123456');
1604 }
1605 echo "</p>".form('notes');
1606 echo "$hiddendo<textarea name=\"text\">".htmlspecialchars($note['text']).'</textarea><br>';
1607 echo submit($I['savenotes']).'</form><br>';
1608 if($num[0]>1){
1609 echo "<br><table><tr><td>$I[revisions]</td>";
1610 if($revision<$num[0]-1){
1611 echo '<td>'.form('notes').hidden('revision', $revision+1);
1612 echo $hiddendo.submit($I['older']).'</form></td>';
1613 }
1614 if($revision>0){
1615 echo '<td>'.form('notes').hidden('revision', $revision-1);
1616 echo $hiddendo.submit($I['newer']).'</form></td>';
1617 }
1618 echo '</tr></table>';
1619 }
1620 print_end();
1621}
1622
1623function send_approve_waiting(){
1624 global $I, $db;
1625 print_start('approve_waiting');
1626 echo "<h2>$I[waitingroom]</h2>";
1627 $result=$db->query('SELECT * FROM ' . PREFIX . 'sessions WHERE entry=0 AND status=1 ORDER BY id LIMIT 100;');
1628 if($tmp=$result->fetchAll(PDO::FETCH_ASSOC)){
1629 echo form('admin', 'approve');
1630 echo '<table>';
1631 echo "<tr><th>$I[sessnick]</th><th>$I[sessua]</th></tr>";
1632 foreach($tmp as $temp){
1633 echo '<tr>'.hidden('alls[]', htmlspecialchars($temp['nickname']));
1634 echo '<td><label><input type="checkbox" name="csid[]" value="'.htmlspecialchars($temp['nickname']).'">';
1635 echo style_this(htmlspecialchars($temp['nickname']), $temp['style']).'</label></td>';
1636 echo "<td>$temp[useragent]</td></tr>";
1637 }
1638 echo "</table><br><table id=\"action\"><tr><td><label><input type=\"radio\" name=\"what\" value=\"allowchecked\" id=\"allowchecked\" checked>$I[allowchecked]</label></td>";
1639 echo "<td><label><input type=\"radio\" name=\"what\" value=\"allowall\" id=\"allowall\">$I[allowall]</label></td>";
1640 echo "<td><label><input type=\"radio\" name=\"what\" value=\"denychecked\" id=\"denychecked\">$I[denychecked]</label></td>";
1641 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>";
1642 echo '</tr><tr><td colspan="8">'.submit($I['butallowdeny']).'</td></tr></table></form>';
1643 }else{
1644 echo "$I[waitempty]<br>";
1645 }
1646 echo '<br>'.form('view').submit($I['backtochat'], 'class="backbutton"').'</form>';
1647 print_end();
1648}
1649
1650function send_waiting_room(){
1651 global $I, $U, $db, $language;
1652 $ga=(int) get_setting('guestaccess');
1653 if($ga===3 && (get_count_mods()>0 || !get_setting('modfallback'))){
1654 $wait=false;
1655 }else{
1656 $wait=true;
1657 }
1658 check_expired();
1659 check_kicked();
1660 $timeleft=get_setting('entrywait')-(time()-$U['lastpost']);
1661 if($wait && ($timeleft<=0 || $ga===1)){
1662 $U['entry']=$U['lastpost'];
1663 $stmt=$db->prepare('UPDATE ' . PREFIX . 'sessions SET entry=lastpost WHERE session=?;');
1664 $stmt->execute([$U['session']]);
1665 send_frameset();
1666 }elseif(!$wait && $U['entry']!=0){
1667 send_frameset();
1668 }else{
1669 $refresh=(int) get_setting('defaultrefresh');
1670 print_start('waitingroom', $refresh, "$_SERVER[SCRIPT_NAME]?action=wait&session=$U[session]&lang=$language&nc=".substr(time(),-6));
1671 echo "<h2>$I[waitingroom]</h2><p>";
1672 if($wait){
1673 printf($I['waittext'], style_this(htmlspecialchars($U['nickname']), $U['style']), $timeleft);
1674 }else{
1675 printf($I['admwaittext'], style_this(htmlspecialchars($U['nickname']), $U['style']));
1676 }
1677 echo '</p><br><p>';
1678 printf($I['waitreload'], $refresh);
1679 echo '</p><br><br>';
1680 echo '<hr>'.form('wait');
1681 if(!isset($_REQUEST['session'])){
1682 echo hidden('session', $U['session']);
1683 }
1684 echo submit($I['reload']).'</form><br>';
1685 echo form('logout');
1686 if(!isset($_REQUEST['session'])){
1687 echo hidden('session', $U['session']);
1688 }
1689 echo submit($I['exit'], 'id="exitbutton"').'</form>';
1690 $rulestxt=get_setting('rulestxt');
1691 if(!empty($rulestxt)){
1692 echo "<div id=\"rules\"><h2>$I[rules]</h2><b>$rulestxt</b></div>";
1693 }
1694 print_end();
1695 }
1696}
1697
1698function send_choose_messages(){
1699 global $I, $U;
1700 print_start('choose_messages');
1701 echo form('admin', 'clean');
1702 echo hidden('what', 'selected').submit($I['delselmes'], 'class="delbutton"').'<br><br>';
1703 print_messages($U['status']);
1704 echo '<br>'.submit($I['delselmes'], 'class="delbutton"')."</form>";
1705 print_end();
1706}
1707
1708function send_debbies_multikick(){
1709 // shows screen of regular guests, in alpha order, and allows multiple ones to be ticked and kicked.
1710 global $I, $U, $db, $language;
1711 print_start('choose_messages'); // uses body class of choose messages to get intended formatting
1712 echo form('admin', 'kick');
1713 echo "<table><tr><td>$I[kickreason]</td><td><input type=\"text\" name=\"kickmessage\" value=\"Use a good, readable, meaningful nick name\" size=\"50\"></td><td> </td></tr>";
1714 echo "<tr><td><label><input type=\"checkbox\" name=\"what\" value=\"purge\" id=\"purge\" checked>$I[kickpurge]</label></td></table><br>";
1715 echo hidden('what', 'purge').submit('Kick selected guests', 'class="delbutton"').'<br><br>';
1716 echo '<div id="messages">';
1717 $users=[];
1718 $foundguest = false;
1719 $stmt=$db->query('SELECT nickname, style FROM ' . PREFIX . 'sessions WHERE entry!=0 AND status=1 ORDER BY LOWER(nickname);');
1720 while($user=$stmt->fetch(PDO::FETCH_NUM)){
1721 echo "<div class=\"msg\"><label><input type=\"checkbox\" name=\"name[]\" value=\"".htmlspecialchars($user[0])."\"> ";
1722 echo style_this(htmlspecialchars($user[0]), $user[1])."</label></div>";
1723 $foundguest = true;
1724 }
1725 if (!$foundguest)
1726 {
1727 echo 'no guests to kick!';
1728 }
1729 echo '</div><br><br>'.submit('Kick selected guests', 'class="delbutton"')."</form>";
1730
1731
1732 print_end();
1733}
1734
1735
1736function send_del_confirm(){
1737 global $I;
1738 print_start('del_confirm');
1739 echo "<table><tr><td colspan=\"2\">$I[confirm]</td></tr><tr><td>".form('delete');
1740 if(isset($_REQUEST['multi'])){
1741 echo hidden('multi', 'on');
1742 }
1743 if(isset($_REQUEST['sendto'])){
1744 echo hidden('sendto', $_REQUEST['sendto']);
1745 }
1746 echo hidden('confirm', 'yes').hidden('what', $_REQUEST['what']).submit($I['yes'], 'class="delbutton"').'</form></td><td>'.form('post');
1747 if(isset($_REQUEST['multi'])){
1748 echo hidden('multi', 'on');
1749 }
1750 if(isset($_REQUEST['sendto'])){
1751 echo hidden('sendto', $_REQUEST['sendto']);
1752 }
1753 echo submit($I['no'], 'class="backbutton"').'</form></td><tr></table>';
1754 print_end();
1755}
1756
1757function send_post($rejected=''){
1758 global $I, $U, $db;
1759 print_start('post');
1760 if(!isset($_REQUEST['sendto'])){
1761 $_REQUEST['sendto']='';
1762 }
1763 echo '<table><tr><td>'.form('post');
1764 echo hidden('postid', substr(time(), -6));
1765 if(isset($_REQUEST['multi'])){
1766 echo hidden('multi', 'on');
1767 }
1768
1769 // debbie's tag enhancement - tags are in new <td> to left of entry box to give more verticle height.
1770 //echo '<small><select name="tags[]" multiple size="4"><option value="" >select tag(s)</option>';
1771 // display_site_tags() function exists in the site_config.php file to allow for site customisation
1772 //display_site_tags();
1773 //echo '</select></small>';
1774 // now move to next column to display everything else
1775 echo '</td><td>';
1776 echo '<table><tr><td>';
1777 echo '<table><tr id="firstline"><td>'.style_this(htmlspecialchars($U['nickname']), $U['style']).'</td><td>:</td>';
1778 if(isset($_REQUEST['multi'])){
1779 echo "<td><textarea name=\"message\" rows=\"3\" cols=\"40\" style=\"$U[style]\" autofocus>$rejected</textarea></td>";
1780 }else{
1781 echo "<td><input type=\"text\" name=\"message\" value=\"$rejected\" size=\"40\" style=\"$U[style]\" autofocus></td>";
1782 }
1783 echo '<td>'.submit($I['talkto']).'</td><td><select name="sendto" size="1">';
1784 echo '<option ';
1785 if($_REQUEST['sendto']==='s *'){
1786 echo 'selected ';
1787 }
1788 echo "value=\"s *\">-$I[toall]-</option>";
1789 if($U['status']>=2){
1790 echo '<option ';
1791 if($_REQUEST['sendto']==='s rg'){
1792 echo 'selected ';
1793 }
1794 echo "value=\"s rg\">-All Reg.Guests-</option>";
1795 }
1796 if($U['status']>=3){
1797 echo '<option ';
1798 if($_REQUEST['sendto']==='s ?'){
1799 echo 'selected ';
1800 }
1801 echo "value=\"s ?\">-$I[tomem]-</option>";
1802 }
1803 if($U['status']>=5){
1804 echo '<option ';
1805 if($_REQUEST['sendto']==='s #'){
1806 echo 'selected ';
1807 }
1808 echo "value=\"s #\">-$I[tostaff]-</option>";
1809 }
1810 if($U['status']>=6){
1811 echo '<option ';
1812 if($_REQUEST['sendto']==='s &'){
1813 echo 'selected ';
1814 }
1815 echo "value=\"s &\">-$I[toadmin]-</option>";
1816 }
1817 $disablepm=(bool) get_setting('disablepm');
1818 if(!$disablepm){
1819 $users=[];
1820 $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);');
1821 $stmt->execute([$U['status'], $U['nickname'], $U['nickname']]);
1822 while($tmp=$stmt->fetch(PDO::FETCH_ASSOC)){
1823 if($tmp['offline']){
1824 $users[]=["$tmp[nickname] $I[offline]", $tmp['style'], $tmp['nickname']];
1825 }else{
1826 $users[]=[$tmp['nickname'], $tmp['style'], $tmp['nickname']];
1827 }
1828 }
1829 foreach($users as $user){
1830 if($U['nickname']!==$user[2]){
1831 echo '<option ';
1832 if($_REQUEST['sendto']==$user[2]){
1833 echo 'selected ';
1834 }
1835 echo 'value="'.htmlspecialchars($user[2])."\" style=\"$user[1]\">".htmlspecialchars($user[0]).'</option>';
1836 }
1837 }
1838 }
1839 echo '</select></td>';
1840
1841 if(get_setting('enfileupload')){
1842 if(!$disablepm && ($U['status']>=5 || ($U['status']>=3 && get_count_mods()==0 && get_setting('memkick')))){
1843 echo '</tr></table><table><tr id="secondline">';
1844 }
1845 printf("<td><input type=\"file\" name=\"file\"><small>$I[maxsize]</small></td>", get_setting('maxuploadsize'));
1846 }
1847 if(!$disablepm && ($U['status']>=5 || ($U['status']>=3 && get_count_mods()==0 && get_setting('memkick')))){
1848 echo "<td><label><input type=\"checkbox\" name=\"kick\" id=\"kick\" value=\"kick\">$I[kick]</label></td>";
1849 echo "<td><label><input type=\"checkbox\" name=\"what\" id=\"what\" value=\"purge\" checked>$I[alsopurge]</label></td>";
1850 }
1851 echo '</tr></table></td></tr></table></form>';
1852
1853 echo '<table><tr id="thirdline"><td>'.form('delete');
1854 if(isset($_REQUEST['multi'])){
1855 echo hidden('multi', 'on');
1856 }
1857 echo hidden('sendto', $_REQUEST['sendto']).hidden('what', 'last');
1858 echo submit($I['dellast'], 'class="delbutton"').'</form></td><td>'.form('delete');
1859 if(isset($_REQUEST['multi'])){
1860 echo hidden('multi', 'on');
1861 }
1862 echo hidden('sendto', $_REQUEST['sendto']).hidden('what', 'all');
1863 echo submit($I['delall'], 'class="delbutton"').'</form></td><td style="width:10px;"></td><td>'.form('post');
1864 if(isset($_REQUEST['multi'])){
1865 echo submit($I['switchsingle']);
1866 }else{
1867 echo hidden('multi', 'on').submit($I['switchmulti']);
1868 }
1869 echo hidden('sendto', $_REQUEST['sendto']).'</form></td>';
1870 echo '</tr></table></td></tr></table>';
1871 print_end();
1872}
1873
1874function send_greeting(){
1875 global $I, $U, $language;
1876 print_start('greeting', $U['refresh'], "$_SERVER[SCRIPT_NAME]?action=view&session=$U[session]&lang=$language");
1877 printf("<h1>$I[greetingmsg]</h1>", style_this(htmlspecialchars($U['nickname']), $U['style']));
1878 printf("<hr><small>$I[entryhelp]</small>", $U['refresh']);
1879 $rulestxt=get_setting('rulestxt');
1880 if(!empty($rulestxt)){
1881 echo "<hr><div id=\"rules\"><h2>$I[rules]</h2>$rulestxt</div>";
1882 }
1883 print_end();
1884}
1885
1886function send_help(){
1887 global $I, $U;
1888 print_start('help');
1889 $rulestxt=get_setting('rulestxt');
1890 if(!empty($rulestxt)){
1891 echo "<div id=\"rules\"><h2>$I[rules]</h2>$rulestxt<br></div><hr>";
1892 }
1893 echo "<h2>$I[help]</h2>$I[helpguest]";
1894 if(get_setting('imgembed')){
1895 echo "<br>$I[helpembed]";
1896 }
1897 if($U['status']>=3){
1898 echo "<br>$I[helpmem]<br>";
1899 if($U['status']>=5){
1900 echo "<br>$I[helpmod]<br>";
1901 if($U['status']>=7){
1902 echo "<br>$I[helpadm]<br>";
1903 }
1904 }
1905 }
1906 echo '<br><hr><div id="backcredit">'.form('view').submit($I['backtochat'], 'class="backbutton"').'</form>'.credit().'</div>';
1907 print_end();
1908}
1909
1910function send_profile($arg=''){
1911 global $I, $L, $U, $db, $language;
1912 print_start('profile');
1913 echo form('profile', 'save')."<h2>$I[profile]</h2><i>$arg</i><table>";
1914 thr();
1915 $ignored=[];
1916 $stmt=$db->prepare('SELECT ign FROM ' . PREFIX . 'ignored WHERE ignby=? ORDER BY LOWER(ign);');
1917 $stmt->execute([$U['nickname']]);
1918 while($tmp=$stmt->fetch(PDO::FETCH_ASSOC)){
1919 $ignored[]=htmlspecialchars($tmp['ign']);
1920 }
1921 if(count($ignored)>0){
1922 echo "<tr><td><table id=\"unignore\"><tr><th>$I[unignore]</th><td>";
1923 echo "<select name=\"unignore\" size=\"1\"><option value=\"\">$I[choose]</option>";
1924 foreach($ignored as $ign){
1925 echo "<option value=\"$ign\">$ign</option>";
1926 }
1927 echo '</select></td></tr></table></td></tr>';
1928 thr();
1929 }
1930 echo "<tr><td><table id=\"ignore\"><tr><th>$I[ignore]</th><td>";
1931 echo "<select name=\"ignore\" size=\"1\"><option value=\"\">$I[choose]</option>";
1932 $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);');
1933 $stmt->execute([$U['nickname'], $U['nickname']]);
1934 while($nick=$stmt->fetch(PDO::FETCH_NUM)){
1935 echo '<option value="'.htmlspecialchars($nick[0])."\" style=\"$nick[1]\">".htmlspecialchars($nick[0]).'</option>';
1936 }
1937 echo '</select></td></tr></table></td></tr>';
1938 thr();
1939 echo "<tr><td><table id=\"refresh\"><tr><th>$I[refreshrate]</th><td>";
1940 echo "<input type=\"number\" name=\"refresh\" size=\"3\" maxlength=\"3\" min=\"5\" max=\"150\" value=\"$U[refresh]\"></td></tr></table></td></tr>";
1941 thr();
1942 preg_match('/#([0-9a-f]{6})/i', $U['style'], $matches);
1943 echo "<tr><td><table id=\"colour\"><tr><th>$I[fontcolour] (<a href=\"$_SERVER[SCRIPT_NAME]?action=colours&session=$U[session]&lang=$language\" target=\"view\">$I[viewexample]</a>)</th><td>";
1944 echo "<input type=\"color\" value=\"#$matches[1]\" name=\"colour\"></td></tr></table></td></tr>";
1945 thr();
1946 echo "<tr><td><table id=\"bgcolour\"><tr><th>$I[bgcolour] (<a href=\"$_SERVER[SCRIPT_NAME]?action=colours&session=$U[session]&lang=$language\" target=\"view\">$I[viewexample]</a>)</th><td>";
1947 echo "<input type=\"color\" value=\"#$U[bgcolour]\" name=\"bgcolour\"></td></tr></table></td></tr>";
1948 thr();
1949 if($U['status']>=3){
1950 echo "<tr><td><table id=\"font\"><tr><th>$I[fontface]</th><td><table>";
1951 echo "<tr><td> </td><td><select name=\"font\" size=\"1\"><option value=\"\">* $I[roomdefault] *</option>";
1952 $F=load_fonts();
1953 foreach($F as $name=>$font){
1954 echo "<option style=\"$font\" ";
1955 if(strpos($U['style'], $font)!==false){
1956 echo 'selected ';
1957 }
1958 echo "value=\"$name\">$name</option>";
1959 }
1960 echo '</select></td><td> </td><td><label><input type="checkbox" name="bold" id="bold" value="on"';
1961 if(strpos($U['style'], 'font-weight:bold;')!==false){
1962 echo ' checked';
1963 }
1964 echo "><b>$I[bold]</b></label></td><td> </td><td><label><input type=\"checkbox\" name=\"italic\" id=\"italic\" value=\"on\"";
1965 if(strpos($U['style'], 'font-style:italic;')!==false){
1966 echo ' checked';
1967 }
1968 echo "><i>$I[italic]</i></label></td><td> </td><td><label><input type=\"checkbox\" name=\"small\" id=\"small\" value=\"on\"";
1969 if(strpos($U['style'], 'font-size:smaller;')!==false){
1970 echo ' checked';
1971 }
1972 echo "><small>$I[small]</small></label></td></tr></table></td></tr></table></td></tr>";
1973 thr();
1974 }
1975 echo '<tr><td>'.style_this(htmlspecialchars($U['nickname'])." : $I[fontexample]", $U['style']).'</td></tr>';
1976 thr();
1977 $bool_settings=['timestamps', 'nocache', 'sortupdown', 'hidechatters'];
1978 if(get_setting('imgembed')){
1979 $bool_settings[]='embed';
1980 }
1981 if($U['status']>=5 && get_setting('incognito')){
1982 $bool_settings[]='incognito';
1983 }
1984 foreach($bool_settings as $setting){
1985 echo "<tr><td><table id=\"$setting\"><tr><th>".$I[$setting].'</th><td>';
1986 echo "<label><input type=\"checkbox\" name=\"$setting\" value=\"on\"";
1987 if($U[$setting]){
1988 echo ' checked';
1989 }
1990 echo "><b>$I[enabled]</b></label></td></tr></table></td></tr>";
1991 thr();
1992 }
1993 if($U['status']>=2 && get_setting('eninbox')){
1994 echo "<tr><td><table id=\"eninbox\"><tr><th>$I[eninbox]</th><td>";
1995 echo "<select name=\"eninbox\" id=\"eninbox\">";
1996 echo '<option value="0"';
1997 if($U['eninbox']==0){
1998 echo ' selected';
1999 }
2000 echo ">$I[disabled]</option>";
2001 echo '<option value="1"';
2002 if($U['eninbox']==1){
2003 echo ' selected';
2004 }
2005 echo ">$I[eninall]</option>";
2006 echo '<option value="3"';
2007 if($U['eninbox']==3){
2008 echo ' selected';
2009 }
2010 echo ">$I[eninmem]</option>";
2011 echo '<option value="5"';
2012 if($U['eninbox']==5){
2013 echo ' selected';
2014 }
2015 echo ">$I[eninstaff]</option>";
2016 echo '</select></td></tr></table></td></tr>';
2017 thr();
2018 }
2019 echo "<tr><td><table id=\"tz\"><tr><th>$I[tz]</th><td>";
2020 echo "<select name=\"tz\">";
2021 $tzs=timezone_identifiers_list();
2022 foreach($tzs as $tz){
2023 echo "<option value=\"$tz\"";
2024 if($U['tz']==$tz){
2025 echo ' selected';
2026 }
2027 echo ">$tz</option>";
2028 }
2029 echo '</select></td></tr></table></td></tr>';
2030 thr();
2031 if($U['status']>=2){
2032 echo "<tr><td><table id=\"changepass\"><tr><th>$I[changepass]</th></tr>";
2033 echo '<tr><td><table>';
2034 echo "<tr><td> </td><td>$I[oldpass]</td><td><input type=\"password\" name=\"oldpass\" size=\"20\"></td></tr>";
2035 echo "<tr><td> </td><td>$I[newpass]</td><td><input type=\"password\" name=\"newpass\" size=\"20\"></td></tr>";
2036 echo "<tr><td> </td><td>$I[confirmpass]</td><td><input type=\"password\" name=\"confirmpass\" size=\"20\"></td></tr>";
2037 echo '</table></td></tr></table></td></tr>';
2038 thr();
2039 echo "<tr><td><table id=\"changenick\"><tr><th>$I[changenick]</th><td><table>";
2040 echo "<tr><td> </td><td>$I[newnickname]</td><td><input type=\"text\" name=\"newnickname\" size=\"20\">";
2041 echo '</table></td></tr></table></td></tr>';
2042 thr();
2043 }
2044 echo '<tr><td>'.submit($I['savechanges']).'</td></tr></table></form>';
2045 if($U['status']>1 && $U['status']<8){
2046 echo '<br>'.form('profile', 'delete').submit($I['deleteacc'], 'class="delbutton"').'</form>';
2047 }
2048 echo "<br><p id=\"changelang\">$I[changelang]";
2049 foreach($L as $lang=>$name){
2050 echo " <a href=\"$_SERVER[SCRIPT_NAME]?lang=$lang&session=$U[session]&action=controls\" target=\"controls\">$name</a>";
2051 }
2052 echo '</p><br>'.form('view').submit($I['backtochat'], 'class="backbutton"').'</form>';
2053 print_end();
2054}
2055
2056function send_controls(){
2057 global $I, $U;
2058 print_start('controls');
2059 $personalnotes=(bool) get_setting('personalnotes');
2060 echo '<table><tr>';
2061 echo '<td>'.form_target('post', 'post').submit($I['reloadpb']).'</form></td>';
2062 echo '<td>'.form_target('view', 'view').submit($I['reloadmsgs']).'</form></td>';
2063 echo '<td>'.form_target('view', 'profile').submit($I['chgprofile']).'</form></td>';
2064 if($U['status']>=5){
2065 echo '<td>'.form_target('view', 'admin').submit($I['adminbtn']).'</form></td>';
2066 if(!$personalnotes){
2067 echo '<td>'.form_target('view', 'notes', 'staff').submit($I['notes']).'</form></td>';
2068 }
2069 }
2070 if($U['status']>=3){
2071 if($personalnotes){
2072 echo '<td>'.form_target('view', 'notes').submit($I['notes']).'</form></td>';
2073 }
2074 echo '<td>'.form_target('_blank', 'login').submit($I['clone']).'</form></td>';
2075 }
2076 if(!isset($_REQUEST['sort'])){
2077 $sort=0;
2078 }else{
2079 $sort=$_REQUEST['sort'];
2080 }
2081 echo '<td>'.form_target('_parent', 'login').hidden('sort', $sort).submit($I['sortframe']).'</form></td>';
2082 echo '<td>'.form_target('view', 'help').submit($I['randh']).'</form></td>';
2083 echo '<td>'.form_target('_parent', 'logout').submit($I['exit'], 'id="exitbutton"').'</form></td>';
2084 echo '</tr></table>';
2085 print_end();
2086}
2087
2088function send_download(){
2089 global $I, $db;
2090 if(isset($_REQUEST['id'])){
2091 $stmt=$db->prepare('SELECT filename, type, data FROM ' . PREFIX . 'files WHERE hash=?;');
2092 $stmt->execute([$_REQUEST['id']]);
2093 if($data=$stmt->fetch(PDO::FETCH_ASSOC)){
2094 header("Content-Type: $data[type]");
2095 header("Content-Disposition: filename=\"$data[filename]\"");
2096 header('Pragma: no-cache');
2097 header('Cache-Control: no-cache, no-store, must-revalidate, max-age=0, private');
2098 header('Expires: 0');
2099 echo base64_decode($data['data']);
2100 }else{
2101 send_error($I['filenotfound']);
2102 }
2103 }else{
2104 send_error($I['filenotfound']);
2105 }
2106}
2107
2108function send_logout(){
2109 global $I, $U;
2110 print_start('logout');
2111 echo '<h1>'.sprintf($I['Adios'], style_this(htmlspecialchars($U['nickname']), $U['style'])).'</h1>'.form_target('_parent', '').submit($I['backtologin'], 'class="backbutton"').'</form>';
2112 print_end();
2113}
2114
2115function send_colours(){
2116 global $I;
2117 print_start('colours');
2118 echo "<h2>$I[colourtable]</h2><kbd><b>";
2119 for($red=0x00;$red<=0xFF;$red+=0x33){
2120 for($green=0x00;$green<=0xFF;$green+=0x33){
2121 for($blue=0x00;$blue<=0xFF;$blue+=0x33){
2122 $hcol=sprintf('%02X%02X%02X', $red, $green, $blue);
2123 echo "<span style=\"color:#$hcol\">$hcol</span> ";
2124 }
2125 echo '<br>';
2126 }
2127 echo '<br>';
2128 }
2129 echo '</b></kbd>'.form('profile').submit($I['backtoprofile'], ' class="backbutton"').'</form>';
2130 print_end();
2131}
2132
2133function send_login(){
2134 global $I, $L;
2135 $ga=(int) get_setting('guestaccess');
2136 if($ga===4){
2137 send_chat_disabled();
2138 }
2139 print_start('login');
2140 $englobal=(int) get_setting('englobalpass');
2141 echo '<h1 id="chatname">'.get_setting('chatname').'</h1>';
2142 echo form_target('_parent', 'login');
2143 if($englobal===1 && isset($_REQUEST['globalpass'])){
2144 echo hidden('globalpass', $_REQUEST['globalpass']);
2145 }
2146 echo '<table>';
2147 if($englobal!==1 || (isset($_REQUEST['globalpass']) && $_REQUEST['globalpass']==get_setting('globalpass'))){
2148 echo "<tr><td>$I[nick]</td><td><input type=\"text\" name=\"nick\" size=\"15\" autofocus></td></tr>";
2149 echo "<tr><td>$I[pass]</td><td><input type=\"password\" name=\"pass\" size=\"15\"></td></tr>";
2150 send_captcha();
2151 if($ga!==0){
2152 if(get_setting('guestreg')!=0){
2153 echo "<tr><td>$I[regpass]</td><td><input type=\"password\" name=\"regpass\" size=\"15\" placeholder=\"$I[optional]\"></td></tr>";
2154 }
2155 if($englobal===2){
2156 echo "<tr><td>$I[globalloginpass]</td><td><input type=\"password\" name=\"globalpass\" size=\"15\"></td></tr>";
2157 }
2158 echo "<tr><td colspan=\"2\">$I[choosecol]<br><select name=\"colour\"><option value=\"\">* $I[randomcol] *</option>";
2159 print_colours();
2160 echo '</select></td></tr>';
2161 }else{
2162 echo "<tr><td colspan=\"2\">$I[noguests]</td></tr>";
2163 }
2164 echo '<tr><td colspan="2">'.submit($I['enter']).'</td></tr></table></form>';
2165 get_nowchatting();
2166 echo '<br><div id="topic">';
2167 echo get_setting('topic');
2168 echo '</div>';
2169 $rulestxt=get_setting('rulestxt');
2170 if(!empty($rulestxt)){
2171 echo "<div id=\"rules\"><h2>$I[rules]</h2><b>$rulestxt</b></div>";
2172 }
2173 }else{
2174 echo "<tr><td>$I[globalloginpass]</td><td><input type=\"password\" name=\"globalpass\" size=\"15\" autofocus></td></tr>";
2175 if($ga===0){
2176 echo "<tr><td colspan=\"2\">$I[noguests]</td></tr>";
2177 }
2178 echo '<tr><td colspan="2">'.submit($I['enter']).'</td></tr></table></form>';
2179 }
2180 echo "<p id=\"changelang\">$I[changelang]";
2181 foreach($L as $lang=>$name){
2182 echo " <a href=\"$_SERVER[SCRIPT_NAME]?lang=$lang\">$name</a>";
2183 }
2184 echo '</p>'.credit();
2185 print_end();
2186}
2187
2188function send_chat_disabled(){
2189 print_start('disabled');
2190 echo get_setting('disabletext');
2191 print_end();
2192}
2193
2194function send_error($err){
2195 global $I;
2196 print_start('error');
2197 echo "<h2>$I[error]: $err</h2>".form_target('_parent', '').submit($I['backtologin'], 'class="backbutton"').'</form>';
2198 print_end();
2199}
2200
2201function send_fatal_error($err){
2202 global $I;
2203 echo '<!DOCTYPE html><html><head>'.meta_html();
2204 echo "<title>$I[fatalerror]</title>";
2205 echo "<style type=\"text/css\">body{background-color:#000000;color:#FF0033;}</style>";
2206 echo '</head><body>';
2207 echo "<h2>$I[fatalerror]: $err</h2>";
2208 print_end();
2209}
2210
2211function print_notifications(){
2212 global $I, $U, $db;
2213 echo '<span id="notifications">';
2214 if($U['status']>=2 && $U['eninbox']!=0){
2215 $stmt=$db->prepare('SELECT COUNT(*) FROM ' . PREFIX . 'inbox WHERE recipient=?;');
2216 $stmt->execute([$U['nickname']]);
2217 $tmp=$stmt->fetch(PDO::FETCH_NUM);
2218 if($tmp[0]>0){
2219 echo '<p>'.form('inbox').submit(sprintf($I['inboxmsgs'], $tmp[0])).'</form></p>';
2220 }
2221 }
2222 if($U['status']>=5 && get_setting('guestaccess')==3){
2223 $result=$db->query('SELECT COUNT(*) FROM ' . PREFIX . 'sessions WHERE entry=0 AND status=1;');
2224 $temp=$result->fetch(PDO::FETCH_NUM);
2225 if($temp[0]>0){
2226 echo '<p>';
2227 echo form('admin', 'approve');
2228 echo submit(sprintf($I['approveguests'], $temp[0])).'</form></p>';
2229 }
2230 }
2231 echo '</span>';
2232}
2233function print_chatters(){
2234 global $I, $U, $db, $language;
2235 $countOfGuests = 0;
2236 if(!$U['hidechatters']){
2237 echo '<div id="chatters"><table><tr>';
2238 $stmt=$db->prepare('SELECT nickname, style, status 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;');
2239 $stmt->execute([$U['nickname'], $U['nickname']]);
2240 $nc=substr(time(), -6);
2241 $G=$M=$S=[];
2242 while($user=$stmt->fetch(PDO::FETCH_NUM)){
2243 // Blake's original rankbadge code with sticky image for each type of user
2244 $membersbadge = "";
2245 switch ($user[2]) {
2246 case 2: // applicant
2247 $membersbadge = '<img src="/rankbadges/rg.png" id="rankbadgeswidth" height="15" width="15">';
2248 break;
2249 case 3: // member
2250 $membersbadge = '<img src="/rankbadges/member.png" id="rankbadgeswidth" height="15" width="15">';
2251 break;
2252 case 5: // mod
2253 $membersbadge = '<img src="/rankbadges/mod.png" id="rankbadgeswidth" height="15" width="15">';
2254 break;
2255 case 6: // supermod
2256 $membersbadge = '<img src="/rankbadges/supermod.png" id="rankbadgeswidth" height="15" width="15">';
2257 break;
2258 case 7: // admin
2259 $membersbadge = '<img src="/rankbadges/admin.png" id="rankbadgeswidth" height="15" width="15">';
2260 break;
2261 case 8: // super admin
2262 $membersbadge = '<img src="/rankbadges/superadmin.png" id="rankbadgeswidth" height="15" width="15">';
2263 break;
2264 case 9: // private messages
2265 $membersbadge = '<img src="/rankbadges/superadmin.png" id="rankbadgeswidth" height="15" width="15">';
2266 break;
2267 }
2268 if (strlen($membersbadge)>0)
2269 {
2270 // OLD $link=$membersbadge."<a href=\"$_SERVER[SCRIPT_NAME]?action=post&session=$U[session]&lang=$language&nc=$nc&sendto=".htmlspecialchars($user[0]).'" target="post">'.style_this(htmlspecialchars($user[0]), $user[1]).'</a>';
2271 $link="<a href=\"$_SERVER[SCRIPT_NAME]?action=post&session=$U[session]&lang=$language&nc=$nc&sendto=".htmlspecialchars($user[0]).'" target="post">'.$membersbadge." ".style_this(htmlspecialchars($user[0]), $user[1]).'</a>';
2272 }
2273 else
2274 {
2275 $link="<a href=\"$_SERVER[SCRIPT_NAME]?action=post&session=$U[session]&lang=$language&nc=$nc&sendto=".htmlspecialchars($user[0]).'" target="post">'.style_this(htmlspecialchars($user[0]), $user[1]).'</a>';
2276 }
2277
2278 //new code
2279 if($user[2]>=5){
2280 $S[]=$link;
2281 }elseif($user[2]>=3){
2282 $M[]=$link;
2283 }else{
2284 $G[]=$link;
2285 $countOfGuests++; // Enhancement to show number of guests
2286 }
2287
2288 }
2289
2290 // Debbie's enhancement for hotlinks to channels
2291 echo "<th>Hotlinks:</th><td> </td>";
2292 // show hotlinks depending on user status value,
2293 // Admins
2294 if($U['status']>=6){
2295 echo "<td><a href=\"$_SERVER[SCRIPT_NAME]?action=post&session=$U[session]&lang=$language&nc=$nc&sendto=s+%26\" target=\"post\"><span style=\"color:#ffffff;font-family:'Arial','Helvetica','sans-serif';\"><small>-Admin-</small></span></a></td><td> </td>";
2296 }
2297 if($U['status']>=5){
2298 // Staff
2299 echo "<td><a href=\"$_SERVER[SCRIPT_NAME]?action=post&session=$U[session]&lang=$language&nc=$nc&sendto=s+%23\" target=\"post\"><span style=\"color:#ffffff;font-family:'Arial','Helvetica','sans-serif';\"><small>-Staff-</small></span></a></td><td> </td>";
2300 }
2301 // members
2302 if($U['status']>=3){
2303 echo "<td><a href=\"$_SERVER[SCRIPT_NAME]?action=post&session=$U[session]&lang=$language&nc=$nc&sendto=s+?\" target=\"post\"><span style=\"color:#ffffff;font-family:'Arial','Helvetica','sans-serif';\"><small>-Members-</small></span></a></td><td> </td>";
2304 }
2305 // RGs
2306 if ($U['status']>=2){
2307 echo "<td><a href=\"$_SERVER[SCRIPT_NAME]?action=post&session=$U[session]&lang=$language&nc=$nc&sendto=s+rg\" target=\"post\"><span style=\"color:#ffffff;font-family:'Arial','Helvetica','sans-serif';\"><small>-Reg Guests-</small></span></a></td><td> </td>";
2308 }
2309 // all chatters
2310 echo "<td><a href=\"$_SERVER[SCRIPT_NAME]?action=post&session=$U[session]&lang=$language&nc=$nc&sendto=s+*\" target=\"post\"><span style=\"color:#ffffff;font-family:'Arial','Helvetica','sans-serif';\"><small>-All Chatters-</small></span></a></td><td> </td>";
2311
2312 if(!empty($S)){
2313 echo "<th>Staff:</th><td> </td><td>".implode(' ', $S).'</td>';
2314 echo '<td> </td>';
2315 }
2316
2317 if(!empty($M)){
2318 echo "<th>$I[members]:</th><td> </td><td>".implode(' ', $M).'</td>';
2319 echo '<td> </td>';
2320 }
2321
2322 if(!empty($G)){
2323 echo "<th>".$countOfGuests." $I[guests]:</th><td> </td><td>".implode(' ', $G).'</td>';
2324 }
2325 echo '</tr></table></div>';
2326 }
2327}
2328
2329// session management
2330
2331function create_session($setup, $nickname, $password){
2332 global $I, $U;
2333 $U['nickname']=preg_replace('/\s/', '', $nickname);
2334 if(check_member($password)){
2335 if($setup && $U['status']>=7){
2336 $U['incognito']=1;
2337 }
2338 $U['entry']=$U['lastpost']=time();
2339 }else{
2340 add_user_defaults($password);
2341 check_captcha(isset($_REQUEST['challenge']) ? $_REQUEST['challenge'] : '', isset($_REQUEST['captcha']) ? $_REQUEST['captcha'] : '');
2342 $ga=(int) get_setting('guestaccess');
2343 if(!valid_nick($U['nickname'])){
2344 send_error(sprintf($I['invalnick'], get_setting('maxname'), get_setting('nickregex')));
2345 }
2346 if(!valid_pass($password)){
2347 send_error(sprintf($I['invalpass'], get_setting('minpass'), get_setting('passregex')));
2348 }
2349 if($ga===0){
2350 send_error($I['noguests']);
2351 }elseif($ga===3){
2352 $U['entry']=0;
2353 }
2354 if(get_setting('englobalpass')!=0 && isset($_REQUEST['globalpass']) && $_REQUEST['globalpass']!=get_setting('globalpass')){
2355 send_error($I['wrongglobalpass']);
2356 }
2357 }
2358 write_new_session($password);
2359}
2360
2361function check_captcha($challenge, $captcha_code){
2362 global $I, $db, $memcached;
2363 $captcha=(int) get_setting('captcha');
2364 if($captcha!==0){
2365 if(empty($challenge)){
2366 send_error($I['wrongcaptcha']);
2367 }
2368 if(MEMCACHED){
2369 if(!$code=$memcached->get(DBNAME . '-' . PREFIX . "captcha-$_REQUEST[challenge]")){
2370 send_error($I['captchaexpire']);
2371 }
2372 $memcached->delete(DBNAME . '-' . PREFIX . "captcha-$_REQUEST[challenge]");
2373 }else{
2374 $stmt=$db->prepare('SELECT code FROM ' . PREFIX . 'captcha WHERE id=?;');
2375 $stmt->execute([$challenge]);
2376 $stmt->bindColumn(1, $code);
2377 if(!$stmt->fetch(PDO::FETCH_BOUND)){
2378 send_error($I['captchaexpire']);
2379 }
2380 $time=time();
2381 $stmt=$db->prepare('DELETE FROM ' . PREFIX . 'captcha WHERE id=? OR time<(?-(SELECT value FROM ' . PREFIX . "settings WHERE setting='captchatime'));");
2382 $stmt->execute([$challenge, $time]);
2383 }
2384 if($captcha_code!==$code){
2385 if($captcha!==3 || strrev($captcha_code)!==$code){
2386 send_error($I['wrongcaptcha']);
2387 }
2388 }
2389 }
2390}
2391
2392function write_new_session($password){
2393 global $I, $U, $db;
2394 $stmt=$db->prepare('SELECT * FROM ' . PREFIX . 'sessions WHERE nickname=?;');
2395 $stmt->execute([$U['nickname']]);
2396 if($temp=$stmt->fetch(PDO::FETCH_ASSOC)){
2397 // check whether alrady logged in
2398 if(password_verify($password, $temp['passhash'])){
2399 $U=$temp;
2400 check_kicked();
2401 setcookie(COOKIENAME, $U['session']);
2402 }else{
2403 send_error("$I[userloggedin]<br>$I[wrongpass]");
2404 }
2405 }else{
2406 // create new session
2407 $stmt=$db->prepare('SELECT null FROM ' . PREFIX . 'sessions WHERE session=?;');
2408 do{
2409 if(function_exists('random_bytes')){
2410 $U['session']=bin2hex(random_bytes(16));
2411 }else{
2412 $U['session']=md5(uniqid($U['nickname'], true).mt_rand());
2413 }
2414 $stmt->execute([$U['session']]);
2415 }while($stmt->fetch(PDO::FETCH_NUM)); // check for hash collision
2416 if(isset($_SERVER['HTTP_USER_AGENT'])){
2417 $useragent=htmlspecialchars($_SERVER['HTTP_USER_AGENT']);
2418 }else{
2419 $useragent='';
2420 }
2421 if(get_setting('trackip')){
2422 $ip=$_SERVER['REMOTE_ADDR'];
2423 }else{
2424 $ip='';
2425 }
2426 $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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);');
2427 $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']]);
2428 setcookie(COOKIENAME, $U['session']);
2429 if($U['status']>=3 && !$U['incognito']){
2430 add_system_message(sprintf(get_setting('msgenter'), style_this(htmlspecialchars($U['nickname']), $U['style'])));
2431 }
2432 }
2433}
2434
2435function approve_session(){
2436 global $db;
2437 if(isset($_REQUEST['what'])){
2438 if($_REQUEST['what']==='allowchecked' && isset($_REQUEST['csid'])){
2439 $stmt=$db->prepare('UPDATE ' . PREFIX . 'sessions SET entry=lastpost WHERE nickname=?;');
2440 foreach($_REQUEST['csid'] as $nick){
2441 $stmt->execute([$nick]);
2442 }
2443 }elseif($_REQUEST['what']==='allowall' && isset($_REQUEST['alls'])){
2444 $stmt=$db->prepare('UPDATE ' . PREFIX . 'sessions SET entry=lastpost WHERE nickname=?;');
2445 foreach($_REQUEST['alls'] as $nick){
2446 $stmt->execute([$nick]);
2447 }
2448 }elseif($_REQUEST['what']==='denychecked' && isset($_REQUEST['csid'])){
2449 $time=60*(get_setting('kickpenalty')-get_setting('guestexpire'))+time();
2450 $stmt=$db->prepare('UPDATE ' . PREFIX . 'sessions SET lastpost=?, status=0, kickmessage=? WHERE nickname=? AND status=1;');
2451 foreach($_REQUEST['csid'] as $nick){
2452 $stmt->execute([$time, $_REQUEST['kickmessage'], $nick]);
2453 }
2454 }elseif($_REQUEST['what']==='denyall' && isset($_REQUEST['alls'])){
2455 $time=60*(get_setting('kickpenalty')-get_setting('guestexpire'))+time();
2456 $stmt=$db->prepare('UPDATE ' . PREFIX . 'sessions SET lastpost=?, status=0, kickmessage=? WHERE nickname=? AND status=1;');
2457 foreach($_REQUEST['alls'] as $nick){
2458 $stmt->execute([$time, $_REQUEST['kickmessage'], $nick]);
2459 }
2460 }
2461 }
2462}
2463
2464function check_login(){
2465 global $I, $U, $db;
2466 $ga=(int) get_setting('guestaccess');
2467 if(isset($_REQUEST['session'])){
2468 parse_sessions();
2469 }
2470 if(isset($U['session'])){
2471 check_kicked();
2472 }elseif(get_setting('englobalpass')==1 && (!isset($_REQUEST['globalpass']) || $_REQUEST['globalpass']!=get_setting('globalpass'))){
2473 send_error($I['wrongglobalpass']);
2474 }elseif(!isset($_REQUEST['nick']) || !isset($_REQUEST['pass'])){
2475 send_login();
2476 }else{
2477 if($ga===4){
2478 send_chat_disabled();
2479 }
2480 if(!empty($_REQUEST['regpass']) && $_REQUEST['regpass']!==$_REQUEST['pass']){
2481 send_error($I['noconfirm']);
2482 }
2483 create_session(false, $_REQUEST['nick'], $_REQUEST['pass']);
2484 if(!empty($_REQUEST['regpass'])){
2485 $guestreg=(int) get_setting('guestreg');
2486 if($guestreg===1){
2487 register_guest(2, $_REQUEST['nick']);
2488 $U['status']=2;
2489 }elseif($guestreg===2){
2490 register_guest(3, $_REQUEST['nick']);
2491 $U['status']=3;
2492 }
2493 }
2494 }
2495 if($U['status']==1){
2496 if($ga===2 || $ga===3){
2497 $stmt=$db->prepare('UPDATE ' . PREFIX . 'sessions SET entry=0 WHERE session=?;');
2498 $stmt->execute([$U['session']]);
2499 send_waiting_room();
2500 }
2501 }
2502}
2503
2504function kill_session(){
2505 global $U, $db;
2506 parse_sessions();
2507 check_expired();
2508 check_kicked();
2509 setcookie(COOKIENAME, false);
2510 $_REQUEST['session']='';
2511 $stmt=$db->prepare('DELETE FROM ' . PREFIX . 'sessions WHERE session=?;');
2512 $stmt->execute([$U['session']]);
2513 if($U['status']>=3 && !$U['incognito']){
2514 add_system_message(sprintf(get_setting('msgexit'), style_this(htmlspecialchars($U['nickname']), $U['style'])));
2515 }
2516}
2517
2518function kick_chatter($names, $mes, $purge){
2519 global $U, $db;
2520 $lonick='';
2521 $time=60*(get_setting('kickpenalty')-get_setting('guestexpire'))+time();
2522 $check=$db->prepare('SELECT style, entry FROM ' . PREFIX . 'sessions WHERE nickname=? AND status!=0 AND (status<? OR nickname=?);');
2523 $stmt=$db->prepare('UPDATE ' . PREFIX . 'sessions SET lastpost=?, status=0, kickmessage=? WHERE nickname=?;');
2524 $all=false;
2525 if($names[0]==='s &'){
2526 $tmp=$db->query('SELECT nickname FROM ' . PREFIX . 'sessions WHERE status=1;');
2527 $names=[];
2528 while($name=$tmp->fetch(PDO::FETCH_NUM)){
2529 $names[]=$name[0];
2530 }
2531 $all=true;
2532 }
2533 $i=0;
2534 foreach($names as $name){
2535 $check->execute([$name, $U['status'], $U['nickname']]);
2536 if($temp=$check->fetch(PDO::FETCH_ASSOC)){
2537 $stmt->execute([$time, $mes, $name]);
2538 if($purge){
2539 del_all_messages($name, $temp['entry']);
2540 }
2541 $lonick.=style_this(htmlspecialchars($name), $temp['style']).', ';
2542 ++$i;
2543 }
2544 }
2545 if($i>0){
2546 if($all){
2547 add_system_message(get_setting('msgallkick'));
2548 }else{
2549 $lonick=substr($lonick, 0, -2);
2550 if($i>1){
2551 add_system_message(sprintf(get_setting('msgmultikick'), $lonick));
2552 }else{
2553 add_system_message(sprintf(get_setting('msgkick'), $lonick));
2554 }
2555 }
2556 return true;
2557 }
2558 return false;
2559}
2560
2561function logout_chatter($names){
2562 global $U, $db;
2563 $stmt=$db->prepare('DELETE FROM ' . PREFIX . 'sessions WHERE nickname=? AND status<?;');
2564 if($names[0]==='s &'){
2565 $tmp=$db->query('SELECT nickname FROM ' . PREFIX . 'sessions WHERE status=1;');
2566 $names=[];
2567 while($name=$tmp->fetch(PDO::FETCH_NUM)){
2568 $names[]=$name[0];
2569 }
2570 }
2571 foreach($names as $name){
2572 $stmt->execute([$name, $U['status']]);
2573 }
2574}
2575
2576function check_session(){
2577 global $U;
2578 parse_sessions();
2579 check_expired();
2580 check_kicked();
2581 if($U['entry']==0){
2582 send_waiting_room();
2583 }
2584}
2585
2586function check_expired(){
2587 global $I, $U;
2588 if(!isset($U['session'])){
2589 setcookie(COOKIENAME, false);
2590 $_REQUEST['session']='';
2591 send_error($I['expire']);
2592 }
2593}
2594
2595function get_count_mods(){
2596 global $db;
2597 $c=$db->query('SELECT COUNT(*) FROM ' . PREFIX . 'sessions WHERE status>=5')->fetch(PDO::FETCH_NUM);
2598 return $c[0];
2599}
2600
2601function check_kicked(){
2602 global $I, $U;
2603 if($U['status']==0){
2604 setcookie(COOKIENAME, false);
2605 $_REQUEST['session']='';
2606 send_error("$I[kicked]<br>$U[kickmessage]");
2607 }
2608}
2609
2610function get_nowchatting(){
2611 global $I, $db;
2612 parse_sessions();
2613 $stmt=$db->query('SELECT COUNT(*) FROM ' . PREFIX . 'sessions WHERE entry!=0 AND status>0 AND incognito=0;');
2614 $count=$stmt->fetch(PDO::FETCH_NUM);
2615 echo '<div id="chatters">'.sprintf($I['curchat'], $count[0]).'<br>';
2616 if(!get_setting('hidechatters')){
2617 $stmt=$db->query('SELECT nickname, style FROM ' . PREFIX . 'sessions WHERE entry!=0 AND status>0 AND incognito=0 ORDER BY status DESC, lastpost DESC;');
2618 while($user=$stmt->fetch(PDO::FETCH_NUM)){
2619 echo style_this(htmlspecialchars($user[0]), $user[1]).' ';
2620 }
2621 }
2622 echo '</div>';
2623}
2624
2625function parse_sessions(){
2626 global $U, $db;
2627 // look for our session
2628 if(isset($_REQUEST['session'])){
2629 $stmt=$db->prepare('SELECT * FROM ' . PREFIX . 'sessions WHERE session=?;');
2630 $stmt->execute([$_REQUEST['session']]);
2631 if($tmp=$stmt->fetch(PDO::FETCH_ASSOC)){
2632 $U=$tmp;
2633 }
2634 }
2635 set_default_tz();
2636}
2637
2638// member handling
2639
2640function check_member($password){
2641 global $I, $U, $db;
2642 $stmt=$db->prepare('SELECT * FROM ' . PREFIX . 'members WHERE nickname=?;');
2643 $stmt->execute([$U['nickname']]);
2644 if($temp=$stmt->fetch(PDO::FETCH_ASSOC)){
2645 if(get_setting('dismemcaptcha')==0){
2646 check_captcha(isset($_REQUEST['challenge']) ? $_REQUEST['challenge'] : '', isset($_REQUEST['captcha']) ? $_REQUEST['captcha'] : '');
2647 }
2648 if($temp['passhash']===md5(sha1(md5($U['nickname'].$password)))){
2649 // old hashing method, update on the fly
2650 $temp['passhash']=password_hash($password, PASSWORD_DEFAULT);
2651 $stmt=$db->prepare('UPDATE ' . PREFIX . 'members SET passhash=? WHERE nickname=?;');
2652 $stmt->execute([$temp['passhash'], $U['nickname']]);
2653 }
2654 if(password_verify($password, $temp['passhash'])){
2655 $U=$temp;
2656 $stmt=$db->prepare('UPDATE ' . PREFIX . 'members SET lastlogin=? WHERE nickname=?;');
2657 $stmt->execute([time(), $U['nickname']]);
2658 return true;
2659 }else{
2660 send_error("$I[regednick]<br>$I[wrongpass]");
2661 }
2662 }
2663 return false;
2664}
2665
2666function delete_account(){
2667 global $U, $db;
2668 if($U['status']<8){
2669 $stmt=$db->prepare('UPDATE ' . PREFIX . 'sessions SET status=1, incognito=0 WHERE nickname=?;');
2670 $stmt->execute([$U['nickname']]);
2671 $stmt=$db->prepare('DELETE FROM ' . PREFIX . 'members WHERE nickname=?;');
2672 $stmt->execute([$U['nickname']]);
2673 $stmt=$db->prepare('DELETE FROM ' . PREFIX . 'inbox WHERE recipient=?;');
2674 $stmt->execute([$U['nickname']]);
2675 $stmt=$db->prepare('DELETE FROM ' . PREFIX . 'notes WHERE type=2 AND editedby=?;');
2676 $stmt->execute([$U['nickname']]);
2677 $U['status']=1;
2678 }
2679}
2680
2681function register_guest($status, $nick){
2682 global $I, $U, $db;
2683 $stmt=$db->prepare('SELECT style FROM ' . PREFIX . 'members WHERE nickname=?');
2684 $stmt->execute([$nick]);
2685 if($tmp=$stmt->fetch(PDO::FETCH_NUM)){
2686 return sprintf($I['alreadyreged'], style_this(htmlspecialchars($nick), $tmp[0]));
2687 }
2688 $stmt=$db->prepare('SELECT * FROM ' . PREFIX . 'sessions WHERE nickname=? AND status=1;');
2689 $stmt->execute([$nick]);
2690 if($reg=$stmt->fetch(PDO::FETCH_ASSOC)){
2691 $reg['status']=$status;
2692 $stmt=$db->prepare('UPDATE ' . PREFIX . 'sessions SET status=? WHERE session=?;');
2693 $stmt->execute([$reg['status'], $reg['session']]);
2694 }else{
2695 return sprintf($I['cantreg'], htmlspecialchars($nick));
2696 }
2697 $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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);');
2698 $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']]);
2699 if($reg['status']==3){
2700 add_system_message(sprintf(get_setting('msgmemreg'), style_this(htmlspecialchars($reg['nickname']), $reg['style'])));
2701 }else{
2702 add_system_message(sprintf(get_setting('msgsureg'), style_this(htmlspecialchars($reg['nickname']), $reg['style'])));
2703 }
2704 return sprintf($I['successreg'], style_this(htmlspecialchars($reg['nickname']), $reg['style']));
2705}
2706
2707function register_new($nick, $pass){
2708 global $I, $U, $db;
2709 $nick=preg_replace('/\s/', '', $nick);
2710 if(empty($nick)){
2711 return '';
2712 }
2713 $stmt=$db->prepare('SELECT null FROM ' . PREFIX . 'sessions WHERE nickname=?');
2714 $stmt->execute([$nick]);
2715 if($stmt->fetch(PDO::FETCH_NUM)){
2716 return sprintf($I['cantreg'], htmlspecialchars($nick));
2717 }
2718 if(!valid_nick($nick)){
2719 return sprintf($I['invalnick'], get_setting('maxname'), get_setting('nickregex'));
2720 }
2721 if(!valid_pass($pass)){
2722 return sprintf($I['invalpass'], get_setting('minpass'), get_setting('passregex'));
2723 }
2724 $stmt=$db->prepare('SELECT null FROM ' . PREFIX . 'members WHERE nickname=?');
2725 $stmt->execute([$nick]);
2726 if($stmt->fetch(PDO::FETCH_NUM)){
2727 return sprintf($I['alreadyreged'], htmlspecialchars($nick));
2728 }
2729 $reg=[
2730 'nickname' =>$nick,
2731 'passhash' =>password_hash($pass, PASSWORD_DEFAULT),
2732 'status' =>3,
2733 'refresh' =>get_setting('defaultrefresh'),
2734 'bgcolour' =>get_setting('colbg'),
2735 'regedby' =>$U['nickname'],
2736 'timestamps' =>get_setting('timestamps'),
2737 'style' =>'color:#'.get_setting('coltxt').';',
2738 'embed' =>1,
2739 'incognito' =>0,
2740 'nocache' =>0,
2741 'nocache_old' =>1,
2742 'tz' =>get_setting('defaulttz'),
2743 'eninbox' =>0,
2744 'sortupdown' =>get_setting('sortupdown'),
2745 'hidechatters' =>get_setting('hidechatters'),
2746 ];
2747 $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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);');
2748 $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']]);
2749 return sprintf($I['successreg'], htmlspecialchars($reg['nickname']));
2750}
2751
2752function change_status($nick, $status){
2753 global $I, $U, $db;
2754 if(empty($nick)){
2755 return '';
2756 }elseif($U['status']<=$status || !preg_match('/^[023567\-]$/', $status)){
2757 return sprintf($I['cantchgstat'], htmlspecialchars($nick));
2758 }
2759 $stmt=$db->prepare('SELECT incognito, style FROM ' . PREFIX . 'members WHERE nickname=? AND status<?;');
2760 $stmt->execute([$nick, $U['status']]);
2761 if(!$old=$stmt->fetch(PDO::FETCH_NUM)){
2762 return sprintf($I['cantchgstat'], htmlspecialchars($nick));
2763 }
2764 if($_REQUEST['set']==='-'){
2765 $stmt=$db->prepare('DELETE FROM ' . PREFIX . 'members WHERE nickname=?;');
2766 $stmt->execute([$nick]);
2767 $stmt=$db->prepare('UPDATE ' . PREFIX . 'sessions SET status=1, incognito=0 WHERE nickname=?;');
2768 $stmt->execute([$nick]);
2769 return sprintf($I['succdel'], style_this(htmlspecialchars($nick), $old[1]));
2770 }else{
2771 if($status<5){
2772 $old[0]=0;
2773 }
2774 $stmt=$db->prepare('UPDATE ' . PREFIX . 'members SET status=?, incognito=? WHERE nickname=?;');
2775 $stmt->execute([$status, $old[0], $nick]);
2776 $stmt=$db->prepare('UPDATE ' . PREFIX . 'sessions SET status=?, incognito=? WHERE nickname=?;');
2777 $stmt->execute([$status, $old[0], $nick]);
2778 return sprintf($I['succchg'], style_this(htmlspecialchars($nick), $old[1]));
2779 }
2780}
2781
2782function passreset($nick, $pass){
2783 global $I, $U, $db;
2784 if(empty($nick)){
2785 return '';
2786 }
2787 $stmt=$db->prepare('SELECT null FROM ' . PREFIX . 'members WHERE nickname=? AND status<?;');
2788 $stmt->execute([$nick, $U['status']]);
2789 if($stmt->fetch(PDO::FETCH_ASSOC)){
2790 $passhash=password_hash($pass, PASSWORD_DEFAULT);
2791 $stmt=$db->prepare('UPDATE ' . PREFIX . 'members SET passhash=? WHERE nickname=?;');
2792 $stmt->execute([$passhash, $nick]);
2793 $stmt=$db->prepare('UPDATE ' . PREFIX . 'sessions SET passhash=? WHERE nickname=?;');
2794 $stmt->execute([$passhash, $nick]);
2795 return sprintf($I['succpassreset'], htmlspecialchars($nick));
2796 }else{
2797 return sprintf($I['cantresetpass'], htmlspecialchars($nick));
2798 }
2799}
2800
2801function amend_profile(){
2802 global $U;
2803 if(isset($_REQUEST['refresh'])){
2804 $U['refresh']=$_REQUEST['refresh'];
2805 }
2806 if($U['refresh']<5){
2807 $U['refresh']=5;
2808 }elseif($U['refresh']>150){
2809 $U['refresh']=150;
2810 }
2811 if(preg_match('/^#([a-f0-9]{6})$/i', $_REQUEST['colour'], $match)){
2812 $colour=$match[1];
2813 }else{
2814 preg_match('/#([0-9a-f]{6})/i', $U['style'], $matches);
2815 $colour=$matches[1];
2816 }
2817 if(preg_match('/^#([a-f0-9]{6})$/i', $_REQUEST['bgcolour'], $match)){
2818 $U['bgcolour']=$match[1];
2819 }
2820 $U['style']="color:#$colour;";
2821 if($U['status']>=3){
2822 $F=load_fonts();
2823 if(isset($F[$_REQUEST['font']])){
2824 $U['style'].=$F[$_REQUEST['font']];
2825 }
2826 if(isset($_REQUEST['small'])){
2827 $U['style'].='font-size:smaller;';
2828 }
2829 if(isset($_REQUEST['italic'])){
2830 $U['style'].='font-style:italic;';
2831 }
2832 if(isset($_REQUEST['bold'])){
2833 $U['style'].='font-weight:bold;';
2834 }
2835 }
2836 if($U['status']>=5 && isset($_REQUEST['incognito']) && get_setting('incognito')){
2837 $U['incognito']=1;
2838 }else{
2839 $U['incognito']=0;
2840 }
2841 if(isset($_REQUEST['tz'])){
2842 $tzs=timezone_identifiers_list();
2843 if(in_array($_REQUEST['tz'], $tzs)){
2844 $U['tz']=$_REQUEST['tz'];
2845 }
2846 }
2847 if(isset($_REQUEST['eninbox']) && $_REQUEST['eninbox']>=0 && $_REQUEST['eninbox']<=5){
2848 $U['eninbox']=$_REQUEST['eninbox'];
2849 }
2850 $bool_settings=['timestamps', 'embed', 'nocache', 'sortupdown', 'hidechatters'];
2851 foreach($bool_settings as $setting){
2852 if(isset($_REQUEST[$setting])){
2853 $U[$setting]=1;
2854 }else{
2855 $U[$setting]=0;
2856 }
2857 }
2858}
2859
2860function save_profile(){
2861 global $I, $U, $db;
2862 amend_profile();
2863 $stmt=$db->prepare('UPDATE ' . PREFIX . 'sessions SET refresh=?, style=?, bgcolour=?, timestamps=?, embed=?, incognito=?, nocache=?, tz=?, eninbox=?, sortupdown=?, hidechatters=? WHERE session=?;');
2864 $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']]);
2865 if($U['status']>=2){
2866 $stmt=$db->prepare('UPDATE ' . PREFIX . 'members SET refresh=?, bgcolour=?, timestamps=?, embed=?, incognito=?, style=?, nocache=?, tz=?, eninbox=?, sortupdown=?, hidechatters=? WHERE nickname=?;');
2867 $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']]);
2868 }
2869 if(!empty($_REQUEST['unignore'])){
2870 $stmt=$db->prepare('DELETE FROM ' . PREFIX . 'ignored WHERE ign=? AND ignby=?;');
2871 $stmt->execute([$_REQUEST['unignore'], $U['nickname']]);
2872 }
2873 if(!empty($_REQUEST['ignore'])){
2874 $stmt=$db->prepare('SELECT null FROM ' . PREFIX . 'messages WHERE poster=? AND poster NOT IN (SELECT ign FROM ' . PREFIX . 'ignored WHERE ignby=?);');
2875 $stmt->execute([$_REQUEST['ignore'], $U['nickname']]);
2876 if($U['nickname']!==$_REQUEST['ignore'] && $stmt->fetch(PDO::FETCH_NUM)){
2877 $stmt=$db->prepare('INSERT INTO ' . PREFIX . 'ignored (ign, ignby) VALUES (?, ?);');
2878 $stmt->execute([$_REQUEST['ignore'], $U['nickname']]);
2879 }
2880 }
2881 if($U['status']>1 && !empty($_REQUEST['newpass'])){
2882 if(!valid_pass($_REQUEST['newpass'])){
2883 return sprintf($I['invalpass'], get_setting('minpass'), get_setting('passregex'));
2884 }
2885 if(!isset($_REQUEST['oldpass'])){
2886 $_REQUEST['oldpass']='';
2887 }
2888 if(!isset($_REQUEST['confirmpass'])){
2889 $_REQUEST['confirmpass']='';
2890 }
2891 if($_REQUEST['newpass']!==$_REQUEST['confirmpass']){
2892 return $I['noconfirm'];
2893 }else{
2894 $U['newhash']=password_hash($_REQUEST['newpass'], PASSWORD_DEFAULT);
2895 }
2896 if(!password_verify($_REQUEST['oldpass'], $U['passhash'])){
2897 return $I['wrongpass'];
2898 }
2899 $U['passhash']=$U['newhash'];
2900 $stmt=$db->prepare('UPDATE ' . PREFIX . 'sessions SET passhash=? WHERE session=?;');
2901 $stmt->execute([$U['passhash'], $U['session']]);
2902 $stmt=$db->prepare('UPDATE ' . PREFIX . 'members SET passhash=? WHERE nickname=?;');
2903 $stmt->execute([$U['passhash'], $U['nickname']]);
2904 }
2905 if($U['status']>1 && !empty($_REQUEST['newnickname'])){
2906 $msg=set_new_nickname();
2907 if($msg!==''){
2908 return $msg;
2909 }
2910 }
2911 return $I['succprofile'];
2912}
2913
2914function set_new_nickname(){
2915 global $I, $U, $db;
2916 $_REQUEST['newnickname']=preg_replace('/\s/', '', $_REQUEST['newnickname']);
2917 if(!valid_nick($_REQUEST['newnickname'])){
2918 return sprintf($I['invalnick'], get_setting('maxname'), get_setting('nickregex'));
2919 }
2920 $stmt=$db->prepare('SELECT id FROM ' . PREFIX . 'sessions WHERE nickname=? UNION SELECT id FROM ' . PREFIX . 'members WHERE nickname=?;');
2921 $stmt->execute([$_REQUEST['newnickname'], $_REQUEST['newnickname']]);
2922 if($stmt->fetch(PDO::FETCH_NUM)){
2923 return $I['nicknametaken'];
2924 }else{
2925 $stmt=$db->prepare('UPDATE ' . PREFIX . 'members SET nickname=? WHERE nickname=?;');
2926 $stmt->execute([$_REQUEST['newnickname'], $U['nickname']]);
2927 $stmt=$db->prepare('UPDATE ' . PREFIX . 'sessions SET nickname=? WHERE nickname=?;');
2928 $stmt->execute([$_REQUEST['newnickname'], $U['nickname']]);
2929 $stmt=$db->prepare('UPDATE ' . PREFIX . 'messages SET poster=? WHERE poster=?;');
2930 $stmt->execute([$_REQUEST['newnickname'], $U['nickname']]);
2931 $stmt=$db->prepare('UPDATE ' . PREFIX . 'messages SET recipient=? WHERE recipient=?;');
2932 $stmt->execute([$_REQUEST['newnickname'], $U['nickname']]);
2933 $stmt=$db->prepare('UPDATE ' . PREFIX . 'ignored SET ignby=? WHERE ignby=?;');
2934 $stmt->execute([$_REQUEST['newnickname'], $U['nickname']]);
2935 $stmt=$db->prepare('UPDATE ' . PREFIX . 'ignored SET ign=? WHERE ign=?;');
2936 $stmt->execute([$_REQUEST['newnickname'], $U['nickname']]);
2937 $stmt=$db->prepare('UPDATE ' . PREFIX . 'inbox SET poster=? WHERE poster=?;');
2938 $stmt->execute([$_REQUEST['newnickname'], $U['nickname']]);
2939 $stmt=$db->prepare('UPDATE ' . PREFIX . 'notes SET editedby=? WHERE editedby=?;');
2940 $stmt->execute([$_REQUEST['newnickname'], $U['nickname']]);
2941 $U['nickname']=$_REQUEST['newnickname'];
2942 }
2943 return '';
2944}
2945
2946//sets default settings for guests
2947function add_user_defaults($password){
2948 global $U;
2949 $U['refresh']=get_setting('defaultrefresh');
2950 $U['bgcolour']=get_setting('colbg');
2951 if(!isset($_REQUEST['colour']) || !preg_match('/^[a-f0-9]{6}$/i', $_REQUEST['colour']) || abs(greyval($_REQUEST['colour'])-greyval(get_setting('colbg')))<75){
2952 do{
2953 $colour=sprintf('%06X', mt_rand(0, 16581375));
2954 }while(abs(greyval($colour)-greyval(get_setting('colbg')))<75);
2955 }else{
2956 $colour=$_REQUEST['colour'];
2957 }
2958 $U['style']="color:#$colour;";
2959 $U['timestamps']=get_setting('timestamps');
2960 $U['embed']=1;
2961 $U['incognito']=0;
2962 $U['status']=1;
2963 $U['nocache']=get_setting('sortupdown');
2964 if($U['nocache']){
2965 $U['nocache_old']=0;
2966 }else{
2967 $U['nocache_old']=1;
2968 }
2969 $U['tz']=get_setting('defaulttz');
2970 $U['eninbox']=0;
2971 $U['sortupdown']=get_setting('sortupdown');
2972 $U['hidechatters']=get_setting('hidechatters');
2973 $U['passhash']=password_hash($password, PASSWORD_DEFAULT);
2974 $U['entry']=$U['lastpost']=time();
2975}
2976
2977// message handling
2978
2979function validate_input(){
2980 global $U, $db;
2981 $inbox=false;
2982 $maxmessage=get_setting('maxmessage');
2983 $message=mb_substr($_REQUEST['message'], 0, $maxmessage);
2984 $rejected=mb_substr($_REQUEST['message'], $maxmessage);
2985 if($U['postid']===$_REQUEST['postid']){// ignore double post=reload from browser or proxy
2986 $message='';
2987 }elseif((time()-$U['lastpost'])<=1){// time between posts too short, reject!
2988 $rejected=$_REQUEST['message'];
2989 $message='';
2990 }
2991 if(!empty($rejected)){
2992 $rejected=trim($rejected);
2993 $rejected=htmlspecialchars($rejected);
2994 }
2995 $message=htmlspecialchars($message);
2996 $message=preg_replace("/(\r?\n|\r\n?)/u", '<br>', $message);
2997 if(isset($_REQUEST['multi'])){
2998 $message=preg_replace('/\s*<br>/u', '<br>', $message);
2999 $message=preg_replace('/<br>(<br>)+/u', '<br><br>', $message);
3000 $message=preg_replace('/<br><br>\s*$/u', '<br>', $message);
3001 $message=preg_replace('/^<br>\s*$/u', '', $message);
3002 }else{
3003 $message=str_replace('<br>', ' ', $message);
3004 }
3005 $message=trim($message);
3006 $message=preg_replace('/\s+/u', ' ', $message);
3007
3008
3009 // New function: add tags
3010 // now see if there is an image link. If there is an image, then add the selected tags.
3011 // If there are no tags selected and none have been manually added, then reject message
3012 //if(preg_match('/(\.jpg|\.jpeg|\.bmp|\.gif|\.mpg|\.mp4|\.mpeg|\.png)/i', $message))
3013 //{
3014 // $taglist = '';
3015 // if (isset($_REQUEST['tags']))
3016 // {
3017 // foreach ($_REQUEST['tags'] as $tag)
3018 // {
3019 // if ($tag != '')
3020 // $taglist = $taglist."[".$tag."] ";
3021 // }
3022 // $message = $taglist.$message;
3023 // }
3024 // $pos = strpos($message, "]");
3025 // if ($pos === false) {
3026 // return "TAGS REQUIRED!";
3027 // }
3028 //}
3029
3030 $recipient='';
3031 if($_REQUEST['sendto']==='s *'){
3032 $poststatus=1;
3033 $displaysend=sprintf(get_setting('msgsendall'), style_this(htmlspecialchars($U['nickname']), $U['style']));
3034 }elseif($_REQUEST['sendto']==='s rg' && $U['status']>=2){
3035 $poststatus=2; // Debbie added RG channel
3036 $displaysend=sprintf("[RG] %s - ", style_this(htmlspecialchars($U['nickname']), $U['style']));
3037 }elseif($_REQUEST['sendto']==='s ?' && $U['status']>=3){
3038 $poststatus=3;
3039 $displaysend=sprintf(get_setting('msgsendmem'), style_this(htmlspecialchars($U['nickname']), $U['style']));
3040 }elseif($_REQUEST['sendto']==='s #' && $U['status']>=5){
3041 $poststatus=5;
3042 $displaysend=sprintf(get_setting('msgsendmod'), style_this(htmlspecialchars($U['nickname']), $U['style']));
3043 }elseif($_REQUEST['sendto']==='s &' && $U['status']>=6){
3044 $poststatus=6;
3045 $displaysend=sprintf(get_setting('msgsendadm'), style_this(htmlspecialchars($U['nickname']), $U['style']));
3046 }else{ // known nick in room?
3047 if(get_setting('disablepm')){
3048 //PMs disabled
3049 return;
3050 }
3051 $stmt=$db->prepare('SELECT null FROM ' . PREFIX . 'ignored WHERE (ignby=? AND ign=?) OR (ign=? AND ignby=?);');
3052 $stmt->execute([$_REQUEST['sendto'], $U['nickname'], $_REQUEST['sendto'], $U['nickname']]);
3053 if($stmt->fetch(PDO::FETCH_NUM)){
3054 //ignored
3055 return;
3056 }
3057 $tmp=false;
3058 $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<=?));');
3059 $stmt->execute([$_REQUEST['sendto'], $U['status']]);
3060 if(!$tmp=$stmt->fetch(PDO::FETCH_ASSOC)){
3061 $stmt=$db->prepare('SELECT style, 1 AS inbox FROM ' . PREFIX . 'members WHERE nickname=? AND eninbox!=0 AND eninbox<=?;');
3062 $stmt->execute([$_REQUEST['sendto'], $U['status']]);
3063 if(!$tmp=$stmt->fetch(PDO::FETCH_ASSOC)){
3064 //nickname left or disabled offline inbox for us
3065 return;
3066 }
3067 }
3068 $recipient=$_REQUEST['sendto'];
3069 $poststatus=9;
3070 $displaysend=sprintf(get_setting('msgsendprv'), style_this(htmlspecialchars($U['nickname']), $U['style']), style_this(htmlspecialchars($recipient), $tmp['style']));
3071 $inbox=$tmp['inbox'];
3072 }
3073 if($poststatus!==9 && preg_match('~^/me~iu', $message)){
3074 $displaysend=style_this(htmlspecialchars("$U[nickname] "), $U['style']);
3075 $message=preg_replace("~^/me\s?~iu", '', $message);
3076 }
3077
3078 // add parseString here
3079 //$message=apply_filter($message, $poststatus, $U['nickname']);
3080 $message=apply_filter(parseString($message), $poststatus, $U['nickname']);
3081 $message=create_hotlinks($message);
3082 $message=apply_linkfilter($message);
3083 if(isset($_FILES['file']) && get_setting('enfileupload')){
3084 if($_FILES['file']['error']===UPLOAD_ERR_OK && $_FILES['file']['size']<=(1024*get_setting('maxuploadsize'))){
3085 $hash=sha1_file($_FILES['file']['tmp_name']);
3086 $name=htmlspecialchars($_FILES['file']['name']);
3087 $message=sprintf(get_setting('msgattache'), "<a class=\"attachment\" href=\"$_SERVER[SCRIPT_NAME]?action=download&id=$hash\" target=\"_blank\">$name</a>", $message);
3088 }
3089 }
3090 if(add_message($message, $recipient, $U['nickname'], $U['status'], $poststatus, $displaysend, $U['style'])){
3091 $U['lastpost']=time();
3092 $stmt=$db->prepare('UPDATE ' . PREFIX . 'sessions SET lastpost=?, postid=? WHERE session=?;');
3093 $stmt->execute([$U['lastpost'], $_REQUEST['postid'], $U['session']]);
3094 $stmt=$db->prepare('SELECT id FROM ' . PREFIX . 'messages WHERE poster=? ORDER BY id DESC LIMIT 1;');
3095 $stmt->execute([$U['nickname']]);
3096 $id=$stmt->fetch(PDO::FETCH_NUM);
3097 if($inbox && $id){
3098 $newmessage=[
3099 'postdate' =>time(),
3100 'poster' =>$U['nickname'],
3101 'recipient' =>$recipient,
3102 'text' =>"<span class=\"usermsg\">$displaysend".style_this($message, $U['style']).'</span>'
3103 ];
3104 if(MSGENCRYPTED){
3105 $newmessage['text']=openssl_encrypt($newmessage['text'], 'aes-256-cbc', ENCRYPTKEY, 0, '1234567890123456');
3106 }
3107 $stmt=$db->prepare('INSERT INTO ' . PREFIX . 'inbox (postdate, postid, poster, recipient, text) VALUES(?, ?, ?, ?, ?)');
3108 $stmt->execute([$newmessage['postdate'], $id[0], $newmessage['poster'], $newmessage['recipient'], $newmessage['text']]);
3109 }
3110 if(isset($hash) && $id){
3111 if(!empty($_FILES['file']['type']) && preg_match('~^[a-z0-9/\-\.\+]*$~i', $_FILES['file']['type'])){
3112 $type=$_FILES['file']['type'];
3113 }else{
3114 $type='application/octet-stream';
3115 }
3116 $stmt=$db->prepare('INSERT INTO ' . PREFIX . 'files (postid, hash, filename, type, data) VALUES (?, ?, ?, ?, ?);');
3117 $stmt->execute([$id[0], $hash, str_replace('"', '\"', $_FILES['file']['name']), $type, base64_encode(file_get_contents($_FILES['file']['tmp_name']))]);
3118 unlink($_FILES['file']['tmp_name']);
3119 }
3120 }
3121 return $rejected;
3122}
3123
3124function apply_filter($message, $poststatus, $nickname){
3125 global $I, $U;
3126 $message=str_replace('<br>', "\n", $message);
3127 $message=apply_mention($message);
3128 $filters=get_filters();
3129 foreach($filters as $filter){
3130 if($poststatus!==9 || !$filter['allowinpm']){
3131 if($filter['cs']){
3132 $message=preg_replace("/$filter[match]/u", $filter['replace'], $message, -1, $count);
3133 }else{
3134 $message=preg_replace("/$filter[match]/iu", $filter['replace'], $message, -1, $count);
3135 }
3136 }
3137 if(isset($count) && $count>0 && $filter['kick'] && ($U['status']<5 || get_setting('filtermodkick'))){
3138 kick_chatter([$nickname], $filter['replace'], false);
3139 setcookie(COOKIENAME, false);
3140 $_REQUEST['session']='';
3141 send_error("$I[kicked]<br>$filter[replace]");
3142 }
3143 }
3144 $message=str_replace("\n", '<br>', $message);
3145 return $message;
3146}
3147
3148function apply_linkfilter($message){
3149 $filters=get_linkfilters();
3150 foreach($filters as $filter){
3151 $message=preg_replace_callback("/<a href=\"([^\"]+)\" target=\"_blank\">(.*?(?=<\/a>))<\/a>/iu",
3152 function ($matched) use(&$filter){
3153 return "<a href=\"$matched[1]\" target=\"_blank\">".preg_replace("/$filter[match]/iu", $filter['replace'], $matched[2]).'</a>';
3154 }
3155 , $message);
3156 }
3157 $redirect=get_setting('redirect');
3158 if(get_setting('imgembed')){
3159 $message=preg_replace_callback('/\[img\]\s?<a href="([^"]+)" target="_blank">(.*?(?=<\/a>))<\/a>/iu',
3160 function ($matched){
3161 return str_ireplace('[/img]', '', "<br><a href=\"$matched[1]\" target=\"_blank\"><img src=\"$matched[1]\"></a><br>");
3162 }
3163 , $message);
3164 }
3165 if(empty($redirect)){
3166 $redirect="$_SERVER[SCRIPT_NAME]?action=redirect&url=";
3167 }
3168 if(get_setting('forceredirect')){
3169 $message=preg_replace_callback('/<a href="([^"]+)" target="_blank">(.*?(?=<\/a>))<\/a>/u',
3170 function ($matched) use($redirect){
3171 return "<a href=\"$redirect".rawurlencode($matched[1])."\" target=\"_blank\">$matched[2]</a>";
3172 }
3173 , $message);
3174 }elseif(preg_match_all('/<a href="([^"]+)" target="_blank">(.*?(?=<\/a>))<\/a>/u', $message, $matches)){
3175 foreach($matches[1] as $match){
3176 if(!preg_match('~^http(s)?://~u', $match)){
3177 $message=preg_replace_callback('/<a href="('.preg_quote($match, '/').')\" target=\"_blank\">(.*?(?=<\/a>))<\/a>/u',
3178 function ($matched) use($redirect){
3179 return "<a href=\"$redirect".rawurlencode($matched[1])."\" target=\"_blank\">$matched[2]</a>";
3180 }
3181 , $message);
3182 }
3183 }
3184 }
3185 return $message;
3186}
3187
3188function create_hotlinks($message){
3189 //Make hotlinks for URLs, redirect through dereferrer script to prevent session leakage
3190 // 1. all explicit schemes with whatever xxx://yyyyyyy
3191 $message=preg_replace('~(^|[^\w"])(\w+://[^\s<>]+)~iu', "$1<<$2>>", $message);
3192 // 2. valid URLs without scheme:
3193 $message=preg_replace('~((?:[^\s<>]*:[^\s<>]*@)?[a-z0-9\-]+(?:\.[a-z0-9\-]+)+(?::\d*)?/[^\s<>]*)(?![^<>]*>)~iu', "<<$1>>", $message); // server/path given
3194 $message=preg_replace('~((?:[^\s<>]*:[^\s<>]*@)?[a-z0-9\-]+(?:\.[a-z0-9\-]+)+:\d+)(?![^<>]*>)~iu', "<<$1>>", $message); // server:port given
3195 $message=preg_replace('~([^\s<>]*:[^\s<>]*@[a-z0-9\-]+(?:\.[a-z0-9\-]+)+(?::\d+)?)(?![^<>]*>)~iu', "<<$1>>", $message); // au:th@server given
3196 // 3. likely servers without any hints but not filenames like *.rar zip exe etc.
3197 $message=preg_replace('~((?:[a-z0-9\-]+\.)*(?:[a-z2-7]{55}d|[a-z2-7]{16})\.onion)(?![^<>]*>)~iu', "<<$1>>", $message);// *.onion
3198 $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
3199 // Convert every <<....>> into proper links:
3200 $message=preg_replace_callback('/<<([^<>]+)>>/u',
3201 function ($matches){
3202 if(strpos($matches[1], '://')===false){
3203 return "<a href=\"http://$matches[1]\" target=\"_blank\">$matches[1]</a>";
3204 }else{
3205 return "<a href=\"$matches[1]\" target=\"_blank\">$matches[1]</a>";
3206 }
3207 }
3208 , $message);
3209 return $message;
3210}
3211
3212function apply_mention($message){
3213 return preg_replace_callback('/\@([^\s]+)/iu', function ($matched){
3214 global $db;
3215 $nick=htmlspecialchars_decode($matched[1]);
3216 $rest='';
3217 for($i=0;$i<=3;++$i){
3218 //match case-sensitive present nicknames
3219 $stmt=$db->prepare('SELECT style FROM ' . PREFIX . 'sessions WHERE nickname=?;');
3220 $stmt->execute([$nick]);
3221 if($tmp=$stmt->fetch(PDO::FETCH_NUM)){
3222 return style_this(htmlspecialchars("@$nick"), $tmp[0]).$rest;
3223 }
3224 //match case-insensitive present nicknames
3225 $stmt=$db->prepare('SELECT style FROM ' . PREFIX . 'sessions WHERE LOWER(nickname)=LOWER(?);');
3226 $stmt->execute([$nick]);
3227 if($tmp=$stmt->fetch(PDO::FETCH_NUM)){
3228 return style_this(htmlspecialchars("@$nick"), $tmp[0]).$rest;
3229 }
3230 //match case-sensitive members
3231 $stmt=$db->prepare('SELECT style FROM ' . PREFIX . 'members WHERE nickname=?;');
3232 $stmt->execute([$nick]);
3233 if($tmp=$stmt->fetch(PDO::FETCH_NUM)){
3234 return style_this(htmlspecialchars("@$nick"), $tmp[0]).$rest;
3235 }
3236 //match case-insensitive members
3237 $stmt=$db->prepare('SELECT style FROM ' . PREFIX . 'members WHERE LOWER(nickname)=LOWER(?);');
3238 $stmt->execute([$nick]);
3239 if($tmp=$stmt->fetch(PDO::FETCH_NUM)){
3240 return style_this(htmlspecialchars("@$nick"), $tmp[0]).$rest;
3241 }
3242 if(strlen($nick)===1){
3243 break;
3244 }
3245 $rest=mb_substr($nick, -1).$rest;
3246 $nick=mb_substr($nick, 0, -1);
3247 }
3248 return $matched[0];
3249 }, $message);
3250}
3251
3252function add_message($message, $recipient, $poster, $delstatus, $poststatus, $displaysend, $style){
3253 global $db;
3254 if($message===''){
3255 return false;
3256 }
3257 $newmessage=[
3258 'postdate' =>time(),
3259 'poststatus' =>$poststatus,
3260 'poster' =>$poster,
3261 'recipient' =>$recipient,
3262 'text' =>"<span class=\"usermsg\">$displaysend".style_this($message, $style).'</span>',
3263 'delstatus' =>$delstatus
3264 ];
3265 //prevent posting the same message twice, if no other message was posted in-between.
3266 $stmt=$db->prepare('SELECT id FROM ' . PREFIX . 'messages WHERE poststatus=? AND poster=? AND recipient=? AND text=? AND id IN (SELECT * FROM (SELECT id FROM ' . PREFIX . 'messages ORDER BY id DESC LIMIT 1) AS t);');
3267 $stmt->execute([$newmessage['poststatus'], $newmessage['poster'], $newmessage['recipient'], $newmessage['text']]);
3268 if($stmt->fetch(PDO::FETCH_NUM)){
3269 return false;
3270 }
3271 write_message($newmessage);
3272 return true;
3273}
3274
3275function add_system_message($mes){
3276 if($mes===''){
3277 return;
3278 }
3279 $sysmessage=[
3280 'postdate' =>time(),
3281 'poststatus' =>1,
3282 'poster' =>'',
3283 'recipient' =>'',
3284 'text' =>"<span class=\"sysmsg\">$mes</span>",
3285 'delstatus' =>4
3286 ];
3287 write_message($sysmessage);
3288}
3289
3290function write_message($message){
3291 global $db;
3292 if(MSGENCRYPTED){
3293 $message['text']=openssl_encrypt($message['text'], 'aes-256-cbc', ENCRYPTKEY, 0, '1234567890123456');
3294 }
3295 $stmt=$db->prepare('INSERT INTO ' . PREFIX . 'messages (postdate, poststatus, poster, recipient, text, delstatus) VALUES (?, ?, ?, ?, ?, ?);');
3296 $stmt->execute([$message['postdate'], $message['poststatus'], $message['poster'], $message['recipient'], $message['text'], $message['delstatus']]);
3297 if($message['poststatus']<9 && get_setting('sendmail')){
3298 $subject='New Chat message';
3299 $headers='From: '.get_setting('mailsender')."\r\nX-Mailer: PHP/".phpversion()."\r\nContent-Type: text/html; charset=UTF-8\r\n";
3300 $body='<html><body style="background-color:#'.get_setting('colbg').';color:#'.get_setting('coltxt').";\">$message[text]</body></html>";
3301 mail(get_setting('mailreceiver'), $subject, $body, $headers);
3302 }
3303}
3304
3305function clean_room(){
3306 global $db;
3307 $db->query('DELETE FROM ' . PREFIX . 'messages;');
3308 add_system_message(sprintf(get_setting('msgclean'), get_setting('chatname')));
3309}
3310
3311function clean_selected($status, $nick){
3312 global $db;
3313 if(isset($_REQUEST['mid'])){
3314 $stmt=$db->prepare('DELETE FROM ' . PREFIX . 'messages WHERE id=? AND (poster=? OR recipient=? OR (poststatus<? AND delstatus<?));');
3315 foreach($_REQUEST['mid'] as $mid){
3316 $stmt->execute([$mid, $nick, $nick, $status, $status]);
3317 }
3318 }
3319}
3320
3321function clean_inbox_selected(){
3322 global $U, $db;
3323 if(isset($_REQUEST['mid'])){
3324 $stmt=$db->prepare('DELETE FROM ' . PREFIX . 'inbox WHERE id=? AND recipient=?;');
3325 foreach($_REQUEST['mid'] as $mid){
3326 $stmt->execute([$mid, $U['nickname']]);
3327 }
3328 }
3329}
3330
3331function del_all_messages($nick, $entry){
3332 global $db;
3333 if($nick==''){
3334 return;
3335 }
3336 $stmt=$db->prepare('DELETE FROM ' . PREFIX . 'messages WHERE poster=? AND postdate>=?;');
3337 $stmt->execute([$nick, $entry]);
3338 $stmt=$db->prepare('DELETE FROM ' . PREFIX . 'inbox WHERE poster=? AND postdate>=?;');
3339 $stmt->execute([$nick, $entry]);
3340}
3341
3342function del_last_message(){
3343 global $U, $db;
3344 if($U['status']>1){
3345 $entry=0;
3346 }else{
3347 $entry=$U['entry'];
3348 }
3349 $stmt=$db->prepare('SELECT id FROM ' . PREFIX . 'messages WHERE poster=? AND postdate>=? ORDER BY id DESC LIMIT 1;');
3350 $stmt->execute([$U['nickname'], $entry]);
3351 if($id=$stmt->fetch(PDO::FETCH_NUM)){
3352 $stmt=$db->prepare('DELETE FROM ' . PREFIX . 'messages WHERE id=?;');
3353 $stmt->execute($id);
3354 $stmt=$db->prepare('DELETE FROM ' . PREFIX . 'inbox WHERE postid=?;');
3355 $stmt->execute($id);
3356 }
3357}
3358
3359function print_messages($delstatus=0){
3360 global $U, $db, $language;
3361 $dateformat=get_setting('dateformat');
3362 if(!$U['embed'] && get_setting('imgembed')){
3363 $removeEmbed=true;
3364 }else{
3365 $removeEmbed=false;
3366 }
3367 if($U['timestamps'] && !empty($dateformat)){
3368 $timestamps=true;
3369 }else{
3370 $timestamps=false;
3371 }
3372 if($U['sortupdown']){
3373 $direction='ASC';
3374 }else{
3375 $direction='DESC';
3376 }
3377 if($U['status']>1){
3378 $entry=0;
3379 }else{
3380 $entry=$U['entry'];
3381 }
3382 echo '<div id="messages">';
3383 if($delstatus>0){
3384 $stmt=$db->prepare('SELECT postdate, id, text FROM ' . PREFIX . 'messages WHERE '.
3385 "(poststatus<? AND delstatus<?) OR ((poster=? OR recipient=?) AND postdate>=?) ORDER BY id $direction;");
3386 $stmt->execute([$U['status'], $delstatus, $U['nickname'], $U['nickname'], $entry]);
3387 while($message=$stmt->fetch(PDO::FETCH_ASSOC)){
3388 prepare_message_print($message, $removeEmbed);
3389 echo "<div class=\"msg\"><label><input type=\"checkbox\" name=\"mid[]\" value=\"$message[id]\">";
3390 if($timestamps){
3391 echo ' <small>'.date($dateformat, $message['postdate']).' - </small>';
3392 }
3393 echo " $message[text]</label></div>";
3394 }
3395 }else{
3396
3397 // init count of messages to zero
3398 $countMessages = 0;
3399 $nc=substr(time(), -6); // not sure why this is needed, debbie
3400 $stmt=$db->prepare('SELECT id, postdate, text FROM ' . PREFIX . 'messages WHERE (poststatus<=? OR '.
3401 '(poststatus=9 AND ( (poster=? AND recipient NOT IN (SELECT ign FROM ' . PREFIX . 'ignored WHERE ignby=?) ) OR recipient=?) AND postdate>=?)'.
3402 ') AND poster NOT IN (SELECT ign FROM ' . PREFIX . "ignored WHERE ignby=?) ORDER BY id $direction;");
3403 $stmt->execute([$U['status'], $U['nickname'], $U['nickname'], $U['nickname'], $entry, $U['nickname']]);
3404 while($message=$stmt->fetch(PDO::FETCH_ASSOC)){
3405 prepare_message_print($message, $removeEmbed);
3406 echo '<div class="msg">';
3407 if($timestamps){
3408 echo '<small>'.date($dateformat, $message['postdate']).' - </small>';
3409 }
3410
3411 // Debbie's new code to add hyperlinks to names in messages.
3412 // The hyperlinks will only be applied for the first 50 messages found - no point doing them for discussions long ago or users no longer there
3413 // and this will keep any extra server load minimal
3414
3415 // How it works:
3416 // a) Clicking on a person's name in their public link will trigger the postbox to do a msg to AllChatters, with the person refereced with @personsname
3417 // b) Clicking [M], [Staff] or [Admin] will trigger the postbox to do a msg to members, staff or all chatters
3418 // c) Clicking on the sender of a PM to you will trigger the postbox to do a reply to that person
3419
3420 // info: the following line is the link we are going to add, around the <span> that is around the username. But we also need to get the user name to add into the postbox text box
3421 // <a href=\"$_SERVER[SCRIPT_NAME]?action=post&session=$U[session]&lang=$language&nc=$nc&sendto=s+*\" target=\"post\">".$AllChatters."</a>
3422 if ($countMessages++ < 50)
3423 {
3424 $GotNameToHyperLink = false;
3425 $IsPM = false; // determines whether to do a sendto the name (for PM if true) or do a @referto for a general message (i.e. if false)
3426 $posOfBracket = strpos($message['text'], "usermsg\">[");
3427 if ($posOfBracket != 0)
3428 {
3429 // if start of text, after span=usermsg starts with "[" then it is a pm or a member/staff/admin messages
3430 // found a "[" at start, so set $posOfBracket to point to it
3431 $posOfBracket += 9;
3432 // find RG, Member, Staff and Admin channel messages & create their own links
3433 if (substr($message['text'], $posOfBracket, 4) == "[RG]")
3434 {
3435 $restOfMessage = substr($message['text'], $posOfBracket +4);
3436 echo "<span class=\"usermsg\"><a href=\"$_SERVER[SCRIPT_NAME]?action=post&session=$U[session]&lang=$language&nc=$nc&sendto=s+rg\" style=\"text-decoration: none;color:#ffffff;\" target=\"post\">[RG]</a>".$restOfMessage."</div>";
3437 }
3438 else if (substr($message['text'], $posOfBracket, 3) == "[M]")
3439 {
3440 $restOfMessage = substr($message['text'], $posOfBracket +3);
3441 echo "<span class=\"usermsg\"><a href=\"$_SERVER[SCRIPT_NAME]?action=post&session=$U[session]&lang=$language&nc=$nc&sendto=s+?\" style=\"text-decoration: none;color:#ffffff;\" target=\"post\">[M]</a>".$restOfMessage."</div>";
3442 }
3443 else if (substr($message['text'], $posOfBracket, 7) == "[Staff]")
3444 {
3445 $restOfMessage = substr($message['text'], $posOfBracket +7);
3446 echo "<span class=\"usermsg\"><a href=\"$_SERVER[SCRIPT_NAME]?action=post&session=$U[session]&lang=$language&nc=$nc&sendto=s+%23\" style=\"text-decoration: none;color:#ffffff;\" target=\"post\">[Staff]</a>".$restOfMessage."</div>";
3447 }
3448 else if (substr($message['text'], $posOfBracket, 7) == "[Admin]")
3449 {
3450 $restOfMessage = substr($message['text'], $posOfBracket +7);
3451 echo "<span class=\"usermsg\"><a href=\"$_SERVER[SCRIPT_NAME]?action=post&session=$U[session]&lang=$language&nc=$nc&sendto=s+%26\" style=\"text-decoration: none;color:#ffffff;\" target=\"post\">[Admin]</a>".$restOfMessage."</div>";
3452 }
3453 else
3454 {
3455 // check for PM
3456 $posEndOfName = strpos($message['text'], "</span> to ");
3457 if ($posEndOfName === false)
3458 {
3459 // didn't find " to ", so just print message as it was
3460 echo "$message[text]</div>";
3461 }
3462 // found a PM
3463 $GotNameToHyperLink = true;
3464 $IsPM = true;
3465 }
3466 }
3467 else
3468 {
3469 // otherwise find end of person's name if it exists (it may not exist, as text may be of form "aaa,bbb,ccc have been kicked")
3470 $posEndOfName = strpos($message['text'], "</span> - ");
3471 if ($posEndOfName === false)
3472 {
3473 // didn't find "</span> - ", so just print message as it was
3474 echo "$message[text]</div>";
3475 }
3476 else
3477 {
3478 $GotNameToHyperLink = true;
3479 }
3480 }
3481 // at this point we have either found a name to put a hyperlink around,
3482 // or have already done the hyperlink around a group message
3483 // or have already printed out a system message that is not going to have a hyperlink
3484
3485 if ($GotNameToHyperLink == true)
3486 {
3487 $posEndOfNameAndSpan = $posEndOfName + 7; // i.e. this should be at beginning of " - " or beginning of " to "
3488 // found end of name at pos $posEndOfName, so get the text up to that point
3489 $beggingOfMessage = substr($message['text'], 0, $posEndOfName);
3490 // now find the position of the last occurance of ">" in the beggingOfMessage - this will be one character before the start of the name for direct message, 2 for PM
3491 $posBegOfName = strrpos($beggingOfMessage, ">");
3492 if ($posBegOfName === false)
3493 {
3494 // didn't find ">", so just print message as it was
3495 echo "$message[text]</div>";
3496 }
3497 else
3498 {
3499 // now extract the person's name
3500 // make sure we can do this... specifically that $posEndOfName and $posBegOfName are non zero and that $posEndOfName-$posBegOfName (=length of the person's name) is positive.
3501 if ($posEndOfName>1 && $posBegOfName>1 && $posEndOfName>$posBegOfName)
3502 {
3503 $fromname = substr($beggingOfMessage, $posBegOfName + 1, $posEndOfName-$posBegOfName);
3504 if ($IsPM == true)
3505 { // adjust for extra '[' character after end of span and before name
3506 // now we need to get the position that the color span around the actual name starts
3507 $posBegOfNameAndSpan = strpos($beggingOfMessage, "usermsg\">") + 10;
3508 }
3509 else
3510 {
3511 // now we need to get the position that the color span around the actual name starts
3512 $posBegOfNameAndSpan = strpos($beggingOfMessage, "usermsg\">") + 9;
3513 }
3514
3515 if ($posBegOfNameAndSpan > 10)
3516 {
3517 // found it, we are good to go
3518 $nameAndSpan = substr($message['text'], $posBegOfNameAndSpan, $posEndOfNameAndSpan - $posBegOfNameAndSpan + 1);
3519 $restOfMessage = substr($message['text'], $posEndOfNameAndSpan);
3520 if ($IsPM == true)
3521 {
3522 echo "<span class=\"usermsg\">[<a href=\"$_SERVER[SCRIPT_NAME]?action=post&session=$U[session]&lang=$language&nc=$nc&sendto=".htmlspecialchars($fromname)."\" target=\"post\">".$nameAndSpan."</a>".$restOfMessage."</div>";
3523 }
3524 else
3525 {
3526 echo "<span class=\"usermsg\"><a href=\"$_SERVER[SCRIPT_NAME]?action=msglink&session=$U[session]&lang=$language&nc=$nc&sendto=s+*&refname=".$fromname."\" target=\"post\">".$nameAndSpan."</a>".$restOfMessage."</div>";
3527 }
3528 }
3529 else
3530 {
3531 // something went wrong, abandon and just continue without hyperlilnk
3532 echo "$message[text]</div>";
3533 }
3534 }
3535 else
3536 {
3537 // failed sanity check, so just print message as it was
3538 echo "$message[text]</div>";
3539 }
3540 }
3541 }
3542 }
3543 else
3544 {
3545 // have processed more than 50 messages, so just print the rest plain
3546 echo "$message[text]</div>";
3547 }
3548 }
3549 }
3550 echo '</div>';
3551}
3552function prepare_message_print(&$message, $removeEmbed){
3553 if(MSGENCRYPTED){
3554 $message['text']=openssl_decrypt($message['text'], 'aes-256-cbc', ENCRYPTKEY, 0, '1234567890123456');
3555 }
3556 if($removeEmbed){
3557 $message['text']=preg_replace_callback('/<img src="([^"]+)"><\/a>/u',
3558 function ($matched){
3559 return "$matched[1]</a>";
3560 }
3561 , $message['text']);
3562 }
3563}
3564
3565// this and that
3566
3567function send_headers(){
3568 header('Content-Type: text/html; charset=UTF-8');
3569 header('Pragma: no-cache');
3570 header('Cache-Control: no-cache, no-store, must-revalidate, max-age=0');
3571 header('Expires: 0');
3572 header('Referrer-Policy: no-referrer');
3573 header('Content-Security-Policy: referrer never');
3574 if($_SERVER['REQUEST_METHOD']==='HEAD'){
3575 exit; // headers sent, no further processing needed
3576 }
3577}
3578
3579function save_setup($C){
3580 global $db;
3581 //sanity checks and escaping
3582 foreach($C['msg_settings'] as $setting){
3583 $_REQUEST[$setting]=htmlspecialchars($_REQUEST[$setting]);
3584 }
3585 foreach($C['number_settings'] as $setting){
3586 settype($_REQUEST[$setting], 'int');
3587 }
3588 foreach($C['colour_settings'] as $setting){
3589 if(preg_match('/^#([a-f0-9]{6})$/i', $_REQUEST[$setting], $match)){
3590 $_REQUEST[$setting]=$match[1];
3591 }else{
3592 unset($_REQUEST[$setting]);
3593 }
3594 }
3595 settype($_REQUEST['guestaccess'], 'int');
3596 if(!preg_match('/^[01234]$/', $_REQUEST['guestaccess'])){
3597 unset($_REQUEST['guestaccess']);
3598 }elseif($_REQUEST['guestaccess']==4){
3599 $db->exec('DELETE FROM ' . PREFIX . 'sessions WHERE status<7;');
3600 }
3601 settype($_REQUEST['englobalpass'], 'int');
3602 settype($_REQUEST['captcha'], 'int');
3603 settype($_REQUEST['dismemcaptcha'], 'int');
3604 settype($_REQUEST['guestreg'], 'int');
3605 if(isset($_REQUEST['defaulttz'])){
3606 $tzs=timezone_identifiers_list();
3607 if(!in_array($_REQUEST['defaulttz'], $tzs)){
3608 unset($_REQUEST['defualttz']);
3609 }
3610 }
3611 $_REQUEST['rulestxt']=preg_replace("/(\r?\n|\r\n?)/u", '<br>', $_REQUEST['rulestxt']);
3612 $_REQUEST['chatname']=htmlspecialchars($_REQUEST['chatname']);
3613 $_REQUEST['redirect']=htmlspecialchars($_REQUEST['redirect']);
3614 if($_REQUEST['memberexpire']<5){
3615 $_REQUEST['memberexpire']=5;
3616 }
3617 if($_REQUEST['captchatime']<30){
3618 $_REQUEST['memberexpire']=30;
3619 }
3620 if($_REQUEST['defaultrefresh']<5){
3621 $_REQUEST['defaultrefresh']=5;
3622 }elseif($_REQUEST['defaultrefresh']>150){
3623 $_REQUEST['defaultrefresh']=150;
3624 }
3625 if($_REQUEST['maxname']<1){
3626 $_REQUEST['maxname']=1;
3627 }elseif($_REQUEST['maxname']>50){
3628 $_REQUEST['maxname']=50;
3629 }
3630 if($_REQUEST['maxmessage']<1){
3631 $_REQUEST['maxmessage']=1;
3632 }elseif($_REQUEST['maxmessage']>16000){
3633 $_REQUEST['maxmessage']=16000;
3634 }
3635 if($_REQUEST['numnotes']<1){
3636 $_REQUEST['numnotes']=1;
3637 }
3638 if(!valid_regex($_REQUEST['nickregex'])){
3639 unset($_REQUEST['nickregex']);
3640 }
3641 if(!valid_regex($_REQUEST['passregex'])){
3642 unset($_REQUEST['passregex']);
3643 }
3644 //save values
3645 foreach($C['settings'] as $setting){
3646 if(isset($_REQUEST[$setting])){
3647 update_setting($setting, $_REQUEST[$setting]);
3648 }
3649 }
3650}
3651
3652function set_default_tz(){
3653 global $U;
3654 if(isset($U['tz'])){
3655 date_default_timezone_set($U['tz']);
3656 }else{
3657 date_default_timezone_set(get_setting('defaulttz'));
3658 }
3659}
3660
3661function valid_admin(){
3662 global $U;
3663 if(isset($_REQUEST['session'])){
3664 parse_sessions();
3665 }
3666 if(!isset($U['session']) && isset($_REQUEST['nick']) && isset($_REQUEST['pass'])){
3667 create_session(true, $_REQUEST['nick'], $_REQUEST['pass']);
3668 }
3669 if(isset($U['status'])){
3670 if($U['status']>=7){
3671 return true;
3672 }
3673 send_access_denied();
3674 }
3675 return false;
3676}
3677
3678function valid_nick($nick){
3679 $len=mb_strlen($nick);
3680 if($len<1 || $len>get_setting('maxname')){
3681 return false;
3682 }
3683 return preg_match('/'.get_setting('nickregex').'/u', $nick);
3684}
3685
3686function valid_pass($pass){
3687 if(mb_strlen($pass)<get_setting('minpass')){
3688 return false;
3689 }
3690 return preg_match('/'.get_setting('passregex').'/u', $pass);
3691}
3692
3693function valid_regex(&$regex){
3694 $regex=preg_replace('~(^|[^\\\\])/~', "$1\/u", $regex); // Escape "/" if not yet escaped
3695 return (@preg_match("/$_REQUEST[match]/u", '') !== false);
3696}
3697
3698function get_timeout($lastpost, $expire){
3699 $s=($lastpost+60*$expire)-time();
3700 $m=floor($s/60);
3701 $s%=60;
3702 if($s<10){
3703 $s="0$s";
3704 }
3705 if($m>60){
3706 $h=floor($m/60);
3707 $m%=60;
3708 if($m<10){
3709 $m="0$m";
3710 }
3711 echo "$h:$m:$s";
3712 }else{
3713 echo "$m:$s";
3714 }
3715}
3716
3717function print_colours(){
3718 global $I;
3719 // Prints a short list with selected named HTML colours and filters out illegible text colours for the given background.
3720 // It's a simple comparison of weighted grey values. This is not very accurate but gets the job done well enough.
3721 // name=>[colour, greyval(colour)]
3722 $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]];
3723 $greybg=greyval(get_setting('colbg'));
3724 foreach($colours as $name=>$colour){
3725 if(abs($greybg-$colour[1])>75){
3726 echo "<option value=\"$colour[0]\" style=\"color:#$colour[0];\">$I[$name]</option>";
3727 }
3728 }
3729}
3730
3731function greyval($colour){
3732 return hexdec(substr($colour, 0, 2))*.3+hexdec(substr($colour, 2, 2))*.59+hexdec(substr($colour, 4, 2))*.11;
3733}
3734
3735function style_this($text, $styleinfo){
3736 return "<span style=\"$styleinfo\">$text</span>";
3737}
3738
3739function check_init(){
3740 global $db;
3741 return @$db->query('SELECT null FROM ' . PREFIX . 'settings LIMIT 1;');
3742}
3743
3744// run every minute doing various database cleanup task
3745function cron(){
3746 global $db;
3747 $time=time();
3748 if(get_setting('nextcron')>$time){
3749 return;
3750 }
3751 update_setting('nextcron', $time+10);
3752 // delete old sessions
3753 $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')));");
3754 $stmt->execute([$time, $time]);
3755 // delete old messages
3756 $limit=get_setting('messagelimit');
3757 $stmt=$db->query('SELECT id FROM ' . PREFIX . "messages WHERE poststatus=1 ORDER BY id DESC LIMIT 1 OFFSET $limit;");
3758 if($id=$stmt->fetch(PDO::FETCH_NUM)){
3759 $stmt=$db->prepare('DELETE FROM ' . PREFIX . 'messages WHERE id<=?;');
3760 $stmt->execute($id);
3761 }
3762 $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);");
3763 $stmt->execute([$time]);
3764 // delete expired ignored people
3765 $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);');
3766 $stmt=$db->prepare('DELETE FROM ' . PREFIX . 'ignored WHERE id=?;');
3767 while($tmp=$result->fetch(PDO::FETCH_NUM)){
3768 $stmt->execute($tmp);
3769 }
3770 // delete files that do not belong to any message
3771 $result=$db->query('SELECT id FROM ' . PREFIX . 'files WHERE postid NOT IN (SELECT id FROM ' . PREFIX . 'messages UNION SELECT postid FROM ' . PREFIX . 'inbox);');
3772 $stmt=$db->prepare('DELETE FROM ' . PREFIX . 'files WHERE id=?;');
3773 while($tmp=$result->fetch(PDO::FETCH_NUM)){
3774 $stmt->execute($tmp);
3775 }
3776 // delete old notes
3777 $limit=get_setting('numnotes');
3778 $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=1 ORDER BY id DESC LIMIT $limit) ) AS t);");
3779 $result=$db->query('SELECT editedby, COUNT(*) AS cnt FROM ' . PREFIX . "notes WHERE type=2 GROUP BY editedby HAVING cnt>$limit;");
3780 $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);");
3781 while($tmp=$result->fetch(PDO::FETCH_NUM)){
3782 $stmt->execute([$tmp[0], $tmp[0]]);
3783 }
3784 // delete old captchas
3785 $stmt=$db->prepare('DELETE FROM ' . PREFIX . 'captcha WHERE time<(?-(SELECT value FROM ' . PREFIX . "settings WHERE setting='captchatime'));");
3786 $stmt->execute([$time]);
3787}
3788
3789function destroy_chat($C){
3790 global $I, $db, $memcached;
3791 setcookie(COOKIENAME, false);
3792 $_REQUEST['session']='';
3793 print_start('destory');
3794 $db->exec('DROP TABLE ' . PREFIX . 'captcha;');
3795 $db->exec('DROP TABLE ' . PREFIX . 'files;');
3796 $db->exec('DROP TABLE ' . PREFIX . 'filter;');
3797 $db->exec('DROP TABLE ' . PREFIX . 'ignored;');
3798 $db->exec('DROP TABLE ' . PREFIX . 'inbox;');
3799 $db->exec('DROP TABLE ' . PREFIX . 'linkfilter;');
3800 $db->exec('DROP TABLE ' . PREFIX . 'members;');
3801 $db->exec('DROP TABLE ' . PREFIX . 'messages;');
3802 $db->exec('DROP TABLE ' . PREFIX . 'notes;');
3803 $db->exec('DROP TABLE ' . PREFIX . 'sessions;');
3804 $db->exec('DROP TABLE ' . PREFIX . 'settings;');
3805 if(MEMCACHED){
3806 $memcached->delete(DBNAME . '-' . PREFIX . 'filter');
3807 $memcached->delete(DBANEM . '-' . PREFIX . 'linkfilter');
3808 foreach($C['settings'] as $setting){
3809 $memcached->delete(DBNAME . '-' . PREFIX . "settings-$setting");
3810 }
3811 $memcached->delete(DBNAME . '-' . PREFIX . 'settings-dbversion');
3812 $memcached->delete(DBNAME . '-' . PREFIX . 'settings-msgencrypted');
3813 $memcached->delete(DBNAME . '-' . PREFIX . 'settings-nextcron');
3814 }
3815 echo "<h2>$I[destroyed]</h2><br><br><br>";
3816 echo form('setup').submit($I['init']).'</form>'.credit();
3817 print_end();
3818}
3819
3820function init_chat(){
3821 global $I, $db;
3822 $suwrite='';
3823 if(check_init()){
3824 $suwrite=$I['initdbexist'];
3825 $result=$db->query('SELECT null FROM ' . PREFIX . 'members WHERE status=8;');
3826 if($result->fetch(PDO::FETCH_NUM)){
3827 $suwrite=$I['initsuexist'];
3828 }
3829 }elseif(!preg_match('/^[a-z0-9]{1,20}$/i', $_REQUEST['sunick'])){
3830 $suwrite=sprintf($I['invalnick'], 20, '^[A-Za-z1-9]*$');
3831 }elseif(mb_strlen($_REQUEST['supass'])<5){
3832 $suwrite=sprintf($I['invalpass'], 5, '.*');
3833 }elseif($_REQUEST['supass']!==$_REQUEST['supassc']){
3834 $suwrite=$I['noconfirm'];
3835 }else{
3836 ignore_user_abort(true);
3837 set_time_limit(0);
3838 if(DBDRIVER===0){//MySQL
3839 $memengine=' ENGINE=MEMORY';
3840 $diskengine=' ENGINE=InnoDB';
3841 $charset=' DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin';
3842 $primary='integer PRIMARY KEY AUTO_INCREMENT';
3843 $longtext='longtext';
3844 }elseif(DBDRIVER===1){//PostgreSQL
3845 $memengine='';
3846 $diskengine='';
3847 $charset='';
3848 $primary='serial PRIMARY KEY';
3849 $longtext='text';
3850 }else{//SQLite
3851 $memengine='';
3852 $diskengine='';
3853 $charset='';
3854 $primary='integer PRIMARY KEY';
3855 $longtext='text';
3856 }
3857 $db->exec('CREATE TABLE ' . PREFIX . "captcha (id $primary, time integer NOT NULL, code char(5) NOT NULL)$memengine$charset;");
3858 $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;");
3859 $db->exec('CREATE INDEX ' . PREFIX . 'files_hash ON ' . PREFIX . 'files(hash);');
3860 $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;");
3861 $db->exec('CREATE TABLE ' . PREFIX . "ignored (id $primary, ign varchar(50) NOT NULL, ignby varchar(50) NOT NULL)$diskengine$charset;");
3862 $db->exec('CREATE INDEX ' . PREFIX . 'ign ON ' . PREFIX . 'ignored(ign);');
3863 $db->exec('CREATE INDEX ' . PREFIX . 'ignby ON ' . PREFIX . 'ignored(ignby);');
3864 $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;");
3865 $db->exec('CREATE INDEX ' . PREFIX . 'inbox_poster ON ' . PREFIX . 'inbox(poster);');
3866 $db->exec('CREATE INDEX ' . PREFIX . 'inbox_recipient ON ' . PREFIX . 'inbox(recipient);');
3867 $db->exec('CREATE TABLE ' . PREFIX . "linkfilter (id $primary, filtermatch varchar(255) NOT NULL, filterreplace varchar(255) NOT NULL, regex smallint NOT NULL)$diskengine$charset;");
3868 $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;");
3869 $db->exec('ALTER TABLE ' . PREFIX . 'inbox ADD FOREIGN KEY (recipient) REFERENCES ' . PREFIX . 'members(nickname) ON DELETE CASCADE ON UPDATE CASCADE;');
3870 $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;");
3871 $db->exec('CREATE INDEX ' . PREFIX . 'poster ON ' . PREFIX . 'messages (poster);');
3872 $db->exec('CREATE INDEX ' . PREFIX . 'recipient ON ' . PREFIX . 'messages(recipient);');
3873 $db->exec('CREATE INDEX ' . PREFIX . 'postdate ON ' . PREFIX . 'messages(postdate);');
3874 $db->exec('CREATE INDEX ' . PREFIX . 'poststatus ON ' . PREFIX . 'messages(poststatus);');
3875 $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;");
3876 $db->exec('CREATE INDEX ' . PREFIX . 'notes_type ON ' . PREFIX . 'notes(type);');
3877 $db->exec('CREATE INDEX ' . PREFIX . 'notes_editedby ON ' . PREFIX . 'notes(editedby);');
3878 $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;");
3879 $db->exec('CREATE INDEX ' . PREFIX . 'status ON ' . PREFIX . 'sessions(status);');
3880 $db->exec('CREATE INDEX ' . PREFIX . 'lastpost ON ' . PREFIX . 'sessions(lastpost);');
3881 $db->exec('CREATE INDEX ' . PREFIX . 'incognito ON ' . PREFIX . 'sessions(incognito);');
3882 $db->exec('CREATE TABLE ' . PREFIX . "settings (setting varchar(50) NOT NULL PRIMARY KEY, value text NOT NULL)$diskengine$charset;");
3883
3884 $settings=[
3885 ['guestaccess', '0'],
3886 ['globalpass', ''],
3887 ['englobalpass', '0'],
3888 ['captcha', '0'],
3889 ['dateformat', 'm-d H:i:s'],
3890 ['rulestxt', ''],
3891 ['msgencrypted', '0'],
3892 ['dbversion', DBVERSION],
3893 ['css', ''],
3894 ['memberexpire', '60'],
3895 ['guestexpire', '15'],
3896 ['kickpenalty', '10'],
3897 ['entrywait', '120'],
3898 ['messageexpire', '14400'],
3899 ['messagelimit', '150'],
3900 ['maxmessage', 2000],
3901 ['captchatime', '600'],
3902 ['colbg', '000000'],
3903 ['coltxt', 'FFFFFF'],
3904 ['maxname', '20'],
3905 ['minpass', '5'],
3906 ['defaultrefresh', '20'],
3907 ['dismemcaptcha', '0'],
3908 ['suguests', '0'],
3909 ['imgembed', '1'],
3910 ['timestamps', '1'],
3911 ['trackip', '0'],
3912 ['captchachars', '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'],
3913 ['memkick', '1'],
3914 ['forceredirect', '0'],
3915 ['redirect', ''],
3916 ['incognito', '1'],
3917 ['chatname', 'My Chat'],
3918 ['topic', ''],
3919 ['msgsendall', $I['sendallmsg']],
3920 ['msgsendmem', $I['sendmemmsg']],
3921 ['msgsendmod', $I['sendmodmsg']],
3922 ['msgsendadm', $I['sendadmmsg']],
3923 ['msgsendprv', $I['sendprvmsg']],
3924 ['msgenter', $I['entermsg']],
3925 ['msgexit', $I['exitmsg']],
3926 ['msgmemreg', $I['memregmsg']],
3927 ['msgsureg', $I['suregmsg']],
3928 ['msgkick', $I['kickmsg']],
3929 ['msgmultikick', $I['multikickmsg']],
3930 ['msgallkick', $I['allkickmsg']],
3931 ['msgclean', $I['cleanmsg']],
3932 ['numnotes', '3'],
3933 ['mailsender', 'www-data <www-data@localhost>'],
3934 ['mailreceiver', 'Webmaster <webmaster@localhost>'],
3935 ['sendmail', '0'],
3936 ['modfallback', '1'],
3937 ['guestreg', '0'],
3938 ['disablepm', '0'],
3939 ['disabletext', "<h1>$I[disabledtext]</h1>"],
3940 ['defaulttz', 'UTC'],
3941 ['eninbox', '0'],
3942 ['passregex', '.*'],
3943 ['nickregex', '^[A-Za-z0-9]*$'],
3944 ['externalcss', ''],
3945 ['enablegreeting', '0'],
3946 ['sortupdown', '0'],
3947 ['hidechatters', '0'],
3948 ['enfileupload', '0'],
3949 ['msgattache', '%2$s [%1$s]'],
3950 ['maxuploadsize', '1024'],
3951 ['nextcron', '0'],
3952 ['personalnotes', '1'],
3953 ['filtermodkick', '0'],
3954 ];
3955 $stmt=$db->prepare('INSERT INTO ' . PREFIX . 'settings (setting, value) VALUES (?, ?);');
3956 foreach($settings as $pair){
3957 $stmt->execute($pair);
3958 }
3959 $reg=[
3960 'nickname' =>$_REQUEST['sunick'],
3961 'passhash' =>password_hash($_REQUEST['supass'], PASSWORD_DEFAULT),
3962 'status' =>8,
3963 'refresh' =>20,
3964 'bgcolour' =>'000000',
3965 'timestamps' =>1,
3966 'style' =>'color:#FFFFFF;',
3967 'embed' =>1,
3968 'incognito' =>0,
3969 'nocache' =>0,
3970 'nocache_old' =>1,
3971 'tz' =>'UTC',
3972 'eninbox' =>0,
3973 'sortupdown' =>0,
3974 'hidechatters' =>0,
3975 ];
3976 $stmt=$db->prepare('INSERT INTO ' . PREFIX . 'members (nickname, passhash, status, refresh, bgcolour, timestamps, style, embed, incognito, nocache, tz, eninbox, sortupdown, hidechatters, nocache_old) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);');
3977 $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']]);
3978 $suwrite=$I['susuccess'];
3979 }
3980 print_start('init');
3981 echo "<h2>$I[init]</h2><br><h3>$I[sulogin]</h3>$suwrite<br><br><br>";
3982 echo form('setup').submit($I['initgosetup']).'</form>'.credit();
3983 print_end();
3984}
3985
3986function update_db(){
3987 global $I, $db, $memcached;
3988 $dbversion=(int) get_setting('dbversion');
3989 $msgencrypted=(bool) get_setting('msgencrypted');
3990 if($dbversion>=DBVERSION && $msgencrypted===MSGENCRYPTED){
3991 return;
3992 }
3993 ignore_user_abort(true);
3994 set_time_limit(0);
3995 if(DBDRIVER===0){//MySQL
3996 $memengine=' ENGINE=MEMORY';
3997 $diskengine=' ENGINE=InnoDB';
3998 $charset=' DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin';
3999 $primary='integer PRIMARY KEY AUTO_INCREMENT';
4000 $longtext='longtext';
4001 }elseif(DBDRIVER===1){//PostgreSQL
4002 $memengine='';
4003 $diskengine='';
4004 $charset='';
4005 $primary='serial PRIMARY KEY';
4006 $longtext='text';
4007 }else{//SQLite
4008 $memengine='';
4009 $diskengine='';
4010 $charset='';
4011 $primary='integer PRIMARY KEY';
4012 $longtext='text';
4013 }
4014 $msg='';
4015 if($dbversion<2){
4016 $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;");
4017 }
4018 if($dbversion<3){
4019 $db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('rulestxt', '');");
4020 }
4021 if($dbversion<4){
4022 $db->exec('ALTER TABLE ' . PREFIX . 'members ADD incognito smallint NOT NULL;');
4023 }
4024 if($dbversion<5){
4025 $db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('globalpass', '');");
4026 }
4027 if($dbversion<6){
4028 $db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('dateformat', 'm-d H:i:s');");
4029 }
4030 if($dbversion<7){
4031 $db->exec('ALTER TABLE ' . PREFIX . 'captcha ADD code char(5) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;');
4032 }
4033 if($dbversion<8){
4034 $db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('captcha', '0'), ('englobalpass', '0');");
4035 $ga=(int) get_setting('guestaccess');
4036 if($ga===-1){
4037 update_setting('guestaccess', 0);
4038 update_setting('englobalpass', 1);
4039 }elseif($ga===4){
4040 update_setting('guestaccess', 1);
4041 update_setting('englobalpass', 2);
4042 }
4043 }
4044 if($dbversion<9){
4045 $db->exec('INSERT INTO ' . PREFIX . "settings (setting,value) VALUES ('msgencrypted', '0');");
4046 $db->exec('ALTER TABLE ' . PREFIX . 'settings MODIFY value varchar(20000) NOT NULL;');
4047 $db->exec('ALTER TABLE ' . PREFIX . 'messages DROP postid;');
4048 }
4049 if($dbversion<10){
4050 $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');");
4051 }
4052 if($dbversion<11){
4053 $db->exec('ALTER TABLE ' , PREFIX . 'captcha CHARACTER SET utf8 COLLATE utf8_bin;');
4054 $db->exec('ALTER TABLE ' . PREFIX . 'filter CHARACTER SET utf8 COLLATE utf8_bin;');
4055 $db->exec('ALTER TABLE ' . PREFIX . 'ignored CHARACTER SET utf8 COLLATE utf8_bin;');
4056 $db->exec('ALTER TABLE ' . PREFIX . 'messages CHARACTER SET utf8 COLLATE utf8_bin;');
4057 $db->exec('ALTER TABLE ' . PREFIX . 'notes CHARACTER SET utf8 COLLATE utf8_bin;');
4058 $db->exec('ALTER TABLE ' . PREFIX . 'settings CHARACTER SET utf8 COLLATE utf8_bin;');
4059 $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;");
4060 $db->exec('ALTER TABLE ' . PREFIX . 'members ADD style varchar(255) NOT NULL;');
4061 $result=$db->query('SELECT * FROM ' . PREFIX . 'members;');
4062 $stmt=$db->prepare('UPDATE ' . PREFIX . 'members SET style=? WHERE id=?;');
4063 $F=load_fonts();
4064 while($temp=$result->fetch(PDO::FETCH_ASSOC)){
4065 $style="color:#$temp[colour];";
4066 if(isset($F[$temp['fontface']])){
4067 $style.=$F[$temp['fontface']];
4068 }
4069 if(strpos($temp['fonttags'], 'i')!==false){
4070 $style.='font-style:italic;';
4071 }
4072 if(strpos($temp['fonttags'], 'b')!==false){
4073 $style.='font-weight:bold;';
4074 }
4075 $stmt->execute([$style, $temp['id']]);
4076 }
4077 $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');");
4078 }
4079 if($dbversion<12){
4080 $db->exec('ALTER TABLE ' . PREFIX . 'captcha MODIFY code char(5) NOT NULL, DROP INDEX id, ADD PRIMARY KEY (id) USING BTREE;');
4081 $db->exec('ALTER TABLE ' . PREFIX . 'captcha ENGINE=MEMORY;');
4082 $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;');
4083 $db->exec('ALTER TABLE ' . PREFIX . 'ignored MODIFY ignored varchar(50) NOT NULL, MODIFY `by` varchar(50) NOT NULL, ADD INDEX(ignored), ADD INDEX(`by`);');
4084 $db->exec('ALTER TABLE ' . PREFIX . 'linkfilter MODIFY match varchar(255) NOT NULL, MODIFY replace varchar(255) NOT NULL;');
4085 $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);');
4086 $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;');
4087 $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;');
4088 $db->exec('ALTER TABLE ' . PREFIX . 'settings DROP PRIMARY KEY, DROP id, ADD PRIMARY KEY(setting);');
4089 $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');");
4090 }
4091 if($dbversion<13){
4092 $db->exec('ALTER TABLE ' . PREFIX . 'filter CHANGE `match` filtermatch varchar(255) NOT NULL, CHANGE `replace` filterreplace varchar(20000) NOT NULL;');
4093 $db->exec('ALTER TABLE ' . PREFIX . 'ignored CHANGE ignored ign varchar(50) NOT NULL, CHANGE `by` ignby varchar(50) NOT NULL;');
4094 $db->exec('ALTER TABLE ' . PREFIX . 'linkfilter CHANGE `match` filtermatch varchar(255) NOT NULL, CHANGE `replace` filterreplace varchar(255) NOT NULL;');
4095 }
4096 if($dbversion<14){
4097 if(MEMCACHED){
4098 $memcached->delete(DBNAME . '-' . PREFIX . 'members');
4099 $memcached->delete(DBNAME . '-' . PREFIX . 'ignored');
4100 }
4101 if(DBDRIVER===0){//MySQL - previously had a wrong SQL syntax and the captcha table was not created.
4102 $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;');
4103 }
4104 }
4105 if($dbversion<15){
4106 $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');");
4107 }
4108 if($dbversion<17){
4109 $db->exec('ALTER TABLE ' . PREFIX . 'members ADD COLUMN nocache smallint NOT NULL DEFAULT 0;');
4110 }
4111 if($dbversion<18){
4112 $db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('disablepm', '0');");
4113 }
4114 if($dbversion<19){
4115 $db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('disabletext', '<h1>$I[disabledtext]</h1>');");
4116 }
4117 if($dbversion<20){
4118 $db->exec('ALTER TABLE ' . PREFIX . 'members ADD COLUMN tz smallint NOT NULL DEFAULT 0;');
4119 $db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('defaulttz', 'UTC');");
4120 }
4121 if($dbversion<21){
4122 $db->exec('ALTER TABLE ' . PREFIX . 'members ADD COLUMN eninbox smallint NOT NULL DEFAULT 0;');
4123 $db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('eninbox', '0');");
4124 if(DBDRIVER===0){
4125 $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;");
4126 }else{
4127 $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);");
4128 $db->exec('CREATE INDEX ' . PREFIX . 'inbox_postid ON ' . PREFIX . 'inbox(postid);');
4129 $db->exec('CREATE INDEX ' . PREFIX . 'inbox_poster ON ' . PREFIX . 'inbox(poster);');
4130 $db->exec('CREATE INDEX ' . PREFIX . 'inbox_recipient ON ' . PREFIX . 'inbox(recipient);');
4131 }
4132 }
4133 if($dbversion<23){
4134 $db->exec('DELETE FROM ' . PREFIX . "settings WHERE setting='enablejs';");
4135 }
4136 if($dbversion<25){
4137 $db->exec('DELETE FROM ' . PREFIX . "settings WHERE setting='keeplimit';");
4138 }
4139 if($dbversion<26){
4140 $db->exec('INSERT INTO ' . PREFIX . 'settings (setting, value) VALUES (\'passregex\', \'.*\'), (\'nickregex\', \'^[A-Za-z0-9]*$\');');
4141 }
4142 if($dbversion<27){
4143 $db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('externalcss', '');");
4144 }
4145 if($dbversion<28){
4146 $db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('enablegreeting', '0');");
4147 }
4148 if($dbversion<29){
4149 $db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('sortupdown', '0');");
4150 $db->exec('ALTER TABLE ' . PREFIX . 'members ADD COLUMN sortupdown smallint NOT NULL DEFAULT 0;');
4151 }
4152 if($dbversion<30){
4153 $db->exec('ALTER TABLE ' . PREFIX . 'filter ADD COLUMN cs smallint NOT NULL DEFAULT 0;');
4154 if(MEMCACHED){
4155 $memcached->delete(DBNAME . '-' . PREFIX . "filter");
4156 }
4157 }
4158 if($dbversion<31){
4159 $db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('hidechatters', '0');");
4160 $db->exec('ALTER TABLE ' . PREFIX . 'members ADD COLUMN hidechatters smallint NOT NULL DEFAULT 0;');
4161 }
4162 if($dbversion<32 && DBDRIVER===0){
4163 //recreate db in utf8mb4
4164 try{
4165 $olddb=new PDO('mysql:host=' . DBHOST . ';dbname=' . DBNAME, DBUSER, DBPASS, [PDO::ATTR_ERRMODE=>PDO::ERRMODE_WARNING, PDO::ATTR_PERSISTENT=>PERSISTENT]);
4166 }catch(PDOException $e){
4167 send_fatal_error($I['nodb']);
4168 }
4169 $db->exec('DROP TABLE ' . PREFIX . 'captcha;');
4170 $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;");
4171 $result=$olddb->query('SELECT filtermatch, filterreplace, allowinpm, regex, kick, cs FROM ' . PREFIX . 'filter;');
4172 $data=$result->fetchAll(PDO::FETCH_NUM);
4173 $db->exec('DROP TABLE ' . PREFIX . 'filter;');
4174 $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;");
4175 $stmt=$db->prepare('INSERT INTO ' . PREFIX . 'filter (filtermatch, filterreplace, allowinpm, regex, kick, cs) VALUES(?, ?, ?, ?, ?, ?);');
4176 foreach($data as $tmp){
4177 $stmt->execute($tmp);
4178 }
4179 $result=$olddb->query('SELECT ign, ignby FROM ' . PREFIX . 'ignored;');
4180 $data=$result->fetchAll(PDO::FETCH_NUM);
4181 $db->exec('DROP TABLE ' . PREFIX . 'ignored;');
4182 $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;");
4183 $stmt=$db->prepare('INSERT INTO ' . PREFIX . 'ignored (ign, ignby) VALUES(?, ?);');
4184 foreach($data as $tmp){
4185 $stmt->execute($tmp);
4186 }
4187 $db->exec('CREATE INDEX ' . PREFIX . 'ign ON ' . PREFIX . 'ignored(ign);');
4188 $db->exec('CREATE INDEX ' . PREFIX . 'ignby ON ' . PREFIX . 'ignored(ignby);');
4189 $result=$olddb->query('SELECT postdate, postid, poster, recipient, text FROM ' . PREFIX . 'inbox;');
4190 $data=$result->fetchAll(PDO::FETCH_NUM);
4191 $db->exec('DROP TABLE ' . PREFIX . 'inbox;');
4192 $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;");
4193 $stmt=$db->prepare('INSERT INTO ' . PREFIX . 'inbox (postdate, postid, poster, recipient, text) VALUES(?, ?, ?, ?, ?);');
4194 foreach($data as $tmp){
4195 $stmt->execute($tmp);
4196 }
4197 $db->exec('CREATE INDEX ' . PREFIX . 'inbox_poster ON ' . PREFIX . 'inbox(poster);');
4198 $db->exec('CREATE INDEX ' . PREFIX . 'inbox_recipient ON ' . PREFIX . 'inbox(recipient);');
4199 $result=$olddb->query('SELECT filtermatch, filterreplace, regex FROM ' . PREFIX . 'linkfilter;');
4200 $data=$result->fetchAll(PDO::FETCH_NUM);
4201 $db->exec('DROP TABLE ' . PREFIX . 'linkfilter;');
4202 $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;");
4203 $stmt=$db->prepare('INSERT INTO ' . PREFIX . 'linkfilter (filtermatch, filterreplace, regex) VALUES(?, ?, ?);');
4204 foreach($data as $tmp){
4205 $stmt->execute($tmp);
4206 }
4207 $result=$olddb->query('SELECT nickname, passhash, status, refresh, bgcolour, regedby, lastlogin, timestamps, embed, incognito, style, nocache, tz, eninbox, sortupdown, hidechatters FROM ' . PREFIX . 'members;');
4208 $data=$result->fetchAll(PDO::FETCH_NUM);
4209 $db->exec('DROP TABLE ' . PREFIX . 'members;');
4210 $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;");
4211 $stmt=$db->prepare('INSERT INTO ' . PREFIX . 'members (nickname, passhash, status, refresh, bgcolour, regedby, lastlogin, timestamps, embed, incognito, style, nocache, tz, eninbox, sortupdown, hidechatters) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);');
4212 foreach($data as $tmp){
4213 $stmt->execute($tmp);
4214 }
4215 $result=$olddb->query('SELECT postdate, poststatus, poster, recipient, text, delstatus FROM ' . PREFIX . 'messages;');
4216 $data=$result->fetchAll(PDO::FETCH_NUM);
4217 $db->exec('DROP TABLE ' . PREFIX . 'messages;');
4218 $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;");
4219 $stmt=$db->prepare('INSERT INTO ' . PREFIX . 'messages (postdate, poststatus, poster, recipient, text, delstatus) VALUES(?, ?, ?, ?, ?, ?);');
4220 foreach($data as $tmp){
4221 $stmt->execute($tmp);
4222 }
4223 $db->exec('CREATE INDEX ' . PREFIX . 'poster ON ' . PREFIX . 'messages (poster);');
4224 $db->exec('CREATE INDEX ' . PREFIX . 'recipient ON ' . PREFIX . 'messages(recipient);');
4225 $db->exec('CREATE INDEX ' . PREFIX . 'postdate ON ' . PREFIX . 'messages(postdate);');
4226 $db->exec('CREATE INDEX ' . PREFIX . 'poststatus ON ' . PREFIX . 'messages(poststatus);');
4227 $result=$olddb->query('SELECT type, lastedited, editedby, text FROM ' . PREFIX . 'notes;');
4228 $data=$result->fetchAll(PDO::FETCH_NUM);
4229 $db->exec('DROP TABLE ' . PREFIX . 'notes;');
4230 $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;");
4231 $stmt=$db->prepare('INSERT INTO ' . PREFIX . 'notes (type, lastedited, editedby, text) VALUES(?, ?, ?, ?);');
4232 foreach($data as $tmp){
4233 $stmt->execute($tmp);
4234 }
4235 $result=$olddb->query('SELECT setting, value FROM ' . PREFIX . 'settings;');
4236 $data=$result->fetchAll(PDO::FETCH_NUM);
4237 $db->exec('DROP TABLE ' . PREFIX . 'settings;');
4238 $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;");
4239 $stmt=$db->prepare('INSERT INTO ' . PREFIX . 'settings (setting, value) VALUES(?, ?);');
4240 foreach($data as $tmp){
4241 $stmt->execute($tmp);
4242 }
4243 }
4244 if($dbversion<33){
4245 $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;");
4246 $db->exec('CREATE INDEX ' . PREFIX . 'files_hash ON ' . PREFIX . 'files(hash);');
4247 $db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('enfileupload', '0'), ('msgattache', '%2\$s [%1\$s]'), ('maxuploadsize', '1024');");
4248 }
4249 if($dbversion<34){
4250 $msg.="<br>$I[cssupdate]";
4251 $db->exec('ALTER TABLE ' . PREFIX . 'members ADD COLUMN nocache_old smallint NOT NULL DEFAULT 0;');
4252 }
4253 if($dbversion<37){
4254 $db->exec('ALTER TABLE ' . PREFIX . 'members MODIFY tz varchar(255) NOT NULL;');
4255 $db->exec('UPDATE ' . PREFIX . "members SET tz='UTC';");
4256 $db->exec('UPDATE ' . PREFIX . "settings SET value='UTC' WHERE setting='defaulttz';");
4257 }
4258 if($dbversion<38){
4259 $db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('nextcron', '0');");
4260 $db->exec('DELETE FROM ' . PREFIX . 'inbox WHERE recipient NOT IN (SELECT nickname FROM ' . PREFIX . 'members);'); // delete inbox of members who deleted themselves
4261 }
4262 if($dbversion<39){
4263 $db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('personalnotes', '1');");
4264 $result=$db->query('SELECT type, id FROM ' . PREFIX . 'notes;');
4265 while($tmp=$result->fetch(PDO::FETCH_NUM)){
4266 if($tmp[0]==='admin'){
4267 $tmp[0]=0;
4268 }else{
4269 $tmp[0]=1;
4270 }
4271 $data[]=$tmp;
4272 }
4273 $db->exec('ALTER TABLE ' . PREFIX . 'notes MODIFY type smallint NOT NULL;');
4274 $stmt=$db->prepare('UPDATE ' . PREFIX . 'notes SET type=? WHERE id=?;');
4275 foreach($data as $tmp){
4276 $stmt->execute($tmp);
4277 }
4278 $db->exec('CREATE INDEX ' . PREFIX . 'notes_type ON ' . PREFIX . 'notes(type);');
4279 $db->exec('CREATE INDEX ' . PREFIX . 'notes_editedby ON ' . PREFIX . 'notes(editedby);');
4280 }
4281 if($dbversion<41){
4282 $db->exec('DROP TABLE ' . PREFIX . 'sessions;');
4283 $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;");
4284 $db->exec('CREATE INDEX ' . PREFIX . 'status ON ' . PREFIX . 'sessions(status);');
4285 $db->exec('CREATE INDEX ' . PREFIX . 'lastpost ON ' . PREFIX . 'sessions(lastpost);');
4286 $db->exec('CREATE INDEX ' . PREFIX . 'incognito ON ' . PREFIX . 'sessions(incognito);');
4287 $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;');
4288 $members=$result->fetchAll(PDO::FETCH_NUM);
4289 $result=$db->query('SELECT postdate, postid, poster, recipient, text FROM ' . PREFIX . 'inbox;');
4290 $inbox=$result->fetchAll(PDO::FETCH_NUM);
4291 $db->exec('DROP TABLE ' . PREFIX . 'inbox;');
4292 $db->exec('DROP TABLE ' . PREFIX . 'members;');
4293 $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");
4294 $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(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);');
4295 foreach($members as $tmp){
4296 $stmt->execute($tmp);
4297 }
4298 $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;");
4299 $stmt=$db->prepare('INSERT INTO ' . PREFIX . 'inbox (postdate, postid, poster, recipient, text) VALUES(?, ?, ?, ?, ?);');
4300 foreach($inbox as $tmp){
4301 $stmt->execute($tmp);
4302 }
4303 $db->exec('CREATE INDEX ' . PREFIX . 'inbox_poster ON ' . PREFIX . 'inbox(poster);');
4304 $db->exec('CREATE INDEX ' . PREFIX . 'inbox_recipient ON ' . PREFIX . 'inbox(recipient);');
4305 $db->exec('ALTER TABLE ' . PREFIX . 'inbox ADD FOREIGN KEY (recipient) REFERENCES ' . PREFIX . 'members(nickname) ON DELETE CASCADE ON UPDATE CASCADE;');
4306 }
4307 if($dbversion<42){
4308 $db->exec('INSERT IGNORE INTO ' . PREFIX . "settings (setting, value) VALUES ('filtermodkick', '1');");
4309 }
4310 update_setting('dbversion', DBVERSION);
4311 if($msgencrypted!==MSGENCRYPTED){
4312 if(!extension_loaded('openssl')){
4313 send_fatal_error($I['opensslextrequired']);
4314 }
4315 $result=$db->query('SELECT id, text FROM ' . PREFIX . 'messages;');
4316 $stmt=$db->prepare('UPDATE ' . PREFIX . 'messages SET text=? WHERE id=?;');
4317 while($message=$result->fetch(PDO::FETCH_ASSOC)){
4318 if(MSGENCRYPTED){
4319 $message['text']=openssl_encrypt($message['text'], 'aes-256-cbc', ENCRYPTKEY, 0, '1234567890123456');
4320 }else{
4321 $message['text']=openssl_decrypt($message['text'], 'aes-256-cbc', ENCRYPTKEY, 0, '1234567890123456');
4322 }
4323 $stmt->execute([$message['text'], $message['id']]);
4324 }
4325 $result=$db->query('SELECT id, text FROM ' . PREFIX . 'notes;');
4326 $stmt=$db->prepare('UPDATE ' . PREFIX . 'notes SET text=? WHERE id=?;');
4327 while($message=$result->fetch(PDO::FETCH_ASSOC)){
4328 if(MSGENCRYPTED){
4329 $message['text']=openssl_encrypt($message['text'], 'aes-256-cbc', ENCRYPTKEY, 0, '1234567890123456');
4330 }else{
4331 $message['text']=openssl_decrypt($message['text'], 'aes-256-cbc', ENCRYPTKEY, 0, '1234567890123456');
4332 }
4333 $stmt->execute([$message['text'], $message['id']]);
4334 }
4335 update_setting('msgencrypted', (int) MSGENCRYPTED);
4336 }
4337 send_update($msg);
4338}
4339
4340
4341function get_setting($setting){
4342 global $db, $memcached;
4343 if(!MEMCACHED || !$value=$memcached->get(DBNAME . '-' . PREFIX . "settings-$setting")){
4344 $stmt=$db->prepare('SELECT value FROM ' . PREFIX . 'settings WHERE setting=?;');
4345 $stmt->execute([$setting]);
4346 $stmt->bindColumn(1, $value);
4347 $stmt->fetch(PDO::FETCH_BOUND);
4348 if(MEMCACHED){
4349 $memcached->set(DBNAME . '-' . PREFIX . "settings-$setting", $value);
4350 }
4351 }
4352 return $value;
4353}
4354
4355function update_setting($setting, $value){
4356 global $db, $memcached;
4357 $stmt=$db->prepare('UPDATE ' . PREFIX . 'settings SET value=? WHERE setting=?;');
4358 $stmt->execute([$value, $setting]);
4359 if(MEMCACHED){
4360 $memcached->set(DBNAME . '-' . PREFIX . "settings-$setting", $value);
4361 }
4362}
4363
4364// configuration, defaults and internals
4365
4366function check_db(){
4367 global $I, $db, $memcached;
4368 $options=[PDO::ATTR_ERRMODE=>PDO::ERRMODE_WARNING, PDO::ATTR_PERSISTENT=>PERSISTENT];
4369 try{
4370 if(DBDRIVER===0){
4371 if(!extension_loaded('pdo_mysql')){
4372 send_fatal_error($I['pdo_mysqlextrequired']);
4373 }
4374 $db=new PDO('mysql:host=' . DBHOST . ';dbname=' . DBNAME . ';charset=utf8mb4', DBUSER, DBPASS, $options);
4375 }elseif(DBDRIVER===1){
4376 if(!extension_loaded('pdo_pgsql')){
4377 send_fatal_error($I['pdo_pgsqlextrequired']);
4378 }
4379 $db=new PDO('pgsql:host=' . DBHOST . ';dbname=' . DBNAME, DBUSER, DBPASS, $options);
4380 }else{
4381 if(!extension_loaded('pdo_sqlite')){
4382 send_fatal_error($I['pdo_sqliteextrequired']);
4383 }
4384 $db=new PDO('sqlite:' . SQLITEDBFILE, NULL, NULL, $options);
4385 }
4386 }catch(PDOException $e){
4387 try{
4388 //Attempt to create database
4389 if(DBDRIVER===0){
4390 $db=new PDO('mysql:host=' . DBHOST, DBUSER, DBPASS, $options);
4391 if(false!==$db->exec('CREATE DATABASE ' . DBNAME)){
4392 $db=new PDO('mysql:host=' . DBHOST . ';dbname=' . DBNAME . ';charset=utf8mb4', DBUSER, DBPASS, $options);
4393 }else{
4394 send_fatal_error($I['nodbsetup']);
4395 }
4396
4397 }elseif(DBDRIVER===1){
4398 $db=new PDO('pgsql:host=' . DBHOST, DBUSER, DBPASS, $options);
4399 if(false!==$db->exec('CREATE DATABASE ' . DBNAME)){
4400 $db=new PDO('pgsql:host=' . DBHOST . ';dbname=' . DBNAME, DBUSER, DBPASS, $options);
4401 }else{
4402 send_fatal_error($I['nodbsetup']);
4403 }
4404 }else{
4405 if(isset($_REQUEST['action']) && $_REQUEST['action']==='setup'){
4406 send_fatal_error($I['nodbsetup']);
4407 }else{
4408 send_fatal_error($I['nodb']);
4409 }
4410 }
4411 }catch(PDOException $e){
4412 if(isset($_REQUEST['action']) && $_REQUEST['action']==='setup'){
4413 send_fatal_error($I['nodbsetup']);
4414 }else{
4415 send_fatal_error($I['nodb']);
4416 }
4417 }
4418 }
4419 if(MEMCACHED){
4420 if(!extension_loaded('memcached')){
4421 send_fatal_error($I['memcachedextrequired']);
4422 }
4423 $memcached=new Memcached();
4424 $memcached->addServer(MEMCACHEDHOST, MEMCACHEDPORT);
4425 }
4426 if(!isset($_REQUEST['action']) || $_REQUEST['action']==='setup'){
4427 if(!check_init()){
4428 send_init();
4429 }
4430 update_db();
4431 }elseif($_REQUEST['action']==='init'){
4432 init_chat();
4433 }
4434}
4435
4436
4437function load_fonts(){
4438 return [
4439 'Arial' =>"font-family:'Arial','Helvetica','sans-serif';",
4440 'Book Antiqua' =>"font-family:'Book Antiqua','MS Gothic';",
4441 'Comic' =>"font-family:'Comic Sans MS','Papyrus';",
4442 'Courier' =>"font-family:'Courier New','Courier','monospace';",
4443 'Cursive' =>"font-family:'Cursive','Papyrus';",
4444 'Fantasy' =>"font-family:'Fantasy','Futura','Papyrus';",
4445 'Garamond' =>"font-family:'Garamond','Palatino','serif';",
4446 'Georgia' =>"font-family:'Georgia','Times New Roman','Times','serif';",
4447 'Serif' =>"font-family:'MS Serif','New York','serif';",
4448 'System' =>"font-family:'System','Chicago','sans-serif';",
4449 'Times New Roman' =>"font-family:'Times New Roman','Times','serif';",
4450 'Verdana' =>"font-family:'Verdana','Geneva','Arial','Helvetica','sans-serif';",
4451 ];
4452}
4453
4454function parseString($string ) {
4455$my_smilies = array(
4456 ':alien:' => '<img src="https://twemoji.maxcdn.com/2/72x72/1f47d.png" alt="" height="13"/>',
4457 ':thinking:' => '<img src="https://twemoji.maxcdn.com/2/72x72/1f914.png" alt="" height="13" />',
4458 ':angel:' => '<img src="https://twemoji.maxcdn.com/2/72x72/1f47c.png" alt="" height="13"/>',
4459 ':sleep:' => '<img src="https://twemoji.maxcdn.com/2/72x72/1f62a.png" alt="" height="13"/>',
4460 ':blue_heart:' => '<img src="https://twemoji.maxcdn.com/2/72x72/1f499.png" alt="" height="13"/>',
4461 ':heart:' => '<img src="https://twemoji.maxcdn.com/2/72x72/2764.png" alt="" height="13"/>',
4462 ':facepalm:' => '<img src="https://twemoji.maxcdn.com/2/72x72/1f926.png" alt="" height="13"/>',
4463 ':shrugs:' => '<img src="https://twemoji.maxcdn.com/2/72x72/1f937-200d-2640-fe0f.png" alt="" height="13"/>',
4464 ':innocent:' => '<img src=”https://twemoji.maxcdn.com/2/72x72/1f607.png" alt="" height="13"/>',
4465 ':star:' => '<img src="https://twemoji.maxcdn.com/2/72x72/2a-20e3.png" alt="" height="13"/>',
4466 ':sunglasses:' => '<img src="https://twemoji.maxcdn.com/2/72x72/1f60e.png" alt="" height="13"/>',
4467 ':point_right:' => '<img src="https://twemoji.maxcdn.com/2/72x72/1f449.png" alt="" height="13"/>',
4468 ':middle_finger:' => '<img src="https://twemoji.maxcdn.com/2/72x72/1f595.png" alt="" height="13"/>',
4469 ':dunno:' => '¯\_(ツ)_/¯',
4470 ':-)' => '<img src="https://twemoji.maxcdn.com/2/72x72/1f604.png" alt="" height="13"/>',
4471 ':)' => '<img src="https://twemoji.maxcdn.com/2/72x72/1f604.png" alt="" height="13"/>',
4472 ':trollface:' => '<img src="smiles/trollface.png" alt="" height="15"/>',
4473 ':sad:' => '<img src="https://twemoji.maxcdn.com/2/72x72/1f622.png" alt="" height="15"/>',
4474 ':inLove:' => '<img src="smiles/inLove.gif" alt="" height="25"/>',
4475 ':blackHole:' => '<img src="smiles/blackhole.gif" alt="" height="25"/>',
4476 ':explode_fu:' => '<img src="smiles/explode_fu.gif" alt="" height="27"/>',
4477
4478
4479);
4480
4481return str_replace(array_keys($my_smilies), array_values($my_smilies), $string);
4482}