[
'enabled' => false,
'site_key' => '',
'action' => 'checker_validate',
'hide_badge' => false
],
'turnstile' => [
'enabled' => false,
'site_key' => '',
'theme' => 'auto',
'size' => 'normal'
]
];
// Get reCAPTCHA settings
if (isset($checker['security']['recaptcha']['enabled']) && $checker['security']['recaptcha']['enabled'] === 'yes') {
$config['recaptcha'] = [
'enabled' => true,
'site_key' => $checker['security']['recaptcha']['site_key'] ?? '',
'action' => $checker['security']['recaptcha']['action'] ?? 'checker_validate',
'hide_badge' => $checker['security']['recaptcha']['hide_badge'] === 'yes'
];
}
// Get Turnstile settings
if (isset($checker['security']['turnstile']['enabled']) && $checker['security']['turnstile']['enabled'] === 'yes') {
$config['turnstile'] = [
'enabled' => true,
'site_key' => $checker['security']['turnstile']['site_key'] ?? '',
'theme' => $checker['security']['turnstile']['theme'] ?? 'auto',
'size' => $checker['security']['turnstile']['size'] ?? 'normal'
];
}
return $config;
}
/**
* Get CAPTCHA field HTML for form
*
* @param int $checker_id Checker post ID
* @return string HTML for CAPTCHA fields
*/
public static function get_captcha_fields($checker_id) {
$config = self::get_captcha_config($checker_id);
// Prefer Turnstile over reCAPTCHA when both are flagged (should not happen in UI)
if ($config['turnstile']['enabled']) {
$config['recaptcha']['enabled'] = false;
}
$html = '';
if ($config['recaptcha']['enabled'] || $config['turnstile']['enabled']) {
// Add container for CAPTCHA
$html .= '
';
if ($config['recaptcha']['enabled']) {
// reCAPTCHA v3 doesn't need visible fields
$html .= '';
}
if ($config['turnstile']['enabled']) {
// Turnstile container will be added dynamically
$html .= '';
$html .= '';
}
$html .= '
';
}
return $html;
}
/**
* Check if CAPTCHA is configured and valid
*
* @param int $checker_id Checker post ID
* @return array Validity check result
*/
public static function validate_captcha_config($checker_id) {
$config = self::get_captcha_config($checker_id);
$result = [
'valid' => false,
'type' => null,
'issues' => []
];
// Check reCAPTCHA
if ($config['recaptcha']['enabled']) {
if (empty($config['recaptcha']['site_key'])) {
$result['issues'][] = 'reCAPTCHA site key is missing';
} elseif (!preg_match('/^6Lc[a-zA-Z0-9_-]{38}$/', $config['recaptcha']['site_key'])) {
$result['issues'][] = 'reCAPTCHA site key appears to be invalid';
}
if (count($result['issues']) === 0) {
$result['valid'] = true;
$result['type'] = 'recaptcha';
return $result;
}
}
// Check Turnstile
if ($config['turnstile']['enabled']) {
if (empty($config['turnstile']['site_key'])) {
$result['issues'][] = 'Turnstile site key is missing';
} elseif (!preg_match('/^0x4AAA[a-zA-Z0-9_-]{33}$/', $config['turnstile']['site_key'])) {
$result['issues'][] = 'Turnstile site key appears to be invalid';
}
if (count($result['issues']) === 0) {
$result['valid'] = true;
$result['type'] = 'turnstile';
return $result;
}
}
// If both are enabled, it's an issue
if ($config['recaptcha']['enabled'] && $config['turnstile']['enabled']) {
$result['issues'][] = 'Both reCAPTCHA and Turnstile are enabled (only one should be used)';
}
return $result;
}
}