diff --git a/.env.example b/.env.example index 670e5402..cbd1aa08 100644 --- a/.env.example +++ b/.env.example @@ -96,6 +96,22 @@ CHANNEL_NAME_SETTING=channel_setting CHANNEL_NAME_MODEL_EVENT=channel_model_event FORCE_SCHEME= +# Captcha settings +# Available drivers: image, cloudflare_turnstile, google_recaptcha_v2 +CAPTCHA_DRIVER=image + +# Cloudflare Turnstile keys (used when CAPTCHA_DRIVER=cloudflare_turnstile) +TURNSTILE_SITE_KEY= +TURNSTILE_SECRET_KEY= +TURNSTILE_THEME=light +TURNSTILE_SIZE=flexible + +# Google reCAPTCHA v2 keys (used when CAPTCHA_DRIVER=google_recaptcha_v2) +RECAPTCHA_SITE_KEY= +RECAPTCHA_SECRET_KEY= +RECAPTCHA_THEME=light +RECAPTCHA_SIZE=normal + CROWDIN_ACCESS_TOKEN= CROWDIN_PROJECT_ID= diff --git a/app/Services/Captcha/CaptchaDriverInterface.php b/app/Services/Captcha/CaptchaDriverInterface.php new file mode 100644 index 00000000..743777c3 --- /dev/null +++ b/app/Services/Captcha/CaptchaDriverInterface.php @@ -0,0 +1,19 @@ + */ + protected array $drivers = []; + + protected ?array $config = null; + + public function driver(?string $name = null): CaptchaDriverInterface + { + $name = $name ?? $this->getDefaultDriver(); + + $driver = $this->getDriverInstance($name); + + if ($name !== 'image' && !$driver->isEnabled()) { + return $this->driver('image'); + } + + return $driver; + } + + public function render(array $context = []): string + { + return $this->driver()->render($context); + } + + public function verify(array $payload, array $context = []): bool + { + try { + return $this->driver()->verify($payload, $context); + } catch (CaptchaValidationException $exception) { + throw $exception; + } + } + + public function isEnabled(): bool + { + return $this->driver()->isEnabled(); + } + + protected function getDriverInstance(string $name): CaptchaDriverInterface + { + if (!isset($this->drivers[$name])) { + try { + $this->drivers[$name] = $this->resolveDriver($name); + } catch (\InvalidArgumentException $exception) { + if ($name !== 'image') { + return $this->getDriverInstance('image'); + } + throw $exception; + } + } + + return $this->drivers[$name]; + } + + protected function resolveDriver(string $name): CaptchaDriverInterface + { + $config = $this->getConfigValue("drivers.$name", []); + + if (!is_array($config) || empty($config)) { + throw new \InvalidArgumentException("Captcha driver [$name] is not defined."); + } + + $driverClass = Arr::get($config, 'class'); + + if (!$driverClass || !class_exists($driverClass)) { + throw new \InvalidArgumentException("Captcha driver class for [$name] is invalid."); + } + + $driver = new $driverClass($config); + + if (!$driver instanceof CaptchaDriverInterface) { + throw new \InvalidArgumentException("Captcha driver [$name] must implement " . CaptchaDriverInterface::class); + } + + return $driver; + } + + protected function getDefaultDriver(): string + { + return (string) $this->getConfigValue('default', 'image'); + } + + protected function getConfigValue(string $key, $default = null) + { + if ($this->config === null) { + $config = null; + if (function_exists('app')) { + try { + $repository = app('config'); + if ($repository) { + $config = $repository->get('captcha'); + } + } catch (\Throwable $exception) { + $config = null; + } + } + + if (!is_array($config) && function_exists('nexus_config')) { + $config = nexus_config('captcha', []); + } + + if (!is_array($config)) { + $path = (defined('ROOT_PATH') ? ROOT_PATH : dirname(__DIR__, 3) . DIRECTORY_SEPARATOR) . 'config/captcha.php'; + $config = is_file($path) ? require $path : []; + } + + $this->config = is_array($config) ? $config : []; + } + + return Arr::get($this->config, $key, $default); + } +} diff --git a/app/Services/Captcha/Drivers/ImageCaptchaDriver.php b/app/Services/Captcha/Drivers/ImageCaptchaDriver.php new file mode 100644 index 00000000..69952c99 --- /dev/null +++ b/app/Services/Captcha/Drivers/ImageCaptchaDriver.php @@ -0,0 +1,156 @@ +config = $config; + } + + public function isEnabled(): bool + { + return true; + } + + public function render(array $context = []): string + { + $labels = $context['labels'] ?? []; + $imageLabel = $labels['image'] ?? 'Security Image'; + $codeLabel = $labels['code'] ?? 'Security Code'; + $secret = $context['secret'] ?? ''; + + $imagehash = $this->issue(); + $imageUrl = htmlspecialchars(sprintf('image.php?action=regimage&imagehash=%s&secret=%s', $imagehash, $secret ?? ''), ENT_QUOTES, 'UTF-8'); + + return implode("\n", [ + sprintf('%sCAPTCHA', htmlspecialchars($imageLabel, ENT_QUOTES, 'UTF-8'), $imageUrl), + sprintf('%s', htmlspecialchars($codeLabel, ENT_QUOTES, 'UTF-8'), htmlspecialchars($imagehash, ENT_QUOTES, 'UTF-8')), + ]); + } + + public function verify(array $payload, array $context = []): bool + { + $imagehash = trim((string) ($payload['imagehash'] ?? '')); + $imagestring = trim((string) ($payload['imagestring'] ?? '')); + + if ($imagehash === '' || $imagestring === '') { + throw new CaptchaValidationException('Missing captcha parameters.'); + } + + $query = sprintf( + "SELECT dateline FROM regimages WHERE imagehash='%s' AND imagestring='%s'", + mysql_real_escape_string($imagehash), + mysql_real_escape_string($imagestring) + ); + + $sql = sql_query($query); + $imgcheck = mysql_fetch_array($sql); + + $this->deleteByHash($imagehash); + + if (empty($imgcheck['dateline'])) { + throw new CaptchaValidationException('Invalid captcha response.'); + } + + return true; + } + + public function issue(): string + { + $random = random_str(); + $imagehash = md5($random); + $dateline = time(); + + $sql = sprintf( + "INSERT INTO `regimages` (`imagehash`, `imagestring`, `dateline`) VALUES ('%s', '%s', '%s')", + mysql_real_escape_string($imagehash), + mysql_real_escape_string($random), + mysql_real_escape_string((string) $dateline) + ); + + sql_query($sql); + + return $imagehash; + } + + public function outputImage(string $imagehash): void + { + $query = sprintf( + "SELECT imagestring FROM regimages WHERE imagehash=%s", + sqlesc($imagehash) + ); + + $sql = sql_query($query); + $regimage = mysql_fetch_array($sql); + $imagestring = $regimage['imagestring'] ?? ''; + + if ($imagestring === '') { + $this->renderFallback(); + return; + } + + $characters = implode(' ', str_split($imagestring)); + + if (!function_exists('imagecreatefrompng')) { + $this->renderFallback(); + return; + } + + $fontwidth = imageFontWidth(5); + $fontheight = imageFontHeight(5); + $textwidth = $fontwidth * strlen($characters); + $textheight = $fontheight; + + $randimg = rand(1, 5); + $imagePath = ROOT_PATH . "public/pic/regimages/reg{$randimg}.png"; + + if (!is_file($imagePath)) { + $this->renderFallback(); + return; + } + + $im = imagecreatefrompng($imagePath); + $imgheight = imagesy($im); + $imgwidth = imagesx($im); + $textposh = (int) floor(($imgwidth - $textwidth) / 2); + $textposv = (int) floor(($imgheight - $textheight) / 2); + + $dots = (int) floor($imgheight * $imgwidth / 35); + for ($i = 1; $i <= $dots; $i++) { + imagesetpixel($im, rand(0, $imgwidth - 1), rand(0, $imgheight - 1), imagecolorallocate($im, rand(0, 255), rand(0, 255), rand(0, 255))); + } + + $textcolor = imagecolorallocate($im, 0, 0, 0); + imagestring($im, 5, $textposh, $textposv, $characters, $textcolor); + + header('Content-type: image/png'); + imagepng($im); + imagedestroy($im); + } + + protected function deleteByHash(string $imagehash): void + { + if ($imagehash === '') { + return; + } + + $delete = sprintf( + "DELETE FROM regimages WHERE imagehash='%s'", + mysql_real_escape_string($imagehash) + ); + + sql_query($delete); + } + + protected function renderFallback(): void + { + http_response_code(404); + } +} diff --git a/app/Services/Captcha/Drivers/RecaptchaV2CaptchaDriver.php b/app/Services/Captcha/Drivers/RecaptchaV2CaptchaDriver.php new file mode 100644 index 00000000..04d0a157 --- /dev/null +++ b/app/Services/Captcha/Drivers/RecaptchaV2CaptchaDriver.php @@ -0,0 +1,134 @@ +config = $config; + } + + public function isEnabled(): bool + { + return !empty($this->config['site_key']) && !empty($this->config['secret_key']); + } + + public function render(array $context = []): string + { + if (!$this->isEnabled()) { + return ''; + } + + $labels = $context['labels'] ?? []; + $label = $labels['image'] ?? $labels['code'] ?? 'Security Check'; + $theme = $this->config['theme'] ?? 'light'; + $size = $this->config['size'] ?? 'normal'; + $validSizes = ['compact', 'normal']; + if (!in_array($size, $validSizes, true)) { + $size = 'normal'; + } + + $attributes = sprintf( + 'class="g-recaptcha" data-sitekey="%s" data-theme="%s" data-size="%s"', + htmlspecialchars($this->config['site_key'], ENT_QUOTES, 'UTF-8'), + htmlspecialchars($theme, ENT_QUOTES, 'UTF-8'), + htmlspecialchars($size, ENT_QUOTES, 'UTF-8') + ); + + return sprintf( + '%s
%s', + htmlspecialchars($label, ENT_QUOTES, 'UTF-8'), + $attributes, + '' + ); + } + + public function verify(array $payload, array $context = []): bool + { + $token = trim((string) ($payload['request']['g-recaptcha-response'] ?? '')); + + if ($token === '') { + throw new CaptchaValidationException('Captcha verification token is missing.'); + } + + $secret = $this->config['secret_key'] ?? ''; + + if ($secret === '') { + throw new CaptchaValidationException('Captcha secret key is not configured.'); + } + + $data = [ + 'secret' => $secret, + 'response' => $token, + ]; + + $remoteIp = $context['ip'] ?? null; + + if (!empty($remoteIp)) { + $data['remoteip'] = $remoteIp; + } + + $result = $this->sendVerificationRequest('https://www.google.com/recaptcha/api/siteverify', $data); + + if (!($result['success'] ?? false)) { + throw new CaptchaValidationException('Captcha verification failed.'); + } + + return true; + } + + protected function sendVerificationRequest(string $url, array $data): array + { + $payload = http_build_query($data); + + if (function_exists('curl_init')) { + $ch = curl_init($url); + curl_setopt_array($ch, [ + CURLOPT_RETURNTRANSFER => true, + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => $payload, + CURLOPT_TIMEOUT => 10, + CURLOPT_SSL_VERIFYPEER => true, + ]); + + $response = curl_exec($ch); + + if ($response === false) { + $error = curl_error($ch); + curl_close($ch); + throw new CaptchaValidationException('Captcha verification request failed: ' . $error); + } + + curl_close($ch); + } else { + $context = stream_context_create([ + 'http' => [ + 'method' => 'POST', + 'header' => "Content-type: application/x-www-form-urlencoded\r\n", + 'content' => $payload, + 'timeout' => 10, + ], + ]); + + $response = file_get_contents($url, false, $context); + + if ($response === false) { + throw new CaptchaValidationException('Captcha verification request failed.'); + } + } + + $decoded = json_decode($response, true); + + if (!is_array($decoded)) { + throw new CaptchaValidationException('Unexpected captcha verification response.'); + } + + return $decoded; + } +} diff --git a/app/Services/Captcha/Drivers/TurnstileCaptchaDriver.php b/app/Services/Captcha/Drivers/TurnstileCaptchaDriver.php new file mode 100644 index 00000000..21a2e214 --- /dev/null +++ b/app/Services/Captcha/Drivers/TurnstileCaptchaDriver.php @@ -0,0 +1,143 @@ +config = $config; + } + + public function isEnabled(): bool + { + return !empty($this->config['site_key']) && !empty($this->config['secret_key']); + } + + public function render(array $context = []): string + { + if (!$this->isEnabled()) { + return ''; + } + + $labels = $context['labels'] ?? []; + $label = $labels['image'] ?? $labels['code'] ?? 'Security Check'; + $theme = $this->config['theme'] ?? 'light'; + $size = $this->config['size'] ?? 'auto'; + if (is_string($size)) { + $size = strtolower($size); + } + $validSizes = ['compact', 'normal', 'flexible']; + if (!in_array($size, $validSizes, true)) { + $size = 'auto'; + } + + $attributes = sprintf( + 'class="cf-turnstile" data-sitekey="%s" data-theme="%s"%s', + htmlspecialchars($this->config['site_key'], ENT_QUOTES, 'UTF-8'), + htmlspecialchars($theme, ENT_QUOTES, 'UTF-8'), + $size === 'auto' ? '' : sprintf(' data-size="%s"', htmlspecialchars($size, ENT_QUOTES, 'UTF-8')) + ); + + $markup = sprintf( + '%s
%s', + htmlspecialchars($label, ENT_QUOTES, 'UTF-8'), + $attributes, + self::$scriptInjected ? '' : '' + ); + + self::$scriptInjected = true; + + return $markup; + } + + public function verify(array $payload, array $context = []): bool + { + $token = trim((string) ($payload['request']['cf-turnstile-response'] ?? '')); + + if ($token === '') { + throw new CaptchaValidationException('Captcha verification token is missing.'); + } + + $secret = $this->config['secret_key'] ?? ''; + + if ($secret === '') { + throw new CaptchaValidationException('Captcha secret key is not configured.'); + } + + $data = [ + 'secret' => $secret, + 'response' => $token, + ]; + + $remoteIp = $context['ip'] ?? null; + + if (!empty($remoteIp)) { + $data['remoteip'] = $remoteIp; + } + + $result = $this->sendVerificationRequest('https://challenges.cloudflare.com/turnstile/v0/siteverify', $data); + + if (!($result['success'] ?? false)) { + throw new CaptchaValidationException('Captcha verification failed.'); + } + + return true; + } + + protected function sendVerificationRequest(string $url, array $data): array + { + $payload = http_build_query($data); + + if (function_exists('curl_init')) { + $ch = curl_init($url); + curl_setopt_array($ch, [ + CURLOPT_RETURNTRANSFER => true, + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => $payload, + CURLOPT_TIMEOUT => 10, + CURLOPT_SSL_VERIFYPEER => true, + ]); + + $response = curl_exec($ch); + + if ($response === false) { + $error = curl_error($ch); + curl_close($ch); + throw new CaptchaValidationException('Captcha verification request failed: ' . $error); + } + + curl_close($ch); + } else { + $context = stream_context_create([ + 'http' => [ + 'method' => 'POST', + 'header' => "Content-type: application/x-www-form-urlencoded\r\n", + 'content' => $payload, + 'timeout' => 10, + ], + ]); + + $response = file_get_contents($url, false, $context); + + if ($response === false) { + throw new CaptchaValidationException('Captcha verification request failed.'); + } + } + + $decoded = json_decode($response, true); + + if (!is_array($decoded)) { + throw new CaptchaValidationException('Unexpected captcha verification response.'); + } + + return $decoded; + } +} diff --git a/app/Services/Captcha/Exceptions/CaptchaValidationException.php b/app/Services/Captcha/Exceptions/CaptchaValidationException.php new file mode 100644 index 00000000..2171f52f --- /dev/null +++ b/app/Services/Captcha/Exceptions/CaptchaValidationException.php @@ -0,0 +1,10 @@ + nexus_env('CAPTCHA_DRIVER', 'image'), + + 'drivers' => [ + 'image' => [ + 'class' => \App\Services\Captcha\Drivers\ImageCaptchaDriver::class, + ], + + 'cloudflare_turnstile' => [ + 'class' => \App\Services\Captcha\Drivers\TurnstileCaptchaDriver::class, + 'site_key' => nexus_env('TURNSTILE_SITE_KEY'), + 'secret_key' => nexus_env('TURNSTILE_SECRET_KEY'), + 'theme' => nexus_env('TURNSTILE_THEME', 'auto'), + 'size' => nexus_env('TURNSTILE_SIZE', 'auto'), + ], + + 'google_recaptcha_v2' => [ + 'class' => \App\Services\Captcha\Drivers\RecaptchaV2CaptchaDriver::class, + 'site_key' => nexus_env('RECAPTCHA_SITE_KEY'), + 'secret_key' => nexus_env('RECAPTCHA_SECRET_KEY'), + 'theme' => nexus_env('RECAPTCHA_THEME', 'light'), + 'size' => nexus_env('RECAPTCHA_SIZE', 'normal'), + ], + ], +]; diff --git a/include/functions.php b/include/functions.php index 89aba8fe..27641fae 100644 --- a/include/functions.php +++ b/include/functions.php @@ -1767,56 +1767,102 @@ function random_str($length="6") } return $str; } -function image_code () { - $randomstr = random_str(); - $imagehash = md5($randomstr); - $dateline = time(); - $sql = 'INSERT INTO `regimages` (`imagehash`, `imagestring`, `dateline`) VALUES (\''.$imagehash.'\', \''.$randomstr.'\', \''.$dateline.'\');'; - sql_query($sql); - return $imagehash; +function captcha_manager(): \App\Services\Captcha\CaptchaManager +{ + static $manager; + + if (!$manager) { + $manager = new \App\Services\Captcha\CaptchaManager(); + } + + return $manager; } -function check_code ($imagehash, $imagestring, $where = 'signup.php',$maxattemptlog=false,$head=true) { - global $lang_functions; +function image_code () { + $driver = captcha_manager()->driver('image'); + + if (!method_exists($driver, 'issue')) { + throw new \RuntimeException('Image captcha driver is unavailable.'); + } + + return $driver->issue(); +} + +function check_code ($imagehash, $imagestring, $where = 'signup.php', $maxattemptlog = false, $head = true) { + global $lang_functions; global $iv; + if ($iv !== 'yes') { return true; } - $query = sprintf("SELECT * FROM regimages WHERE imagehash='%s' AND imagestring='%s'", - mysql_real_escape_string((string)$imagehash), - mysql_real_escape_string((string)$imagestring) - ); - $sql = sql_query($query); - $imgcheck = mysql_fetch_array($sql); - if(!$imgcheck['dateline']) { - $delete = sprintf("DELETE FROM regimages WHERE imagehash='%s'", - mysql_real_escape_string((string)$imagehash) - ); - sql_query($delete); - if (!$maxattemptlog) - stderr('Error',$lang_functions['std_invalid_image_code']."".$lang_functions['std_here_to_request_new'], false); - else - failedlogins($lang_functions['std_invalid_image_code']."".$lang_functions['std_here_to_request_new'],true,$head); - }else{ - $delete = sprintf("DELETE FROM regimages WHERE imagehash='%s'", - mysql_real_escape_string((string)$imagehash) - ); - sql_query($delete); - return true; - } + + $manager = captcha_manager(); + + if (!$manager->isEnabled()) { + return true; + } + + $payload = [ + 'imagehash' => $imagehash, + 'imagestring' => $imagestring, + 'request' => array_merge($_POST ?? [], $_GET ?? []), + ]; + + $context = [ + 'where' => $where, + 'maxattemptlog' => $maxattemptlog, + 'head' => $head, + 'ip' => getip(), + ]; + + try { + if ($manager->verify($payload, $context)) { + return true; + } + } catch (\App\Services\Captcha\Exceptions\CaptchaValidationException $exception) { + $message = $exception->getMessage(); + + $defaultMessage = $lang_functions['std_invalid_image_code'] . "" . $lang_functions['std_here_to_request_new']; + + if ($message === '' || $message === 'Invalid captcha response.' || $message === 'Missing captcha parameters.') { + $message = $defaultMessage; + } + + if (!$maxattemptlog) { + stderr('Error', $message, false); + } else { + failedlogins($message, true, $head); + } + } + + return false; } + function show_image_code () { - global $lang_functions; - global $iv; - if ($iv == "yes") { - unset($imagehash); - $imagehash = image_code () ; - print ("".$lang_functions['row_security_image'].""); - print ("\"CAPTCHA\""); - print ("".$lang_functions['row_security_code'].""); - print(""); - print(""); - } + global $lang_functions; + global $iv; + + if ($iv !== 'yes') { + return; + } + + $manager = captcha_manager(); + + if (!$manager->isEnabled()) { + return; + } + + $markup = $manager->render([ + 'labels' => [ + 'image' => $lang_functions['row_security_image'], + 'code' => $lang_functions['row_security_code'], + ], + 'secret' => $_GET['secret'] ?? '', + ]); + + if ($markup !== '') { + echo $markup; + } } function get_ip_location($ip) diff --git a/include/globalfunctions.php b/include/globalfunctions.php index c0a0e89d..dd8003f4 100644 --- a/include/globalfunctions.php +++ b/include/globalfunctions.php @@ -307,6 +307,7 @@ function nexus_config($key, $default = null) $files = [ ROOT_PATH . 'config/nexus.php', ROOT_PATH . 'config/emoji.php', + ROOT_PATH . 'config/captcha.php', ]; foreach ($files as $file) { $basename = basename($file); diff --git a/public/complains.php b/public/complains.php index 8f8c8b1f..91b80f5b 100644 --- a/public/complains.php +++ b/public/complains.php @@ -18,7 +18,7 @@ if($_SERVER['REQUEST_METHOD'] === 'POST'){ switch($action = filter_input(INPUT_POST, 'action', FILTER_SANITIZE_FULL_SPECIAL_CHARS)){ case 'new': cur_user_check(); - check_code ($_POST['imagehash'], $_POST['imagestring'],'complains.php'); + check_code ($_POST['imagehash'] ?? null, $_POST['imagestring'] ?? null,'complains.php'); \Nexus\Database\NexusLock::lockOrFail("complains:lock:" . getip(), 10); $email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL); \Nexus\Database\NexusLock::lockOrFail("complains:lock:" . $email, 600); diff --git a/public/confirm_resend.php b/public/confirm_resend.php index ce9b6115..0022b1d9 100644 --- a/public/confirm_resend.php +++ b/public/confirm_resend.php @@ -29,7 +29,7 @@ bark($lang_confirm_resend['std_need_admin_verification']); if ($_SERVER["REQUEST_METHOD"] == "POST") { if ($iv == "yes") - check_code ($_POST['imagehash'], $_POST['imagestring'],"confirm_resend.php",true); + check_code ($_POST['imagehash'] ?? null, $_POST['imagestring'] ?? null,"confirm_resend.php",true); $email = unesc(htmlspecialchars(trim($_POST["email"] ?? ''))); $wantpassword = unesc(htmlspecialchars(trim($_POST["wantpassword"]))); $passagain = unesc(htmlspecialchars(trim($_POST["passagain"]))); diff --git a/public/image.php b/public/image.php index f013e5d4..fa2df541 100644 --- a/public/image.php +++ b/public/image.php @@ -1,60 +1,22 @@ driver('image'); + +if (!method_exists($driver, 'outputImage')) { + http_response_code(404); + exit('Captcha driver does not support image rendering'); } + +$driver->outputImage($imagehash); + ?> diff --git a/public/recover.php b/public/recover.php index 128c23f9..5e5979cc 100644 --- a/public/recover.php +++ b/public/recover.php @@ -28,7 +28,7 @@ $mailTwoFour = sprintf($lang_recover['mail_two_four'], $siteName); if ($_SERVER["REQUEST_METHOD"] == "POST") { if ($iv == "yes") - check_code ($_POST['imagehash'], $_POST['imagestring'],"recover.php",true); + check_code ($_POST['imagehash'] ?? null, $_POST['imagestring'] ?? null,"recover.php",true); $email = unesc(htmlspecialchars(trim($_POST["email"] ?? ''))); $email = safe_email($email); if (!$email) diff --git a/public/takelogin.php b/public/takelogin.php index 398f4b07..23a44761 100644 --- a/public/takelogin.php +++ b/public/takelogin.php @@ -15,7 +15,7 @@ function bark($text = "") stderr($lang_takelogin['std_login_fail'], $text,false); } if ($iv == "yes") { - check_code ($_POST['imagehash'], $_POST['imagestring'],'login.php',true); + check_code($_POST['imagehash'] ?? null, $_POST['imagestring'] ?? null, 'login.php', true); } //同时支持新旧两种登录方式 $useChallengeResponse = \App\Models\Setting::getIsUseChallengeResponseAuthentication(); diff --git a/public/takesignup.php b/public/takesignup.php index 3358a344..94d4a075 100644 --- a/public/takesignup.php +++ b/public/takesignup.php @@ -21,13 +21,13 @@ if ($type == 'invite'){ registration_check(); failedloginscheck ("Invite Signup"); if ($iv == "yes") - check_code ($_POST['imagehash'], $_POST['imagestring'],'signup.php?type=invite&invitenumber='.htmlspecialchars($_POST['hash'])); + check_code ($_POST['imagehash'] ?? null, $_POST['imagestring'] ?? null,'signup.php?type=invite&invitenumber='.htmlspecialchars($_POST['hash'])); } else{ registration_check("normal"); failedloginscheck ("Signup"); if ($iv == "yes") - check_code ($_POST['imagehash'], $_POST['imagestring']); + check_code ($_POST['imagehash'] ?? null, $_POST['imagestring'] ?? null); } function isportopen($port) {