settings = new ConvertKit_Settings(); } /** * Enqueues the Cloudflare Turnstile client-side script if Cloudflare Turnstile * site and secret keys are set and scripts are enabled. * * @since 3.3.7 */ public function enqueue_scripts() { // Don't run if Cloudflare Turnstile or scripts are disabled. if ( ! $this->settings->has_cloudflare_turnstile_site_and_secret_keys() || $this->settings->scripts_disabled() ) { return; } // Enqueue Cloudflare Turnstile JS. add_filter( 'convertkit_output_scripts_footer', function ( $scripts ) { $scripts[] = array( 'src' => self::CLIENT_SCRIPT_URL, 'async' => true, 'defer' => true, ); return $scripts; } ); } /** * Verifies a Cloudflare Turnstile response token against the Siteverify API, * if Cloudflare Turnstile site and secret keys are set, and scripts are enabled. * * Mirrors the request format documented at * https://developers.cloudflare.com/turnstile/get-started/server-side-validation/ * * @since 3.3.7 * * @param string $cloudflare_turnstile_response Cloudflare Turnstile response token from the client. * @param string $plugin_action Plugin action string (unused). * @return bool|WP_Error */ public function verify( $cloudflare_turnstile_response, $plugin_action ) { unset( $plugin_action ); // Don't run if Turnstile or scripts are disabled. if ( ! $this->settings->has_cloudflare_turnstile_site_and_secret_keys() || $this->settings->scripts_disabled() ) { return true; } // POST to Cloudflare Siteverify. $response = wp_remote_post( self::SITEVERIFY_URL, array( 'body' => array( 'secret' => $this->settings->cloudflare_turnstile_secret_key(), 'response' => $cloudflare_turnstile_response, 'remoteip' => ( isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : '' ), ), ) ); // Bail if the request itself errored. if ( is_wp_error( $response ) ) { return $response; } // Decode response. $body = json_decode( wp_remote_retrieve_body( $response ), true ); // If the response body couldn't be decoded, treat that as a failure. if ( ! is_array( $body ) ) { return new WP_Error( 'convertkit_cloudflare_turnstile_failed', __( 'Cloudflare Turnstile failure: invalid response from Siteverify.', 'convertkit' ) ); } // If the token verified, return true. if ( $body['success'] === true ) { return true; } // Return an error. return new WP_Error( 'convertkit_cloudflare_turnstile_failed', sprintf( /* translators: Error codes */ __( 'Cloudflare Turnstile failure: %s', 'convertkit' ), implode( ', ', $body['error-codes'] ) ) ); } /** * Inserts a Cloudflare Turnstile widget div immediately before the given * submit button within an existing DOM tree. `data-appearance=interaction-only` * keeps the widget invisible unless Cloudflare determines a challenge is * required, and the `convertKitTurnstileFormSubmit` callback submits the * enclosing form once the challenge is solved. * * @since 3.3.7 * * @param ConvertKit_HTML_Parser $parser Parser wrapping the DOM. * @param DOMElement $button