*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
/*
* status codes
* 0 - Kicked/Banned
* 1 - Guest
* 2 - Applicant
* 3 - Member
* 4 - System message
* 5 - Moderator
* 6 - Super-Moderator
* 7 - Admin
* 8 - Super-Admin
* 9 - Private messages
*/
if (!extension_loaded('gettext')) {
prepare_stylesheets('fatal_error');
send_headers();
echo '
'.meta_html();
echo '';
if ($difficulty===4) {
echo _('Type the characters connected by dotted lines:');
} elseif ($difficulty===7 || $difficulty===8 || $difficulty===10) {
echo _('Type the five largest characters:');
} else {
echo _('Type the characters in the image:');
}
if($difficulty===1 || $difficulty===2){
$fontwidth = imagefontwidth(5);
$fontheight = imagefontheight(5);
$CAPTCHAWIDTH = $fontwidth * 5 * 3;
$CAPTCHAHEIGHT = $fontheight * 3;
$im=imagecreatetruecolor($CAPTCHAWIDTH, $CAPTCHAHEIGHT);
$bg=imagecolorallocate($im, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
imagefill($im, 0, 0, $bg);
$margins = 0;
if($difficulty===2){
for($i=0; $i<5; $i++){
for($j=0; $j<2; $j++){
imagefilledrectangle($im, mt_rand($i * $CAPTCHAWIDTH / 5, ($i + 1) * $CAPTCHAWIDTH / 5), mt_rand(0, $CAPTCHAHEIGHT), mt_rand(($i + 0.5) * $CAPTCHAWIDTH / 5, ($i + 1.5) * $CAPTCHAWIDTH / 5), mt_rand(0, $CAPTCHAHEIGHT), imagecolorallocate($im, mt_rand(128, 255), mt_rand(128, 255), mt_rand(128, 255)));
}
}
}
imagefilter($im, IMG_FILTER_SMOOTH, 5);
$xoffset=0;
for($i=0; $i<5; $i++){
$xoffset+= mt_rand(0, ($CAPTCHAWIDTH - (5 * $fontwidth)) - $xoffset); // randomly shift characters to the right
imagechar($im, 5, $xoffset + $i * $fontwidth, mt_rand(0, $CAPTCHAHEIGHT - $fontheight), $code[$i], imagecolorallocate($im, mt_rand(224, 255), mt_rand(224, 255), mt_rand(224, 255)));
if($difficulty===2){
imagelayereffect($im,IMG_EFFECT_OVERLAY);
}
}
}elseif($difficulty===3){ // hard
$CAPTCHAWIDTH=120;
$CAPTCHAHEIGHT=80;
$im=imagecreatetruecolor(55, 24);
$bg=imagecolorallocatealpha($im, 0, 0, 0, 127);
$fg=imagecolorallocate($im, 255, 255, 255);
$cc=imagecolorallocate($im, 200, 200, 200);
$cb=imagecolorallocatealpha($im, 0, 0, 0, 127);
imagefill($im, 0, 0, $bg);
$line=imagecolorallocate($im, 255, 255, 255);
$deg=(mt_rand(0,1)*2-1)*mt_rand(10, 20);
$background=imagecreatetruecolor(120, 80);
imagefill($background, 0, 0, $cb);
for ($i=0; $i<20; $i++) {
$char=imagecreatetruecolor(12, 16);
imagestring($char, 5, 2, 2, $captchachars[mt_rand(0, $length)], $cc);
$char = imagerotate($char, (mt_rand(0,1)*2-1)*mt_rand(10, 20), $cb);
$char = imagescale($char, 24, 32);
imagefilter($char, IMG_FILTER_SMOOTH, 0.6);
imagecopy($background, $char, rand(0, 100), rand(0, 60), 0, 0, 24, 32);
}
imagestring($im, 5, 5, 5, $code, $fg);
$im = imagescale($im, 110, 48);
imagefilter($im, IMG_FILTER_SMOOTH, 0.5);
imagefilter($im, IMG_FILTER_GAUSSIAN_BLUR);
$im = imagerotate($im, $deg, $bg);
$im = imagecrop($im, array('x'=>0, 'y'=>0, 'width'=>120, 'height'=>80));
imagecopy($background, $im, 0, 0, 0, 0, 110, 80);
imagedestroy($im);
$im = $background;
for($i=0;$i<1000;++$i){
$c = mt_rand(100,230);
$dots=imagecolorallocate($im, $c, $c, $c);
imagesetpixel($im, mt_rand(0, 120), mt_rand(0, 80), $dots);
}
imagedestroy($char);
}elseif($difficulty===4){ // extreme
$CAPTCHAWIDTH = 300;
$CAPTCHAHEIGHT = 300;
$im=imagecreatetruecolor($CAPTCHAWIDTH, $CAPTCHAHEIGHT);
$bg=imagecolorallocate($im, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
$fg=imagecolorallocate($im, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
imagefill($im, 0, 0, $bg);
imagelayereffect($im,IMG_EFFECT_NORMAL);
$fontwidth = imagefontwidth(5); // 9 pixels wide
$fontheight = imagefontheight(5); // 10 pixels high
for($i=0; $i<20; ++$i){
$leftx = mt_rand(0, $CAPTCHAWIDTH - $fontwidth);
$topy = mt_rand(0, $CAPTCHAHEIGHT - $fontheight);
for($j=0; $j<($numpoints * 2); $j+=2){
$points[$j]=$leftx + mt_rand(0, $fontwidth);
$points[$j+1]=$topy + mt_rand(0, $fontheight);
}
$numpoints=(int) mt_rand(3,6);
for($k=0; $k<($numpoints * 2); $k+=2){
$points[$k]=mt_rand(0, $CAPTCHAWIDTH);
$points[$k+1]=mt_rand(0, $CAPTCHAHEIGHT);
}
imagefilledpolygon( $im, $points, $numpoints, imagecolorallocate($im, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255)));
}
$chars=[];
$x = $y = 0;
imagelayereffect($im,IMG_EFFECT_NORMAL);
for($i=0; $i<20; ++$i){
$found=false;
while(!$found){
$x=mt_rand(0, $CAPTCHAWIDTH - $fontwidth);
$y=mt_rand(0, $CAPTCHAHEIGHT - $fontheight);
$found=true;
foreach($chars as $char){
if($char['x']>=$x && ($char['x']-$x)<25){
$found=false;
}elseif($char['x']<$x && ($x-$char['x'])<25){
$found=false;
}
if(!$found){
if($char['y']>=$y && ($char['y']-$y)<25){
break;
}elseif($char['y']<$y && ($y-$char['y'])<25){
break;
}else{
$found=true;
}
}
}
}
$chars[]=['x', 'y'];
$chars[$i]['x']=$x;
$chars[$i]['y']=$y;
imagelayereffect($im, IMG_EFFECT_OVERLAY);
$fg = imagecolorallocate($im, 255, 255, 255);
if($i<5){ // characters in solution
imagechar($im, 5, $chars[$i]['x'], $chars[$i]['y'], $code[$i], $fg);
}else{ // spurious characters
imagechar($im, 5, $chars[$i]['x'], $chars[$i]['y'], $captchachars[mt_rand(0, $length)], $fg);
}
}
imagelayereffect($im, IMG_EFFECT_OVERLAY);
for($i=5; $i<19; ++$i){ // solid lines between spurious characters
imageline($im, $chars[$i]['x'] + $fontwidth / 2, $chars[$i]['y'] + $fontheight / 2, $chars[$i + 1]['x'] + $fontwidth / 2, $chars[$i + 1]['y'] + $fontheight / 2, imagecolorallocate($im, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255)));
}
// dashed lines between characters in solution
imagelayereffect($im,IMG_EFFECT_OVERLAY);
for($i=0; $i<4; ++$i){
$dottedlinecolor = imagecolorallocate($im, 255, 255, 255);
$dottedlinestyle = array($dottedlinecolor, $dottedlinecolor, $dottedlinecolor, IMG_COLOR_TRANSPARENT, IMG_COLOR_TRANSPARENT, IMG_COLOR_TRANSPARENT);
imagesetstyle($im, $dottedlinestyle);
$follow=imagecolorallocate($im, mt_rand(10, 255), mt_rand(10, 255), mt_rand(10, 255));
imageline($im, $chars[$i]['x']+ $fontwidth / 2, $chars[$i]['y']+ $fontheight / 2, $chars[$i+1]['x']+4, $chars[$i+1]['y']+8, IMG_COLOR_STYLED);
}
} elseif ($difficulty===5 || $difficulty===6 || $difficulty===7 || $difficulty===8 || $difficulty===9 || $difficulty===10){ // TrueType
$CAPTCHAWIDTH = 620;
$CAPTCHAHEIGHT = 177;
$im = imagecreatetruecolor($CAPTCHAWIDTH, $CAPTCHAHEIGHT);
if ($difficulty===5 || $difficulty===6) {
imagelayereffect($im,IMG_EFFECT_MULTIPLY);
} else {
imagelayereffect($im,IMG_EFFECT_OVERLAY);
}
if ($difficulty===8){
imagefill($im, 0, 0, imagecolorallocate($im, 0, 0, 0));
} else {
imagefill($im, 0, 0, imagecolorallocate($im, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255)));
}
if ($difficulty===7 || $difficulty===8 || $difficulty===10){
for($i=0; $i<50; ++$i){ // small spurious characters
if ($difficulty===7 || $difficulty===10) {
$color = imagecolorallocate($im, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
} else {
$lightness = mt_rand(127, 255);
$color = imagecolorallocate($im, $lightness, $lightness, $lightness);
}
$charsize = mt_rand($CAPTCHAHEIGHT * 0.18 , $CAPTCHAHEIGHT * 0.25);
// $color = imagecolorallocate($im, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
imagefttext($im, $charsize, mt_rand(0, 90) - 45, mt_rand(0, $CAPTCHAWIDTH), mt_rand(0, $CAPTCHAHEIGHT), $color, get_setting('captchattfont'), $captchachars[mt_rand(0, strlen($captchachars)-1)]);
}
}
// characters in solution
for($i=0; $i<5; ++$i){
if ($difficulty===8) {
$lightness = mt_rand(127, 255);
$color = imagecolorallocate($im, $lightness, $lightness, $lightness);
} else {
$color = imagecolorallocate($im, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
}
$charsize = mt_rand($CAPTCHAHEIGHT * 0.5 , $CAPTCHAHEIGHT * 0.7);
imagefttext($im, $charsize, mt_rand(0, 90) - 45, ($CAPTCHAWIDTH / 8 * ($i * 1.5 + 0.5)), $CAPTCHAHEIGHT - $charsize / 2, $color, get_setting('captchattfont'), $code[$i-5]);
}
if ($difficulty===7 || $difficulty===8 || $difficulty===10){
for($i=0; $i<50; ++$i){ // more small spurious characters
if ($difficulty===7) {
$color = imagecolorallocate($im, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
} else { // monochrome
$lightness = mt_rand(127, 255);
$color = imagecolorallocate($im, $lightness, $lightness, $lightness);
}
$charsize = mt_rand($CAPTCHAHEIGHT * 0.18 , $CAPTCHAHEIGHT * 0.25);
imagefttext($im, $charsize, mt_rand(0, 90) - 45, mt_rand(0, $CAPTCHAWIDTH), mt_rand(0, $CAPTCHAHEIGHT), $color, get_setting('captchattfont'), $captchachars[mt_rand(0, strlen($captchachars)-1)]);
}
}
if ($difficulty===9 || $difficulty===10){
imagelayereffect($im,IMG_EFFECT_MULTIPLY);
$interval=mt_rand(3, $CAPTCHAWIDTH/32);
$x=0;
while ($x<$CAPTCHAWIDTH) {
$interval=mt_rand(2, $CAPTCHAWIDTH/32);
$line=imagecolorallocate($im, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
imagefilledrectangle($im, $x, 0, $x + $interval, $CAPTCHAHEIGHT, imagecolorallocate($im, mt_rand(128, 255), mt_rand(128, 255), mt_rand(128, 255)));
$x+=$interval;
}
$y=0;
while ($y<$CAPTCHAHEIGHT) {
$interval=mt_rand(3, $CAPTCHAHEIGHT/16);
imagefilledrectangle($im, 0, $y, $CAPTCHAWIDTH, $y + $interval, imagecolorallocate($im, mt_rand(128, 255), mt_rand(128, 255), mt_rand(128, 255)));
$y+=$interval;
}
}
if ($difficulty===5 || $difficulty===6){
if ($difficulty===6) {
$iterations = 10; // hollow
} else {
$iterations = 1; // solid
}
for($i=0; $i<$iterations; ++$i){ // apply layers of hollow or solid shapes
for($j=0; $j<5; ++$j){
$width = mt_rand(1, $CAPTCHAWIDTH / 5 - 1);
$height = mt_rand(1, $CAPTCHAHEIGHT - 1);
$center_x = $j * $CAPTCHAWIDTH / 5 + mt_rand(0, $CAPTCHAWIDTH / 5 - $width / 2);
$center_y = $height / 2 + mt_rand(0, $CAPTCHAHEIGHT - $height);
if ($difficulty===6){
imagelayereffect($im,IMG_EFFECT_OVERLAY);
imageellipse( $im, $center_x, $center_y, $width, $height, imagecolorallocate($im, mt_rand(127, 255), mt_rand(127, 255), mt_rand(127, 255)));
imagelayereffect($im,IMG_EFFECT_MULTIPLY);
imageellipse( $im, $center_x, $center_y, $width, $height, imagecolorallocate($im, mt_rand(127, 255), mt_rand(127, 255), mt_rand(127, 255)));
} else {
imagefilledellipse( $im, $center_x, $center_y, $width, $height, imagecolorallocate($im, mt_rand(127, 255), mt_rand(127, 255), mt_rand(127, 255)));
}
}
for($j=0; $j<5; ++$j){
$width = mt_rand(1, $CAPTCHAWIDTH / 5 - 1);
$height = mt_rand(1, $CAPTCHAHEIGHT - 1);
$center_x = $j * $CAPTCHAWIDTH / 5 + $width / 2 + mt_rand(0, $CAPTCHAWIDTH / 5 - $width / 2);
$center_y = $height / 2 + mt_rand(0, $CAPTCHAHEIGHT - $height);
if ($difficulty===6){
// https://www.php.net/manual/en/function.imagearc.php
imagelayereffect($im,IMG_EFFECT_OVERLAY);
imagearc($im, $center_x, $center_y, $width, $height, mt_rand(0, 360), mt_rand(0, 360), imagecolorallocate($im, mt_rand(127, 255), mt_rand(127, 255), mt_rand(127, 255)));
imagelayereffect($im,IMG_EFFECT_MULTIPLY);
imagearc($im, $center_x, $center_y, $width, $height, mt_rand(0, 360), mt_rand(0, 360), imagecolorallocate($im, mt_rand(127, 255), mt_rand(127, 255), mt_rand(127, 255)));
} else {
imagefilledarc($im, $center_x, $center_y, $width, $height, mt_rand(0, 360), mt_rand(0, 360), imagecolorallocate($im, mt_rand(127, 255), mt_rand(127, 255), mt_rand(127, 255)), IMG_ARC_PIE);
}
}
for($j=0; $j<5; ++$j){
$numpoints=(int) mt_rand(3,6);
for($k=0; $k<($numpoints * 2); $k+=2){
$points[$k] = mt_rand($j * $CAPTCHAWIDTH / 5, ($j + 1) * $CAPTCHAWIDTH / 5);
$points[$k+1] = mt_rand(0, $CAPTCHAHEIGHT);
}
if ($difficulty===6){
imagelayereffect($im,IMG_EFFECT_OVERLAY);
imagepolygon( $im, $points, $numpoints, imagecolorallocate($im, mt_rand(127, 255), mt_rand(127, 255), mt_rand(127, 255)));
imagelayereffect($im,IMG_EFFECT_MULTIPLY);
imagepolygon( $im, $points, $numpoints, imagecolorallocate($im, mt_rand(127, 255), mt_rand(127, 255), mt_rand(127, 255)));
} else {
imagefilledpolygon( $im, $points, $numpoints, imagecolorallocate($im, mt_rand(127, 255), mt_rand(127, 255), mt_rand(127, 255)));
}
}
for($j=0; $j<5; $j++){
if ($difficulty===6){
imagelayereffect($im,IMG_EFFECT_OVERLAY);
imagerectangle($im, mt_rand($j * $CAPTCHAWIDTH / 5, ($j + 1) * $CAPTCHAWIDTH / 5), mt_rand(0, $CAPTCHAHEIGHT), mt_rand($j * $CAPTCHAWIDTH / 5, ($j + 1) * $CAPTCHAWIDTH / 5), mt_rand(0, $CAPTCHAHEIGHT), imagecolorallocate($im, mt_rand(127, 255), mt_rand(127, 255), mt_rand(127, 255)));
imagelayereffect($im,IMG_EFFECT_MULTIPLY);
imagerectangle($im, mt_rand($j * $CAPTCHAWIDTH / 5, ($j + 1) * $CAPTCHAWIDTH / 5), mt_rand(0, $CAPTCHAHEIGHT), mt_rand($j * $CAPTCHAWIDTH / 5, ($j + 1) * $CAPTCHAWIDTH / 5), mt_rand(0, $CAPTCHAHEIGHT), imagecolorallocate($im, mt_rand(127, 255), mt_rand(127, 255), mt_rand(127, 255)));
} else {
imagefilledrectangle($im, mt_rand($j * $CAPTCHAWIDTH / 5, ($j + 1) * $CAPTCHAWIDTH / 5), mt_rand(0, $CAPTCHAHEIGHT), mt_rand($j * $CAPTCHAWIDTH / 5, ($j + 1) * $CAPTCHAWIDTH / 5), mt_rand(0, $CAPTCHAHEIGHT), imagecolorallocate($im, mt_rand(127, 255), mt_rand(127, 255), mt_rand(127, 255)));
}
}
}
}
}
echo ' ';
echo ' |
'._('Successfully reset password for username %s. Please remove the password reset define from the script again.').'
', $user['nickname']);
}
} else {
echo ''._("Please modify the script and put the following at the bottom of it (change the password). Then refresh this page: define('RESET_SUPERADMIN_PASSWORD', 'changeme');").'
';
}
echo '';
$hiddendo=hidden('do', 'public');
}
if(isset($_POST['text'])){
if(MSGENCRYPTED){
try {
$_POST['text']=base64_encode(sodium_crypto_aead_aes256gcm_encrypt($_POST['text'], '', AES_IV, ENCRYPTKEY));
} catch (SodiumException $e){
send_error($e->getMessage());
}
}
$time=time();
$stmt=$db->prepare('INSERT INTO ' . PREFIX . 'notes (type, lastedited, editedby, text) VALUES (?, ?, ?, ?);');
$stmt->execute([$type, $time, $U['nickname'], $_POST['text']]);
echo ''._('Notes saved!').' ';
}
$dateformat=get_setting('dateformat');
if(($type!==2) && ($type !==3)){
$stmt=$db->prepare('SELECT COUNT(*) FROM ' . PREFIX . 'notes WHERE type=?;');
$stmt->execute([$type]);
}else{
$stmt=$db->prepare('SELECT COUNT(*) FROM ' . PREFIX . 'notes WHERE type=? AND editedby=?;');
$stmt->execute([$type, $U['nickname']]);
}
$num=$stmt->fetch(PDO::FETCH_NUM);
if(!empty($_POST['revision'])){
$revision=intval($_POST['revision']);
}else{
$revision=0;
}
if(($type!==2) && ($type !==3)){
$stmt=$db->prepare('SELECT * FROM ' . PREFIX . "notes WHERE type=? ORDER BY id DESC LIMIT 1 OFFSET $revision;");
$stmt->execute([$type]);
}else{
$stmt=$db->prepare('SELECT * FROM ' . PREFIX . "notes WHERE type=? AND editedby=? ORDER BY id DESC LIMIT 1 OFFSET $revision;");
$stmt->execute([$type, $U['nickname']]);
}
if($note=$stmt->fetch(PDO::FETCH_ASSOC)){
printf(_('Last edited by %1$s at %2$s'), htmlspecialchars($note['editedby']), date($dateformat, $note['lastedited']));
}else{
$note['text']='';
}
if(MSGENCRYPTED){
try {
$note['text']=sodium_crypto_aead_aes256gcm_decrypt(base64_decode($note['text']), null, AES_IV, ENCRYPTKEY);
} catch (SodiumException $e){
send_error($e->getMessage());
}
}
echo "
".form('notes');
echo "$hiddendo';
if($wait){
printf(_('Welcome %1$s, your login has been delayed, you can access the chat in %2$d seconds.'), style_this(htmlspecialchars($U['nickname']), $U['style']), $timeleft);
}else{
printf(_('Welcome %1$s, your login has been delayed, you can access the chat as soon, as a moderator lets you in.'), style_this(htmlspecialchars($U['nickname']), $U['style']));
}
echo '
';
printf(_("If this page doesn't refresh every %d seconds, use the button below to reload it manually!"), $refresh);
echo '
'.form('view').submit(_('Back to the chat.'), 'class="backbutton"').''.credit().'
';
print_end();
}
function view_publicnotes(): void
{
global $db;
$dateformat = get_setting('dateformat');
print_start('publicnotes');
echo '';
$query = $db->query('SELECT lastedited, editedby, text FROM ' . PREFIX . 'notes INNER JOIN (SELECT MAX(id) AS latest FROM ' . PREFIX . 'notes WHERE type=3 GROUP BY editedby) AS t ON t.latest = id;');
while($result = $query->fetch(PDO::FETCH_OBJ)){
if (!empty($result->text)) {
if(MSGENCRYPTED){
try {
$result->text = sodium_crypto_aead_aes256gcm_decrypt(base64_decode($result->text), null, AES_IV, ENCRYPTKEY);
} catch (SodiumException $e){
send_error($e->getMessage());
}
}
echo '