Move CAPTCHA code around a bit

This commit is contained in:
Floorb 2022-08-27 02:48:10 -04:00
parent 86afab0458
commit 624d9d63d8
7 changed files with 60 additions and 146 deletions

View file

@ -1,107 +1,11 @@
<?php
use JetBrains\PhpStorm\ArrayShape;
#[ArrayShape(['code' => "mixed|string", 'image_src' => "string"])]
function captcha($color, $mul, $allowed) : array {
$bg_path = __DIR__ . '/../public/assets/img/captcha/';
$font_path = __DIR__ . '/../public/assets/fonts/';
$fonts = [
$font_path . 'LMS Pretty Pony.ttf',
$font_path . 'PonyvilleMedium0.4.ttf'
];
$backgrounds = [
$bg_path . 'text3.png',
$bg_path . 'text2.png',
$bg_path . 'text1.png'
];
$captcha_config = [
'min_length' => 5,
'max_length' => 5,
'backgrounds' => $backgrounds,
'fonts' => $fonts,
'characters' => $allowed,
'min_font_size' => 28,
'max_font_size' => 28,
'color' => $color,
'angle_min' => 0,
'angle_max' => 10,
'shadow' => true,
'shadow_color' => '#fff',
'shadow_offset_x' => -1,
'shadow_offset_y' => 1
];
// Overwrite defaults with custom config values
if (!empty($config) && is_array($config)) {
foreach ($config as $key => $value) {
$captcha_config[$key] = $value;
}
}
// Restrict certain values
if ($captcha_config['min_length'] < 1) {
$captcha_config['min_length'] = 1;
}
if ($captcha_config['angle_min'] < 0) {
$captcha_config['angle_min'] = 0;
}
if ($captcha_config['angle_max'] > 10) {
$captcha_config['angle_max'] = 10;
}
if ($captcha_config['angle_max'] < $captcha_config['angle_min']) {
$captcha_config['angle_max'] = $captcha_config['angle_min'];
}
if ($captcha_config['min_font_size'] < 10) {
$captcha_config['min_font_size'] = 10;
}
if ($captcha_config['max_font_size'] < $captcha_config['min_font_size']) {
$captcha_config['max_font_size'] = $captcha_config['min_font_size'];
}
$captcha_config['code'] = '';
return $captcha_config;
}
if (!function_exists('hex2rgb')) {
function hex2rgb($hex_str) : array|null {
$hex_str = preg_replace("/[^0-9A-Fa-f]/", '', $hex_str); // Gets a proper hex string
if (strlen($hex_str) == 6) {
$color_val = hexdec($hex_str);
return [
'r' => 0xFF & ($color_val >> 0x10),
'g' => 0xFF & ($color_val >> 0x8),
'b' => 0xFF & $color_val
];
} elseif (strlen($hex_str) == 3) {
return [
'r' => hexdec(str_repeat(substr($hex_str, 0, 1), 2)),
'g' => hexdec(str_repeat(substr($hex_str, 1, 1), 2)),
'b' => hexdec(str_repeat(substr($hex_str, 2, 1), 2))
];
}
return null;
}
}
function setupCaptcha() : string {
global $captcha_config;
global $redis;
$allowed = "ABCDEFGHIJKLMNOPQRSTUVYXYZabcdefghijklmnopqrstuvwxyz0123456789";
$code = '';
for ($i = 0; $i < 5; $i++) {
$code .= substr($captcha_config['allowed'], rand() % (strlen($captcha_config['allowed'])), 1);
$code .= substr($allowed, rand() % (strlen($allowed)), 1);
}
$token = pp_random_password();
@ -114,12 +18,12 @@ function setupCaptcha() : string {
function checkCaptcha(string $token, string $answer) : bool {
global $redis;
$redis_answer = $redis->get('captcha/' . $token);
$redis_answer = $redis->get('captcha/' . md5($token));
if (!$redis_answer) {
return false;
}
$redis->del('captcha/' . $token);
return $redis_answer === $answer;
return strtolower($redis_answer) === strtolower($answer);
}

View file

@ -260,8 +260,7 @@ if ($site_permissions) {
}
// CAPTCHA configuration
$captcha_config = $site_info['captcha'];
$captcha_enabled = (bool) $captcha_config['enabled'];
$captcha_enabled = (bool) $site_info['captcha']['enabled'];
$total_pastes = Paste::count();
$total_page_views = PageView::select('tpage')->orderBy('id', 'desc')->first()->tpage;

View file

@ -5,17 +5,41 @@ require_once(__DIR__ . '/../includes/common.php');
require_once(__DIR__ . '/../includes/captcha.php');
if (empty($_GET['t'])) {
die('No token provided.');
die('Invalid token provided.');
}
$captcha_token = 'captcha/' . md5($_GET['t']);
$captcha_code = $redis->get($captcha_token);
if (!$captcha_code) {
die('No token provided.');
die('Invalid token provided.');
}
$captcha_config = captcha($captcha_config['colour'], $captcha_config['multiple'], $captcha_config['allowed']);
$bg_path = __DIR__ . '/assets/img/captcha/';
$font_path = __DIR__ . '/assets/fonts/';
$captcha_config = [
'min_length' => 5,
'max_length' => 5,
'backgrounds' => [
$bg_path . 'text3.png',
$bg_path . 'text2.png',
$bg_path . 'text1.png'
],
'fonts' => [
$font_path . 'LMS Pretty Pony.ttf',
$font_path . 'PonyvilleMedium0.4.ttf'
],
'min_font_size' => 28,
'max_font_size' => 28,
'color' => ['r' => 0, 'g' => 0, 'b' => 0],
'angle_min' => 0,
'angle_max' => 10,
'shadow' => true,
'shadow_color' => ['r' => 0xFF, 'g' => 0xFF, 'b' => 0xFF],
'shadow_offset_x' => -1,
'shadow_offset_y' => 1
];
// Pick random background, get info, and start captcha
$background = $captcha_config['backgrounds'][rand(0, count($captcha_config['backgrounds']) - 1)];
@ -23,7 +47,7 @@ list($bg_width, $bg_height, $bg_type, $bg_attr) = getimagesize($background);
$captcha = imagecreatefrompng($background);
$color = hex2rgb($captcha_config['color']);
$color = $captcha_config['color'];
$color = imagecolorallocate($captcha, $color['r'], $color['g'], $color['b']);
// Determine text angle
@ -51,13 +75,6 @@ $text_pos_y_min = $box_height;
$text_pos_y_max = (int) ($bg_height - ($box_height / 2));
$text_pos_y = rand($text_pos_y_min, $text_pos_y_max);
// Draw shadow
if ($captcha_config['shadow']) {
$shadow_color = hex2rgb($captcha_config['shadow_color']);
$shadow_color = imagecolorallocate($captcha, $shadow_color['r'], $shadow_color['g'], $shadow_color['b']);
imagettftext($captcha, $font_size, $angle, $text_pos_x + $captcha_config['shadow_offset_x'], $text_pos_y + $captcha_config['shadow_offset_y'], $shadow_color, $font, $captcha_code);
}
// Draw text
imagettftext($captcha, $font_size, $angle, $text_pos_x, $text_pos_y, $color, $font, $captcha_code);

View file

@ -5,13 +5,12 @@ require_once(__DIR__ . '/../includes/common.php');
use PonePaste\Models\Paste;
$popular_pastes = Paste::getMostViewed();//->map('transformPasteRow');
$monthly_popular_pastes = Paste::getMonthPopular();//->map('transformPasteRow');
$recent_pastes = Paste::getRecent();//->map('transformPasteRow');
$updated_pastes = Paste::getRecentlyUpdated();//->map('transformPasteRow');
$random_pastes = Paste::getRandom();//->map('transformPasteRow');
$popular_pastes = Paste::getMostViewed();
$monthly_popular_pastes = Paste::getMonthPopular();
$recent_pastes = Paste::getRecent();
$updated_pastes = Paste::getRecentlyUpdated();
$random_pastes = Paste::getRandom();
// Theme
$page_template = 'discover';
$page_title = 'Discover';

View file

@ -10,12 +10,12 @@ use PonePaste\Models\User;
function verifyCaptcha() : string|bool {
global $captcha_config;
global $captcha_enabled;
global $current_user;
if ($captcha_config['enabled'] && !$current_user) {
if ($captcha_enabled && !$current_user) {
if (empty($_POST['captcha_answer']) ||
!checkCaptcha($_POST['captcha_token'], strtolower(trim($_POST['captcha_answer'])))) {
!checkCaptcha($_POST['captcha_token'], trim($_POST['captcha_answer']))) {
return 'Wrong CAPTCHA.';
}
}
@ -64,11 +64,6 @@ function validatePasteFields() : string|null {
$priority = 0.9;
$changefreq = 'weekly';
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
if ($captcha_config['enabled']) {
}
}
updatePageViews();
// POST Handler

View file

@ -62,7 +62,6 @@ if (isset($_POST['forgot'])) {
}
if ($user->banned) {
// User is banned
$error = 'You are banned.';
} else {
// Login successful
@ -101,34 +100,35 @@ if (isset($_POST['forgot'])) {
$username = trim($_POST['username']);
$password = pp_password_hash($_POST['password']);
if (empty($_POST['password']) || empty($_POST['username'])) {
if ($captcha_config['enabled'] && !checkCaptcha($_POST['captcha_token'], trim($_POST['captcha_answer']))) {
$error = 'Incorrect CAPTCHA.';
} elseif (empty($_POST['password']) || empty($_POST['username'])) {
$error = 'All fields must be filled out.';
} elseif (strlen($username) > 25) {
$error = 'Username too long.';
} elseif (!preg_match('/^[A-Za-z0-9._\\-]+$/', $username)) {
$error = 'Username is invalid - please use A-Za-z0-9, periods, hyphens, and underscores only.';
} elseif (User::where('username', $username)->first()) {
$error = 'That username has already been taken.';
} else {
if (User::where('username', $username)->first()) {
$error = 'That username has already been taken.';
} else {
/* this is displayed to the user in the template, hence the variable rather than inlining */
$recovery_code = pp_random_token();
/* this is displayed to the user in the template, hence the variable rather than inlining */
$recovery_code = pp_random_token();
$user = new User([
'username' => $username,
'password' => $password,
'recovery_code_hash' => pp_password_hash($recovery_code),
'date' => $date,
'ip' => $ip
]);
$user->save();
$user = new User([
'username' => $username,
'password' => $password,
'recovery_code_hash' => pp_password_hash($recovery_code),
'date' => $date,
'ip' => $ip
]);
$user->save();
$success = 'Your account was successfully registered.';
}
$success = 'Your account was successfully registered.';
}
}
// Theme
$page_template = 'login';
$page_title = 'Login / Register';
require_once(__DIR__ . '/../theme/' . $default_theme . '/common.php');

View file

@ -293,7 +293,7 @@
</div>
<div class="column is-4">
<!-- CAPTCHA -->
<?php if ($captcha_config['enabled'] && $current_user === null): ?>
<?php if ($captcha_enabled && $current_user === null): ?>
<div class="is-one-quarter">
<div class="captcha_container">
<img src="/captcha?t=<?= setupCaptcha() ?>" alt="CAPTCHA Image" />