Compare commits

...

8 Commits

2 changed files with 62 additions and 44 deletions

View File

@ -1,3 +1,15 @@
Version 1.20.5 - Jul. 19, 2016
Check permission before selectively deleting a message.
Version 1.20.4 - Jul. 12, 2016
Third attempt to fix the same bug
Version 1.20.3 - Jul. 10, 2016
Yesterdays bugfix broke more than it fixed, refixed.
Version 1.20.2 - Jul. 9, 2016
Fix bug preventing to send PMs to number-only nicknames
Version 1.20.1 - Jun. 13, 2016 Version 1.20.1 - Jun. 13, 2016
Bugfix when logging guests out via admin section Bugfix when logging guests out via admin section
Don't hide image embedding option in profile with cookies disabled Don't hide image embedding option in profile with cookies disabled

View File

@ -151,7 +151,7 @@ function route_admin(){
if($_REQUEST['what']==='choose'){ if($_REQUEST['what']==='choose'){
send_choose_messages(); send_choose_messages();
}elseif($_REQUEST['what']==='selected'){ }elseif($_REQUEST['what']==='selected'){
clean_selected(); clean_selected($U['status']);
}elseif($_REQUEST['what']==='room'){ }elseif($_REQUEST['what']==='room'){
clean_room(); clean_room();
}elseif($_REQUEST['what']==='nick'){ }elseif($_REQUEST['what']==='nick'){
@ -843,7 +843,7 @@ function send_admin($arg=''){
print_start('admin'); print_start('admin');
$chlist="<select name=\"name[]\" size=\"5\" multiple><option value=\"\">$I[choose]</option>"; $chlist="<select name=\"name[]\" size=\"5\" multiple><option value=\"\">$I[choose]</option>";
$chlist.="<option value=\"&\">$I[allguests]</option>"; $chlist.="<option value=\"&\">$I[allguests]</option>";
array_multisort(array_map('strtolower', array_keys($P)), SORT_ASC, SORT_STRING, $P); sort_names($P);
foreach($P as $user){ foreach($P as $user){
if($user[2]<$U['status']){ if($user[2]<$U['status']){
$chlist.="<option value=\"$user[0]\" style=\"$user[1]\">$user[0]</option>"; $chlist.="<option value=\"$user[0]\" style=\"$user[1]\">$user[0]</option>";
@ -940,20 +940,20 @@ function send_admin($arg=''){
frmadm('status'); frmadm('status');
echo "<table class=\"right-table\"><td class=\"right\"><select name=\"name\" size=\"1\"><option value=\"\">$I[choose]</option>"; echo "<table class=\"right-table\"><td class=\"right\"><select name=\"name\" size=\"1\"><option value=\"\">$I[choose]</option>";
read_members(); read_members();
array_multisort(array_map('strtolower', array_keys($A)), SORT_ASC, SORT_STRING, $A); sort_names($A);
foreach($A as $member){ foreach($A as $member){
echo "<option value=\"$member[0]\" style=\"$member[2]\">$member[0]"; echo "<option value=\"$member[0]\" style=\"$member[1]\">$member[0]";
if($member[1]==0){ if($member[2]==0){
echo ' (!)'; echo ' (!)';
}elseif($member[1]==2){ }elseif($member[2]==2){
echo ' (G)'; echo ' (G)';
}elseif($member[1]==5){ }elseif($member[2]==5){
echo ' (M)'; echo ' (M)';
}elseif($member[1]==6){ }elseif($member[2]==6){
echo ' (SM)'; echo ' (SM)';
}elseif($member[1]==7){ }elseif($member[2]==7){
echo ' (A)'; echo ' (A)';
}elseif($member[1]==8){ }elseif($member[2]==8){
echo ' (SA)'; echo ' (SA)';
} }
echo '</option>'; echo '</option>';
@ -974,7 +974,7 @@ function send_admin($arg=''){
frmadm('passreset'); frmadm('passreset');
echo "<table class=\"right-table\"><td><select name=\"name\" size=\"1\"><option value=\"\">$I[choose]</option>"; echo "<table class=\"right-table\"><td><select name=\"name\" size=\"1\"><option value=\"\">$I[choose]</option>";
foreach($A as $member){ foreach($A as $member){
echo "<option value=\"$member[0]\" style=\"$member[2]\">$member[0]</option>"; echo "<option value=\"$member[0]\" style=\"$member[1]\">$member[0]</option>";
} }
echo '</select></td><td><input type="password" name="pass"></td><td>'.submit($I['change']).'</td></tr></table></form></td></tr></table></td></tr>'; echo '</select></td><td><input type="password" name="pass"></td><td>'.submit($I['change']).'</td></tr></table></form></td></tr></table></td></tr>';
thr(); thr();
@ -1459,7 +1459,7 @@ function send_approve_waiting(){
echo '<table class="center-table left">'; echo '<table class="center-table left">';
echo "<tr><th class=\"padded\">$I[sessnick]</th><th class=\"padded\">$I[sessua]</th></tr>"; echo "<tr><th class=\"padded\">$I[sessnick]</th><th class=\"padded\">$I[sessua]</th></tr>";
foreach($tmp as $temp){ foreach($tmp as $temp){
echo '<tr>'.hidden('alls[]', $temp['nickname'])."<td class=\"padded\"><input type=\"checkbox\" name=\"csid[]\" id=\"$temp[nickname]]\" value=\"$temp[nickname]\"><label for=\"$temp[nickname]\"> ".style_this($temp['nickname'], $temp['style'])."</label></td><td class=\"padded\">$temp[useragent]</td></tr>"; echo '<tr>'.hidden('alls[]', $temp['nickname'])."<td class=\"padded\"><input type=\"checkbox\" name=\"csid[]\" id=\"$temp[nickname]\" value=\"$temp[nickname]\"><label for=\"$temp[nickname]\"> ".style_this($temp['nickname'], $temp['style'])."</label></td><td class=\"padded\">$temp[useragent]</td></tr>";
} }
echo "</table><br><table class=\"center-table left\"><tr><td><input type=\"radio\" name=\"what\" value=\"allowchecked\" id=\"allowchecked\" checked><label for=\"allowchecked\">$I[allowchecked]</label></td>"; echo "</table><br><table class=\"center-table left\"><tr><td><input type=\"radio\" name=\"what\" value=\"allowchecked\" id=\"allowchecked\" checked><label for=\"allowchecked\">$I[allowchecked]</label></td>";
echo "<td><input type=\"radio\" name=\"what\" value=\"allowall\" id=\"allowall\"><label for=\"allowall\">$I[allowall]</label></td>"; echo "<td><input type=\"radio\" name=\"what\" value=\"allowall\" id=\"allowall\"><label for=\"allowall\">$I[allowall]</label></td>";
@ -1613,28 +1613,27 @@ function send_post(){
$disablepm=(bool) get_setting('disablepm'); $disablepm=(bool) get_setting('disablepm');
if(!$disablepm){ if(!$disablepm){
$ignored=array(); $ignored=array();
$ignore=get_ignored(); $ignore=get_ignored($U['nickname']);
foreach($ignore as $ign){ foreach($ignore as $ign){
if($ign['ignored']===$U['nickname']){ if($ign['ignored']===$U['nickname']){
$ignored[]=$ign['by']; $ignored[]=$ign['by'];
} }else{
if($ign['by']===$U['nickname']){
$ignored[]=$ign['ignored']; $ignored[]=$ign['ignored'];
} }
} }
$stmt=$db->prepare('SELECT nickname, style, status FROM ' . PREFIX . 'members WHERE eninbox!=0 AND eninbox<=? AND nickname NOT IN (SELECT nickname FROM ' . PREFIX . 'sessions WHERE incognito=0) AND nickname NOT IN (SELECT ign FROM ' . PREFIX . 'ignored WHERE ignby=?) AND nickname NOT IN (SELECT ignby FROM ' . PREFIX . 'ignored WHERE ign=?);'); $stmt=$db->prepare('SELECT nickname, style, status FROM ' . PREFIX . 'members WHERE eninbox!=0 AND eninbox<=? AND nickname NOT IN (SELECT nickname FROM ' . PREFIX . 'sessions WHERE incognito=0) AND nickname NOT IN (SELECT ign FROM ' . PREFIX . 'ignored WHERE ignby=?) AND nickname NOT IN (SELECT ignby FROM ' . PREFIX . 'ignored WHERE ign=?);');
$stmt->execute(array($U['status'], $U['nickname'], $U['nickname'])); $stmt->execute(array($U['status'], $U['nickname'], $U['nickname']));
while($tmp=$stmt->fetch(PDO::FETCH_ASSOC)){ while($tmp=$stmt->fetch(PDO::FETCH_ASSOC)){
$P[$tmp['nickname']]=["$tmp[nickname] $I[offline]", $tmp['style'], $tmp['status']]; $P[$tmp['nickname']]=["$tmp[nickname] $I[offline]", $tmp['style'], $tmp['status'], $tmp['nickname']];
} }
array_multisort(array_map('strtolower', array_keys($P)), SORT_ASC, SORT_STRING, $P); sort_names($P);
foreach($P as $name => $user){ foreach($P as $user){
if($U['nickname']!==$user[0] && !in_array($user[0], $ignored)){ if($U['nickname']!==$user[3] && !in_array($user[3], $ignored)){
echo '<option '; echo '<option ';
if($_REQUEST['sendto']===$name){ if($_REQUEST['sendto']==$user[3]){
echo 'selected '; echo 'selected ';
} }
echo "value=\"$name\" style=\"$user[1]\">$user[0]</option>"; echo "value=\"$user[3]\" style=\"$user[1]\">$user[0]</option>";
} }
} }
} }
@ -1698,9 +1697,9 @@ function send_profile($arg=''){
print_start('profile'); print_start('profile');
echo "<$H[form]>$H[commonform]".hidden('action', 'profile').hidden('do', 'save')."<h2>$I[profile]</h2><i>$arg</i><table class=\"center-table\">"; echo "<$H[form]>$H[commonform]".hidden('action', 'profile').hidden('do', 'save')."<h2>$I[profile]</h2><i>$arg</i><table class=\"center-table\">";
thr(); thr();
array_multisort(array_map('strtolower', array_keys($P)), SORT_ASC, SORT_STRING, $P); sort_names($P);
$ignored=array(); $ignored=array();
$ignore=get_ignored(); $ignore=get_ignored($U['nickname']);
foreach($ignore as $ign){ foreach($ignore as $ign){
if($ign['by']===$U['nickname']){ if($ign['by']===$U['nickname']){
$ignored[]=$ign['ignored']; $ignored[]=$ign['ignored'];
@ -2114,7 +2113,7 @@ function write_new_session(){
if($U['status']>=3 && !$U['incognito']){ if($U['status']>=3 && !$U['incognito']){
add_system_message(sprintf(get_setting('msgenter'), style_this($U['nickname'], $U['style']))); add_system_message(sprintf(get_setting('msgenter'), style_this($U['nickname'], $U['style'])));
} }
$P[$U['nickname']]=[$U['nickname'], $U['style'], $U['status']]; $P[$U['nickname']]=[$U['nickname'], $U['style'], $U['status'], $U['nickname']];
} }
} }
@ -2350,7 +2349,7 @@ function parse_sessions(){
$stmt=$db->query('SELECT nickname, style, status, incognito FROM ' . PREFIX . 'sessions WHERE entry!=0 AND status>0 ORDER BY status DESC, lastpost DESC;'); $stmt=$db->query('SELECT nickname, style, status, incognito FROM ' . PREFIX . 'sessions WHERE entry!=0 AND status>0 ORDER BY status DESC, lastpost DESC;');
while($temp=$stmt->fetch(PDO::FETCH_ASSOC)){ while($temp=$stmt->fetch(PDO::FETCH_ASSOC)){
if(!$temp['incognito']){ if(!$temp['incognito']){
$P[$temp['nickname']]=[$temp['nickname'], $temp['style'], $temp['status']]; $P[$temp['nickname']]=[$temp['nickname'], $temp['style'], $temp['status'], $temp['nickname']];
} }
if($temp['status']>=5){ if($temp['status']>=5){
++$countmods; ++$countmods;
@ -2382,9 +2381,7 @@ function read_members(){
global $A, $db; global $A, $db;
$result=$db->query('SELECT * FROM ' . PREFIX . 'members;'); $result=$db->query('SELECT * FROM ' . PREFIX . 'members;');
while($temp=$result->fetch(PDO::FETCH_ASSOC)){ while($temp=$result->fetch(PDO::FETCH_ASSOC)){
$A[$temp['nickname']][0]=$temp['nickname']; $A[$temp['nickname']]=[$temp['nickname'], $temp['style'], $temp['status'], $temp['nickname']];
$A[$temp['nickname']][1]=$temp['status'];
$A[$temp['nickname']][2]=$temp['style'];
} }
} }
@ -2758,7 +2755,7 @@ function validate_input(){
$stmt=$db->prepare('SELECT nickname, style, status FROM ' . PREFIX . 'members WHERE eninbox!=0 AND eninbox<=? AND nickname NOT IN (SELECT nickname FROM ' . PREFIX . 'sessions WHERE incognito=0) AND nickname NOT IN (SELECT ign FROM ' . PREFIX . 'ignored WHERE ignby=?) AND nickname NOT IN (SELECT ignby FROM ' . PREFIX . 'ignored WHERE ign=?);'); $stmt=$db->prepare('SELECT nickname, style, status FROM ' . PREFIX . 'members WHERE eninbox!=0 AND eninbox<=? AND nickname NOT IN (SELECT nickname FROM ' . PREFIX . 'sessions WHERE incognito=0) AND nickname NOT IN (SELECT ign FROM ' . PREFIX . 'ignored WHERE ignby=?) AND nickname NOT IN (SELECT ignby FROM ' . PREFIX . 'ignored WHERE ign=?);');
$stmt->execute(array($U['status'], $U['nickname'], $U['nickname'])); $stmt->execute(array($U['status'], $U['nickname'], $U['nickname']));
while($tmp=$stmt->fetch(PDO::FETCH_ASSOC)){ while($tmp=$stmt->fetch(PDO::FETCH_ASSOC)){
$P[$tmp['nickname']]=[$tmp['nickname'], $tmp['style'], $tmp['status']]; $P[$tmp['nickname']]=[$tmp['nickname'], $tmp['style'], $tmp['status'], $tmp['nickname']];
$inboxes[$tmp['nickname']]=true; $inboxes[$tmp['nickname']]=true;
} }
if(isSet($P[$_REQUEST['sendto']])){ if(isSet($P[$_REQUEST['sendto']])){
@ -2821,11 +2818,11 @@ function apply_filter(){
} }
read_members(); read_members();
if(isSet($A[$matched[1]])){ if(isSet($A[$matched[1]])){
return style_this($matched[0], $A[$matched[1]][2]); return style_this($matched[0], $A[$matched[1]][1]);
} }
foreach($A as $user){ foreach($A as $user){
if(strtolower($user[0])===$nick){ if(strtolower($user[0])===$nick){
return style_this($matched[0], $user[2]); return style_this($matched[0], $user[1]);
} }
} }
return "$matched[0]"; return "$matched[0]";
@ -2891,7 +2888,7 @@ function create_hotlinks(){
global $U; global $U;
//Make hotlinks for URLs, redirect through dereferrer script to prevent session leakage //Make hotlinks for URLs, redirect through dereferrer script to prevent session leakage
// 1. all explicit schemes with whatever xxx://yyyyyyy // 1. all explicit schemes with whatever xxx://yyyyyyy
$U['message']=preg_replace('~(\w*://[^\s<>]+)~i', "<<$1>>", $U['message']); $U['message']=preg_replace('~(\w+://[^\s<>]+)~i', "<<$1>>", $U['message']);
// 2. valid URLs without scheme: // 2. valid URLs without scheme:
$U['message']=preg_replace('~((?:[^\s<>]*:[^\s<>]*@)?[a-z0-9\-]+(?:\.[a-z0-9\-]+)+(?::\d*)?/[^\s<>]*)(?![^<>]*>)~i', "<<$1>>", $U['message']); // server/path given $U['message']=preg_replace('~((?:[^\s<>]*:[^\s<>]*@)?[a-z0-9\-]+(?:\.[a-z0-9\-]+)+(?::\d*)?/[^\s<>]*)(?![^<>]*>)~i', "<<$1>>", $U['message']); // server/path given
$U['message']=preg_replace('~((?:[^\s<>]*:[^\s<>]*@)?[a-z0-9\-]+(?:\.[a-z0-9\-]+)+:\d+)(?![^<>]*>)~i', "<<$1>>", $U['message']); // server:port given $U['message']=preg_replace('~((?:[^\s<>]*:[^\s<>]*@)?[a-z0-9\-]+(?:\.[a-z0-9\-]+)+:\d+)(?![^<>]*>)~i', "<<$1>>", $U['message']); // server:port given
@ -2938,7 +2935,7 @@ function add_system_message($mes){
'poster' =>'', 'poster' =>'',
'recipient' =>'', 'recipient' =>'',
'text' =>"<span class=\"sysmsg\">$mes</span>", 'text' =>"<span class=\"sysmsg\">$mes</span>",
'delstatus' =>9 'delstatus' =>4
); );
write_message($sysmessage); write_message($sysmessage);
} }
@ -2974,12 +2971,12 @@ function clean_room(){
add_system_message(sprintf($msg, get_setting('chatname'))); add_system_message(sprintf($msg, get_setting('chatname')));
} }
function clean_selected(){ function clean_selected($status){
global $db; global $db;
if(isSet($_REQUEST['mid'])){ if(isSet($_REQUEST['mid'])){
$stmt=$db->prepare('DELETE FROM ' . PREFIX . 'messages WHERE id=?;'); $stmt=$db->prepare('DELETE FROM ' . PREFIX . 'messages WHERE id=? AND (delstatus=9 OR delstatus<?);');
foreach($_REQUEST['mid'] as $mid){ foreach($_REQUEST['mid'] as $mid){
$stmt->execute(array($mid)); $stmt->execute(array($mid, $status));
} }
} }
} }
@ -3057,9 +3054,9 @@ function print_messages($delstatus=''){
$db->exec('DELETE FROM ' . PREFIX . 'messages WHERE id IN (SELECT * FROM (SELECT id FROM ' . PREFIX . "messages WHERE postdate<$expire) AS t);"); $db->exec('DELETE FROM ' . PREFIX . 'messages WHERE id IN (SELECT * FROM (SELECT id FROM ' . PREFIX . "messages WHERE postdate<$expire) AS t);");
if(!empty($delstatus)){ if(!empty($delstatus)){
$stmt=$db->prepare('SELECT postdate, id, text FROM ' . PREFIX . 'messages WHERE '. $stmt=$db->prepare('SELECT postdate, id, text FROM ' . PREFIX . 'messages WHERE '.
'id IN (SELECT * FROM (SELECT id FROM ' . PREFIX . "messages WHERE poststatus=1 ORDER BY id DESC LIMIT $messagelimit) AS t) ". '(id IN (SELECT * FROM (SELECT id FROM ' . PREFIX . "messages WHERE poststatus=1 ORDER BY id DESC LIMIT $messagelimit) AS t) ".
'OR (poststatus>1 AND (poststatus<? OR poster=? OR recipient=?) ) ORDER BY id DESC;'); 'OR (poststatus>1 AND (poststatus<? OR poster=? OR recipient=?) ) ) AND (poster=? OR recipient=? OR delstatus<?) ORDER BY id DESC;');
$stmt->execute(array($U['status'], $U['nickname'], $U['nickname'])); $stmt->execute(array($U['status'], $U['nickname'], $U['nickname'], $U['nickname'], $U['nickname'], $delstatus));
while($message=$stmt->fetch(PDO::FETCH_ASSOC)){ while($message=$stmt->fetch(PDO::FETCH_ASSOC)){
prepare_message_print($message, $injectRedirect, $redirect, $removeEmbed); prepare_message_print($message, $injectRedirect, $redirect, $removeEmbed);
echo "<div class=\"msg\"><input type=\"checkbox\" name=\"mid[]\" id=\"$message[id]\" value=\"$message[id]\"><label for=\"$message[id]\">"; echo "<div class=\"msg\"><input type=\"checkbox\" name=\"mid[]\" id=\"$message[id]\" value=\"$message[id]\"><label for=\"$message[id]\">";
@ -3114,6 +3111,14 @@ function prepare_message_print(&$message, $injectRedirect, $redirect, $removeEmb
// this and that // this and that
function sort_names(&$names){
$keys=[];
foreach($names as $v){
$keys[]=$v[3];
}
array_multisort(array_map('strtolower', $keys), SORT_ASC, SORT_STRING, $names);
}
function send_headers(){ function send_headers(){
header('Content-Type: text/html; charset=UTF-8'); header('Content-Type: text/html; charset=UTF-8');
header('Pragma: no-cache'); header('Pragma: no-cache');
@ -3187,12 +3192,13 @@ function save_setup(){
} }
} }
function get_ignored(){ function get_ignored($name){
global $db; global $db;
$ignored=array(); $ignored=array();
$result=$db->query('SELECT ign, ignby FROM ' . PREFIX . 'ignored;'); $stmt=$db->prepare('SELECT ign, ignby FROM ' . PREFIX . 'ignored WHERE ign=? OR ignby=?;');
while($tmp=$result->fetch(PDO::FETCH_ASSOC)){ $stmt->execute([$name, $name]);
$ignored[]=array('ignored'=>$tmp['ign'], 'by'=>$tmp['ignby']); while($tmp=$stmt->fetch(PDO::FETCH_ASSOC)){
$ignored[]=['ignored'=>$tmp['ign'], 'by'=>$tmp['ignby']];
} }
return $ignored; return $ignored;
} }
@ -3742,7 +3748,7 @@ function load_lang(){
function load_config(){ function load_config(){
date_default_timezone_set('UTC'); date_default_timezone_set('UTC');
define('VERSION', '1.20.1'); // Script version define('VERSION', '1.20.5'); // Script version
define('DBVERSION', 23); // Database version define('DBVERSION', 23); // Database version
define('MSGENCRYPTED', false); // Store messages encrypted in the database to prevent other database users from reading them - true/false - visit the setup page after editing! define('MSGENCRYPTED', false); // Store messages encrypted in the database to prevent other database users from reading them - true/false - visit the setup page after editing!
define('ENCRYPTKEY', 'MY_KEY'); // Encryption key for messages define('ENCRYPTKEY', 'MY_KEY'); // Encryption key for messages