# contact-forms/2.3.5/classes/Validation/Cap.php

Contact Forms by Cimatti, version 2.3.5. 69 lines.

- Page: https://pluginprobe.com/plugins/contact-forms/2.3.5/code/classes/Validation/Cap.php
- Raw: https://pluginprobe.com/plugins/contact-forms/2.3.5/raw/classes/Validation/Cap.php
- Modified: 2026-08-05T09:37:24+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/contact-forms/2.3.5/code/classes/Validation/Cap.php#L10-L20`.

```php
<?php
/**
 * Cap (capjs.js.org) Validation
 *
 * Verifies the proof-of-work token against the self-hosted Cap Standalone
 * instance via its reCAPTCHA-compatible siteverify endpoint:
 * POST {instance}/{siteKey}/siteverify with a JSON body {secret, response}.
 *
 * The instance URL, site key and secret live on this object (not on the
 * Element) so they survive the encrypted-form serialization round trip:
 * Element::__sleep() only keeps attributes, label, validation and errors.
 *
 * @package Contact Forms
 */

// phpcs:disable WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput -- Server-side CAPTCHA validation requires POST data

class AccuaForm_Validation_Cap extends Validation {
	protected $message = 'Captcha verification failed. Please retry.';
	protected $instanceUrl;
	protected $siteKey;
	protected $secretKey;

	public function isValid( $value ) {
		if ( isset( $_POST['accua-forms-cap-response'] ) && '' !== $_POST['accua-forms-cap-response'] ) {
			$response = stripslashes_deep( $_POST['accua-forms-cap-response'] );
		} elseif ( isset( $_POST['cap-token'] ) ) {
			// Fallback: the hidden input injected by the cap-widget itself
			// (covers the edge case where our sync script did not run).
			$response = stripslashes_deep( $_POST['cap-token'] );
		} else {
			$response = (string) $value;
		}

		if ( '' === $response || ! is_string( $response ) ) {
			return false;
		}

		if ( empty( $this->instanceUrl ) || empty( $this->siteKey ) || empty( $this->secretKey ) ) {
			return false;
		}

		$verify_url = trailingslashit( $this->instanceUrl ) . rawurlencode( $this->siteKey ) . '/siteverify';

		$response_obj = wp_remote_post(
			$verify_url,
			array(
				'headers' => array( 'Content-Type' => 'application/json' ),
				'body'    => wp_json_encode(
					array(
						'secret'   => $this->secretKey,
						'response' => $response,
					)
				),
				'timeout' => 20,
			)
		);

		if ( is_wp_error( $response_obj ) ) {
			return false;
		}

		$body   = wp_remote_retrieve_body( $response_obj );
		$result = json_decode( $body, true );

		return ! empty( $result['success'] );
	}
}

```
