PluginProbe ʕ •ᴥ•ʔ
CloudSecure WP Security / 0.9.0
CloudSecure WP Security v0.9.0
1.4.10 1.4.9 trunk 0.9.0 1.0.2 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.3.1 1.3.10 1.3.11 1.3.12 1.3.13 1.3.14 1.3.15 1.3.16 1.3.17 1.3.18 1.3.19 1.3.2 1.3.20 1.3.21 1.3.22 1.3.23 1.3.24 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8
cloudsecure-wp-security / modules / captcha.php
cloudsecure-wp-security / modules Last commit date
admin 2 years ago captcha.php 2 years ago cloudsecure-wp.php 2 years ago common.php 2 years ago config.php 2 years ago disable-author-query.php 2 years ago disable-login.php 2 years ago disable-restapi.php 2 years ago disable-xmlrpc.php 2 years ago htaccess.php 2 years ago login-log.php 2 years ago login-notification.php 2 years ago rename-login-page.php 2 years ago restrict-admin-page.php 2 years ago unify-messages.php 2 years ago update-notice.php 2 years ago
captcha.php
370 lines
1 <?php
2
3 class CloudSecureWP_CAPTCHA extends CloudSecureWP_Common {
4 private const KEY_FEATURE = 'captcha';
5 private const KEY_LOGIN = self::KEY_FEATURE . '_login';
6 private const KEY_COMMENT = self::KEY_FEATURE . '_comment';
7 private const KEY_LOST_PASSWORD = self::KEY_FEATURE . '_lost_password';
8 private const KEY_REGISTER = self::KEY_FEATURE . '_register';
9 private const LOGIN_VALUES = array( 1, 2 ); // 無効, 有効 .
10 private const COMMENT_VALUES = array( 1, 2 ); // 無効, 有効 .
11 private const LOST_PASSWORD_VALUES = array( 1, 2 ); // 無効, 有効 .
12 private const REGISTER_VALUES = array( 1, 2 ); // 無効, 有効 .
13 private const ERROR_CODE = 'cloudsecurewp_captcha_error';
14 private const CAPTCHA_FORM_NAME = 'cloudsecurewp_captcha';
15 private const PREFIX_FORM_NAME = 'cloudsecurewp_captcha_prefix';
16 private const CAPTCHA_ERROR_MESSAGE = 'エラー:画像認証に失敗しました';
17
18 private $config;
19 private $captcha;
20 private $allowed_html;
21
22 function __construct( array $info, CloudSecureWP_Config $config ) {
23 parent::__construct( $info );
24 $this->config = $config;
25 $this->captcha = new CloudSecureWP_ReallySimpleCaptcha();
26 $this->allowed_html = array(
27 'p' => array(
28 'class' => array(),
29 ),
30 'style' => array(),
31 'label' => array(
32 'for' => array(),
33 ),
34 'img' => array(
35 'src' => array(),
36 'alt' => array(),
37 ),
38 'input' => array(
39 'type' => array(),
40 'id' => array(),
41 'name' => array(),
42 'class' => array(),
43 'value' => array(),
44 'size' => array(),
45 'aria-required' => array(),
46 ),
47 );
48 }
49
50 /**
51 * 機能毎のKEY取得
52 *
53 * @return string
54 */
55 public function get_feature_key(): string {
56 return self::KEY_FEATURE;
57 }
58
59 /**
60 * 有効無効判定
61 *
62 * @return bool
63 */
64 public function is_enabled(): bool {
65 return $this->config->get( $this->get_feature_key() ) === 't' ? true : false;
66 }
67
68 /**
69 * ログインフォームの有効無効判定
70 */
71 public function is_login_form_enabled(): bool {
72 return ( (int) $this->config->get( self::KEY_LOGIN ) === (int) self::LOGIN_VALUES[1] ) ? true : false;
73 }
74
75 /**
76 * コメントフォームの有効無効判定
77 */
78 public function is_comment_form_enabled(): bool {
79 return ( (int) $this->config->get( self::KEY_COMMENT ) === (int) self::COMMENT_VALUES[1] ) ? true : false;
80 }
81
82 /**
83 * パスワードリセットフォームの有効無効判定
84 */
85 public function is_lost_password_form_enabled(): bool {
86 return ( (int) $this->config->get( self::KEY_LOST_PASSWORD ) === (int) self::LOST_PASSWORD_VALUES[1] ) ? true : false;
87 }
88
89 /**
90 * ユーザー登録フォームの有効無効判定
91 */
92 public function is_register_form_enabled(): bool {
93 return ( (int) $this->config->get( self::KEY_REGISTER ) === (int) self::REGISTER_VALUES[1] ) ? true : false;
94 }
95
96 /**
97 * 初期設定値取得
98 *
99 * @return array
100 */
101 public function get_default(): array {
102 return array(
103 self::KEY_FEATURE => 'f',
104 self::KEY_LOGIN => self::LOGIN_VALUES[1],
105 self::KEY_COMMENT => self::COMMENT_VALUES[1],
106 self::KEY_LOST_PASSWORD => self::LOST_PASSWORD_VALUES[1],
107 self::KEY_REGISTER => self::REGISTER_VALUES[1],
108 );
109 }
110
111 /**
112 * 設定値key取得
113 */
114 public function get_keys(): array {
115 return array(
116 self::KEY_FEATURE,
117 self::KEY_LOGIN,
118 self::KEY_COMMENT,
119 self::KEY_LOST_PASSWORD,
120 self::KEY_REGISTER,
121 );
122 }
123
124 /**
125 * 設定値取得
126 */
127 public function get_settings(): array {
128 $settings = array();
129 $keys = $this->get_keys();
130
131 foreach ( $keys as $key ) {
132 $settings[ $key ] = $this->config->get( $key );
133 }
134
135 return $settings;
136 }
137
138 /**
139 * 設定値保存
140 *
141 * @param array $settings
142 * @return void
143 */
144 public function save_settings( $settings ): void {
145 $keys = $this->get_keys();
146
147 foreach ( $keys as $key ) {
148 $this->config->set( $key, $settings[ $key ] ?? '' );
149 }
150 $this->config->save();
151 }
152
153 /**
154 * 設定定義値取得
155 *
156 * @return array
157 */
158 public function get_constant_settings(): array {
159 return array(
160 self::KEY_LOGIN => self::LOGIN_VALUES,
161 self::KEY_COMMENT => self::COMMENT_VALUES,
162 self::KEY_LOST_PASSWORD => self::LOST_PASSWORD_VALUES,
163 self::KEY_REGISTER => self::REGISTER_VALUES,
164 );
165 }
166
167 /**
168 * 動作環境チェック
169 *
170 * @return string
171 */
172 public function check_modules(): string {
173 $ret = $this->check_gd();
174 if ( '' !== $ret ) {
175 return $ret;
176 }
177
178 $ret = $this->check_captcha_save_dir();
179 if ( '' !== $ret ) {
180 return $ret;
181 }
182
183 return $ret;
184 }
185
186 /**
187 * GDライブラリチェック
188 *
189 * @return string
190 */
191 public function check_gd(): string {
192 $gd = gd_info();
193
194 if ( empty( $gd ) ) {
195 return 'GDライブラリを利用できません';
196 }
197
198 if ( ! array_key_exists( 'FreeType Support', $gd ) || false === $gd['FreeType Support'] ) {
199 return 'FreeType が無効です';
200 }
201
202 return '';
203 }
204
205 /**
206 * 画像認証画像保存確認
207 *
208 * @return string
209 */
210 public function check_captcha_save_dir(): string {
211 if ( ! $this->captcha->make_tmp_dir() ) {
212 return '画像認証画像保存ディレクトリを作成できません: ' . $this->captcha->tmp_dir;
213 }
214
215 return '';
216 }
217
218 /**
219 * 有効化
220 *
221 * @return void
222 */
223 public function activate(): void {
224 $settings = $this->get_default();
225 $this->save_settings( $settings );
226 }
227
228 /**
229 * 無効化
230 *
231 * @return void
232 */
233 public function deactivate(): void {
234 $settings = $this->get_settings();
235 $settings[ self::KEY_FEATURE ] = 'f';
236 $this->save_settings( $settings );
237 }
238
239 /**
240 * 画像認証
241 *
242 * @return string
243 */
244 function create_captcha(): string {
245 $word = $this->captcha->generate_random_word();
246 $prefix = mt_rand();
247 $this->captcha->generate_image( $prefix, $word );
248
249 $captcha = '<p class="cloudsecure-wp-captcha-block">' . "\n";
250 $captcha .= ' <style>' . "\n";
251 $captcha .= ' .cloudsecure-wp-captcha-block label{' . "\n";
252 $captcha .= ' display: block;' . "\n";
253 $captcha .= ' }' . "\n";
254 $captcha .= ' .cloudsecure-wp-captcha-block label img{' . "\n";
255 $captcha .= ' border: 1px solid #CCCCCC;' . "\n";
256 $captcha .= ' padding: 8px;' . "\n";
257 $captcha .= ' margin-top: 2px;' . "\n";
258 $captcha .= ' }' . "\n";
259 $captcha .= ' </style>' . "\n";
260 $captcha .= ' <label for="' . self::CAPTCHA_FORM_NAME . '">画像に表示された文字を�
261 �力してください</label>' . "\n";
262 $captcha .= ' <label for="' . self::CAPTCHA_FORM_NAME . '"><img src="' . $this->info['plugin_url'] . 'really-simple-captcha/tmp/' . $prefix . '.png" alt="CAPTCHA"></label>' . "\n";
263 $captcha .= ' <input type="text" id="' . self::CAPTCHA_FORM_NAME . '" name="' . self::CAPTCHA_FORM_NAME . '" class="input" value="" size="10" aria-required="true" />' . "\n";
264 $captcha .= ' <input type="hidden" id="' . self::PREFIX_FORM_NAME . '" name="' . self::PREFIX_FORM_NAME . '" value="' . $prefix . '" />' . "\n";
265 $captcha .= wp_nonce_field( $this->get_feature_key() . '_csrf', 'cloudsecurewp_captcha_wpnonce', true, false ) . "\n";
266 $captcha .= '</p>' . "\n";
267
268 return $captcha;
269 }
270
271 /**
272 * 画像認証チェック
273 *
274 * @return bool
275 */
276 public function check_captcha(): bool {
277 if ( ! empty( $_POST ) && check_admin_referer( $this->get_feature_key() . '_csrf', 'cloudsecurewp_captcha_wpnonce' ) ) {
278 return $this->captcha->check( sanitize_text_field( $_POST[ self::PREFIX_FORM_NAME ] ?? ''), sanitize_text_field( $_POST[ self::CAPTCHA_FORM_NAME ] ?? ''), false );
279 }
280 return false;
281 }
282
283 /**
284 * 画像認証エラー
285 */
286 public function get_captcha_error() {
287 return new WP_Error( self::ERROR_CODE, self::CAPTCHA_ERROR_MESSAGE );
288 }
289
290 /**
291 * エラーコード追加
292 */
293 public function shake_error_codes( $error_codes ) {
294 array_push( $error_codes, self::ERROR_CODE );
295 return $error_codes;
296 }
297
298 /**
299 * ログインフォーム画像認証
300 */
301 public function login_form() {
302 echo wp_kses( $this->create_captcha(), $this->allowed_html );
303 }
304
305 /**
306 * ログインフォーム画像認証チェック
307 */
308 public function wp_authenticate_user( $user, $password ) {
309 if ( $this->check_captcha() ) {
310 return $user;
311 }
312
313 return $this->get_captcha_error();
314 }
315
316 /**
317 * コメントフォーム画像認証
318 */
319 public function comment_form_default_fields() {
320 echo wp_kses( $this->create_captcha(), $this->allowed_html );
321 }
322
323 /**
324 * コメントフォーム画像認証チェック
325 */
326 public function preprocess_comment( $comment_data ) {
327 if ( is_admin() || $this->check_captcha() ) {
328 return $comment_data;
329 }
330
331 wp_die( esc_html( self::CAPTCHA_ERROR_MESSAGE ), esc_html( 'ERROR' ), array( 'back_link' => true ) );
332 }
333
334 /**
335 * パスワードリセットフォーム画像認証
336 */
337 public function lostpassword_form() {
338 echo wp_kses( $this->create_captcha(), $this->allowed_html );
339 }
340
341 /**
342 * パスワードリセットフォーム画像認証チェック
343 */
344 public function allow_password_reset( $allow_reset, $user_id ) {
345 if ( $this->check_captcha() ) {
346 return $allow_reset;
347 }
348
349 return $this->get_captcha_error();
350 }
351
352 /**
353 * ユーザー登録フォーム画像認証
354 */
355 public function register_form() {
356 echo wp_kses( $this->create_captcha(), $this->allowed_html );
357 }
358
359 /**
360 * ユーザー登録フォーム画像認証チェック
361 */
362 public function register_post( $username, $email, $errors ) {
363 if ( $this->check_captcha() ) {
364 return $errors;
365 }
366
367 $errors->add( self::CAPTCHA_FORM_NAME, self::CAPTCHA_ERROR_MESSAGE );
368 }
369 }
370