PluginProbe ʕ •ᴥ•ʔ
CloudSecure WP Security / 1.4.6
CloudSecure WP Security v1.4.6
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 / server-error-notification.php
cloudsecure-wp-security / modules Last commit date
admin 3 months ago cli 8 months ago lib 3 months ago captcha.php 3 months ago cloudsecure-wp.php 3 months ago common.php 3 months ago config.php 2 years ago disable-access-system-file.php 4 months ago disable-author-query.php 2 years ago disable-login.php 3 months ago disable-restapi.php 7 months ago disable-xmlrpc.php 1 year ago htaccess.php 3 months ago login-log.php 3 months ago login-notification.php 1 year ago rename-login-page.php 3 months ago restrict-admin-page.php 3 months ago server-error-notification.php 3 months ago two-factor-authentication.php 3 months ago unify-messages.php 2 years ago update-notice.php 7 months ago waf-engine.php 3 months ago waf.php 3 months ago
server-error-notification.php
264 lines
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit;
5 }
6
7 class CloudSecureWP_Server_Error_Notification extends CloudSecureWP_Common {
8 private const KEY_FEATURE = 'server_error_notification';
9 private const TABLE_NAME = 'cloudsecurewp_server_error';
10 private const MAX_ITEMS = 10000;
11
12 private $config;
13
14 function __construct( array $info, CloudSecureWP_Config $config ) {
15 parent::__construct( $info );
16 $this->config = $config;
17 }
18
19 /**
20 * 機能毎のKEY取得
21 *
22 * @return string
23 */
24 public function get_feature_key(): string {
25 return self::KEY_FEATURE;
26 }
27
28 /**
29 * テーブル名取得
30 *
31 * @return string
32 */
33 public function get_table_name(): string {
34 global $wpdb;
35
36 return $wpdb->prefix . self::TABLE_NAME;
37 }
38
39 /**
40 * サーバーエラーを追加
41 *
42 * @param array $error
43 *
44 * @return void
45 */
46 private function insert_error( array $error ): void {
47 global $wpdb;
48 $table_name = $wpdb->prefix . self::TABLE_NAME;
49 $max_items = self::MAX_ITEMS;
50 $error['created_at'] = current_time( 'mysql' );
51
52 if ( is_null( $error['message'] ) ) {
53 $error['message'] = '';
54 }
55
56 if ( is_null( $error['file'] ) ) {
57 $error['file'] = '';
58 }
59
60 if ( mb_strlen( $error['message'], 'UTF-8' ) > 65535 ) {
61 $error['message'] = mb_substr( $error['message'], 0, 65535, 'UTF-8' );
62 }
63
64 if ( mb_strlen( $error['file'], 'UTF-8' ) > 65535 ) {
65 $error['file'] = mb_substr( $error['file'], 0, 65535, 'UTF-8' );
66 }
67
68 $wpdb->query( 'START TRANSACTION' );
69 $wpdb->insert( $table_name, $error );
70 $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}cloudsecurewp_server_error WHERE id <= (SELECT id FROM (SELECT id FROM {$wpdb->prefix}cloudsecurewp_server_error ORDER BY id DESC LIMIT 1 OFFSET %d) tmp)", $max_items ) );
71 $wpdb->query( 'COMMIT' );
72 }
73
74 /**
75 * サーバーエラーを取得
76 *
77 * @param string $orderby
78 * @param string $order
79 * @param int $per_page
80 * @param int $offset
81 *
82 * @return array
83 */
84 public function get_server_errors( string $orderby, string $order, int $per_page, int $offset ): array {
85 global $wpdb;
86 $table_name = $wpdb->prefix . self::TABLE_NAME;
87 $allowed_orderby = array( 'created_at', 'type', 'message', 'file', 'line', 'id' );
88 $orderby = in_array( $orderby, $allowed_orderby, true ) ? $orderby : 'created_at';
89 $order = ( 'asc' === $order ) ? 'ASC' : 'DESC';
90 $sql = "SELECT * FROM $table_name ORDER BY {$orderby} {$order} LIMIT %d OFFSET %d";
91
92 return array(
93 $wpdb->get_results( $wpdb->prepare( $sql, $per_page, $offset ), ARRAY_A ),
94 $wpdb->get_var( "SELECT count(*) FROM {$wpdb->prefix}cloudsecurewp_server_error" ),
95 );
96 }
97
98 /**
99 * 有効無効判定
100 *
101 * @return bool
102 */
103 public function is_enabled(): bool {
104 return $this->config->get( $this->get_feature_key() ) === 't';
105 }
106
107 /**
108 * 初期設定値取得
109 *
110 * @return array
111 */
112 public function get_default(): array {
113 return array( self::KEY_FEATURE => $this->check_environment() ? 't' : 'f' );
114 }
115
116 /**
117 * 設定値取得
118 */
119 public function get_settings(): array {
120 $settings = array();
121 $default = $this->get_default();
122
123 foreach ( $default as $key => $val ) {
124 $settings[ $key ] = $this->config->get( $key );
125 }
126
127 return $settings;
128 }
129
130 /**
131 * 設定値保存
132 *
133 * @param array $settings
134 *
135 * @return void
136 */
137 public function save_settings( array $settings ): void {
138 $default = $this->get_default();
139
140 foreach ( $default as $key => $val ) {
141 $this->config->set( $key, $settings[ $key ] ?? '' );
142 }
143
144 $this->config->save();
145 }
146
147 /**
148 * エラータイプ名称を取得
149 *
150 * @param int $error_type
151 *
152 * @return string
153 */
154 private function get_error_type_name( int $error_type ): string {
155 // 下記のコードを参考にさせていただきました。
156 // https://github.com/WordPress/WordPress/blob/aac1b7c487c9a5fd206f6845e4eba4164b02f02b/wp-includes/error-protection.php#L48
157 $constants = get_defined_constants( true );
158 $constants = $constants['Core'] ?? $constants['internal'];
159
160 foreach ( $constants as $constant => $value ) {
161 if ( 0 === strpos( $constant, 'E_' ) && $error_type === $value ) {
162 return $constant;
163 }
164 }
165
166 return '';
167 }
168
169 /**
170 * メール本文取得
171 *
172 * @param array{ type: int , message: string, file: string, line: int } $error
173 *
174 * @return string
175 */
176 private function get_body( array $error ): string {
177 $date = $this->get_date();
178 $time = $this->get_time();
179
180 $text = "$date $time にサーバーエラーが発生しました。" . PHP_EOL;
181 $text .= PHP_EOL;
182 $text .= '【サーバーエラー�
183 報】' . PHP_EOL;
184 $text .= PHP_EOL;
185 $text .= "・エラータイプ:{$error['type']}" . PHP_EOL;
186 $text .= PHP_EOL;
187 $text .= "・エラーメッセージ:{$error['message']}" . PHP_EOL;
188 $text .= PHP_EOL;
189 $text .= "・エラー箇所:{$error['file']}:{$error['line']}" . PHP_EOL;
190 $text .= PHP_EOL;
191 $text .= '--' . PHP_EOL;
192 $text .= 'CloudSecure WP Security' . PHP_EOL;
193
194 return $text;
195 }
196
197 /**
198 * 通知
199 */
200 public function notification( $args, $error ) {
201
202 $error['type'] = $this->get_error_type_name( $error['type'] );
203
204 $this->insert_error( $error );
205
206 $enable_email_server_error_notification = get_option( 'cloudsecurewp_enable_email_server_error_notification', 't' );
207 if ( 't' === $enable_email_server_error_notification ) {
208 $option_name = "cloudsecurewp_error_type_{$error['type']}_email_last_sent";
209 $last_sent = get_option( $option_name );
210 if ( ! $last_sent || time() > $last_sent + HOUR_IN_SECONDS ) {
211 update_option( $option_name, time() );
212 $to = get_option( 'admin_email' );
213 $this->wp_send_mail( $to, esc_html( 'サーバーエラー通知' ), $this->get_body( $error ) );
214 }
215 }
216
217 return $args;
218 }
219
220 /**
221 * 有効化
222 *
223 * @return void
224 */
225 public function activate(): void {
226 $this->save_settings( $this->get_default() );
227
228 global $wpdb;
229 $table_name = $this->get_table_name();
230 $table = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $table_name ) ) );
231 $charset_collate = $wpdb->get_charset_collate();
232
233 if ( ! is_null( $table ) ) {
234 $sql = "ALTER TABLE {$table_name} ALTER message DROP DEFAULT";
235 $sql2 = "ALTER TABLE {$table_name} ALTER file DROP DEFAULT";
236 $wpdb->query( $sql );
237 $wpdb->query( $sql2 );
238
239 } else {
240 $sql = "CREATE TABLE {$table_name} (
241 id BIGINT( 20 ) UNSIGNED NOT NULL AUTO_INCREMENT,
242 type VARCHAR( 31 ) NOT NULL DEFAULT 0,
243 message VARCHAR( 65535 ) NOT NULL,
244 file VARCHAR( 65535 ) NOT NULL,
245 line INT NOT NULL DEFAULT 0,
246 created_at DATETIME,
247 UNIQUE KEY id ( id )
248 ) {$charset_collate}";
249
250 $wpdb->query( $sql );
251 }
252 }
253
254 /**
255 * 無効化
256 *
257 * @return void
258 */
259 public function deactivate(): void {
260 $this->config->set( $this->get_feature_key(), 'f' );
261 $this->config->save();
262 }
263 }
264