register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'injectScript'); $controller->register_hook('FORM_REGISTER_OUTPUT', 'BEFORE', $this, 'handleFormOutput', []); $controller->register_hook('FORM_LOGIN_OUTPUT', 'BEFORE', $this, 'handleFormOutput', []); $controller->register_hook('AUTH_USER_CHANGE', 'BEFORE', $this, 'handleRegister', []); $controller->register_hook('AUTH_LOGIN_CHECK', 'BEFORE', $this, 'handleLogin', []); } private function getHTML() { $siteKey = $this->getConf('sitekey'); $html = '
'; $html .= '
'; $html .= '
'; return $html; } public function injectScript(Event $event, $param) { global $ACT; if ($ACT === 'register' || $ACT === 'login') { $event->data['script'][] = [ 'type' => 'text/javascript', 'src' => self::TURNSTILE_CHALLENGE, 'async' => 'async', 'defer' => 'defer', '_data' => '' ]; } } public function handleFormOutput(Event $event, $param) { $form = $event->data; $html = $this->getHTML(); if (empty($html)) return; $pos = $form->findPositionByAttribute('type', 'submit'); if(!$pos) return; $form->addHTML($html, $pos); } private function generateResponse(Event $event): ?array { $private = $this->getConf('secretkey'); if (empty($private)) return null; global $INPUT; $ts_response = $INPUT->post->str('cf-turnstile-response'); if (empty($ts_response)) return null; $ip = $INPUT->server->str('REMOTE_ADDR'); $data = [ 'secret' => $private, 'response' => $ts_response, 'remoteip' => $ip ]; $options = [ 'http' => [ 'header' => "Content-type: application/json\r\n", 'method' => 'POST', 'content' => json_encode($data) ] ]; $context = stream_context_create($options); $result = @file_get_contents(self::TURNSTILE_SITEVERIFY, false, $context); if ($result === false) return null; $outcome = json_decode($result, true); if (json_last_error() !== JSON_ERROR_NONE) return null; return $outcome; } private function checkToken(Event $event) { $public = $this->getConf('sitekey'); $private = $this->getConf('secretkey'); if (empty($public) || empty($private)) return; $response = $this->generateResponse($event); if (!is_null($response) && isset($response['success']) && $response['success'] === true) { return; } // add msg here global $INPUT; global $ACT; switch($ACT) { case 'register': $INPUT->post->set('save', false); break; case 'login': $event->result = false; $event->preventDefault(); $event->stopPropagation(); break; } } public function handleRegister(Event $event, $param) { if ($event->data['type'] !== 'create') { return; } $this->checkToken($event); } public function handleLogin(Event $event, $param) { global $INPUT; if (!$INPUT->bool('u')) return; $this->checkToken($event); } }