Math Captcha - Version 1.2.0

Version Description

  • Tweak: Added option to reset settings to defaults
  • Tweak: Code rewritten to singleton design pattern
  • Fix: Contact Form 7 compatibility issues
  • New: Option to donate this plugin :)
Download this release

Release Info

Developer dfactory
Plugin Icon 128x128 Math Captcha
Version 1.2.0
Comparing to
See all releases

Code changes from version 1.1.1 to 1.2.0

css/admin.css CHANGED
@@ -4,6 +4,8 @@
4
  .df-credits h3 { font-size: 14px; line-height: 1.4; margin: 0; padding: 8px 12px; border-bottom: 1px solid #eee; }
5
  .df-credits .df-link { font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-style:italic; padding-bottom: 10px; margin: 0; }
6
  .df-credits .df-link a { vertical-align: middle; padding: 5px 0 0 4px; }
 
 
7
  .math-captcha-settings { margin-right: 300px; }
8
  .math-captcha-settings hr, .df-credits hr { border: solid #eee; border-width: 1px 0 0; clear: both; height: 0; }
9
  .math-captcha-settings form { float: left; min-width: 463px; width: auto; }
4
  .df-credits h3 { font-size: 14px; line-height: 1.4; margin: 0; padding: 8px 12px; border-bottom: 1px solid #eee; }
5
  .df-credits .df-link { font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; font-style:italic; padding-bottom: 10px; margin: 0; }
6
  .df-credits .df-link a { vertical-align: middle; padding: 5px 0 0 4px; }
7
+ .math-captcha-settings .df-credits form { min-width: 260px; margin-bottom: 1em; }
8
+ .math-captcha-settings .df-credits form input { margin: 0; padding: 0; }
9
  .math-captcha-settings { margin-right: 300px; }
10
  .math-captcha-settings hr, .df-credits hr { border: solid #eee; border-width: 1px 0 0; clear: both; height: 0; }
11
  .math-captcha-settings form { float: left; min-width: 463px; width: auto; }
css/{front.css → frontend.css} RENAMED
File without changes
includes/class-cookie-session.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if(!defined('ABSPATH')) exit;
3
+
4
+ new Math_Captcha_Cookie_Session();
5
+
6
+ class Math_Captcha_Cookie_Session
7
+ {
8
+ public $session_ids;
9
+
10
+
11
+ public function __construct()
12
+ {
13
+ // sets instance
14
+ Math_Captcha()->cookie_session = $this;
15
+
16
+ // actions
17
+ add_action('plugins_loaded', array(&$this, 'init_session'), 1);
18
+ }
19
+
20
+
21
+ /**
22
+ * Initializes cookie-session
23
+ */
24
+ public function init_session()
25
+ {
26
+ if(is_admin())
27
+ return;
28
+
29
+ if(isset($_COOKIE['mc_session_ids']))
30
+ $this->session_ids = $_COOKIE['mc_session_ids'];
31
+ else
32
+ {
33
+ foreach(array('default', 'multi') as $place)
34
+ {
35
+ switch($place)
36
+ {
37
+ case 'multi':
38
+ for($i = 0; $i < 5; $i++)
39
+ {
40
+ $this->session_ids[$place][$i] = sha1(wp_generate_password(64, false, false));
41
+ }
42
+ break;
43
+
44
+ case 'default':
45
+ $this->session_ids[$place] = sha1(wp_generate_password(64, false, false));
46
+ break;
47
+ }
48
+ }
49
+ }
50
+
51
+ if(!isset($_COOKIE['mc_session_ids']))
52
+ {
53
+ setcookie('mc_session_ids[default]', $this->session_ids['default'], current_time('timestamp', true) + apply_filters('math_captcha_time', Math_Captcha()->options['general']['time']), COOKIEPATH, COOKIE_DOMAIN, (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? true : false), true);
54
+
55
+ for($i = 0; $i < 5; $i++)
56
+ {
57
+ setcookie('mc_session_ids[multi]['.$i.']', $this->session_ids['multi'][$i], current_time('timestamp', true) + apply_filters('math_captcha_time', Math_Captcha()->options['general']['time']), COOKIEPATH, COOKIE_DOMAIN);
58
+ }
59
+ }
60
+ }
61
+ }
62
+ ?>
includes/class-core.php ADDED
@@ -0,0 +1,763 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if(!defined('ABSPATH')) exit;
3
+
4
+ new Math_Captcha_Core();
5
+
6
+ class Math_Captcha_Core
7
+ {
8
+ public $session_number = 0;
9
+ public $login_failed = false;
10
+ public $error_messages;
11
+ public $errors;
12
+
13
+
14
+ /**
15
+ *
16
+ */
17
+ public function __construct()
18
+ {
19
+ // sets instance
20
+ Math_Captcha()->core = $this;
21
+
22
+ // actions
23
+ add_action('init', array(&$this, 'load_actions_filters'), 1);
24
+ add_action('plugins_loaded', array(&$this, 'load_defaults'));
25
+ add_action('admin_init', array(&$this, 'flush_rewrites'));
26
+
27
+ // filters
28
+ add_filter('shake_error_codes', array(&$this, 'add_shake_error_codes'), 1);
29
+ add_filter('mod_rewrite_rules', array(&$this, 'block_direct_comments'));
30
+ }
31
+
32
+
33
+ /**
34
+ * Load defaults
35
+ */
36
+ public function load_defaults()
37
+ {
38
+ $this->error_messages = array(
39
+ 'fill' => '<strong>'. __('ERROR', 'math-captcha').'</strong>: '.__('Please enter captcha value.', 'math-captcha'),
40
+ 'wrong' => '<strong>'. __('ERROR', 'math-captcha').'</strong>: '.__('Invalid captcha value.', 'math-captcha'),
41
+ 'time' => '<strong>'. __('ERROR', 'math-captcha').'</strong>: '.__('Captcha time expired.', 'math-captcha')
42
+ );
43
+ }
44
+
45
+
46
+ /**
47
+ * Loads required filters
48
+ */
49
+ public function load_actions_filters()
50
+ {
51
+ // Contact Form 7
52
+ if(Math_Captcha()->options['general']['enable_for']['contact_form_7'] && class_exists('WPCF7_ContactForm'))
53
+ include_once(MATH_CAPTCHA_PATH.'includes/integration-cf7.php');
54
+
55
+ if(is_admin())
56
+ return;
57
+
58
+ $action = (isset($_GET['action']) && $_GET['action'] !== '' ? $_GET['action'] : null);
59
+
60
+ // comments
61
+ if(Math_Captcha()->options['general']['enable_for']['comment_form'])
62
+ {
63
+ if(!is_user_logged_in())
64
+ add_action('comment_form_after_fields', array(&$this, 'add_captcha_form'));
65
+ elseif(!Math_Captcha()->options['general']['hide_for_logged_users'])
66
+ add_action('comment_form_logged_in_after', array(&$this, 'add_captcha_form'));
67
+
68
+ add_filter('preprocess_comment', array(&$this, 'add_comment_with_captcha'));
69
+ }
70
+
71
+ // registration
72
+ if(Math_Captcha()->options['general']['enable_for']['registration_form'] && (!is_user_logged_in() || (is_user_logged_in() && !Math_Captcha()->options['general']['hide_for_logged_users'])) && $action === 'register')
73
+ {
74
+ add_action('register_form', array(&$this, 'add_captcha_form'));
75
+ add_action('register_post', array(&$this, 'add_user_with_captcha'), 10, 3);
76
+ add_action('signup_extra_fields', array(&$this, 'add_captcha_form'));
77
+ add_filter('wpmu_validate_user_signup', array(&$this, 'validate_user_with_captcha'));
78
+ }
79
+
80
+ // lost password
81
+ if(Math_Captcha()->options['general']['enable_for']['reset_password_form'] && (!is_user_logged_in() || (is_user_logged_in() && !Math_Captcha()->options['general']['hide_for_logged_users'])) && $action === 'lostpassword')
82
+ {
83
+ add_action('lostpassword_form', array(&$this, 'add_captcha_form'));
84
+ add_action('lostpassword_post', array(&$this, 'check_lost_password_with_captcha'));
85
+ }
86
+
87
+ // login
88
+ if(Math_Captcha()->options['general']['enable_for']['login_form'] && (!is_user_logged_in() || (is_user_logged_in() && !Math_Captcha()->options['general']['hide_for_logged_users'])) && $action === null)
89
+ {
90
+ add_action('login_form', array(&$this, 'add_captcha_form'));
91
+ add_filter('login_redirect', array(&$this, 'redirect_login_with_captcha'), 10, 3);
92
+ add_filter('authenticate', array(&$this, 'authenticate_user'), 1000, 3);
93
+ }
94
+
95
+ // bbPress
96
+ if(Math_Captcha()->options['general']['enable_for']['bbpress'] && class_exists('bbPress') && (!is_user_logged_in() || (is_user_logged_in() && !Math_Captcha()->options['general']['hide_for_logged_users'])))
97
+ {
98
+ add_action('bbp_theme_after_reply_form_content', array(&$this, 'add_bbp_captcha_form'));
99
+ add_action('bbp_theme_after_topic_form_content', array(&$this, 'add_bbp_captcha_form'));
100
+ add_action('bbp_new_reply_pre_extras', array(&$this, 'check_bbpress_captcha'));
101
+ add_action('bbp_new_topic_pre_extras', array(&$this, 'check_bbpress_captcha'));
102
+ }
103
+ }
104
+
105
+
106
+ /**
107
+ * Adds lost password errors
108
+ */
109
+ public function add_lostpassword_captcha_message($errors)
110
+ {
111
+ return $errors.$this->errors->errors['math-captcha-error'][0];
112
+ }
113
+
114
+
115
+ /**
116
+ * Adds lost password errors (special way)
117
+ */
118
+ public function add_lostpassword_wp_message()
119
+ {
120
+ return $this->errors;
121
+ }
122
+
123
+
124
+ /**
125
+ * Validates lost password form
126
+ */
127
+ public function check_lost_password_with_captcha()
128
+ {
129
+ $this->errors = new WP_Error();
130
+ $user_error = false;
131
+ $user_data = null;
132
+
133
+ // checks captcha
134
+ if(isset($_POST['mc-value']) && $_POST['mc-value'] !== '')
135
+ {
136
+ if(Math_Captcha()->cookie_session->session_ids['default'] !== '' && get_transient('mc_'.Math_Captcha()->cookie_session->session_ids['default']) !== false)
137
+ {
138
+ if(strcmp(get_transient('mc_'.Math_Captcha()->cookie_session->session_ids['default']), sha1(AUTH_KEY.$_POST['mc-value'].Math_Captcha()->cookie_session->session_ids['default'], false)) !== 0)
139
+ $this->errors->add('math-captcha-error', $this->error_messages['wrong']);
140
+ }
141
+ else
142
+ $this->errors->add('math-captcha-error', $this->error_messages['time']);
143
+ }
144
+ else
145
+ $this->errors->add('math-captcha-error', $this->error_messages['fill']);
146
+
147
+ // checks user_login (from wp-login.php)
148
+ if(empty($_POST['user_login']))
149
+ $user_error = true;
150
+ elseif(strpos($_POST['user_login'], '@'))
151
+ {
152
+ $user_data = get_user_by('email', trim($_POST['user_login']));
153
+
154
+ if(empty($user_data))
155
+ $user_error = true;
156
+ }
157
+ else
158
+ $user_data = get_user_by('login', trim($_POST['user_login']));
159
+
160
+ if(!$user_data)
161
+ $user_error = true;
162
+
163
+ // something went wrong?
164
+ if(!empty($this->errors->errors))
165
+ {
166
+ // nasty hack (captcha is wrong but user_login is fine)
167
+ if($user_error === false)
168
+ add_filter('allow_password_reset', array(&$this, 'add_lostpassword_wp_message'));
169
+ else
170
+ add_filter('login_errors', array(&$this, 'add_lostpassword_captcha_message'));
171
+ }
172
+ }
173
+
174
+
175
+ /**
176
+ * Validates register form
177
+ */
178
+ public function add_user_with_captcha($login, $email, $errors)
179
+ {
180
+ if(isset($_POST['mc-value']) && $_POST['mc-value'] !== '')
181
+ {
182
+ if(Math_Captcha()->cookie_session->session_ids['default'] !== '' && get_transient('mc_'.Math_Captcha()->cookie_session->session_ids['default']) !== false)
183
+ {
184
+ if(strcmp(get_transient('mc_'.Math_Captcha()->cookie_session->session_ids['default']), sha1(AUTH_KEY.$_POST['mc-value'].Math_Captcha()->cookie_session->session_ids['default'], false)) !== 0)
185
+ $errors->add('math-captcha-error', $this->error_messages['wrong']);
186
+ }
187
+ else
188
+ $errors->add('math-captcha-error', $this->error_messages['time']);
189
+ }
190
+ else
191
+ $errors->add('math-captcha-error', $this->error_messages['fill']);
192
+
193
+ return $errors;
194
+ }
195
+
196
+
197
+ /**
198
+ * Validates register form
199
+ */
200
+ public function validate_user_with_captcha($result)
201
+ {
202
+ if(isset($_POST['mc-value']) && $_POST['mc-value'] !== '')
203
+ {
204
+ if(Math_Captcha()->cookie_session->session_ids['default'] !== '' && get_transient('mc_'.Math_Captcha()->cookie_session->session_ids['default']) !== false)
205
+ {
206
+ if(strcmp(get_transient('mc_'.Math_Captcha()->cookie_session->session_ids['default']), sha1(AUTH_KEY.$_POST['mc-value'].Math_Captcha()->cookie_session->session_ids['default'], false)) !== 0)
207
+ $results['errors']->add('math-captcha-error', $this->error_messages['wrong']);
208
+ }
209
+ else
210
+ $results['errors']->add('math-captcha-error', $this->error_messages['time']);
211
+ }
212
+ else
213
+ $results['errors']->add('math-captcha-error', $this->error_messages['fill']);
214
+
215
+ return $results;
216
+ }
217
+
218
+
219
+ /**
220
+ * Posts login form
221
+ */
222
+ public function redirect_login_with_captcha($redirect, $bool, $errors)
223
+ {
224
+ if($this->login_failed === false && !empty($_POST))
225
+ {
226
+ $error = '';
227
+
228
+ if(isset($_POST['mc-value']) && $_POST['mc-value'] !== '')
229
+ {
230
+ if(Math_Captcha()->cookie_session->session_ids['default'] !== '' && get_transient('mc_'.Math_Captcha()->cookie_session->session_ids['default']) !== false)
231
+ {
232
+ if(strcmp(get_transient('mc_'.Math_Captcha()->cookie_session->session_ids['default']), sha1(AUTH_KEY.$_POST['mc-value'].Math_Captcha()->cookie_session->session_ids['default'], false)) !== 0)
233
+ $error = 'wrong';
234
+ }
235
+ else
236
+ $error = 'time';
237
+ }
238
+ else
239
+ $error = 'fill';
240
+
241
+ if(is_wp_error($errors) && !empty($error))
242
+ $errors->add('math-captcha-error', $this->error_messages[$error]);
243
+ }
244
+
245
+ return $redirect;
246
+ }
247
+
248
+
249
+ /**
250
+ * Authenticate user
251
+ */
252
+ public function authenticate_user($user, $username, $password)
253
+ {
254
+ // user gave us valid login and password
255
+ if(!is_wp_error($user))
256
+ {
257
+ if(!empty($_POST))
258
+ {
259
+ if(isset($_POST['mc-value']) && $_POST['mc-value'] !== '')
260
+ {
261
+ if(Math_Captcha()->cookie_session->session_ids['default'] !== '' && get_transient('mc_'.Math_Captcha()->cookie_session->session_ids['default']) !== false)
262
+ {
263
+ if(strcmp(get_transient('mc_'.Math_Captcha()->cookie_session->session_ids['default']), sha1(AUTH_KEY.$_POST['mc-value'].Math_Captcha()->cookie_session->session_ids['default'], false)) !== 0)
264
+ $error = 'wrong';
265
+ }
266
+ else
267
+ $error = 'time';
268
+ }
269
+ else
270
+ $error = 'fill';
271
+ }
272
+
273
+ if(!empty($error))
274
+ {
275
+ // destroy cookie
276
+ wp_clear_auth_cookie();
277
+
278
+ $user = new WP_Error();
279
+ $user->add('math-captcha-error', $this->error_messages[$error]);
280
+
281
+ // inform redirect function that we failed to login
282
+ $this->login_failed = true;
283
+ }
284
+ }
285
+
286
+ return $user;
287
+ }
288
+
289
+
290
+ /**
291
+ * Adds shake
292
+ */
293
+ public function add_shake_error_codes($codes)
294
+ {
295
+ $codes[] = 'math-captcha-error';
296
+
297
+ return $codes;
298
+ }
299
+
300
+
301
+ /**
302
+ * Adds captcha to comment form
303
+ */
304
+ public function add_comment_with_captcha($comment)
305
+ {
306
+ if(isset($_POST['mc-value']) && (!is_admin() || DOING_AJAX) && ($comment['comment_type'] === '' || $comment['comment_type'] === 'comment'))
307
+ {
308
+ if($_POST['mc-value'] !== '')
309
+ {
310
+ if(Math_Captcha()->cookie_session->session_ids['default'] !== '' && get_transient('mc_'.Math_Captcha()->cookie_session->session_ids['default']) !== false)
311
+ {
312
+ if(strcmp(get_transient('mc_'.Math_Captcha()->cookie_session->session_ids['default']), sha1(AUTH_KEY.$_POST['mc-value'].Math_Captcha()->cookie_session->session_ids['default'], false)) === 0)
313
+ return $comment;
314
+ else
315
+ wp_die($this->error_messages['wrong']);
316
+ }
317
+ else
318
+ wp_die($this->error_messages['time']);
319
+ }
320
+ else
321
+ wp_die($this->error_messages['fill']);
322
+ }
323
+ else
324
+ return $comment;
325
+ }
326
+
327
+
328
+ /**
329
+ * Shows and generates captcha
330
+ */
331
+ public function add_captcha_form()
332
+ {
333
+ if(is_admin())
334
+ return;
335
+
336
+ $captcha_title = apply_filters('math_captcha_title', Math_Captcha()->options['general']['title']);
337
+
338
+ echo '
339
+ <p class="math-captcha-form">';
340
+
341
+ if(!empty($captcha_title))
342
+ echo '
343
+ <label>'.$captcha_title.'<br/></label>';
344
+
345
+ echo '
346
+ <span>'.$this->generate_captcha_phrase('default').'</span>
347
+ </p>';
348
+ }
349
+
350
+
351
+ /**
352
+ * Shows and generates captcha for bbPress
353
+ */
354
+ public function add_bbp_captcha_form()
355
+ {
356
+ if(is_admin())
357
+ return;
358
+
359
+ $captcha_title = apply_filters('math_captcha_title', Math_Captcha()->options['general']['title']);
360
+
361
+ echo '
362
+ <p class="math-captcha-form">';
363
+
364
+ if(!empty($captcha_title))
365
+ echo '
366
+ <label>'.$captcha_title.'<br/></label>';
367
+
368
+ echo '
369
+ <span>'.$this->generate_captcha_phrase('bbpress').'</span>
370
+ </p>';
371
+ }
372
+
373
+
374
+ /**
375
+ * Validates bbpress topics and replies
376
+ */
377
+ public function check_bbpress_captcha()
378
+ {
379
+ if(isset($_POST['mc-value']) && $_POST['mc-value'] !== '')
380
+ {
381
+ if(Math_Captcha()->cookie_session->session_ids['default'] !== '' && get_transient('bbp_'.Math_Captcha()->cookie_session->session_ids['default']) !== false)
382
+ {
383
+ if(strcmp(get_transient('bbp_'.Math_Captcha()->cookie_session->session_ids['default']), sha1(AUTH_KEY.$_POST['mc-value'].Math_Captcha()->cookie_session->session_ids['default'], false)) !== 0)
384
+ bbp_add_error('math-captcha-wrong', $this->error_messages['wrong']);
385
+ }
386
+ else
387
+ bbp_add_error('math-captcha-wrong', $this->error_messages['time']);
388
+ }
389
+ else
390
+ bbp_add_error('math-captcha-wrong', $this->error_messages['fill']);
391
+ }
392
+
393
+
394
+ /**
395
+ * Encodes chars
396
+ */
397
+ private function encode_operation($string)
398
+ {
399
+ $chars = str_split($string);
400
+ $seed = mt_rand(0, (int)abs(crc32($string) / strlen($string)));
401
+
402
+ foreach($chars as $key => $char)
403
+ {
404
+ $ord = ord($char);
405
+
406
+ // ignore non-ascii chars
407
+ if($ord < 128)
408
+ {
409
+ // pseudo "random function"
410
+ $r = ($seed * (1 + $key)) % 100;
411
+
412
+ if($r > 60 && $char !== '@') {} // plain character (not encoded), if not @-sign
413
+ elseif($r < 45) $chars[$key] = '&#x'.dechex($ord).';'; // hexadecimal
414
+ else $chars[$key] = '&#'.$ord.';'; // decimal (ascii)
415
+ }
416
+ }
417
+
418
+ return implode('', $chars);
419
+ }
420
+
421
+
422
+ /**
423
+ * Converts numbers to words
424
+ */
425
+ private function numberToWords($number)
426
+ {
427
+ $words = array(
428
+ 1 => __('one', 'math-captcha'),
429
+ 2 => __('two', 'math-captcha'),
430
+ 3 => __('three', 'math-captcha'),
431
+ 4 => __('four', 'math-captcha'),
432
+ 5 => __('five', 'math-captcha'),
433
+ 6 => __('six', 'math-captcha'),
434
+ 7 => __('seven', 'math-captcha'),
435
+ 8 => __('eight', 'math-captcha'),
436
+ 9 => __('nine', 'math-captcha'),
437
+ 10 => __('ten', 'math-captcha'),
438
+ 11 => __('eleven', 'math-captcha'),
439
+ 12 => __('twelve', 'math-captcha'),
440
+ 13 => __('thirteen', 'math-captcha'),
441
+ 14 => __('fourteen', 'math-captcha'),
442
+ 15 => __('fifteen', 'math-captcha'),
443
+ 16 => __('sixteen', 'math-captcha'),
444
+ 17 => __('seventeen', 'math-captcha'),
445
+ 18 => __('eighteen', 'math-captcha'),
446
+ 19 => __('nineteen', 'math-captcha'),
447
+ 20 => __('twenty', 'math-captcha'),
448
+ 30 => __('thirty', 'math-captcha'),
449
+ 40 => __('forty', 'math-captcha'),
450
+ 50 => __('fifty', 'math-captcha'),
451
+ 60 => __('sixty', 'math-captcha'),
452
+ 70 => __('seventy', 'math-captcha'),
453
+ 80 => __('eighty', 'math-captcha'),
454
+ 90 => __('ninety', 'math-captcha')
455
+ );
456
+
457
+ if(isset($words[$number]))
458
+ return $words[$number];
459
+ else
460
+ {
461
+ $reverse = false;
462
+
463
+ switch(get_bloginfo('language'))
464
+ {
465
+ case 'de-DE':
466
+ $spacer = 'und';
467
+ $reverse = true;
468
+ break;
469
+
470
+ case 'nl-NL':
471
+ $spacer = 'en';
472
+ $reverse = true;
473
+ break;
474
+
475
+ case 'ru-RU':
476
+ case 'pl-PL':
477
+ case 'en-EN':
478
+ default:
479
+ $spacer = ' ';
480
+ }
481
+
482
+ $first = (int)(substr($number, 0, 1) * 10);
483
+ $second = (int)substr($number, -1);
484
+
485
+ return ($reverse === false ? $words[$first].$spacer.$words[$second] : $words[$second].$spacer.$words[$first]);
486
+ }
487
+ }
488
+
489
+
490
+ /**
491
+ * Generates captcha
492
+ */
493
+ public function generate_captcha_phrase($form = '')
494
+ {
495
+ $ops = array(
496
+ 'addition' => '+',
497
+ 'subtraction' => '&#8722;',
498
+ 'multiplication' => '&#215;',
499
+ 'division' => '&#247;',
500
+ );
501
+
502
+ $operations = $groups = array();
503
+ $input = '<input type="text" size="2" length="2" id="mc-input" class="mc-input" name="mc-value" value="" aria-required="true"/>';
504
+
505
+ // available operations
506
+ foreach(Math_Captcha()->options['general']['mathematical_operations'] as $operation => $enable)
507
+ {
508
+ if($enable === true)
509
+ $operations[] = $operation;
510
+ }
511
+
512
+ // available groups
513
+ foreach(Math_Captcha()->options['general']['groups'] as $group => $enable)
514
+ {
515
+ if($enable === true)
516
+ $groups[] = $group;
517
+ }
518
+
519
+ // number of groups
520
+ $ao = count($groups);
521
+
522
+ // operation
523
+ $rnd_op = $operations[mt_rand(0, count($operations) - 1)];
524
+ $number[3] = $ops[$rnd_op];
525
+
526
+ // place where to put empty input
527
+ $rnd_input = mt_rand(0, 2);
528
+
529
+ // which random operation
530
+ switch($rnd_op)
531
+ {
532
+ case 'addition':
533
+ if($rnd_input === 0)
534
+ {
535
+ $number[0] = mt_rand(1, 10);
536
+ $number[1] = mt_rand(1, 89);
537
+ }
538
+ elseif($rnd_input === 1)
539
+ {
540
+ $number[0] = mt_rand(1, 89);
541
+ $number[1] = mt_rand(1, 10);
542
+ }
543
+ elseif($rnd_input === 2)
544
+ {
545
+ $number[0] = mt_rand(1, 9);
546
+ $number[1] = mt_rand(1, 10 - $number[0]);
547
+ }
548
+
549
+ $number[2] = $number[0] + $number[1];
550
+ break;
551
+
552
+ case 'subtraction':
553
+ if($rnd_input === 0)
554
+ {
555
+ $number[0] = mt_rand(2, 10);
556
+ $number[1] = mt_rand(1, $number[0] - 1);
557
+ }
558
+ elseif($rnd_input === 1)
559
+ {
560
+ $number[0] = mt_rand(11, 99);
561
+ $number[1] = mt_rand(1, 10);
562
+ }
563
+ elseif($rnd_input === 2)
564
+ {
565
+ $number[0] = mt_rand(11, 99);
566
+ $number[1] = mt_rand($number[0] - 10, $number[0] - 1);
567
+ }
568
+
569
+ $number[2] = $number[0] - $number[1];
570
+ break;
571
+
572
+ case 'multiplication':
573
+ if($rnd_input === 0)
574
+ {
575
+ $number[0] = mt_rand(1, 10);
576
+ $number[1] = mt_rand(1, 9);
577
+ }
578
+ elseif($rnd_input === 1)
579
+ {
580
+ $number[0] = mt_rand(1, 9);
581
+ $number[1] = mt_rand(1, 10);
582
+ }
583
+ elseif($rnd_input === 2)
584
+ {
585
+ $number[0] = mt_rand(1, 10);
586
+ $number[1] = ($number[0] > 5 ? 1 : ($number[0] === 4 && $number[0] === 5 ? mt_rand(1, 2) : ($number[0] === 3 ? mt_rand(1, 3) : ($number[0] === 2 ? mt_rand(1, 5) : mt_rand(1, 10)))));
587
+ }
588
+
589
+ $number[2] = $number[0] * $number[1];
590
+ break;
591
+
592
+ case 'division':
593
+ $divide = array(1 => 99, 2 => 49, 3 => 33, 4 => 24, 5 => 19, 6 => 16, 7 => 14, 8 => 12, 9 => 11, 10 => 9);
594
+
595
+ if($rnd_input === 0)
596
+ {
597
+ $divide = array(2 => array(1, 2), 3 => array(1, 3), 4 => array(1, 2, 4), 5 => array(1, 5), 6 => array(1, 2, 3, 6), 7 => array(1, 7), 8 => array(1, 2, 4, 8), 9 => array(1, 3, 9), 10 => array(1, 2, 5, 10));
598
+ $number[0] = mt_rand(2, 10);
599
+ $number[1] = $divide[$number[0]][mt_rand(0, count($divide[$number[0]]) - 1)];
600
+ }
601
+ elseif($rnd_input === 1)
602
+ {
603
+ $number[1] = mt_rand(1, 10);
604
+ $number[0] = $number[1] * mt_rand(1, $divide[$number[1]]);
605
+ }
606
+ elseif($rnd_input === 2)
607
+ {
608
+ $number[2] = mt_rand(1, 10);
609
+ $number[0] = $number[2] * mt_rand(1, $divide[$number[2]]);
610
+ $number[1] = (int)($number[0] / $number[2]);
611
+ }
612
+
613
+ if(!isset($number[2]))
614
+ $number[2] = (int)($number[0] / $number[1]);
615
+
616
+ break;
617
+ }
618
+
619
+ // words
620
+ if($ao === 1 && $groups[0] === 'words')
621
+ {
622
+ if($rnd_input === 0)
623
+ {
624
+ $number[1] = $this->numberToWords($number[1]);
625
+ $number[2] = $this->numberToWords($number[2]);
626
+ }
627
+ elseif($rnd_input === 1)
628
+ {
629
+ $number[0] = $this->numberToWords($number[0]);
630
+ $number[2] = $this->numberToWords($number[2]);
631
+ }
632
+ elseif($rnd_input === 2)
633
+ {
634
+ $number[0] = $this->numberToWords($number[0]);
635
+ $number[1] = $this->numberToWords($number[1]);
636
+ }
637
+ }
638
+ // numbers and words
639
+ elseif($ao === 2)
640
+ {
641
+ if($rnd_input === 0)
642
+ {
643
+ if(mt_rand(1, 2) === 2)
644
+ {
645
+ $number[1] = $this->numberToWords($number[1]);
646
+ $number[2] = $this->numberToWords($number[2]);
647
+ }
648
+ else
649
+ $number[$tmp = mt_rand(1, 2)] = $this->numberToWords($number[$tmp]);
650
+ }
651
+ elseif($rnd_input === 1)
652
+ {
653
+ if(mt_rand(1, 2) === 2)
654
+ {
655
+ $number[0] = $this->numberToWords($number[0]);
656
+ $number[2] = $this->numberToWords($number[2]);
657
+ }
658
+ else
659
+ $number[$tmp = array_rand(array(0 => 0, 2 => 2), 1)] = $this->numberToWords($number[$tmp]);
660
+ }
661
+ elseif($rnd_input === 2)
662
+ {
663
+ if(mt_rand(1, 2) === 2)
664
+ {
665
+ $number[0] = $this->numberToWords($number[0]);
666
+ $number[1] = $this->numberToWords($number[1]);
667
+ }
668
+ else
669
+ $number[$tmp = mt_rand(0, 1)] = $this->numberToWords($number[$tmp]);
670
+ }
671
+ }
672
+
673
+ if(in_array($form, array('default', 'bbpress'), true))
674
+ {
675
+ // position of empty input
676
+ if($rnd_input === 0)
677
+ $return = $input.' '.$number[3].' '.$this->encode_operation($number[1]).' = '.$this->encode_operation($number[2]);
678
+ elseif($rnd_input === 1)
679
+ $return = $this->encode_operation($number[0]).' '.$number[3].' '.$input.' = '.$this->encode_operation($number[2]);
680
+ elseif($rnd_input === 2)
681
+ $return = $this->encode_operation($number[0]).' '.$number[3].' '.$this->encode_operation($number[1]).' = '.$input;
682
+
683
+ $transient_name = ($form === 'bbpress' ? 'bbp' : 'mc');
684
+ $session_id = Math_Captcha()->cookie_session->session_ids['default'];
685
+ }
686
+ elseif($form === 'cf7')
687
+ {
688
+ $return = array();
689
+
690
+ if($rnd_input === 0)
691
+ {
692
+ $return['input'] = 1;
693
+ $return[2] = ' '.$number[3].' '.$this->encode_operation($number[1]).' = ';
694
+ $return[3] = $this->encode_operation($number[2]);
695
+ }
696
+ elseif($rnd_input === 1)
697
+ {
698
+ $return[1] = $this->encode_operation($number[0]).' '.$number[3].' ';
699
+ $return['input'] = 2;
700
+ $return[3] = ' = '.$this->encode_operation($number[2]);
701
+ }
702
+ elseif($rnd_input === 2)
703
+ {
704
+ $return[1] = $this->encode_operation($number[0]).' '.$number[3].' ';
705
+ $return[2] = $this->encode_operation($number[1]).' = ';
706
+ $return['input'] = 3;
707
+ }
708
+
709
+ $transient_name = 'cf7';
710
+ $session_id = Math_Captcha()->cookie_session->session_ids['multi'][$this->session_number++];
711
+ }
712
+
713
+ set_transient($transient_name.'_'.$session_id, sha1(AUTH_KEY.$number[$rnd_input].$session_id, false), apply_filters('math_captcha_time', Math_Captcha()->options['general']['time']));
714
+
715
+ return $return;
716
+ }
717
+
718
+
719
+ /**
720
+ *
721
+ */
722
+ public function flush_rewrites()
723
+ {
724
+ if(Math_Captcha()->options['general']['flush_rules'])
725
+ {
726
+ global $wp_rewrite;
727
+
728
+ $wp_rewrite->flush_rules();
729
+
730
+ Math_Captcha()->options['general']['flush_rules'] = false;
731
+ update_option('math_captcha_options', Math_Captcha()->options['general']);
732
+ }
733
+ }
734
+
735
+
736
+ /**
737
+ *
738
+ */
739
+ public function block_direct_comments($rules)
740
+ {
741
+ if(Math_Captcha()->options['general']['block_direct_comments'])
742
+ {
743
+ $new_rules =
744
+ <<<EOT
745
+ \n# BEGIN Math Captcha
746
+ <IfModule mod_rewrite.c>
747
+ RewriteEngine On
748
+ RewriteCond %{REQUEST_METHOD} POST
749
+ RewriteCond %{REQUEST_URI} .wp-comments-post.php*
750
+ RewriteCond %{HTTP_REFERER} !.*{$_SERVER['HTTP_HOST']}.* [OR]
751
+ RewriteCond %{HTTP_USER_AGENT} ^$
752
+ RewriteRule (.*) ^http://%{REMOTE_ADDR}/$ [R=301,L]
753
+ </IfModule>
754
+ # END Math Captcha\n\n
755
+ EOT;
756
+
757
+ return $new_rules.$rules;
758
+ }
759
+
760
+ return $rules;
761
+ }
762
+ }
763
+ ?>
includes/class-settings.php ADDED
@@ -0,0 +1,387 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if(!defined('ABSPATH')) exit;
3
+
4
+ new Math_Captcha_Settings();
5
+
6
+ class Math_Captcha_Settings
7
+ {
8
+ public $mathematical_operations;
9
+ public $groups;
10
+ public $forms;
11
+
12
+
13
+ /**
14
+ *
15
+ */
16
+ public function __construct()
17
+ {
18
+ // actions
19
+ add_action('init', array(&$this, 'load_defaults'));
20
+ add_action('admin_init', array(&$this, 'register_settings'));
21
+ add_action('admin_menu', array(&$this, 'admin_menu_options'));
22
+ }
23
+
24
+
25
+ /**
26
+ *
27
+ */
28
+ public function load_defaults()
29
+ {
30
+ if(!is_admin())
31
+ return;
32
+
33
+ $this->forms = array(
34
+ 'login_form' => __('login form', 'math-captcha'),
35
+ 'registration_form' => __('registration form', 'math-captcha'),
36
+ 'reset_password_form' => __('reset password form', 'math-captcha'),
37
+ 'comment_form' => __('comment form', 'math-captcha'),
38
+ 'bbpress' => __('bbpress', 'math-captcha'),
39
+ 'contact_form_7' => __('contact form 7', 'math-captcha')
40
+ );
41
+
42
+ $this->mathematical_operations = array(
43
+ 'addition' => __('addition (+)', 'math-captcha'),
44
+ 'subtraction' => __('subtraction (-)', 'math-captcha'),
45
+ 'multiplication' => __('multiplication (&#215;)', 'math-captcha'),
46
+ 'division' => __('division (&#247;)', 'math-captcha')
47
+ );
48
+
49
+ $this->groups = array(
50
+ 'numbers' => __('numbers', 'math-captcha'),
51
+ 'words' => __('words', 'math-captcha')
52
+ );
53
+ }
54
+
55
+
56
+ /**
57
+ * Adds options menu
58
+ */
59
+ public function admin_menu_options()
60
+ {
61
+ add_options_page(
62
+ __('Math Captcha', 'math-captcha'),
63
+ __('Math Captcha', 'math-captcha'),
64
+ 'manage_options',
65
+ 'math-captcha',
66
+ array(&$this, 'options_page')
67
+ );
68
+ }
69
+
70
+
71
+ /**
72
+ * Shows options page
73
+ */
74
+ public function options_page()
75
+ {
76
+ echo '
77
+ <div class="wrap">
78
+ <h2>'.__('Math Captcha', 'math-captcha').'</h2>
79
+ <div class="math-captcha-settings">
80
+ <div class="df-credits">
81
+ <h3 class="hndle">'.__('Math Captcha', 'math-captcha').' '.Math_Captcha()->defaults['version'].'</h3>
82
+ <div class="inside">
83
+ <h4 class="inner">'.__('Need support?', 'math-captcha').'</h4>
84
+ <p class="inner">'.__('If you are having problems with this plugin, please talk about them in the', 'math-captcha').' <a href="http://www.dfactory.eu/support/?utm_source=math-captcha-settings&utm_medium=link&utm_campaign=support" target="_blank" title="'.__('Support forum','math-captcha').'">'.__('Support forum', 'math-captcha').'</a></p>
85
+ <hr/>
86
+ <h4 class="inner">'.__('Do you like this plugin?', 'math-captcha').'</h4>
87
+ <p class="inner"><a href="http://wordpress.org/support/view/plugin-reviews/wp-math-captcha" target="_blank" title="'.__('Rate it 5', 'math-captcha').'">'.__('Rate it 5', 'math-captcha').'</a> '.__('on WordPress.org', 'math-captcha').'<br/>'.
88
+ __('Blog about it & link to the', 'math-captcha').' <a href="http://www.dfactory.eu/plugins/math-captcha/?utm_source=math-captcha-settings&utm_medium=link&utm_campaign=blog-about" target="_blank" title="'.__('plugin page', 'math-captcha').'">'.__('plugin page', 'math-captcha').'</a><br/>'.
89
+ __('Check out our other', 'math-captcha').' <a href="http://www.dfactory.eu/plugins/?utm_source=math-captcha-settings&utm_medium=link&utm_campaign=other-plugins" target="_blank" title="'.__('WordPress plugins', 'math-captcha').'">'.__('WordPress plugins', 'math-captcha').'</a>
90
+ </p>
91
+ <form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank" class="inner">
92
+ <input type="hidden" name="cmd" value="_s-xclick">
93
+ <input type="hidden" name="hosted_button_id" value="BJSHR9GS5QJTC">
94
+ <input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
95
+ <img alt="" border="0" src="https://www.paypalobjects.com/pl_PL/i/scr/pixel.gif" width="1" height="1">
96
+ </form>
97
+ <hr/>
98
+ <p class="df-link inner">Created by <a href="http://www.dfactory.eu/?utm_source=math-captcha-settings&utm_medium=link&utm_campaign=created-by" target="_blank" title="dFactory - Quality plugins for WordPress"><img src="'.DOWNLOAD_ATTACHMENTS_URL.'/images/logo-dfactory.png" title="dFactory - Quality plugins for WordPress" alt="dFactory - Quality plugins for WordPress"/></a></p>
99
+ </div>
100
+ </div>
101
+ <form action="options.php" method="post">';
102
+
103
+ wp_nonce_field('update-options');
104
+ settings_fields('math_captcha_options');
105
+ do_settings_sections('math_captcha_options');
106
+
107
+ echo '
108
+ <p class="submit">';
109
+
110
+ submit_button('', 'primary', 'save_mc_general', false);
111
+
112
+ echo ' ';
113
+
114
+ submit_button(__('Reset to defaults', 'math-captcha'), 'secondary reset_mc_settings', 'reset_mc_general', false);
115
+
116
+ echo '
117
+ </p>
118
+ </form>
119
+ </div>
120
+ <div class="clear"></div>
121
+ </div>';
122
+ }
123
+
124
+
125
+ /**
126
+ *
127
+ */
128
+ public function register_settings()
129
+ {
130
+ // general settings
131
+ register_setting('math_captcha_options', 'math_captcha_options', array(&$this, 'validate_settings'));
132
+ add_settings_section('math_captcha_settings', __('Math Captcha settings', 'math-captcha'), '', 'math_captcha_options');
133
+ add_settings_field('mc_general_enable_captcha_for', __('Enable Math Captcha for', 'math-captcha'), array(&$this, 'mc_general_enable_captcha_for'), 'math_captcha_options', 'math_captcha_settings');
134
+ add_settings_field('mc_general_hide_for_logged_users', __('Hide for logged in users', 'math-captcha'), array(&$this, 'mc_general_hide_for_logged_users'), 'math_captcha_options', 'math_captcha_settings');
135
+ add_settings_field('mc_general_mathematical_operations', __('Mathematical operations', 'math-captcha'), array(&$this, 'mc_general_mathematical_operations'), 'math_captcha_options', 'math_captcha_settings');
136
+ add_settings_field('mc_general_groups', __('Display captcha as', 'math-captcha'), array(&$this, 'mc_general_groups'), 'math_captcha_options', 'math_captcha_settings');
137
+ add_settings_field('mc_general_title', __('Captcha field title', 'math-captcha'), array(&$this, 'mc_general_title'), 'math_captcha_options', 'math_captcha_settings');
138
+ add_settings_field('mc_general_time', __('Captcha time', 'math-captcha'), array(&$this, 'mc_general_time'), 'math_captcha_options', 'math_captcha_settings');
139
+ add_settings_field('mc_general_block_direct_comments', __('Block Direct Comments', 'math-captcha'), array(&$this, 'mc_general_block_direct_comments'), 'math_captcha_options', 'math_captcha_settings');
140
+ add_settings_field('mc_general_deactivation_delete', __('Deactivation', 'math-captcha'), array(&$this, 'mc_general_deactivation_delete'), 'math_captcha_options', 'math_captcha_settings');
141
+ }
142
+
143
+
144
+ /**
145
+ *
146
+ */
147
+ public function mc_general_enable_captcha_for()
148
+ {
149
+ echo '
150
+ <div id="mc_general_enable_captcha_for">
151
+ <fieldset>';
152
+
153
+ foreach($this->forms as $val => $trans)
154
+ {
155
+ echo '
156
+ <input id="mc-general-enable-captcha-for-'.$val.'" type="checkbox" name="math_captcha_options[enable_for][]" value="'.$val.'" '.checked(true, Math_Captcha()->options['general']['enable_for'][$val], false).' '.disabled((($val === 'contact_form_7' && !class_exists('WPCF7_ContactForm')) || ($val === 'bbpress' && !class_exists('bbPress'))), true, false).'/><label for="mc-general-enable-captcha-for-'.$val.'">'.esc_html($trans).'</label>';
157
+ }
158
+
159
+ echo '
160
+ <br/>
161
+ <span class="description">'.__('Select where you\'d like to use Math Captcha.', 'math-captcha').'</span>
162
+ </fieldset>
163
+ </div>';
164
+ }
165
+
166
+
167
+ /**
168
+ *
169
+ */
170
+ public function mc_general_hide_for_logged_users()
171
+ {
172
+ echo '
173
+ <div id="mc_general_hide_for_logged_users">
174
+ <fieldset>
175
+ <input id="mc-general-hide-for-logged" type="checkbox" name="math_captcha_options[hide_for_logged_users]" '.checked(true, Math_Captcha()->options['general']['hide_for_logged_users'], false).'/><label for="mc-general-hide-for-logged">'.__('Enable to hide captcha for logged in users.', 'math-captcha').'</label>
176
+ </fieldset>
177
+ </div>';
178
+ }
179
+
180
+
181
+ /**
182
+ *
183
+ */
184
+ public function mc_general_mathematical_operations()
185
+ {
186
+ echo '
187
+ <div id="mc_general_mathematical_operations">
188
+ <fieldset>';
189
+
190
+ foreach($this->mathematical_operations as $val => $trans)
191
+ {
192
+ echo '
193
+ <input id="mc-general-mathematical-operations-'.$val.'" type="checkbox" name="math_captcha_options[mathematical_operations][]" value="'.$val.'" '.checked(true, Math_Captcha()->options['general']['mathematical_operations'][$val], false).'/><label for="mc-general-mathematical-operations-'.$val.'">'.esc_html($trans).'</label>';
194
+ }
195
+
196
+ echo '
197
+ <br/>
198
+ <span class="description">'.__('Select which mathematical operations to use in your captcha.', 'math-captcha').'</span>
199
+ </fieldset>
200
+ </div>';
201
+ }
202
+
203
+
204
+ /**
205
+ *
206
+ */
207
+ public function mc_general_groups()
208
+ {
209
+ echo '
210
+ <div id="mc_general_groups">
211
+ <fieldset>';
212
+
213
+ foreach($this->groups as $val => $trans)
214
+ {
215
+ echo '
216
+ <input id="mc-general-groups-'.$val.'" type="checkbox" name="math_captcha_options[groups][]" value="'.$val.'" '.checked(true, Math_Captcha()->options['general']['groups'][$val], false).'/><label for="mc-general-groups-'.$val.'">'.esc_html($trans).'</label>';
217
+ }
218
+
219
+ echo '
220
+ <br/>
221
+ <span class="description">'.__('Select how you\'d like to display you captcha.', 'math-captcha').'</span>
222
+ </fieldset>
223
+ </div>';
224
+ }
225
+
226
+
227
+ /**
228
+ *
229
+ */
230
+ public function mc_general_title()
231
+ {
232
+ echo '
233
+ <div id="mc_general_title">
234
+ <fieldset>
235
+ <input type="text" name="math_captcha_options[title]" value="'.Math_Captcha()->options['general']['title'].'"/>
236
+ <br/>
237
+ <span class="description">'.__('How to entitle field with captcha?', 'math-captcha').'</span>
238
+ </fieldset>
239
+ </div>';
240
+ }
241
+
242
+
243
+ /**
244
+ *
245
+ */
246
+ public function mc_general_time()
247
+ {
248
+ echo '
249
+ <div id="mc_general_time">
250
+ <fieldset>
251
+ <input type="text" name="math_captcha_options[time]" value="'.Math_Captcha()->options['general']['time'].'"/>
252
+ <br/>
253
+ <span class="description">'.__('Enter the time (in seconds) a user has to enter captcha value.', 'math-captcha').'</span>
254
+ </fieldset>
255
+ </div>';
256
+ }
257
+
258
+
259
+ /**
260
+ *
261
+ */
262
+ public function mc_general_block_direct_comments()
263
+ {
264
+ echo '
265
+ <div id="mc_general_block_direct_comments">
266
+ <fieldset>
267
+ <input id="mc-general-block-direct-comments" type="checkbox" name="math_captcha_options[block_direct_comments]" '.checked(true, Math_Captcha()->options['general']['block_direct_comments'], false).'/><label for="mc-general-block-direct-comments">'.__('Blocks direct access to wp-comments-post.php. Enable this to prevent spambots from posting to Wordpress via a URL.', 'math-captcha').'</label>
268
+ </fieldset>
269
+ </div>';
270
+ }
271
+
272
+
273
+ /**
274
+ *
275
+ */
276
+ public function mc_general_deactivation_delete()
277
+ {
278
+ echo '
279
+ <div id="mc_general_deactivation_delete">
280
+ <fieldset>
281
+ <input id="mc-general-deactivation-delete" type="checkbox" name="math_captcha_options[deactivation_delete]" '.checked(true, Math_Captcha()->options['general']['deactivation_delete'], false).'/><label for="mc-general-deactivation-delete">'.__('Delete settings on plugin deactivation.', 'math-captcha').'</label>
282
+ </fieldset>
283
+ </div>';
284
+ }
285
+
286
+
287
+ /**
288
+ * Validates settings
289
+ */
290
+ public function validate_settings($input)
291
+ {
292
+ if(isset($_POST['save_mc_general']))
293
+ {
294
+ // enable captcha forms
295
+ $enable_for = array();
296
+
297
+ if(empty($input['enable_for']))
298
+ {
299
+ foreach(Math_Captcha()->defaults['general']['enable_for'] as $enable => $bool)
300
+ {
301
+ $input['enable_for'][$enable] = false;
302
+ }
303
+ }
304
+ else
305
+ {
306
+ foreach($this->forms as $enable => $trans)
307
+ {
308
+ $enable_for[$enable] = (in_array($enable, $input['enable_for']) ? true : false);
309
+ }
310
+
311
+ $input['enable_for'] = $enable_for;
312
+ }
313
+
314
+ if(!class_exists('WPCF7_ContactForm') && Math_Captcha()->options['general']['enable_for']['contact_form_7'])
315
+ $input['enable_for']['contact_form_7'] = true;
316
+
317
+ if(!class_exists('bbPress') && Math_Captcha()->options['general']['enable_for']['bbpress'])
318
+ $input['enable_for']['bbpress'] = true;
319
+
320
+ // enable mathematical operations
321
+ $mathematical_operations = array();
322
+
323
+ if(empty($input['mathematical_operations']))
324
+ {
325
+ add_settings_error('empty-operations', 'settings_updated', __('You need to check at least one mathematical operation. Defaults settings of this option restored.', 'math-captcha'), 'error');
326
+
327
+ $input['mathematical_operations'] = Math_Captcha()->defaults['general']['mathematical_operations'];
328
+ }
329
+ else
330
+ {
331
+ foreach($this->mathematical_operations as $operation => $trans)
332
+ {
333
+ $mathematical_operations[$operation] = (in_array($operation, $input['mathematical_operations']) ? true : false);
334
+ }
335
+
336
+ $input['mathematical_operations'] = $mathematical_operations;
337
+ }
338
+
339
+ // enable groups
340
+ $groups = array();
341
+
342
+ if(empty($input['groups']))
343
+ {
344
+ add_settings_error('empty-groups', 'settings_updated', __('You need to check at least one group. Defaults settings of this option restored.', 'math-captcha'), 'error');
345
+
346
+ $input['groups'] = Math_Captcha()->defaults['general']['groups'];
347
+ }
348
+ else
349
+ {
350
+ foreach($this->groups as $group => $trans)
351
+ {
352
+ $groups[$group] = (in_array($group, $input['groups']) ? true : false);
353
+ }
354
+
355
+ $input['groups'] = $groups;
356
+ }
357
+
358
+ // hide for logged in users
359
+ $input['hide_for_logged_users'] = isset($input['hide_for_logged_users']);
360
+
361
+ // block direct comments access
362
+ $input['block_direct_comments'] = isset($input['block_direct_comments']);
363
+
364
+ // deactivation delete
365
+ $input['deactivation_delete'] = isset($input['deactivation_delete']);
366
+
367
+ // captcha title
368
+ $input['title'] = trim($input['title']);
369
+
370
+ // captcha time
371
+ $time = (int)$input['time'];
372
+ $input['time'] = ($time < 0 ? Math_Captcha()->defaults['general']['time'] : $time);
373
+
374
+ // flush rules
375
+ $input['flush_rules'] = true;
376
+ }
377
+ elseif(isset($_POST['reset_mc_general']))
378
+ {
379
+ $input = Math_Captcha()->defaults['general'];
380
+
381
+ add_settings_error('settings', 'settings_reset', __('Settings restored to defaults.', 'math-captcha'), 'updated');
382
+ }
383
+
384
+ return $input;
385
+ }
386
+ }
387
+ ?>
includes/class-update.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if(!defined('ABSPATH')) exit;
3
+
4
+ new Math_Captcha_Update();
5
+
6
+ class Math_Captcha_Update
7
+ {
8
+ /**
9
+ *
10
+ */
11
+ public function __construct()
12
+ {
13
+ // actions
14
+ add_action('init', array(&$this, 'check_update'));
15
+ }
16
+
17
+
18
+ /**
19
+ *
20
+ */
21
+ public function check_update()
22
+ {
23
+ if(!is_admin() || !current_user_can('manage_options'))
24
+ return;
25
+
26
+ // gets current database version
27
+ $current_db_version = get_option('math_captcha_version', '1.0.0');
28
+
29
+ // new version?
30
+ if(version_compare($current_db_version, Math_Captcha()->defaults['version'], '<'))
31
+ {
32
+ if(version_compare($current_db_version, '1.0.9', '<'))
33
+ {
34
+ update_option('math_captcha_options', Math_Captcha()->options['general']);
35
+ delete_option('mc_options');
36
+ }
37
+
38
+ // updates plugin version
39
+ update_option('math_captcha_version', Math_Captcha()->defaults['version']);
40
+ }
41
+ }
42
+ }
43
+ ?>
includes/integration-cf7.php ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ A module for [mathcaptcha]
4
+ **/
5
+
6
+ // shortcode handler
7
+ add_action('init', 'wpcf7_add_shortcode_mathcaptcha', 5);
8
+
9
+ function wpcf7_add_shortcode_mathcaptcha()
10
+ {
11
+ wpcf7_add_shortcode('mathcaptcha', 'wpcf7_mathcaptcha_shortcode_handler', true);
12
+ }
13
+
14
+
15
+ function wpcf7_mathcaptcha_shortcode_handler($tag)
16
+ {
17
+ if(!is_user_logged_in() || (is_user_logged_in() && !Math_Captcha()->options['general']['hide_for_logged_users']))
18
+ {
19
+ $tag = new WPCF7_Shortcode($tag);
20
+
21
+ if(empty($tag->name))
22
+ return '';
23
+
24
+ $validation_error = wpcf7_get_validation_error($tag->name);
25
+ $class = wpcf7_form_controls_class($tag->type);
26
+
27
+ if($validation_error)
28
+ $class .= ' wpcf7-not-valid';
29
+
30
+ $atts = array();
31
+ $atts['size'] = 2;
32
+ $atts['maxlength'] = 2;
33
+ $atts['class'] = $tag->get_class_option($class);
34
+ $atts['id'] = $tag->get_option('id', 'id', true);
35
+ $atts['tabindex'] = $tag->get_option('tabindex', 'int', true);
36
+ $atts['aria-required'] = 'true';
37
+ $atts['type'] = 'text';
38
+ $atts['name'] = $tag->name;
39
+ $atts['value'] = '';
40
+ $atts = wpcf7_format_atts($atts);
41
+
42
+ $mc_form = Math_Captcha()->core->generate_captcha_phrase('cf7');
43
+ $mc_form[$mc_form['input']] = '<input %2$s />';
44
+
45
+ $math_captcha_title = apply_filters('math_captcha_title', Math_Captcha()->options['general']['title']);
46
+
47
+ return sprintf(((empty($math_captcha_title)) ? '' : $math_captcha_title).'<span class="wpcf7-form-control-wrap %1$s">'.$mc_form[1].$mc_form[2].$mc_form[3].'%3$s</span><input type="hidden" value="'.(Math_Captcha()->core->session_number - 1).'" name="'.$tag->name.'-sn" />', $tag->name, $atts, $validation_error);
48
+ }
49
+ }
50
+
51
+
52
+ // validation
53
+ add_filter('wpcf7_validate_mathcaptcha', 'wpcf7_mathcaptcha_validation_filter', 10, 2);
54
+
55
+ function wpcf7_mathcaptcha_validation_filter($result, $tag)
56
+ {
57
+ $tag = new WPCF7_Shortcode($tag);
58
+ $name = $tag->name;
59
+
60
+ if(!is_admin() && isset($_POST[$name]))
61
+ {
62
+ if($_POST[$name] !== '')
63
+ {
64
+ $session_id = (isset($_POST[$name.'-sn']) && $_POST[$name.'-sn'] !== '' ? Math_Captcha()->cookie_session->session_ids['multi'][$_POST[$name.'-sn']] : '');
65
+
66
+ if($session_id !== '' && get_transient('cf7_'.$session_id) !== false)
67
+ {
68
+ if(strcmp(get_transient('cf7_'.$session_id), sha1(AUTH_KEY.$_POST[$name].$session_id, false)) !== 0)
69
+ {
70
+ $result['valid'] = false;
71
+ $result['reason'][$name] = wpcf7_get_message('wrong_mathcaptcha');
72
+ }
73
+ }
74
+ else
75
+ {
76
+ $result['valid'] = false;
77
+ $result['reason'][$name] = wpcf7_get_message('time_mathcaptcha');
78
+ }
79
+ }
80
+ else
81
+ {
82
+ $result['valid'] = false;
83
+ $result['reason'][$name] = wpcf7_get_message('fill_mathcaptcha');
84
+ }
85
+ }
86
+
87
+ return $result;
88
+ }
89
+
90
+
91
+ // messages
92
+ add_filter('wpcf7_messages', 'wpcf7_mathcaptcha_messages');
93
+
94
+ function wpcf7_mathcaptcha_messages($messages)
95
+ {
96
+ return array_merge(
97
+ $messages,
98
+ array(
99
+ 'wrong_mathcaptcha' => array(
100
+ 'description' => __('Invalid captcha value.', 'math-captcha'),
101
+ 'default' => Math_Captcha()->core->error_messages['wrong']
102
+ ),
103
+ 'fill_mathcaptcha' => array(
104
+ 'description' => __('Please enter captcha value.', 'math-captcha'),
105
+ 'default' => Math_Captcha()->core->error_messages['fill']
106
+ ),
107
+ 'time_mathcaptcha' => array(
108
+ 'description' => __('Captcha time expired.', 'math-captcha'),
109
+ 'default' => Math_Captcha()->core->error_messages['time']
110
+ )
111
+ )
112
+ );
113
+ }
114
+
115
+
116
+ // warning message
117
+ add_action('wpcf7_admin_notices', 'wpcf7_mathcaptcha_display_warning_message');
118
+
119
+ function wpcf7_mathcaptcha_display_warning_message()
120
+ {
121
+ if(empty($_GET['post']) || !($contact_form = wpcf7_contact_form( $_GET['post'])))
122
+ return;
123
+
124
+ $has_tags = (bool)$contact_form->form_scan_shortcode(array('type' => array('mathcaptcha')));
125
+
126
+ if(!$has_tags)
127
+ return;
128
+ }
129
+
130
+
131
+ // tag generator
132
+ add_action('admin_init', 'wpcf7_add_tag_generator_mathcaptcha', 45);
133
+
134
+ function wpcf7_add_tag_generator_mathcaptcha()
135
+ {
136
+ if(!function_exists('wpcf7_add_tag_generator'))
137
+ return;
138
+