Version Description
- Warning: I don't recommend Google reCAPTCHA v2. You should enable v3 in plugin settings (requires different keys)!
- New: Hooks - sgr_render_list + sgr_verify_list. You are able to customize where Google reCAPTCHA will be rendered and verified - e.g. via functions.php.
Download this release
Release Info
Developer | Minor |
Plugin | Simple Google reCAPTCHA |
Version | 4.0 |
Comparing to | |
See all releases |
Code changes from version 3.9 to 4.0
- entity.php +21 -41
- readme.txt +43 -6
- sgr.js +3 -3
- simple-google-recaptcha.php +180 -186
- uninstall.php +15 -14
entity.php
CHANGED
@@ -1,17 +1,20 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
|
4 |
-
|
5 |
|
6 |
if (!defined('ABSPATH')) {
|
7 |
-
die();
|
8 |
}
|
9 |
|
10 |
/**
|
11 |
-
* Class
|
|
|
12 |
*/
|
13 |
-
class
|
14 |
{
|
|
|
|
|
|
|
15 |
/** @var int */
|
16 |
const INT = 1;
|
17 |
|
@@ -19,25 +22,25 @@ class SimpleGoogleRecaptchaEntity
|
|
19 |
const STRING = 2;
|
20 |
|
21 |
/** @var string */
|
22 |
-
const PAGE_QUERY = '?page=
|
23 |
|
24 |
/** @var string */
|
25 |
-
const VERSION = '
|
26 |
|
27 |
/** @var string */
|
28 |
-
const LOGIN_DISABLE = '
|
29 |
|
30 |
/** @var string */
|
31 |
-
const BADGE_HIDE = '
|
32 |
|
33 |
/** @var string */
|
34 |
-
const SITE_KEY = '
|
35 |
|
36 |
/** @var string */
|
37 |
-
const SECRET_KEY = '
|
38 |
|
39 |
/** @var string */
|
40 |
-
const HASH = '
|
41 |
|
42 |
/** @var string */
|
43 |
private $name;
|
@@ -46,56 +49,34 @@ class SimpleGoogleRecaptchaEntity
|
|
46 |
private $type;
|
47 |
|
48 |
/** @var string|int */
|
49 |
-
private $value;
|
50 |
|
51 |
/**
|
52 |
* @param string $name
|
53 |
* @param int $type
|
54 |
-
* @param string|int $value
|
55 |
*/
|
56 |
-
public function __construct($name, $type
|
57 |
{
|
58 |
$this->name = $name;
|
59 |
$this->type = $type;
|
60 |
-
$this->value = $value;
|
61 |
}
|
62 |
|
63 |
/**
|
64 |
* @return string
|
65 |
*/
|
66 |
-
public function getName()
|
67 |
{
|
68 |
return $this->name;
|
69 |
}
|
70 |
|
71 |
-
/**
|
72 |
-
* @param string $name
|
73 |
-
* @return Entity
|
74 |
-
*/
|
75 |
-
public function setName($name)
|
76 |
-
{
|
77 |
-
$this->name = $name;
|
78 |
-
return $this;
|
79 |
-
}
|
80 |
-
|
81 |
/**
|
82 |
* @return int
|
83 |
*/
|
84 |
-
public function getType()
|
85 |
{
|
86 |
return $this->type;
|
87 |
}
|
88 |
|
89 |
-
/**
|
90 |
-
* @param int $type
|
91 |
-
* @return Entity
|
92 |
-
*/
|
93 |
-
public function setType($type)
|
94 |
-
{
|
95 |
-
$this->type = $type;
|
96 |
-
return $this;
|
97 |
-
}
|
98 |
-
|
99 |
/**
|
100 |
* @return int|string
|
101 |
*/
|
@@ -105,12 +86,11 @@ class SimpleGoogleRecaptchaEntity
|
|
105 |
}
|
106 |
|
107 |
/**
|
108 |
-
* @param
|
109 |
-
* @return
|
110 |
*/
|
111 |
public function setValue($value)
|
112 |
{
|
113 |
$this->value = $value;
|
114 |
-
return $this;
|
115 |
}
|
116 |
}
|
1 |
<?php
|
2 |
|
3 |
+
namespace NovaMi\WordPress\SimpleGoogleRecaptcha;
|
|
|
4 |
|
5 |
if (!defined('ABSPATH')) {
|
6 |
+
die('Direct access not allowed');
|
7 |
}
|
8 |
|
9 |
/**
|
10 |
+
* Class Entity
|
11 |
+
* @package NovaMi\WordPress\SimpleGoogleRecaptcha
|
12 |
*/
|
13 |
+
class Entity
|
14 |
{
|
15 |
+
/** @var string */
|
16 |
+
const PREFIX = 'sgr_';
|
17 |
+
|
18 |
/** @var int */
|
19 |
const INT = 1;
|
20 |
|
22 |
const STRING = 2;
|
23 |
|
24 |
/** @var string */
|
25 |
+
const PAGE_QUERY = '?page=' . self::PREFIX . 'options';
|
26 |
|
27 |
/** @var string */
|
28 |
+
const VERSION = self::PREFIX . 'version';
|
29 |
|
30 |
/** @var string */
|
31 |
+
const LOGIN_DISABLE = self::PREFIX . 'login_disable';
|
32 |
|
33 |
/** @var string */
|
34 |
+
const BADGE_HIDE = self::PREFIX . 'badge_hide';
|
35 |
|
36 |
/** @var string */
|
37 |
+
const SITE_KEY = self::PREFIX . 'site_key';
|
38 |
|
39 |
/** @var string */
|
40 |
+
const SECRET_KEY = self::PREFIX . 'secret_key';
|
41 |
|
42 |
/** @var string */
|
43 |
+
const HASH = self::PREFIX . 'hash';
|
44 |
|
45 |
/** @var string */
|
46 |
private $name;
|
49 |
private $type;
|
50 |
|
51 |
/** @var string|int */
|
52 |
+
private $value = '';
|
53 |
|
54 |
/**
|
55 |
* @param string $name
|
56 |
* @param int $type
|
|
|
57 |
*/
|
58 |
+
public function __construct(string $name, int $type = self::INT)
|
59 |
{
|
60 |
$this->name = $name;
|
61 |
$this->type = $type;
|
|
|
62 |
}
|
63 |
|
64 |
/**
|
65 |
* @return string
|
66 |
*/
|
67 |
+
public function getName(): string
|
68 |
{
|
69 |
return $this->name;
|
70 |
}
|
71 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
72 |
/**
|
73 |
* @return int
|
74 |
*/
|
75 |
+
public function getType(): int
|
76 |
{
|
77 |
return $this->type;
|
78 |
}
|
79 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
80 |
/**
|
81 |
* @return int|string
|
82 |
*/
|
86 |
}
|
87 |
|
88 |
/**
|
89 |
+
* @param $value
|
90 |
+
* @return void
|
91 |
*/
|
92 |
public function setValue($value)
|
93 |
{
|
94 |
$this->value = $value;
|
|
|
95 |
}
|
96 |
}
|
readme.txt
CHANGED
@@ -3,8 +3,8 @@ Contributors: Minor
|
|
3 |
Tags: recaptcha, spam, protect, google, invisible
|
4 |
Requires at least: 4.6
|
5 |
Tested up to: 6.0
|
6 |
-
Stable tag:
|
7 |
-
Requires PHP: 7.
|
8 |
License: GPLv3
|
9 |
License URI: http://www.gnu.org/licenses/gpl-3.0.html
|
10 |
Donate link: https://www.paypal.me/NovaMi
|
@@ -40,17 +40,50 @@ If you write me (on support forum etc.), be patient, please. I work on this plug
|
|
40 |
|
41 |
== Frequently Asked Questions ==
|
42 |
= Why to install this plugin? =
|
43 |
-
* No ads
|
44 |
-
* Only
|
45 |
-
*
|
46 |
* Possibility to replace v3 reCAPTCHA badge by text
|
47 |
* reCAPTCHA language based on WordPress settings
|
48 |
* Works in countries where Google domain is blocked
|
49 |
-
* Emergency reCAPTCHA deactivate link
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
|
51 |
= How to disable this plugin? =
|
52 |
Use standard WordPress Plugins page. In emergency case, rename plugin folder under /wp-content/plugins/ over FTP access or use emergency reCAPTCHA deactivate link.
|
53 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
== Screenshots ==
|
55 |
1. New comment
|
56 |
2. New password
|
@@ -61,6 +94,10 @@ Use standard WordPress Plugins page. In emergency case, rename plugin folder und
|
|
61 |
7. Emergency reCAPTCHA deactivate link
|
62 |
|
63 |
== Changelog ==
|
|
|
|
|
|
|
|
|
64 |
= 3.9 =
|
65 |
* Bugfix: reCAPTCHA verification has been rewritten. More reliable and prevents brute force attacks now.
|
66 |
|
3 |
Tags: recaptcha, spam, protect, google, invisible
|
4 |
Requires at least: 4.6
|
5 |
Tested up to: 6.0
|
6 |
+
Stable tag: 4.0
|
7 |
+
Requires PHP: 7.2
|
8 |
License: GPLv3
|
9 |
License URI: http://www.gnu.org/licenses/gpl-3.0.html
|
10 |
Donate link: https://www.paypal.me/NovaMi
|
40 |
|
41 |
== Frequently Asked Questions ==
|
42 |
= Why to install this plugin? =
|
43 |
+
* No ads, user tracking, send statistics neither survey
|
44 |
+
* Only arround 20kB size (without readme file)
|
45 |
+
* Google reCAPTCHA v3 (invisible) support
|
46 |
* Possibility to replace v3 reCAPTCHA badge by text
|
47 |
* reCAPTCHA language based on WordPress settings
|
48 |
* Works in countries where Google domain is blocked
|
49 |
+
* Emergency reCAPTCHA deactivate link for admin
|
50 |
+
* Hooks - Possibility to customize where reCAPTCHA will be rendered and verified
|
51 |
+
|
52 |
+
= In case you have a problem =
|
53 |
+
1. Important message could be shown in browser console (F12) on problematic page
|
54 |
+
2. Double check if you have correct keys in settings - is those keys for correct version reCAPTCHA?
|
55 |
+
3. Try to create new website in Google reCAPTCHA console (and use different website name)
|
56 |
|
57 |
= How to disable this plugin? =
|
58 |
Use standard WordPress Plugins page. In emergency case, rename plugin folder under /wp-content/plugins/ over FTP access or use emergency reCAPTCHA deactivate link.
|
59 |
|
60 |
+
= How to use hooks? =
|
61 |
+
For example, you can use this in your global functions.php file:
|
62 |
+
|
63 |
+
<pre><code>
|
64 |
+
function customSgrRenderList(array $list): array //Where reCAPTCHA is rendered
|
65 |
+
{
|
66 |
+
//unset($list[0]);
|
67 |
+
$list[] = 'register_form';
|
68 |
+
|
69 |
+
return $list;
|
70 |
+
}
|
71 |
+
|
72 |
+
add_action('sgr_render_list', 'customSgrRenderList');
|
73 |
+
|
74 |
+
function customSgrVerifyList(array $list): array //Where reCAPTCHA is verified
|
75 |
+
{
|
76 |
+
//unset($list[0]);
|
77 |
+
$list[] = 'lostpassword_post';
|
78 |
+
|
79 |
+
return $list;
|
80 |
+
}
|
81 |
+
|
82 |
+
add_action('sgr_verify_list', 'customSgrVerifyList');
|
83 |
+
</code></pre>
|
84 |
+
|
85 |
+
Variable $list is array of default hooks, indexed by numbers.
|
86 |
+
|
87 |
== Screenshots ==
|
88 |
1. New comment
|
89 |
2. New password
|
94 |
7. Emergency reCAPTCHA deactivate link
|
95 |
|
96 |
== Changelog ==
|
97 |
+
= 4.0 =
|
98 |
+
* Warning: I don't recommend Google reCAPTCHA v2. You should enable v3 in plugin settings (requires different keys)!
|
99 |
+
* New: Hooks - sgr_render_list + sgr_verify_list. You are able to customize where Google reCAPTCHA will be rendered and verified - e.g. via functions.php.
|
100 |
+
|
101 |
= 3.9 =
|
102 |
* Bugfix: reCAPTCHA verification has been rewritten. More reliable and prevents brute force attacks now.
|
103 |
|
sgr.js
CHANGED
@@ -2,7 +2,7 @@ function sgr_2() {
|
|
2 |
console.log('SGR_2 loaded!');
|
3 |
let recaptcha = document.getElementsByClassName('sgr-main');
|
4 |
for (let i = 0; i < recaptcha.length; i++) {
|
5 |
-
grecaptcha.render(recaptcha.item(i), {'sitekey':
|
6 |
}
|
7 |
}
|
8 |
|
@@ -10,7 +10,7 @@ function sgr_3() {
|
|
10 |
console.log('SGR_3 loaded!');
|
11 |
let actionName = window.location.pathname;
|
12 |
actionName = actionName.replace(/[^a-zA-Z/]/g, '_');
|
13 |
-
grecaptcha.execute(
|
14 |
let recaptcha = document.getElementsByClassName('sgr-main');
|
15 |
for (let i = 0; i < recaptcha.length; i++) {
|
16 |
recaptcha.item(i).value = token;
|
@@ -31,7 +31,7 @@ document.addEventListener('DOMContentLoaded', function (event) {
|
|
31 |
let sgr_site_key = document.getElementById('sgr_site_key');
|
32 |
let sgr_secret_key = document.getElementById('sgr_secret_key');
|
33 |
|
34 |
-
if (sgr_site_key.value ===
|
35 |
sgr_site_key.value = '';
|
36 |
sgr_secret_key.value = '';
|
37 |
}
|
2 |
console.log('SGR_2 loaded!');
|
3 |
let recaptcha = document.getElementsByClassName('sgr-main');
|
4 |
for (let i = 0; i < recaptcha.length; i++) {
|
5 |
+
grecaptcha.render(recaptcha.item(i), {'sitekey': sgr.sgr_site_key});
|
6 |
}
|
7 |
}
|
8 |
|
10 |
console.log('SGR_3 loaded!');
|
11 |
let actionName = window.location.pathname;
|
12 |
actionName = actionName.replace(/[^a-zA-Z/]/g, '_');
|
13 |
+
grecaptcha.execute(sgr.sgr_site_key, {action: 'sgr_' + actionName}).then(function (token) {
|
14 |
let recaptcha = document.getElementsByClassName('sgr-main');
|
15 |
for (let i = 0; i < recaptcha.length; i++) {
|
16 |
recaptcha.item(i).value = token;
|
31 |
let sgr_site_key = document.getElementById('sgr_site_key');
|
32 |
let sgr_secret_key = document.getElementById('sgr_secret_key');
|
33 |
|
34 |
+
if (sgr_site_key.value === sgr.sgr_site_key) {
|
35 |
sgr_site_key.value = '';
|
36 |
sgr_secret_key.value = '';
|
37 |
}
|
simple-google-recaptcha.php
CHANGED
@@ -2,26 +2,24 @@
|
|
2 |
/*
|
3 |
* Plugin Name: Simple Google reCAPTCHA
|
4 |
* Description: Simply protect your WordPress against spam comments and brute-force attacks, thanks to Google reCAPTCHA!
|
5 |
-
* Version:
|
6 |
* Author: Michal Novák
|
7 |
* Author URI: https://www.novami.cz
|
8 |
* License: GPLv3
|
9 |
* Text Domain: simple-google-recaptcha
|
10 |
*/
|
11 |
|
12 |
-
|
13 |
-
|
14 |
|
15 |
if (!defined('ABSPATH')) {
|
16 |
die('Direct access not allowed!');
|
17 |
}
|
18 |
|
19 |
-
include sprintf('%s/entity.php', dirname(__FILE__));
|
20 |
-
|
21 |
/**
|
22 |
-
* Class
|
|
|
23 |
*/
|
24 |
-
class
|
25 |
{
|
26 |
/** @var string */
|
27 |
const UPDATE = 'update';
|
@@ -30,21 +28,9 @@ class SimpleGoogleRecaptcha
|
|
30 |
const DISABLE = 'disable';
|
31 |
|
32 |
/** @var string */
|
33 |
-
const
|
34 |
-
|
35 |
-
/** @var string */
|
36 |
-
const SGR_V2 = 'v2 "I\'m not a robot" Checkbox';
|
37 |
-
|
38 |
-
/** @var string */
|
39 |
-
const SGR_V3 = 'v3';
|
40 |
-
|
41 |
-
/** @var string */
|
42 |
-
const SGR_MAIN = 'sgr_main';
|
43 |
|
44 |
-
/** @var
|
45 |
-
const SGR_ACTION = 'sgr_action';
|
46 |
-
|
47 |
-
/** @var SimpleGoogleRecaptcha */
|
48 |
public static $instance;
|
49 |
|
50 |
/** @var string */
|
@@ -54,7 +40,7 @@ class SimpleGoogleRecaptcha
|
|
54 |
private $options;
|
55 |
|
56 |
/**
|
57 |
-
*
|
58 |
*/
|
59 |
private function __construct()
|
60 |
{
|
@@ -63,10 +49,12 @@ class SimpleGoogleRecaptcha
|
|
63 |
}
|
64 |
|
65 |
/**
|
66 |
-
* @return
|
67 |
*/
|
68 |
-
public static function getInstance()
|
69 |
{
|
|
|
|
|
70 |
if (!self::$instance instanceof self) {
|
71 |
self::$instance = new self();
|
72 |
}
|
@@ -78,31 +66,56 @@ class SimpleGoogleRecaptcha
|
|
78 |
* @param int $type
|
79 |
* @return int
|
80 |
*/
|
81 |
-
private function getOptionFilter($type)
|
82 |
{
|
83 |
return $type === Entity::INT ? FILTER_SANITIZE_NUMBER_INT : FILTER_SANITIZE_FULL_SPECIAL_CHARS;
|
84 |
}
|
85 |
|
86 |
/**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
87 |
* @return void
|
88 |
*/
|
89 |
-
private function
|
90 |
{
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
|
|
|
|
|
|
|
|
96 |
}
|
97 |
}
|
98 |
|
99 |
/**
|
100 |
-
* @param
|
101 |
-
* @return
|
102 |
*/
|
103 |
-
|
104 |
{
|
105 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
106 |
}
|
107 |
|
108 |
/**
|
@@ -115,18 +128,28 @@ class SimpleGoogleRecaptcha
|
|
115 |
$this->options = [
|
116 |
Entity::SITE_KEY => new Entity(__('Site Key', 'simple-google-recaptcha'), Entity::STRING),
|
117 |
Entity::SECRET_KEY => new Entity(__('Secret Key', 'simple-google-recaptcha'), Entity::STRING),
|
118 |
-
Entity::LOGIN_DISABLE => new Entity(__('Disable on login form', 'simple-google-recaptcha')
|
119 |
-
Entity::VERSION => new Entity(__('Enable reCAPTCHA v3', 'simple-google-recaptcha')
|
120 |
-
Entity::BADGE_HIDE => new Entity(__('Hide reCAPTCHA v3 badge', 'simple-google-recaptcha')
|
121 |
];
|
122 |
|
123 |
$this->updateSettings();
|
124 |
|
125 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
|
127 |
$this->disableProtection();
|
128 |
|
129 |
-
$this->
|
|
|
130 |
|
131 |
$this->frontend();
|
132 |
|
@@ -144,13 +167,14 @@ class SimpleGoogleRecaptcha
|
|
144 |
|
145 |
if ($postAction === self::UPDATE && current_user_can('manage_options')) {
|
146 |
$hash = null;
|
|
|
147 |
foreach ($this->options as $key => $option) {
|
148 |
$postValue = filter_input(INPUT_POST, $key, $this->getOptionFilter($option->getType()));
|
149 |
|
150 |
if ($postValue) {
|
151 |
update_option($key, $postValue);
|
152 |
|
153 |
-
if (substr($key, -strlen(
|
154 |
$hash .= $postValue;
|
155 |
}
|
156 |
} else {
|
@@ -165,22 +189,24 @@ class SimpleGoogleRecaptcha
|
|
165 |
}
|
166 |
|
167 |
/**
|
168 |
-
* @param $links
|
169 |
* @return array
|
170 |
*/
|
171 |
-
public function actionLinks($links)
|
172 |
{
|
173 |
return array_merge(['settings' => sprintf('<a href="options-general.php%s">%s</a>', Entity::PAGE_QUERY, __('Settings', 'simple-google-recaptcha'))], $links);
|
174 |
}
|
175 |
|
176 |
/**
|
177 |
-
* @param $plugin
|
178 |
* @return void
|
179 |
*/
|
180 |
-
public function activation($plugin)
|
181 |
{
|
182 |
if ($plugin === plugin_basename(__FILE__) && (!get_option(Entity::SITE_KEY) || !get_option(Entity::SECRET_KEY))) {
|
183 |
-
|
|
|
|
|
184 |
}
|
185 |
}
|
186 |
|
@@ -191,14 +217,14 @@ class SimpleGoogleRecaptcha
|
|
191 |
{
|
192 |
echo sprintf('<div class="wrap"><h1>%s - %s</h1><form method="post" action="%s">', $this->pluginName, __('Settings', 'simple-google-recaptcha'), Entity::PAGE_QUERY);
|
193 |
|
194 |
-
settings_fields('
|
195 |
-
do_settings_sections('
|
196 |
|
197 |
echo sprintf('<input type="hidden" name="%s" value="%s">', self::SGR_ACTION, self::UPDATE);
|
198 |
|
199 |
submit_button();
|
200 |
|
201 |
-
echo sprintf('%s</form>%s</div>', PHP_EOL, $this->
|
202 |
}
|
203 |
|
204 |
/**
|
@@ -206,92 +232,80 @@ class SimpleGoogleRecaptcha
|
|
206 |
*/
|
207 |
public function adminMenu()
|
208 |
{
|
209 |
-
add_submenu_page('options-general.php', $this->pluginName, 'Google reCAPTCHA', 'manage_options', '
|
210 |
add_action('admin_init', [$this, 'displayOptions']);
|
211 |
}
|
212 |
|
213 |
/**
|
214 |
* @return void
|
215 |
*/
|
216 |
-
public function
|
217 |
{
|
218 |
-
|
219 |
-
}
|
220 |
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
echo sprintf('<input type="text" name="%1$s" class="regular-text" id="%1$s" value="%2$s" />', Entity::SECRET_KEY, $this->getOptionValue(Entity::SECRET_KEY));
|
227 |
}
|
228 |
|
229 |
/**
|
230 |
* @return void
|
231 |
*/
|
232 |
-
public function
|
233 |
{
|
234 |
-
|
235 |
-
|
236 |
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
public function display_sgr_version()
|
241 |
-
{
|
242 |
-
echo sprintf('<input type="checkbox" name="%1$s" id="%1$s" value="3" %2$s />', Entity::VERSION, checked(3, $this->getOptionValue(Entity::VERSION), false));
|
243 |
-
}
|
244 |
|
245 |
-
|
246 |
-
* @return void
|
247 |
-
*/
|
248 |
-
public function display_sgr_badge_hide()
|
249 |
-
{
|
250 |
-
echo sprintf('<input type="checkbox" name="%1$s" id="%1$s" value="1" %2$s />', Entity::BADGE_HIDE, checked(1, $this->getOptionValue(Entity::BADGE_HIDE), false));
|
251 |
}
|
252 |
|
253 |
/**
|
254 |
-
* @
|
|
|
255 |
*/
|
256 |
-
public function
|
257 |
{
|
258 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
259 |
|
260 |
-
|
261 |
-
|
262 |
-
register_setting('sgr_header_section', $key);
|
263 |
}
|
264 |
-
}
|
265 |
-
|
266 |
-
/**
|
267 |
-
* @return void
|
268 |
-
*/
|
269 |
-
public function enqueueMain()
|
270 |
-
{
|
271 |
-
$jsName = 'sgr.js';
|
272 |
-
$jsPath = sprintf('%s%s', plugin_dir_path(__FILE__), $jsName);
|
273 |
-
wp_enqueue_script(self::SGR_MAIN, sprintf('%s%s', plugin_dir_url(__FILE__), $jsName), [], filemtime($jsPath));
|
274 |
-
|
275 |
-
wp_localize_script(self::SGR_MAIN, self::SGR_MAIN, [Entity::SITE_KEY => $this->getOptionValue(Entity::SITE_KEY)]);
|
276 |
|
277 |
-
$
|
278 |
-
$cssPath = sprintf('%s%s', plugin_dir_path(__FILE__), $cssName);
|
279 |
-
wp_enqueue_style(self::SGR_MAIN, sprintf('%s%s', plugin_dir_url(__FILE__), $cssName), [], filemtime($cssPath));
|
280 |
}
|
281 |
|
282 |
/**
|
283 |
-
* @
|
|
|
284 |
*/
|
285 |
-
public function
|
286 |
{
|
287 |
-
$
|
288 |
-
|
|
|
|
|
|
|
|
|
|
|
289 |
|
290 |
-
if (
|
291 |
-
$
|
292 |
}
|
293 |
|
294 |
-
|
295 |
}
|
296 |
|
297 |
/**
|
@@ -304,79 +318,50 @@ class SimpleGoogleRecaptcha
|
|
304 |
$recaptchaSecretKey = $this->getOptionValue(Entity::SECRET_KEY);
|
305 |
|
306 |
if ($rcpActivate && $recaptchaSiteKey && $recaptchaSecretKey) {
|
307 |
-
|
308 |
-
|
309 |
-
'comment_form_after_fields',
|
310 |
-
'lostpassword_form',
|
311 |
-
'register_form',
|
312 |
-
'woocommerce_lostpassword_form',
|
313 |
-
'woocommerce_register_form'
|
314 |
-
];
|
315 |
|
316 |
-
$
|
317 |
-
'
|
318 |
-
'
|
319 |
-
'preprocess_comment',
|
320 |
-
'registration_errors',
|
321 |
-
'woocommerce_register_post'
|
322 |
-
];
|
323 |
-
|
324 |
-
if (!$this->getOptionValue(Entity::LOGIN_DISABLE)) {
|
325 |
-
array_push($sgr_display_list, 'login_form', 'woocommerce_login_form');
|
326 |
-
$sgr_verify_list[] = 'authenticate';
|
327 |
}
|
328 |
|
329 |
-
|
330 |
-
|
331 |
-
foreach ($sgr_display_list as $sgr_display) {
|
332 |
-
add_action($sgr_display, [$this, 'enqueueScripts']);
|
333 |
-
add_action($sgr_display, [$this, $sgrDisplay]);
|
334 |
-
}
|
335 |
-
|
336 |
-
foreach ($sgr_verify_list as $sgr_verify) {
|
337 |
-
add_action($sgr_verify, [$this, 'verify']);
|
338 |
}
|
339 |
}
|
340 |
}
|
341 |
|
342 |
/**
|
343 |
-
* @return
|
344 |
*/
|
345 |
-
public function
|
346 |
{
|
347 |
-
$this->
|
|
|
|
|
|
|
348 |
|
349 |
-
echo '<div class="sgr-main"></div>';
|
|
|
|
|
350 |
}
|
351 |
|
352 |
/**
|
353 |
-
* @return
|
354 |
*/
|
355 |
-
|
356 |
{
|
357 |
-
$
|
358 |
|
359 |
if ($this->getOptionValue(Entity::BADGE_HIDE)) {
|
360 |
-
$
|
361 |
-
$cssPath = sprintf('%s%s', plugin_dir_path(__FILE__), $cssName);
|
362 |
-
wp_enqueue_style('sgr_hide', sprintf('%s%s', plugin_dir_url(__FILE__), $cssName), [], filemtime($cssPath));
|
363 |
|
364 |
-
$
|
|
|
365 |
}
|
366 |
|
367 |
-
$
|
368 |
-
|
369 |
-
echo sprintf('<input type="hidden" name="g-recaptcha-response" class="sgr-main">%s', $badgeText);
|
370 |
-
}
|
371 |
-
|
372 |
-
/**
|
373 |
-
* @return void
|
374 |
-
*/
|
375 |
-
private function displayDisableProtection()
|
376 |
-
{
|
377 |
-
if ($this->adminCookieHash()) {
|
378 |
-
echo sprintf('<p class="sgr-infotext"><a href="?%s=%s">%s</a></p>', self::SGR_ACTION, self::DISABLE, __('Emergency reCAPTCHA deactivate', 'simple-google-recaptcha'));
|
379 |
-
}
|
380 |
}
|
381 |
|
382 |
/**
|
@@ -394,16 +379,17 @@ class SimpleGoogleRecaptcha
|
|
394 |
|
395 |
foreach ($keys as $key) {
|
396 |
delete_option($key);
|
|
|
397 |
$this->options[$key]->setValue('');
|
398 |
}
|
399 |
}
|
400 |
}
|
401 |
|
402 |
/**
|
403 |
-
* @param $error_code
|
404 |
-
* @return string
|
405 |
*/
|
406 |
-
private function errorMessage($error_code)
|
407 |
{
|
408 |
switch ($error_code) {
|
409 |
case 'missing-input-secret':
|
@@ -424,21 +410,39 @@ class SimpleGoogleRecaptcha
|
|
424 |
}
|
425 |
|
426 |
/**
|
427 |
-
* @param $response
|
428 |
-
* @return array
|
429 |
*/
|
430 |
-
private function
|
431 |
{
|
432 |
$secretKey = $this->getOptionValue(Entity::SECRET_KEY);
|
433 |
$rcpUrl = sprintf('https://www.recaptcha.net/recaptcha/api/siteverify?secret=%s&response=%s', $secretKey, $response);
|
434 |
-
$response =
|
435 |
|
436 |
-
$
|
437 |
'success' => false,
|
438 |
'error-codes' => ['general-fail']
|
439 |
];
|
440 |
|
441 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
442 |
}
|
443 |
|
444 |
/**
|
@@ -449,23 +453,17 @@ class SimpleGoogleRecaptcha
|
|
449 |
{
|
450 |
if (!empty($_POST)) {
|
451 |
$response = strval(filter_input(INPUT_POST, 'g-recaptcha-response', FILTER_SANITIZE_FULL_SPECIAL_CHARS));
|
452 |
-
$parsedResponse = $this->
|
|
|
453 |
|
454 |
-
if (
|
455 |
-
|
456 |
} else {
|
457 |
-
$
|
458 |
-
|
459 |
-
$failedMsg = '<p><strong>%s:</strong> Google reCAPTCHA %s. %s</p>';
|
460 |
-
$error = __('Error', 'simple-google-recaptcha');
|
461 |
-
$verificationFailed = __('verification failed', 'simple-google-recaptcha');
|
462 |
-
|
463 |
-
if (!$response) {
|
464 |
-
wp_die(sprintf($failedMsg, $error, $verificationFailed, __('Do you have JavaScript enabled?', 'simple-google-recaptcha')), $errorTitle, $errorParams);
|
465 |
}
|
466 |
|
467 |
-
|
468 |
-
wp_die(sprintf($failedMsg, $error, $verificationFailed, $this->errorMessage($recaptcha_error_code)), $errorTitle, $errorParams);
|
469 |
}
|
470 |
}
|
471 |
}
|
@@ -473,7 +471,7 @@ class SimpleGoogleRecaptcha
|
|
473 |
/**
|
474 |
* @return string
|
475 |
*/
|
476 |
-
public function
|
477 |
{
|
478 |
$class = 'warning';
|
479 |
$name = __('Notice', 'simple-google-recaptcha');
|
@@ -487,7 +485,7 @@ class SimpleGoogleRecaptcha
|
|
487 |
$msg = __('You have to <a href="https://www.google.com/recaptcha/admin" rel="external">register your domain</a>, get required Google reCAPTCHA keys %s and save them bellow.', 'simple-google-recaptcha');
|
488 |
}
|
489 |
|
490 |
-
$type = $this->getOptionValue(Entity::VERSION) === 3 ?
|
491 |
|
492 |
return sprintf('<div class="notice notice-%s"><p><strong>%s:</strong> Google reCAPTCHA %s!</p><p>%s</p></div>', $class, $name, $status, sprintf($msg, $type));
|
493 |
}
|
@@ -495,16 +493,12 @@ class SimpleGoogleRecaptcha
|
|
495 |
/**
|
496 |
* @return bool
|
497 |
*/
|
498 |
-
public function adminCookieHash()
|
499 |
{
|
500 |
$cookieHash = filter_input(INPUT_COOKIE, Entity::HASH, FILTER_SANITIZE_SPECIAL_CHARS);
|
501 |
|
502 |
-
|
503 |
-
return true;
|
504 |
-
} else {
|
505 |
-
return false;
|
506 |
-
}
|
507 |
}
|
508 |
}
|
509 |
|
510 |
-
|
2 |
/*
|
3 |
* Plugin Name: Simple Google reCAPTCHA
|
4 |
* Description: Simply protect your WordPress against spam comments and brute-force attacks, thanks to Google reCAPTCHA!
|
5 |
+
* Version: 4.0
|
6 |
* Author: Michal Novák
|
7 |
* Author URI: https://www.novami.cz
|
8 |
* License: GPLv3
|
9 |
* Text Domain: simple-google-recaptcha
|
10 |
*/
|
11 |
|
12 |
+
namespace NovaMi\WordPress\SimpleGoogleRecaptcha;
|
|
|
13 |
|
14 |
if (!defined('ABSPATH')) {
|
15 |
die('Direct access not allowed!');
|
16 |
}
|
17 |
|
|
|
|
|
18 |
/**
|
19 |
+
* Class Core
|
20 |
+
* @package NovaMi\WordPress\SimpleGoogleRecaptcha
|
21 |
*/
|
22 |
+
class Core
|
23 |
{
|
24 |
/** @var string */
|
25 |
const UPDATE = 'update';
|
28 |
const DISABLE = 'disable';
|
29 |
|
30 |
/** @var string */
|
31 |
+
const SGR_ACTION = Entity::PREFIX . 'action';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
|
33 |
+
/** @var Core */
|
|
|
|
|
|
|
34 |
public static $instance;
|
35 |
|
36 |
/** @var string */
|
40 |
private $options;
|
41 |
|
42 |
/**
|
43 |
+
* Core constructor.
|
44 |
*/
|
45 |
private function __construct()
|
46 |
{
|
49 |
}
|
50 |
|
51 |
/**
|
52 |
+
* @return Core
|
53 |
*/
|
54 |
+
public static function getInstance(): Core
|
55 |
{
|
56 |
+
require_once dirname(__FILE__) . '/entity.php';
|
57 |
+
|
58 |
if (!self::$instance instanceof self) {
|
59 |
self::$instance = new self();
|
60 |
}
|
66 |
* @param int $type
|
67 |
* @return int
|
68 |
*/
|
69 |
+
private function getOptionFilter(int $type): int
|
70 |
{
|
71 |
return $type === Entity::INT ? FILTER_SANITIZE_NUMBER_INT : FILTER_SANITIZE_FULL_SPECIAL_CHARS;
|
72 |
}
|
73 |
|
74 |
/**
|
75 |
+
* @param string $id
|
76 |
+
* @return int|string
|
77 |
+
*/
|
78 |
+
private function getOptionValue(string $id)
|
79 |
+
{
|
80 |
+
return $this->options[$id]->getValue() ?? '';
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* @param string $ext
|
85 |
+
* @param string $name
|
86 |
* @return void
|
87 |
*/
|
88 |
+
private function enqueue(string $ext = 'js', string $name = 'sgr')
|
89 |
{
|
90 |
+
$fileName = $name . '.' . $ext;
|
91 |
+
$dirPath = plugin_dir_path(__FILE__) . $fileName;
|
92 |
+
$dirUrl = plugin_dir_url(__FILE__) . $fileName;
|
93 |
+
|
94 |
+
if ($ext === 'js') {
|
95 |
+
wp_enqueue_script($name, $dirUrl, [], filemtime($dirPath));
|
96 |
+
wp_localize_script($name, $name, [Entity::SITE_KEY => $this->getOptionValue(Entity::SITE_KEY)]);
|
97 |
+
} else {
|
98 |
+
wp_enqueue_style($name, $dirUrl, [], filemtime($dirPath));
|
99 |
}
|
100 |
}
|
101 |
|
102 |
/**
|
103 |
+
* @param array $atts
|
104 |
+
* @return void
|
105 |
*/
|
106 |
+
public function displayInput(array $atts)
|
107 |
{
|
108 |
+
$key = $atts['key'];
|
109 |
+
$type = $atts['type'];
|
110 |
+
$val = $this->getOptionValue($key);
|
111 |
+
|
112 |
+
if ($type === Entity::INT) {
|
113 |
+
$defaultVal = $key === Entity::VERSION ? 3 : 1;
|
114 |
+
|
115 |
+
echo sprintf('<input type="checkbox" name="%1$s" id="%1$s" value="%2$d" %3$s />', $key, $defaultVal, checked($defaultVal, $val, false));
|
116 |
+
} else {
|
117 |
+
echo sprintf('<input type="text" name="%1$s" class="regular-text" id="%1$s" value="%2$s" />', $key, $val);
|
118 |
+
}
|
119 |
}
|
120 |
|
121 |
/**
|
128 |
$this->options = [
|
129 |
Entity::SITE_KEY => new Entity(__('Site Key', 'simple-google-recaptcha'), Entity::STRING),
|
130 |
Entity::SECRET_KEY => new Entity(__('Secret Key', 'simple-google-recaptcha'), Entity::STRING),
|
131 |
+
Entity::LOGIN_DISABLE => new Entity(__('Disable on login form', 'simple-google-recaptcha')),
|
132 |
+
Entity::VERSION => new Entity(__('Enable reCAPTCHA v3', 'simple-google-recaptcha')),
|
133 |
+
Entity::BADGE_HIDE => new Entity(__('Hide reCAPTCHA v3 badge', 'simple-google-recaptcha'))
|
134 |
];
|
135 |
|
136 |
$this->updateSettings();
|
137 |
|
138 |
+
/**
|
139 |
+
* @var string $id
|
140 |
+
* @var Entity $option
|
141 |
+
*/
|
142 |
+
foreach ($this->options as $id => $option) {
|
143 |
+
$type = $option->getType();
|
144 |
+
$filter = $this->getOptionFilter($type);
|
145 |
+
$filteredValue = filter_var(get_option($id), $filter);
|
146 |
+
$option->setValue($type === Entity::INT ? intval($filteredValue) : strval($filteredValue));
|
147 |
+
}
|
148 |
|
149 |
$this->disableProtection();
|
150 |
|
151 |
+
$this->enqueue();
|
152 |
+
$this->enqueue('css');
|
153 |
|
154 |
$this->frontend();
|
155 |
|
167 |
|
168 |
if ($postAction === self::UPDATE && current_user_can('manage_options')) {
|
169 |
$hash = null;
|
170 |
+
|
171 |
foreach ($this->options as $key => $option) {
|
172 |
$postValue = filter_input(INPUT_POST, $key, $this->getOptionFilter($option->getType()));
|
173 |
|
174 |
if ($postValue) {
|
175 |
update_option($key, $postValue);
|
176 |
|
177 |
+
if (substr($key, -strlen('_key')) === '_key') {
|
178 |
$hash .= $postValue;
|
179 |
}
|
180 |
} else {
|
189 |
}
|
190 |
|
191 |
/**
|
192 |
+
* @param array $links
|
193 |
* @return array
|
194 |
*/
|
195 |
+
public function actionLinks(array $links): array
|
196 |
{
|
197 |
return array_merge(['settings' => sprintf('<a href="options-general.php%s">%s</a>', Entity::PAGE_QUERY, __('Settings', 'simple-google-recaptcha'))], $links);
|
198 |
}
|
199 |
|
200 |
/**
|
201 |
+
* @param string $plugin
|
202 |
* @return void
|
203 |
*/
|
204 |
+
public function activation(string $plugin)
|
205 |
{
|
206 |
if ($plugin === plugin_basename(__FILE__) && (!get_option(Entity::SITE_KEY) || !get_option(Entity::SECRET_KEY))) {
|
207 |
+
$adminUrl = admin_url('options-general.php' . Entity::PAGE_QUERY);
|
208 |
+
|
209 |
+
exit(wp_redirect($adminUrl));
|
210 |
}
|
211 |
}
|
212 |
|
217 |
{
|
218 |
echo sprintf('<div class="wrap"><h1>%s - %s</h1><form method="post" action="%s">', $this->pluginName, __('Settings', 'simple-google-recaptcha'), Entity::PAGE_QUERY);
|
219 |
|
220 |
+
settings_fields(Entity::PREFIX . 'header_section');
|
221 |
+
do_settings_sections(Entity::PREFIX . 'options');
|
222 |
|
223 |
echo sprintf('<input type="hidden" name="%s" value="%s">', self::SGR_ACTION, self::UPDATE);
|
224 |
|
225 |
submit_button();
|
226 |
|
227 |
+
echo sprintf('%s</form>%s</div>', PHP_EOL, $this->protectionStatus());
|
228 |
}
|
229 |
|
230 |
/**
|
232 |
*/
|
233 |
public function adminMenu()
|
234 |
{
|
235 |
+
add_submenu_page('options-general.php', $this->pluginName, 'Google reCAPTCHA', 'manage_options', Entity::PREFIX . 'options', [$this, 'optionsPage']);
|
236 |
add_action('admin_init', [$this, 'displayOptions']);
|
237 |
}
|
238 |
|
239 |
/**
|
240 |
* @return void
|
241 |
*/
|
242 |
+
public function displayOptions()
|
243 |
{
|
244 |
+
add_settings_section(Entity::PREFIX . 'header_section', __('Google reCAPTCHA keys', 'simple-google-recaptcha'), [], Entity::PREFIX . 'options');
|
|
|
245 |
|
246 |
+
foreach ($this->options as $key => $option) {
|
247 |
+
$args = ['key' => $key, 'type' => $option->getType()];
|
248 |
+
add_settings_field($key, $option->getName(), [$this, 'displayInput'], Entity::PREFIX . 'options', Entity::PREFIX . 'header_section', $args);
|
249 |
+
register_setting(Entity::PREFIX . 'header_section', $key);
|
250 |
+
}
|
|
|
251 |
}
|
252 |
|
253 |
/**
|
254 |
* @return void
|
255 |
*/
|
256 |
+
public function enqueueScripts()
|
257 |
{
|
258 |
+
$apiUrlBase = sprintf('https://www.recaptcha.net/recaptcha/api.js?hl=%s', get_locale());
|
259 |
+
$jsUrl = sprintf('%s&onload=sgr_2&render=explicit', $apiUrlBase);
|
260 |
|
261 |
+
if ($this->getOptionValue(Entity::VERSION) === 3) {
|
262 |
+
$jsUrl = sprintf('%s&render=%s&onload=sgr_3', $apiUrlBase, $this->getOptionValue(Entity::SITE_KEY));
|
263 |
+
}
|
|
|
|
|
|
|
|
|
264 |
|
265 |
+
wp_enqueue_script(Entity::PREFIX . 'recaptcha', $jsUrl, [], time());
|
|
|
|
|
|
|
|
|
|
|
266 |
}
|
267 |
|
268 |
/**
|
269 |
+
* @param array|null $list
|
270 |
+
* @return array|string[]
|
271 |
*/
|
272 |
+
public function renderList(?array $list = []): array
|
273 |
{
|
274 |
+
$list ?: $list = [
|
275 |
+
'bp_after_signup_profile_fields',
|
276 |
+
'comment_form_after_fields',
|
277 |
+
'lostpassword_form',
|
278 |
+
'register_form',
|
279 |
+
'woocommerce_lostpassword_form',
|
280 |
+
'woocommerce_register_form'
|
281 |
+
];
|
282 |
|
283 |
+
if (!$this->getOptionValue(Entity::LOGIN_DISABLE)) {
|
284 |
+
array_push($list, 'login_form', 'woocommerce_login_form');
|
|
|
285 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
286 |
|
287 |
+
return $list;
|
|
|
|
|
288 |
}
|
289 |
|
290 |
/**
|
291 |
+
* @param array|null $list
|
292 |
+
* @return array|string[]
|
293 |
*/
|
294 |
+
public function verifyList(?array $list = []): array
|
295 |
{
|
296 |
+
$list ?: $list = [
|
297 |
+
'bp_signup_validate',
|
298 |
+
'lostpassword_post',
|
299 |
+
'preprocess_comment',
|
300 |
+
'registration_errors',
|
301 |
+
'woocommerce_register_post'
|
302 |
+
];
|
303 |
|
304 |
+
if (!$this->getOptionValue(Entity::LOGIN_DISABLE)) {
|
305 |
+
$list[] = 'authenticate';
|
306 |
}
|
307 |
|
308 |
+
return $list;
|
309 |
}
|
310 |
|
311 |
/**
|
318 |
$recaptchaSecretKey = $this->getOptionValue(Entity::SECRET_KEY);
|
319 |
|
320 |
if ($rcpActivate && $recaptchaSiteKey && $recaptchaSecretKey) {
|
321 |
+
add_action(Entity::PREFIX . 'display_list', [$this, 'renderList']);
|
322 |
+
add_action(Entity::PREFIX . 'verify_list', [$this, 'verifyList']);
|
|
|
|
|
|
|
|
|
|
|
|
|
323 |
|
324 |
+
foreach (apply_filters(Entity::PREFIX . 'render_list', self::renderList()) as $display) {
|
325 |
+
add_action($display, [$this, 'enqueueScripts']);
|
326 |
+
add_action($display, [$this, 'render']);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
327 |
}
|
328 |
|
329 |
+
foreach (apply_filters(Entity::PREFIX . 'verify_list', self::verifyList()) as $verify) {
|
330 |
+
add_action($verify, [$this, 'verify']);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
331 |
}
|
332 |
}
|
333 |
}
|
334 |
|
335 |
/**
|
336 |
+
* @return bool
|
337 |
*/
|
338 |
+
public function render(): bool
|
339 |
{
|
340 |
+
if ($this->adminCookieHash()) {
|
341 |
+
$linkText = __('Emergency reCAPTCHA deactivate', 'simple-google-recaptcha');
|
342 |
+
echo sprintf('<p class="sgr-infotext"><a href="?%s=%s">%s</a></p>', self::SGR_ACTION, self::DISABLE, $linkText);
|
343 |
+
}
|
344 |
|
345 |
+
echo $this->getOptionValue(Entity::VERSION) === 3 ? self::v3Render() : '<div class="sgr-main"></div>';
|
346 |
+
|
347 |
+
return true;
|
348 |
}
|
349 |
|
350 |
/**
|
351 |
+
* @return string
|
352 |
*/
|
353 |
+
private function v3Render(): string
|
354 |
{
|
355 |
+
$badgeReplacement = null;
|
356 |
|
357 |
if ($this->getOptionValue(Entity::BADGE_HIDE)) {
|
358 |
+
$this->enqueue('css', Entity::PREFIX . 'hide');
|
|
|
|
|
359 |
|
360 |
+
$msg = __('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.', 'simple-google-recaptcha');
|
361 |
+
$badgeReplacement = sprintf('%s<p class="sgr-infotext">%s</p>', PHP_EOL, $msg);
|
362 |
}
|
363 |
|
364 |
+
return sprintf('<input type="hidden" name="g-recaptcha-response" class="sgr-main">%s', $badgeReplacement);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
365 |
}
|
366 |
|
367 |
/**
|
379 |
|
380 |
foreach ($keys as $key) {
|
381 |
delete_option($key);
|
382 |
+
|
383 |
$this->options[$key]->setValue('');
|
384 |
}
|
385 |
}
|
386 |
}
|
387 |
|
388 |
/**
|
389 |
+
* @param string|null $error_code
|
390 |
+
* @return string
|
391 |
*/
|
392 |
+
private function errorMessage(?string $error_code): string
|
393 |
{
|
394 |
switch ($error_code) {
|
395 |
case 'missing-input-secret':
|
410 |
}
|
411 |
|
412 |
/**
|
413 |
+
* @param string $response
|
414 |
+
* @return array
|
415 |
*/
|
416 |
+
private function responseParse(string $response): array
|
417 |
{
|
418 |
$secretKey = $this->getOptionValue(Entity::SECRET_KEY);
|
419 |
$rcpUrl = sprintf('https://www.recaptcha.net/recaptcha/api/siteverify?secret=%s&response=%s', $secretKey, $response);
|
420 |
+
$response = wp_remote_get($rcpUrl);
|
421 |
|
422 |
+
$failedResponse = [
|
423 |
'success' => false,
|
424 |
'error-codes' => ['general-fail']
|
425 |
];
|
426 |
|
427 |
+
if ($response instanceof \WP_Error) {
|
428 |
+
$failedResponse['error-msg'] = $response->get_error_message();
|
429 |
+
unset($response);
|
430 |
+
}
|
431 |
+
|
432 |
+
return isset($response['body']) ? (array)json_decode($response['body'], 1) : $failedResponse;
|
433 |
+
}
|
434 |
+
|
435 |
+
/**
|
436 |
+
* @param string $msg
|
437 |
+
* @return void
|
438 |
+
*/
|
439 |
+
private function wpDie(string $msg)
|
440 |
+
{
|
441 |
+
$error = __('Error', 'simple-google-recaptcha');
|
442 |
+
$verificationFailed = __('verification failed', 'simple-google-recaptcha');
|
443 |
+
$errorParams = ['response' => 403, 'back_link' => 1];
|
444 |
+
|
445 |
+
wp_die(sprintf('<p><strong>%s:</strong> Google reCAPTCHA %s. %s</p>', $error, $verificationFailed, $msg), 'Forbidden by reCAPTCHA', $errorParams);
|
446 |
}
|
447 |
|
448 |
/**
|
453 |
{
|
454 |
if (!empty($_POST)) {
|
455 |
$response = strval(filter_input(INPUT_POST, 'g-recaptcha-response', FILTER_SANITIZE_FULL_SPECIAL_CHARS));
|
456 |
+
$parsedResponse = $this->responseParse($response);
|
457 |
+
$errorCode = $parsedResponse['error-codes'][0] ?? null;
|
458 |
|
459 |
+
if (($parsedResponse['success'] ?? null) !== true || $errorCode) {
|
460 |
+
$this->wpDie($parsedResponse['error-msg'] ?? $this->errorMessage($errorCode));
|
461 |
} else {
|
462 |
+
if ($this->getOptionValue(Entity::VERSION) === 3 && floatval($parsedResponse['score'] ?? 0) < 0.5) {
|
463 |
+
$this->wpDie(__('You are probably not a human!', 'simple-google-recaptcha'));
|
|
|
|
|
|
|
|
|
|
|
|
|
464 |
}
|
465 |
|
466 |
+
return $input;
|
|
|
467 |
}
|
468 |
}
|
469 |
}
|
471 |
/**
|
472 |
* @return string
|
473 |
*/
|
474 |
+
public function protectionStatus(): string
|
475 |
{
|
476 |
$class = 'warning';
|
477 |
$name = __('Notice', 'simple-google-recaptcha');
|
485 |
$msg = __('You have to <a href="https://www.google.com/recaptcha/admin" rel="external">register your domain</a>, get required Google reCAPTCHA keys %s and save them bellow.', 'simple-google-recaptcha');
|
486 |
}
|
487 |
|
488 |
+
$type = $this->getOptionValue(Entity::VERSION) === 3 ? 'v3' : 'v2 "I\'m not a robot" Checkbox';
|
489 |
|
490 |
return sprintf('<div class="notice notice-%s"><p><strong>%s:</strong> Google reCAPTCHA %s!</p><p>%s</p></div>', $class, $name, $status, sprintf($msg, $type));
|
491 |
}
|
493 |
/**
|
494 |
* @return bool
|
495 |
*/
|
496 |
+
public function adminCookieHash(): bool
|
497 |
{
|
498 |
$cookieHash = filter_input(INPUT_COOKIE, Entity::HASH, FILTER_SANITIZE_SPECIAL_CHARS);
|
499 |
|
500 |
+
return $cookieHash === md5($this->getOptionValue(Entity::SITE_KEY) . $this->getOptionValue(Entity::SECRET_KEY));
|
|
|
|
|
|
|
|
|
501 |
}
|
502 |
}
|
503 |
|
504 |
+
Core::getInstance();
|
uninstall.php
CHANGED
@@ -1,33 +1,34 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
|
4 |
-
|
5 |
|
6 |
if (!defined('WP_UNINSTALL_PLUGIN')) {
|
7 |
die('Direct access not allowed');
|
8 |
}
|
9 |
|
10 |
-
include sprintf('%s/entity.php', dirname(__FILE__));
|
11 |
-
|
12 |
/**
|
13 |
-
* Class
|
|
|
14 |
*/
|
15 |
-
class
|
16 |
{
|
17 |
-
/**
|
18 |
-
|
19 |
-
|
20 |
-
public function
|
21 |
{
|
22 |
-
|
|
|
|
|
23 |
|
24 |
foreach ($constants as $constant) {
|
25 |
-
|
26 |
-
delete_option($constant);
|
27 |
|
|
|
|
|
28 |
}
|
29 |
}
|
30 |
}
|
31 |
}
|
32 |
|
33 |
-
|
1 |
<?php
|
2 |
|
3 |
+
namespace NovaMi\WordPress\SimpleGoogleRecaptcha;
|
|
|
4 |
|
5 |
if (!defined('WP_UNINSTALL_PLUGIN')) {
|
6 |
die('Direct access not allowed');
|
7 |
}
|
8 |
|
|
|
|
|
9 |
/**
|
10 |
+
* Class Uninstall
|
11 |
+
* @package NovaMi\WordPress\SimpleGoogleRecaptcha
|
12 |
*/
|
13 |
+
class Uninstall
|
14 |
{
|
15 |
+
/**
|
16 |
+
* @return void
|
17 |
+
*/
|
18 |
+
public static function run()
|
19 |
{
|
20 |
+
require_once dirname(__FILE__) . '/entity.php';
|
21 |
+
|
22 |
+
$constants = (new \ReflectionClass(Entity::class))->getConstants();
|
23 |
|
24 |
foreach ($constants as $constant) {
|
25 |
+
$constPrefix = substr($constant, 0, strlen(Entity::PREFIX));
|
|
|
26 |
|
27 |
+
if ($constPrefix === Entity::PREFIX) {
|
28 |
+
delete_option($constant);
|
29 |
}
|
30 |
}
|
31 |
}
|
32 |
}
|
33 |
|
34 |
+
Uninstall::run();
|