Advertisement
Guest User

Untitled

a guest
Nov 28th, 2022
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 31.40 KB | None | 0 0
  1. <?php
  2. /**
  3. * Base class to handle Google reCAPTCHA API functionality.
  4. *
  5. * @tutorial https://developers.google.com/recaptcha/docs/faq
  6. * @since 4.5.3
  7. * @since 4.5.7.2 refactored by Günter
  8. */
  9. if( ! defined('AVIA_FW') ) { exit( 'No direct script access allowed' ); }
  10.  
  11.  
  12. if( ! class_exists( 'av_google_recaptcha' ) )
  13. {
  14.  
  15. class av_google_recaptcha
  16. {
  17.  
  18. const API_URL = 'https://www.google.com/recaptcha/api.js';
  19. const API_VERIFY_URL = 'https://www.google.com/recaptcha/api/siteverify';
  20. const API_URL_LANG = '?hl=fr';
  21.  
  22. const AJAX_VERIFY_NONCE = 'av_google_recaptcha_verify_nonce';
  23. const TRANSIENT_PREFIX = 'av_google_recaptcha_';
  24.  
  25. /**
  26. *
  27. * @since 4.5.7.2
  28. * @var av_google_recaptcha
  29. */
  30. static protected $_instance = null;
  31.  
  32. /**
  33. * Version of reCAPTCHA
  34. *
  35. * @since 4.5.7.2
  36. * @var string
  37. */
  38. protected $version;
  39.  
  40. /**
  41. *
  42. * @since 4.5.7.2
  43. * @var array
  44. */
  45. protected $site_keys;
  46.  
  47. /**
  48. *
  49. * @since 4.5.7.2
  50. * @var array
  51. */
  52. protected $secret_keys;
  53.  
  54. /**
  55. * Stores the last verified keys (user might change keys and save without verifying)
  56. *
  57. * @since 4.5.7.2
  58. * @var array '' | 'string combination to verify' | 'verify_error'
  59. */
  60. protected $verified_keys;
  61.  
  62. /**
  63. * V3 score threshold (0.0 - 1.0)
  64. *
  65. * @since 4.5.7.2
  66. * @var float
  67. */
  68. protected $score;
  69.  
  70. /**
  71. * Backend theme color for V2
  72. *
  73. * @since 4.5.7.2
  74. * @var string
  75. */
  76. protected $theme;
  77.  
  78. /**
  79. * Contains the option value
  80. *
  81. * @since 4.5.7.2
  82. * @var string
  83. */
  84. protected $display_badge;
  85.  
  86. /**
  87. * Contains the HTML for replacement text
  88. *
  89. * @since 4.6.2
  90. * @var string
  91. */
  92. protected $display_badge_html;
  93.  
  94. /**
  95. *
  96. * @since 4.5.7.2
  97. * @var boolean|null
  98. */
  99. protected $loading_prohibited;
  100.  
  101.  
  102. /**
  103. * Return the instance of this class
  104. *
  105. * @since 4.5.7.2
  106. * @return av_google_recaptcha
  107. */
  108. static public function instance()
  109. {
  110. if( is_null( av_google_recaptcha::$_instance ) )
  111. {
  112. av_google_recaptcha::$_instance = new av_google_recaptcha();
  113. }
  114.  
  115. return av_google_recaptcha::$_instance;
  116. }
  117.  
  118.  
  119. /**
  120. *
  121. * @since 4.5.7.2
  122. */
  123. protected function __construct()
  124. {
  125. $this->loading_prohibited = null;
  126. $this->version = '';
  127. $this->site_keys = array();
  128. $this->secret_keys = array();
  129. $this->verified_keys = array();
  130. $this->score = 0.5;
  131. $this->theme = 'light';
  132. $this->display_badge = '';
  133. $this->display_badge_html = '';
  134.  
  135.  
  136. // needed because not all framework functions are loaded at this point
  137. add_action( 'after_setup_theme', array( $this, 'handler_after_setup_theme' ), 10 );
  138.  
  139. add_action( 'init', array( $this, 'handler_wp_register_scripts' ), 20 );
  140. add_action( 'wp_enqueue_scripts', array( $this, 'handler_wp_enqueue_scripts' ), 500 );
  141. add_action( 'admin_enqueue_scripts', array( $this, 'handler_wp_admin_enqueue_scripts' ), 500 );
  142.  
  143. add_filter( 'body_class', array( $this, 'handler_body_class' ), 500, 2 );
  144.  
  145. // We hook with low priority as reCAPTCHA verification should overrule other positive checks
  146. add_filter( 'avf_form_send', array( $this, 'handler_avf_form_send' ), 999999, 4 );
  147.  
  148. add_action( 'wp_ajax_avia_recaptcha_verify_frontend', array( $this, 'handler_recaptcha_verify_frontend' ), 10 );
  149. add_action( 'wp_ajax_nopriv_avia_recaptcha_verify_frontend', array( $this, 'handler_recaptcha_verify_frontend' ), 10 );
  150. }
  151.  
  152. /**
  153. *
  154. * @since 4.5.7.2
  155. */
  156. public function __destruct()
  157. {
  158. unset( $this->site_keys );
  159. unset( $this->secret_keys );
  160. unset( $this->verified_keys );
  161. }
  162.  
  163. /**
  164. * @since 4.5.7.2
  165. */
  166. public function handler_after_setup_theme()
  167. {
  168. $this->version = avia_get_option( 'avia_recaptcha_version', '' );
  169.  
  170. $this->site_keys['avia_recaptcha_v2'] = avia_get_option( 'avia_recaptcha_pkey_v2', '' );
  171. $this->site_keys['avia_recaptcha_v3'] = avia_get_option( 'avia_recaptcha_pkey_v3', '' );
  172.  
  173. $this->secret_keys['avia_recaptcha_v2'] = avia_get_option( 'avia_recaptcha_skey_v2', '' );
  174. $this->secret_keys['avia_recaptcha_v3'] = avia_get_option( 'avia_recaptcha_skey_v3', '' );
  175.  
  176. $this->verified_keys['avia_recaptcha_v2'] = avia_get_option( 'recaptcha_verified_keys_v2', '' );
  177. $this->verified_keys['avia_recaptcha_v3'] = avia_get_option( 'recaptcha_verified_keys_v3', '' );
  178.  
  179. $this->score = avia_get_option( 'avia_recaptcha_score', 5 );
  180. $this->score = is_numeric( $this->score ) ? $this->score / 10.0 : 0.5;
  181.  
  182. $this->display_badge = avia_get_option( 'avia_recaptcha_badge', '' );
  183. if( ! current_theme_supports( 'avia_recaptcha_show_legal_information' ) )
  184. {
  185. $this->display_badge = 'contact_only_message';
  186. }
  187.  
  188. /**
  189. * see https://developers.google.com/recaptcha/docs/faq#id-like-to-hide-the-recaptcha-badge-what-is-allowed
  190. *
  191. * @since 4.5.7.2
  192. * @param string
  193. * @return string
  194. */
  195. $badge = '<div class="av-google-badge-message hidden">';
  196. $badge .= __( 'This site is protected by reCAPTCHA and the Google <a href="https://policies.google.com/privacy">Privacy Policy</a> and <a href="https://policies.google.com/terms">Terms of Service</a> apply.', 'avia_framework' );
  197. $badge .= '</div>';
  198.  
  199. $this->display_badge_html = apply_filters( 'avf_google_recaptcha_badge_content', $badge );
  200. }
  201.  
  202. /**
  203. * @since 4.5.7.2
  204. */
  205. public function handler_wp_register_scripts()
  206. {
  207. $vn = avia_get_theme_version();
  208. $min_js = avia_minify_extension( 'js' );
  209.  
  210. wp_register_script( 'avia_google_recaptcha_front_script' , AVIA_JS_URL . "conditional_load/avia_google_recaptcha_front{$min_js}.js", array( 'jquery' ), $vn, true );
  211. wp_register_script( 'avia_google_recaptcha_api_script' , AVIA_JS_URL . "conditional_load/avia_google_recaptcha_api{$min_js}.js", array( 'jquery' ), $vn, true );
  212. }
  213.  
  214. /**
  215. * Frontend we load conditionally. This script checks after pageload if loading of main scripts are necessary.
  216. *
  217. * @since 4.5.7.2
  218. */
  219. public function handler_wp_enqueue_scripts()
  220. {
  221. if( $this->is_loading_prohibited() )
  222. {
  223. return;
  224. }
  225.  
  226. wp_enqueue_script( 'avia_google_recaptcha_front_script' );
  227.  
  228. $args = array(
  229. 'version' => $this->get_version(),
  230. 'site_key2' => $this->get_site_key( 'avia_recaptcha_v2' ),
  231. 'site_key3' => $this->get_site_key( 'avia_recaptcha_v3' ),
  232. 'api' => apply_filters( 'av_google_recaptcha_apiurl', av_google_recaptcha::API_URL ),
  233. 'avia_api_script' => AVIA_JS_URL . 'conditional_load/avia_google_recaptcha_api.js',
  234. 'theme' => $this->get_theme(),
  235. 'score' => $this->get_score(),
  236. 'verify_nonce' => wp_create_nonce( av_google_recaptcha::AJAX_VERIFY_NONCE ),
  237. // 'submission_nonce' => wp_create_nonce( av_google_recaptcha::AJAX_SUBMISSION_NONCE ),
  238. 'cannot_use' => '<h3 class="av-recaptcha-error-main">' . __( 'Sorry, a problem occurred trying to communicate with Google reCAPTCHA API. You are currently not able to submit the contact form. Please try again later - reload the page and also check your internet connection.', 'avia_framework' ) . '</h3>',
  239. 'init_error_msg' => __( 'Initial setting failed. Sitekey 2 and/or sitekey 3 missing in frontend.', 'avia_framework' ),
  240. 'v3_timeout_pageload' => __( 'Timeout occurred connecting to V3 API on initial pageload', 'avia_framework' ),
  241. 'v3_timeout_verify' => __( 'Timeout occurred connecting to V3 API on verifying submit', 'avia_framework' ),
  242. 'v2_timeout_verify' => __( 'Timeout occurred connecting to V2 API on verifying you as human. Please try again and check your internet connection. It might be necessary to reload the page.', 'avia_framework' ),
  243. 'verify_msg' => __( 'Verify....', 'avia_framework' ),
  244. 'connection_error' => __( 'Could not connect to the internet. Please reload the page and try again.', 'avia_framework' ),
  245. 'validate_first' => __( 'Please validate that you are a human first', 'avia_framework' ),
  246. 'validate_submit' => __( 'Before submitting we validate that you are a human first.', 'avia_framework' ),
  247. 'no_token' => __( 'Missing internal token on valid submit - unable to proceed.', 'avia_framework' ),
  248. 'invalid_version' => __( 'Invalid reCAPTCHA version found.', 'avia_framework' ),
  249. 'api_load_error' => __( 'Google reCAPTCHA API could not be loaded.', 'avia_framework' ),
  250. );
  251.  
  252. wp_localize_script( 'avia_google_recaptcha_front_script', 'AviaReCAPTCHA_front', $args );
  253. }
  254.  
  255.  
  256. /**
  257. *
  258. * @since 4.5.7.2
  259. */
  260. public function handler_wp_admin_enqueue_scripts()
  261. {
  262. /**
  263. * Some 3rd party plugins need to supress loading scripts
  264. * Not loading the scripts might result in breaking backend !!!
  265. * Check if everything is working as expected.
  266. *
  267. * @since 4.7.5.1
  268. * @param boolean
  269. * @return string return 'skip_loading' to prohibit loading of backend scripts
  270. */
  271. $skip_loading = apply_filters( 'avf_skip_enqueue_scripts_backend_grecaptcha', '' );
  272.  
  273. if( 'skip_loading' === $skip_loading )
  274. {
  275. return;
  276. }
  277.  
  278. /**
  279. * In backend we must enqueue to validate keys and localize script
  280. */
  281. wp_enqueue_script( 'avia_google_recaptcha_front_script' );
  282.  
  283. $args = array(
  284. 'version' => $this->get_version(),
  285. // 'site_key' => $this->get_site_key(),
  286. 'api' => apply_filters( 'av_google_recaptcha_apiurl', av_google_recaptcha::API_URL ),
  287. 'theme' => $this->get_theme(),
  288. 'api_load_error' => __( 'Google reCAPTCHA API could not be loaded. We are not able to verify keys. Check your internet connection and try again.', 'avia_framework' ),
  289. 'invalid_version' => __( 'Please select Version 2 or 3 for reCAPTCHA', 'avia_framework' ),
  290. 'invalid_keys' => __( 'You have to enter a site key and a secret key to verify it.', 'avia_framework' ),
  291. 'v3_timeout' => __( 'A network timeout problem occurred. Could be caused by an invalid V3 sitekey. Please recheck the key and try again.', 'avia_framework' )
  292. );
  293.  
  294. wp_localize_script( 'avia_google_recaptcha_front_script', 'AviaReCAPTCHA_data', $args );
  295. }
  296.  
  297. /**
  298. * We add classes to allow js script to decide what to load
  299. *
  300. * @since 4.5.7.2
  301. * @param array $classes
  302. * @param array $class
  303. * @return array
  304. */
  305. public function handler_body_class( array $classes, array $class )
  306. {
  307. if( $this->is_loading_prohibited() )
  308. {
  309. return $classes;
  310. }
  311.  
  312. /**
  313. * Allows to disable recaptcha for special pages.
  314. * Only makes sense for V3 as V2 is only loaded if needed on page/post.
  315. * Be careful not to disable it on pages where you need it !!!
  316. *
  317. * @since 4.5.7.2
  318. * @param boolean
  319. * @return boolean
  320. */
  321. $disable = apply_filters( 'avf_disable_recaptchaV3_for_post', false );
  322.  
  323. if( false === $disable )
  324. {
  325. $classes[] = 'av-recaptcha-enabled';
  326. }
  327.  
  328. if( $this->show_extended_errors() )
  329. {
  330. $classes[] = 'av-recaptcha-extended-errors';
  331. }
  332.  
  333. if( in_array( $this->display_badge, array( 'contact_only_message', 'hide' ) ) )
  334. {
  335. $classes[] = 'av-google-badge-hide';
  336. }
  337.  
  338. return $classes;
  339. }
  340.  
  341. /**
  342. * Returns the selected version for the recaptcha
  343. *
  344. * @since 4.5.7.2
  345. * @return string '' | 'avia_recaptcha_v2' | 'avia_recaptcha_v3'
  346. */
  347. public function get_version()
  348. {
  349. return $this->version;
  350. }
  351.  
  352. /**
  353. * Returns the site key for the selected version
  354. *
  355. * @since 4.5.7.2
  356. * @param string $version
  357. * @return string
  358. */
  359. public function get_site_key( $version = null )
  360. {
  361. if( is_null( $version ) )
  362. {
  363. $version = $this->get_version();
  364. }
  365.  
  366. return isset( $this->site_keys[ $version ] ) ? $this->site_keys[ $version ] : '';
  367. }
  368.  
  369. /**
  370. * Returns the secret key for the selected version
  371. *
  372. * @since 4.5.7.2
  373. * @param string $version
  374. * @return string
  375. */
  376. public function get_secret_key( $version = null )
  377. {
  378. if( is_null( $version ) )
  379. {
  380. $version = $this->get_version();
  381. }
  382.  
  383. return isset( $this->secret_keys[ $version ] ) ? $this->secret_keys[ $version ] : '';
  384. }
  385.  
  386.  
  387. /**
  388. * Returns the last saved verified key string:
  389. * "version site_key secret_key"
  390. *
  391. * @since 4.5.7.2
  392. * @param string $version
  393. * @return string
  394. */
  395. public function get_verified_keys( $version = null )
  396. {
  397. if( is_null( $version ) )
  398. {
  399. $version = $this->get_version();
  400. }
  401.  
  402. return isset( $this->verified_keys[ $version ] ) ? $this->verified_keys[ $version ] : '';
  403. }
  404.  
  405. /**
  406. * Returns the float value for selected score threshold (0.0 - 1.0)
  407. *
  408. * @since 4.5.7.2
  409. * @return float
  410. */
  411. public function get_score()
  412. {
  413. return $this->score;
  414. }
  415.  
  416. /**
  417. * Returns the necessary HTML if user selected to use
  418. *
  419. * @since 4.5.7.2
  420. * @return string
  421. */
  422. public function get_display_badge_html()
  423. {
  424. if( ! in_array( $this->display_badge, array( 'message', 'contact_only_message' ) ) )
  425. {
  426. return '';
  427. }
  428.  
  429. return $this->display_badge_html;
  430. }
  431.  
  432. /**
  433. * Returns the selected backend theme style
  434. *
  435. * @since 4.5.7.2
  436. * @return string 'light' | 'dark'
  437. */
  438. public function get_theme()
  439. {
  440. if( ! in_array( $this->theme, array( 'light', 'dark' ) ) )
  441. {
  442. $this->theme = 'light';
  443. }
  444.  
  445. return $this->theme;
  446. }
  447.  
  448. /**
  449. *
  450. * @since 4.5.7.2
  451. * @return boolean
  452. */
  453. public function is_loading_prohibited()
  454. {
  455. if( is_null( $this->loading_prohibited ) )
  456. {
  457. // Check backend setting
  458. $prohibited = ! $this->is_activated() || ! $this->are_keys_set();
  459.  
  460. /**
  461. * Filter allows to supress loading of script on desired pages
  462. *
  463. * @since 4.5.7.2
  464. * @param boolean
  465. * @return boolean
  466. */
  467. $prohibited = apply_filters( 'avf_load_google_recaptcha_api_prohibited', $prohibited );
  468.  
  469. $this->loading_prohibited = is_bool( $prohibited ) ? $prohibited : true;
  470. }
  471.  
  472. return $this->loading_prohibited;
  473. }
  474.  
  475. /**
  476. * Checks if the version activates gRECAPTCHA
  477. *
  478. * @since 4.5.7.2
  479. * @param string $version
  480. * @return boolean
  481. */
  482. public function is_activated( $version = null )
  483. {
  484. if( is_null( $version ) )
  485. {
  486. $version = $this->get_version();
  487. }
  488.  
  489. return in_array( $version, array( 'avia_recaptcha_v2', 'avia_recaptcha_v3' ) );
  490. }
  491.  
  492. /**
  493. * Checks if all necessary keys are set for a version.
  494. * Returns false if an invalid version or if disabled
  495. *
  496. * @since 4.5.7.2
  497. * @param string $version
  498. * @return boolean
  499. */
  500. public function are_keys_set( $version = null )
  501. {
  502. if( is_null( $version ) )
  503. {
  504. $version = $this->get_version();
  505. }
  506.  
  507. $keys2 = ! empty( $this->get_site_key( 'avia_recaptcha_v2' ) ) && ! empty( $this->get_secret_key( 'avia_recaptcha_v2' ) );
  508. $keys3 = ! empty( $this->get_site_key( 'avia_recaptcha_v3' ) ) && ! empty( $this->get_secret_key( 'avia_recaptcha_v3' ) );
  509.  
  510. if( 'avia_recaptcha_v2' == $version )
  511. {
  512. return $keys2;
  513. }
  514.  
  515. if( 'avia_recaptcha_v3' == $version )
  516. {
  517. return $keys2 && $keys3;
  518. }
  519.  
  520. return false;
  521. }
  522.  
  523. /**
  524. * Allow admins to see more detailed error messages
  525. *
  526. * @since 4.5.7.2
  527. * @return boolean
  528. */
  529. protected function show_extended_errors()
  530. {
  531. $show_extended_errors = current_user_can( 'manage_options' );
  532.  
  533. /**
  534. *
  535. *
  536. * @since 4.5.7.2
  537. * @param boolean
  538. * @return boolean return true to show extended messages
  539. */
  540. return apply_filters( 'avf_recaptcha_show_extended_error_messages', $show_extended_errors );
  541. }
  542.  
  543. /**
  544. * Verify a token with gRECAPTCHA.
  545. *
  546. * @since 4.5.7.2
  547. * @param string $token
  548. * @param string|null $secretkey if null -> verification of key
  549. * @return array|\WP_Error check $result['success'] = true
  550. */
  551. protected function verify_token( $token, $secretkey = null )
  552. {
  553. if( is_null( $secretkey ) )
  554. {
  555. $secretkey = $this->get_secret_key();
  556. }
  557.  
  558. $params = array(
  559. 'body' => array(
  560. 'secret' => $secretkey,
  561. 'response' => $token,
  562. 'remoteip' => $_SERVER['REMOTE_ADDR'],
  563. )
  564. );
  565.  
  566. $response = wp_safe_remote_post( av_google_recaptcha::API_VERIFY_URL, $params );
  567.  
  568. if( $response instanceof WP_Error )
  569. {
  570. $msg = $response->get_error_messages();
  571. $msg = implode( '<br />', $msg );
  572.  
  573. return new WP_Error( 'site_down', sprintf( __( 'Unable to communicate with gRECAPTCHA: <br /><br />%s', 'avia_framework' ), $msg ) );
  574. }
  575.  
  576. $code = wp_remote_retrieve_response_code( $response );
  577. if ( 200 != $code )
  578. {
  579. $msg = wp_remote_retrieve_response_message( $response );
  580. if( empty( $msg ) )
  581. {
  582. $msg = __( 'Unknown error code', 'avia_framework' );
  583. }
  584. return new WP_Error( 'invalid_response', sprintf( __( 'gRECAPTCHA returned error %d (= %s).', 'avia_framework' ), $code, $msg ) );
  585. }
  586.  
  587.  
  588. $body = wp_remote_retrieve_body( $response );
  589. $result = json_decode( $body, true );
  590.  
  591. if( true === $result['success'] )
  592. {
  593. return $result;
  594. }
  595.  
  596. if( isset( $result['error-codes'] ) && is_array( $result['error-codes'] ) )
  597. {
  598. foreach( $result['error-codes'] as $key => $value )
  599. {
  600. switch( $value )
  601. {
  602. case 'missing-input-secret':
  603. $result['error-codes'][ $key ] = __( 'The secret parameter is missing.', 'avia_framework' );
  604. break;
  605. case 'invalid-input-secret':
  606. $result['error-codes'][ $key ] = __( 'The secret parameter is invalid or malformed.', 'avia_framework' );
  607. break;
  608. case 'missing-input-response':
  609. $result['error-codes'][ $key ] = __( 'The response parameter is missing.', 'avia_framework' );
  610. break;
  611. case 'invalid-input-response':
  612. $result['error-codes'][ $key ] = __( 'The response parameter is invalid or malformed.', 'avia_framework' );
  613. break;
  614. case 'bad-request':
  615. $result['error-codes'][ $key ] = __( 'The request is invalid or malformed.', 'avia_framework' );
  616. break;
  617. case 'timeout-or-duplicate':
  618. $result['error-codes'][ $key ] = __( 'The response is no longer valid: either is too old or has been used previously.', 'avia_framework' );
  619. break;
  620. default:
  621. $result['error-codes'][ $key ] = sprintf( __( '%s - unknown error code', 'avia_framework' ), $value );
  622. }
  623. }
  624. }
  625.  
  626. return $result;
  627. }
  628.  
  629. /**
  630. * Callback - verifies the token and creates a transient if valid.
  631. * In case of a false score returns
  632. *
  633. * @since 4.5.7.2
  634. */
  635. public function handler_recaptcha_verify_frontend()
  636. {
  637. header( "Content-Type: application/json" );
  638. $response = array(
  639. 'success' => false,
  640. 'alert' => '',
  641. 'score_failed' => false,
  642. 'transient' => ''
  643. );
  644.  
  645. $show_extended_errors = $this->show_extended_errors();
  646.  
  647. /**
  648. * Nonce check removed with 4.7.4.1
  649. *
  650. * Makes problems with caching plugins.
  651. * As reCaptcha is bound to a site verifying the reCaptcha should be enough to verify a valid callback.
  652. *
  653. */
  654. // $nonce = isset( $_REQUEST['_wpnonce'] ) ? $_REQUEST['_wpnonce'] : '';
  655. // $result = wp_verify_nonce( $nonce, av_google_recaptcha::AJAX_VERIFY_NONCE );
  656. //
  657. // if( 1 !== $result )
  658. // {
  659. // $response['alert'] = __( 'Sorry, but the session time for this page has expired. Please reload the page.', 'avia_framework' );
  660. // if( true === $show_extended_errors )
  661. // {
  662. // $response['alert'] .= '<br />' . __( 'WP Nonce check failed.', 'avia_framework' );
  663. // }
  664. //
  665. // echo json_encode( $response );
  666. // exit;
  667. // }
  668.  
  669. $version = isset( $_REQUEST['version'] ) ? $_REQUEST['version'] : '';
  670. $token = isset( $_REQUEST['token'] ) ? $_REQUEST['token'] : '';
  671. $score = isset( $_REQUEST['score'] ) ? $_REQUEST['score'] : -1;
  672. $action = isset( $_REQUEST['recaptcha_action'] ) ? $_REQUEST['recaptcha_action'] : '';
  673. $secret_key = $this->get_secret_key( $version );
  674.  
  675.  
  676. $check = $this->verify_token( $token, $secret_key );
  677.  
  678. $validate_error = __( 'Sorry, but the verification failed. Please reload the page and try again.', 'avia_framework' );
  679.  
  680. if( true !== $check['success'] )
  681. {
  682. $response['alert'] = $validate_error;
  683. if( true === $show_extended_errors )
  684. {
  685. $response['alert'] .= '<br />' . __( 'API check returned false.', 'avia_framework' );
  686. }
  687.  
  688. echo json_encode( $response );
  689. exit;
  690. }
  691.  
  692. if( 'avia_recaptcha_v3' == $version )
  693. {
  694. if( ! isset( $check['score'] ) || ! isset( $check['action'] ) || ( $check['action'] != $action ) )
  695. {
  696. $response['alert'] = $validate_error;
  697. if( true === $show_extended_errors )
  698. {
  699. $response['alert'] .= '<br />' . __( 'Invalid V3 response. Actions:', 'avia_framework' ) . $check['action'] . '/' . $action;
  700. }
  701.  
  702. echo json_encode( $response );
  703. exit;
  704. }
  705.  
  706. if( (float) $score >= (float)$check['score'] )
  707. {
  708. if( true === $show_extended_errors )
  709. {
  710. $response['score_failed'] = sprintf( __( 'Score requested %s - returned %s', 'avia_framework' ), $score, $check['score'] );
  711. }
  712. else
  713. {
  714. $response['score_failed'] = true;
  715. }
  716.  
  717. echo json_encode( $response );
  718. exit;
  719. }
  720. }
  721.  
  722. $transient = uniqid( av_google_recaptcha::TRANSIENT_PREFIX, true );
  723.  
  724. /**
  725. * @since 4.5.7.2
  726. * @param int
  727. * @return int
  728. */
  729. $expiration = 30 * MINUTE_IN_SECONDS;
  730. $expiration = apply_filters( 'avf_recaptcha_transient_expiration', $expiration );
  731. if( ! is_numeric( $expiration ) )
  732. {
  733. $expiration = 30 * MINUTE_IN_SECONDS;
  734. }
  735.  
  736. set_transient( $transient, $version, $expiration );
  737.  
  738. $response['success'] = true;
  739. $response['transient'] = $transient;
  740.  
  741. echo json_encode( $response );
  742. exit;
  743. }
  744.  
  745.  
  746. /**
  747. * Check if we have a valid token.
  748. * This is also a fallback to prevent bots using same token several times.
  749. * In case $proceed !== true we also remove the transient to clean up.
  750. *
  751. * @since 4.5.7.2
  752. * @param boolean $proceed
  753. * @param array $new_post
  754. * @param array $form_params
  755. * @param avia_form $form_class
  756. * @return boolean|null true if you want to continue | null for error message
  757. */
  758. public function handler_avf_form_send( $proceed, array $new_post, array $form_params, avia_form $form_class )
  759. {
  760. $use_recaptcha = false;
  761.  
  762. foreach( $form_class->form_elements as $element )
  763. {
  764. if( isset( $element['type'] ) && ( 'grecaptcha' == $element['type'] ) )
  765. {
  766. $use_recaptcha = $element;
  767. break;
  768. }
  769. }
  770.  
  771. if( false === $use_recaptcha )
  772. {
  773. return $proceed;
  774. }
  775.  
  776. $show_extended_errors = $this->show_extended_errors();
  777. $token = isset( $element['token_input'] ) ? $element['token_input'] : '';
  778. $token_value = ( isset( $_REQUEST[ $token ] ) ) ? trim( $_REQUEST[ $token ] ) : '';
  779. $requested_version = ( isset( $_REQUEST[ $token . '-version' ] ) ) ? trim( $_REQUEST[ $token . '-version' ] ) : $element['version'];
  780.  
  781. if( true !== $proceed )
  782. {
  783. if( ! empty( $token_value ) )
  784. {
  785. delete_transient( $token_value );
  786. }
  787.  
  788. return $proceed;
  789. }
  790.  
  791. $reload_msg = '<br />' . __( 'Form could not be submitted. Please reload page and try again.', 'avia_framework' );
  792.  
  793. if( empty( $token_value ) )
  794. {
  795. $form_class->submit_error .= __( 'Invalid form for reCAPTCHA sent.', 'avia_framework' ) . $reload_msg;
  796. if( $show_extended_errors )
  797. {
  798. $form_class->submit_error .= '<br />' . __( 'Name for token field was missing.', 'avia_framework' );
  799. }
  800. return null;
  801. }
  802.  
  803. $version = get_transient( $token_value );
  804.  
  805. if( false === $version )
  806. {
  807. $form_class->submit_error .= __( 'Token to validate form already expired.', 'avia_framework' ) . $reload_msg;
  808. if( $show_extended_errors )
  809. {
  810. $form_class->submit_error .= '<br />' . __( 'Transient to verify form was missing or expired.', 'avia_framework' );
  811. }
  812. return null;
  813. }
  814.  
  815. delete_transient( $token_value );
  816.  
  817. if( $version != $requested_version )
  818. {
  819. $form_class->submit_error .= __( 'Token to validate form is not valid.', 'avia_framework' ) . $reload_msg;
  820. if( $show_extended_errors )
  821. {
  822. $form_class->submit_error .= '<br />' . __( 'reCAPTCHA version in transient differs from selected version in element.', 'avia_framework' );
  823. }
  824. return null;
  825. }
  826.  
  827. return $proceed;
  828. }
  829.  
  830.  
  831.  
  832.  
  833. /**
  834. * Output options page backend HTML or perform the key verification and return HTML message
  835. *
  836. * @since 4.5.7.2
  837. * @param string $api_key
  838. * @param boolean $ajax
  839. * @param array|boolean|null $check_keys
  840. * @param array $element used in backend for output of key verification
  841. * @return string|array
  842. */
  843. public function backend_html( $api_key = '', $ajax = true, $check_keys = false, $element = array() )
  844. {
  845. $return = array(
  846. 'html' => '',
  847. 'update_input_fields' => array()
  848. );
  849.  
  850. $api_key = trim( $api_key );
  851. $valid_key = false;
  852.  
  853. $response_text = __( 'Could not connect and verify these API Keys with Google reCAPTCHA.', 'avia_framework' );
  854. $response_class = "av-notice-error";
  855.  
  856. $content_default = '<h4>' . esc_html__( 'Troubleshooting:', 'avia_framework' ) . '</h4>';
  857. $content_default .= '<ol>';
  858. $content_default .= '<li>';
  859. $content_default .= esc_html__( 'Check if you typed the keys correctly.', 'avia_framework' );
  860. $content_default .= '</li>';
  861. $content_default .= '<li>';
  862. $content_default .= esc_html__( 'If you use the restriction setting on Google try to remove that, wait a few minutes for google to apply your changes and then check again if the keys work here. If it does, you probably have a syntax error in your referrer url', 'avia_framework' );
  863. $content_default .= '</li>';
  864. $content_default .= '<li>';
  865. $content_default .= esc_html__( 'If none of this helps: deactivate all plugins and then check if the API works by using the button above. If thats the case then one of your plugins is interfering.', 'avia_framework' );
  866. $content_default .= '</li>';
  867. $content_default .= '</ol>';
  868.  
  869.  
  870. if( $ajax )
  871. {
  872. /**
  873. * called by user pressing the ajax check button
  874. */
  875. $token = isset( $check_keys['token'] ) ? trim( $check_keys['token'] ) : '';
  876. $secretkey = isset( $check_keys['secretkey'] ) ? trim( $check_keys['secretkey'] ) : '';
  877. $version = isset( $check_keys['version'] ) ? trim( $check_keys['version'] ) : '';
  878. switch( $version )
  879. {
  880. case 'avia_recaptcha_v2':
  881. $verify_field = 'recaptcha_verified_keys_v2';
  882. break;
  883. case 'avia_recaptcha_v3':
  884. $verify_field = 'recaptcha_verified_keys_v3';
  885. break;
  886. default:
  887. $verify_field = '';
  888. break;
  889. }
  890.  
  891. $check = $this->verify_token( $token, $secretkey );
  892.  
  893. if( true === $check['success'] )
  894. {
  895. $valid_key = true;
  896. $response_class = '';
  897. $response_text = __( 'We were able to properly connect and verify your API keys with Google reCAPTCHA', 'avia_framework' );
  898.  
  899. //will be stripped from the final output but tells the ajax script to save the page after the check was performed
  900. $response_text .= ' avia_trigger_save';
  901.  
  902. $keys = array(
  903. $check_keys['version'],
  904. $check_keys['sitekey'],
  905. $check_keys['secretkey']
  906. );
  907. if( ! empty( $verify_field ) )
  908. {
  909. $return['update_input_fields'][ $verify_field ] = implode( ' ', $keys );
  910. }
  911. }
  912. else
  913. {
  914. $content_default = '';
  915. if( $check instanceof WP_Error )
  916. {
  917. $response_text = $check->get_error_message();
  918. }
  919. else
  920. {
  921. $msg = '';
  922.  
  923. if( is_array( $check['error-codes'] ) && count( $check['error-codes'] ) > 0 )
  924. {
  925. $msg = implode( '<br />', $check['error-codes'] );
  926. }
  927.  
  928. $response_text = __( 'Error on connecting to Google reCAPTCHA - please retry.', 'avia_framework' );
  929.  
  930. if( ! empty( $msg) )
  931. {
  932. $response_text .= '<br /><br />' . $msg;
  933. }
  934. }
  935.  
  936. if( ! empty( $verify_field ) )
  937. {
  938. $return['update_input_fields'][ $verify_field ] = 'verify_error';
  939. }
  940. }
  941. }
  942. else
  943. {
  944. /**
  945. * called on a normal page load. in this case we either show the stored result or if we got no stored result we show nothing
  946. */
  947. if( $this->is_activated() )
  948. {
  949. switch( $element['id'] )
  950. {
  951. case 'avia_recaptcha_key_verify_v2':
  952. $version = 'avia_recaptcha_v2';
  953. break;
  954. case 'avia_recaptcha_key_verify_v3':
  955. $version = 'avia_recaptcha_v3';
  956. break;
  957. default:
  958. $version = '';
  959. break;
  960. }
  961.  
  962. $keys = array(
  963. $version,
  964. $this->get_site_key( $version ),
  965. $this->get_secret_key( $version )
  966. );
  967.  
  968. $check = implode( ' ', $keys );
  969.  
  970. if( $this->get_verified_keys( $version ) == $check )
  971. {
  972. $valid_key = true;
  973. }
  974. else if( '' == $this->get_site_key( $version ) && '' == $this->get_secret_key( $version ) )
  975. {
  976. $response_class = '';
  977. $response_text = '';
  978. }
  979. else if( 'verify_error' == $this->get_verified_keys() )
  980. {
  981. $response_text = __( 'A connection error occurred last time we tried verify your keys with Google reCAPTCHA - please revalidate the keys.', 'avia_framework' );
  982. }
  983. else if( '' == $this->get_verified_keys( $version ) )
  984. {
  985. $response_text = __( 'Please verify the keys', 'avia_framework' );
  986. }
  987. else
  988. {
  989. $response_text = __( 'Please verify the keys - the last verified keys are different.', 'avia_framework' );
  990. }
  991.  
  992. $content_default = '';
  993. }
  994.  
  995. if( $valid_key )
  996. {
  997. $response_class = '';
  998. $response_text = __( 'Last time we checked we were able to connected to Google reCAPTCHA with your API keys', 'avia_framework' );
  999. }
  1000. }
  1001.  
  1002. if( $valid_key )
  1003. {
  1004. $content_default = __( 'If you ever change your API key or the URL restrictions of the key please verify the key here again, to test if it works properly','avia_framework');
  1005. }
  1006.  
  1007. $output = '';
  1008.  
  1009. if( ! empty( $response_text ) )
  1010. {
  1011. $output = "<div class='av-verification-response-wrapper'>";
  1012. $output .= "<div class='av-text-notice {$response_class}'>";
  1013. $output .= $response_text;
  1014. $output .= "</div>";
  1015. $output .= "<div class='av-verification-cell'>{$content_default}</div>";
  1016. $output .= "</div>";
  1017. }
  1018.  
  1019. if( $ajax )
  1020. {
  1021. $return['html'] = $output;
  1022. }
  1023. else
  1024. {
  1025. $return = $output;
  1026. }
  1027.  
  1028. return $return;
  1029. }
  1030.  
  1031. }
  1032.  
  1033. /**
  1034. * Returns the main instance of av_google_recaptcha to prevent the need to use globals.
  1035. *
  1036. * @since 4.5.7.2
  1037. * @return av_google_recaptcha
  1038. */
  1039. function Avia_Google_reCAPTCHA()
  1040. {
  1041. return av_google_recaptcha::instance();
  1042. }
  1043. }
  1044.  
  1045. Avia_Google_reCAPTCHA();
  1046.  
  1047.  
  1048. if( ! function_exists( 'av_recaptcha_api_check' ) )
  1049. {
  1050. /**
  1051. * Callback function:
  1052. * - ajax callback from verification button
  1053. * - php callback when creating output on option page
  1054. *
  1055. * @since 4.5.7.2
  1056. * @param string $value
  1057. * @param boolean $ajax
  1058. * @param array|null $js_value
  1059. * @param array $element
  1060. * @return string
  1061. */
  1062. function av_recaptcha_api_check( $value, $ajax = true, $js_value = null, $element = array() )
  1063. {
  1064. $api = Avia_Google_reCAPTCHA();
  1065. return $api->backend_html( $value, $ajax, $js_value, $element );
  1066. }
  1067.  
  1068. }
  1069.  
  1070.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement