Defender Security – Malware Scanner, Login Security & Firewall - Version 2.4.5

Version Description

( 2020-12-17 ) =

  • New: Add pagination option for IP lockout logs
  • Enhance: Display Blocklist Monitor in the config structure
  • Fix: Malware Scanning marks own files as suspicious
  • Fix: The IP 127.0.0.1 shows as blocked
  • Fix: Display Notifications in the Hub
  • Fix: File Scan display issue in MS Edge
  • Fix: Hero Image overlaps in Preset Configs
  • Fix: Redirect Url UI needs improvement on Choose redirect page
  • Fix: Display MaxMind link
Download this release

Release Info

Developer rickjc89
Plugin Icon 128x128 Defender Security – Malware Scanner, Login Security & Firewall
Version 2.4.5
Comparing to
See all releases

Code changes from version 2.3.2 to 2.4.5

Files changed (123) hide show
  1. app/behavior/activator-free.php +0 -46
  2. app/behavior/blacklist-free.php +0 -13
  3. app/behavior/endpoint.php +0 -29
  4. app/behavior/utils.php +0 -1238
  5. app/behavior/wpmudev.php +0 -167
  6. app/component/cli.php +0 -267
  7. app/component/data-factory.php +0 -224
  8. app/component/error-code.php +0 -19
  9. app/component/jed.php +0 -71
  10. app/component/public-suffix.php +0 -8796
  11. app/controller.php +0 -57
  12. app/controller/dashboard.php +0 -744
  13. app/controller/debug.php +0 -79
  14. app/controller/gdpr.php +0 -24
  15. app/controller/requirement.php +0 -102
  16. app/controller/tutorial.php +0 -61
  17. app/controller/waf.php +0 -174
  18. app/module/advanced-tools.php +0 -19
  19. app/module/advanced-tools/component/auth-api.php +0 -368
  20. app/module/advanced-tools/component/auth-listener.php +0 -460
  21. app/module/advanced-tools/component/mask-api.php +0 -320
  22. app/module/advanced-tools/component/mask-login-listener.php +0 -291
  23. app/module/advanced-tools/component/security-header.php +0 -129
  24. app/module/advanced-tools/component/security-headers-listener.php +0 -45
  25. app/module/advanced-tools/component/security-headers/sh-content-type-options.php +0 -77
  26. app/module/advanced-tools/component/security-headers/sh-feature-policy.php +0 -161
  27. app/module/advanced-tools/component/security-headers/sh-referrer-policy.php +0 -87
  28. app/module/advanced-tools/component/security-headers/sh-strict-transport.php +0 -176
  29. app/module/advanced-tools/component/security-headers/sh-x-frame.php +0 -118
  30. app/module/advanced-tools/component/security-headers/sh-xss-protection.php +0 -99
  31. app/module/advanced-tools/controller/main.php +0 -129
  32. app/module/advanced-tools/controller/rest.php +0 -121
  33. app/module/advanced-tools/css/login-admin.css +0 -34
  34. app/module/advanced-tools/css/login.css +0 -21
  35. app/module/advanced-tools/img/2factor-disabled.svg +0 -85
  36. app/module/advanced-tools/model/auth-settings.php +0 -171
  37. app/module/advanced-tools/model/mask-settings.php +0 -153
  38. app/module/advanced-tools/model/security-headers-settings.php +0 -310
  39. app/module/advanced-tools/view/login/disabled.php +0 -156
  40. app/module/advanced-tools/view/login/enabled.php +0 -50
  41. app/module/advanced-tools/view/login/otp.php +0 -331
  42. app/module/advanced-tools/view/main-free.php +0 -269
  43. app/module/advanced-tools/view/mask-login/enabled.php +0 -116
  44. app/module/audit.php +0 -25
  45. app/module/audit/controller/main-free.php +0 -79
  46. app/module/audit/view/main-free.php +0 -1
  47. app/module/hardener.php +0 -60
  48. app/module/hardener/component/change-admin-service.php +0 -117
  49. app/module/hardener/component/change-admin.php +0 -86
  50. app/module/hardener/component/db-prefix-service.php +0 -262
  51. app/module/hardener/component/db-prefix.php +0 -97
  52. app/module/hardener/component/disable-file-editor-service.php +0 -102
  53. app/module/hardener/component/disable-file-editor.php +0 -128
  54. app/module/hardener/component/disable-trackback-service.php +0 -109
  55. app/module/hardener/component/disable-trackback.php +0 -102
  56. app/module/hardener/component/disable-xml-rpc-service.php +0 -44
  57. app/module/hardener/component/disable-xml-rpc.php +0 -96
  58. app/module/hardener/component/hide-error-service.php +0 -144
  59. app/module/hardener/component/hide-error.php +0 -91
  60. app/module/hardener/component/login-duration-service.php +0 -57
  61. app/module/hardener/component/login-duration.php +0 -176
  62. app/module/hardener/component/php-version-service.php +0 -68
  63. app/module/hardener/component/php-version.php +0 -81
  64. app/module/hardener/component/prevent-enum-users-service.php +0 -47
  65. app/module/hardener/component/prevent-enum-users.php +0 -125
  66. app/module/hardener/component/prevent-php-service.php +0 -95
  67. app/module/hardener/component/prevent-php.php +0 -212
  68. app/module/hardener/component/protect-information-service.php +0 -191
  69. app/module/hardener/component/protect-information.php +0 -94
  70. app/module/hardener/component/security-key-service.php +0 -137
  71. app/module/hardener/component/security-key.php +0 -166
  72. app/module/hardener/component/servers/apache-service.php +0 -290
  73. app/module/hardener/component/servers/iis-service.php +0 -122
  74. app/module/hardener/component/sh-content-security-service.php +0 -173
  75. app/module/hardener/component/sh-content-security.php +0 -331
  76. app/module/hardener/component/sh-content-type-options-service.php +0 -78
  77. app/module/hardener/component/sh-content-type-options.php +0 -121
  78. app/module/hardener/component/sh-feature-policy-service.php +0 -96
  79. app/module/hardener/component/sh-feature-policy.php +0 -175
  80. app/module/hardener/component/sh-referrer-policy-service.php +0 -97
  81. app/module/hardener/component/sh-referrer-policy.php +0 -132
  82. app/module/hardener/component/sh-strict-transport-service.php +0 -112
  83. app/module/hardener/component/sh-strict-transport.php +0 -149
  84. app/module/hardener/component/sh-x-frame-service.php +0 -102
  85. app/module/hardener/component/sh-x-frame.php +0 -125
  86. app/module/hardener/component/sh-xss-protection-service.php +0 -86
  87. app/module/hardener/component/sh-xss-protection.php +0 -128
  88. app/module/hardener/component/wp-rest-api-service.php +0 -51
  89. app/module/hardener/component/wp-rest-api.php +0 -120
  90. app/module/hardener/component/wp-version-service.php +0 -59
  91. app/module/hardener/component/wp-version.php +0 -75
  92. app/module/hardener/controller/main.php +0 -273
  93. app/module/hardener/controller/rest.php +0 -197
  94. app/module/hardener/irule-service.php +0 -30
  95. app/module/hardener/js/scripts.js +0 -230
  96. app/module/hardener/model/settings.php +0 -620
  97. app/module/hardener/rule-service.php +0 -142
  98. app/module/hardener/rule.php +0 -177
  99. app/module/hardener/view/email/notification.php +0 -366
  100. app/module/hardener/view/layouts/layout.php +0 -176
  101. app/module/hardener/view/main.php +0 -2
  102. app/module/hardener/view/rules/db-prefix.php +0 -101
  103. app/module/hardener/view/tweaks/csp/debug-bar.php +0 -21
  104. app/module/hardener/view/tweaks/csp/notification-bar.php +0 -16
  105. app/module/ip-lockout.php +0 -51
  106. app/module/ip-lockout/behavior/widget.php +0 -91
  107. app/module/ip-lockout/component/ip-api.php +0 -218
  108. app/module/ip-lockout/component/login-listener.php +0 -185
  109. app/module/ip-lockout/component/login-protection-api.php +0 -644
  110. app/module/ip-lockout/component/logs-table.php +0 -586
  111. app/module/ip-lockout/component/notfound-listener.php +0 -203
  112. app/module/ip-lockout/controller/main.php +0 -467
  113. app/module/ip-lockout/controller/rest.php +0 -450
  114. app/module/ip-lockout/model/ip-model-legacy.php +0 -167
  115. app/module/ip-lockout/model/ip-model.php +0 -151
  116. app/module/ip-lockout/model/log-model-legacy.php +0 -166
  117. app/module/ip-lockout/model/log-model.php +0 -281
  118. app/module/ip-lockout/model/settings.php +0 -767
  119. app/module/ip-lockout/view/detect-404/enabled.php +0 -196
  120. app/module/ip-lockout/view/emails/404-ban.php +0 -694
  121. app/module/ip-lockout/view/emails/404-lockout.php +0 -697
  122. app/module/ip-lockout/view/emails/login-lockout.php +0 -697
  123. app/module/ip-lockout/view/emails/login-username-ban.php +0 -606
app/behavior/activator-free.php DELETED
@@ -1,46 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Behavior;
7
-
8
- use Hammer\Base\Behavior;
9
- use Hammer\Helper\WP_Helper;
10
-
11
- class Activator_Free extends Behavior {
12
- /**
13
- * Check if we should show activator screen
14
- * @return bool
15
- */
16
- public function isShowActivator() {
17
- $cache = WP_Helper::getCache();
18
- if ( $cache->get( 'wdf_isActivated', false ) == 1 ) {
19
- return 0;
20
- }
21
- if ( get_site_transient( 'wp_defender_free_is_activated' ) == 1 ) {
22
- return 0;
23
- }
24
-
25
- if ( get_site_option( 'wp_defender_free_is_activated' ) == 1 ) {
26
- return 0;
27
- }
28
-
29
- $keys = array(
30
- 'wp_defender',
31
- 'wd_scan_settings',
32
- 'wd_hardener_settings',
33
- 'wd_audit_settings',
34
- 'wd_2auth_settings',
35
- 'wd_masking_login_settings',
36
- );
37
- foreach ( $keys as $key ) {
38
- $option = get_site_option( $key );
39
- if ( is_array( $option ) ) {
40
- return 0;
41
- }
42
- }
43
-
44
- return 1;
45
- }
46
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/behavior/blacklist-free.php DELETED
@@ -1,13 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Behavior;
7
-
8
- use Hammer\Base\Behavior;
9
- use WP_Defender\Component\Error_Code;
10
-
11
- class Blacklist_Free extends Behavior {
12
-
13
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
app/behavior/endpoint.php DELETED
@@ -1,29 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Behavior;
7
-
8
- use Hammer\Helper\WP_Helper;
9
-
10
- class Endpoint extends \Hammer\Base\Behavior {
11
-
12
- /**
13
- * This will contains the endpoints of current session
14
- * @return array
15
- */
16
- public function getAllAvailableEndpoints( $module ) {
17
- $endpoints = (array) WP_Helper::getArrayCache()->get( 'endpoints' );
18
-
19
- return isset( $endpoints[ $module ] ) ? $endpoints[ $module ] : array();
20
- }
21
-
22
- /**
23
- * a quick helper for static class
24
- * @return Endpoint
25
- */
26
- public static function instance() {
27
- return new Endpoint();
28
- }
29
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/behavior/utils.php DELETED
@@ -1,1238 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Behavior;
7
-
8
- use Hammer\Base\Behavior;
9
- use Hammer\Helper\Log_Helper;
10
- use Hammer\Helper\WP_Helper;
11
- use WP_Defender\Component\Error_Code;
12
- use WP_Defender\Component\Jed;
13
- use WP_Defender\Module\Two_Factor\Model\Auth_Settings;
14
- use WP_Defender\Module\Hardener\Model\Settings;
15
- use WP_Defender\Module\IP_Lockout\Component\Login_Protection_Api;
16
- use WP_Defender\Module\Scan\Component\Scan_Api;
17
- use WP_Defender\Module\Scan\Model\Result_Item;
18
-
19
- class Utils extends Behavior {
20
- /**
21
- * @return bool
22
- */
23
- public function isActivatedSingle() {
24
- if ( WP_Helper::is_network_activate( wp_defender()->plugin_slug ) ) {
25
- return false;
26
- }
27
-
28
- return true;
29
- }
30
-
31
- /**
32
- * @param $endPoint
33
- * @param array $bodyArgs
34
- * @param array $requestArgs
35
- * @param bool $returnRaw
36
- *
37
- * @return array|mixed|object|\WP_Error
38
- */
39
- public function devCall( $endPoint, $bodyArgs = array(), $requestArgs = array(), $returnRaw = false ) {
40
- $api_key = $this->getAPIKey();
41
- if ( $api_key !== false ) {
42
- $domain = network_site_url();
43
- $post_vars['body'] = $bodyArgs;
44
- $post_vars['body']['domain'] = $domain;
45
- $post_vars['timeout'] = 30;
46
- $post_vars['httpversion'] = '1.1';
47
-
48
- $post_vars = array_merge( $post_vars, $requestArgs );
49
- $headers = isset( $post_vars['headers'] ) ? $post_vars['headers'] : array();
50
- $post_vars['headers'] = array_merge( $headers, array(
51
- 'Authorization' => 'Basic ' . $api_key
52
- ) );
53
-
54
- $response = wp_remote_request( $endPoint,
55
- apply_filters( 'wd_wpmudev_call_request_args',
56
- $post_vars ) );
57
-
58
- if ( is_wp_error( $response ) ) {
59
- return $response;
60
- }
61
-
62
- if ( $returnRaw == true ) {
63
- return $response;
64
- }
65
-
66
- if (
67
- 'OK' !== wp_remote_retrieve_response_message( $response )
68
- or 200 !== wp_remote_retrieve_response_code( $response )
69
- ) {
70
- return new \WP_Error( wp_remote_retrieve_response_code( $response ),
71
- wp_remote_retrieve_response_message( $response ) );
72
- } else {
73
- $data = wp_remote_retrieve_body( $response );
74
-
75
- return json_decode( $data, true );
76
- }
77
- } else {
78
- return new \WP_Error( 'dashboard_required',
79
- sprintf( esc_html__( "WPMU DEV Dashboard will be required for this action. Please visit <a href=\"%s\">here</a> and install the WPMU DEV Dashboard",
80
- "defender-security" )
81
- , 'https://premium.wpmudev.org/project/wpmu-dev-dashboard/' ) );
82
- }
83
- }
84
-
85
- /**
86
- * @return string
87
- */
88
- public function getPHPVersion() {
89
- return phpversion();
90
- }
91
-
92
- /**
93
- * @return string
94
- */
95
- public function getWPVersion() {
96
- global $wp_version;
97
-
98
- return $wp_version;
99
- }
100
-
101
- public function getAPIKey() {
102
- if ( ( $version = $this->isDashboardInstalled() ) !== false ) {
103
- if ( version_compare( $version, '4.0.0' ) >= 0 ) {
104
- //this is version 4+
105
- //instanize once
106
- \WPMUDEV_Dashboard::instance();
107
- $membeshipStatus = \WPMUDEV_Dashboard::$api->get_membership_data();
108
-
109
- if ( $membeshipStatus['membership'] != 'free' ) {
110
- return \WPMUDEV_Dashboard::$api->get_key();
111
- } else {
112
- return false;
113
- }
114
- } else {
115
- global $wpmudev_un;
116
- $api_key = $wpmudev_un->get_apikey();
117
-
118
- return $api_key;
119
- }
120
- }
121
-
122
- return false;
123
- }
124
-
125
- /**
126
- * Check if WPMUDEV Dashboard installed, return version, else return false
127
- * @return bool|string
128
- */
129
- public function isDashboardInstalled() {
130
- //check if this is new
131
- if ( class_exists( 'WPMUDEV_Dashboard' ) ) {
132
- return \WPMUDEV_Dashboard::$version;
133
- }
134
-
135
- return false;
136
- }
137
-
138
- /**
139
- * Check if current user qualify for current operation
140
- * @return bool
141
- */
142
- public function checkPermission() {
143
- if ( ! is_user_logged_in() ) {
144
- return false;
145
- }
146
- $cap = is_multisite() ? 'manage_network_options' : 'manage_options';
147
-
148
- return current_user_can( $cap );
149
- }
150
-
151
- /**
152
- * @param $timestring string
153
- * @param bool $i18n
154
- *
155
- * @return false|string
156
- */
157
- public function formatDateTime( $timestring, $i18n = true ) {
158
- if ( strlen( $timestring ) == 0 ) {
159
- return null;
160
- }
161
- if ( ! filter_var( $timestring, FILTER_VALIDATE_INT ) ) {
162
- $timestring = strtotime( $timestring );
163
- }
164
- $format = get_option( 'date_format' ) . ' ' . get_option( 'time_format' );
165
- if ( $i18n == false ) {
166
- return date( $format, $timestring );
167
- } else {
168
- $time = get_date_from_gmt( date( 'Y-m-d H:i:s', $timestring ), 'Y-m-d H:i:s' );
169
-
170
- return date_i18n( $format, strtotime( $time ) );
171
- }
172
- }
173
-
174
- /**
175
- * Get user display name if logged in, or Guest instead
176
- *
177
- * @param null $user_id
178
- *
179
- * @return string
180
- */
181
- public function getDisplayName( $user_id = null ) {
182
- if ( ! is_user_logged_in() && is_null( $user_id ) ) {
183
- return esc_html__( "Guest", "defender-security" );
184
- }
185
-
186
- if ( is_null( $user_id ) ) {
187
- $user_id = get_current_user_id();
188
- }
189
-
190
- $userdata = get_userdata( $user_id );
191
- if ( ! is_object( $userdata ) ) {
192
- return __( "Guest", "defender-security" );
193
- }
194
-
195
- $fullname = trim( $userdata->first_name . ' ' . $userdata->last_name );
196
- if ( empty( $fullname ) ) {
197
- $fullname = $userdata->display_name;
198
- }
199
-
200
- return $fullname;
201
- }
202
-
203
- /**
204
- * @param $get_avatar
205
- *
206
- * @return mixed
207
- */
208
- public function getAvatarUrl( $get_avatar ) {
209
- preg_match( "/src='(.*?)'/i", $get_avatar, $matches );
210
-
211
- return $matches[1];
212
- }
213
-
214
- /**
215
- * Make filesize friendy with human, src from http://jeffreysambells.com/2012/10/25/human-readable-filesize-php
216
- *
217
- * @param $bytes
218
- *
219
- * @return string
220
- *
221
- */
222
- public function makeReadable( $bytes ) {
223
- if ( $bytes >= 1073741824 ) {
224
- $bytes = number_format( $bytes / 1073741824, 2 ) . ' GB';
225
- } elseif ( $bytes >= 1048576 ) {
226
- $bytes = number_format( $bytes / 1048576, 2 ) . ' MB';
227
- } elseif ( $bytes >= 1024 ) {
228
- $bytes = number_format( $bytes / 1024, 2 ) . ' KB';
229
- } elseif ( $bytes > 1 ) {
230
- $bytes = $bytes . ' bytes';
231
- } elseif ( $bytes == 1 ) {
232
- $bytes = $bytes . ' byte';
233
- } else {
234
- $bytes = '0 bytes';
235
- }
236
-
237
- return $bytes;
238
- }
239
-
240
- /**
241
- * @param $timestamp
242
- *
243
- * @return false|int
244
- */
245
- public function localToUtc( $timestring ) {
246
- $tz = get_option( 'timezone_string' );
247
- if ( ! $tz ) {
248
- $gmt_offset = get_option( 'gmt_offset' );
249
- if ( $gmt_offset == 0 ) {
250
- return strtotime( $timestring );
251
- }
252
- $tz = $this->getTimezoneString( $gmt_offset );
253
- }
254
- if ( ! $tz ) {
255
- $tz = 'UTC';
256
- }
257
- $timezone = new \DateTimeZone( $tz );
258
- $time = new \DateTime( $timestring, $timezone );
259
-
260
- return $time->getTimestamp();
261
- }
262
-
263
- /**
264
- * @param $time string - format H:i
265
- * @param $hook string - hook
266
- *
267
- * @return false|int
268
- */
269
- public function reportCronTimestamp( $time, $hook ) {
270
- wp_clear_scheduled_hook( $hook );
271
- $timeString = date( 'Y-m-d', current_time( 'timestamp' ) ) . ' ' . $time . ':00';
272
- $timestamp = $this->localToUtc( $timeString );
273
- if ( $timestamp > time() ) {
274
- return $timestamp;
275
- } else {
276
- //time is passed, tomorrow
277
- $timeString = date( 'Y-m-d', strtotime( 'tomorrow', current_time( 'timestamp' ) ) ) . ' ' . $time . ':00';
278
-
279
- return $this->localToUtc( $timeString );
280
- }
281
- }
282
-
283
- /**
284
- * @param $interval
285
- * @param $day
286
- * @param $lastReportTime
287
- *
288
- * @return bool
289
- */
290
- public function isReportTime( $interval, $day, $lastReportTime = false ) {
291
- if ( $interval == 1 ) {
292
- //this is daily, always send when interval come
293
- return true;
294
- }
295
- $current_day = strtolower( strftime( '%A', current_time( 'timestamp' ) ) );
296
- if ( $interval == 7 && $current_day == strtolower( $day ) ) {
297
- //check the day
298
- return true;
299
- } elseif ( $interval == 30
300
- && $lastReportTime
301
- && strtotime( '+30 days', $lastReportTime ) < time()
302
- && $current_day == strtolower( $day )
303
- ) {
304
- return true;
305
- }
306
-
307
- return false;
308
- }
309
-
310
- /**
311
- * @param $timezone
312
- *
313
- * @return false|string
314
- */
315
- public function getTimezoneString( $timezone ) {
316
- $timezone = explode( '.', $timezone );
317
- if ( isset( $timezone[1] ) ) {
318
- $timezone[1] = 30;
319
- } else {
320
- $timezone[1] = '00';
321
- }
322
- $offset = implode( ':', $timezone );
323
- list( $hours, $minutes ) = explode( ':', $offset );
324
- $seconds = $hours * 60 * 60 + $minutes * 60;
325
- $lc = localtime( time(), true );
326
- if ( isset( $lc['tm_isdst'] ) ) {
327
- $isdst = $lc['tm_isdst'];
328
- } else {
329
- $isdst = 0;
330
- }
331
- $tz = timezone_name_from_abbr( '', $seconds, $isdst );
332
- if ( $tz === false ) {
333
- $tz = timezone_name_from_abbr( '', $seconds, 0 );
334
- }
335
-
336
- return $tz;
337
- }
338
-
339
- /**
340
- * Get days of week
341
- * @return mixed|void
342
- * @access public
343
- * @since 1.0
344
- */
345
- public function getDaysOfWeek() {
346
- $timestamp = strtotime( 'next Sunday' );
347
- $days = array();
348
- for ( $i = 0; $i < 7; $i ++ ) {
349
- $days[] = strftime( '%A', $timestamp );
350
- $timestamp = strtotime( '+1 day', $timestamp );
351
- }
352
-
353
- return apply_filters( 'wd_scan_get_days_of_week', $days );
354
- }
355
-
356
- /**
357
- * Validates that the IP that made the request is from cloudflare
358
- *
359
- * @param String $ip - the ip to check
360
- *
361
- * @return bool
362
- */
363
- private function _validateCloudflareIP( $ip ) {
364
- $cloudflare_ips = array(
365
- '199.27.128.0/21',
366
- '173.245.48.0/20',
367
- '103.21.244.0/22',
368
- '103.22.200.0/22',
369
- '103.31.4.0/22',
370
- '141.101.64.0/18',
371
- '108.162.192.0/18',
372
- '190.93.240.0/20',
373
- '188.114.96.0/20',
374
- '197.234.240.0/22',
375
- '198.41.128.0/17',
376
- '162.158.0.0/15',
377
- '104.16.0.0/12',
378
- );
379
- $is_cf_ip = false;
380
- foreach ( $cloudflare_ips as $cloudflare_ip ) {
381
- if ( $this->_cloudflareIpInRange( $ip, $cloudflare_ip ) ) {
382
- $is_cf_ip = true;
383
- break;
384
- }
385
- }
386
-
387
- return $is_cf_ip;
388
- }
389
-
390
- /**
391
- * Check if the cloudflare IP is in range
392
- *
393
- * @param String $ip - the current IP
394
- * @param String $range - the allowed range of cloudflare ips
395
- *
396
- * @return bool
397
- */
398
- function _cloudflareIpInRange( $ip, $range ) {
399
- if ( strpos( $range, '/' ) == false ) {
400
- $range .= '/32';
401
- }
402
-
403
- // $range is in IP/CIDR format eg 127.0.0.1/24
404
- list( $range, $netmask ) = explode( '/', $range, 2 );
405
- $range_decimal = ip2long( $range );
406
- $ip_decimal = ip2long( $ip );
407
- $wildcard_decimal = pow( 2, ( 32 - $netmask ) ) - 1;
408
- $netmask_decimal = ~$wildcard_decimal;
409
-
410
- return ( ( $ip_decimal & $netmask_decimal ) == ( $range_decimal & $netmask_decimal ) );
411
- }
412
-
413
- /**
414
- * Check if there are any cloudflare headers in the request
415
- *
416
- * @return bool
417
- */
418
- function _cloudflareRequestsCheck() {
419
- $flag = true;
420
-
421
- if ( ! isset( $_SERVER['HTTP_CF_CONNECTING_IP'] ) ) {
422
- $flag = false;
423
- }
424
- if ( ! isset( $_SERVER['HTTP_CF_IPCOUNTRY'] ) ) {
425
- $flag = false;
426
- }
427
- if ( ! isset( $_SERVER['HTTP_CF_RAY'] ) ) {
428
- $flag = false;
429
- }
430
- if ( ! isset( $_SERVER['HTTP_CF_VISITOR'] ) ) {
431
- $flag = false;
432
- }
433
-
434
- return $flag;
435
- }
436
-
437
- /**
438
- * Check if the request is from cloudflare. If it is, we get the IP
439
- *
440
- * @return bool
441
- */
442
- function isCloudflare() {
443
- if ( php_sapi_name() == 'cli' ) {
444
- return false;
445
- }
446
- if ( isset( $_SERVER['HTTP_CLIENT_IP'] ) ) {
447
- $ip = $_SERVER['HTTP_CLIENT_IP'];
448
- } elseif ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
449
- $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
450
- } else {
451
- $ip = $_SERVER['REMOTE_ADDR'];
452
- }
453
- if ( isset( $ip ) ) {
454
- $request_check = $this->_cloudflareRequestsCheck();
455
- if ( ! $request_check ) {
456
- return false;
457
- }
458
-
459
- $ip_check = $this->_validateCloudflareIP( $ip );
460
-
461
- return $ip_check;
462
- }
463
-
464
- return false;
465
- }
466
-
467
- /**
468
- * A shorhand function to get user IP
469
- * @return mixed|string
470
- */
471
- public function getUserIp() {
472
- $client = isset( $_SERVER['HTTP_CLIENT_IP'] ) ? $_SERVER['HTTP_CLIENT_IP'] : null;
473
- $forward = isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : null;
474
- $is_cf = $this->isCloudflare(); //Check if request is from CloudFlare
475
- if ( $is_cf ) {
476
- $cf_ip = $_SERVER['HTTP_CF_CONNECTING_IP']; //We already make sure this is set in the checks
477
- if ( filter_var( $cf_ip, FILTER_VALIDATE_IP ) ) {
478
- return apply_filters( 'defender_user_ip', $cf_ip );
479
- }
480
- } else {
481
- $remote = isset( $_SERVER['REMOTE_ADDR'] ) ? $_SERVER['REMOTE_ADDR'] : null;
482
- }
483
- $client_real = isset( $_SERVER['HTTP_X_REAL_IP'] ) ? $_SERVER['HTTP_X_REAL_IP'] : null;
484
- $ret = $remote;
485
- if ( filter_var( $client, FILTER_VALIDATE_IP ) ) {
486
- $ret = $client;
487
- } elseif ( filter_var( $client_real, FILTER_VALIDATE_IP ) ) {
488
- $ret = $client_real;
489
- } elseif ( ! empty( $forward ) ) {
490
- $forward = explode( ',', $forward );
491
- $ip = array_shift( $forward );
492
- $ip = trim( $ip );
493
- if ( filter_var( $ip, FILTER_VALIDATE_IP ) ) {
494
- $ret = $ip;
495
- }
496
- }
497
-
498
- return apply_filters( 'defender_user_ip', $ret );
499
- }
500
-
501
- /**
502
- * Return times frame for selectbox
503
- * @access public
504
- * @since 1.0
505
- */
506
- public function getTimes() {
507
- $data = array();
508
- for ( $i = 0; $i < 24; $i ++ ) {
509
- foreach ( apply_filters( 'wd_scan_get_times_interval', array( '00', '30' ) ) as $min ) {
510
- $time = $i . ':' . $min;
511
- $data[ $time ] = apply_filters( 'wd_scan_get_times_hour_min',
512
- strftime( '%I:%M %p', strtotime( $time ) ) );
513
- }
514
- }
515
-
516
- return apply_filters( 'wd_scan_get_times', $data );
517
- }
518
-
519
- /**
520
- * a quick helper for static class
521
- * @return Utils
522
- */
523
- public static function instance() {
524
- return new Utils();
525
- }
526
-
527
- /**
528
- * Determine the server
529
- * Incase we are using a hybrid server and need to know where static files are houses, pass true as a param
530
- *
531
- * @param $useStaticPath - use static path instead of home url. This is the path to Defender changelog
532
- */
533
- public function determineServer( $useStaticPath = false ) {
534
- $url = ( $useStaticPath ) ? wp_defender()->getPluginUrl() . 'changelog.txt' : home_url();
535
- $server_type = get_site_option( 'wd_util_server' );
536
- if ( ! is_array( $server_type ) ) {
537
- $server_type = array();
538
- }
539
-
540
- if ( isset( $server_type[ $url ] ) && ! empty( $server_type[ $url ] ) ) {
541
- return strtolower( $server_type[ $url ] );
542
- }
543
-
544
- //url should be end with php
545
- global $is_apache, $is_nginx, $is_IIS, $is_iis7;
546
-
547
- $server = null;
548
- $ssl_verify = apply_filters( 'defender_ssl_verify',
549
- true ); //most hosts dont really have valid ssl or ssl still pending
550
-
551
- if ( $is_nginx ) {
552
- $server = 'nginx';
553
- } elseif ( $is_apache ) {
554
- //case the url is detecting php file
555
- if ( pathinfo( $url, PATHINFO_EXTENSION ) == 'php' ) {
556
- $server = 'apache';
557
- } else {
558
- //so the server software is apache, let see what the header return
559
- $request = wp_remote_head( $url, array(
560
- 'user-agent' => 'WP Defender self ping - determine server type',
561
- 'sslverify' => $ssl_verify
562
- ) );
563
- $server = wp_remote_retrieve_header( $request, 'server' );
564
- $server = explode( '/', $server );
565
- if ( strtolower( $server[0] ) == 'nginx' ) {
566
- //proxy case
567
- $server = 'nginx';
568
- } else {
569
- $server = 'apache';
570
- }
571
- }
572
- } elseif ( $is_iis7 || $is_IIS ) {
573
- $server = 'iis';
574
- }
575
-
576
- if ( is_null( $server ) && ( php_sapi_name() !== 'cli' ) ) {
577
- //if fall in here, means there is st unknowed.
578
- //we need to check there is not cli evn
579
- $request = wp_remote_head( $url, array(
580
- 'user-agent' => 'WP Defender self ping - determine server type',
581
- 'sslverify' => $ssl_verify
582
- ) );
583
- $server = wp_remote_retrieve_header( $request, 'server' );
584
- $server = explode( '/', $server );
585
- $server = $server[0];
586
- }
587
-
588
- $server_type[ $url ] = $server;
589
- update_site_option( 'wd_util_server', $server_type );
590
-
591
- return $server;
592
- }
593
-
594
- /**
595
- * Determine the Apache version
596
- * Most web servers have apache_get_version disabled, so we just get a simple curl of the headers
597
- *
598
- * @return String
599
- */
600
- public function determineApacheVersion() {
601
- if ( ! function_exists( 'apache_get_version' ) ) {
602
- $version = '2.2'; //default supported is 2.2
603
- $url = home_url();
604
- $apache_version = get_site_transient( 'wd_util_apache_version' );
605
- if ( ! is_array( $apache_version ) ) {
606
- $apache_version = array();
607
- }
608
-
609
- if ( isset( $apache_version[ $url ] ) && ! empty( $apache_version[ $url ] ) ) {
610
- return strtolower( $apache_version[ $url ] );
611
- }
612
-
613
- $apache_version[ $url ] = $version; //default is 2.2
614
-
615
- if ( isset( $_SERVER['SERVER_SOFTWARE'] ) ) {
616
- $server = explode( " ", $_SERVER['SERVER_SOFTWARE'] );
617
- if ( is_array( $server ) && count( $server ) > 1 ) {
618
- $server = $server[0];
619
- $server = explode( "/", $server );
620
- if ( is_array( $server ) && count( $server ) > 1 ) {
621
- $version = $server[1];
622
- $apache_version[ $url ] = $version;
623
- }
624
- }
625
- }
626
-
627
- set_site_transient( 'wd_util_apache_version', $apache_version, 3600 );
628
- } else {
629
- $version = apache_get_version();
630
- $version = explode( '/', $version );
631
- $version = $version[1];
632
- }
633
-
634
- return $version;
635
- }
636
-
637
- public function format_frequency_for_hub( $frequency, $day, $time ) {
638
- $time = strftime( '%I:%M %p', strtotime( $time ) );
639
- if ( 1 == $frequency ) {
640
- return 'Daily at ' . $time;
641
- } elseif ( 7 == $frequency ) {
642
- return 'Weekly on ' . $day . ' at ' . $time;
643
- } elseif ( 30 == $frequency ) {
644
- return 'Monthly on ';
645
- }
646
- }
647
-
648
- /**
649
- * Return /wp-content/uploads/wp-defender dir, and create if not any
650
- * @return string
651
- */
652
- public function getDefUploadDir() {
653
- $uploadDir = WP_Helper::getUploadDir();
654
- $defDir = $uploadDir . DIRECTORY_SEPARATOR . 'wp-defender';
655
- if ( ! is_dir( $defDir ) ) {
656
- wp_mkdir_p( $defDir );
657
- }
658
-
659
- if ( ! is_file( $defDir . DIRECTORY_SEPARATOR . 'index.php' ) ) {
660
- //create a blank index file
661
- file_put_contents( $defDir . DIRECTORY_SEPARATOR . 'index.php', '' );
662
- }
663
-
664
- return $defDir;
665
- }
666
-
667
- public function recipientsToString( $recipients ) {
668
- $strings = [];
669
- foreach ( $recipients as $recipient ) {
670
- $strings[] = $recipient['email'];
671
- }
672
-
673
- return implode( ', ', $strings );
674
- }
675
-
676
-
677
- /**
678
- * @return array|void
679
- */
680
- public function submitStatsToDev() {
681
- return false;
682
- }
683
-
684
- /**
685
- * @param null $result
686
- *
687
- * @return bool
688
- */
689
- public function checkRequirement( &$result = null ) {
690
- $meet = true;
691
-
692
- if ( version_compare( $this->getPHPVersion(), '5.6', '>=' ) == false ) {
693
- $meet = false;
694
- $result['php'] = array(
695
- 'status' => $this->getPHPVersion(),
696
- 'message' => __( "Please upgrade to 5.6 or later", "defender-security" )
697
- );
698
- }
699
-
700
- return $meet;
701
- }
702
-
703
- /**
704
- * @return string|null
705
- */
706
- public function getSummaryClass() {
707
- return null;
708
- }
709
-
710
-
711
- /**
712
- * @param $freq
713
- *
714
- * @return string
715
- */
716
- public function frequencyToText( $freq ) {
717
- $text = '';
718
- switch ( $freq ) {
719
- case 1:
720
- $text = __( "daily", "defender-security" );
721
- break;
722
- case 7:
723
- $text = __( "weekly", "defender-security" );
724
- break;
725
- case 30:
726
- $text = __( "monthly", "defender-security" );
727
- break;
728
- }
729
-
730
- return $text;
731
- }
732
-
733
- /**
734
- * List server types
735
- *
736
- * @return Array
737
- */
738
- public function serverTypes() {
739
- return apply_filters( 'defender_server_types', array(
740
- 'apache' => 'Apache',
741
- 'litespeed' => 'LiteSpeed',
742
- 'nginx' => 'NGINX',
743
- 'iis' => 'IIS',
744
- 'iis-7' => 'IIS 7'
745
- ) );
746
- }
747
-
748
- /**
749
- * Get the current page URL
750
- *
751
- * @return String
752
- */
753
- public function currentPageURL() {
754
- $protocol = "http";
755
- if ( is_ssl() ) {
756
- $protocol .= "s";
757
- }
758
- $url = "$protocol://";
759
- if ( $_SERVER["SERVER_PORT"] != "80" ) {
760
- $url .= $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . $_SERVER["REQUEST_URI"];
761
- } else {
762
- $url .= $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"];
763
- }
764
-
765
- return apply_filters( 'defender_current_page_url', $url );
766
- }
767
-
768
- /**
769
- * site url with correct sheme
770
- *
771
- * @return string
772
- */
773
- public function siteURLWithScheme() {
774
- $current_scheme = ( is_ssl() ) ? 'https' : 'http';
775
-
776
- return network_site_url( '', $current_scheme );
777
- }
778
-
779
- /**
780
- * @param $campaign
781
- *
782
- * @return string
783
- */
784
- public function campaignURL( $campaign ) {
785
- $url = "https://premium.wpmudev.org/project/wp-defender/?utm_source=defender&utm_medium=plugin&utm_campaign=" . $campaign;
786
-
787
- return $url;
788
- }
789
-
790
- /**
791
- * We will need to convert mo translate into json for frontend can read
792
- *
793
- * @param $handle
794
- */
795
- public function createTranslationJson( $handle ) {
796
- $locale = determine_locale();
797
- $mo_file = "wpdef-{$locale}.mo";
798
- $mo_path = wp_defender()->getPluginPath() . 'languages/' . $mo_file;
799
- $json_path = wp_defender()->getPluginPath() . 'languages/' . "wpdef-{$locale}-{$handle}.json";
800
- if ( file_exists( $json_path ) ) {
801
- $data = json_decode( file_get_contents( $json_path ), true );
802
- if ( isset( $data['version'] ) ) {
803
- return;
804
- }
805
- @unlink( $json_path );
806
- }
807
-
808
- if ( ! file_exists( $mo_path ) ) {
809
- //no translation found
810
- return;
811
- }
812
- //import from mo
813
- $translations = new \Gettext\Translations();
814
- \Gettext\Extractors\Mo::fromFile( $mo_path, $translations );
815
- $translations->setDomain( 'messages' );
816
- $translations->setLanguage( get_locale() );
817
- //export to json
818
- Jed::toFile( $translations, $json_path );
819
- }
820
-
821
- /**
822
- * @return string
823
- */
824
- public function maybeHighContrast() {
825
- return \WP_Defender\Module\Setting\Model\Settings::instance()->high_contrast_mode == 0 ? '' : 'sui-color-accessible';
826
- }
827
-
828
-
829
- /**
830
- * Copy the list from here
831
- * https://gist.github.com/DHS/1340150
832
- * @return array
833
- */
834
- public function countriesList() {
835
- $country_array = array(
836
- "AF" => "Afghanistan",
837
- "AL" => "Albania",
838
- "DZ" => "Algeria",
839
- "AS" => "American Samoa",
840
- "AD" => "Andorra",
841
- "AO" => "Angola",
842
- "AI" => "Anguilla",
843
- "AQ" => "Antarctica",
844
- "AG" => "Antigua and Barbuda",
845
- "AR" => "Argentina",
846
- "AM" => "Armenia",
847
- "AW" => "Aruba",
848
- "AU" => "Australia",
849
- "AT" => "Austria",
850
- "AZ" => "Azerbaijan",
851
- "BS" => "Bahamas",
852
- "BH" => "Bahrain",
853
- "BD" => "Bangladesh",
854
- "BB" => "Barbados",
855
- "BY" => "Belarus",
856
- "BE" => "Belgium",
857
- "BZ" => "Belize",
858
- "BJ" => "Benin",
859
- "BM" => "Bermuda",
860
- "BT" => "Bhutan",
861
- "BO" => "Bolivia",
862
- "BA" => "Bosnia and Herzegovina",
863
- "BW" => "Botswana",
864
- "BV" => "Bouvet Island",
865
- "BR" => "Brazil",
866
- "BQ" => "British Antarctic Territory",
867
- "IO" => "British Indian Ocean Territory",
868
- "VG" => "British Virgin Islands",
869
- "BN" => "Brunei",
870
- "BG" => "Bulgaria",
871
- "BF" => "Burkina Faso",
872
- "BI" => "Burundi",
873
- "KH" => "Cambodia",
874
- "CM" => "Cameroon",
875
- "CA" => "Canada",
876
- "CT" => "Canton and Enderbury Islands",
877
- "CV" => "Cape Verde",
878
- "KY" => "Cayman Islands",
879
- "CF" => "Central African Republic",
880
- "TD" => "Chad",
881
- "CL" => "Chile",
882
- "CN" => "China",
883
- "CX" => "Christmas Island",
884
- "CC" => "Cocos [Keeling] Islands",
885
- "CO" => "Colombia",
886
- "KM" => "Comoros",
887
- "CG" => "Congo - Brazzaville",
888
- "CD" => "Congo - Kinshasa",
889
- "CK" => "Cook Islands",
890
- "CR" => "Costa Rica",
891
- "HR" => "Croatia",
892
- "CU" => "Cuba",
893
- "CY" => "Cyprus",
894
- "CZ" => "Czech Republic",
895
- "CI" => "Côte d’Ivoire",
896
- "DK" => "Denmark",
897
- "DJ" => "Djibouti",
898
- "DM" => "Dominica",
899
- "DO" => "Dominican Republic",
900
- "NQ" => "Dronning Maud Land",
901
- "DD" => "East Germany",
902
- "EC" => "Ecuador",
903
- "EG" => "Egypt",
904
- "SV" => "El Salvador",
905
- "GQ" => "Equatorial Guinea",
906
- "ER" => "Eritrea",
907
- "EE" => "Estonia",
908
- "ET" => "Ethiopia",
909
- "FK" => "Falkland Islands",
910
- "FO" => "Faroe Islands",
911
- "FJ" => "Fiji",
912
- "FI" => "Finland",
913
- "FR" => "France",
914
- "GF" => "French Guiana",
915
- "PF" => "French Polynesia",
916
- "TF" => "French Southern Territories",
917
- "FQ" => "French Southern and Antarctic Territories",
918
- "GA" => "Gabon",
919
- "GM" => "Gambia",
920
- "GE" => "Georgia",
921
- "DE" => "Germany",
922
- "GH" => "Ghana",
923
- "GI" => "Gibraltar",
924
- "GR" => "Greece",
925
- "GL" => "Greenland",
926
- "GD" => "Grenada",
927
- "GP" => "Guadeloupe",
928
- "GU" => "Guam",
929
- "GT" => "Guatemala",
930
- "GG" => "Guernsey",
931
- "GN" => "Guinea",
932
- "GW" => "Guinea-Bissau",
933
- "GY" => "Guyana",
934
- "HT" => "Haiti",
935
- "HM" => "Heard Island and McDonald Islands",
936
- "HN" => "Honduras",
937
- "HK" => "Hong Kong SAR China",
938
- "HU" => "Hungary",
939
- "IS" => "Iceland",
940
- "IN" => "India",
941
- "ID" => "Indonesia",
942
- "IR" => "Iran",
943
- "IQ" => "Iraq",
944
- "IE" => "Ireland",
945
- "IM" => "Isle of Man",
946
- "IL" => "Israel",
947
- "IT" => "Italy",
948
- "JM" => "Jamaica",
949
- "JP" => "Japan",
950
- "JE" => "Jersey",
951
- "JT" => "Johnston Island",
952
- "JO" => "Jordan",
953
- "KZ" => "Kazakhstan",
954
- "KE" => "Kenya",
955
- "KI" => "Kiribati",
956
- "KW" => "Kuwait",
957
- "KG" => "Kyrgyzstan",
958
- "LA" => "Laos",
959
- "LV" => "Latvia",
960
- "LB" => "Lebanon",
961
- "LS" => "Lesotho",
962
- "LR" => "Liberia",
963
- "LY" => "Libya",
964
- "LI" => "Liechtenstein",
965
- "LT" => "Lithuania",
966
- "LU" => "Luxembourg",
967
- "MO" => "Macau SAR China",
968
- "MK" => "Macedonia",
969
- "MG" => "Madagascar",
970
- "MW" => "Malawi",
971
- "MY" => "Malaysia",
972
- "MV" => "Maldives",
973
- "ML" => "Mali",
974
- "MT" => "Malta",
975
- "MH" => "Marshall Islands",
976
- "MQ" => "Martinique",
977
- "MR" => "Mauritania",
978
- "MU" => "Mauritius",
979
- "YT" => "Mayotte",
980
- "FX" => "Metropolitan France",
981
- "MX" => "Mexico",
982
- "FM" => "Micronesia",
983
- "MI" => "Midway Islands",
984
- "MD" => "Moldova",
985
- "MC" => "Monaco",
986
- "MN" => "Mongolia",
987
- "ME" => "Montenegro",
988
- "MS" => "Montserrat",
989
- "MA" => "Morocco",
990
- "MZ" => "Mozambique",
991
- "MM" => "Myanmar [Burma]",
992
- "NA" => "Namibia",
993
- "NR" => "Nauru",
994
- "NP" => "Nepal",
995
- "NL" => "Netherlands",
996
- "AN" => "Netherlands Antilles",
997
- "NT" => "Neutral Zone",
998
- "NC" => "New Caledonia",
999
- "NZ" => "New Zealand",
1000
- "NI" => "Nicaragua",
1001
- "NE" => "Niger",
1002
- "NG" => "Nigeria",
1003
- "NU" => "Niue",
1004
- "NF" => "Norfolk Island",
1005
- "KP" => "North Korea",
1006
- "MP" => "Northern Mariana Islands",
1007
- "NO" => "Norway",
1008
- "OM" => "Oman",
1009
- "PC" => "Pacific Islands Trust Territory",
1010
- "PK" => "Pakistan",
1011
- "PW" => "Palau",
1012
- "PS" => "Palestinian Territories",
1013
- "PA" => "Panama",
1014
- "PZ" => "Panama Canal Zone",
1015
- "PG" => "Papua New Guinea",
1016
- "PY" => "Paraguay",
1017
- "YD" => "People's Democratic Republic of Yemen",
1018
- "PE" => "Peru",
1019
- "PH" => "Philippines",
1020
- "PN" => "Pitcairn Islands",
1021
- "PL" => "Poland",
1022
- "PT" => "Portugal",
1023
- "PR" => "Puerto Rico",
1024
- "QA" => "Qatar",
1025
- "RO" => "Romania",
1026
- "RU" => "Russia",
1027
- "RW" => "Rwanda",
1028
- "RE" => "Réunion",
1029
- "BL" => "Saint Barthélemy",
1030
- "SH" => "Saint Helena",
1031
- "KN" => "Saint Kitts and Nevis",
1032
- "LC" => "Saint Lucia",
1033
- "MF" => "Saint Martin",
1034
- "PM" => "Saint Pierre and Miquelon",
1035
- "VC" => "Saint Vincent and the Grenadines",
1036
- "WS" => "Samoa",
1037
- "SM" => "San Marino",
1038
- "SA" => "Saudi Arabia",
1039
- "SN" => "Senegal",
1040
- "RS" => "Serbia",
1041
- "CS" => "Serbia and Montenegro",
1042
- "SC" => "Seychelles",
1043
- "SL" => "Sierra Leone",
1044
- "SG" => "Singapore",
1045
- "SK" => "Slovakia",
1046
- "SI" => "Slovenia",
1047
- "SB" => "Solomon Islands",
1048
- "SO" => "Somalia",
1049
- "ZA" => "South Africa",
1050
- "GS" => "South Georgia and the South Sandwich Islands",
1051
- "KR" => "South Korea",
1052
- "ES" => "Spain",
1053
- "LK" => "Sri Lanka",
1054
- "SD" => "Sudan",
1055
- "SR" => "Suriname",
1056
- "SJ" => "Svalbard and Jan Mayen",
1057
- "SZ" => "Swaziland",
1058
- "SE" => "Sweden",
1059
- "CH" => "Switzerland",
1060
- "SY" => "Syria",
1061
- "ST" => "São Tomé and Príncipe",
1062
- "TW" => "Taiwan",
1063
- "TJ" => "Tajikistan",
1064
- "TZ" => "Tanzania",
1065
- "TH" => "Thailand",
1066
- "TL" => "Timor-Leste",
1067
- "TG" => "Togo",
1068
- "TK" => "Tokelau",
1069
- "TO" => "Tonga",
1070
- "TT" => "Trinidad and Tobago",
1071
- "TN" => "Tunisia",
1072
- "TR" => "Turkey",
1073
- "TM" => "Turkmenistan",
1074
- "TC" => "Turks and Caicos Islands",
1075
- "TV" => "Tuvalu",
1076
- "UM" => "U.S. Minor Outlying Islands",
1077
- "PU" => "U.S. Miscellaneous Pacific Islands",
1078
- "VI" => "U.S. Virgin Islands",
1079
- "UG" => "Uganda",
1080
- "UA" => "Ukraine",
1081
- "SU" => "Union of Soviet Socialist Republics",
1082
- "AE" => "United Arab Emirates",
1083
- "GB" => "United Kingdom",
1084
- "US" => "United States",
1085
- "ZZ" => "Unknown or Invalid Region",
1086
- "UY" => "Uruguay",
1087
- "UZ" => "Uzbekistan",
1088
- "VU" => "Vanuatu",
1089
- "VA" => "Vatican City",
1090
- "VE" => "Venezuela",
1091
- "VN" => "Vietnam",
1092
- "WK" => "Wake Island",
1093
- "WF" => "Wallis and Futuna",
1094
- "EH" => "Western Sahara",
1095
- "YE" => "Yemen",
1096
- "ZM" => "Zambia",
1097
- "ZW" => "Zimbabwe",
1098
- "AX" => "Åland Islands",
1099
- );
1100
-
1101
- return $country_array;
1102
- }
1103
-
1104
- /**
1105
- * @param $dir
1106
- *
1107
- * @return bool|void|\WP_Error
1108
- */
1109
- public function removeDir( $dir ) {
1110
- if ( ! is_dir( $dir ) ) {
1111
- return;
1112
- }
1113
- $it = new \RecursiveDirectoryIterator( $dir, \RecursiveDirectoryIterator::SKIP_DOTS );
1114
- $files = new \RecursiveIteratorIterator( $it,
1115
- \RecursiveIteratorIterator::CHILD_FIRST );
1116
- foreach ( $files as $file ) {
1117
- if ( $file->isDir() ) {
1118
- $res = @rmdir( $file->getRealPath() );
1119
- } else {
1120
- $res = @unlink( $file->getRealPath() );
1121
- }
1122
- if ( $res == false ) {
1123
- return new \WP_Error( Error_Code::NOT_WRITEABLE,
1124
- __( "Defender doesn't have enough permission to remove this file", "defender-security" ) );
1125
- }
1126
- }
1127
- $res = @rmdir( $dir );
1128
- if ( $res == false ) {
1129
- return new \WP_Error( Error_Code::NOT_WRITEABLE,
1130
- __( "Defender doesn't have enough permission to remove this file", "defender-security" ) );
1131
- }
1132
-
1133
- return true;
1134
- }
1135
-
1136
- public function parseDomain( $domain ) {
1137
- //FILTER_VALIDATE_DOMAIN filter will be added in PHP 7
1138
- $filter_domain = version_compare( PHP_VERSION, '7.0', '>=' ) ? FILTER_VALIDATE_DOMAIN : FILTER_VALIDATE_URL;
1139
- if ( ! filter_var( $domain, $filter_domain ) ) {
1140
- return false;
1141
- }
1142
- $suffix = $this->getDomainSuffix( $domain );
1143
- if ( $suffix == false ) {
1144
- return false;
1145
- }
1146
- //exclude 'www.'
1147
- $domain = str_replace( 'www.', '', $domain );
1148
- $host = parse_url( $domain, PHP_URL_HOST );
1149
- $host_without_tld = str_replace( $suffix, '', $host );
1150
- //remove righter . if any
1151
- $host_without_tld = rtrim( $host_without_tld, '.' );
1152
- $parts = explode( '.', $host_without_tld );
1153
- if ( count( $parts ) == 1 ) {
1154
- return [
1155
- 'host' => $host,
1156
- 'tld' => $suffix
1157
- ];
1158
- }
1159
- //parse to get the root & subdomain
1160
- $domain = array_pop( $parts );
1161
-
1162
- return [
1163
- 'host' => $host,
1164
- 'tld' => $suffix,
1165
- 'subdomain' => str_replace( $domain, '', $host_without_tld ),
1166
- ];
1167
- }
1168
-
1169
- private function getDomainSuffix( $domain ) {
1170
- $tlds = include dirname( __DIR__ ) . '/component/public-suffix.php';
1171
- //whitelist development
1172
- $tlds['localhost'] = 1;
1173
- $parts = explode( '.', $domain );
1174
- $parts = array_reverse( $parts );
1175
- $suffix = '';
1176
- $list = [];
1177
- $length = 0;
1178
- foreach ( $parts as $part ) {
1179
- $suffix = rtrim( $part . '.' . $suffix, '.' );
1180
- $notAllow = '!' . $suffix;
1181
- if ( isset( $tlds[ $notAllow ] ) ) {
1182
- //this wont be here
1183
- continue;
1184
- }
1185
- if ( isset( $tlds[ $suffix ] ) ) {
1186
- if ( $length > strlen( $suffix ) ) {
1187
- //put at last
1188
- $list[] = $suffix;
1189
- } else {
1190
- array_unshift( $list, $suffix );
1191
- }
1192
- }
1193
- };
1194
- if ( empty( $list ) ) {
1195
- return false;
1196
- }
1197
-
1198
- //the lenghter will be use
1199
- return $list[0];
1200
- }
1201
-
1202
- public function log( $log, $group = null ) {
1203
- if ( ! defined( 'DEFENDER_DEBUG' ) ) {
1204
- return;
1205
- }
1206
- $log_path = self::getDefUploadDir();
1207
- $log_name = hash( 'sha256', network_home_url() . $group . SECURE_AUTH_SALT );
1208
- $log_path = $log_path . '/' . $log_name;
1209
-
1210
- $log = sprintf( '%s - %s' . PHP_EOL, date( 'Y-m-d H:i:s', current_time( 'timestamp' ) ), $log );
1211
- file_put_contents( $log_path, $log, FILE_APPEND );
1212
- }
1213
-
1214
- public function read_log( $group = null ) {
1215
- if ( ! defined( 'DEFENDER_DEBUG' ) ) {
1216
- return;
1217
- }
1218
- $log_path = self::getDefUploadDir();
1219
- $log_name = hash( 'sha256', network_home_url() . $group . SECURE_AUTH_SALT );
1220
- $log_path = $log_path . '/' . $log_name;
1221
- if ( ! file_exists( $log_path ) ) {
1222
- return;
1223
- }
1224
- $text = file( $log_path );
1225
-
1226
- return implode( array_reverse( $text ), PHP_EOL );
1227
- }
1228
-
1229
- public function clear_log( $group = null ) {
1230
- if ( ! defined( 'DEFENDER_DEBUG' ) ) {
1231
- return;
1232
- }
1233
- $log_path = self::getDefUploadDir();
1234
- $log_name = hash( 'sha256', network_home_url() . $group . SECURE_AUTH_SALT );
1235
- $log_path = $log_path . '/' . $log_name;
1236
- @unlink( $log_path );
1237
- }
1238
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/behavior/wpmudev.php DELETED
@@ -1,167 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Behavior;
7
-
8
- use Hammer\Base\Behavior;
9
- use WP_Defender\Module\Advanced_Tools\Model\Security_Headers_Settings;
10
- use WP_Defender\Module\Hardener\Model\Settings;
11
- use WP_Defender\Module\IP_Lockout\Model\Log_Model;
12
- use WP_Defender\Module\Scan\Component\Scan_Api;
13
- use WP_Defender\Module\Scan\Component\Scanning;
14
- use WP_Defender\Module\Scan\Model\Result_Item;
15
- use WP_Defender\Module\Scan\Model\Scan;
16
-
17
- /**
18
- * This class contains everything relate to WPMUDEV
19
- * Class WPMUDEV
20
- * @package WP_Defender\Behavior
21
- * @since 2.2
22
- */
23
- class WPMUDEV extends Behavior {
24
- /**
25
- * @param $campaign
26
- *
27
- * @return string
28
- */
29
- public function campaignURL( $campaign ) {
30
- $url = "https://premium.wpmudev.org/project/wp-defender/?utm_source=defender&utm_medium=plugin&utm_campaign=" . $campaign;
31
-
32
- return $url;
33
- }
34
-
35
- /**
36
- * Get whitelabel status from Dev Dashboard
37
- * Properties
38
- * - hide_branding
39
- * - hero_image
40
- * - footer_text
41
- * - change_footer
42
- * - hide_doc_link
43
- *
44
- * @return mixed
45
- */
46
- public function whiteLabelStatus() {
47
- if ( \WP_Defender\Behavior\Utils::instance()->getAPIKey() ) {
48
- $site = \WPMUDEV_Dashboard::$site;
49
- if ( is_object( $site ) ) {
50
- $info = $site->get_wpmudev_branding( array() );
51
- $info['enabled'] = $this->is_whitelabel_enabled();
52
-
53
- return $info;
54
- }
55
- } else {
56
- return [
57
- 'enabled' => false,
58
- 'hide_branding' => false,
59
- 'hero_image' => '',
60
- 'footer_text' => '',
61
- 'change_footer' => false,
62
- 'hide_doc_link' => false
63
- ];
64
- }
65
- }
66
-
67
- public function is_whitelabel_enabled() {
68
- if ( \WP_Defender\Behavior\Utils::instance()->getAPIKey() ) {
69
- $site = \WPMUDEV_Dashboard::$site;
70
- $settings = $site->get_whitelabel_settings();
71
-
72
- return $settings['enabled'];
73
- }
74
-
75
- return false;
76
- }
77
-
78
- public function is_dev_dashboard_installed() {
79
- var_dump( get_plugins() );
80
- die;
81
- }
82
-
83
- /**
84
- * a quick helper for static class
85
- * @return WPMUDEV
86
- */
87
- public static function instance() {
88
- return new WPMUDEV();
89
- }
90
-
91
- /**
92
- * Return the highcontrast css class if it is
93
- * @return string
94
- */
95
- public function maybeHighContrast() {
96
- return \WP_Defender\Module\Setting\Model\Settings::instance()->high_contrast_mode;
97
- }
98
-
99
- /**
100
- * @return array
101
- */
102
- public function stats_summary() {
103
- $count = 0;
104
- $scan = Scan_Api::getLastScan();
105
- if ( is_object( $scan ) ) {
106
- $count += $scan->countAll( Result_Item::STATUS_ISSUE );
107
- }
108
- $count += count( Settings::instance()->getIssues() );
109
-
110
- $scan_setting = \WP_Defender\Module\Scan\Model\Settings::instance();
111
-
112
- $next_scan = $scan_setting->report === true ?
113
- Utils::instance()->getNextRun( $scan_setting->frequency, $scan_setting->day, $scan_setting->time,
114
- $scan_setting->last_report_sent ) : 'N/A';
115
-
116
- return [
117
- 'count' => $count,
118
- 'next_scan' => $next_scan
119
- ];
120
- }
121
-
122
- public function stats_report() {
123
- $scan = \WP_Defender\Module\Scan\Model\Settings::instance();
124
- $audit = \WP_Defender\Module\Audit\Model\Settings::instance();
125
- $firewall = \WP_Defender\Module\IP_Lockout\Model\Settings::instance();
126
-
127
- return [
128
- 'scan' => $scan->report === true ? sprintf( '%s, %s', $scan->day, $scan->time ) : false,
129
- 'audit' => $audit->notification === true ? sprintf( '%s, %s', $audit->day, $audit->time ) : false,
130
- 'firewall' => $firewall->report === true ? sprintf( '%s, %s', $firewall->report_day,
131
- $firewall->report_time ) : false
132
- ];
133
- }
134
-
135
- public function stats_security_tweaks() {
136
- $settings = Settings::instance();
137
-
138
- return [
139
- 'issues' => count( $settings->issues ),
140
- 'fixed' => count( $settings->fixed ),
141
- 'notification' => $settings->notification
142
- ];
143
- }
144
-
145
- public function stats_malware_scan() {
146
- $scan = Scan_Api::getLastScan();
147
- $count = 0;
148
- if ( is_object( $scan ) ) {
149
- $count = $scan->countAll( Result_Item::STATUS_ISSUE );
150
- }
151
-
152
- return [
153
- 'count' => $count,
154
- 'notification' => \WP_Defender\Module\Scan\Model\Settings::instance()->notification
155
- ];
156
- }
157
-
158
- public function stats_security_headers() {
159
- $settings = Security_Headers_Settings::instance();
160
- $headers = [];
161
- foreach ( $settings->getHeaders() as $header ) {
162
- $headers[ $header::$rule_slug ] = $header->check();
163
- }
164
-
165
- return $headers;
166
- }
167
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/component/cli.php DELETED
@@ -1,267 +0,0 @@
1
- <?php
2
-
3
- namespace WP_Defender\Component;
4
-
5
- use Faker\Factory;
6
- use WP_Defender\Module\Hardener\Component\Change_Admin_Service;
7
- use WP_Defender\Module\Hardener\Model\Settings;
8
- use WP_Defender\Module\Scan\Component\Scan_Api;
9
- use WP_Defender\Module\Scan\Component\Scanning;
10
- use WP_Defender\Module\Scan\Model\Result_Item;
11
- use WP_Defender\Module\Setting\Component\Backup_Settings;
12
- use function WP_CLI\Utils\format_items;
13
-
14
- class Cli {
15
-
16
- /**
17
- *
18
- * This is a helper for scan module
19
- * #Options
20
- * <command>
21
- * : Value can be run - Perform a scan, or (un)ignore|delete|resolve to do the relevant task
22
- *
23
- * [--type=<type>]
24
- * : Default is all, or core|plugins|content
25
- *
26
- * @param $args
27
- * @param $options
28
- *
29
- * @throws \WP_CLI\ExitException
30
- */
31
- public function scan( $args, $options ) {
32
- if ( empty( $args ) ) {
33
- \WP_CLI::error( 'Invalid command' );
34
- }
35
- list( $command ) = $args;
36
- switch ( $command ) {
37
- case 'run':
38
- $this->scan_all();
39
- break;
40
- default:
41
- $commands = [
42
- 'ignore',
43
- 'unignore',
44
- 'resolve',
45
- 'delete'
46
- ];
47
- if ( in_array( $command, $commands ) ) {
48
- \WP_CLI::confirm( 'This can cause your site get fatal error and can\'t restore back unless you have a backup, are you sure to continue?', $options );
49
- $this->scan_task( $command, $options );
50
- } else {
51
- \WP_CLI::error( sprintf( 'Unknown command %s', $command ) );
52
- }
53
-
54
- }
55
- }
56
-
57
- private function scan_task( $task, $options ) {
58
- $type = isset( $options['type'] ) ? $options['type'] : null;
59
- $active = Scan_Api::getActiveScan();
60
- if ( is_object( $active ) ) {
61
- return \WP_CLI::error( "A scan is running, you need to wait till it complete to continue" );
62
- }
63
- $model = Scan_Api::getLastScan();
64
- switch ( $task ) {
65
- case 'ignore':
66
- $items = $model->getItems( 0, Result_Item::STATUS_ISSUE, $type );
67
- foreach ( $items as $item ) {
68
- $item->ignore();
69
- }
70
- \WP_CLI::log( sprintf( 'Ignored %s items', count( $items ) ) );
71
- break;
72
- case 'unignore':
73
- $items = $model->getItems( 0, Result_Item::STATUS_IGNORED, $type );
74
- foreach ( $items as $item ) {
75
- $item->unignore();
76
- }
77
- \WP_CLI::log( sprintf( 'Unignored %s items', count( $items ) ) );
78
- break;
79
- case 'resolve':
80
- $items = $model->getItems( 0, Result_Item::STATUS_ISSUE, $type );
81
- $resolved = [];
82
- foreach ( $items as $item ) {
83
- if ( $item->type == 'core' ) {
84
- \WP_CLI::log( sprintf( 'Reverting %s to original', $item->raw['file'] ) );
85
- $ret = $item->resolve();
86
- if ( ! is_wp_error( $ret ) ) {
87
- $resolved[] = $item;
88
- } else {
89
- return \WP_CLI::error( $ret->get_error_message() );
90
- }
91
- } elseif ( $item->type == 'content' ) {
92
- //if this is content, we will try to delete them
93
- $whitelist = [
94
- //wordfence waf
95
- ABSPATH . '/wordfence-waf.php',
96
- //any files inside plugins, if delete can cause fatal error
97
- WP_CONTENT_DIR . '/plugins/',
98
- //any files inside themes
99
- WP_CONTENT_DIR . '/themes/'
100
- ];
101
- $path = $item->raw['file'];
102
- $can_delete = true;
103
- $current = '';
104
- foreach ( $whitelist as $value ) {
105
- $current = $value;
106
- if ( strpos( $value, $path ) > 0 ) {
107
- //ignore this
108
- $can_delete = false;
109
- break;
110
- }
111
- }
112
- if ( $can_delete == false ) {
113
- \WP_CLI::log( sprintf( "Ignore file %s as it is in %s", $path, $current ) );
114
- } else {
115
- if ( @unlink( $path ) ) {
116
- \WP_CLI::log( sprintf( 'Delete file %s', $path ) );
117
- $item->markAsResolved();
118
- $resolved[] = $item;
119
- } else {
120
- return \WP_CLI::error( sprintf( "Can't remove file %s", $path ) );
121
- }
122
- }
123
- }
124
- }
125
- \WP_CLI::log( sprintf( 'Resolved %s items', count( $resolved ) ) );
126
- break;
127
- case 'delete':
128
- break;
129
- }
130
- }
131
-
132
- /**
133
- * Perform a scan
134
- */
135
- private function scan_all() {
136
- echo 'Check if there is a scan ongoing...' . PHP_EOL;
137
- $model = Scan_Api::getActiveScan();
138
- $start = microtime( true );
139
- if ( ! is_object( $model ) ) {
140
- echo 'No active scan, create one now...' . PHP_EOL;
141
- Scan_Api::createScan();
142
- } else {
143
- echo 'Found active scan, process...' . PHP_EOL;
144
- }
145
- //echo sprintf( 'Total core files: %d' . PHP_EOL, count( Scan_Api::getCoreFiles() ) );
146
- //echo sprintf( 'Total content files: %d' . PHP_EOL, count( Scan_Api::getContentFiles() ) );
147
- echo '=============================================' . PHP_EOL;
148
- $is_done = false;
149
- while ( $is_done == false ) {
150
- $memory = ( memory_get_peak_usage( true ) / 1024 / 1024 );
151
- echo 'Memory: ' . $memory . ' MB' . PHP_EOL;
152
- if ( $memory > 256 ) {
153
- break;
154
- }
155
- $scanning = new Scanning();
156
- $scanning->releaseLock();
157
- $is_done = $scanning->run();
158
- $progress = $scanning->getScanProgress();
159
- //$is_done = Scan_Api::processActiveScan();
160
- //$progress = Scan_Api::getScanProgress();
161
- echo 'Scanning at ' . $progress . PHP_EOL;
162
- gc_collect_cycles();
163
- }
164
- if ( $is_done ) {
165
- $model = Scan_Api::getLastScan();
166
- $finish = microtime( true ) - $start;
167
- //\WP_CLI::log( sprintf( 'Found %s issues. Please go to %s for more info.' . PHP_EOL, count( $model->getItems() ), network_admin_url( 'admin.php?page=wdf-scan&view=issues' ) ) );
168
- $results = $model->getItemsAsJson();
169
- if ( count( $results ) ) {
170
- format_items( 'table', $results, [ 'type', 'short_desc', 'full_path' ] );
171
- } else {
172
- \WP_CLI::log( 'All good!' );
173
- }
174
- \WP_CLI::log( 'Scan take ' . round( $finish, 2 ) . 's to process.' );
175
- \WP_CLI::success( 'Scan done.' );
176
- } else {
177
- \WP_CLI::log( 'Run the command wp defender scan run again to continue process the scan.' );
178
- }
179
- }
180
-
181
- public function tweaks( $task, $options ) {
182
- $task = array_shift( $task );
183
- $model = Settings::instance();
184
- switch ( $task ) {
185
- case 'resolve':
186
- $tweaks = $model->getDefinedRules( true );
187
- foreach ( $tweaks as $tweak ) {
188
- if ( $tweak->check() == false ) {
189
- $slug = $tweak::$slug;
190
- if ( in_array( $slug, [
191
- 'protect-information',
192
- 'prevent-php-executed'
193
- ] ) ) {
194
- continue;
195
- }
196
- \WP_CLI::log( sprintf( 'Resolving %s', $tweak->getTitle() ) );
197
- $service = $tweak->getService();
198
- switch ( $slug ) {
199
- case 'replace-admin-username':
200
- fwrite( STDOUT, 'Please enter new admin username:' );
201
- $username = strtolower( trim( fgets( STDIN ) ) );
202
- $service->setUsername( $username );
203
- break;
204
- case 'db-prefix':
205
- fwrite( STDOUT, 'Please enter new db prefix:' );
206
- $prefix = strtolower( trim( fgets( STDIN ) ) );
207
- $service->new_prefix = $prefix;
208
- break;
209
- default:
210
- break;
211
- }
212
- $ret = $service->process();
213
- if ( is_wp_error( $ret ) ) {
214
- \WP_CLI::error( $ret->get_error_message() );
215
-
216
- return;
217
- }
218
- \WP_CLI::success( 'Done' );
219
- }
220
- }
221
- break;
222
- case 'ignore':
223
- $tweaks = $model->getIssues();
224
- foreach ( $tweaks as $tweak ) {
225
- $tweak->ignore();
226
- \WP_CLI::success( sprintf( 'Ignored %s', $tweak->getTitle() ) );
227
- }
228
- break;
229
- case 'revert':
230
- $tweaks = $model->getFixed();
231
- foreach ( $tweaks as $tweak ) {
232
- $tweak->revert();
233
- \WP_CLI::success( sprintf( 'Reverted %s', $tweak->getTitle() ) );
234
- }
235
- break;
236
- case 'unignore':
237
- $tweaks = $model->getIgnore();
238
- foreach ( $tweaks as $tweak ) {
239
- $tweak->restore();
240
- \WP_CLI::success( sprintf( 'Restore %s', $tweak->getTitle() ) );
241
- }
242
- break;
243
- default:
244
- \WP_CLI::error( 'Invalid command, only resolve|ignore allow' );
245
- break;
246
- }
247
- }
248
-
249
- /**
250
- * This will generate randomly settings, use to check upgrade scenario
251
- */
252
- public function seeding() {
253
- //reset all the data before generate
254
- $this->reset();
255
- $faker = Factory::create();
256
- //start with tweaks
257
- $tweaks = Settings::instance();
258
-
259
- }
260
-
261
- /**
262
- * Reset all settings
263
- */
264
- public function reset() {
265
- Backup_Settings::resetSettings();
266
- }
267
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/component/data-factory.php DELETED
@@ -1,224 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Component;
7
-
8
- use Hammer\Base\Container;
9
- use WP_Defender\Behavior\Utils;
10
- use WP_Defender\Module\Advanced_Tools\Component\Mask_Api;
11
- use WP_Defender\Module\Advanced_Tools\Model\Mask_Settings;
12
- use WP_Defender\Module\Advanced_Tools\Model\Security_Headers_Settings;
13
- use WP_Defender\Module\Hardener\Model\Settings;
14
- use WP_Defender\Module\IP_Lockout\Model\Log_Model;
15
- use WP_Defender\Module\Two_Factor\Model\Auth_Settings;
16
-
17
- class Data_Factory {
18
- public static function buildData() {
19
- if ( ! Utils::instance()->checkPermission() ) {
20
- return [];
21
- }
22
-
23
- return [
24
- 'security_tweaks' => self::buildTweaksData(),
25
- 'scan' => self::buildScanData(),
26
- 'blacklist' => self::buildBlacklistData(),
27
- 'ip_lockout' => self::buildIpLockoutData(),
28
- 'audit' => self::buildAuditData(),
29
- 'report' => self::buildReportData(),
30
- 'advanced_tools' => self::buildAToolsData(),
31
- 'two_fa' => self::buildTwoFaData(),
32
- 'waf' => self::buildWafData(),
33
- 'settings' => self::buildSettingsData()
34
- ];
35
- }
36
-
37
- public static function buildSettingsData() {
38
- $module = Container::instance()->get( 'setting' );
39
- $controller = $module->getController( 'main' );
40
-
41
- return $controller->scriptsData();
42
- }
43
-
44
- public static function buildWafData() {
45
- return Container::instance()->get( 'waf' )->_scriptsData();
46
- }
47
-
48
- public static function buildTwoFaData() {
49
- $settings = Auth_Settings::instance();
50
-
51
- return [
52
- 'enabled' => $settings->enabled,
53
- 'useable' => $settings->enabled && count( $settings->user_roles ),
54
- 'nonces' => [
55
- 'updateSettings' => wp_create_nonce( 'updateSettings' ),
56
- ],
57
- 'endpoints' => [
58
- 'updateSettings' => 'wp-defender/v1/twoFa/updateSettings',
59
- ]
60
- ];
61
- }
62
-
63
- /**
64
- * @return array
65
- */
66
- public static function buildAToolsData() {
67
- $headers = [];
68
- if ( isset( wp_defender()->global['security_headers_enabled'] ) ) {
69
- $headers = wp_defender()->global['security_headers_enabled'];
70
- }
71
- $data = [];
72
- foreach ( $headers as $header ) {
73
- $data[] = [
74
- 'slug' => $header::$rule_slug,
75
- 'title' => $header->getTitle()
76
- ];
77
- }
78
-
79
- return [
80
- 'security_headers' => $data,
81
- 'mask_login' => [
82
- 'enabled' => Mask_Settings::instance()->enabled,
83
- 'useable' => strlen( Mask_Settings::instance()->mask_url ) > 0,
84
- 'login_url' => Mask_Api::getNewLoginUrl()
85
- ],
86
- 'nonces' => [
87
- 'updateSettings' => wp_create_nonce( 'updateSettings' )
88
- ],
89
- 'endpoints' => [
90
- 'updateSettings' => 'wp-defender/v1/advanced-tools/updateSettings'
91
- ]
92
- ];
93
- }
94
-
95
- /**
96
- * @return array
97
- */
98
- public static function buildReportData() {
99
- if ( ! class_exists( '\WP_Defender\Module\Audit\Model\Settings' ) ) {
100
- return [
101
- 'scan' => \WP_Defender\Module\Scan\Model\Settings::instance()->report ? \WP_Defender\Module\Scan\Model\Settings::instance()->frequency : - 1,
102
- 'ip_lockout' => \WP_Defender\Module\IP_Lockout\Model\Settings::instance()->report ? \WP_Defender\Module\IP_Lockout\Model\Settings::instance()->report_frequency : - 1,
103
- 'audit' => - 1
104
- ];
105
- } else {
106
- return [
107
- 'scan' => \WP_Defender\Module\Scan\Model\Settings::instance()->report ? \WP_Defender\Module\Scan\Model\Settings::instance()->frequency : - 1,
108
- 'ip_lockout' => \WP_Defender\Module\IP_Lockout\Model\Settings::instance()->report ? \WP_Defender\Module\IP_Lockout\Model\Settings::instance()->report_frequency : - 1,
109
- 'audit' => \WP_Defender\Module\Audit\Model\Settings::instance()->notification ? \WP_Defender\Module\Audit\Model\Settings::instance()->frequency : - 1
110
- ];
111
- }
112
- }
113
-
114
- /**
115
- * @return array
116
- */
117
- public static function buildAuditData() {
118
- if ( ! class_exists( '\WP_Defender\Module\Audit\Model\Settings' ) ) {
119
- //free version
120
- return [];
121
- }
122
- $setting = \WP_Defender\Module\Audit\Model\Settings::instance();
123
-
124
- return [
125
- 'enabled' => $setting->enabled,
126
- 'report' => $setting->notification,
127
- 'nonces' => [
128
- 'summary' => wp_create_nonce( 'summary' ),
129
- 'updateSettings' => wp_create_nonce( 'updateSettings' )
130
- ],
131
- 'endpoints' => [
132
- 'summary' => 'wp-defender/v1/audit/summary',
133
- 'updateSettings' => 'wp-defender/v1/audit/updateSettings'
134
- ]
135
- ];
136
- }
137
-
138
- /**
139
- * @return array
140
- */
141
- private static function buildIpLockoutData() {
142
- $summaryData = Log_Model::getSummary();
143
- $settings = \WP_Defender\Module\IP_Lockout\Model\Settings::instance();
144
-
145
- return [
146
- 'nonces' => [
147
- 'updateSettings' => wp_create_nonce( 'updateSettings' ),
148
- ],
149
- 'endpoints' => [
150
- 'updateSettings' => 'wp-defender/v1/lockout/updateSettings'
151
- ],
152
- 'summary' => [
153
- 'ip' => [
154
- 'week' => $summaryData['loginLockoutThisWeek'],
155
- ],
156
- 'nf' => [
157
- 'week' => $summaryData['lockout404ThisWeek'],
158
- ],
159
- 'lastLockout' => $summaryData['lastLockout']
160
- ],
161
- 'notification' => $settings->login_lockout_notification && $settings->ip_lockout_notification,
162
- 'enabled' => $settings->login_protection || $settings->detect_404
163
- ];
164
- }
165
-
166
- /**
167
- * @return array
168
- */
169
- private static function buildBlacklistData() {
170
- return [
171
- 'nonces' => [
172
- 'toggleBlacklistWidget' => wp_create_nonce( 'toggleBlacklistWidget' ),
173
- 'blacklistWidgetStatus' => wp_create_nonce( 'blacklistWidgetStatus' )
174
- ],
175
- 'endpoints' => [
176
- 'toggleBlacklistWidget' => 'wp-defender/v1/toggleBlacklistWidget',
177
- 'blacklistWidgetStatus' => 'wp-defender/v1/blacklistWidgetStatus'
178
- ]
179
- ];
180
- }
181
-
182
- /**
183
- * @return array
184
- */
185
- private static function buildTweaksData() {
186
- $rules = Settings::instance()->getTweaksAsArray( 'issues' );
187
- $resolved = Settings::instance()->getTweaksAsArray( 'fixed' );
188
- $ignored = Settings::instance()->getTweaksAsArray( 'ignore' );
189
- $total = count( Settings::instance()->getDefinedRules() );
190
-
191
- return [
192
- 'rules' => array_slice( $rules, 0, 5 ),
193
- 'count' => [
194
- 'issues' => count( $rules ),
195
- 'resolved' => count( $resolved ) + count( $ignored ),
196
- 'total' => $total
197
- ],
198
- ];
199
- }
200
-
201
- /**
202
- * @return array
203
- */
204
- private static function buildScanData() {
205
- $settings = \WP_Defender\Module\Scan\Model\Settings::instance();
206
-
207
- return array_merge( \WP_Defender\Module\Scan\Component\Data_Factory::buildLiteData(), [
208
- 'nonces' => [
209
- 'newScan' => wp_create_nonce( 'newScan' ),
210
- 'processScan' => wp_create_nonce( 'processScan' ),
211
- 'cancelScan' => wp_create_nonce( 'cancelScan' )
212
- ],
213
- 'endpoints' => [
214
- 'newScan' => 'wp-defender/v1/scan/newScan',
215
- 'processScan' => 'wp-defender/v1/scan/processScan',
216
- 'cancelScan' => 'wp-defender/v1/scan/cancelScan',
217
- ],
218
- 'report' => [
219
- 'enabled' => $settings->report,
220
- 'frequency' => $settings->frequency
221
- ]
222
- ] );
223
- }
224
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/component/error-code.php DELETED
@@ -1,19 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
- namespace WP_Defender\Component;
6
-
7
- class Error_Code {
8
- const NOT_WRITEABLE = 1;
9
- const WPDEBUG_NOT_FOUND = 2;
10
- const UNKNOWN_WPCONFIG = 3;
11
- const IS_EMPTY = 4;
12
- const VALIDATE = 5;
13
- const SQL_ERROR = 6;
14
- const DB_ERROR = 7;
15
- const INVALID = 8;
16
- const SCAN_ERROR = 9;
17
- const API_ERROR = 10;
18
-
19
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/component/jed.php DELETED
@@ -1,71 +0,0 @@
1
- <?php
2
-
3
- namespace WP_Defender\Component;
4
-
5
- use Gettext\Generators\Generator;
6
- use Gettext\Generators\GeneratorInterface;
7
- use Gettext\Translations;
8
-
9
- class Jed extends Generator implements GeneratorInterface {
10
- public static $options = [
11
- 'json' => 0,
12
- ];
13
-
14
- /**
15
- * {@parentDoc}.
16
- */
17
- public static function toString( Translations $translations, array $options = [] ) {
18
- $domain = $translations->getDomain() ?: 'messages';
19
- $options += static::$options;
20
-
21
- return json_encode( [
22
- "translation-revision-date" => date( 'Y-m-d' ),
23
- "generator" => "wp-defender",
24
- "version" => "1",
25
- "domain" => "messages",
26
- "locale_data" => [
27
- "messages" => [
28
- '' => [
29
- 'domain' => $domain,
30
- 'lang' => $translations->getLanguage() ?: 'en',
31
- 'plural-forms' => $translations->getHeader( 'Plural-Forms' ) ?: 'nplurals=2; plural=(n != 1);',
32
- ],
33
- ] + static::buildMessages( $translations ),
34
- ],
35
- ], $options['json'] );
36
- }
37
-
38
- /**
39
- * Generates an array with all translations.
40
- *
41
- * @param Translations $translations
42
- *
43
- * @return array
44
- */
45
- protected static function buildMessages( Translations $translations ) {
46
- $pluralForm = $translations->getPluralForms();
47
- $pluralSize = is_array( $pluralForm ) ? ( $pluralForm[0] - 1 ) : null;
48
- $messages = [];
49
- $context_glue = '\u0004';
50
-
51
- foreach ( $translations as $translation ) {
52
- if ( $translation->isDisabled() ) {
53
- continue;
54
- }
55
-
56
- $key = ( $translation->hasContext() ? $translation->getContext() . $context_glue : '' )
57
- . $translation->getOriginal();
58
-
59
- if ( $translation->hasPluralTranslations( true ) ) {
60
- $message = $translation->getPluralTranslations( $pluralSize );
61
- array_unshift( $message, $translation->getTranslation() );
62
- } else {
63
- $message = [ $translation->getTranslation() ];
64
- }
65
-
66
- $messages[ $key ] = $message;
67
- }
68
-
69
- return $messages;
70
- }
71
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/component/public-suffix.php DELETED
@@ -1,8796 +0,0 @@
1
- <?php
2
- return array (
3
- 'ac' => 1,
4
- 'com.ac' => 1,
5
- 'edu.ac' => 1,
6
- 'gov.ac' => 1,
7
- 'net.ac' => 1,
8
- 'mil.ac' => 1,
9
- 'org.ac' => 1,
10
- 'ad' => 1,
11
- 'nom.ad' => 1,
12
- 'ae' => 1,
13
- 'co.ae' => 1,
14
- 'net.ae' => 1,
15
- 'org.ae' => 1,
16
- 'sch.ae' => 1,
17
- 'ac.ae' => 1,
18
- 'gov.ae' => 1,
19
- 'mil.ae' => 1,
20
- 'aero' => 1,
21
- 'accident-investigation.aero' => 1,
22
- 'accident-prevention.aero' => 1,
23
- 'aerobatic.aero' => 1,
24
- 'aeroclub.aero' => 1,
25
- 'aerodrome.aero' => 1,
26
- 'agents.aero' => 1,
27
- 'aircraft.aero' => 1,
28
- 'airline.aero' => 1,
29
- 'airport.aero' => 1,
30
- 'air-surveillance.aero' => 1,
31
- 'airtraffic.aero' => 1,
32
- 'air-traffic-control.aero' => 1,
33
- 'ambulance.aero' => 1,
34
- 'amusement.aero' => 1,
35
- 'association.aero' => 1,
36
- 'author.aero' => 1,
37
- 'ballooning.aero' => 1,
38
- 'broker.aero' => 1,
39
- 'caa.aero' => 1,
40
- 'cargo.aero' => 1,
41
- 'catering.aero' => 1,
42
- 'certification.aero' => 1,
43
- 'championship.aero' => 1,
44
- 'charter.aero' => 1,
45
- 'civilaviation.aero' => 1,
46
- 'club.aero' => 1,
47
- 'conference.aero' => 1,
48
- 'consultant.aero' => 1,
49
- 'consulting.aero' => 1,
50
- 'control.aero' => 1,
51
- 'council.aero' => 1,
52
- 'crew.aero' => 1,
53
- 'design.aero' => 1,
54
- 'dgca.aero' => 1,
55
- 'educator.aero' => 1,
56
- 'emergency.aero' => 1,
57
- 'engine.aero' => 1,
58
- 'engineer.aero' => 1,
59
- 'entertainment.aero' => 1,
60
- 'equipment.aero' => 1,
61
- 'exchange.aero' => 1,
62
- 'express.aero' => 1,
63
- 'federation.aero' => 1,
64
- 'flight.aero' => 1,
65
- 'freight.aero' => 1,
66
- 'fuel.aero' => 1,
67
- 'gliding.aero' => 1,
68
- 'government.aero' => 1,
69
- 'groundhandling.aero' => 1,
70
- 'group.aero' => 1,
71
- 'hanggliding.aero' => 1,
72
- 'homebuilt.aero' => 1,
73
- 'insurance.aero' => 1,
74
- 'journal.aero' => 1,
75
- 'journalist.aero' => 1,
76
- 'leasing.aero' => 1,
77
- 'logistics.aero' => 1,
78
- 'magazine.aero' => 1,
79
- 'maintenance.aero' => 1,
80
- 'media.aero' => 1,
81
- 'microlight.aero' => 1,
82
- 'modelling.aero' => 1,
83
- 'navigation.aero' => 1,
84
- 'parachuting.aero' => 1,
85
- 'paragliding.aero' => 1,
86
- 'passenger-association.aero' => 1,
87
- 'pilot.aero' => 1,
88
- 'press.aero' => 1,
89
- 'production.aero' => 1,
90
- 'recreation.aero' => 1,
91
- 'repbody.aero' => 1,
92
- 'res.aero' => 1,
93
- 'research.aero' => 1,
94
- 'rotorcraft.aero' => 1,
95
- 'safety.aero' => 1,
96
- 'scientist.aero' => 1,
97
- 'services.aero' => 1,
98
- 'show.aero' => 1,
99
- 'skydiving.aero' => 1,
100
- 'software.aero' => 1,
101
- 'student.aero' => 1,
102
- 'trader.aero' => 1,
103
- 'trading.aero' => 1,
104
- 'trainer.aero' => 1,
105
- 'union.aero' => 1,
106
- 'workinggroup.aero' => 1,
107
- 'works.aero' => 1,
108
- 'af' => 1,
109
- 'gov.af' => 1,
110
- 'com.af' => 1,
111
- 'org.af' => 1,
112
- 'net.af' => 1,
113
- 'edu.af' => 1,
114
- 'ag' => 1,
115
- 'com.ag' => 1,
116
- 'org.ag' => 1,
117
- 'net.ag' => 1,
118
- 'co.ag' => 1,
119
- 'nom.ag' => 1,
120
- 'ai' => 1,
121
- 'off.ai' => 1,
122
- 'com.ai' => 1,
123
- 'net.ai' => 1,
124
- 'org.ai' => 1,
125
- 'al' => 1,
126
- 'com.al' => 1,
127
- 'edu.al' => 1,
128
- 'gov.al' => 1,
129
- 'mil.al' => 1,
130
- 'net.al' => 1,
131
- 'org.al' => 1,
132
- 'am' => 1,
133
- 'co.am' => 1,
134
- 'com.am' => 1,
135
- 'commune.am' => 1,
136
- 'net.am' => 1,
137
- 'org.am' => 1,
138
- 'ao' => 1,
139
- 'ed.ao' => 1,
140
- 'gv.ao' => 1,
141
- 'og.ao' => 1,
142
- 'co.ao' => 1,
143
- 'pb.ao' => 1,
144
- 'it.ao' => 1,
145
- 'aq' => 1,
146
- 'ar' => 1,
147
- 'com.ar' => 1,
148
- 'edu.ar' => 1,
149
- 'gob.ar' => 1,
150
- 'gov.ar' => 1,
151
- 'int.ar' => 1,
152
- 'mil.ar' => 1,
153
- 'musica.ar' => 1,
154
- 'net.ar' => 1,
155
- 'org.ar' => 1,
156
- 'tur.ar' => 1,
157
- 'arpa' => 1,
158
- 'e164.arpa' => 1,
159
- 'in-addr.arpa' => 1,
160
- 'ip6.arpa' => 1,
161
- 'iris.arpa' => 1,
162
- 'uri.arpa' => 1,
163
- 'urn.arpa' => 1,
164
- 'as' => 1,
165
- 'gov.as' => 1,
166
- 'asia' => 1,
167
- 'at' => 1,
168
- 'ac.at' => 1,
169
- 'co.at' => 1,
170
- 'gv.at' => 1,
171
- 'or.at' => 1,
172
- 'au' => 1,
173
- 'com.au' => 1,
174
- 'net.au' => 1,
175
- 'org.au' => 1,
176
- 'edu.au' => 1,
177
- 'gov.au' => 1,
178
- 'asn.au' => 1,
179
- 'id.au' => 1,
180
- 'info.au' => 1,
181
- 'conf.au' => 1,
182
- 'oz.au' => 1,
183
- 'act.au' => 1,
184
- 'nsw.au' => 1,
185
- 'nt.au' => 1,
186
- 'qld.au' => 1,
187
- 'sa.au' => 1,
188
- 'tas.au' => 1,
189
- 'vic.au' => 1,
190
- 'wa.au' => 1,
191
- 'act.edu.au' => 1,
192
- 'catholic.edu.au' => 1,
193
- 'eq.edu.au' => 1,
194
- 'nsw.edu.au' => 1,
195
- 'nt.edu.au' => 1,
196
- 'qld.edu.au' => 1,
197
- 'sa.edu.au' => 1,
198
- 'tas.edu.au' => 1,
199
- 'vic.edu.au' => 1,
200
- 'wa.edu.au' => 1,
201
- 'qld.gov.au' => 1,
202
- 'sa.gov.au' => 1,
203
- 'tas.gov.au' => 1,
204
- 'vic.gov.au' => 1,
205
- 'wa.gov.au' => 1,
206
- 'education.tas.edu.au' => 1,
207
- 'schools.nsw.edu.au' => 1,
208
- 'aw' => 1,
209
- 'com.aw' => 1,
210
- 'ax' => 1,
211
- 'az' => 1,
212
- 'com.az' => 1,
213
- 'net.az' => 1,
214
- 'int.az' => 1,
215
- 'gov.az' => 1,
216
- 'org.az' => 1,
217
- 'edu.az' => 1,
218
- 'info.az' => 1,
219
- 'pp.az' => 1,
220
- 'mil.az' => 1,
221
- 'name.az' => 1,
222
- 'pro.az' => 1,
223
- 'biz.az' => 1,
224
- 'ba' => 1,
225
- 'com.ba' => 1,
226
- 'edu.ba' => 1,
227
- 'gov.ba' => 1,
228
- 'mil.ba' => 1,
229
- 'net.ba' => 1,
230
- 'org.ba' => 1,
231
- 'bb' => 1,
232
- 'biz.bb' => 1,
233
- 'co.bb' => 1,
234
- 'com.bb' => 1,
235
- 'edu.bb' => 1,
236
- 'gov.bb' => 1,
237
- 'info.bb' => 1,
238
- 'net.bb' => 1,
239
- 'org.bb' => 1,
240
- 'store.bb' => 1,
241
- 'tv.bb' => 1,
242
- '*.bd' => 1,
243
- 'be' => 1,
244
- 'ac.be' => 1,
245
- 'bf' => 1,
246
- 'gov.bf' => 1,
247
- 'bg' => 1,
248
- 'a.bg' => 1,
249
- 'b.bg' => 1,
250
- 'c.bg' => 1,
251
- 'd.bg' => 1,
252
- 'e.bg' => 1,
253
- 'f.bg' => 1,
254
- 'g.bg' => 1,
255
- 'h.bg' => 1,
256
- 'i.bg' => 1,
257
- 'j.bg' => 1,
258
- 'k.bg' => 1,
259
- 'l.bg' => 1,
260
- 'm.bg' => 1,
261
- 'n.bg' => 1,
262
- 'o.bg' => 1,
263
- 'p.bg' => 1,
264
- 'q.bg' => 1,
265
- 'r.bg' => 1,
266
- 's.bg' => 1,
267
- 't.bg' => 1,
268
- 'u.bg' => 1,
269
- 'v.bg' => 1,
270
- 'w.bg' => 1,
271
- 'x.bg' => 1,
272
- 'y.bg' => 1,
273
- 'z.bg' => 1,
274
- '0.bg' => 1,
275
- '1.bg' => 1,
276
- '2.bg' => 1,
277
- '3.bg' => 1,
278
- '4.bg' => 1,
279
- '5.bg' => 1,
280
- '6.bg' => 1,
281
- '7.bg' => 1,
282
- '8.bg' => 1,
283
- '9.bg' => 1,
284
- 'bh' => 1,
285
- 'com.bh' => 1,
286
- 'edu.bh' => 1,
287
- 'net.bh' => 1,
288
- 'org.bh' => 1,
289
- 'gov.bh' => 1,
290
- 'bi' => 1,
291
- 'co.bi' => 1,
292
- 'com.bi' => 1,
293
- 'edu.bi' => 1,
294
- 'or.bi' => 1,
295
- 'org.bi' => 1,
296
- 'biz' => 1,
297
- 'bj' => 1,
298
- 'asso.bj' => 1,
299
- 'barreau.bj' => 1,
300
- 'gouv.bj' => 1,
301
- 'bm' => 1,
302
- 'com.bm' => 1,
303
- 'edu.bm' => 1,
304
- 'gov.bm' => 1,
305
- 'net.bm' => 1,
306
- 'org.bm' => 1,
307
- 'bn' => 1,
308
- 'com.bn' => 1,
309
- 'edu.bn' => 1,
310
- 'gov.bn' => 1,
311
- 'net.bn' => 1,
312
- 'org.bn' => 1,
313
- 'bo' => 1,
314
- 'com.bo' => 1,
315
- 'edu.bo' => 1,
316
- 'gob.bo' => 1,
317
- 'int.bo' => 1,
318
- 'org.bo' => 1,
319
- 'net.bo' => 1,
320
- 'mil.bo' => 1,
321
- 'tv.bo' => 1,
322
- 'web.bo' => 1,
323
- 'academia.bo' => 1,
324
- 'agro.bo' => 1,
325
- 'arte.bo' => 1,
326
- 'blog.bo' => 1,
327
- 'bolivia.bo' => 1,
328
- 'ciencia.bo' => 1,
329
- 'cooperativa.bo' => 1,
330
- 'democracia.bo' => 1,
331
- 'deporte.bo' => 1,
332
- 'ecologia.bo' => 1,
333
- 'economia.bo' => 1,
334
- 'empresa.bo' => 1,
335
- 'indigena.bo' => 1,
336
- 'industria.bo' => 1,
337
- 'info.bo' => 1,
338
- 'medicina.bo' => 1,
339
- 'movimiento.bo' => 1,
340
- 'musica.bo' => 1,
341
- 'natural.bo' => 1,
342
- 'nombre.bo' => 1,
343
- 'noticias.bo' => 1,
344
- 'patria.bo' => 1,
345
- 'politica.bo' => 1,
346
- 'profesional.bo' => 1,
347
- 'plurinacional.bo' => 1,
348
- 'pueblo.bo' => 1,
349
- 'revista.bo' => 1,
350
- 'salud.bo' => 1,
351
- 'tecnologia.bo' => 1,
352
- 'tksat.bo' => 1,
353
- 'transporte.bo' => 1,
354
- 'wiki.bo' => 1,
355
- 'br' => 1,
356
- '9guacu.br' => 1,
357
- 'abc.br' => 1,
358
- 'adm.br' => 1,
359
- 'adv.br' => 1,
360
- 'agr.br' => 1,
361
- 'aju.br' => 1,
362
- 'am.br' => 1,
363
- 'anani.br' => 1,
364
- 'aparecida.br' => 1,
365
- 'arq.br' => 1,
366
- 'art.br' => 1,
367
- 'ato.br' => 1,
368
- 'b.br' => 1,
369
- 'barueri.br' => 1,
370
- 'belem.br' => 1,
371
- 'bhz.br' => 1,
372
- 'bio.br' => 1,
373
- 'blog.br' => 1,
374
- 'bmd.br' => 1,
375
- 'boavista.br' => 1,
376
- 'bsb.br' => 1,
377
- 'campinagrande.br' => 1,
378
- 'campinas.br' => 1,
379
- 'caxias.br' => 1,
380
- 'cim.br' => 1,
381
- 'cng.br' => 1,
382
- 'cnt.br' => 1,
383
- 'com.br' => 1,
384
- 'contagem.br' => 1,
385
- 'coop.br' => 1,
386
- 'cri.br' => 1,
387
- 'cuiaba.br' => 1,
388
- 'curitiba.br' => 1,
389
- 'def.br' => 1,
390
- 'ecn.br' => 1,
391
- 'eco.br' => 1,
392
- 'edu.br' => 1,
393
- 'emp.br' => 1,
394
- 'eng.br' => 1,
395
- 'esp.br' => 1,
396
- 'etc.br' => 1,
397
- 'eti.br' => 1,
398
- 'far.br' => 1,
399
- 'feira.br' => 1,
400
- 'flog.br' => 1,
401
- 'floripa.br' => 1,
402
- 'fm.br' => 1,
403
- 'fnd.br' => 1,
404
- 'fortal.br' => 1,
405
- 'fot.br' => 1,
406
- 'foz.br' => 1,
407
- 'fst.br' => 1,
408
- 'g12.br' => 1,
409
- 'ggf.br' => 1,
410
- 'goiania.br' => 1,
411
- 'gov.br' => 1,
412
- 'ac.gov.br' => 1,
413
- 'al.gov.br' => 1,
414
- 'am.gov.br' => 1,
415
- 'ap.gov.br' => 1,
416
- 'ba.gov.br' => 1,
417
- 'ce.gov.br' => 1,
418
- 'df.gov.br' => 1,
419
- 'es.gov.br' => 1,
420
- 'go.gov.br' => 1,
421
- 'ma.gov.br' => 1,
422
- 'mg.gov.br' => 1,
423
- 'ms.gov.br' => 1,
424
- 'mt.gov.br' => 1,
425
- 'pa.gov.br' => 1,
426
- 'pb.gov.br' => 1,
427
- 'pe.gov.br' => 1,
428
- 'pi.gov.br' => 1,
429
- 'pr.gov.br' => 1,
430
- 'rj.gov.br' => 1,
431
- 'rn.gov.br' => 1,
432
- 'ro.gov.br' => 1,
433
- 'rr.gov.br' => 1,
434
- 'rs.gov.br' => 1,
435
- 'sc.gov.br' => 1,
436
- 'se.gov.br' => 1,
437
- 'sp.gov.br' => 1,
438
- 'to.gov.br' => 1,
439
- 'gru.br' => 1,
440
- 'imb.br' => 1,
441
- 'ind.br' => 1,
442
- 'inf.br' => 1,
443
- 'jab.br' => 1,
444
- 'jampa.br' => 1,
445
- 'jdf.br' => 1,
446
- 'joinville.br' => 1,
447
- 'jor.br' => 1,
448
- 'jus.br' => 1,
449
- 'leg.br' => 1,
450
- 'lel.br' => 1,
451
- 'londrina.br' => 1,
452
- 'macapa.br' => 1,
453
- 'maceio.br' => 1,
454
- 'manaus.br' => 1,
455
- 'maringa.br' => 1,
456
- 'mat.br' => 1,
457
- 'med.br' => 1,
458
- 'mil.br' => 1,
459
- 'morena.br' => 1,
460
- 'mp.br' => 1,
461
- 'mus.br' => 1,
462
- 'natal.br' => 1,
463
- 'net.br' => 1,
464
- 'niteroi.br' => 1,
465
- '*.nom.br' => 1,
466
- 'not.br' => 1,
467
- 'ntr.br' => 1,
468
- 'odo.br' => 1,
469
- 'ong.br' => 1,
470
- 'org.br' => 1,
471
- 'osasco.br' => 1,
472
- 'palmas.br' => 1,
473
- 'poa.br' => 1,
474
- 'ppg.br' => 1,
475
- 'pro.br' => 1,
476
- 'psc.br' => 1,
477
- 'psi.br' => 1,
478
- 'pvh.br' => 1,
479
- 'qsl.br' => 1,
480
- 'radio.br' => 1,
481
- 'rec.br' => 1,
482
- 'recife.br' => 1,
483
- 'ribeirao.br' => 1,
484
- 'rio.br' => 1,
485
- 'riobranco.br' => 1,
486
- 'riopreto.br' => 1,
487
- 'salvador.br' => 1,
488
- 'sampa.br' => 1,
489
- 'santamaria.br' => 1,
490
- 'santoandre.br' => 1,
491
- 'saobernardo.br' => 1,
492
- 'saogonca.br' => 1,
493
- 'sjc.br' => 1,
494
- 'slg.br' => 1,
495
- 'slz.br' => 1,
496
- 'sorocaba.br' => 1,
497
- 'srv.br' => 1,
498
- 'taxi.br' => 1,
499
- 'tc.br' => 1,
500
- 'teo.br' => 1,
501
- 'the.br' => 1,
502
- 'tmp.br' => 1,
503
- 'trd.br' => 1,
504
- 'tur.br' => 1,
505
- 'tv.br' => 1,
506
- 'udi.br' => 1,
507
- 'vet.br' => 1,
508
- 'vix.br' => 1,
509
- 'vlog.br' => 1,
510
- 'wiki.br' => 1,
511
- 'zlg.br' => 1,
512
- 'bs' => 1,
513
- 'com.bs' => 1,
514
- 'net.bs' => 1,
515
- 'org.bs' => 1,
516
- 'edu.bs' => 1,
517
- 'gov.bs' => 1,
518
- 'bt' => 1,
519
- 'com.bt' => 1,
520
- 'edu.bt' => 1,
521
- 'gov.bt' => 1,
522
- 'net.bt' => 1,
523
- 'org.bt' => 1,
524
- 'bv' => 1,
525
- 'bw' => 1,
526
- 'co.bw' => 1,
527
- 'org.bw' => 1,
528
- 'by' => 1,
529
- 'gov.by' => 1,
530
- 'mil.by' => 1,
531
- 'com.by' => 1,
532
- 'of.by' => 1,
533
- 'bz' => 1,
534
- 'com.bz' => 1,
535
- 'net.bz' => 1,
536
- 'org.bz' => 1,
537
- 'edu.bz' => 1,
538
- 'gov.bz' => 1,
539
- 'ca' => 1,
540
- 'ab.ca' => 1,
541
- 'bc.ca' => 1,
542
- 'mb.ca' => 1,
543
- 'nb.ca' => 1,
544
- 'nf.ca' => 1,
545
- 'nl.ca' => 1,
546
- 'ns.ca' => 1,
547
- 'nt.ca' => 1,
548
- 'nu.ca' => 1,
549
- 'on.ca' => 1,
550
- 'pe.ca' => 1,
551
- 'qc.ca' => 1,
552
- 'sk.ca' => 1,
553
- 'yk.ca' => 1,
554
- 'gc.ca' => 1,
555
- 'cat' => 1,
556
- 'cc' => 1,
557
- 'cd' => 1,
558
- 'gov.cd' => 1,
559
- 'cf' => 1,
560
- 'cg' => 1,
561
- 'ch' => 1,
562
- 'ci' => 1,
563
- 'org.ci' => 1,
564
- 'or.ci' => 1,
565
- 'com.ci' => 1,
566
- 'co.ci' => 1,
567
- 'edu.ci' => 1,
568
- 'ed.ci' => 1,
569
- 'ac.ci' => 1,
570
- 'net.ci' => 1,
571
- 'go.ci' => 1,
572
- 'asso.ci' => 1,
573
- 'aéroport.ci' => 1,
574
- 'int.ci' => 1,
575
- 'presse.ci' => 1,
576
- 'md.ci' => 1,
577
- 'gouv.ci' => 1,
578
- '*.ck' => 1,
579
- '!www.ck' => 1,
580
- 'cl' => 1,
581
- 'gov.cl' => 1,
582
- 'gob.cl' => 1,
583
- 'co.cl' => 1,
584
- 'mil.cl' => 1,
585
- 'cm' => 1,
586
- 'co.cm' => 1,
587
- 'com.cm' => 1,
588
- 'gov.cm' => 1,
589
- 'net.cm' => 1,
590
- 'cn' => 1,
591
- 'ac.cn' => 1,
592
- 'com.cn' => 1,
593
- 'edu.cn' => 1,
594
- 'gov.cn' => 1,
595
- 'net.cn' => 1,
596
- 'org.cn' => 1,
597
- 'mil.cn' => 1,
598
- '公司.cn' => 1,
599
- '网络.cn' => 1,
600
- '網絡.cn' => 1,
601
- 'ah.cn' => 1,
602
- 'bj.cn' => 1,
603
- 'cq.cn' => 1,
604
- 'fj.cn' => 1,
605
- 'gd.cn' => 1,
606
- 'gs.cn' => 1,
607
- 'gz.cn' => 1,
608
- 'gx.cn' => 1,
609
- 'ha.cn' => 1,
610
- 'hb.cn' => 1,
611
- 'he.cn' => 1,
612
- 'hi.cn' => 1,
613
- 'hl.cn' => 1,
614
- 'hn.cn' => 1,
615
- 'jl.cn' => 1,
616
- 'js.cn' => 1,
617
- 'jx.cn' => 1,
618
- 'ln.cn' => 1,
619
- 'nm.cn' => 1,
620
- 'nx.cn' => 1,
621
- 'qh.cn' => 1,
622
- 'sc.cn' => 1,
623
- 'sd.cn' => 1,
624
- 'sh.cn' => 1,
625
- 'sn.cn' => 1,
626
- 'sx.cn' => 1,
627
- 'tj.cn' => 1,
628
- 'xj.cn' => 1,
629
- 'xz.cn' => 1,
630
- 'yn.cn' => 1,
631
- 'zj.cn' => 1,
632
- 'hk.cn' => 1,
633
- 'mo.cn' => 1,
634
- 'tw.cn' => 1,
635
- 'co' => 1,
636
- 'arts.co' => 1,
637
- 'com.co' => 1,
638
- 'edu.co' => 1,
639
- 'firm.co' => 1,
640
- 'gov.co' => 1,
641
- 'info.co' => 1,
642
- 'int.co' => 1,
643
- 'mil.co' => 1,
644
- 'net.co' => 1,
645
- 'nom.co' => 1,
646
- 'org.co' => 1,
647
- 'rec.co' => 1,
648
- 'web.co' => 1,
649
- 'com' => 1,
650
- 'coop' => 1,
651
- 'cr' => 1,
652
- 'ac.cr' => 1,
653
- 'co.cr' => 1,
654
- 'ed.cr' => 1,
655
- 'fi.cr' => 1,
656
- 'go.cr' => 1,
657
- 'or.cr' => 1,
658
- 'sa.cr' => 1,
659
- 'cu' => 1,
660
- 'com.cu' => 1,
661
- 'edu.cu' => 1,
662
- 'org.cu' => 1,
663
- 'net.cu' => 1,
664
- 'gov.cu' => 1,
665
- 'inf.cu' => 1,
666
- 'cv' => 1,
667
- 'cw' => 1,
668
- 'com.cw' => 1,
669
- 'edu.cw' => 1,
670
- 'net.cw' => 1,
671
- 'org.cw' => 1,
672
- 'cx' => 1,
673
- 'gov.cx' => 1,
674
- 'cy' => 1,
675
- 'ac.cy' => 1,
676
- 'biz.cy' => 1,
677
- 'com.cy' => 1,
678
- 'ekloges.cy' => 1,
679
- 'gov.cy' => 1,
680
- 'ltd.cy' => 1,
681
- 'name.cy' => 1,
682
- 'net.cy' => 1,
683
- 'org.cy' => 1,
684
- 'parliament.cy' => 1,
685
- 'press.cy' => 1,
686
- 'pro.cy' => 1,
687
- 'tm.cy' => 1,
688
- 'cz' => 1,
689
- 'de' => 1,
690
- 'dj' => 1,
691
- 'dk' => 1,
692
- 'dm' => 1,
693
- 'com.dm' => 1,
694
- 'net.dm' => 1,
695
- 'org.dm' => 1,
696
- 'edu.dm' => 1,
697
- 'gov.dm' => 1,
698
- 'do' => 1,
699
- 'art.do' => 1,
700
- 'com.do' => 1,
701
- 'edu.do' => 1,
702
- 'gob.do' => 1,
703
- 'gov.do' => 1,
704
- 'mil.do' => 1,
705
- 'net.do' => 1,
706
- 'org.do' => 1,
707
- 'sld.do' => 1,
708
- 'web.do' => 1,
709
- 'dz' => 1,
710
- 'com.dz' => 1,
711
- 'org.dz' => 1,
712
- 'net.dz' => 1,
713
- 'gov.dz' => 1,
714
- 'edu.dz' => 1,
715
- 'asso.dz' => 1,
716
- 'pol.dz' => 1,
717
- 'art.dz' => 1,
718
- 'ec' => 1,
719
- 'com.ec' => 1,
720
- 'info.ec' => 1,
721
- 'net.ec' => 1,
722
- 'fin.ec' => 1,
723
- 'k12.ec' => 1,
724
- 'med.ec' => 1,
725
- 'pro.ec' => 1,
726
- 'org.ec' => 1,
727
- 'edu.ec' => 1,
728
- 'gov.ec' => 1,
729
- 'gob.ec' => 1,
730
- 'mil.ec' => 1,
731
- 'edu' => 1,
732
- 'ee' => 1,
733
- 'edu.ee' => 1,
734
- 'gov.ee' => 1,
735
- 'riik.ee' => 1,
736
- 'lib.ee' => 1,
737
- 'med.ee' => 1,
738
- 'com.ee' => 1,
739
- 'pri.ee' => 1,
740
- 'aip.ee' => 1,
741
- 'org.ee' => 1,
742
- 'fie.ee' => 1,
743
- 'eg' => 1,
744
- 'com.eg' => 1,
745
- 'edu.eg' => 1,
746
- 'eun.eg' => 1,
747
- 'gov.eg' => 1,
748
- 'mil.eg' => 1,
749
- 'name.eg' => 1,
750
- 'net.eg' => 1,
751
- 'org.eg' => 1,
752
- 'sci.eg' => 1,
753
- '*.er' => 1,
754
- 'es' => 1,
755
- 'com.es' => 1,
756
- 'nom.es' => 1,
757
- 'org.es' => 1,
758
- 'gob.es' => 1,
759
- 'edu.es' => 1,
760
- 'et' => 1,
761
- 'com.et' => 1,
762
- 'gov.et' => 1,
763
- 'org.et' => 1,
764
- 'edu.et' => 1,
765
- 'biz.et' => 1,
766
- 'name.et' => 1,
767
- 'info.et' => 1,
768
- 'net.et' => 1,
769
- 'eu' => 1,
770
- 'fi' => 1,
771
- 'aland.fi' => 1,
772
- '*.fj' => 1,
773
- '*.fk' => 1,
774
- 'fm' => 1,
775
- 'fo' => 1,
776
- 'fr' => 1,
777
- 'asso.fr' => 1,
778
- 'com.fr' => 1,
779
- 'gouv.fr' => 1,
780
- 'nom.fr' => 1,
781
- 'prd.fr' => 1,
782
- 'tm.fr' => 1,
783
- 'aeroport.fr' => 1,
784
- 'avocat.fr' => 1,
785
- 'avoues.fr' => 1,
786
- 'cci.fr' => 1,
787
- 'chambagri.fr' => 1,
788
- 'chirurgiens-dentistes.fr' => 1,
789
- 'experts-comptables.fr' => 1,
790
- 'geometre-expert.fr' => 1,
791
- 'greta.fr' => 1,
792
- 'huissier-justice.fr' => 1,
793
- 'medecin.fr' => 1,
794
- 'notaires.fr' => 1,
795
- 'pharmacien.fr' => 1,
796
- 'port.fr' => 1,
797
- 'veterinaire.fr' => 1,
798
- 'ga' => 1,
799
- 'gb' => 1,
800
- 'gd' => 1,
801
- 'ge' => 1,
802
- 'com.ge' => 1,
803
- 'edu.ge' => 1,
804
- 'gov.ge' => 1,
805
- 'org.ge' => 1,
806
- 'mil.ge' => 1,
807
- 'net.ge' => 1,
808
- 'pvt.ge' => 1,
809
- 'gf' => 1,
810
- 'gg' => 1,
811
- 'co.gg' => 1,
812
- 'net.gg' => 1,
813
- 'org.gg' => 1,
814
- 'gh' => 1,
815
- 'com.gh' => 1,
816
- 'edu.gh' => 1,
817
- 'gov.gh' => 1,
818
- 'org.gh' => 1,
819
- 'mil.gh' => 1,
820
- 'gi' => 1,
821
- 'com.gi' => 1,
822
- 'ltd.gi' => 1,
823
- 'gov.gi' => 1,
824
- 'mod.gi' => 1,
825
- 'edu.gi' => 1,
826
- 'org.gi' => 1,
827
- 'gl' => 1,
828
- 'co.gl' => 1,
829
- 'com.gl' => 1,
830
- 'edu.gl' => 1,
831
- 'net.gl' => 1,
832
- 'org.gl' => 1,
833
- 'gm' => 1,
834
- 'gn' => 1,
835
- 'ac.gn' => 1,
836
- 'com.gn' => 1,
837
- 'edu.gn' => 1,
838
- 'gov.gn' => 1,
839
- 'org.gn' => 1,
840
- 'net.gn' => 1,
841
- 'gov' => 1,
842
- 'gp' => 1,
843
- 'com.gp' => 1,
844
- 'net.gp' => 1,
845
- 'mobi.gp' => 1,
846
- 'edu.gp' => 1,
847
- 'org.gp' => 1,
848
- 'asso.gp' => 1,
849
- 'gq' => 1,
850
- 'gr' => 1,
851
- 'com.gr' => 1,
852
- 'edu.gr' => 1,
853
- 'net.gr' => 1,
854
- 'org.gr' => 1,
855
- 'gov.gr' => 1,
856
- 'gs' => 1,
857
- 'gt' => 1,
858
- 'com.gt' => 1,
859
- 'edu.gt' => 1,
860
- 'gob.gt' => 1,
861
- 'ind.gt' => 1,
862
- 'mil.gt' => 1,
863
- 'net.gt' => 1,
864
- 'org.gt' => 1,
865
- 'gu' => 1,
866
- 'com.gu' => 1,
867
- 'edu.gu' => 1,
868
- 'gov.gu' => 1,
869
- 'guam.gu' => 1,
870
- 'info.gu' => 1,
871
- 'net.gu' => 1,
872
- 'org.gu' => 1,
873
- 'web.gu' => 1,
874
- 'gw' => 1,
875
- 'gy' => 1,
876
- 'co.gy' => 1,
877
- 'com.gy' => 1,
878
- 'edu.gy' => 1,
879
- 'gov.gy' => 1,
880
- 'net.gy' => 1,
881
- 'org.gy' => 1,
882
- 'hk' => 1,
883
- 'com.hk' => 1,
884
- 'edu.hk' => 1,
885
- 'gov.hk' => 1,
886
- 'idv.hk' => 1,
887
- 'net.hk' => 1,
888
- 'org.hk' => 1,
889
- '公司.hk' => 1,
890
- '教育.hk' => 1,
891
- '敎育.hk' => 1,
892
- '政府.hk' => 1,
893
- '個人.hk' => 1,
894
- '个人.hk' => 1,
895
- '箇人.hk' => 1,
896
- '網络.hk' => 1,
897
- '网络.hk' => 1,
898
- '组織.hk' => 1,
899
- '網絡.hk' => 1,
900
- '网絡.hk' => 1,
901
- '组织.hk' => 1,
902
- '組織.hk' => 1,
903
- '組织.hk' => 1,
904
- 'hm' => 1,
905
- 'hn' => 1,
906
- 'com.hn' => 1,
907
- 'edu.hn' => 1,
908
- 'org.hn' => 1,
909
- 'net.hn' => 1,
910
- 'mil.hn' => 1,
911
- 'gob.hn' => 1,
912
- 'hr' => 1,
913
- 'iz.hr' => 1,
914
- 'from.hr' => 1,
915
- 'name.hr' => 1,
916
- 'com.hr' => 1,
917
- 'ht' => 1,
918
- 'com.ht' => 1,
919
- 'shop.ht' => 1,
920
- 'firm.ht' => 1,
921
- 'info.ht' => 1,
922
- 'adult.ht' => 1,
923
- 'net.ht' => 1,
924
- 'pro.ht' => 1,
925
- 'org.ht' => 1,
926
- 'med.ht' => 1,
927
- 'art.ht' => 1,
928
- 'coop.ht' => 1,
929
- 'pol.ht' => 1,
930
- 'asso.ht' => 1,
931
- 'edu.ht' => 1,
932
- 'rel.ht' => 1,
933
- 'gouv.ht' => 1,
934
- 'perso.ht' => 1,
935
- 'hu' => 1,
936
- 'co.hu' => 1,
937
- 'info.hu' => 1,
938
- 'org.hu' => 1,
939
- 'priv.hu' => 1,
940
- 'sport.hu' => 1,
941
- 'tm.hu' => 1,
942
- '2000.hu' => 1,
943
- 'agrar.hu' => 1,
944
- 'bolt.hu' => 1,
945
- 'casino.hu' => 1,
946
- 'city.hu' => 1,
947
- 'erotica.hu' => 1,
948
- 'erotika.hu' => 1,
949
- 'film.hu' => 1,
950
- 'forum.hu' => 1,
951
- 'games.hu' => 1,
952
- 'hotel.hu' => 1,
953
- 'ingatlan.hu' => 1,
954
- 'jogasz.hu' => 1,
955
- 'konyvelo.hu' => 1,
956
- 'lakas.hu' => 1,
957
- 'media.hu' => 1,
958
- 'news.hu' => 1,
959
- 'reklam.hu' => 1,
960
- 'sex.hu' => 1,
961
- 'shop.hu' => 1,
962
- 'suli.hu' => 1,
963
- 'szex.hu' => 1,
964
- 'tozsde.hu' => 1,
965
- 'utazas.hu' => 1,
966
- 'video.hu' => 1,
967
- 'id' => 1,
968
- 'ac.id' => 1,
969
- 'biz.id' => 1,
970
- 'co.id' => 1,
971
- 'desa.id' => 1,
972
- 'go.id' => 1,
973
- 'mil.id' => 1,
974
- 'my.id' => 1,
975
- 'net.id' => 1,
976
- 'or.id' => 1,
977
- 'ponpes.id' => 1,
978
- 'sch.id' => 1,
979
- 'web.id' => 1,
980
- 'ie' => 1,
981
- 'gov.ie' => 1,
982
- 'il' => 1,
983
- 'ac.il' => 1,
984
- 'co.il' => 1,
985
- 'gov.il' => 1,
986
- 'idf.il' => 1,
987
- 'k12.il' => 1,
988
- 'muni.il' => 1,
989
- 'net.il' => 1,
990
- 'org.il' => 1,
991
- 'im' => 1,
992
- 'ac.im' => 1,
993
- 'co.im' => 1,
994
- 'com.im' => 1,
995
- 'ltd.co.im' => 1,
996
- 'net.im' => 1,
997
- 'org.im' => 1,
998
- 'plc.co.im' => 1,
999
- 'tt.im' => 1,
1000
- 'tv.im' => 1,
1001
- 'in' => 1,
1002
- 'co.in' => 1,
1003
- 'firm.in' => 1,
1004
- 'net.in' => 1,
1005
- 'org.in' => 1,
1006
- 'gen.in' => 1,
1007
- 'ind.in' => 1,
1008
- 'nic.in' => 1,
1009
- 'ac.in' => 1,
1010
- 'edu.in' => 1,
1011
- 'res.in' => 1,
1012
- 'gov.in' => 1,
1013
- 'mil.in' => 1,
1014
- 'info' => 1,
1015
- 'int' => 1,
1016
- 'eu.int' => 1,
1017
- 'io' => 1,
1018
- 'com.io' => 1,
1019
- 'iq' => 1,
1020
- 'gov.iq' => 1,
1021
- 'edu.iq' => 1,
1022
- 'mil.iq' => 1,
1023
- 'com.iq' => 1,
1024
- 'org.iq' => 1,
1025
- 'net.iq' => 1,
1026
- 'ir' => 1,
1027
- 'ac.ir' => 1,
1028
- 'co.ir' => 1,
1029
- 'gov.ir' => 1,
1030
- 'id.ir' => 1,
1031
- 'net.ir' => 1,
1032
- 'org.ir' => 1,
1033
- 'sch.ir' => 1,
1034
- 'ایران.ir' => 1,
1035
- 'ايران.ir' => 1,
1036
- 'is' => 1,
1037
- 'net.is' => 1,
1038
- 'com.is' => 1,
1039
- 'edu.is' => 1,
1040
- 'gov.is' => 1,
1041
- 'org.is' => 1,
1042
- 'int.is' => 1,
1043
- 'it' => 1,
1044
- 'gov.it' => 1,
1045
- 'edu.it' => 1,
1046
- 'abr.it' => 1,
1047
- 'abruzzo.it' => 1,
1048
- 'aosta-valley.it' => 1,
1049
- 'aostavalley.it' => 1,
1050
- 'bas.it' => 1,
1051
- 'basilicata.it' => 1,
1052
- 'cal.it' => 1,
1053
- 'calabria.it' => 1,
1054
- 'cam.it' => 1,
1055
- 'campania.it' => 1,
1056
- 'emilia-romagna.it' => 1,
1057
- 'emiliaromagna.it' => 1,
1058
- 'emr.it' => 1,
1059
- 'friuli-v-giulia.it' => 1,
1060
- 'friuli-ve-giulia.it' => 1,
1061
- 'friuli-vegiulia.it' => 1,
1062
- 'friuli-venezia-giulia.it' => 1,
1063
- 'friuli-veneziagiulia.it' => 1,
1064
- 'friuli-vgiulia.it' => 1,
1065
- 'friuliv-giulia.it' => 1,
1066
- 'friulive-giulia.it' => 1,
1067
- 'friulivegiulia.it' => 1,
1068
- 'friulivenezia-giulia.it' => 1,
1069
- 'friuliveneziagiulia.it' => 1,
1070
- 'friulivgiulia.it' => 1,
1071
- 'fvg.it' => 1,
1072
- 'laz.it' => 1,
1073
- 'lazio.it' => 1,
1074
- 'lig.it' => 1,
1075
- 'liguria.it' => 1,
1076
- 'lom.it' => 1,
1077
- 'lombardia.it' => 1,
1078
- 'lombardy.it' => 1,
1079
- 'lucania.it' => 1,
1080
- 'mar.it' => 1,
1081
- 'marche.it' => 1,
1082
- 'mol.it' => 1,
1083
- 'molise.it' => 1,
1084
- 'piedmont.it' => 1,
1085
- 'piemonte.it' => 1,
1086
- 'pmn.it' => 1,
1087
- 'pug.it' => 1,
1088
- 'puglia.it' => 1,
1089
- 'sar.it' => 1,
1090
- 'sardegna.it' => 1,
1091
- 'sardinia.it' => 1,
1092
- 'sic.it' => 1,
1093
- 'sicilia.it' => 1,
1094
- 'sicily.it' => 1,
1095
- 'taa.it' => 1,
1096
- 'tos.it' => 1,
1097
- 'toscana.it' => 1,
1098
- 'trentin-sud-tirol.it' => 1,
1099
- 'trentin-süd-tirol.it' => 1,
1100
- 'trentin-sudtirol.it' => 1,
1101
- 'trentin-südtirol.it' => 1,
1102
- 'trentin-sued-tirol.it' => 1,
1103
- 'trentin-suedtirol.it' => 1,
1104
- 'trentino-a-adige.it' => 1,
1105
- 'trentino-aadige.it' => 1,
1106
- 'trentino-alto-adige.it' => 1,
1107
- 'trentino-altoadige.it' => 1,
1108
- 'trentino-s-tirol.it' => 1,
1109
- 'trentino-stirol.it' => 1,
1110
- 'trentino-sud-tirol.it' => 1,
1111
- 'trentino-süd-tirol.it' => 1,
1112
- 'trentino-sudtirol.it' => 1,
1113
- 'trentino-südtirol.it' => 1,
1114
- 'trentino-sued-tirol.it' => 1,
1115
- 'trentino-suedtirol.it' => 1,
1116
- 'trentino.it' => 1,
1117
- 'trentinoa-adige.it' => 1,
1118
- 'trentinoaadige.it' => 1,
1119
- 'trentinoalto-adige.it' => 1,
1120
- 'trentinoaltoadige.it' => 1,
1121
- 'trentinos-tirol.it' => 1,
1122
- 'trentinostirol.it' => 1,
1123
- 'trentinosud-tirol.it' => 1,
1124
- 'trentinosüd-tirol.it' => 1,
1125
- 'trentinosudtirol.it' => 1,
1126
- 'trentinosüdtirol.it' => 1,
1127
- 'trentinosued-tirol.it' => 1,
1128
- 'trentinosuedtirol.it' => 1,
1129
- 'trentinsud-tirol.it' => 1,
1130
- 'trentinsüd-tirol.it' => 1,
1131
- 'trentinsudtirol.it' => 1,
1132
- 'trentinsüdtirol.it' => 1,
1133
- 'trentinsued-tirol.it' => 1,
1134
- 'trentinsuedtirol.it' => 1,
1135
- 'tuscany.it' => 1,
1136
- 'umb.it' => 1,
1137
- 'umbria.it' => 1,
1138
- 'val-d-aosta.it' => 1,
1139
- 'val-daosta.it' => 1,
1140
- 'vald-aosta.it' => 1,
1141
- 'valdaosta.it' => 1,
1142
- 'valle-aosta.it' => 1,
1143
- 'valle-d-aosta.it' => 1,
1144
- 'valle-daosta.it' => 1,
1145
- 'valleaosta.it' => 1,
1146
- 'valled-aosta.it' => 1,
1147
- 'valledaosta.it' => 1,
1148
- 'vallee-aoste.it' => 1,
1149
- 'vallée-aoste.it' => 1,
1150
- 'vallee-d-aoste.it' => 1,
1151
- 'vallée-d-aoste.it' => 1,
1152
- 'valleeaoste.it' => 1,
1153
- 'valléeaoste.it' => 1,
1154
- 'valleedaoste.it' => 1,
1155
- 'valléedaoste.it' => 1,
1156
- 'vao.it' => 1,
1157
- 'vda.it' => 1,
1158
- 'ven.it' => 1,
1159
- 'veneto.it' => 1,
1160
- 'ag.it' => 1,
1161
- 'agrigento.it' => 1,
1162
- 'al.it' => 1,
1163
- 'alessandria.it' => 1,
1164
- 'alto-adige.it' => 1,
1165
- 'altoadige.it' => 1,
1166
- 'an.it' => 1,
1167
- 'ancona.it' => 1,
1168
- 'andria-barletta-trani.it' => 1,
1169
- 'andria-trani-barletta.it' => 1,
1170
- 'andriabarlettatrani.it' => 1,
1171
- 'andriatranibarletta.it' => 1,
1172
- 'ao.it' => 1,
1173
- 'aosta.it' => 1,
1174
- 'aoste.it' => 1,
1175
- 'ap.it' => 1,
1176
- 'aq.it' => 1,
1177
- 'aquila.it' => 1,
1178
- 'ar.it' => 1,
1179
- 'arezzo.it' => 1,
1180
- 'ascoli-piceno.it' => 1,
1181
- 'ascolipiceno.it' => 1,
1182
- 'asti.it' => 1,
1183
- 'at.it' => 1,
1184
- 'av.it' => 1,
1185
- 'avellino.it' => 1,
1186
- 'ba.it' => 1,
1187
- 'balsan-sudtirol.it' => 1,
1188
- 'balsan-südtirol.it' => 1,
1189
- 'balsan-suedtirol.it' => 1,
1190
- 'balsan.it' => 1,
1191
- 'bari.it' => 1,
1192
- 'barletta-trani-andria.it' => 1,
1193
- 'barlettatraniandria.it' => 1,
1194
- 'belluno.it' => 1,
1195
- 'benevento.it' => 1,
1196
- 'bergamo.it' => 1,
1197
- 'bg.it' => 1,
1198
- 'bi.it' => 1,
1199
- 'biella.it' => 1,
1200
- 'bl.it' => 1,
1201
- 'bn.it' => 1,
1202
- 'bo.it' => 1,
1203
- 'bologna.it' => 1,
1204
- 'bolzano-altoadige.it' => 1,
1205
- 'bolzano.it' => 1,
1206
- 'bozen-sudtirol.it' => 1,
1207
- 'bozen-südtirol.it' => 1,
1208
- 'bozen-suedtirol.it' => 1,
1209
- 'bozen.it' => 1,
1210
- 'br.it' => 1,
1211
- 'brescia.it' => 1,
1212
- 'brindisi.it' => 1,
1213
- 'bs.it' => 1,
1214
- 'bt.it' => 1,
1215
- 'bulsan-sudtirol.it' => 1,
1216
- 'bulsan-südtirol.it' => 1,
1217
- 'bulsan-suedtirol.it' => 1,
1218
- 'bulsan.it' => 1,
1219
- 'bz.it' => 1,
1220
- 'ca.it' => 1,
1221
- 'cagliari.it' => 1,
1222
- 'caltanissetta.it' => 1,
1223
- 'campidano-medio.it' => 1,
1224
- 'campidanomedio.it' => 1,
1225
- 'campobasso.it' => 1,
1226
- 'carbonia-iglesias.it' => 1,
1227
- 'carboniaiglesias.it' => 1,
1228
- 'carrara-massa.it' => 1,
1229
- 'carraramassa.it' => 1,
1230
- 'caserta.it' => 1,
1231
- 'catania.it' => 1,
1232
- 'catanzaro.it' => 1,
1233
- 'cb.it' => 1,
1234
- 'ce.it' => 1,
1235
- 'cesena-forli.it' => 1,
1236
- 'cesena-forlì.it' => 1,
1237
- 'cesenaforli.it' => 1,
1238
- 'cesenaforlì.it' => 1,
1239
- 'ch.it' => 1,
1240
- 'chieti.it' => 1,
1241
- 'ci.it' => 1,
1242
- 'cl.it' => 1,
1243
- 'cn.it' => 1,
1244
- 'co.it' => 1,
1245
- 'como.it' => 1,
1246
- 'cosenza.it' => 1,
1247
- 'cr.it' => 1,
1248
- 'cremona.it' => 1,
1249
- 'crotone.it' => 1,
1250
- 'cs.it' => 1,
1251
- 'ct.it' => 1,
1252
- 'cuneo.it' => 1,
1253
- 'cz.it' => 1,
1254
- 'dell-ogliastra.it' => 1,
1255
- 'dellogliastra.it' => 1,
1256
- 'en.it' => 1,
1257
- 'enna.it' => 1,
1258
- 'fc.it' => 1,
1259
- 'fe.it' => 1,
1260
- 'fermo.it' => 1,
1261
- 'ferrara.it' => 1,
1262
- 'fg.it' => 1,
1263
- 'fi.it' => 1,
1264
- 'firenze.it' => 1,
1265
- 'florence.it' => 1,
1266
- 'fm.it' => 1,
1267
- 'foggia.it' => 1,
1268
- 'forli-cesena.it' => 1,
1269
- 'forlì-cesena.it' => 1,
1270
- 'forlicesena.it' => 1,
1271
- 'forlìcesena.it' => 1,
1272
- 'fr.it' => 1,
1273
- 'frosinone.it' => 1,
1274
- 'ge.it' => 1,
1275
- 'genoa.it' => 1,
1276
- 'genova.it' => 1,
1277
- 'go.it' => 1,
1278
- 'gorizia.it' => 1,
1279
- 'gr.it' => 1,
1280
- 'grosseto.it' => 1,
1281
- 'iglesias-carbonia.it' => 1,
1282
- 'iglesiascarbonia.it' => 1,
1283
- 'im.it' => 1,
1284
- 'imperia.it' => 1,
1285
- 'is.it' => 1,
1286
- 'isernia.it' => 1,
1287
- 'kr.it' => 1,
1288
- 'la-spezia.it' => 1,
1289
- 'laquila.it' => 1,
1290
- 'laspezia.it' => 1,
1291
- 'latina.it' => 1,
1292
- 'lc.it' => 1,
1293
- 'le.it' => 1,
1294
- 'lecce.it' => 1,
1295
- 'lecco.it' => 1,
1296
- 'li.it' => 1,
1297
- 'livorno.it' => 1,
1298
- 'lo.it' => 1,
1299
- 'lodi.it' => 1,
1300
- 'lt.it' => 1,
1301
- 'lu.it' => 1,
1302
- 'lucca.it' => 1,
1303
- 'macerata.it' => 1,
1304
- 'mantova.it' => 1,
1305
- 'massa-carrara.it' => 1,
1306
- 'massacarrara.it' => 1,
1307
- 'matera.it' => 1,
1308
- 'mb.it' => 1,
1309
- 'mc.it' => 1,
1310
- 'me.it' => 1,
1311
- 'medio-campidano.it' => 1,
1312
- 'mediocampidano.it' => 1,
1313
- 'messina.it' => 1,
1314
- 'mi.it' => 1,
1315
- 'milan.it' => 1,
1316
- 'milano.it' => 1,
1317
- 'mn.it' => 1,
1318
- 'mo.it' => 1,
1319
- 'modena.it' => 1,
1320
- 'monza-brianza.it' => 1,
1321
- 'monza-e-della-brianza.it' => 1,
1322
- 'monza.it' => 1,
1323
- 'monzabrianza.it' => 1,
1324
- 'monzaebrianza.it' => 1,
1325
- 'monzaedellabrianza.it' => 1,
1326
- 'ms.it' => 1,
1327
- 'mt.it' => 1,
1328
- 'na.it' => 1,
1329
- 'naples.it' => 1,
1330
- 'napoli.it' => 1,
1331
- 'no.it' => 1,
1332
- 'novara.it' => 1,
1333
- 'nu.it' => 1,
1334
- 'nuoro.it' => 1,
1335
- 'og.it' => 1,
1336
- 'ogliastra.it' => 1,
1337
- 'olbia-tempio.it' => 1,
1338
- 'olbiatempio.it' => 1,
1339
- 'or.it' => 1,
1340
- 'oristano.it' => 1,
1341
- 'ot.it' => 1,
1342
- 'pa.it' => 1,
1343
- 'padova.it' => 1,
1344
- 'padua.it' => 1,
1345
- 'palermo.it' => 1,
1346
- 'parma.it' => 1,
1347
- 'pavia.it' => 1,
1348
- 'pc.it' => 1,
1349
- 'pd.it' => 1,
1350
- 'pe.it' => 1,
1351
- 'perugia.it' => 1,
1352
- 'pesaro-urbino.it' => 1,
1353
- 'pesarourbino.it' => 1,
1354
- 'pescara.it' => 1,
1355
- 'pg.it' => 1,
1356
- 'pi.it' => 1,
1357
- 'piacenza.it' => 1,
1358
- 'pisa.it' => 1,
1359
- 'pistoia.it' => 1,
1360
- 'pn.it' => 1,
1361
- 'po.it' => 1,
1362
- 'pordenone.it' => 1,
1363
- 'potenza.it' => 1,
1364
- 'pr.it' => 1,
1365
- 'prato.it' => 1,
1366
- 'pt.it' => 1,
1367
- 'pu.it' => 1,
1368
- 'pv.it' => 1,
1369
- 'pz.it' => 1,
1370
- 'ra.it' => 1,
1371
- 'ragusa.it' => 1,
1372
- 'ravenna.it' => 1,
1373
- 'rc.it' => 1,
1374
- 're.it' => 1,
1375
- 'reggio-calabria.it' => 1,
1376
- 'reggio-emilia.it' => 1,
1377
- 'reggiocalabria.it' => 1,
1378
- 'reggioemilia.it' => 1,
1379
- 'rg.it' => 1,
1380
- 'ri.it' => 1,
1381
- 'rieti.it' => 1,
1382
- 'rimini.it' => 1,
1383
- 'rm.it' => 1,
1384
- 'rn.it' => 1,
1385
- 'ro.it' => 1,
1386
- 'roma.it' => 1,
1387
- 'rome.it' => 1,
1388
- 'rovigo.it' => 1,
1389
- 'sa.it' => 1,
1390
- 'salerno.it' => 1,
1391
- 'sassari.it' => 1,
1392
- 'savona.it' => 1,
1393
- 'si.it' => 1,
1394
- 'siena.it' => 1,
1395
- 'siracusa.it' => 1,
1396
- 'so.it' => 1,
1397
- 'sondrio.it' => 1,
1398
- 'sp.it' => 1,
1399
- 'sr.it' => 1,
1400
- 'ss.it' => 1,
1401
- 'suedtirol.it' => 1,
1402
- 'südtirol.it' => 1,
1403
- 'sv.it' => 1,
1404
- 'ta.it' => 1,
1405
- 'taranto.it' => 1,
1406
- 'te.it' => 1,
1407
- 'tempio-olbia.it' => 1,
1408
- 'tempioolbia.it' => 1,
1409
- 'teramo.it' => 1,
1410
- 'terni.it' => 1,
1411
- 'tn.it' => 1,
1412
- 'to.it' => 1,
1413
- 'torino.it' => 1,
1414
- 'tp.it' => 1,
1415
- 'tr.it' => 1,
1416
- 'trani-andria-barletta.it' => 1,
1417
- 'trani-barletta-andria.it' => 1,
1418
- 'traniandriabarletta.it' => 1,
1419
- 'tranibarlettaandria.it' => 1,
1420
- 'trapani.it' => 1,
1421
- 'trento.it' => 1,
1422
- 'treviso.it' => 1,
1423
- 'trieste.it' => 1,
1424
- 'ts.it' => 1,
1425
- 'turin.it' => 1,
1426
- 'tv.it' => 1,
1427
- 'ud.it' => 1,
1428
- 'udine.it' => 1,
1429
- 'urbino-pesaro.it' => 1,
1430
- 'urbinopesaro.it' => 1,
1431
- 'va.it' => 1,
1432
- 'varese.it' => 1,
1433
- 'vb.it' => 1,
1434
- 'vc.it' => 1,
1435
- 've.it' => 1,
1436
- 'venezia.it' => 1,
1437
- 'venice.it' => 1,
1438
- 'verbania.it' => 1,
1439
- 'vercelli.it' => 1,
1440
- 'verona.it' => 1,
1441
- 'vi.it' => 1,
1442
- 'vibo-valentia.it' => 1,
1443
- 'vibovalentia.it' => 1,
1444
- 'vicenza.it' => 1,
1445
- 'viterbo.it' => 1,
1446
- 'vr.it' => 1,
1447
- 'vs.it' => 1,
1448
- 'vt.it' => 1,
1449
- 'vv.it' => 1,
1450
- 'je' => 1,
1451
- 'co.je' => 1,
1452
- 'net.je' => 1,
1453
- 'org.je' => 1,
1454
- '*.jm' => 1,
1455
- 'jo' => 1,
1456
- 'com.jo' => 1,
1457
- 'org.jo' => 1,
1458
- 'net.jo' => 1,
1459
- 'edu.jo' => 1,
1460
- 'sch.jo' => 1,
1461
- 'gov.jo' => 1,
1462
- 'mil.jo' => 1,
1463
- 'name.jo' => 1,
1464
- 'jobs' => 1,
1465
- 'jp' => 1,
1466
- 'ac.jp' => 1,
1467
- 'ad.jp' => 1,
1468
- 'co.jp' => 1,
1469
- 'ed.jp' => 1,
1470
- 'go.jp' => 1,
1471
- 'gr.jp' => 1,
1472
- 'lg.jp' => 1,
1473
- 'ne.jp' => 1,
1474
- 'or.jp' => 1,
1475
- 'aichi.jp' => 1,
1476
- 'akita.jp' => 1,
1477
- 'aomori.jp' => 1,
1478
- 'chiba.jp' => 1,
1479
- 'ehime.jp' => 1,
1480
- 'fukui.jp' => 1,
1481
- 'fukuoka.jp' => 1,
1482
- 'fukushima.jp' => 1,
1483
- 'gifu.jp' => 1,
1484
- 'gunma.jp' => 1,
1485
- 'hiroshima.jp' => 1,
1486
- 'hokkaido.jp' => 1,
1487
- 'hyogo.jp' => 1,
1488
- 'ibaraki.jp' => 1,
1489
- 'ishikawa.jp' => 1,
1490
- 'iwate.jp' => 1,
1491
- 'kagawa.jp' => 1,
1492
- 'kagoshima.jp' => 1,
1493
- 'kanagawa.jp' => 1,
1494
- 'kochi.jp' => 1,
1495
- 'kumamoto.jp' => 1,
1496
- 'kyoto.jp' => 1,
1497
- 'mie.jp' => 1,
1498
- 'miyagi.jp' => 1,
1499
- 'miyazaki.jp' => 1,
1500
- 'nagano.jp' => 1,
1501
- 'nagasaki.jp' => 1,
1502
- 'nara.jp' => 1,
1503
- 'niigata.jp' => 1,
1504
- 'oita.jp' => 1,
1505
- 'okayama.jp' => 1,
1506
- 'okinawa.jp' => 1,
1507
- 'osaka.jp' => 1,
1508
- 'saga.jp' => 1,
1509
- 'saitama.jp' => 1,
1510
- 'shiga.jp' => 1,
1511
- 'shimane.jp' => 1,
1512
- 'shizuoka.jp' => 1,
1513
- 'tochigi.jp' => 1,
1514
- 'tokushima.jp' => 1,
1515
- 'tokyo.jp' => 1,
1516
- 'tottori.jp' => 1,
1517
- 'toyama.jp' => 1,
1518
- 'wakayama.jp' => 1,
1519
- 'yamagata.jp' => 1,
1520
- 'yamaguchi.jp' => 1,
1521
- 'yamanashi.jp' => 1,
1522
- '栃木.jp' => 1,
1523
- '愛知.jp' => 1,
1524
- '愛媛.jp' => 1,
1525
- '兵庫.jp' => 1,
1526
- '熊本.jp' => 1,
1527
- '茨城.jp' => 1,
1528
- '北海道.jp' => 1,
1529
- '千葉.jp' => 1,
1530
- '和歌山.jp' => 1,
1531
- '長崎.jp' => 1,
1532
- '長野.jp' => 1,
1533
- '新潟.jp' => 1,
1534
- '青森.jp' => 1,
1535
- '静岡.jp' => 1,
1536
- '東京.jp' => 1,
1537
- '石川.jp' => 1,
1538
- '埼玉.jp' => 1,
1539
- '三重.jp' => 1,
1540
- '京都.jp' => 1,
1541
- '佐賀.jp' => 1,
1542
- '大分.jp' => 1,
1543
- '大阪.jp' => 1,
1544
- '奈良.jp' => 1,
1545
- '宮城.jp' => 1,
1546
- '宮崎.jp' => 1,
1547
- '富山.jp' => 1,
1548
- '山口.jp' => 1,
1549
- '山形.jp' => 1,
1550
- '山梨.jp' => 1,
1551
- '岩手.jp' => 1,
1552
- '岐阜.jp' => 1,
1553
- '岡山.jp' => 1,
1554
- '島根.jp' => 1,
1555
- '広島.jp' => 1,
1556
- '徳島.jp' => 1,
1557
- '沖縄.jp' => 1,
1558
- '滋賀.jp' => 1,
1559
- '神奈川.jp' => 1,
1560
- '福井.jp' => 1,
1561
- '福岡.jp' => 1,
1562
- '福島.jp' => 1,
1563
- '秋田.jp' => 1,
1564
- '群馬.jp' => 1,
1565
- '香川.jp' => 1,
1566
- '高知.jp' => 1,
1567
- '鳥取.jp' => 1,
1568
- '鹿児島.jp' => 1,
1569
- '*.kawasaki.jp' => 1,
1570
- '*.kitakyushu.jp' => 1,
1571
- '*.kobe.jp' => 1,
1572
- '*.nagoya.jp' => 1,
1573
- '*.sapporo.jp' => 1,
1574
- '*.sendai.jp' => 1,
1575
- '*.yokohama.jp' => 1,
1576
- '!city.kawasaki.jp' => 1,
1577
- '!city.kitakyushu.jp' => 1,
1578
- '!city.kobe.jp' => 1,
1579
- '!city.nagoya.jp' => 1,
1580
- '!city.sapporo.jp' => 1,
1581
- '!city.sendai.jp' => 1,
1582
- '!city.yokohama.jp' => 1,
1583
- 'aisai.aichi.jp' => 1,
1584
- 'ama.aichi.jp' => 1,
1585
- 'anjo.aichi.jp' => 1,
1586
- 'asuke.aichi.jp' => 1,
1587
- 'chiryu.aichi.jp' => 1,
1588
- 'chita.aichi.jp' => 1,
1589
- 'fuso.aichi.jp' => 1,
1590
- 'gamagori.aichi.jp' => 1,
1591
- 'handa.aichi.jp' => 1,
1592
- 'hazu.aichi.jp' => 1,
1593
- 'hekinan.aichi.jp' => 1,
1594
- 'higashiura.aichi.jp' => 1,
1595
- 'ichinomiya.aichi.jp' => 1,
1596
- 'inazawa.aichi.jp' => 1,
1597
- 'inuyama.aichi.jp' => 1,
1598
- 'isshiki.aichi.jp' => 1,
1599
- 'iwakura.aichi.jp' => 1,
1600
- 'kanie.aichi.jp' => 1,
1601
- 'kariya.aichi.jp' => 1,
1602
- 'kasugai.aichi.jp' => 1,
1603
- 'kira.aichi.jp' => 1,
1604
- 'kiyosu.aichi.jp' => 1,
1605
- 'komaki.aichi.jp' => 1,
1606
- 'konan.aichi.jp' => 1,
1607
- 'kota.aichi.jp' => 1,
1608
- 'mihama.aichi.jp' => 1,
1609
- 'miyoshi.aichi.jp' => 1,
1610
- 'nishio.aichi.jp' => 1,
1611
- 'nisshin.aichi.jp' => 1,
1612
- 'obu.aichi.jp' => 1,
1613
- 'oguchi.aichi.jp' => 1,
1614
- 'oharu.aichi.jp' => 1,
1615
- 'okazaki.aichi.jp' => 1,
1616
- 'owariasahi.aichi.jp' => 1,
1617
- 'seto.aichi.jp' => 1,
1618
- 'shikatsu.aichi.jp' => 1,
1619
- 'shinshiro.aichi.jp' => 1,
1620
- 'shitara.aichi.jp' => 1,
1621
- 'tahara.aichi.jp' => 1,
1622
- 'takahama.aichi.jp' => 1,
1623
- 'tobishima.aichi.jp' => 1,
1624
- 'toei.aichi.jp' => 1,
1625
- 'togo.aichi.jp' => 1,
1626
- 'tokai.aichi.jp' => 1,
1627
- 'tokoname.aichi.jp' => 1,
1628
- 'toyoake.aichi.jp' => 1,
1629
- 'toyohashi.aichi.jp' => 1,
1630
- 'toyokawa.aichi.jp' => 1,
1631
- 'toyone.aichi.jp' => 1,
1632
- 'toyota.aichi.jp' => 1,
1633
- 'tsushima.aichi.jp' => 1,
1634
- 'yatomi.aichi.jp' => 1,
1635
- 'akita.akita.jp' => 1,
1636
- 'daisen.akita.jp' => 1,
1637
- 'fujisato.akita.jp' => 1,
1638
- 'gojome.akita.jp' => 1,
1639
- 'hachirogata.akita.jp' => 1,
1640
- 'happou.akita.jp' => 1,
1641
- 'higashinaruse.akita.jp' => 1,
1642
- 'honjo.akita.jp' => 1,
1643
- 'honjyo.akita.jp' => 1,
1644
- 'ikawa.akita.jp' => 1,
1645
- 'kamikoani.akita.jp' => 1,
1646
- 'kamioka.akita.jp' => 1,
1647
- 'katagami.akita.jp' => 1,
1648
- 'kazuno.akita.jp' => 1,
1649
- 'kitaakita.akita.jp' => 1,
1650
- 'kosaka.akita.jp' => 1,
1651
- 'kyowa.akita.jp' => 1,
1652
- 'misato.akita.jp' => 1,
1653
- 'mitane.akita.jp' => 1,
1654
- 'moriyoshi.akita.jp' => 1,
1655
- 'nikaho.akita.jp' => 1,
1656
- 'noshiro.akita.jp' => 1,
1657
- 'odate.akita.jp' => 1,
1658
- 'oga.akita.jp' => 1,
1659
- 'ogata.akita.jp' => 1,
1660
- 'semboku.akita.jp' => 1,
1661
- 'yokote.akita.jp' => 1,
1662
- 'yurihonjo.akita.jp' => 1,
1663
- 'aomori.aomori.jp' => 1,
1664
- 'gonohe.aomori.jp' => 1,
1665
- 'hachinohe.aomori.jp' => 1,
1666
- 'hashikami.aomori.jp' => 1,
1667
- 'hiranai.aomori.jp' => 1,
1668
- 'hirosaki.aomori.jp' => 1,
1669
- 'itayanagi.aomori.jp' => 1,
1670
- 'kuroishi.aomori.jp' => 1,
1671
- 'misawa.aomori.jp' => 1,
1672
- 'mutsu.aomori.jp' => 1,
1673
- 'nakadomari.aomori.jp' => 1,
1674
- 'noheji.aomori.jp' => 1,
1675
- 'oirase.aomori.jp' => 1,
1676
- 'owani.aomori.jp' => 1,
1677
- 'rokunohe.aomori.jp' => 1,
1678
- 'sannohe.aomori.jp' => 1,
1679
- 'shichinohe.aomori.jp' => 1,
1680
- 'shingo.aomori.jp' => 1,
1681
- 'takko.aomori.jp' => 1,
1682
- 'towada.aomori.jp' => 1,
1683
- 'tsugaru.aomori.jp' => 1,
1684
- 'tsuruta.aomori.jp' => 1,
1685
- 'abiko.chiba.jp' => 1,
1686
- 'asahi.chiba.jp' => 1,
1687
- 'chonan.chiba.jp' => 1,
1688
- 'chosei.chiba.jp' => 1,
1689
- 'choshi.chiba.jp' => 1,
1690
- 'chuo.chiba.jp' => 1,
1691
- 'funabashi.chiba.jp' => 1,
1692
- 'futtsu.chiba.jp' => 1,
1693
- 'hanamigawa.chiba.jp' => 1,
1694
- 'ichihara.chiba.jp' => 1,
1695
- 'ichikawa.chiba.jp' => 1,
1696
- 'ichinomiya.chiba.jp' => 1,
1697
- 'inzai.chiba.jp' => 1,
1698
- 'isumi.chiba.jp' => 1,
1699
- 'kamagaya.chiba.jp' => 1,
1700
- 'kamogawa.chiba.jp' => 1,
1701
- 'kashiwa.chiba.jp' => 1,
1702
- 'katori.chiba.jp' => 1,
1703
- 'katsuura.chiba.jp' => 1,
1704
- 'kimitsu.chiba.jp' => 1,
1705
- 'kisarazu.chiba.jp' => 1,
1706
- 'kozaki.chiba.jp' => 1,
1707
- 'kujukuri.chiba.jp' => 1,
1708
- 'kyonan.chiba.jp' => 1,
1709
- 'matsudo.chiba.jp' => 1,
1710
- 'midori.chiba.jp' => 1,
1711
- 'mihama.chiba.jp' => 1,
1712
- 'minamiboso.chiba.jp' => 1,
1713
- 'mobara.chiba.jp' => 1,
1714
- 'mutsuzawa.chiba.jp' => 1,
1715
- 'nagara.chiba.jp' => 1,
1716
- 'nagareyama.chiba.jp' => 1,
1717
- 'narashino.chiba.jp' => 1,
1718
- 'narita.chiba.jp' => 1,
1719
- 'noda.chiba.jp' => 1,
1720
- 'oamishirasato.chiba.jp' => 1,
1721
- 'omigawa.chiba.jp' => 1,
1722
- 'onjuku.chiba.jp' => 1,
1723
- 'otaki.chiba.jp' => 1,
1724
- 'sakae.chiba.jp' => 1,
1725
- 'sakura.chiba.jp' => 1,
1726
- 'shimofusa.chiba.jp' => 1,
1727
- 'shirako.chiba.jp' => 1,
1728
- 'shiroi.chiba.jp' => 1,
1729
- 'shisui.chiba.jp' => 1,
1730
- 'sodegaura.chiba.jp' => 1,
1731
- 'sosa.chiba.jp' => 1,
1732
- 'tako.chiba.jp' => 1,
1733
- 'tateyama.chiba.jp' => 1,
1734
- 'togane.chiba.jp' => 1,
1735
- 'tohnosho.chiba.jp' => 1,
1736
- 'tomisato.chiba.jp' => 1,
1737
- 'urayasu.chiba.jp' => 1,
1738
- 'yachimata.chiba.jp' => 1,
1739
- 'yachiyo.chiba.jp' => 1,
1740
- 'yokaichiba.chiba.jp' => 1,
1741
- 'yokoshibahikari.chiba.jp' => 1,
1742
- 'yotsukaido.chiba.jp' => 1,
1743
- 'ainan.ehime.jp' => 1,
1744
- 'honai.ehime.jp' => 1,
1745
- 'ikata.ehime.jp' => 1,
1746
- 'imabari.ehime.jp' => 1,
1747
- 'iyo.ehime.jp' => 1,
1748
- 'kamijima.ehime.jp' => 1,
1749
- 'kihoku.ehime.jp' => 1,
1750
- 'kumakogen.ehime.jp' => 1,
1751
- 'masaki.ehime.jp' => 1,
1752
- 'matsuno.ehime.jp' => 1,
1753
- 'matsuyama.ehime.jp' => 1,
1754
- 'namikata.ehime.jp' => 1,
1755
- 'niihama.ehime.jp' => 1,
1756
- 'ozu.ehime.jp' => 1,
1757
- 'saijo.ehime.jp' => 1,
1758
- 'seiyo.ehime.jp' => 1,
1759
- 'shikokuchuo.ehime.jp' => 1,
1760
- 'tobe.ehime.jp' => 1,
1761
- 'toon.ehime.jp' => 1,
1762
- 'uchiko.ehime.jp' => 1,
1763
- 'uwajima.ehime.jp' => 1,
1764
- 'yawatahama.ehime.jp' => 1,
1765
- 'echizen.fukui.jp' => 1,
1766
- 'eiheiji.fukui.jp' => 1,
1767
- 'fukui.fukui.jp' => 1,
1768
- 'ikeda.fukui.jp' => 1,
1769
- 'katsuyama.fukui.jp' => 1,
1770
- 'mihama.fukui.jp' => 1,
1771
- 'minamiechizen.fukui.jp' => 1,
1772
- 'obama.fukui.jp' => 1,
1773
- 'ohi.fukui.jp' => 1,
1774
- 'ono.fukui.jp' => 1,
1775
- 'sabae.fukui.jp' => 1,
1776
- 'sakai.fukui.jp' => 1,
1777
- 'takahama.fukui.jp' => 1,
1778
- 'tsuruga.fukui.jp' => 1,
1779
- 'wakasa.fukui.jp' => 1,
1780
- 'ashiya.fukuoka.jp' => 1,
1781
- 'buzen.fukuoka.jp' => 1,
1782
- 'chikugo.fukuoka.jp' => 1,
1783
- 'chikuho.fukuoka.jp' => 1,
1784
- 'chikujo.fukuoka.jp' => 1,
1785
- 'chikushino.fukuoka.jp' => 1,
1786
- 'chikuzen.fukuoka.jp' => 1,
1787
- 'chuo.fukuoka.jp' => 1,
1788
- 'dazaifu.fukuoka.jp' => 1,
1789
- 'fukuchi.fukuoka.jp' => 1,
1790
- 'hakata.fukuoka.jp' => 1,
1791
- 'higashi.fukuoka.jp' => 1,
1792
- 'hirokawa.fukuoka.jp' => 1,
1793
- 'hisayama.fukuoka.jp' => 1,
1794
- 'iizuka.fukuoka.jp' => 1,
1795
- 'inatsuki.fukuoka.jp' => 1,
1796
- 'kaho.fukuoka.jp' => 1,
1797
- 'kasuga.fukuoka.jp' => 1,
1798
- 'kasuya.fukuoka.jp' => 1,
1799
- 'kawara.fukuoka.jp' => 1,
1800
- 'keisen.fukuoka.jp' => 1,
1801
- 'koga.fukuoka.jp' => 1,
1802
- 'kurate.fukuoka.jp' => 1,
1803
- 'kurogi.fukuoka.jp' => 1,
1804
- 'kurume.fukuoka.jp' => 1,
1805
- 'minami.fukuoka.jp' => 1,
1806
- 'miyako.fukuoka.jp' => 1,
1807
- 'miyama.fukuoka.jp' => 1,
1808
- 'miyawaka.fukuoka.jp' => 1,
1809
- 'mizumaki.fukuoka.jp' => 1,
1810
- 'munakata.fukuoka.jp' => 1,
1811
- 'nakagawa.fukuoka.jp' => 1,
1812
- 'nakama.fukuoka.jp' => 1,
1813
- 'nishi.fukuoka.jp' => 1,
1814
- 'nogata.fukuoka.jp' => 1,
1815
- 'ogori.fukuoka.jp' => 1,
1816
- 'okagaki.fukuoka.jp' => 1,
1817
- 'okawa.fukuoka.jp' => 1,
1818
- 'oki.fukuoka.jp' => 1,
1819
- 'omuta.fukuoka.jp' => 1,
1820
- 'onga.fukuoka.jp' => 1,
1821
- 'onojo.fukuoka.jp' => 1,
1822
- 'oto.fukuoka.jp' => 1,
1823
- 'saigawa.fukuoka.jp' => 1,
1824
- 'sasaguri.fukuoka.jp' => 1,
1825
- 'shingu.fukuoka.jp' => 1,
1826
- 'shinyoshitomi.fukuoka.jp' => 1,
1827
- 'shonai.fukuoka.jp' => 1,
1828
- 'soeda.fukuoka.jp' => 1,
1829
- 'sue.fukuoka.jp' => 1,
1830
- 'tachiarai.fukuoka.jp' => 1,
1831
- 'tagawa.fukuoka.jp' => 1,
1832
- 'takata.fukuoka.jp' => 1,
1833
- 'toho.fukuoka.jp' => 1,
1834
- 'toyotsu.fukuoka.jp' => 1,
1835
- 'tsuiki.fukuoka.jp' => 1,
1836
- 'ukiha.fukuoka.jp' => 1,
1837
- 'umi.fukuoka.jp' => 1,
1838
- 'usui.fukuoka.jp' => 1,
1839
- 'yamada.fukuoka.jp' => 1,
1840
- 'yame.fukuoka.jp' => 1,
1841
- 'yanagawa.fukuoka.jp' => 1,
1842
- 'yukuhashi.fukuoka.jp' => 1,
1843
- 'aizubange.fukushima.jp' => 1,
1844
- 'aizumisato.fukushima.jp' => 1,
1845
- 'aizuwakamatsu.fukushima.jp' => 1,
1846
- 'asakawa.fukushima.jp' => 1,
1847
- 'bandai.fukushima.jp' => 1,
1848
- 'date.fukushima.jp' => 1,
1849
- 'fukushima.fukushima.jp' => 1,
1850
- 'furudono.fukushima.jp' => 1,
1851
- 'futaba.fukushima.jp' => 1,
1852
- 'hanawa.fukushima.jp' => 1,
1853
- 'higashi.fukushima.jp' => 1,
1854
- 'hirata.fukushima.jp' => 1,
1855
- 'hirono.fukushima.jp' => 1,
1856
- 'iitate.fukushima.jp' => 1,
1857
- 'inawashiro.fukushima.jp' => 1,
1858
- 'ishikawa.fukushima.jp' => 1,
1859
- 'iwaki.fukushima.jp' => 1,
1860
- 'izumizaki.fukushima.jp' => 1,
1861
- 'kagamiishi.fukushima.jp' => 1,
1862
- 'kaneyama.fukushima.jp' => 1,
1863
- 'kawamata.fukushima.jp' => 1,
1864
- 'kitakata.fukushima.jp' => 1,
1865
- 'kitashiobara.fukushima.jp' => 1,
1866
- 'koori.fukushima.jp' => 1,
1867
- 'koriyama.fukushima.jp' => 1,
1868
- 'kunimi.fukushima.jp' => 1,
1869
- 'miharu.fukushima.jp' => 1,
1870
- 'mishima.fukushima.jp' => 1,
1871
- 'namie.fukushima.jp' => 1,
1872
- 'nango.fukushima.jp' => 1,
1873
- 'nishiaizu.fukushima.jp' => 1,
1874
- 'nishigo.fukushima.jp' => 1,
1875
- 'okuma.fukushima.jp' => 1,
1876
- 'omotego.fukushima.jp' => 1,
1877
- 'ono.fukushima.jp' => 1,
1878
- 'otama.fukushima.jp' => 1,
1879
- 'samegawa.fukushima.jp' => 1,
1880
- 'shimogo.fukushima.jp' => 1,
1881
- 'shirakawa.fukushima.jp' => 1,
1882
- 'showa.fukushima.jp' => 1,
1883
- 'soma.fukushima.jp' => 1,
1884
- 'sukagawa.fukushima.jp' => 1,
1885
- 'taishin.fukushima.jp' => 1,
1886
- 'tamakawa.fukushima.jp' => 1,
1887
- 'tanagura.fukushima.jp' => 1,
1888
- 'tenei.fukushima.jp' => 1,
1889
- 'yabuki.fukushima.jp' => 1,
1890
- 'yamato.fukushima.jp' => 1,
1891
- 'yamatsuri.fukushima.jp' => 1,
1892
- 'yanaizu.fukushima.jp' => 1,
1893
- 'yugawa.fukushima.jp' => 1,
1894
- 'anpachi.gifu.jp' => 1,
1895
- 'ena.gifu.jp' => 1,
1896
- 'gifu.gifu.jp' => 1,
1897
- 'ginan.gifu.jp' => 1,
1898
- 'godo.gifu.jp' => 1,
1899
- 'gujo.gifu.jp' => 1,
1900
- 'hashima.gifu.jp' => 1,
1901
- 'hichiso.gifu.jp' => 1,
1902
- 'hida.gifu.jp' => 1,
1903
- 'higashishirakawa.gifu.jp' => 1,
1904
- 'ibigawa.gifu.jp' => 1,
1905
- 'ikeda.gifu.jp' => 1,
1906
- 'kakamigahara.gifu.jp' => 1,
1907
- 'kani.gifu.jp' => 1,
1908
- 'kasahara.gifu.jp' => 1,
1909
- 'kasamatsu.gifu.jp' => 1,
1910
- 'kawaue.gifu.jp' => 1,
1911
- 'kitagata.gifu.jp' => 1,
1912
- 'mino.gifu.jp' => 1,
1913
- 'minokamo.gifu.jp' => 1,
1914
- 'mitake.gifu.jp' => 1,
1915
- 'mizunami.gifu.jp' => 1,
1916
- 'motosu.gifu.jp' => 1,
1917
- 'nakatsugawa.gifu.jp' => 1,
1918
- 'ogaki.gifu.jp' => 1,
1919
- 'sakahogi.gifu.jp' => 1,
1920
- 'seki.gifu.jp' => 1,
1921
- 'sekigahara.gifu.jp' => 1,
1922
- 'shirakawa.gifu.jp' => 1,
1923
- 'tajimi.gifu.jp' => 1,
1924
- 'takayama.gifu.jp' => 1,
1925
- 'tarui.gifu.jp' => 1,
1926
- 'toki.gifu.jp' => 1,
1927
- 'tomika.gifu.jp' => 1,
1928
- 'wanouchi.gifu.jp' => 1,
1929
- 'yamagata.gifu.jp' => 1,
1930
- 'yaotsu.gifu.jp' => 1,
1931
- 'yoro.gifu.jp' => 1,
1932
- 'annaka.gunma.jp' => 1,
1933
- 'chiyoda.gunma.jp' => 1,
1934
- 'fujioka.gunma.jp' => 1,
1935
- 'higashiagatsuma.gunma.jp' => 1,
1936
- 'isesaki.gunma.jp' => 1,
1937
- 'itakura.gunma.jp' => 1,
1938
- 'kanna.gunma.jp' => 1,
1939
- 'kanra.gunma.jp' => 1,
1940
- 'katashina.gunma.jp' => 1,
1941
- 'kawaba.gunma.jp' => 1,
1942
- 'kiryu.gunma.jp' => 1,
1943
- 'kusatsu.gunma.jp' => 1,
1944
- 'maebashi.gunma.jp' => 1,
1945
- 'meiwa.gunma.jp' => 1,
1946
- 'midori.gunma.jp' => 1,
1947
- 'minakami.gunma.jp' => 1,
1948
- 'naganohara.gunma.jp' => 1,
1949
- 'nakanojo.gunma.jp' => 1,
1950
- 'nanmoku.gunma.jp' => 1,
1951
- 'numata.gunma.jp' => 1,
1952
- 'oizumi.gunma.jp' => 1,
1953
- 'ora.gunma.jp' => 1,
1954
- 'ota.gunma.jp' => 1,
1955
- 'shibukawa.gunma.jp' => 1,
1956
- 'shimonita.gunma.jp' => 1,
1957
- 'shinto.gunma.jp' => 1,
1958
- 'showa.gunma.jp' => 1,
1959
- 'takasaki.gunma.jp' => 1,
1960
- 'takayama.gunma.jp' => 1,
1961
- 'tamamura.gunma.jp' => 1,
1962
- 'tatebayashi.gunma.jp' => 1,
1963
- 'tomioka.gunma.jp' => 1,
1964
- 'tsukiyono.gunma.jp' => 1,
1965
- 'tsumagoi.gunma.jp' => 1,
1966
- 'ueno.gunma.jp' => 1,
1967
- 'yoshioka.gunma.jp' => 1,
1968
- 'asaminami.hiroshima.jp' => 1,
1969
- 'daiwa.hiroshima.jp' => 1,
1970
- 'etajima.hiroshima.jp' => 1,
1971
- 'fuchu.hiroshima.jp' => 1,
1972
- 'fukuyama.hiroshima.jp' => 1,
1973
- 'hatsukaichi.hiroshima.jp' => 1,
1974
- 'higashihiroshima.hiroshima.jp' => 1,
1975
- 'hongo.hiroshima.jp' => 1,
1976
- 'jinsekikogen.hiroshima.jp' => 1,
1977
- 'kaita.hiroshima.jp' => 1,
1978
- 'kui.hiroshima.jp' => 1,
1979
- 'kumano.hiroshima.jp' => 1,
1980
- 'kure.hiroshima.jp' => 1,
1981
- 'mihara.hiroshima.jp' => 1,
1982
- 'miyoshi.hiroshima.jp' => 1,
1983
- 'naka.hiroshima.jp' => 1,
1984
- 'onomichi.hiroshima.jp' => 1,
1985
- 'osakikamijima.hiroshima.jp' => 1,
1986
- 'otake.hiroshima.jp' => 1,
1987
- 'saka.hiroshima.jp' => 1,
1988
- 'sera.hiroshima.jp' => 1,
1989
- 'seranishi.hiroshima.jp' => 1,
1990
- 'shinichi.hiroshima.jp' => 1,
1991
- 'shobara.hiroshima.jp' => 1,
1992
- 'takehara.hiroshima.jp' => 1,
1993
- 'abashiri.hokkaido.jp' => 1,
1994
- 'abira.hokkaido.jp' => 1,
1995
- 'aibetsu.hokkaido.jp' => 1,
1996
- 'akabira.hokkaido.jp' => 1,
1997
- 'akkeshi.hokkaido.jp' => 1,
1998
- 'asahikawa.hokkaido.jp' => 1,
1999
- 'ashibetsu.hokkaido.jp' => 1,
2000
- 'ashoro.hokkaido.jp' => 1,
2001
- 'assabu.hokkaido.jp' => 1,
2002
- 'atsuma.hokkaido.jp' => 1,
2003
- 'bibai.hokkaido.jp' => 1,
2004
- 'biei.hokkaido.jp' => 1,
2005
- 'bifuka.hokkaido.jp' => 1,
2006
- 'bihoro.hokkaido.jp' => 1,
2007
- 'biratori.hokkaido.jp' => 1,
2008
- 'chippubetsu.hokkaido.jp' => 1,
2009
- 'chitose.hokkaido.jp' => 1,
2010
- 'date.hokkaido.jp' => 1,
2011
- 'ebetsu.hokkaido.jp' => 1,
2012
- 'embetsu.hokkaido.jp' => 1,
2013
- 'eniwa.hokkaido.jp' => 1,
2014
- 'erimo.hokkaido.jp' => 1,
2015
- 'esan.hokkaido.jp' => 1,
2016
- 'esashi.hokkaido.jp' => 1,
2017
- 'fukagawa.hokkaido.jp' => 1,
2018
- 'fukushima.hokkaido.jp' => 1,
2019
- 'furano.hokkaido.jp' => 1,
2020
- 'furubira.hokkaido.jp' => 1,
2021
- 'haboro.hokkaido.jp' => 1,
2022
- 'hakodate.hokkaido.jp' => 1,
2023
- 'hamatonbetsu.hokkaido.jp' => 1,
2024
- 'hidaka.hokkaido.jp' => 1,
2025
- 'higashikagura.hokkaido.jp' => 1,
2026
- 'higashikawa.hokkaido.jp' => 1,
2027
- 'hiroo.hokkaido.jp' => 1,
2028
- 'hokuryu.hokkaido.jp' => 1,
2029
- 'hokuto.hokkaido.jp' => 1,
2030
- 'honbetsu.hokkaido.jp' => 1,
2031
- 'horokanai.hokkaido.jp' => 1,
2032
- 'horonobe.hokkaido.jp' => 1,
2033
- 'ikeda.hokkaido.jp' => 1,
2034
- 'imakane.hokkaido.jp' => 1,
2035
- 'ishikari.hokkaido.jp' => 1,
2036
- 'iwamizawa.hokkaido.jp' => 1,
2037
- 'iwanai.hokkaido.jp' => 1,
2038
- 'kamifurano.hokkaido.jp' => 1,
2039
- 'kamikawa.hokkaido.jp' => 1,
2040
- 'kamishihoro.hokkaido.jp' => 1,
2041
- 'kamisunagawa.hokkaido.jp' => 1,
2042
- 'kamoenai.hokkaido.jp' => 1,
2043
- 'kayabe.hokkaido.jp' => 1,
2044
- 'kembuchi.hokkaido.jp' => 1,
2045
- 'kikonai.hokkaido.jp' => 1,
2046
- 'kimobetsu.hokkaido.jp' => 1,
2047
- 'kitahiroshima.hokkaido.jp' => 1,
2048
- 'kitami.hokkaido.jp' => 1,
2049
- 'kiyosato.hokkaido.jp' => 1,
2050
- 'koshimizu.hokkaido.jp' => 1,
2051
- 'kunneppu.hokkaido.jp' => 1,
2052
- 'kuriyama.hokkaido.jp' => 1,
2053
- 'kuromatsunai.hokkaido.jp' => 1,
2054
- 'kushiro.hokkaido.jp' => 1,
2055
- 'kutchan.hokkaido.jp' => 1,
2056
- 'kyowa.hokkaido.jp' => 1,
2057
- 'mashike.hokkaido.jp' => 1,
2058
- 'matsumae.hokkaido.jp' => 1,
2059
- 'mikasa.hokkaido.jp' => 1,
2060
- 'minamifurano.hokkaido.jp' => 1,
2061
- 'mombetsu.hokkaido.jp' => 1,
2062
- 'moseushi.hokkaido.jp' => 1,
2063
- 'mukawa.hokkaido.jp' => 1,
2064
- 'muroran.hokkaido.jp' => 1,
2065
- 'naie.hokkaido.jp' => 1,
2066
- 'nakagawa.hokkaido.jp' => 1,
2067
- 'nakasatsunai.hokkaido.jp' => 1,
2068
- 'nakatombetsu.hokkaido.jp' => 1,
2069
- 'nanae.hokkaido.jp' => 1,
2070
- 'nanporo.hokkaido.jp' => 1,
2071
- 'nayoro.hokkaido.jp' => 1,
2072
- 'nemuro.hokkaido.jp' => 1,
2073
- 'niikappu.hokkaido.jp' => 1,
2074
- 'niki.hokkaido.jp' => 1,
2075
- 'nishiokoppe.hokkaido.jp' => 1,
2076
- 'noboribetsu.hokkaido.jp' => 1,
2077
- 'numata.hokkaido.jp' => 1,
2078
- 'obihiro.hokkaido.jp' => 1,
2079
- 'obira.hokkaido.jp' => 1,
2080
- 'oketo.hokkaido.jp' => 1,
2081
- 'okoppe.hokkaido.jp' => 1,
2082
- 'otaru.hokkaido.jp' => 1,
2083
- 'otobe.hokkaido.jp' => 1,
2084
- 'otofuke.hokkaido.jp' => 1,
2085
- 'otoineppu.hokkaido.jp' => 1,
2086
- 'oumu.hokkaido.jp' => 1,
2087
- 'ozora.hokkaido.jp' => 1,
2088
- 'pippu.hokkaido.jp' => 1,
2089
- 'rankoshi.hokkaido.jp' => 1,
2090
- 'rebun.hokkaido.jp' => 1,
2091
- 'rikubetsu.hokkaido.jp' => 1,
2092
- 'rishiri.hokkaido.jp' => 1,
2093
- 'rishirifuji.hokkaido.jp' => 1,
2094
- 'saroma.hokkaido.jp' => 1,
2095
- 'sarufutsu.hokkaido.jp' => 1,
2096
- 'shakotan.hokkaido.jp' => 1,
2097
- 'shari.hokkaido.jp' => 1,
2098
- 'shibecha.hokkaido.jp' => 1,
2099
- 'shibetsu.hokkaido.jp' => 1,
2100
- 'shikabe.hokkaido.jp' => 1,
2101
- 'shikaoi.hokkaido.jp' => 1,
2102
- 'shimamaki.hokkaido.jp' => 1,
2103
- 'shimizu.hokkaido.jp' => 1,
2104
- 'shimokawa.hokkaido.jp' => 1,
2105
- 'shinshinotsu.hokkaido.jp' => 1,
2106
- 'shintoku.hokkaido.jp' => 1,
2107
- 'shiranuka.hokkaido.jp' => 1,
2108
- 'shiraoi.hokkaido.jp' => 1,
2109
- 'shiriuchi.hokkaido.jp' => 1,
2110
- 'sobetsu.hokkaido.jp' => 1,
2111
- 'sunagawa.hokkaido.jp' => 1,
2112
- 'taiki.hokkaido.jp' => 1,
2113
- 'takasu.hokkaido.jp' => 1,
2114
- 'takikawa.hokkaido.jp' => 1,
2115
- 'takinoue.hokkaido.jp' => 1,
2116
- 'teshikaga.hokkaido.jp' => 1,
2117
- 'tobetsu.hokkaido.jp' => 1,
2118
- 'tohma.hokkaido.jp' => 1,
2119
- 'tomakomai.hokkaido.jp' => 1,
2120
- 'tomari.hokkaido.jp' => 1,
2121
- 'toya.hokkaido.jp' => 1,
2122
- 'toyako.hokkaido.jp' => 1,
2123
- 'toyotomi.hokkaido.jp' => 1,
2124
- 'toyoura.hokkaido.jp' => 1,
2125
- 'tsubetsu.hokkaido.jp' => 1,
2126
- 'tsukigata.hokkaido.jp' => 1,
2127
- 'urakawa.hokkaido.jp' => 1,
2128
- 'urausu.hokkaido.jp' => 1,
2129
- 'uryu.hokkaido.jp' => 1,
2130
- 'utashinai.hokkaido.jp' => 1,
2131
- 'wakkanai.hokkaido.jp' => 1,
2132
- 'wassamu.hokkaido.jp' => 1,
2133
- 'yakumo.hokkaido.jp' => 1,
2134
- 'yoichi.hokkaido.jp' => 1,
2135
- 'aioi.hyogo.jp' => 1,
2136
- 'akashi.hyogo.jp' => 1,
2137
- 'ako.hyogo.jp' => 1,
2138
- 'amagasaki.hyogo.jp' => 1,
2139
- 'aogaki.hyogo.jp' => 1,
2140
- 'asago.hyogo.jp' => 1,
2141
- 'ashiya.hyogo.jp' => 1,
2142
- 'awaji.hyogo.jp' => 1,
2143
- 'fukusaki.hyogo.jp' => 1,
2144
- 'goshiki.hyogo.jp' => 1,
2145
- 'harima.hyogo.jp' => 1,
2146
- 'himeji.hyogo.jp' => 1,
2147
- 'ichikawa.hyogo.jp' => 1,
2148
- 'inagawa.hyogo.jp' => 1,
2149
- 'itami.hyogo.jp' => 1,
2150
- 'kakogawa.hyogo.jp' => 1,
2151
- 'kamigori.hyogo.jp' => 1,
2152
- 'kamikawa.hyogo.jp' => 1,
2153
- 'kasai.hyogo.jp' => 1,
2154
- 'kasuga.hyogo.jp' => 1,
2155
- 'kawanishi.hyogo.jp' => 1,
2156
- 'miki.hyogo.jp' => 1,
2157
- 'minamiawaji.hyogo.jp' => 1,
2158
- 'nishinomiya.hyogo.jp' => 1,
2159
- 'nishiwaki.hyogo.jp' => 1,
2160
- 'ono.hyogo.jp' => 1,
2161
- 'sanda.hyogo.jp' => 1,
2162
- 'sannan.hyogo.jp' => 1,
2163
- 'sasayama.hyogo.jp' => 1,
2164
- 'sayo.hyogo.jp' => 1,
2165
- 'shingu.hyogo.jp' => 1,
2166
- 'shinonsen.hyogo.jp' => 1,
2167
- 'shiso.hyogo.jp' => 1,
2168
- 'sumoto.hyogo.jp' => 1,
2169
- 'taishi.hyogo.jp' => 1,
2170
- 'taka.hyogo.jp' => 1,
2171
- 'takarazuka.hyogo.jp' => 1,
2172
- 'takasago.hyogo.jp' => 1,
2173
- 'takino.hyogo.jp' => 1,
2174
- 'tamba.hyogo.jp' => 1,
2175
- 'tatsuno.hyogo.jp' => 1,
2176
- 'toyooka.hyogo.jp' => 1,
2177
- 'yabu.hyogo.jp' => 1,
2178
- 'yashiro.hyogo.jp' => 1,
2179
- 'yoka.hyogo.jp' => 1,
2180
- 'yokawa.hyogo.jp' => 1,
2181
- 'ami.ibaraki.jp' => 1,
2182
- 'asahi.ibaraki.jp' => 1,
2183
- 'bando.ibaraki.jp' => 1,
2184
- 'chikusei.ibaraki.jp' => 1,
2185
- 'daigo.ibaraki.jp' => 1,
2186
- 'fujishiro.ibaraki.jp' => 1,
2187
- 'hitachi.ibaraki.jp' => 1,
2188
- 'hitachinaka.ibaraki.jp' => 1,
2189
- 'hitachiomiya.ibaraki.jp' => 1,
2190
- 'hitachiota.ibaraki.jp' => 1,
2191
- 'ibaraki.ibaraki.jp' => 1,
2192
- 'ina.ibaraki.jp' => 1,
2193
- 'inashiki.ibaraki.jp' => 1,
2194
- 'itako.ibaraki.jp' => 1,
2195
- 'iwama.ibaraki.jp' => 1,
2196
- 'joso.ibaraki.jp' => 1,
2197
- 'kamisu.ibaraki.jp' => 1,
2198
- 'kasama.ibaraki.jp' => 1,
2199
- 'kashima.ibaraki.jp' => 1,
2200
- 'kasumigaura.ibaraki.jp' => 1,
2201
- 'koga.ibaraki.jp' => 1,
2202
- 'miho.ibaraki.jp' => 1,
2203
- 'mito.ibaraki.jp' => 1,
2204
- 'moriya.ibaraki.jp' => 1,
2205
- 'naka.ibaraki.jp' => 1,
2206
- 'namegata.ibaraki.jp' => 1,
2207
- 'oarai.ibaraki.jp' => 1,
2208
- 'ogawa.ibaraki.jp' => 1,
2209
- 'omitama.ibaraki.jp' => 1,
2210
- 'ryugasaki.ibaraki.jp' => 1,
2211
- 'sakai.ibaraki.jp' => 1,
2212
- 'sakuragawa.ibaraki.jp' => 1,
2213
- 'shimodate.ibaraki.jp' => 1,
2214
- 'shimotsuma.ibaraki.jp' => 1,
2215
- 'shirosato.ibaraki.jp' => 1,
2216
- 'sowa.ibaraki.jp' => 1,
2217
- 'suifu.ibaraki.jp' => 1,
2218
- 'takahagi.ibaraki.jp' => 1,
2219
- 'tamatsukuri.ibaraki.jp' => 1,
2220
- 'tokai.ibaraki.jp' => 1,
2221
- 'tomobe.ibaraki.jp' => 1,
2222
- 'tone.ibaraki.jp' => 1,
2223
- 'toride.ibaraki.jp' => 1,
2224
- 'tsuchiura.ibaraki.jp' => 1,
2225
- 'tsukuba.ibaraki.jp' => 1,
2226
- 'uchihara.ibaraki.jp' => 1,
2227
- 'ushiku.ibaraki.jp' => 1,
2228
- 'yachiyo.ibaraki.jp' => 1,
2229
- 'yamagata.ibaraki.jp' => 1,
2230
- 'yawara.ibaraki.jp' => 1,
2231
- 'yuki.ibaraki.jp' => 1,
2232
- 'anamizu.ishikawa.jp' => 1,
2233
- 'hakui.ishikawa.jp' => 1,
2234
- 'hakusan.ishikawa.jp' => 1,
2235
- 'kaga.ishikawa.jp' => 1,
2236
- 'kahoku.ishikawa.jp' => 1,
2237
- 'kanazawa.ishikawa.jp' => 1,
2238
- 'kawakita.ishikawa.jp' => 1,
2239
- 'komatsu.ishikawa.jp' => 1,
2240
- 'nakanoto.ishikawa.jp' => 1,
2241
- 'nanao.ishikawa.jp' => 1,
2242
- 'nomi.ishikawa.jp' => 1,
2243
- 'nonoichi.ishikawa.jp' => 1,
2244
- 'noto.ishikawa.jp' => 1,
2245
- 'shika.ishikawa.jp' => 1,
2246
- 'suzu.ishikawa.jp' => 1,
2247
- 'tsubata.ishikawa.jp' => 1,
2248
- 'tsurugi.ishikawa.jp' => 1,
2249
- 'uchinada.ishikawa.jp' => 1,
2250
- 'wajima.ishikawa.jp' => 1,
2251
- 'fudai.iwate.jp' => 1,
2252
- 'fujisawa.iwate.jp' => 1,
2253
- 'hanamaki.iwate.jp' => 1,
2254
- 'hiraizumi.iwate.jp' => 1,
2255
- 'hirono.iwate.jp' => 1,
2256
- 'ichinohe.iwate.jp' => 1,
2257
- 'ichinoseki.iwate.jp' => 1,
2258
- 'iwaizumi.iwate.jp' => 1,
2259
- 'iwate.iwate.jp' => 1,
2260
- 'joboji.iwate.jp' => 1,
2261
- 'kamaishi.iwate.jp' => 1,
2262
- 'kanegasaki.iwate.jp' => 1,
2263
- 'karumai.iwate.jp' => 1,
2264
- 'kawai.iwate.jp' => 1,
2265
- 'kitakami.iwate.jp' => 1,
2266
- 'kuji.iwate.jp' => 1,
2267
- 'kunohe.iwate.jp' => 1,
2268
- 'kuzumaki.iwate.jp' => 1,
2269
- 'miyako.iwate.jp' => 1,
2270
- 'mizusawa.iwate.jp' => 1,
2271
- 'morioka.iwate.jp' => 1,
2272
- 'ninohe.iwate.jp' => 1,
2273
- 'noda.iwate.jp' => 1,
2274
- 'ofunato.iwate.jp' => 1,
2275
- 'oshu.iwate.jp' => 1,
2276
- 'otsuchi.iwate.jp' => 1,
2277
- 'rikuzentakata.iwate.jp' => 1,
2278
- 'shiwa.iwate.jp' => 1,
2279
- 'shizukuishi.iwate.jp' => 1,
2280
- 'sumita.iwate.jp' => 1,
2281
- 'tanohata.iwate.jp' => 1,
2282
- 'tono.iwate.jp' => 1,
2283
- 'yahaba.iwate.jp' => 1,
2284
- 'yamada.iwate.jp' => 1,
2285
- 'ayagawa.kagawa.jp' => 1,
2286
- 'higashikagawa.kagawa.jp' => 1,
2287
- 'kanonji.kagawa.jp' => 1,
2288
- 'kotohira.kagawa.jp' => 1,
2289
- 'manno.kagawa.jp' => 1,
2290
- 'marugame.kagawa.jp' => 1,
2291
- 'mitoyo.kagawa.jp' => 1,
2292
- 'naoshima.kagawa.jp' => 1,
2293
- 'sanuki.kagawa.jp' => 1,
2294
- 'tadotsu.kagawa.jp' => 1,
2295
- 'takamatsu.kagawa.jp' => 1,
2296
- 'tonosho.kagawa.jp' => 1,
2297
- 'uchinomi.kagawa.jp' => 1,
2298
- 'utazu.kagawa.jp' => 1,
2299
- 'zentsuji.kagawa.jp' => 1,
2300
- 'akune.kagoshima.jp' => 1,
2301
- 'amami.kagoshima.jp' => 1,
2302
- 'hioki.kagoshima.jp' => 1,
2303
- 'isa.kagoshima.jp' => 1,
2304
- 'isen.kagoshima.jp' => 1,
2305
- 'izumi.kagoshima.jp' => 1,
2306
- 'kagoshima.kagoshima.jp' => 1,
2307
- 'kanoya.kagoshima.jp' => 1,
2308
- 'kawanabe.kagoshima.jp' => 1,
2309
- 'kinko.kagoshima.jp' => 1,
2310
- 'kouyama.kagoshima.jp' => 1,
2311
- 'makurazaki.kagoshima.jp' => 1,
2312
- 'matsumoto.kagoshima.jp' => 1,
2313
- 'minamitane.kagoshima.jp' => 1,
2314
- 'nakatane.kagoshima.jp' => 1,
2315
- 'nishinoomote.kagoshima.jp' => 1,
2316
- 'satsumasendai.kagoshima.jp' => 1,
2317
- 'soo.kagoshima.jp' => 1,
2318
- 'tarumizu.kagoshima.jp' => 1,
2319
- 'yusui.kagoshima.jp' => 1,
2320
- 'aikawa.kanagawa.jp' => 1,
2321
- 'atsugi.kanagawa.jp' => 1,
2322
- 'ayase.kanagawa.jp' => 1,
2323
- 'chigasaki.kanagawa.jp' => 1,
2324
- 'ebina.kanagawa.jp' => 1,
2325
- 'fujisawa.kanagawa.jp' => 1,
2326
- 'hadano.kanagawa.jp' => 1,
2327
- 'hakone.kanagawa.jp' => 1,
2328
- 'hiratsuka.kanagawa.jp' => 1,
2329
- 'isehara.kanagawa.jp' => 1,
2330
- 'kaisei.kanagawa.jp' => 1,
2331
- 'kamakura.kanagawa.jp' => 1,
2332
- 'kiyokawa.kanagawa.jp' => 1,
2333
- 'matsuda.kanagawa.jp' => 1,
2334
- 'minamiashigara.kanagawa.jp' => 1,
2335
- 'miura.kanagawa.jp' => 1,
2336
- 'nakai.kanagawa.jp' => 1,
2337
- 'ninomiya.kanagawa.jp' => 1,
2338
- 'odawara.kanagawa.jp' => 1,
2339
- 'oi.kanagawa.jp' => 1,
2340
- 'oiso.kanagawa.jp' => 1,
2341
- 'sagamihara.kanagawa.jp' => 1,
2342
- 'samukawa.kanagawa.jp' => 1,
2343
- 'tsukui.kanagawa.jp' => 1,
2344
- 'yamakita.kanagawa.jp' => 1,
2345
- 'yamato.kanagawa.jp' => 1,
2346
- 'yokosuka.kanagawa.jp' => 1,
2347
- 'yugawara.kanagawa.jp' => 1,
2348
- 'zama.kanagawa.jp' => 1,
2349
- 'zushi.kanagawa.jp' => 1,
2350
- 'aki.kochi.jp' => 1,
2351
- 'geisei.kochi.jp' => 1,
2352
- 'hidaka.kochi.jp' => 1,
2353
- 'higashitsuno.kochi.jp' => 1,
2354
- 'ino.kochi.jp' => 1,
2355
- 'kagami.kochi.jp' => 1,
2356
- 'kami.kochi.jp' => 1,
2357
- 'kitagawa.kochi.jp' => 1,
2358
- 'kochi.kochi.jp' => 1,
2359
- 'mihara.kochi.jp' => 1,
2360
- 'motoyama.kochi.jp' => 1,
2361
- 'muroto.kochi.jp' => 1,
2362
- 'nahari.kochi.jp' => 1,
2363
- 'nakamura.kochi.jp' => 1,
2364
- 'nankoku.kochi.jp' => 1,
2365
- 'nishitosa.kochi.jp' => 1,
2366
- 'niyodogawa.kochi.jp' => 1,
2367
- 'ochi.kochi.jp' => 1,
2368
- 'okawa.kochi.jp' => 1,
2369
- 'otoyo.kochi.jp' => 1,
2370
- 'otsuki.kochi.jp' => 1,
2371
- 'sakawa.kochi.jp' => 1,
2372
- 'sukumo.kochi.jp' => 1,
2373
- 'susaki.kochi.jp' => 1,
2374
- 'tosa.kochi.jp' => 1,
2375
- 'tosashimizu.kochi.jp' => 1,
2376
- 'toyo.kochi.jp' => 1,
2377
- 'tsuno.kochi.jp' => 1,
2378
- 'umaji.kochi.jp' => 1,
2379
- 'yasuda.kochi.jp' => 1,
2380
- 'yusuhara.kochi.jp' => 1,
2381
- 'amakusa.kumamoto.jp' => 1,
2382
- 'arao.kumamoto.jp' => 1,
2383
- 'aso.kumamoto.jp' => 1,
2384
- 'choyo.kumamoto.jp' => 1,
2385
- 'gyokuto.kumamoto.jp' => 1,
2386
- 'kamiamakusa.kumamoto.jp' => 1,
2387
- 'kikuchi.kumamoto.jp' => 1,
2388
- 'kumamoto.kumamoto.jp' => 1,
2389
- 'mashiki.kumamoto.jp' => 1,
2390
- 'mifune.kumamoto.jp' => 1,
2391
- 'minamata.kumamoto.jp' => 1,
2392
- 'minamioguni.kumamoto.jp' => 1,
2393
- 'nagasu.kumamoto.jp' => 1,
2394
- 'nishihara.kumamoto.jp' => 1,
2395
- 'oguni.kumamoto.jp' => 1,
2396
- 'ozu.kumamoto.jp' => 1,
2397
- 'sumoto.kumamoto.jp' => 1,
2398
- 'takamori.kumamoto.jp' => 1,
2399
- 'uki.kumamoto.jp' => 1,
2400
- 'uto.kumamoto.jp' => 1,
2401
- 'yamaga.kumamoto.jp' => 1,
2402
- 'yamato.kumamoto.jp' => 1,
2403
- 'yatsushiro.kumamoto.jp' => 1,
2404
- 'ayabe.kyoto.jp' => 1,
2405
- 'fukuchiyama.kyoto.jp' => 1,
2406
- 'higashiyama.kyoto.jp' => 1,
2407
- 'ide.kyoto.jp' => 1,
2408
- 'ine.kyoto.jp' => 1,
2409
- 'joyo.kyoto.jp' => 1,
2410
- 'kameoka.kyoto.jp' => 1,
2411
- 'kamo.kyoto.jp' => 1,
2412
- 'kita.kyoto.jp' => 1,
2413
- 'kizu.kyoto.jp' => 1,
2414
- 'kumiyama.kyoto.jp' => 1,
2415
- 'kyotamba.kyoto.jp' => 1,
2416
- 'kyotanabe.kyoto.jp' => 1,
2417
- 'kyotango.kyoto.jp' => 1,
2418
- 'maizuru.kyoto.jp' => 1,
2419
- 'minami.kyoto.jp' => 1,
2420
- 'minamiyamashiro.kyoto.jp' => 1,
2421
- 'miyazu.kyoto.jp' => 1,
2422
- 'muko.kyoto.jp' => 1,
2423
- 'nagaokakyo.kyoto.jp' => 1,
2424
- 'nakagyo.kyoto.jp' => 1,
2425
- 'nantan.kyoto.jp' => 1,
2426
- 'oyamazaki.kyoto.jp' => 1,
2427
- 'sakyo.kyoto.jp' => 1,
2428
- 'seika.kyoto.jp' => 1,
2429
- 'tanabe.kyoto.jp' => 1,
2430
- 'uji.kyoto.jp' => 1,
2431
- 'ujitawara.kyoto.jp' => 1,
2432
- 'wazuka.kyoto.jp' => 1,
2433
- 'yamashina.kyoto.jp' => 1,
2434
- 'yawata.kyoto.jp' => 1,
2435
- 'asahi.mie.jp' => 1,
2436
- 'inabe.mie.jp' => 1,
2437
- 'ise.mie.jp' => 1,
2438
- 'kameyama.mie.jp' => 1,
2439
- 'kawagoe.mie.jp' => 1,
2440
- 'kiho.mie.jp' => 1,
2441
- 'kisosaki.mie.jp' => 1,
2442
- 'kiwa.mie.jp' => 1,
2443
- 'komono.mie.jp' => 1,
2444
- 'kumano.mie.jp' => 1,
2445
- 'kuwana.mie.jp' => 1,
2446
- 'matsusaka.mie.jp' => 1,
2447
- 'meiwa.mie.jp' => 1,
2448
- 'mihama.mie.jp' => 1,
2449
- 'minamiise.mie.jp' => 1,
2450
- 'misugi.mie.jp' => 1,
2451
- 'miyama.mie.jp' => 1,
2452
- 'nabari.mie.jp' => 1,
2453
- 'shima.mie.jp' => 1,
2454
- 'suzuka.mie.jp' => 1,
2455
- 'tado.mie.jp' => 1,
2456
- 'taiki.mie.jp' => 1,
2457
- 'taki.mie.jp' => 1,
2458
- 'tamaki.mie.jp' => 1,
2459
- 'toba.mie.jp' => 1,
2460
- 'tsu.mie.jp' => 1,
2461
- 'udono.mie.jp' => 1,
2462
- 'ureshino.mie.jp' => 1,
2463
- 'watarai.mie.jp' => 1,
2464
- 'yokkaichi.mie.jp' => 1,
2465
- 'furukawa.miyagi.jp' => 1,
2466
- 'higashimatsushima.miyagi.jp' => 1,
2467
- 'ishinomaki.miyagi.jp' => 1,
2468
- 'iwanuma.miyagi.jp' => 1,
2469
- 'kakuda.miyagi.jp' => 1,
2470
- 'kami.miyagi.jp' => 1,
2471
- 'kawasaki.miyagi.jp' => 1,
2472
- 'marumori.miyagi.jp' => 1,
2473
- 'matsushima.miyagi.jp' => 1,
2474
- 'minamisanriku.miyagi.jp' => 1,
2475
- 'misato.miyagi.jp' => 1,
2476
- 'murata.miyagi.jp' => 1,
2477
- 'natori.miyagi.jp' => 1,
2478
- 'ogawara.miyagi.jp' => 1,
2479
- 'ohira.miyagi.jp' => 1,
2480
- 'onagawa.miyagi.jp' => 1,
2481
- 'osaki.miyagi.jp' => 1,
2482
- 'rifu.miyagi.jp' => 1,
2483
- 'semine.miyagi.jp' => 1,
2484
- 'shibata.miyagi.jp' => 1,
2485
- 'shichikashuku.miyagi.jp' => 1,
2486
- 'shikama.miyagi.jp' => 1,
2487
- 'shiogama.miyagi.jp' => 1,
2488
- 'shiroishi.miyagi.jp' => 1,
2489
- 'tagajo.miyagi.jp' => 1,
2490
- 'taiwa.miyagi.jp' => 1,
2491
- 'tome.miyagi.jp' => 1,
2492
- 'tomiya.miyagi.jp' => 1,
2493
- 'wakuya.miyagi.jp' => 1,
2494
- 'watari.miyagi.jp' => 1,
2495
- 'yamamoto.miyagi.jp' => 1,
2496
- 'zao.miyagi.jp' => 1,
2497
- 'aya.miyazaki.jp' => 1,
2498
- 'ebino.miyazaki.jp' => 1,
2499
- 'gokase.miyazaki.jp' => 1,
2500
- 'hyuga.miyazaki.jp' => 1,
2501
- 'kadogawa.miyazaki.jp' => 1,
2502
- 'kawaminami.miyazaki.jp' => 1,
2503
- 'kijo.miyazaki.jp' => 1,
2504
- 'kitagawa.miyazaki.jp' => 1,
2505
- 'kitakata.miyazaki.jp' => 1,
2506
- 'kitaura.miyazaki.jp' => 1,
2507
- 'kobayashi.miyazaki.jp' => 1,
2508
- 'kunitomi.miyazaki.jp' => 1,
2509
- 'kushima.miyazaki.jp' => 1,
2510
- 'mimata.miyazaki.jp' => 1,
2511
- 'miyakonojo.miyazaki.jp' => 1,
2512
- 'miyazaki.miyazaki.jp' => 1,
2513
- 'morotsuka.miyazaki.jp' => 1,
2514
- 'nichinan.miyazaki.jp' => 1,
2515
- 'nishimera.miyazaki.jp' => 1,
2516
- 'nobeoka.miyazaki.jp' => 1,
2517
- 'saito.miyazaki.jp' => 1,
2518
- 'shiiba.miyazaki.jp' => 1,
2519
- 'shintomi.miyazaki.jp' => 1,
2520
- 'takaharu.miyazaki.jp' => 1,
2521
- 'takanabe.miyazaki.jp' => 1,
2522
- 'takazaki.miyazaki.jp' => 1,
2523
- 'tsuno.miyazaki.jp' => 1,
2524
- 'achi.nagano.jp' => 1,
2525
- 'agematsu.nagano.jp' => 1,
2526
- 'anan.nagano.jp' => 1,
2527
- 'aoki.nagano.jp' => 1,
2528
- 'asahi.nagano.jp' => 1,
2529
- 'azumino.nagano.jp' => 1,
2530
- 'chikuhoku.nagano.jp' => 1,
2531
- 'chikuma.nagano.jp' => 1,
2532
- 'chino.nagano.jp' => 1,
2533
- 'fujimi.nagano.jp' => 1,
2534
- 'hakuba.nagano.jp' => 1,
2535
- 'hara.nagano.jp' => 1,
2536
- 'hiraya.nagano.jp' => 1,
2537
- 'iida.nagano.jp' => 1,
2538
- 'iijima.nagano.jp' => 1,
2539
- 'iiyama.nagano.jp' => 1,
2540
- 'iizuna.nagano.jp' => 1,
2541
- 'ikeda.nagano.jp' => 1,
2542
- 'ikusaka.nagano.jp' => 1,
2543
- 'ina.nagano.jp' => 1,
2544
- 'karuizawa.nagano.jp' => 1,
2545
- 'kawakami.nagano.jp' => 1,
2546
- 'kiso.nagano.jp' => 1,
2547
- 'kisofukushima.nagano.jp' => 1,
2548
- 'kitaaiki.nagano.jp' => 1,
2549
- 'komagane.nagano.jp' => 1,
2550
- 'komoro.nagano.jp' => 1,
2551
- 'matsukawa.nagano.jp' => 1,
2552
- 'matsumoto.nagano.jp' => 1,
2553
- 'miasa.nagano.jp' => 1,
2554
- 'minamiaiki.nagano.jp' => 1,
2555
- 'minamimaki.nagano.jp' => 1,
2556
- 'minamiminowa.nagano.jp' => 1,
2557
- 'minowa.nagano.jp' => 1,
2558
- 'miyada.nagano.jp' => 1,
2559
- 'miyota.nagano.jp' => 1,
2560
- 'mochizuki.nagano.jp' => 1,
2561
- 'nagano.nagano.jp' => 1,
2562
- 'nagawa.nagano.jp' => 1,
2563
- 'nagiso.nagano.jp' => 1,
2564
- 'nakagawa.nagano.jp' => 1,
2565
- 'nakano.nagano.jp' => 1,
2566
- 'nozawaonsen.nagano.jp' => 1,
2567
- 'obuse.nagano.jp' => 1,
2568
- 'ogawa.nagano.jp' => 1,
2569
- 'okaya.nagano.jp' => 1,
2570
- 'omachi.nagano.jp' => 1,
2571
- 'omi.nagano.jp' => 1,
2572
- 'ookuwa.nagano.jp' => 1,
2573
- 'ooshika.nagano.jp' => 1,
2574
- 'otaki.nagano.jp' => 1,
2575
- 'otari.nagano.jp' => 1,
2576
- 'sakae.nagano.jp' => 1,
2577
- 'sakaki.nagano.jp' => 1,
2578
- 'saku.nagano.jp' => 1,
2579
- 'sakuho.nagano.jp' => 1,
2580
- 'shimosuwa.nagano.jp' => 1,
2581
- 'shinanomachi.nagano.jp' => 1,
2582
- 'shiojiri.nagano.jp' => 1,
2583
- 'suwa.nagano.jp' => 1,
2584
- 'suzaka.nagano.jp' => 1,
2585
- 'takagi.nagano.jp' => 1,
2586
- 'takamori.nagano.jp' => 1,
2587
- 'takayama.nagano.jp' => 1,
2588
- 'tateshina.nagano.jp' => 1,
2589
- 'tatsuno.nagano.jp' => 1,
2590
- 'togakushi.nagano.jp' => 1,
2591
- 'togura.nagano.jp' => 1,
2592
- 'tomi.nagano.jp' => 1,
2593
- 'ueda.nagano.jp' => 1,
2594
- 'wada.nagano.jp' => 1,
2595
- 'yamagata.nagano.jp' => 1,
2596
- 'yamanouchi.nagano.jp' => 1,
2597
- 'yasaka.nagano.jp' => 1,
2598
- 'yasuoka.nagano.jp' => 1,
2599
- 'chijiwa.nagasaki.jp' => 1,
2600
- 'futsu.nagasaki.jp' => 1,
2601
- 'goto.nagasaki.jp' => 1,
2602
- 'hasami.nagasaki.jp' => 1,
2603
- 'hirado.nagasaki.jp' => 1,
2604
- 'iki.nagasaki.jp' => 1,
2605
- 'isahaya.nagasaki.jp' => 1,
2606
- 'kawatana.nagasaki.jp' => 1,
2607
- 'kuchinotsu.nagasaki.jp' => 1,
2608
- 'matsuura.nagasaki.jp' => 1,
2609
- 'nagasaki.nagasaki.jp' => 1,
2610
- 'obama.nagasaki.jp' => 1,
2611
- 'omura.nagasaki.jp' => 1,
2612
- 'oseto.nagasaki.jp' => 1,
2613
- 'saikai.nagasaki.jp' => 1,
2614
- 'sasebo.nagasaki.jp' => 1,
2615
- 'seihi.nagasaki.jp' => 1,
2616
- 'shimabara.nagasaki.jp' => 1,
2617
- 'shinkamigoto.nagasaki.jp' => 1,
2618
- 'togitsu.nagasaki.jp' => 1,
2619
- 'tsushima.nagasaki.jp' => 1,
2620
- 'unzen.nagasaki.jp' => 1,
2621
- 'ando.nara.jp' => 1,
2622
- 'gose.nara.jp' => 1,
2623
- 'heguri.nara.jp' => 1,
2624
- 'higashiyoshino.nara.jp' => 1,
2625
- 'ikaruga.nara.jp' => 1,
2626
- 'ikoma.nara.jp' => 1,
2627
- 'kamikitayama.nara.jp' => 1,
2628
- 'kanmaki.nara.jp' => 1,
2629
- 'kashiba.nara.jp' => 1,
2630
- 'kashihara.nara.jp' => 1,
2631
- 'katsuragi.nara.jp' => 1,
2632
- 'kawai.nara.jp' => 1,
2633
- 'kawakami.nara.jp' => 1,
2634
- 'kawanishi.nara.jp' => 1,
2635
- 'koryo.nara.jp' => 1,
2636
- 'kurotaki.nara.jp' => 1,
2637
- 'mitsue.nara.jp' => 1,
2638
- 'miyake.nara.jp' => 1,
2639
- 'nara.nara.jp' => 1,
2640
- 'nosegawa.nara.jp' => 1,
2641
- 'oji.nara.jp' => 1,
2642
- 'ouda.nara.jp' => 1,
2643
- 'oyodo.nara.jp' => 1,
2644
- 'sakurai.nara.jp' => 1,
2645
- 'sango.nara.jp' => 1,
2646
- 'shimoichi.nara.jp' => 1,
2647
- 'shimokitayama.nara.jp' => 1,
2648
- 'shinjo.nara.jp' => 1,
2649
- 'soni.nara.jp' => 1,
2650
- 'takatori.nara.jp' => 1,
2651
- 'tawaramoto.nara.jp' => 1,
2652
- 'tenkawa.nara.jp' => 1,
2653
- 'tenri.nara.jp' => 1,
2654
- 'uda.nara.jp' => 1,
2655
- 'yamatokoriyama.nara.jp' => 1,
2656
- 'yamatotakada.nara.jp' => 1,
2657
- 'yamazoe.nara.jp' => 1,
2658
- 'yoshino.nara.jp' => 1,
2659
- 'aga.niigata.jp' => 1,
2660
- 'agano.niigata.jp' => 1,
2661
- 'gosen.niigata.jp' => 1,
2662
- 'itoigawa.niigata.jp' => 1,
2663
- 'izumozaki.niigata.jp' => 1,
2664
- 'joetsu.niigata.jp' => 1,
2665
- 'kamo.niigata.jp' => 1,
2666
- 'kariwa.niigata.jp' => 1,
2667
- 'kashiwazaki.niigata.jp' => 1,
2668
- 'minamiuonuma.niigata.jp' => 1,
2669
- 'mitsuke.niigata.jp' => 1,
2670
- 'muika.niigata.jp' => 1,
2671
- 'murakami.niigata.jp' => 1,
2672
- 'myoko.niigata.jp' => 1,
2673
- 'nagaoka.niigata.jp' => 1,
2674
- 'niigata.niigata.jp' => 1,
2675
- 'ojiya.niigata.jp' => 1,
2676
- 'omi.niigata.jp' => 1,
2677
- 'sado.niigata.jp' => 1,
2678
- 'sanjo.niigata.jp' => 1,
2679
- 'seiro.niigata.jp' => 1,
2680
- 'seirou.niigata.jp' => 1,
2681
- 'sekikawa.niigata.jp' => 1,
2682
- 'shibata.niigata.jp' => 1,
2683
- 'tagami.niigata.jp' => 1,
2684
- 'tainai.niigata.jp' => 1,
2685
- 'tochio.niigata.jp' => 1,
2686
- 'tokamachi.niigata.jp' => 1,
2687
- 'tsubame.niigata.jp' => 1,
2688
- 'tsunan.niigata.jp' => 1,
2689
- 'uonuma.niigata.jp' => 1,
2690
- 'yahiko.niigata.jp' => 1,
2691
- 'yoita.niigata.jp' => 1,
2692
- 'yuzawa.niigata.jp' => 1,
2693
- 'beppu.oita.jp' => 1,
2694
- 'bungoono.oita.jp' => 1,
2695
- 'bungotakada.oita.jp' => 1,
2696
- 'hasama.oita.jp' => 1,
2697
- 'hiji.oita.jp' => 1,
2698
- 'himeshima.oita.jp' => 1,
2699
- 'hita.oita.jp' => 1,
2700
- 'kamitsue.oita.jp' => 1,
2701
- 'kokonoe.oita.jp' => 1,
2702
- 'kuju.oita.jp' => 1,
2703
- 'kunisaki.oita.jp' => 1,
2704
- 'kusu.oita.jp' => 1,
2705
- 'oita.oita.jp' => 1,
2706
- 'saiki.oita.jp' => 1,
2707
- 'taketa.oita.jp' => 1,
2708
- 'tsukumi.oita.jp' => 1,
2709
- 'usa.oita.jp' => 1,
2710
- 'usuki.oita.jp' => 1,
2711
- 'yufu.oita.jp' => 1,
2712
- 'akaiwa.okayama.jp' => 1,
2713
- 'asakuchi.okayama.jp' => 1,
2714
- 'bizen.okayama.jp' => 1,
2715
- 'hayashima.okayama.jp' => 1,
2716
- 'ibara.okayama.jp' => 1,
2717
- 'kagamino.okayama.jp' => 1,
2718
- 'kasaoka.okayama.jp' => 1,
2719
- 'kibichuo.okayama.jp' => 1,
2720
- 'kumenan.okayama.jp' => 1,
2721
- 'kurashiki.okayama.jp' => 1,
2722
- 'maniwa.okayama.jp' => 1,
2723
- 'misaki.okayama.jp' => 1,
2724
- 'nagi.okayama.jp' => 1,
2725
- 'niimi.okayama.jp' => 1,
2726
- 'nishiawakura.okayama.jp' => 1,
2727
- 'okayama.okayama.jp' => 1,
2728
- 'satosho.okayama.jp' => 1,
2729
- 'setouchi.okayama.jp' => 1,
2730
- 'shinjo.okayama.jp' => 1,
2731
- 'shoo.okayama.jp' => 1,
2732
- 'soja.okayama.jp' => 1,
2733
- 'takahashi.okayama.jp' => 1,
2734
- 'tamano.okayama.jp' => 1,
2735
- 'tsuyama.okayama.jp' => 1,
2736
- 'wake.okayama.jp' => 1,
2737
- 'yakage.okayama.jp' => 1,
2738
- 'aguni.okinawa.jp' => 1,
2739
- 'ginowan.okinawa.jp' => 1,
2740
- 'ginoza.okinawa.jp' => 1,
2741
- 'gushikami.okinawa.jp' => 1,
2742
- 'haebaru.okinawa.jp' => 1,
2743
- 'higashi.okinawa.jp' => 1,
2744
- 'hirara.okinawa.jp' => 1,
2745
- 'iheya.okinawa.jp' => 1,
2746
- 'ishigaki.okinawa.jp' => 1,
2747
- 'ishikawa.okinawa.jp' => 1,
2748
- 'itoman.okinawa.jp' => 1,
2749
- 'izena.okinawa.jp' => 1,
2750
- 'kadena.okinawa.jp' => 1,
2751
- 'kin.okinawa.jp' => 1,
2752
- 'kitadaito.okinawa.jp' => 1,
2753
- 'kitanakagusuku.okinawa.jp' => 1,
2754
- 'kumejima.okinawa.jp' => 1,
2755
- 'kunigami.okinawa.jp' => 1,
2756
- 'minamidaito.okinawa.jp' => 1,
2757
- 'motobu.okinawa.jp' => 1,
2758
- 'nago.okinawa.jp' => 1,
2759
- 'naha.okinawa.jp' => 1,
2760
- 'nakagusuku.okinawa.jp' => 1,
2761
- 'nakijin.okinawa.jp' => 1,
2762
- 'nanjo.okinawa.jp' => 1,
2763
- 'nishihara.okinawa.jp' => 1,
2764
- 'ogimi.okinawa.jp' => 1,
2765
- 'okinawa.okinawa.jp' => 1,
2766
- 'onna.okinawa.jp' => 1,
2767
- 'shimoji.okinawa.jp' => 1,
2768
- 'taketomi.okinawa.jp' => 1,
2769
- 'tarama.okinawa.jp' => 1,
2770
- 'tokashiki.okinawa.jp' => 1,
2771
- 'tomigusuku.okinawa.jp' => 1,
2772
- 'tonaki.okinawa.jp' => 1,
2773
- 'urasoe.okinawa.jp' => 1,
2774
- 'uruma.okinawa.jp' => 1,
2775
- 'yaese.okinawa.jp' => 1,
2776
- 'yomitan.okinawa.jp' => 1,
2777
- 'yonabaru.okinawa.jp' => 1,
2778
- 'yonaguni.okinawa.jp' => 1,
2779
- 'zamami.okinawa.jp' => 1,
2780
- 'abeno.osaka.jp' => 1,
2781
- 'chihayaakasaka.osaka.jp' => 1,
2782
- 'chuo.osaka.jp' => 1,
2783
- 'daito.osaka.jp' => 1,
2784
- 'fujiidera.osaka.jp' => 1,
2785
- 'habikino.osaka.jp' => 1,
2786
- 'hannan.osaka.jp' => 1,
2787
- 'higashiosaka.osaka.jp' => 1,
2788
- 'higashisumiyoshi.osaka.jp' => 1,
2789
- 'higashiyodogawa.osaka.jp' => 1,
2790
- 'hirakata.osaka.jp' => 1,
2791
- 'ibaraki.osaka.jp' => 1,
2792
- 'ikeda.osaka.jp' => 1,
2793
- 'izumi.osaka.jp' => 1,
2794
- 'izumiotsu.osaka.jp' => 1,
2795
- 'izumisano.osaka.jp' => 1,
2796
- 'kadoma.osaka.jp' => 1,
2797
- 'kaizuka.osaka.jp' => 1,
2798
- 'kanan.osaka.jp' => 1,
2799
- 'kashiwara.osaka.jp' => 1,
2800
- 'katano.osaka.jp' => 1,
2801
- 'kawachinagano.osaka.jp' => 1,
2802
- 'kishiwada.osaka.jp' => 1,
2803
- 'kita.osaka.jp' => 1,
2804
- 'kumatori.osaka.jp' => 1,
2805
- 'matsubara.osaka.jp' => 1,
2806
- 'minato.osaka.jp' => 1,
2807
- 'minoh.osaka.jp' => 1,
2808
- 'misaki.osaka.jp' => 1,
2809
- 'moriguchi.osaka.jp' => 1,
2810
- 'neyagawa.osaka.jp' => 1,
2811
- 'nishi.osaka.jp' => 1,
2812
- 'nose.osaka.jp' => 1,
2813
- 'osakasayama.osaka.jp' => 1,
2814
- 'sakai.osaka.jp' => 1,
2815
- 'sayama.osaka.jp' => 1,
2816
- 'sennan.osaka.jp' => 1,
2817
- 'settsu.osaka.jp' => 1,
2818
- 'shijonawate.osaka.jp' => 1,
2819
- 'shimamoto.osaka.jp' => 1,
2820
- 'suita.osaka.jp' => 1,
2821
- 'tadaoka.osaka.jp' => 1,
2822
- 'taishi.osaka.jp' => 1,
2823
- 'tajiri.osaka.jp' => 1,
2824
- 'takaishi.osaka.jp' => 1,
2825
- 'takatsuki.osaka.jp' => 1,
2826
- 'tondabayashi.osaka.jp' => 1,
2827
- 'toyonaka.osaka.jp' => 1,
2828
- 'toyono.osaka.jp' => 1,
2829
- 'yao.osaka.jp' => 1,
2830
- 'ariake.saga.jp' => 1,
2831
- 'arita.saga.jp' => 1,
2832
- 'fukudomi.saga.jp' => 1,
2833
- 'genkai.saga.jp' => 1,
2834
- 'hamatama.saga.jp' => 1,
2835
- 'hizen.saga.jp' => 1,
2836
- 'imari.saga.jp' => 1,
2837
- 'kamimine.saga.jp' => 1,
2838
- 'kanzaki.saga.jp' => 1,
2839
- 'karatsu.saga.jp' => 1,
2840
- 'kashima.saga.jp' => 1,
2841
- 'kitagata.saga.jp' => 1,
2842
- 'kitahata.saga.jp' => 1,
2843
- 'kiyama.saga.jp' => 1,
2844
- 'kouhoku.saga.jp' => 1,
2845
- 'kyuragi.saga.jp' => 1,
2846
- 'nishiarita.saga.jp' => 1,
2847
- 'ogi.saga.jp' => 1,
2848
- 'omachi.saga.jp' => 1,
2849
- 'ouchi.saga.jp' => 1,
2850
- 'saga.saga.jp' => 1,
2851
- 'shiroishi.saga.jp' => 1,
2852
- 'taku.saga.jp' => 1,
2853
- 'tara.saga.jp' => 1,
2854
- 'tosu.saga.jp' => 1,
2855
- 'yoshinogari.saga.jp' => 1,
2856
- 'arakawa.saitama.jp' => 1,
2857
- 'asaka.saitama.jp' => 1,
2858
- 'chichibu.saitama.jp' => 1,
2859
- 'fujimi.saitama.jp' => 1,
2860
- 'fujimino.saitama.jp' => 1,
2861
- 'fukaya.saitama.jp' => 1,
2862
- 'hanno.saitama.jp' => 1,
2863
- 'hanyu.saitama.jp' => 1,
2864
- 'hasuda.saitama.jp' => 1,
2865
- 'hatogaya.saitama.jp' => 1,
2866
- 'hatoyama.saitama.jp' => 1,
2867
- 'hidaka.saitama.jp' => 1,
2868
- 'higashichichibu.saitama.jp' => 1,
2869
- 'higashimatsuyama.saitama.jp' => 1,
2870
- 'honjo.saitama.jp' => 1,
2871
- 'ina.saitama.jp' => 1,
2872
- 'iruma.saitama.jp' => 1,
2873
- 'iwatsuki.saitama.jp' => 1,
2874
- 'kamiizumi.saitama.jp' => 1,
2875
- 'kamikawa.saitama.jp' => 1,
2876
- 'kamisato.saitama.jp' => 1,
2877
- 'kasukabe.saitama.jp' => 1,
2878
- 'kawagoe.saitama.jp' => 1,
2879
- 'kawaguchi.saitama.jp' => 1,
2880
- 'kawajima.saitama.jp' => 1,
2881
- 'kazo.saitama.jp' => 1,
2882
- 'kitamoto.saitama.jp' => 1,
2883
- 'koshigaya.saitama.jp' => 1,
2884
- 'kounosu.saitama.jp' => 1,
2885
- 'kuki.saitama.jp' => 1,
2886
- 'kumagaya.saitama.jp' => 1,
2887
- 'matsubushi.saitama.jp' => 1,
2888
- 'minano.saitama.jp' => 1,
2889
- 'misato.saitama.jp' => 1,
2890
- 'miyashiro.saitama.jp' => 1,
2891
- 'miyoshi.saitama.jp' => 1,
2892
- 'moroyama.saitama.jp' => 1,
2893
- 'nagatoro.saitama.jp' => 1,
2894
- 'namegawa.saitama.jp' => 1,
2895
- 'niiza.saitama.jp' => 1,
2896
- 'ogano.saitama.jp' => 1,
2897
- 'ogawa.saitama.jp' => 1,
2898
- 'ogose.saitama.jp' => 1,
2899
- 'okegawa.saitama.jp' => 1,
2900
- 'omiya.saitama.jp' => 1,
2901
- 'otaki.saitama.jp' => 1,
2902
- 'ranzan.saitama.jp' => 1,
2903
- 'ryokami.saitama.jp' => 1,
2904
- 'saitama.saitama.jp' => 1,
2905
- 'sakado.saitama.jp' => 1,
2906
- 'satte.saitama.jp' => 1,
2907
- 'sayama.saitama.jp' => 1,
2908
- 'shiki.saitama.jp' => 1,
2909
- 'shiraoka.saitama.jp' => 1,
2910
- 'soka.saitama.jp' => 1,
2911
- 'sugito.saitama.jp' => 1,
2912
- 'toda.saitama.jp' => 1,
2913
- 'tokigawa.saitama.jp' => 1,
2914
- 'tokorozawa.saitama.jp' => 1,
2915
- 'tsurugashima.saitama.jp' => 1,
2916
- 'urawa.saitama.jp' => 1,
2917
- 'warabi.saitama.jp' => 1,
2918
- 'yashio.saitama.jp' => 1,
2919
- 'yokoze.saitama.jp' => 1,
2920
- 'yono.saitama.jp' => 1,
2921
- 'yorii.saitama.jp' => 1,
2922
- 'yoshida.saitama.jp' => 1,
2923
- 'yoshikawa.saitama.jp' => 1,
2924
- 'yoshimi.saitama.jp' => 1,
2925
- 'aisho.shiga.jp' => 1,
2926
- 'gamo.shiga.jp' => 1,
2927
- 'higashiomi.shiga.jp' => 1,
2928
- 'hikone.shiga.jp' => 1,
2929
- 'koka.shiga.jp' => 1,
2930
- 'konan.shiga.jp' => 1,
2931
- 'kosei.shiga.jp' => 1,
2932
- 'koto.shiga.jp' => 1,
2933
- 'kusatsu.shiga.jp' => 1,
2934
- 'maibara.shiga.jp' => 1,
2935
- 'moriyama.shiga.jp' => 1,
2936
- 'nagahama.shiga.jp' => 1,
2937
- 'nishiazai.shiga.jp' => 1,
2938
- 'notogawa.shiga.jp' => 1,
2939
- 'omihachiman.shiga.jp' => 1,
2940
- 'otsu.shiga.jp' => 1,
2941
- 'ritto.shiga.jp' => 1,
2942
- 'ryuoh.shiga.jp' => 1,
2943
- 'takashima.shiga.jp' => 1,
2944
- 'takatsuki.shiga.jp' => 1,
2945
- 'torahime.shiga.jp' => 1,
2946
- 'toyosato.shiga.jp' => 1,
2947
- 'yasu.shiga.jp' => 1,
2948
- 'akagi.shimane.jp' => 1,
2949
- 'ama.shimane.jp' => 1,
2950
- 'gotsu.shimane.jp' => 1,
2951
- 'hamada.shimane.jp' => 1,
2952
- 'higashiizumo.shimane.jp' => 1,
2953
- 'hikawa.shimane.jp' => 1,
2954
- 'hikimi.shimane.jp' => 1,
2955
- 'izumo.shimane.jp' => 1,
2956
- 'kakinoki.shimane.jp' => 1,
2957
- 'masuda.shimane.jp' => 1,
2958
- 'matsue.shimane.jp' => 1,
2959
- 'misato.shimane.jp' => 1,
2960
- 'nishinoshima.shimane.jp' => 1,
2961
- 'ohda.shimane.jp' => 1,
2962
- 'okinoshima.shimane.jp' => 1,
2963
- 'okuizumo.shimane.jp' => 1,
2964
- 'shimane.shimane.jp' => 1,
2965
- 'tamayu.shimane.jp' => 1,
2966
- 'tsuwano.shimane.jp' => 1,
2967
- 'unnan.shimane.jp' => 1,
2968
- 'yakumo.shimane.jp' => 1,
2969
- 'yasugi.shimane.jp' => 1,
2970
- 'yatsuka.shimane.jp' => 1,
2971
- 'arai.shizuoka.jp' => 1,
2972
- 'atami.shizuoka.jp' => 1,
2973
- 'fuji.shizuoka.jp' => 1,
2974
- 'fujieda.shizuoka.jp' => 1,
2975
- 'fujikawa.shizuoka.jp' => 1,
2976
- 'fujinomiya.shizuoka.jp' => 1,
2977
- 'fukuroi.shizuoka.jp' => 1,
2978
- 'gotemba.shizuoka.jp' => 1,
2979
- 'haibara.shizuoka.jp' => 1,
2980
- 'hamamatsu.shizuoka.jp' => 1,
2981
- 'higashiizu.shizuoka.jp' => 1,
2982
- 'ito.shizuoka.jp' => 1,
2983
- 'iwata.shizuoka.jp' => 1,
2984
- 'izu.shizuoka.jp' => 1,
2985
- 'izunokuni.shizuoka.jp' => 1,
2986
- 'kakegawa.shizuoka.jp' => 1,
2987
- 'kannami.shizuoka.jp' => 1,
2988
- 'kawanehon.shizuoka.jp' => 1,
2989
- 'kawazu.shizuoka.jp' => 1,
2990
- 'kikugawa.shizuoka.jp' => 1,
2991
- 'kosai.shizuoka.jp' => 1,
2992
- 'makinohara.shizuoka.jp' => 1,
2993
- 'matsuzaki.shizuoka.jp' => 1,
2994
- 'minamiizu.shizuoka.jp' => 1,
2995
- 'mishima.shizuoka.jp' => 1,
2996
- 'morimachi.shizuoka.jp' => 1,
2997
- 'nishiizu.shizuoka.jp' => 1,
2998
- 'numazu.shizuoka.jp' => 1,
2999
- 'omaezaki.shizuoka.jp' => 1,
3000
- 'shimada.shizuoka.jp' => 1,
3001
- 'shimizu.shizuoka.jp' => 1,
3002
- 'shimoda.shizuoka.jp' => 1,
3003
- 'shizuoka.shizuoka.jp' => 1,
3004
- 'susono.shizuoka.jp' => 1,
3005
- 'yaizu.shizuoka.jp' => 1,
3006
- 'yoshida.shizuoka.jp' => 1,
3007
- 'ashikaga.tochigi.jp' => 1,
3008
- 'bato.tochigi.jp' => 1,
3009
- 'haga.tochigi.jp' => 1,
3010
- 'ichikai.tochigi.jp' => 1,
3011
- 'iwafune.tochigi.jp' => 1,
3012
- 'kaminokawa.tochigi.jp' => 1,
3013
- 'kanuma.tochigi.jp' => 1,
3014
- 'karasuyama.tochigi.jp' => 1,
3015
- 'kuroiso.tochigi.jp' => 1,
3016
- 'mashiko.tochigi.jp' => 1,
3017
- 'mibu.tochigi.jp' => 1,
3018
- 'moka.tochigi.jp' => 1,
3019
- 'motegi.tochigi.jp' => 1,
3020
- 'nasu.tochigi.jp' => 1,
3021
- 'nasushiobara.tochigi.jp' => 1,
3022
- 'nikko.tochigi.jp' => 1,
3023
- 'nishikata.tochigi.jp' => 1,
3024
- 'nogi.tochigi.jp' => 1,
3025
- 'ohira.tochigi.jp' => 1,
3026
- 'ohtawara.tochigi.jp' => 1,
3027
- 'oyama.tochigi.jp' => 1,
3028
- 'sakura.tochigi.jp' => 1,
3029
- 'sano.tochigi.jp' => 1,
3030
- 'shimotsuke.tochigi.jp' => 1,
3031
- 'shioya.tochigi.jp' => 1,
3032
- 'takanezawa.tochigi.jp' => 1,
3033
- 'tochigi.tochigi.jp' => 1,
3034
- 'tsuga.tochigi.jp' => 1,
3035
- 'ujiie.tochigi.jp' => 1,
3036
- 'utsunomiya.tochigi.jp' => 1,
3037
- 'yaita.tochigi.jp' => 1,
3038
- 'aizumi.tokushima.jp' => 1,
3039
- 'anan.tokushima.jp' => 1,
3040
- 'ichiba.tokushima.jp' => 1,
3041
- 'itano.tokushima.jp' => 1,
3042
- 'kainan.tokushima.jp' => 1,
3043
- 'komatsushima.tokushima.jp' => 1,
3044
- 'matsushige.tokushima.jp' => 1,
3045
- 'mima.tokushima.jp' => 1,
3046
- 'minami.tokushima.jp' => 1,
3047
- 'miyoshi.tokushima.jp' => 1,
3048
- 'mugi.tokushima.jp' => 1,
3049
- 'nakagawa.tokushima.jp' => 1,
3050
- 'naruto.tokushima.jp' => 1,
3051
- 'sanagochi.tokushima.jp' => 1,
3052
- 'shishikui.tokushima.jp' => 1,
3053
- 'tokushima.tokushima.jp' => 1,
3054
- 'wajiki.tokushima.jp' => 1,
3055
- 'adachi.tokyo.jp' => 1,
3056
- 'akiruno.tokyo.jp' => 1,
3057
- 'akishima.tokyo.jp' => 1,
3058
- 'aogashima.tokyo.jp' => 1,
3059
- 'arakawa.tokyo.jp' => 1,
3060
- 'bunkyo.tokyo.jp' => 1,
3061
- 'chiyoda.tokyo.jp' => 1,
3062
- 'chofu.tokyo.jp' => 1,
3063
- 'chuo.tokyo.jp' => 1,
3064
- 'edogawa.tokyo.jp' => 1,
3065
- 'fuchu.tokyo.jp' => 1,
3066
- 'fussa.tokyo.jp' => 1,
3067
- 'hachijo.tokyo.jp' => 1,
3068
- 'hachioji.tokyo.jp' => 1,
3069
- 'hamura.tokyo.jp' => 1,
3070
- 'higashikurume.tokyo.jp' => 1,
3071
- 'higashimurayama.tokyo.jp' => 1,
3072
- 'higashiyamato.tokyo.jp' => 1,
3073
- 'hino.tokyo.jp' => 1,
3074
- 'hinode.tokyo.jp' => 1,
3075
- 'hinohara.tokyo.jp' => 1,
3076
- 'inagi.tokyo.jp' => 1,
3077
- 'itabashi.tokyo.jp' => 1,
3078
- 'katsushika.tokyo.jp' => 1,
3079
- 'kita.tokyo.jp' => 1,
3080
- 'kiyose.tokyo.jp' => 1,
3081
- 'kodaira.tokyo.jp' => 1,
3082
- 'koganei.tokyo.jp' => 1,
3083
- 'kokubunji.tokyo.jp' => 1,
3084
- 'komae.tokyo.jp' => 1,
3085
- 'koto.tokyo.jp' => 1,
3086
- 'kouzushima.tokyo.jp' => 1,
3087
- 'kunitachi.tokyo.jp' => 1,
3088
- 'machida.tokyo.jp' => 1,
3089
- 'meguro.tokyo.jp' => 1,
3090
- 'minato.tokyo.jp' => 1,
3091
- 'mitaka.tokyo.jp' => 1,
3092
- 'mizuho.tokyo.jp' => 1,
3093
- 'musashimurayama.tokyo.jp' => 1,
3094
- 'musashino.tokyo.jp' => 1,
3095
- 'nakano.tokyo.jp' => 1,
3096
- 'nerima.tokyo.jp' => 1,
3097
- 'ogasawara.tokyo.jp' => 1,
3098
- 'okutama.tokyo.jp' => 1,
3099
- 'ome.tokyo.jp' => 1,
3100
- 'oshima.tokyo.jp' => 1,
3101
- 'ota.tokyo.jp' => 1,
3102
- 'setagaya.tokyo.jp' => 1,
3103
- 'shibuya.tokyo.jp' => 1,
3104
- 'shinagawa.tokyo.jp' => 1,
3105
- 'shinjuku.tokyo.jp' => 1,
3106
- 'suginami.tokyo.jp' => 1,
3107
- 'sumida.tokyo.jp' => 1,
3108
- 'tachikawa.tokyo.jp' => 1,
3109
- 'taito.tokyo.jp' => 1,
3110
- 'tama.tokyo.jp' => 1,
3111
- 'toshima.tokyo.jp' => 1,
3112
- 'chizu.tottori.jp' => 1,
3113
- 'hino.tottori.jp' => 1,
3114
- 'kawahara.tottori.jp' => 1,
3115
- 'koge.tottori.jp' => 1,
3116
- 'kotoura.tottori.jp' => 1,
3117
- 'misasa.tottori.jp' => 1,
3118
- 'nanbu.tottori.jp' => 1,
3119
- 'nichinan.tottori.jp' => 1,
3120
- 'sakaiminato.tottori.jp' => 1,
3121
- 'tottori.tottori.jp' => 1,
3122
- 'wakasa.tottori.jp' => 1,
3123
- 'yazu.tottori.jp' => 1,
3124
- 'yonago.tottori.jp' => 1,
3125
- 'asahi.toyama.jp' => 1,
3126
- 'fuchu.toyama.jp' => 1,
3127
- 'fukumitsu.toyama.jp' => 1,
3128
- 'funahashi.toyama.jp' => 1,
3129
- 'himi.toyama.jp' => 1,
3130
- 'imizu.toyama.jp' => 1,
3131
- 'inami.toyama.jp' => 1,
3132
- 'johana.toyama.jp' => 1,
3133
- 'kamiichi.toyama.jp' => 1,
3134
- 'kurobe.toyama.jp' => 1,
3135
- 'nakaniikawa.toyama.jp' => 1,
3136
- 'namerikawa.toyama.jp' => 1,
3137
- 'nanto.toyama.jp' => 1,
3138
- 'nyuzen.toyama.jp' => 1,
3139
- 'oyabe.toyama.jp' => 1,
3140
- 'taira.toyama.jp' => 1,
3141
- 'takaoka.toyama.jp' => 1,
3142
- 'tateyama.toyama.jp' => 1,
3143
- 'toga.toyama.jp' => 1,
3144
- 'tonami.toyama.jp' => 1,
3145
- 'toyama.toyama.jp' => 1,
3146
- 'unazuki.toyama.jp' => 1,
3147
- 'uozu.toyama.jp' => 1,
3148
- 'yamada.toyama.jp' => 1,
3149
- 'arida.wakayama.jp' => 1,
3150
- 'aridagawa.wakayama.jp' => 1,
3151
- 'gobo.wakayama.jp' => 1,
3152
- 'hashimoto.wakayama.jp' => 1,
3153
- 'hidaka.wakayama.jp' => 1,
3154
- 'hirogawa.wakayama.jp' => 1,
3155
- 'inami.wakayama.jp' => 1,
3156
- 'iwade.wakayama.jp' => 1,
3157
- 'kainan.wakayama.jp' => 1,
3158
- 'kamitonda.wakayama.jp' => 1,
3159
- 'katsuragi.wakayama.jp' => 1,
3160
- 'kimino.wakayama.jp' => 1,
3161
- 'kinokawa.wakayama.jp' => 1,
3162
- 'kitayama.wakayama.jp' => 1,
3163
- 'koya.wakayama.jp' => 1,
3164
- 'koza.wakayama.jp' => 1,
3165
- 'kozagawa.wakayama.jp' => 1,
3166
- 'kudoyama.wakayama.jp' => 1,
3167
- 'kushimoto.wakayama.jp' => 1,
3168
- 'mihama.wakayama.jp' => 1,
3169
- 'misato.wakayama.jp' => 1,
3170
- 'nachikatsuura.wakayama.jp' => 1,
3171
- 'shingu.wakayama.jp' => 1,
3172
- 'shirahama.wakayama.jp' => 1,
3173
- 'taiji.wakayama.jp' => 1,
3174
- 'tanabe.wakayama.jp' => 1,
3175
- 'wakayama.wakayama.jp' => 1,
3176
- 'yuasa.wakayama.jp' => 1,
3177
- 'yura.wakayama.jp' => 1,
3178
- 'asahi.yamagata.jp' => 1,
3179
- 'funagata.yamagata.jp' => 1,
3180
- 'higashine.yamagata.jp' => 1,
3181
- 'iide.yamagata.jp' => 1,
3182
- 'kahoku.yamagata.jp' => 1,
3183
- 'kaminoyama.yamagata.jp' => 1,
3184
- 'kaneyama.yamagata.jp' => 1,
3185
- 'kawanishi.yamagata.jp' => 1,
3186
- 'mamurogawa.yamagata.jp' => 1,
3187
- 'mikawa.yamagata.jp' => 1,
3188
- 'murayama.yamagata.jp' => 1,
3189
- 'nagai.yamagata.jp' => 1,
3190
- 'nakayama.yamagata.jp' => 1,
3191
- 'nanyo.yamagata.jp' => 1,
3192
- 'nishikawa.yamagata.jp' => 1,
3193
- 'obanazawa.yamagata.jp' => 1,
3194
- 'oe.yamagata.jp' => 1,
3195
- 'oguni.yamagata.jp' => 1,
3196
- 'ohkura.yamagata.jp' => 1,
3197
- 'oishida.yamagata.jp' => 1,
3198
- 'sagae.yamagata.jp' => 1,
3199
- 'sakata.yamagata.jp' => 1,
3200
- 'sakegawa.yamagata.jp' => 1,
3201
- 'shinjo.yamagata.jp' => 1,
3202
- 'shirataka.yamagata.jp' => 1,
3203
- 'shonai.yamagata.jp' => 1,
3204
- 'takahata.yamagata.jp' => 1,
3205
- 'tendo.yamagata.jp' => 1,
3206
- 'tozawa.yamagata.jp' => 1,
3207
- 'tsuruoka.yamagata.jp' => 1,
3208
- 'yamagata.yamagata.jp' => 1,
3209
- 'yamanobe.yamagata.jp' => 1,
3210
- 'yonezawa.yamagata.jp' => 1,
3211
- 'yuza.yamagata.jp' => 1,
3212
- 'abu.yamaguchi.jp' => 1,
3213
- 'hagi.yamaguchi.jp' => 1,
3214
- 'hikari.yamaguchi.jp' => 1,
3215
- 'hofu.yamaguchi.jp' => 1,
3216
- 'iwakuni.yamaguchi.jp' => 1,
3217
- 'kudamatsu.yamaguchi.jp' => 1,
3218
- 'mitou.yamaguchi.jp' => 1,
3219
- 'nagato.yamaguchi.jp' => 1,
3220
- 'oshima.yamaguchi.jp' => 1,
3221
- 'shimonoseki.yamaguchi.jp' => 1,
3222
- 'shunan.yamaguchi.jp' => 1,
3223
- 'tabuse.yamaguchi.jp' => 1,
3224
- 'tokuyama.yamaguchi.jp' => 1,
3225
- 'toyota.yamaguchi.jp' => 1,
3226
- 'ube.yamaguchi.jp' => 1,
3227
- 'yuu.yamaguchi.jp' => 1,
3228
- 'chuo.yamanashi.jp' => 1,
3229
- 'doshi.yamanashi.jp' => 1,
3230
- 'fuefuki.yamanashi.jp' => 1,
3231
- 'fujikawa.yamanashi.jp' => 1,
3232
- 'fujikawaguchiko.yamanashi.jp' => 1,
3233
- 'fujiyoshida.yamanashi.jp' => 1,
3234
- 'hayakawa.yamanashi.jp' => 1,
3235
- 'hokuto.yamanashi.jp' => 1,
3236
- 'ichikawamisato.yamanashi.jp' => 1,
3237
- 'kai.yamanashi.jp' => 1,
3238
- 'kofu.yamanashi.jp' => 1,
3239
- 'koshu.yamanashi.jp' => 1,
3240
- 'kosuge.yamanashi.jp' => 1,
3241
- 'minami-alps.yamanashi.jp' => 1,
3242
- 'minobu.yamanashi.jp' => 1,
3243
- 'nakamichi.yamanashi.jp' => 1,
3244
- 'nanbu.yamanashi.jp' => 1,
3245
- 'narusawa.yamanashi.jp' => 1,
3246
- 'nirasaki.yamanashi.jp' => 1,
3247
- 'nishikatsura.yamanashi.jp' => 1,
3248
- 'oshino.yamanashi.jp' => 1,
3249
- 'otsuki.yamanashi.jp' => 1,
3250
- 'showa.yamanashi.jp' => 1,
3251
- 'tabayama.yamanashi.jp' => 1,
3252
- 'tsuru.yamanashi.jp' => 1,
3253
- 'uenohara.yamanashi.jp' => 1,
3254
- 'yamanakako.yamanashi.jp' => 1,
3255
- 'yamanashi.yamanashi.jp' => 1,
3256
- 'ke' => 1,
3257
- 'ac.ke' => 1,
3258
- 'co.ke' => 1,
3259
- 'go.ke' => 1,
3260
- 'info.ke' => 1,
3261
- 'me.ke' => 1,
3262
- 'mobi.ke' => 1,
3263
- 'ne.ke' => 1,
3264
- 'or.ke' => 1,
3265
- 'sc.ke' => 1,
3266
- 'kg' => 1,
3267
- 'org.kg' => 1,
3268
- 'net.kg' => 1,
3269
- 'com.kg' => 1,
3270
- 'edu.kg' => 1,
3271
- 'gov.kg' => 1,
3272
- 'mil.kg' => 1,
3273
- '*.kh' => 1,
3274
- 'ki' => 1,
3275
- 'edu.ki' => 1,
3276
- 'biz.ki' => 1,
3277
- 'net.ki' => 1,
3278
- 'org.ki' => 1,
3279
- 'gov.ki' => 1,
3280
- 'info.ki' => 1,
3281
- 'com.ki' => 1,
3282
- 'km' => 1,
3283
- 'org.km' => 1,
3284
- 'nom.km' => 1,
3285
- 'gov.km' => 1,
3286
- 'prd.km' => 1,
3287
- 'tm.km' => 1,
3288
- 'edu.km' => 1,
3289
- 'mil.km' => 1,
3290
- 'ass.km' => 1,
3291
- 'com.km' => 1,
3292
- 'coop.km' => 1,
3293
- 'asso.km' => 1,
3294
- 'presse.km' => 1,
3295
- 'medecin.km' => 1,
3296
- 'notaires.km' => 1,
3297
- 'pharmaciens.km' => 1,
3298
- 'veterinaire.km' => 1,
3299
- 'gouv.km' => 1,
3300
- 'kn' => 1,
3301
- 'net.kn' => 1,
3302
- 'org.kn' => 1,
3303
- 'edu.kn' => 1,
3304
- 'gov.kn' => 1,
3305
- 'kp' => 1,
3306
- 'com.kp' => 1,
3307
- 'edu.kp' => 1,
3308
- 'gov.kp' => 1,
3309
- 'org.kp' => 1,
3310
- 'rep.kp' => 1,
3311
- 'tra.kp' => 1,
3312
- 'kr' => 1,
3313
- 'ac.kr' => 1,
3314
- 'co.kr' => 1,
3315
- 'es.kr' => 1,
3316
- 'go.kr' => 1,
3317
- 'hs.kr' => 1,
3318
- 'kg.kr' => 1,
3319
- 'mil.kr' => 1,
3320
- 'ms.kr' => 1,
3321
- 'ne.kr' => 1,
3322
- 'or.kr' => 1,
3323
- 'pe.kr' => 1,
3324
- 're.kr' => 1,
3325
- 'sc.kr' => 1,
3326
- 'busan.kr' => 1,
3327
- 'chungbuk.kr' => 1,
3328
- 'chungnam.kr' => 1,
3329
- 'daegu.kr' => 1,
3330
- 'daejeon.kr' => 1,
3331
- 'gangwon.kr' => 1,
3332
- 'gwangju.kr' => 1,
3333
- 'gyeongbuk.kr' => 1,
3334
- 'gyeonggi.kr' => 1,
3335
- 'gyeongnam.kr' => 1,
3336
- 'incheon.kr' => 1,
3337
- 'jeju.kr' => 1,
3338
- 'jeonbuk.kr' => 1,
3339
- 'jeonnam.kr' => 1,
3340
- 'seoul.kr' => 1,
3341
- 'ulsan.kr' => 1,
3342
- 'kw' => 1,
3343
- 'com.kw' => 1,
3344
- 'edu.kw' => 1,
3345
- 'emb.kw' => 1,
3346
- 'gov.kw' => 1,
3347
- 'ind.kw' => 1,
3348
- 'net.kw' => 1,
3349
- 'org.kw' => 1,
3350
- 'ky' => 1,
3351
- 'edu.ky' => 1,
3352
- 'gov.ky' => 1,
3353
- 'com.ky' => 1,
3354
- 'org.ky' => 1,
3355
- 'net.ky' => 1,
3356
- 'kz' => 1,
3357
- 'org.kz' => 1,
3358
- 'edu.kz' => 1,
3359
- 'net.kz' => 1,
3360
- 'gov.kz' => 1,
3361
- 'mil.kz' => 1,
3362
- 'com.kz' => 1,
3363
- 'la' => 1,
3364
- 'int.la' => 1,
3365
- 'net.la' => 1,
3366
- 'info.la' => 1,
3367
- 'edu.la' => 1,
3368
- 'gov.la' => 1,
3369
- 'per.la' => 1,
3370
- 'com.la' => 1,
3371
- 'org.la' => 1,
3372
- 'lb' => 1,
3373
- 'com.lb' => 1,
3374
- 'edu.lb' => 1,
3375
- 'gov.lb' => 1,
3376
- 'net.lb' => 1,
3377
- 'org.lb' => 1,
3378
- 'lc' => 1,
3379
- 'com.lc' => 1,
3380
- 'net.lc' => 1,
3381
- 'co.lc' => 1,
3382
- 'org.lc' => 1,
3383
- 'edu.lc' => 1,
3384
- 'gov.lc' => 1,
3385
- 'li' => 1,
3386
- 'lk' => 1,
3387
- 'gov.lk' => 1,
3388
- 'sch.lk' => 1,
3389
- 'net.lk' => 1,
3390
- 'int.lk' => 1,
3391
- 'com.lk' => 1,
3392
- 'org.lk' => 1,
3393
- 'edu.lk' => 1,
3394
- 'ngo.lk' => 1,
3395
- 'soc.lk' => 1,
3396
- 'web.lk' => 1,
3397
- 'ltd.lk' => 1,
3398
- 'assn.lk' => 1,
3399
- 'grp.lk' => 1,
3400
- 'hotel.lk' => 1,
3401
- 'ac.lk' => 1,
3402
- 'lr' => 1,
3403
- 'com.lr' => 1,
3404
- 'edu.lr' => 1,
3405
- 'gov.lr' => 1,
3406
- 'org.lr' => 1,
3407
- 'net.lr' => 1,
3408
- 'ls' => 1,
3409
- 'ac.ls' => 1,
3410
- 'biz.ls' => 1,
3411
- 'co.ls' => 1,
3412
- 'edu.ls' => 1,
3413
- 'gov.ls' => 1,
3414
- 'info.ls' => 1,
3415
- 'net.ls' => 1,
3416
- 'org.ls' => 1,
3417
- 'sc.ls' => 1,
3418
- 'lt' => 1,
3419
- 'gov.lt' => 1,
3420
- 'lu' => 1,
3421
- 'lv' => 1,
3422
- 'com.lv' => 1,
3423
- 'edu.lv' => 1,
3424
- 'gov.lv' => 1,
3425
- 'org.lv' => 1,
3426
- 'mil.lv' => 1,
3427
- 'id.lv' => 1,
3428
- 'net.lv' => 1,
3429
- 'asn.lv' => 1,
3430
- 'conf.lv' => 1,
3431
- 'ly' => 1,
3432
- 'com.ly' => 1,
3433
- 'net.ly' => 1,
3434
- 'gov.ly' => 1,
3435
- 'plc.ly' => 1,
3436
- 'edu.ly' => 1,
3437
- 'sch.ly' => 1,
3438
- 'med.ly' => 1,
3439
- 'org.ly' => 1,
3440
- 'id.ly' => 1,
3441
- 'ma' => 1,
3442
- 'co.ma' => 1,
3443
- 'net.ma' => 1,
3444
- 'gov.ma' => 1,
3445
- 'org.ma' => 1,
3446
- 'ac.ma' => 1,
3447
- 'press.ma' => 1,
3448
- 'mc' => 1,
3449
- 'tm.mc' => 1,
3450
- 'asso.mc' => 1,
3451
- 'md' => 1,
3452
- 'me' => 1,
3453
- 'co.me' => 1,
3454
- 'net.me' => 1,
3455
- 'org.me' => 1,
3456
- 'edu.me' => 1,
3457
- 'ac.me' => 1,
3458
- 'gov.me' => 1,
3459
- 'its.me' => 1,
3460
- 'priv.me' => 1,
3461
- 'mg' => 1,
3462
- 'org.mg' => 1,
3463
- 'nom.mg' => 1,
3464
- 'gov.mg' => 1,
3465
- 'prd.mg' => 1,
3466
- 'tm.mg' => 1,
3467
- 'edu.mg' => 1,
3468
- 'mil.mg' => 1,
3469
- 'com.mg' => 1,
3470
- 'co.mg' => 1,
3471
- 'mh' => 1,
3472
- 'mil' => 1,
3473
- 'mk' => 1,
3474
- 'com.mk' => 1,
3475
- 'org.mk' => 1,
3476
- 'net.mk' => 1,
3477
- 'edu.mk' => 1,
3478
- 'gov.mk' => 1,
3479
- 'inf.mk' => 1,
3480
- 'name.mk' => 1,
3481
- 'ml' => 1,
3482
- 'com.ml' => 1,
3483
- 'edu.ml' => 1,
3484
- 'gouv.ml' => 1,
3485
- 'gov.ml' => 1,
3486
- 'net.ml' => 1,
3487
- 'org.ml' => 1,
3488
- 'presse.ml' => 1,
3489
- '*.mm' => 1,
3490
- 'mn' => 1,
3491
- 'gov.mn' => 1,
3492
- 'edu.mn' => 1,
3493
- 'org.mn' => 1,
3494
- 'mo' => 1,
3495
- 'com.mo' => 1,
3496
- 'net.mo' => 1,
3497
- 'org.mo' => 1,
3498
- 'edu.mo' => 1,
3499
- 'gov.mo' => 1,
3500
- 'mobi' => 1,
3501
- 'mp' => 1,
3502
- 'mq' => 1,
3503
- 'mr' => 1,
3504
- 'gov.mr' => 1,
3505
- 'ms' => 1,
3506
- 'com.ms' => 1,
3507
- 'edu.ms' => 1,
3508
- 'gov.ms' => 1,
3509
- 'net.ms' => 1,
3510
- 'org.ms' => 1,
3511
- 'mt' => 1,
3512
- 'com.mt' => 1,
3513
- 'edu.mt' => 1,
3514
- 'net.mt' => 1,
3515
- 'org.mt' => 1,
3516
- 'mu' => 1,
3517
- 'com.mu' => 1,
3518
- 'net.mu' => 1,
3519
- 'org.mu' => 1,
3520
- 'gov.mu' => 1,
3521
- 'ac.mu' => 1,
3522
- 'co.mu' => 1,
3523
- 'or.mu' => 1,
3524
- 'museum' => 1,
3525
- 'academy.museum' => 1,
3526
- 'agriculture.museum' => 1,
3527
- 'air.museum' => 1,
3528
- 'airguard.museum' => 1,
3529
- 'alabama.museum' => 1,
3530
- 'alaska.museum' => 1,
3531
- 'amber.museum' => 1,
3532
- 'ambulance.museum' => 1,
3533
- 'american.museum' => 1,
3534
- 'americana.museum' => 1,
3535
- 'americanantiques.museum' => 1,
3536
- 'americanart.museum' => 1,
3537
- 'amsterdam.museum' => 1,
3538
- 'and.museum' => 1,
3539
- 'annefrank.museum' => 1,
3540
- 'anthro.museum' => 1,
3541
- 'anthropology.museum' => 1,
3542
- 'antiques.museum' => 1,
3543
- 'aquarium.museum' => 1,
3544
- 'arboretum.museum' => 1,
3545
- 'archaeological.museum' => 1,
3546
- 'archaeology.museum' => 1,
3547
- 'architecture.museum' => 1,
3548
- 'art.museum' => 1,
3549
- 'artanddesign.museum' => 1,
3550
- 'artcenter.museum' => 1,
3551
- 'artdeco.museum' => 1,
3552
- 'arteducation.museum' => 1,
3553
- 'artgallery.museum' => 1,
3554
- 'arts.museum' => 1,
3555
- 'artsandcrafts.museum' => 1,
3556
- 'asmatart.museum' => 1,
3557
- 'assassination.museum' => 1,
3558
- 'assisi.museum' => 1,
3559
- 'association.museum' => 1,
3560
- 'astronomy.museum' => 1,
3561
- 'atlanta.museum' => 1,
3562
- 'austin.museum' => 1,
3563
- 'australia.museum' => 1,
3564
- 'automotive.museum' => 1,
3565
- 'aviation.museum' => 1,
3566
- 'axis.museum' => 1,
3567
- 'badajoz.museum' => 1,
3568
- 'baghdad.museum' => 1,
3569
- 'bahn.museum' => 1,
3570
- 'bale.museum' => 1,
3571
- 'baltimore.museum' => 1,
3572
- 'barcelona.museum' => 1,
3573
- 'baseball.museum' => 1,
3574
- 'basel.museum' => 1,
3575
- 'baths.museum' => 1,
3576
- 'bauern.museum' => 1,
3577
- 'beauxarts.museum' => 1,
3578
- 'beeldengeluid.museum' => 1,
3579
- 'bellevue.museum' => 1,
3580
- 'bergbau.museum' => 1,
3581
- 'berkeley.museum' => 1,
3582
- 'berlin.museum' => 1,
3583
- 'bern.museum' => 1,
3584
- 'bible.museum' => 1,
3585
- 'bilbao.museum' => 1,
3586
- 'bill.museum' => 1,
3587
- 'birdart.museum' => 1,
3588
- 'birthplace.museum' => 1,
3589
- 'bonn.museum' => 1,
3590
- 'boston.museum' => 1,
3591
- 'botanical.museum' => 1,
3592
- 'botanicalgarden.museum' => 1,
3593
- 'botanicgarden.museum' => 1,
3594
- 'botany.museum' => 1,
3595
- 'brandywinevalley.museum' => 1,
3596
- 'brasil.museum' => 1,
3597
- 'bristol.museum' => 1,
3598
- 'british.museum' => 1,
3599
- 'britishcolumbia.museum' => 1,
3600
- 'broadcast.museum' => 1,
3601
- 'brunel.museum' => 1,
3602
- 'brussel.museum' => 1,
3603
- 'brussels.museum' => 1,
3604
- 'bruxelles.museum' => 1,
3605
- 'building.museum' => 1,
3606
- 'burghof.museum' => 1,
3607
- 'bus.museum' => 1,
3608
- 'bushey.museum' => 1,
3609
- 'cadaques.museum' => 1,
3610
- 'california.museum' => 1,
3611
- 'cambridge.museum' => 1,
3612
- 'can.museum' => 1,
3613
- 'canada.museum' => 1,
3614
- 'capebreton.museum' => 1,
3615
- 'carrier.museum' => 1,
3616
- 'cartoonart.museum' => 1,
3617
- 'casadelamoneda.museum' => 1,
3618
- 'castle.museum' => 1,
3619
- 'castres.museum' => 1,
3620
- 'celtic.museum' => 1,
3621
- 'center.museum' => 1,
3622
- 'chattanooga.museum' => 1,
3623
- 'cheltenham.museum' => 1,
3624
- 'chesapeakebay.museum' => 1,
3625
- 'chicago.museum' => 1,
3626
- 'children.museum' => 1,
3627
- 'childrens.museum' => 1,
3628
- 'childrensgarden.museum' => 1,
3629
- 'chiropractic.museum' => 1,
3630
- 'chocolate.museum' => 1,
3631
- 'christiansburg.museum' => 1,
3632
- 'cincinnati.museum' => 1,
3633
- 'cinema.museum' => 1,
3634
- 'circus.museum' => 1,
3635
- 'civilisation.museum' => 1,
3636
- 'civilization.museum' => 1,
3637
- 'civilwar.museum' => 1,
3638
- 'clinton.museum' => 1,
3639
- 'clock.museum' => 1,
3640
- 'coal.museum' => 1,
3641
- 'coastaldefence.museum' => 1,
3642
- 'cody.museum' => 1,
3643
- 'coldwar.museum' => 1,
3644
- 'collection.museum' => 1,
3645
- 'colonialwilliamsburg.museum' => 1,
3646
- 'coloradoplateau.museum' => 1,
3647
- 'columbia.museum' => 1,
3648
- 'columbus.museum' => 1,
3649
- 'communication.museum' => 1,
3650
- 'communications.museum' => 1,
3651
- 'community.museum' => 1,
3652
- 'computer.museum' => 1,
3653
- 'computerhistory.museum' => 1,
3654
- 'comunicações.museum' => 1,
3655
- 'contemporary.museum' => 1,
3656
- 'contemporaryart.museum' => 1,
3657
- 'convent.museum' => 1,
3658
- 'copenhagen.museum' => 1,
3659
- 'corporation.museum' => 1,
3660
- 'correios-e-telecomunicações.museum' => 1,
3661
- 'corvette.museum' => 1,
3662
- 'costume.museum' => 1,
3663
- 'countryestate.museum' => 1,
3664
- 'county.museum' => 1,
3665
- 'crafts.museum' => 1,
3666
- 'cranbrook.museum' => 1,
3667
- 'creation.museum' => 1,
3668
- 'cultural.museum' => 1,
3669
- 'culturalcenter.museum' => 1,
3670
- 'culture.museum' => 1,
3671
- 'cyber.museum' => 1,
3672
- 'cymru.museum' => 1,
3673
- 'dali.museum' => 1,
3674
- 'dallas.museum' => 1,
3675
- 'database.museum' => 1,
3676
- 'ddr.museum' => 1,
3677
- 'decorativearts.museum' => 1,
3678
- 'delaware.museum' => 1,
3679
- 'delmenhorst.museum' => 1,
3680
- 'denmark.museum' => 1,
3681
- 'depot.museum' => 1,
3682
- 'design.museum' => 1,
3683
- 'detroit.museum' => 1,
3684
- 'dinosaur.museum' => 1,
3685
- 'discovery.museum' => 1,
3686
- 'dolls.museum' => 1,
3687
- 'donostia.museum' => 1,
3688
- 'durham.museum' => 1,
3689
- 'eastafrica.museum' => 1,
3690
- 'eastcoast.museum' => 1,
3691
- 'education.museum' => 1,
3692
- 'educational.museum' => 1,
3693
- 'egyptian.museum' => 1,
3694
- 'eisenbahn.museum' => 1,
3695
- 'elburg.museum' => 1,
3696
- 'elvendrell.museum' => 1,
3697
- 'embroidery.museum' => 1,
3698
- 'encyclopedic.museum' => 1,
3699
- 'england.museum' => 1,
3700
- 'entomology.museum' => 1,
3701
- 'environment.museum' => 1,
3702
- 'environmentalconservation.museum' => 1,
3703
- 'epilepsy.museum' => 1,
3704
- 'essex.museum' => 1,
3705
- 'estate.museum' => 1,
3706
- 'ethnology.museum' => 1,
3707
- 'exeter.museum' => 1,
3708
- 'exhibition.museum' => 1,
3709
- 'family.museum' => 1,
3710
- 'farm.museum' => 1,
3711
- 'farmequipment.museum' => 1,
3712
- 'farmers.museum' => 1,
3713
- 'farmstead.museum' => 1,
3714
- 'field.museum' => 1,
3715
- 'figueres.museum' => 1,
3716
- 'filatelia.museum' => 1,
3717
- 'film.museum' => 1,
3718
- 'fineart.museum' => 1,
3719
- 'finearts.museum' => 1,
3720
- 'finland.museum' => 1,
3721
- 'flanders.museum' => 1,
3722
- 'florida.museum' => 1,
3723
- 'force.museum' => 1,
3724
- 'fortmissoula.museum' => 1,
3725
- 'fortworth.museum' => 1,
3726
- 'foundation.museum' => 1,
3727
- 'francaise.museum' => 1,
3728
- 'frankfurt.museum' => 1,
3729
- 'franziskaner.museum' => 1,
3730
- 'freemasonry.museum' => 1,
3731
- 'freiburg.museum' => 1,
3732
- 'fribourg.museum' => 1,
3733
- 'frog.museum' => 1,
3734
- 'fundacio.museum' => 1,
3735
- 'furniture.museum' => 1,
3736
- 'gallery.museum' => 1,
3737
- 'garden.museum' => 1,
3738
- 'gateway.museum' => 1,
3739
- 'geelvinck.museum' => 1,
3740
- 'gemological.museum' => 1,
3741
- 'geology.museum' => 1,
3742
- 'georgia.museum' => 1,
3743
- 'giessen.museum' => 1,
3744
- 'glas.museum' => 1,
3745
- 'glass.museum' => 1,
3746
- 'gorge.museum' => 1,
3747
- 'grandrapids.museum' => 1,
3748
- 'graz.museum' => 1,
3749
- 'guernsey.museum' => 1,
3750
- 'halloffame.museum' => 1,
3751
- 'hamburg.museum' => 1,
3752
- 'handson.museum' => 1,
3753
- 'harvestcelebration.museum' => 1,
3754
- 'hawaii.museum' => 1,
3755
- 'health.museum' => 1,
3756
- 'heimatunduhren.museum' => 1,
3757
- 'hellas.museum' => 1,
3758
- 'helsinki.museum' => 1,
3759
- 'hembygdsforbund.museum' => 1,
3760
- 'heritage.museum' => 1,
3761
- 'histoire.museum' => 1,
3762
- 'historical.museum' => 1,
3763
- 'historicalsociety.museum' => 1,
3764
- 'historichouses.museum' => 1,
3765
- 'historisch.museum' => 1,
3766
- 'historisches.museum' => 1,
3767
- 'history.museum' => 1,
3768
- 'historyofscience.museum' => 1,
3769
- 'horology.museum' => 1,
3770
- 'house.museum' => 1,
3771
- 'humanities.museum' => 1,
3772
- 'illustration.museum' => 1,
3773
- 'imageandsound.museum' => 1,
3774
- 'indian.museum' => 1,
3775
- 'indiana.museum' => 1,
3776
- 'indianapolis.museum' => 1,
3777
- 'indianmarket.museum' => 1,
3778
- 'intelligence.museum' => 1,
3779
- 'interactive.museum' => 1,
3780
- 'iraq.museum' => 1,
3781
- 'iron.museum' => 1,
3782
- 'isleofman.museum' => 1,
3783
- 'jamison.museum' => 1,
3784
- 'jefferson.museum' => 1,
3785
- 'jerusalem.museum' => 1,
3786
- 'jewelry.museum' => 1,
3787
- 'jewish.museum' => 1,
3788
- 'jewishart.museum' => 1,
3789
- 'jfk.museum' => 1,
3790
- 'journalism.museum' => 1,
3791
- 'judaica.museum' => 1,
3792
- 'judygarland.museum' => 1,
3793
- 'juedisches.museum' => 1,
3794
- 'juif.museum' => 1,
3795
- 'karate.museum' => 1,
3796
- 'karikatur.museum' => 1,
3797
- 'kids.museum' => 1,
3798
- 'koebenhavn.museum' => 1,
3799
- 'koeln.museum' => 1,
3800
- 'kunst.museum' => 1,
3801
- 'kunstsammlung.museum' => 1,
3802
- 'kunstunddesign.museum' => 1,
3803
- 'labor.museum' => 1,
3804
- 'labour.museum' => 1,
3805
- 'lajolla.museum' => 1,
3806
- 'lancashire.museum' => 1,
3807
- 'landes.museum' => 1,
3808
- 'lans.museum' => 1,
3809
- 'läns.museum' => 1,
3810
- 'larsson.museum' => 1,
3811
- 'lewismiller.museum' => 1,
3812
- 'lincoln.museum' => 1,
3813
- 'linz.museum' => 1,
3814
- 'living.museum' => 1,
3815
- 'livinghistory.museum' => 1,
3816
- 'localhistory.museum' => 1,
3817
- 'london.museum' => 1,
3818
- 'losangeles.museum' => 1,
3819
- 'louvre.museum' => 1,
3820
- 'loyalist.museum' => 1,
3821
- 'lucerne.museum' => 1,
3822
- 'luxembourg.museum' => 1,
3823
- 'luzern.museum' => 1,
3824
- 'mad.museum' => 1,
3825
- 'madrid.museum' => 1,
3826
- 'mallorca.museum' => 1,
3827
- 'manchester.museum' => 1,
3828
- 'mansion.museum' => 1,
3829
- 'mansions.museum' => 1,
3830
- 'manx.museum' => 1,
3831
- 'marburg.museum' => 1,
3832
- 'maritime.museum' => 1,
3833
- 'maritimo.museum' => 1,
3834
- 'maryland.museum' => 1,
3835
- 'marylhurst.museum' => 1,
3836
- 'media.museum' => 1,
3837
- 'medical.museum' => 1,
3838
- 'medizinhistorisches.museum' => 1,
3839
- 'meeres.museum' => 1,
3840
- 'memorial.museum' => 1,
3841
- 'mesaverde.museum' => 1,
3842
- 'michigan.museum' => 1,
3843
- 'midatlantic.museum' => 1,
3844
- 'military.museum' => 1,
3845
- 'mill.museum' => 1,
3846
- 'miners.museum' => 1,
3847
- 'mining.museum' => 1,
3848
- 'minnesota.museum' => 1,
3849
- 'missile.museum' => 1,
3850
- 'missoula.museum' => 1,
3851
- 'modern.museum' => 1,
3852
- 'moma.museum' => 1,
3853
- 'money.museum' => 1,
3854
- 'monmouth.museum' => 1,
3855
- 'monticello.museum' => 1,
3856
- 'montreal.museum' => 1,
3857
- 'moscow.museum' => 1,
3858
- 'motorcycle.museum' => 1,
3859
- 'muenchen.museum' => 1,
3860
- 'muenster.museum' => 1,
3861
- 'mulhouse.museum' => 1,
3862
- 'muncie.museum' => 1,
3863
- 'museet.museum' => 1,
3864
- 'museumcenter.museum' => 1,
3865
- 'museumvereniging.museum' => 1,
3866
- 'music.museum' => 1,
3867
- 'national.museum' => 1,
3868
- 'nationalfirearms.museum' => 1,
3869
- 'nationalheritage.museum' => 1,
3870
- 'nativeamerican.museum' => 1,
3871
- 'naturalhistory.museum' => 1,
3872
- 'naturalhistorymuseum.museum' => 1,
3873
- 'naturalsciences.museum' => 1,
3874
- 'nature.museum' => 1,
3875
- 'naturhistorisches.museum' => 1,
3876
- 'natuurwetenschappen.museum' => 1,
3877
- 'naumburg.museum' => 1,
3878
- 'naval.museum' => 1,
3879
- 'nebraska.museum' => 1,
3880
- 'neues.museum' => 1,
3881
- 'newhampshire.museum' => 1,
3882
- 'newjersey.museum' => 1,
3883
- 'newmexico.museum' => 1,
3884
- 'newport.museum' => 1,
3885
- 'newspaper.museum' => 1,
3886
- 'newyork.museum' => 1,
3887
- 'niepce.museum' => 1,
3888
- 'norfolk.museum' => 1,
3889
- 'north.museum' => 1,
3890
- 'nrw.museum' => 1,
3891
- 'nuernberg.museum' => 1,
3892
- 'nuremberg.museum' => 1,
3893
- 'nyc.museum' => 1,
3894
- 'nyny.museum' => 1,
3895
- 'oceanographic.museum' => 1,
3896
- 'oceanographique.museum' => 1,
3897
- 'omaha.museum' => 1,
3898
- 'online.museum' => 1,
3899
- 'ontario.museum' => 1,
3900
- 'openair.museum' => 1,
3901
- 'oregon.museum' => 1,
3902
- 'oregontrail.museum' => 1,
3903
- 'otago.museum' => 1,
3904
- 'oxford.museum' => 1,
3905
- 'pacific.museum' => 1,
3906
- 'paderborn.museum' => 1,
3907
- 'palace.museum' => 1,
3908
- 'paleo.museum' => 1,
3909
- 'palmsprings.museum' => 1,
3910
- 'panama.museum' => 1,
3911
- 'paris.museum' => 1,
3912
- 'pasadena.museum' => 1,
3913
- 'pharmacy.museum' => 1,
3914
- 'philadelphia.museum' => 1,
3915
- 'philadelphiaarea.museum' => 1,
3916
- 'philately.museum' => 1,
3917
- 'phoenix.museum' => 1,
3918
- 'photography.museum' => 1,
3919
- 'pilots.museum' => 1,
3920
- 'pittsburgh.museum' => 1,
3921
- 'planetarium.museum' => 1,
3922
- 'plantation.museum' => 1,
3923
- 'plants.museum' => 1,
3924
- 'plaza.museum' => 1,
3925
- 'portal.museum' => 1,
3926
- 'portland.museum' => 1,
3927
- 'portlligat.museum' => 1,
3928
- 'posts-and-telecommunications.museum' => 1,
3929
- 'preservation.museum' => 1,
3930
- 'presidio.museum' => 1,
3931
- 'press.museum' => 1,
3932
- 'project.museum' => 1,
3933
- 'public.museum' => 1,
3934
- 'pubol.museum' => 1,
3935
- 'quebec.museum' => 1,
3936
- 'railroad.museum' => 1,
3937
- 'railway.museum' => 1,
3938
- 'research.museum' => 1,
3939
- 'resistance.museum' => 1,
3940
- 'riodejaneiro.museum' => 1,
3941
- 'rochester.museum' => 1,
3942
- 'rockart.museum' => 1,
3943
- 'roma.museum' => 1,
3944
- 'russia.museum' => 1,
3945
- 'saintlouis.museum' => 1,
3946
- 'salem.museum' => 1,
3947
- 'salvadordali.museum' => 1,
3948
- 'salzburg.museum' => 1,
3949
- 'sandiego.museum' => 1,
3950
- 'sanfrancisco.museum' => 1,
3951
- 'santabarbara.museum' => 1,
3952
- 'santacruz.museum' => 1,
3953
- 'santafe.museum' => 1,
3954
- 'saskatchewan.museum' => 1,
3955
- 'satx.museum' => 1,
3956
- 'savannahga.museum' => 1,
3957
- 'schlesisches.museum' => 1,
3958
- 'schoenbrunn.museum' => 1,
3959
- 'schokoladen.museum' => 1,
3960
- 'school.museum' => 1,
3961
- 'schweiz.museum' => 1,
3962
- 'science.museum' => 1,
3963
- 'scienceandhistory.museum' => 1,
3964
- 'scienceandindustry.museum' => 1,
3965
- 'sciencecenter.museum' => 1,
3966
- 'sciencecenters.museum' => 1,
3967
- 'science-fiction.museum' => 1,
3968
- 'sciencehistory.museum' => 1,
3969
- 'sciences.museum' => 1,
3970
- 'sciencesnaturelles.museum' => 1,
3971
- 'scotland.museum' => 1,
3972
- 'seaport.museum' => 1,
3973
- 'settlement.museum' => 1,
3974
- 'settlers.museum' => 1,
3975
- 'shell.museum' => 1,
3976
- 'sherbrooke.museum' => 1,
3977
- 'sibenik.museum' => 1,
3978
- 'silk.museum' => 1,
3979
- 'ski.museum' => 1,
3980
- 'skole.museum' => 1,
3981
- 'society.museum' => 1,
3982
- 'sologne.museum' => 1,
3983
- 'soundandvision.museum' => 1,
3984
- 'southcarolina.museum' => 1,
3985
- 'southwest.museum' => 1,
3986
- 'space.museum' => 1,
3987
- 'spy.museum' => 1,
3988
- 'square.museum' => 1,
3989
- 'stadt.museum' => 1,
3990
- 'stalbans.museum' => 1,
3991
- 'starnberg.museum' => 1,
3992
- 'state.museum' => 1,
3993
- 'stateofdelaware.museum' => 1,
3994
- 'station.museum' => 1,
3995
- 'steam.museum' => 1,
3996
- 'steiermark.museum' => 1,
3997
- 'stjohn.museum' => 1,
3998
- 'stockholm.museum' => 1,
3999
- 'stpetersburg.museum' => 1,
4000
- 'stuttgart.museum' => 1,
4001
- 'suisse.museum' => 1,
4002
- 'surgeonshall.museum' => 1,
4003
- 'surrey.museum' => 1,
4004
- 'svizzera.museum' => 1,
4005
- 'sweden.museum' => 1,
4006
- 'sydney.museum' => 1,
4007
- 'tank.museum' => 1,
4008
- 'tcm.museum' => 1,
4009
- 'technology.museum' => 1,
4010
- 'telekommunikation.museum' => 1,
4011
- 'television.museum' => 1,
4012
- 'texas.museum' => 1,
4013
- 'textile.museum' => 1,
4014
- 'theater.museum' => 1,
4015
- 'time.museum' => 1,
4016
- 'timekeeping.museum' => 1,
4017
- 'topology.museum' => 1,
4018
- 'torino.museum' => 1,
4019
- 'touch.museum' => 1,
4020
- 'town.museum' => 1,
4021
- 'transport.museum' => 1,
4022
- 'tree.museum' => 1,
4023
- 'trolley.museum' => 1,
4024
- 'trust.museum' => 1,
4025
- 'trustee.museum' => 1,
4026
- 'uhren.museum' => 1,
4027
- 'ulm.museum' => 1,
4028
- 'undersea.museum' => 1,
4029
- 'university.museum' => 1,
4030
- 'usa.museum' => 1,
4031
- 'usantiques.museum' => 1,
4032
- 'usarts.museum' => 1,
4033
- 'uscountryestate.museum' => 1,
4034
- 'usculture.museum' => 1,
4035
- 'usdecorativearts.museum' => 1,
4036
- 'usgarden.museum' => 1,
4037
- 'ushistory.museum' => 1,
4038
- 'ushuaia.museum' => 1,
4039
- 'uslivinghistory.museum' => 1,
4040
- 'utah.museum' => 1,
4041
- 'uvic.museum' => 1,
4042
- 'valley.museum' => 1,
4043
- 'vantaa.museum' => 1,
4044
- 'versailles.museum' => 1,
4045
- 'viking.museum' => 1,
4046
- 'village.museum' => 1,
4047
- 'virginia.museum' => 1,
4048
- 'virtual.museum' => 1,
4049
- 'virtuel.museum' => 1,
4050
- 'vlaanderen.museum' => 1,
4051
- 'volkenkunde.museum' => 1,
4052
- 'wales.museum' => 1,
4053
- 'wallonie.museum' => 1,
4054
- 'war.museum' => 1,
4055
- 'washingtondc.museum' => 1,
4056
- 'watchandclock.museum' => 1,
4057
- 'watch-and-clock.museum' => 1,
4058
- 'western.museum' => 1,
4059
- 'westfalen.museum' => 1,
4060
- 'whaling.museum' => 1,
4061
- 'wildlife.museum' => 1,
4062
- 'williamsburg.museum' => 1,
4063
- 'windmill.museum' => 1,
4064
- 'workshop.museum' => 1,
4065
- 'york.museum' => 1,
4066
- 'yorkshire.museum' => 1,
4067
- 'yosemite.museum' => 1,
4068
- 'youth.museum' => 1,
4069
- 'zoological.museum' => 1,
4070
- 'zoology.museum' => 1,
4071
- 'ירושלים.museum' => 1,
4072
- 'иком.museum' => 1,
4073
- 'mv' => 1,
4074
- 'aero.mv' => 1,
4075
- 'biz.mv' => 1,
4076
- 'com.mv' => 1,
4077
- 'coop.mv' => 1,
4078
- 'edu.mv' => 1,
4079
- 'gov.mv' => 1,
4080
- 'info.mv' => 1,
4081
- 'int.mv' => 1,
4082
- 'mil.mv' => 1,
4083
- 'museum.mv' => 1,
4084
- 'name.mv' => 1,
4085
- 'net.mv' => 1,
4086
- 'org.mv' => 1,
4087
- 'pro.mv' => 1,
4088
- 'mw' => 1,
4089
- 'ac.mw' => 1,
4090
- 'biz.mw' => 1,
4091
- 'co.mw' => 1,
4092
- 'com.mw' => 1,
4093
- 'coop.mw' => 1,
4094
- 'edu.mw' => 1,
4095
- 'gov.mw' => 1,
4096
- 'int.mw' => 1,
4097
- 'museum.mw' => 1,
4098
- 'net.mw' => 1,
4099
- 'org.mw' => 1,
4100
- 'mx' => 1,
4101
- 'com.mx' => 1,
4102
- 'org.mx' => 1,
4103
- 'gob.mx' => 1,
4104
- 'edu.mx' => 1,
4105
- 'net.mx' => 1,
4106
- 'my' => 1,
4107
- 'com.my' => 1,
4108
- 'net.my' => 1,
4109
- 'org.my' => 1,
4110
- 'gov.my' => 1,
4111
- 'edu.my' => 1,
4112
- 'mil.my' => 1,
4113
- 'name.my' => 1,
4114
- 'mz' => 1,
4115
- 'ac.mz' => 1,
4116
- 'adv.mz' => 1,
4117
- 'co.mz' => 1,
4118
- 'edu.mz' => 1,
4119
- 'gov.mz' => 1,
4120
- 'mil.mz' => 1,
4121
- 'net.mz' => 1,
4122
- 'org.mz' => 1,
4123
- 'na' => 1,
4124
- 'info.na' => 1,
4125
- 'pro.na' => 1,
4126
- 'name.na' => 1,
4127
- 'school.na' => 1,
4128
- 'or.na' => 1,
4129
- 'dr.na' => 1,
4130
- 'us.na' => 1,
4131
- 'mx.na' => 1,
4132
- 'ca.na' => 1,
4133
- 'in.na' => 1,
4134
- 'cc.na' => 1,
4135
- 'tv.na' => 1,
4136
- 'ws.na' => 1,
4137
- 'mobi.na' => 1,
4138
- 'co.na' => 1,
4139
- 'com.na' => 1,
4140
- 'org.na' => 1,
4141
- 'name' => 1,
4142
- 'nc' => 1,
4143
- 'asso.nc' => 1,
4144
- 'nom.nc' => 1,
4145
- 'ne' => 1,
4146
- 'net' => 1,
4147
- 'nf' => 1,
4148
- 'com.nf' => 1,
4149
- 'net.nf' => 1,
4150
- 'per.nf' => 1,
4151
- 'rec.nf' => 1,
4152
- 'web.nf' => 1,
4153
- 'arts.nf' => 1,
4154
- 'firm.nf' => 1,
4155
- 'info.nf' => 1,
4156
- 'other.nf' => 1,
4157
- 'store.nf' => 1,
4158
- 'ng' => 1,
4159
- 'com.ng' => 1,
4160
- 'edu.ng' => 1,
4161
- 'gov.ng' => 1,
4162
- 'i.ng' => 1,
4163
- 'mil.ng' => 1,
4164
- 'mobi.ng' => 1,
4165
- 'name.ng' => 1,
4166
- 'net.ng' => 1,
4167
- 'org.ng' => 1,
4168
- 'sch.ng' => 1,
4169
- 'ni' => 1,
4170
- 'ac.ni' => 1,
4171
- 'biz.ni' => 1,
4172
- 'co.ni' => 1,
4173
- 'com.ni' => 1,
4174
- 'edu.ni' => 1,
4175
- 'gob.ni' => 1,
4176
- 'in.ni' => 1,
4177
- 'info.ni' => 1,
4178
- 'int.ni' => 1,
4179
- 'mil.ni' => 1,
4180
- 'net.ni' => 1,
4181
- 'nom.ni' => 1,
4182
- 'org.ni' => 1,
4183
- 'web.ni' => 1,
4184
- 'nl' => 1,
4185
- 'no' => 1,
4186
- 'fhs.no' => 1,
4187
- 'vgs.no' => 1,
4188
- 'fylkesbibl.no' => 1,
4189
- 'folkebibl.no' => 1,
4190
- 'museum.no' => 1,
4191
- 'idrett.no' => 1,
4192
- 'priv.no' => 1,
4193
- 'mil.no' => 1,
4194
- 'stat.no' => 1,
4195
- 'dep.no' => 1,
4196
- 'kommune.no' => 1,
4197
- 'herad.no' => 1,
4198
- 'aa.no' => 1,
4199
- 'ah.no' => 1,
4200
- 'bu.no' => 1,
4201
- 'fm.no' => 1,
4202
- 'hl.no' => 1,
4203
- 'hm.no' => 1,
4204
- 'jan-mayen.no' => 1,
4205
- 'mr.no' => 1,
4206
- 'nl.no' => 1,
4207
- 'nt.no' => 1,
4208
- 'of.no' => 1,
4209
- 'ol.no' => 1,
4210
- 'oslo.no' => 1,
4211
- 'rl.no' => 1,
4212
- 'sf.no' => 1,
4213
- 'st.no' => 1,
4214
- 'svalbard.no' => 1,
4215
- 'tm.no' => 1,
4216
- 'tr.no' => 1,
4217
- 'va.no' => 1,
4218
- 'vf.no' => 1,
4219
- 'gs.aa.no' => 1,
4220
- 'gs.ah.no' => 1,
4221
- 'gs.bu.no' => 1,
4222
- 'gs.fm.no' => 1,
4223
- 'gs.hl.no' => 1,
4224
- 'gs.hm.no' => 1,
4225
- 'gs.jan-mayen.no' => 1,
4226
- 'gs.mr.no' => 1,
4227
- 'gs.nl.no' => 1,
4228
- 'gs.nt.no' => 1,
4229
- 'gs.of.no' => 1,
4230
- 'gs.ol.no' => 1,
4231
- 'gs.oslo.no' => 1,
4232
- 'gs.rl.no' => 1,
4233
- 'gs.sf.no' => 1,
4234
- 'gs.st.no' => 1,
4235
- 'gs.svalbard.no' => 1,
4236
- 'gs.tm.no' => 1,
4237
- 'gs.tr.no' => 1,
4238
- 'gs.va.no' => 1,
4239
- 'gs.vf.no' => 1,
4240
- 'akrehamn.no' => 1,
4241
- 'åkrehamn.no' => 1,
4242
- 'algard.no' => 1,
4243
- 'ålgård.no' => 1,
4244
- 'arna.no' => 1,
4245
- 'brumunddal.no' => 1,
4246
- 'bryne.no' => 1,
4247
- 'bronnoysund.no' => 1,
4248
- 'brønnøysund.no' => 1,
4249
- 'drobak.no' => 1,
4250
- 'drøbak.no' => 1,
4251
- 'egersund.no' => 1,
4252
- 'fetsund.no' => 1,
4253
- 'floro.no' => 1,
4254
- 'florø.no' => 1,
4255
- 'fredrikstad.no' => 1,
4256
- 'hokksund.no' => 1,
4257
- 'honefoss.no' => 1,
4258
- 'hønefoss.no' => 1,
4259
- 'jessheim.no' => 1,
4260
- 'jorpeland.no' => 1,
4261
- 'jørpeland.no' => 1,
4262
- 'kirkenes.no' => 1,
4263
- 'kopervik.no' => 1,
4264
- 'krokstadelva.no' => 1,
4265
- 'langevag.no' => 1,
4266
- 'langevåg.no' => 1,
4267
- 'leirvik.no' => 1,
4268
- 'mjondalen.no' => 1,
4269
- 'mjøndalen.no' => 1,
4270
- 'mo-i-rana.no' => 1,
4271
- 'mosjoen.no' => 1,
4272
- 'mosjøen.no' => 1,
4273
- 'nesoddtangen.no' => 1,
4274
- 'orkanger.no' => 1,
4275
- 'osoyro.no' => 1,
4276
- 'osøyro.no' => 1,
4277
- 'raholt.no' => 1,
4278
- 'råholt.no' => 1,
4279
- 'sandnessjoen.no' => 1,
4280
- 'sandnessjøen.no' => 1,
4281
- 'skedsmokorset.no' => 1,
4282
- 'slattum.no' => 1,
4283
- 'spjelkavik.no' => 1,
4284
- 'stathelle.no' => 1,
4285
- 'stavern.no' => 1,
4286
- 'stjordalshalsen.no' => 1,
4287
- 'stjørdalshalsen.no' => 1,
4288
- 'tananger.no' => 1,
4289
- 'tranby.no' => 1,
4290
- 'vossevangen.no' => 1,
4291
- 'afjord.no' => 1,
4292
- 'åfjord.no' => 1,
4293
- 'agdenes.no' => 1,
4294
- 'al.no' => 1,
4295
- 'ål.no' => 1,
4296
- 'alesund.no' => 1,
4297
- 'ålesund.no' => 1,
4298
- 'alstahaug.no' => 1,
4299
- 'alta.no' => 1,
4300
- 'áltá.no' => 1,
4301
- 'alaheadju.no' => 1,
4302
- 'álaheadju.no' => 1,
4303
- 'alvdal.no' => 1,
4304
- 'amli.no' => 1,
4305
- 'åmli.no' => 1,
4306
- 'amot.no' => 1,
4307
- 'åmot.no' => 1,
4308
- 'andebu.no' => 1,
4309
- 'andoy.no' => 1,
4310
- 'andøy.no' => 1,
4311
- 'andasuolo.no' => 1,
4312
- 'ardal.no' => 1,
4313
- 'årdal.no' => 1,
4314
- 'aremark.no' => 1,
4315
- 'arendal.no' => 1,
4316
- 'ås.no' => 1,
4317
- 'aseral.no' => 1,
4318
- 'åseral.no' => 1,
4319
- 'asker.no' => 1,
4320
- 'askim.no' => 1,
4321
- 'askvoll.no' => 1,
4322
- 'askoy.no' => 1,
4323
- 'askøy.no' => 1,
4324
- 'asnes.no' => 1,
4325
- 'åsnes.no' => 1,
4326
- 'audnedaln.no' => 1,
4327
- 'aukra.no' => 1,
4328
- 'aure.no' => 1,
4329
- 'aurland.no' => 1,
4330
- 'aurskog-holand.no' => 1,
4331
- 'aurskog-høland.no' => 1,
4332
- 'austevoll.no' => 1,
4333
- 'austrheim.no' => 1,
4334
- 'averoy.no' => 1,
4335
- 'averøy.no' => 1,
4336
- 'balestrand.no' => 1,
4337
- 'ballangen.no' => 1,
4338
- 'balat.no' => 1,
4339
- 'bálát.no' => 1,
4340
- 'balsfjord.no' => 1,
4341
- 'bahccavuotna.no' => 1,
4342
- 'báhccavuotna.no' => 1,
4343
- 'bamble.no' => 1,
4344
- 'bardu.no' => 1,
4345
- 'beardu.no' => 1,
4346
- 'beiarn.no' => 1,
4347
- 'bajddar.no' => 1,
4348
- 'bájddar.no' => 1,
4349
- 'baidar.no' => 1,
4350
- 'báidár.no' => 1,
4351
- 'berg.no' => 1,
4352
- 'bergen.no' => 1,
4353
- 'berlevag.no' => 1,
4354
- 'berlevåg.no' => 1,
4355
- 'bearalvahki.no' => 1,
4356
- 'bearalváhki.no' => 1,
4357
- 'bindal.no' => 1,
4358
- 'birkenes.no' => 1,
4359
- 'bjarkoy.no' => 1,
4360
- 'bjarkøy.no' => 1,
4361
- 'bjerkreim.no' => 1,
4362
- 'bjugn.no' => 1,
4363
- 'bodo.no' => 1,
4364
- 'bodø.no' => 1,
4365
- 'badaddja.no' => 1,
4366
- 'bådåddjå.no' => 1,
4367
- 'budejju.no' => 1,
4368
- 'bokn.no' => 1,
4369
- 'bremanger.no' => 1,
4370
- 'bronnoy.no' => 1,
4371
- 'brønnøy.no' => 1,
4372
- 'bygland.no' => 1,
4373
- 'bykle.no' => 1,
4374
- 'barum.no' => 1,
4375
- 'bærum.no' => 1,
4376
- 'bo.telemark.no' => 1,
4377
- 'bø.telemark.no' => 1,
4378
- 'bo.nordland.no' => 1,
4379
- 'bø.nordland.no' => 1,
4380
- 'bievat.no' => 1,
4381
- 'bievát.no' => 1,
4382
- 'bomlo.no' => 1,
4383
- 'bømlo.no' => 1,
4384
- 'batsfjord.no' => 1,
4385
- 'båtsfjord.no' => 1,
4386
- 'bahcavuotna.no' => 1,
4387
- 'báhcavuotna.no' => 1,
4388
- 'dovre.no' => 1,
4389
- 'drammen.no' => 1,
4390
- 'drangedal.no' => 1,
4391
- 'dyroy.no' => 1,
4392
- 'dyrøy.no' => 1,
4393
- 'donna.no' => 1,
4394
- 'dønna.no' => 1,
4395
- 'eid.no' => 1,
4396
- 'eidfjord.no' => 1,
4397
- 'eidsberg.no' => 1,
4398
- 'eidskog.no' => 1,
4399
- 'eidsvoll.no' => 1,
4400
- 'eigersund.no' => 1,
4401
- 'elverum.no' => 1,
4402
- 'enebakk.no' => 1,
4403
- 'engerdal.no' => 1,
4404
- 'etne.no' => 1,
4405
- 'etnedal.no' => 1,
4406
- 'evenes.no' => 1,
4407
- 'evenassi.no' => 1,
4408
- 'evenášši.no' => 1,
4409
- 'evje-og-hornnes.no' => 1,
4410
- 'farsund.no' => 1,
4411
- 'fauske.no' => 1,
4412
- 'fuossko.no' => 1,
4413
- 'fuoisku.no' => 1,
4414
- 'fedje.no' => 1,
4415
- 'fet.no' => 1,
4416
- 'finnoy.no' => 1,
4417
- 'finnøy.no' => 1,
4418
- 'fitjar.no' => 1,
4419
- 'fjaler.no' => 1,
4420
- 'fjell.no' => 1,
4421
- 'flakstad.no' => 1,
4422
- 'flatanger.no' => 1,
4423
- 'flekkefjord.no' => 1,
4424
- 'flesberg.no' => 1,
4425
- 'flora.no' => 1,
4426
- 'fla.no' => 1,
4427
- 'flå.no' => 1,
4428
- 'folldal.no' => 1,
4429
- 'forsand.no' => 1,
4430
- 'fosnes.no' => 1,
4431
- 'frei.no' => 1,
4432
- 'frogn.no' => 1,
4433
- 'froland.no' => 1,
4434
- 'frosta.no' => 1,
4435
- 'frana.no' => 1,
4436
- 'fræna.no' => 1,
4437
- 'froya.no' => 1,
4438
- 'frøya.no' => 1,
4439
- 'fusa.no' => 1,
4440
- 'fyresdal.no' => 1,
4441
- 'forde.no' => 1,
4442
- 'førde.no' => 1,
4443
- 'gamvik.no' => 1,
4444
- 'gangaviika.no' => 1,
4445
- 'gáŋgaviika.no' => 1,
4446
- 'gaular.no' => 1,
4447
- 'gausdal.no' => 1,
4448
- 'gildeskal.no' => 1,
4449
- 'gildeskål.no' => 1,
4450
- 'giske.no' => 1,
4451
- 'gjemnes.no' => 1,
4452
- 'gjerdrum.no' => 1,
4453
- 'gjerstad.no' => 1,
4454
- 'gjesdal.no' => 1,
4455
- 'gjovik.no' => 1,
4456
- 'gjøvik.no' => 1,
4457
- 'gloppen.no' => 1,
4458
- 'gol.no' => 1,
4459
- 'gran.no' => 1,
4460
- 'grane.no' => 1,
4461
- 'granvin.no' => 1,
4462
- 'gratangen.no' => 1,
4463
- 'grimstad.no' => 1,
4464
- 'grong.no' => 1,
4465
- 'kraanghke.no' => 1,
4466
- 'kråanghke.no' => 1,
4467
- 'grue.no' => 1,
4468
- 'gulen.no' => 1,
4469
- 'hadsel.no' => 1,
4470
- 'halden.no' => 1,
4471
- 'halsa.no' => 1,
4472
- 'hamar.no' => 1,
4473
- 'hamaroy.no' => 1,
4474
- 'habmer.no' => 1,
4475
- 'hábmer.no' => 1,
4476
- 'hapmir.no' => 1,
4477
- 'hápmir.no' => 1,
4478
- 'hammerfest.no' => 1,
4479
- 'hammarfeasta.no' => 1,
4480
- 'hámmárfeasta.no' => 1,
4481
- 'haram.no' => 1,
4482
- 'hareid.no' => 1,
4483
- 'harstad.no' => 1,
4484
- 'hasvik.no' => 1,
4485
- 'aknoluokta.no' => 1,
4486
- 'ákŋoluokta.no' => 1,
4487
- 'hattfjelldal.no' => 1,
4488
- 'aarborte.no' => 1,
4489
- 'haugesund.no' => 1,
4490
- 'hemne.no' => 1,
4491
- 'hemnes.no' => 1,
4492
- 'hemsedal.no' => 1,
4493
- 'heroy.more-og-romsdal.no' => 1,
4494
- 'herøy.møre-og-romsdal.no' => 1,
4495
- 'heroy.nordland.no' => 1,
4496
- 'herøy.nordland.no' => 1,
4497
- 'hitra.no' => 1,
4498
- 'hjartdal.no' => 1,
4499
- 'hjelmeland.no' => 1,
4500
- 'hobol.no' => 1,
4501
- 'hobøl.no' => 1,
4502
- 'hof.no' => 1,
4503
- 'hol.no' => 1,
4504
- 'hole.no' => 1,
4505
- 'holmestrand.no' => 1,
4506
- 'holtalen.no' => 1,
4507
- 'holtålen.no' => 1,
4508
- 'hornindal.no' => 1,
4509
- 'horten.no' => 1,
4510
- 'hurdal.no' => 1,
4511
- 'hurum.no' => 1,
4512
- 'hvaler.no' => 1,
4513
- 'hyllestad.no' => 1,
4514
- 'hagebostad.no' => 1,
4515
- 'hægebostad.no' => 1,
4516
- 'hoyanger.no' => 1,
4517
- 'høyanger.no' => 1,
4518
- 'hoylandet.no' => 1,
4519
- 'høylandet.no' => 1,
4520
- 'ha.no' => 1,
4521
- 'hå.no' => 1,
4522
- 'ibestad.no' => 1,
4523
- 'inderoy.no' => 1,
4524
- 'inderøy.no' => 1,
4525
- 'iveland.no' => 1,
4526
- 'jevnaker.no' => 1,
4527
- 'jondal.no' => 1,
4528
- 'jolster.no' => 1,
4529
- 'jølster.no' => 1,
4530
- 'karasjok.no' => 1,
4531
- 'karasjohka.no' => 1,
4532
- 'kárášjohka.no' => 1,
4533
- 'karlsoy.no' => 1,
4534
- 'galsa.no' => 1,
4535
- 'gálsá.no' => 1,
4536
- 'karmoy.no' => 1,
4537
- 'karmøy.no' => 1,
4538
- 'kautokeino.no' => 1,
4539
- 'guovdageaidnu.no' => 1,
4540
- 'klepp.no' => 1,
4541
- 'klabu.no' => 1,
4542
- 'klæbu.no' => 1,
4543
- 'kongsberg.no' => 1,
4544
- 'kongsvinger.no' => 1,
4545
- 'kragero.no' => 1,
4546
- 'kragerø.no' => 1,
4547
- 'kristiansand.no' => 1,
4548
- 'kristiansund.no' => 1,
4549
- 'krodsherad.no' => 1,
4550
- 'krødsherad.no' => 1,
4551
- 'kvalsund.no' => 1,
4552
- 'rahkkeravju.no' => 1,
4553
- 'ráhkkerávju.no' => 1,
4554
- 'kvam.no' => 1,
4555
- 'kvinesdal.no' => 1,
4556
- 'kvinnherad.no' => 1,
4557
- 'kviteseid.no' => 1,
4558
- 'kvitsoy.no' => 1,
4559
- 'kvitsøy.no' => 1,
4560
- 'kvafjord.no' => 1,
4561
- 'kvæfjord.no' => 1,
4562
- 'giehtavuoatna.no' => 1,
4563
- 'kvanangen.no' => 1,
4564
- 'kvænangen.no' => 1,
4565
- 'navuotna.no' => 1,
4566
- 'návuotna.no' => 1,
4567
- 'kafjord.no' => 1,
4568
- 'kåfjord.no' => 1,
4569
- 'gaivuotna.no' => 1,
4570
- 'gáivuotna.no' => 1,
4571
- 'larvik.no' => 1,
4572
- 'lavangen.no' => 1,
4573
- 'lavagis.no' => 1,
4574
- 'loabat.no' => 1,
4575
- 'loabát.no' => 1,
4576
- 'lebesby.no' => 1,
4577
- 'davvesiida.no' => 1,
4578
- 'leikanger.no' => 1,
4579
- 'leirfjord.no' => 1,
4580
- 'leka.no' => 1,
4581
- 'leksvik.no' => 1,
4582
- 'lenvik.no' => 1,
4583
- 'leangaviika.no' => 1,
4584
- 'leaŋgaviika.no' => 1,
4585
- 'lesja.no' => 1,
4586
- 'levanger.no' => 1,
4587
- 'lier.no' => 1,
4588
- 'lierne.no' => 1,
4589
- 'lillehammer.no' => 1,
4590
- 'lillesand.no' => 1,
4591
- 'lindesnes.no' => 1,
4592
- 'lindas.no' => 1,
4593
- 'lindås.no' => 1,
4594
- 'lom.no' => 1,
4595
- 'loppa.no' => 1,
4596
- 'lahppi.no' => 1,
4597
- 'láhppi.no' => 1,
4598
- 'lund.no' => 1,
4599
- 'lunner.no' => 1,
4600
- 'luroy.no' => 1,
4601
- 'lurøy.no' => 1,
4602
- 'luster.no' => 1,
4603
- 'lyngdal.no' => 1,
4604
- 'lyngen.no' => 1,
4605
- 'ivgu.no' => 1,
4606
- 'lardal.no' => 1,
4607
- 'lerdal.no' => 1,
4608
- 'lærdal.no' => 1,
4609
- 'lodingen.no' => 1,
4610
- 'lødingen.no' => 1,
4611
- 'lorenskog.no' => 1,
4612
- 'lørenskog.no' => 1,
4613
- 'loten.no' => 1,
4614
- 'løten.no' => 1,
4615
- 'malvik.no' => 1,
4616
- 'masoy.no' => 1,
4617
- 'måsøy.no' => 1,
4618
- 'muosat.no' => 1,
4619
- 'muosát.no' => 1,
4620
- 'mandal.no' => 1,
4621
- 'marker.no' => 1,
4622
- 'marnardal.no' => 1,
4623
- 'masfjorden.no' => 1,
4624
- 'meland.no' => 1,
4625
- 'meldal.no' => 1,
4626
- 'melhus.no' => 1,
4627
- 'meloy.no' => 1,
4628
- 'meløy.no' => 1,
4629
- 'meraker.no' => 1,
4630
- 'meråker.no' => 1,
4631
- 'moareke.no' => 1,
4632
- 'moåreke.no' => 1,
4633
- 'midsund.no' => 1,
4634
- 'midtre-gauldal.no' => 1,
4635
- 'modalen.no' => 1,
4636
- 'modum.no' => 1,
4637
- 'molde.no' => 1,
4638
- 'moskenes.no' => 1,
4639
- 'moss.no' => 1,
4640
- 'mosvik.no' => 1,
4641
- 'malselv.no' => 1,
4642
- 'målselv.no' => 1,
4643
- 'malatvuopmi.no' => 1,
4644
- 'málatvuopmi.no' => 1,
4645
- 'namdalseid.no' => 1,
4646
- 'aejrie.no' => 1,
4647
- 'namsos.no' => 1,
4648
- 'namsskogan.no' => 1,
4649
- 'naamesjevuemie.no' => 1,
4650
- 'nååmesjevuemie.no' => 1,
4651
- 'laakesvuemie.no' => 1,
4652
- 'nannestad.no' => 1,
4653
- 'narvik.no' => 1,
4654
- 'narviika.no' => 1,
4655
- 'naustdal.no' => 1,
4656
- 'nedre-eiker.no' => 1,
4657
- 'nes.akershus.no' => 1,
4658
- 'nes.buskerud.no' => 1,
4659
- 'nesna.no' => 1,
4660
- 'nesodden.no' => 1,
4661
- 'nesseby.no' => 1,
4662
- 'unjarga.no' => 1,
4663
- 'unjárga.no' => 1,
4664
- 'nesset.no' => 1,
4665
- 'nissedal.no' => 1,
4666
- 'nittedal.no' => 1,
4667
- 'nord-aurdal.no' => 1,
4668
- 'nord-fron.no' => 1,
4669
- 'nord-odal.no' => 1,
4670
- 'norddal.no' => 1,
4671
- 'nordkapp.no' => 1,
4672
- 'davvenjarga.no' => 1,
4673
- 'davvenjárga.no' => 1,
4674
- 'nordre-land.no' => 1,
4675
- 'nordreisa.no' => 1,
4676
- 'raisa.no' => 1,
4677
- 'ráisa.no' => 1,
4678
- 'nore-og-uvdal.no' => 1,
4679
- 'notodden.no' => 1,
4680
- 'naroy.no' => 1,
4681
- 'nærøy.no' => 1,
4682
- 'notteroy.no' => 1,
4683
- 'nøtterøy.no' => 1,
4684
- 'odda.no' => 1,
4685
- 'oksnes.no' => 1,
4686
- 'øksnes.no' => 1,
4687
- 'oppdal.no' => 1,
4688
- 'oppegard.no' => 1,
4689
- 'oppegård.no' => 1,
4690
- 'orkdal.no' => 1,
4691
- 'orland.no' => 1,
4692
- 'ørland.no' => 1,
4693
- 'orskog.no' => 1,
4694
- 'ørskog.no' => 1,
4695
- 'orsta.no' => 1,
4696
- 'ørsta.no' => 1,
4697
- 'os.hedmark.no' => 1,
4698
- 'os.hordaland.no' => 1,
4699
- 'osen.no' => 1,
4700
- 'osteroy.no' => 1,
4701
- 'osterøy.no' => 1,
4702
- 'ostre-toten.no' => 1,
4703
- 'østre-toten.no' => 1,
4704
- 'overhalla.no' => 1,
4705
- 'ovre-eiker.no' => 1,
4706
- 'øvre-eiker.no' => 1,
4707
- 'oyer.no' => 1,
4708
- 'øyer.no' => 1,
4709
- 'oygarden.no' => 1,
4710
- 'øygarden.no' => 1,
4711
- 'oystre-slidre.no' => 1,
4712
- 'øystre-slidre.no' => 1,
4713
- 'porsanger.no' => 1,
4714
- 'porsangu.no' => 1,
4715
- 'porsáŋgu.no' => 1,
4716
- 'porsgrunn.no' => 1,
4717
- 'radoy.no' => 1,
4718
- 'radøy.no' => 1,
4719
- 'rakkestad.no' => 1,
4720
- 'rana.no' => 1,
4721
- 'ruovat.no' => 1,
4722
- 'randaberg.no' => 1,
4723
- 'rauma.no' => 1,
4724
- 'rendalen.no' => 1,
4725
- 'rennebu.no' => 1,
4726
- 'rennesoy.no' => 1,
4727
- 'rennesøy.no' => 1,
4728
- 'rindal.no' => 1,
4729
- 'ringebu.no' => 1,
4730
- 'ringerike.no' => 1,
4731
- 'ringsaker.no' => 1,
4732
- 'rissa.no' => 1,
4733
- 'risor.no' => 1,
4734
- 'risør.no' => 1,
4735
- 'roan.no' => 1,
4736
- 'rollag.no' => 1,
4737
- 'rygge.no' => 1,
4738
- 'ralingen.no' => 1,
4739
- 'rælingen.no' => 1,
4740
- 'rodoy.no' => 1,
4741
- 'rødøy.no' => 1,
4742
- 'romskog.no' => 1,
4743
- 'rømskog.no' => 1,
4744
- 'roros.no' => 1,
4745
- 'røros.no' => 1,
4746
- 'rost.no' => 1,
4747
- 'røst.no' => 1,
4748
- 'royken.no' => 1,
4749
- 'røyken.no' => 1,
4750
- 'royrvik.no' => 1,
4751
- 'røyrvik.no' => 1,
4752
- 'rade.no' => 1,
4753
- 'råde.no' => 1,
4754
- 'salangen.no' => 1,
4755
- 'siellak.no' => 1,
4756
- 'saltdal.no' => 1,
4757
- 'salat.no' => 1,
4758
- 'sálát.no' => 1,
4759
- 'sálat.no' => 1,
4760
- 'samnanger.no' => 1,
4761
- 'sande.more-og-romsdal.no' => 1,
4762
- 'sande.møre-og-romsdal.no' => 1,
4763
- 'sande.vestfold.no' => 1,
4764
- 'sandefjord.no' => 1,
4765
- 'sandnes.no' => 1,
4766
- 'sandoy.no' => 1,
4767
- 'sandøy.no' => 1,
4768
- 'sarpsborg.no' => 1,
4769
- 'sauda.no' => 1,
4770
- 'sauherad.no' => 1,
4771
- 'sel.no' => 1,
4772
- 'selbu.no' => 1,
4773
- 'selje.no' => 1,
4774
- 'seljord.no' => 1,
4775
- 'sigdal.no' => 1,
4776
- 'siljan.no' => 1,
4777
- 'sirdal.no' => 1,
4778
- 'skaun.no' => 1,
4779
- 'skedsmo.no' => 1,
4780
- 'ski.no' => 1,
4781
- 'skien.no' => 1,
4782
- 'skiptvet.no' => 1,
4783
- 'skjervoy.no' => 1,
4784
- 'skjervøy.no' => 1,
4785
- 'skierva.no' => 1,
4786
- 'skiervá.no' => 1,
4787
- 'skjak.no' => 1,
4788
- 'skjåk.no' => 1,
4789
- 'skodje.no' => 1,
4790
- 'skanland.no' => 1,
4791
- 'skånland.no' => 1,
4792
- 'skanit.no' => 1,
4793
- 'skánit.no' => 1,
4794
- 'smola.no' => 1,
4795
- 'smøla.no' => 1,
4796
- 'snillfjord.no' => 1,
4797
- 'snasa.no' => 1,
4798
- 'snåsa.no' => 1,
4799
- 'snoasa.no' => 1,
4800
- 'snaase.no' => 1,
4801
- 'snåase.no' => 1,
4802
- 'sogndal.no' => 1,
4803
- 'sokndal.no' => 1,
4804
- 'sola.no' => 1,
4805
- 'solund.no' => 1,
4806
- 'songdalen.no' => 1,
4807
- 'sortland.no' => 1,
4808
- 'spydeberg.no' => 1,
4809
- 'stange.no' => 1,
4810
- 'stavanger.no' => 1,
4811
- 'steigen.no' => 1,
4812
- 'steinkjer.no' => 1,
4813
- 'stjordal.no' => 1,
4814
- 'stjørdal.no' => 1,
4815
- 'stokke.no' => 1,
4816
- 'stor-elvdal.no' => 1,
4817
- 'stord.no' => 1,
4818
- 'stordal.no' => 1,
4819
- 'storfjord.no' => 1,
4820
- 'omasvuotna.no' => 1,
4821
- 'strand.no' => 1,
4822
- 'stranda.no' => 1,
4823
- 'stryn.no' => 1,
4824
- 'sula.no' => 1,
4825
- 'suldal.no' => 1,
4826
- 'sund.no' => 1,
4827
- 'sunndal.no' => 1,
4828
- 'surnadal.no' => 1,
4829
- 'sveio.no' => 1,
4830
- 'svelvik.no' => 1,
4831
- 'sykkylven.no' => 1,
4832
- 'sogne.no' => 1,
4833
- 'søgne.no' => 1,
4834
- 'somna.no' => 1,
4835
- 'sømna.no' => 1,
4836
- 'sondre-land.no' => 1,
4837
- 'søndre-land.no' => 1,
4838
- 'sor-aurdal.no' => 1,
4839
- 'sør-aurdal.no' => 1,
4840
- 'sor-fron.no' => 1,
4841
- 'sør-fron.no' => 1,
4842
- 'sor-odal.no' => 1,
4843
- 'sør-odal.no' => 1,
4844
- 'sor-varanger.no' => 1,
4845
- 'sør-varanger.no' => 1,
4846
- 'matta-varjjat.no' => 1,
4847
- 'mátta-várjjat.no' => 1,
4848
- 'sorfold.no' => 1,
4849
- 'sørfold.no' => 1,
4850
- 'sorreisa.no' => 1,
4851
- 'sørreisa.no' => 1,
4852
- 'sorum.no' => 1,
4853
- 'sørum.no' => 1,
4854
- 'tana.no' => 1,
4855
- 'deatnu.no' => 1,
4856
- 'time.no' => 1,
4857
- 'tingvoll.no' => 1,
4858
- 'tinn.no' => 1,
4859
- 'tjeldsund.no' => 1,
4860
- 'dielddanuorri.no' => 1,
4861
- 'tjome.no' => 1,
4862
- 'tjøme.no' => 1,
4863
- 'tokke.no' => 1,
4864
- 'tolga.no' => 1,
4865
- 'torsken.no' => 1,
4866
- 'tranoy.no' => 1,
4867
- 'tranøy.no' => 1,
4868
- 'tromso.no' => 1,
4869
- 'tromsø.no' => 1,
4870
- 'tromsa.no' => 1,
4871
- 'romsa.no' => 1,
4872
- 'trondheim.no' => 1,
4873
- 'troandin.no' => 1,
4874
- 'trysil.no' => 1,
4875
- 'trana.no' => 1,
4876
- 'træna.no' => 1,
4877
- 'trogstad.no' => 1,
4878
- 'trøgstad.no' => 1,
4879
- 'tvedestrand.no' => 1,
4880
- 'tydal.no' => 1,
4881
- 'tynset.no' => 1,
4882
- 'tysfjord.no' => 1,
4883
- 'divtasvuodna.no' => 1,
4884
- 'divttasvuotna.no' => 1,
4885
- 'tysnes.no' => 1,
4886
- 'tysvar.no' => 1,
4887
- 'tysvær.no' => 1,
4888
- 'tonsberg.no' => 1,
4889
- 'tønsberg.no' => 1,
4890
- 'ullensaker.no' => 1,
4891
- 'ullensvang.no' => 1,
4892
- 'ulvik.no' => 1,
4893
- 'utsira.no' => 1,
4894
- 'vadso.no' => 1,
4895
- 'vadsø.no' => 1,
4896
- 'cahcesuolo.no' => 1,
4897
- 'čáhcesuolo.no' => 1,
4898
- 'vaksdal.no' => 1,
4899
- 'valle.no' => 1,
4900
- 'vang.no' => 1,
4901
- 'vanylven.no' => 1,
4902
- 'vardo.no' => 1,
4903
- 'vardø.no' => 1,
4904
- 'varggat.no' => 1,
4905
- 'várggát.no' => 1,
4906
- 'vefsn.no' => 1,
4907
- 'vaapste.no' => 1,
4908
- 'vega.no' => 1,
4909
- 'vegarshei.no' => 1,
4910
- 'vegårshei.no' => 1,
4911
- 'vennesla.no' => 1,
4912
- 'verdal.no' => 1,
4913
- 'verran.no' => 1,
4914
- 'vestby.no' => 1,
4915
- 'vestnes.no' => 1,
4916
- 'vestre-slidre.no' => 1,
4917
- 'vestre-toten.no' => 1,
4918
- 'vestvagoy.no' => 1,
4919
- 'vestvågøy.no' => 1,
4920
- 'vevelstad.no' => 1,
4921
- 'vik.no' => 1,
4922
- 'vikna.no' => 1,
4923
- 'vindafjord.no' => 1,
4924
- 'volda.no' => 1,
4925
- 'voss.no' => 1,
4926
- 'varoy.no' => 1,
4927
- 'værøy.no' => 1,
4928
- 'vagan.no' => 1,
4929
- 'vågan.no' => 1,
4930
- 'voagat.no' => 1,
4931
- 'vagsoy.no' => 1,
4932
- 'vågsøy.no' => 1,
4933
- 'vaga.no' => 1,
4934
- 'vågå.no' => 1,
4935
- 'valer.ostfold.no' => 1,
4936
- 'våler.østfold.no' => 1,
4937
- 'valer.hedmark.no' => 1,
4938
- 'våler.hedmark.no' => 1,
4939
- '*.np' => 1,
4940
- 'nr' => 1,
4941
- 'biz.nr' => 1,
4942
- 'info.nr' => 1,
4943
- 'gov.nr' => 1,
4944
- 'edu.nr' => 1,
4945
- 'org.nr' => 1,
4946
- 'net.nr' => 1,
4947
- 'com.nr' => 1,
4948
- 'nu' => 1,
4949
- 'nz' => 1,
4950
- 'ac.nz' => 1,
4951
- 'co.nz' => 1,
4952
- 'cri.nz' => 1,
4953
- 'geek.nz' => 1,
4954
- 'gen.nz' => 1,
4955
- 'govt.nz' => 1,
4956
- 'health.nz' => 1,
4957
- 'iwi.nz' => 1,
4958
- 'kiwi.nz' => 1,
4959
- 'maori.nz' => 1,
4960
- 'mil.nz' => 1,
4961
- 'māori.nz' => 1,
4962
- 'net.nz' => 1,
4963
- 'org.nz' => 1,
4964
- 'parliament.nz' => 1,
4965
- 'school.nz' => 1,
4966
- 'om' => 1,
4967
- 'co.om' => 1,
4968
- 'com.om' => 1,
4969
- 'edu.om' => 1,
4970
- 'gov.om' => 1,
4971
- 'med.om' => 1,
4972
- 'museum.om' => 1,
4973
- 'net.om' => 1,
4974
- 'org.om' => 1,
4975
- 'pro.om' => 1,
4976
- 'onion' => 1,
4977
- 'org' => 1,
4978
- 'pa' => 1,
4979
- 'ac.pa' => 1,
4980
- 'gob.pa' => 1,
4981
- 'com.pa' => 1,
4982
- 'org.pa' => 1,
4983
- 'sld.pa' => 1,
4984
- 'edu.pa' => 1,
4985
- 'net.pa' => 1,
4986
- 'ing.pa' => 1,
4987
- 'abo.pa' => 1,
4988
- 'med.pa' => 1,
4989
- 'nom.pa' => 1,
4990
- 'pe' => 1,
4991
- 'edu.pe' => 1,
4992
- 'gob.pe' => 1,
4993
- 'nom.pe' => 1,
4994
- 'mil.pe' => 1,
4995
- 'org.pe' => 1,
4996
- 'com.pe' => 1,
4997
- 'net.pe' => 1,
4998
- 'pf' => 1,
4999
- 'com.pf' => 1,
5000
- 'org.pf' => 1,
5001
- 'edu.pf' => 1,
5002
- '*.pg' => 1,
5003
- 'ph' => 1,
5004
- 'com.ph' => 1,
5005
- 'net.ph' => 1,
5006
- 'org.ph' => 1,
5007
- 'gov.ph' => 1,
5008
- 'edu.ph' => 1,
5009
- 'ngo.ph' => 1,
5010
- 'mil.ph' => 1,
5011
- 'i.ph' => 1,
5012
- 'pk' => 1,
5013
- 'com.pk' => 1,
5014
- 'net.pk' => 1,
5015
- 'edu.pk' => 1,
5016
- 'org.pk' => 1,
5017
- 'fam.pk' => 1,
5018
- 'biz.pk' => 1,
5019
- 'web.pk' => 1,
5020
- 'gov.pk' => 1,
5021
- 'gob.pk' => 1,
5022
- 'gok.pk' => 1,
5023
- 'gon.pk' => 1,
5024
- 'gop.pk' => 1,
5025
- 'gos.pk' => 1,
5026
- 'info.pk' => 1,
5027
- 'pl' => 1,
5028
- 'com.pl' => 1,
5029
- 'net.pl' => 1,
5030
- 'org.pl' => 1,
5031
- 'aid.pl' => 1,
5032
- 'agro.pl' => 1,
5033
- 'atm.pl' => 1,
5034
- 'auto.pl' => 1,
5035
- 'biz.pl' => 1,
5036
- 'edu.pl' => 1,
5037
- 'gmina.pl' => 1,
5038
- 'gsm.pl' => 1,
5039
- 'info.pl' => 1,
5040
- 'mail.pl' => 1,
5041
- 'miasta.pl' => 1,
5042
- 'media.pl' => 1,
5043
- 'mil.pl' => 1,
5044
- 'nieruchomosci.pl' => 1,
5045
- 'nom.pl' => 1,
5046
- 'pc.pl' => 1,
5047
- 'powiat.pl' => 1,
5048
- 'priv.pl' => 1,
5049
- 'realestate.pl' => 1,
5050
- 'rel.pl' => 1,
5051
- 'sex.pl' => 1,
5052
- 'shop.pl' => 1,
5053
- 'sklep.pl' => 1,
5054
- 'sos.pl' => 1,
5055
- 'szkola.pl' => 1,
5056
- 'targi.pl' => 1,
5057
- 'tm.pl' => 1,
5058
- 'tourism.pl' => 1,
5059
- 'travel.pl' => 1,
5060
- 'turystyka.pl' => 1,
5061
- 'gov.pl' => 1,
5062
- 'ap.gov.pl' => 1,
5063
- 'ic.gov.pl' => 1,
5064
- 'is.gov.pl' => 1,
5065
- 'us.gov.pl' => 1,
5066
- 'kmpsp.gov.pl' => 1,
5067
- 'kppsp.gov.pl' => 1,
5068
- 'kwpsp.gov.pl' => 1,
5069
- 'psp.gov.pl' => 1,
5070
- 'wskr.gov.pl' => 1,
5071
- 'kwp.gov.pl' => 1,
5072
- 'mw.gov.pl' => 1,
5073
- 'ug.gov.pl' => 1,
5074
- 'um.gov.pl' => 1,
5075
- 'umig.gov.pl' => 1,
5076
- 'ugim.gov.pl' => 1,
5077
- 'upow.gov.pl' => 1,
5078
- 'uw.gov.pl' => 1,
5079
- 'starostwo.gov.pl' => 1,
5080
- 'pa.gov.pl' => 1,
5081
- 'po.gov.pl' => 1,
5082
- 'psse.gov.pl' => 1,
5083
- 'pup.gov.pl' => 1,
5084
- 'rzgw.gov.pl' => 1,
5085
- 'sa.gov.pl' => 1,
5086
- 'so.gov.pl' => 1,
5087
- 'sr.gov.pl' => 1,
5088
- 'wsa.gov.pl' => 1,
5089
- 'sko.gov.pl' => 1,
5090
- 'uzs.gov.pl' => 1,
5091
- 'wiih.gov.pl' => 1,
5092
- 'winb.gov.pl' => 1,
5093
- 'pinb.gov.pl' => 1,
5094
- 'wios.gov.pl' => 1,
5095
- 'witd.gov.pl' => 1,
5096
- 'wzmiuw.gov.pl' => 1,
5097
- 'piw.gov.pl' => 1,
5098
- 'wiw.gov.pl' => 1,
5099
- 'griw.gov.pl' => 1,
5100
- 'wif.gov.pl' => 1,
5101
- 'oum.gov.pl' => 1,
5102
- 'sdn.gov.pl' => 1,
5103
- 'zp.gov.pl' => 1,
5104
- 'uppo.gov.pl' => 1,
5105
- 'mup.gov.pl' => 1,
5106
- 'wuoz.gov.pl' => 1,
5107
- 'konsulat.gov.pl' => 1,
5108
- 'oirm.gov.pl' => 1,
5109
- 'augustow.pl' => 1,
5110
- 'babia-gora.pl' => 1,
5111
- 'bedzin.pl' => 1,
5112
- 'beskidy.pl' => 1,
5113
- 'bialowieza.pl' => 1,
5114
- 'bialystok.pl' => 1,
5115
- 'bielawa.pl' => 1,
5116
- 'bieszczady.pl' => 1,
5117
- 'boleslawiec.pl' => 1,
5118
- 'bydgoszcz.pl' => 1,
5119
- 'bytom.pl' => 1,
5120
- 'cieszyn.pl' => 1,
5121
- 'czeladz.pl' => 1,
5122
- 'czest.pl' => 1,
5123
- 'dlugoleka.pl' => 1,
5124
- 'elblag.pl' => 1,
5125
- 'elk.pl' => 1,
5126
- 'glogow.pl' => 1,
5127
- 'gniezno.pl' => 1,
5128
- 'gorlice.pl' => 1,
5129
- 'grajewo.pl' => 1,
5130
- 'ilawa.pl' => 1,
5131
- 'jaworzno.pl' => 1,
5132
- 'jelenia-gora.pl' => 1,
5133
- 'jgora.pl' => 1,
5134
- 'kalisz.pl' => 1,
5135
- 'kazimierz-dolny.pl' => 1,
5136
- 'karpacz.pl' => 1,
5137
- 'kartuzy.pl' => 1,
5138
- 'kaszuby.pl' => 1,
5139
- 'katowice.pl' => 1,
5140
- 'kepno.pl' => 1,
5141
- 'ketrzyn.pl' => 1,
5142
- 'klodzko.pl' => 1,
5143
- 'kobierzyce.pl' => 1,
5144
- 'kolobrzeg.pl' => 1,
5145
- 'konin.pl' => 1,
5146
- 'konskowola.pl' => 1,
5147
- 'kutno.pl' => 1,
5148
- 'lapy.pl' => 1,
5149
- 'lebork.pl' => 1,
5150
- 'legnica.pl' => 1,
5151
- 'lezajsk.pl' => 1,
5152
- 'limanowa.pl' => 1,
5153
- 'lomza.pl' => 1,
5154
- 'lowicz.pl' => 1,
5155
- 'lubin.pl' => 1,
5156
- 'lukow.pl' => 1,
5157
- 'malbork.pl' => 1,
5158
- 'malopolska.pl' => 1,
5159
- 'mazowsze.pl' => 1,
5160
- 'mazury.pl' => 1,
5161
- 'mielec.pl' => 1,
5162
- 'mielno.pl' => 1,
5163
- 'mragowo.pl' => 1,
5164
- 'naklo.pl' => 1,
5165
- 'nowaruda.pl' => 1,
5166
- 'nysa.pl' => 1,
5167
- 'olawa.pl' => 1,
5168
- 'olecko.pl' => 1,
5169
- 'olkusz.pl' => 1,
5170
- 'olsztyn.pl' => 1,
5171
- 'opoczno.pl' => 1,
5172
- 'opole.pl' => 1,
5173
- 'ostroda.pl' => 1,
5174
- 'ostroleka.pl' => 1,
5175
- 'ostrowiec.pl' => 1,
5176
- 'ostrowwlkp.pl' => 1,
5177
- 'pila.pl' => 1,
5178
- 'pisz.pl' => 1,
5179
- 'podhale.pl' => 1,
5180
- 'podlasie.pl' => 1,
5181
- 'polkowice.pl' => 1,
5182
- 'pomorze.pl' => 1,
5183
- 'pomorskie.pl' => 1,
5184
- 'prochowice.pl' => 1,
5185
- 'pruszkow.pl' => 1,
5186
- 'przeworsk.pl' => 1,
5187
- 'pulawy.pl' => 1,
5188
- 'radom.pl' => 1,
5189
- 'rawa-maz.pl' => 1,
5190
- 'rybnik.pl' => 1,
5191
- 'rzeszow.pl' => 1,
5192
- 'sanok.pl' => 1,
5193
- 'sejny.pl' => 1,
5194
- 'slask.pl' => 1,
5195
- 'slupsk.pl' => 1,
5196
- 'sosnowiec.pl' => 1,
5197
- 'stalowa-wola.pl' => 1,
5198
- 'skoczow.pl' => 1,
5199
- 'starachowice.pl' => 1,
5200
- 'stargard.pl' => 1,
5201
- 'suwalki.pl' => 1,
5202
- 'swidnica.pl' => 1,
5203
- 'swiebodzin.pl' => 1,
5204
- 'swinoujscie.pl' => 1,
5205
- 'szczecin.pl' => 1,
5206
- 'szczytno.pl' => 1,
5207
- 'tarnobrzeg.pl' => 1,
5208
- 'tgory.pl' => 1,
5209
- 'turek.pl' => 1,
5210
- 'tychy.pl' => 1,
5211
- 'ustka.pl' => 1,
5212
- 'walbrzych.pl' => 1,
5213
- 'warmia.pl' => 1,
5214
- 'warszawa.pl' => 1,
5215
- 'waw.pl' => 1,
5216
- 'wegrow.pl' => 1,
5217
- 'wielun.pl' => 1,
5218
- 'wlocl.pl' => 1,
5219
- 'wloclawek.pl' => 1,
5220
- 'wodzislaw.pl' => 1,
5221
- 'wolomin.pl' => 1,
5222
- 'wroclaw.pl' => 1,
5223
- 'zachpomor.pl' => 1,
5224
- 'zagan.pl' => 1,
5225
- 'zarow.pl' => 1,
5226
- 'zgora.pl' => 1,
5227
- 'zgorzelec.pl' => 1,
5228
- 'pm' => 1,
5229
- 'pn' => 1,
5230
- 'gov.pn' => 1,
5231
- 'co.pn' => 1,
5232
- 'org.pn' => 1,
5233
- 'edu.pn' => 1,
5234
- 'net.pn' => 1,
5235
- 'post' => 1,
5236
- 'pr' => 1,
5237
- 'com.pr' => 1,
5238
- 'net.pr' => 1,
5239
- 'org.pr' => 1,
5240
- 'gov.pr' => 1,
5241
- 'edu.pr' => 1,
5242
- 'isla.pr' => 1,
5243
- 'pro.pr' => 1,
5244
- 'biz.pr' => 1,
5245
- 'info.pr' => 1,
5246
- 'name.pr' => 1,
5247
- 'est.pr' => 1,
5248
- 'prof.pr' => 1,
5249
- 'ac.pr' => 1,
5250
- 'pro' => 1,
5251
- 'aaa.pro' => 1,
5252
- 'aca.pro' => 1,
5253
- 'acct.pro' => 1,
5254
- 'avocat.pro' => 1,
5255
- 'bar.pro' => 1,
5256
- 'cpa.pro' => 1,
5257
- 'eng.pro' => 1,
5258
- 'jur.pro' => 1,
5259
- 'law.pro' => 1,
5260
- 'med.pro' => 1,
5261
- 'recht.pro' => 1,
5262
- 'ps' => 1,
5263
- 'edu.ps' => 1,
5264
- 'gov.ps' => 1,
5265
- 'sec.ps' => 1,
5266
- 'plo.ps' => 1,
5267
- 'com.ps' => 1,
5268
- 'org.ps' => 1,
5269
- 'net.ps' => 1,
5270
- 'pt' => 1,
5271
- 'net.pt' => 1,
5272
- 'gov.pt' => 1,
5273
- 'org.pt' => 1,
5274
- 'edu.pt' => 1,
5275
- 'int.pt' => 1,
5276
- 'publ.pt' => 1,
5277
- 'com.pt' => 1,
5278
- 'nome.pt' => 1,
5279
- 'pw' => 1,
5280
- 'co.pw' => 1,
5281
- 'ne.pw' => 1,
5282
- 'or.pw' => 1,
5283
- 'ed.pw' => 1,
5284
- 'go.pw' => 1,
5285
- 'belau.pw' => 1,
5286
- 'py' => 1,
5287
- 'com.py' => 1,
5288
- 'coop.py' => 1,
5289
- 'edu.py' => 1,
5290
- 'gov.py' => 1,
5291
- 'mil.py' => 1,
5292
- 'net.py' => 1,
5293
- 'org.py' => 1,
5294
- 'qa' => 1,
5295
- 'com.qa' => 1,
5296
- 'edu.qa' => 1,
5297
- 'gov.qa' => 1,
5298
- 'mil.qa' => 1,
5299
- 'name.qa' => 1,
5300
- 'net.qa' => 1,
5301
- 'org.qa' => 1,
5302
- 'sch.qa' => 1,
5303
- 're' => 1,
5304
- 'asso.re' => 1,
5305
- 'com.re' => 1,
5306
- 'nom.re' => 1,
5307
- 'ro' => 1,
5308
- 'arts.ro' => 1,
5309
- 'com.ro' => 1,
5310
- 'firm.ro' => 1,
5311
- 'info.ro' => 1,
5312
- 'nom.ro' => 1,
5313
- 'nt.ro' => 1,
5314
- 'org.ro' => 1,
5315
- 'rec.ro' => 1,
5316
- 'store.ro' => 1,
5317
- 'tm.ro' => 1,
5318
- 'www.ro' => 1,
5319
- 'rs' => 1,
5320
- 'ac.rs' => 1,
5321
- 'co.rs' => 1,
5322
- 'edu.rs' => 1,
5323
- 'gov.rs' => 1,
5324
- 'in.rs' => 1,
5325
- 'org.rs' => 1,
5326
- 'ru' => 1,
5327
- 'ac.ru' => 1,
5328
- 'edu.ru' => 1,
5329
- 'gov.ru' => 1,
5330
- 'int.ru' => 1,
5331
- 'mil.ru' => 1,
5332
- 'test.ru' => 1,
5333
- 'rw' => 1,
5334
- 'ac.rw' => 1,
5335
- 'co.rw' => 1,
5336
- 'coop.rw' => 1,
5337
- 'gov.rw' => 1,
5338
- 'mil.rw' => 1,
5339
- 'net.rw' => 1,
5340
- 'org.rw' => 1,
5341
- 'sa' => 1,
5342
- 'com.sa' => 1,
5343
- 'net.sa' => 1,
5344
- 'org.sa' => 1,
5345
- 'gov.sa' => 1,
5346
- 'med.sa' => 1,
5347
- 'pub.sa' => 1,
5348
- 'edu.sa' => 1,
5349
- 'sch.sa' => 1,
5350
- 'sb' => 1,
5351
- 'com.sb' => 1,
5352
- 'edu.sb' => 1,
5353
- 'gov.sb' => 1,
5354
- 'net.sb' => 1,
5355
- 'org.sb' => 1,
5356
- 'sc' => 1,
5357
- 'com.sc' => 1,
5358
- 'gov.sc' => 1,
5359
- 'net.sc' => 1,
5360
- 'org.sc' => 1,
5361
- 'edu.sc' => 1,
5362
- 'sd' => 1,
5363
- 'com.sd' => 1,
5364
- 'net.sd' => 1,
5365
- 'org.sd' => 1,
5366
- 'edu.sd' => 1,
5367
- 'med.sd' => 1,
5368
- 'tv.sd' => 1,
5369
- 'gov.sd' => 1,
5370
- 'info.sd' => 1,
5371
- 'se' => 1,
5372
- 'a.se' => 1,
5373
- 'ac.se' => 1,
5374
- 'b.se' => 1,
5375
- 'bd.se' => 1,
5376
- 'brand.se' => 1,
5377
- 'c.se' => 1,
5378
- 'd.se' => 1,
5379
- 'e.se' => 1,
5380
- 'f.se' => 1,
5381
- 'fh.se' => 1,
5382
- 'fhsk.se' => 1,
5383
- 'fhv.se' => 1,
5384
- 'g.se' => 1,
5385
- 'h.se' => 1,
5386
- 'i.se' => 1,
5387
- 'k.se' => 1,
5388
- 'komforb.se' => 1,
5389
- 'kommunalforbund.se' => 1,
5390
- 'komvux.se' => 1,
5391
- 'l.se' => 1,
5392
- 'lanbib.se' => 1,
5393
- 'm.se' => 1,
5394
- 'n.se' => 1,
5395
- 'naturbruksgymn.se' => 1,
5396
- 'o.se' => 1,
5397
- 'org.se' => 1,
5398
- 'p.se' => 1,
5399
- 'parti.se' => 1,
5400
- 'pp.se' => 1,
5401
- 'press.se' => 1,
5402
- 'r.se' => 1,
5403
- 's.se' => 1,
5404
- 't.se' => 1,
5405
- 'tm.se' => 1,
5406
- 'u.se' => 1,
5407
- 'w.se' => 1,
5408
- 'x.se' => 1,
5409
- 'y.se' => 1,
5410
- 'z.se' => 1,
5411
- 'sg' => 1,
5412
- 'com.sg' => 1,
5413
- 'net.sg' => 1,
5414
- 'org.sg' => 1,
5415
- 'gov.sg' => 1,
5416
- 'edu.sg' => 1,
5417
- 'per.sg' => 1,
5418
- 'sh' => 1,
5419
- 'com.sh' => 1,
5420
- 'net.sh' => 1,
5421
- 'gov.sh' => 1,
5422
- 'org.sh' => 1,
5423
- 'mil.sh' => 1,
5424
- 'si' => 1,
5425
- 'sj' => 1,
5426
- 'sk' => 1,
5427
- 'sl' => 1,
5428
- 'com.sl' => 1,
5429
- 'net.sl' => 1,
5430
- 'edu.sl' => 1,
5431
- 'gov.sl' => 1,
5432
- 'org.sl' => 1,
5433
- 'sm' => 1,
5434
- 'sn' => 1,
5435
- 'art.sn' => 1,
5436
- 'com.sn' => 1,
5437
- 'edu.sn' => 1,
5438
- 'gouv.sn' => 1,
5439
- 'org.sn' => 1,
5440
- 'perso.sn' => 1,
5441
- 'univ.sn' => 1,
5442
- 'so' => 1,
5443
- 'com.so' => 1,
5444
- 'net.so' => 1,
5445
- 'org.so' => 1,
5446
- 'sr' => 1,
5447
- 'st' => 1,
5448
- 'co.st' => 1,
5449
- 'com.st' => 1,
5450
- 'consulado.st' => 1,
5451
- 'edu.st' => 1,
5452
- 'embaixada.st' => 1,
5453
- 'gov.st' => 1,
5454
- 'mil.st' => 1,
5455
- 'net.st' => 1,
5456
- 'org.st' => 1,
5457
- 'principe.st' => 1,
5458
- 'saotome.st' => 1,
5459
- 'store.st' => 1,
5460
- 'su' => 1,
5461
- 'sv' => 1,
5462
- 'com.sv' => 1,
5463
- 'edu.sv' => 1,
5464
- 'gob.sv' => 1,
5465
- 'org.sv' => 1,
5466
- 'red.sv' => 1,
5467
- 'sx' => 1,
5468
- 'gov.sx' => 1,
5469
- 'sy' => 1,
5470
- 'edu.sy' => 1,
5471
- 'gov.sy' => 1,
5472
- 'net.sy' => 1,
5473
- 'mil.sy' => 1,
5474
- 'com.sy' => 1,
5475
- 'org.sy' => 1,
5476
- 'sz' => 1,
5477
- 'co.sz' => 1,
5478
- 'ac.sz' => 1,
5479
- 'org.sz' => 1,
5480
- 'tc' => 1,
5481
- 'td' => 1,
5482
- 'tel' => 1,
5483
- 'tf' => 1,
5484
- 'tg' => 1,
5485
- 'th' => 1,
5486
- 'ac.th' => 1,
5487
- 'co.th' => 1,
5488
- 'go.th' => 1,
5489
- 'in.th' => 1,
5490
- 'mi.th' => 1,
5491
- 'net.th' => 1,
5492
- 'or.th' => 1,
5493
- 'tj' => 1,
5494
- 'ac.tj' => 1,
5495
- 'biz.tj' => 1,
5496
- 'co.tj' => 1,
5497
- 'com.tj' => 1,
5498
- 'edu.tj' => 1,
5499
- 'go.tj' => 1,
5500
- 'gov.tj' => 1,
5501
- 'int.tj' => 1,
5502
- 'mil.tj' => 1,
5503
- 'name.tj' => 1,
5504
- 'net.tj' => 1,
5505
- 'nic.tj' => 1,
5506
- 'org.tj' => 1,
5507
- 'test.tj' => 1,
5508
- 'web.tj' => 1,
5509
- 'tk' => 1,
5510
- 'tl' => 1,
5511
- 'gov.tl' => 1,
5512
- 'tm' => 1,
5513
- 'com.tm' => 1,
5514
- 'co.tm' => 1,
5515
- 'org.tm' => 1,
5516
- 'net.tm' => 1,
5517
- 'nom.tm' => 1,
5518
- 'gov.tm' => 1,
5519
- 'mil.tm' => 1,
5520
- 'edu.tm' => 1,
5521
- 'tn' => 1,
5522
- 'com.tn' => 1,
5523
- 'ens.tn' => 1,
5524
- 'fin.tn' => 1,
5525
- 'gov.tn' => 1,
5526
- 'ind.tn' => 1,
5527
- 'intl.tn' => 1,
5528
- 'nat.tn' => 1,
5529
- 'net.tn' => 1,
5530
- 'org.tn' => 1,
5531
- 'info.tn' => 1,
5532
- 'perso.tn' => 1,
5533
- 'tourism.tn' => 1,
5534
- 'edunet.tn' => 1,
5535
- 'rnrt.tn' => 1,
5536
- 'rns.tn' => 1,
5537
- 'rnu.tn' => 1,
5538
- 'mincom.tn' => 1,
5539
- 'agrinet.tn' => 1,
5540
- 'defense.tn' => 1,
5541
- 'turen.tn' => 1,
5542
- 'to' => 1,
5543
- 'com.to' => 1,
5544
- 'gov.to' => 1,
5545
- 'net.to' => 1,
5546
- 'org.to' => 1,
5547
- 'edu.to' => 1,
5548
- 'mil.to' => 1,
5549
- 'tr' => 1,
5550
- 'av.tr' => 1,
5551
- 'bbs.tr' => 1,
5552
- 'bel.tr' => 1,
5553
- 'biz.tr' => 1,
5554
- 'com.tr' => 1,
5555
- 'dr.tr' => 1,
5556
- 'edu.tr' => 1,
5557
- 'gen.tr' => 1,
5558
- 'gov.tr' => 1,
5559
- 'info.tr' => 1,
5560
- 'mil.tr' => 1,
5561
- 'k12.tr' => 1,
5562
- 'kep.tr' => 1,
5563
- 'name.tr' => 1,
5564
- 'net.tr' => 1,
5565
- 'org.tr' => 1,
5566
- 'pol.tr' => 1,
5567
- 'tel.tr' => 1,
5568
- 'tsk.tr' => 1,
5569
- 'tv.tr' => 1,
5570
- 'web.tr' => 1,
5571
- 'nc.tr' => 1,
5572
- 'gov.nc.tr' => 1,
5573
- 'tt' => 1,
5574
- 'co.tt' => 1,
5575
- 'com.tt' => 1,
5576
- 'org.tt' => 1,
5577
- 'net.tt' => 1,
5578
- 'biz.tt' => 1,
5579
- 'info.tt' => 1,
5580
- 'pro.tt' => 1,
5581
- 'int.tt' => 1,
5582
- 'coop.tt' => 1,
5583
- 'jobs.tt' => 1,
5584
- 'mobi.tt' => 1,
5585
- 'travel.tt' => 1,
5586
- 'museum.tt' => 1,
5587
- 'aero.tt' => 1,
5588
- 'name.tt' => 1,
5589
- 'gov.tt' => 1,
5590
- 'edu.tt' => 1,
5591
- 'tv' => 1,
5592
- 'tw' => 1,
5593
- 'edu.tw' => 1,
5594
- 'gov.tw' => 1,
5595
- 'mil.tw' => 1,
5596
- 'com.tw' => 1,
5597
- 'net.tw' => 1,
5598
- 'org.tw' => 1,
5599
- 'idv.tw' => 1,
5600
- 'game.tw' => 1,
5601
- 'ebiz.tw' => 1,
5602
- 'club.tw' => 1,
5603
- '網路.tw' => 1,
5604
- '組織.tw' => 1,
5605
- '商業.tw' => 1,
5606
- 'tz' => 1,
5607
- 'ac.tz' => 1,
5608
- 'co.tz' => 1,
5609
- 'go.tz' => 1,
5610
- 'hotel.tz' => 1,
5611
- 'info.tz' => 1,
5612
- 'me.tz' => 1,
5613
- 'mil.tz' => 1,
5614
- 'mobi.tz' => 1,
5615
- 'ne.tz' => 1,
5616
- 'or.tz' => 1,
5617
- 'sc.tz' => 1,
5618
- 'tv.tz' => 1,
5619
- 'ua' => 1,
5620
- 'com.ua' => 1,
5621
- 'edu.ua' => 1,
5622
- 'gov.ua' => 1,
5623
- 'in.ua' => 1,
5624
- 'net.ua' => 1,
5625
- 'org.ua' => 1,
5626
- 'cherkassy.ua' => 1,
5627
- 'cherkasy.ua' => 1,
5628
- 'chernigov.ua' => 1,
5629
- 'chernihiv.ua' => 1,
5630
- 'chernivtsi.ua' => 1,
5631
- 'chernovtsy.ua' => 1,
5632
- 'ck.ua' => 1,
5633
- 'cn.ua' => 1,
5634
- 'cr.ua' => 1,
5635
- 'crimea.ua' => 1,
5636
- 'cv.ua' => 1,
5637
- 'dn.ua' => 1,
5638
- 'dnepropetrovsk.ua' => 1,
5639
- 'dnipropetrovsk.ua' => 1,
5640
- 'dominic.ua' => 1,
5641
- 'donetsk.ua' => 1,
5642
- 'dp.ua' => 1,
5643
- 'if.ua' => 1,
5644
- 'ivano-frankivsk.ua' => 1,
5645
- 'kh.ua' => 1,
5646
- 'kharkiv.ua' => 1,
5647
- 'kharkov.ua' => 1,
5648
- 'kherson.ua' => 1,
5649
- 'khmelnitskiy.ua' => 1,
5650
- 'khmelnytskyi.ua' => 1,
5651
- 'kiev.ua' => 1,
5652
- 'kirovograd.ua' => 1,
5653
- 'km.ua' => 1,
5654
- 'kr.ua' => 1,
5655
- 'krym.ua' => 1,
5656
- 'ks.ua' => 1,
5657
- 'kv.ua' => 1,
5658
- 'kyiv.ua' => 1,
5659
- 'lg.ua' => 1,
5660
- 'lt.ua' => 1,
5661
- 'lugansk.ua' => 1,
5662
- 'lutsk.ua' => 1,
5663
- 'lv.ua' => 1,
5664
- 'lviv.ua' => 1,
5665
- 'mk.ua' => 1,
5666
- 'mykolaiv.ua' => 1,
5667
- 'nikolaev.ua' => 1,
5668
- 'od.ua' => 1,
5669
- 'odesa.ua' => 1,
5670
- 'odessa.ua' => 1,
5671
- 'pl.ua' => 1,
5672
- 'poltava.ua' => 1,
5673
- 'rivne.ua' => 1,
5674
- 'rovno.ua' => 1,
5675
- 'rv.ua' => 1,
5676
- 'sb.ua' => 1,
5677
- 'sebastopol.ua' => 1,
5678
- 'sevastopol.ua' => 1,
5679
- 'sm.ua' => 1,
5680
- 'sumy.ua' => 1,
5681
- 'te.ua' => 1,
5682
- 'ternopil.ua' => 1,
5683
- 'uz.ua' => 1,
5684
- 'uzhgorod.ua' => 1,
5685
- 'vinnica.ua' => 1,
5686
- 'vinnytsia.ua' => 1,
5687
- 'vn.ua' => 1,
5688
- 'volyn.ua' => 1,
5689
- 'yalta.ua' => 1,
5690
- 'zaporizhzhe.ua' => 1,
5691
- 'zaporizhzhia.ua' => 1,
5692
- 'zhitomir.ua' => 1,
5693
- 'zhytomyr.ua' => 1,
5694
- 'zp.ua' => 1,
5695
- 'zt.ua' => 1,
5696
- 'ug' => 1,
5697
- 'co.ug' => 1,
5698
- 'or.ug' => 1,
5699
- 'ac.ug' => 1,
5700
- 'sc.ug' => 1,
5701
- 'go.ug' => 1,
5702
- 'ne.ug' => 1,
5703
- 'com.ug' => 1,
5704
- 'org.ug' => 1,
5705
- 'uk' => 1,
5706
- 'ac.uk' => 1,
5707
- 'co.uk' => 1,
5708
- 'gov.uk' => 1,
5709
- 'ltd.uk' => 1,
5710
- 'me.uk' => 1,
5711
- 'net.uk' => 1,
5712
- 'nhs.uk' => 1,
5713
- 'org.uk' => 1,
5714
- 'plc.uk' => 1,
5715
- 'police.uk' => 1,
5716
- '*.sch.uk' => 1,
5717
- 'us' => 1,
5718
- 'dni.us' => 1,
5719
- 'fed.us' => 1,
5720
- 'isa.us' => 1,
5721
- 'kids.us' => 1,
5722
- 'nsn.us' => 1,
5723
- 'ak.us' => 1,
5724
- 'al.us' => 1,
5725
- 'ar.us' => 1,
5726
- 'as.us' => 1,
5727
- 'az.us' => 1,
5728
- 'ca.us' => 1,
5729
- 'co.us' => 1,
5730
- 'ct.us' => 1,
5731
- 'dc.us' => 1,
5732
- 'de.us' => 1,
5733
- 'fl.us' => 1,
5734
- 'ga.us' => 1,
5735
- 'gu.us' => 1,
5736
- 'hi.us' => 1,
5737
- 'ia.us' => 1,
5738
- 'id.us' => 1,
5739
- 'il.us' => 1,
5740
- 'in.us' => 1,
5741
- 'ks.us' => 1,
5742
- 'ky.us' => 1,
5743
- 'la.us' => 1,
5744
- 'ma.us' => 1,
5745
- 'md.us' => 1,
5746
- 'me.us' => 1,
5747
- 'mi.us' => 1,
5748
- 'mn.us' => 1,
5749
- 'mo.us' => 1,
5750
- 'ms.us' => 1,
5751
- 'mt.us' => 1,
5752
- 'nc.us' => 1,
5753
- 'nd.us' => 1,
5754
- 'ne.us' => 1,
5755
- 'nh.us' => 1,
5756
- 'nj.us' => 1,
5757
- 'nm.us' => 1,
5758
- 'nv.us' => 1,
5759
- 'ny.us' => 1,
5760
- 'oh.us' => 1,
5761
- 'ok.us' => 1,
5762
- 'or.us' => 1,
5763
- 'pa.us' => 1,
5764
- 'pr.us' => 1,
5765
- 'ri.us' => 1,
5766
- 'sc.us' => 1,
5767
- 'sd.us' => 1,
5768
- 'tn.us' => 1,
5769
- 'tx.us' => 1,
5770
- 'ut.us' => 1,
5771
- 'vi.us' => 1,
5772
- 'vt.us' => 1,
5773
- 'va.us' => 1,
5774
- 'wa.us' => 1,
5775
- 'wi.us' => 1,
5776
- 'wv.us' => 1,
5777
- 'wy.us' => 1,
5778
- 'k12.ak.us' => 1,
5779
- 'k12.al.us' => 1,
5780
- 'k12.ar.us' => 1,
5781
- 'k12.as.us' => 1,
5782
- 'k12.az.us' => 1,
5783
- 'k12.ca.us' => 1,
5784
- 'k12.co.us' => 1,
5785
- 'k12.ct.us' => 1,
5786
- 'k12.dc.us' => 1,
5787
- 'k12.de.us' => 1,
5788
- 'k12.fl.us' => 1,
5789
- 'k12.ga.us' => 1,
5790
- 'k12.gu.us' => 1,
5791
- 'k12.ia.us' => 1,
5792
- 'k12.id.us' => 1,
5793
- 'k12.il.us' => 1,
5794
- 'k12.in.us' => 1,
5795
- 'k12.ks.us' => 1,
5796
- 'k12.ky.us' => 1,
5797
- 'k12.la.us' => 1,
5798
- 'k12.ma.us' => 1,
5799
- 'k12.md.us' => 1,
5800
- 'k12.me.us' => 1,
5801
- 'k12.mi.us' => 1,
5802
- 'k12.mn.us' => 1,
5803
- 'k12.mo.us' => 1,
5804
- 'k12.ms.us' => 1,
5805
- 'k12.mt.us' => 1,
5806
- 'k12.nc.us' => 1,
5807
- 'k12.ne.us' => 1,
5808
- 'k12.nh.us' => 1,
5809
- 'k12.nj.us' => 1,
5810
- 'k12.nm.us' => 1,
5811
- 'k12.nv.us' => 1,
5812
- 'k12.ny.us' => 1,
5813
- 'k12.oh.us' => 1,
5814
- 'k12.ok.us' => 1,
5815
- 'k12.or.us' => 1,
5816
- 'k12.pa.us' => 1,
5817
- 'k12.pr.us' => 1,
5818
- 'k12.ri.us' => 1,
5819
- 'k12.sc.us' => 1,
5820
- 'k12.tn.us' => 1,
5821
- 'k12.tx.us' => 1,
5822
- 'k12.ut.us' => 1,
5823
- 'k12.vi.us' => 1,
5824
- 'k12.vt.us' => 1,
5825
- 'k12.va.us' => 1,
5826
- 'k12.wa.us' => 1,
5827
- 'k12.wi.us' => 1,
5828
- 'k12.wy.us' => 1,
5829
- 'cc.ak.us' => 1,
5830
- 'cc.al.us' => 1,
5831
- 'cc.ar.us' => 1,
5832
- 'cc.as.us' => 1,
5833
- 'cc.az.us' => 1,
5834
- 'cc.ca.us' => 1,
5835
- 'cc.co.us' => 1,
5836
- 'cc.ct.us' => 1,
5837
- 'cc.dc.us' => 1,
5838
- 'cc.de.us' => 1,
5839
- 'cc.fl.us' => 1,
5840
- 'cc.ga.us' => 1,
5841
- 'cc.gu.us' => 1,
5842
- 'cc.hi.us' => 1,
5843
- 'cc.ia.us' => 1,
5844
- 'cc.id.us' => 1,
5845
- 'cc.il.us' => 1,
5846
- 'cc.in.us' => 1,
5847
- 'cc.ks.us' => 1,
5848
- 'cc.ky.us' => 1,
5849
- 'cc.la.us' => 1,
5850
- 'cc.ma.us' => 1,
5851
- 'cc.md.us' => 1,
5852
- 'cc.me.us' => 1,
5853
- 'cc.mi.us' => 1,
5854
- 'cc.mn.us' => 1,
5855
- 'cc.mo.us' => 1,
5856
- 'cc.ms.us' => 1,
5857
- 'cc.mt.us' => 1,
5858
- 'cc.nc.us' => 1,
5859
- 'cc.nd.us' => 1,
5860
- 'cc.ne.us' => 1,
5861
- 'cc.nh.us' => 1,
5862
- 'cc.nj.us' => 1,
5863
- 'cc.nm.us' => 1,
5864
- 'cc.nv.us' => 1,
5865
- 'cc.ny.us' => 1,
5866
- 'cc.oh.us' => 1,
5867
- 'cc.ok.us' => 1,
5868
- 'cc.or.us' => 1,
5869
- 'cc.pa.us' => 1,
5870
- 'cc.pr.us' => 1,
5871
- 'cc.ri.us' => 1,
5872
- 'cc.sc.us' => 1,
5873
- 'cc.sd.us' => 1,
5874
- 'cc.tn.us' => 1,
5875
- 'cc.tx.us' => 1,
5876
- 'cc.ut.us' => 1,
5877
- 'cc.vi.us' => 1,
5878
- 'cc.vt.us' => 1,
5879
- 'cc.va.us' => 1,
5880
- 'cc.wa.us' => 1,
5881
- 'cc.wi.us' => 1,
5882
- 'cc.wv.us' => 1,
5883
- 'cc.wy.us' => 1,
5884
- 'lib.ak.us' => 1,
5885
- 'lib.al.us' => 1,
5886
- 'lib.ar.us' => 1,
5887
- 'lib.as.us' => 1,
5888
- 'lib.az.us' => 1,
5889
- 'lib.ca.us' => 1,
5890
- 'lib.co.us' => 1,
5891
- 'lib.ct.us' => 1,
5892
- 'lib.dc.us' => 1,
5893
- 'lib.fl.us' => 1,
5894
- 'lib.ga.us' => 1,
5895
- 'lib.gu.us' => 1,
5896
- 'lib.hi.us' => 1,
5897
- 'lib.ia.us' => 1,
5898
- 'lib.id.us' => 1,
5899
- 'lib.il.us' => 1,
5900
- 'lib.in.us' => 1,
5901
- 'lib.ks.us' => 1,
5902
- 'lib.ky.us' => 1,
5903
- 'lib.la.us' => 1,
5904
- 'lib.ma.us' => 1,
5905
- 'lib.md.us' => 1,
5906
- 'lib.me.us' => 1,
5907
- 'lib.mi.us' => 1,
5908
- 'lib.mn.us' => 1,
5909
- 'lib.mo.us' => 1,
5910
- 'lib.ms.us' => 1,
5911
- 'lib.mt.us' => 1,
5912
- 'lib.nc.us' => 1,
5913
- 'lib.nd.us' => 1,
5914
- 'lib.ne.us' => 1,
5915
- 'lib.nh.us' => 1,
5916
- 'lib.nj.us' => 1,
5917
- 'lib.nm.us' => 1,
5918
- 'lib.nv.us' => 1,
5919
- 'lib.ny.us' => 1,
5920
- 'lib.oh.us' => 1,
5921
- 'lib.ok.us' => 1,
5922
- 'lib.or.us' => 1,
5923
- 'lib.pa.us' => 1,
5924
- 'lib.pr.us' => 1,
5925
- 'lib.ri.us' => 1,
5926
- 'lib.sc.us' => 1,
5927
- 'lib.sd.us' => 1,
5928
- 'lib.tn.us' => 1,
5929
- 'lib.tx.us' => 1,
5930
- 'lib.ut.us' => 1,
5931
- 'lib.vi.us' => 1,
5932
- 'lib.vt.us' => 1,
5933
- 'lib.va.us' => 1,
5934
- 'lib.wa.us' => 1,
5935
- 'lib.wi.us' => 1,
5936
- 'lib.wy.us' => 1,
5937
- 'pvt.k12.ma.us' => 1,
5938
- 'chtr.k12.ma.us' => 1,
5939
- 'paroch.k12.ma.us' => 1,
5940
- 'ann-arbor.mi.us' => 1,
5941
- 'cog.mi.us' => 1,
5942
- 'dst.mi.us' => 1,
5943
- 'eaton.mi.us' => 1,
5944
- 'gen.mi.us' => 1,
5945
- 'mus.mi.us' => 1,
5946
- 'tec.mi.us' => 1,
5947
- 'washtenaw.mi.us' => 1,
5948
- 'uy' => 1,
5949
- 'com.uy' => 1,
5950
- 'edu.uy' => 1,
5951
- 'gub.uy' => 1,
5952
- 'mil.uy' => 1,
5953
- 'net.uy' => 1,
5954
- 'org.uy' => 1,
5955
- 'uz' => 1,
5956
- 'co.uz' => 1,
5957
- 'com.uz' => 1,
5958
- 'net.uz' => 1,
5959
- 'org.uz' => 1,
5960
- 'va' => 1,
5961
- 'vc' => 1,
5962
- 'com.vc' => 1,
5963
- 'net.vc' => 1,
5964
- 'org.vc' => 1,
5965
- 'gov.vc' => 1,
5966
- 'mil.vc' => 1,
5967
- 'edu.vc' => 1,
5968
- 've' => 1,
5969
- 'arts.ve' => 1,
5970
- 'co.ve' => 1,
5971
- 'com.ve' => 1,
5972
- 'e12.ve' => 1,
5973
- 'edu.ve' => 1,
5974
- 'firm.ve' => 1,
5975
- 'gob.ve' => 1,
5976
- 'gov.ve' => 1,
5977
- 'info.ve' => 1,
5978
- 'int.ve' => 1,
5979
- 'mil.ve' => 1,
5980
- 'net.ve' => 1,
5981
- 'org.ve' => 1,
5982
- 'rec.ve' => 1,
5983
- 'store.ve' => 1,
5984
- 'tec.ve' => 1,
5985
- 'web.ve' => 1,
5986
- 'vg' => 1,
5987
- 'vi' => 1,
5988
- 'co.vi' => 1,
5989
- 'com.vi' => 1,
5990
- 'k12.vi' => 1,
5991
- 'net.vi' => 1,
5992
- 'org.vi' => 1,
5993
- 'vn' => 1,
5994
- 'com.vn' => 1,
5995
- 'net.vn' => 1,
5996
- 'org.vn' => 1,
5997
- 'edu.vn' => 1,
5998
- 'gov.vn' => 1,
5999
- 'int.vn' => 1,
6000
- 'ac.vn' => 1,
6001
- 'biz.vn' => 1,
6002
- 'info.vn' => 1,
6003
- 'name.vn' => 1,
6004
- 'pro.vn' => 1,
6005
- 'health.vn' => 1,
6006
- 'vu' => 1,
6007
- 'com.vu' => 1,
6008
- 'edu.vu' => 1,
6009
- 'net.vu' => 1,
6010
- 'org.vu' => 1,
6011
- 'wf' => 1,
6012
- 'ws' => 1,
6013
- 'com.ws' => 1,
6014
- 'net.ws' => 1,
6015
- 'org.ws' => 1,
6016
- 'gov.ws' => 1,
6017
- 'edu.ws' => 1,
6018
- 'yt' => 1,
6019
- 'امارات' => 1,
6020
- 'հայ' => 1,
6021
- 'বাংলা' => 1,
6022
- 'бг' => 1,
6023
- 'бел' => 1,
6024
- '中国' => 1,
6025
- '中國' => 1,
6026
- 'الجزائر' => 1,
6027
- 'مصر' => 1,
6028
- 'ею' => 1,
6029
- 'გე' => 1,
6030
- 'ελ' => 1,
6031
- '香港' => 1,
6032
- '公司.香港' => 1,
6033
- '教育.香港' => 1,
6034
- '政府.香港' => 1,
6035
- '個人.香港' => 1,
6036
- '網絡.香港' => 1,
6037
- '組織.香港' => 1,
6038
- 'ಭಾರತ' => 1,
6039
- 'ଭାରତ' => 1,
6040
- 'ভাৰত' => 1,
6041
- 'भारतम्' => 1,
6042
- 'भारोत' => 1,
6043
- 'ڀارت' => 1,
6044
- 'ഭാരതം' => 1,
6045
- 'भारत' => 1,
6046
- 'بارت' => 1,
6047
- 'بھارت' => 1,
6048
- 'భారత్' => 1,
6049
- 'ભારત' => 1,
6050
- 'ਭਾਰਤ' => 1,
6051
- 'ভারত' => 1,
6052
- 'இந்தியா' => 1,
6053
- 'ایران' => 1,
6054
- 'ايران' => 1,
6055
- 'عراق' => 1,
6056
- 'الاردن' => 1,
6057
- '한국' => 1,
6058
- 'қаз' => 1,
6059
- 'ලංකා' => 1,
6060
- 'இலங்கை' => 1,
6061
- 'المغرب' => 1,
6062
- 'мкд' => 1,
6063
- 'мон' => 1,
6064
- '澳門' => 1,
6065
- '澳门' => 1,
6066
- 'مليسيا' => 1,
6067
- 'عمان' => 1,
6068
- 'پاکستان' => 1,
6069
- 'پاكستان' => 1,
6070
- 'فلسطين' => 1,
6071
- 'срб' => 1,
6072
- 'пр.срб' => 1,
6073
- 'орг.срб' => 1,
6074
- 'обр.срб' => 1,
6075
- 'од.срб' => 1,
6076
- 'упр.срб' => 1,
6077
- 'ак.срб' => 1,
6078
- 'рф' => 1,
6079
- 'قطر' => 1,
6080
- 'السعودية' => 1,
6081
- 'السعودیة' => 1,
6082
- 'السعودیۃ' => 1,
6083
- 'السعوديه' => 1,
6084
- 'سودان' => 1,
6085
- '新加坡' => 1,
6086
- 'சிங்கப்பூர்' => 1,
6087
- 'سورية' => 1,
6088
- 'سوريا' => 1,
6089
- 'ไทย' => 1,
6090
- 'ศึกษา.ไทย' => 1,
6091
- 'ธุรกิจ.ไทย' => 1,
6092
- 'รัฐบาล.ไทย' => 1,
6093
- 'ทหาร.ไทย' => 1,
6094
- 'เน็ต.ไทย' => 1,
6095
- 'องค์กร.ไทย' => 1,
6096
- 'تونس' => 1,
6097
- '台灣' => 1,
6098
- '台湾' => 1,
6099
- '臺灣' => 1,
6100
- 'укр' => 1,
6101
- 'اليمن' => 1,
6102
- 'xxx' => 1,
6103
- '*.ye' => 1,
6104
- 'ac.za' => 1,
6105
- 'agric.za' => 1,
6106
- 'alt.za' => 1,
6107
- 'co.za' => 1,
6108
- 'edu.za' => 1,
6109
- 'gov.za' => 1,
6110
- 'grondar.za' => 1,
6111
- 'law.za' => 1,
6112
- 'mil.za' => 1,
6113
- 'net.za' => 1,
6114
- 'ngo.za' => 1,
6115
- 'nic.za' => 1,
6116
- 'nis.za' => 1,
6117
- 'nom.za' => 1,
6118
- 'org.za' => 1,
6119
- 'school.za' => 1,
6120
- 'tm.za' => 1,
6121
- 'web.za' => 1,
6122
- 'zm' => 1,
6123
- 'ac.zm' => 1,
6124
- 'biz.zm' => 1,
6125
- 'co.zm' => 1,
6126
- 'com.zm' => 1,
6127
- 'edu.zm' => 1,
6128
- 'gov.zm' => 1,
6129
- 'info.zm' => 1,
6130
- 'mil.zm' => 1,
6131
- 'net.zm' => 1,
6132
- 'org.zm' => 1,
6133
- 'sch.zm' => 1,
6134
- 'zw' => 1,
6135
- 'ac.zw' => 1,
6136
- 'co.zw' => 1,
6137
- 'gov.zw' => 1,
6138
- 'mil.zw' => 1,
6139
- 'org.zw' => 1,
6140
- 'aaa' => 1,
6141
- 'aarp' => 1,
6142
- 'abarth' => 1,
6143
- 'abb' => 1,
6144
- 'abbott' => 1,
6145
- 'abbvie' => 1,
6146
- 'abc' => 1,
6147
- 'able' => 1,
6148
- 'abogado' => 1,
6149
- 'abudhabi' => 1,
6150
- 'academy' => 1,
6151
- 'accenture' => 1,
6152
- 'accountant' => 1,
6153
- 'accountants' => 1,
6154
- 'aco' => 1,
6155
- 'actor' => 1,
6156
- 'adac' => 1,
6157
- 'ads' => 1,
6158
- 'adult' => 1,
6159
- 'aeg' => 1,
6160
- 'aetna' => 1,
6161
- 'afamilycompany' => 1,
6162
- 'afl' => 1,
6163
- 'africa' => 1,
6164
- 'agakhan' => 1,
6165
- 'agency' => 1,
6166
- 'aig' => 1,
6167
- 'aigo' => 1,
6168
- 'airbus' => 1,
6169
- 'airforce' => 1,
6170
- 'airtel' => 1,
6171
- 'akdn' => 1,
6172
- 'alfaromeo' => 1,
6173
- 'alibaba' => 1,
6174
- 'alipay' => 1,
6175
- 'allfinanz' => 1,
6176
- 'allstate' => 1,
6177
- 'ally' => 1,
6178
- 'alsace' => 1,
6179
- 'alstom' => 1,
6180
- 'americanexpress' => 1,
6181
- 'americanfamily' => 1,
6182
- 'amex' => 1,
6183
- 'amfam' => 1,
6184
- 'amica' => 1,
6185
- 'amsterdam' => 1,
6186
- 'analytics' => 1,
6187
- 'android' => 1,
6188
- 'anquan' => 1,
6189
- 'anz' => 1,
6190
- 'aol' => 1,
6191
- 'apartments' => 1,
6192
- 'app' => 1,
6193
- 'apple' => 1,
6194
- 'aquarelle' => 1,
6195
- 'arab' => 1,
6196
- 'aramco' => 1,
6197
- 'archi' => 1,
6198
- 'army' => 1,
6199
- 'art' => 1,
6200
- 'arte' => 1,
6201
- 'asda' => 1,
6202
- 'associates' => 1,
6203
- 'athleta' => 1,
6204
- 'attorney' => 1,
6205
- 'auction' => 1,
6206
- 'audi' => 1,
6207
- 'audible' => 1,
6208
- 'audio' => 1,
6209
- 'auspost' => 1,
6210
- 'author' => 1,
6211
- 'auto' => 1,
6212
- 'autos' => 1,
6213
- 'avianca' => 1,
6214
- 'aws' => 1,
6215
- 'axa' => 1,
6216
- 'azure' => 1,
6217
- 'baby' => 1,
6218
- 'baidu' => 1,
6219
- 'banamex' => 1,
6220
- 'bananarepublic' => 1,
6221
- 'band' => 1,
6222
- 'bank' => 1,
6223
- 'bar' => 1,
6224
- 'barcelona' => 1,
6225
- 'barclaycard' => 1,
6226
- 'barclays' => 1,
6227
- 'barefoot' => 1,
6228
- 'bargains' => 1,
6229
- 'baseball' => 1,
6230
- 'basketball' => 1,
6231
- 'bauhaus' => 1,
6232
- 'bayern' => 1,
6233
- 'bbc' => 1,
6234
- 'bbt' => 1,
6235
- 'bbva' => 1,
6236
- 'bcg' => 1,
6237
- 'bcn' => 1,
6238
- 'beats' => 1,
6239
- 'beauty' => 1,
6240
- 'beer' => 1,
6241
- 'bentley' => 1,
6242
- 'berlin' => 1,
6243
- 'best' => 1,
6244
- 'bestbuy' => 1,
6245
- 'bet' => 1,
6246
- 'bharti' => 1,
6247
- 'bible' => 1,
6248
- 'bid' => 1,
6249
- 'bike' => 1,
6250
- 'bing' => 1,
6251
- 'bingo' => 1,
6252
- 'bio' => 1,
6253
- 'black' => 1,
6254
- 'blackfriday' => 1,
6255
- 'blockbuster' => 1,
6256
- 'blog' => 1,
6257
- 'bloomberg' => 1,
6258
- 'blue' => 1,
6259
- 'bms' => 1,
6260
- 'bmw' => 1,
6261
- 'bnl' => 1,
6262
- 'bnpparibas' => 1,
6263
- 'boats' => 1,
6264
- 'boehringer' => 1,
6265
- 'bofa' => 1,
6266
- 'bom' => 1,
6267
- 'bond' => 1,
6268
- 'boo' => 1,
6269
- 'book' => 1,
6270
- 'booking' => 1,
6271
- 'bosch' => 1,
6272
- 'bostik' => 1,
6273
- 'boston' => 1,
6274
- 'bot' => 1,
6275
- 'boutique' => 1,
6276
- 'box' => 1,
6277
- 'bradesco' => 1,
6278
- 'bridgestone' => 1,
6279
- 'broadway' => 1,
6280
- 'broker' => 1,
6281
- 'brother' => 1,
6282
- 'brussels' => 1,
6283
- 'budapest' => 1,
6284
- 'bugatti' => 1,
6285
- 'build' => 1,
6286
- 'builders' => 1,
6287
- 'business' => 1,
6288
- 'buy' => 1,
6289
- 'buzz' => 1,
6290
- 'bzh' => 1,
6291
- 'cab' => 1,
6292
- 'cafe' => 1,
6293
- 'cal' => 1,
6294
- 'call' => 1,
6295
- 'calvinklein' => 1,
6296
- 'cam' => 1,
6297
- 'camera' => 1,
6298
- 'camp' => 1,
6299
- 'cancerresearch' => 1,
6300
- 'canon' => 1,
6301
- 'capetown' => 1,
6302
- 'capital' => 1,
6303
- 'capitalone' => 1,
6304
- 'car' => 1,
6305
- 'caravan' => 1,
6306
- 'cards' => 1,
6307
- 'care' => 1,
6308
- 'career' => 1,
6309
- 'careers' => 1,
6310
- 'cars' => 1,
6311
- 'cartier' => 1,
6312
- 'casa' => 1,
6313
- 'case' => 1,
6314
- 'caseih' => 1,
6315
- 'cash' => 1,
6316
- 'casino' => 1,
6317
- 'catering' => 1,
6318
- 'catholic' => 1,
6319
- 'cba' => 1,
6320
- 'cbn' => 1,
6321
- 'cbre' => 1,
6322
- 'cbs' => 1,
6323
- 'ceb' => 1,
6324
- 'center' => 1,
6325
- 'ceo' => 1,
6326
- 'cern' => 1,
6327
- 'cfa' => 1,
6328
- 'cfd' => 1,
6329
- 'chanel' => 1,
6330
- 'channel' => 1,
6331
- 'charity' => 1,
6332
- 'chase' => 1,
6333
- 'chat' => 1,
6334
- 'cheap' => 1,
6335
- 'chintai' => 1,
6336
- 'christmas' => 1,
6337
- 'chrome' => 1,
6338
- 'chrysler' => 1,
6339
- 'church' => 1,
6340
- 'cipriani' => 1,
6341
- 'circle' => 1,
6342
- 'cisco' => 1,
6343
- 'citadel' => 1,
6344
- 'citi' => 1,
6345
- 'citic' => 1,
6346
- 'city' => 1,
6347
- 'cityeats' => 1,
6348
- 'claims' => 1,
6349
- 'cleaning' => 1,
6350
- 'click' => 1,
6351
- 'clinic' => 1,
6352
- 'clinique' => 1,
6353
- 'clothing' => 1,
6354
- 'cloud' => 1,
6355
- 'club' => 1,
6356
- 'clubmed' => 1,
6357
- 'coach' => 1,
6358
- 'codes' => 1,
6359
- 'coffee' => 1,
6360
- 'college' => 1,
6361
- 'cologne' => 1,
6362
- 'comcast' => 1,
6363
- 'commbank' => 1,
6364
- 'community' => 1,
6365
- 'company' => 1,
6366
- 'compare' => 1,
6367
- 'computer' => 1,
6368
- 'comsec' => 1,
6369
- 'condos' => 1,
6370
- 'construction' => 1,
6371
- 'consulting' => 1,
6372
- 'contact' => 1,
6373
- 'contractors' => 1,
6374
- 'cooking' => 1,
6375
- 'cookingchannel' => 1,
6376
- 'cool' => 1,
6377
- 'corsica' => 1,
6378
- 'country' => 1,
6379
- 'coupon' => 1,
6380
- 'coupons' => 1,
6381
- 'courses' => 1,
6382
- 'cpa' => 1,
6383
- 'credit' => 1,
6384
- 'creditcard' => 1,
6385
- 'creditunion' => 1,
6386
- 'cricket' => 1,
6387
- 'crown' => 1,
6388
- 'crs' => 1,
6389
- 'cruise' => 1,
6390
- 'cruises' => 1,
6391
- 'csc' => 1,
6392
- 'cuisinella' => 1,
6393
- 'cymru' => 1,
6394
- 'cyou' => 1,
6395
- 'dabur' => 1,
6396
- 'dad' => 1,
6397
- 'dance' => 1,
6398
- 'data' => 1,
6399
- 'date' => 1,
6400
- 'dating' => 1,
6401
- 'datsun' => 1,
6402
- 'day' => 1,
6403
- 'dclk' => 1,
6404
- 'dds' => 1,
6405
- 'deal' => 1,
6406
- 'dealer' => 1,
6407
- 'deals' => 1,
6408
- 'degree' => 1,
6409
- 'delivery' => 1,
6410
- 'dell' => 1,
6411
- 'deloitte' => 1,
6412
- 'delta' => 1,
6413
- 'democrat' => 1,
6414
- 'dental' => 1,
6415
- 'dentist' => 1,
6416
- 'desi' => 1,
6417
- 'design' => 1,
6418
- 'dev' => 1,
6419
- 'dhl' => 1,
6420
- 'diamonds' => 1,
6421
- 'diet' => 1,
6422
- 'digital' => 1,
6423
- 'direct' => 1,
6424
- 'directory' => 1,
6425
- 'discount' => 1,
6426
- 'discover' => 1,
6427
- 'dish' => 1,
6428
- 'diy' => 1,
6429
- 'dnp' => 1,
6430
- 'docs' => 1,
6431
- 'doctor' => 1,
6432
- 'dodge' => 1,
6433
- 'dog' => 1,
6434
- 'domains' => 1,
6435
- 'dot' => 1,
6436
- 'download' => 1,
6437
- 'drive' => 1,
6438
- 'dtv' => 1,
6439
- 'dubai' => 1,
6440
- 'duck' => 1,
6441
- 'dunlop' => 1,
6442
- 'duns' => 1,
6443
- 'dupont' => 1,
6444
- 'durban' => 1,
6445
- 'dvag' => 1,
6446
- 'dvr' => 1,
6447
- 'earth' => 1,
6448
- 'eat' => 1,
6449
- 'eco' => 1,
6450
- 'edeka' => 1,
6451
- 'education' => 1,
6452
- 'email' => 1,
6453
- 'emerck' => 1,
6454
- 'energy' => 1,
6455
- 'engineer' => 1,
6456
- 'engineering' => 1,
6457
- 'enterprises' => 1,
6458
- 'epson' => 1,
6459
- 'equipment' => 1,
6460
- 'ericsson' => 1,
6461
- 'erni' => 1,
6462
- 'esq' => 1,
6463
- 'estate' => 1,
6464
- 'esurance' => 1,
6465
- 'etisalat' => 1,
6466
- 'eurovision' => 1,
6467
- 'eus' => 1,
6468
- 'events' => 1,
6469
- 'everbank' => 1,
6470
- 'exchange' => 1,
6471
- 'expert' => 1,
6472
- 'exposed' => 1,
6473
- 'express' => 1,
6474
- 'extraspace' => 1,
6475
- 'fage' => 1,
6476
- 'fail' => 1,
6477
- 'fairwinds' => 1,
6478
- 'faith' => 1,
6479
- 'family' => 1,
6480
- 'fan' => 1,
6481
- 'fans' => 1,
6482
- 'farm' => 1,
6483
- 'farmers' => 1,
6484
- 'fashion' => 1,
6485
- 'fast' => 1,
6486
- 'fedex' => 1,
6487
- 'feedback' => 1,
6488
- 'ferrari' => 1,
6489
- 'ferrero' => 1,
6490
- 'fiat' => 1,
6491
- 'fidelity' => 1,
6492
- 'fido' => 1,
6493
- 'film' => 1,
6494
- 'final' => 1,
6495
- 'finance' => 1,
6496
- 'financial' => 1,
6497
- 'fire' => 1,
6498
- 'firestone' => 1,
6499
- 'firmdale' => 1,
6500
- 'fish' => 1,
6501
- 'fishing' => 1,
6502
- 'fit' => 1,
6503
- 'fitness' => 1,
6504
- 'flickr' => 1,
6505
- 'flights' => 1,
6506
- 'flir' => 1,
6507
- 'florist' => 1,
6508
- 'flowers' => 1,
6509
- 'fly' => 1,
6510
- 'foo' => 1,
6511
- 'food' => 1,
6512
- 'foodnetwork' => 1,
6513
- 'football' => 1,
6514
- 'ford' => 1,
6515
- 'forex' => 1,
6516
- 'forsale' => 1,
6517
- 'forum' => 1,
6518
- 'foundation' => 1,
6519
- 'fox' => 1,
6520
- 'free' => 1,
6521
- 'fresenius' => 1,
6522
- 'frl' => 1,
6523
- 'frogans' => 1,
6524
- 'frontdoor' => 1,
6525
- 'frontier' => 1,
6526
- 'ftr' => 1,
6527
- 'fujitsu' => 1,
6528
- 'fujixerox' => 1,
6529
- 'fun' => 1,
6530
- 'fund' => 1,
6531
- 'furniture' => 1,
6532
- 'futbol' => 1,
6533
- 'fyi' => 1,
6534
- 'gal' => 1,
6535
- 'gallery' => 1,
6536
- 'gallo' => 1,
6537
- 'gallup' => 1,
6538
- 'game' => 1,
6539
- 'games' => 1,
6540
- 'gap' => 1,
6541
- 'garden' => 1,
6542
- 'gay' => 1,
6543
- 'gbiz' => 1,
6544
- 'gdn' => 1,
6545
- 'gea' => 1,
6546
- 'gent' => 1,
6547
- 'genting' => 1,
6548
- 'george' => 1,
6549
- 'ggee' => 1,
6550
- 'gift' => 1,
6551
- 'gifts' => 1,
6552
- 'gives' => 1,
6553
- 'giving' => 1,
6554
- 'glade' => 1,
6555
- 'glass' => 1,
6556
- 'gle' => 1,
6557
- 'global' => 1,
6558
- 'globo' => 1,
6559
- 'gmail' => 1,
6560
- 'gmbh' => 1,
6561
- 'gmo' => 1,
6562
- 'gmx' => 1,
6563
- 'godaddy' => 1,
6564
- 'gold' => 1,
6565
- 'goldpoint' => 1,
6566
- 'golf' => 1,
6567
- 'goo' => 1,
6568
- 'goodyear' => 1,
6569
- 'goog' => 1,
6570
- 'google' => 1,
6571
- 'gop' => 1,
6572
- 'got' => 1,
6573
- 'grainger' => 1,
6574
- 'graphics' => 1,
6575
- 'gratis' => 1,
6576
- 'green' => 1,
6577
- 'gripe' => 1,
6578
- 'grocery' => 1,
6579
- 'group' => 1,
6580
- 'guardian' => 1,
6581
- 'gucci' => 1,
6582
- 'guge' => 1,
6583
- 'guide' => 1,
6584
- 'guitars' => 1,
6585
- 'guru' => 1,
6586
- 'hair' => 1,
6587
- 'hamburg' => 1,
6588
- 'hangout' => 1,
6589
- 'haus' => 1,
6590
- 'hbo' => 1,
6591
- 'hdfc' => 1,
6592
- 'hdfcbank' => 1,
6593
- 'health' => 1,
6594
- 'healthcare' => 1,
6595
- 'help' => 1,
6596
- 'helsinki' => 1,
6597
- 'here' => 1,
6598
- 'hermes' => 1,
6599
- 'hgtv' => 1,
6600
- 'hiphop' => 1,
6601
- 'hisamitsu' => 1,
6602
- 'hitachi' => 1,
6603
- 'hiv' => 1,
6604
- 'hkt' => 1,
6605
- 'hockey' => 1,
6606
- 'holdings' => 1,
6607
- 'holiday' => 1,
6608
- 'homedepot' => 1,
6609
- 'homegoods' => 1,
6610
- 'homes' => 1,
6611
- 'homesense' => 1,
6612
- 'honda' => 1,
6613
- 'honeywell' => 1,
6614
- 'horse' => 1,
6615
- 'hospital' => 1,
6616
- 'host' => 1,
6617
- 'hosting' => 1,
6618
- 'hot' => 1,
6619
- 'hoteles' => 1,
6620
- 'hotels' => 1,
6621
- 'hotmail' => 1,
6622
- 'house' => 1,
6623
- 'how' => 1,
6624
- 'hsbc' => 1,
6625
- 'hughes' => 1,
6626
- 'hyatt' => 1,
6627
- 'hyundai' => 1,
6628
- 'ibm' => 1,
6629
- 'icbc' => 1,
6630
- 'ice' => 1,
6631
- 'icu' => 1,
6632
- 'ieee' => 1,
6633
- 'ifm' => 1,
6634
- 'ikano' => 1,
6635
- 'imamat' => 1,
6636
- 'imdb' => 1,
6637
- 'immo' => 1,
6638
- 'immobilien' => 1,
6639
- 'inc' => 1,
6640
- 'industries' => 1,
6641
- 'infiniti' => 1,
6642
- 'ing' => 1,
6643
- 'ink' => 1,
6644
- 'institute' => 1,
6645
- 'insurance' => 1,
6646
- 'insure' => 1,
6647
- 'intel' => 1,
6648
- 'international' => 1,
6649
- 'intuit' => 1,
6650
- 'investments' => 1,
6651
- 'ipiranga' => 1,
6652
- 'irish' => 1,
6653
- 'iselect' => 1,
6654
- 'ismaili' => 1,
6655
- 'ist' => 1,
6656
- 'istanbul' => 1,
6657
- 'itau' => 1,
6658
- 'itv' => 1,
6659
- 'iveco' => 1,
6660
- 'jaguar' => 1,
6661
- 'java' => 1,
6662
- 'jcb' => 1,
6663
- 'jcp' => 1,
6664
- 'jeep' => 1,
6665
- 'jetzt' => 1,
6666
- 'jewelry' => 1,
6667
- 'jio' => 1,
6668
- 'jll' => 1,
6669
- 'jmp' => 1,
6670
- 'jnj' => 1,
6671
- 'joburg' => 1,
6672
- 'jot' => 1,
6673
- 'joy' => 1,
6674
- 'jpmorgan' => 1,
6675
- 'jprs' => 1,
6676
- 'juegos' => 1,
6677
- 'juniper' => 1,
6678
- 'kaufen' => 1,
6679
- 'kddi' => 1,
6680
- 'kerryhotels' => 1,
6681
- 'kerrylogistics' => 1,
6682
- 'kerryproperties' => 1,
6683
- 'kfh' => 1,
6684
- 'kia' => 1,
6685
- 'kim' => 1,
6686
- 'kinder' => 1,
6687
- 'kindle' => 1,
6688
- 'kitchen' => 1,
6689
- 'kiwi' => 1,
6690
- 'koeln' => 1,
6691
- 'komatsu' => 1,
6692
- 'kosher' => 1,
6693
- 'kpmg' => 1,
6694
- 'kpn' => 1,
6695
- 'krd' => 1,
6696
- 'kred' => 1,
6697
- 'kuokgroup' => 1,
6698
- 'kyoto' => 1,
6699
- 'lacaixa' => 1,
6700
- 'ladbrokes' => 1,
6701
- 'lamborghini' => 1,
6702
- 'lamer' => 1,
6703
- 'lancaster' => 1,
6704
- 'lancia' => 1,
6705
- 'lancome' => 1,
6706
- 'land' => 1,
6707
- 'landrover' => 1,
6708
- 'lanxess' => 1,
6709
- 'lasalle' => 1,
6710
- 'lat' => 1,
6711
- 'latino' => 1,
6712
- 'latrobe' => 1,
6713
- 'law' => 1,
6714
- 'lawyer' => 1,
6715
- 'lds' => 1,
6716
- 'lease' => 1,
6717
- 'leclerc' => 1,
6718
- 'lefrak' => 1,
6719
- 'legal' => 1,
6720
- 'lego' => 1,
6721
- 'lexus' => 1,
6722
- 'lgbt' => 1,
6723
- 'liaison' => 1,
6724
- 'lidl' => 1,
6725
- 'life' => 1,
6726
- 'lifeinsurance' => 1,
6727
- 'lifestyle' => 1,
6728
- 'lighting' => 1,
6729
- 'like' => 1,
6730
- 'lilly' => 1,
6731
- 'limited' => 1,
6732
- 'limo' => 1,
6733
- 'lincoln' => 1,
6734
- 'linde' => 1,
6735
- 'link' => 1,
6736
- 'lipsy' => 1,
6737
- 'live' => 1,
6738
- 'living' => 1,
6739
- 'lixil' => 1,
6740
- 'llc' => 1,
6741
- 'loan' => 1,
6742
- 'loans' => 1,
6743
- 'locker' => 1,
6744
- 'locus' => 1,
6745
- 'loft' => 1,
6746
- 'lol' => 1,
6747
- 'london' => 1,
6748
- 'lotte' => 1,
6749
- 'lotto' => 1,
6750
- 'love' => 1,
6751
- 'lpl' => 1,
6752
- 'lplfinancial' => 1,
6753
- 'ltd' => 1,
6754
- 'ltda' => 1,
6755
- 'lundbeck' => 1,
6756
- 'lupin' => 1,
6757
- 'luxe' => 1,
6758
- 'luxury' => 1,
6759
- 'macys' => 1,
6760
- 'madrid' => 1,
6761
- 'maif' => 1,
6762
- 'maison' => 1,
6763
- 'makeup' => 1,
6764
- 'man' => 1,
6765
- 'management' => 1,
6766
- 'mango' => 1,
6767
- 'map' => 1,
6768
- 'market' => 1,
6769
- 'marketing' => 1,
6770
- 'markets' => 1,
6771
- 'marriott' => 1,
6772
- 'marshalls' => 1,
6773
- 'maserati' => 1,
6774
- 'mattel' => 1,
6775
- 'mba' => 1,
6776
- 'mckinsey' => 1,
6777
- 'med' => 1,
6778
- 'media' => 1,
6779
- 'meet' => 1,
6780
- 'melbourne' => 1,
6781
- 'meme' => 1,
6782
- 'memorial' => 1,
6783
- 'men' => 1,
6784
- 'menu' => 1,
6785
- 'merckmsd' => 1,
6786
- 'metlife' => 1,
6787
- 'miami' => 1,
6788
- 'microsoft' => 1,
6789
- 'mini' => 1,
6790
- 'mint' => 1,
6791
- 'mit' => 1,
6792
- 'mitsubishi' => 1,
6793
- 'mlb' => 1,
6794
- 'mls' => 1,
6795
- 'mma' => 1,
6796
- 'mobile' => 1,
6797
- 'mobily' => 1,
6798
- 'moda' => 1,
6799
- 'moe' => 1,
6800
- 'moi' => 1,
6801
- 'mom' => 1,
6802
- 'monash' => 1,
6803
- 'money' => 1,
6804
- 'monster' => 1,
6805
- 'mopar' => 1,
6806
- 'mormon' => 1,
6807
- 'mortgage' => 1,
6808
- 'moscow' => 1,
6809
- 'moto' => 1,
6810
- 'motorcycles' => 1,
6811
- 'mov' => 1,
6812
- 'movie' => 1,
6813
- 'movistar' => 1,
6814
- 'msd' => 1,
6815
- 'mtn' => 1,
6816
- 'mtr' => 1,
6817
- 'mutual' => 1,
6818
- 'nab' => 1,
6819
- 'nadex' => 1,
6820
- 'nagoya' => 1,
6821
- 'nationwide' => 1,
6822
- 'natura' => 1,
6823
- 'navy' => 1,
6824
- 'nba' => 1,
6825
- 'nec' => 1,
6826
- 'netbank' => 1,
6827
- 'netflix' => 1,
6828
- 'network' => 1,
6829
- 'neustar' => 1,
6830
- 'new' => 1,
6831
- 'newholland' => 1,
6832
- 'news' => 1,
6833
- 'next' => 1,
6834
- 'nextdirect' => 1,
6835
- 'nexus' => 1,
6836
- 'nfl' => 1,
6837
- 'ngo' => 1,
6838
- 'nhk' => 1,
6839
- 'nico' => 1,
6840
- 'nike' => 1,
6841
- 'nikon' => 1,
6842
- 'ninja' => 1,
6843
- 'nissan' => 1,
6844
- 'nissay' => 1,
6845
- 'nokia' => 1,
6846
- 'northwesternmutual' => 1,
6847
- 'norton' => 1,
6848
- 'now' => 1,
6849
- 'nowruz' => 1,
6850
- 'nowtv' => 1,
6851
- 'nra' => 1,
6852
- 'nrw' => 1,
6853
- 'ntt' => 1,
6854
- 'nyc' => 1,
6855
- 'obi' => 1,
6856
- 'observer' => 1,
6857
- 'off' => 1,
6858
- 'office' => 1,
6859
- 'okinawa' => 1,
6860
- 'olayan' => 1,
6861
- 'olayangroup' => 1,
6862
- 'oldnavy' => 1,
6863
- 'ollo' => 1,
6864
- 'omega' => 1,
6865
- 'one' => 1,
6866
- 'ong' => 1,
6867
- 'onl' => 1,
6868
- 'online' => 1,
6869
- 'onyourside' => 1,
6870
- 'ooo' => 1,
6871
- 'open' => 1,
6872
- 'oracle' => 1,
6873
- 'orange' => 1,
6874
- 'organic' => 1,
6875
- 'origins' => 1,
6876
- 'osaka' => 1,
6877
- 'otsuka' => 1,
6878
- 'ott' => 1,
6879
- 'ovh' => 1,
6880
- 'page' => 1,
6881
- 'panasonic' => 1,
6882
- 'paris' => 1,
6883
- 'pars' => 1,
6884
- 'partners' => 1,
6885
- 'parts' => 1,
6886
- 'party' => 1,
6887
- 'passagens' => 1,
6888
- 'pay' => 1,
6889
- 'pccw' => 1,
6890
- 'pet' => 1,
6891
- 'pfizer' => 1,
6892
- 'pharmacy' => 1,
6893
- 'phd' => 1,
6894
- 'philips' => 1,
6895
- 'phone' => 1,
6896
- 'photo' => 1,
6897
- 'photography' => 1,
6898
- 'photos' => 1,
6899
- 'physio' => 1,
6900
- 'piaget' => 1,
6901
- 'pics' => 1,
6902
- 'pictet' => 1,
6903
- 'pictures' => 1,
6904
- 'pid' => 1,
6905
- 'pin' => 1,
6906
- 'ping' => 1,
6907
- 'pink' => 1,
6908
- 'pioneer' => 1,
6909
- 'pizza' => 1,
6910
- 'place' => 1,
6911
- 'play' => 1,
6912
- 'playstation' => 1,
6913
- 'plumbing' => 1,
6914
- 'plus' => 1,
6915
- 'pnc' => 1,
6916
- 'pohl' => 1,
6917
- 'poker' => 1,
6918
- 'politie' => 1,
6919
- 'porn' => 1,
6920
- 'pramerica' => 1,
6921
- 'praxi' => 1,
6922
- 'press' => 1,
6923
- 'prime' => 1,
6924
- 'prod' => 1,
6925
- 'productions' => 1,
6926
- 'prof' => 1,
6927
- 'progressive' => 1,
6928
- 'promo' => 1,
6929
- 'properties' => 1,
6930
- 'property' => 1,
6931
- 'protection' => 1,
6932
- 'pru' => 1,
6933
- 'prudential' => 1,
6934
- 'pub' => 1,
6935
- 'pwc' => 1,
6936
- 'qpon' => 1,
6937
- 'quebec' => 1,
6938
- 'quest' => 1,
6939
- 'qvc' => 1,
6940
- 'racing' => 1,
6941
- 'radio' => 1,
6942
- 'raid' => 1,
6943
- 'read' => 1,
6944
- 'realestate' => 1,
6945
- 'realtor' => 1,
6946
- 'realty' => 1,
6947
- 'recipes' => 1,
6948
- 'red' => 1,
6949
- 'redstone' => 1,
6950
- 'redumbrella' => 1,
6951
- 'rehab' => 1,
6952
- 'reise' => 1,
6953
- 'reisen' => 1,
6954
- 'reit' => 1,
6955
- 'reliance' => 1,
6956
- 'ren' => 1,
6957
- 'rent' => 1,
6958
- 'rentals' => 1,
6959
- 'repair' => 1,
6960
- 'report' => 1,
6961
- 'republican' => 1,
6962
- 'rest' => 1,
6963
- 'restaurant' => 1,
6964
- 'review' => 1,
6965
- 'reviews' => 1,
6966
- 'rexroth' => 1,
6967
- 'rich' => 1,
6968
- 'richardli' => 1,
6969
- 'ricoh' => 1,
6970
- 'rightathome' => 1,
6971
- 'ril' => 1,
6972
- 'rio' => 1,
6973
- 'rip' => 1,
6974
- 'rmit' => 1,
6975
- 'rocher' => 1,
6976
- 'rocks' => 1,
6977
- 'rodeo' => 1,
6978
- 'rogers' => 1,
6979
- 'room' => 1,
6980
- 'rsvp' => 1,
6981
- 'rugby' => 1,
6982
- 'ruhr' => 1,
6983
- 'run' => 1,
6984
- 'rwe' => 1,
6985
- 'ryukyu' => 1,
6986
- 'saarland' => 1,
6987
- 'safe' => 1,
6988
- 'safety' => 1,
6989
- 'sakura' => 1,
6990
- 'sale' => 1,
6991
- 'salon' => 1,
6992
- 'samsclub' => 1,
6993
- 'samsung' => 1,
6994
- 'sandvik' => 1,
6995
- 'sandvikcoromant' => 1,
6996
- 'sanofi' => 1,
6997
- 'sap' => 1,
6998
- 'sarl' => 1,
6999
- 'sas' => 1,
7000
- 'save' => 1,
7001
- 'saxo' => 1,
7002
- 'sbi' => 1,
7003
- 'sbs' => 1,
7004
- 'sca' => 1,
7005
- 'scb' => 1,
7006
- 'schaeffler' => 1,
7007
- 'schmidt' => 1,
7008
- 'scholarships' => 1,
7009
- 'school' => 1,
7010
- 'schule' => 1,
7011
- 'schwarz' => 1,
7012
- 'science' => 1,
7013
- 'scjohnson' => 1,
7014
- 'scor' => 1,
7015
- 'scot' => 1,
7016
- 'search' => 1,
7017
- 'seat' => 1,
7018
- 'secure' => 1,
7019
- 'security' => 1,
7020
- 'seek' => 1,
7021
- 'select' => 1,
7022
- 'sener' => 1,
7023
- 'services' => 1,
7024
- 'ses' => 1,
7025
- 'seven' => 1,
7026
- 'sew' => 1,
7027
- 'sex' => 1,
7028
- 'sexy' => 1,
7029
- 'sfr' => 1,
7030
- 'shangrila' => 1,
7031
- 'sharp' => 1,
7032
- 'shaw' => 1,
7033
- 'shell' => 1,
7034
- 'shia' => 1,
7035
- 'shiksha' => 1,
7036
- 'shoes' => 1,
7037
- 'shop' => 1,
7038
- 'shopping' => 1,
7039
- 'shouji' => 1,
7040
- 'show' => 1,
7041
- 'showtime' => 1,
7042
- 'shriram' => 1,
7043
- 'silk' => 1,
7044
- 'sina' => 1,
7045
- 'singles' => 1,
7046
- 'site' => 1,
7047
- 'ski' => 1,
7048
- 'skin' => 1,
7049
- 'sky' => 1,
7050
- 'skype' => 1,
7051
- 'sling' => 1,
7052
- 'smart' => 1,
7053
- 'smile' => 1,
7054
- 'sncf' => 1,
7055
- 'soccer' => 1,
7056
- 'social' => 1,
7057
- 'softbank' => 1,
7058
- 'software' => 1,
7059
- 'sohu' => 1,
7060
- 'solar' => 1,
7061
- 'solutions' => 1,
7062
- 'song' => 1,
7063
- 'sony' => 1,
7064
- 'soy' => 1,
7065
- 'space' => 1,
7066
- 'sport' => 1,
7067
- 'spot' => 1,
7068
- 'spreadbetting' => 1,
7069
- 'srl' => 1,
7070
- 'srt' => 1,
7071
- 'stada' => 1,
7072
- 'staples' => 1,
7073
- 'star' => 1,
7074
- 'starhub' => 1,
7075
- 'statebank' => 1,
7076
- 'statefarm' => 1,
7077
- 'stc' => 1,
7078
- 'stcgroup' => 1,
7079
- 'stockholm' => 1,
7080
- 'storage' => 1,
7081
- 'store' => 1,
7082
- 'stream' => 1,
7083
- 'studio' => 1,
7084
- 'study' => 1,
7085
- 'style' => 1,
7086
- 'sucks' => 1,
7087
- 'supplies' => 1,
7088
- 'supply' => 1,
7089
- 'support' => 1,
7090
- 'surf' => 1,
7091
- 'surgery' => 1,
7092
- 'suzuki' => 1,
7093
- 'swatch' => 1,
7094
- 'swiftcover' => 1,
7095
- 'swiss' => 1,
7096
- 'sydney' => 1,
7097
- 'symantec' => 1,
7098
- 'systems' => 1,
7099
- 'tab' => 1,
7100
- 'taipei' => 1,
7101
- 'talk' => 1,
7102
- 'taobao' => 1,
7103
- 'target' => 1,
7104
- 'tatamotors' => 1,
7105
- 'tatar' => 1,
7106
- 'tattoo' => 1,
7107
- 'tax' => 1,
7108
- 'taxi' => 1,
7109
- 'tci' => 1,
7110
- 'tdk' => 1,
7111
- 'team' => 1,
7112
- 'tech' => 1,
7113
- 'technology' => 1,
7114
- 'telefonica' => 1,
7115
- 'temasek' => 1,
7116
- 'tennis' => 1,
7117
- 'teva' => 1,
7118
- 'thd' => 1,
7119
- 'theater' => 1,
7120
- 'theatre' => 1,
7121
- 'tiaa' => 1,
7122
- 'tickets' => 1,
7123
- 'tienda' => 1,
7124
- 'tiffany' => 1,
7125
- 'tips' => 1,
7126
- 'tires' => 1,
7127
- 'tirol' => 1,
7128
- 'tjmaxx' => 1,
7129
- 'tjx' => 1,
7130
- 'tkmaxx' => 1,
7131
- 'tmall' => 1,
7132
- 'today' => 1,
7133
- 'tokyo' => 1,
7134
- 'tools' => 1,
7135
- 'top' => 1,
7136
- 'toray' => 1,
7137
- 'toshiba' => 1,
7138
- 'total' => 1,
7139
- 'tours' => 1,
7140
- 'town' => 1,
7141
- 'toyota' => 1,
7142
- 'toys' => 1,
7143
- 'trade' => 1,
7144
- 'trading' => 1,
7145
- 'training' => 1,
7146
- 'travel' => 1,
7147
- 'travelchannel' => 1,
7148
- 'travelers' => 1,
7149
- 'travelersinsurance' => 1,
7150
- 'trust' => 1,
7151
- 'trv' => 1,
7152
- 'tube' => 1,
7153
- 'tui' => 1,
7154
- 'tunes' => 1,
7155
- 'tushu' => 1,
7156
- 'tvs' => 1,
7157
- 'ubank' => 1,
7158
- 'ubs' => 1,
7159
- 'uconnect' => 1,
7160
- 'unicom' => 1,
7161
- 'university' => 1,
7162
- 'uno' => 1,
7163
- 'uol' => 1,
7164
- 'ups' => 1,
7165
- 'vacations' => 1,
7166
- 'vana' => 1,
7167
- 'vanguard' => 1,
7168
- 'vegas' => 1,
7169
- 'ventures' => 1,
7170
- 'verisign' => 1,
7171
- 'versicherung' => 1,
7172
- 'vet' => 1,
7173
- 'viajes' => 1,
7174
- 'video' => 1,
7175
- 'vig' => 1,
7176
- 'viking' => 1,
7177
- 'villas' => 1,
7178
- 'vin' => 1,
7179
- 'vip' => 1,
7180
- 'virgin' => 1,
7181
- 'visa' => 1,
7182
- 'vision' => 1,
7183
- 'vistaprint' => 1,
7184
- 'viva' => 1,
7185
- 'vivo' => 1,
7186
- 'vlaanderen' => 1,
7187
- 'vodka' => 1,
7188
- 'volkswagen' => 1,
7189
- 'volvo' => 1,
7190
- 'vote' => 1,
7191
- 'voting' => 1,
7192
- 'voto' => 1,
7193
- 'voyage' => 1,
7194
- 'vuelos' => 1,
7195
- 'wales' => 1,
7196
- 'walmart' => 1,
7197
- 'walter' => 1,
7198
- 'wang' => 1,
7199
- 'wanggou' => 1,
7200
- 'warman' => 1,
7201
- 'watch' => 1,
7202
- 'watches' => 1,
7203
- 'weather' => 1,
7204
- 'weatherchannel' => 1,
7205
- 'webcam' => 1,
7206
- 'weber' => 1,
7207
- 'website' => 1,
7208
- 'wed' => 1,
7209
- 'wedding' => 1,
7210
- 'weibo' => 1,
7211
- 'weir' => 1,
7212
- 'whoswho' => 1,
7213
- 'wien' => 1,
7214
- 'wiki' => 1,
7215
- 'williamhill' => 1,
7216
- 'win' => 1,
7217
- 'windows' => 1,
7218
- 'wine' => 1,
7219
- 'winners' => 1,
7220
- 'wme' => 1,
7221
- 'wolterskluwer' => 1,
7222
- 'woodside' => 1,
7223
- 'work' => 1,
7224
- 'works' => 1,
7225
- 'world' => 1,
7226
- 'wow' => 1,
7227
- 'wtc' => 1,
7228
- 'wtf' => 1,
7229
- 'xbox' => 1,
7230
- 'xerox' => 1,
7231
- 'xfinity' => 1,
7232
- 'xihuan' => 1,
7233
- 'xin' => 1,
7234
- 'कॉम' => 1,
7235
- 'セール' => 1,
7236
- '佛山' => 1,
7237
- '慈善' => 1,
7238
- '集团' => 1,
7239
- '在线' => 1,
7240
- '大众汽车' => 1,
7241
- '点看' => 1,
7242
- 'คอม' => 1,
7243
- '八卦' => 1,
7244
- 'موقع' => 1,
7245
- '公益' => 1,
7246
- '公司' => 1,
7247
- '香格里拉' => 1,
7248
- '网站' => 1,
7249
- '移动' => 1,
7250
- '我爱你' => 1,
7251
- 'москва' => 1,
7252
- 'католик' => 1,
7253
- 'онлайн' => 1,
7254
- 'сайт' => 1,
7255
- '联通' => 1,
7256
- 'קום' => 1,
7257
- '时尚' => 1,
7258
- '微博' => 1,
7259
- '淡马锡' => 1,
7260
- 'ファッション' => 1,
7261
- 'орг' => 1,
7262
- 'नेट' => 1,
7263
- 'ストア' => 1,
7264
- '삼성' => 1,
7265
- '商标' => 1,
7266
- '商店' => 1,
7267
- '商城' => 1,
7268
- 'дети' => 1,
7269
- 'ポイント' => 1,
7270
- '新闻' => 1,
7271
- '工行' => 1,
7272
- '家電' => 1,
7273
- 'كوم' => 1,
7274
- '中文网' => 1,
7275
- '中信' => 1,
7276
- '娱乐' => 1,
7277
- '谷歌' => 1,
7278
- '電訊盈科' => 1,
7279
- '购物' => 1,
7280
- 'クラウド' => 1,
7281
- '通販' => 1,
7282
- '网店' => 1,
7283
- 'संगठन' => 1,
7284
- '餐厅' => 1,
7285
- '网络' => 1,
7286
- 'ком' => 1,
7287
- '诺基亚' => 1,
7288
- '食品' => 1,
7289
- '飞利浦' => 1,
7290
- '手表' => 1,
7291
- '手机' => 1,
7292
- 'ارامكو' => 1,
7293
- 'العليان' => 1,
7294
- 'اتصالات' => 1,
7295
- 'بازار' => 1,
7296
- 'موبايلي' => 1,
7297
- 'ابوظبي' => 1,
7298
- 'كاثوليك' => 1,
7299
- 'همراه' => 1,
7300
- '닷컴' => 1,
7301
- '政府' => 1,
7302
- 'شبكة' => 1,
7303
- 'بيتك' => 1,
7304
- 'عرب' => 1,
7305
- '机构' => 1,
7306
- '组织机构' => 1,
7307
- '健康' => 1,
7308
- '招聘' => 1,
7309
- 'рус' => 1,
7310
- '珠宝' => 1,
7311
- '大拿' => 1,
7312
- 'みんな' => 1,
7313
- 'グーグル' => 1,
7314
- '世界' => 1,
7315
- '書籍' => 1,
7316
- '网址' => 1,
7317
- '닷넷' => 1,
7318
- 'コム' => 1,
7319
- '天主教' => 1,
7320
- '游戏' => 1,
7321
- 'vermögensberater' => 1,
7322
- 'vermögensberatung' => 1,
7323
- '企业' => 1,
7324
- '信息' => 1,
7325
- '嘉里大酒店' => 1,
7326
- '嘉里' => 1,
7327
- '广东' => 1,
7328
- '政务' => 1,
7329
- 'xyz' => 1,
7330
- 'yachts' => 1,
7331
- 'yahoo' => 1,
7332
- 'yamaxun' => 1,
7333
- 'yandex' => 1,
7334
- 'yodobashi' => 1,
7335
- 'yoga' => 1,
7336
- 'yokohama' => 1,
7337
- 'you' => 1,
7338
- 'youtube' => 1,
7339
- 'yun' => 1,
7340
- 'zappos' => 1,
7341
- 'zara' => 1,
7342
- 'zero' => 1,
7343
- 'zip' => 1,
7344
- 'zone' => 1,
7345
- 'zuerich' => 1,
7346
- 'cc.ua' => 2,
7347
- 'inf.ua' => 2,
7348
- 'ltd.ua' => 2,
7349
- 'beep.pl' => 2,
7350
- 'barsy.ca' => 2,
7351
- '*.compute.estate' => 2,
7352
- '*.alces.network' => 2,
7353
- 'alwaysdata.net' => 2,
7354
- 'cloudfront.net' => 2,
7355
- '*.compute.amazonaws.com' => 2,
7356
- '*.compute-1.amazonaws.com' => 2,
7357
- '*.compute.amazonaws.com.cn' => 2,
7358
- 'us-east-1.amazonaws.com' => 2,
7359
- 'cn-north-1.eb.amazonaws.com.cn' => 2,
7360
- 'cn-northwest-1.eb.amazonaws.com.cn' => 2,
7361
- 'elasticbeanstalk.com' => 2,
7362
- 'ap-northeast-1.elasticbeanstalk.com' => 2,
7363
- 'ap-northeast-2.elasticbeanstalk.com' => 2,
7364
- 'ap-northeast-3.elasticbeanstalk.com' => 2,
7365
- 'ap-south-1.elasticbeanstalk.com' => 2,
7366
- 'ap-southeast-1.elasticbeanstalk.com' => 2,
7367
- 'ap-southeast-2.elasticbeanstalk.com' => 2,
7368
- 'ca-central-1.elasticbeanstalk.com' => 2,
7369
- 'eu-central-1.elasticbeanstalk.com' => 2,
7370
- 'eu-west-1.elasticbeanstalk.com' => 2,
7371
- 'eu-west-2.elasticbeanstalk.com' => 2,
7372
- 'eu-west-3.elasticbeanstalk.com' => 2,
7373
- 'sa-east-1.elasticbeanstalk.com' => 2,
7374
- 'us-east-1.elasticbeanstalk.com' => 2,
7375
- 'us-east-2.elasticbeanstalk.com' => 2,
7376
- 'us-gov-west-1.elasticbeanstalk.com' => 2,
7377
- 'us-west-1.elasticbeanstalk.com' => 2,
7378
- 'us-west-2.elasticbeanstalk.com' => 2,
7379
- '*.elb.amazonaws.com' => 2,
7380
- '*.elb.amazonaws.com.cn' => 2,
7381
- 's3.amazonaws.com' => 2,
7382
- 's3-ap-northeast-1.amazonaws.com' => 2,
7383
- 's3-ap-northeast-2.amazonaws.com' => 2,
7384
- 's3-ap-south-1.amazonaws.com' => 2,
7385
- 's3-ap-southeast-1.amazonaws.com' => 2,
7386
- 's3-ap-southeast-2.amazonaws.com' => 2,
7387
- 's3-ca-central-1.amazonaws.com' => 2,
7388
- 's3-eu-central-1.amazonaws.com' => 2,
7389
- 's3-eu-west-1.amazonaws.com' => 2,
7390
- 's3-eu-west-2.amazonaws.com' => 2,
7391
- 's3-eu-west-3.amazonaws.com' => 2,
7392
- 's3-external-1.amazonaws.com' => 2,
7393
- 's3-fips-us-gov-west-1.amazonaws.com' => 2,
7394
- 's3-sa-east-1.amazonaws.com' => 2,
7395
- 's3-us-gov-west-1.amazonaws.com' => 2,
7396
- 's3-us-east-2.amazonaws.com' => 2,
7397
- 's3-us-west-1.amazonaws.com' => 2,
7398
- 's3-us-west-2.amazonaws.com' => 2,
7399
- 's3.ap-northeast-2.amazonaws.com' => 2,
7400
- 's3.ap-south-1.amazonaws.com' => 2,
7401
- 's3.cn-north-1.amazonaws.com.cn' => 2,
7402
- 's3.ca-central-1.amazonaws.com' => 2,
7403
- 's3.eu-central-1.amazonaws.com' => 2,
7404
- 's3.eu-west-2.amazonaws.com' => 2,
7405
- 's3.eu-west-3.amazonaws.com' => 2,
7406
- 's3.us-east-2.amazonaws.com' => 2,
7407
- 's3.dualstack.ap-northeast-1.amazonaws.com' => 2,
7408
- 's3.dualstack.ap-northeast-2.amazonaws.com' => 2,
7409
- 's3.dualstack.ap-south-1.amazonaws.com' => 2,
7410
- 's3.dualstack.ap-southeast-1.amazonaws.com' => 2,
7411
- 's3.dualstack.ap-southeast-2.amazonaws.com' => 2,
7412
- 's3.dualstack.ca-central-1.amazonaws.com' => 2,
7413
- 's3.dualstack.eu-central-1.amazonaws.com' => 2,
7414
- 's3.dualstack.eu-west-1.amazonaws.com' => 2,
7415
- 's3.dualstack.eu-west-2.amazonaws.com' => 2,
7416
- 's3.dualstack.eu-west-3.amazonaws.com' => 2,
7417
- 's3.dualstack.sa-east-1.amazonaws.com' => 2,
7418
- 's3.dualstack.us-east-1.amazonaws.com' => 2,
7419
- 's3.dualstack.us-east-2.amazonaws.com' => 2,
7420
- 's3-website-us-east-1.amazonaws.com' => 2,
7421
- 's3-website-us-west-1.amazonaws.com' => 2,
7422
- 's3-website-us-west-2.amazonaws.com' => 2,
7423
- 's3-website-ap-northeast-1.amazonaws.com' => 2,
7424
- 's3-website-ap-southeast-1.amazonaws.com' => 2,
7425
- 's3-website-ap-southeast-2.amazonaws.com' => 2,
7426
- 's3-website-eu-west-1.amazonaws.com' => 2,
7427
- 's3-website-sa-east-1.amazonaws.com' => 2,
7428
- 's3-website.ap-northeast-2.amazonaws.com' => 2,
7429
- 's3-website.ap-south-1.amazonaws.com' => 2,
7430
- 's3-website.ca-central-1.amazonaws.com' => 2,
7431
- 's3-website.eu-central-1.amazonaws.com' => 2,
7432
- 's3-website.eu-west-2.amazonaws.com' => 2,
7433
- 's3-website.eu-west-3.amazonaws.com' => 2,
7434
- 's3-website.us-east-2.amazonaws.com' => 2,
7435
- 't3l3p0rt.net' => 2,
7436
- 'tele.amune.org' => 2,
7437
- 'apigee.io' => 2,
7438
- 'on-aptible.com' => 2,
7439
- 'user.aseinet.ne.jp' => 2,
7440
- 'gv.vc' => 2,
7441
- 'd.gv.vc' => 2,
7442
- 'user.party.eus' => 2,
7443
- 'pimienta.org' => 2,
7444
- 'poivron.org' => 2,
7445
- 'potager.org' => 2,
7446
- 'sweetpepper.org' => 2,
7447
- 'myasustor.com' => 2,
7448
- 'go-vip.co' => 2,
7449
- 'go-vip.net' => 2,
7450
- 'wpcomstaging.com' => 2,
7451
- 'myfritz.net' => 2,
7452
- '*.awdev.ca' => 2,
7453
- '*.advisor.ws' => 2,
7454
- 'b-data.io' => 2,
7455
- 'backplaneapp.io' => 2,
7456
- 'balena-devices.com' => 2,
7457
- 'app.banzaicloud.io' => 2,
7458
- 'betainabox.com' => 2,
7459
- 'bnr.la' => 2,
7460
- 'blackbaudcdn.net' => 2,
7461
- 'boomla.net' => 2,
7462
- 'boxfuse.io' => 2,
7463
- 'square7.ch' => 2,
7464
- 'bplaced.com' => 2,
7465
- 'bplaced.de' => 2,
7466
- 'square7.de' => 2,
7467
- 'bplaced.net' => 2,
7468
- 'square7.net' => 2,
7469
- 'browsersafetymark.io' => 2,
7470
- 'uk0.bigv.io' => 2,
7471
- 'dh.bytemark.co.uk' => 2,
7472
- 'vm.bytemark.co.uk' => 2,
7473
- 'mycd.eu' => 2,
7474
- 'carrd.co' => 2,
7475
- 'crd.co' => 2,
7476
- 'uwu.ai' => 2,
7477
- 'ae.org' => 2,
7478
- 'ar.com' => 2,
7479
- 'br.com' => 2,
7480
- 'cn.com' => 2,
7481
- 'com.de' => 2,
7482
- 'com.se' => 2,
7483
- 'de.com' => 2,
7484
- 'eu.com' => 2,
7485
- 'gb.com' => 2,
7486
- 'gb.net' => 2,
7487
- 'hu.com' => 2,
7488
- 'hu.net' => 2,
7489
- 'jp.net' => 2,
7490
- 'jpn.com' => 2,
7491
- 'kr.com' => 2,
7492
- 'mex.com' => 2,
7493
- 'no.com' => 2,
7494
- 'qc.com' => 2,
7495
- 'ru.com' => 2,
7496
- 'sa.com' => 2,
7497
- 'se.net' => 2,
7498
- 'uk.com' => 2,
7499
- 'uk.net' => 2,
7500
- 'us.com' => 2,
7501
- 'uy.com' => 2,
7502
- 'za.bz' => 2,
7503
- 'za.com' => 2,
7504
- 'africa.com' => 2,
7505
- 'gr.com' => 2,
7506
- 'in.net' => 2,
7507
- 'us.org' => 2,
7508
- 'co.com' => 2,
7509
- 'c.la' => 2,
7510
- 'certmgr.org' => 2,
7511
- 'xenapponazure.com' => 2,
7512
- 'discourse.group' => 2,
7513
- 'virtueeldomein.nl' => 2,
7514
- 'cleverapps.io' => 2,
7515
- '*.lcl.dev' => 2,
7516
- '*.stg.dev' => 2,
7517
- 'c66.me' => 2,
7518
- 'cloud66.ws' => 2,
7519
- 'cloud66.zone' => 2,
7520
- 'jdevcloud.com' => 2,
7521
- 'wpdevcloud.com' => 2,
7522
- 'cloudaccess.host' => 2,
7523
- 'freesite.host' => 2,
7524
- 'cloudaccess.net' => 2,
7525
- 'cloudcontrolled.com' => 2,
7526
- 'cloudcontrolapp.com' => 2,
7527
- 'cloudera.site' => 2,
7528
- 'trycloudflare.com' => 2,
7529
- 'workers.dev' => 2,
7530
- 'wnext.app' => 2,
7531
- 'co.ca' => 2,
7532
- '*.otap.co' => 2,
7533
- 'co.cz' => 2,
7534
- 'c.cdn77.org' => 2,
7535
- 'cdn77-ssl.net' => 2,
7536
- 'r.cdn77.net' => 2,
7537
- 'rsc.cdn77.org' => 2,
7538
- 'ssl.origin.cdn77-secure.org' => 2,
7539
- 'cloudns.asia' => 2,
7540
- 'cloudns.biz' => 2,
7541
- 'cloudns.club' => 2,
7542
- 'cloudns.cc' => 2,
7543
- 'cloudns.eu' => 2,
7544
- 'cloudns.in' => 2,
7545
- 'cloudns.info' => 2,
7546
- 'cloudns.org' => 2,
7547
- 'cloudns.pro' => 2,
7548
- 'cloudns.pw' => 2,
7549
- 'cloudns.us' => 2,
7550
- 'cloudeity.net' => 2,
7551
- 'cnpy.gdn' => 2,
7552
- 'co.nl' => 2,
7553
- 'co.no' => 2,
7554
- 'webhosting.be' => 2,
7555
- 'hosting-cluster.nl' => 2,
7556
- 'dyn.cosidns.de' => 2,
7557
- 'dynamisches-dns.de' => 2,
7558
- 'dnsupdater.de' => 2,
7559
- 'internet-dns.de' => 2,
7560
- 'l-o-g-i-n.de' => 2,
7561
- 'dynamic-dns.info' => 2,
7562
- 'feste-ip.net' => 2,
7563
- 'knx-server.net' => 2,
7564
- 'static-access.net' => 2,
7565
- 'realm.cz' => 2,
7566
- '*.cryptonomic.net' => 2,
7567
- 'cupcake.is' => 2,
7568
- 'cyon.link' => 2,
7569
- 'cyon.site' => 2,
7570
- 'daplie.me' => 2,
7571
- 'localhost.daplie.me' => 2,
7572
- 'dattolocal.com' => 2,
7573
- 'dattorelay.com' => 2,
7574
- 'dattoweb.com' => 2,
7575
- 'mydatto.com' => 2,
7576
- 'dattolocal.net' => 2,
7577
- 'mydatto.net' => 2,
7578
- 'biz.dk' => 2,
7579
- 'co.dk' => 2,
7580
- 'firm.dk' => 2,
7581
- 'reg.dk' => 2,
7582
- 'store.dk' => 2,
7583
- '*.dapps.earth' => 2,
7584
- '*.bzz.dapps.earth' => 2,
7585
- 'debian.net' => 2,
7586
- 'dedyn.io' => 2,
7587
- 'dnshome.de' => 2,
7588
- 'online.th' => 2,
7589
- 'shop.th' => 2,
7590
- 'drayddns.com' => 2,
7591
- 'dreamhosters.com' => 2,
7592
- 'mydrobo.com' => 2,
7593
- 'drud.io' => 2,
7594
- 'drud.us' => 2,
7595
- 'duckdns.org' => 2,
7596
- 'dy.fi' => 2,
7597
- 'tunk.org' => 2,
7598
- 'dyndns-at-home.com' => 2,
7599
- 'dyndns-at-work.com' => 2,
7600
- 'dyndns-blog.com' => 2,
7601
- 'dyndns-free.com' => 2,
7602
- 'dyndns-home.com' => 2,
7603
- 'dyndns-ip.com' => 2,
7604
- 'dyndns-mail.com' => 2,
7605
- 'dyndns-office.com' => 2,
7606
- 'dyndns-pics.com' => 2,
7607
- 'dyndns-remote.com' => 2,
7608
- 'dyndns-server.com' => 2,
7609
- 'dyndns-web.com' => 2,
7610
- 'dyndns-wiki.com' => 2,
7611
- 'dyndns-work.com' => 2,
7612
- 'dyndns.biz' => 2,
7613
- 'dyndns.info' => 2,
7614
- 'dyndns.org' => 2,
7615
- 'dyndns.tv' => 2,
7616
- 'at-band-camp.net' => 2,
7617
- 'ath.cx' => 2,
7618
- 'barrel-of-knowledge.info' => 2,
7619
- 'barrell-of-knowledge.info' => 2,
7620
- 'better-than.tv' => 2,
7621
- 'blogdns.com' => 2,
7622
- 'blogdns.net' => 2,
7623
- 'blogdns.org' => 2,
7624
- 'blogsite.org' => 2,
7625
- 'boldlygoingnowhere.org' => 2,
7626
- 'broke-it.net' => 2,
7627
- 'buyshouses.net' => 2,
7628
- 'cechire.com' => 2,
7629
- 'dnsalias.com' => 2,
7630
- 'dnsalias.net' => 2,
7631
- 'dnsalias.org' => 2,
7632
- 'dnsdojo.com' => 2,
7633
- 'dnsdojo.net' => 2,
7634
- 'dnsdojo.org' => 2,
7635
- 'does-it.net' => 2,
7636
- 'doesntexist.com' => 2,
7637
- 'doesntexist.org' => 2,
7638
- 'dontexist.com' => 2,
7639
- 'dontexist.net' => 2,
7640
- 'dontexist.org' => 2,
7641
- 'doomdns.com' => 2,
7642
- 'doomdns.org' => 2,
7643
- 'dvrdns.org' => 2,
7644
- 'dyn-o-saur.com' => 2,
7645
- 'dynalias.com' => 2,
7646
- 'dynalias.net' => 2,
7647
- 'dynalias.org' => 2,
7648
- 'dynathome.net' => 2,
7649
- 'dyndns.ws' => 2,
7650
- 'endofinternet.net' => 2,
7651
- 'endofinternet.org' => 2,
7652
- 'endoftheinternet.org' => 2,
7653
- 'est-a-la-maison.com' => 2,
7654
- 'est-a-la-masion.com' => 2,
7655
- 'est-le-patron.com' => 2,
7656
- 'est-mon-blogueur.com' => 2,
7657
- 'for-better.biz' => 2,
7658
- 'for-more.biz' => 2,
7659
- 'for-our.info' => 2,
7660
- 'for-some.biz' => 2,
7661
- 'for-the.biz' => 2,
7662
- 'forgot.her.name' => 2,
7663
- 'forgot.his.name' => 2,
7664
- 'from-ak.com' => 2,
7665
- 'from-al.com' => 2,
7666
- 'from-ar.com' => 2,
7667
- 'from-az.net' => 2,
7668
- 'from-ca.com' => 2,
7669
- 'from-co.net' => 2,
7670
- 'from-ct.com' => 2,
7671
- 'from-dc.com' => 2,
7672
- 'from-de.com' => 2,
7673
- 'from-fl.com' => 2,
7674
- 'from-ga.com' => 2,
7675
- 'from-hi.com' => 2,
7676
- 'from-ia.com' => 2,
7677
- 'from-id.com' => 2,
7678
- 'from-il.com' => 2,
7679
- 'from-in.com' => 2,
7680
- 'from-ks.com' => 2,
7681
- 'from-ky.com' => 2,
7682
- 'from-la.net' => 2,
7683
- 'from-ma.com' => 2,
7684
- 'from-md.com' => 2,
7685
- 'from-me.org' => 2,
7686
- 'from-mi.com' => 2,
7687
- 'from-mn.com' => 2,
7688
- 'from-mo.com' => 2,
7689
- 'from-ms.com' => 2,
7690
- 'from-mt.com' => 2,
7691
- 'from-nc.com' => 2,
7692
- 'from-nd.com' => 2,
7693
- 'from-ne.com' => 2,
7694
- 'from-nh.com' => 2,
7695
- 'from-nj.com' => 2,
7696
- 'from-nm.com' => 2,
7697
- 'from-nv.com' => 2,
7698
- 'from-ny.net' => 2,
7699
- 'from-oh.com' => 2,
7700
- 'from-ok.com' => 2,
7701
- 'from-or.com' => 2,
7702
- 'from-pa.com' => 2,
7703
- 'from-pr.com' => 2,
7704
- 'from-ri.com' => 2,
7705
- 'from-sc.com' => 2,
7706
- 'from-sd.com' => 2,
7707
- 'from-tn.com' => 2,
7708
- 'from-tx.com' => 2,
7709
- 'from-ut.com' => 2,
7710
- 'from-va.com' => 2,
7711
- 'from-vt.com' => 2,
7712
- 'from-wa.com' => 2,
7713
- 'from-wi.com' => 2,
7714
- 'from-wv.com' => 2,
7715
- 'from-wy.com' => 2,
7716
- 'ftpaccess.cc' => 2,
7717
- 'fuettertdasnetz.de' => 2,
7718
- 'game-host.org' => 2,
7719
- 'game-server.cc' => 2,
7720
- 'getmyip.com' => 2,
7721
- 'gets-it.net' => 2,
7722
- 'go.dyndns.org' => 2,
7723
- 'gotdns.com' => 2,
7724
- 'gotdns.org' => 2,
7725
- 'groks-the.info' => 2,
7726
- 'groks-this.info' => 2,
7727
- 'ham-radio-op.net' => 2,
7728
- 'here-for-more.info' => 2,
7729
- 'hobby-site.com' => 2,
7730
- 'hobby-site.org' => 2,
7731
- 'home.dyndns.org' => 2,
7732
- 'homedns.org' => 2,
7733
- 'homeftp.net' => 2,
7734
- 'homeftp.org' => 2,
7735
- 'homeip.net' => 2,
7736
- 'homelinux.com' => 2,
7737
- 'homelinux.net' => 2,
7738
- 'homelinux.org' => 2,
7739
- 'homeunix.com' => 2,
7740
- 'homeunix.net' => 2,
7741
- 'homeunix.org' => 2,
7742
- 'iamallama.com' => 2,
7743
- 'in-the-band.net' => 2,
7744
- 'is-a-anarchist.com' => 2,
7745
- 'is-a-blogger.com' => 2,
7746
- 'is-a-bookkeeper.com' => 2,
7747
- 'is-a-bruinsfan.org' => 2,
7748
- 'is-a-bulls-fan.com' => 2,
7749
- 'is-a-candidate.org' => 2,
7750
- 'is-a-caterer.com' => 2,
7751
- 'is-a-celticsfan.org' => 2,
7752
- 'is-a-chef.com' => 2,
7753
- 'is-a-chef.net' => 2,
7754
- 'is-a-chef.org' => 2,
7755
- 'is-a-conservative.com' => 2,
7756
- 'is-a-cpa.com' => 2,
7757
- 'is-a-cubicle-slave.com' => 2,
7758
- 'is-a-democrat.com' => 2,
7759
- 'is-a-designer.com' => 2,
7760
- 'is-a-doctor.com' => 2,
7761
- 'is-a-financialadvisor.com' => 2,
7762
- 'is-a-geek.com' => 2,
7763
- 'is-a-geek.net' => 2,
7764
- 'is-a-geek.org' => 2,
7765
- 'is-a-green.com' => 2,
7766
- 'is-a-guru.com' => 2,
7767
- 'is-a-hard-worker.com' => 2,
7768
- 'is-a-hunter.com' => 2,
7769
- 'is-a-knight.org' => 2,
7770
- 'is-a-landscaper.com' => 2,
7771
- 'is-a-lawyer.com' => 2,
7772
- 'is-a-liberal.com' => 2,
7773
- 'is-a-libertarian.com' => 2,
7774
- 'is-a-linux-user.org' => 2,
7775
- 'is-a-llama.com' => 2,
7776
- 'is-a-musician.com' => 2,
7777
- 'is-a-nascarfan.com' => 2,
7778
- 'is-a-nurse.com' => 2,
7779
- 'is-a-painter.com' => 2,
7780
- 'is-a-patsfan.org' => 2,
7781
- 'is-a-personaltrainer.com' => 2,
7782
- 'is-a-photographer.com' => 2,
7783
- 'is-a-player.com' => 2,
7784
- 'is-a-republican.com' => 2,
7785
- 'is-a-rockstar.com' => 2,
7786
- 'is-a-socialist.com' => 2,
7787
- 'is-a-soxfan.org' => 2,
7788
- 'is-a-student.com' => 2,
7789
- 'is-a-teacher.com' => 2,
7790
- 'is-a-techie.com' => 2,
7791
- 'is-a-therapist.com' => 2,
7792
- 'is-an-accountant.com' => 2,
7793
- 'is-an-actor.com' => 2,
7794
- 'is-an-actress.com' => 2,
7795
- 'is-an-anarchist.com' => 2,
7796
- 'is-an-artist.com' => 2,
7797
- 'is-an-engineer.com' => 2,
7798
- 'is-an-entertainer.com' => 2,
7799
- 'is-by.us' => 2,
7800
- 'is-certified.com' => 2,
7801
- 'is-found.org' => 2,
7802
- 'is-gone.com' => 2,
7803
- 'is-into-anime.com' => 2,
7804
- 'is-into-cars.com' => 2,
7805
- 'is-into-cartoons.com' => 2,
7806
- 'is-into-games.com' => 2,
7807
- 'is-leet.com' => 2,
7808
- 'is-lost.org' => 2,
7809
- 'is-not-certified.com' => 2,
7810
- 'is-saved.org' => 2,
7811
- 'is-slick.com' => 2,
7812
- 'is-uberleet.com' => 2,
7813
- 'is-very-bad.org' => 2,
7814
- 'is-very-evil.org' => 2,
7815
- 'is-very-good.org' => 2,
7816
- 'is-very-nice.org' => 2,
7817
- 'is-very-sweet.org' => 2,
7818
- 'is-with-theband.com' => 2,
7819
- 'isa-geek.com' => 2,
7820
- 'isa-geek.net' => 2,
7821
- 'isa-geek.org' => 2,
7822
- 'isa-hockeynut.com' => 2,
7823
- 'issmarterthanyou.com' => 2,
7824
- 'isteingeek.de' => 2,
7825
- 'istmein.de' => 2,
7826
- 'kicks-ass.net' => 2,
7827
- 'kicks-ass.org' => 2,
7828
- 'knowsitall.info' => 2,
7829
- 'land-4-sale.us' => 2,
7830
- 'lebtimnetz.de' => 2,
7831
- 'leitungsen.de' => 2,
7832
- 'likes-pie.com' => 2,
7833
- 'likescandy.com' => 2,
7834
- 'merseine.nu' => 2,
7835
- 'mine.nu' => 2,
7836
- 'misconfused.org' => 2,
7837
- 'mypets.ws' => 2,
7838
- 'myphotos.cc' => 2,
7839
- 'neat-url.com' => 2,
7840
- 'office-on-the.net' => 2,
7841
- 'on-the-web.tv' => 2,
7842
- 'podzone.net' => 2,
7843
- 'podzone.org' => 2,
7844
- 'readmyblog.org' => 2,
7845
- 'saves-the-whales.com' => 2,
7846
- 'scrapper-site.net' => 2,
7847
- 'scrapping.cc' => 2,
7848
- 'selfip.biz' => 2,
7849
- 'selfip.com' => 2,
7850
- 'selfip.info' => 2,
7851
- 'selfip.net' => 2,
7852
- 'selfip.org' => 2,
7853
- 'sells-for-less.com' => 2,
7854
- 'sells-for-u.com' => 2,
7855
- 'sells-it.net' => 2,
7856
- 'sellsyourhome.org' => 2,
7857
- 'servebbs.com' => 2,
7858
- 'servebbs.net' => 2,
7859
- 'servebbs.org' => 2,
7860
- 'serveftp.net' => 2,
7861
- 'serveftp.org' => 2,
7862
- 'servegame.org' => 2,
7863
- 'shacknet.nu' => 2,
7864
- 'simple-url.com' => 2,
7865
- 'space-to-rent.com' => 2,
7866
- 'stuff-4-sale.org' => 2,
7867
- 'stuff-4-sale.us' => 2,
7868
- 'teaches-yoga.com' => 2,
7869
- 'thruhere.net' => 2,
7870
- 'traeumtgerade.de' => 2,
7871
- 'webhop.biz' => 2,
7872
- 'webhop.info' => 2,
7873
- 'webhop.net' => 2,
7874
- 'webhop.org' => 2,
7875
- 'worse-than.tv' => 2,
7876
- 'writesthisblog.com' => 2,
7877
- 'ddnss.de' => 2,
7878
- 'dyn.ddnss.de' => 2,
7879
- 'dyndns.ddnss.de' => 2,
7880
- 'dyndns1.de' => 2,
7881
- 'dyn-ip24.de' => 2,
7882
- 'home-webserver.de' => 2,
7883
- 'dyn.home-webserver.de' => 2,
7884
- 'myhome-server.de' => 2,
7885
- 'ddnss.org' => 2,
7886
- 'definima.net' => 2,
7887
- 'definima.io' => 2,
7888
- 'bci.dnstrace.pro' => 2,
7889
- 'ddnsfree.com' => 2,
7890
- 'ddnsgeek.com' => 2,
7891
- 'giize.com' => 2,
7892
- 'gleeze.com' => 2,
7893
- 'kozow.com' => 2,
7894
- 'loseyourip.com' => 2,
7895
- 'ooguy.com' => 2,
7896
- 'theworkpc.com' => 2,
7897
- 'casacam.net' => 2,
7898
- 'dynu.net' => 2,
7899
- 'accesscam.org' => 2,
7900
- 'camdvr.org' => 2,
7901
- 'freeddns.org' => 2,
7902
- 'mywire.org' => 2,
7903
- 'webredirect.org' => 2,
7904
- 'myddns.rocks' => 2,
7905
- 'blogsite.xyz' => 2,
7906
- 'dynv6.net' => 2,
7907
- 'e4.cz' => 2,
7908
- 'mytuleap.com' => 2,
7909
- 'onred.one' => 2,
7910
- 'staging.onred.one' => 2,
7911
- 'enonic.io' => 2,
7912
- 'customer.enonic.io' => 2,
7913
- 'eu.org' => 2,
7914
- 'al.eu.org' => 2,
7915
- 'asso.eu.org' => 2,
7916
- 'at.eu.org' => 2,
7917
- 'au.eu.org' => 2,
7918
- 'be.eu.org' => 2,
7919
- 'bg.eu.org' => 2,
7920
- 'ca.eu.org' => 2,
7921
- 'cd.eu.org' => 2,
7922
- 'ch.eu.org' => 2,
7923
- 'cn.eu.org' => 2,
7924
- 'cy.eu.org' => 2,
7925
- 'cz.eu.org' => 2,
7926
- 'de.eu.org' => 2,
7927
- 'dk.eu.org' => 2,
7928
- 'edu.eu.org' => 2,
7929
- 'ee.eu.org' => 2,
7930
- 'es.eu.org' => 2,
7931
- 'fi.eu.org' => 2,
7932
- 'fr.eu.org' => 2,
7933
- 'gr.eu.org' => 2,
7934
- 'hr.eu.org' => 2,
7935
- 'hu.eu.org' => 2,
7936
- 'ie.eu.org' => 2,
7937
- 'il.eu.org' => 2,
7938
- 'in.eu.org' => 2,
7939
- 'int.eu.org' => 2,
7940
- 'is.eu.org' => 2,
7941
- 'it.eu.org' => 2,
7942
- 'jp.eu.org' => 2,
7943
- 'kr.eu.org' => 2,
7944
- 'lt.eu.org' => 2,
7945
- 'lu.eu.org' => 2,
7946
- 'lv.eu.org' => 2,
7947
- 'mc.eu.org' => 2,
7948
- 'me.eu.org' => 2,
7949
- 'mk.eu.org' => 2,
7950
- 'mt.eu.org' => 2,
7951
- 'my.eu.org' => 2,
7952
- 'net.eu.org' => 2,
7953
- 'ng.eu.org' => 2,
7954
- 'nl.eu.org' => 2,
7955
- 'no.eu.org' => 2,
7956
- 'nz.eu.org' => 2,
7957
- 'paris.eu.org' => 2,
7958
- 'pl.eu.org' => 2,
7959
- 'pt.eu.org' => 2,
7960
- 'q-a.eu.org' => 2,
7961
- 'ro.eu.org' => 2,
7962
- 'ru.eu.org' => 2,
7963
- 'se.eu.org' => 2,
7964
- 'si.eu.org' => 2,
7965
- 'sk.eu.org' => 2,
7966
- 'tr.eu.org' => 2,
7967
- 'uk.eu.org' => 2,
7968
- 'us.eu.org' => 2,
7969
- 'eu-1.evennode.com' => 2,
7970
- 'eu-2.evennode.com' => 2,
7971
- 'eu-3.evennode.com' => 2,
7972
- 'eu-4.evennode.com' => 2,
7973
- 'us-1.evennode.com' => 2,
7974
- 'us-2.evennode.com' => 2,
7975
- 'us-3.evennode.com' => 2,
7976
- 'us-4.evennode.com' => 2,
7977
- 'twmail.cc' => 2,
7978
- 'twmail.net' => 2,
7979
- 'twmail.org' => 2,
7980
- 'mymailer.com.tw' => 2,
7981
- 'url.tw' => 2,
7982
- 'apps.fbsbx.com' => 2,
7983
- 'ru.net' => 2,
7984
- 'adygeya.ru' => 2,
7985
- 'bashkiria.ru' => 2,
7986
- 'bir.ru' => 2,
7987
- 'cbg.ru' => 2,
7988
- 'com.ru' => 2,
7989
- 'dagestan.ru' => 2,
7990
- 'grozny.ru' => 2,
7991
- 'kalmykia.ru' => 2,
7992
- 'kustanai.ru' => 2,
7993
- 'marine.ru' => 2,
7994
- 'mordovia.ru' => 2,
7995
- 'msk.ru' => 2,
7996
- 'mytis.ru' => 2,
7997
- 'nalchik.ru' => 2,
7998
- 'nov.ru' => 2,
7999
- 'pyatigorsk.ru' => 2,
8000
- 'spb.ru' => 2,
8001
- 'vladikavkaz.ru' => 2,
8002
- 'vladimir.ru' => 2,
8003
- 'abkhazia.su' => 2,
8004
- 'adygeya.su' => 2,
8005
- 'aktyubinsk.su' => 2,
8006
- 'arkhangelsk.su' => 2,
8007
- 'armenia.su' => 2,
8008
- 'ashgabad.su' => 2,
8009
- 'azerbaijan.su' => 2,
8010
- 'balashov.su' => 2,
8011
- 'bashkiria.su' => 2,
8012
- 'bryansk.su' => 2,
8013
- 'bukhara.su' => 2,
8014
- 'chimkent.su' => 2,
8015
- 'dagestan.su' => 2,
8016
- 'east-kazakhstan.su' => 2,
8017
- 'exnet.su' => 2,
8018
- 'georgia.su' => 2,
8019
- 'grozny.su' => 2,
8020
- 'ivanovo.su' => 2,
8021
- 'jambyl.su' => 2,
8022
- 'kalmykia.su' => 2,
8023
- 'kaluga.su' => 2,
8024
- 'karacol.su' => 2,
8025
- 'karaganda.su' => 2,
8026
- 'karelia.su' => 2,
8027
- 'khakassia.su' => 2,
8028
- 'krasnodar.su' => 2,
8029
- 'kurgan.su' => 2,
8030
- 'kustanai.su' => 2,
8031
- 'lenug.su' => 2,
8032
- 'mangyshlak.su' => 2,
8033
- 'mordovia.su' => 2,
8034
- 'msk.su' => 2,
8035
- 'murmansk.su' => 2,
8036
- 'nalchik.su' => 2,
8037
- 'navoi.su' => 2,
8038
- 'north-kazakhstan.su' => 2,
8039
- 'nov.su' => 2,
8040
- 'obninsk.su' => 2,
8041
- 'penza.su' => 2,
8042
- 'pokrovsk.su' => 2,
8043
- 'sochi.su' => 2,
8044
- 'spb.su' => 2,
8045
- 'tashkent.su' => 2,
8046
- 'termez.su' => 2,
8047
- 'togliatti.su' => 2,
8048
- 'troitsk.su' => 2,
8049
- 'tselinograd.su' => 2,
8050
- 'tula.su' => 2,
8051
- 'tuva.su' => 2,
8052
- 'vladikavkaz.su' => 2,
8053
- 'vladimir.su' => 2,
8054
- 'vologda.su' => 2,
8055
- 'channelsdvr.net' => 2,
8056
- 'fastly-terrarium.com' => 2,
8057
- 'fastlylb.net' => 2,
8058
- 'map.fastlylb.net' => 2,
8059
- 'freetls.fastly.net' => 2,
8060
- 'map.fastly.net' => 2,
8061
- 'a.prod.fastly.net' => 2,
8062
- 'global.prod.fastly.net' => 2,
8063
- 'a.ssl.fastly.net' => 2,
8064
- 'b.ssl.fastly.net' => 2,
8065
- 'global.ssl.fastly.net' => 2,
8066
- 'fastpanel.direct' => 2,
8067
- 'fastvps-server.com' => 2,
8068
- 'fhapp.xyz' => 2,
8069
- 'fedorainfracloud.org' => 2,
8070
- 'fedorapeople.org' => 2,
8071
- 'cloud.fedoraproject.org' => 2,
8072
- 'app.os.fedoraproject.org' => 2,
8073
- 'app.os.stg.fedoraproject.org' => 2,
8074
- 'mydobiss.com' => 2,
8075
- 'filegear.me' => 2,
8076
- 'filegear-au.me' => 2,
8077
- 'filegear-de.me' => 2,
8078
- 'filegear-gb.me' => 2,
8079
- 'filegear-ie.me' => 2,
8080
- 'filegear-jp.me' => 2,
8081
- 'filegear-sg.me' => 2,
8082
- 'firebaseapp.com' => 2,
8083
- 'flynnhub.com' => 2,
8084
- 'flynnhosting.net' => 2,
8085
- 'freebox-os.com' => 2,
8086
- 'freeboxos.com' => 2,
8087
- 'fbx-os.fr' => 2,
8088
- 'fbxos.fr' => 2,
8089
- 'freebox-os.fr' => 2,
8090
- 'freeboxos.fr' => 2,
8091
- 'freedesktop.org' => 2,
8092
- '*.futurecms.at' => 2,
8093
- '*.ex.futurecms.at' => 2,
8094
- '*.in.futurecms.at' => 2,
8095
- 'futurehosting.at' => 2,
8096
- 'futuremailing.at' => 2,
8097
- '*.ex.ortsinfo.at' => 2,
8098
- '*.kunden.ortsinfo.at' => 2,
8099
- '*.statics.cloud' => 2,
8100
- 'service.gov.uk' => 2,
8101
- 'gehirn.ne.jp' => 2,
8102
- 'usercontent.jp' => 2,
8103
- 'lab.ms' => 2,
8104
- 'github.io' => 2,
8105
- 'githubusercontent.com' => 2,
8106
- 'gitlab.io' => 2,
8107
- 'glitch.me' => 2,
8108
- 'cloudapps.digital' => 2,
8109
- 'london.cloudapps.digital' => 2,
8110
- 'homeoffice.gov.uk' => 2,
8111
- 'ro.im' => 2,
8112
- 'shop.ro' => 2,
8113
- 'goip.de' => 2,
8114
- 'run.app' => 2,
8115
- 'a.run.app' => 2,
8116
- 'web.app' => 2,
8117
- '*.0emm.com' => 2,
8118
- 'appspot.com' => 2,
8119
- 'blogspot.ae' => 2,
8120
- 'blogspot.al' => 2,
8121
- 'blogspot.am' => 2,
8122
- 'blogspot.ba' => 2,
8123
- 'blogspot.be' => 2,
8124
- 'blogspot.bg' => 2,
8125
- 'blogspot.bj' => 2,
8126
- 'blogspot.ca' => 2,
8127
- 'blogspot.cf' => 2,
8128
- 'blogspot.ch' => 2,
8129
- 'blogspot.cl' => 2,
8130
- 'blogspot.co.at' => 2,
8131
- 'blogspot.co.id' => 2,
8132
- 'blogspot.co.il' => 2,
8133
- 'blogspot.co.ke' => 2,
8134
- 'blogspot.co.nz' => 2,
8135
- 'blogspot.co.uk' => 2,
8136
- 'blogspot.co.za' => 2,
8137
- 'blogspot.com' => 2,
8138
- 'blogspot.com.ar' => 2,
8139
- 'blogspot.com.au' => 2,
8140
- 'blogspot.com.br' => 2,
8141
- 'blogspot.com.by' => 2,
8142
- 'blogspot.com.co' => 2,
8143
- 'blogspot.com.cy' => 2,
8144
- 'blogspot.com.ee' => 2,
8145
- 'blogspot.com.eg' => 2,
8146
- 'blogspot.com.es' => 2,
8147
- 'blogspot.com.mt' => 2,
8148
- 'blogspot.com.ng' => 2,
8149
- 'blogspot.com.tr' => 2,
8150
- 'blogspot.com.uy' => 2,
8151
- 'blogspot.cv' => 2,
8152
- 'blogspot.cz' => 2,
8153
- 'blogspot.de' => 2,
8154
- 'blogspot.dk' => 2,
8155
- 'blogspot.fi' => 2,
8156
- 'blogspot.fr' => 2,
8157
- 'blogspot.gr' => 2,
8158
- 'blogspot.hk' => 2,
8159
- 'blogspot.hr' => 2,
8160
- 'blogspot.hu' => 2,
8161
- 'blogspot.ie' => 2,
8162
- 'blogspot.in' => 2,
8163
- 'blogspot.is' => 2,
8164
- 'blogspot.it' => 2,
8165
- 'blogspot.jp' => 2,
8166
- 'blogspot.kr' => 2,
8167
- 'blogspot.li' => 2,
8168
- 'blogspot.lt' => 2,
8169
- 'blogspot.lu' => 2,
8170
- 'blogspot.md' => 2,
8171
- 'blogspot.mk' => 2,
8172
- 'blogspot.mr' => 2,
8173
- 'blogspot.mx' => 2,
8174
- 'blogspot.my' => 2,
8175
- 'blogspot.nl' => 2,
8176
- 'blogspot.no' => 2,
8177
- 'blogspot.pe' => 2,
8178
- 'blogspot.pt' => 2,
8179
- 'blogspot.qa' => 2,
8180
- 'blogspot.re' => 2,
8181
- 'blogspot.ro' => 2,
8182
- 'blogspot.rs' => 2,
8183
- 'blogspot.ru' => 2,
8184
- 'blogspot.se' => 2,
8185
- 'blogspot.sg' => 2,
8186
- 'blogspot.si' => 2,
8187
- 'blogspot.sk' => 2,
8188
- 'blogspot.sn' => 2,
8189
- 'blogspot.td' => 2,
8190
- 'blogspot.tw' => 2,
8191
- 'blogspot.ug' => 2,
8192
- 'blogspot.vn' => 2,
8193
- 'cloudfunctions.net' => 2,
8194
- 'cloud.goog' => 2,
8195
- 'codespot.com' => 2,
8196
- 'googleapis.com' => 2,
8197
- 'googlecode.com' => 2,
8198
- 'pagespeedmobilizer.com' => 2,
8199
- 'publishproxy.com' => 2,
8200
- 'withgoogle.com' => 2,
8201
- 'withyoutube.com' => 2,
8202
- 'fin.ci' => 2,
8203
- 'free.hr' => 2,
8204
- 'caa.li' => 2,
8205
- 'ua.rs' => 2,
8206
- 'conf.se' => 2,
8207
- 'hs.zone' => 2,
8208
- 'hs.run' => 2,
8209
- 'hashbang.sh' => 2,
8210
- 'hasura.app' => 2,
8211
- 'hasura-app.io' => 2,
8212
- 'hepforge.org' => 2,
8213
- 'herokuapp.com' => 2,
8214
- 'herokussl.com' => 2,
8215
- 'myravendb.com' => 2,
8216
- 'ravendb.community' => 2,
8217
- 'ravendb.me' => 2,
8218
- 'development.run' => 2,
8219
- 'ravendb.run' => 2,
8220
- 'bpl.biz' => 2,
8221
- 'orx.biz' => 2,
8222
- 'ng.city' => 2,
8223
- 'biz.gl' => 2,
8224
- 'ng.ink' => 2,
8225
- 'col.ng' => 2,
8226
- 'firm.ng' => 2,
8227
- 'gen.ng' => 2,
8228
- 'ltd.ng' => 2,
8229
- 'ng.school' => 2,
8230
- 'sch.so' => 2,
8231
- 'häkkinen.fi' => 2,
8232
- '*.moonscale.io' => 2,
8233
- 'moonscale.net' => 2,
8234
- 'iki.fi' => 2,
8235
- 'dyn-berlin.de' => 2,
8236
- 'in-berlin.de' => 2,
8237
- 'in-brb.de' => 2,
8238
- 'in-butter.de' => 2,
8239
- 'in-dsl.de' => 2,
8240
- 'in-dsl.net' => 2,
8241
- 'in-dsl.org' => 2,
8242
- 'in-vpn.de' => 2,
8243
- 'in-vpn.net' => 2,
8244
- 'in-vpn.org' => 2,
8245
- 'biz.at' => 2,
8246
- 'info.at' => 2,
8247
- 'info.cx' => 2,
8248
- 'ac.leg.br' => 2,
8249
- 'al.leg.br' => 2,
8250
- 'am.leg.br' => 2,
8251
- 'ap.leg.br' => 2,
8252
- 'ba.leg.br' => 2,
8253
- 'ce.leg.br' => 2,
8254
- 'df.leg.br' => 2,
8255
- 'es.leg.br' => 2,
8256
- 'go.leg.br' => 2,
8257
- 'ma.leg.br' => 2,
8258
- 'mg.leg.br' => 2,
8259
- 'ms.leg.br' => 2,
8260
- 'mt.leg.br' => 2,
8261
- 'pa.leg.br' => 2,
8262
- 'pb.leg.br' => 2,
8263
- 'pe.leg.br' => 2,
8264
- 'pi.leg.br' => 2,
8265
- 'pr.leg.br' => 2,
8266
- 'rj.leg.br' => 2,
8267
- 'rn.leg.br' => 2,
8268
- 'ro.leg.br' => 2,
8269
- 'rr.leg.br' => 2,
8270
- 'rs.leg.br' => 2,
8271
- 'sc.leg.br' => 2,
8272
- 'se.leg.br' => 2,
8273
- 'sp.leg.br' => 2,
8274
- 'to.leg.br' => 2,
8275
- 'pixolino.com' => 2,
8276
- 'ipifony.net' => 2,
8277
- 'mein-iserv.de' => 2,
8278
- 'test-iserv.de' => 2,
8279
- 'iserv.dev' => 2,
8280
- 'iobb.net' => 2,
8281
- 'myjino.ru' => 2,
8282
- '*.hosting.myjino.ru' => 2,
8283
- '*.landing.myjino.ru' => 2,
8284
- '*.spectrum.myjino.ru' => 2,
8285
- '*.vps.myjino.ru' => 2,
8286
- '*.triton.zone' => 2,
8287
- '*.cns.joyent.com' => 2,
8288
- 'js.org' => 2,
8289
- 'kaas.gg' => 2,
8290
- 'khplay.nl' => 2,
8291
- 'keymachine.de' => 2,
8292
- 'kinghost.net' => 2,
8293
- 'uni5.net' => 2,
8294
- 'knightpoint.systems' => 2,
8295
- 'co.krd' => 2,
8296
- 'edu.krd' => 2,
8297
- 'git-repos.de' => 2,
8298
- 'lcube-server.de' => 2,
8299
- 'svn-repos.de' => 2,
8300
- 'leadpages.co' => 2,
8301
- 'lpages.co' => 2,
8302
- 'lpusercontent.com' => 2,
8303
- 'lelux.site' => 2,
8304
- 'co.business' => 2,
8305
- 'co.education' => 2,
8306
- 'co.events' => 2,
8307
- 'co.financial' => 2,
8308
- 'co.network' => 2,
8309
- 'co.place' => 2,
8310
- 'co.technology' => 2,
8311
- 'app.lmpm.com' => 2,
8312
- 'linkitools.space' => 2,
8313
- 'linkyard.cloud' => 2,
8314
- 'linkyard-cloud.ch' => 2,
8315
- 'members.linode.com' => 2,
8316
- 'nodebalancer.linode.com' => 2,
8317
- 'we.bs' => 2,
8318
- 'loginline.app' => 2,
8319
- 'loginline.dev' => 2,
8320
- 'loginline.io' => 2,
8321
- 'loginline.services' => 2,
8322
- 'loginline.site' => 2,
8323
- 'krasnik.pl' => 2,
8324
- 'leczna.pl' => 2,
8325
- 'lubartow.pl' => 2,
8326
- 'lublin.pl' => 2,
8327
- 'poniatowa.pl' => 2,
8328
- 'swidnik.pl' => 2,
8329
- 'uklugs.org' => 2,
8330
- 'glug.org.uk' => 2,
8331
- 'lug.org.uk' => 2,
8332
- 'lugs.org.uk' => 2,
8333
- 'barsy.bg' => 2,
8334
- 'barsy.co.uk' => 2,
8335
- 'barsyonline.co.uk' => 2,
8336
- 'barsycenter.com' => 2,
8337
- 'barsyonline.com' => 2,
8338
- 'barsy.club' => 2,
8339
- 'barsy.de' => 2,
8340
- 'barsy.eu' => 2,
8341
- 'barsy.in' => 2,
8342
- 'barsy.info' => 2,
8343
- 'barsy.io' => 2,
8344
- 'barsy.me' => 2,
8345
- 'barsy.menu' => 2,
8346
- 'barsy.mobi' => 2,
8347
- 'barsy.net' => 2,
8348
- 'barsy.online' => 2,
8349
- 'barsy.org' => 2,
8350
- 'barsy.pro' => 2,
8351
- 'barsy.pub' => 2,
8352
- 'barsy.shop' => 2,
8353
- 'barsy.site' => 2,
8354
- 'barsy.support' => 2,
8355
- 'barsy.uk' => 2,
8356
- '*.magentosite.cloud' => 2,
8357
- 'mayfirst.info' => 2,
8358
- 'mayfirst.org' => 2,
8359
- 'hb.cldmail.ru' => 2,
8360
- 'miniserver.com' => 2,
8361
- 'memset.net' => 2,
8362
- 'cloud.metacentrum.cz' => 2,
8363
- 'custom.metacentrum.cz' => 2,
8364
- 'flt.cloud.muni.cz' => 2,
8365
- 'usr.cloud.muni.cz' => 2,
8366
- 'meteorapp.com' => 2,
8367
- 'eu.meteorapp.com' => 2,
8368
- 'co.pl' => 2,
8369
- 'azurecontainer.io' => 2,
8370
- 'azurewebsites.net' => 2,
8371
- 'azure-mobile.net' => 2,
8372
- 'cloudapp.net' => 2,
8373
- 'mozilla-iot.org' => 2,
8374
- 'bmoattachments.org' => 2,
8375
- 'net.ru' => 2,
8376
- 'org.ru' => 2,
8377
- 'pp.ru' => 2,
8378
- 'ui.nabu.casa' => 2,
8379
- 'pony.club' => 2,
8380
- 'of.fashion' => 2,
8381
- 'on.fashion' => 2,
8382
- 'of.football' => 2,
8383
- 'in.london' => 2,
8384
- 'of.london' => 2,
8385
- 'for.men' => 2,
8386
- 'and.mom' => 2,
8387
- 'for.mom' => 2,
8388
- 'for.one' => 2,
8389
- 'for.sale' => 2,
8390
- 'of.work' => 2,
8391
- 'to.work' => 2,
8392
- 'nctu.me' => 2,
8393
- 'bitballoon.com' => 2,
8394
- 'netlify.com' => 2,
8395
- '4u.com' => 2,
8396
- 'ngrok.io' => 2,
8397
- 'nh-serv.co.uk' => 2,
8398
- 'nfshost.com' => 2,
8399
- 'dnsking.ch' => 2,
8400
- 'mypi.co' => 2,
8401
- 'n4t.co' => 2,
8402
- '001www.com' => 2,
8403
- 'ddnslive.com' => 2,
8404
- 'myiphost.com' => 2,
8405
- 'forumz.info' => 2,
8406
- '16-b.it' => 2,
8407
- '32-b.it' => 2,
8408
- '64-b.it' => 2,
8409
- 'soundcast.me' => 2,
8410
- 'tcp4.me' => 2,
8411
- 'dnsup.net' => 2,
8412
- 'hicam.net' => 2,
8413
- 'now-dns.net' => 2,
8414
- 'ownip.net' => 2,
8415
- 'vpndns.net' => 2,
8416
- 'dynserv.org' => 2,
8417
- 'now-dns.org' => 2,
8418
- 'x443.pw' => 2,
8419
- 'now-dns.top' => 2,
8420
- 'ntdll.top' => 2,
8421
- 'freeddns.us' => 2,
8422
- 'crafting.xyz' => 2,
8423
- 'zapto.xyz' => 2,
8424
- 'nsupdate.info' => 2,
8425
- 'nerdpol.ovh' => 2,
8426
- 'blogsyte.com' => 2,
8427
- 'brasilia.me' => 2,
8428
- 'cable-modem.org' => 2,
8429
- 'ciscofreak.com' => 2,
8430
- 'collegefan.org' => 2,
8431
- 'couchpotatofries.org' => 2,
8432
- 'damnserver.com' => 2,
8433
- 'ddns.me' => 2,
8434
- 'ditchyourip.com' => 2,
8435
- 'dnsfor.me' => 2,
8436
- 'dnsiskinky.com' => 2,
8437
- 'dvrcam.info' => 2,
8438
- 'dynns.com' => 2,
8439
- 'eating-organic.net' => 2,
8440
- 'fantasyleague.cc' => 2,
8441
- 'geekgalaxy.com' => 2,
8442
- 'golffan.us' => 2,
8443
- 'health-carereform.com' => 2,
8444
- 'homesecuritymac.com' => 2,
8445
- 'homesecuritypc.com' => 2,
8446
- 'hopto.me' => 2,
8447
- 'ilovecollege.info' => 2,
8448
- 'loginto.me' => 2,
8449
- 'mlbfan.org' => 2,
8450
- 'mmafan.biz' => 2,
8451
- 'myactivedirectory.com' => 2,
8452
- 'mydissent.net' => 2,
8453
- 'myeffect.net' => 2,
8454
- 'mymediapc.net' => 2,
8455
- 'mypsx.net' => 2,
8456
- 'mysecuritycamera.com' => 2,
8457
- 'mysecuritycamera.net' => 2,
8458
- 'mysecuritycamera.org' => 2,
8459
- 'net-freaks.com' => 2,
8460
- 'nflfan.org' => 2,
8461
- 'nhlfan.net' => 2,
8462
- 'no-ip.ca' => 2,
8463
- 'no-ip.co.uk' => 2,
8464
- 'no-ip.net' => 2,
8465
- 'noip.us' => 2,
8466
- 'onthewifi.com' => 2,
8467
- 'pgafan.net' => 2,
8468
- 'point2this.com' => 2,
8469
- 'pointto.us' => 2,
8470
- 'privatizehealthinsurance.net' => 2,
8471
- 'quicksytes.com' => 2,
8472
- 'read-books.org' => 2,
8473
- 'securitytactics.com' => 2,
8474
- 'serveexchange.com' => 2,
8475
- 'servehumour.com' => 2,
8476
- 'servep2p.com' => 2,
8477
- 'servesarcasm.com' => 2,
8478
- 'stufftoread.com' => 2,
8479
- 'ufcfan.org' => 2,
8480
- 'unusualperson.com' => 2,
8481
- 'workisboring.com' => 2,
8482
- '3utilities.com' => 2,
8483
- 'bounceme.net' => 2,
8484
- 'ddns.net' => 2,
8485
- 'ddnsking.com' => 2,
8486
- 'gotdns.ch' => 2,
8487
- 'hopto.org' => 2,
8488
- 'myftp.biz' => 2,
8489
- 'myftp.org' => 2,
8490
- 'myvnc.com' => 2,
8491
- 'no-ip.biz' => 2,
8492
- 'no-ip.info' => 2,
8493
- 'no-ip.org' => 2,
8494
- 'noip.me' => 2,
8495
- 'redirectme.net' => 2,
8496
- 'servebeer.com' => 2,
8497
- 'serveblog.net' => 2,
8498
- 'servecounterstrike.com' => 2,
8499
- 'serveftp.com' => 2,
8500
- 'servegame.com' => 2,
8501
- 'servehalflife.com' => 2,
8502
- 'servehttp.com' => 2,
8503
- 'serveirc.com' => 2,
8504
- 'serveminecraft.net' => 2,
8505
- 'servemp3.com' => 2,
8506
- 'servepics.com' => 2,
8507
- 'servequake.com' => 2,
8508
- 'sytes.net' => 2,
8509
- 'webhop.me' => 2,
8510
- 'zapto.org' => 2,
8511
- 'stage.nodeart.io' => 2,
8512
- 'nodum.co' => 2,
8513
- 'nodum.io' => 2,
8514
- 'pcloud.host' => 2,
8515
- 'nyc.mn' => 2,
8516
- 'nom.ae' => 2,
8517
- 'nom.af' => 2,
8518
- 'nom.ai' => 2,
8519
- 'nom.al' => 2,
8520
- 'nym.by' => 2,
8521
- 'nym.bz' => 2,
8522
- 'nom.cl' => 2,
8523
- 'nym.ec' => 2,
8524
- 'nom.gd' => 2,
8525
- 'nom.ge' => 2,
8526
- 'nom.gl' => 2,
8527
- 'nym.gr' => 2,
8528
- 'nom.gt' => 2,
8529
- 'nym.gy' => 2,
8530
- 'nym.hk' => 2,
8531
- 'nom.hn' => 2,
8532
- 'nym.ie' => 2,
8533
- 'nom.im' => 2,
8534
- 'nom.ke' => 2,
8535
- 'nym.kz' => 2,
8536
- 'nym.la' => 2,
8537
- 'nym.lc' => 2,
8538
- 'nom.li' => 2,
8539
- 'nym.li' => 2,
8540
- 'nym.lt' => 2,
8541
- 'nym.lu' => 2,
8542
- 'nym.me' => 2,
8543
- 'nom.mk' => 2,
8544
- 'nym.mn' => 2,
8545
- 'nym.mx' => 2,
8546
- 'nom.nu' => 2,
8547
- 'nym.nz' => 2,
8548
- 'nym.pe' => 2,
8549
- 'nym.pt' => 2,
8550
- 'nom.pw' => 2,
8551
- 'nom.qa' => 2,
8552
- 'nym.ro' => 2,
8553
- 'nom.rs' => 2,
8554
- 'nom.si' => 2,
8555
- 'nym.sk' => 2,
8556
- 'nom.st' => 2,
8557
- 'nym.su' => 2,
8558
- 'nym.sx' => 2,
8559
- 'nom.tj' => 2,
8560
- 'nym.tw' => 2,
8561
- 'nom.ug' => 2,
8562
- 'nom.uy' => 2,
8563
- 'nom.vc' => 2,
8564
- 'nom.vg' => 2,
8565
- 'cya.gg' => 2,
8566
- 'cloudycluster.net' => 2,
8567
- 'nid.io' => 2,
8568
- 'opencraft.hosting' => 2,
8569
- 'operaunite.com' => 2,
8570
- 'outsystemscloud.com' => 2,
8571
- 'ownprovider.com' => 2,
8572
- 'own.pm' => 2,
8573
- 'ox.rs' => 2,
8574
- 'oy.lc' => 2,
8575
- 'pgfog.com' => 2,
8576
- 'pagefrontapp.com' => 2,
8577
- 'art.pl' => 2,
8578
- 'gliwice.pl' => 2,
8579
- 'krakow.pl' => 2,
8580
- 'poznan.pl' => 2,
8581
- 'wroc.pl' => 2,
8582
- 'zakopane.pl' => 2,
8583
- 'pantheonsite.io' => 2,
8584
- 'gotpantheon.com' => 2,
8585
- 'mypep.link' => 2,
8586
- 'on-web.fr' => 2,
8587
- '*.platform.sh' => 2,
8588
- '*.platformsh.site' => 2,
8589
- 'dyn53.io' => 2,
8590
- 'co.bn' => 2,
8591
- 'xen.prgmr.com' => 2,
8592
- 'priv.at' => 2,
8593
- 'prvcy.page' => 2,
8594
- '*.dweb.link' => 2,
8595
- 'protonet.io' => 2,
8596
- 'chirurgiens-dentistes-en-france.fr' => 2,
8597
- 'byen.site' => 2,
8598
- 'pubtls.org' => 2,
8599
- 'qualifioapp.com' => 2,
8600
- 'instantcloud.cn' => 2,
8601
- 'ras.ru' => 2,
8602
- 'qa2.com' => 2,
8603
- 'dev-myqnapcloud.com' => 2,
8604
- 'alpha-myqnapcloud.com' => 2,
8605
- 'myqnapcloud.com' => 2,
8606
- '*.quipelements.com' => 2,
8607
- 'vapor.cloud' => 2,
8608
- 'vaporcloud.io' => 2,
8609
- 'rackmaze.com' => 2,
8610
- 'rackmaze.net' => 2,
8611
- '*.on-rancher.cloud' => 2,
8612
- '*.on-rio.io' => 2,
8613
- 'readthedocs.io' => 2,
8614
- 'rhcloud.com' => 2,
8615
- 'app.render.com' => 2,
8616
- 'onrender.com' => 2,
8617
- 'repl.co' => 2,
8618
- 'repl.run' => 2,
8619
- 'resindevice.io' => 2,
8620
- 'devices.resinstaging.io' => 2,
8621
- 'hzc.io' => 2,
8622
- 'wellbeingzone.eu' => 2,
8623
- 'ptplus.fit' => 2,
8624
- 'wellbeingzone.co.uk' => 2,
8625
- 'git-pages.rit.edu' => 2,
8626
- 'sandcats.io' => 2,
8627
- 'logoip.de' => 2,
8628
- 'logoip.com' => 2,
8629
- 'schokokeks.net' => 2,
8630
- 'scrysec.com' => 2,
8631
- 'firewall-gateway.com' => 2,
8632
- 'firewall-gateway.de' => 2,
8633
- 'my-gateway.de' => 2,
8634
- 'my-router.de' => 2,
8635
- 'spdns.de' => 2,
8636
- 'spdns.eu' => 2,
8637
- 'firewall-gateway.net' => 2,
8638
- 'my-firewall.org' => 2,
8639
- 'myfirewall.org' => 2,
8640
- 'spdns.org' => 2,
8641
- 'biz.ua' => 2,
8642
- 'co.ua' => 2,
8643
- 'pp.ua' => 2,
8644
- 'shiftedit.io' => 2,
8645
- 'myshopblocks.com' => 2,
8646
- 'shopitsite.com' => 2,
8647
- 'mo-siemens.io' => 2,
8648
- '1kapp.com' => 2,
8649
- 'appchizi.com' => 2,
8650
- 'applinzi.com' => 2,
8651
- 'sinaapp.com' => 2,
8652
- 'vipsinaapp.com' => 2,
8653
- 'siteleaf.net' => 2,
8654
- 'bounty-full.com' => 2,
8655
- 'alpha.bounty-full.com' => 2,
8656
- 'beta.bounty-full.com' => 2,
8657
- 'stackhero-network.com' => 2,
8658
- 'static.land' => 2,
8659
- 'dev.static.land' => 2,
8660
- 'sites.static.land' => 2,
8661
- 'apps.lair.io' => 2,
8662
- '*.stolos.io' => 2,
8663
- 'spacekit.io' => 2,
8664
- 'customer.speedpartner.de' => 2,
8665
- 'api.stdlib.com' => 2,
8666
- 'storj.farm' => 2,
8667
- 'utwente.io' => 2,
8668
- 'soc.srcf.net' => 2,
8669
- 'user.srcf.net' => 2,
8670
- 'temp-dns.com' => 2,
8671
- 'applicationcloud.io' => 2,
8672
- 'scapp.io' => 2,
8673
- '*.s5y.io' => 2,
8674
- '*.sensiosite.cloud' => 2,
8675
- 'syncloud.it' => 2,
8676
- 'diskstation.me' => 2,
8677
- 'dscloud.biz' => 2,
8678
- 'dscloud.me' => 2,
8679
- 'dscloud.mobi' => 2,
8680
- 'dsmynas.com' => 2,
8681
- 'dsmynas.net' => 2,
8682
- 'dsmynas.org' => 2,
8683
- 'familyds.com' => 2,
8684
- 'familyds.net' => 2,
8685
- 'familyds.org' => 2,
8686
- 'i234.me' => 2,
8687
- 'myds.me' => 2,
8688
- 'synology.me' => 2,
8689
- 'vpnplus.to' => 2,
8690
- 'taifun-dns.de' => 2,
8691
- 'gda.pl' => 2,
8692
- 'gdansk.pl' => 2,
8693
- 'gdynia.pl' => 2,
8694
- 'med.pl' => 2,
8695
- 'sopot.pl' => 2,
8696
- 'edugit.org' => 2,
8697
- 'telebit.app' => 2,
8698
- 'telebit.io' => 2,
8699
- '*.telebit.xyz' => 2,
8700
- 'gwiddle.co.uk' => 2,
8701
- 'thingdustdata.com' => 2,
8702
- 'cust.dev.thingdust.io' => 2,
8703
- 'cust.disrec.thingdust.io' => 2,
8704
- 'cust.prod.thingdust.io' => 2,
8705
- 'cust.testing.thingdust.io' => 2,
8706
- 'arvo.network' => 2,
8707
- 'azimuth.network' => 2,
8708
- 'bloxcms.com' => 2,
8709
- 'townnews-staging.com' => 2,
8710
- '12hp.at' => 2,
8711
- '2ix.at' => 2,
8712
- '4lima.at' => 2,
8713
- 'lima-city.at' => 2,
8714
- '12hp.ch' => 2,
8715
- '2ix.ch' => 2,
8716
- '4lima.ch' => 2,
8717
- 'lima-city.ch' => 2,
8718
- 'trafficplex.cloud' => 2,
8719
- 'de.cool' => 2,
8720
- '12hp.de' => 2,
8721
- '2ix.de' => 2,
8722
- '4lima.de' => 2,
8723
- 'lima-city.de' => 2,
8724
- '1337.pictures' => 2,
8725
- 'clan.rip' => 2,
8726
- 'lima-city.rocks' => 2,
8727
- 'webspace.rocks' => 2,
8728
- 'lima.zone' => 2,
8729
- '*.transurl.be' => 2,
8730
- '*.transurl.eu' => 2,
8731
- '*.transurl.nl' => 2,
8732
- 'tuxfamily.org' => 2,
8733
- 'dd-dns.de' => 2,
8734
- 'diskstation.eu' => 2,
8735
- 'diskstation.org' => 2,
8736
- 'dray-dns.de' => 2,
8737
- 'draydns.de' => 2,
8738
- 'dyn-vpn.de' => 2,
8739
- 'dynvpn.de' => 2,
8740
- 'mein-vigor.de' => 2,
8741
- 'my-vigor.de' => 2,
8742
- 'my-wan.de' => 2,
8743
- 'syno-ds.de' => 2,
8744
- 'synology-diskstation.de' => 2,
8745
- 'synology-ds.de' => 2,
8746
- 'uber.space' => 2,
8747
- '*.uberspace.de' => 2,
8748
- 'hk.com' => 2,
8749
- 'hk.org' => 2,
8750
- 'ltd.hk' => 2,
8751
- 'inc.hk' => 2,
8752
- 'virtualuser.de' => 2,
8753
- 'virtual-user.de' => 2,
8754
- 'lib.de.us' => 2,
8755
- '2038.io' => 2,
8756
- 'router.management' => 2,
8757
- 'v-info.info' => 2,
8758
- 'voorloper.cloud' => 2,
8759
- 'wafflecell.com' => 2,
8760
- '*.webhare.dev' => 2,
8761
- 'wedeploy.io' => 2,
8762
- 'wedeploy.me' => 2,
8763
- 'wedeploy.sh' => 2,
8764
- 'remotewd.com' => 2,
8765
- 'wmflabs.org' => 2,
8766
- 'half.host' => 2,
8767
- 'xnbay.com' => 2,
8768
- 'u2.xnbay.com' => 2,
8769
- 'u2-local.xnbay.com' => 2,
8770
- 'cistron.nl' => 2,
8771
- 'demon.nl' => 2,
8772
- 'xs4all.space' => 2,
8773
- 'yandexcloud.net' => 2,
8774
- 'storage.yandexcloud.net' => 2,
8775
- 'website.yandexcloud.net' => 2,
8776
- 'official.academy' => 2,
8777
- 'yolasite.com' => 2,
8778
- 'ybo.faith' => 2,
8779
- 'yombo.me' => 2,
8780
- 'homelink.one' => 2,
8781
- 'ybo.party' => 2,
8782
- 'ybo.review' => 2,
8783
- 'ybo.science' => 2,
8784
- 'ybo.trade' => 2,
8785
- 'nohost.me' => 2,
8786
- 'noho.st' => 2,
8787
- 'za.net' => 2,
8788
- 'za.org' => 2,
8789
- 'now.sh' => 2,
8790
- 'bss.design' => 2,
8791
- 'basicserver.io' => 2,
8792
- 'virtualserver.io' => 2,
8793
- 'site.builder.nu' => 2,
8794
- 'enterprisecloud.nu' => 2,
8795
- 'zone.id' => 2,
8796
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/controller.php DELETED
@@ -1,57 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use Hammer\WP\Component;
10
-
11
-
12
- class Controller extends Component {
13
- protected $slug;
14
-
15
- /**
16
- * @return bool
17
- */
18
- protected function isInPage() {
19
- return HTTP_Helper::retrieveGet( 'page' ) == $this->slug;
20
- }
21
-
22
- /**
23
- * @param $view
24
- *
25
- * @return bool
26
- */
27
- public function isView( $view ) {
28
- return HTTP_Helper::retrieveGet( 'view' ) == $view;
29
- }
30
-
31
- /**
32
- * @return bool
33
- */
34
- public function isDashboard() {
35
- return HTTP_Helper::retrieveGet( 'page' ) == 'wp-defender';
36
- }
37
-
38
- /**
39
- * @param $viewFile
40
- * @param array $params
41
- * @param bool $echo
42
- *
43
- * @return bool|string
44
- */
45
- public function renderPartial( $viewFile, $params = array(), $echo = true ) {
46
- ob_start();
47
- $content = parent::renderPartial( $viewFile, $params, $echo );
48
- ob_end_clean();
49
-
50
- $content = apply_filters( 'wd_render_partial', $content, $viewFile, $params );
51
- if ( $echo ) {
52
- echo $content;
53
- }
54
-
55
- return $content;
56
- }
57
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/controller/dashboard.php DELETED
@@ -1,744 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Controller;
7
-
8
- use Hammer\Base\Container;
9
- use Hammer\Helper\HTTP_Helper;
10
- use WP_Defender\Behavior\Utils;
11
- use WP_Defender\Behavior\WPMUDEV;
12
- use WP_Defender\Component\Data_Factory;
13
- use WP_Defender\Controller;
14
- use WP_Defender\Module\Advanced_Tools\Model\Mask_Settings;
15
- use WP_Defender\Module\Audit\Component\Audit_API;
16
- use WP_Defender\Module\Audit\Model\Events;
17
- use WP_Defender\Module\IP_Lockout\Component\Login_Protection_Api;
18
- use WP_Defender\Module\IP_Lockout\Model\Log_Model;
19
- use WP_Defender\Module\Scan\Component\Scan_Api;
20
- use WP_Defender\Module\Scan\Component\Scanning;
21
- use WP_Defender\Module\Scan\Model\Result_Item;
22
- use WP_Defender\Module\Scan\Model\Settings;
23
- use WP_Defender\Module\Setting\Component\Backup_Settings;
24
- use WP_Defender\Module\Two_Factor\Model\Auth_Settings;
25
-
26
- class Dashboard extends Controller {
27
- protected $slug = 'wp-defender';
28
-
29
- public function __construct() {
30
- if ( $this->isNetworkActivate( wp_defender()->plugin_slug ) ) {
31
- $this->addAction( 'network_admin_menu', 'admin_menu' );
32
- } else {
33
- $this->addAction( 'admin_menu', 'admin_menu' );
34
- }
35
-
36
- if ( $this->isInPage() ) {
37
- $this->addAction( 'defender_enqueue_assets', 'scripts', 11 );
38
- }
39
-
40
- $this->addAjaxAction( 'wp-defender/v1/blacklistWidgetStatus', 'blacklistWidgetStatus' );
41
- $this->addAjaxAction( 'wp-defender/v1/toggleBlacklistWidget', 'toggleBlacklistWidget' );
42
-
43
- $module_activation = wp_defender()->isFree ? 'activateModuleFree' : 'activateModule';
44
- $this->addAjaxAction( 'wp-defender/v1/activateModule', $module_activation );
45
- $this->addAjaxAction( 'wp-defender/v1/skipActivator', 'skipQuickSetup' );
46
- $this->addAjaxAction( 'wp-defender/v1/hideFeature', 'hideFeature' );
47
- $this->addAjaxAction( 'wp-defender/v1/hideTutorials', 'hideTutorials' );
48
- $this->addAction( 'defenderSubmitStats', 'defenderSubmitStats' );
49
- $this->addFilter( 'wdp_register_hub_action', 'addMyEndpoint' );
50
- add_filter( 'custom_menu_order', '__return_true' );
51
- $this->addFilter( 'menu_order', 'menuOrder' );
52
- }
53
-
54
- /**
55
- * Activate modules
56
- */
57
- public function activateModule() {
58
- if ( ! Utils::instance()->checkPermission() ) {
59
- return;
60
- }
61
-
62
- if ( ! wp_verify_nonce( HTTP_Helper::retrieveGet( '_wpnonce' ), 'activateModule' ) ) {
63
- return;
64
- }
65
-
66
- $activator = $_POST;
67
- $activated = array();
68
- if ( count( $activator ) ) {
69
- foreach ( $activator as $item => $status ) {
70
- if ( 'false' === (string) $status ) {
71
- continue;
72
- }
73
- switch ( $item ) {
74
- case 'activate_scan':
75
- $settings = \WP_Defender\Module\Scan\Model\Settings::instance();
76
- $settings->notification = true;
77
- $settings->time = '4:00';
78
- $settings->day = 'monday';
79
- $settings->frequency = 7;
80
- $cron_time = Utils::instance()->reportCronTimestamp( $settings->time,
81
- 'scanReportCron' );
82
- wp_schedule_event( $cron_time, 'daily', 'scanReportCron' );
83
- $settings->save();
84
- //start a new scan
85
- Scan_Api::createScan();
86
- $activated[] = $item;
87
- break;
88
- case 'activate_audit':
89
- $settings = \WP_Defender\Module\Audit\Model\Settings::instance();
90
- $settings->enabled = true;
91
- $settings->notification = true;
92
- $settings->time = '4:00';
93
- $settings->day = 'monday';
94
- $settings->frequency = 7;
95
- $cron_time = Utils::instance()->reportCronTimestamp( $settings->time,
96
- 'auditReportCron' );
97
- wp_schedule_event( $cron_time, 'daily', 'auditReportCron' );
98
- $activated[] = $item;
99
- $settings->save();
100
- break;
101
- case 'activate_blacklist':
102
- if ( $this->hasMethod( 'toggleStatus' ) ) {
103
- $this->toggleStatus( - 1, false );
104
- }
105
- $activated[] = $item;
106
- break;
107
- case 'activate_lockout':
108
- $settings = \WP_Defender\Module\IP_Lockout\Model\Settings::instance();
109
- $settings->detect_404 = true;
110
- $settings->login_protection = true;
111
- $settings->report = true;
112
- $settings->report_frequency = 7;
113
- $settings->report_day = 'monday';
114
- $settings->report_time = '4:00';
115
- $cron_time = Utils::instance()->reportCronTimestamp( $settings->report_time,
116
- 'lockoutReportCron' );
117
- wp_schedule_event( $cron_time, 'daily', 'lockoutReportCron' );
118
- $activated[] = $item;
119
- $settings->save();
120
- break;
121
- default:
122
- //param not from the button on frontend, log it
123
- Utils::instance()->log( sprintf( 'Unexpected value %s from IP %s', $item,
124
- Utils::instance()->getUserIp() ) );
125
- break;
126
- }
127
- }
128
- }
129
-
130
- update_site_option( 'wp_defender_is_activated', 1 );
131
- wp_send_json_success(
132
- array(
133
- 'activated' => $activated,
134
- )
135
- );
136
- }
137
-
138
- /**
139
- * Activate modules
140
- */
141
- public function activateModuleFree() {
142
- if ( ! Utils::instance()->checkPermission() ) {
143
- return;
144
- }
145
-
146
- if ( ! wp_verify_nonce( HTTP_Helper::retrieveGet( '_wpnonce' ), 'activateModule' ) ) {
147
- return;
148
- }
149
-
150
- $activator = $_POST;
151
- $activated = array();
152
- if ( count( $activator ) ) {
153
- foreach ( $activator as $item => $status ) {
154
- if ( 'false' === (string) $status ) {
155
- continue;
156
- }
157
- switch ( $item ) {
158
- case 'activate_scan':
159
- //start a new scan
160
- Scan_Api::createScan();
161
- $activated[] = $item;
162
- break;
163
- case 'activate_lockout':
164
- $settings = \WP_Defender\Module\IP_Lockout\Model\Settings::instance();
165
- $settings->detect_404 = true;
166
- $settings->login_protection = true;
167
- $activated[] = $item;
168
- $settings->save();
169
- break;
170
- default:
171
- //param not from the button on frontend, log it
172
- Utils::instance()->log( sprintf( 'Unexpected value %s from IP %s', $item,
173
- Utils::instance()->getUserIp() ) );
174
- break;
175
- }
176
- }
177
- }
178
-
179
- update_site_option( 'wp_defender_free_is_activated', 1 );
180
- wp_send_json_success(
181
- array(
182
- 'activated' => $activated,
183
- )
184
- );
185
- }
186
-
187
- /**
188
- * Skip quick setup
189
- */
190
- public function skipQuickSetup() {
191
- if ( ! $this->checkPermission() ) {
192
- return;
193
- }
194
-
195
- if ( ! wp_verify_nonce( HTTP_Helper::retrieveGet( '_wpnonce' ), 'skipActivator' ) ) {
196
- return;
197
- }
198
- $is_free = wp_defender()->isFree ? '_free' : null;
199
- update_site_option( 'wp_defender' . $is_free . '_is_activated', 1 );
200
- wp_send_json_success();
201
- }
202
-
203
- public function hideFeature() {
204
- if ( ! $this->checkPermission() ) {
205
- return;
206
- }
207
-
208
- if ( ! wp_verify_nonce( HTTP_Helper::retrieveGet( '_wpnonce' ), 'hideFeature' ) ) {
209
- return;
210
- }
211
-
212
- delete_site_option( 'waf_show_new_feature' );
213
- wp_send_json_success();
214
- }
215
-
216
- public function hideTutorials() {
217
- if ( ! $this->checkPermission() ) {
218
- return;
219
- }
220
-
221
- if ( ! wp_verify_nonce( HTTP_Helper::retrieveGet( '_wpnonce' ), 'hideTutorials' ) ) {
222
- return;
223
- }
224
- delete_site_option( 'wp_defender_show_tutorials' );
225
- wp_send_json_success( array(
226
- 'message' => sprintf( __( "The widget has been removed. You can check all defender tutorials at the <a href=\"%s\">tutorials' tab</a> at any time.",
227
- "defender-security" ),
228
- network_admin_url( 'admin.php?page=wdf-tutorial' ) ),
229
- ) );
230
- }
231
-
232
- public function menuOrder( $menu_order ) {
233
- global $submenu;
234
- if ( isset( $submenu['wp-defender'] ) ) {
235
- $defender_menu = $submenu['wp-defender'];
236
- $defender_menu[0][0] = esc_html__( 'Dashboard', "defender-security" );
237
- $defender_menu = array_values( $defender_menu );
238
- $submenu['wp-defender'] = $defender_menu;
239
- }
240
-
241
- global $menu;
242
- $count = $this->countTotalIssues();
243
- $indicator = $count > 0 ? ' <span class="update-plugins wd-issue-indicator-sidebar"><span class="plugin-count">' . $count . '</span></span>' : null;
244
- foreach ( $menu as $k => $item ) {
245
- if ( 'wp-defender' === $item[2] ) {
246
- $menu[ $k ][0] .= $indicator;
247
- }
248
- }
249
-
250
- return $menu_order;
251
- }
252
-
253
- public function defenderSubmitStats() {
254
- if ( $this->hasMethod( '_submitStatsToDev' ) ) {
255
- $this->_submitStatsToDev();
256
- }
257
- }
258
-
259
- /**
260
- * @param $actions
261
- *
262
- * @return mixed
263
- */
264
- public function addMyEndpoint( $actions ) {
265
- $actions['defender_new_scan'] = array( &$this, 'newScan' );
266
- $actions['defender_schedule_scan'] = array( &$this, 'scheduleScan' );
267
- $actions['defender_manage_audit_log'] = array( &$this, 'manageAuditLog' );
268
- $actions['defender_manage_lockout'] = array( &$this, 'manageLockout' );
269
- $actions['defender_whitelist_ip'] = array( &$this, 'whitelistIP' );
270
- $actions['defender_blacklist_ip'] = array( &$this, 'blacklistIP' );
271
- $actions['defender_get_stats'] = array( &$this, 'getStats' );
272
- $actions['defender_get_scan_progress'] = array( &$this, 'getScanProgress' );
273
-
274
- //backup/restore settings
275
- $actions['defender_export_settings'] = array( &$this, 'exportSettings' );
276
- $actions['defender_import_settings'] = array( &$this, 'importSettings' );
277
-
278
- $actions['defender_get_stats_v2'] = [ &$this, 'defender_get_stats_v2' ];
279
-
280
- return $actions;
281
- }
282
-
283
- public function defender_get_stats_v2( $params, $action ) {
284
- if ( ! class_exists( WPMUDEV::class ) ) {
285
- return wp_send_json_error();
286
- }
287
- $date_format = 'm/d/Y';
288
- $wpmudev = WPMUDEV::instance();
289
- $summary = $wpmudev->stats_summary();
290
- $report = $wpmudev->stats_report();
291
- $tweaks = $wpmudev->stats_security_tweaks();
292
- global $wp_version;
293
- $for_hub = true;
294
- $scan = $wpmudev->stats_malware_scan();
295
- $firewall = Log_Model::getSummary( $for_hub );
296
-
297
- $audit = Audit_API::summary( $for_hub );
298
- $security_headers = $wpmudev->stats_security_headers();
299
-
300
- $ret = [
301
- 'summary' => [
302
- 'count' => $summary['count'],
303
- 'next_scan' => $summary['next_scan']
304
- ],
305
- 'report' => [
306
- 'malware_scan' => $report['scan'],
307
- 'firewall' => $report['firewall'],
308
- 'audit_logging' => $report['audit']
309
- ],
310
- 'security_tweaks' => [
311
- 'issues' => $tweaks['issues'],
312
- 'fixed' => $tweaks['fixed'],
313
- 'notification' => $tweaks['notification'],
314
- 'wp_version' => $wp_version,
315
- 'php_version' => phpversion()
316
- ],
317
- 'malware_scan' => [
318
- 'count' => $scan['count'],
319
- 'notification' => $scan['notification']
320
- ],
321
- 'firewall' => [
322
- 'last_lockout' => $firewall['lastLockout'],
323
- '24_hours' => [
324
- 'login_lockout' => $firewall['loginLockoutToday'],
325
- '404_lockout' => $firewall['lockout404Today']
326
- ],
327
- '7_days' => [
328
- 'login_lockout' => $firewall['loginLockoutThisWeek'],
329
- '404_lockout' => $firewall['lockout404ThisWeek']
330
- ],
331
- '30_days' => [
332
- 'login_lockout' => $firewall['lockoutLoginThisMonth'],
333
- '404_lockout' => $firewall['lockout404ThisMonth']
334
- ],
335
- 'notification_status' => [
336
- 'login_lockout' => \WP_Defender\Module\IP_Lockout\Model\Settings::instance()->login_lockout_notification,
337
- '404_lockout' => \WP_Defender\Module\IP_Lockout\Model\Settings::instance()->ip_lockout_notification
338
- ]
339
- ],
340
- 'audit' => [
341
- 'last_event' => $audit['lastEvent'],
342
- '24_hours' => $audit['day_count'],
343
- '7_days' => $audit['last_7_days'],
344
- '30_days' => $audit['last_30_days']
345
- ],
346
- 'advanced_tools' => [
347
- 'security_headers' => $security_headers,
348
- 'mask_login' => Mask_Settings::instance()->isEnabled()
349
- ],
350
- 'two_fa' => [
351
- 'status' => Auth_Settings::instance()->enabled,
352
- 'lost_phone' => Auth_Settings::instance()->lost_phone
353
- ]
354
- ];
355
- Utils::instance()->log( json_encode( $ret ) );
356
- wp_send_json_success( [
357
- 'stats' => $ret
358
- ] );
359
- }
360
-
361
- public function importSettings( $params ) {
362
- //dirty but quick
363
- $configs = json_decode( json_encode( $params->configs ), true );
364
- foreach ( $configs as $module => $mdata ) {
365
- foreach ( $mdata as $key => $value ) {
366
- if ( 'geoIP_db' === $key ) {
367
- if ( ! empty( $value ) ) {
368
- //download it
369
- Login_Protection_Api::downloadGeoIP();
370
- } else {
371
- //reset it
372
- $mdata[ $key ] = '';
373
- }
374
- } elseif ( is_string( $value ) ) {
375
- $value = str_replace( '{nl}', PHP_EOL, $value );
376
- $mdata[ $key ] = $value;
377
- }
378
- }
379
- $configs[ $module ] = $mdata;
380
- }
381
- Backup_Settings::restoreData( $configs );
382
-
383
- wp_send_json_success();
384
- }
385
-
386
- public function exportSettings() {
387
- $data = Backup_Settings::parseDataForHub();
388
- //we have to replace all the new line in configs
389
- $configs = $data['configs'];
390
- foreach ( $configs as $module => $mdata ) {
391
- foreach ( $mdata as $key => $value ) {
392
- if ( is_string( $value ) ) {
393
- $value = str_replace( array( "\r", "\n" ), '{nl}', $value );
394
- $mdata[ $key ] = $value;
395
- }
396
- }
397
- $configs[ $module ] = $mdata;
398
- }
399
- $data['configs'] = $configs;
400
- wp_send_json_success( $data );
401
- }
402
-
403
- public function getScanProgress() {
404
- $scanning = new Scanning();
405
- $ret = $scanning->run();
406
- if ( is_wp_error( $ret ) ) {
407
- wp_send_json_error(
408
- array(
409
- 'message' => $ret->get_error_message(),
410
- )
411
- );
412
- } else {
413
- $percent = $scanning->getScanProgress();
414
- if ( true === $ret ) {
415
- $percent = 100;
416
- }
417
- wp_send_json_success(
418
- array(
419
- 'progress' => $percent,
420
- )
421
- );
422
- }
423
- }
424
-
425
- /**
426
- * @param $params
427
- * @param $action
428
- */
429
- public function newScan( $params, $action ) {
430
- $ret = Scan_Api::createScan();
431
- if ( is_wp_error( $ret ) ) {
432
- wp_send_json_error(
433
- array(
434
- 'message' => $ret->get_error_message(),
435
- )
436
- );
437
- }
438
-
439
- wp_send_json_success();
440
- }
441
-
442
- /**
443
- * @param $params
444
- * @param $action
445
- */
446
- public function scheduleScan( $params, $action ) {
447
- $frequency = $params['frequency'];
448
- $day = $params['day'];
449
- $time = $params['time'];
450
- $allowed_freq = array( 1, 7, 30 );
451
- if ( ! in_array( $frequency, $allowed_freq ) || ! in_array( $day,
452
- Utils::instance()->getDaysOfWeek() ) || ! in_array( $time, Utils::instance()->getTimes() ) ) {
453
- wp_send_json_error();
454
- }
455
- $settings = Settings::instance();
456
- $settings->frequency = $frequency;
457
- $settings->day = $day;
458
- $settings->time = $time;
459
-
460
- wp_send_json_success();
461
- }
462
-
463
- /**
464
- * Hub Audit log endpoint
465
- *
466
- * @param $params
467
- * @param $action
468
- */
469
- public function manageAuditLog( $params, $action ) {
470
- $response = null;
471
- if ( class_exists( '\WP_Defender\Module\Audit\Model\Settings' ) ) {
472
- $response = array();
473
- $settings = \WP_Defender\Module\Audit\Model\Settings::instance();
474
- if ( true === $settings->enabled ) {
475
- $settings->enabled = false;
476
- $response['enabled'] = false;
477
- } else {
478
- $settings->enabled = true;
479
- $response['enabled'] = true;
480
- }
481
- $settings->save();
482
- }
483
- wp_send_json_success( $response );
484
- }
485
-
486
- /**
487
- * Hub Lockouts endpoint
488
- *
489
- * @param $params
490
- * @param $action
491
- */
492
- public function manageLockout( $params, $action ) {
493
- $type = $params['type'];
494
- $settings = \WP_Defender\Module\IP_Lockout\Model\Settings::instance();
495
- $response = array();
496
- if ( 'login' === $type ) {
497
- if ( $settings->login_protection ) {
498
- $settings->login_protection = 0;
499
- $response[ $type ] = 'disabled';
500
- } else {
501
- $settings->login_protection = 1;
502
- $response[ $type ] = 'enabled';
503
- }
504
- $settings->save();
505
- } elseif ( '404' === $type ) {
506
- if ( $settings->detect_404 ) {
507
- $settings->detect_404 = 0;
508
- $response[ $type ] = 'disabled';
509
- } else {
510
- $settings->detect_404 = 1;
511
- $response[ $type ] = 'enabled';
512
- }
513
- $settings->save();
514
- } else {
515
- $response[ $type ] = 'invalid';
516
- }
517
- wp_send_json_success();
518
- }
519
-
520
- /**
521
- * Hub Whitelist IP endpoint
522
- *
523
- * @param $params
524
- * @param $action
525
- */
526
- public function whitelistIP( $params, $action ) {
527
- $settings = \WP_Defender\Module\IP_Lockout\Model\Settings::instance();
528
- $ip = $params['ip'];
529
- if ( $ip && filter_var( $ip, FILTER_VALIDATE_IP ) ) {
530
- $settings->removeIpFromList( $ip, 'blocklist' );
531
- $settings->addIpToList( $ip, 'allowlist' );
532
- } else {
533
- wp_send_json_error();
534
- }
535
- wp_send_json_success();
536
- }
537
-
538
- /**
539
- * Hub Blacklist IP endpoint
540
- *
541
- * @param $params
542
- * @param $action
543
- */
544
- public function blacklistIP( $params, $action ) {
545
- $settings = \WP_Defender\Module\IP_Lockout\Model\Settings::instance();
546
- $ip = $params['ip'];
547
- if ( $ip && filter_var( $ip, FILTER_VALIDATE_IP ) ) {
548
- $settings->removeIpFromList( $ip, 'allowlist' );
549
- $settings->addIpToList( $ip, 'blocklist' );
550
- } else {
551
- wp_send_json_error();
552
- }
553
- wp_send_json_success();
554
- }
555
-
556
- /**
557
- * Hub Stats endpoint
558
- *
559
- * @param $params
560
- * @param $action
561
- */
562
- public function getStats( $params, $action ) {
563
- $stats = Utils::instance()->generateStats();
564
- wp_send_json_success(
565
- array(
566
- 'stats' => $stats,
567
- )
568
- );
569
- }
570
-
571
- public function actionIndex() {
572
- $this->render( 'main' );
573
- }
574
-
575
- public function blacklistWidgetStatus() {
576
- if ( ! $this->checkPermission() ) {
577
- return;
578
- }
579
-
580
- if ( ! wp_verify_nonce( HTTP_Helper::retrieveGet( '_wpnonce' ), 'blacklistWidgetStatus' ) ) {
581
- return;
582
- }
583
-
584
- if ( $this->hasMethod( 'pullBlacklistStatus' ) ) {
585
- $this->pullBlacklistStatus();
586
- }
587
-
588
- exit;
589
- }
590
-
591
- public function toggleBlacklistWidget() {
592
- if ( ! $this->checkPermission() ) {
593
- return;
594
- }
595
-
596
- if ( ! wp_verify_nonce( HTTP_Helper::retrieveGet( '_wpnonce' ), 'toggleBlacklistWidget' ) ) {
597
- return;
598
- }
599
-
600
- if ( $this->hasMethod( 'toggleStatus' ) ) {
601
- $this->toggleStatus();
602
- }
603
-
604
- exit;
605
- }
606
-
607
- /**
608
- * @param bool $detail
609
- *
610
- * @return array|int|null|string
611
- */
612
- public function countTotalIssues( $detail = false ) {
613
- $hardener_count = count( \WP_Defender\Module\Hardener\Model\Settings::instance()->issues );
614
- $scan = Scan_Api::getLastScan();
615
- $total = $hardener_count;
616
- $scan_count = 0;
617
- if ( is_object( $scan ) ) {
618
- $scan_count = $scan->countAll( Result_Item::STATUS_ISSUE );
619
-
620
- $total += $scan_count;
621
- }
622
- if ( false === $detail ) {
623
- return $total;
624
- }
625
-
626
- return array( $hardener_count, $scan_count );
627
- }
628
-
629
- /**
630
- *
631
- */
632
- public function admin_menu() {
633
- $cap = is_multisite() ? 'manage_network_options' : 'manage_options';
634
- $menu_title = wp_defender()->isFree ? esc_html__( 'Defender',
635
- "defender-security" ) : esc_html__( 'Defender Pro',
636
- "defender-security" );
637
- add_menu_page(
638
- $menu_title,
639
- $menu_title,
640
- $cap,
641
- 'wp-defender',
642
- array(
643
- &$this,
644
- 'actionIndex',
645
- ),
646
- $this->get_menu_icon()
647
- );
648
- }
649
-
650
- /**
651
- * Return svg image
652
- * @return string
653
- */
654
- private function get_menu_icon() {
655
- ob_start();
656
- ?>
657
- <svg width="17px" height="18px" viewBox="10 397 17 18" version="1.1" xmlns="http://www.w3.org/2000/svg"
658
- >
659
- <!-- Generator: Sketch 3.8.3 (29802) - http://www.bohemiancoding.com/sketch -->
660
- <desc>Created with Sketch.</desc>
661
- <defs></defs>
662
- <path
663
- d="M24.8009393,403.7962 L23.7971393,410.1724 C23.7395393,410.5372 23.5313393,410.8528 23.2229393,411.0532 L18.4001393,413.6428 L13.5767393,411.0532 C13.2683393,410.8528 13.0601393,410.5372 13.0019393,410.1724 L11.9993393,403.7962 L11.6153393,401.3566 C12.5321393,402.9514 14.4893393,405.5518 18.4001393,408.082 C22.3115393,405.5518 24.2675393,402.9514 25.1855393,401.3566 L24.8009393,403.7962 Z M26.5985393,398.0644 C25.7435393,397.87 22.6919393,397.2106 19.9571393,397 L19.9571393,403.4374 L18.4037393,404.5558 L16.8431393,403.4374 L16.8431393,397 C14.1077393,397.2106 11.0561393,397.87 10.2011393,398.0644 C10.0685393,398.0938 9.98213933,398.221 10.0031393,398.3536 L10.8875393,403.969 L11.8913393,410.3446 C12.0071393,411.0796 12.4559393,411.7192 13.1105393,412.0798 L16.8431393,414.1402 L18.4001393,415 L19.9571393,414.1402 L23.6891393,412.0798 C24.3431393,411.7192 24.7925393,411.0796 24.9083393,410.3446 L25.9121393,403.969 L26.7965393,398.3536 C26.8175393,398.221 26.7311393,398.0938 26.5985393,398.0644 L26.5985393,398.0644 Z"
664
- id="Defender-Icon" stroke="none" fill="#FFFFFF" fill-rule="evenodd"></path>
665
- </svg>
666
- <?php
667
- $svg = ob_get_clean();
668
-
669
- return 'data:image/svg+xml;base64,' . base64_encode( $svg );
670
- }
671
-
672
- public function isShowTutorials() {
673
- return get_site_option( 'wp_defender_show_tutorials' );
674
- }
675
-
676
- public function scripts() {
677
- wp_enqueue_style( 'defender' );
678
- wp_register_script(
679
- 'defender-dashboard',
680
- wp_defender()->getPluginUrl() . 'assets/app/dashboard.js',
681
- array(
682
- 'def-vue',
683
- 'defender',
684
- 'wp-i18n',
685
- ),
686
- wp_defender()->version,
687
- true
688
- );
689
- Utils::instance()->createTranslationJson( 'defender-dashboard' );
690
- wp_set_script_translations( 'defender-dashboard', 'wpdef', wp_defender()->getPluginPath() . 'languages' );
691
- $waf = Container::instance()->get( 'waf' );
692
- wp_localize_script(
693
- 'defender-dashboard',
694
- 'dashboard',
695
- array_merge(
696
- Data_Factory::buildData(),
697
- array(
698
- 'quick_setup' => array(
699
- 'show' => $this->isShowActivator(),
700
- 'nonces' => array(
701
- 'skip' => wp_create_nonce( 'skipActivator' ),
702
- 'activate' => wp_create_nonce( 'activateModule' ),
703
- ),
704
- 'endpoints' => array(
705
- 'skip' => 'wp-defender/v1/skipActivator',
706
- 'activate' => 'wp-defender/v1/activateModule',
707
- ),
708
- ),
709
- 'new_features' => array(
710
- 'show' => $waf->maybe_show_modal(),
711
- 'nonces' => array(
712
- 'hide' => wp_create_nonce( 'hideFeature' ),
713
- ),
714
- 'endpoints' => array(
715
- 'hide' => 'wp-defender/v1/hideFeature',
716
- ),
717
- ),
718
- 'tutorials' => array(
719
- 'show' => $this->isShowTutorials(),
720
- 'nonces' => array(
721
- 'hide' => wp_create_nonce( 'hideTutorials' ),
722
- ),
723
- 'endpoints' => array(
724
- 'hide' => 'wp-defender/v1/hideTutorials',
725
- ),
726
- )
727
- )
728
- )
729
- );
730
- wp_enqueue_script( 'defender-dashboard' );
731
- wp_enqueue_script( 'wpmudev-sui' );
732
- }
733
-
734
- /**
735
- * @return array
736
- */
737
- public function behaviors() {
738
- return array(
739
- 'utils' => '\WP_Defender\Behavior\Utils',
740
- 'activator' => wp_defender()->isFree ? '\WP_Defender\Behavior\Activator_Free' : '\WP_Defender\Behavior\Activator',
741
- 'blacklist' => wp_defender()->isFree ? '\WP_Defender\Behavior\Blacklist_Free' : '\WP_Defender\Behavior\Blacklist',
742
- );
743
- }
744
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/controller/debug.php DELETED
@@ -1,79 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Controller;
7
-
8
- use Hammer\Base\Container;
9
- use Hammer\Helper\HTTP_Helper;
10
- use WP_Defender\Controller;
11
- use WP_Defender\Module\Hardener\Model\Settings;
12
- use WP_Defender\Module\Scan\Component\Scan_Api;
13
- use WP_Defender\Module\Scan\Component\Scanning;
14
-
15
- class Debug extends Controller {
16
- protected $slug = 'wdf-debug';
17
-
18
- public function __construct() {
19
- if ( HTTP_Helper::retrieveGet( 'page' ) != 'wdf-debug' ) {
20
- return;
21
- }
22
- if ( $this->isInPage() ) {
23
- $this->addAction( 'defender_enqueue_assets', 'scripts', 11 );
24
- }
25
- if ( $this->isNetworkActivate( wp_defender()->plugin_slug ) ) {
26
- $this->addAction( 'network_admin_menu', 'adminMenu' );
27
- } else {
28
- $this->addAction( 'admin_menu', 'adminMenu' );
29
- }
30
-
31
- $this->addAction( 'wp_loaded', 'clearTweaksCache' );
32
- }
33
-
34
- public function clearTweaksCache() {
35
- if ( $_SERVER['REQUEST_METHOD'] != 'POST' ) {
36
- return;
37
- }
38
-
39
- if ( isset( $_POST['_defnonce'] ) && wp_verify_nonce( $_POST['_defnonce'], 'flush_tweaks_cache' ) ) {
40
- $model = Settings::instance();
41
- $model->setDValues( 'head_requests', null );
42
- }
43
- }
44
-
45
- public function scripts() {
46
- wp_enqueue_style( 'defender' );
47
- wp_enqueue_script( 'wpmudev-sui' );
48
- }
49
-
50
- /**
51
- * Add submit admin page
52
- */
53
- public function adminMenu() {
54
- $cap = is_multisite() ? 'manage_network_options' : 'manage_options';
55
- add_submenu_page( 'wp-defender', esc_html__( "Debug", "defender-security" ), esc_html__( "Debug", "defender-security" ), $cap, $this->slug, array(
56
- &$this,
57
- 'actionIndex'
58
- ) );
59
- }
60
-
61
- public function actionIndex() {
62
- $cache = Container::instance()->get( 'cache' );
63
- $scanning = new Scanning();
64
- $this->render( 'debug', [
65
- 'core' => $cache->get( Scan_Api::CACHE_CORE, [] ),
66
- 'content' => $cache->get( Scan_Api::CACHE_CONTENT, [] ),
67
- 'progress' => $scanning->getScanProgress()
68
- ] );
69
- }
70
-
71
- /**
72
- * @return array
73
- */
74
- public function behaviors() {
75
- return array(
76
- 'utils' => '\WP_Defender\Behavior\Utils'
77
- );
78
- }
79
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/controller/gdpr.php DELETED
@@ -1,24 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Controller;
7
-
8
- use WP_Defender\Controller;
9
-
10
- class GDPR extends Controller {
11
- public function __construct() {
12
- $this->addFilter( 'wp_get_default_privacy_policy_content', 'addPolicy' );
13
- }
14
-
15
- public function addPolicy( $content ) {
16
- $pluginName = wp_defender()->isFree ? __( "Defender", "defender-security" ) : __( "Defender Pro", "defender-security" );
17
- $content .= '<h3>' . sprintf( __( 'Plugin: %s', "defender-security" ), $pluginName ) . '</h3>';
18
- $content .= '<p><strong>' . __( "Third parties", "defender-security" ) . '</strong></p>';
19
- $content .= '<p>' . __( "This site may be using WPMU DEV third-party cloud storage to store backups of its audit logs where personal information is collected.", "defender-security" ) . '</p>';
20
- $content .= '<p><strong>' . __( "Additional data", "defender-security" ) . '</strong></p>';
21
- $content .= '<p>' . __( "This site creates and stores an activity log that capture the IP address, username, email address and tracks user activity (like when a user makes a comment). Information will be stored locally for 30 days and remotely for 1 year. Information on remote logs cannot be cleared for security purposes.", "defender-security" ) . '</p>';
22
- return $content;
23
- }
24
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/controller/requirement.php DELETED
@@ -1,102 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Author: Hoang Ngo
5
- */
6
- class WD_Requirement {
7
- protected $slug = 'wp-defender';
8
-
9
- public function __construct() {
10
- if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
11
- require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
12
- }
13
-
14
- $networkActivate = is_plugin_active_for_network( 'wp-defender/wp-defender.php' );
15
-
16
- if ( $networkActivate ) {
17
- add_action( 'network_admin_menu', array( &$this, 'admin_menu' ) );
18
- } else {
19
- add_action( 'admin_menu', array( &$this, 'admin_menu' ) );
20
- }
21
-
22
- if ( isset( $_GET['page'] ) && $_GET['page'] == $this->slug ) {
23
- add_action( 'defender_enqueue_assets', array( &$this, 'scripts' ), 11 );
24
- }
25
- }
26
-
27
- public function actionIndex() {
28
- ?>
29
- <div class="wrap">
30
- <div class="wp-defender">
31
- <div class="wdf-requirement">
32
- <h2 class="title">
33
-
34
- </h2>
35
- </div>
36
- </div>
37
- <dialog id="requirement" title="<?php esc_attr_e( "Required Modules", "defender-security" ) ?>">
38
- <div class="line">
39
- <?php _e( "It looks like some required PHP modules are missing or outdated. We recommend you get in touch with your web hosting service to update the modules listed below.", "defender-security" ) ?>
40
- </div>
41
- <table class="table">
42
- <thead>
43
- <tr>
44
- <th><?php _e( "Module", "defender-security" ) ?></th>
45
- <th><?php _e( "Version", "defender-security" ) ?></th>
46
- </tr>
47
- </thead>
48
- <tbody>
49
- <tr>
50
- <td><?php _e( "PHP version", "defender-security" ) ?></td>
51
- <td>
52
- <?php _e( "Please upgrade to 5.6 or later.", "defender-security" ) ?>
53
- </td>
54
- </tr>
55
- </tbody>
56
- </table>
57
- </dialog>
58
- </div>
59
- <?php
60
- }
61
-
62
- /**
63
- *
64
- */
65
- public function admin_menu() {
66
- $cap = is_multisite() ? 'manage_network_options' : 'manage_options';
67
- $menu_title = esc_html__( "Defender%s", "defender-security" );
68
- $menu_title = sprintf( $menu_title, ' <span class="update-plugins wd-issue-indicator-sidebar"></span>' );
69
- add_menu_page( esc_html__( "Defender", "defender-security" ), $menu_title, $cap, 'wp-defender', array(
70
- &$this,
71
- 'actionIndex'
72
- ), $this->get_menu_icon() );
73
- }
74
-
75
- /**
76
- * Return svg image
77
- * @return string
78
- */
79
- private function get_menu_icon() {
80
- ob_start();
81
- ?>
82
- <svg width="17px" height="18px" viewBox="10 397 17 18" version="1.1" xmlns="http://www.w3.org/2000/svg"
83
- xmlns:xlink="http://www.w3.org/1999/xlink">
84
- <!-- Generator: Sketch 3.8.3 (29802) - http://www.bohemiancoding.com/sketch -->
85
- <desc>Created with Sketch.</desc>
86
- <defs></defs>
87
- <path
88
- d="M24.8009393,403.7962 L23.7971393,410.1724 C23.7395393,410.5372 23.5313393,410.8528 23.2229393,411.0532 L18.4001393,413.6428 L13.5767393,411.0532 C13.2683393,410.8528 13.0601393,410.5372 13.0019393,410.1724 L11.9993393,403.7962 L11.6153393,401.3566 C12.5321393,402.9514 14.4893393,405.5518 18.4001393,408.082 C22.3115393,405.5518 24.2675393,402.9514 25.1855393,401.3566 L24.8009393,403.7962 Z M26.5985393,398.0644 C25.7435393,397.87 22.6919393,397.2106 19.9571393,397 L19.9571393,403.4374 L18.4037393,404.5558 L16.8431393,403.4374 L16.8431393,397 C14.1077393,397.2106 11.0561393,397.87 10.2011393,398.0644 C10.0685393,398.0938 9.98213933,398.221 10.0031393,398.3536 L10.8875393,403.969 L11.8913393,410.3446 C12.0071393,411.0796 12.4559393,411.7192 13.1105393,412.0798 L16.8431393,414.1402 L18.4001393,415 L19.9571393,414.1402 L23.6891393,412.0798 C24.3431393,411.7192 24.7925393,411.0796 24.9083393,410.3446 L25.9121393,403.969 L26.7965393,398.3536 C26.8175393,398.221 26.7311393,398.0938 26.5985393,398.0644 L26.5985393,398.0644 Z"
89
- id="Defender-Icon" stroke="none" fill="#FFFFFF" fill-rule="evenodd"></path>
90
- </svg>
91
- <?php
92
- $svg = ob_get_clean();
93
-
94
- return 'data:image/svg+xml;base64,' . base64_encode( $svg );
95
- }
96
-
97
- public function scripts() {
98
- WDEV_Plugin_Ui::load( wp_defender()->getPluginUrl() . 'shared-ui/' );
99
- wp_enqueue_script( 'defender' );
100
- wp_enqueue_style( 'defender' );
101
- }
102
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/controller/tutorial.php DELETED
@@ -1,61 +0,0 @@
1
- <?php
2
-
3
- namespace WP_Defender\Controller;
4
-
5
- use Hammer\Helper\HTTP_Helper;
6
- use WP_Defender\Behavior\Utils;
7
- use WP_Defender\Behavior\WPMUDEV;
8
- use WP_Defender\Controller;
9
-
10
- class Tutorial extends Controller {
11
- public $slug = 'wdf-tutorial';
12
-
13
- public function __construct() {
14
- if ( $this->isNetworkActivate( wp_defender()->plugin_slug ) ) {
15
- $this->addAction( 'network_admin_menu', 'admin_menu' );
16
- } else {
17
- $this->addAction( 'admin_menu', 'admin_menu' );
18
- }
19
-
20
- if ( $this->isInPage() ) {
21
- $this->addAction( 'defender_enqueue_assets', 'scripts', 11 );
22
- }
23
- }
24
-
25
- public function admin_menu() {
26
- $cap = is_multisite() ? 'manage_network_options' : 'manage_options';
27
- $action = 'actionIndex';
28
- add_submenu_page( 'wp-defender', esc_html__( 'Tutorials', "defender-security" ),
29
- esc_html__( 'Tutorials', "defender-security" ), $cap, $this->slug, array(
30
- &$this,
31
- $action
32
- ) );
33
- }
34
-
35
- public function actionIndex() {
36
- $this->render( 'main' );
37
- }
38
-
39
- public function scripts() {
40
- wp_enqueue_style( 'wpmudev-sui' );
41
- wp_enqueue_style( 'defender' );
42
- wp_enqueue_media();
43
- wp_register_script( 'defender-tutorial', wp_defender()->getPluginUrl() . 'assets/app/tutorial.js', array(
44
- 'def-vue',
45
- 'defender',
46
- 'wp-i18n'
47
- ), wp_defender()->version, true );
48
- wp_localize_script( 'defender-tutorial', 'tutorial', $this->_scriptsData() );
49
- Utils::instance()->createTranslationJson( 'defender-tutorial' );
50
- wp_set_script_translations( 'defender-tutorial', 'wpdef', wp_defender()->getPluginPath() . 'languages' );
51
- wp_enqueue_script( 'defender-tutorial' );
52
- wp_enqueue_script( 'wpmudev-sui' );
53
- }
54
-
55
- public function _scriptsData() {
56
- return array(
57
- 'time_read' => __( 'min read', "defender-security" ),
58
- 'title_read_link' => __( 'Read article', "defender-security" ),
59
- );
60
- }
61
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/controller/waf.php DELETED
@@ -1,174 +0,0 @@
1
- <?php
2
-
3
- namespace WP_Defender\Controller;
4
-
5
- use Hammer\Helper\HTTP_Helper;
6
- use WP_Defender\Behavior\Utils;
7
- use WP_Defender\Behavior\WPMUDEV;
8
- use WP_Defender\Controller;
9
-
10
- class Waf extends Controller {
11
- public $slug = 'wdf-waf';
12
-
13
- public function __construct() {
14
- if ( $this->isNetworkActivate( wp_defender()->plugin_slug ) ) {
15
- $this->addAction( 'network_admin_menu', 'admin_menu' );
16
- } else {
17
- $this->addAction( 'admin_menu', 'admin_menu' );
18
- }
19
-
20
- if ( $this->isInPage() ) {
21
- $this->addAction( 'defender_enqueue_assets', 'scripts', 11 );
22
- }
23
- $this->addAjaxAction( 'wp-defender/v1/waf/recheck', 'recheck' );
24
- }
25
-
26
- public function admin_menu() {
27
- $cap = is_multisite() ? 'manage_network_options' : 'manage_options';
28
- $action = "actionIndex";
29
- if ( $this->maybe_show_widget() ) {
30
- add_submenu_page( 'wp-defender', esc_html__( "WAF", "defender-security" ),
31
- esc_html__( "WAF", "defender-security" ), $cap, $this->slug, array(
32
- &$this,
33
- $action
34
- ) );
35
- }
36
- }
37
-
38
- public function actionIndex() {
39
- $this->render( 'main' );
40
- }
41
-
42
- public function scripts() {
43
- wp_enqueue_style( 'wpmudev-sui' );
44
- wp_enqueue_style( 'defender' );
45
- wp_enqueue_media();
46
- wp_register_script( 'defender-waf', wp_defender()->getPluginUrl() . 'assets/app/waf.js', array(
47
- 'def-vue',
48
- 'defender',
49
- 'wp-i18n'
50
- ), wp_defender()->version, true );
51
- wp_localize_script( 'defender-waf', 'waf', $this->_scriptsData() );
52
- Utils::instance()->createTranslationJson( 'defender-waf' );
53
- wp_set_script_translations( 'defender-waf', 'wpdef', wp_defender()->getPluginPath() . 'languages' );
54
- wp_enqueue_script( 'defender-waf' );
55
- wp_enqueue_script( 'wpmudev-sui' );
56
- }
57
-
58
- /**
59
- * Checks whether we're on WPMU DEV Hosting
60
- *
61
- * @return bool
62
- */
63
- public function is_wpmu_hosting() {
64
- return isset( $_SERVER['WPMUDEV_HOSTED'] ) && ! empty( $_SERVER['WPMUDEV_HOSTED'] );
65
- }
66
-
67
- public function recheck() {
68
- if ( ! Utils::instance()->checkPermission() ) {
69
- return;
70
- }
71
-
72
- if ( ! wp_verify_nonce( HTTP_Helper::retrieveGet( '_wpnonce' ), 'recheckWaf' ) ) {
73
- return;
74
- }
75
- delete_site_transient( 'def_waf_status' );
76
- $data = $this->_scriptsData();
77
- wp_send_json_success( [
78
- 'waf' => $data['waf'],
79
- ] );
80
- }
81
-
82
- /**
83
- * @param $site_id
84
- *
85
- * @return bool|mixed
86
- */
87
- public function get_waf_status( $site_id ) {
88
- $cached = get_site_transient( 'def_waf_status' );
89
- if ( in_array( $cached, [ 'enabled', 'disabled' ] ) ) {
90
- return $cached === 'enabled';
91
- }
92
-
93
- $url = "https://premium.wpmudev.org/api/hub/v1/sites/$site_id/modules/hosting";
94
- $ret = Utils::instance()->devCall( $url );
95
- if ( is_wp_error( $ret ) ) {
96
- return $ret;
97
- }
98
- $status = $ret['waf']['is_active'];
99
- set_site_transient( 'def_waf_status', $status === true ? 'enabled' : 'disabled', 300 );
100
-
101
- return $status;
102
- }
103
-
104
- public function maybe_show_modal() {
105
- $show = get_site_option( 'waf_show_new_feature' );
106
- //hide it if the site is Hosted && Enable Whitelabel
107
- if ( $this->is_wpmu_hosting() && WPMUDEV::instance()->is_whitelabel_enabled() ) {
108
- return false;
109
- }
110
- if (
111
- //not hosted on us
112
- ! $this->is_wpmu_hosting()
113
- //is pro
114
- && wp_defender()->isFree == false
115
- //and enable whitelabel
116
- && WPMUDEV::instance()->is_whitelabel_enabled()
117
- ) {
118
- //hide it
119
- return false;
120
- }
121
-
122
- return $show;
123
- }
124
-
125
- /**
126
- * @return bool
127
- */
128
- public function maybe_show_widget() {
129
- if (
130
- //not hosted on us
131
- ! $this->is_wpmu_hosting()
132
- //is pro
133
- && wp_defender()->isFree == false
134
- //and enable whitelabel
135
- && WPMUDEV::instance()->is_whitelabel_enabled()
136
- ) {
137
- //hide it
138
- return false;
139
- }
140
-
141
- return true;
142
- }
143
-
144
- public function _scriptsData() {
145
- $site_id = null;
146
- $waf_status = false;
147
- if ( class_exists( '\WPMUDEV_Dashboard' ) ) {
148
- $site_id = \WPMUDEV_Dashboard::$api->get_site_id();
149
- if ( $this->is_wpmu_hosting() ) {
150
- $waf_status = $this->get_waf_status( $site_id );
151
- if ( is_wp_error( $waf_status ) ) {
152
- //false safe
153
- $waf_status = false;
154
- }
155
- }
156
- }
157
-
158
- return [
159
- 'site_id' => $site_id,
160
- 'waf' => [
161
- 'hosted' => $this->is_wpmu_hosting(),
162
- 'status' => $waf_status,
163
- 'maybe_show' => $this->maybe_show_widget(),
164
- 'whitelabel_enable' => WPMUDEV::instance()->is_whitelabel_enabled(),
165
- ],
166
- 'nonces' => [
167
- 'recheck' => wp_create_nonce( 'recheckWaf' )
168
- ],
169
- 'endpoints' => [
170
- 'recheck' => 'wp-defender/v1/waf/recheck'
171
- ]
172
- ];
173
- }
174
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/advanced-tools.php DELETED
@@ -1,19 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module;
7
-
8
- use Hammer\Base\Module;
9
- use WP_Defender\Module\Advanced_Tools\Controller\Main;
10
- use WP_Defender\Module\Advanced_Tools\Controller\Mask_Login;
11
- use WP_Defender\Module\Advanced_Tools\Controller\Rest;
12
- use WP_Defender\Module\Advanced_Tools\Controller\Rest_Auth;
13
-
14
- class Advanced_Tools extends Module {
15
- public function __construct() {
16
- $main = new Main();
17
- $rest = new Rest();
18
- }
19
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/advanced-tools/component/auth-api.php DELETED
@@ -1,368 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Advanced_Tools\Component;
7
-
8
- use Hammer\Base\Component;
9
- use WP_Defender\Behavior\Utils;
10
- use WP_Defender\Module\Advanced_Tools\Model\Auth_Settings;
11
-
12
- class Auth_API extends Component {
13
- /**
14
- * @param int $length
15
- *
16
- * @return string
17
- */
18
- public static function generateSecret( $length = 16 ) {
19
- $strings = "ABCDEFGHIJKLMNOPQRSTUVWXYS234567";
20
- $secret = array();
21
- for ( $i = 0; $i < $length; $i ++ ) {
22
- $secret[] = $strings[ rand( 0, strlen( $strings ) - 1 ) ];
23
- }
24
-
25
- return implode( "", $secret );
26
- }
27
-
28
- /**
29
- * @param $name
30
- * @param $secret
31
- * @param int $width
32
- * @param int $height
33
- * @param null $title
34
- *
35
- * @return string
36
- */
37
- public static function generateQRCode( $name, $holder, $secret, $width = 200, $height = 200, $title = null ) {
38
- $chl = ( 'otpauth://totp/' . rawurlencode( $name ) . ':' . rawurlencode( $holder ) . '?secret=' . $secret . '' );
39
- if ( ! is_null( $title ) ) {
40
- $chl .= ( '&issuer=' . rawurlencode( $title ) );
41
- }
42
- //manually include the autoload
43
- require_once wp_defender()->getPluginPath() . 'vendor/phpqrcode/phpqrcode.php';
44
-
45
- $code = \QRcode::svg( $chl, false, QR_ECLEVEL_L, 4 );
46
-
47
- }
48
-
49
- /**
50
- * Calculate the TOTP code
51
- *
52
- * @param $secret
53
- * @param $counter
54
- *
55
- * @return \string
56
- *
57
- * reference: https://tools.ietf.org/html/rfc4226#section-5.3
58
- * https://garbagecollected.org/2014/09/14/how-google-authenticator-works/
59
- */
60
- public static function generateCode( $secret, $counter = null ) {
61
- //secret should be base 32, as GA want it
62
- include_once wp_defender()->getPluginPath() . 'vendor/binary-to-text-php/Base2n.php';
63
- $base32 = new \Base2n( 5, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', false, true, true );
64
- $secret = $base32->decode( $secret );
65
- //timestep fixed at 30
66
- if ( is_null( $counter ) ) {
67
- $counter = time();
68
- }
69
- $input = floor( $counter / 30 );
70
- //according to https://tools.ietf.org/html/rfc4226#section-5.3, should be a 8 bytes value
71
- $time = chr( 0 ) . chr( 0 ) . chr( 0 ) . chr( 0 ) . pack( 'N*', $input );
72
- $hmac = hash_hmac( 'sha1', $time, $secret, true );
73
- //now we have 20 bytes sha1, need to short it down
74
- //getting last byte of the hmac
75
- $offset = ord( substr( $hmac, - 1 ) ) & 0x0F;
76
- $four_bytes = substr( $hmac, $offset, 4 );
77
- //now convert it into INT
78
- $value = unpack( 'N', $four_bytes );
79
- $value = $value[1];
80
- //make sure it always act like 32 bits
81
- $value = $value & 0x7FFFFFFF;;
82
- //we so close
83
- $code = $value % pow( 10, 6 );
84
- //in some case we have the 0 before, so it become lesser than 6, make sure it always right
85
- $code = str_pad( $code, 6, '0', STR_PAD_LEFT );
86
-
87
- return $code;
88
- }
89
-
90
- /**
91
- * @param $secret
92
- * @param $userCode
93
- * @param int $window
94
- *
95
- * @return bool
96
- */
97
- public static function compare( $secret, $userCode, $window = 1 ) {
98
- if ( strlen( $userCode ) != 6 ) {
99
- return false;
100
- }
101
-
102
- /**
103
- * window is 30 seconds, before and after
104
- */
105
- for ( $i = - $window; $i <= $window; $i ++ ) {
106
- $counter = $i == 0 ? null : $i * 30 + time();
107
- $code = self::generateCode( $secret, $counter );
108
- if ( self::hasEqual( $code, $userCode ) ) {
109
- return true;
110
- }
111
- }
112
-
113
-
114
- return false;
115
- }
116
-
117
- /**
118
- * Timing attack safe string comparison, replacement of has_equals which only on 5.6+
119
- *
120
- * @param $known_string
121
- * @param $user_string
122
- *
123
- * @return bool
124
- * reference: http://php.net/manual/en/function.hash-equals.php#119576
125
- */
126
- private static function hasEqual( $known_string, $user_string ) {
127
- if ( function_exists( 'hash_equals' ) ) {
128
- return hash_equals( $known_string, $user_string );
129
- }
130
-
131
- $ret = 0;
132
-
133
- if ( strlen( $known_string ) !== strlen( $user_string ) ) {
134
- $user_string = $known_string;
135
- $ret = 1;
136
- }
137
-
138
- $res = $known_string ^ $user_string;
139
-
140
- for ( $i = strlen( $res ) - 1; $i >= 0; -- $i ) {
141
- $ret |= ord( $res[ $i ] );
142
- }
143
-
144
- return ! $ret;
145
- }
146
-
147
- /**
148
- * @return bool
149
- */
150
- public static function isEnableForCurrentRole( $user = null ) {
151
- if ( $user == null ) {
152
- $user = wp_get_current_user();
153
- }
154
- if ( ! $user instanceof \WP_User ) {
155
- return false;
156
- }
157
- $settings = Auth_Settings::instance();
158
- if ( 0 === count( $user->roles ) ) {
159
- return true;
160
- }
161
-
162
- if ( Utils::instance()->isActivatedSingle() ) {
163
- $allowedForThisRole = array_intersect( $settings->user_roles, $user->roles );
164
- if ( ! is_array( $allowedForThisRole ) ) {
165
- $allowedForThisRole = [];
166
- }
167
-
168
- return count( $allowedForThisRole ) > 0;
169
- } else {
170
- $blogs = get_blogs_of_user( $user->ID );
171
- $userRoles = array();
172
- foreach ( $blogs as $blog ) {
173
- //get user roles for this blog
174
- $u = new \WP_User( $user->ID, '', $blog->userblog_id );
175
- $userRoles = array_merge( $u->roles, $userRoles );
176
- }
177
- $allowedForThisRole = array_intersect( $settings->user_roles, $userRoles );
178
-
179
- return count( $allowedForThisRole ) > 0;
180
- }
181
- }
182
-
183
- /**
184
- * @param null $user
185
- *
186
- * @return bool
187
- */
188
- public static function isForcedRole( $user = null ) {
189
- if ( $user == null ) {
190
- $user = wp_get_current_user();
191
- }
192
- if ( ! $user instanceof \WP_User ) {
193
- return false;
194
- }
195
- $settings = Auth_Settings::instance();
196
- if ( 0 === count( $user->roles ) ) {
197
- //this mean user just added but have no roles, we dnt force them
198
- return false;
199
- }
200
-
201
- if ( Utils::instance()->isActivatedSingle() ) {
202
- $isForced = array_intersect( $settings->force_auth_roles, $user->roles );
203
-
204
- return count( $isForced ) > 0;
205
- } else {
206
- $blogs = get_blogs_of_user( $user->ID );
207
- $userRoles = array();
208
- foreach ( $blogs as $blog ) {
209
- //get user roles for this blog
210
- $u = new \WP_User( $user->ID, '', $blog->userblog_id );
211
- $userRoles = array_merge( $u->roles, $userRoles );
212
- }
213
- $isForced = array_intersect( $settings->force_auth_roles, $userRoles );
214
-
215
- return count( $isForced ) > 0;
216
- }
217
- }
218
-
219
- /**
220
- * @return bool|mixed|string
221
- */
222
- public static function createSecretForCurrentUser() {
223
- if ( ! is_user_logged_in() ) {
224
- return false;
225
- }
226
-
227
- $secret = get_user_meta( get_current_user_id(), 'defenderAuthSecret', true );
228
- if ( ! $secret ) {
229
- $secret = self::generateSecret();
230
- update_user_meta( get_current_user_id(), 'defenderAuthSecret', $secret );
231
- }
232
-
233
- return $secret;
234
- }
235
-
236
- /**
237
- * @param null $userID
238
- *
239
- * @return bool|mixed
240
- */
241
- public static function getUserSecret( $userID = null ) {
242
- if ( $userID == null ) {
243
- $userID = get_current_user_id();
244
- }
245
- $secret = get_user_meta( $userID, 'defenderAuthSecret', true );
246
- if ( ! $secret ) {
247
- return false;
248
- }
249
-
250
- return $secret;
251
- }
252
-
253
- /**
254
- * @param $userID
255
- *
256
- * @return mixed
257
- */
258
- public static function isUserEnableOTP( $userID ) {
259
- if ( $userID instanceof \WP_User ) {
260
- $user = $userID;
261
- $userID = $user->ID;
262
- } else {
263
- $user = get_user_by( 'id', $userID );
264
- }
265
- if ( ! self::isEnableForCurrentRole( $user ) ) {
266
- return false;
267
- }
268
-
269
- $isOn = get_user_meta( $userID, 'defenderAuthOn', true );
270
-
271
- return $isOn;
272
- }
273
-
274
- /**
275
- * @param $userID
276
- *
277
- * @return bool|mixed|string
278
- */
279
- public static function getBackupEmail( $userID ) {
280
- $email = get_user_meta( $userID, 'defenderAuthEmail', true );
281
- if ( empty( $email ) ) {
282
- $user = get_user_by( 'id', $userID );
283
- if ( ! is_object( $user ) ) {
284
- return false;
285
- }
286
- $email = $user->user_email;
287
- }
288
-
289
- return $email;
290
- }
291
-
292
- /**
293
- * Generate single code, use in case lost phone
294
- *
295
- * @param $userID
296
- *
297
- * @return string
298
- */
299
- public static function createBackupCode( $userID ) {
300
- $code = wp_generate_password( 20, false );
301
- update_user_meta( $userID, 'defenderBackupCode', array(
302
- 'code' => $code,
303
- 'time' => time()
304
- ) );
305
-
306
- return $code;
307
- }
308
-
309
- /**
310
- * @return bool
311
- */
312
- public static function isJetPackSSO() {
313
- if ( is_plugin_active_for_network( 'jetpack/jetpack.php' ) ) {
314
- //loop through all sites
315
- $settings = Auth_Settings::instance();
316
- $isConflict = $settings->isConflict( 'jetpack/jetpack.php' );
317
- if ( $isConflict === 0 ) {
318
- //no data, init
319
- global $wpdb;
320
- $sql = "SELECT blog_id FROM `{$wpdb->base_prefix}blogs`";
321
- $blogs = $wpdb->get_col( $sql );
322
- foreach ( $blogs as $id ) {
323
- $options = get_blog_option( $id, 'jetpack_active_modules', array() );
324
- if ( array_search( 'sso', $options ) ) {
325
- $settings->markAsConflict( 'jetpack/jetpack.php' );
326
-
327
- return true;
328
- }
329
- }
330
- } else {
331
- //get the data from cache
332
- return $isConflict;
333
- }
334
-
335
- } elseif ( is_plugin_active( 'jetpack/jetpack.php' ) ) {
336
- //ugly but faster
337
- $settings = Auth_Settings::instance();
338
- $isConflict = $settings->isConflict( 'jetpack/jetpack.php' );
339
- if ( $isConflict === 0 ) {
340
- $options = get_option( 'jetpack_active_modules', array() );
341
- if ( array_search( 'sso', $options ) ) {
342
- $settings->markAsConflict( 'jetpack/jetpack.php' );
343
-
344
- return true;
345
- }
346
- } else {
347
- return $isConflict;
348
- }
349
-
350
- }
351
-
352
- return false;
353
- }
354
-
355
- /**
356
- * @return bool
357
- */
358
- public static function isTML() {
359
- if ( is_plugin_active( 'theme-my-login/theme-my-login.php' ) || is_plugin_active_for_network( 'theme-my-login/theme-my-login.php' ) ) {
360
- $settings = Auth_Settings::instance();
361
- $settings->markAsConflict( 'theme-my-login/theme-my-login.php' );
362
-
363
- return true;
364
- }
365
-
366
- return false;
367
- }
368
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/advanced-tools/component/auth-listener.php DELETED
@@ -1,460 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Advanced_Tools\Component;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use Hammer\WP\Component;
10
- use WP_Defender\Behavior\Utils;
11
- use WP_Defender\Module\Advanced_Tools\Model\Auth_Settings;
12
-
13
- class Auth_Listener extends Component {
14
- protected $sessionToken;
15
-
16
- public function __construct() {
17
- $this->addAction( 'update_option_jetpack_active_modules', 'listenForJetpackOption', 10, 3 );
18
- $setting = Auth_Settings::instance();
19
- if ( $setting->enabled ) {
20
- //prepare for the login part
21
- $isJetpackSSO = Auth_API::isJetPackSSO();
22
- $isTML = Auth_API::isTML();
23
- if ( ! defined( 'DOING_AJAX' ) && ! $isJetpackSSO && ! $isTML ) {
24
- /**
25
- * hook into wordpress login, can't use authenticate hook as that badly conflict
26
- */
27
- $this->addAction( 'wp_login', 'maybeShowOTPLogin', 9, 2 );
28
- $this->addAction( 'login_form_defenderVerifyOTP', 'defenderVerifyOTP' );
29
- $this->addAction( 'set_logged_in_cookie', 'storeSessionKey' );
30
- /**
31
- * end
32
- */
33
- } else {
34
- if ( $isJetpackSSO ) {
35
- wp_defender()->global['compatibility'][] = __( "We've detected a conflict with Jetpack's Wordpress.com Log In feature. Please disable it and return to this page to continue setup.", "defender-security" );
36
- }
37
- if ( $isTML ) {
38
- wp_defender()->global['compatibility'][] = __( "We've detected a conflict with Theme my login. Please disable it and return to this page to continue setup.", "defender-security" );
39
- }
40
- }
41
- $this->addFilter( 'ms_shortcode_ajax_login', 'm2NoAjax' );
42
- $this->addAction( 'show_user_profile', 'showUsers2FactorActivation' );
43
- $this->addAction( 'profile_update', 'saveBackupEmail' );
44
- //$this->add_action( 'wp_login', 'markAsForceAuth', 10, 2 );
45
- $this->addFilter( 'login_redirect', 'loginRedirect', 99 );
46
- $this->addAction( 'current_screen', 'forceProfilePage', 1 );
47
- $this->addAjaxAction( 'defVerifyOTP', 'verifyConfigOTP' );
48
- $this->addAjaxAction( 'defDisableOTP', 'disableOTP' );
49
- $this->addAjaxAction( 'defRetrieveOTP', 'retrieveOTP', false, true );
50
- if ( Utils::instance()->isActivatedSingle() ) {
51
- $this->addFilter( 'manage_users_columns', 'alterUsersTable' );
52
- $this->addFilter( 'manage_users_custom_column', 'alterUsersTableRow', 10, 3 );
53
- } else {
54
- $this->addFilter( 'wpmu_users_columns', 'alterUsersTable' );
55
- $this->addFilter( 'manage_users_custom_column', 'alterUsersTableRow', 10, 3 );
56
- }
57
- }
58
- }
59
-
60
- /**
61
- * If user have flag then force enable
62
- */
63
- public function forceProfilePage() {
64
- $user = wp_get_current_user();
65
- if ( ! is_object( $user ) ) {
66
- return;
67
- }
68
-
69
- $settings = Auth_Settings::instance();
70
- if ( $settings->force_auth != true ) {
71
- return;
72
- }
73
-
74
- //not enable for this role oass
75
- if ( ! Auth_API::isEnableForCurrentRole( $user ) ) {
76
- return;
77
- }
78
-
79
- //check if this role is forced
80
- if ( ! Auth_API::isForcedRole( $user ) ) {
81
- return;
82
- }
83
-
84
- //user already enable OTP
85
- if ( Auth_API::isUserEnableOTP( $user->ID ) ) {
86
- return;
87
- }
88
-
89
- $screen = get_current_screen();
90
- if ( $screen->id != 'profile' ) {
91
- wp_safe_redirect( admin_url( 'profile.php' ) . '#show2AuthActivator' );
92
- exit;
93
- }
94
- }
95
-
96
- public function loginRedirect( $url ) {
97
- $settings = Auth_Settings::instance();
98
- if ( $settings->force_auth != true ) {
99
- return $url;
100
- }
101
-
102
- return $url;
103
- }
104
-
105
- /**
106
- * @param $userLogin
107
- * @param $user
108
- */
109
- public function markAsForceAuth( $userLogin, $user ) {
110
- $settings = Auth_Settings::instance();
111
- if ( $settings->force_auth != true ) {
112
- return;
113
- }
114
- //not enable for this role oass
115
- if ( ! Auth_API::isEnableForCurrentRole( $user ) ) {
116
- return;
117
- }
118
- //user already enable OTP
119
- if ( Auth_API::isUserEnableOTP( $user->ID ) ) {
120
- return;
121
- }
122
- //if this is normal user, force them
123
- // if ( ! current_user_can( 'subscriber' ) ) {
124
- // return;
125
- // }
126
- $flag = get_user_meta( $user->ID, 'defenderForceAuth', true );
127
- if ( $flag === '' ) {
128
- update_user_meta( $user->ID, 'defenderForceAuth', 1 );
129
- }
130
- }
131
-
132
- /**
133
- * We have some feature conflict with jetpack, so listen to know when Defender can on
134
- *
135
- * @param $old_value
136
- * @param $value
137
- * @param $option
138
- */
139
- public function listenForJetpackOption( $old_value, $value, $option ) {
140
- $settings = Auth_Settings::instance();
141
- if ( array_search( 'sso', $value ) !== false ) {
142
- $settings->markAsConflict( 'jetpack/jetpack.php' );
143
- } else {
144
- $settings->markAsUnConflict( 'jetpack/jetpack.php' );
145
- }
146
- }
147
-
148
- /**
149
- * Stop ajax login on membership 2
150
- * @return bool
151
- */
152
- public function m2NoAjax() {
153
- return false;
154
- }
155
-
156
- /**
157
- * Return 2 factor auth status
158
- *
159
- * @param $val
160
- * @param $column_name
161
- * @param $user_id
162
- *
163
- * @return string
164
- */
165
- public function alterUsersTableRow( $val, $column_name, $user_id ) {
166
- if ( $column_name != 'defAuth' ) {
167
- return $val;
168
- }
169
-
170
- if ( Auth_API::isUserEnableOTP( $user_id ) ) {
171
- return '<span class="def-oval oval-green"></span>';
172
- }
173
-
174
- return '<span class="def-oval"></span>';
175
- }
176
-
177
- /**
178
- * Add the auth column inside users on single site
179
- *
180
- * @param $columns
181
- *
182
- * @return mixed
183
- *
184
- */
185
- public function alterUsersTable( $columns ) {
186
- $columns = array_slice( $columns, 0, count( $columns ) - 1 ) + array(
187
- 'defAuth' => __( "Two Factor", "defender-security" )
188
- ) + array_slice( $columns, count( $columns ) - 1 );
189
-
190
- return $columns;
191
- }
192
-
193
- /**
194
- * Generate an email for backup otp
195
- */
196
- public function retrieveOTP() {
197
- if ( ! wp_verify_nonce( HTTP_Helper::retrieveGet( 'nonce' ), 'defRetrieveOTP' ) ) {
198
- wp_send_json_error( array() );
199
- }
200
-
201
- $token = HTTP_Helper::retrieveGet( 'token' );
202
- $query = new \WP_User_Query( array(
203
- 'meta_key' => 'defOTPLoginToken',
204
- 'meta_value' => $token,
205
- 'blog_id' => 0
206
- ) );
207
- $res = $query->get_results();
208
- if ( empty( $res ) ) {
209
- //no user
210
- wp_send_json_error( array(
211
- 'message' => __( "Your token is invalid", "defender-security" )
212
- ) );
213
- }
214
-
215
- $user = $res[0];
216
- //create a backup code for this user
217
- $code = Auth_API::createBackupCode( $user->ID );
218
- //send email
219
- $backupEmail = Auth_API::getBackupEmail( $user->ID );
220
-
221
- $settings = Auth_Settings::instance();
222
- $subject = ! empty( $settings->email_subject ) ? esc_attr( $settings->email_subject ) : __( 'Your OTP code', "defender-security" );
223
- $sender = ! empty( $settings->email_sender ) ? esc_attr( $settings->email_sender ) : false;
224
- $body = ! empty( $settings->email_body ) ? $settings->email_body : $settings->two_factor_opt_email_default_body();
225
- $params = [
226
- 'display_name' => $user->display_name,
227
- 'passcode' => $code,
228
- ];
229
- foreach ( $params as $key => $val ) {
230
- $body = str_replace( '{{' . $key . '}}', $val, $body );
231
- }
232
- $headers = array( 'Content-Type: text/html; charset=UTF-8' );
233
- if ( $sender ) {
234
- $from_email = get_bloginfo( 'admin_email' );
235
- $headers[] = sprintf( 'From: %s <%s>', $sender, $from_email );
236
- }
237
-
238
- //send
239
- wp_mail( $backupEmail, $subject, $body, $headers );
240
-
241
- wp_send_json_success( array(
242
- 'message' => __( "Your code has been sent to your email.", "defender-security" )
243
- ) );
244
- }
245
-
246
- /**
247
- * disable OTP feature
248
- */
249
- public function disableOTP() {
250
- if ( ! is_user_logged_in() ) {
251
- return;
252
- }
253
-
254
- update_user_meta( get_current_user_id(), 'defenderAuthOn', 0 );
255
- delete_user_meta( get_current_user_id(), 'defenderAuthSecret' );
256
- wp_send_json_success();
257
- }
258
-
259
- /**
260
- * Saving backup email when profile saved
261
- *
262
- * @param $userID
263
- */
264
- public function saveBackupEmail( $userID ) {
265
- $email = HTTP_Helper::retrievePost( 'def_backup_email' );
266
- if ( $email && get_current_user_id() == $userID ) {
267
- update_user_meta( $userID, 'defenderAuthEmail', $email );
268
- }
269
- }
270
-
271
- /**
272
- * An ajax function for verify the OTP user input when configuring the 2 factors
273
- */
274
- public function verifyConfigOTP() {
275
- if ( ! wp_verify_nonce( HTTP_Helper::retrievePost( 'nonce' ), 'defVerifyOTP' ) ) {
276
- return;
277
- }
278
-
279
- if ( ! is_user_logged_in() ) {
280
- return;
281
- }
282
-
283
- $otp = HTTP_Helper::retrievePost( 'otp' );
284
- $otp = trim( $otp );
285
- if ( strlen( $otp ) == 0 ) {
286
- wp_send_json_error( array(
287
- 'message' => __( "Please input a valid OTP code", "defender-security" )
288
- ) );
289
- }
290
-
291
- $secret = Auth_API::getUserSecret();
292
- //at this stage, secret should have value, do not need to check
293
- $res = Auth_API::compare( $secret, $otp );
294
- if ( $res ) {
295
- //save it
296
- update_user_meta( get_current_user_id(), 'defenderAuthOn', 1 );
297
- update_user_meta( get_current_user_id(), 'defenderForceAuth', 0 );
298
- wp_send_json_success();
299
- } else {
300
- //now need to check if the current user have backup otp
301
- wp_send_json_error( array(
302
- 'message' => __( "Your OTP code is incorrect. Please try again.", "defender-security" )
303
- ) );
304
- }
305
- }
306
-
307
- /**
308
- * Show an section inside my profile page for user can activate 2 factor login
309
- *
310
- * @param $profileuser
311
- */
312
- public function showUsers2FactorActivation( $profileuser ) {
313
- if ( ! Auth_API::isEnableForCurrentRole() ) {
314
- return;
315
- }
316
-
317
- $isOn = get_user_meta( $profileuser->ID, 'defenderAuthOn', true );
318
- wp_enqueue_style( 'defAuth', wp_defender()->getPluginUrl() . 'app/module/advanced-tools/css/login-admin.css' );
319
- $secretKey = Auth_API::createSecretForCurrentUser();
320
- if ( $isOn && $isOn == 1 ) {
321
- $email = Auth_API::getBackupEmail( $profileuser->ID );
322
- $this->renderPartial( 'login/enabled', array(
323
- 'email' => $email
324
- ) );
325
- } else {
326
- //show the screen
327
- $this->renderPartial( 'login/disabled', array(
328
- 'secretKey' => $secretKey
329
- ) );
330
- }
331
- }
332
-
333
- /**
334
- * We will check and show the OTP screen if user signon successfully
335
- *
336
- * @param $userLogin
337
- * @param $user
338
- */
339
- public function maybeShowOTPLogin( $userLogin, $user ) {
340
- if ( ! Auth_API::isUserEnableOTP( $user->ID ) ) {
341
- //no enable, then just return
342
- return;
343
- }
344
-
345
- //clean up session and auth cookies for preventing
346
- $token = $this->sessionToken;
347
- if ( $token ) {
348
- $sManager = \WP_Session_Tokens::get_instance( $user->ID );
349
- $sManager->destroy( $token );
350
- }
351
- wp_clear_auth_cookie();
352
-
353
- $this->showOTPScreen( $user );
354
- }
355
-
356
- /**
357
- * verify OTP code which user input in order to login
358
- */
359
- public function defenderVerifyOTP() {
360
- if ( ( $otp = HTTP_Helper::retrievePost( 'otp', null ) ) != null ) {
361
- $params = array();
362
- if ( ! wp_verify_nonce( HTTP_Helper::retrievePost( '_wpnonce' ), 'DefOtpCheck' ) ) {
363
- $params['error'] = new \WP_Error( 'security_fail', __( "Some error happen", "defender-security" ) );
364
- }
365
-
366
- $login_token = HTTP_Helper::retrievePost( 'login_token' );
367
- $query = new \WP_User_Query( array(
368
- 'meta_key' => 'defOTPLoginToken',
369
- 'meta_value' => $login_token,
370
- 'blog_id' => 0
371
- ) );
372
- $res = $query->get_results();
373
- if ( empty( $res ) ) {
374
- //no users, redirect to the login page immediatly
375
- wp_redirect( site_url( 'wp-login.php', 'login_post' ) );
376
- exit;
377
- } else {
378
- $user = $res[0];
379
- $secret = Auth_API::getUserSecret( $user->ID );
380
- $redirect = HTTP_Helper::retrievePost( 'redirect_to', admin_url() );
381
- if ( Auth_API::compare( $secret, $otp ) ) {
382
- //sign in
383
- delete_user_meta( $user->ID, 'defOTPLoginToken' );
384
- wp_set_current_user( $user->ID, $user->user_login );
385
- wp_set_auth_cookie( $user->ID, true );
386
- $redirect = apply_filters( 'login_redirect', $redirect, isset( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '', $user );
387
- wp_safe_redirect( $redirect );
388
- exit;
389
- } else {
390
- $backupCode = get_user_meta( $user->ID, 'defenderBackupCode', true );
391
- if ( $backupCode && $backupCode['code'] == $otp && strtotime( '+3 minutes', $backupCode['time'] ) > time() ) {
392
- delete_user_meta( $user->ID, 'defOTPLoginToken' );
393
- delete_user_meta( $user->ID, 'defenderBackupCode' );
394
- wp_set_current_user( $user->ID, $user->user_login );
395
- wp_set_auth_cookie( $user->ID, true );
396
- $redirect = apply_filters( 'login_redirect', $redirect, isset( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '', $user );
397
- wp_safe_redirect( $redirect );
398
- exit;
399
- } else {
400
- $params['error'] = new \WP_Error( 'opt_fail', __( "Whoops, the passcode you entered was incorrect or expired.", "defender-security" ) );
401
- $this->showOTPScreen( $user, $params );
402
- }
403
- }
404
- }
405
- }
406
- }
407
-
408
- /**
409
- * Show the OTP screen
410
- *
411
- * @param $user
412
- * @param $params
413
- */
414
- private function showOTPScreen( $user, $params = array() ) {
415
- //now show the OTP screen
416
- $this->addAction( 'login_enqueue_scripts', 'includeAuthStyles' );
417
- wp_enqueue_script( 'jquery' );
418
- $params['loginToken'] = $this->createLoginToken( $user );
419
- $params['redirect_to'] = HTTP_Helper::retrievePost( 'redirect_to' );
420
- if ( ! isset( $params['error'] ) ) {
421
- $params['error'] = null;
422
- }
423
- //if this goes here then the current user is ok, need to show the 2 auth
424
- $this->renderPartial( 'login/otp', $params );
425
- exit;
426
- }
427
-
428
- /**
429
- * We will empty all auth cookies or session, so should not rely on wp_get_session_token
430
- *
431
- * @param $cookie
432
- */
433
- public function storeSessionKey( $cookie ) {
434
- $cookie = wp_parse_auth_cookie( $cookie, 'logged_in' );
435
- $this->sessionToken = ! empty( $cookie['token'] ) ? $cookie['token'] : '';
436
- }
437
-
438
- /**
439
- * Create a unique token to retrieve user later
440
- *
441
- * @param $user
442
- *
443
- * @return string
444
- */
445
- private function createLoginToken( $user ) {
446
- $tmp = uniqid();
447
- // create and store a login token so we can query this user again
448
- update_user_meta( $user->ID, 'defOTPLoginToken', $tmp );
449
-
450
- return $tmp;
451
- }
452
-
453
- /**
454
- * add css for OTP page
455
- */
456
- public function includeAuthStyles() {
457
- //enqueue css here
458
- wp_enqueue_style( 'defAuth', wp_defender()->getPluginUrl() . 'app/module/advanced-tools/css/login.css' );
459
- }
460
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/advanced-tools/component/mask-api.php DELETED
@@ -1,320 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Advanced_Tools\Component;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use Hammer\WP\Component;
10
- use WP_Defender\Behavior\Utils;
11
- use WP_Defender\Component\Error_Code;
12
- use WP_Defender\Module\Advanced_Tools\Model\Mask_Settings;
13
- use WP_Defender\Module\Two_Factor\Component\Auth_API;
14
-
15
- class Mask_Api extends Component {
16
- /**
17
- * This will filter all the scheme, domain, params, only path return
18
- *
19
- * @param null $requestUri
20
- *
21
- * @return mixed|string
22
- */
23
-
24
- public static function getRequestPath( $requestUri = null ) {
25
- if ( empty( $requestUri ) ) {
26
- $requestUri = $_SERVER['REQUEST_URI'];
27
- }
28
- //
29
- $requestUri = '/' . ltrim( $requestUri, '/' );
30
- $prefix = parse_url( self::siteUrl(), PHP_URL_PATH );
31
- $requestPath = parse_url( $requestUri, PHP_URL_PATH );
32
- //clean it a bit
33
- if ( Utils::instance()->isActivatedSingle() == false
34
- && defined( 'SUBDOMAIN_INSTALL' )
35
- && constant( 'SUBDOMAIN_INSTALL' ) == false
36
- && get_current_blog_id() != 1
37
- ) {
38
- $prefix = parse_url( self::networkSiteUrl(), PHP_URL_PATH );
39
- //get the prefix
40
- $siteInfo = get_blog_details();
41
- $path = $siteInfo->path;
42
- if ( ! empty( $path ) && strpos( $requestPath, $path ) === 0 ) {
43
- $requestPath = substr( $requestPath, strlen( $path ) );
44
- $requestPath = '/' . ltrim( $requestPath, '/' );
45
- }
46
- } elseif ( self::getHomeUrl() != self::siteUrl() && strpos( $requestPath, (string) $prefix . '/' ) !== 0 ) {
47
- //this case when a wp install inside a sub folder and domain changed into that subfolder
48
- $prefix = parse_url( self::getHomeUrl(), PHP_URL_PATH );
49
- }
50
- if ( strlen( $prefix ) && strpos( $requestPath, (string) $prefix ) === 0 ) {
51
- $requestPath = substr( $requestPath, strlen( $prefix ) );
52
- }
53
- $requestPath = untrailingslashit( $requestPath );
54
- if ( substr( $requestPath, 0, 1 ) != '/' ) {
55
- $requestPath = '/' . $requestPath;
56
- }
57
-
58
- return $requestPath;
59
- }
60
-
61
- /**
62
- * A clone of network_site_url but remove the filter
63
- *
64
- * @param string $path
65
- * @param null $scheme
66
- *
67
- * @return string
68
- */
69
- private static function siteUrl( $path = '', $scheme = null ) {
70
- if ( empty( $blog_id ) || ! is_multisite() ) {
71
- $url = get_option( 'siteurl' );
72
- } else {
73
- switch_to_blog( $blog_id );
74
- $url = get_option( 'siteurl' );
75
- restore_current_blog();
76
- }
77
-
78
- $url = set_url_scheme( $url, $scheme );
79
-
80
- if ( $path && is_string( $path ) ) {
81
- $url .= '/' . ltrim( $path, '/' );
82
- }
83
-
84
- return $url;
85
- }
86
-
87
- /**
88
- * Generate a random unique onetime pass and store in user meta
89
- * Laterly we can use it to by pass the mask admin
90
- * @return bool
91
- */
92
- public static function generateTicket() {
93
- $otp = wp_generate_password( 12, false );
94
- $settings = Mask_Settings::instance();
95
- $settings->otps[ $otp ] = [
96
- 'otp' => $otp,
97
- 'bind_to' => null,
98
- 'expiry' => strtotime( '+3 day' ),
99
- 'used' => 0
100
- ];
101
- $settings->save();
102
-
103
- return $otp;
104
- }
105
-
106
- /**
107
- * @param $ticket
108
- *
109
- * @return bool
110
- */
111
- public static function redeemTicket( $ticket ) {
112
- $settings = Mask_Settings::instance();
113
- $detail = isset( $settings->otps[ $ticket ] ) ? $settings->otps[ $ticket ] : false;
114
- if ( $detail === false ) {
115
- return false;
116
- }
117
-
118
- /**
119
- * ticket expired
120
- */
121
- if ( $detail['expiry'] < time() ) {
122
- unset( $settings->otps[ $ticket ] );
123
- $settings->save();
124
-
125
- return false;
126
- }
127
-
128
- $userIP = Utils::instance()->getUserIp();
129
- if ( $detail['bind_to'] !== null && $detail['bind_to'] != $userIP ) {
130
- //this is binded to an IP but current IP not the same, not allow
131
- return false;
132
- }
133
-
134
- if ( $detail['bind_to'] === null ) {
135
- $detail['bind_to'] = $userIP;
136
- }
137
- $detail['used'] += 1;
138
- $settings->otps[ $ticket ] = $detail;
139
- $settings->save();
140
-
141
- return true;
142
- }
143
-
144
- /**
145
- * @param $url
146
- * @param $user_id
147
- *
148
- * @return string
149
- */
150
- public static function maybeAppendTicketToUrl( $url ) {
151
- return add_query_arg( 'ticket', self::generateTicket(), $url );
152
- }
153
-
154
- /**
155
- * A clone of network_site_url but remove the filter
156
- *
157
- * @param string $path
158
- * @param null $scheme
159
- *
160
- * @return string
161
- */
162
- private static function networkSiteUrl( $path = '', $scheme = null ) {
163
- $current_network = get_network();
164
-
165
- if ( 'relative' == $scheme ) {
166
- $url = $current_network->path;
167
- } else {
168
- $url = set_url_scheme( 'http://' . $current_network->domain . $current_network->path, $scheme );
169
- }
170
-
171
- if ( $path && is_string( $path ) ) {
172
- $url .= ltrim( $path, '/' );
173
- }
174
-
175
- return $url;
176
- }
177
-
178
- /**
179
- * clone from get_home_url function without the filter
180
- *
181
- * @param null $blog_id
182
- * @param string $path
183
- * @param null $scheme
184
- *
185
- * @return mixed|void
186
- */
187
- private static function getHomeUrl( $blog_id = null, $path = '', $scheme = null ) {
188
- global $pagenow;
189
-
190
- $orig_scheme = $scheme;
191
-
192
- if ( empty( $blog_id ) || ! is_multisite() ) {
193
- $url = get_option( 'home' );
194
- } else {
195
- switch_to_blog( $blog_id );
196
- $url = get_option( 'home' );
197
- restore_current_blog();
198
- }
199
-
200
- if ( ! in_array( $scheme, array( 'http', 'https', 'relative' ) ) ) {
201
- if ( is_ssl() && ! is_admin() && 'wp-login.php' !== $pagenow ) {
202
- $scheme = 'https';
203
- } else {
204
- $scheme = parse_url( $url, PHP_URL_SCHEME );
205
- }
206
- }
207
-
208
- $url = set_url_scheme( $url, $scheme );
209
-
210
- if ( $path && is_string( $path ) ) {
211
- $url .= '/' . ltrim( $path, '/' );
212
- }
213
-
214
- return $url;
215
- }
216
-
217
- /**
218
- * @return string
219
- */
220
- public static function getRedirectUrl() {
221
- $settings = Mask_Settings::instance();
222
-
223
- return untrailingslashit( get_home_url( get_current_blog_id() ) ) . '/' . ltrim( $settings->redirect_traffic_url, '/' );
224
- }
225
-
226
- /**
227
- * @return string
228
- */
229
- public static function getNewLoginUrl( $domain = null ) {
230
- $settings = Mask_Settings::instance();
231
- if ( $domain == null ) {
232
- $domain = site_url();
233
- }
234
-
235
- return untrailingslashit( $domain . '/' . ltrim( $settings->mask_url, '/' ) );
236
- }
237
-
238
- /**
239
- * @return bool
240
- */
241
- public static function isEnabled() {
242
- $model = Mask_Settings::instance();
243
-
244
- return $model->isEnabled();
245
- }
246
-
247
- /**
248
- * @param null $slug
249
- *
250
- * @return bool|\WP_Error
251
- */
252
- public static function isValidMaskSlug( $slug = null, $context = 'login' ) {
253
- if ( empty( $slug ) ) {
254
- return true;
255
- }
256
-
257
- if ( $context == 'redirect' && $slug == '/' ) {
258
- //redirect to home
259
- return true;
260
- }
261
- //validate slug, only allow a-z,0-9 and -
262
- if ( preg_match( '|[^a-z0-9-]|i', $slug ) ) {
263
- return new \WP_Error( Error_Code::VALIDATE, __( "The URL is invalid", "defender-security" ) );
264
- }
265
- //if context is login, we will check for exists page
266
- if ( $context == 'login' ) {
267
- if ( in_array( $slug, array( 'admin', 'backend', 'wp-login', 'wp-login.php', 'login' ) ) ) {
268
- return new \WP_Error( Error_Code::VALIDATE, __( "A page already exists at this URL, please pick a unique page for your new login area.", "defender-security" ) );
269
- }
270
-
271
- //check if any URL appear
272
- $post = get_posts( array(
273
- 'name' => $slug,
274
- 'post_type' => array( 'post', 'page' ),
275
- 'post_status' => 'publish',
276
- 'numberposts' => 1
277
- ) );
278
- if ( $post ) {
279
- return new \WP_Error( Error_Code::VALIDATE, __( "A page already exists at this URL, please pick a unique page for your new login area.", "defender-security" ) );
280
- }
281
- }
282
-
283
- return true;
284
- }
285
-
286
- /**
287
- * @return null|string
288
- */
289
- public static function createOTPKey() {
290
- if ( ! is_user_logged_in() ) {
291
- return null;
292
- }
293
-
294
- $secret = Auth_API::getUserSecret();
295
- $otp = uniqid();
296
- $key = md5( $otp . $secret );
297
- set_site_transient( $key, $otp, 300 );
298
-
299
- return $otp;
300
- }
301
-
302
- /**
303
- * @param $otp
304
- *
305
- * @return bool
306
- */
307
- public static function verifyOTP( $otp ) {
308
- $key = HTTP_Helper::retrieveGet( 'otp' );
309
- $secret = Auth_API::getUserSecret();
310
- $key = md5( $key . $secret );
311
- $check = get_site_transient( $key );
312
- if ( $check == $otp ) {
313
- delete_site_transient( $key );
314
-
315
- return true;
316
- }
317
-
318
- return false;
319
- }
320
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/advanced-tools/component/mask-login-listener.php DELETED
@@ -1,291 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Advanced_Tools\Component;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use Hammer\WP\Component;
10
- use WP_Defender\Module\Advanced_Tools\Model\Mask_Settings;
11
- use WP_Defender\Module\Two_Factor\Component\Auth_API;
12
-
13
- class Mask_Login_Listener extends Component {
14
- public function __construct() {
15
- $settings = Mask_Settings::instance();
16
- $emergencySwitch = apply_filters( 'wpd_masklogin_disabled', 0 );
17
-
18
- if ( true === $settings->isEnabled() && 0 === $emergencySwitch ) {
19
- $isJetpackSSO = Auth_API::isJetPackSSO();
20
- $isTML = Auth_API::isTML();
21
- if ( ! $isJetpackSSO && ! $isTML ) {
22
- $this->addAction( 'init', 'handleLoginRequest', 9999 );
23
- $this->addFilter( 'wp_redirect', 'filterWPRedirect', 10, 2 );
24
- $this->addFilter( 'site_url', 'filterSiteUrl', 9999, 4 );
25
- $this->addFilter( 'network_site_url', 'filterNetworkSiteUrl', 9999, 3 );
26
- $this->addFilter( 'wp_mail', 'filterEmailBody', 999 );
27
- //$this->addFilter( 'network_admin_url', 'filterAdminUrl', 9999, 2 );
28
- //$this->add_filter( 'adminUrl', 'filterAdminUrl', 9999, 2 );
29
- remove_action( 'template_redirect', 'wp_redirect_admin_locations' );
30
- //if prosite is activate and useremail is not defined, we need to update the
31
- //email to match the new login URL
32
- $this->addFilter( 'update_welcome_email', 'updateWelcomeEmailPrositeCase', 10, 6 );
33
- $this->addFilter( 'report_email_logs_link', 'updateReportLogsLink', 10, 2 );
34
- } else {
35
- if ( $isJetpackSSO ) {
36
- wp_defender()->global['compatibility'][] = __( "We've detected a conflict with Jetpack's Wordpress.com Log In feature. Please disable it and return to this page to continue setup.", "defender-security" );
37
- }
38
- if ( $isTML ) {
39
- wp_defender()->global['compatibility'][] = __( "We've detected a conflict with Theme my login. Please disable it and return to this page to continue setup.", "defender-security" );
40
- }
41
- }
42
- }
43
- }
44
-
45
- public function filterEmailBody( $args ) {
46
- $patterns = array(
47
- //approve comment
48
- '/(' . preg_quote( site_url(), '/' ) . '\/wp-admin\/comment\.php\?.+)/',
49
- //all comments
50
- '/(' . preg_quote( site_url(), '/' ) . '\/wp-admin\/edit-comments\.php\?.+$)/',
51
- );
52
-
53
- $message = $args['message'];
54
- foreach ( $patterns as $pattern ) {
55
- if ( preg_match_all( $pattern, $message, $matches ) ) {
56
- foreach ( $matches[0] as $url ) {
57
- parse_str( parse_url( $url, PHP_URL_QUERY ), $parts );
58
- if ( ! isset( $parts['ticket'] ) ) {
59
- $new_url = add_query_arg( 'ticket', Mask_Api::generateTicket(), $url );
60
- $message = str_replace( $url, $new_url, $message );
61
- }
62
- }
63
- }
64
- }
65
- $args['message'] = $message;
66
-
67
- return $args;
68
- }
69
-
70
- /**
71
- * @param $logs_url
72
- * @param $email
73
- *
74
- * @return string
75
- */
76
- public function updateReportLogsLink( $logs_url, $email ) {
77
- $user = get_user_by( 'email', $email );
78
- if ( is_object( $user ) ) {
79
- $logs_url = Mask_Api::maybeAppendTicketToUrl( $logs_url );
80
- } else {
81
- $logs_url = add_query_arg( 'redirect_to', $logs_url, Mask_Api::getNewLoginUrl() );
82
- }
83
-
84
- return $logs_url;
85
- }
86
-
87
- public function handleLoginRequest() {
88
- $ticket = HTTP_Helper::retrieveGet( 'ticket', false );
89
- if ( false !== $ticket && Mask_Api::redeemTicket( $ticket ) ) {
90
- //we have an express ticket
91
- return true;
92
- }
93
- //need to check if the current request is for signup, login, if those is not the slug, then we redirect
94
- //to the 404 redirect, or 403 wp die
95
- $requestPath = Mask_Api::getRequestPath();
96
- $settings = Mask_Settings::instance();
97
- if ( '/' . ltrim( $settings->mask_url, '/' ) === $requestPath ) {
98
- //we need to redirect this one to wp-login and open it
99
- $this->_showLoginPage();
100
- }
101
- if ( is_user_logged_in() ) {
102
- //do nothing
103
- return;
104
- }
105
-
106
- if ( defined( 'DOING_AJAX' ) ) {
107
- //we listen on normal requests, not ajax
108
- return;
109
- }
110
- $requestPath = ltrim( $requestPath, '/' );
111
- if ( ! $requestPath ) {
112
- return;
113
- }
114
- // decoded url path, e.g. for case 'wp-%61dmin'
115
- $requestPath = rawurldecode( strtolower( $requestPath ) );
116
- /**
117
- * Cases:
118
- * /wp-admin/admin.php
119
- * /login/
120
- * /wp-login.php
121
- * /wp-signup.php and etc.
122
- */
123
- $loginSlugs = apply_filters(
124
- 'wd_login_slugs',
125
- array(
126
- 'wp-admin',
127
- 'wp-login',
128
- 'wp-login.php',
129
- 'login',
130
- 'dashboard',
131
- 'admin',
132
- 'wp-signup.php',
133
- )
134
- );
135
- // check the request path contains default login text
136
- if ( in_array( $requestPath, $loginSlugs, true ) ) {
137
- return $this->_maybeLock();
138
- }
139
- // or the request path starts from 'wp-admin/' or 'login/'
140
- if (
141
- 0 === strpos( $requestPath, 'wp-admin/' )
142
- || 0 === strpos( $requestPath, 'login/' )
143
- ) {
144
- return $this->_maybeLock();
145
- }
146
- // for case '/something/wp-login.php' or '/something/wp-login.php'
147
- if (
148
- preg_match( '/wp-login\.php/i', $requestPath )
149
- || preg_match( '/wp-signup\.php/i', $requestPath )
150
- ) {
151
- return $this->_maybeLock();
152
- }
153
- }
154
-
155
- /**
156
- * @param $welcome_email
157
- * @param $blog_id
158
- * @param $user_id
159
- * @param $password
160
- * @param $title
161
- * @param $meta
162
- *
163
- * @return mixed
164
- */
165
- public function updateWelcomeEmailPrositeCase( $welcome_email, $blog_id, $user_id, $password, $title, $meta ) {
166
- $url = get_blogaddress_by_id( $blog_id );
167
- $welcome_email = str_replace( $url . 'wp-login.php', Mask_Api::getNewLoginUrl( rtrim( $url, '/' ) ), $welcome_email );
168
-
169
- return $welcome_email;
170
- }
171
-
172
- /**
173
- * @param $url
174
- * @param $path
175
- * @param $scheme
176
- *
177
- * @return string
178
- */
179
- public function filterNetworkSiteUrl( $url, $path, $scheme ) {
180
- return $this->alterLoginUrl( $url, $scheme );
181
- }
182
-
183
- /**
184
- * @param $url
185
- * @param $path
186
- * @param $scheme
187
- * @param $blog_id
188
- *
189
- * @return string
190
- */
191
- public function filterSiteUrl( $url, $path, $scheme, $blog_id ) {
192
- return $this->alterLoginUrl( $url, $scheme );
193
- }
194
-
195
- /**
196
- * @param $location
197
- * @param $status
198
- *
199
- * @return string
200
- */
201
- public function filterWPRedirect( $location, $status ) {
202
- return $this->alterLoginUrl( $location );
203
- }
204
-
205
- /**
206
- * @param $currentUrl
207
- * @param null $scheme
208
- *
209
- * @return string
210
- */
211
- private function alterLoginUrl( $currentUrl, $scheme = null ) {
212
- if ( stristr( $currentUrl, 'wp-login.php' ) !== false ) {
213
- //this is URL go to old wp-login.php
214
- $parts = parse_url( $currentUrl );
215
- if ( isset( $parts['query'] ) ) {
216
- parse_str( $parts['query'], $strings );
217
-
218
- return add_query_arg( $strings, Mask_Api::getNewLoginUrl() );
219
- } else {
220
- return Mask_Api::getNewLoginUrl();
221
- }
222
- } else {
223
- //this case when admin map a domain into subsite, we need to update the new domain/masked-login into the list
224
- if ( ! function_exists( 'get_current_screen' ) ) {
225
- require_once( ABSPATH . 'wp-admin/includes/screen.php' );
226
- }
227
- $screen = get_current_screen();
228
- if ( ! is_object( $screen ) ) {
229
- return $currentUrl;
230
- }
231
- if ( 'sites-network' === $screen->id ) {
232
- //case URLs inside sites list, need to check those with custom domain cause when redirect, it will require re-loggin
233
- $requestPath = Mask_Api::getRequestPath( $currentUrl );
234
- if ( '/wp-admin' === $requestPath ) {
235
- $currentDomain = $_SERVER['HTTP_HOST'];
236
- $subDomain = parse_url( $currentUrl, PHP_URL_HOST );
237
- if ( ! empty( $subDomain ) && false === stristr( $subDomain, $currentDomain ) ) {
238
- return Mask_Api::getNewLoginUrl( $subDomain );
239
- }
240
- }
241
- } elseif ( 'my-sites' === $screen->id ) {
242
- //case inside my sites page, sometime the login session does not share between sites and we get block
243
- //we will add an OTP key for redirect to wp-admin without get block
244
- $otp = Mask_Api::createOTPKey();
245
-
246
- return add_query_arg(
247
- array(
248
- 'otp' => $otp,
249
- ),
250
- $currentUrl
251
- );
252
- }
253
- }
254
-
255
- return $currentUrl;
256
- }
257
-
258
- /**
259
- * Filter admin URL when sync with HUB
260
- *
261
- * @param $currentUrl
262
- * @param null $scheme
263
- *
264
- * @return mixed
265
- */
266
- public function filterAdminUrl( $currentUrl, $scheme = null ) {
267
- //we just need to add a otp if not any
268
- parse_str( parse_url( $currentUrl, PHP_URL_QUERY ), $parts );
269
- if ( ! isset( $parts['ticket'] ) ) {
270
-
271
- }
272
-
273
- return $currentUrl;
274
- }
275
-
276
- private function _showLoginPage() {
277
- global $error, $interim_login, $action, $user_login, $user, $redirect_to;
278
- require_once ABSPATH . 'wp-login.php';
279
- die;
280
- }
281
-
282
- private function _maybeLock() {
283
- $settings = Mask_Settings::instance();
284
- if ( true === $settings->isRedirect() ) {
285
- wp_safe_redirect( Mask_Api::getRedirectUrl() );
286
- die;
287
- } else {
288
- wp_die( __( 'This feature is disabled', "defender-security" ) );
289
- }
290
- }
291
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/advanced-tools/component/security-header.php DELETED
@@ -1,129 +0,0 @@
1
- <?php
2
-
3
- namespace WP_Defender\Module\Advanced_Tools\Component;
4
-
5
- use Hammer\WP\Component;
6
- use WP_Defender\Behavior\Utils;
7
- use WP_Defender\Module\Advanced_Tools\Model\Security_Headers_Settings;
8
-
9
- abstract class Security_Header extends Component {
10
-
11
- /**
12
- * @var string
13
- */
14
- static $rule_slug;
15
-
16
- /**
17
- * Use for cache
18
- *
19
- * @var Security_Headers_Settings
20
- */
21
- public $model;
22
-
23
- /**
24
- * @return array
25
- */
26
- public function getMiscData() {
27
- return array();
28
- }
29
-
30
- /**
31
- * @return mixed
32
- */
33
- abstract function check();
34
-
35
- /**
36
- * @return string
37
- */
38
- abstract function getTitle();
39
-
40
- /**
41
- * @return mixed
42
- */
43
- abstract function addHooks();
44
-
45
- /**
46
- * Safe way to get cached model
47
- *
48
- * @return Security_Headers_Settings
49
- */
50
- protected function getModel() {
51
- if ( is_object( $this->model ) ) {
52
- return $this->model;
53
- }
54
-
55
- return $this->model = Security_Headers_Settings::instance();
56
- }
57
-
58
- /**
59
- * Check if the header is out or not
60
- *
61
- * @param $header
62
- * @param $somewhere
63
- *
64
- * @return bool
65
- */
66
- protected function maybeSubmitHeader( $header, $somewhere ) {
67
- if ( false === $somewhere ) {
68
- return true;
69
- }
70
- $list = headers_list();
71
- $match = false;
72
- foreach ( $list as $item ) {
73
- if ( stristr( $item, $header ) ) {
74
- $match = true;
75
- }
76
- }
77
-
78
- return $match;
79
- }
80
-
81
-
82
- /**
83
- * @param $url
84
- * @param $origin
85
- * @param $ttl
86
- *
87
- * @return array|mixed
88
- */
89
- protected function headRequest( $url, $origin, $ttl = null ) {
90
- $model = $this->getModel();
91
- $cached = $model->getDataValues( 'head_requests' );
92
- if ( ! is_array( $cached ) ) {
93
- $cached = array();
94
- }
95
- if ( isset( $cached[ $url ] ) ) {
96
- $cache = $cached[ $url ];
97
- if ( $cache['ttl'] > time() ) {
98
-
99
- return $cache['data'];
100
- }
101
- }
102
-
103
- //no cache or cache expired
104
- $request = wp_remote_head(
105
- $url,
106
- array(
107
- 'user-agent' => 'WP Defender self ping - ' . $origin,
108
- )
109
- );
110
- if ( ! is_wp_error( $request ) ) {
111
- $headers = wp_remote_retrieve_headers( $request );
112
- $headers = $headers->getAll();
113
- if ( null === $ttl ) {
114
- $ttl = strtotime( '+1 day' );
115
- }
116
- $headers['response_code'] = wp_remote_retrieve_response_code( $request );
117
- $cached[ $url ] = array(
118
- 'ttl' => apply_filters( 'wd_head_request_ttl', $ttl ),
119
- 'data' => $headers,
120
- );
121
- $model->setDataValues( 'head_requests', $cached );
122
- Utils::instance()->log( sprintf( 'Fetched header for %s into cache', $url ), 'security-headers' );
123
-
124
- return $headers;
125
- }
126
-
127
- return $request;
128
- }
129
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/advanced-tools/component/security-headers-listener.php DELETED
@@ -1,45 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Advanced_Tools\Component;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use Hammer\WP\Component;
10
- use WP_Defender\Module\Advanced_Tools\Model\Security_Headers_Settings;
11
-
12
- class Security_Headers_Listener extends Component {
13
- public function __construct() {
14
- //init dependency
15
- $this->initHeaders();
16
- }
17
-
18
- /**
19
- * Init headers
20
- */
21
- public function initHeaders() {
22
- $settings = Security_Headers_Settings::instance();
23
- if ( ! defined( 'DOING_AJAX' ) ) {
24
-
25
- //refresh if on admin, on page with headers
26
- if ( ( is_admin() || is_network_admin() )
27
- &&
28
- (
29
- ( 'wdf-advanced-tools' === HTTP_Helper::retrieveGet( 'page' ) )
30
- || ( 'wp-defender' === HTTP_Helper::retrieveGet( 'page' ) )
31
- )
32
- ) {
33
- //this mean we dont have any data or data is overdue need to refresh list of headers
34
- $settings->refreshHeaders();
35
- } elseif ( defined( 'DOING_CRON' ) ) {
36
- //if this is in cronjob, we refresh it too
37
- $settings->refreshHeaders();
38
- }
39
- }
40
-
41
- foreach ( $settings->getHeaders() as $rule ) {
42
- $rule->addHooks();
43
- }
44
- }
45
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/advanced-tools/component/security-headers/sh-content-type-options.php DELETED
@@ -1,77 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Advanced_Tools\Component\Security_Headers;
7
-
8
- use WP_Defender\Behavior\Utils;
9
- use WP_Defender\Module\Advanced_Tools\Component\Security_Header;
10
-
11
- class Sh_Content_Type_Options extends Security_Header {
12
- static $rule_slug = 'sh_content_type_options';
13
-
14
- public function check() {
15
- $model = $this->getModel();
16
-
17
- if ( ! $model->sh_content_type_options ) {
18
- return false;
19
- }
20
- if ( isset( $model->sh_content_type_options_mode ) && 'nosniff' === $model->sh_content_type_options_mode ) {
21
- return true;
22
- }
23
-
24
- $headers = $this->headRequest( network_site_url(), self::$rule_slug );
25
- if ( is_wp_error( $headers ) ) {
26
- Utils::instance()->log( sprintf( 'Self ping error: %s', $headers->get_error_message() ) );
27
-
28
- return false;
29
- }
30
- if ( isset( $headers['x-content-type-options'] ) && is_null( $model->sh_content_type_options_mode ) ) {
31
- $model->sh_content_type_options_mode = 'nosniff';
32
- $model->save();
33
-
34
- return true;
35
- }
36
-
37
- return false;
38
- }
39
-
40
- /**
41
- * @return array
42
- */
43
- public function getMiscData() {
44
- $model = $this->getModel();
45
-
46
- return array(
47
- 'intro_text' => esc_html__( 'The X-Content-Type-Options header is used to protect against MIME sniffing attacks. The most common example of this is when a website allows users to upload content to a website, however the user disguises a particular file type as something else.', "defender-security" ),
48
- 'mode' => isset( $model->sh_content_type_options_mode ) ? $model->sh_content_type_options_mode : 'nosniff',
49
- );
50
- }
51
-
52
- public function addHooks() {
53
- $this->addAction( 'send_headers', 'appendHeader' );
54
- }
55
-
56
- public function appendHeader() {
57
- if ( headers_sent() ) {
58
- return;
59
- }
60
- $model = $this->getModel();
61
- if ( ! $this->maybeSubmitHeader( 'X-Content-Type-Options', false ) ) {
62
- //this mean Defender can't override the already output, marked to show notification
63
-
64
- return;
65
- }
66
- if ( true === $model->sh_content_type_options && 'nosniff' === $model->sh_content_type_options_mode ) {
67
- header( 'X-Content-Type-Options: nosniff' );
68
- }
69
- }
70
-
71
- /**
72
- * @return string
73
- */
74
- public function getTitle() {
75
- return __( 'X-Content-Type-Options', "defender-security" );
76
- }
77
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/advanced-tools/component/security-headers/sh-feature-policy.php DELETED
@@ -1,161 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Advanced_Tools\Component\Security_Headers;
7
-
8
- use WP_Defender\Behavior\Utils;
9
- use WP_Defender\Module\Advanced_Tools\Component\Security_Header;
10
-
11
- class Sh_Feature_Policy extends Security_Header {
12
- static $rule_slug = 'sh_feature_policy';
13
-
14
- public function check() {
15
- $model = $this->getModel();
16
-
17
- if ( ! $model->sh_feature_policy ) {
18
- return false;
19
- }
20
- if ( isset( $model->sh_feature_policy_mode ) && ! empty( $model->sh_feature_policy_mode ) ) {
21
- return true;
22
- }
23
- $headers = $this->headRequest( network_site_url(), self::$rule_slug );
24
- if ( is_wp_error( $headers ) ) {
25
- Utils::instance()->log( sprintf( 'Self ping error: %s', $headers->get_error_message() ) );
26
-
27
- return false;
28
- }
29
- if ( isset( $headers['feature-policy'] ) ) {
30
- return true;
31
- }
32
-
33
- return false;
34
- }
35
-
36
- /**
37
- * @return array
38
- */
39
- public function getMiscData() {
40
- $model = $this->getModel();
41
-
42
- return array(
43
- 'intro_text' => esc_html__( 'The Feature-Policy response header provides control over what browser features can be used when web pages are embedded in iframes.', "defender-security" ),
44
- 'mode' => isset( $model->sh_feature_policy_mode ) ? $model->sh_feature_policy_mode : 'self',
45
- 'values' => isset( $model->sh_feature_policy_urls ) ? $model->sh_feature_policy_urls : '',
46
- );
47
- }
48
-
49
- public function addHooks() {
50
- $this->addAction( 'send_headers', 'appendHeader' );
51
- $this->addFilter( 'processing_security_headers', 'filteringHeaders' );
52
- }
53
-
54
- public function filteringHeaders( $data ) {
55
- if ( ! isset( $data['sh_feature_policy'] ) ) {
56
- return $data;
57
- }
58
- if ( 'origins' !== $data['sh_feature_policy_mode'] || empty( $data['sh_feature_policy_urls'] ) ) {
59
- return $data;
60
- }
61
- $urls = sanitize_textarea_field( $data['sh_feature_policy_urls'] );
62
- $urls = explode( PHP_EOL, $urls );
63
- $urls = array_map( 'trim', $urls );
64
- foreach ( $urls as $key => $url ) {
65
- if ( false === filter_var( $url, FILTER_VALIDATE_URL ) ) {
66
- unset( $urls[ $key ] );
67
- }
68
- }
69
- $data['sh_feature_policy_urls'] = implode( PHP_EOL, $urls );
70
-
71
- return $data;
72
- }
73
-
74
- public function appendHeader() {
75
- if ( headers_sent() ) {
76
- return;
77
- }
78
- $model = $this->getModel();
79
- if ( ! $this->maybeSubmitHeader( 'Feature-Policy', false ) ) {
80
-
81
- return;
82
- }
83
-
84
- if ( true === $model->sh_feature_policy
85
- && isset( $model->sh_feature_policy_mode )
86
- && in_array( $model->sh_feature_policy_mode, array( 'self', 'allow', 'origins', 'none' ), true )
87
- ) {
88
- $headers = '';
89
- $features = array(
90
- 'accelerometer',
91
- 'autoplay',
92
- 'camera',
93
- 'encrypted-media',
94
- 'fullscreen',
95
- 'geolocation',
96
- 'gyroscope',
97
- 'magnetometer',
98
- 'microphone',
99
- 'midi',
100
- 'payment',
101
- 'usb',
102
- );
103
-
104
- switch ( $model->sh_feature_policy_mode ) {
105
- case 'self':
106
- array_walk(
107
- $features,
108
- function ( &$value, $key ) {
109
- $value .= " 'self'";
110
- }
111
- );
112
- $headers = 'Feature-Policy: ' . implode( '; ', $features );
113
- break;
114
- case 'allow':
115
- array_walk(
116
- $features,
117
- function ( &$value, $key ) {
118
- $value .= ' *';
119
- }
120
- );
121
- $headers = 'Feature-Policy: ' . implode( '; ', $features );
122
- break;
123
- case 'origins':
124
- if ( isset( $model->sh_feature_policy_urls ) && ! empty( $model->sh_feature_policy_urls ) ) {
125
- $urls = explode( PHP_EOL, $model->sh_feature_policy_urls );
126
- $urls = array_map( 'trim', $urls );
127
- $urls = implode( ' ', $urls );
128
- array_walk(
129
- $features,
130
- function ( &$value, $key ) use ( $urls ) {
131
- $value .= ' ' . $urls;
132
- }
133
- );
134
- $headers = 'Feature-Policy: ' . implode( '; ', $features );
135
- }
136
- break;
137
- case 'none':
138
- array_walk(
139
- $features,
140
- function ( &$value, $key ) {
141
- $value .= " 'none'";
142
- }
143
- );
144
- $headers = 'Feature-Policy: ' . implode( '; ', $features );
145
- break;
146
- default:
147
- break;
148
- }
149
- if ( strlen( $headers ) > 0 ) {
150
- header( trim( $headers ) );
151
- }
152
- }
153
- }
154
-
155
- /**
156
- * @return string
157
- */
158
- public function getTitle() {
159
- return __( 'Feature-Policy', "defender-security" );
160
- }
161
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/advanced-tools/component/security-headers/sh-referrer-policy.php DELETED
@@ -1,87 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Advanced_Tools\Component\Security_Headers;
7
-
8
- use WP_Defender\Behavior\Utils;
9
- use WP_Defender\Module\Advanced_Tools\Component\Security_Header;
10
-
11
- class Sh_Referrer_Policy extends Security_Header {
12
- static $rule_slug = 'sh_referrer_policy';
13
-
14
- public function check() {
15
- $model = $this->getModel();
16
-
17
- if ( ! $model->sh_referrer_policy ) {
18
- return false;
19
- }
20
- if ( isset( $model->sh_referrer_policy_mode ) && ! empty( $model->sh_referrer_policy_mode ) ) {
21
- return true;
22
- }
23
- $headers = $this->headRequest( network_site_url(), self::$rule_slug );
24
- if ( is_wp_error( $headers ) ) {
25
- Utils::instance()->log( sprintf( 'Self ping error: %s', $headers->get_error_message() ) );
26
-
27
- return false;
28
- }
29
-
30
- return false;
31
- }
32
-
33
- /**
34
- * @return array
35
- */
36
- public function getMiscData() {
37
- $model = $this->getModel();
38
-
39
- return array(
40
- 'intro_text' => esc_html__( 'The Referrer-Policy HTTP header tells web-browsers how to handle referrer information that is sent to websites when a user clicks a link that leads to another page or website link. Referrer headers tell website owners inbound visitors came from (like Google Analytics Acquisition Reports), but there are cases where you may want to control or restrict the amount of information present in this header.', "defender-security" ),
41
- 'mode' => isset( $model->sh_referrer_policy_mode ) ? $model->sh_referrer_policy_mode : 'origin-when-cross-origin',
42
- );
43
- }
44
-
45
- public function addHooks() {
46
- $this->addAction( 'send_headers', 'appendHeader' );
47
- }
48
-
49
- public function appendHeader() {
50
- if ( headers_sent() ) {
51
- return;
52
- }
53
- $model = $this->getModel();
54
- if ( ! $this->maybeSubmitHeader( 'Referrer-Policy', false ) ) {
55
-
56
- return;
57
- }
58
-
59
- if ( true === $model->sh_referrer_policy
60
- && isset( $model->sh_referrer_policy_mode )
61
- && in_array(
62
- $model->sh_referrer_policy_mode,
63
- array(
64
- 'no-referrer',
65
- 'no-referrer-when-downgrade',
66
- 'origin',
67
- 'origin-when-cross-origin',
68
- 'same-origin',
69
- 'strict-origin',
70
- 'strict-origin-when-cross-origin',
71
- 'unsafe-url',
72
- ),
73
- true
74
- )
75
- ) {
76
- $headers = 'Referrer-Policy: ' . $model->sh_referrer_policy_mode;
77
- header( $headers );
78
- }
79
- }
80
-
81
- /**
82
- * @return string
83
- */
84
- public function getTitle() {
85
- return __( 'Referrer Policy', "defender-security" );
86
- }
87
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/advanced-tools/component/security-headers/sh-strict-transport.php DELETED
@@ -1,176 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Advanced_Tools\Component\Security_Headers;
7
-
8
- use WP_Defender\Behavior\Utils;
9
- use WP_Defender\Module\Advanced_Tools\Component\Security_Header;
10
-
11
- class Sh_Strict_Transport extends Security_Header {
12
- static $rule_slug = 'sh_strict_transport';
13
-
14
- /**
15
- * Get time in seconds
16
- *
17
- * @return array
18
- */
19
- private function timeInSeconds() {
20
- return array(
21
- '1 hour' => 1 * 3600,
22
- '24 hours' => 86400,
23
- '7 days' => 7 * 86400,
24
- '30 days' => 30 * 86400,
25
- '3 months' => ( 3 * 30 + 1 ) * 86400,
26
- '6 months' => ( 6 * 30 + 3 ) * 86400,
27
- '1 year' => 365 * 86400,
28
- '2 years' => 365 * 2 * 86400,
29
- );
30
- }
31
-
32
- /**
33
- * Check HTTPS
34
- *
35
- * @return bool
36
- */
37
- private function isHttps() {
38
- return isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && 'https' === $_SERVER['HTTP_X_FORWARDED_PROTO'];
39
- }
40
-
41
- public function check() {
42
- $model = $this->getModel();
43
-
44
- if ( ! $model->sh_strict_transport ) {
45
- return false;
46
- }
47
- //'max-age' directive is required
48
- if ( ! empty( $model->hsts_cache_duration ) ) {
49
- return true;
50
- }
51
- $headers = $this->headRequest( network_site_url(), self::$rule_slug );
52
- if ( is_wp_error( $headers ) ) {
53
- Utils::instance()->log( sprintf( 'Self ping error: %s', $headers->get_error_message() ) );
54
-
55
- return false;
56
- }
57
-
58
- if ( isset( $headers['strict-transport-security'] ) ) {
59
- $hsts_cache_duration = '';
60
- $hsts_preload = 0;
61
- $include_subdomain = 0;
62
- $header_sts = is_array( $headers['strict-transport-security'] )
63
- ? $headers['strict-transport-security'][0]
64
- : $headers['strict-transport-security'];
65
-
66
- $content = explode( ';', $header_sts );
67
- foreach ( $content as $line ) {
68
- if ( stristr( $line, 'max-age' ) ) {
69
- $value = explode( '=', $line );
70
- $arr = $this->timeInSeconds();
71
- $seconds = isset( $value[1] ) ? (int) $value[1] : 0;
72
- $closest = null;
73
- $key = null;
74
- foreach ( $arr as $k => $item ) {
75
- if ( is_null( $closest ) || ( ! is_null( $closest ) && ( abs( $seconds - $closest ) > abs( $item - $seconds ) ) ) ) {
76
- $closest = $item;
77
- $key = $k;
78
- }
79
- }
80
- $hsts_cache_duration = $key;
81
- } elseif ( stristr( $line, 'preload' ) ) {
82
- $hsts_preload = 1;
83
- } elseif ( stristr( $line, 'includeSubDomains' ) ) {
84
- $include_subdomain = 1;
85
- }
86
- }
87
-
88
- if ( ( '' !== $hsts_cache_duration )
89
- || ( 0 !== $hsts_preload )
90
- || ( 0 !== $include_subdomain )
91
- ) {
92
- if ( is_null( $model->hsts_preload ) && $hsts_preload ) {
93
- $model->hsts_preload = $hsts_preload;
94
- }
95
- if ( is_null( $model->include_subdomain ) && $include_subdomain ) {
96
- $model->include_subdomain = $include_subdomain;
97
- }
98
- if ( is_null( $model->hsts_cache_duration ) && $hsts_cache_duration ) {
99
- $model->hsts_cache_duration = $hsts_cache_duration;
100
- }
101
- $model->save();
102
- }
103
-
104
- return true;
105
- }
106
-
107
- return false;
108
- }
109
-
110
- public function getMiscData() {
111
- $model = $this->getModel();
112
- $site_url = network_site_url();
113
- $domain_data = Utils::instance()->parseDomain( $site_url );
114
- $allow_subdomain = false;
115
- if ( is_array( $domain_data ) && ! isset( $domain_data['subdomain'] ) ) {
116
- $allow_subdomain = true;
117
- } elseif ( ! $domain_data && ! is_multisite() ) {
118
- //case if a single site installs in a folder, e.g. http://example.com/something/folder/
119
- $allow_subdomain = true;
120
- } elseif ( ! $domain_data && is_multisite() && is_subdomain_install() && is_main_site() ) {
121
- //case if it's a main MU site with subdomain install
122
- $allow_subdomain = true;
123
- }
124
-
125
- return array(
126
- 'intro_text' => esc_html__( 'The HTTP Strict-Transport-Security response header (HSTS) lets a web site tell browsers that it should only be accessed using HTTPS, instead of using HTTP. This is extremely important for websites that store and process sensitive information like ECommerce stores and helps prevent Protocol Downgrade and Clickjacking attacks.', "defender-security" ),
127
- 'hsts_preload' => isset( $model->hsts_preload ) ? $model->hsts_preload : 0,
128
- 'include_subdomain' => isset( $model->include_subdomain ) ? $model->include_subdomain : 0,
129
- 'hsts_cache_duration' => isset( $model->hsts_cache_duration ) ? $model->hsts_cache_duration : '30 days',
130
- 'allow_subdomain' => $allow_subdomain,
131
- );
132
- }
133
-
134
- public function addHooks() {
135
- $this->addAction( 'send_headers', 'appendHeader' );
136
- }
137
-
138
- public function appendHeader() {
139
- if ( headers_sent() ) {
140
- return;
141
- }
142
-
143
- if ( ! $this->maybeSubmitHeader( 'Strict-Transport-Security', false ) ) {
144
- return;
145
- }
146
- $model = $this->getModel();
147
- //header is ignored by the browser when your site is accessed using HTTP
148
- if ( true === $model->sh_strict_transport ) {
149
- $headers = 'Strict-Transport-Security:';
150
- if ( isset( $model->hsts_cache_duration ) && ! empty( $model->hsts_cache_duration ) ) {
151
- $arr = $this->timeInSeconds();
152
- //set default for a week, so RIPs wont waring weak header
153
- $seconds = isset( $arr[ $model->hsts_cache_duration ] ) ? $arr[ $model->hsts_cache_duration ] : 604800;
154
- if ( ! is_null( $seconds ) ) {
155
- $headers .= ' max-age=' . $seconds;
156
- }
157
- }
158
-
159
- if ( '1' === (string) $model->include_subdomain ) {
160
- $headers .= ' ; includeSubDomains';
161
- }
162
- if ( '1' === (string) $model->hsts_preload ) {
163
- $headers .= ' ; preload';
164
- }
165
-
166
- header( $headers );
167
- }
168
- }
169
-
170
- /**
171
- * @return string
172
- */
173
- public function getTitle() {
174
- return __( 'Strict Transport', "defender-security" );
175
- }
176
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/advanced-tools/component/security-headers/sh-x-frame.php DELETED
@@ -1,118 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Advanced_Tools\Component\Security_Headers;
7
-
8
- use WP_Defender\Behavior\Utils;
9
- use WP_Defender\Module\Advanced_Tools\Component\Security_Header;
10
-
11
- class Sh_X_Frame extends Security_Header {
12
- static $rule_slug = 'sh_xframe';
13
-
14
- public function check() {
15
- $model = $this->getModel();
16
-
17
- if ( ! $model->sh_xframe ) {
18
- return false;
19
- }
20
- if ( isset( $model->sh_xframe_mode ) && ! empty( $model->sh_xframe_mode ) ) {
21
- return true;
22
- }
23
- $headers = $this->headRequest( network_site_url(), self::$rule_slug );
24
- if ( is_wp_error( $headers ) ) {
25
- Utils::instance()->log( sprintf( 'Self ping error: %s', $headers->get_error_message() ), 'security-headers' );
26
-
27
- return false;
28
- }
29
-
30
- if ( isset( $headers['x-frame-options'] ) ) {
31
- $header_xframe = is_array( $headers['x-frame-options'] ) ? $headers['x-frame-options'][0] : $headers['x-frame-options'];
32
-
33
- $content = strtolower( trim( $header_xframe ) );
34
- if ( stristr( $content, 'allow-from' ) ) {
35
- $model->sh_xframe_mode = 'allow-from';
36
- $urls = explode( ' ', $content );
37
- unset( $urls[0] );
38
- $model->sh_xframe_urls = implode( PHP_EOL, $urls );
39
- } elseif ( in_array( strtolower( $content ), array( 'sameorigin', 'deny' ), true ) ) {
40
- $model->sh_xframe_mode = strtolower( $content );
41
- }
42
- $model->save();
43
-
44
- return true;
45
- }
46
-
47
- return false;
48
- }
49
-
50
- /**
51
- * @return array
52
- */
53
- public function getMiscData() {
54
- $model = $this->getModel();
55
-
56
- return array(
57
- 'intro_text' => __( "The X-Frame-Options HTTP response header controls whether or not a browser can render a webpage inside a <frame>, <iframe> or <object> tag. Websites can avoid clickjacking attacks by ensuring that their content isn't embedded into other websites.", "defender-security" ),
58
- 'mode' => isset( $model->sh_xframe_mode ) ? $model->sh_xframe_mode : 'sameorigin',
59
- 'values' => isset( $model->sh_xframe_urls ) ? $model->sh_xframe_urls : '',
60
- );
61
- }
62
-
63
- public function addHooks() {
64
- $this->addAction( 'send_headers', 'appendHeader' );
65
- $this->addFilter( 'processing_security_headers', 'filteringHeaders' );
66
- }
67
-
68
- public function filteringHeaders( $data ) {
69
- if ( ! isset( $data['sh_xframe'] ) ) {
70
- return $data;
71
- }
72
- if ( 'allow-from' !== $data['sh_xframe_mode'] || empty( $data['sh_xframe_urls'] ) ) {
73
- return $data;
74
- }
75
- $urls = sanitize_textarea_field( $data['sh_xframe_urls'] );
76
- $urls = explode( PHP_EOL, $urls );
77
- $urls = array_map( 'trim', $urls );
78
- foreach ( $urls as $key => $url ) {
79
- if ( false === filter_var( trim( $url ), FILTER_VALIDATE_URL ) ) {
80
- unset( $urls[ $key ] );
81
- }
82
- }
83
-
84
- $data['sh_xframe_urls'] = implode( PHP_EOL, $urls );
85
-
86
- return $data;
87
- }
88
-
89
- public function appendHeader() {
90
- if ( headers_sent() ) {
91
- return;
92
- }
93
-
94
- if ( ! $this->maybeSubmitHeader( 'X-Frame-Options', false ) ) {
95
- return;
96
- }
97
-
98
- $model = $this->getModel();
99
- $mode = $model->sh_xframe_mode;
100
-
101
- if ( true === $model->sh_xframe && in_array( $mode, array( 'sameorigin', 'allow-from', 'deny' ), true ) ) {
102
- $headers = 'X-Frame-Options: ' . $mode;
103
- if ( 'allow-from' === $mode && isset( $model->sh_xframe_urls ) && ! empty( $model->sh_xframe_urls ) ) {
104
- $urls = explode( PHP_EOL, $model->sh_xframe_urls );
105
- $urls = array_map( 'trim', $urls );
106
- $headers .= ' ' . implode( ' ', $urls );
107
- }
108
- header( trim( $headers ) );
109
- }
110
- }
111
-
112
- /**
113
- * @return string
114
- */
115
- public function getTitle() {
116
- return __( 'X-Frame-Options', "defender-security" );
117
- }
118
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/advanced-tools/component/security-headers/sh-xss-protection.php DELETED
@@ -1,99 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Advanced_Tools\Component\Security_Headers;
7
-
8
- use WP_Defender\Behavior\Utils;
9
- use WP_Defender\Module\Advanced_Tools\Component\Security_Header;
10
-
11
- class Sh_XSS_Protection extends Security_Header {
12
- static $rule_slug = 'sh_xss_protection';
13
-
14
- public function check() {
15
- $model = $this->getModel();
16
-
17
- if ( ! $model->sh_xss_protection ) {
18
- return false;
19
- }
20
- if ( isset( $model->sh_xss_protection_mode ) && ! empty( $model->sh_xss_protection_mode ) ) {
21
- return true;
22
- }
23
- $headers = $this->headRequest( network_site_url(), self::$rule_slug );
24
- if ( is_wp_error( $headers ) ) {
25
- Utils::instance()->log( sprintf( 'Self ping error: %s', $headers->get_error_message() ) );
26
-
27
- return false;
28
- }
29
-
30
- if ( isset( $headers['x-xss-protection'] ) ) {
31
- $header_xss_protection = is_array( $headers['x-xss-protection'] )
32
- ? $headers['x-xss-protection'][0]
33
- : $headers['x-xss-protection'];
34
- $content = strtolower( trim( $header_xss_protection ) );
35
- $content = explode( ';', $content );
36
- if ( 1 === count( $content ) ) {
37
- $model->sh_xss_protection_mode = 'sanitize';
38
- } else {
39
- $content = explode( '=', $content[1] );
40
- $model->sh_xss_protection_mode = $content[1];
41
- }
42
- $model->save();
43
-
44
- return true;
45
- }
46
-
47
- return false;
48
- }
49
-
50
- /**
51
- * @return array
52
- */
53
- public function getMiscData() {
54
- $model = $this->getModel();
55
-
56
- return array(
57
- 'intro_text' => esc_html__( 'The HTTP X-XSS-Protection response header that stops pages from loading when they detect reflected cross-site scripting (XSS) attacks on Chrome, IE and Safari.', "defender-security" ),
58
- 'mode' => isset( $model->sh_xss_protection_mode ) ? $model->sh_xss_protection_mode : 'sanitize',
59
- );
60
- }
61
-
62
- public function addHooks() {
63
- $this->addAction( 'send_headers', 'appendHeader' );
64
- }
65
-
66
- public function appendHeader() {
67
- if ( headers_sent() ) {
68
- return;
69
- }
70
- $model = $this->getModel();
71
- if ( ! $this->maybeSubmitHeader( 'X-XSS-Protection', false ) ) {
72
-
73
- return;
74
- }
75
- if ( true === $model->sh_xss_protection && in_array( $model->sh_xss_protection_mode, array( 'sanitize', 'block', 'none' ), true ) ) {
76
- $headers = '';
77
- switch ( $model->sh_xss_protection_mode ) {
78
- case 'sanitize':
79
- $headers = 'X-XSS-Protection: 1';
80
- break;
81
- case 'block':
82
- $headers = 'X-XSS-Protection: 1; mode=block';
83
- break;
84
- default:
85
- break;
86
- }
87
- if ( strlen( $headers ) > 0 ) {
88
- header( trim( $headers ) );
89
- }
90
- }
91
- }
92
-
93
- /**
94
- * @return string
95
- */
96
- public function getTitle() {
97
- return __( 'X-XSS-Protection', "defender-security" );
98
- }
99
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/advanced-tools/controller/main.php DELETED
@@ -1,129 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Advanced_Tools\Controller;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use Hammer\Helper\WP_Helper;
10
- use WP_Defender\Behavior\Utils;
11
- use WP_Defender\Controller;
12
- use WP_Defender\Module\Advanced_Tools\Component\Mask_Api;
13
- use WP_Defender\Module\Advanced_Tools\Component\Mask_Login_Listener;
14
- use WP_Defender\Module\Advanced_Tools\Component\Security_Headers_Listener;
15
- use WP_Defender\Module\Advanced_Tools\Model\Mask_Settings;
16
- use WP_Defender\Module\Advanced_Tools\Model\Security_Headers_Settings;
17
-
18
- class Main extends Controller {
19
- protected $slug = 'wdf-advanced-tools';
20
-
21
- /**
22
- * @return array
23
- */
24
- public function behaviors() {
25
- $behaviors = array(
26
- 'utils' => '\WP_Defender\Behavior\Utils',
27
- 'endpoints' => '\WP_Defender\Behavior\Endpoint',
28
- 'wpmudev' => '\WP_Defender\Behavior\WPMUDEV',
29
- );
30
-
31
- return $behaviors;
32
- }
33
-
34
- public function __construct() {
35
- if ( $this->isNetworkActivate( wp_defender()->plugin_slug ) ) {
36
- $this->addAction( 'network_admin_menu', 'adminMenu' );
37
- } else {
38
- $this->addAction( 'admin_menu', 'adminMenu' );
39
- }
40
- $this->addAction( 'defender_enqueue_assets', 'scripts', 12 );
41
-
42
- new Mask_Login_Listener();
43
- new Security_Headers_Listener();
44
- }
45
-
46
- /**
47
- * Add submit admin page
48
- */
49
- public function adminMenu() {
50
- $cap = is_multisite() ? 'manage_network_options' : 'manage_options';
51
- add_submenu_page(
52
- 'wp-defender',
53
- esc_html__( 'Advanced Tools', "defender-security" ),
54
- esc_html__( 'Advanced Tools', "defender-security" ),
55
- $cap,
56
- $this->slug,
57
- array(
58
- &$this,
59
- 'actionIndex',
60
- )
61
- );
62
- }
63
-
64
- /**
65
- * a simple router
66
- */
67
- public function actionIndex() {
68
- $this->render( 'main' );
69
- }
70
-
71
- /**
72
- * Enqueue scripts & styles
73
- */
74
- public function scripts() {
75
- if ( $this->isInPage() ) {
76
- wp_enqueue_style( 'wpmudev-sui' );
77
- wp_enqueue_media();
78
- wp_enqueue_style( 'defender' );
79
- wp_register_script(
80
- 'defender-adtools',
81
- wp_defender()->getPluginUrl() . 'assets/app/advanced-tools.js',
82
- array(
83
- 'def-vue',
84
- 'defender',
85
- 'wp-i18n',
86
- ),
87
- wp_defender()->version,
88
- true
89
- );
90
- wp_localize_script( 'defender-adtools', 'advanced_tools', $this->_scriptsData() );
91
- Utils::instance()->createTranslationJson( 'defender-adtools' );
92
- wp_set_script_translations( 'defender-adtools', 'wpdef', wp_defender()->getPluginPath() . 'languages' );
93
- wp_enqueue_script( 'defender-adtools' );
94
- wp_enqueue_script( 'wpmudev-sui' );
95
- }
96
- }
97
-
98
- /**
99
- * @return array
100
- */
101
- public function _scriptsData() {
102
- if ( ! $this->checkPermission() ) {
103
- return array();
104
- }
105
- $allRoles = get_editable_roles();
106
- $ml_settings = Mask_Settings::instance();
107
- $sh_settings = Security_Headers_Settings::instance();
108
-
109
- return array(
110
- 'misc' => array(
111
- 'all_roles' => $allRoles,
112
- 'compatibility' => isset( wp_defender()->global['compatibility'] ) && is_array( wp_defender()->global['compatibility'] ) ? wp_defender()->global['compatibility'] : false,
113
- 'new_login_url' => Mask_Api::getNewLoginUrl(),
114
- 'login_redirect_url' => Mask_Api::getRedirectUrl(),
115
- 'home_url' => trailingslashit( network_home_url() ),
116
- 'security_headers' => $sh_settings->getHeadersAsArray( true ),
117
- ),
118
- 'model' => array(
119
- 'mask_login' => $ml_settings->export( array( 'otp' ) ),
120
- 'security_headers' => $sh_settings,
121
- ),
122
- 'nonces' => array(
123
- 'updateSettings' => wp_create_nonce( 'updateSettings' ),
124
- 'sendTestEmail' => wp_create_nonce( 'sendTestEmail' ),
125
- ),
126
- 'endpoints' => $this->getAllAvailableEndpoints( \WP_Defender\Module\Advanced_Tools::getClassName() ),
127
- );
128
- }
129
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/advanced-tools/controller/rest.php DELETED
@@ -1,121 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Advanced_Tools\Controller;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use WP_Defender\Behavior\Utils;
10
- use WP_Defender\Controller;
11
- use WP_Defender\Module\Advanced_Tools;
12
-
13
- class Rest extends Controller {
14
- public function __construct() {
15
- $namespace = 'wp-defender/v1';
16
- $namespace .= '/advanced-tools';
17
- $routes = array(
18
- $namespace . '/updateSettings' => 'updateSettings',
19
- $namespace . '/sendTestEmail' => 'sendTestEmail',
20
-
21
- );
22
- $this->registerEndpoints( $routes, Advanced_Tools::getClassName() );
23
- }
24
-
25
- /**
26
- * Send test email
27
- */
28
- public function sendTestEmail() {
29
- if ( ! $this->checkPermission() ) {
30
- return;
31
- }
32
-
33
- if ( ! wp_verify_nonce( HTTP_Helper::retrieveGet( '_wpnonce' ), 'sendTestEmail' ) ) {
34
- return;
35
- }
36
-
37
- //get the backup email from current user
38
- $backup_email = \WP_Defender\Module\Two_Factor\Component\Auth_API::getBackupEmail( get_current_user_id() );
39
- $subject = wp_kses_post( HTTP_Helper::retrievePost( 'email_subject' ) );
40
- $sender = HTTP_Helper::retrievePost( 'email_sender' );
41
- $body = wp_kses_post( HTTP_Helper::retrievePost( 'email_body' ) );
42
- $params = array(
43
- 'pass_code' => '[a-sample-passcode]',
44
- 'display_name' => Utils::instance()->getDisplayName(),
45
- );
46
- foreach ( $params as $key => $param ) {
47
- $body = str_replace( "{{$key}}", $param, $body );
48
- }
49
- $headers = array( 'Content-Type: text/html; charset=UTF-8' );
50
- if ( $sender ) {
51
- $from_email = get_bloginfo( 'admin_email' );
52
- $headers[] = sprintf( 'From: %s <%s>', $sender, $from_email );
53
- }
54
-
55
- $send_mail = wp_mail( $backup_email, $subject, $body, $headers );
56
- if ( $send_mail ) {
57
- wp_send_json_success(
58
- array(
59
- 'message' => __( 'Test email has been sent to your email.', "defender-security" ),
60
- )
61
- );
62
- } else {
63
- wp_send_json_error(
64
- array(
65
- 'message' => __( 'Test email failed.', "defender-security" ),
66
- )
67
- );
68
- }
69
-
70
- }
71
-
72
- /**
73
- * An endpoint for update settings
74
- */
75
- public function updateSettings() {
76
- if ( ! $this->checkPermission() ) {
77
- return;
78
- }
79
-
80
- if ( ! wp_verify_nonce( HTTP_Helper::retrieveGet( '_wpnonce' ), 'updateSettings' ) ) {
81
- return;
82
- }
83
-
84
- $data = stripslashes( $_POST['data'] );
85
- $data = json_decode( $data, true );
86
- $module = $data['module'];
87
- $settings = $data['settings'];
88
- if ( 'security-headers' === $module ) {
89
- $model = Advanced_Tools\Model\Security_Headers_Settings::instance();
90
- $settings = apply_filters( 'processing_security_headers', $settings );
91
- } else {
92
- $model = Advanced_Tools\Model\Mask_Settings::instance();
93
- }
94
- $model->import( $settings );
95
- if ( $model->validate() ) {
96
- $model->save();
97
- $res = array(
98
- 'message' => __( 'Your settings have been updated.', "defender-security" ),
99
- );
100
- $this->submitStatsToDev();
101
- wp_send_json_success( $res );
102
- } else {
103
- $res = array(
104
- 'message' => implode( '<br/>', $model->getErrors() ),
105
- );
106
- wp_send_json_error( $res );
107
- }
108
- }
109
-
110
- /**
111
- * Import Utils into the class
112
- * @return array
113
- */
114
- public function behaviors() {
115
- $behaviors = array(
116
- 'utils' => '\WP_Defender\Behavior\Utils',
117
- );
118
-
119
- return $behaviors;
120
- }
121
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/advanced-tools/css/login-admin.css DELETED
@@ -1,34 +0,0 @@
1
- .def-notification {
2
- padding: 10px 20px;
3
- border-radius: 4px;
4
- background-color: #D1F1EA;
5
- color: #666;
6
- display: block;
7
- clear: right;
8
- width: 50%;
9
- margin-bottom: 10px;
10
- }
11
-
12
- .card {
13
- margin-top: 10px;
14
- padding: 30px 30px;
15
- }
16
-
17
- .well {
18
- border-radius: 5px;
19
- background-color: #F9F9F9;
20
- padding: 15px;
21
- margin-top: 15px;
22
- width: 50%;
23
- }
24
-
25
- .line {
26
- margin-bottom: 20px;
27
- }
28
-
29
- .error {
30
- color: #FF6D6D;
31
- font-size: 12px !important;
32
- font-weight: 500;
33
- padding-bottom: 10px;
34
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/advanced-tools/css/login.css DELETED
@@ -1,21 +0,0 @@
1
- body.login div#login h1 a {
2
- background-image: url("../img/2factor-disabled.svg");
3
- }
4
-
5
- body.login div#login form {
6
- padding-bottom: 26px;
7
- }
8
-
9
- .float-r {
10
- float: right;
11
- }
12
-
13
- .clearfix {
14
- clear: both;
15
- }
16
-
17
- .def-ajaxloader {
18
- width: 20px;
19
- position: relative;
20
- top: 5px;
21
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/advanced-tools/img/2factor-disabled.svg DELETED
@@ -1,85 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
- <svg width="128px" height="128px" viewBox="0 0 128 128" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3
- <!-- Generator: Sketch 45.1 (43504) - http://www.bohemiancoding.com/sketch -->
4
- <title>graphic-defender-2factor-disabled</title>
5
- <desc>Created with Sketch.</desc>
6
- <defs>
7
- <circle id="path-1" cx="64" cy="64" r="64"></circle>
8
- <polygon id="path-3" points="0.327466846 0.3500558 3.88734603 0.3500558 3.88734603 21.3428699 0.327466846 21.3428699 0.327466846 0.3500558"></polygon>
9
- <polygon id="path-5" points="51.1257801 0.184853857 51.1257801 49.0738103 0.330536413 49.0738103 0.330536413 0.184853857"></polygon>
10
- </defs>
11
- <g id="Security-Plugin" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
12
- <g id="Advanced-Tools---2-Factor---Disabled" transform="translate(-726.000000, -223.000000)">
13
- <g id="graphic-defender-2factor-disabled" transform="translate(726.000000, 223.000000)">
14
- <mask id="mask-2" fill="white">
15
- <use xlink:href="#path-1"></use>
16
- </mask>
17
- <use id="mask" fill="#333333" xlink:href="#path-1"></use>
18
- <g id="graphic" mask="url(#mask-2)">
19
- <g transform="translate(-6.000000, 10.000000)">
20
- <path d="M39.4062404,173.10829 C44.5020972,174.081424 53.4377494,173.063861 54.0267519,168.804431 C53.575243,166.584784 53.2010742,166.272707 53.2010742,166.272707 C53.2010742,166.272707 66.6772379,143.156842 65.7953453,123.921688 C64.9134527,104.686534 45.3095141,107.332196 45.3095141,107.332196 C45.3095141,107.332196 37.373913,118.626064 34.904757,136.272889 C32.4359591,153.919715 37.417954,162.29669 37.417954,162.29669 C37.417954,162.29669 35.7354476,166.837383 34.6032737,173.249817 C34.7436317,172.456549 34.891867,171.690869 35.044399,170.959585 C35.3802558,171.617418 36.4050128,172.535016 39.4062404,173.10829" id="Fill-19" fill="#9F5622"></path>
21
- <path d="M98.7215192,173.10829 C93.6256624,174.081424 84.6900102,173.063861 84.1006496,168.804431 C84.5525166,166.584784 84.9266854,166.272707 84.9266854,166.272707 C84.9266854,166.272707 71.4505217,143.156842 72.3324143,123.921688 C73.2143069,104.686534 92.8182455,107.332196 92.8182455,107.332196 C92.8182455,107.332196 100.753847,118.626064 103.223003,136.272889 C105.691801,153.919715 100.709806,162.29669 100.709806,162.29669 C100.709806,162.29669 102.392312,166.837383 103.524486,173.249817 C103.384128,172.456549 103.235893,171.690869 103.083361,170.959585 C102.747504,171.617418 101.722747,172.535016 98.7215192,173.10829" id="Fill-77" fill="#9F5622"></path>
22
- <path d="M45.5730793,111.169696 C44.4412634,111.145332 43.5396777,111.197643 42.9821841,111.245655 C42.9291918,111.344187 42.8747673,111.447376 42.8207008,111.549132 C45.055688,112.721121 54.9878107,118.292633 62.1181432,128.225332 C63.6098056,130.696504 64.5615192,132.467564 65.1673504,133.735218 C65.5007008,131.627717 65.7244859,129.513409 65.8032583,127.424898 C60.5981944,123.105273 50.4301125,115.602542 45.5730793,111.169696" id="Fill-123" fill="#98480C"></path>
23
- <path d="M95.3429003,111.617065 C95.2684246,111.475897 95.1939488,111.334728 95.1216215,111.200725 C91.5313913,110.649665 73.9902148,108.978569 72.3789616,128.537265 C72.495688,130.435162 72.7262762,132.348825 73.0445882,134.254963 C74.7668389,130.825706 78.878399,123.432255 86.114,117.877224 C91.3011611,113.894757 94.0055601,112.275973 95.3429003,111.617065" id="Fill-125" fill="#98480C"></path>
24
- <path d="M100.613739,76.4418678 C106.021821,71.862837 111.178547,67.119348 111.178547,67.119348 L111.178547,70.2465609 C119.016399,59.9806461 122.406118,48.4047988 122.238905,47.40121 C122.0409,46.2105903 119.117013,44.801768 115.563662,39.7637592 C102.081412,32.6214743 69.0639693,25.4283113 69.0639693,25.4283113 C69.0639693,25.4283113 38.0946087,33.1162819 24.6123581,40.2589251 C19.0610537,41.4491865 16.0870384,46.2105903 15.8886752,47.40121 C15.7228951,48.3961997 19.056399,59.7882408 26.7553248,69.9896623 L28.2978312,69.1609222 L36.5098517,74.7177445 L31.6094936,75.5826725 C31.6728696,75.6457327 31.7355294,75.7095095 31.7996215,75.7722115 C34.3769105,77.9549545 35.7650946,78.1530925 35.7650946,78.1530925 C35.7650946,78.1530925 39.7799795,83.113351 42.1592634,84.5021087 C49.0983939,85.69237 69.0639693,85.2437827 69.0639693,85.2437827 C69.0639693,85.2437827 89.0291867,85.69237 95.9686752,84.5021087 C98.3479591,83.113351 102.362844,78.1530925 102.362844,78.1530925 C102.362844,78.1530925 102.51645,78.1298032 102.810414,78.0230308 C100.344123,78.2670308 98.7471918,78.0223142 100.613739,76.4418678" id="Fill-127" fill="#9F5622"></path>
25
- <path d="M82.4067212,34.5627971 L69.0637545,31.4660394 L55.7211458,34.5627971 L55.499509,37.0296693 C55.499509,37.0296693 60.1549565,40.9662743 62.0845217,42.1733756 C64.014087,43.3804769 65.8169003,45.3865797 65.8169003,45.3865797 L66.623601,45.9931759 L69.0637545,45.9931759 L71.504266,45.9931759 L72.3109668,45.3865797 C72.3109668,45.3865797 74.1137801,43.3804769 76.0433453,42.1733756 C77.9729105,40.9662743 82.6283581,37.0296693 82.6283581,37.0296693 L82.4067212,34.5627971 Z" id="Fill-129" fill="#98480C"></path>
26
- <path d="M68.0702916,21.3509674 C67.9360205,19.1470849 67.4053811,10.2917838 67.2954578,6.37237709 C67.2199079,3.67010396 67.526046,1.65253568 67.7824143,0.467290455 C66.6745882,0.59090279 64.8008798,0.851026138 61.97689,1.39993656 C56.8996522,2.38740206 54.2400102,7.87149016 54.2400102,10.2297985 C54.2400102,10.8908558 54.3234373,13.0567589 54.4491151,15.8432317 C54.0899847,16.1409762 53.6216471,16.6067618 53.5629258,17.0546326 C53.5396522,17.2334226 53.5503939,17.6859512 53.5840512,18.2839483 C54.0459437,18.8876781 54.4791918,19.419032 54.620624,19.4867501 C54.9657903,19.6515665 57.1918261,24.4624153 59.2427724,26.2796957 C60.7566343,27.6215166 62.5981176,28.5348147 63.6006752,28.9748029 C63.6364808,28.837217 63.6726445,28.6996311 63.7095243,28.5631201 C64.6053811,25.2481598 66.7372481,22.5136399 68.0702916,21.3509674" id="Fill-131" fill="#FF5B0C"></path>
27
- <path d="M60.4257545,37.7939518 C61.9381841,38.0959959 62.4806394,33.2980458 63.6006394,28.9748388 C62.5980818,28.5348505 60.7565985,27.6215524 59.2427366,26.2797316 C57.1917903,24.4624511 54.9657545,19.6516023 54.6205882,19.4867859 C54.479156,19.4190678 54.0459079,18.8873557 53.5843734,18.2839841 C53.6896419,20.1528593 54.0201279,23.4516963 54.2399744,24.3241486 C54.4308184,25.0815877 54.7480563,25.5523894 54.943555,25.7877903 C55.1963427,30.4553204 55.4437596,34.4015994 55.5458056,34.6309093 C55.6782864,34.9297286 60.6420205,37.9225803 60.4257545,37.7939518" id="Fill-133" fill="#FFBC00"></path>
28
- <path d="M70.0574322,21.3509674 C70.1917033,19.1470849 70.7223427,10.2917838 70.832266,6.37237709 C70.9078159,3.67010396 70.6016777,1.65253568 70.3453095,0.467290455 C71.4531355,0.59090279 73.326844,0.851026138 76.1508338,1.39993656 C81.2280716,2.38740206 83.8877136,7.87149016 83.8877136,10.2297985 C83.8877136,10.8908558 83.8042864,13.0567589 83.6786087,15.8432317 C84.0377391,16.1409762 84.5060767,16.6067618 84.564798,17.0546326 C84.5880716,17.2334226 84.5773299,17.6859512 84.5436726,18.2839483 C84.0817801,18.8876781 83.648532,19.419032 83.5070997,19.4867501 C83.1619335,19.6515665 80.9358977,24.4624153 78.8849514,26.2796957 C77.3710895,27.6215166 75.5296061,28.5348147 74.5270486,28.9748029 C74.491243,28.837217 74.4550793,28.6996311 74.4181995,28.5631201 C73.5223427,25.2481598 71.3904757,22.5136399 70.0574322,21.3509674" id="Fill-135" fill="#FF5B0C"></path>
29
- <g id="Group-139" stroke-width="1" fill="none" transform="translate(66.956522, 0.008241)">
30
- <mask id="mask-4" fill="white">
31
- <use xlink:href="#path-3"></use>
32
- </mask>
33
- <g id="Clip-138"></g>
34
- <path d="M3.38871611,0.459192952 C2.50431714,0.361019677 2.10723274,0.349912482 2.10723274,0.349912482 C2.10723274,0.349912482 1.71050639,0.361019677 0.826107417,0.459192952 C0.569381074,1.64443818 0.263601023,3.66200646 0.339150895,6.36392129 C0.449074169,10.2836863 0.979713555,19.1386291 1.1136266,21.3428699 C1.55976471,20.9537598 1.91638875,20.7405733 2.10723274,20.7405733 C2.29843478,20.7405733 2.65505882,20.9537598 3.10083887,21.3428699 C3.23510997,19.1386291 3.76574936,10.2836863 3.87567263,6.36392129 C3.95122251,3.66200646 3.6450844,1.64443818 3.38871611,0.459192952" id="Fill-137" fill="#FFBC00" mask="url(#mask-4)"></path>
35
- </g>
36
- <path d="M63.7094527,29.1566743 C64.6053095,25.841714 66.7371765,23.1071941 68.0702199,21.9445216 C68.5163581,21.5554115 68.8729821,21.342225 69.0638261,21.342225 C69.2546701,21.342225 69.6112941,21.5554115 70.0574322,21.9445216 C71.3904757,23.1071941 73.5223427,25.841714 74.4181995,29.1566743 C74.4550793,29.2931853 74.491243,29.4304129 74.5270486,29.5683571 C75.471601,33.2143836 76.0054629,37.1982837 77.0567161,38.1753586 C77.2002967,38.0908006 77.3413708,38.0080341 77.4860256,37.9224012 C77.5579949,37.8797639 77.6299642,37.8367683 77.7019335,37.7937727 C76.1895038,38.096175 75.6470486,33.2978667 74.5270486,28.9746596 C74.491243,28.8370737 74.4550793,28.6998461 74.4181995,28.5629768 C73.5223427,25.2480164 71.3904757,22.5134966 70.0574322,21.3508241 C69.6112941,20.9620722 69.2546701,20.7488858 69.0638261,20.7488858 C68.8729821,20.7488858 68.5163581,20.9620722 68.0702199,21.3508241 C66.7371765,22.5134966 64.6053095,25.2480164 63.7094527,28.5629768 C63.6725729,28.6998461 63.6364092,28.8370737 63.6006036,28.9746596 C62.4806036,33.2978667 61.9381483,38.096175 60.4257187,37.7937727 C60.497688,37.8367683 60.5696573,37.8797639 60.6419847,37.9224012 C60.7862813,38.0080341 60.9273555,38.0908006 61.0709361,38.1753586 C62.1221893,37.1982837 62.6560512,33.2143836 63.6006036,29.5683571 C63.6364092,29.4304129 63.6725729,29.2931853 63.7094527,29.1566743" id="Fill-140" fill="#98480C"></path>
37
- <path d="M62.1412379,38.8049932 C62.167734,38.8204 62.1938721,38.8358068 62.2207263,38.8512135 C62.3263529,38.9128405 62.4305473,38.973751 62.5336675,39.0339448 C62.5648184,39.0518596 62.5959693,39.0701327 62.6267621,39.0880476 C62.7220051,39.1432253 62.8154578,39.1976863 62.9078363,39.2514308 C62.9414936,39.2707789 62.975867,39.2904852 63.0091662,39.3098332 C63.249422,39.4492106 63.4789361,39.5817803 63.6941279,39.7053927 C63.7188338,39.7197245 63.7424655,39.7329815 63.7668133,39.7469551 C63.8502404,39.7949668 63.9318772,39.8419037 64.0106496,39.8866907 C64.0378619,39.9024558 64.0647161,39.9175043 64.0912123,39.932911 C64.1606752,39.9723236 64.2272737,40.0103031 64.2920818,40.0475659 C64.3232327,40.0651225 64.3550997,40.0830373 64.3851765,40.1002355 C64.4507008,40.1374984 64.5126445,40.1726115 64.573156,40.2070079 C64.5928491,40.2181151 64.6146905,40.2306555 64.6340256,40.2414044 C64.713156,40.2861915 64.7876317,40.3277539 64.8563785,40.3664499 C64.8678363,40.3728993 64.8775038,40.3782737 64.8886036,40.3843648 C64.9430281,40.41482 64.9938721,40.4434837 65.0407775,40.4692811 C65.0608286,40.4803883 65.0787315,40.4904206 65.0973504,40.5004529 C65.1320818,40.5198009 65.1639488,40.5373574 65.1936675,40.5534808 C65.2108542,40.5627965 65.2273248,40.5717539 65.2427212,40.5799947 C65.2695754,40.5946849 65.2928491,40.6072253 65.3143325,40.6183325 C65.3250742,40.6240652 65.3372481,40.6305145 65.3469156,40.6355307 C65.3741279,40.6495043 65.3966854,40.6609698 65.4102916,40.6674191 C65.8940256,40.8866966 69.0638977,40.9963354 69.0638977,40.9963354 C69.0638977,40.9963354 72.2337698,40.8866966 72.7175038,40.6674191 C72.73111,40.6609698 72.7536675,40.6495043 72.7808798,40.6355307 C72.7905473,40.6305145 72.8027212,40.6240652 72.8134629,40.6183325 C72.8349463,40.6072253 72.8582199,40.5946849 72.8850742,40.5799947 C72.9004706,40.5717539 72.9169412,40.5627965 72.9341279,40.5534808 C72.9638465,40.5373574 72.9957136,40.5198009 73.030445,40.5004529 C73.0490639,40.4904206 73.0669668,40.4803883 73.0870179,40.4692811 C73.1339233,40.4434837 73.1847673,40.41482 73.2391918,40.3843648 C73.2502916,40.3782737 73.2599591,40.3728993 73.2714169,40.3664499 C73.3401637,40.3277539 73.4146394,40.2861915 73.4937698,40.2414044 C73.5131049,40.2306555 73.5345882,40.2181151 73.5546394,40.2070079 C73.6151509,40.1726115 73.6770946,40.1374984 73.7426189,40.1002355 C73.7726957,40.0830373 73.8045627,40.0651225 73.8357136,40.0475659 C73.9005217,40.0103031 73.9671202,39.9723236 74.0365831,39.932911 C74.0630793,39.9175043 74.0899335,39.9024558 74.1171458,39.8866907 C74.1959182,39.8419037 74.277555,39.7949668 74.3609821,39.7469551 C74.3853299,39.7329815 74.4089616,39.7197245 74.4336675,39.7053927 C74.6488593,39.5817803 74.8783734,39.4492106 75.1186292,39.3098332 C75.1519284,39.2904852 75.1863018,39.2707789 75.2199591,39.2514308 C75.3123376,39.1976863 75.4057903,39.1432253 75.5010332,39.0880476 C75.5318261,39.0701327 75.562977,39.0518596 75.5941279,39.0339448 C75.6972481,38.973751 75.8014425,38.9128405 75.9070691,38.8512135 C75.9339233,38.8358068 75.9600614,38.8204 75.9865575,38.8049932 C76.1265575,38.7229433 76.2687059,38.6401768 76.4119284,38.5559771 C76.6231816,38.4320065 76.8408798,38.3030197 77.0567877,38.1754661 C76.0055345,37.1983912 75.4716726,33.214491 74.5271202,29.5684646 C74.4913146,29.4305204 74.4551509,29.2932928 74.4182711,29.1567818 C73.5224143,25.8418214 71.3905473,23.1073016 70.0575038,21.9446291 C69.6113657,21.5555189 69.2547417,21.3423325 69.0638977,21.3423325 C68.8730537,21.3423325 68.5164297,21.5555189 68.0702916,21.9446291 C66.7372481,23.1073016 64.6053811,25.8418214 63.7095243,29.1567818 C63.6726445,29.2932928 63.6364808,29.4305204 63.6006752,29.5684646 C62.6561228,33.214491 62.1222609,37.1983912 61.0710077,38.1754661 C61.2869156,38.3030197 61.5046138,38.4320065 61.715867,38.5559771 C61.8590895,38.6401768 62.0012379,38.7229433 62.1412379,38.8049932" id="Fill-142" fill="#9F5622"></path>
38
- <path d="M77.7019693,37.7939518 C76.1895396,38.0959959 75.6470844,33.2980458 74.5270844,28.9748388 C75.5296419,28.5348505 77.3711253,27.6215524 78.8849872,26.2797316 C80.9359335,24.4624511 83.1619693,19.6516023 83.5071355,19.4867859 C83.6485678,19.4190678 84.0818159,18.8873557 84.5433504,18.2839841 C84.4380818,20.1528593 84.1075959,23.4516963 83.8877494,24.3241486 C83.6969054,25.0815877 83.3796675,25.5523894 83.1841688,25.7877903 C82.9313811,30.4553204 82.6839642,34.4015994 82.5819182,34.6309093 C82.4494373,34.9297286 77.4857033,37.9225803 77.7019693,37.7939518" id="Fill-144" fill="#FFBC00"></path>
39
- <path d="M69.0638619,21.8109128 C68.2421228,21.7654091 66.4196164,23.9409862 66.6924552,24.9556822 C67.0827366,25.1900082 69.2282097,25.7364106 69.9690281,25.7364106 C70.7102046,25.7364106 72.3092839,25.1423548 72.1921995,24.6196 C72.0751151,24.0968452 70.07,21.866807 69.0638619,21.8109128" id="Fill-146" fill="#98480C"></path>
40
- <path d="M64.7448082,30.6150849 C64.6058824,31.069405 64.9764706,29.5201304 65.1325831,28.9748029 C65.2883376,28.4294755 67.8713555,27.6487471 69.9538107,27.6487471 C72.036266,27.6487471 73.3231202,26.9987971 73.7914578,28.0457398 C74.2594373,29.0926825 74.2984655,29.4832258 74.2984655,29.4832258 C74.2984655,29.4832258 73.442711,28.7806062 73.3829156,28.5853345 C73.3231202,28.3904211 72.9722251,28.8153609 70.4758568,29.0321304 C67.9798465,29.2488999 66.0295141,28.7763066 65.8343734,29.0321304 C65.6395908,29.2879542 64.864399,30.2248999 64.7448082,30.6150849" id="Fill-148" fill="#98480C"></path>
41
- <path d="M69.5063836,31.2004341 C70.2028031,30.4981727 70.5533402,29.6393357 71.7431611,29.795553 C72.9333402,29.951412 73.7135448,31.9030537 73.0890946,31.7858907 C72.4653606,31.6687278 71.5598363,31.1613797 71.4080205,31.1613797 C71.2562046,31.1613797 69.5063836,31.2004341 69.5063836,31.2004341" id="Fill-150" fill="#98480C"></path>
42
- <path d="M57.8664041,17.6369721 C57.6744859,17.2525198 63.2447673,17.2084493 63.8488082,17.2084493 C64.452491,17.2084493 66.2810844,16.8429868 66.3372992,17.4502996 C66.3935141,18.057254 64.961289,20.6258825 64.2179642,20.8125551 C63.4746394,20.9995859 59.2184246,20.3456946 57.8664041,17.6369721" id="Fill-152" fill="#1F191A"></path>
43
- <path d="M80.294046,17.7116769 C80.4859642,17.3272247 75.1308747,17.0724758 74.5271918,17.0724758 C73.923509,17.0724758 71.8739949,16.8159354 71.8181381,17.4232482 C71.7619233,18.0302026 73.1937903,20.5988311 73.9374731,20.785862 C74.680798,20.9725345 78.9416675,20.4203994 80.294046,17.7116769" id="Fill-154" fill="#1F191A"></path>
44
- <path d="M94.7082813,75.6808458 L100.201223,76.8281116 C100.313652,76.7091571 100.449355,76.5808869 100.613703,76.4418678 C106.021785,71.862837 111.178512,67.119348 111.178512,67.119348 L111.178512,70.2465609 C113.456465,67.263025 115.355954,64.1702085 116.904189,61.2568987 L113.182194,53.8505492 C113.182194,53.8505492 102.36424,53.9677122 100.094164,55.6234009 C97.824445,57.2787313 100.595801,60.469721 100.410685,62.0906549 C99.873243,66.7954479 98.0990742,68.495207 98.0990742,68.495207 C98.0990742,68.495207 99.141376,69.1168517 99.186133,71.0294391 C99.23089,72.9416681 97.5168747,73.5661791 94.7082813,75.6808458" id="Fill-156" fill="#98480C"></path>
45
- <path d="M41.3225575,68.7320053 C40.1828645,67.469368 38.6013299,59.9103841 38.6013299,59.9103841 C38.3517647,55.955506 39.2884399,55.7545016 38.5798465,55.100252 C37.8712532,54.4456441 34.6555499,56.6817733 34.6555499,56.6817733 L28.4719182,69.2784076 L36.5099233,74.718067 L31.6095652,75.5826367 C31.6729412,75.6456969 31.735601,75.7094737 31.7996931,75.7721756 C32.8820972,76.6890567 33.7518159,77.2526573 34.4002558,77.6016382 C36.4322251,77.7782784 46.7392327,78.5643812 44.5751407,76.1523283 C42.1772379,73.4801521 41.0565217,70.5345956 41.3225575,68.7320053" id="Fill-158" fill="#98480C"></path>
46
- <path d="M35.7649872,78.1532358 C35.7649872,78.1532358 40.873734,79.3065927 45.099156,79.6104282 C49.3249361,79.914622 55.3284655,73.2814767 69.0638619,73.2814767 L69.0638619,74.2209304 C69.0638619,74.2209304 58.0801279,76.5702814 48.5239642,81.1858584 C47.5575703,81.7383518 37.5058568,80.2886837 35.7649872,78.1532358" id="Fill-160" fill="#98480C"></path>
47
- <path d="M39.5202097,79.7762479 C39.5202097,79.7762479 40.3763223,82.7332699 41.895555,83.1481774 C40.6248133,83.8113844 37.0517698,81.6279248 36.5096726,78.4494755 C39.503023,79.3061627 39.5202097,79.7762479 39.5202097,79.7762479" id="Fill-162" fill="#98480C"></path>
48
- <path d="M66.0684706,45.7797028 C66.2947621,45.9380699 59.2184962,42.6288423 38.4469361,41.7442079 C35.2981893,41.9100993 37.1761944,40.6940405 39.2203376,40.1963665 C41.2644808,39.6986925 51.6499028,36.547832 52.9206445,35.884625 C54.1913862,35.2210596 55.9036113,34.9448129 54.578087,36.4926543 C53.2522046,38.0404957 45.6284706,40.4174355 44.523509,40.8043959 C43.4189054,41.1913562 61.0965013,42.2970596 66.0684706,45.7797028" id="Fill-164" fill="#98480C"></path>
49
- <path d="M30.8233811,67.6705874 C36.5096726,68.1127254 57.8924348,69.0525374 67.1732532,66.399351 C64.5218465,68.0575477 60.2677801,69.3291424 50.0477801,69.3291424 C39.8277801,69.3291424 31.5412839,68.7762907 30.8233811,67.6705874" id="Fill-166" fill="#98480C"></path>
50
- <path d="M102.362772,78.1532358 C102.362772,78.1532358 97.2540256,79.3065927 93.0286036,79.6104282 C88.8028235,79.914622 82.7992941,73.2814767 69.0638977,73.2814767 L69.0638977,74.2209304 C69.0638977,74.2209304 80.0476317,76.5702814 89.6037954,81.1858584 C90.5701893,81.7383518 100.621903,80.2886837 102.362772,78.1532358" id="Fill-168" fill="#98480C"></path>
51
- <path d="M98.6075499,79.7762479 C98.6075499,79.7762479 97.7514373,82.7332699 96.2322046,83.1481774 C97.5029463,83.8113844 101.07599,81.6279248 101.618087,78.4494755 C98.6247366,79.3061627 98.6075499,79.7762479 98.6075499,79.7762479" id="Fill-170" fill="#98480C"></path>
52
- <path d="M72.059289,45.7797028 C71.8329974,45.9380699 78.9092634,42.6288423 99.6808235,41.7442079 C102.829928,41.9100993 100.951565,40.6940405 98.907422,40.1963665 C96.8632788,39.6986925 86.4778568,36.547832 85.2071151,35.884625 C83.9363734,35.2210596 82.2241483,34.9448129 83.5496726,36.4926543 C84.875555,38.0404957 92.499289,40.4174355 93.6042506,40.8043959 C94.7088542,41.1913562 77.0312583,42.2970596 72.059289,45.7797028" id="Fill-172" fill="#98480C"></path>
53
- <path d="M107.304414,67.6705874 C101.618123,68.1127254 80.2353606,69.0525374 70.9541841,66.399351 C73.6059488,68.0575477 77.8600153,69.3291424 88.0800153,69.3291424 C98.3000153,69.3291424 106.586153,68.7762907 107.304414,67.6705874" id="Fill-174" fill="#98480C"></path>
54
- <path d="M69.2970997,45.2821363 C69.2970997,43.7894725 69.0640051,43.3473345 69.0640051,43.3473345 C69.0640051,43.3473345 68.8305524,43.7894725 68.8305524,45.2821363 C68.8305524,46.7748 68.1122916,62.6401744 68.0571509,63.3033815 C68.0020102,63.9669468 68.5788389,64.3539072 69.0640051,64.3539072 C69.5488133,64.3539072 70.1256419,63.9669468 70.0705013,63.3033815 C70.0153606,62.6401744 69.2970997,46.7748 69.2970997,45.2821363" id="Fill-176" fill="#98480C"></path>
55
- <path d="M93.986046,104.143571 L69.0638977,104.143571 L44.1417494,104.143571 L42.3571969,111.286214 C55.8394476,115.253991 65.4145882,130.614526 65.4145882,130.614526 C65.4145882,130.614526 66.9416982,131.919442 69.0638977,131.919442 C71.1860972,131.919442 72.7132072,130.614526 72.7132072,130.614526 C72.7132072,130.614526 82.2883478,115.253991 95.7702404,111.286214 L93.986046,104.143571 Z" id="Fill-178" fill="#1F191A"></path>
56
- <path d="M96.7585115,83.8684969 L95.9686394,84.5019653 C95.9686394,84.5019653 90.2730384,85.0311695 69.0639335,85.0311695 C47.8548286,85.0311695 42.1592276,84.5019653 42.1592276,84.5019653 L41.3693555,83.8684969 C41.3693555,83.8684969 40.0373862,84.4679272 40.4076164,86.8384176 C40.7015806,88.7241327 42.2261841,89.3593927 42.2261841,89.3593927 C42.2261841,89.3593927 42.8588696,98.5156628 42.7707877,99.2655777 C41.8455703,99.7062825 41.4048031,103.939199 44.1417852,104.143428 C52.4304297,104.480227 69.0639335,104.732826 69.0639335,104.732826 C69.0639335,104.732826 85.6970793,104.480227 93.9860818,104.143428 C96.7227059,103.939199 96.2822967,99.7062825 95.3567212,99.2655777 C95.2686394,98.5156628 95.9013248,89.3593927 95.9013248,89.3593927 C95.9013248,89.3593927 97.4259284,88.7241327 97.7202506,86.8384176 C98.0901228,84.4679272 96.7585115,83.8684969 96.7585115,83.8684969" id="Fill-180" fill="#FFBC00"></path>
57
- <path d="M97.7202864,86.8382385 C98.0901586,84.4681063 96.7585473,83.8683178 96.7585473,83.8683178 L95.9686752,84.5017862 C95.9686752,84.5017862 90.2730742,85.0309903 69.0639693,85.0309903 C47.8548645,85.0309903 42.1592634,84.5017862 42.1592634,84.5017862 L41.3693913,83.8683178 C41.3693913,83.8683178 40.037422,84.4681063 40.4076522,86.8382385 C40.7016164,88.7239536 42.2262199,89.3595718 42.2262199,89.3595718 C42.2262199,89.3595718 42.4038159,91.9317833 42.5577801,94.4609991 C45.7312327,93.6591313 47.6615141,93.0145557 47.6615141,93.0145557 C47.6615141,93.0145557 53.1952737,93.8920241 54.7030486,93.7666203 C56.2111816,93.6412164 58.7168593,94.3932811 62.7260153,94.3932811 C66.7348133,94.3932811 68.5587519,92.3875366 68.5587519,92.3875366 C68.5587519,92.3875366 70.914046,92.2266614 70.9545064,90.8654925 C70.9759898,90.1331342 71.0651458,89.4874837 71.1761432,88.9102678 C71.0533299,90.2700035 71.8961944,89.7744793 72.5739949,90.3961239 C73.2528696,91.0188435 73.7000818,92.7748552 77.0260665,93.1779389 C80.3520512,93.5813809 83.7786496,91.7662502 85.0887775,91.6652106 C86.3989054,91.5645292 91.640133,92.1696922 92.696757,92.1696922 C92.9681637,92.1696922 94.0430486,92.4563295 95.6679079,92.8902267 C95.7903632,90.967607 95.9013606,89.3595718 95.9013606,89.3595718 C95.9013606,89.3595718 97.4259642,88.7239536 97.7202864,86.8382385" id="Fill-182" fill="#FF9000"></path>
58
- <polygon id="Fill-184" fill="#98480C" points="70.36289 71.8627295 75.0011509 71.8627295 75.0011509 85.0161568 70.954399 85.0161568 70.0742967 78.0616194"></polygon>
59
- <path d="M71.5167621,76.4331254 C71.5751253,74.6670814 69.7175294,74.374353 69.7483223,73.2815483 C69.7791151,72.1883853 71.3585013,72.839052 71.2346138,71.1969786 C71.1107263,69.5549051 68.8710844,67.5366203 67.1735396,67.8641034 C66.80689,67.4789345 66.6210588,66.1464294 66.2186036,65.7745175 C65.8161483,65.4029639 64.1440256,65.3409786 63.3079642,65.6817186 C62.4719028,66.0224587 62.1005985,66.6423119 60.7378363,66.983052 C59.3757903,67.3237921 58.7255601,67.2929786 57.9202916,68.3463706 C57.1153811,69.3997627 54.7930281,74.9770079 51.9446905,75.1317921 C49.0959949,75.2865762 48.2910844,75.1317921 42.841468,74.7290667 C37.3918517,74.3263413 32.716711,73.5689022 31.5089872,73.2815483 C30.3016215,72.9938361 29.3105217,72.4051548 29.3105217,72.4051548 C29.3105217,72.4051548 23.7735396,74.049378 19.9262251,79.3206379 C17.4305729,82.7402209 16.7538465,88.1261357 16.5855601,91.4901827 C11.0596777,90.9860593 8.00581586,89.5378244 6.5137954,88.647099 C8.57870588,89.8817891 13.6409054,92.1906526 24.138757,91.5664999 C36.7924655,90.8144352 47.6616215,87.1787994 47.6616215,87.1787994 C47.6616215,87.1787994 53.1953811,88.0562678 54.703156,87.930864 C56.211289,87.8054602 58.7169668,88.5578831 62.7257647,88.5578831 C66.7349207,88.5578831 68.5588593,86.5517803 68.5588593,86.5517803 C68.5588593,86.5517803 70.9141535,86.3909051 70.9542558,85.0297363 C70.9947161,83.6685674 71.2654066,82.5986937 71.4823887,81.7316159 C71.6990128,80.8638214 70.8321586,80.8018361 70.6151765,79.1285909 C70.3985524,77.455704 71.458399,78.1991695 71.5167621,76.4331254" id="Fill-192" fill="#FF5B0C"></path>
60
- <path d="M18.2097391,67.119348 C18.2097391,67.119348 22.3531662,69.7255977 23.7144962,70.0810279 C25.0758261,70.4360999 29.3105575,72.4052981 29.3105575,72.4052981 C29.3105575,72.4052981 32.5617084,72.0025727 35.5342916,68.160558 C38.5068747,64.3185433 40.6741893,59.9806461 40.6741893,59.9806461 C40.6741893,59.9806461 40.9216061,61.3131512 41.7576675,63.0791953 C42.5937289,64.8452394 45.814087,67.8642467 45.814087,67.8642467 L48.4458005,51.4599941 L24.6125013,40.2589251 C24.6125013,40.2589251 15.0216061,40.4731865 11.3970026,53.8505492 C-0.254506394,61.8738855 3.60354987,65.5292276 2.24293606,69.1609222 C2.06140153,69.6446226 -0.416705882,78.6031131 0.460531969,83.2670602 C1.21209207,88.0564112 4.46932992,87.3039883 5.5968491,88.0564112 C4.99961125,67.1773921 18.2097391,67.119348 18.2097391,67.119348" id="Fill-196" fill="#9F5622"></path>
61
- <path d="M19.9262609,79.3206737 C23.7735754,74.0494138 29.3105575,72.4051906 29.3105575,72.4051906 C29.3105575,72.4051906 25.0758261,70.4363507 23.7144962,70.0809204 C22.3531662,69.7254902 18.2097391,67.1192405 18.2097391,67.1192405 C18.2097391,67.1192405 4.99961125,67.1772846 5.5968491,88.0563037 C5.64053197,88.0853257 5.6910179,88.1193639 5.74544246,88.1562684 C5.76262916,88.1677339 5.78089003,88.179916 5.79879284,88.1920981 C5.82493095,88.2096546 5.85214322,88.2279278 5.88042967,88.2469175 C5.89833248,88.2587413 5.91766752,88.2712816 5.93628645,88.283822 C6.04119693,88.3529733 6.16042967,88.4303653 6.29577494,88.5145651 C6.30938107,88.5231642 6.32298721,88.531405 6.33730946,88.5400041 C6.38421483,88.5690261 6.43291049,88.5987648 6.48375448,88.62922 C6.49342199,88.635311 6.50380563,88.6414021 6.5138312,88.6471348 C8.00585166,89.5378602 11.0597136,90.9860952 16.5855959,91.4902185 C16.7538824,88.1261715 17.4306087,82.7402567 19.9262609,79.3206737" id="Fill-206" fill="#FFAD00"></path>
62
- <path d="M120.61734,86.0000752 C120.437238,85.4146185 120.830384,82.7951119 120.109974,80.0928388 C118.219795,73.3371559 109.964092,71.469714 109.964092,71.469714 C108.012685,72.4600458 106.509207,72.8452147 104.303223,73.0150473 C102.097596,73.1845216 96.0457289,73.863852 91.973555,73.665714 C87.9013811,73.4675759 87.2507928,72.1092734 86.6571355,70.5248858 C86.0631202,68.9401398 84.5925831,66.5345363 83.5463427,65.9652029 C82.5001023,65.3958696 79.361023,64.1575965 78.2864962,63.3654026 C77.2119693,62.5728505 75.1474169,64.6670943 73.9880307,65.9652029 C72.9135038,65.6219548 71.3115601,66.4976317 70.4529412,67.864175 C69.5946803,69.2307184 71.5181586,71.1189416 71.5181586,71.1189416 C71.5181586,71.1189416 70.4529412,72.2224952 70.3684399,73.5524922 C70.2835806,74.8824893 71.6692583,75.2504599 71.7258312,76.12757 C71.7824041,77.0050385 70.6513043,77.4009562 70.5864962,78.701573 C70.522046,80.002548 71.8672634,80.3156993 71.838977,80.8581604 C71.8103325,81.4009797 71.3015345,81.7023072 71.1762148,83.0692088 C71.0508951,84.4361104 71.8955499,83.9380781 72.5740665,84.5604394 C73.2529412,85.1831589 73.7001535,86.9391706 77.0257801,87.3426126 C80.3517647,87.7460546 83.7787212,85.9305656 85.0888491,85.829526 C86.398977,85.7288446 91.6398465,86.3340076 92.6964706,86.3340076 C93.7534527,86.3340076 106.959284,90.6704717 117.541637,91.1749533 C118.268491,91.2097081 118.952737,91.2240399 119.604041,91.2236816 C120.32445,90.3411971 120.797442,86.5851736 120.61734,86.0000752" id="Fill-208" fill="#FF5B0C"></path>
63
- <path d="M120.61734,86.0000752 C120.437238,85.4146185 120.830384,82.7951119 120.109974,80.0928388 C118.219795,73.3371559 109.964092,71.469714 109.964092,71.469714 C108.012685,72.4600458 106.509207,72.8452147 104.303223,73.0150473 C102.097596,73.1845216 96.0457289,73.863852 91.973555,73.665714 C87.9013811,73.4675759 87.2507928,72.1092734 86.6571355,70.5248858 C86.0631202,68.9401398 84.5925831,66.5345363 83.5463427,65.9652029 C82.5001023,65.3958696 79.361023,64.1575965 78.2864962,63.3654026 C77.2119693,62.5728505 75.1474169,64.6670943 73.9880307,65.9652029 C72.9135038,65.6219548 71.3115601,66.4976317 70.4529412,67.864175 C69.5946803,69.2307184 71.5181586,71.1189416 71.5181586,71.1189416 C71.5181586,71.1189416 70.4529412,72.2224952 70.3684399,73.5524922 C70.2835806,74.8824893 71.6692583,75.2504599 71.7258312,76.12757 C71.7824041,77.0050385 70.6513043,77.4009562 70.5864962,78.701573 C70.522046,80.002548 71.8672634,80.3156993 71.838977,80.8581604 C71.8103325,81.4009797 71.3015345,81.7023072 71.1762148,83.0692088 C71.0508951,84.4361104 71.8955499,83.9380781 72.5740665,84.5604394 C73.2529412,85.1831589 73.7001535,86.9391706 77.0257801,87.3426126 C80.3517647,87.7460546 83.7787212,85.9305656 85.0888491,85.829526 C86.398977,85.7288446 91.6398465,86.3340076 92.6964706,86.3340076 C93.7534527,86.3340076 106.959284,90.6704717 117.541637,91.1749533 C118.268491,91.2097081 118.952737,91.2240399 119.604041,91.2236816 C120.32445,90.3411971 120.797442,86.5851736 120.61734,86.0000752" id="Fill-210" fill="#FF5B0C"></path>
64
- <g id="Group-222" stroke-width="1" fill="none" transform="translate(88.797954, 39.420869)">
65
- <mask id="mask-6" fill="white">
66
- <use xlink:href="#path-5"></use>
67
- </mask>
68
- <g id="Clip-221"></g>
69
- <path d="M49.9089258,32.9952493 C48.1451407,26.1080717 47.9159847,22.6809645 46.842532,20.1868617 C44.3651407,14.4297515 37.9154731,12.160659 36.5043734,9.44584552 C33.7831458,2.68872952 26.765601,0.342961527 26.765601,0.342961527 C20.9217647,-1.75199883 0.178132992,17.6623037 0.331381074,17.7755254 C0.484987212,17.8887471 6.62565217,26.4061744 6.62565217,26.4061744 C6.62565217,26.4061744 8.32248082,24.5953433 9.11414322,22.4727941 C9.90616368,20.3506032 10.1270844,18.0868852 10.1270844,18.0868852 C10.1270844,18.0868852 10.1324552,17.945358 11.5177749,20.4355195 C12.9034527,22.9256811 16.952711,30.9454344 21.1659591,32.048988 C21.1659591,32.048988 24.7687212,30.7526708 24.9037084,30.7075254 C25.0386957,30.6627383 26.7938875,30.1220687 27.5314834,29.7168352 C28.2687212,29.3116018 31.8346036,27.4197956 31.8346036,27.4197956 C31.8346036,27.4197956 36.6157289,26.2273844 41.9167519,36.0672846 C44.8836061,41.574662 43.616087,47.3636605 43.1348593,49.0738103 C44.080844,48.7230379 45.016087,48.4432082 46.079156,48.3249703 C50.6146547,47.8204887 51.017468,44.39159 51.1184399,43.8462626 C51.2190537,43.3009351 50.2734271,34.4176869 49.9089258,32.9952493" id="Fill-220" fill="#9F5622" mask="url(#mask-6)"></path>
70
- </g>
71
- <path d="M130.714598,75.4880464 C125.413575,65.6481463 120.632808,66.8405574 120.632808,66.8405574 C120.632808,66.8405574 117.066926,68.7323636 116.32933,69.1375971 C115.592092,69.5428305 113.836542,70.0835001 113.701555,70.1286455 C113.566568,70.1734326 109.963806,71.4697498 109.963806,71.4697498 C109.963806,71.4697498 118.219867,73.3371918 120.110046,80.0928746 C120.830455,82.7951477 120.437309,85.4146543 120.617412,86.000111 C120.797514,86.5852094 120.324164,90.3412329 119.604113,91.2237175 C126.214189,91.2212094 129.120174,89.5393651 131.932706,88.4949304 C132.413934,86.7844223 133.681453,80.9954238 130.714598,75.4880464" id="Fill-223" fill="#FFAD00"></path>
72
- <path d="M62.0177801,68.6410338 C61.1788542,68.6009046 61.4982404,69.1609222 61.4982404,69.1609222 C61.4982404,69.1609222 64.5349156,68.5210044 65.0941995,68.6808047 C65.5084706,68.7994009 66.930312,68.0688341 67.8462199,67.8491982 C67.6170639,67.8198179 67.3907724,67.822326 67.1734322,67.8642467 C67.1734322,67.8642467 62.8567059,68.6808047 62.0177801,68.6410338" id="Fill-225" fill="#E43500"></path>
73
- <path d="M69.5144041,79.6354015 C70.5277033,79.9553604 70.9018721,80.1954191 70.9541483,80.2953838 C70.8130742,80.0137627 70.6827417,79.649375 70.6154271,79.12877 C70.398445,77.4558831 71.4582916,78.1993486 71.5166547,76.4329463 C71.5750179,74.6669022 70.3275499,74.3945968 70.3583427,73.3014338 C70.3894936,72.2082708 71.6419744,72.7611225 71.518087,71.119049 C71.4539949,70.2720358 70.5427417,69.4056746 69.7177801,68.7320769 C69.9938414,69.460494 70.5201841,71.0778449 70.074046,71.8392253 C69.4889821,72.8388728 69.4492379,73.0388023 69.5688286,73.4784323 C69.6887775,73.9180623 70.8979335,75.0294984 71.1668338,75.397469 C71.4360921,75.7657979 71.2423836,77.6937921 70.7253504,78.0449228 C70.2079591,78.3960535 68.5011049,79.3154426 69.5144041,79.6354015" id="Fill-227" fill="#E43500"></path>
74
- <path d="M70.9543274,85.0296288 C70.9944297,83.6684599 71.2654783,82.5989445 71.4824604,81.7315084 C71.6317698,81.1338696 71.2669105,80.918175 70.9543274,80.2954555 C71.0066036,80.3954203 70.5676266,81.4344805 70.5676266,82.7537286 C70.5676266,84.0650943 71.0961176,85.0127888 70.6628696,85.7347565 C70.8322302,85.5452176 70.9460921,85.3151912 70.9543274,85.0296288" id="Fill-229" fill="#FF3500"></path>
75
- <path d="M84.2314476,85.592262 C82.9130844,85.6721621 79.7167161,86.4718802 78.1985575,86.1519213 C76.680399,85.8319624 75.2023427,84.3127847 75.2023427,84.3127847 C75.2023427,84.3127847 73.0446957,84.2730138 72.8449003,84.1931137 C72.6451049,84.1132135 71.2698107,83.1135659 71.5183018,82.6338068 C71.7664348,82.1540476 72.4127263,81.7495307 72.1259233,81.3038097 C71.8387621,80.858447 71.6296573,79.7953809 71.5183018,79.2357216 C71.4065882,78.675704 71.6464859,78.1959448 71.7664348,77.5563853 C71.8860256,76.9168258 72.3257187,75.9573075 71.9261279,75.4374191 C71.5265371,74.917889 70.5279182,73.798212 70.5676624,73.3188112 C70.6077647,72.8386937 72.6053606,71.1998449 72.6053606,71.1998449 C72.6053606,71.1998449 71.1419847,70.0987994 70.2371765,68.7225821 C70.2873043,69.9071107 71.5183018,71.1188699 71.5183018,71.1188699 C71.5183018,71.1188699 70.4530844,72.2227818 70.3682251,73.5524206 C70.2833657,74.8824176 71.6694015,75.2503883 71.7256164,76.1274984 C71.7574834,76.6208728 71.4137494,76.9623295 71.0950793,77.3976599 C71.0027008,77.6964793 70.8788133,77.9404793 70.7255652,78.0447436 C70.6507315,78.2371489 70.5988133,78.4524852 70.5866394,78.7018596 C70.5221893,80.0024764 71.8670486,80.3156276 71.8387621,80.858447 C71.8104757,81.4009081 71.3016777,81.7025938 71.1763581,83.0691372 C71.0510384,84.4360388 71.895335,83.9380065 72.5742097,84.560726 C73.2527263,85.1830872 73.6999386,86.939099 77.0259233,87.342541 C80.3519079,87.745983 83.7785064,85.930494 85.0889923,85.8298126 C85.2007059,85.8212135 85.3428542,85.8179888 85.5064859,85.8187054 C85.2379437,85.6764617 84.8301176,85.556074 84.2314476,85.592262" id="Fill-231" fill="#E43500"></path>
76
- <path d="M45.1709821,99.3815941 C46.4009054,99.526346 58.6414169,99.7434737 71.0423376,99.8158496 C83.4432583,99.8885838 93.7889361,99.5987219 93.7889361,99.5987219 C93.7889361,99.5987219 87.6393197,99.3815941 68.5395243,98.9473386 C49.4393708,98.5130831 45.1709821,99.3815941 45.1709821,99.3815941" id="Fill-233" fill="#F9D400"></path>
77
- <path d="M44.4475294,89.2460634 C44.4475294,89.2460634 62.4208798,90.0425568 70.0743325,89.6803189 C77.7274271,89.3184394 93.4994476,89.2460634 93.4994476,89.2460634 C93.4994476,89.2460634 84.6303939,89.1736875 70.3629258,89.2460634 C56.0954578,89.3184394 44.4475294,89.2460634 44.4475294,89.2460634" id="Fill-235" fill="#FF7E00"></path>
78
- <path d="M28.6531662,40.2588176 C26.7139335,40.2606091 26.462578,40.6927148 28.4719898,41.4390467 C30.4810435,42.1850203 35.3151611,47.8891025 40.4622199,48.6590819 C45.6092788,49.4294197 34.4056982,43.2129733 38.3457494,41.4630526 C44.1179744,38.8997985 32.8141381,41.1982714 32.2609412,41.0778837 C31.7077442,40.957496 29.5429361,40.258101 28.6531662,40.2588176" id="Fill-237" fill="#98480C"></path>
79
- <path d="M100.438578,45.1806667 C101.692133,45.8399325 103.048092,44.966047 106.193616,42.8198502 C109.339499,40.6736535 111.877402,40.2085844 109.267887,39.4575947 C106.658373,38.7062467 105.292389,41.8047959 99.719601,40.4343113 C94.1471714,39.064185 95.2553555,40.3515448 95.2553555,40.3515448 C95.2553555,40.3515448 102.118578,42.3193098 101.153616,43.5353686 C100.188297,44.7514273 98.3292685,44.0717386 100.438578,45.1806667" id="Fill-239" fill="#98480C"></path>
80
- </g>
81
- </g>
82
- </g>
83
- </g>
84
- </g>
85
- </svg>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/advanced-tools/model/auth-settings.php DELETED
@@ -1,171 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Author: Hoang Ngo
5
- */
6
-
7
- namespace WP_Defender\Module\Advanced_Tools\Model;
8
-
9
- use Hammer\Helper\WP_Helper;
10
-
11
- class Auth_Settings extends \Hammer\WP\Settings {
12
- private static $_instance;
13
- public $enabled = false;
14
- public $lost_phone = true;
15
- public $force_auth = false;
16
- public $force_auth_mess = "You are required to setup two-factor authentication to use this site.";
17
- public $user_roles = array();
18
- public $force_auth_roles = array();
19
- public $custom_graphic = false;
20
- public $custom_graphic_url = '';
21
- public $is_conflict = array();
22
- public $email_subject = '';
23
- public $email_sender = '';
24
- public $email_body = '';
25
-
26
- public function __construct( $id, $is_multi ) {
27
- //fetch the userRoles
28
- if ( ! function_exists( 'get_editable_roles' ) ) {
29
- include_once ABSPATH . 'wp-admin/includes/user.php';
30
- }
31
- $this->user_roles = array_keys( get_editable_roles() );
32
- //remove subscriber from the list
33
- unset( $this->user_roles[ array_search( 'subscriber', $this->user_roles ) ] );
34
- $this->custom_graphic_url = wp_defender()->getPluginUrl() . 'assets/img/2factor-disabled.svg';
35
- $this->email_subject = 'Your OTP code';
36
- $this->email_sender = 'admin';
37
- $this->email_body = 'Hi {{display_name}},
38
-
39
- Your temporary login passcode is <strong>{{passcode}}</strong>.
40
-
41
- Copy and paste the passcode into the input field on the login screen to complete logging in.
42
-
43
- Regards,
44
- Administrator';
45
- parent::__construct( $id, $is_multi );
46
- //have to force it here if it has not convert the new config
47
- $this->enabled = ! ! $this->enabled;
48
- $this->force_auth = ! ! $this->force_auth;
49
- $this->custom_graphic = ! ! $this->custom_graphic;
50
- if ( ! is_array( $this->user_roles ) ) {
51
- $this->user_roles = [];
52
- }
53
- $this->user_roles = array_values( $this->user_roles );
54
- if ( ! is_array( $this->force_auth_roles ) ) {
55
- $this->force_auth_roles = [];
56
- }
57
- $this->force_auth_roles = array_values( $this->force_auth_roles );
58
- }
59
-
60
- /**
61
- * @return Auth_Settings
62
- */
63
- public static function instance() {
64
- if ( is_null( self::$_instance ) ) {
65
- $class = new Auth_Settings( 'wd_2auth_settings', WP_Helper::is_network_activate( wp_defender()->plugin_slug ) );
66
- self::$_instance = $class;
67
- }
68
-
69
- return self::$_instance;
70
- }
71
-
72
- /**
73
- * @param $plugin
74
- *
75
- * @return bool|int
76
- */
77
- public function isConflict( $plugin ) {
78
- if ( in_array( $plugin, $this->is_conflict ) ) {
79
- return true;
80
- } elseif ( in_array( '!' . $plugin, $this->is_conflict ) ) {
81
- return false;
82
- }
83
-
84
- return 0;
85
- }
86
-
87
- /**
88
- * @param $plugin
89
- */
90
- public function markAsConflict( $plugin ) {
91
- if ( ! in_array( $plugin, $this->is_conflict ) ) {
92
- $this->is_conflict [] = $plugin;
93
- $this->save();
94
- }
95
- }
96
-
97
- /**
98
- * @param $plugin
99
- */
100
- public function markAsUnConflict( $plugin ) {
101
- if ( ( $i = array_search( $plugin, $this->is_conflict ) ) !== false ) {
102
- unset( $this->is_conflict[ $i ] );
103
- }
104
- if ( ! in_array( '!' . $plugin, $this->is_conflict ) ) {
105
- $this->is_conflict [] = '!' . $plugin;
106
- }
107
- $this->save();
108
- }
109
-
110
- public function events() {
111
- $that = $this;
112
-
113
- return array(
114
- self::EVENT_AFTER_DELETED => array(
115
- array(
116
- function () use ( $that ) {
117
- global $wpdb;
118
- $sql = "DELETE from " . $wpdb->usermeta . " WHERE meta_key IN ('defOTPLoginToken','defenderBackupCode','defenderAuthSecret','defenderAuthOn','defenderAuthEmail')";
119
- $wpdb->query( $sql );
120
- }
121
- )
122
- )
123
- );
124
- }
125
-
126
- /**
127
- * Email default body.
128
- */
129
- public function two_factor_opt_email_default_body() {
130
- $content = 'Hi {{display_name}},
131
-
132
- Your temporary login passcode is <strong>{{passcode}}</strong>.
133
-
134
- Copy and paste the passcode into the input field on the login screen to complete logging in.
135
-
136
- Regards,
137
- Administrator';
138
-
139
- return $content;
140
- }
141
-
142
- /**
143
- * Define labels for settings key, we will use it for HUB
144
- *
145
- * @param null $key
146
- *
147
- * @return array|mixed
148
- */
149
- public function labels( $key = null ) {
150
- $labels = [
151
- 'enabled' => __( 'Two Factor Authentication', "defender-security" ),
152
- 'user_roles' => __( "User Roles", "defender-security" ),
153
- 'lost_phone' => __( 'Lost Phone', "defender-security" ),
154
- 'force_auth' => __( "Force Authentication", "defender-security" ),
155
- 'force_auth_mess' => __( "Custom warning message", "defender-security" ),
156
- 'force_auth_roles' => __( "Force Authentication", "defender-security" ),
157
- 'custom_graphic' => __( "Custom Graphic", "defender-security" ),
158
- 'custom_graphic_url' => __( "Custom Graphic Image", "defender-security" ),
159
- 'email_subject' => __( "Subject", "defender-security" ),
160
- 'email_sender' => __( "Sender", "defender-security" ),
161
- 'email_body' => __( "Body", "defender-security" )
162
-
163
- ];
164
-
165
- if ( $key != null ) {
166
- return isset( $labels[ $key ] ) ? $labels[ $key ] : null;
167
- }
168
-
169
- return $labels;
170
- }
171
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/advanced-tools/model/mask-settings.php DELETED
@@ -1,153 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Advanced_Tools\Model;
7
-
8
- use Hammer\Helper\WP_Helper;
9
-
10
- class Mask_Settings extends \Hammer\WP\Settings {
11
- public $mask_url = '';
12
- public $redirect_traffic = false;
13
- public $redirect_traffic_url = '';
14
- public $enabled = false;
15
- public $otps = [];
16
- private static $_instance;
17
-
18
- public function __construct( $id, $is_multi ) {
19
- parent::__construct( $id, $is_multi );
20
- $this->enabled = ! ! $this->enabled;
21
- $this->redirect_traffic = ! ! $this->redirect_traffic;
22
- }
23
-
24
- /**
25
- * @return Mask_Settings
26
- */
27
- public static function instance() {
28
- if ( is_null( self::$_instance ) ) {
29
- $class = new Mask_Settings( 'wd_masking_login_settings',
30
- WP_Helper::is_network_activate( wp_defender()->plugin_slug ) );
31
- self::$_instance = $class;
32
- }
33
-
34
- return self::$_instance;
35
- }
36
-
37
- /**
38
- * @return bool
39
- */
40
- public function isEnabled() {
41
- return $this->enabled && ( strlen( trim( $this->mask_url ) ) > 0 );
42
- }
43
-
44
- public function isRedirect() {
45
- return $this->redirect_traffic && ( strlen( trim( $this->redirect_traffic_url ) ) > 0 );
46
- }
47
-
48
- /**
49
- * Return the attributes we will run an xss filters
50
- * @return array
51
- */
52
- public function filters() {
53
- return [
54
- 'mask_url',
55
- 'redirect_traffic_url'
56
- ];
57
- }
58
-
59
- public function events() {
60
- $that = $this;
61
-
62
- return array(
63
- self::EVENT_AFTER_VALIDATE => array(
64
- array(
65
- function () use ( $that ) {
66
- if ( empty( $this->mask_url ) ) {
67
- return;
68
- }
69
- $forbidden = [
70
- 'login',
71
- 'wp-admin',
72
- 'admin',
73
- 'dashboard'
74
- ];
75
-
76
- if ( in_array( $this->mask_url, $forbidden, true ) ) {
77
- $this->errors[] = __( 'A page already exists at this URL, please pick a unique page for your new login area.',
78
- 'wpdef' );
79
-
80
- return false;
81
- }
82
- $exits = get_page_by_path( $this->mask_url, OBJECT, [ 'post', 'page' ] );
83
- if ( is_object( $exits ) ) {
84
- $this->errors[] = __( 'A page already exists at this URL, please pick a unique page for your new login area.',
85
- 'wpdef' );
86
-
87
- return false;
88
- }
89
-
90
- if ( $this->mask_url === $this->redirect_traffic_url ) {
91
- $this->errors[] = __( 'Redirect URL must different from Login URL', 'wpdef' );
92
-
93
- return false;
94
- }
95
- }
96
- )
97
- )
98
- );
99
- }
100
-
101
- /**
102
- * Define labels for settings key, we will use it for HUB
103
- *
104
- * @param null $key
105
- *
106
- * @return array|mixed
107
- */
108
- public function labels( $key = null ) {
109
- $labels = [
110
- 'enabled' => __( 'Enable', "defender-security" ),
111
- 'mask_url' => __( "Masking URL", "defender-security" ),
112
- 'redirect_traffic' => __( 'Redirect traffic', "defender-security" ),
113
- 'redirect_traffic_url' => __( "Redirection URL", "defender-security" ),
114
- ];
115
-
116
- if ( $key != null ) {
117
- return isset( $labels[ $key ] ) ? $labels[ $key ] : null;
118
- }
119
-
120
- return $labels;
121
- }
122
-
123
- public function beforeValidate() {
124
- if ( $this->mask_url === $this->redirect_traffic_url && strlen( $this->redirect_traffic_url ) > 0 ) {
125
- $this->addError( 'redirect_traffic_url',
126
- __( "Redirect URL must different from Login URL", "defender-security" ) );
127
- }
128
- }
129
-
130
- /**
131
- * @return array
132
- */
133
- public function export_strings( $configs ) {
134
- $class = new Mask_Settings( 'wd_masking_login_settings',
135
- WP_Helper::is_network_activate( wp_defender()->plugin_slug ) );
136
- $class->import( $configs );
137
-
138
- return [
139
- $class->isEnabled() ? __( 'Active', "defender-security" ) : __( 'Inactive', "defender-security" )
140
- ];
141
- }
142
-
143
- public function format_hub_data() {
144
- return [
145
- 'enabled' => $this->enabled ? __( 'Active', "defender-security" ) : __( 'Inactivate',
146
- "defender-security" ),
147
- 'mask_url' => $this->mask_url,
148
- 'redirect_traffic' => $this->redirect_traffic ? __( 'Yes', "defender-security" ) : __( 'No',
149
- "defender-security" ),
150
- 'redirect_traffic_url' => $this->redirect_traffic_url
151
- ];
152
- }
153
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/advanced-tools/model/security-headers-settings.php DELETED
@@ -1,310 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Advanced_Tools\Model;
7
-
8
- use Hammer\Helper\WP_Helper;
9
- use WP_Defender\Module\Advanced_Tools\Component\Security_Headers\Sh_X_Frame;
10
- use WP_Defender\Module\Advanced_Tools\Component\Security_Headers\Sh_XSS_Protection;
11
- use WP_Defender\Module\Advanced_Tools\Component\Security_Headers\Sh_Content_Type_Options;
12
- use WP_Defender\Module\Advanced_Tools\Component\Security_Headers\Sh_Strict_Transport;
13
- use WP_Defender\Module\Advanced_Tools\Component\Security_Headers\Sh_Feature_Policy;
14
- use WP_Defender\Module\Advanced_Tools\Component\Security_Headers\Sh_Referrer_Policy;
15
-
16
- class Security_Headers_Settings extends \Hammer\WP\Settings {
17
- /**
18
- * @var bool
19
- */
20
- public $sh_xframe = false;
21
- /**
22
- * @var string
23
- */
24
- public $sh_xframe_mode = 'sameorigin';
25
- /**
26
- * @var string
27
- */
28
- public $sh_xframe_urls = '';
29
- /**
30
- * @var bool
31
- */
32
- public $sh_xss_protection = false;
33
- /**
34
- * @var string
35
- */
36
- public $sh_xss_protection_mode = 'sanitize';
37
- /**
38
- * @var bool
39
- */
40
- public $sh_content_type_options = false;
41
- /**
42
- * @var string
43
- */
44
- public $sh_content_type_options_mode = 'nosniff';
45
- /**
46
- * @var bool
47
- */
48
- public $sh_strict_transport = false;
49
- /**
50
- * @var int
51
- */
52
- public $hsts_preload = 0;
53
- /**
54
- * @var int
55
- */
56
- public $include_subdomain = 0;
57
- /**
58
- * @var string
59
- */
60
- public $hsts_cache_duration = '30 days';
61
- /**
62
- * @var bool
63
- */
64
- public $sh_referrer_policy = false;
65
- /**
66
- * @var string
67
- */
68
- public $sh_referrer_policy_mode = 'origin-when-cross-origin';
69
- /**
70
- * @var bool
71
- */
72
- public $sh_feature_policy = false;
73
- /**
74
- * @var string
75
- */
76
- public $sh_feature_policy_mode = 'self';
77
- /**
78
- * @var string
79
- */
80
- public $sh_feature_policy_urls = '';
81
- /**
82
- * Contains all the data generated by rules
83
- * @var array
84
- */
85
- public $data = array();
86
-
87
- private static $_instance;
88
-
89
- public function __construct( $id, $is_multi ) {
90
- parent::__construct( $id, $is_multi );
91
- }
92
-
93
- /**
94
- * @return Security_Headers_Settings
95
- */
96
- public static function instance() {
97
- if ( is_null( self::$_instance ) ) {
98
- $class = new Security_Headers_Settings( 'wd_security_headers_settings',
99
- WP_Helper::is_network_activate( "defender-security" ) );
100
- self::$_instance = $class;
101
- }
102
-
103
- return self::$_instance;
104
- }
105
-
106
- /**
107
- * Define labels for settings key, we will use it for HUB
108
- *
109
- * @param null $key
110
- *
111
- * @return string
112
- */
113
- public function labels( $key = null ) {
114
- $labels = array(
115
- 'sh_xframe' => __( 'X-Frame-Options', "defender-security" ),
116
- 'sh_xframe_urls' => __( 'Allow-from', "defender-security" ),
117
- 'sh_xss_protection' => __( 'X-XSS-Protection', "defender-security" ),
118
- 'sh_content_type_options' => __( 'X-Content-Type-Options', "defender-security" ),
119
- 'sh_strict_transport' => __( 'Strict Transport', "defender-security" ),
120
- 'hsts_preload' => __( 'HSTS Preload', "defender-security" ),
121
- 'include_subdomain' => __( 'Include Subdomains', "defender-security" ),
122
- 'hsts_cache_duration' => __( 'Browser caching', "defender-security" ),
123
- 'sh_referrer_policy' => __( 'Referrer Policy', "defender-security" ),
124
- 'sh_referrer_policy_mode' => __( 'Referrer Information', "defender-security" ),
125
- 'sh_feature_policy' => __( 'Feature-Policy', "defender-security" ),
126
- 'sh_feature_policy_urls' => __( 'Specific Origins', "defender-security" ),
127
- );
128
-
129
- if ( null !== $key ) {
130
- return isset( $labels[ $key ] ) ? $labels[ $key ] : null;
131
- }
132
- }
133
-
134
- /**
135
- * Get headers
136
- *
137
- * @return array
138
- */
139
- public function getHeaders() {
140
- return array(
141
- Sh_X_Frame::$rule_slug => new Sh_X_Frame(),
142
- Sh_XSS_Protection::$rule_slug => new Sh_XSS_Protection(),
143
- Sh_Content_Type_Options::$rule_slug => new Sh_Content_Type_Options(),
144
- Sh_Strict_Transport::$rule_slug => new Sh_Strict_Transport(),
145
- Sh_Referrer_Policy::$rule_slug => new Sh_Referrer_Policy(),
146
- Sh_Feature_Policy::$rule_slug => new Sh_Feature_Policy(),
147
- );
148
- }
149
-
150
- /**
151
- * Filter the security headers and return data as array
152
- *
153
- * @param bool $sort
154
- *
155
- * @return array
156
- */
157
- public function getHeadersAsArray( $sort = false ) {
158
- $headers = $this->getHeaders();
159
- $data = array();
160
- foreach ( $headers as $header ) {
161
- $data[ $header::$rule_slug ] = array(
162
- 'slug' => $header::$rule_slug,
163
- 'title' => $header->getTitle(),
164
- 'misc' => $header->getMiscData(),
165
- );
166
- }
167
-
168
- if ( $sort ) {
169
- ksort( $data );
170
- }
171
-
172
- return $data;
173
- }
174
-
175
- /**
176
- * @param $key
177
- *
178
- * @return mixed
179
- */
180
- public function getDataValues( $key ) {
181
- if ( is_array( $this->data ) && isset( $this->data[ $key ] ) ) {
182
- return $this->data[ $key ];
183
- }
184
-
185
- return null;
186
- }
187
-
188
- /**
189
- * @param $key
190
- * @param $value
191
- */
192
- public function setDataValues( $key, $value ) {
193
- if ( null === $value ) {
194
- unset( $this->data[ $key ] );
195
- } elseif ( is_array( $this->data ) ) {
196
- $this->data[ $key ] = $value;
197
- }
198
- $this->save();
199
- }
200
-
201
- public function afterValidate() {
202
- if ( true === $this->sh_xframe
203
- && ( empty( $this->sh_xframe_mode )
204
- || ! in_array( $this->sh_xframe_mode, array( 'sameorigin', 'allow-from', 'deny' ), true ) )
205
- ) {
206
- $this->addError( 'sh_xframe_mode', __( 'X-Frame-Options mode is invalid', "defender-security" ) );
207
-
208
- return false;
209
- }
210
-
211
- if ( true === $this->sh_xss_protection
212
- && ( empty( $this->sh_xss_protection_mode )
213
- || ! in_array( $this->sh_xss_protection_mode, array( 'sanitize', 'block', 'none' ), true ) )
214
- ) {
215
- $this->addError( 'sh_xss_protection_mode',
216
- __( 'X-XSS-Protection mode is invalid', "defender-security" ) );
217
-
218
- return false;
219
- }
220
-
221
- if ( true === $this->sh_referrer_policy
222
- && ( empty( $this->sh_referrer_policy_mode )
223
- || ! in_array(
224
- $this->sh_referrer_policy_mode,
225
- array(
226
- 'no-referrer',
227
- 'no-referrer-when-downgrade',
228
- 'origin',
229
- 'origin-when-cross-origin',
230
- 'same-origin',
231
- 'strict-origin',
232
- 'strict-origin-when-cross-origin',
233
- 'unsafe-url',
234
- ),
235
- true
236
- )
237
- )
238
- ) {
239
- $this->addError( 'sh_referrer_policy_mode',
240
- __( 'Referrer Policy mode is invalid', "defender-security" ) );
241
-
242
- return false;
243
- }
244
- }
245
-
246
- /**
247
- * Refresh headers
248
- */
249
- public function refreshHeaders() {
250
- $defined_headers = $this->getHeaders();
251
- $enabled = [];
252
- foreach ( $defined_headers as $header ) {
253
- $status = $header->check();
254
- if ( $status == true ) {
255
- $enabled[] = $header;
256
- }
257
- }
258
- wp_defender()->global['security_headers_enabled'] = $enabled;
259
- }
260
-
261
- /**
262
- * @return bool
263
- */
264
- public function is_any_activated() {
265
- if ( $this->sh_xframe === true || $this->sh_xss_protection === true || $this->sh_content_type_options === true ||
266
- $this->sh_feature_policy === true || $this->sh_strict_transport === true || $this->sh_referrer_policy === true ) {
267
- return true;
268
- }
269
-
270
- return false;
271
- }
272
-
273
- /**
274
- * @return array
275
- */
276
- public function export_strings( $configs ) {
277
- $class = new Security_Headers_Settings( 'wd_security_headers_settings',
278
- WP_Helper::is_network_activate( "defender-security" ) );
279
- $class->import( $configs );
280
-
281
- return [
282
- $class->is_any_activated() ? __( 'Active', "defender-security" ) : __( 'Inactive', "defender-security" )
283
- ];
284
- }
285
-
286
- public function format_hub_data() {
287
- return [
288
- 'sh_xframe' => $this->sh_xframe ? sprintf( __( 'Mode: %s%s',
289
- "defender-security" ), $this->sh_xframe_mode,
290
- $this->sh_xframe_mode == 'allow-from' ? ',urls: ' . $this->sh_xframe_urls : '' ) : __( 'Inactivate',
291
- "defender-security" ),
292
- 'sh_xss_protection' => $this->sh_xss_protection ? sprintf( __( 'Mode: %s',
293
- "defender-security" ), $this->sh_xss_protection_mode ) : __( 'Inactivate',
294
- "defender-security" ),
295
- 'sh_content_type_options' => $this->sh_content_type_options ? sprintf( __( 'Mode: %s',
296
- "defender-security" ), 'nosniff' ) : __( 'Inactivate',
297
- "defender-security" ),
298
- 'sh_strict_transport' => $this->sh_strict_transport ? sprintf( __( 'Enabled%s',
299
- "defender-security" ), $this->hsts_preload ? ',HSTS preloaded, ' : '' ) : __( 'Inactivate',
300
- "defender-security" ),
301
- 'sh_referrer_policy' => $this->sh_referrer_policy ? sprintf( __( 'Mode: %s',
302
- "defender-security" ), $this->sh_referrer_policy_mode ) : __( 'Inactivate',
303
- "defender-security" ),
304
- 'sh_feature_policy' => $this->sh_feature_policy ? sprintf( __( 'Mode: %s%s',
305
- "defender-security" ), $this->sh_feature_policy_mode,
306
- $this->sh_feature_policy_mode == 'origins' ? ',urls: ' . $this->sh_feature_policy_urls : '' ) : __( 'Inactivate',
307
- "defender-security" ),
308
- ];
309
- }
310
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/advanced-tools/view/login/disabled.php DELETED
@@ -1,156 +0,0 @@
1
- <h2><?php _e( "Security", "defender-security" ) ?></h2>
2
- <table class="form-table" id="defender-security">
3
- <tbody>
4
- <tr class="user-sessions-wrap hide-if-no-js">
5
- <th><?php _e( "Two Factor Authentication", "defender-security" ) ?></th>
6
- <td aria-live="assertive">
7
- <?php
8
- $settings = \WP_Defender\Module\Advanced_Tools\Model\Auth_Settings::instance();
9
- $force_auth_for_curr_user = false;
10
- $user = wp_get_current_user();
11
- if ( $user->ID && isset( $settings->force_auth_roles ) && ! empty( $settings->force_auth_roles ) ) {
12
- $curr_user_roles = (array) $user->roles;
13
- if ( ! empty( array_intersect( $curr_user_roles, $settings->force_auth_roles ) ) ) {
14
- $force_auth_for_curr_user = true;
15
- }
16
- }
17
- if ( $force_auth_for_curr_user && $settings->force_auth ):
18
- ?>
19
- <div class="def-warning">
20
- <i class="dashicons dashicons-warning" aria-hidden="true"></i>
21
- <?php
22
- echo $settings->force_auth_mess
23
- ?>
24
- </div>
25
- <?php endif; ?>
26
- <?php
27
- $email = '';
28
- if ( is_object( $user ) ) {
29
- $email = $user->user_email;
30
- }
31
- ?>
32
- <div id="def2">
33
- <div class="destroy-sessions">
34
- <button type="button" class="button" id="show2AuthActivator">
35
- <?php _e( "Enable", "defender-security" ) ?>
36
- </button>
37
- </div>
38
- <p class="description">
39
- <?php _e( "Use the Google Authenticator app to sign in with a separate passcode.", "defender-security" ) ?>
40
- </p>
41
- </div>
42
- <div id="def2qr">
43
- <button type="button" id="hide2AuthActivator"
44
- class="button"><?php _e( "Cancel", "defender-security" ) ?></button>
45
- <p><?php _e( "Use the Google Authenticator app to sign in with a separate passcode.", "defender-security" ) ?></p>
46
- <div class="card">
47
- <p>
48
- <strong><?php _e( "1. Install the Verification app", "defender-security" ) ?></strong>
49
- </p>
50
- <p>
51
- <?php _e( "Download and install the Google Authenticator app on your device using the links below.", "defender-security" ) ?>
52
- </p>
53
- <a href="https://itunes.apple.com/vn/app/google-authenticator/id388497605?mt=8">
54
- <img src="<?php echo wp_defender()->getPluginUrl() . 'assets/img/ios-download.svg' ?>"/>
55
- </a>
56
- <a href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2">
57
- <img src="<?php echo wp_defender()->getPluginUrl() . 'assets/img/android-download.svg' ?>"/>
58
- </a>
59
- <div class="line"></div>
60
- <p><strong><?php _e( "2. Scan the barcode", "defender-security" ) ?></strong></p>
61
- <p><?php _e( "Open the Google Authenticator app you just downloaded, tap the \"+\" symbol and then use your phone's camera to scan the barcode below.", "defender-security" ) ?></p>
62
- <?php echo \WP_Defender\Module\Advanced_Tools\Component\Auth_API::generateQRCode( urlencode( get_bloginfo( 'name' ) ), $email, $secretKey, 149, 149, urlencode( get_bloginfo( 'name' ) ) ) ?>
63
- <div class="line"></div>
64
- <p><strong><?php _e( "3. Enter passcode", "defender-security" ) ?></strong></p>
65
- <p>
66
- <?php _e( "Enter the 6 digit passcode that is shown on your device into the input field below and hit \"Verify\".", "defender-security" ) ?>
67
- </p>
68
- <div class="well">
69
- <p class="error"></p>
70
- <input type="text" id="otpCode" class="def-small-text">
71
- <button type="button" class="button button-primary" id="verifyOTP">
72
- <?php _e( "Verify", "defender-security" ) ?>
73
- </button>
74
- <input type="hidden" id="defNonce" value="<?php echo wp_create_nonce( 'defVerifyOTP' ) ?>"/>
75
- </div>
76
- </div>
77
- </div>
78
- </td>
79
- </tr>
80
- </tbody>
81
- </table>
82
- <script type="text/javascript">
83
- jQuery(function ($) {
84
- $('#def2qr').hide();
85
- $('#show2AuthActivator').click(function () {
86
- $('#def2').hide();
87
- $('#def2qr').show();
88
- });
89
- $('#hide2AuthActivator').click(function () {
90
- $('#def2qr').hide();
91
- $('#def2').show();
92
- })
93
- $("input#otpCode").keydown(function (event) {
94
- if (event.keyCode == 13) {
95
- event.preventDefault();
96
-
97
- var data = {
98
- action: 'defVerifyOTP',
99
- otp: $('#otpCode').val(),
100
- nonce: $('#defNonce').val()
101
- }
102
- var that = $(this).next('#verifyOTP');
103
- var parent = that.closest('.well');
104
- $.ajax({
105
- type: 'POST',
106
- url: ajaxurl,
107
- data: data,
108
- beforeSend: function () {
109
- that.attr('disabled', 'disabled');
110
- },
111
- success: function (data) {
112
- if (data.success == true) {
113
- location.reload();
114
- } else {
115
- that.removeAttr('disabled');
116
- parent.find('.error').text(data.data.message);
117
- }
118
- }
119
- })
120
- }
121
- });
122
- $('#verifyOTP').click(function () {
123
- var data = {
124
- action: 'defVerifyOTP',
125
- otp: $('#otpCode').val(),
126
- nonce: $('#defNonce').val()
127
- }
128
- var that = $(this);
129
- var parent = that.closest('.well');
130
- $.ajax({
131
- type: 'POST',
132
- url: ajaxurl,
133
- data: data,
134
- beforeSend: function () {
135
- that.attr('disabled', 'disabled');
136
- },
137
- success: function (data) {
138
- if (data.success == true) {
139
- location.reload();
140
- } else {
141
- that.removeAttr('disabled');
142
- parent.find('.error').text(data.data.message);
143
- }
144
- }
145
- })
146
- });
147
- })
148
- </script>
149
- <?php if ( $force_auth_for_curr_user && $settings->force_auth ): ?>
150
- <script type="text/javascript">
151
- jQuery(function ($) {
152
- $('html, body').animate({scrollTop: $("#show2AuthActivator").offset().top}, 1000);
153
- });
154
- </script>
155
- <?php endif; ?>
156
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/advanced-tools/view/login/enabled.php DELETED
@@ -1,50 +0,0 @@
1
- <h2><?php _e( "Security", "defender-security" ) ?></h2>
2
- <table class="form-table">
3
- <tbody>
4
- <tr class="user-sessions-wrap hide-if-no-js">
5
- <th><?php _e( "Two Factor Authentication", "defender-security" ) ?></th>
6
- <td aria-live="assertive">
7
- <div class="def-notification">
8
- <?php _e( "Two factor authentication is active.", "defender-security" ) ?>
9
- </div>
10
- <button type="button" class="button" id="disableOTP">
11
- <?php _e( "Disable", "defender-security" ) ?>
12
- </button>
13
- </td>
14
- </tr>
15
- <tr class="user-sessions-wrap hide-if-no-js">
16
- <th><?php _e( "Fallback email address", "defender-security" ) ?></th>
17
- <td aria-live="assertive">
18
- <input type="text" class="regular-text" name="def_backup_email" value="<?php echo $email ?>"/>
19
- <p class="description">
20
- <?php _e( "If you ever lose your device, you can send a fallback passcode to this email address.", "defender-security" ) ?>
21
- </p>
22
- </td>
23
- </tr>
24
- </tbody>
25
- </table>
26
- <script type="text/javascript">
27
- jQuery(function ($) {
28
- $('#disableOTP').click(function () {
29
- var data = {
30
- action: 'defDisableOTP'
31
- }
32
- var that = $(this);
33
- $.ajax({
34
- type: 'POST',
35
- url: ajaxurl,
36
- data: data,
37
- beforeSend: function () {
38
- that.attr('disabled', 'disabled');
39
- },
40
- success: function (data) {
41
- if (data.success == true) {
42
- location.reload();
43
- } else {
44
- that.removeAttr('disabled');
45
- }
46
- }
47
- })
48
- })
49
- })
50
- </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/advanced-tools/view/login/otp.php DELETED
@@ -1,331 +0,0 @@
1
- <?php
2
- if ( ! function_exists( 'login_header' ) ) {
3
- //copy from wp-login
4
- /**
5
- * Output the login page header.
6
- *
7
- * @param string $title Optional. WordPress login Page title to display in the `<title>` element.
8
- * Default 'Log In'.
9
- * @param string $message Optional. Message to display in header. Default empty.
10
- * @param WP_Error $wp_error Optional. The error to pass. Default empty.
11
- */
12
- function login_header( $title = 'Log In', $message = '', $wp_error = '' ) {
13
- global $error, $interim_login, $action;
14
-
15
- if ( empty( $wp_error ) ) {
16
- $wp_error = new WP_Error();
17
- }
18
-
19
- // Shake it!
20
- $shake_error_codes = array(
21
- 'empty_password',
22
- 'empty_email',
23
- 'invalid_email',
24
- 'invalidcombo',
25
- 'empty_username',
26
- 'invalid_username',
27
- 'incorrect_password'
28
- );
29
- /**
30
- * Filters the error codes array for shaking the login form.
31
- *
32
- * @since 3.0.0
33
- *
34
- * @param array $shake_error_codes Error codes that shake the login form.
35
- */
36
- $shake_error_codes = apply_filters( 'shake_error_codes', $shake_error_codes );
37
-
38
- if ( $shake_error_codes && $wp_error->get_error_code() && in_array( $wp_error->get_error_code(), $shake_error_codes ) ) {
39
- add_action( 'login_head', 'wp_shake_js', 12 );
40
- }
41
-
42
- $separator = is_rtl() ? ' &rsaquo; ' : ' &lsaquo; ';
43
-
44
- ?><!DOCTYPE html>
45
- <!--[if IE 8]>
46
- <html xmlns="http://www.w3.org/1999/xhtml" class="ie8" <?php language_attributes(); ?>>
47
- <![endif]-->
48
- <!--[if !(IE 8) ]><!-->
49
- <html xmlns="http://www.w3.org/1999/xhtml" <?php language_attributes(); ?>>
50
- <!--<![endif]-->
51
- <head>
52
- <meta http-equiv="Content-Type"
53
- content="<?php bloginfo( 'html_type' ); ?>; charset=<?php bloginfo( 'charset' ); ?>"/>
54
- <title><?php echo get_bloginfo( 'name', 'display' ) . $separator . $title; ?></title>
55
- <?php
56
-
57
- wp_enqueue_style( 'login' );
58
-
59
- /*
60
- * Remove all stored post data on logging out.
61
- * This could be added by add_action('login_head'...) like wp_shake_js(),
62
- * but maybe better if it's not removable by plugins
63
- */
64
- if ( 'loggedout' == $wp_error->get_error_code() ) {
65
- ?>
66
- <script>if ("sessionStorage" in window) {
67
- try {
68
- for (var key in sessionStorage) {
69
- if (key.indexOf("wp-autosave-") != -1) {
70
- sessionStorage.removeItem(key)
71
- }
72
- }
73
- } catch (e) {
74
- }
75
- }
76
- ;</script>
77
- <?php
78
- }
79
-
80
- /**
81
- * Enqueue scripts and styles for the login page.
82
- *
83
- * @since 3.1.0
84
- */
85
- do_action( 'login_enqueue_scripts' );
86
-
87
- /**
88
- * Fires in the login page header after scripts are enqueued.
89
- *
90
- * @since 2.1.0
91
- */
92
- do_action( 'login_head' );
93
-
94
- if ( is_multisite() ) {
95
- $login_header_url = network_home_url();
96
- $login_header_title = get_network()->site_name;
97
- } else {
98
- $login_header_url = __( 'https://wordpress.org/' );
99
- $login_header_title = __( 'Powered by WordPress' );
100
- }
101
-
102
- /**
103
- * Filters link URL of the header logo above login form.
104
- *
105
- * @since 2.1.0
106
- *
107
- * @param string $login_header_url Login header logo URL.
108
- */
109
- $login_header_url = apply_filters( 'login_headerurl', $login_header_url );
110
-
111
- /**
112
- * Filters the title attribute of the header logo above login form.
113
- *
114
- * @since 2.1.0
115
- *
116
- * @param string $login_header_title Login header logo title attribute.
117
- */
118
- $login_header_title = apply_filters( 'login_headertitle', $login_header_title );
119
-
120
- $classes = array( 'login-action-' . $action, 'wp-core-ui' );
121
- if ( is_rtl() ) {
122
- $classes[] = 'rtl';
123
- }
124
- if ( $interim_login ) {
125
- $classes[] = 'interim-login';
126
- ?>
127
- <style type="text/css">html {
128
- background-color: transparent;
129
- }</style>
130
- <?php
131
-
132
- if ( 'success' === $interim_login ) {
133
- $classes[] = 'interim-login-success';
134
- }
135
- }
136
- $classes[] = ' locale-' . sanitize_html_class( strtolower( str_replace( '_', '-', get_locale() ) ) );
137
-
138
- /**
139
- * Filters the login page body classes.
140
- *
141
- * @since 3.5.0
142
- *
143
- * @param array $classes An array of body classes.
144
- * @param string $action The action that brought the visitor to the login page.
145
- */
146
- $classes = apply_filters( 'login_body_class', $classes, $action );
147
-
148
- ?>
149
- </head>
150
- <body class="login <?php echo esc_attr( implode( ' ', $classes ) ); ?>">
151
- <?php
152
- /**
153
- * Fires in the login page header after the body tag is opened.
154
- *
155
- * @since 4.6.0
156
- */
157
- do_action( 'login_header' );
158
- ?>
159
- <div id="login">
160
-
161
- <h1><a href="<?php echo esc_url( $login_header_url ); ?>" title="<?php echo esc_attr( $login_header_title ); ?>"
162
- tabindex="-1"><?php bloginfo( 'name' ); ?></a></h1>
163
- <?php
164
-
165
- unset( $login_header_url, $login_header_title );
166
-
167
- /**
168
- * Filters the message to display above the login form.
169
- *
170
- * @since 2.1.0
171
- *
172
- * @param string $message Login message text.
173
- */
174
- $message = apply_filters( 'login_message', $message );
175
- if ( ! empty( $message ) ) {
176
- echo $message . "\n";
177
- }
178
-
179
- // In case a plugin uses $error rather than the $wp_errors object
180
- if ( ! empty( $error ) ) {
181
- $wp_error->add( 'error', $error );
182
- unset( $error );
183
- }
184
-
185
- if ( $wp_error->get_error_code() ) {
186
- $errors = '';
187
- $messages = '';
188
- foreach ( $wp_error->get_error_codes() as $code ) {
189
- $severity = $wp_error->get_error_data( $code );
190
- foreach ( $wp_error->get_error_messages( $code ) as $error_message ) {
191
- if ( 'message' == $severity ) {
192
- $messages .= ' ' . $error_message . "<br />\n";
193
- } else {
194
- $errors .= ' ' . $error_message . "<br />\n";
195
- }
196
- }
197
- }
198
- if ( ! empty( $errors ) ) {
199
- /**
200
- * Filters the error messages displayed above the login form.
201
- *
202
- * @since 2.1.0
203
- *
204
- * @param string $errors Login error message.
205
- */
206
- echo '<div id="login_error">' . apply_filters( 'login_errors', $errors ) . "</div>\n";
207
- }
208
- if ( ! empty( $messages ) ) {
209
- /**
210
- * Filters instructional messages displayed above the login form.
211
- *
212
- * @since 2.5.0
213
- *
214
- * @param string $messages Login messages.
215
- */
216
- echo '<p class="message">' . apply_filters( 'login_messages', $messages ) . "</p>\n";
217
- }
218
- }
219
- }
220
- }
221
- login_header( '', '', $error );
222
- ?>
223
- <form method="post"
224
- action="<?php echo esc_url( add_query_arg( 'action', 'defenderVerifyOTP', site_url( 'wp-login.php', 'login_post' ) ) ); ?>">
225
- <p><?php _e( "Open the Google Authenticator app and enter the 6 digit passcode.", "defender-security" ) ?></p>
226
- <input type="text" autofocus value="" autocomplete="off" name="otp">
227
- <button class="button button-primary float-r"
228
- type="submit"><?php _e( "Authenticate", "defender-security" ) ?></button>
229
- <input type="hidden" name="login_token" value="<?php echo $loginToken ?>"/>
230
- <input type="hidden" name="redirect_to" value="<?php echo $redirect_to ?>"/>
231
- <?php wp_nonce_field( 'DefOtpCheck' ) ?>
232
- </form>
233
- <?php
234
- $settings = \WP_Defender\Module\Advanced_Tools\Model\Auth_Settings::instance();
235
-
236
- if ( wp_defender()->isFree == false && $settings->custom_graphic ) {
237
- ?>
238
- <style type="text/css">
239
- body.login div#login h1 a {
240
- background-image: url("<?php echo $settings->custom_graphic_url ?>");
241
- }
242
- </style>
243
- <?php
244
- }
245
- ?>
246
- <?php if ( \WP_Defender\Module\Advanced_Tools\Model\Auth_Settings::instance()->lost_phone ): ?>
247
- <p id="nav">
248
- <a id="lostPhone"
249
- href="<?php echo admin_url( 'admin-ajax.php?action=defRetrieveOTP&token=' . $loginToken . '&nonce=' . wp_create_nonce( 'defRetrieveOTP' ) ) ?>">
250
- <?php _e( "Lost your device?", "defender-security" ) ?></a>
251
- <img class="def-ajaxloader"
252
- src="<?php echo wp_defender()->getPluginUrl() . 'app/module/advanced-tools/img/spinner.svg' ?>"/>
253
- <strong class="notification">
254
-
255
- </strong>
256
- </p>
257
- <script type="text/javascript">
258
- jQuery(function ($) {
259
- $('.def-ajaxloader').hide();
260
- var isSent = false;
261
- $('#lostPhone').click(function (e) {
262
- e.preventDefault();
263
- var that = $(this);
264
- if (isSent == false) {
265
- isSent = true;
266
- $.ajax({
267
- type: 'GET',
268
- url: that.attr('href'),
269
- beforeSend: function () {
270
- that.attr('disabled', 'disabled');
271
- $('.def-ajaxloader').show();
272
- },
273
- success: function (data) {
274
- that.removeAttr('disabled');
275
- $('.def-ajaxloader').hide();
276
- $('.notification').text(data.data.message);
277
- isSent = false;
278
- }
279
- })
280
- }
281
-
282
- })
283
- })
284
- </script>
285
- <?php endif; ?>
286
- <?php
287
- if ( ! function_exists( 'login_footer' ) ) {
288
- //copy from wp login
289
- /**
290
- * Outputs the footer for the login page.
291
- *
292
- * @param string $input_id Which input to auto-focus
293
- */
294
- function login_footer( $input_id = '' ) {
295
- global $interim_login;
296
-
297
- // Don't allow interim logins to navigate away from the page.
298
- if ( ! $interim_login ): ?>
299
- <p id="backtoblog"><a href="<?php echo esc_url( home_url( '/' ) ); ?>"><?php
300
- /* translators: %s: site title */
301
- printf( _x( '&larr; Back to %s', 'site' ), get_bloginfo( 'title', 'display' ) );
302
- ?></a></p>
303
- <?php endif; ?>
304
-
305
- </div>
306
-
307
- <?php if ( ! empty( $input_id ) ) : ?>
308
- <script type="text/javascript">
309
- try {
310
- document.getElementById('<?php echo $input_id; ?>').focus();
311
- } catch (e) {
312
- }
313
- if (typeof wpOnload == 'function') wpOnload();
314
- </script>
315
- <?php endif; ?>
316
-
317
- <?php
318
- /**
319
- * Fires in the login page footer.
320
- *
321
- * @since 3.1.0
322
- */
323
- do_action( 'login_footer' ); ?>
324
- <div class="clear"></div>
325
- </body>
326
- </html>
327
- <?php
328
- }
329
- }
330
- login_footer();
331
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/advanced-tools/view/main-free.php DELETED
@@ -1,269 +0,0 @@
1
- <div class="sui-box">
2
- <div class="sui-box-header">
3
- <h3 class="sui-box-title">
4
- <?php _e( "Two-Factor Authentication", "defender-security" ) ?>
5
- </h3>
6
- </div>
7
- <form method="post" id="advanced-settings-frm" class="advanced-settings-frm">
8
- <div class="sui-box-body sui-upsell-items">
9
- <div class="padding-30 no-padding-bottom">
10
- <p>
11
- <?php _e( "Configure your two-factor authentication settings. Our recommendations are enabled by default.", "defender-security" ) ?>
12
- </p>
13
- <?php
14
- $enabledRoles = $settings->user_roles;
15
- $allRoles = get_editable_roles();
16
- ?>
17
- <?php if ( isset( wp_defender()->global['compatibility'] ) ): ?>
18
- <div class="sui-notice sui-notice-error">
19
- <p>
20
- <?php echo implode( '<br/>', array_unique( wp_defender()->global['compatibility'] ) ); ?>
21
- </p>
22
- </div>
23
- <?php endif; ?>
24
- <?php
25
- if ( count( $enabledRoles ) ):
26
- ?>
27
- <div class="sui-notice sui-notice-info no-margin-bottom">
28
- <p>
29
- <?php
30
- printf( __( "<strong>Two-factor authentication is now active.</strong> User roles with this feature enabled must visit their <a href='%s'>Profile page</a> to complete setup and sync their account with the Authenticator app.", "defender-security" ),
31
- admin_url( 'profile.php' ) );
32
- ?>
33
- </p>
34
- </div>
35
- <?php else: ?>
36
- <div class="sui-notice sui-notice-warning no-margin-bottom">
37
- <p>
38
- <?php
39
- _e( "<strong>Two-factor authentication is currently inactive.</strong> Configure and save your settings to complete setup.", "defender-security" )
40
- ?>
41
- </p>
42
- </div>
43
- <?php endif; ?>
44
- </div>
45
- <div class="sui-box-settings-row">
46
- <div class="sui-box-settings-col-1">
47
- <span class="sui-settings-label">
48
- <?php esc_html_e( "User Roles", "defender-security" ) ?>
49
- </span>
50
- <span class="sui-description">
51
- <?php esc_html_e( "Choose the user roles you want to enable two-factor authentication for. Users with those roles will then be required to use the Google Authenticator app to login.", "defender-security" ) ?>
52
- </span>
53
- </div>
54
-
55
- <div class="sui-box-settings-col-2">
56
- <div class="sui-field-list">
57
- <div class="sui-field-list-header">
58
- <h3 class="sui-field-list-title"><?php _e( "User role", "defender-security" ) ?></h3>
59
- </div>
60
- <div class="sui-field-list-body">
61
- <?php
62
- foreach ( $allRoles as $role => $detail ):
63
- ?>
64
- <div class="sui-field-list-item">
65
- <label class="sui-field-list-item-label"
66
- for="toggle_<?php echo esc_attr( $role ) ?>_role">
67
- <?php echo $detail['name'] ?>
68
- </label>
69
- <label class="sui-toggle">
70
- <input type="checkbox" <?php echo in_array( $role, $enabledRoles ) ? 'checked="checked"' : null ?>
71
- name="userRoles[]" value="<?php echo esc_attr( $role ) ?>"
72
- id="toggle_<?php echo esc_attr( $role ) ?>_role"/>
73
- <span class="sui-toggle-slider"></span>
74
- </label>
75
- </div>
76
- <?php endforeach; ?>
77
- </div>
78
- </div>
79
- </div>
80
- </div>
81
- <div class="sui-box-settings-row">
82
- <div class="sui-box-settings-col-1">
83
- <span class="sui-settings-label">
84
- <?php _e( "Lost Phone", "defender-security" ) ?>
85
- </span>
86
- <span class="sui-description">
87
- <?php _e( "If a user is unable to access their phone, you can allow an option to send the one time password to their registered email.", "defender-security" ) ?>
88
- </span>
89
- </div>
90
- <div class="sui-box-settings-col-2">
91
- <div class="sui-form-field">
92
- <input type="hidden" name="lostPhone" value="0"/>
93
- <label class="sui-toggle">
94
- <input role="presentation" type="checkbox" name="lostPhone" class="toggle-checkbox"
95
- id="lostPhone" value="1"
96
- <?php checked( true, $settings->lost_phone ) ?>/>
97
- <span class="sui-toggle-slider"></span>
98
- </label>
99
- <label for="lostPhone" class="sui-toggle-label">
100
- <?php _e( "Enable lost phone option", "defender-security" ) ?>
101
- </label>
102
- </div>
103
- </div>
104
- </div>
105
- <div class="sui-box-settings-row">
106
- <div class="sui-box-settings-col-1">
107
- <span class="sui-settings-label">
108
- <?php _e( "Force Authentication", "defender-security" ) ?>
109
- </span>
110
- <span class="sui-description">
111
- <?php _e( "By default, two-factor authentication is optional for users. This setting forces users to activate two-factor.", "defender-security" ) ?>
112
- </span>
113
- </div>
114
- <div class="sui-box-settings-col-2">
115
- <div class="sui-form-field">
116
- <input type="hidden" name="forceAuth" value="0"/>
117
- <label class="sui-toggle">
118
- <input role="presentation" type="checkbox" name="forceAuth" class="toggle-checkbox"
119
- id="forceAuth" value="1"
120
- <?php checked( true, $settings->force_auth ) ?>/>
121
- <span class="sui-toggle-slider"></span>
122
- </label>
123
- <label for="forceAuth" class="sui-toggle-label">
124
- <?php _e( "Force users to log in with two-factor authentication", "defender-security" ) ?>
125
- </label>
126
- <span class="sui-description sui-toggle-content">
127
- <?php _e( "Note: Users will be forced to set up two-factor when they next login.", "defender-security" ) ?>
128
- </span>
129
- <div id="forceAuthRoles" class="sui-border-frame sui-toggle-content"
130
- aria-hidden="<?php echo ! $settings->force_auth ?>">
131
- <strong><?php _e( "User Roles", "defender-security" ) ?></strong>
132
- <ul>
133
- <?php
134
- $forceAuthRoles = $settings->force_auth_roles;
135
- foreach ( $allRoles as $role => $detail ):
136
- ?>
137
- <li>
138
- <label for="forceAuth<?php echo esc_attr( $role ) ?>" class="sui-checkbox">
139
- <input id="forceAuth<?php echo esc_attr( $role ) ?>" type="checkbox"
140
- name="forceAuthRoles[]"
141
- value="<?php echo esc_attr( $role ) ?>" <?php echo in_array( $role, $forceAuthRoles ) ? 'checked="checked"' : null ?> />
142
- <span aria-hidden="true"></span>
143
- <span><?php echo $detail['name'] ?></span>
144
- </label>
145
- </li>
146
- <?php endforeach; ?>
147
- </ul>
148
- <strong><?php _e( "Custom warning message", "defender-security" ) ?></strong>
149
- <textarea class="sui-form-control"
150
- name="forceAuthMess"><?php echo $settings->force_auth_mess ?></textarea>
151
- <span class="sui-description">
152
- <?php _e( "Note: This is shown in the users Profile area indicating they must use two-factor authentication.", "defender-security" ) ?>
153
- </span>
154
- </div>
155
- </div>
156
- </div>
157
- </div>
158
- <div class="sui-box-settings-row sui-disabled">
159
- <div class="sui-box-settings-col-1">
160
- <span class="sui-settings-label">
161
- <?php _e( "Custom Graphic", "defender-security" ) ?>
162
- </span>
163
- <span class="sui-description">
164
- <?php _e( "By default, Defender’s icon appears above the login fields. You can upload your own branding, or turn this feature off.", "defender-security" ) ?>
165
- </span>
166
- </div>
167
- <div class="sui-box-settings-col-2">
168
- <label class="sui-toggle">
169
- <input role="presentation" type="checkbox" name="customGraphic" class="toggle-checkbox"
170
- id="customGraphic" value="0"/>
171
- <span class="sui-toggle-slider"></span>
172
- </label>
173
- <label for="customGraphic" class="sui-toggle-label">
174
- <?php _e( "Enable custom graphics above login fields", "defender-security" ) ?>
175
- </label>
176
- </div>
177
- </div>
178
- <div class="sui-box-settings-row">
179
- <div class="sui-box-settings-col-1">
180
- <span class="sui-settings-label">
181
- <?php _e( "Emails", "defender-security" ) ?>
182
- </span>
183
- <span class="sui-description">
184
- <?php _e( 'Customize the default copy for emails the two-factor feature sends to users.', "defender-security" ); ?>
185
- </span>
186
- </div>
187
- <div class="sui-box-settings-col-2">
188
- <div class="sui-field-list">
189
- <div class="sui-field-list-header">
190
- <h3 class="sui-field-list-title"><?php _e( "Email", "defender-security" ) ?></h3>
191
- </div>
192
- <div class="sui-field-list-body">
193
- <div class="sui-field-list-item">
194
- <label class="sui-field-list-item-label" for="demo-table-2-toggle-5">
195
- <?php _e( "Lost phone one time password", "defender-security" ) ?>
196
- </label>
197
- <button type="button" class="sui-button-icon"
198
- data-a11y-dialog-show="edit-one-time-password-email">
199
- <i class="sui-icon-pencil" aria-hidden="true"></i>
200
- </button>
201
- </div>
202
- </div>
203
- </div>
204
- </div>
205
- </div>
206
- <div class="sui-box-settings-row">
207
- <div class="sui-box-settings-col-1">
208
- <span class="sui-settings-label">
209
- <?php _e( "App Download", "defender-security" ) ?>
210
- </span>
211
- <span class="sui-description">
212
- <?php _e( 'Need the app? Here’s links to the official Google Authenticator apps.', "defender-security" ); ?>
213
- </span>
214
- </div>
215
- <div class="sui-box-settings-col-2">
216
- <a href="https://itunes.apple.com/vn/app/google-authenticator/id388497605?mt=8">
217
- <img src="<?php echo wp_defender()->getPluginUrl() . 'assets/img/ios-download.svg' ?>"/>
218
- </a>
219
- <a href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2">
220
- <img src="<?php echo wp_defender()->getPluginUrl() . 'assets/img/android-download.svg' ?>"/>
221
- </a>
222
- </div>
223
- </div>
224
- <div class="sui-box-settings-row">
225
- <div class="sui-box-settings-col-1">
226
- <span class="sui-settings-label">
227
- <?php _e( "Active Users", "defender-security" ) ?>
228
- </span>
229
- <span class="sui-description">
230
- <?php _e( "Here’s a quick link to see which of your users have enabled two-factor verification.", "defender-security" ) ?>
231
- </span>
232
- </div>
233
- <div class="sui-box-settings-col-2">
234
- <?php printf( __( "<a href=\"%s\">View users</a> who have enabled this feature.", "defender-security" ), network_admin_url( 'users.php' ) ) ?>
235
- </div>
236
- </div>
237
- <div class="sui-box-settings-row">
238
- <div class="sui-box-settings-col-1">
239
- <span class="sui-settings-label">
240
- <?php _e( "Deactivate", "defender-security" ) ?>
241
- </span>
242
- <span class="sui-description">
243
- <?php _e( "Disable two-factor authentication on your website.", "defender-security" ) ?>
244
- </span>
245
- </div>
246
- <div class="sui-box-settings-col-2">
247
- <button type="button" class="sui-button sui-button-ghost deactivate-2factor">
248
- <?php _e( "Deactivate", "defender-security" ) ?>
249
- </button>
250
- </div>
251
- </div>
252
- </div>
253
- <div class="sui-box-footer">
254
- <input type="hidden" name="action" value="saveAdvancedSettings"/>
255
- <?php wp_nonce_field( 'saveAdvancedSettings' ) ?>
256
- <div class="sui-actions-right">
257
- <button type="submit" class="sui-button sui-button-blue">
258
- <i class="sui-icon-save" aria-hidden="true"></i>
259
- <?php _e( "Save Changes", "defender-security" ) ?></button>
260
- </div>
261
- </div>
262
- </form>
263
- <?php
264
- $view = '2factor-otp-email-edit-from';
265
- $settings = array( 'settings' => $settings );
266
- $controller->renderPartial( $view, $settings );
267
- ?>
268
- </div>
269
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/advanced-tools/view/mask-login/enabled.php DELETED
@@ -1,116 +0,0 @@
1
- <div class="sui-box">
2
- <div class="sui-box-header">
3
- <h3 class="sui-box-title">
4
- <?php _e( "Mask Login Area", "defender-security" ) ?>
5
- </h3>
6
- </div>
7
- <form method="post" id="ad-mask-settings-frm" class="advanced-settings-frm">
8
- <div class="sui-box-body">
9
- <p>
10
- <?php _e( "Change your default WordPress login URL to hide your login area from hackers and bots.", "defender-security" ) ?>
11
- </p>
12
- <?php if ( isset( wp_defender()->global['compatibility'] ) ): ?>
13
- <div class="sui-notice sui-notice-error">
14
- <p>
15
- <?php echo implode( '<br/>', array_unique( wp_defender()->global['compatibility'] ) ); ?>
16
- </p>
17
- </div>
18
- <?php else: ?>
19
- <?php if ( strlen( trim( $settings->maskUrl ) ) == 0 ): ?>
20
- <div class="sui-notice sui-notice-warning">
21
- <p>
22
- <?php _e( "Masking is currently inactive. Choose your URL and save your settings to finish setup. ", "defender-security" ) ?>
23
- </p>
24
- </div>
25
- <?php else: ?>
26
- <div class="sui-notice sui-notice-info">
27
- <p>
28
- <?php printf( __( "Masking is currently active at <strong>%s</strong>", "defender-security" ), \WP_Defender\Module\Advanced_Tools\Component\Mask_Api::getNewLoginUrl() ) ?>
29
- </p>
30
- </div>
31
- <?php endif; ?>
32
- <?php endif; ?>
33
- <div class="sui-box-settings-row">
34
- <div class="sui-box-settings-col-1">
35
- <span class="sui-settings-label">
36
- <?php _e( "Masking URL", "defender-security" ) ?>
37
- </span>
38
- <span class="sui-description">
39
- <?php _e( 'Choose the new URL slug where users of your website will now navigate to log in or register.', "defender-security" ) ?>
40
- </span>
41
- </div>
42
-
43
- <div class="sui-box-settings-col-2">
44
- <span class="sui-description">
45
- <?php _e( "You can specify any URLs. For security reasons, less obvious URLs are recommended as they are harder for bots to guess.", "defender-security" ) ?>
46
- </span>
47
- <div class="sui-form-field">
48
- <label class="sui-label"><?php _e( 'New Login URL', "defender-security" ) ?></label>
49
- <input type="text" class="sui-form-control" name="maskUrl"
50
- value="<?php echo $settings->maskUrl ?>"
51
- placeholder="<?php _e( 'I.e. dashboard', "defender-security" ); ?>"/>
52
- <span class="sui-description">
53
- <?php printf( __( "Users will login at <a href='%s'>%s</a>. Note: Registration and Password Reset emails have hardcoded URLs in them. We will update them automatically to match your new login URL.", "defender-security" ), get_site_url() . '/' . $settings->maskUrl,get_site_url() . '/' . $settings->maskUrl ) ?>
54
- </span>
55
- </div>
56
- </div>
57
- </div>
58
- <div class="sui-box-settings-row">
59
- <div class="sui-box-settings-col-1">
60
- <span class="sui-settings-label">
61
- <?php _e( "Redirect traffic", "defender-security" ) ?>
62
- </span>
63
- <span class="sui-description">
64
- <?php _e( 'With this feature you can send visitors and bots who try to visit the default Wordpress login URLs to a separate URL to avoid 404s.', "defender-security" ) ?>
65
- </span>
66
- </div>
67
-
68
- <div class="sui-box-settings-col-2">
69
- <input type="hidden" name="redirectTraffic" value="0"/>
70
- <label class="sui-toggle">
71
- <input role="presentation" type="checkbox" name="redirectTraffic" class="toggle-checkbox"
72
- id="redirectTraffic" value="1"
73
- <?php checked( true, $settings->redirectTraffic ) ?>/>
74
- <span class="sui-toggle-slider"></span>
75
- </label>
76
- <label for="redirectTraffic" class="sui-toggle-label">
77
- <?php _e( "Enable 404 redirection", "defender-security" ) ?>
78
- </label>
79
- <div id="redirectTrafficContainer" class="sui-border-frame sui-toggle-content"
80
- aria-hidden="<?php echo (bool)! $settings->redirectTraffic ?>">
81
- <label class="sui-label"><?php _e( "Redirection URL", "defender-security" ) ?></label>
82
- <input type="text" class="sui-form-control" name="redirectTrafficUrl"
83
- value="<?php echo $settings->redirectTrafficUrl ?>"/>
84
- <span class="sui-description">
85
- <?php printf( __( "Visitors who visit the default login URLs will be redirected to <a href='%s'>%s</a>", "defender-security" ), get_site_url() . '/' . $settings->redirectTrafficUrl,get_site_url() . '/' . $settings->redirectTrafficUrl ) ?>
86
- </span>
87
- </div>
88
- </div>
89
- </div>
90
- <div class="sui-box-settings-row">
91
- <div class="sui-box-settings-col-1">
92
- <span class="sui-settings-label">
93
- <?php _e( "Deactivate", "defender-security" ) ?>
94
- </span>
95
- <span class="sui-description">
96
- <?php _e( "Disable login area masking and return to the default wp-admin and wp-login URLS.", "defender-security" ) ?>
97
- </span>
98
- </div>
99
- <div class="sui-box-settings-col-2">
100
- <button type="button" class="sui-button sui-button-ghost deactivate-atmasking">
101
- <?php _e( "Deactivate", "defender-security" ) ?>
102
- </button>
103
- </div>
104
- </div>
105
- </div>
106
- <div class="sui-box-footer">
107
- <input type="hidden" name="action" value="saveATMaskLoginSettings"/>
108
- <?php wp_nonce_field( 'saveATMaskLoginSettings' ) ?>
109
- <div class="sui-actions-right">
110
- <button type="submit" class="sui-button sui-button-blue">
111
- <i class="sui-icon-save" aria-hidden="true"></i>
112
- <?php _e( "Save Changes", "defender-security" ) ?></button>
113
- </div>
114
- </div>
115
- </form>
116
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/audit.php DELETED
@@ -1,25 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module;
7
-
8
- use Hammer\Base\Module;
9
- use WP_Defender\Module\Audit\Controller\Main;
10
- use WP_Defender\Module\Audit\Controller\Main_Free;
11
- use WP_Defender\Module\Audit\Controller\Rest;
12
-
13
- class Audit extends Module {
14
- public function __construct() {
15
- if ( file_exists( __DIR__ . '/audit/test' ) ) {
16
- @unlink( __DIR__ . '/audit/test' );
17
- }
18
- if ( wp_defender()->isFree ) {
19
- new Main_Free();
20
- } else {
21
- new Main();
22
- new Rest();
23
- }
24
- }
25
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/audit/controller/main-free.php DELETED
@@ -1,79 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Audit\Controller;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use Hammer\Helper\Log_Helper;
10
- use Hammer\Helper\WP_Helper;
11
- use WP_Defender\Behavior\Utils;
12
- use WP_Defender\Module\Audit\Component\Audit_API;
13
- use WP_Defender\Module\Audit\Model\Settings;
14
-
15
- class Main_Free extends \WP_Defender\Controller {
16
- protected $slug = 'wdf-logging';
17
-
18
- /**
19
- * Declaring behaviors
20
- * @return array
21
- */
22
- /**
23
- * @return array
24
- */
25
- public function behaviors() {
26
- $behaviors = [
27
- 'utils' => '\WP_Defender\Behavior\Utils',
28
- 'endpoints' => '\WP_Defender\Behavior\Endpoint',
29
- 'wpmudev' => '\WP_Defender\Behavior\WPMUDEV'
30
- ];
31
-
32
- return $behaviors;
33
- }
34
-
35
- public function __construct() {
36
- if ( $this->isNetworkActivate( wp_defender()->plugin_slug ) ) {
37
- $this->addAction( 'network_admin_menu', 'adminMenu' );
38
- } else {
39
- $this->addAction( 'admin_menu', 'adminMenu' );
40
- }
41
-
42
- if ( $this->isInPage() || $this->isDashboard() ) {
43
- $this->addAction( 'defender_enqueue_assets', 'scripts', 11 );
44
- }
45
- }
46
-
47
- /**
48
- * Add submit admin page
49
- */
50
- public function adminMenu() {
51
- $cap = is_multisite() ? 'manage_network_options' : 'manage_options';
52
- add_submenu_page( 'wp-defender', esc_html__( "Audit Logging", "defender-security" ), esc_html__( "Audit Logging", "defender-security" ), $cap, $this->slug, array(
53
- &$this,
54
- 'actionIndex'
55
- ) );
56
- }
57
-
58
- public function scripts() {
59
- if ( $this->isInPage() ) {
60
- wp_enqueue_style( 'wpmudev-sui' );
61
- wp_enqueue_style( 'defender' );
62
-
63
- wp_register_script( 'defender-audit', wp_defender()->getPluginUrl() . 'assets/app/audit.js', array(
64
- 'def-vue',
65
- 'defender',
66
- 'wp-i18n'
67
- ), wp_defender()->version, true );
68
- Utils::instance()->createTranslationJson( 'defender-audit' );
69
- wp_set_script_translations( 'defender-audit', 'wpdef', wp_defender()->getPluginPath() . 'languages' );
70
- wp_localize_script( 'defender-audit', 'auditData', [] );
71
- wp_enqueue_script( 'defender-audit' );
72
- wp_enqueue_script( 'wpmudev-sui' );
73
- }
74
- }
75
-
76
- public function actionIndex() {
77
- $this->renderPartial( 'main-free' );
78
- }
79
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/audit/view/main-free.php DELETED
@@ -1 +0,0 @@
1
- <div id="defender"></div>
 
app/module/hardener.php DELETED
@@ -1,60 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module;
7
-
8
- use Hammer\Base\Module;
9
- use Hammer\Helper\HTTP_Helper;
10
-
11
- use WP_Defender\Module\Hardener\Controller\Main;
12
- use WP_Defender\Module\Hardener\Controller\Rest;
13
- use WP_Defender\Module\Hardener\Model\Settings;
14
-
15
- class Hardener extends Module {
16
- const Settings = 'hardener_settings';
17
-
18
- public function __construct() {
19
- //init dependency
20
- $this->initRulesStats();
21
- //call the controller
22
- new Main();
23
- new Rest();
24
- }
25
-
26
- /**
27
- * Init rules status
28
- */
29
- public function initRulesStats() {
30
- $settings = Settings::instance( true );
31
- /**
32
- * now we have a list of rules, and lists of their status
33
- */
34
- if ( ! defined( 'DOING_AJAX' ) ) {
35
- //only init when page load
36
- $interval = '+0 seconds';
37
- //only refresh if on admin, if not we just do the listening
38
-
39
- if ( ( ( is_admin() || is_network_admin() )
40
- ) && ( HTTP_Helper::retrieveGet( 'page' ) == 'wdf-hardener'
41
- || HTTP_Helper::retrieveGet( 'page' ) == 'wp-defender'
42
- || HTTP_Helper::retrieveGet( 'page' ) == 'wdf-setting' )
43
- ) {
44
- //this mean we dont have any data, or data is overdue need to refresh
45
- //refetch those list
46
- $settings->refreshStatus();
47
- } elseif ( defined( 'DOING_CRON' ) ) {
48
- //if this is in cronjob, we refresh it too
49
- $settings->refreshStatus();
50
- }
51
- $settings->save();
52
- }
53
-
54
- //we will need to add every hooks needed
55
- foreach ( $settings->getDefinedRules( true ) as $rule ) {
56
- $rule->addHooks();
57
- }
58
- }
59
-
60
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/change-admin-service.php DELETED
@@ -1,117 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use WP_Defender\Component\Error_Code;
9
- use WP_Defender\Module\Hardener\IRule_Service;
10
- use WP_Defender\Module\Hardener\Rule_Service;
11
-
12
- class Change_Admin_Service extends Rule_Service implements IRule_Service {
13
- /**
14
- * @var null
15
- */
16
- protected $username;
17
-
18
- /**
19
- * @return mixed
20
- */
21
- public function getUsername() {
22
- return $this->username;
23
- }
24
-
25
- /**
26
- * @param mixed $username
27
- */
28
- public function setUsername( $username ) {
29
- $this->username = $username;
30
- }
31
-
32
- public function __construct( $username = null ) {
33
- $this->username = $username;
34
- }
35
-
36
- /**
37
- * @return bool
38
- */
39
- public function check() {
40
- $user = get_user_by( 'login', 'admin' );
41
-
42
- return ( ! is_object( $user ) );
43
- }
44
-
45
- /**
46
- * @return bool|\WP_Error
47
- */
48
- public function process() {
49
- if ( is_wp_error( ( $error = $this->validate() ) ) ) {
50
- return $error;
51
- }
52
-
53
- $admin_data = get_user_by( 'login', 'admin' );
54
-
55
- //create new admin account
56
- global $wpdb;
57
- $wpdb->update( $wpdb->users, array(
58
- 'ID' => $admin_data->ID,
59
- 'user_login' => trim( $this->username )
60
- ), array(
61
- 'ID' => $admin_data->ID
62
- ) );
63
-
64
- if ( is_multisite() ) {
65
- $site_admins = get_site_option( 'site_admins' );
66
- if ( is_array( $site_admins ) ) {
67
- //replace the admin
68
- $a_key = array_search( strtolower( 'admin' ), array_map( 'strtolower', $site_admins ) );
69
- if ( isset( $site_admins[ $a_key ] ) ) {
70
- $site_admins[ $a_key ] = $this->username;
71
- //reupdate
72
- update_site_option( 'site_admins', $site_admins );
73
- }
74
- }
75
- }
76
- clean_user_cache( $admin_data->ID );
77
- $this->store( 'fixed', Change_Admin::$slug );
78
-
79
- return true;
80
- }
81
-
82
- /**
83
- * @param null $username
84
- *
85
- * @return bool|\WP_Error
86
- */
87
- public function validate( $username = null ) {
88
- if ( is_null( $username ) ) {
89
- $username = $this->username;
90
- }
91
- if ( strlen( $username ) == 0 ) {
92
- return new \WP_Error( Error_Code::VALIDATE, __( "The username can't be empty!", "defender-security" ) );
93
- }
94
- if ( strtolower( $username ) == 'admin' ) {
95
- return new \WP_Error( Error_Code::VALIDATE, __( "You can't use admin as a username again!", "defender-security" ) );
96
- }
97
-
98
- if ( ! validate_username( $username ) ) {
99
- return new \WP_Error( Error_Code::VALIDATE, __( "The username is invalid!", "defender-security" ) );
100
- }
101
-
102
- //now check if the username unique
103
- if ( username_exists( $username ) ) {
104
- return new \WP_Error( Error_Code::VALIDATE, __( "The username already exists!", "defender-security" ) );
105
- }
106
-
107
- return true;
108
- }
109
-
110
- public function revert() {
111
-
112
- }
113
-
114
- public function listen() {
115
-
116
- }
117
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/change-admin.php DELETED
@@ -1,86 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use WP_Defender\Module\Hardener\Model\Settings;
10
- use WP_Defender\Module\Hardener\Rule;
11
-
12
- class Change_Admin extends Rule {
13
- static $slug = 'replace-admin-username';
14
- static $service;
15
-
16
- public function getDescription() {
17
- $this->renderPartial( 'rules/change-admin' );
18
- }
19
-
20
- /**
21
- * This will return the short summary why this rule show up as issue
22
- *
23
- * @return string
24
- */
25
- function getErrorReason() {
26
- return __( "You have a user account with the admin username.", "defender-security" );
27
- }
28
-
29
- /**
30
- * This will return a short summary to show why this rule works
31
- * @return mixed
32
- */
33
- function getSuccessReason() {
34
- return __( "You don't have a user account sporting the admin username, great.", "defender-security" );
35
- }
36
-
37
- public function check() {
38
- return $this->getService()->check();
39
- }
40
-
41
- public function addHooks() {
42
- $this->addAction( 'processingHardener' . self::$slug, 'process' );
43
- }
44
-
45
- public function revert() {
46
-
47
- }
48
-
49
- /**
50
- * @return string
51
- */
52
- public function getTitle() {
53
- return __( "Change default admin user account", "defender-security" );
54
- }
55
-
56
- /**
57
- *
58
- */
59
- public function process() {
60
- $username = HTTP_Helper::retrievePost( 'username' );
61
- $this->getService()->setUsername( $username );
62
- $ret = $this->getService()->process();
63
- if ( is_wp_error( $ret ) ) {
64
- wp_send_json_error( array(
65
- 'message' => $ret->get_error_message()
66
- ) );
67
- } else {
68
- wp_send_json_success( array(
69
- 'message' => sprintf( __( "Your admin name has changed. You will need to <a href='%s'><strong>%s</strong></a>.<br/>This will auto reload after <span class='hardener-timer'>5</span> seconds.", "defender-security" ), wp_login_url( network_admin_url( 'admin.php?page=wdf-hardener' ) ), "re-login" ),
70
- 'reload' => 5,
71
- 'url' => wp_login_url( network_admin_url( 'admin.php?page=wdf-hardener' ) )
72
- ) );
73
- }
74
- }
75
-
76
- /**
77
- * @return Change_Admin_Service
78
- */
79
- public function getService() {
80
- if ( self::$service == null ) {
81
- self::$service = new Change_Admin_Service();
82
- }
83
-
84
- return self::$service;
85
- }
86
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/db-prefix-service.php DELETED
@@ -1,262 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Faker\Factory;
9
- use Hammer\Helper\Log_Helper;
10
- use Hammer\Helper\WP_Helper;
11
- use WP_Defender\Behavior\Utils;
12
- use WP_Defender\Component\Error_Code;
13
- use WP_Defender\Module\Hardener\IRule_Service;
14
- use WP_Defender\Module\Hardener\Model\Settings;
15
- use WP_Defender\Module\Hardener\Rule_Service;
16
-
17
- class DB_Prefix_Service extends Rule_Service implements IRule_Service {
18
- public $new_prefix;
19
- protected $old_prefix;
20
-
21
- /**
22
- * @return bool
23
- */
24
- public function check() {
25
- global $wpdb;
26
-
27
- return $wpdb->prefix != 'wp_';
28
- }
29
-
30
- public function process() {
31
- $config_path = $this->retrieveWPConfigPath();
32
- if ( ! is_writeable( $config_path ) ) {
33
- return new \WP_Error( Error_Code::NOT_WRITEABLE,
34
- sprintf( __( "The file %s is not writable", "defender-security" ), $config_path ) );
35
- }
36
-
37
- $hook_line = $this->findDefaultHookLine( file( $config_path ) );
38
- if ( $hook_line === false ) {
39
- return new \WP_Error( Error_Code::UNKNOWN_WPCONFIG, __( "Your wp-config.php was modified by a 3rd party, this will cause conflict with Defender. Please revert it to original for updating your database prefix", "defender-security" ) );
40
- }
41
-
42
- if ( ! Utils::instance()->isActivatedSingle() ) {
43
- //validate if this network is too big, then we will prevent it
44
- $sites = get_sites( array(
45
- 'count' => true
46
- ) );
47
-
48
- if ( $sites >= 100 ) {
49
- return new \WP_Error( Error_Code::VALIDATE, __( "Unfortunately it's not safe to do this via a plugin for larger WordPress Multisite installs. You can ignore this step, or follow a tutorial online on how to use a scalable tool like WP-CLI.", "defender-security" ) );
50
- }
51
- }
52
- if ( is_wp_error( $is_valid = $this->validatePrefix() ) ) {
53
- return $is_valid;
54
- }
55
-
56
- //mark this here
57
- Settings::instance()->is_prefix_changed = true;
58
- Settings::instance()->save();
59
-
60
- $prefix = $this->new_prefix;
61
- set_time_limit( - 1 );
62
- //add trailing underscore if not present
63
- if ( substr( $prefix, - 1 ) != '_' ) {
64
- $this->new_prefix .= '_';
65
- }
66
-
67
- global $wpdb;
68
- $wpdb->query( 'BEGIN' );
69
- //run a query to change db prefix
70
- if ( is_wp_error( ( $err = $this->changeDBPrefix() ) ) ) {
71
- return $err;
72
- }
73
- //update data
74
- if ( is_wp_error( ( $err = $this->updateData() ) ) ) {
75
- return $err;
76
- }
77
- //almost there, now just need to update wpconfig
78
- if ( is_wp_error( ( $err = $this->writeToWpConfig() ) ) ) {
79
- $wpdb->query( 'ROLLBACK' );
80
-
81
- return $err;
82
- }
83
- //all good
84
- $wpdb->query( 'COMMIT' );
85
- //because we write to db so the later query will be error as the table from $wpdb not there anymore
86
- //replace the $wpdb isntance
87
- $wpdb->set_prefix( $this->new_prefix );
88
- //some time it can be gap time from io or so, just sleep it for 3s
89
- sleep(3);
90
-
91
- return true;
92
- }
93
-
94
- /**
95
- * @return bool|\WP_Error
96
- */
97
- private function writeToWpConfig() {
98
- $config_path = $this->retrieveWpConfigPath();
99
- $config = file( $config_path );
100
- $hook_line = $this->findDefaultHookLine( $config );
101
- $new_prefix = "\$table_prefix = '" . $this->new_prefix . "';" . PHP_EOL;
102
- $config[ $hook_line ] = $new_prefix;
103
- if ( ! file_put_contents( $config_path, implode( null, $config ), LOCK_EX ) ) {
104
- //should not happen
105
- return new \WP_Error( Error_Code::NOT_WRITEABLE,
106
- sprintf( __( "The file %s is not writable", "defender-security" ), $config_path ) );
107
- }
108
-
109
- return true;
110
- }
111
-
112
- /**
113
- * @return bool|\WP_Error
114
- */
115
- private function updateData() {
116
- global $wpdb;
117
- $prefix = $this->new_prefix;
118
- $old_prefix = $this->old_prefix;
119
- if ( is_multisite() ) {
120
- /**
121
- * case multiste
122
- * in multisite, blog options will have a option name $prefix_id_user_roles, we have to update this or
123
- * we will have issue with roles
124
- */
125
- $sql = "SELECT blog_id FROM `{$prefix}blogs`";
126
- $blogs = $wpdb->get_col( $sql );
127
- if ( is_array( $blogs ) && count( $blogs ) ) {
128
- foreach ( $blogs as $blog_id ) {
129
- if ( $blog_id == 1 ) {
130
- continue;
131
- }
132
- $sql = "UPDATE `{$prefix}{$blog_id}_options` SET option_name=%s WHERE option_name=%s";
133
- $sql = $wpdb->prepare( $sql, $prefix . $blog_id . '_user_roles', $old_prefix . $blog_id . '_user_roles' );
134
- if ( $wpdb->query( $sql ) == false ) {
135
- return new \WP_Error( Error_Code::SQL_ERROR, $wpdb->last_error );
136
- }
137
- }
138
- }
139
- }
140
- //now update the main blog
141
- $sql = "UPDATE `{$prefix}options` SET option_name=%s WHERE option_name=%s";
142
- $sql = $wpdb->prepare( $sql, $prefix . 'user_roles', $old_prefix . 'user_roles' );
143
- $wpdb->query( $sql );
144
- //we will need to update the prefix inside user meta, or we will get issue with permission
145
- $sql = "SELECT * FROM {$prefix}usermeta";
146
- $rows = $wpdb->get_results( $sql, ARRAY_A );
147
- foreach ( $rows as $row ) {
148
- if ( strpos( $row['meta_key'], $old_prefix ) === 0 ) {
149
- $clean_name = substr( $row['meta_key'], strlen( $old_prefix ), strlen( $row['meta_key'] ) );
150
- $new_name = $prefix . $clean_name;
151
- $sql = $wpdb->prepare( "UPDATE `{$prefix}usermeta` SET meta_key=%s WHERE meta_key=%s", $new_name, $row['meta_key'] );
152
- //run the updater
153
- if ( $wpdb->query( $sql ) === false ) {
154
- return new \WP_Error( Error_Code::SQL_ERROR, $wpdb->last_error );
155
- }
156
- }
157
- }
158
-
159
- return true;
160
- }
161
-
162
- /**
163
- * @param null $old_prefix
164
- *
165
- * @return bool|\WP_Error
166
- */
167
- private function changeDBPrefix( $old_prefix = null ) {
168
- global $wpdb;
169
- if ( is_null( $old_prefix ) ) {
170
- $old_prefix = $wpdb->prefix;
171
- }
172
- //cache it
173
- $this->old_prefix = $old_prefix;
174
- $tables = $this->getTables();
175
-
176
- foreach ( $tables as $table ) {
177
- $new_table_name = substr_replace( $table, $this->new_prefix, 0, strlen( $this->old_prefix ) );
178
- $sql = "RENAME TABLE `{$table}` TO `{$new_table_name}`";
179
- if ( $wpdb->query( $sql ) === false ) {
180
- return new \WP_Error( Error_Code::SQL_ERROR, $wpdb->last_error );
181
- }
182
- }
183
-
184
- return true;
185
- }
186
-
187
- /**
188
- * Validate the current prefix
189
- *
190
- * @return bool|\WP_Error
191
- */
192
- private function validatePrefix() {
193
- $new_prefix = trim( $this->new_prefix );
194
-
195
- global $wpdb;
196
- if ( $new_prefix == $wpdb->prefix ) {
197
- return new \WP_Error( Error_Code::VALIDATE, __( "You are currently using this prefix.", "defender-security" ) );
198
- }
199
-
200
- if ( strlen( $new_prefix ) == 0 ) {
201
- return new \WP_Error( Error_Code::VALIDATE, __( "Your prefix can't be empty!", "defender-security" ) );
202
- }
203
-
204
- if ( preg_match( '|[^a-z0-9_]|i', $new_prefix ) ) {
205
- return new \WP_Error( Error_Code::VALIDATE, __( "Table prefix can only contain numbers, letters, and underscores.", "defender-security" ) );
206
- }
207
-
208
- if ( count( $tables = $this->getTables( $new_prefix ) ) ) {
209
- return new \WP_Error( Error_Code::VALIDATE, __( "This prefix is already in use. Please choose a different prefix.", "defender-security" ) );
210
- }
211
-
212
- $this->new_prefix = $new_prefix;
213
-
214
- return true;
215
- }
216
-
217
- private function getTables( $prefix = null ) {
218
- global $wpdb;
219
-
220
- if ( ! $prefix ) {
221
- $prefix = $wpdb->base_prefix;
222
- }
223
-
224
- $results = $wpdb->get_col( $wpdb->prepare( "SHOW TABLES LIKE %s", $prefix . '%' ) );
225
- $results = array_unique( $results );
226
-
227
- return $results;
228
- }
229
-
230
- public function revert() {
231
- $this->new_prefix = 'wp_';
232
- if ( Settings::instance()->is_prefix_changed == true ) {
233
- set_time_limit( - 1 );
234
- global $wpdb;
235
- $wpdb->query( 'BEGIN' );
236
- //run a query to change db prefix
237
- if ( is_wp_error( ( $err = $this->changeDBPrefix() ) ) ) {
238
- return $err;
239
- }
240
- //update data
241
- if ( is_wp_error( ( $err = $this->updateData() ) ) ) {
242
- return $err;
243
- }
244
- //almost there, now just need to update wpconfig
245
- if ( is_wp_error( ( $err = $this->writeToWpConfig() ) ) ) {
246
- $wpdb->query( 'ROLLBACK' );
247
-
248
- return $err;
249
- }
250
- //all good
251
- $wpdb->query( 'COMMIT' );
252
- //restore back
253
- $wpdb->set_prefix( 'wp_' );
254
-
255
- return true;
256
- }
257
- }
258
-
259
- public function listen() {
260
- // TODO: Implement listen() method.
261
- }
262
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/db-prefix.php DELETED
@@ -1,97 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use WP_Defender\Behavior\Utils;
10
- use WP_Defender\Module\Hardener\Model\Settings;
11
- use WP_Defender\Module\Hardener\Rule;
12
-
13
- class DB_Prefix extends Rule {
14
- static $slug = 'db-prefix';
15
- static $service;
16
-
17
- function getDescription() {
18
- $this->renderPartial( 'rules/db-prefix' );
19
- }
20
-
21
- function check() {
22
- return $this->getService()->check();
23
- }
24
-
25
- function addHooks() {
26
- $this->addAction( 'processingHardener' . self::$slug, 'process' );
27
- $this->addAction( 'processRevert' . self::$slug, 'revert' );
28
- }
29
-
30
- function getMiscData() {
31
- $prefix = wp_generate_password( 6, false );
32
-
33
- return [
34
- 'prefix' => 'wp_' . $prefix . '_'
35
- ];
36
- }
37
-
38
- function revert() {
39
- if ( Settings::instance()->is_prefix_changed == true ) {
40
- $ret = $this->getService()->revert();
41
- if ( ! is_wp_error( $ret ) ) {
42
- Settings::instance()->addToIssues( self::$slug );
43
- } else {
44
- wp_send_json_error( array(
45
- 'message' => $ret->get_error_message()
46
- ) );
47
- }
48
- }
49
- }
50
-
51
- public function getTitle() {
52
- return __( "Change default database prefix", "defender-security" );
53
- }
54
-
55
- function process() {
56
- $dbprefix = HTTP_Helper::retrievePost( 'dbprefix' );
57
- $this->getService()->new_prefix = $dbprefix;
58
- $ret = $this->getService()->process();
59
- if ( is_wp_error( $ret ) ) {
60
- wp_send_json_error( array(
61
- 'message' => $ret->get_error_message()
62
- ) );
63
- } else {
64
- //leave the rest to the @Rest.processTweak
65
- }
66
- }
67
-
68
- /**
69
- * @return DB_Prefix_Service
70
- */
71
- function getService() {
72
- if ( static::$service == null ) {
73
- static::$service = new DB_Prefix_Service();
74
- }
75
-
76
- return static::$service;
77
- }
78
-
79
- /**
80
- * This will return the short summary why this rule show up as issue
81
- *
82
- * @return string
83
- */
84
- function getErrorReason() {
85
- return __( "Your database prefix is the default wp_ prefix.", "defender-security" );
86
- }
87
-
88
- /**
89
- * This will return a short summary to show why this rule works
90
- * @return mixed
91
- */
92
- function getSuccessReason() {
93
- global $wpdb;
94
-
95
- return sprintf( __( "Your database prefix is set to <strong>%s</strong> and is unique, %s would be proud.", "defender-security" ), $wpdb->prefix, \WP_Defender\Behavior\Utils::instance()->getDisplayName() );
96
- }
97
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/disable-file-editor-service.php DELETED
@@ -1,102 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\Array_Helper;
9
- use WP_Defender\Component\Error_Code;
10
- use WP_Defender\Module\Hardener\IRule_Service;
11
- use WP_Defender\Module\Hardener\Rule_Service;
12
-
13
- class Disable_File_Editor_Service extends Rule_Service implements IRule_Service {
14
- /**
15
- * @return bool
16
- */
17
- public function check() {
18
- if ( defined( 'DISALLOW_FILE_EDIT' ) && constant( 'DISALLOW_FILE_EDIT' ) === true ) {
19
- return true;
20
- }
21
-
22
- return false;
23
- }
24
-
25
- /**
26
- * @return bool|int|\WP_Error
27
- */
28
- public function process() {
29
- $config_path = $this->retrieveWPConfigPath();
30
- if ( ! is_writeable( $config_path ) ) {
31
- return new \WP_Error( Error_Code::NOT_WRITEABLE,
32
- sprintf( __( "The file %s is not writable", "defender-security" ), $config_path ) );
33
- }
34
- $config = file( $config_path );
35
- $line = $this->findLine( $config );
36
- if ( false === $line ) {
37
- //no defined, we just need to inject
38
- $hook_line = $this->findDefaultHookLine( $config );
39
- if ( $hook_line === false ) {
40
- return new \WP_Error( Error_Code::UNKNOWN_WPCONFIG, __( "Defender can't recognize your wp-config.php, please revert it to original state for further process.", "defender-security" ) );
41
- }
42
- $config = Array_Helper::injectLine( $config, $hook_line + 1, PHP_EOL . "define( 'DISALLOW_FILE_EDIT', true );" . PHP_EOL );
43
-
44
- return file_put_contents( $config_path, implode( null, $config ), LOCK_EX );
45
- } else {
46
- list( $value, $line ) = $line;
47
- if ( true === $value ) {
48
- //already disable it, if we sitll here mean st not work, do nothing
49
- return;
50
- } else {
51
- $config[ $line ] = "define( 'DISALLOW_FILE_EDIT', true );" . PHP_EOL;
52
-
53
- return file_put_contents( $config_path, implode( null, $config ), LOCK_EX );
54
- }
55
- }
56
-
57
- return false;
58
- }
59
-
60
- /**
61
- * @return int|\WP_Error
62
- */
63
- public function revert() {
64
- $config_path = $this->retrieveWPConfigPath();
65
- if ( ! is_writeable( $config_path ) ) {
66
- return new \WP_Error( Error_Code::NOT_WRITEABLE,
67
- sprintf( __( "The file %s is not writable", "defender-security" ), $config_path ) );
68
- }
69
- $config = file( $config_path );
70
- $line = $this->findLine( $config );
71
- if ( $line === false ) {
72
- //perhaps this already removed manually, do nothing
73
- return;
74
- } else {
75
- $value = $line[0];
76
- $line = $line[1];
77
- if ( $value == "true" ) {
78
- //value is true, we will remove this
79
- unset( $config[ $line ] );
80
-
81
- //save it
82
- return file_put_contents( $config_path, implode( null, $config ), LOCK_EX );
83
- }
84
- }
85
- }
86
-
87
- /**
88
- * @param $config
89
- *
90
- * @return array|bool
91
- */
92
- private function findLine( $config ) {
93
- $pattern = "/^define\(\s*['|\"]DISALLOW_FILE_EDIT['|\"],(.*)\)/";
94
- foreach ( $config as $k => $line ) {
95
- if ( preg_match( $pattern, $line, $matches ) ) {
96
- return array( trim( $matches[1] ), $k );
97
- }
98
- }
99
-
100
- return false;
101
- }
102
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/disable-file-editor.php DELETED
@@ -1,128 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use WP_Defender\Module\Hardener\Model\Settings;
9
- use WP_Defender\Module\Hardener\Rule;
10
-
11
- class Disable_File_Editor extends Rule {
12
- static $slug = 'disable-file-editor';
13
-
14
- /**
15
- * This will return the short summary why this rule show up as issue
16
- *
17
- * @return string
18
- */
19
- function getErrorReason() {
20
- return __( "The file editor is currently enabled.", "defender-security" );
21
- }
22
-
23
- /**
24
- * This will return a short summary to show why this rule works
25
- * @return mixed
26
- */
27
- function getSuccessReason() {
28
- return __( "You've disabled the file editor, winning.", "defender-security" );
29
- }
30
-
31
- static $service;
32
-
33
- function getDescription() {
34
- $this->renderPartial( 'rules/disable-file-editor' );
35
- }
36
-
37
- function check() {
38
- return $this->getService()->check();
39
- }
40
-
41
- public function getTitle() {
42
- return __( "Disable the file editor", "defender-security" );
43
- }
44
-
45
- function addHooks() {
46
- $this->addAction( 'processingHardener' . self::$slug, 'process' );
47
- $this->addAction( 'processRevert' . self::$slug, 'revert' );
48
- //Extra hardener actions incase setup is messed
49
- if ( $this->check() ) {
50
- $this->addAction( 'current_screen', 'current_screen' );
51
- if ( is_network_admin() ) {
52
- $this->addAction( 'network_admin_menu', 'editor_admin_menu', 999 );
53
- } elseif ( is_user_admin() ) {
54
- $this->addAction( 'user_admin_menu', 'editor_admin_menu', 999 );
55
- } else {
56
- $this->addAction( 'admin_menu', 'editor_admin_menu', 999 );
57
- }
58
- $this->addFilter( 'plugin_action_links', 'action_links', 10, 4 );
59
- }
60
- }
61
-
62
- function revert() {
63
- $ret = $this->getService()->revert();
64
- if ( ! is_wp_error( $ret ) ) {
65
- Settings::instance()->addToIssues( self::$slug );
66
- } else {
67
- wp_send_json_error( array(
68
- 'message' => $ret->get_error_message()
69
- ) );
70
- }
71
- }
72
-
73
- function process() {
74
- $ret = $this->getService()->process();
75
- if ( ! is_wp_error( $ret ) ) {
76
- Settings::instance()->addToResolved( self::$slug );
77
- } else {
78
- wp_send_json_error( array(
79
- 'message' => $ret->get_error_message()
80
- ) );
81
- }
82
- }
83
-
84
- /**
85
- * @return Disable_File_Editor_Service
86
- */
87
- function getService() {
88
- if ( self::$service == null ) {
89
- self::$service = new Disable_File_Editor_Service();
90
- }
91
-
92
- return self::$service;
93
- }
94
-
95
- /**
96
- * Sometimes the roles are messed in the installation
97
- * So we manually check if the pages are accessed and disable access to the,
98
- */
99
- function current_screen() {
100
- $current_screen = get_current_screen();
101
- if ( $current_screen->id == 'theme-editor-network' || $current_screen->id == 'theme-editor' ) {
102
- wp_die( '<p>' . __( 'Sorry, you are not allowed to edit templates for this site.' ) . '</p>' );
103
- }
104
- if ( $current_screen->id == 'plugin-editor-network' || $current_screen->id == 'plugin-editor' ) {
105
- wp_die( '<p>' . __( 'Sorry, you are not allowed to edit plugins for this site.' ) . '</p>' );
106
- }
107
- }
108
-
109
- /**
110
- * Remove the edit in the admin menu
111
- */
112
- function editor_admin_menu() {
113
- remove_submenu_page( 'themes.php', 'theme-editor.php' );
114
- remove_submenu_page( 'plugins.php', 'plugin-editor.php' );
115
- }
116
-
117
- /**
118
- * Remove any edit links from the plugin list
119
- *
120
- */
121
- function action_links( $actions, $plugin_file, $plugin_data, $context ) {
122
- if ( isset( $actions['edit'] ) ) {
123
- unset( $actions['edit'] );
124
- }
125
-
126
- return $actions;
127
- }
128
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/disable-trackback-service.php DELETED
@@ -1,109 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Base\Container;
9
- use Hammer\Helper\WP_Helper;
10
- use WP_Defender\Module\Hardener\IRule_Service;
11
- use WP_Defender\Module\Hardener\Model\Settings;
12
- use WP_Defender\Module\Hardener\Rule_Service;
13
-
14
- class Disable_Trackback_Service extends Rule_Service implements IRule_Service {
15
- const CACHE_KEY = 'disable_trackback';
16
- const PROCESS_POSTS_KEYS = 'disable_trackback_post_keys';
17
- public $process_posts;
18
-
19
- /**
20
- * @return bool
21
- */
22
- public function process() {
23
- //first need to cache the status
24
- Settings::instance()->setDValues( self::CACHE_KEY, 1 );
25
- Settings::instance()->setDValues( self::PROCESS_POSTS_KEYS, $this->process_posts );
26
- $this->handle_change( false, ( $this->process_posts === 'yes' ) );
27
- return true;
28
- }
29
-
30
- /**
31
- * @return bool
32
- */
33
- public function revert() {
34
- Settings::instance()->setDValues( self::CACHE_KEY, 0 );
35
- $process_posts = Settings::instance()->getDValues( self::PROCESS_POSTS_KEYS );
36
- Settings::instance()->setDValues( self::PROCESS_POSTS_KEYS, 'no' );
37
- //Only check posts if it was previously true
38
- $process = false;
39
- if ( !empty( $process_posts ) && $process_posts === 'yes' ) {
40
- $process = true;
41
- }
42
- $this->handle_change( true, $process );
43
- return true;
44
- }
45
-
46
- /**
47
- * @return mixed
48
- */
49
- public function check() {
50
- $key = Settings::instance()->getDValues( self::CACHE_KEY );
51
-
52
- return $key == 1;
53
- }
54
-
55
- /**
56
- * Handle WordPress Settings Changes
57
- *
58
- * @param Boolean $revert - set to true to revert changes
59
- * @param Boolean $handle_posts - set to true to also update posts
60
- */
61
- private function handle_change( $revert = false, $handle_posts = false ) {
62
- global $wpdb;
63
- if ( is_multisite() ) {
64
-
65
- $blogs = $wpdb->get_results( "SELECT blog_id FROM {$wpdb->blogs} WHERE
66
- site_id = '{$wpdb->siteid}'
67
- AND spam = '0'
68
- AND deleted = '0'
69
- AND archived = '0'
70
- AND mature = '0'
71
- AND public = '1'
72
- " );
73
- foreach ( $blogs as $blog ) {
74
- update_blog_option( $blog->blog_id, 'default_pingback_flag', ( $revert ) ? 1 : 0 );
75
- update_blog_option( $blog->blog_id, 'default_ping_status', ( $revert ) ? 'open' : 'closed' );
76
- if ( $handle_posts ) {
77
- $this->posts_ping_status( $wpdb, $revert, $blog->blog_id );
78
- }
79
- }
80
-
81
- } else {
82
- update_option( 'default_pingback_flag', ( $revert ) ? 1 : 0 );
83
- update_option( 'default_ping_status', ( $revert ) ? 'open' : 'closed' );
84
- if ( $handle_posts ) {
85
- $this->posts_ping_status( $wpdb, $revert, 0 );
86
- }
87
- }
88
- }
89
-
90
- /**
91
- * Update the post ping status
92
- *
93
- * @param Boolean $revert - set to true to revert changes
94
- * @param Int $blog_id - the blog id if multisite
95
- *
96
- */
97
- private function posts_ping_status( $wpdb, $revert = false, $blog_id = 0 ) {
98
- $defender_post_types = array( 'wd_ip_lockout', 'wd_iplockout_log' );
99
- $defender_post_types = "'" . implode( "','", $defender_post_types ) . "'";
100
- $ping_status = ( $revert ) ? 'open' : 'closed';
101
- if ( $blog_id > 0 ) {
102
- $wpdb->set_blog_id( $blog_id );
103
- $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->posts} SET `ping_status` = %s WHERE `post_status` != %s AND `post_type` NOT IN(%s)", $ping_status, 'inherit', $defender_post_types ) );
104
- } else {
105
-
106
- $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->posts} SET `ping_status` = %s WHERE `post_status` != %s AND `post_type` NOT IN(%s)", $ping_status, 'inherit', $defender_post_types ) );
107
- }
108
- }
109
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/disable-trackback.php DELETED
@@ -1,102 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use WP_Defender\Module\Hardener\Model\Settings;
10
- use WP_Defender\Module\Hardener\Rule;
11
-
12
- class Disable_Trackback extends Rule {
13
- static $slug = 'disable-trackback';
14
- static $service;
15
-
16
- function getDescription() {
17
- $this->renderPartial( 'rules/disable-trackback' );
18
- }
19
-
20
- /**
21
- * @return bool
22
- */
23
- function check() {
24
- return $this->getService()->check();
25
- }
26
-
27
- /**
28
- * This will return the short summary why this rule show up as issue
29
- *
30
- * @return string
31
- */
32
- function getErrorReason() {
33
- return __( "Trackbacks and pingbacks are currently enabled.", "defender-security" );
34
- }
35
-
36
- /**
37
- * This will return a short summary to show why this rule works
38
- * @return mixed
39
- */
40
- function getSuccessReason() {
41
- return __( "Trackbacks and pingbacks are disabled, nice work!", "defender-security" );
42
- }
43
-
44
- public function getTitle() {
45
- return __( "Disable trackbacks and pingbacks", "defender-security" );
46
- }
47
-
48
- function addHooks() {
49
- $this->addAction( 'processingHardener' . self::$slug, 'process' );
50
- $this->addAction( 'processRevert' . self::$slug, 'revert' );
51
- if ( in_array( self::$slug, (array) Settings::instance()->fixed ) ) {
52
- $this->addFilter( 'wp_headers', 'removePingback' );
53
- }
54
- }
55
-
56
- /**
57
- * @param $headers
58
- *
59
- * @return mixed
60
- */
61
- public function removePingback( $headers ) {
62
- unset( $headers['X-Pingback'] );
63
-
64
- return $headers;
65
- }
66
-
67
- function revert() {
68
- $ret = $this->getService()->revert();
69
- if ( ! is_wp_error( $ret ) ) {
70
- Settings::instance()->addToIssues( self::$slug );
71
- } else {
72
- wp_send_json_error( array(
73
- 'message' => $ret->get_error_message()
74
- ) );
75
- }
76
- }
77
-
78
- function process() {
79
- $process_posts = HTTP_Helper::retrievePost( 'updatePosts' );
80
- $this->getService()->process_posts = $process_posts;
81
-
82
- $ret = $this->getService()->process();
83
- if ( ! is_wp_error( $ret ) ) {
84
- Settings::instance()->addToResolved( self::$slug );
85
- } else {
86
- wp_send_json_error( array(
87
- 'message' => $ret->get_error_message()
88
- ) );
89
- }
90
- }
91
-
92
- /**
93
- * @return Disable_Trackback_Service
94
- */
95
- public function getService() {
96
- if ( self::$service == null ) {
97
- self::$service = new Disable_Trackback_Service();
98
- }
99
-
100
- return self::$service;
101
- }
102
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/disable-xml-rpc-service.php DELETED
@@ -1,44 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Base\Container;
9
- use Hammer\Helper\WP_Helper;
10
- use WP_Defender\Module\Hardener\IRule_Service;
11
- use WP_Defender\Module\Hardener\Model\Settings;
12
- use WP_Defender\Module\Hardener\Rule_Service;
13
-
14
- class Disable_Xml_Rpc_Service extends Rule_Service implements IRule_Service {
15
- const CACHE_KEY = 'disable_xml_rpc';
16
-
17
- /**
18
- * @return bool
19
- */
20
- public function process() {
21
- //first need to cache the status
22
- Settings::instance()->setDValues( self::CACHE_KEY, 1 );
23
-
24
- return true;
25
- }
26
-
27
- /**
28
- * @return bool
29
- */
30
- public function revert() {
31
- Settings::instance()->setDValues( self::CACHE_KEY, 0 );
32
-
33
- return true;
34
- }
35
-
36
- /**
37
- * @return mixed
38
- */
39
- public function check() {
40
- $key = Settings::instance()->getDValues( self::CACHE_KEY );
41
-
42
- return $key == 1;
43
- }
44
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/disable-xml-rpc.php DELETED
@@ -1,96 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use WP_Defender\Module\Hardener\Model\Settings;
10
- use WP_Defender\Module\Hardener\Rule;
11
-
12
- class Disable_Xml_Rpc extends Rule {
13
- static $slug = 'disable-xml-rpc';
14
- static $service;
15
-
16
- function getDescription() {
17
- $this->renderPartial( 'rules/disable-xml-rpc' );
18
- }
19
-
20
- /**
21
- * @return bool
22
- */
23
- function check() {
24
- return $this->getService()->check();
25
- }
26
-
27
- public function getTitle() {
28
- return __( "Disable XML RPC", "defender-security" );
29
- }
30
-
31
- function addHooks() {
32
- $this->addAction( 'processingHardener' . self::$slug, 'process' );
33
- $this->addAction( 'processRevert' . self::$slug, 'revert' );
34
- if ( in_array( self::$slug, Settings::instance()->fixed ) ) {
35
- add_filter( 'xmlrpc_enabled', '__return_false' );
36
- $this->addFilter( 'xmlrpc_methods', 'block_xmlrpc_attacks' );
37
- }
38
- }
39
-
40
- function block_xmlrpc_attacks( $methods ) {
41
- unset( $methods['pingback.ping'] );
42
- unset( $methods['pingback.extensions.getPingbacks'] );
43
-
44
- return $methods;
45
- }
46
-
47
- function revert() {
48
- $ret = $this->getService()->revert();
49
- if ( ! is_wp_error( $ret ) ) {
50
- Settings::instance()->addToIssues( self::$slug );
51
- } else {
52
- wp_send_json_error( array(
53
- 'message' => $ret->get_error_message()
54
- ) );
55
- }
56
- }
57
-
58
- function process() {
59
- $ret = $this->getService()->process();
60
- if ( ! is_wp_error( $ret ) ) {
61
- Settings::instance()->addToResolved( self::$slug );
62
- } else {
63
- wp_send_json_error( array(
64
- 'message' => $ret->get_error_message()
65
- ) );
66
- }
67
- }
68
-
69
- /**
70
- * @return Disable_Xml_Rpc_Service
71
- */
72
- public function getService() {
73
- if ( self::$service == null ) {
74
- self::$service = new Disable_Xml_Rpc_Service();
75
- }
76
-
77
- return self::$service;
78
- }
79
-
80
- /**
81
- * This will return the short summary why this rule show up as issue
82
- *
83
- * @return string
84
- */
85
- function getErrorReason() {
86
- return __( "XML-RPC is currently enabled.", "defender-security" );
87
- }
88
-
89
- /**
90
- * This will return a short summary to show why this rule works
91
- * @return mixed
92
- */
93
- function getSuccessReason() {
94
- return __( "XML-RPC is disabled.", "defender-security" );
95
- }
96
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/hide-error-service.php DELETED
@@ -1,144 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\Array_Helper;
9
- use Hammer\Helper\WP_Helper;
10
- use WP_Defender\Component\Error_Code;
11
- use WP_Defender\Module\Hardener\IRule_Service;
12
- use WP_Defender\Module\Hardener\Rule_Service;
13
-
14
- class Hide_Error_Service extends Rule_Service implements IRule_Service {
15
-
16
- /**
17
- * @return bool
18
- */
19
- public function check() {
20
- if ( defined( 'WP_DEBUG' ) && constant( 'WP_DEBUG' ) == false ) {
21
- return true;
22
- }
23
- if ( defined( 'WP_DEBUG_DISPLAY' ) && constant( 'WP_DEBUG_DISPLAY' ) == false ) {
24
- return true;
25
- }
26
-
27
- return false;
28
- }
29
-
30
- /**
31
- * Process to fix the wp-config base on scenario
32
- *
33
- * @return bool|\WP_Error
34
- */
35
- public function process() {
36
- $config_path = $this->retrieveWPConfigPath();
37
- //check if can write
38
- if ( ! is_writeable( $config_path ) ) {
39
- return new \WP_Error( Error_Code::NOT_WRITEABLE,
40
- sprintf( __( "The file %s is not writable", "defender-security" ), $config_path ) );
41
- }
42
- $config = file( $config_path );
43
- if ( ( $info = $this->findWPDebugLine( $config ) ) === - 1 ) {
44
- //this is a rare case, wpdebug is not defined
45
- if ( constant( 'WP_DEBUG' ) == null ) {
46
- //nowhere, find the hook line, hook after $prefix
47
- $hookline = $this->findDefaultHookLine( $config );
48
- if ( $hookline === false ) {
49
- return new \WP_Error( Error_Code::UNKNOWN_WPCONFIG, __( "Defender can't recognize your wp-config.php, please revert it to original state for further process.", "defender-security" ) );
50
- }
51
- $config = Array_Helper::injectLine( $config, $hookline + 1, PHP_EOL . "define( 'WP_DEBUG', false );" . PHP_EOL );
52
- file_put_contents( $config_path, implode( null, $config ), LOCK_EX );
53
-
54
- return true;
55
- } else {
56
- //already somewhere
57
- return new \WP_Error( Error_Code::UNKNOWN_WPCONFIG, __( "Defender can't recognize your wp-config.php, please revert it to original state for further process.", "defender-security" ) );
58
- }
59
- }
60
-
61
- list( $value, $line ) = $info;
62
- if ( $value == 1 ) {
63
- if ( constant( 'WP_DEBUG_LOG' ) == true ) {
64
- //debug need to be on for logging, so we just hide it
65
- $display_line = $this->findDebugDisplayLine( $config );
66
- if ( $display_line === false ) {
67
- $config = Array_Helper::injectLine( $config, $line + 1, "define( 'WP_DEBUG_DISPLAY', false );" . PHP_EOL );
68
- } else {
69
- $config[ $display_line ] = "define( 'WP_DEBUG_DISPLAY', false );" . PHP_EOL;
70
- }
71
- } else {
72
- //change wpdebug to off
73
- $config[ $line ] = 'define( \'WP_DEBUG\', false );' . PHP_EOL;
74
- }
75
- file_put_contents( $config_path, implode( null, $config ), LOCK_EX );
76
-
77
- return true;
78
-
79
- } elseif ( $value == 0 ) {
80
- //debug already off
81
- //this is a rare case, debug is off, but error still showing up
82
- return new \WP_Error( 0, __( "WP_DEBUG get override somewhere, please check with your host provider", "defender-security" ) );
83
- }
84
- }
85
-
86
- /**
87
- * This will parse wpconfig lines and check if we do have any defined wp_debug
88
- * result code
89
- * 1. found and enable
90
- * 0. found and disable
91
- * -1. not found
92
- *
93
- * @param $config
94
- *
95
- * @return int|array
96
- */
97
- private function findWPDebugLine( $config ) {
98
- $pattern = "/^define\(\s*['|\"]WP_DEBUG['|\"],(.*)\)/";
99
- foreach ( $config as $key => $line ) {
100
- $line = trim( $line );
101
- if ( preg_match( $pattern, $line, $matches ) ) {
102
- if ( trim( $matches[1] ) == true ) {
103
- return array( 1, $key );
104
- } else {
105
- return array( 0, $key );
106
- }
107
- }
108
- }
109
-
110
- return - 1;
111
- }
112
-
113
- /**
114
- * @param $config
115
- *
116
- * @return bool|string
117
- */
118
- private static function findDebugDisplayLine( $config ) {
119
- $pattern = "/^define\(\s*['|\"]WP_DEBUG_DISPLAY['|\"], (.*)\)/";
120
- foreach ( $config as $key => $line ) {
121
- $line = trim( $line );
122
- if ( preg_match( $pattern, $line, $matches ) ) {
123
- return $key;
124
- }
125
- }
126
-
127
- return false;
128
- }
129
-
130
- public function revert() {
131
- $config_path = $this->retrieveWPConfigPath();
132
- //check if can write
133
- if ( ! is_writeable( $config_path ) ) {
134
- return new \WP_Error( Error_Code::NOT_WRITEABLE,
135
- sprintf( __( "The file %s is not writable", "defender-security" ), $config_path ) );
136
- }
137
- $config = file( $config_path );
138
-
139
- }
140
-
141
- public function listen() {
142
-
143
- }
144
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/hide-error.php DELETED
@@ -1,91 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\WP_Helper;
9
- use WP_Defender\Module\Hardener\Model\Settings;
10
- use WP_Defender\Module\Hardener\Rule;
11
-
12
- class Hide_Error extends Rule {
13
- static $slug = 'hide-error';
14
- static $service;
15
-
16
- function getDescription() {
17
- $this->renderPartial( 'rules/hide-error' );
18
- }
19
-
20
- /**
21
- * @return bool|false|mixed|null
22
- */
23
- function check() {
24
- $stat = WP_Helper::getArrayCache()->get( self::$slug . 'stat', null );
25
- if ( $stat === null ) {
26
- $stat = $this->getService()->check();
27
- WP_Helper::getArrayCache()->set( self::$slug . 'stat', $stat );
28
- }
29
-
30
- return $stat;
31
- }
32
-
33
- /**
34
- * This will return the short summary why this rule show up as issue
35
- *
36
- * @return string
37
- */
38
- function getErrorReason() {
39
- return __( "Error debugging is currently allowed.", "defender-security" );
40
- }
41
-
42
- /**
43
- * This will return a short summary to show why this rule works
44
- * @return mixed
45
- */
46
- function getSuccessReason() {
47
- return __( "You've disabled all error reporting, Houston will never report a problem.", "defender-security" );
48
- }
49
-
50
- public function getTitle() {
51
- return __( "Hide error reporting", "defender-security" );
52
- }
53
-
54
- function revert() {
55
- $ret = $this->getService()->revert();
56
- if ( ! is_wp_error( $ret ) ) {
57
- Settings::instance()->addToIssues( self::$slug );
58
- } else {
59
- wp_send_json_error( array(
60
- 'message' => $ret->get_error_message()
61
- ) );
62
- }
63
- }
64
-
65
- function addHooks() {
66
- $this->addAction( 'processingHardener' . self::$slug, 'process' );
67
- $this->addAction( 'processRevert' . self::$slug, 'revert' );
68
- }
69
-
70
- function process() {
71
- $ret = $this->getService()->process();
72
- if ( ! is_wp_error( $ret ) ) {
73
- Settings::instance()->addToResolved( self::$slug );
74
- } else {
75
- wp_send_json_error( array(
76
- 'message' => $ret->get_error_message()
77
- ) );
78
- }
79
- }
80
-
81
- /**
82
- * @return Hide_Error_Service
83
- */
84
- public function getService() {
85
- if ( self::$service == null ) {
86
- self::$service = new Hide_Error_Service();
87
- }
88
-
89
- return self::$service;
90
- }
91
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/login-duration-service.php DELETED
@@ -1,57 +0,0 @@
1
- <?php
2
- /**
3
- * @author Paul Kevin
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use WP_Defender\Module\Hardener\IRule_Service;
9
- use WP_Defender\Module\Hardener\Rule_Service;
10
- use WP_Defender\Module\Hardener\Model\Settings;
11
-
12
- class Login_Duration_Service extends Rule_Service implements IRule_Service {
13
-
14
- const CACHE_KEY = 'login_duration';
15
- const DURATION_CACHE_KEY = 'login_duration_days';
16
- const DEFAULT_DAYS = 14;
17
-
18
- protected $duration;
19
-
20
- /**
21
- * @param mixed $duration
22
- */
23
- public function setDuration( $duration ) {
24
- $this->duration = $duration;
25
- }
26
-
27
- /**
28
- * @return bool
29
- */
30
- public function check() {
31
- $key = Settings::instance()->getDValues( self::CACHE_KEY );
32
-
33
- return ( $key == 1 );
34
- }
35
-
36
- public function process() {
37
- Settings::instance()->setDValues( self::CACHE_KEY, 1 );
38
- Settings::instance()->setDValues( self::DURATION_CACHE_KEY, $this->duration );
39
- return true;
40
- }
41
-
42
- public function revert() {
43
- Settings::instance()->setDValues( self::CACHE_KEY, 0 );
44
- Settings::instance()->setDValues( self::DURATION_CACHE_KEY, self::DEFAULT_DAYS );
45
- return true;
46
- }
47
-
48
- public function getDuration( $in_seconds = false ) {
49
- $duration = Settings::instance()->getDValues( self::DURATION_CACHE_KEY );
50
- if ( !empty( $duration ) ) {
51
- $duration = intval( $duration );
52
- return ( $in_seconds ) ? $duration * DAY_IN_SECONDS : $duration;
53
- } else {
54
- return ( $in_seconds ) ? self::DEFAULT_DAYS * DAY_IN_SECONDS : self::DEFAULT_DAYS;
55
- }
56
- }
57
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/login-duration.php DELETED
@@ -1,176 +0,0 @@
1
- <?php
2
- /**
3
- * @author Paul Kevin
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\WP_Helper;
9
- use Hammer\Helper\HTTP_Helper;
10
- use WP_Defender\Module\Hardener\Model\Settings;
11
- use WP_Defender\Module\Hardener\Rule;
12
- use WP_Defender\Behavior\Utils;
13
-
14
- class Login_Duration extends Rule {
15
-
16
- static $slug = 'login-duration';
17
-
18
- static $service;
19
-
20
- /**
21
- * @return Login_Duration_Service
22
- */
23
- public function getService() {
24
- if ( self::$service == null ) {
25
- self::$service = new Login_Duration_Service();
26
- }
27
-
28
- return self::$service;
29
- }
30
-
31
- function getDescription() {
32
- $this->renderPartial( 'rules/login-duration' );
33
- }
34
-
35
- /**
36
- * @return string
37
- */
38
- public function getTitle() {
39
- return __( "Manage Login Duration", "defender-security" );
40
- }
41
-
42
- /**
43
- * This will return the short summary why this rule show up as issue
44
- *
45
- * @return string
46
- */
47
- function getErrorReason() {
48
- $days = $this->getService()->getDuration();
49
-
50
- return sprintf( __( "Your current login duration is the default %d days.", "defender-security" ), $days );
51
- }
52
-
53
- /**
54
- * This will return a short summary to show why this rule works
55
- * @return mixed
56
- */
57
- function getSuccessReason() {
58
- $days = $this->getService()->getDuration();
59
-
60
- return sprintf( __( "You've adjusted the default login duration to %d days.", "defender-security" ), $days );
61
- }
62
-
63
- /**
64
- * @return bool
65
- */
66
- function check() {
67
- return $this->getService()->check();
68
- }
69
-
70
- function addHooks() {
71
- $this->addAction( 'processingHardener' . self::$slug, 'process' );
72
- $this->addAction( 'processRevert' . self::$slug, 'revert' );
73
- $this->addAction( 'wp_login', 'login_action_handler', 9, 2 );
74
- if ( $this->check() ) {
75
- $this->addFilter( 'auth_cookie_expiration', 'cookie_duration', 10, 3 );
76
- $this->addFilter( 'login_message', 'login_message' );
77
- }
78
-
79
- }
80
-
81
- function revert() {
82
- $settings = Settings::instance();
83
- $service = $this->getService();
84
- $ret = $service->revert();
85
- if ( ! is_wp_error( $ret ) ) {
86
- Settings::instance()->addToIssues( self::$slug );
87
- } else {
88
- wp_send_json_error( array(
89
- 'message' => $ret->get_error_message()
90
- ) );
91
- }
92
- }
93
-
94
- function process() {
95
- $service = $this->getService();
96
- $duration = HTTP_Helper::retrievePost( 'duration' );
97
- if ( is_numeric( $duration ) && intval( $duration ) > 0 ) {
98
- $service->setDuration( $duration );
99
- $ret = $service->process();
100
- if ( ! is_wp_error( $ret ) ) {
101
- Settings::instance()->addToResolved( self::$slug );
102
- } else {
103
- wp_send_json_error( array(
104
- 'message' => $ret->get_error_message()
105
- ) );
106
- }
107
- } else {
108
- wp_send_json_error( array(
109
- 'message' => __( 'Duration can only be a number and greater than 0', "defender-security" )
110
- ) );
111
- }
112
- }
113
-
114
- /**
115
- * Set the last login user meta
116
- */
117
- function login_action_handler( $user_login, $user = '' ) {
118
- if ( $user == '' ) {
119
- $user = get_user_by( 'login', $user_login );
120
- }
121
- if ( ! $user ) {
122
- return;
123
- }
124
- $last_login_time = current_time( 'mysql' );
125
- update_user_meta( $user->ID, 'last_login_time', $last_login_time );
126
- }
127
-
128
- public function getMiscData() {
129
- return [
130
- 'duration' => $this->getService()->getDuration()
131
- ];
132
- }
133
-
134
- /**
135
- * Handle the custom login message
136
- *
137
- */
138
- function login_message( $message = '' ) {
139
- $login_msg = HTTP_Helper::retrieveGet( 'defender_login_message', false );
140
- if ( $login_msg ) {
141
- $logout_msg = strip_tags( $login_msg );
142
- if ( $logout_msg == 'session_expired' ) {
143
- $duration = $this->getService()->getDuration( false );
144
- $msg = sprintf( __( 'Your session has expired because it has been over %d days since your last login. Please log back in to continue.', "defender-security" ), $duration );
145
- $msg = htmlspecialchars( $msg, ENT_QUOTES, 'UTF-8' );
146
- $message .= '<p class="login message">' . $msg . '</p>';
147
- }
148
- }
149
-
150
- return $message;
151
- }
152
-
153
- /**
154
- * Cookie duration in days in seconds
155
- *
156
- * @param Integer $duration - default duration
157
- * @param Integer $user_id - current user id
158
- * @param Boolean $remember - remember me login
159
- *
160
- * @return Integer $duration
161
- */
162
- function cookie_duration( $duration, $user_id, $remember ) {
163
- $dur = $this->getService()->getDuration( true );
164
- if ( $dur < 2 ) {
165
- //duration set smaller than 2 days, use the custom for both remember & non remeber
166
- return $dur;
167
- } elseif ( $remember ) {
168
- //this case only
169
- return $dur;
170
- }
171
-
172
- //return default
173
- return $duration;
174
- }
175
-
176
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/php-version-service.php DELETED
@@ -1,68 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use WP_Defender\Behavior\Utils;
9
- use WP_Defender\Module\Hardener\IRule_Service;
10
- use WP_Defender\Module\Hardener\Model\Settings;
11
- use WP_Defender\Module\Hardener\Rule_Service;
12
-
13
- class PHP_Version_Service extends Rule_Service implements IRule_Service {
14
-
15
- /**
16
- * @return bool
17
- */
18
- public function check() {
19
- $this->queryVersion();
20
- if ( version_compare( phpversion(), Settings::instance()->min_php_version, '<=' ) ) {
21
- return false;
22
- }
23
-
24
- return true;
25
- }
26
-
27
- public function process() {
28
-
29
- }
30
-
31
- public function revert() {
32
-
33
- }
34
-
35
- public function listen() {
36
-
37
- }
38
-
39
- protected function queryVersion() {
40
- $infos = [
41
- '7.2' => [ '30 Nov 2019', '30 Nov 2020' ],
42
- '7.3' => [ '6 Dec 2020', '6 Dec 2021' ],
43
- '7.4' => [ '28 Nov 2021', '28 Nov 2022' ]
44
- ];
45
- $minVersion = null;
46
- $stableVersion = null;
47
- foreach ( $infos as $php => $dates ) {
48
- list( $active, $security ) = $dates;
49
- //get the one still have security updates
50
- if ( $minVersion == null && strtotime( $active ) < time() && strtotime( $security ) > time() ) {
51
- $minVersion = $php;
52
- }
53
- //if no min available, we pick the current active
54
- if ( $minVersion == null && strtotime( $active ) > time() ) {
55
- $minVersion = $php;
56
- }
57
- //pick the nearest the min version, we want stable, not features
58
- if ( $stableVersion == null && $minVersion != null && version_compare( $php, $minVersion, '>' ) ) {
59
- $stableVersion = $php;
60
- }
61
- }
62
-
63
- $settings = Settings::instance();
64
- $settings->stable_php_version = $stableVersion;
65
- $settings->min_php_version = $minVersion;
66
- $settings->save();
67
- }
68
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/php-version.php DELETED
@@ -1,81 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use WP_Defender\Module\Hardener\Model\Settings;
9
- use WP_Defender\Module\Hardener\Rule;
10
-
11
- class PHP_Version extends Rule {
12
- static $slug = 'php-version';
13
- static $service;
14
-
15
- function getDescription() {
16
- $this->renderPartial( 'rules/php-version' );
17
- }
18
-
19
- /**
20
- * This will return the short summary why this rule show up as issue
21
- *
22
- * @return string
23
- */
24
- function getErrorReason() {
25
- $settings = Settings::instance();
26
-
27
- return sprintf( __( "PHP versions older than %s are no longer supported. For security and stability we strongly recommend you upgrade your PHP version to version %s or newer as soon as possible. ", "defender-security" ), $settings->min_php_version, $settings->min_php_version );
28
- }
29
-
30
- /**
31
- * This will return a short summary to show why this rule works
32
- * @return mixed
33
- */
34
- function getSuccessReason() {
35
- return __( "You have the latest version of PHP installed, good stuff!", "defender-security" );
36
- }
37
-
38
- public function getMiscData() {
39
- $settings = Settings::instance();
40
-
41
- return [
42
- 'min_php_version' => $settings->min_php_version,
43
- 'stable_php_version' => $settings->stable_php_version,
44
- 'php_version' => phpversion()
45
- ];
46
- }
47
-
48
- /**
49
- * @return bool
50
- */
51
- function check() {
52
- return $this->getService()->check();
53
- }
54
-
55
- function revert() {
56
- // TODO: Implement revert() method.
57
- }
58
-
59
- public function getTitle() {
60
- return __( "Update PHP to latest version", "defender-security" );
61
- }
62
-
63
- function addHooks() {
64
- // TODO: Implement addHooks() method.
65
- }
66
-
67
- function process() {
68
- // TODO: Implement process() method.
69
- }
70
-
71
- /**
72
- * @return PHP_Version_Service
73
- */
74
- function getService() {
75
- if ( static::$service == null ) {
76
- static::$service = new PHP_Version_Service();
77
- }
78
-
79
- return static::$service;
80
- }
81
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/prevent-enum-users-service.php DELETED
@@ -1,47 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use WP_Defender\Module\Hardener\IRule_Service;
9
- use WP_Defender\Module\Hardener\Model\Settings;
10
- use WP_Defender\Module\Hardener\Rule_Service;
11
-
12
- class Prevent_Enum_Users_Service extends Rule_Service implements IRule_Service {
13
- const CACHE_KEY = 'prevent_enum_users';
14
-
15
- /**
16
- * Check if current rule fixed or not
17
- * @return bool
18
- */
19
- public function check() {
20
- $flag = Settings::instance()->getDValues( Prevent_Enum_Users_Service::CACHE_KEY );
21
- if ( $flag == 0 ) {
22
- return false;
23
- }
24
-
25
- return true;
26
- }
27
-
28
- /**
29
- * Process the rule
30
- * @return bool|\WP_Error
31
- */
32
- public function process() {
33
- Settings::instance()->setDValues( self::CACHE_KEY, 1 );
34
-
35
- return true;
36
- }
37
-
38
- /**
39
- * Revert if able
40
- * @return bool|\WP_Error
41
- */
42
- public function revert() {
43
- Settings::instance()->setDValues( self::CACHE_KEY, 0 );
44
-
45
- return true;
46
- }
47
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/prevent-enum-users.php DELETED
@@ -1,125 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use WP_Defender\Module\Hardener\Model\Settings;
9
- use WP_Defender\Module\Hardener\Rule;
10
-
11
- class Prevent_Enum_Users extends Rule {
12
- static $slug = 'prevent-enum-users';
13
- static $service;
14
-
15
- /**
16
- * Return this rule content, we will try to use renderPartial
17
- *
18
- * @return mixed
19
- */
20
- function getDescription() {
21
-
22
- }
23
-
24
- /**
25
- * This will return the short summary why this rule show up as issue
26
- *
27
- * @return string
28
- */
29
- function getErrorReason() {
30
- return __( "User enumeration is currently allowed.", "defender-security" );
31
- }
32
-
33
- /**
34
- * This will return a short summary to show why this rule works
35
- * @return mixed
36
- */
37
- function getSuccessReason() {
38
- return __( "User enumeration is currently blocked, nice work!", "defender-security" );
39
- }
40
-
41
- /**
42
- * @return mixed
43
- */
44
- function check() {
45
- return $this->getService()->check();
46
- }
47
-
48
- /**
49
- * implement the revert function
50
- *
51
- * @return mixed
52
- */
53
- function revert() {
54
- $this->getService()->revert();
55
- Settings::instance()->addToIssues( self::$slug );
56
- }
57
-
58
- /**
59
- * implement the process function
60
- * @return mixed
61
- */
62
- function process() {
63
- $this->getService()->process();
64
- Settings::instance()->addToResolved( self::$slug );
65
- }
66
-
67
- /**
68
- * @return mixed
69
- */
70
- function getTitle() {
71
- return __( "Prevent user enumeration", "defender-security" );
72
- }
73
-
74
- /**
75
- * Return Service class
76
- * @return Prevent_Enum_Users_Service
77
- */
78
- function getService() {
79
- if ( self::$service == null ) {
80
- self::$service = new Prevent_Enum_Users_Service();
81
- }
82
-
83
- return self::$service;
84
- }
85
-
86
- /**
87
- * @return mixed
88
- */
89
- function addHooks() {
90
- $this->addAction( 'processingHardener' . self::$slug, 'process' );
91
- $this->addAction( 'processRevert' . self::$slug, 'revert' );
92
- $flag = Settings::instance()->getDValues( Prevent_Enum_Users_Service::CACHE_KEY );
93
- if ( php_sapi_name() == 'cli' ) {
94
- //in cli, ignore this
95
- $flag = 0;
96
- }
97
- if ( $flag == 1 ) {
98
- if ( ! is_admin() ) {
99
- // default URL format
100
- if ( ! isset( $_SERVER['QUERY_STRING'] ) ) {
101
- return;
102
- }
103
-
104
- if ( preg_match( '/author=([0-9]*)/i', $_SERVER['QUERY_STRING'] ) ) {
105
- wp_die( __( 'Sorry, you are not allowed to access this page', "defender-security" ) );
106
- }
107
- $this->addFilter( 'redirect_canonical', 'checkEnum', 10, 2 );
108
- }
109
- }
110
- }
111
-
112
- /**
113
- * @param $redirect
114
- * @param $request
115
- *
116
- * @return mixed
117
- */
118
- public function checkEnum( $redirect, $request ) {
119
- if ( preg_match( '/\?author=([0-9]*)(\/*)/i', $request ) ) {
120
- wp_die( __( 'Sorry, you are not allowed to access this page', "defender-security" ) );
121
- }
122
-
123
- return $redirect;
124
- }
125
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/prevent-php-service.php DELETED
@@ -1,95 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\WP_Helper;
9
- use Hammer\Helper\Log_Helper;
10
- use WP_Defender\Behavior\Utils;
11
- use WP_Defender\Component\Error_Code;
12
- use WP_Defender\Module\Hardener\IRule_Service;
13
- use WP_Defender\Module\Hardener\Rule_Service;
14
-
15
- class Prevent_PHP_Service extends Rule_Service implements IRule_Service {
16
-
17
- /**
18
- * @return bool
19
- */
20
- public function check() {
21
- $cache = WP_Helper::getArrayCache()->get( 'Prevent_PHP_Service', null );
22
- if ( $cache === null ) {
23
- //init upload dir and a php file
24
- Utils::instance()->getDefUploadDir();
25
- $url = WP_Helper::getUploadUrl();
26
- $url = $url . '/wp-defender/index.php';
27
- $headers = $this->headRequest( $url, 'Prevent PHP Execution', strtotime( '+1 day' ) );
28
-
29
- if ( is_wp_error( $headers ) ) {
30
- Utils::instance()->log( sprintf( 'Self ping error: %s', $headers->get_error_message() ), 'tweaks' );
31
-
32
- return false;
33
- }
34
-
35
- if ( 200 == $headers['response_code'] ) {
36
- WP_Helper::getArrayCache()->set( 'Prevent_PHP_Service', false );
37
-
38
- return false;
39
- }
40
- WP_Helper::getArrayCache()->set( 'Prevent_PHP_Service', true );
41
-
42
- return true;
43
- } else {
44
- return $cache;
45
- }
46
- }
47
-
48
- /**
49
- * Return the nginx rules use to put in site-enabled config files
50
- * @return string
51
- */
52
- public function getNginxRules() {
53
- if ( DIRECTORY_SEPARATOR == '\\' ) {
54
- //Windows
55
- $wp_includes = str_replace( ABSPATH, '', WPINC );
56
- $wp_content = str_replace( ABSPATH, '', WP_CONTENT_DIR );
57
- } else {
58
- $wp_includes = str_replace( $_SERVER['DOCUMENT_ROOT'], '', ABSPATH . WPINC );
59
- $wp_content = str_replace( $_SERVER['DOCUMENT_ROOT'], '', WP_CONTENT_DIR );
60
- }
61
-
62
- $rules = "# Stop php access except to needed files in wp-includes
63
- location ~* ^$wp_includes/.*(?<!(js/tinymce/wp-tinymce))\.php$ {
64
- internal; #internal allows ms-files.php rewrite in multisite to work
65
- }
66
-
67
- # Specifically locks down upload directories in case full wp-content rule below is skipped
68
- location ~* /(?:uploads|files)/.*\.php$ {
69
- deny all;
70
- }
71
-
72
- # Deny direct access to .php files in the /wp-content/ directory (including sub-folders).
73
- # Note this can break some poorly coded plugins/themes, replace the plugin or remove this block if it causes trouble
74
- location ~* ^$wp_content/.*\.php$ {
75
- deny all;
76
- }
77
- ";
78
-
79
- return $rules;
80
- }
81
-
82
- /**
83
- * @return bool|\WP_Error
84
- */
85
- public function process() {
86
- return new \WP_Error( Error_Code::INVALID, __( "Process is not possible on your current server", "defender-security" ) );
87
- }
88
-
89
- /**
90
- * @return bool|\WP_Error
91
- */
92
- public function revert() {
93
- return new \WP_Error( Error_Code::INVALID, __( "Revert is not possible on your current server", "defender-security" ) );
94
- }
95
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/prevent-php.php DELETED
@@ -1,212 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\WP_Helper;
9
- use Hammer\Helper\HTTP_Helper;
10
- use WP_Defender\Module\Hardener\Model\Settings;
11
- use WP_Defender\Module\Hardener\Rule;
12
- use WP_Defender\Module\Hardener\Component\Servers\Apache_Service;
13
- use WP_Defender\Module\Hardener\Component\Servers\Iis_Service;
14
-
15
- class Prevent_Php extends Rule {
16
- static $slug = 'prevent-php-executed';
17
- static $service;
18
- static $apache_service;
19
- static $iis_service;
20
-
21
- function getDescription() {
22
- $this->renderPartial( 'rules/prevent-php-executed' );
23
- }
24
-
25
- /**
26
- * This will return the short summary why this rule show up as issue
27
- *
28
- * @return string
29
- */
30
- function getErrorReason() {
31
- return __( "PHP execution is currently allowed in all directories.", "defender-security" );
32
- }
33
-
34
- /**
35
- * This will return a short summary to show why this rule works
36
- * @return mixed
37
- */
38
- function getSuccessReason() {
39
- return __( "You've disabled PHP execution, good stuff.", "defender-security" );
40
- }
41
-
42
- /**
43
- * @return bool|false|mixed|null
44
- */
45
- function check() {
46
- return $this->getService()->check();
47
- }
48
-
49
- public function getMiscData() {
50
- $settings = Settings::instance();
51
-
52
- return [
53
- 'active_server' => $settings->active_server,
54
- 'nginx_rules' => $this->getService()->getNginxRules(),
55
- 'wp_content_dir' => WP_CONTENT_DIR
56
- ];
57
- }
58
-
59
- /**
60
- * @return string|void
61
- */
62
- public function getTitle() {
63
- return __( "Prevent PHP execution", "defender-security" );
64
- }
65
-
66
-
67
- function revert() {
68
- $settings = Settings::instance();
69
- $server = $settings->active_server;
70
- if ( in_array( $settings->active_server, array( 'apache', 'litespeed' ) ) ) {
71
- $service = $this->getApacheService();
72
- $service->setHtConfig( $settings->getNewHtConfig() );
73
- } else if ( $server == 'iis-7' ) {
74
- $service = $this->getIisService();
75
- } else {
76
- $service = $this->getService();
77
- }
78
- $ret = $service->revert();
79
- if ( ! is_wp_error( $ret ) ) {
80
- if ( in_array( $settings->active_server, array( 'apache', 'litespeed' ) ) ) {
81
- $settings->saveExcludedFilePaths( array() );
82
- $settings->saveNewHtConfig( array() );
83
- }
84
- $url = WP_Helper::getUploadUrl();
85
- $url = $url . '/wp-defender/index.php';
86
- $this->getService()->clearHeadRequest( $url );
87
- $settings->addToIssues( self::$slug );
88
- } else {
89
- wp_send_json_error( array(
90
- 'message' => $ret->get_error_message()
91
- ) );
92
- }
93
- }
94
-
95
- function addHooks() {
96
- $this->addAction( 'processingHardener' . self::$slug, 'process', 10, 2 );
97
- $this->addAction( 'processRevert' . self::$slug, 'revert' );
98
- $this->addAction( 'processUpdate' . self::$slug, 'update', 10, 2 );
99
- }
100
-
101
- function process() {
102
- $file_paths = HTTP_Helper::retrievePost( 'file_paths' ); //File paths to ignore. Apache and litespeed mainly
103
- if ( $file_paths ) {
104
- $file_paths = sanitize_textarea_field( $file_paths );
105
- } else {
106
- $file_paths = '';
107
- }
108
- $server = HTTP_Helper::retrievePost( 'current_server' ); //Current server
109
-
110
- if ( in_array( $server, array( 'apache', 'litespeed' ) ) ) {
111
- $service = $this->getApacheService();
112
- $service->setExcludeFilePaths( $file_paths ); //Set the paths
113
- } else if ( $server == 'iis-7' ) {
114
- $service = $this->getIisService();
115
- } else {
116
- $service = $this->getService();
117
- }
118
- $ret = $service->process();
119
- if ( ! is_wp_error( $ret ) ) {
120
- $settings = Settings::instance();
121
- $url = WP_Helper::getUploadUrl();
122
- $url = $url . '/wp-defender/index.php';
123
- $this->getService()->clearHeadRequest( $url );
124
- $ret = $this->getService()->check();
125
- if ( $ret == false ) {
126
- wp_send_json_error( [
127
- 'message' => __( "The rules can't apply to your host. This can because of your host doesn't allow for overriding, or you apply for the wrong webserver", "defender-security" )
128
- ] );
129
- }
130
- $settings->saveExcludedFilePaths( $service->getExcludedFilePaths() );
131
- $settings->saveNewHtConfig( $service->getNewHtConfig() );
132
- $settings->setActiveServer( $server );
133
- $settings->addToResolved( self::$slug );
134
- $this->getService()->clearHeadRequest( $url );
135
- } else {
136
- wp_send_json_error( array(
137
- 'message' => $ret->get_error_message()
138
- ) );
139
- }
140
- }
141
-
142
- function update() {
143
- if ( ! $this->verifyNonce() ) {
144
- return;
145
- }
146
- $settings = Settings::instance();
147
-
148
- $file_paths = HTTP_Helper::retrievePost( 'file_paths' ); //File paths to ignore. Apache and litespeed mainly
149
- if ( $file_paths ) {
150
- $file_paths = sanitize_textarea_field( $file_paths );
151
- } else {
152
- $file_paths = '';
153
- }
154
-
155
- $server = HTTP_Helper::retrievePost( 'current_server' ); //Current server
156
-
157
- if ( in_array( $server, array( 'apache', 'litespeed' ) ) ) {
158
- $service = $this->getApacheService();
159
- $service->setHtConfig( $settings->getNewHtConfig() ); //Set the previous template
160
- $service->unProtectContentDir(); //revert first
161
- $service->setExcludeFilePaths( $file_paths ); //Set the paths
162
- } else {
163
- $service = $this->getService();
164
- }
165
- $ret = $service->process();
166
- if ( ! is_wp_error( $ret ) ) {
167
- if ( in_array( $server, array( 'apache', 'litespeed' ) ) ) {
168
- $settings->saveExcludedFilePaths( $service->getExcludedFilePaths() );
169
- $settings->saveNewHtConfig( $service->getNewHtConfig() );
170
- }
171
- $settings->setActiveServer( $server );
172
- $settings->save();
173
- } else {
174
- wp_send_json_error( array(
175
- 'message' => $ret->get_error_message()
176
- ) );
177
- }
178
- }
179
-
180
- /**
181
- * @return Prevent_PHP_Service
182
- */
183
- public function getService() {
184
- if ( self::$service == null ) {
185
- self::$service = new Prevent_PHP_Service();
186
- }
187
-
188
- return self::$service;
189
- }
190
-
191
- /**
192
- * @return Apache_Service
193
- */
194
- public function getApacheService() {
195
- if ( self::$apache_service == null ) {
196
- self::$apache_service = new Apache_Service();
197
- }
198
-
199
- return self::$apache_service;
200
- }
201
-
202
- /**
203
- * @return Iis_Service
204
- */
205
- public function getIisService() {
206
- if ( self::$iis_service == null ) {
207
- self::$iis_service = new Iis_Service();
208
- }
209
-
210
- return self::$iis_service;
211
- }
212
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/protect-information-service.php DELETED
@@ -1,191 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\WP_Helper;
9
- use WP_Defender\Behavior\Utils;
10
- use WP_Defender\Component\Error_Code;
11
- use WP_Defender\Module\Hardener\IRule_Service;
12
- use WP_Defender\Module\Hardener\Rule_Service;
13
-
14
- class Protect_Information_Service extends Rule_Service implements IRule_Service {
15
-
16
- /**
17
- * @return bool
18
- */
19
- public function check() {
20
- $cache = WP_Helper::getArrayCache()->get( 'Protect_Information_Service', null );
21
- if ( $cache === null ) {
22
- $url = wp_defender()->getPluginUrl() . 'languages/wpdef-default.pot';
23
- $headers = $this->headRequest( $url, 'Protect Information', strtotime( '+1 day' ) );
24
-
25
- if ( is_wp_error( $headers ) ) {
26
- Utils::instance()->log( sprintf( 'Self ping error: %s', $headers->get_error_message() ), 'tweaks' );
27
-
28
- return false;
29
- }
30
-
31
- if ( 200 == $headers['response_code'] ) {
32
- WP_Helper::getArrayCache()->set( 'Protect_Information_Service', false );
33
-
34
- return false;
35
- }
36
- WP_Helper::getArrayCache()->set( 'Protect_Information_Service', true );
37
-
38
- return true;
39
- } else {
40
- return $cache;
41
- }
42
- }
43
-
44
- /**
45
- * @return bool|\WP_Error
46
- */
47
- public function process() {
48
- $htPath = ABSPATH . '.htaccess';
49
- if ( ! is_file( $htPath ) ) {
50
- file_put_contents( $htPath, '', LOCK_EX );
51
- }
52
- if ( ! is_writeable( $htPath ) ) {
53
- return new \WP_Error( Error_Code::NOT_WRITEABLE,
54
- sprintf( __( "The file %s is not writable", "defender-security" ), $htPath ) );
55
- }
56
- $htConfig = file( $htPath );
57
- $htConfig = array_map( 'trim', $htConfig );
58
- $rules = $this->apache_rule();
59
- $containsSearch = array_diff( array_map( 'trim', $rules ), $htConfig );
60
- if ( count( $containsSearch ) < count( $rules ) ) {
61
- //search the wrapper block
62
- $htContent = file_get_contents( $htPath );
63
- preg_match( '/## WP Defender(.*?)## WP Defender - End ##/s', $htContent, $matches );
64
- if ( count( $matches ) ) {
65
- //remove the whole parts as it partial done
66
- $htContent = str_replace( $matches[0], '', $htContent );
67
- $htConfig = explode( PHP_EOL, $htContent );
68
- $htConfig = array_merge( $htConfig, $rules );
69
- file_put_contents( $htPath, implode( PHP_EOL, $htConfig ), LOCK_EX );
70
- }
71
- } elseif ( count( $containsSearch ) == 0 || ( count( $containsSearch ) == count( $rules ) ) ) {
72
- //append this
73
- $htConfig = array_merge( $htConfig, $rules );
74
- file_put_contents( $htPath, implode( PHP_EOL, $htConfig ), LOCK_EX );
75
- }
76
- $url = wp_defender()->getPluginUrl() . 'languages/wpdef-default.pot';
77
- $this->clearHeadRequest( $url );
78
- if ( ! $this->check() ) {
79
- wp_send_json_error( [
80
- 'message' => __( "The rules can't apply to your host. This can because of your host doesn't allow for overriding, or you apply for the wrong webserver", "defender-security" )
81
- ] );
82
- }
83
-
84
- return true;
85
- }
86
-
87
- /**
88
- * @return bool|\WP_Error
89
- */
90
- public function revert() {
91
- global $is_apache;
92
- if ( $is_apache ) {
93
- $htPath = ABSPATH . '.htaccess';
94
- if ( ! is_writeable( $htPath ) ) {
95
- return new \WP_Error( Error_Code::NOT_WRITEABLE,
96
- sprintf( __( "The file %s is not writable", "defender-security" ), $htPath ) );
97
- }
98
- $htConfig = file_get_contents( $htPath );
99
- $rules = $this->apache_rule();
100
-
101
- preg_match_all( '/## WP Defender(.*?)## WP Defender - End ##/s', $htConfig, $matches );
102
- if ( is_array( $matches ) && count( $matches ) > 0 ) {
103
- $htConfig = str_replace( implode( '', $matches[0] ), '', $htConfig );
104
- } else {
105
- $htConfig = str_replace( implode( '', $rules ), '', $htConfig );
106
- }
107
- $htConfig = trim( $htConfig );
108
- file_put_contents( $htPath, $htConfig, LOCK_EX );
109
- $url = wp_defender()->getPluginUrl() . 'languages/wpdef-default.pot';
110
- $this->clearHeadRequest( $url );
111
-
112
- return true;
113
- } else {
114
- //Other servers we cant revert
115
- return new \WP_Error( Error_Code::INVALID, __( "Revert is not possible on your current server", "defender-security" ) );
116
- }
117
- }
118
-
119
- public function getNginxRules() {
120
- if ( DIRECTORY_SEPARATOR == '\\' ) {
121
- //Windows
122
- $wp_includes = str_replace( ABSPATH, '', WPINC );
123
- $wp_content = str_replace( ABSPATH, '', WP_CONTENT_DIR );
124
- } else {
125
- $wp_includes = str_replace( $_SERVER['DOCUMENT_ROOT'], '', ABSPATH . WPINC );
126
- $wp_content = str_replace( $_SERVER['DOCUMENT_ROOT'], '', WP_CONTENT_DIR );
127
- }
128
-
129
- $rules = "# Turn off directory indexing
130
- autoindex off;
131
-
132
- # Deny access to htaccess and other hidden files
133
- location ~ /\. {
134
- deny all;
135
- }
136
-
137
- # Deny access to wp-config.php file
138
- location = /wp-config.php {
139
- deny all;
140
- }
141
-
142
- # Deny access to revealing or potentially dangerous files in the /wp-content/ directory (including sub-folders)
143
- location ~* ^$wp_content/.*\.(md|exe|sh|bak|inc|pot|po|mo|log|sql)$ {
144
- deny all;
145
- }
146
- ";
147
-
148
- return $rules;
149
- }
150
-
151
- /**
152
- * Get Apache rule depending on the version
153
- *
154
- * @return array
155
- */
156
- protected static function apache_rule() {
157
- $version = Utils::instance()->determineApacheVersion();
158
- if ( floatval( $version ) >= 2.4 ) {
159
- $rules = array(
160
- PHP_EOL . '## WP Defender - Prevent information disclosure ##' . PHP_EOL,
161
- '<FilesMatch "\.(md|exe|sh|bak|inc|pot|po|mo|log|sql)$">' . PHP_EOL .
162
- 'Require all denied' . PHP_EOL .
163
- '</FilesMatch>' . PHP_EOL,
164
- '<Files robots.txt>' . PHP_EOL .
165
- 'Require all granted' . PHP_EOL .
166
- '</Files>' . PHP_EOL,
167
- '<Files ads.txt>' . PHP_EOL .
168
- 'Require all granted' . PHP_EOL .
169
- '</Files>' . PHP_EOL,
170
- '## WP Defender - End ##'
171
- );
172
- } else {
173
- $rules = array(
174
- PHP_EOL . '## WP Defender - Prevent information disclosure ##' . PHP_EOL,
175
- '<FilesMatch "\.(md|exe|sh|bak|inc|pot|po|mo|log|sql)$">' . PHP_EOL .
176
- 'Order allow,deny' . PHP_EOL .
177
- 'Deny from all' . PHP_EOL .
178
- '</FilesMatch>' . PHP_EOL,
179
- '<Files robots.txt>' . PHP_EOL .
180
- 'Allow from all' . PHP_EOL .
181
- '</Files>' . PHP_EOL,
182
- '<Files ads.txt>' . PHP_EOL .
183
- 'Allow from all' . PHP_EOL .
184
- '</Files>' . PHP_EOL,
185
- '## WP Defender - End ##'
186
- );
187
- }
188
-
189
- return $rules;
190
- }
191
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/protect-information.php DELETED
@@ -1,94 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\WP_Helper;
9
- use WP_Defender\Module\Hardener\Model\Settings;
10
- use WP_Defender\Module\Hardener\Rule;
11
-
12
- class Protect_Information extends Rule {
13
- static $slug = 'protect-information';
14
- static $service;
15
-
16
- function getDescription() {
17
- $this->renderPartial( 'rules/protect-information' );
18
- }
19
-
20
- /**
21
- * This will return the short summary why this rule show up as issue
22
- *
23
- * @return string
24
- */
25
- function getErrorReason() {
26
- return __( "You don't have information disclosure protection active.", "defender-security" );
27
- }
28
-
29
- /**
30
- * This will return a short summary to show why this rule works
31
- * @return mixed
32
- */
33
- function getSuccessReason() {
34
- return __( "You've automatically enabled information disclosure protection.", "defender-security" );
35
- }
36
-
37
- public function getMiscData() {
38
- $settings = Settings::instance();
39
-
40
- return [
41
- 'active_server' => $settings->active_server,
42
- 'nginx_rules' => $this->getService()->getNginxRules(),
43
- ];
44
- }
45
-
46
- /**
47
- * @return bool|false|mixed|null
48
- */
49
- function check() {
50
- return $this->getService()->check();
51
- }
52
-
53
- public function getTitle() {
54
- return __( "Prevent Information Disclosure", "defender-security" );
55
- }
56
-
57
- function revert() {
58
- $ret = $this->getService()->revert();
59
- if ( ! is_wp_error( $ret ) ) {
60
- Settings::instance()->addToIssues( self::$slug );
61
- } else {
62
- wp_send_json_error( array(
63
- 'message' => $ret->get_error_message()
64
- ) );
65
- }
66
- }
67
-
68
- function addHooks() {
69
- $this->addAction( 'processingHardener' . self::$slug, 'process' );
70
- $this->addAction( 'processRevert' . self::$slug, 'revert' );
71
- }
72
-
73
- function process() {
74
- $ret = $this->getService()->process();
75
- if ( ! is_wp_error( $ret ) ) {
76
- Settings::instance()->addToResolved( self::$slug );
77
- } else {
78
- wp_send_json_error( array(
79
- 'message' => $ret->get_error_message()
80
- ) );
81
- }
82
- }
83
-
84
- /**
85
- * @return Protect_Information_Service
86
- */
87
- public function getService() {
88
- if ( self::$service == null ) {
89
- self::$service = new Protect_Information_Service();
90
- }
91
-
92
- return self::$service;
93
- }
94
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/security-key-service.php DELETED
@@ -1,137 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\WP_Helper;
9
- use WP_Defender\Component\Error_Code;
10
- use WP_Defender\Module\Hardener\IRule_Service;
11
- use WP_Defender\Module\Hardener\Model\Settings;
12
- use WP_Defender\Module\Hardener\Rule_Service;
13
-
14
- class Security_Key_Service extends Rule_Service implements IRule_Service {
15
- const CACHE_KEY = 'security_key';
16
- const DEFAULT_DAYS = '60 days';
17
-
18
- /**
19
- * @return bool
20
- */
21
- public function check() {
22
- $last = Settings::instance()->getDValues( self::CACHE_KEY );
23
- $reminder = Settings::instance()->getDValues( 'securityReminderDate' );
24
- $interval = Settings::instance()->getDValues( 'securityReminderDuration' );
25
- if ( $interval == null ) {
26
- $interval = self::DEFAULT_DAYS;
27
- }
28
- if ( ! $last ) {
29
- if ( file_exists( ABSPATH . 'wp-config' ) ) {
30
- $last = filemtime( ABSPATH . 'wp-config' );
31
- } else {
32
- //looks like the site is new instance, we should get the date from files
33
- $last = filemtime( ABSPATH . WPINC . '/general-template.php' );
34
- }
35
- }
36
-
37
- if ( $last ) {
38
- //date we should remind user
39
- $reminder = strtotime( '+' . $interval, $last );
40
- if ( $reminder < time() ) {
41
- return false;
42
- }
43
-
44
- return true;
45
- }
46
-
47
- return false;
48
- }
49
-
50
- /**
51
- * @return bool|\WP_Error
52
- */
53
- public function process() {
54
- $config_path = $this->retrieveWPConfigPath();
55
- //check if can write
56
- if ( ! is_writeable( $config_path ) ) {
57
- return new \WP_Error( Error_Code::NOT_WRITEABLE,
58
- sprintf( __( "The file %s is not writable", "defender-security" ), $config_path ) );
59
- }
60
-
61
- return $this->generateSalt( $config_path );
62
-
63
- }
64
-
65
- public function revert() {
66
- Settings::instance()->setDValues( self::CACHE_KEY, null );
67
- Settings::instance()->setDValues( 'securityReminderDate', null );
68
- }
69
-
70
- /**
71
- * This function will check & generate new salt if needed
72
- * Cover case
73
- * All salt provided in wp-config
74
- * No salt in wp-config
75
- * Partial salt (missing some) in wp-config
76
- *
77
- * @param null $path
78
- *
79
- * @return bool|\WP_Error
80
- */
81
- private function generateSalt( $path ) {
82
- $const = array(
83
- 'AUTH_KEY',
84
- 'SECURE_AUTH_KEY',
85
- 'LOGGED_IN_KEY',
86
- 'NONCE_KEY',
87
- 'AUTH_SALT',
88
- 'SECURE_AUTH_SALT',
89
- 'LOGGED_IN_SALT',
90
- 'NONCE_SALT',
91
- );
92
- $config = file( $path );
93
- //we need a place where we can inject the define in case wp config missing
94
- $hook_line = false;
95
- $missing = array();
96
- foreach ( $const as $key ) {
97
- //generate salt
98
- $salt = wp_generate_password( 64, true, true );
99
- //replace it to the wp config
100
- if ( defined( $key ) ) {
101
- $old_salt = constant( $key );
102
- //replace
103
- foreach ( $config as $index => $line ) {
104
- $line = trim( $line );
105
-
106
- $pattern = '/^define\(\s*(\'|\")' . $key . '(\'|\")\s*,\s*(\'|\")' . preg_quote( $old_salt, '/' ) . '(\'|\")\s*\)/';
107
-
108
- if ( preg_match( $pattern, $line ) === 1 ) {
109
- //match
110
- $new_line = "define( '$key', '$salt' );" . PHP_EOL;
111
- $config[ $index ] = $new_line;
112
- if ( $hook_line === false ) {
113
- $hook_line = $index;
114
- }
115
- //break out of the config line loop
116
- break;
117
- }
118
- }
119
- } else {
120
- //we don't have any key like this, so we will inject
121
- $missing[] = $key;
122
- }
123
- }
124
- //now check the missing
125
- if ( count( $missing ) ) {
126
- //for any reason we missing a security key, this mean wp-config altered by 3rd party, halt
127
- return new \WP_Error( Error_Code::UNKNOWN_WPCONFIG, __( "Defender can't recognize your wp-config.php, please revert it to original state for further process.", "defender-security" ) );
128
- }
129
-
130
- //we already check for perm above, no need to check again
131
- //lock the file
132
- file_put_contents( $path, implode( '', $config ), LOCK_EX );
133
- Settings::instance()->setDValues( self::CACHE_KEY, time() );
134
-
135
- return true;
136
- }
137
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/security-key.php DELETED
@@ -1,166 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use Hammer\Helper\WP_Helper;
10
- use WP_Defender\Behavior\Endpoint;
11
- use WP_Defender\Behavior\Utils;
12
- use WP_Defender\Module\Advanced_Tools\Component\Mask_Api;
13
- use WP_Defender\Module\Hardener;
14
- use WP_Defender\Module\Hardener\Model\Settings;
15
- use WP_Defender\Module\Hardener\Rule;
16
-
17
- class Security_Key extends Rule {
18
- static $slug = 'security-key';
19
- static $service;
20
-
21
- function getDescription() {
22
- $settings = Settings::instance();
23
- $time = $settings->getDValues( Security_Key_Service::CACHE_KEY );
24
- $interval = $settings->getDValues( 'securityReminderDuration' );
25
- if ( ! $interval ) {
26
- $interval = Security_Key_Service::DEFAULT_DAYS;
27
- }
28
- if ( $time ) {
29
- $daysAgo = ( time() - $time ) / ( 60 * 60 * 24 );
30
- } else {
31
- $daysAgo = __( "unknown", "defender-security" );
32
- }
33
-
34
- $this->renderPartial( 'rules/security-key', array(
35
- 'interval' => $interval,
36
- 'daysAgo' => $daysAgo
37
- ) );
38
- }
39
-
40
- private function calculateDaysApplied() {
41
- $settings = Settings::instance();
42
- $time = $settings->getDValues( Security_Key_Service::CACHE_KEY );
43
- $timestamp = filemtime( ABSPATH . '/' . WPINC . '/general-template.php' );
44
- $interval = $settings->getDValues( 'securityReminderDuration' );
45
- if ( ! $interval ) {
46
- $interval = Security_Key_Service::DEFAULT_DAYS;
47
- }
48
- $daysAgo = __( "unknown", "defender-security" );
49
- if ( $time ) {
50
- $daysAgo = ( time() - $time ) / ( 60 * 60 * 24 );
51
- } elseif ( $timestamp != false ) {
52
- $daysAgo = ( time() - $timestamp ) / ( 60 * 60 * 24 );
53
- }
54
- if ( $daysAgo != __( "unknown", "defender-security" ) ) {
55
- $daysAgo = round( $daysAgo );
56
- if ( $daysAgo == 0 ) {
57
- $daysAgo = 1;
58
- }
59
- }
60
-
61
- return $daysAgo;
62
- }
63
-
64
- /**
65
- * This will return the short summary why this rule show up as issue
66
- *
67
- * @return string
68
- */
69
- function getErrorReason() {
70
- if ( $this->calculateDaysApplied() == __( "unknown", "defender-security" ) ) {
71
- return __( "We can’t tell how old your security keys are, perhaps it’s time to update them?", "defender-security" );
72
- }
73
-
74
- return sprintf( __( "Your current security keys are %s days old. Time to update them!", "defender-security" ), $this->calculateDaysApplied() );
75
- }
76
-
77
- /**
78
- * This will return a short summary to show why this rule works
79
- * @return mixed
80
- */
81
- function getSuccessReason() {
82
- return sprintf( __( "Your security keys are less than %s days old, nice work.", "defender-security" ), $this->calculateDaysApplied() );
83
- }
84
-
85
- /**
86
- * @return string
87
- */
88
- function getTitle() {
89
- return __( "Update old security keys", "defender-security" );
90
- }
91
-
92
- function check() {
93
- return $this->getService()->check();
94
- }
95
-
96
- function addHooks() {
97
- $this->addAction( 'processingHardener' . self::$slug, 'process' );
98
- $namespace = 'wp-defender/v1';
99
- $namespace .= '/tweaks';
100
- $routes = [
101
- $namespace . '/updateSecurityReminder' => 'updateSecurityReminder',
102
- ];
103
- $this->registerEndpoints( $routes, Hardener::getClassName() );
104
- }
105
-
106
- public function getMiscData() {
107
- $settings = Settings::instance();
108
- $reminder = $settings->getDValues( 'securityReminderDuration' );
109
- if ( $reminder == null ) {
110
- $reminder = Security_Key_Service::DEFAULT_DAYS;
111
- }
112
-
113
- return [
114
- 'reminder' => $reminder,
115
- ];
116
- }
117
-
118
- public function updateSecurityReminder() {
119
- if ( ! Utils::instance()->checkPermission() ) {
120
- return;
121
- }
122
-
123
- $reminder = HTTP_Helper::retrievePost( 'remind_date', null );
124
-
125
- if ( $reminder ) {
126
- $settings = Settings::instance();
127
- $settings->setDValues( 'securityReminderDuration', $reminder );
128
- $settings->setDValues( 'securityReminderDate', strtotime( '+' . $reminder, current_time( 'timestamp' ) ) );
129
- }
130
- }
131
-
132
- function revert() {
133
-
134
- }
135
-
136
- function process() {
137
- $ret = $this->getService()->process();
138
- if ( is_wp_error( $ret ) ) {
139
- wp_send_json_error( array(
140
- 'message' => $ret->get_error_message()
141
- ) );
142
- } else {
143
- Settings::instance()->addToResolved( self::$slug );
144
- $url = wp_login_url( network_admin_url( 'admin.php?page=wdf-hardener' ) );
145
- if ( Mask_Api::isEnabled() ) {
146
- $url = Mask_Api::getNewLoginUrl();
147
- }
148
- wp_send_json_success( array(
149
- 'message' => sprintf( __( 'All key salts have been regenerated. You will now need to <a href="%s"><strong>re-login</strong></a>.<br/>This will auto reload after <span class="hardener-timer">3</span> seconds.', "defender-security" ), wp_login_url( network_admin_url( 'admin.php?page=wdf-hardener' ) ) ),
150
- 'reload' => 3,
151
- 'url' => $url
152
- ) );
153
- }
154
- }
155
-
156
- /**
157
- * @return Security_Key_Service
158
- */
159
- public function getService() {
160
- if ( self::$service == null ) {
161
- self::$service = new Security_Key_Service();
162
- }
163
-
164
- return self::$service;
165
- }
166
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/servers/apache-service.php DELETED
@@ -1,290 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Paul Kevin
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component\Servers;
7
-
8
- use WP_Defender\Behavior\Utils;
9
- use WP_Defender\Component\Error_Code;
10
- use WP_Defender\Module\Hardener\IRule_Service;
11
- use WP_Defender\Module\Hardener\Rule_Service;
12
-
13
- class Apache_Service extends Rule_Service implements IRule_Service {
14
-
15
- /**
16
- * Exclude file paths
17
- *
18
- * @var array|bool|mixed
19
- */
20
- private $exclude_file_paths = array();
21
-
22
- /**
23
- * New htaccess file
24
- *
25
- * @var array|bool|mixed
26
- */
27
- private $new_htconfig = array();
28
-
29
- /**
30
- * The htaccess inside wp-content
31
- * @var string
32
- */
33
- public $contentdir_path = null;
34
-
35
- /**
36
- * The htaccess path inside wp-includes
37
- * @var null
38
- */
39
- public $includedir_path = null;
40
-
41
- /**
42
- * @return bool
43
- */
44
- public function check() {
45
- return true;
46
- }
47
-
48
- /**
49
- * @return bool|\WP_Error
50
- */
51
- public function process() {
52
- $ret = $this->protectContentDir();
53
- if ( is_wp_error( $ret ) ) {
54
- return $ret;
55
- }
56
-
57
- $ret = $this->protectIncludesDir();
58
- if ( is_wp_error( $ret ) ) {
59
- return $ret;
60
- }
61
-
62
- $ret = $this->protectUploadsDir();
63
- if ( is_wp_error( $ret ) ) {
64
- return $ret;
65
- }
66
-
67
- return true;
68
- }
69
-
70
- public function protectContentDir() {
71
- $ht_path = $this->contentdir_path;
72
- if ( $ht_path == null ) {
73
- $ht_path = WP_CONTENT_DIR . '/' . '.htaccess';
74
- }
75
- if ( ! file_exists( $ht_path ) ) {
76
- if ( file_put_contents( $ht_path, '', LOCK_EX ) === false ) {
77
- return new \WP_Error( Error_Code::NOT_WRITEABLE,
78
- sprintf( __( "The file %s is not writable", "defender-security" ), $ht_path ) );
79
- }
80
- } elseif ( ! is_writeable( $ht_path ) ) {
81
- return new \WP_Error( Error_Code::NOT_WRITEABLE,
82
- sprintf( __( "The file %s is not writable", "defender-security" ), $ht_path ) );
83
- }
84
-
85
- $exists_rules = $this->cleanupOldRules( file_get_contents( $ht_path ) );
86
- $rule = [
87
- '## WP Defender - Protect PHP Executed ##',
88
- '<Files *.php>',
89
- $this->generateHtAccessRule( false ),
90
- '</Files>',
91
- ];
92
- if ( ! empty( $this->exclude_file_paths ) ) {
93
- foreach ( $this->exclude_file_paths as $file_path ) {
94
- $rule[] = sprintf( "<Files %s>", sanitize_file_name( $file_path ) );
95
- $rule[] = $this->generateHtAccessRule( true );
96
- $rule[] = "</Files>";
97
- }
98
- }
99
- $rule[] = '## WP Defender - End ##';
100
- file_put_contents( $ht_path, $exists_rules . implode( PHP_EOL, $rule ), LOCK_EX );
101
- }
102
-
103
- public function protectIncludesDir() {
104
- $ht_path = $this->includedir_path;
105
- if ( $ht_path == null ) {
106
- $ht_path = ABSPATH . WPINC . '/' . '.htaccess';
107
- }
108
- if ( ! is_file( $ht_path ) ) {
109
- if ( file_put_contents( $ht_path, '', LOCK_EX ) === false ) {
110
- return new \WP_Error( Error_Code::NOT_WRITEABLE,
111
- sprintf( __( "The file %s is not writable", "defender-security" ), $ht_path ) );
112
- }
113
- } elseif ( ! is_writeable( $ht_path ) ) {
114
- return new \WP_Error( Error_Code::NOT_WRITEABLE,
115
- sprintf( __( "The file %s is not writable", "defender-security" ), $ht_path ) );
116
- }
117
- $exists_rules = $this->cleanupOldRules( file_get_contents( $ht_path ) );
118
-
119
- $rule = [
120
- '## WP Defender - Protect PHP Executed ##',
121
- '<Files *.php>',
122
- $this->generateHtAccessRule( false ),
123
- '</Files>',
124
- '<Files wp-tinymce.php>',
125
- $this->generateHtAccessRule( true ),
126
- '</Files>',
127
- '<Files ms-files.php>',
128
- $this->generateHtAccessRule( true ),
129
- '</Files>',
130
- '## WP Defender - End ##',
131
- ];
132
- //no exclude here
133
- file_put_contents( $ht_path, $exists_rules . implode( PHP_EOL, $rule ), LOCK_EX );
134
- }
135
-
136
- /**
137
- * Protect uploads directory
138
- * This only when user provide a custom uploads
139
- */
140
- public function protectUploadsDir() {
141
- if ( defined( 'UPLOADS' ) ) {
142
- $this->contentdir_path = ABSPATH . UPLOADS . '/' . '.htaccess';
143
- //should be same with protect content dirs
144
- $this->protectContentDir();
145
- }
146
- }
147
-
148
- public function unProtectContentDir() {
149
- $ht_path = $this->contentdir_path;
150
- if ( $ht_path == null ) {
151
- $ht_path = WP_CONTENT_DIR . '/' . '.htaccess';
152
- }
153
- if ( ! file_exists( $ht_path ) ) {
154
- //do nothing
155
- return;
156
- }
157
- if ( ! is_writeable( $ht_path ) ) {
158
- return new \WP_Error( Error_Code::NOT_WRITEABLE,
159
- sprintf( __( "The file %s is not writable", "defender-security" ), $ht_path ) );
160
- }
161
- $ht_config = $this->cleanupOldRules( file_get_contents( $ht_path ) );
162
- $ht_config = trim( $ht_config );
163
- file_put_contents( $ht_path, trim( $ht_config ), LOCK_EX );
164
- }
165
-
166
- public function unProtectIncludeDir() {
167
- $ht_path = $this->includedir_path;
168
- if ( $ht_path == null ) {
169
- $ht_path = ABSPATH . WPINC . '/' . '.htaccess';
170
- }
171
- if ( ! is_writeable( $ht_path ) ) {
172
- return new \WP_Error( Error_Code::NOT_WRITEABLE,
173
- sprintf( __( "The file %s is not writable", "defender-security" ), $ht_path ) );
174
- }
175
- $ht_config = $this->cleanupOldRules( file_get_contents( $ht_path ) );
176
- file_put_contents( $ht_path, trim( $ht_config ), LOCK_EX );
177
- }
178
-
179
- public function unProtectUploadDir() {
180
- if ( defined( 'UPLOADS' ) ) {
181
- $this->contentdir_path = ABSPATH . UPLOADS . '/' . '.htaccess';
182
- $this->unProtectContentDir();
183
- }
184
- }
185
-
186
- /**
187
- * @return bool|\WP_Error
188
- */
189
- public function revert() {
190
- $ret = $this->unProtectContentDir();
191
- if ( is_wp_error( $ret ) ) {
192
- return $ret;
193
- }
194
-
195
- $ret = $this->unProtectIncludeDir();
196
- if ( is_wp_error( $ret ) ) {
197
- return $ret;
198
- }
199
- $ret = $this->unProtectUploadDir();
200
- if ( is_wp_error( $ret ) ) {
201
- return $ret;
202
- }
203
-
204
- return true;
205
- }
206
-
207
- /**
208
- * Set the exclude file paths
209
- *
210
- * @param String $paths
211
- */
212
- public function setExcludeFilePaths( $paths ) {
213
- if ( ! empty( $paths ) ) {
214
- $this->exclude_file_paths = explode( "\n", $paths );
215
- }
216
- }
217
-
218
-
219
- /**
220
- * Get the exclude file paths
221
- *
222
- * @return Array - $exclude_file_paths
223
- */
224
- public function getExcludedFilePaths() {
225
- return $this->exclude_file_paths;
226
- }
227
-
228
- /**
229
- * Set the exclude file paths
230
- *
231
- * @param String $paths
232
- */
233
- public function setHtConfig( $config = array() ) {
234
- if ( ! empty( $config ) ) {
235
- $this->new_htconfig = $config;
236
- }
237
- }
238
-
239
-
240
- /**
241
- * Get the new HT config
242
- *
243
- * @return Array - $new_htconfig
244
- */
245
- public function getNewHtConfig() {
246
- return $this->new_htconfig;
247
- }
248
-
249
- /**
250
- * @param $exists_rules
251
- *
252
- * @return string|string[]|null
253
- */
254
- private function cleanupOldRules( $exists_rules ) {
255
- $pattern = '/(## WP Defender - Protect PHP Executed ##((.|\n)*)## WP Defender - End ##)/';
256
- if ( preg_match( $pattern, $exists_rules ) ) {
257
- //replace it
258
- $exists_rules = preg_replace( $pattern, '', $exists_rules );
259
- }
260
- $exists_rules = trim( $exists_rules );
261
- if ( strlen( $exists_rules ) ) {
262
- $exists_rules .= PHP_EOL;
263
- }
264
-
265
- return $exists_rules;
266
- }
267
-
268
- /**
269
- * Return the correct apache rules for allow/deny
270
- *
271
- * @return String
272
- */
273
- protected function generateHtAccessRule( $allow = true ) {
274
- $version = Utils::instance()->determineApacheVersion();
275
- if ( floatval( $version ) >= 2.4 ) {
276
- if ( $allow ) {
277
- return 'Require all granted';
278
- } else {
279
- return 'Require all denied';
280
- }
281
- } else {
282
- if ( $allow ) {
283
- return 'Allow from all';
284
- } else {
285
- return 'Order allow,deny' . PHP_EOL .
286
- 'Deny from all';
287
- }
288
- }
289
- }
290
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/servers/iis-service.php DELETED
@@ -1,122 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Paul Kevin
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component\Servers;
7
-
8
- use WP_Defender\Component\Error_Code;
9
- use WP_Defender\Module\Hardener\IRule_Service;
10
- use WP_Defender\Module\Hardener\Rule_Service;
11
-
12
- /**
13
- * IIS 7 Service
14
- *
15
- * Protect th uploads directory
16
- */
17
- class Iis_Service extends Rule_Service implements IRule_Service {
18
-
19
- /**
20
- * @return bool
21
- */
22
- public function check() {
23
- return true;
24
- }
25
-
26
- public function process() {
27
- $path = WP_CONTENT_DIR . '/uploads';
28
- $filename = 'web.config';
29
- if ( ! file_exists( $path . '/' . $filename ) ) {
30
- $fp = fopen( $path . '/' . $filename, 'w' );
31
- fwrite( $fp, '<configuration/>' );
32
- fclose( $fp );
33
- }
34
-
35
- $formatxml = PHP_EOL;
36
- $formatxml = " <handlers accessPolicy=\"Read\" />";
37
- $formatxml .= PHP_EOL;
38
-
39
- $doc = new \DOMDocument();
40
- $doc->preserveWhiteSpace = true;
41
- if ( $doc->load( $path . '/' . $filename ) === false ) {
42
- return new \WP_Error( Error_Code::NOT_WRITEABLE,
43
- sprintf( __( "The file %s could not be loaded", "defender-security" ), $filename ) );
44
- }
45
- $xpath = new \DOMXPath( $doc );
46
- $read_accesspolicy = $xpath->query( '/configuration/system.webServer/handlers[starts-with(@accessPolicy,\'Read\')]' );
47
- if ( $read_accesspolicy->length > 0 ) {
48
- return true;
49
- }
50
-
51
- $xmlnodes = $xpath->query( '/configuration/system.webServer/handlers' );
52
- if ( $xmlnodes->length > 0 ) {
53
- $handlers_node = $xmlnodes->item(0);
54
- }
55
- else {
56
- $handlers_node = $doc->createElement( 'handlers' );
57
- $xmlnodes = $xpath->query( '/configuration/system.webServer' );
58
- if ( $xmlnodes->length > 0 ) {
59
- $system_webServer_node = $xmlnodes->item(0);
60
- $handler_fragment = $doc->createDocumentFragment();
61
- $handler_fragment->appendXML( $formatxml );
62
- $system_webServer_node->appendChild( $handler_fragment );
63
- }
64
- else {
65
- $system_webServer_node = $doc->createElement( 'system.webServer' );
66
- $handler_fragment = $doc->createDocumentFragment();
67
- $handler_fragment->appendXML( $formatxml );
68
- $system_webServer_node->appendChild( $handler_fragment );
69
-
70
- $xmlnodes = $xpath->query( '/configuration' );
71
- if ( $xmlnodes->length > 0 ) {
72
- $config_node = $xmlnodes->item(0);
73
- $config_node->appendChild( $system_webServer_node );
74
- }
75
- else {
76
- $config_node = $doc->createElement( 'configuration' );
77
- $doc->appendChild( $config_node );
78
- $config_node->appendChild( $system_webServer_node );
79
- }
80
- }
81
- }
82
-
83
- $rule_fragment = $doc->createDocumentFragment();
84
- $rule_fragment->appendXML( $formatxml );
85
- $handlers_node->appendChild( $rule_fragment );
86
-
87
- $doc->encoding = "UTF-8";
88
- $doc->formatOutput = true;
89
- saveDomDocument( $doc, $path .'/'. $filename );
90
- return true;
91
- }
92
-
93
- /**
94
- * @return bool|\WP_Error
95
- */
96
- public function revert() {
97
- $path = WP_CONTENT_DIR . '/uploads';
98
- $filename = 'web.config';
99
-
100
- if ( ! file_exists( $path . '/' . $filename ) ) {
101
- return true;
102
- }
103
-
104
- $doc = new DOMDocument();
105
- $doc->preserveWhiteSpace = false;
106
- if ( $doc->load( $path . '/' . $filename ) === false ) {
107
- return false;
108
- }
109
-
110
- $xpath = new DOMXPath( $doc );
111
- $handlers = $xpath->query( '/configuration/system.webServer/handlers[contains(@accessPolicy,\'Read\')]' );
112
- if ( $handlers->length > 0 ) {
113
- $child = $handlers->item(0);
114
- $parent = $child->parentNode;
115
- $parent->removeChild( $child );
116
- $doc->formatOutput = true;
117
- saveDomDocument( $doc, $path .'/'. $filename );
118
- }
119
- return true;
120
- }
121
- }
122
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/sh-content-security-service.php DELETED
@@ -1,173 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use WP_Defender\Component\Error_Code;
10
- use WP_Defender\Module\Hardener\IRule_Service;
11
- use WP_Defender\Module\Hardener\Model\Settings;
12
- use WP_Defender\Module\Hardener\Rule_Service;
13
-
14
- class Sh_Content_Security_Service extends Rule_Service implements IRule_Service {
15
- //the data we use for real
16
- const KEY_DATA = 'sh_content_security',
17
- //this is the data showing in test pharse
18
- KEY_TEMP_DATA = 'sh_content_security_temp',
19
- //this is the data queue for approval, passing from test
20
- KEY_STAGING_DATA = 'sh_content_security_staging';
21
-
22
- /**
23
- * @return bool
24
- */
25
- public function check() {
26
- $is_test = isset( $_COOKIE[ Sh_Content_Security::$slug . '-testing' ] );
27
- $is_staging = isset( $_COOKIE[ Sh_Content_Security::$slug . '-staging' ] );
28
-
29
- if ( $is_staging || $is_test ) {
30
- //this case we are in staging mode, so just return base on the current screen
31
- $settings = Settings::instance();
32
- $data = $settings->getDValues( self::KEY_DATA );
33
- if ( is_array( $data ) ) {
34
- $data = array_filter( $data );
35
- }
36
- unset( $data['somewhere'] );
37
- if ( ! ! $data == false || empty( $data ) ) {
38
- return false;
39
- }
40
-
41
- $keys = $this->getKeys();
42
- foreach ( $keys as $key ) {
43
- if ( isset( $data[ $key ] ) && $data[ $key ] == 1 ) {
44
-
45
- return true;
46
- }
47
- }
48
-
49
- return false;
50
- }
51
-
52
- $response = wp_remote_head( network_site_url() );
53
- if ( is_wp_error( $response ) ) {
54
- return false;
55
- }
56
- $headers = $response['headers'];
57
- if ( isset( $headers['content-security-policy'] ) ) {
58
- $settings = Settings::instance();
59
- $data = $settings->getDValues( self::KEY_DATA );
60
- if ( $data === null ) {
61
- $data['somewhere'] = true;
62
- $settings->setDValues( self::KEY_DATA, $data );
63
- }
64
-
65
- return true;
66
- }
67
-
68
- return false;
69
- }
70
-
71
- public function getKeys() {
72
- $keys = [
73
- 'base_uri',
74
- 'child_src',
75
- 'default_src',
76
- 'font_src',
77
- 'frame_ancestors',
78
- 'form_action',
79
- 'img_src',
80
- 'media_src',
81
- 'object_src',
82
- 'plugin_types',
83
- 'sandbox',
84
- 'script_src',
85
- 'style_src',
86
- 'worker_src',
87
- ];
88
-
89
- return $keys;
90
- }
91
-
92
- /**
93
- * @return bool|\WP_Error
94
- */
95
- public function process() {
96
- $params = [
97
- 'base_uri' => is_array( $_POST ) && isset( $_POST['base_uri'] ) ? $_POST['base_uri'] : 0,
98
- 'child_src' => is_array( $_POST ) && isset( $_POST['child_src'] ) ? $_POST['child_src'] : 0,
99
- 'default_src' => is_array( $_POST ) && isset( $_POST['default_src'] ) ? $_POST['default_src'] : 0,
100
- 'font_src' => is_array( $_POST ) && isset( $_POST['font_src'] ) ? $_POST['font_src'] : 0,
101
- 'frame_ancestors' => is_array( $_POST ) && isset( $_POST['frame_ancestors'] ) ? $_POST['frame_ancestors'] : 0,
102
- 'form_action' => is_array( $_POST ) && isset( $_POST['form_action'] ) ? $_POST['form_action'] : 0,
103
- 'img_src' => is_array( $_POST ) && isset( $_POST['img_src'] ) ? $_POST['img_src'] : 0,
104
- 'media_src' => is_array( $_POST ) && isset( $_POST['media_src'] ) ? $_POST['media_src'] : 0,
105
- 'object_src' => is_array( $_POST ) && isset( $_POST['object_src'] ) ? $_POST['object_src'] : 0,
106
- 'plugin_types' => is_array( $_POST ) && isset( $_POST['plugin_types'] ) ? $_POST['plugin_types'] : 0,
107
- 'sandbox' => is_array( $_POST ) && isset( $_POST['sandbox'] ) ? $_POST['sandbox'] : 0,
108
- 'script_src' => is_array( $_POST ) && isset( $_POST['script_src'] ) ? $_POST['script_src'] : 0,
109
- 'style_src' => is_array( $_POST ) && isset( $_POST['style_src'] ) ? $_POST['style_src'] : 0,
110
- 'worker_src' => is_array( $_POST ) && isset( $_POST['worker_src'] ) ? $_POST['worker_src'] : 0,
111
- 'url_ignores' => is_array( $_POST ) && isset( $_POST['url_ignores'] ) ? $_POST['url_ignores'] : "",
112
- 'base_uri_values' => is_array( $_POST ) && isset( $_POST['base_uri_values'] ) ? $_POST['base_uri_values'] : [],
113
- 'child_src_values' => is_array( $_POST ) && isset( $_POST['child_src_values'] ) ? $_POST['child_src_values'] : [],
114
- 'frame_ancestors_values' => is_array( $_POST ) && isset( $_POST['frame_ancestors_values'] ) ? $_POST['frame_ancestors_values'] : [],
115
- 'default_src_values' => is_array( $_POST ) && isset( $_POST['default_src_values'] ) ? $_POST['default_src_values'] : [],
116
- 'font_src_values' => is_array( $_POST ) && isset( $_POST['font_src_values'] ) ? $_POST['font_src_values'] : [],
117
- 'form_action_values' => is_array( $_POST ) && isset( $_POST['form_action_values'] ) ? $_POST['form_action_values'] : [],
118
- 'img_src_values' => is_array( $_POST ) && isset( $_POST['img_src_values'] ) ? $_POST['img_src_values'] : [],
119
- 'media_src_values' => is_array( $_POST ) && isset( $_POST['media_src_values'] ) ? $_POST['media_src_values'] : [],
120
- 'object_src_values' => is_array( $_POST ) && isset( $_POST['object_src_values'] ) ? $_POST['object_src_values'] : [],
121
- 'plugin_types_values' => is_array( $_POST ) && isset( $_POST['plugin_types_values'] ) ? $_POST['plugin_types_values'] : [],
122
- 'sandbox_values' => is_array( $_POST ) && isset( $_POST['sandbox_values'] ) ? $_POST['sandbox_values'] : [],
123
- 'script_src_values' => is_array( $_POST ) && isset( $_POST['script_src_values'] ) ? $_POST['script_src_values'] : [],
124
- 'style_src_values' => is_array( $_POST ) && isset( $_POST['style_src_values'] ) ? $_POST['style_src_values'] : [],
125
- 'worker_src_values' => is_array( $_POST ) && isset( $_POST['worker_src_values'] ) ? $_POST['worker_src_values'] : [],
126
- ];
127
- $scenario = HTTP_Helper::retrievePost( 'scenario' );
128
- $settings = Settings::instance();
129
- $data = $settings->getDValues( self::KEY_DATA );
130
- foreach ( $params as $key => $value ) {
131
- if ( is_array( $value ) ) {
132
- $value = array_map( 'stripslashes', $value );
133
- }
134
- if ( is_array( $value ) && empty( $value ) ) {
135
- //dont save this, and we remove the key of the trigger
136
- $trigger = str_replace( '_values', '', $key );
137
- unset( $data[ $trigger ] );
138
- continue;
139
- }
140
-
141
- $data[ $key ] = $value;
142
- }
143
-
144
- if ( $scenario == 'enforce' ) {
145
- unset( $data['somewhere'] );
146
- }
147
- //set enable flag
148
- if ( $scenario == 'temp' ) {
149
- /**
150
- * If this is temp then it is flaging for test, the flow will be
151
- * - store the flag in cookies
152
- * - reload page
153
- * - show a small banner for cancel, or apply the changes.
154
- */
155
- $settings->setDValues( self::KEY_TEMP_DATA, $data );
156
- setcookie( Sh_Content_Security::$slug . '-testing', true, 0, '', '', true, true );
157
- //clear the old staging
158
- setcookie( Sh_Content_Security::$slug . '-staging', false, - 1, '', '', true, true );
159
- //a simple flag to use while cookie being set
160
- } else {
161
- $settings->setDValues( self::KEY_DATA, $data );
162
- }
163
- }
164
-
165
- public function revert() {
166
- $settings = Settings::instance();
167
- $settings->setDValues( self::KEY_TEMP_DATA, null );
168
- }
169
-
170
- public function listen() {
171
-
172
- }
173
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/sh-content-security.php DELETED
@@ -1,331 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use WP_Defender\Module\Hardener\Model\Settings;
10
- use WP_Defender\Module\Hardener\Rule;
11
-
12
- class Sh_Content_Security extends Rule {
13
- static $slug = 'sh-content-security';
14
- static $service;
15
-
16
- public function getDescription() {
17
-
18
- }
19
-
20
- public function check() {
21
- return $this->getService()->check();
22
- }
23
-
24
- /**
25
- * @return array
26
- */
27
- public function getMiscData() {
28
- $settings = Settings::instance();
29
- $is_test = isset( $_COOKIE[ self::$slug . '-testing' ] );
30
- $is_staging = isset( $_COOKIE[ self::$slug . '-staging' ] );
31
- if ( $is_test ) {
32
- $data = $settings->getDValues( Sh_Content_Security_Service::KEY_TEMP_DATA );
33
- } elseif ( $is_staging ) {
34
- $data = $settings->getDValues( Sh_Content_Security_Service::KEY_STAGING_DATA );
35
- } else {
36
- $data = $settings->getDValues( Sh_Content_Security_Service::KEY_DATA );
37
- }
38
-
39
- return [
40
- 'is_opened' => $is_test || $is_staging,
41
- 'text' => [
42
- ///mix stirng with html should be parsed from php
43
- 'base_uri_text' => esc_html__( "Restricts the URLs which can be used in a document's <base> element. You can read more about this directive", "defender-security" ),
44
- 'base_uri_desc' => sprintf( __( "Example value for this directive can be <strong>%s</strong>. Press Enter to separate the values.", "defender-security" ), network_site_url() ),
45
- 'child_src_text' => __( "Defines the valid sources for web workers and nested browsing contexts loaded using elements such as &#x3C;frame&#x3E; and &#x3C;iframe&#x3E;. Note, that Instead of child-src, authors who wish to regulate nested browsing contexts and workers should use the <strong>frame-src</strong> and <strong>worker-src</strong> directives, respectively.", "defender-security" ),
46
- 'child_src_desc' => sprintf( __( "Example value for this directive can be <strong>%s</strong>. Press Enter to separate the values.", "defender-security" ), network_site_url() ),
47
- 'default_src_text' => __( "" ),
48
- 'default_src_desc' => sprintf( __( "Example value for this directive can be <strong>'unsafe-eval'</strong>; <strong>'unsafe-inline'</strong>; <strong>%s</strong>. Press Enter to separate the values.", "defender-security" ), network_site_url() ),
49
- 'font_src_desc' => __( "Example value for this directive can be <strong>font.example.com.</strong> Press Enter to separate the values.", "defender-security" ),
50
- 'form_action_desc' => __( "Example value for this directive can ba <strong>'self'</strong>. Press Enter to separate the values.", "defender-security" ),
51
- 'frame_ancestors_desc' => __( "Example value for this directive can ba <strong>'self'</strong>. Press Enter to separate the values.", "defender-security" ),
52
- 'img_src_desc' => __( "Example value for this directive can be <strong>'self'</strong>; <strong>img.example.com.</strong> Press Enter to separate the values.", "defender-security" ),
53
- 'media_src_text' => __( "Specifies valid sources for loading media using the &lt;frame&gt; , &lt;frame&gt; and &lt;frame&gt; elements.", "defender-security" ),
54
- 'media_src_desc' => __( "Example value for this directive can be <strong>media.example.com</strong>. Press Enter to separate the values.", "defender-security" ),
55
- 'object_src_text' => __( "Specifies valid sources for the &lt;frame&gt;, &lt;frame&gt;, and &lt;frame&gt; elements. You can read more about this directive", "defender-security" ),
56
- 'object_src_desc' => sprintf( __( "Example value for this directive can be <strong>%s</strong>. Press Enter to separate the values.", "defender-security" ), network_site_url() ),
57
- 'sandbox_text' => __( "Enables a sandbox for the requested resource similar to the &lt;iframe&gt;, sandbox attribute. You can read more about this directive here.", "defender-security" ),
58
- 'sandbox_desc' => __( "Example value for this directive can be <strong>allow-forms</strong>; <strong>allow-scripts</strong>. Press Enter to separate the values.", "defender-security" ),
59
- 'script_src_desc' => __( "Example value for this directive can be <strong>'self' js.example.com</strong>. Press Enter to separate the values.", "defender-security" ),
60
- 'style_src_desc' => __( "Example value for this directive can be <strong>'self' css.example.com</strong>. Press Enter to separate the values.", "defender-security" ),
61
- 'worker_src_desc' => __( "Example value for this directive can be <strong>'self'</strong>. Press Enter to separate the values.", "defender-security" ),
62
- 'plugin_type_desc' => __( "Example value for this directive can be <strong>application/pdf</strong>. Press Enter to separate the values.", "defender-security" ),
63
- 'frame_ancestors_text' => esc_html__( "Specifies valid sources for nested browsing contexts loading using elements such as <frame> and <iframe>.You can read more about this directive", "defender-security" ),
64
- ],
65
- 'data' => [
66
- 'base_uri' => is_array( $data ) && isset( $data['base_uri'] ) ? $data['base_uri'] : 0,
67
- 'child_src' => is_array( $data ) && isset( $data['child_src'] ) ? $data['child_src'] : 0,
68
- 'default_src' => is_array( $data ) && isset( $data['default_src'] ) ? $data['default_src'] : 0,
69
- 'font_src' => is_array( $data ) && isset( $data['font_src'] ) ? $data['font_src'] : 0,
70
- 'frame_ancestors' => is_array( $data ) && isset( $data['frame_ancestors'] ) ? $data['frame_ancestors'] : 0,
71
- 'form_action' => is_array( $data ) && isset( $data['form_action'] ) ? $data['form_action'] : 0,
72
- 'img_src' => is_array( $data ) && isset( $data['img_src'] ) ? $data['img_src'] : 0,
73
- 'media_src' => is_array( $data ) && isset( $data['media_src'] ) ? $data['media_src'] : 0,
74
- 'object_src' => is_array( $data ) && isset( $data['object_src'] ) ? $data['object_src'] : 0,
75
- 'plugin_types' => is_array( $data ) && isset( $data['plugin_types'] ) ? $data['plugin_types'] : 0,
76
- 'sandbox' => is_array( $data ) && isset( $data['sandbox'] ) ? $data['sandbox'] : 0,
77
- 'script_src' => is_array( $data ) && isset( $data['script_src'] ) ? $data['script_src'] : 0,
78
- 'style_src' => is_array( $data ) && isset( $data['style_src'] ) ? $data['style_src'] : 0,
79
- 'worker_src' => is_array( $data ) && isset( $data['worker_src'] ) ? $data['worker_src'] : 0,
80
- 'url_ignores' => is_array( $data ) && isset( $data['url_ignores'] ) ? $data['url_ignores'] : "",
81
- 'base_uri_values' => is_array( $data ) && isset( $data['base_uri_values'] ) ? $data['base_uri_values'] : [ "'none'" ],
82
- 'child_src_values' => is_array( $data ) && isset( $data['child_src_values'] ) ? $data['child_src_values'] : [],
83
- 'frame_ancestors_values' => is_array( $data ) && isset( $data['frame_ancestors_values'] ) ? $data['frame_ancestors_values'] : [],
84
- 'default_src_values' => is_array( $data ) && isset( $data['default_src_values'] ) ? $data['default_src_values'] : [],
85
- 'font_src_values' => is_array( $data ) && isset( $data['font_src_values'] ) ? $data['font_src_values'] : [],
86
- 'form_action_values' => is_array( $data ) && isset( $data['form_action_values'] ) ? $data['form_action_values'] : [],
87
- 'img_src_values' => is_array( $data ) && isset( $data['img_src_values'] ) ? $data['img_src_values'] : [],
88
- 'media_src_values' => is_array( $data ) && isset( $data['media_src_values'] ) ? $data['media_src_values'] : [],
89
- 'object_src_values' => is_array( $data ) && isset( $data['object_src_values'] ) ? $data['object_src_values'] : [ "'none'" ],
90
- 'plugin_types_values' => is_array( $data ) && isset( $data['plugin_types_values'] ) ? $data['plugin_types_values'] : [],
91
- 'sandbox_values' => is_array( $data ) && isset( $data['sandbox_values'] ) ? $data['sandbox_values'] : [],
92
- 'script_src_values' => is_array( $data ) && isset( $data['script_src_values'] ) ? $data['script_src_values'] : [
93
- "'unsafe-inline'",
94
- "'self'",
95
- "'unsafe-eval'"
96
- ],
97
- 'style_src_values' => is_array( $data ) && isset( $data['style_src_values'] ) ? $data['style_src_values'] : [],
98
- 'worker_src_values' => is_array( $data ) && isset( $data['worker_src_values'] ) ? $data['worker_src_values'] : [],
99
- ]
100
- ];
101
- }
102
-
103
- /**
104
- * This will return the short summary why this rule show up as issue
105
- *
106
- * @return string
107
- */
108
- function getErrorReason() {
109
- return __( "Content-Security-Policy isn't enforced. Your site is at risk of XSS attacks.", "defender-security" );
110
- }
111
-
112
- /**
113
- * This will return a short summary to show why this rule works
114
- * @return mixed
115
- */
116
- function getSuccessReason() {
117
- return __( "You've enforced Content-Security-Policy, good job!", "defender-security" );
118
- }
119
-
120
- public function addHooks() {
121
- $this->addAction( 'processingHardener' . self::$slug, 'process' );
122
- $this->addAction( 'wp_loaded', 'appendHeader', 999 );
123
- $this->addAction( 'processRevert' . self::$slug, 'revert' );
124
- $is_test = isset( $_COOKIE[ self::$slug . '-testing' ] );
125
- $is_staging = isset( $_COOKIE[ self::$slug . '-staging' ] );
126
- if ( $is_test || $is_staging ) {
127
- $this->addAction( 'admin_enqueue_scripts', 'enqueueCspDebugBar' );
128
- if ( $is_test ) {
129
- $this->addAction( 'admin_footer', 'debugBar', 9999 );
130
- } elseif ( $is_staging ) {
131
- $this->addAction( 'tweaks_footer', 'stagingNotification', 9999 );
132
- }
133
- $this->addAjaxAction( 'defender-csp-debug-cancel', 'cancelDebug' );
134
- $this->addAjaxAction( 'defender-csp-debug-apply', 'applyDebug' );
135
- $this->addAjaxAction( 'defender-csp-debug-staging', 'applyStaging' );
136
- }
137
- }
138
-
139
- /**
140
- * Cancel the debug, redirect to security tweaks page
141
- */
142
- public function cancelDebug() {
143
- setcookie( self::$slug . '-testing', false, - 1, '', '', true, true );
144
- $status = $this->check();
145
- wp_redirect( network_admin_url( 'admin.php?page=wdf-hardener&view=' . ( $status == true ? 'resolved' : 'issues' ) ) );
146
- exit;
147
- }
148
-
149
- /**
150
- * We applying the debug to a staging parameter before real apply to site
151
- */
152
- public function applyDebug() {
153
- $settings = Settings::instance();
154
- $test_data = $settings->getDValues( Sh_Content_Security_Service::KEY_TEMP_DATA );
155
- $settings->setDValues( Sh_Content_Security_Service::KEY_STAGING_DATA, $test_data );
156
- $settings->setDValues( Sh_Content_Security_Service::KEY_TEMP_DATA, null );
157
- $status = $this->check();
158
- setcookie( self::$slug . '-testing', false, - 1, '', '', true, true );
159
- setcookie( self::$slug . '-staging', true, 0, '', '', true, true );
160
- wp_redirect( network_admin_url( 'admin.php?page=wdf-hardener&view=' . ( $status == true ? 'resolved' : 'issues' ) ) );
161
- exit;
162
- }
163
-
164
- public function applyStaging() {
165
- $settings = Settings::instance();
166
- $stagingData = $settings->getDValues( Sh_Content_Security_Service::KEY_STAGING_DATA );
167
- $settings->setDValues( Sh_Content_Security_Service::KEY_DATA, $stagingData );
168
- $settings->setDValues( Sh_Content_Security_Service::KEY_STAGING_DATA, null );
169
- setcookie( self::$slug . '-testing', false, - 1, '', '', true, true );
170
- setcookie( self::$slug . '-staging', false, - 1, '', '', true, true );
171
- wp_redirect( network_admin_url( 'admin.php?page=wdf-hardener&view=resolved' ) );
172
- exit;
173
- }
174
-
175
- public function enqueueCspDebugBar() {
176
- wp_enqueue_style( 'defender-csp-debug-bar', wp_defender()->getPluginUrl() . '/assets/css/csp-debug-bar.css' );
177
- }
178
-
179
- public function debugBar() {
180
- $this->renderPartial( '/tweaks/csp/debug-bar' );
181
- }
182
-
183
- public function stagingNotification() {
184
- $this->renderPartial( '/tweaks/csp/notification-bar' );
185
- }
186
-
187
- public function revert() {
188
- $this->getService()->revert();
189
- Settings::instance()->addToIssues( Sh_Content_Security::$slug );
190
- }
191
-
192
- /**
193
- *
194
- */
195
- public function appendHeader() {
196
- if ( headers_sent() ) {
197
- //header already sent, do nothing
198
- return;
199
- }
200
-
201
- $settings = Settings::instance();
202
- $is_test = isset( $_COOKIE[ self::$slug . '-testing' ] );
203
- if ( $is_test ) {
204
- $data = $settings->getDValues( Sh_Content_Security_Service::KEY_TEMP_DATA );
205
- } else {
206
- $data = $settings->getDValues( Sh_Content_Security_Service::KEY_DATA );
207
- }
208
-
209
- if ( ! $this->maybeSubmitHeader( 'Content-Security-Policy', isset( $data['somewhere'] ) ? $data['somewhere'] : false ) ) {
210
- //this mean Defender can't override the already output, marked to show notification
211
- $data['overrideable'] = false;
212
- $settings->setDValues( Sh_Content_Security_Service::KEY_DATA, $data );
213
-
214
- return;
215
- }
216
-
217
- if ( is_array( $data ) ) {
218
- $keys = [
219
- 'base_uri',
220
- 'child_src',
221
- 'default_src',
222
- 'font_src',
223
- 'frame_ancestors',
224
- 'form_action',
225
- 'img_src',
226
- 'media_src',
227
- 'object_src',
228
- 'plugin_types',
229
- 'sandbox',
230
- 'script_src',
231
- 'style_src',
232
- 'worker_src',
233
- ];
234
- $headers = [];
235
- $data = array_filter( $data );
236
- foreach ( $keys as $key ) {
237
- if ( ! isset( $data[ $key ] ) || ( isset( $data[ $key ] ) && $data[ $key ] != 1 ) ) {
238
- //this rule not enable, move forward
239
- continue;
240
- }
241
-
242
- if ( isset( $data[ $key . '_values' ] ) ) {
243
- $value = $data[ $key . '_values' ];
244
- $value = implode( ' ', $value );
245
- /**
246
- * with the javascript rules, many place using inline especially in wp-admin, we should check
247
- * and append that if it missing so everything wont broke down
248
- */
249
- if ( $key == 'script_src' && ( is_admin() || is_network_admin() ) ) {
250
- $uris = [
251
- str_replace( network_site_url(), '', network_admin_url( 'admin.php?page=wdf-hardener' ) ),
252
- str_replace( network_site_url(), '', network_admin_url( 'admin.php?page=wdf-hardener&view=resolved' ) ),
253
- str_replace( network_site_url(), '', network_admin_url( 'admin.php?page=wdf-hardener&view=issues' ) ),
254
- str_replace( network_site_url(), '', network_admin_url( 'admin.php?page=wdf-hardener&view=ignore' ) )
255
- ];
256
- $uri = $_SERVER['REQUEST_URI'];
257
- if ( in_array( $uri, $uris ) && current_user_can( 'manage_options' ) ) {
258
- //read the data output from wp_localization
259
- if ( stristr( $value, 'unsafe-inline' ) == false ) {
260
- $value .= " 'unsafe-inline'";
261
- }
262
- /**
263
- * underscore require new Function so we need this
264
- */
265
- if ( stristr( $value, 'unsafe-eval' ) == false ) {
266
- $value .= " 'unsafe-eval'";
267
- }
268
- /**
269
- * to load the needed js from core
270
- */
271
- if ( stristr( $value, 'self' ) == false ) {
272
- $value .= " 'self'";
273
- }
274
- }
275
- }
276
-
277
- $headers[] = str_replace( '_', '-', $key ) . ' ' . $value;
278
- }
279
- }
280
- $headers = array_filter( $headers );
281
- if ( empty( $headers ) ) {
282
- return;
283
- }
284
- $headers = implode( '; ', $headers );
285
- $headers = "Content-Security-Policy: " . $headers;
286
- header( $headers );
287
- }
288
- }
289
-
290
- /**
291
- * @return string
292
- */
293
- public function getTitle() {
294
- return __( "Content-Security-Policy Security Header", "defender-security" );
295
- }
296
-
297
- /**
298
- * Store a flag that we enable this
299
- * @return mixed|void
300
- */
301
- public function process() {
302
- //calling the service
303
- $this->getService()->process();
304
- Settings::instance()->addToResolved( Sh_Content_Security::$slug );
305
- $scenario = HTTP_Helper::retrievePost( 'scenario' );
306
- if ( $scenario == 'temp' ) {
307
- // $status = $this->check();
308
- // $url = network_admin_url( 'admin.php?page=wdf-hardener' );
309
- // if ( $status == true ) {
310
- // $url = add_query_arg( 'view', 'resolved', $url );
311
- // } else {
312
- // $url = add_query_arg( 'view', 'issues', $url );
313
- // }
314
- wp_send_json_success( [
315
- 'reload' => 1,
316
- //'url' => $url
317
- ] );
318
- }
319
- }
320
-
321
- /**
322
- * @return Sh_Content_Security_Service
323
- */
324
- public function getService() {
325
- if ( self::$service == null ) {
326
- self::$service = new Sh_Content_Security_Service();
327
- }
328
-
329
- return self::$service;
330
- }
331
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/sh-content-type-options-service.php DELETED
@@ -1,78 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use WP_Defender\Behavior\Utils;
10
- use WP_Defender\Component\Error_Code;
11
- use WP_Defender\Module\Hardener\IRule_Service;
12
- use WP_Defender\Module\Hardener\Model\Settings;
13
- use WP_Defender\Module\Hardener\Rule_Service;
14
-
15
- class Sh_Content_Type_Options_Service extends Rule_Service implements IRule_Service {
16
- const KEY = 'sh_content_type_options';
17
- public $mode;
18
- public $scenario;
19
-
20
- /**
21
- * @return bool
22
- */
23
- public function check() {
24
- $settings = Settings::instance();
25
-
26
- $data = $settings->getDValues( self::KEY );
27
- if ( is_array( $data ) && $data['mode'] == 'nosniff' ) {
28
- return true;
29
- }
30
-
31
- $headers = $this->headRequest( network_site_url(), self::KEY );
32
- if ( is_wp_error( $headers ) ) {
33
- Utils::instance()->log( sprintf( 'Self ping error: %s', $headers->get_error_message() ),'tweaks' );
34
-
35
- return false;
36
- }
37
-
38
- if ( isset( $headers['x-content-type-options'] ) ) {
39
- $data = $settings->getDValues( self::KEY );
40
- if ( $data === null ) {
41
- $data['mode'] = 'nosniff';
42
- $data['somewhere'] = 1;
43
- $settings->setDValues( self::KEY, $data );
44
- }
45
-
46
- return true;
47
- }
48
-
49
- return false;
50
- }
51
-
52
- /**
53
- * @return bool|\WP_Error
54
- */
55
- public function process() {
56
- $mode = $this->mode;
57
- $scenario = $this->scenario;
58
- if ( empty( $mode ) || ! in_array( $mode, [ 'nosniff' ] ) ) {
59
- return new \WP_Error( Error_Code::INVALID, __( "Mode empty or invalid", "defender-security" ) );
60
- }
61
- $settings = Settings::instance();
62
- $data = $settings->getDValues( self::KEY );
63
- $data['mode'] = $mode;
64
- if ( $scenario == 'enforce' ) {
65
- unset( $data['somewhere'] );
66
- }
67
- $settings->setDValues( self::KEY, $data );
68
- }
69
-
70
- public function revert() {
71
- $settings = Settings::instance();
72
- $settings->setDValues( self::KEY, null );
73
- }
74
-
75
- public function listen() {
76
-
77
- }
78
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/sh-content-type-options.php DELETED
@@ -1,121 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use WP_Defender\Module\Hardener\Model\Settings;
10
- use WP_Defender\Module\Hardener\Rule;
11
-
12
- class Sh_Content_Type_Options extends Rule {
13
- static $slug = 'sh-content-type-options';
14
- static $service;
15
-
16
- public function getDescription() {
17
-
18
- }
19
-
20
- public function check() {
21
- return $this->getService()->check();
22
- }
23
-
24
- /**
25
- * @return array
26
- */
27
- public function getMiscData() {
28
- $settings = Settings::instance();
29
- $data = $settings->getDValues( Sh_Content_Type_Options_Service::KEY );
30
-
31
- return [
32
- 'mode' => is_array( $data ) && isset( $data['mode'] ) ? $data['mode'] : 'nosniff',
33
- ];
34
- }
35
-
36
- /**
37
- * This will return the short summary why this rule show up as issue
38
- *
39
- * @return string
40
- */
41
- function getErrorReason() {
42
- return __( "The X-Content-Type-Options header isn't enforced. Your site is at risk of MIME type sniffing and XSS attacks.", "defender-security" );
43
- }
44
-
45
- /**
46
- * This will return a short summary to show why this rule works
47
- * @return mixed
48
- */
49
- function getSuccessReason() {
50
- return __( "You've enforced X-Content-Type-Options, well done!", "defender-security" );
51
- }
52
-
53
- public function addHooks() {
54
- $this->addAction( 'processingHardener' . self::$slug, 'process' );
55
- $this->addAction( 'wp', 'appendHeader', PHP_INT_MAX );
56
- $this->addAction( 'processRevert' . self::$slug, 'revert' );
57
- }
58
-
59
- public function revert() {
60
- $this->getService()->revert();
61
- Settings::instance()->addToIssues( self::$slug );
62
- }
63
-
64
- public function appendHeader() {
65
- if ( headers_sent() ) {
66
- //header already sent, do nothing
67
- return;
68
- }
69
- $settings = Settings::instance();
70
- $data = $settings->getDValues( Sh_Content_Type_Options_Service::KEY );
71
- if ( ! $this->maybeSubmitHeader( 'X-Content-Type-Options', isset( $data['somewhere'] ) ? $data['somewhere'] : false ) ) {
72
- //this mean Defender can't override the already output, marked to show notification
73
- $data['overrideable'] = false;
74
- $settings->setDValues( Sh_Content_Type_Options_Service::KEY, $data );
75
-
76
- return;
77
- }
78
- if ( is_array( $data ) && $data['mode'] == 'nosniff' ) {
79
- header( 'X-Content-Type-Options: nosniff' );
80
- }
81
- }
82
-
83
- /**
84
- * @return string
85
- */
86
- public function getTitle() {
87
- return __( "X-Content-Type-Options Security Header", "defender-security" );
88
- }
89
-
90
- /**
91
- * Store a flag that we enable this
92
- * @return mixed|void
93
- */
94
- public function process() {
95
- //calling the service
96
- $mode = HTTP_Helper::retrievePost( 'mode' );
97
- $scenario = HTTP_Helper::retrievePost( 'scenario' );
98
- $service = $this->getService();
99
- $service->mode = $mode;
100
- $service->scenario = $scenario;
101
- $ret = $service->process();
102
- if ( is_wp_error( $ret ) ) {
103
- wp_send_json_error( [
104
- 'message' => $ret->get_error_message()
105
- ] );
106
- }
107
- $this->getService()->process();
108
- Settings::instance()->addToResolved( self::$slug );
109
- }
110
-
111
- /**
112
- * @return Sh_Content_Type_Options_Service
113
- */
114
- public function getService() {
115
- if ( self::$service == null ) {
116
- self::$service = new Sh_Content_Type_Options_Service();
117
- }
118
-
119
- return self::$service;
120
- }
121
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/sh-feature-policy-service.php DELETED
@@ -1,96 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use WP_Defender\Behavior\Utils;
10
- use WP_Defender\Component\Error_Code;
11
- use WP_Defender\Module\Hardener\IRule_Service;
12
- use WP_Defender\Module\Hardener\Model\Settings;
13
- use WP_Defender\Module\Hardener\Rule_Service;
14
-
15
- class Sh_Feature_Policy_Service extends Rule_Service implements IRule_Service {
16
- const KEY = 'sh_feature_policy';
17
- public $mode;
18
- public $scenario;
19
- public $values;
20
-
21
- /**
22
- * @return bool
23
- */
24
- public function check() {
25
- $settings = Settings::instance();
26
- $headers = $this->headRequest( network_site_url(), self::KEY );
27
- if ( is_wp_error( $headers ) ) {
28
- Utils::instance()->log( sprintf( 'Self ping error: %s', $headers->get_error_message() ), 'tweaks' );
29
-
30
- return false;
31
- }
32
-
33
- if ( isset( $headers['feature-policy'] ) ) {
34
- $data = $settings->getDValues( self::KEY );
35
- if ( $data === null ) {
36
- $data['somewhere'] = true;
37
- $settings->setDValues( self::KEY, $data );
38
- }
39
-
40
- return true;
41
- }
42
-
43
- $data = $settings->getDValues( self::KEY );
44
- if ( is_array( $data ) && isset( $data['mode'] ) && in_array( $data['mode'], [
45
- 'self',
46
- 'allow',
47
- 'origins',
48
- 'none'
49
- ] ) ) {
50
- return true;
51
- }
52
-
53
- return false;
54
- }
55
-
56
- /**
57
- * @param $mode
58
- * @param $values
59
- * @param $scenario
60
- *
61
- * @return bool|\WP_Error
62
- */
63
- public function process() {
64
- $mode = $this->mode;
65
- $scenario = $this->scenario;
66
- $values = $this->values;
67
- if ( empty( $mode ) || ! in_array( $mode, [ 'self', 'allow', 'origins', 'none' ] ) ) {
68
- return new \WP_Error( Error_Code::INVALID, __( "Mode empty or invalid", "defender-security" ) );
69
- }
70
- $values = trim( $values );
71
- $values = sanitize_textarea_field( $values );
72
- $values = explode( PHP_EOL, $values );
73
- foreach ( $values as $key => $url ) {
74
- if ( filter_var( $url, FILTER_VALIDATE_URL ) == false ) {
75
- unset( $values[ $key ] );
76
- }
77
- }
78
- $settings = Settings::instance();
79
- $data = $settings->getDValues( self::KEY );
80
- $data['mode'] = $mode;
81
- $data['values'] = $values;
82
- if ( $scenario == 'enforce' ) {
83
- unset( $data['somewhere'] );
84
- }
85
- $settings->setDValues( self::KEY, $data );
86
- }
87
-
88
- public function revert() {
89
- $settings = Settings::instance();
90
- $settings->setDValues( self::KEY, null );
91
- }
92
-
93
- public function listen() {
94
-
95
- }
96
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/sh-feature-policy.php DELETED
@@ -1,175 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use WP_Defender\Module\Hardener\Model\Settings;
10
- use WP_Defender\Module\Hardener\Rule;
11
-
12
- class Sh_Feature_Policy extends Rule {
13
- static $slug = 'sh-feature-policy';
14
- static $service;
15
-
16
- public function getDescription() {
17
-
18
- }
19
-
20
- public function check() {
21
- return $this->getService()->check();
22
- }
23
-
24
- /**
25
- * @return array
26
- */
27
- public function getMiscData() {
28
- $settings = Settings::instance();
29
- $data = $settings->getDValues( Sh_Feature_Policy_Service::KEY );
30
-
31
- return [
32
- 'mode' => is_array( $data ) && isset( $data['mode'] ) ? $data['mode'] : 'self',
33
- 'values' => is_array( $data ) && isset( $data['values'] ) ? $data['values'] : array(),
34
- ];
35
- }
36
-
37
- /**
38
- * This will return the short summary why this rule show up as issue
39
- *
40
- * @return string
41
- */
42
- function getErrorReason() {
43
- return __( "The Feature-Policy header isn't enforced. All browser features are accessible when embedded through an iframe.", "defender-security" );
44
- }
45
-
46
- /**
47
- * This will return a short summary to show why this rule works
48
- * @return mixed
49
- */
50
- function getSuccessReason() {
51
- return __( "You've enforced Feature-Policy, good job!", "defender-security" );
52
- }
53
-
54
- public function addHooks() {
55
- $this->addAction( 'processingHardener' . self::$slug, 'process' );
56
- $this->addAction( 'wp', 'appendHeader', PHP_INT_MAX );
57
- $this->addAction( 'processRevert' . self::$slug, 'revert' );
58
- }
59
-
60
- public function revert() {
61
- $this->getService()->revert();
62
- Settings::instance()->addToIssues( self::$slug );
63
- }
64
-
65
- public function appendHeader() {
66
- if ( headers_sent() ) {
67
- //header already sent, do nothing
68
- return;
69
- }
70
- $settings = Settings::instance();
71
- $data = $settings->getDValues( Sh_Feature_Policy_Service::KEY );
72
- if ( ! $this->maybeSubmitHeader( 'Feature-Policy', isset( $data['somewhere'] ) ? $data['somewhere'] : false ) ) {
73
- //this mean Defender can't override the already output, marked to show notification
74
- $data['overrideable'] = false;
75
- $settings->setDValues( Sh_Feature_Policy_Service::KEY, $data );
76
-
77
- return;
78
- }
79
- if ( is_array( $data ) && in_array( $data['mode'], [ 'self', 'allow', 'origins', 'none' ] ) ) {
80
- $headers = '';
81
- $features = [
82
- 'accelerometer',
83
- 'ambient-light-sensor',
84
- 'autoplay',
85
- 'camera',
86
- 'encrypted-media',
87
- 'fullscreen',
88
- 'geolocation',
89
- 'gyroscope',
90
- 'magnetometer',
91
- 'microphone',
92
- 'midi',
93
- 'payment',
94
- 'picture-in-picture',
95
- 'speaker',
96
- 'usb',
97
- //'vibrate',
98
- 'vr'
99
- ];
100
- switch ( $data['mode'] ) {
101
- case 'self':
102
- array_walk( $features, function ( &$value, $key ) {
103
- $value .= " 'self'";
104
- } );
105
- $headers = 'Feature-Policy: ' . implode( '; ', $features );
106
- break;
107
- case 'allow':
108
- array_walk( $features, function ( &$value, $key ) {
109
- $value .= " *";
110
- } );
111
- $headers = 'Feature-Policy: ' . implode( '; ', $features );
112
- break;
113
- case 'origins':
114
- $urls = implode( ' ', $data['values'] );
115
- array_walk( $features, function ( &$value, $key ) use ( $urls ) {
116
- $value .= " " . $urls;
117
- } );
118
- $headers = 'Feature-Policy: ' . implode( '; ', $features );
119
- break;
120
- case 'none':
121
- array_walk( $features, function ( &$value, $key ) {
122
- $value .= " 'none'";
123
- } );
124
- $headers = 'Feature-Policy: ' . implode( '; ', $features );
125
- break;
126
- default:
127
- break;
128
- }
129
- if ( strlen( $headers ) > 0 ) {
130
- header( trim( $headers ) );
131
- }
132
- }
133
- }
134
-
135
- /**
136
- * @return string
137
- */
138
- public function getTitle() {
139
- return __( "Feature-Policy Security Header", "defender-security" );
140
- }
141
-
142
- /**
143
- * Store a flag that we enable this
144
- * @return mixed|void
145
- */
146
- public function process() {
147
- //calling the service
148
- $mode = HTTP_Helper::retrievePost( 'mode' );
149
- $values = HTTP_Helper::retrievePost( 'values' );
150
- $scenario = HTTP_Helper::retrievePost( 'scenario' );
151
- $service = $this->getService();
152
- $service->mode = $mode;
153
- $service->values = $values;
154
- $service->scenario = $scenario;
155
- $ret = $service->process();
156
- if ( ! is_wp_error( $ret ) ) {
157
- Settings::instance()->addToResolved( self::$slug );
158
- } else {
159
- wp_send_json_error( [
160
- 'message' => $ret->get_error_message()
161
- ] );
162
- }
163
- }
164
-
165
- /**
166
- * @return Sh_Feature_Policy_Service
167
- */
168
- public function getService() {
169
- if ( self::$service == null ) {
170
- self::$service = new Sh_Feature_Policy_Service();
171
- }
172
-
173
- return self::$service;
174
- }
175
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/sh-referrer-policy-service.php DELETED
@@ -1,97 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use WP_Defender\Behavior\Utils;
10
- use WP_Defender\Component\Error_Code;
11
- use WP_Defender\Module\Hardener\IRule_Service;
12
- use WP_Defender\Module\Hardener\Model\Settings;
13
- use WP_Defender\Module\Hardener\Rule_Service;
14
-
15
- class Sh_Referrer_Policy_Service extends Rule_Service implements IRule_Service {
16
- const KEY = 'sh_referrer_policy';
17
- public $mode;
18
- public $scenario;
19
-
20
- /**
21
- * @return bool
22
- */
23
- public function check() {
24
- $settings = Settings::instance();
25
- $headers = $this->headRequest( network_site_url(), self::KEY );
26
- if ( is_wp_error( $headers ) ) {
27
- Utils::instance()->log( sprintf( 'Self ping error: %s', $headers->get_error_message() ), 'tweaks' );
28
-
29
- return false;
30
- }
31
-
32
- if ( isset( $headers['referrer-policy'] ) ) {
33
- $data = $settings->getDValues( self::KEY );
34
- if ( $data === null ) {
35
- $data['somewhere'] = true;
36
- $settings->setDValues( self::KEY, $data );
37
- }
38
-
39
- return true;
40
- }
41
-
42
- $data = $settings->getDValues( self::KEY );
43
- if ( is_array( $data ) && isset( $data['mode'] ) && in_array( $data['mode'], [
44
- 'no-referrer',
45
- 'no-referrer-when-downgrade',
46
- 'origin',
47
- 'origin-when-cross-origin',
48
- 'same-origin',
49
- 'strict-origin',
50
- 'strict-origin-when-cross-origin',
51
- 'unsafe-url'
52
- ] ) ) {
53
- return true;
54
- }
55
-
56
- return false;
57
- }
58
-
59
- /**
60
- * @return bool|\WP_Error
61
- */
62
- public function process() {
63
- $mode = $this->mode;
64
- $scenario = $this->scenario;
65
- if ( empty( $mode ) || ! in_array( $mode, [
66
- 'no-referrer',
67
- 'no-referrer-when-downgrade',
68
- 'origin',
69
- 'origin-when-cross-origin',
70
- 'same-origin',
71
- 'strict-origin',
72
- 'strict-origin-when-cross-origin',
73
- 'unsafe-url'
74
- ] ) ) {
75
- return new \WP_Error( Error_Code::INVALID, __( "Mode empty or invalid", "defender-security" ) );
76
- }
77
- $settings = Settings::instance();
78
- $data = $settings->getDValues( self::KEY );
79
- $data['mode'] = $mode;
80
- $data = [
81
- 'mode' => $mode
82
- ];
83
- if ( $scenario == 'enforce' ) {
84
- unset( $data['somewhere'] );
85
- }
86
- $settings->setDValues( self::KEY, $data );
87
- }
88
-
89
- public function revert() {
90
- $settings = Settings::instance();
91
- $settings->setDValues( self::KEY, null );
92
- }
93
-
94
- public function listen() {
95
-
96
- }
97
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/sh-referrer-policy.php DELETED
@@ -1,132 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use WP_Defender\Module\Hardener\Model\Settings;
10
- use WP_Defender\Module\Hardener\Rule;
11
-
12
- class Sh_Referrer_Policy extends Rule {
13
- static $slug = 'sh-referrer-policy';
14
- static $service;
15
-
16
- public function getDescription() {
17
-
18
- }
19
-
20
- public function check() {
21
- return $this->getService()->check();
22
- }
23
-
24
- /**
25
- * @return array
26
- */
27
- public function getMiscData() {
28
- $settings = Settings::instance();
29
- $data = $settings->getDValues( Sh_Referrer_Policy_Service::KEY );
30
-
31
- return [
32
- 'mode' => is_array( $data ) && isset( $data['mode'] ) ? $data['mode'] : 'origin-when-cross-origin',
33
- 'values' => is_array( $data ) && isset( $data['values'] ) ? $data['values'] : [],
34
- ];
35
- }
36
-
37
- /**
38
- * This will return the short summary why this rule show up as issue
39
- *
40
- * @return string
41
- */
42
- function getErrorReason() {
43
- return __( "Referrer policy header isn't active. We recommend you choose a policy from the options below.", "defender-security" );
44
- }
45
-
46
- /**
47
- * This will return a short summary to show why this rule works
48
- * @return mixed
49
- */
50
- function getSuccessReason() {
51
- return __( "You've enforced Referrer policy, well done!", "defender-security" );
52
- }
53
-
54
- public function addHooks() {
55
- $this->addAction( 'processingHardener' . self::$slug, 'process' );
56
- $this->addAction( 'wp', 'appendHeader', PHP_INT_MAX );
57
- $this->addAction( 'processRevert' . self::$slug, 'revert' );
58
- }
59
-
60
- public function revert() {
61
- $this->getService()->revert();
62
- Settings::instance()->addToIssues( self::$slug );
63
- }
64
-
65
- public function appendHeader() {
66
- if ( headers_sent() ) {
67
- //header already sent, do nothing
68
- return;
69
- }
70
- $settings = Settings::instance();
71
- $data = $settings->getDValues( Sh_Referrer_Policy_Service::KEY );
72
- if ( ! $this->maybeSubmitHeader( 'Referrer-Policy', isset( $data['somewhere'] ) ? $data['somewhere'] : false ) ) {
73
- //this mean Defender can't override the already output, marked to show notification
74
- $data['overrideable'] = false;
75
- $settings->setDValues( Sh_Referrer_Policy_Service::KEY, $data );
76
-
77
- return;
78
- }
79
- if ( is_array( $data ) && isset( $data['mode'] ) && in_array( $data['mode'], [
80
- 'no-referrer',
81
- 'no-referrer-when-downgrade',
82
- 'origin',
83
- 'origin-when-cross-origin',
84
- 'same-origin',
85
- 'strict-origin',
86
- 'strict-origin-when-cross-origin',
87
- 'unsafe-url'
88
- ] ) ) {
89
- $headers = 'Referrer-Policy: ' . $data['mode'];
90
- header( $headers );
91
- }
92
- }
93
-
94
- /**
95
- * @return string
96
- */
97
- public function getTitle() {
98
- return __( "Referrer Policy Security Header", "defender-security" );
99
- }
100
-
101
- /**
102
- * Store a flag that we enable this
103
- * @return mixed|void
104
- */
105
- public function process() {
106
- //calling the service
107
- $mode = HTTP_Helper::retrievePost( 'mode' );
108
- $scenario = HTTP_Helper::retrievePost( 'scenario' );
109
- $service = $this->getService();
110
- $service->mode = $mode;
111
- $service->scenario = $scenario;
112
- $ret = $service->process();
113
- if ( ! is_wp_error( $ret ) ) {
114
- Settings::instance()->addToResolved( self::$slug );
115
- } else {
116
- wp_send_json_error( [
117
- 'message' => $ret->get_error_message()
118
- ] );
119
- }
120
- }
121
-
122
- /**
123
- * @return Sh_Referrer_Policy_Service
124
- */
125
- public function getService() {
126
- if ( self::$service == null ) {
127
- self::$service = new Sh_Referrer_Policy_Service();
128
- }
129
-
130
- return self::$service;
131
- }
132
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/sh-strict-transport-service.php DELETED
@@ -1,112 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use WP_Defender\Behavior\Utils;
10
- use WP_Defender\Component\Error_Code;
11
- use WP_Defender\Module\Hardener\IRule_Service;
12
- use WP_Defender\Module\Hardener\Model\Settings;
13
- use WP_Defender\Module\Hardener\Rule_Service;
14
-
15
- class Sh_Strict_Transport_Service extends Rule_Service implements IRule_Service {
16
- const KEY = 'sh_strict_transport';
17
- public $hsts;
18
- public $include_subdomain;
19
- public $hsts_cache_duration;
20
- public $scenario;
21
-
22
- /**
23
- * @return bool
24
- */
25
- public function check() {
26
- $settings = Settings::instance();
27
-
28
- $headers = $this->headRequest( network_site_url(), self::KEY );
29
- if ( is_wp_error( $headers ) ) {
30
- Utils::instance()->log( sprintf( 'Self ping error: %s', $headers->get_error_message() ),'tweaks' );
31
-
32
- return false;
33
- }
34
- if ( isset( $headers['strict-transport-security'] ) ) {
35
- $data = $settings->getDValues( self::KEY );
36
- if ( $data === null ) {
37
- $data = [ 'somewhere' => true ];
38
- //someone applied first, we need to get the current settings
39
- $content = explode( ';', $headers['strict-transport-security'] );
40
- foreach ( $content as $line ) {
41
- if ( stristr( $line, 'max-age' ) ) {
42
- $value = explode( '=', $line );
43
- $arr = [
44
- '1 hour' => 1 * 3600,
45
- '24 hours' => 86400,
46
- '7 days' => 7 * 86400,
47
- '3 months' => ( 3 * 30 + 1 ) * 86400,
48
- '6 months' => ( 6 * 30 + 3 ) * 86400,
49
- '12 months' => 365 * 86400
50
- ];
51
- $seconds = $value[1];
52
- $closest = null;
53
- $key = null;
54
- //get the closest
55
- foreach ( $arr as $k => $item ) {
56
- if ( $closest === null || abs( $seconds - $closest ) > abs( $item - $seconds ) ) {
57
- $closest = $item;
58
- $key = $k;
59
- }
60
- }
61
- $data['hsts_cache_duration'] = $key;
62
- } elseif ( stristr( $line, 'preload' ) ) {
63
- $data['hsts_preload'] = 1;
64
- } elseif ( stristr( $line, 'includeSubDomains' ) ) {
65
- $data['include_subdomain'] = 1;
66
- }
67
- }
68
- $settings->setDValues( self::KEY, $data );
69
- }
70
-
71
- return true;
72
- }
73
-
74
- $data = $settings->getDValues( self::KEY );
75
- if ( is_array( $data ) && isset( $data['hsts_cache_duration'] ) ) {
76
- return true;
77
- }
78
-
79
- return false;
80
- }
81
-
82
- /**
83
- * @return bool|\WP_Error
84
- */
85
- public function process() {
86
- $hsts = $this->hsts;
87
- $include_subdomain = $this->include_subdomain;
88
- $hsts_cache_duration = $this->hsts_cache_duration;
89
- $scenario = $this->scenario;
90
- $settings = Settings::instance();
91
- $data = $settings->getDValues( self::KEY );
92
- if ( ! is_array( $data ) ) {
93
- $data = [];
94
- }
95
- $data['hsts_preload'] = $hsts;
96
- $data['include_subdomain'] = $include_subdomain;
97
- $data['hsts_cache_duration'] = $hsts_cache_duration;
98
- if ( $scenario == 'enforce' ) {
99
- unset( $data['somewhere'] );
100
- }
101
- $settings->setDValues( self::KEY, $data );
102
- }
103
-
104
- public function revert() {
105
- $settings = Settings::instance();
106
- $settings->setDValues( self::KEY, null );
107
- }
108
-
109
- public function listen() {
110
-
111
- }
112
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/sh-strict-transport.php DELETED
@@ -1,149 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use WP_Defender\Behavior\Utils;
10
- use WP_Defender\Module\Hardener\Model\Settings;
11
- use WP_Defender\Module\Hardener\Rule;
12
-
13
- class Sh_Strict_Transport extends Rule {
14
- static $slug = 'sh-strict-transport';
15
- static $service;
16
-
17
- public function getDescription() {
18
-
19
- }
20
-
21
- public function check() {
22
- return $this->getService()->check();
23
- }
24
-
25
- public function getMiscData() {
26
- $settings = Settings::instance();
27
- $data = $settings->getDValues( Sh_Strict_Transport_Service::KEY );
28
- //we need to check if this is root domain to show the subdomain option
29
- $site_url = network_site_url();
30
- $domain_data = Utils::instance()->parseDomain( $site_url );
31
- $allow_subdomain = false;
32
- if ( is_array( $domain_data ) && ! isset( $domain_data['subdomain'] ) ) {
33
- $allow_subdomain = true;
34
- }
35
-
36
- return [
37
- 'hsts_preload' => is_array( $data ) && isset( $data['hsts_preload'] ) ? $data['hsts_preload'] : 0,
38
- 'include_subdomain' => is_array( $data ) && isset( $data['include_subdomain'] ) ? $data['include_subdomain'] : 0,
39
- 'hsts_cache_duration' => is_array( $data ) && isset( $data['hsts_cache_duration'] ) ? $data['hsts_cache_duration'] : '7 days',
40
- 'somewhere' => is_array( $data ) && isset( $data['somewhere'] ) ? $data['somewhere'] : false,
41
- 'allow_subdomain' => $allow_subdomain
42
- ];
43
- }
44
-
45
- /**
46
- * This will return the short summary why this rule show up as issue
47
- *
48
- * @return string
49
- */
50
- function getErrorReason() {
51
- return __( "The Strict Transport Security header isn't enforced. Visitors and bots can access your site without https.", "defender-security" );
52
- }
53
-
54
- /**
55
- * This will return a short summary to show why this rule works
56
- * @return mixed
57
- */
58
- function getSuccessReason() {
59
- return __( "You've enforced Strict Transport, well done!", "defender-security" );
60
- }
61
-
62
- public function addHooks() {
63
- $this->addAction( 'processingHardener' . self::$slug, 'process' );
64
- $this->addAction( 'wp', 'appendHeader', PHP_INT_MAX );
65
- $this->addAction( 'processRevert' . self::$slug, 'revert' );
66
- }
67
-
68
- public function revert() {
69
- $this->getService()->revert();
70
- Settings::instance()->addToIssues( self::$slug );
71
- }
72
-
73
- public function appendHeader() {
74
- if ( headers_sent() ) {
75
- //header already sent, do nothing
76
- return;
77
- }
78
-
79
- $settings = Settings::instance();
80
- $data = $settings->getDValues( Sh_Strict_Transport_Service::KEY );
81
- if ( ! $this->maybeSubmitHeader( 'Strict-Transport-Security', isset( $data['somewhere'] ) ? $data['somewhere'] : false ) ) {
82
- $data['overrideable'] = false;
83
- $settings->setDValues( Sh_Strict_Transport_Service::KEY, $data );
84
-
85
- return;
86
- }
87
- if ( is_array( $data ) && isset( $data['hsts_cache_duration'] ) ) {
88
- $arr = [
89
- '1 hour' => 1 * 3600,
90
- '24 hours' => 86400,
91
- '7 days' => 7 * 86400,
92
- '3 months' => ( 3 * 30 + 1 ) * 86400,
93
- '6 months' => ( 6 * 30 + 3 ) * 86400,
94
- '12 months' => 365 * 86400
95
- ];
96
- $seconds = isset( $arr[ $data['hsts_cache_duration'] ] ) ? $arr[ $data['hsts_cache_duration'] ] : null;
97
- if ( $seconds === null ) {
98
- return;
99
- }
100
- $headers = 'Strict-Transport-Security: max-age=' . $seconds;
101
- if ( $data['include_subdomain'] == 1 ) {
102
- $headers .= ' ; includeSubDomains';
103
- }
104
- if ( $data['hsts_preload'] == 1 ) {
105
- $headers .= ' ; preload';
106
- }
107
-
108
- header( $headers );
109
- }
110
- }
111
-
112
- /**
113
- * @return string
114
- */
115
- public function getTitle() {
116
- return __( "Strict Transport Security Header", "defender-security" );
117
- }
118
-
119
- /**
120
- * Store a flag that we enable this
121
- * @return mixed|void
122
- */
123
- public function process() {
124
- $service = $this->getService();
125
- $service->hsts = HTTP_Helper::retrievePost( 'hsts_preload' );
126
- $service->include_subdomain = HTTP_Helper::retrievePost( 'include_subdomain' );
127
- $service->hsts_cache_duration = HTTP_Helper::retrievePost( 'hsts_cache_duration' );
128
- $service->scenario = HTTP_Helper::retrievePost( 'scenario' );
129
- $ret = $service->process();
130
- if ( is_wp_error( $ret ) ) {
131
- wp_send_json_error( [
132
- 'message' => $ret->get_error_message()
133
- ] );
134
- } else {
135
- Settings::instance()->addToResolved( Sh_Strict_Transport::$slug );
136
- }
137
- }
138
-
139
- /**
140
- * @return Sh_Strict_Transport_Service
141
- */
142
- public function getService() {
143
- if ( self::$service == null ) {
144
- self::$service = new Sh_Strict_Transport_Service();
145
- }
146
-
147
- return self::$service;
148
- }
149
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/sh-x-frame-service.php DELETED
@@ -1,102 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use WP_Defender\Behavior\Utils;
10
- use WP_Defender\Component\Error_Code;
11
- use WP_Defender\Module\Hardener\IRule_Service;
12
- use WP_Defender\Module\Hardener\Model\Settings;
13
- use WP_Defender\Module\Hardener\Rule_Service;
14
-
15
- class Sh_X_Frame_Service extends Rule_Service implements IRule_Service {
16
- const KEY = 'sh_xframe';
17
- public $mode;
18
- public $values;
19
- public $scenario;
20
-
21
- /**
22
- * @return bool
23
- */
24
- public function check() {
25
- $settings = Settings::instance();
26
-
27
- $headers = $this->headRequest( network_site_url(), self::KEY );
28
-
29
- if ( is_wp_error( $headers ) ) {
30
- Utils::instance()->log( sprintf( 'Self ping error: %s', $headers->get_error_message() ),'tweaks' );
31
-
32
- return false;
33
- }
34
- if ( isset( $headers['x-frame-options'] ) ) {
35
- $settings = Settings::instance();
36
- $data = $settings->getDValues( self::KEY );
37
- if ( $data === null ) {
38
- $data = [ 'somewhere' => true ];
39
- $content = strtolower( trim( $headers['x-frame-options'] ) );
40
- if ( stristr( $content, 'allow-from' ) ) {
41
- $data['mode'] = 'allow-from';
42
- $urls = explode( ' ', $content );
43
- unset( $urls[0] );
44
- $data['values'] = implode( PHP_EOL, $urls );
45
- } elseif ( in_array( strtolower( $content ), [ 'sameorigin', 'deny' ] ) ) {
46
- $data['mode'] = strtolower( $content );
47
- }
48
- $settings->setDValues( self::KEY, $data );
49
- }
50
-
51
- return true;
52
- }
53
- $data = $settings->getDValues( self::KEY );
54
- if ( is_array( $data ) && in_array( $data['mode'], [ 'sameorigin', 'allow-from', 'deny' ] ) ) {
55
- return true;
56
- }
57
-
58
- return false;
59
- }
60
-
61
- /**
62
- * @return bool|\WP_Error
63
- */
64
- public function process() {
65
- $mode = $this->mode;
66
- $values = $this->values;
67
- $scenario = $this->scenario;
68
- if ( empty( $mode ) || ! in_array( $mode, [ 'sameorigin', 'allow-from', 'deny' ] ) ) {
69
- return new \WP_Error( Error_Code::INVALID, __( "Mode empty or invalid", "defender-security" ) );
70
- }
71
- $values = trim( $values );
72
- $values = sanitize_textarea_field( $values );
73
- $values = explode( PHP_EOL, $values );
74
- foreach ( $values as $key => $url ) {
75
- if ( filter_var( $url, FILTER_VALIDATE_URL ) == false ) {
76
- unset( $values[ $key ] );
77
- }
78
- }
79
- $settings = Settings::instance();
80
- $data = $settings->getDValues( self::KEY );
81
- if ( ! is_array( $data ) ) {
82
- $data = [];
83
- }
84
- $data['mode'] = $mode;
85
- $data['values'] = implode( ' ', $values );
86
- if ( $scenario == 'enforce' ) {
87
- unset( $data['somewhere'] );
88
- }
89
- $settings->setDValues( self::KEY, $data );
90
-
91
- return true;
92
- }
93
-
94
- public function revert() {
95
- $settings = Settings::instance();
96
- $settings->setDValues( self::KEY, null );
97
- }
98
-
99
- public function listen() {
100
-
101
- }
102
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/sh-x-frame.php DELETED
@@ -1,125 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use WP_Defender\Module\Hardener\Model\Settings;
10
- use WP_Defender\Module\Hardener\Rule;
11
-
12
- class Sh_X_Frame extends Rule {
13
- const KEY = 'sh_xframe';
14
- static $slug = 'sh-xframe';
15
- static $service;
16
-
17
- public function getDescription() {
18
- $this->renderPartial( 'rules/security-headers-x-frame' );
19
- }
20
-
21
- public function check() {
22
- return $this->getService()->check();
23
- }
24
-
25
- public function getMiscData() {
26
- $settings = Settings::instance();
27
- $data = $settings->getDValues( self::KEY );
28
-
29
- return [
30
- 'intro_text' => esc_html__( "The X-Frame-Options HTTP response header controls whether or not a browser can render a webpage inside a <frame>, <iframe> or <object> tag. Websites can avoid clickjacking attacks by ensuring that their content isn't embedded into other websites.", "defender-security" ),
31
- 'mode' => is_array( $data ) && isset( $data['mode'] ) ? $data['mode'] : 'sameorigin',
32
- 'values' => is_array( $data ) && isset( $data['values'] ) ? $data['values'] : array(),
33
- ];
34
- }
35
-
36
- /**
37
- * This will return the short summary why this rule show up as issue
38
- *
39
- * @return string
40
- */
41
- function getErrorReason() {
42
- return __( "The X-Frame-Option header isn't enforced, so anyone can embed your web pages.", "defender-security" );
43
- }
44
-
45
- /**
46
- * This will return a short summary to show why this rule works
47
- * @return mixed
48
- */
49
- function getSuccessReason() {
50
- return __( "You've enforced X-Frame-Options, good stuff.", "defender-security" );
51
- }
52
-
53
- public function addHooks() {
54
- $this->addAction( 'processingHardener' . self::$slug, 'process' );
55
- $this->addAction( 'wp', 'appendHeader', PHP_INT_MAX );
56
- $this->addAction( 'processRevert' . self::$slug, 'revert' );
57
- }
58
-
59
- public function revert() {
60
- $this->getService()->revert();
61
- Settings::instance()->addToIssues( self::$slug );
62
- }
63
-
64
- public function appendHeader() {
65
- if ( headers_sent() ) {
66
- //header already sent, do nothing
67
- return;
68
- }
69
- $settings = Settings::instance();
70
- $data = $settings->getDValues( self::KEY );
71
-
72
- if ( ! $this->maybeSubmitHeader( 'X-Frame-Options', isset( $data['somewhere'] ) ? $data['somewhere'] : false ) ) {
73
- $data['overrideable'] = false;
74
-
75
- return;
76
- }
77
-
78
- if ( is_array( $data ) && in_array( $data['mode'], [ 'sameorigin', 'allow-from', 'deny' ] ) ) {
79
- if ( ! isset( $data['values'] ) ) {
80
- $data['values'] = '';
81
- }
82
- $headers = 'X-Frame-Options: ' . $data['mode'];
83
- if ( $data['mode'] == 'allow-from' ) {
84
- $headers .= ' ' . $data['values'];
85
- }
86
- header( trim( $headers ) );
87
- }
88
- }
89
-
90
- /**
91
- * @return string
92
- */
93
- public function getTitle() {
94
- return __( "X-Frame-Options Security Header", "defender-security" );
95
- }
96
-
97
- /**
98
- * Store a flag that we enable this
99
- * @return mixed|void
100
- */
101
- public function process() {
102
- $service = $this->getService();
103
- $service->mode = HTTP_Helper::retrievePost( 'mode' );
104
- $service->values = HTTP_Helper::retrievePost( 'values' );
105
- $service->scenario = HTTP_Helper::retrievePost( 'scenario' );
106
- $ret = $this->getService()->process();
107
- if ( is_wp_error( $ret ) ) {
108
- wp_send_json_error( [
109
- 'message' => $ret->get_error_message()
110
- ] );
111
- }
112
- Settings::instance()->addToResolved( self::$slug );
113
- }
114
-
115
- /**
116
- * @return Sh_X_Frame_Service
117
- */
118
- public function getService() {
119
- if ( self::$service == null ) {
120
- self::$service = new Sh_X_Frame_Service();
121
- }
122
-
123
- return self::$service;
124
- }
125
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/sh-xss-protection-service.php DELETED
@@ -1,86 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use WP_Defender\Behavior\Utils;
10
- use WP_Defender\Component\Error_Code;
11
- use WP_Defender\Module\Hardener\IRule_Service;
12
- use WP_Defender\Module\Hardener\Model\Settings;
13
- use WP_Defender\Module\Hardener\Rule_Service;
14
-
15
- class Sh_XSS_Protection_Service extends Rule_Service implements IRule_Service {
16
- const KEY = 'sh_xss_protection';
17
- static $error;
18
- public $mode;
19
- public $scenario;
20
-
21
- /**
22
- * @return bool
23
- */
24
- public function check() {
25
- //priority to get check from db first
26
- $settings = Settings::instance();
27
-
28
- $headers = $this->headRequest( network_site_url(), self::KEY );
29
- if ( is_wp_error( $headers ) ) {
30
- Utils::instance()->log( sprintf( 'Self ping error: %s', $headers->get_error_message() ),'tweaks' );
31
-
32
- return false;
33
- }
34
- if ( isset( $headers['x-xss-protection'] ) ) {
35
- $data = $settings->getDValues( self::KEY );
36
- if ( $data === null ) {
37
- $data['somewhere'] = true;
38
- $content = strtolower( trim( $headers['x-xss-protection'] ) );
39
- $content = explode( ';', $content );
40
- if ( count( $content ) == 1 ) {
41
- $data['mode'] = 'sanitize';
42
- } else {
43
- $content = explode( '=', $content[1] );
44
- $data['mode'] = $content[1];
45
- }
46
- $settings->setDValues( self::KEY, $data );
47
- }
48
-
49
- return true;
50
- }
51
- $data = $settings->getDValues( self::KEY );
52
- if ( is_array( $data ) && isset( $data['mode'] ) && in_array( $data['mode'], [
53
- 'sanitize',
54
- 'block',
55
- 'none'
56
- ] ) ) {
57
- //we can't check by request but we activate this
58
- return true;
59
- }
60
-
61
- return false;
62
- }
63
-
64
- /**
65
- * @return bool|\WP_Error
66
- */
67
- public function process() {
68
- $mode = $this->mode;
69
- $scenario = $this->scenario;
70
- if ( empty( $mode ) || ! in_array( $mode, [ 'sanitize', 'block', 'none' ] ) ) {
71
- return new \WP_Error( Error_Code::INVALID, __( "Mode empty or invalid", "defender-security" ) );
72
- }
73
- $settings = Settings::instance();
74
- $data = $settings->getDValues( self::KEY );
75
- $data['mode'] = $mode;
76
- if ( $scenario == 'enforce' ) {
77
- unset( $data['somewhere'] );
78
- }
79
- $settings->setDValues( self::KEY, $data );
80
- }
81
-
82
- public function revert() {
83
- $settings = Settings::instance();
84
- $settings->setDValues( self::KEY, null );
85
- }
86
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/sh-xss-protection.php DELETED
@@ -1,128 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use WP_Defender\Module\Hardener\Model\Settings;
10
- use WP_Defender\Module\Hardener\Rule;
11
-
12
- class Sh_XSS_Protection extends Rule {
13
- const KEY = 'sh_xss_protection';
14
- static $slug = 'sh-xss-protection';
15
- static $service;
16
-
17
- public function getDescription() {
18
-
19
- }
20
-
21
- public function check() {
22
- return $this->getService()->check();
23
- }
24
-
25
- /**
26
- * @return array
27
- */
28
- public function getMiscData() {
29
- $settings = Settings::instance();
30
- $data = $settings->getDValues( self::KEY );
31
- $miscs = [
32
- 'mode' => is_array( $data ) && isset( $data['mode'] ) ? $data['mode'] : 'sanitize',
33
- ];
34
-
35
- return $miscs;
36
- }
37
-
38
- /**
39
- * This will return the short summary why this rule show up as issue
40
- *
41
- * @return string
42
- */
43
- function getErrorReason() {
44
- return __( "The X-XSS-Protection header isn't enforced. Older browsers are at risk of XSS attacks.", "defender-security" );
45
- }
46
-
47
- /**
48
- * This will return a short summary to show why this rule works
49
- * @return mixed
50
- */
51
- function getSuccessReason() {
52
- return __( "You've enforced X-XSS-Protection, good stuff.", "defender-security" );
53
- }
54
-
55
- public function addHooks() {
56
- $this->addAction( 'processingHardener' . self::$slug, 'process' );
57
- $this->addAction( 'wp_loaded', 'appendHeader', 999 );
58
- $this->addAction( 'processRevert' . self::$slug, 'revert' );
59
- }
60
-
61
- public function revert() {
62
- $this->getService()->revert();
63
- Settings::instance()->addToIssues( self::$slug );
64
- }
65
-
66
- public function appendHeader() {
67
- if ( headers_sent() ) {
68
- //header already sent, do nothing
69
- return;
70
- }
71
- $settings = Settings::instance();
72
- $data = $settings->getDValues( self::KEY );
73
- if ( ! $this->maybeSubmitHeader( 'X-XSS-Protection', isset( $data['somewhere'] ) ? $data['somewhere'] : false ) ) {
74
- $data['overrideable'] = false;
75
-
76
- return;
77
- }
78
- if ( is_array( $data ) && in_array( $data['mode'], [ 'sanitize', 'block', 'none' ] ) ) {
79
- $headers = '';
80
- switch ( $data['mode'] ) {
81
- case 'sanitize':
82
- $headers = 'X-XSS-Protection: 1';
83
- break;
84
- case 'block':
85
- $headers = 'X-XSS-Protection: 1; mode=block';
86
- break;
87
- default:
88
- break;
89
- }
90
- if ( strlen( $headers ) > 0 ) {
91
- header( trim( $headers ) );
92
- }
93
- }
94
- }
95
-
96
- /**
97
- * @return string
98
- */
99
- public function getTitle() {
100
- return __( "X-XSS-Protection Security Header", "defender-security" );
101
- }
102
-
103
- /**
104
- * Store a flag that we enable this
105
- * @return mixed|void
106
- */
107
- public function process() {
108
- $service = $this->getService();
109
- $service->mode = HTTP_Helper::retrievePost( 'mode' );
110
- $service->scenario = HTTP_Helper::retrievePost( 'scenario' );
111
- $ret = $service->process();
112
- if ( is_wp_error( $ret ) ) {
113
- wp_send_json_error( [ 'message' => $ret->get_error_message() ] );
114
- }
115
- Settings::instance()->addToResolved( self::$slug );
116
- }
117
-
118
- /**
119
- * @return Sh_XSS_Protection_Service
120
- */
121
- public function getService() {
122
- if ( self::$service == null ) {
123
- self::$service = new Sh_XSS_Protection_Service();
124
- }
125
-
126
- return self::$service;
127
- }
128
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/wp-rest-api-service.php DELETED
@@ -1,51 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use WP_Defender\Module\Hardener\IRule_Service;
10
- use WP_Defender\Module\Hardener\Model\Settings;
11
- use WP_Defender\Module\Hardener\Rule_Service;
12
-
13
- class WP_Rest_API_Service extends Rule_Service implements IRule_Service {
14
- const KEY = 'wp_rest_api';
15
-
16
- /**
17
- * @return bool
18
- */
19
- public function process() {
20
- //$mode = HTTP_Helper::retrievePost( 'mode' );
21
- //always this
22
- $mode = 'allow-auth';
23
- $settings = Settings::instance();
24
- $data = $settings->getDValues( self::KEY );
25
- if ( in_array( $mode, [ 'allow-auth', 'allow-all' ] ) ) {
26
- $data['mode'] = $mode;
27
- $settings->setDValues( self::KEY, $data );
28
- }
29
- }
30
-
31
- /**
32
- * @return bool
33
- */
34
- public function revert() {
35
- $settings = Settings::instance();
36
- $settings->setDValues( self::KEY, null );
37
- }
38
-
39
- /**
40
- * @return mixed
41
- */
42
- public function check() {
43
- $settings = Settings::instance();
44
- $data = $settings->getDValues( self::KEY );
45
- if ( is_array( $data ) && isset( $data['mode'] ) && in_array( $data['mode'], [ 'allow-auth', 'allow-all' ] ) ) {
46
- return true;
47
- }
48
-
49
- return false;
50
- }
51
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/wp-rest-api.php DELETED
@@ -1,120 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use WP_Defender\Module\Hardener\Model\Settings;
10
- use WP_Defender\Module\Hardener\Rule;
11
-
12
- class WP_Rest_Api extends Rule {
13
- static $slug = 'wp-rest-api';
14
- static $service;
15
-
16
- function getDescription() {
17
-
18
- }
19
-
20
- /**
21
- * @return bool
22
- */
23
- function check() {
24
- return $this->getService()->check();
25
- }
26
-
27
- /**
28
- * This will return the short summary why this rule show up as issue
29
- *
30
- * @return string
31
- */
32
- function getErrorReason() {
33
- return __( "The WordPress Rest API is publicly accessible. You may want to prevent unauthorized requests.", "defender-security" );
34
- }
35
-
36
- /**
37
- * This will return a short summary to show why this rule works
38
- * @return mixed
39
- */
40
- function getSuccessReason() {
41
- $mode = $this->getMiscData()['mode'];
42
- if ( $mode == 'allow-all' ) {
43
- return __( "You are currently allowing all requests to the REST API, good job!", "defender-security" );
44
- }
45
-
46
- return __( "You are currently blocking unauthorized requests to the REST API, good job!", "defender-security" );
47
- }
48
-
49
- public function getTitle() {
50
- return __( "WordPress REST API", "defender-security" );
51
- }
52
-
53
- function addHooks() {
54
- $this->addAction( 'processingHardener' . self::$slug, 'process' );
55
- $this->addAction( 'processRevert' . self::$slug, 'revert' );
56
- if ( in_array( self::$slug, (array) Settings::instance()->fixed ) ) {
57
- $this->addFilter( 'rest_authentication_errors', 'maybeAllow' );
58
- }
59
- }
60
-
61
- public function maybeAllow( $result ) {
62
- if ( ! empty( $result ) ) {
63
- return $result;
64
- }
65
-
66
- $mode = $this->getMiscData()['mode'];
67
- if ( $mode == 'allow-auth' && ! is_user_logged_in() ) {
68
- return new \WP_Error( 'rest_not_logged_in', __( 'The WordPress Rest API has been locked to authorized access only. Log in to use the API.', "defender-security" ), array( 'status' => 401 ) );
69
- }
70
-
71
- //delegate to other
72
-
73
- return $result;
74
- }
75
-
76
- function getMiscData() {
77
- $data = Settings::instance()->getDValues( WP_Rest_API_Service::KEY );
78
- $mode = 'allow-all';
79
- if ( is_array( $data ) && isset( $data['mode'] ) && in_array( $data['mode'], [ 'allow-auth', 'block-all' ] ) ) {
80
- $mode = $data['mode'];
81
- }
82
-
83
- return [
84
- 'mode' => $mode
85
- ];
86
- }
87
-
88
- function revert() {
89
- $ret = $this->getService()->revert();
90
- if ( ! is_wp_error( $ret ) ) {
91
- Settings::instance()->addToIssues( self::$slug );
92
- } else {
93
- wp_send_json_error( array(
94
- 'message' => $ret->get_error_message()
95
- ) );
96
- }
97
- }
98
-
99
- function process() {
100
- $ret = $this->getService()->process();
101
- if ( ! is_wp_error( $ret ) ) {
102
- Settings::instance()->addToResolved( self::$slug );
103
- } else {
104
- wp_send_json_error( array(
105
- 'message' => $ret->get_error_message()
106
- ) );
107
- }
108
- }
109
-
110
- /**
111
- * @return WP_Rest_API_Service
112
- */
113
- public function getService() {
114
- if ( self::$service == null ) {
115
- self::$service = new WP_Rest_API_Service();
116
- }
117
-
118
- return self::$service;
119
- }
120
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/wp-version-service.php DELETED
@@ -1,59 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use WP_Defender\Module\Hardener\IRule_Service;
9
- use WP_Defender\Module\Hardener\Rule_Service;
10
-
11
- class WP_Version_Service extends Rule_Service implements IRule_Service {
12
-
13
- /**
14
- * @return bool
15
- */
16
- public function check() {
17
- global $wp_version;
18
- if ( version_compare( $wp_version, $this->getLatestVersion(), '<' ) ) {
19
- return false;
20
- }
21
-
22
- return true;
23
- }
24
-
25
- /**
26
- * @return bool
27
- */
28
- public function getLatestVersion() {
29
- if ( ! function_exists( 'get_core_updates' ) ) {
30
- include_once ABSPATH . 'wp-admin/includes/update.php';
31
- }
32
- $update_data = get_core_updates();
33
-
34
- if ( $update_data === false ) {
35
- wp_version_check( array(), true );
36
- $update_data = get_core_updates();
37
- }
38
-
39
- if ( isset( $update_data[0] ) && is_object( $update_data[0] ) ) {
40
- $latest = $update_data[0];
41
-
42
- return $latest->version;
43
- }
44
-
45
- return false;
46
- }
47
-
48
- public function process() {
49
-
50
- }
51
-
52
- public function revert() {
53
-
54
- }
55
-
56
- public function listen() {
57
-
58
- }
59
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/component/wp-version.php DELETED
@@ -1,75 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Component;
7
-
8
- use WP_Defender\Module\Hardener\Rule;
9
-
10
- class WP_Version extends Rule {
11
- static $slug = 'wp-version';
12
- static $service;
13
-
14
- function getDescription() {
15
- $this->renderPartial( 'rules/wp-version' );
16
- }
17
-
18
- /**
19
- * @return bool
20
- */
21
- function check() {
22
- return $this->getService()->check();
23
- }
24
-
25
- function revert() {
26
- // TODO: Implement revert() method.
27
- }
28
-
29
- public function getTitle() {
30
- return __( "Update WordPress to latest version", "defender-security" );
31
- }
32
-
33
- /**
34
- * This will return the short summary why this rule show up as issue
35
- *
36
- * @return string
37
- */
38
- function getErrorReason() {
39
- return sprintf( __( "Your current WordPress version is out of date, which means you could be missing out on the latest security patches in v%s", "defender-security" ), $this->getService()->getLatestVersion() );
40
- }
41
-
42
- public function getMiscData() {
43
- return [
44
- 'latest_wp' => $this->getService()->getLatestVersion(),
45
- 'core_update_url' => network_admin_url( 'update-core.php' )
46
- ];
47
- }
48
-
49
- /**
50
- * This will return a short summary to show why this rule works
51
- * @return mixed
52
- */
53
- function getSuccessReason() {
54
- // TODO: Implement getSuccessReason() method.
55
- }
56
-
57
- function addHooks() {
58
- // TODO: Implement addHooks() method.
59
- }
60
-
61
- function process() {
62
- // TODO: Implement process() method.
63
- }
64
-
65
- /**
66
- * @return WP_Version_Service
67
- */
68
- function getService() {
69
- if ( static::$service == null ) {
70
- static::$service = new WP_Version_Service();
71
- }
72
-
73
- return static::$service;
74
- }
75
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/controller/main.php DELETED
@@ -1,273 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Controller;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use WP_Defender\Behavior\Utils;
10
- use WP_Defender\Controller;
11
- use WP_Defender\Module\Hardener;
12
-
13
- class Main extends Controller {
14
- protected $slug = 'wdf-hardener';
15
-
16
- /**
17
- * @return array
18
- */
19
- public function behaviors() {
20
- $behaviors = [
21
- 'utils' => '\WP_Defender\Behavior\Utils',
22
- 'endpoints' => '\WP_Defender\Behavior\Endpoint',
23
- 'wpmudev' => '\WP_Defender\Behavior\WPMUDEV'
24
- ];
25
-
26
- return $behaviors;
27
- }
28
-
29
- /**
30
- * Main constructor.
31
- */
32
- public function __construct() {
33
- if ( $this->isNetworkActivate( wp_defender()->plugin_slug ) ) {
34
- $this->addAction( 'network_admin_menu', 'adminMenu' );
35
- } else {
36
- $this->addAction( 'admin_menu', 'adminMenu' );
37
- }
38
-
39
- if ( $this->isInPage() ) {
40
- $this->addAction( 'defender_enqueue_assets', 'scripts', 11 );
41
- }
42
-
43
- if ( ! wp_next_scheduled( 'tweaksSendNotification' ) ) {
44
- wp_schedule_event( time(), 'twicedaily', 'tweaksSendNotification' );
45
- }
46
-
47
- $this->addAction( 'tweaksSendNotification', 'tweaksSendNotification' );
48
- $this->addAction( 'wp_loaded', 'maybeUnsubscribe' );
49
- }
50
-
51
- public function maybeUnsubscribe() {
52
- if ( ! is_user_logged_in() ) {
53
- return;
54
- }
55
-
56
- $action = HTTP_Helper::retrieveGet( 'action' );
57
- if ( $action == 'unsubscribe_notification' ) {
58
- $user = get_user_by( 'id', get_current_user_id() );
59
- if ( ! is_object( $user ) ) {
60
- return;
61
- }
62
- $model = Hardener\Model\Settings::instance();
63
- foreach ( $model->receipts as $key => $val ) {
64
- if ( $val['email'] == $user->user_email ) {
65
- unset( $model->receipts[ $key ] );
66
- break;
67
- }
68
- }
69
- $model->receipts = array_filter( $model->receipts );
70
- //check if empty recipients, then we disable notification
71
- if ( empty( $model->receipts ) ) {
72
- $model->notification = false;
73
- }
74
- $model->save();
75
- wp_redirect( network_admin_url( 'admin.php?page=wdf-hardener&view=notification' ) );
76
- exit;
77
- }
78
- }
79
-
80
- public function tweaksSendNotification() {
81
- $settings = Hardener\Model\Settings::instance();
82
-
83
- $lastAction = $settings->last_sent
84
- ? apply_filters( 'wd_tweaks_last_notification_sent', $settings->last_sent )
85
- : apply_filters( 'wd_tweaks_last_action_time', $settings->last_seen );
86
-
87
- if ( ! $lastAction ) {
88
- //should not in here
89
- $lastAction = $settings->last_seen = time();
90
- $settings->save();
91
- }
92
-
93
- //Daily
94
- if ( true === $settings->notification_repeat ) {
95
- if ( strtotime( apply_filters( 'wd_tweaks_notification_interval', '+24 hours' ), $lastAction ) > time() ) {
96
- return;
97
- }
98
- //or weekly
99
- } else {
100
- if ( strtotime( apply_filters( 'wd_tweaks_notification_interval', '+7 days' ), $lastAction ) > time() ) {
101
- return;
102
- }
103
- }
104
-
105
- //notification can send
106
- $settings->refreshStatus();
107
- $tweaks = $settings->getIssues();
108
-
109
- if ( ! count( $tweaks ) ) {
110
- return;
111
- }
112
-
113
- $no_reply_email = "noreply@" . parse_url( get_site_url(), PHP_URL_HOST );
114
- $no_reply_email = apply_filters( 'wd_scan_noreply_email', $no_reply_email );
115
- $headers = array(
116
- 'From: Defender <' . $no_reply_email . '>',
117
- 'Content-Type: text/html; charset=UTF-8'
118
- );
119
-
120
- $subject = _n( 'Security Tweak Report for %s. %s tweak needs attention.',
121
- 'Security Tweak Report for %s. %s tweaks needs attention.', count( $tweaks ), "defender-security" );
122
- $subject = sprintf( $subject, network_site_url(), count( $tweaks ) );
123
-
124
- foreach ( $settings->receipts as $receipt ) {
125
- $email = $receipt['email'];
126
- $ret = wp_mail( $email, $subject, $this->prepareEmailContent( $receipt['first_name'], $email ),
127
- $headers );
128
- }
129
- $settings->last_sent = time();
130
- $settings->save();
131
- }
132
-
133
- private function prepareEmailContent( $firstName, $email = null ) {
134
- $issues = "";
135
- foreach ( Hardener\Model\Settings::instance()->getIssues() as $issue ) {
136
- $issue = '<tr style="border:none;padding:0;text-align:left;vertical-align:top">
137
- <td class="wpmudev-table__row--label"
138
- style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;border-radius:0 0 0 4px;border-top:.5px solid #d8d8d8;color:#333;font-family:\'Open Sans\',Helvetica,Arial,sans-serif;font-size:16px;font-weight:600;hyphens:auto;line-height:20px;margin:0;padding:10px 15px;text-align:left;vertical-align:top;word-wrap:break-word">
139
- <img class="wpmudev-table__icon"
140
- src="' . wp_defender()->getPluginUrl() . 'assets/email-assets/img/Warning@2x.png"
141
- alt="Hero Image"
142
- style="-ms-interpolation-mode:bicubic;clear:both;display:inline-block;margin-right:10px;max-width:100%;outline:0;text-decoration:none;vertical-align:middle;width:18px">
143
- ' . $issue->getTitle() . '
144
- <span style="color: #888888;font-family: \'Open Sans\';padding-left: 32px;font-size: 13px;font-weight:300;letter-spacing: -0.25px;line-height: 22px;display: block">
145
- ' . $issue->getErrorReason() . '
146
- </span>
147
- </td>
148
- <td class="wpmudev-table__row--warning text-right"
149
- style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;border-radius:0 0 4px 0;border-top:.5px solid #d8d8d8;color:#FACD25;font-family:\'Open Sans\',Helvetica,Arial,sans-serif;font-size:12px;font-weight:400;hyphens:auto;line-height:20px;margin:0;padding:10px 15px;text-align:right;vertical-align:top;word-wrap:break-word">
150
- </td>
151
- </tr>';
152
- $issues .= $issue;
153
- }
154
- $contents = $this->renderPartial( 'email/notification', array(
155
- 'userName' => $firstName,
156
- 'siteUrl' => network_site_url(),
157
- 'viewUrl' => apply_filters( 'report_email_logs_link', network_admin_url( 'admin.php?page=wdf-hardener' ),
158
- $email ),
159
- 'issues' => $issues,
160
- 'count' => count( Hardener\Model\Settings::instance()->getIssues() )
161
- ), false );
162
-
163
- return $contents;
164
- }
165
-
166
- /**
167
- * Add submit admin page
168
- */
169
- public function adminMenu() {
170
- $cap = is_multisite() ? 'manage_network_options' : 'manage_options';
171
- add_submenu_page( 'wp-defender', esc_html__( "Security Tweaks", "defender-security" ),
172
- esc_html__( "Security Tweaks", "defender-security" ), $cap, $this->slug, array(
173
- &$this,
174
- 'actionIndex'
175
- ) );
176
- }
177
-
178
- /**
179
- * Main screen
180
- */
181
- public function actionIndex() {
182
- //update the last seen
183
- $settings = Hardener\Model\Settings::instance();
184
- $settings->last_seen = time();
185
- $settings->save();
186
-
187
- return $this->render( 'main' );
188
- }
189
-
190
- /**
191
- * Enqueue scripts & styles
192
- */
193
- public function scripts() {
194
- if ( $this->isInPage() ) {
195
- wp_enqueue_style( 'defender' );
196
- wp_register_script( 'defender-hardener', wp_defender()->getPluginUrl() . 'assets/app/security-tweaks.js',
197
- array(
198
- 'def-vue',
199
- 'defender',
200
- 'wp-i18n'
201
- ), false, true );
202
- wp_localize_script( 'defender-hardener', 'security_tweaks', $this->_scriptsData() );
203
- Utils::instance()->createTranslationJson( 'defender-hardener' );
204
- wp_set_script_translations( 'defender-hardener', 'wpdef', wp_defender()->getPluginPath() . 'languages' );
205
- wp_enqueue_script( 'defender-hardener' );
206
- wp_enqueue_script( 'wpmudev-sui' );
207
- }
208
- }
209
-
210
- /**
211
- * @return array
212
- */
213
- public function _scriptsData() {
214
- if ( ! $this->checkPermission() ) {
215
- return [];
216
- }
217
- global $wp_version;
218
- $settings = Hardener\Model\Settings::instance();
219
-
220
- return [
221
- 'summary' => [
222
- 'issues_count' => $this->getCount( 'issues' ),
223
- 'fixed_count' => $this->getCount( 'fixed' ),
224
- 'ignore_count' => $this->getCount( 'ignore' ),
225
- 'php_version' => phpversion(),
226
- 'wp_version' => $wp_version
227
- ],
228
- 'issues' => $settings->getTweaksAsArray( 'issues', true ),
229
- 'fixed' => $settings->getTweaksAsArray( 'fixed', true ),
230
- 'ignored' => $settings->getTweaksAsArray( 'ignore', true ),
231
- 'endpoints' => $this->getAllAvailableEndpoints( Hardener::getClassName() ),
232
- 'nonces' => [
233
- 'processTweak' => wp_create_nonce( 'processTweak' ),
234
- 'ignoreTweak' => wp_create_nonce( 'ignoreTweak' ),
235
- 'restoreTweak' => wp_create_nonce( 'restoreTweak' ),
236
- 'revertTweak' => wp_create_nonce( 'revertTweak' ),
237
- 'updateSettings' => wp_create_nonce( 'updateSettings' ),
238
- 'recheck' => wp_create_nonce( 'recheck' )
239
- ],
240
- 'model' => [
241
- 'notification_repeat' => $settings->notification_repeat,
242
- 'recipients' => $settings->receipts,
243
- 'notification' => $settings->notification
244
- ]
245
- ];
246
- }
247
-
248
- /**
249
- *
250
- * @param $type
251
- *
252
- * @return int
253
- */
254
- public function getCount( $type ) {
255
- $settings = Hardener\Model\Settings::instance();
256
-
257
- switch ( $type ) {
258
- case 'issues':
259
- return count( (array) array_filter( $settings->issues ) );
260
- break;
261
- case 'fixed':
262
- return count( (array) array_filter( $settings->fixed ) );
263
- break;
264
- case 'ignore':
265
- return count( (array) array_filter( $settings->ignore ) );
266
- break;
267
- default:
268
- //param not from the button on frontend, log it
269
- error_log( sprintf( 'Unexpected value %s from IP %s', $type, Utils::instance()->getUserIp() ) );
270
- break;
271
- }
272
- }
273
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/controller/rest.php DELETED
@@ -1,197 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Controller;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use Hammer\Helper\WP_Helper;
10
- use WP_Defender\Behavior\Utils;
11
- use WP_Defender\Controller;
12
- use WP_Defender\Module\Hardener;
13
- use WP_Defender\Module\Hardener\Model\Settings;
14
-
15
- class Rest extends Controller {
16
- public function __construct() {
17
- $namespace = 'wp-defender/v1';
18
- $namespace .= '/tweaks';
19
- $routes = [
20
- $namespace . '/processTweak' => 'processTweak',
21
- $namespace . '/revertTweak' => 'revertTweak',
22
- $namespace . '/ignoreTweak' => 'ignoreTweak',
23
- $namespace . '/restoreTweak' => 'restoreTweak',
24
- $namespace . '/updateSettings' => 'updateSettings',
25
- $namespace . '/reCheck' => 'reCheck',
26
- ];
27
- $this->registerEndpoints( $routes, Hardener::getClassName() );
28
- }
29
-
30
- /**
31
- * Save settings
32
- */
33
- public function updateSettings() {
34
- if ( ! $this->checkPermission() ) {
35
- return;
36
- }
37
-
38
- if ( ! wp_verify_nonce( HTTP_Helper::retrieveGet( '_wpnonce' ), 'updateSettings' ) ) {
39
- return;
40
- }
41
-
42
- $settings = Hardener\Model\Settings::instance();
43
- $data = stripslashes( $_POST['data'] );
44
- $data = json_decode( $data, true );
45
- $settings->notification = $data['notification'];
46
- $settings->notification_repeat = $data['notification_repeat'];
47
- $recipients = [];
48
- foreach ( $data['recipients'] as $key => $recipient ) {
49
- if ( filter_var( $recipient['email'], FILTER_VALIDATE_EMAIL ) ) {
50
- $recipients[] = $recipient;
51
- }
52
- }
53
- $settings->receipts = $recipients;
54
- $settings->save();
55
- $this->submitStatsToDev();
56
- wp_send_json_success( array(
57
- 'message' => __( "Your settings have been updated.", "defender-security" )
58
- ) );
59
- }
60
-
61
- public function reCheck() {
62
- if ( ! $this->checkPermission() ) {
63
- return;
64
- }
65
-
66
- if ( ! wp_verify_nonce( HTTP_Helper::retrieveGet( '_wpnonce' ), 'recheck' ) ) {
67
- return;
68
- }
69
- $type = HTTP_Helper::retrievePost( 'type' );
70
- if ( $type == 'prevent-php' ) {
71
- $url = WP_Helper::getUploadUrl();
72
- $url = $url . '/wp-defender/index.php';
73
- } else {
74
- $url = wp_defender()->getPluginUrl() . 'languages/wpdef-default.pot';
75
- }
76
- $model = Settings::instance();
77
- $cache = $model->getDValues( 'head_requests' );
78
- Utils::instance()->log( sprintf( 'clean up %s', $url ), 'tweaks' );
79
- unset( $cache[ $url ] );
80
- $model->setDValues( 'head_requests', $cache );
81
- wp_send_json_success( $this->tweaksSummary() );
82
- }
83
-
84
- /**
85
- * Endpoint for recieve process request for all tweaks, we will dispatch the envelope to tweak from here
86
- */
87
- public function processTweak() {
88
- if ( ! $this->checkPermission() ) {
89
- return;
90
- }
91
-
92
- if ( ! wp_verify_nonce( HTTP_Helper::retrieveGet( '_wpnonce' ), 'processTweak' ) ) {
93
- return;
94
- }
95
-
96
- $slug = HTTP_Helper::retrievePost( 'slug' );
97
- do_action( "processingHardener" . $slug );
98
- //fall back
99
- wp_send_json_success( array_merge( [
100
- 'message' => __( "Security tweak successfully resolved.", "defender-security" ),
101
- ], $this->tweaksSummary() ) );
102
- }
103
-
104
- /**
105
- * Revert a tweak request, this will un-apply the affect of a tweak
106
- */
107
- public function revertTweak() {
108
- if ( ! $this->checkPermission() ) {
109
- return;
110
- }
111
-
112
- if ( ! wp_verify_nonce( HTTP_Helper::retrieveGet( '_wpnonce' ), 'revertTweak' ) ) {
113
- return;
114
- }
115
-
116
- $slug = HTTP_Helper::retrievePost( 'slug' );
117
- do_action( "processRevert" . $slug );
118
- //fall back
119
- wp_send_json_success( array_merge( [
120
- 'message' => __( "Security tweak successfully reverted.", "defender-security" ),
121
- ], $this->tweaksSummary() ) );
122
- }
123
-
124
- /**
125
- * Ignore a tweak request
126
- */
127
- public function ignoreTweak() {
128
- if ( ! $this->checkPermission() ) {
129
- return;
130
- }
131
-
132
- if ( ! wp_verify_nonce( HTTP_Helper::retrieveGet( '_wpnonce' ), 'ignoreTweak' ) ) {
133
- return;
134
- }
135
- $slug = HTTP_Helper::retrievePost( 'slug' );
136
- $rule = Hardener\Model\Settings::instance()->getRuleBySlug( $slug );
137
- if ( is_object( $rule ) ) {
138
- $rule->ignore();
139
- wp_send_json_success( array_merge( [
140
- 'message' => __( "Security tweak successfully ignored.", "defender-security" ),
141
- ], $this->tweaksSummary() ) );
142
- }
143
- }
144
-
145
- /**
146
- * Restore request, to move a tweak from ignored to issues section
147
- */
148
- public function restoreTweak() {
149
- if ( ! $this->checkPermission() ) {
150
- return;
151
- }
152
-
153
- if ( ! wp_verify_nonce( HTTP_Helper::retrieveGet( '_wpnonce' ), 'restoreTweak' ) ) {
154
- return;
155
- }
156
-
157
- $slug = HTTP_Helper::retrievePost( 'slug' );
158
- $rule = Hardener\Model\Settings::instance()->getRuleBySlug( $slug );
159
- if ( is_object( $rule ) ) {
160
- $rule->restore();
161
- wp_send_json_success( array_merge( [
162
- 'message' => __( "Security tweak successfully restored.", "defender-security" ),
163
- ], $this->tweaksSummary() ) );
164
- }
165
- }
166
-
167
- /**
168
- * Shorthand for returning the count of tweaks, by each section
169
- * @return array
170
- */
171
- private function tweaksSummary() {
172
- $settings = Hardener\Model\Settings::instance( true );
173
-
174
- return [
175
- 'summary' => [
176
- 'issues' => count( $settings->issues ),
177
- 'fixed' => count( $settings->fixed ),
178
- 'ignore' => count( $settings->ignore ),
179
- ],
180
- 'issues' => $settings->getTweaksAsArray( 'issues', true ),
181
- 'fixed' => $settings->getTweaksAsArray( 'fixed', true ),
182
- 'ignore' => $settings->getTweaksAsArray( 'ignore', true ),
183
- ];
184
- }
185
-
186
- /**
187
- * Declaring behaviors
188
- * @return array
189
- */
190
- public function behaviors() {
191
- $behaviors = array(
192
- 'utils' => '\WP_Defender\Behavior\Utils',
193
- );
194
-
195
- return $behaviors;
196
- }
197
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/irule-service.php DELETED
@@ -1,30 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener;
7
-
8
- /**
9
- * Interface IRule_Service
10
- * @package WP_Defender\Module\Hardener
11
- */
12
- interface IRule_Service {
13
- /**
14
- * Check if current rule fixed or not
15
- * @return bool
16
- */
17
- public function check();
18
-
19
- /**
20
- * Process the rule
21
- * @return bool|\WP_Error
22
- */
23
- public function process();
24
-
25
- /**
26
- * Revert if able
27
- * @return bool|\WP_Error
28
- */
29
- public function revert();
30
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/js/scripts.js DELETED
@@ -1,230 +0,0 @@
1
- jQuery(function ($) {
2
- WDHardener.formHandler();
3
- WDHardener.settingsFormHandler();
4
- var hash = window.location.hash;
5
- if ($(hash).size() > 0) {
6
- $(hash).addClass('sui-accordion-item--open');
7
- }
8
- //On key up or is a user decides to paste
9
- $('.hardener-instructions textarea.hardener-php-excuted-ignore').on('keyup keypress paste', function (e) {
10
- var text_val = $(this).val();
11
- //We cant allow index.php
12
- if (text_val.includes('index.php')) {
13
- text_val = text_val.replace(/index.php/g, '');
14
- $(this).val(text_val);
15
- }
16
-
17
- //no fancy scripts or html code. We also validate server side
18
- if (/<[a-z][\s\S]*>/i.test(text_val)) {
19
- text_val = text_val.replace(/<\/?[^>]+(>|$)/g, "");
20
- $(this).val(text_val);
21
- }
22
-
23
- //Nginx
24
- var excludedFiles = text_val.split('\n');
25
- var newRule = "";
26
- var $wp_content = $('.hardener-wp-content-dir').val();
27
- $.each(excludedFiles, function (index, file) {
28
- if (file) {
29
- newRule += "\n location ~* ^" + $wp_content + "/.*&#92;" + file + "$ {" +
30
- " \n allow all;" +
31
- "\n}";
32
- }
33
- });
34
- $('span.hardener-nginx-extra-instructions').html(newRule);
35
- });
36
-
37
- /**
38
- * Validate that the number put is greater than 0 and is actually a number
39
- */
40
- $(document).on('keyup keypress paste', '.defender-login-duration', function () {
41
- var text_val = $(this).val();
42
- if (/^-?[0-9]+$/i.test(text_val)) {
43
- //is integer
44
- if (text_val <= 0) {
45
- $(this).val('');
46
- }
47
- } else {
48
- $(this).val('');
49
- }
50
- });
51
-
52
- /**
53
- * Pevent PHP update posts toggle
54
- */
55
- $(document).on('change', 'input.trackback-toggle-update-posts', function () {
56
- if (this.checked) {
57
- $('.hardener-frm-process-trackback [name="updatePosts"]').val('yes');
58
- } else {
59
- $('.hardener-frm-process-trackback [name="updatePosts"]').val('no');
60
- }
61
- });
62
-
63
- /**
64
- * Toggle text area
65
- */
66
- $(document).on('click', 'button.hardener-php-excuted-execption', function () {
67
- $('.hardener-instructions textarea.hardener-php-excuted-ignore').toggle('fast');
68
- });
69
-
70
- $('div.hardener').on('form-submitted', function (e, data, form) {
71
- if (form.hasClass('rule-process') == false) {
72
- return;
73
- }
74
- if (data.success == true) {
75
- Defender.showNotification('success', data.data.message);
76
- $('.count-issues').text(data.data.issues);
77
- $('.count-ignored').text(data.data.ignore);
78
- $('.count-resolved').text(data.data.fixed);
79
- $('.issues-actioned').text(10 - data.data.issues);
80
- if (data.data.issues > 0) {
81
- $('.issues i').removeClass('sui-icon-check-tick sui-success').addClass('sui-icon-info sui-warning');
82
- $('.count-issues').removeClass('wd-hide');
83
- } else {
84
- $('.count-issues').addClass('wd-hide');
85
- $('.issues i').removeClass('sui-icon-info sui-warning').addClass('sui-icon-check-tick sui-success');
86
- }
87
- if (data.data.ignore > 0) {
88
- $('.count-ignored').removeClass('wd-hide');
89
- } else {
90
- $('.count-ignored').addClass('wd-hide');
91
- }
92
- if (data.data.fixed > 0) {
93
- $('.count-resolved').removeClass('wd-hide');
94
- } else {
95
- $('.count-resolved').addClass('wd-hide');
96
- }
97
- var update_rules = true;
98
- if (typeof data.data.update !== "undefined") {
99
- update_rules = false;
100
- }
101
- if (update_rules) {
102
- form.closest('.sui-accordion-item').slideUp(500, function () {
103
- $(this).remove();
104
- if ($('.sui-accordion-item').size() == 0) {
105
- setTimeout(function () {
106
- location.reload();
107
- }, 500)
108
- }
109
- });
110
- }
111
- } else {
112
- Defender.showNotification('error', data.data.message);
113
- }
114
- });
115
- $('div.hardener').on('settings-form-submitted', function (e, data, form) {
116
- console.log(data);
117
- if (data.success == true) {
118
- location.reload();
119
- Defender.showNotification('success', data.data.message);
120
- } else {
121
- Defender.showNotification('error', data.data.message);
122
- }
123
- });
124
- });
125
-
126
- function debounce(fn, delay) {
127
- var timer = null;
128
- return function () {
129
- var context = this, args = arguments;
130
- clearTimeout(timer);
131
- timer = setTimeout(function () {
132
- fn.apply(context, args);
133
- }, delay);
134
- };
135
- }
136
-
137
- window.WDHardener = window.WDHardener || {};
138
-
139
- WDHardener.formHandler = function () {
140
- var jq = jQuery;
141
- jq('body').on('submit', '.hardener-frm', function () {
142
- var data = jq(this).serialize();
143
- console.log(data);
144
- var that = jq(this);
145
- jq.ajax({
146
- type: 'POST',
147
- url: ajaxurl,
148
- data: data,
149
- beforeSend: function () {
150
- that.find('.sui-button').attr('disabled', 'disabled');
151
- that.find('.sui-button').html('<span class="sui-loading-text">' + that.find('.sui-button').text())
152
- that.find('.sui-button').append('<i class="sui-icon-loader sui-loading" aria-hidden="true"></i>');
153
- that.find('.sui-button').addClass('sui-button-onload')
154
- },
155
- success: function (data) {
156
- if (data.data != undefined && data.data.reload != undefined) {
157
- if (data.data.message != undefined) {
158
-
159
- //Modal should not close
160
- Defender.showNotification('success', data.data.message, false);
161
-
162
- //Count down timer
163
- if (jq('.hardener-timer').length) {
164
- var duration = data.data.reload;
165
- var refreshTimer = setInterval(function () {
166
- seconds = parseInt(duration % 60, 10);
167
- seconds = seconds < 10 ? "0" + seconds : seconds;
168
- jq('.hardener-timer').html(seconds);
169
-
170
- if (--duration < 0) {
171
- clearInterval(refreshTimer);
172
- if (data.data != undefined && data.data.url != undefined) {
173
- location.href = data.data.url;
174
- } else {
175
- location.reload()
176
- }
177
- }
178
- }, 1000);
179
- }
180
-
181
- } else {
182
- setTimeout(function () {
183
- if (data.data != undefined && data.data.url != undefined) {
184
- location.href = data.data.url;
185
- } else {
186
- location.reload()
187
- }
188
- }, 1500)
189
- }
190
- } else if (data.data != undefined && data.data.url != undefined) {
191
- location.href = data.data.url;
192
- } else {
193
- that.find('.sui-button').html(that.find('.sui-button').text())
194
- that.find('.sui-button').removeClass('sui-button-onload')
195
- that.find('.sui-button').removeAttr('disabled');
196
- jq('div.hardener').trigger('form-submitted', [data, that])
197
- }
198
- }
199
- })
200
- return false;
201
- })
202
- }
203
-
204
- WDHardener.settingsFormHandler = function () {
205
- var jq = jQuery;
206
- jq('body').on('submit', '.hardener-settings-frm', function () {
207
- var data = jq(this).serialize();
208
- var that = jq(this);
209
- jq.ajax({
210
- type: 'POST',
211
- url: ajaxurl,
212
- data: data,
213
- beforeSend: function () {
214
- that.find('.sui-button-blue').attr('disabled', 'disabled');
215
- },
216
- success: function (data) {
217
- if (data.data != undefined && data.data.url != undefined) {
218
- location.href = data.data.url;
219
- } else {
220
- that.find('.sui-button').removeAttr('disabled');
221
- jq('div.hardener').trigger('settings-form-submitted', [data, that])
222
- }
223
- },
224
- error: function (xhr) {
225
- jq('div.hardener').trigger('settings-form-submitted', [data, that, xhr])
226
- }
227
- })
228
- return false;
229
- })
230
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/model/settings.php DELETED
@@ -1,620 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener\Model;
7
-
8
- use Hammer\Helper\WP_Helper;
9
- use WP_Defender\Behavior\Utils;
10
- use WP_Defender\Module\Hardener\Component\Change_Admin;
11
- use WP_Defender\Module\Hardener\Component\Disable_File_Editor;
12
- use WP_Defender\Module\Hardener\Component\Disable_Trackback;
13
- use WP_Defender\Module\Hardener\Component\Disable_Xml_Rpc;
14
- use WP_Defender\Module\Hardener\Component\Hide_Error;
15
- use WP_Defender\Module\Hardener\Component\Login_Duration;
16
- use WP_Defender\Module\Hardener\Component\PHP_Version;
17
- use WP_Defender\Module\Hardener\Component\Prevent_Enum_Users;
18
- use WP_Defender\Module\Hardener\Component\Prevent_Php;
19
- use WP_Defender\Module\Hardener\Component\Protect_Information;
20
- use WP_Defender\Module\Hardener\Component\Security_Key;
21
- use WP_Defender\Module\Hardener\Component\WP_Version;
22
- use WP_Defender\Module\Hardener\Rule;
23
-
24
- class Settings extends \Hammer\WP\Settings {
25
- private static $_instance;
26
- /**
27
- * @var string
28
- */
29
- public $id = 'hardener_settings';
30
- /**
31
- * Contains issues rules
32
- *
33
- * @var array
34
- */
35
- public $issues = array();
36
-
37
- /**
38
- * Contains fixed rules
39
- * @var array
40
- */
41
-
42
- public $fixed = array();
43
-
44
- /**
45
- * Contains ignored issue
46
- * @var array
47
- */
48
- public $ignore = array();
49
-
50
- /**
51
- * Store the last status check, we will check & fetch the status intervally, this can reduce load time.
52
- * @var null
53
- */
54
- public $last_status_check = null;
55
-
56
- /**
57
- * Toggle notification
58
- * @var bool
59
- */
60
- public $notification = true;
61
- /**
62
- * @var bool
63
- */
64
- public $notification_repeat = false;
65
-
66
- /**
67
- * Holding recipients info
68
- * @var array
69
- */
70
- public $receipts = array();
71
-
72
- /**
73
- * Contains all the data generated by rules
74
- * @var array
75
- */
76
- public $data = array();
77
-
78
- /**
79
- * Holding excluded file path info
80
- * @var array
81
- */
82
- public $exclude_file_paths = array();
83
-
84
- /**
85
- * Holds new htconfig structure for defender
86
- *
87
- * @var array
88
- */
89
- public $new_htconfig = array();
90
-
91
- /**
92
- * Current active server
93
- *
94
- * @var String
95
- */
96
- public $active_server = 'apache';
97
-
98
- /**
99
- * Last time visit into the hardener page
100
- *
101
- * @var integer
102
- */
103
- public $last_seen;
104
-
105
- /**
106
- * Last notification sent out
107
- *
108
- * @var integer
109
- */
110
- public $last_sent;
111
-
112
- /**
113
- * @var string
114
- */
115
- public $min_php_version = '';
116
- /**
117
- * @var string
118
- */
119
- public $stable_php_version = '';
120
-
121
- /**
122
- * We have to flag if the db prefix changed by us or not
123
- *
124
- * @var bool
125
- */
126
- public $is_prefix_changed = false;
127
-
128
- public $automate = false;
129
-
130
- public function __construct( $id, $is_multi ) {
131
- if ( is_admin() || is_network_admin() && current_user_can( 'manage_options' ) ) {
132
- $user = wp_get_current_user();
133
- if ( is_object( $user ) ) {
134
- $this->receipts[] = array(
135
- 'first_name' => $user->display_name,
136
- 'email' => $user->user_email
137
- );
138
- }
139
- }
140
- $this->active_server = Utils::instance()->determineServer();
141
- parent::__construct( $id, $is_multi );
142
- $this->notification = ! ! $this->notification;
143
- if ( ! is_array( $this->receipts ) ) {
144
- $this->receipts = [];
145
- }
146
- $this->receipts = array_values( $this->receipts );
147
- }
148
-
149
- /**
150
- * @param $slug
151
- * @param bool $devPush
152
- */
153
- public function addToIssues( $slug, $devPush = true ) {
154
- $this->addToList( 'issues', $slug, $devPush );
155
- }
156
-
157
- /**
158
- * shorthand to add to a list
159
- *
160
- * @param $slug
161
- * @param $devPush
162
- */
163
- public function addToIgnore( $slug, $devPush = true ) {
164
- $this->addToList( 'ignore', $slug, $devPush );
165
- }
166
-
167
- /**
168
- * shorthand to add to a list
169
- *
170
- * @param $slug
171
- * @param $devPush
172
- */
173
- public function addToResolved( $slug, $devPush = true ) {
174
- $this->addToList( 'fixed', $slug, $devPush );
175
- }
176
-
177
- /**
178
- * @param $list
179
- * @param $slug
180
- * @param $devPush
181
- */
182
- private function addToList( $list, $slug, $devPush ) {
183
- $lists = array(
184
- 'issues',
185
- 'fixed',
186
- 'ignore'
187
- );
188
- if ( ! in_array( $list, $lists ) ) {
189
- return;
190
- }
191
-
192
- //remove from lists
193
- foreach ( $lists as $l ) {
194
- if ( $l == $list ) {
195
- continue;
196
- }
197
- $key = array_search( $slug, $this->{$l} );
198
- if ( $key !== false ) {
199
- unset( $this->{$l}[ $key ] );
200
- }
201
- }
202
-
203
- array_push( $this->$list, $slug );
204
- $this->$list = array_unique( $this->$list );
205
- $this->last_status_check = time();
206
- $this->save();
207
- if ( $devPush ) {
208
- Utils::instance()->submitStatsToDev();
209
- }
210
- }
211
-
212
- /**
213
- * @return Settings
214
- */
215
- public static function instance( $refresh = false ) {
216
- if ( $refresh == true ) {
217
- self::$_instance = null;
218
- }
219
- if ( is_null( self::$_instance ) ) {
220
- self::$_instance = new Settings( 'wd_hardener_settings',
221
- WP_Helper::is_network_activate( wp_defender()->plugin_slug ) );
222
- }
223
-
224
- return self::$_instance;
225
- }
226
-
227
- /**
228
- * refresh rules status and store the index
229
- */
230
- public function refreshStatus() {
231
- $definedRules = $this->getDefinedRules( true );
232
- $this->fixed = array();
233
- $this->issues = array();
234
- if ( ! is_array( $this->ignore ) ) {
235
- $this->ignore = array();
236
- }
237
-
238
- foreach ( $definedRules as $rule ) {
239
- if (
240
- empty( $rule::$slug )
241
- || in_array( $rule::$slug, $this->ignore, true )
242
- ) {
243
- //this rule ignored, no process
244
- continue;
245
- }
246
- if ( $rule->getService()->check() ) {
247
- $this->fixed[] = $rule::$slug;
248
- } else {
249
- $this->issues[] = $rule::$slug;
250
- }
251
- }
252
-
253
- $this->last_status_check = time();
254
- $this->save();
255
- }
256
-
257
- /**
258
- * Get Issues tweaks as object
259
- * @return Rule[]
260
- */
261
- public function getIssues() {
262
- $rules = $this->getDefinedRules( true );
263
- $issues = array();
264
- foreach ( $this->issues as $issue ) {
265
- if ( isset( $rules[ $issue ] ) ) {
266
- $issues[] = $rules[ $issue ];
267
- }
268
- }
269
-
270
- return $issues;
271
- }
272
-
273
- /**
274
- * Filter the tweaks and return data as array
275
- *
276
- *
277
- * @param $type
278
- *
279
- * @return array
280
- */
281
- public function getTweaksAsArray( $type, $sort = false ) {
282
- $rules = $this->getDefinedRules( true );
283
-
284
- $arr = $this->$type;
285
- $data = array();
286
- foreach ( $arr as $tweak ) {
287
- if ( isset( $rules[ $tweak ] ) ) {
288
- $curr = $rules[ $tweak ];
289
- $data[ $curr::$slug ] = array(
290
- 'slug' => $curr::$slug,
291
- 'title' => $curr->getTitle(),
292
- 'errorReason' => $curr->getErrorReason(),
293
- 'successReason' => $curr->getSuccessReason(),
294
- 'status' => $type,
295
- 'misc' => $curr->getMiscData()
296
- );
297
- }
298
- }
299
-
300
- if ( $sort ) {
301
- ksort( $data );
302
- }
303
-
304
- return $data;
305
- }
306
-
307
- /**
308
- * @return array
309
- */
310
- public function getIgnore() {
311
- $rules = $this->getDefinedRules( true );
312
- $issues = array();
313
- foreach ( $this->ignore as $issue ) {
314
- if ( isset( $rules[ $issue ] ) ) {
315
- $issues[] = $rules[ $issue ];
316
- }
317
- }
318
-
319
- return $issues;
320
- }
321
-
322
- /**
323
- * @return Rule[]
324
- */
325
- public function getFixed() {
326
- $rules = $this->getDefinedRules( true );
327
- $issues = array();
328
- if ( is_array( $this->fixed ) && ! empty( $this->fixed ) ) {
329
- foreach ( $this->fixed as $issue ) {
330
- if ( isset( $rules[ $issue ] ) ) {
331
- $issues[] = $rules[ $issue ];
332
- }
333
- }
334
- }
335
-
336
- return $issues;
337
- }
338
-
339
- /**
340
- * @param $slug
341
- *
342
- * @return Rule
343
- */
344
- public function getRuleBySlug( $slug ) {
345
- $rules = $this->getDefinedRules( true );
346
- if ( isset( $rules[ $slug ] ) ) {
347
- return $rules[ $slug ];
348
- }
349
- }
350
-
351
- /**
352
- *
353
- * @param bool $init
354
- *
355
- * @return array
356
- */
357
- public function getDefinedRules( $init = false ) {
358
- return array(
359
- Disable_Trackback::$slug => $init == true ? new Disable_Trackback() : Disable_Trackback::getClassName(),
360
- WP_Version::$slug => $init == true ? new WP_Version() : WP_Version::getClassName(),
361
- PHP_Version::$slug => $init == true ? new PHP_Version() : PHP_Version::getClassName(),
362
- Change_Admin::$slug => $init == true ? new Change_Admin() : Change_Admin::getClassName(),
363
- //DB_Prefix::$slug => $init == true ? new DB_Prefix() : DB_Prefix::getClassName(),
364
- Disable_File_Editor::$slug => $init == true ? new Disable_File_Editor() : Disable_File_Editor::getClassName(),
365
- Hide_Error::$slug => $init == true ? new Hide_Error() : Hide_Error::getClassName(),
366
- Prevent_Enum_Users::$slug => $init == true ? new Prevent_Enum_Users() : Prevent_Enum_Users::getClassName(),
367
- Security_Key::$slug => $init == true ? new Security_Key() : Security_Key::getClassName(),
368
- Protect_Information::$slug => $init == true ? new Protect_Information() : Protect_Information::getClassName(),
369
- Prevent_Php::$slug => $init == true ? new Prevent_Php() : Prevent_Php::getClassName(),
370
- Login_Duration::$slug => $init == true ? new Login_Duration() : Login_Duration::getClassName(),
371
- Disable_Xml_Rpc::$slug => $init == true ? new Disable_Xml_Rpc() : Disable_Xml_Rpc::getClassName(),
372
- //WP_Rest_Api::$slug => $init == true ? new WP_Rest_Api() : WP_Rest_Api::getClassName(),
373
- );
374
- }
375
-
376
- /**
377
- * @param $key
378
- *
379
- * @return mixed
380
- */
381
- public function getDValues( $key ) {
382
- if ( is_array( $this->data ) && isset( $this->data[ $key ] ) ) {
383
- return $this->data[ $key ];
384
- }
385
-
386
- return null;
387
- }
388
-
389
- /**
390
- * @param $key
391
- * @param $value
392
- */
393
- public function setDValues( $key, $value ) {
394
- if ( ! is_array( $this->data ) ) {
395
- $this->data = [];
396
- }
397
- if ( $value == null ) {
398
- unset( $this->data[ $key ] );
399
- } else {
400
- $this->data[ $key ] = $value;
401
- }
402
- $this->save();
403
- }
404
-
405
- /**
406
- * Save the exclude file paths
407
- *
408
- * @param Array - $paths
409
- */
410
- public function saveExcludedFilePaths( $paths = array() ) {
411
- $this->exclude_file_paths = $paths;
412
- }
413
-
414
- /**
415
- * Save the htconfig
416
- *
417
- * @param Array - $config
418
- */
419
- public function saveNewHtConfig( $config = array() ) {
420
- $this->new_htconfig = $config;
421
- }
422
-
423
- /**
424
- * Get the exclude file paths
425
- *
426
- * @return Array - $paths
427
- */
428
- public function getExcludedFilePaths() {
429
- return $this->exclude_file_paths;
430
- }
431
-
432
- /**
433
- * Get the new htconfig
434
- *
435
- * @return Array - $paths
436
- */
437
- public function getNewHtConfig() {
438
- return $this->new_htconfig;
439
- }
440
-
441
- /**
442
- * Set the active server
443
- *
444
- * @param String $server
445
- */
446
- public function setActiveServer( $server ) {
447
- $this->active_server = $server;
448
- }
449
-
450
- /**
451
- * @return array
452
- */
453
- public function events() {
454
- return array(
455
- self::EVENT_BEFORE_SAVE => array(
456
- array(
457
- function () {
458
- //need to turn off notification or report off if no recipients
459
- if ( empty( $this->receipts ) ) {
460
- $this->notification = false;
461
- }
462
- //sanitize
463
- foreach ( $this->receipts as $key => &$receipt ) {
464
- $receipt = array_map( 'sanitize_text_field', $receipt );
465
- if ( ! filter_var( $receipt['email'], FILTER_VALIDATE_EMAIL ) ) {
466
- unset( $this->receipts[ $key ] );
467
- }
468
- }
469
- }
470
- ),
471
- ),
472
- );
473
- }
474
-
475
- /**
476
- * Define labels for settings key, we will use it for HUB
477
- *
478
- * @param null $key
479
- *
480
- * @return array|mixed
481
- */
482
- public function labels( $key = null ) {
483
- $labels = [
484
- 'notification' => __( 'Email reminders', "defender-security" ),
485
- 'notification_repeat' => __( "Remind every 24 hours", "defender-security" ),
486
- 'receipts' => __( 'Email reminder recipients', "defender-security" ),
487
- ];
488
-
489
- if ( $key != null ) {
490
- return isset( $labels[ $key ] ) ? $labels[ $key ] : null;
491
- }
492
-
493
- return $labels;
494
- }
495
-
496
- /**
497
- * Get export strings, use in config import.export
498
- *
499
- * @param $configs
500
- *
501
- * @return array
502
- */
503
- public function export_strings( $configs ) {
504
- $this->refreshStatus();
505
- $strings = [];
506
- $model = new Settings( 'wd_hardener_settings',
507
- WP_Helper::is_network_activate( wp_defender()->plugin_slug ) );
508
- $model->import( $configs );
509
- if ( $model->automate ) {
510
- //if automate, mean enable as much as possible
511
- $count = count( $this->getDefinedRules() );
512
- $manual_done = [
513
- Change_Admin::$slug,
514
- PHP_Version::$slug,
515
- Prevent_Php::$slug,
516
- Protect_Information::$slug,
517
- WP_Version::$slug
518
- ];
519
- if ( is_array( $this->fixed ) && ! empty( $this->fixed ) ) {
520
- foreach ( $manual_done as $slug ) {
521
- if ( ! in_array( $slug, $this->fixed ) ) {
522
- $count -= 1;
523
- }
524
- }
525
- }
526
- $strings[] = sprintf( __( '%d/%d recommendations activated', "defender-security" ),
527
- $count, count( $model->getDefinedRules() ) );
528
- } elseif ( empty( $model->getIssues() ) ) {
529
- $strings[] = __( 'All available recommendations activated', "defender-security" );
530
- } else {
531
- $strings[] = sprintf( __( '%d/%d recommendations activated', "defender-security" ),
532
- count( $model->getFixed() ), count( $model->getDefinedRules() ) );
533
- }
534
-
535
- if ( $model->notification ) {
536
- $strings[] = __( 'Email notifications active', "defender-security" );
537
- }
538
-
539
- return $strings;
540
- }
541
-
542
- /**
543
- * This is for the case like Change_Admin
544
- * @return array
545
- */
546
- public function export_extra() {
547
- return [];
548
- }
549
-
550
- public function automate() {
551
- $need_reauth = false;
552
- //force a refresh
553
- $this->refreshStatus();
554
- if ( $this->automate === true ) {
555
- //if automate is true, auto resolve all
556
- $manual_done = [
557
- Change_Admin::$slug,
558
- PHP_Version::$slug,
559
- Prevent_Php::$slug,
560
- Protect_Information::$slug,
561
- WP_Version::$slug
562
- ];
563
- foreach ( $this->getIssues() as $issue ) {
564
- if ( in_array( $issue::$slug, $manual_done ) ) {
565
- continue;
566
- }
567
- if ( $issue::$slug === Security_Key::$slug ) {
568
- $need_reauth = true;
569
- }
570
- $ret = $issue->getService()->process();
571
- }
572
- $this->automate = false;
573
- $this->save();
574
- } else {
575
- //there are some tweak that need manual apply, as files based, or change admin
576
- foreach ( $this->getIssues() as $item ) {
577
- if ( in_array( $item::$slug,
578
- [
579
- Change_Admin::$slug,
580
- PHP_Version::$slug,
581
- Prevent_Php::$slug,
582
- Protect_Information::$slug,
583
- WP_Version::$slug
584
- ] ) ) {
585
- continue;
586
- }
587
-
588
- if ( in_array( $item::$slug, [
589
- Security_Key::$slug
590
- ] ) ) {
591
- $need_reauth = true;
592
- }
593
-
594
- $ret = $item->getService()->process();
595
- }
596
- }
597
-
598
- return $need_reauth;
599
- }
600
-
601
- public function format_hub_data() {
602
- return [
603
- 'notification' => $this->notification ? __( 'Active', "defender-security" ) : __( 'Inactivate',
604
- "defender-security" ),
605
- 'notification_repeat' => $this->notification_repeat ? __( 'Yes', "defender-security" ) : __( 'No',
606
- "defender-security" ),
607
- 'receipts' => empty( $this->receipts ) ? __( 'No recipients',
608
- "defender-security" ) : Utils::instance()->recipientsToString( $this->receipts )
609
- ];
610
- }
611
-
612
- public function resolve( $rules ) {
613
- if ( $rules == true ) {
614
- $rules = $this->getDefinedRules( true );
615
- }
616
- foreach ( $rules as $key => $rule ) {
617
- $rule->process();
618
- }
619
- }
620
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/rule-service.php DELETED
@@ -1,142 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener;
7
-
8
- use Hammer\Base\Component;
9
- use Hammer\Base\Container;
10
- use WP_Defender\Behavior\Utils;
11
- use WP_Defender\Module\Hardener;
12
-
13
- class Rule_Service extends Component {
14
- /**
15
- * Attach Utils to all component rules
16
- *
17
- * @return array
18
- */
19
- public function behaviors() {
20
- return array(
21
- 'utils' => '\WP_Defender\Behavior\Utils'
22
- );
23
- }
24
-
25
- /**
26
- * @param $curr_status
27
- * @param $slug
28
- */
29
- protected function store( $curr_status, $slug ) {
30
- $settings = Hardener\Model\Settings::instance();
31
- switch ( $curr_status ) {
32
- case 'fixed':
33
- $settings->addToResolved( $slug );
34
- break;
35
- case 'ignore':
36
- $settings->addToIgnore( $slug );
37
- break;
38
- case 'issue':
39
- $settings->addToIssues( $slug );
40
- break;
41
- default:
42
- //param not from the button on frontend, log it
43
- error_log( sprintf( 'Unexpected value %s from IP %s', $curr_status, Utils::instance()->getUserIp() ) );
44
- break;
45
- }
46
- }
47
-
48
- /**
49
- * @param $slug
50
- */
51
- public function ignore( $slug ) {
52
- self::store( 'ignore', $slug );
53
- }
54
-
55
- /**
56
- * A helper function for child class
57
- * @return string
58
- */
59
- public function retrieveWPConfigPath() {
60
- if ( file_exists( ABSPATH . 'wp-config.php' ) ) {
61
- return ( ABSPATH . 'wp-config.php' );
62
- } elseif ( @file_exists( dirname( ABSPATH ) . '/wp-config.php' ) && ! @file_exists( dirname( ABSPATH ) . '/wp-settings.php' ) ) {
63
- return ( dirname( ABSPATH ) . '/wp-config.php' );
64
- } elseif ( defined( 'WD_TEST' ) && constant( 'WD_TEST' ) == true ) {
65
- //case tests
66
- return '/tmp/wordpress-tests-lib/wp-tests-config.php';
67
- }
68
- }
69
-
70
- /**
71
- * @param $config
72
- *
73
- * @return bool|int|string
74
- */
75
- protected function findDefaultHookLine( $config ) {
76
- global $wpdb;
77
- $pattern = '/^\$table_prefix\s*=\s*[\'|\"]' . $wpdb->prefix . '[\'|\"]/';
78
- foreach ( $config as $k => $line ) {
79
- if ( preg_match( $pattern, $line ) ) {
80
- return $k;
81
- }
82
- }
83
-
84
- return false;
85
- }
86
-
87
- /**
88
- * @param $url
89
- * @param $origin
90
- *
91
- * @return array|mixed|\WP_Error
92
- */
93
- protected function headRequest( $url, $origin, $ttl = null ) {
94
- $settings = Hardener\Model\Settings::instance();
95
- $cached = $settings->getDValues( 'head_requests' );
96
- if ( ! is_array( $cached ) ) {
97
- $cached = [];
98
- }
99
- if ( isset( $cached[ $url ] ) ) {
100
- $cache = $cached[ $url ];
101
- if ( $cache['ttl'] > time() ) {
102
- //we'll use the cache
103
- //Utils::instance()->log( sprintf( 'Header for %s return from cached', $url ) );
104
-
105
- return $cache['data'];
106
- }
107
- }
108
-
109
- //no cache or cache expired
110
- $request = wp_remote_head( $url, [
111
- 'user-agent' => 'WP Defender self ping - ' . $origin
112
- ] );
113
- if ( ! is_wp_error( $request ) ) {
114
- $headers = wp_remote_retrieve_headers( $request );
115
- $headers = $headers->getAll();
116
- if ( $ttl === null ) {
117
- $ttl = strtotime( '+1 day' );
118
- }
119
- $headers['response_code'] = wp_remote_retrieve_response_code( $request );
120
- $cached[ $url ] = [
121
- 'ttl' => apply_filters( 'wd_tweaks_head_request_ttl', $ttl ),
122
- 'data' => $headers
123
- ];
124
- $settings->setDValues( 'head_requests', $cached );
125
- Utils::instance()->log( sprintf( 'Fetched header for %s into cache', $url ), 'tweaks' );
126
-
127
- return $headers;
128
- }
129
-
130
- return $request;
131
- }
132
-
133
- /**
134
- * @param $url
135
- */
136
- public function clearHeadRequest( $url ) {
137
- $settings = Hardener\Model\Settings::instance();
138
- $cached = $settings->getDValues( 'head_requests' );
139
- unset( $cached[ $url ] );
140
- $settings->setDValues( 'head_requests', $cached );
141
- }
142
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/rule.php DELETED
@@ -1,177 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Hardener;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use Hammer\WP\Component;
10
- use WP_Defender\Module\Hardener\Model\Settings;
11
-
12
- /**
13
- * Class Rule
14
- * @package WP_Defender\Module\Hardener
15
- */
16
- abstract class Rule extends Component {
17
-
18
- /**
19
- *
20
- * @var string
21
- */
22
- static $slug;
23
-
24
- /**
25
- * Return this rule content, we will try to use renderPartial
26
- *
27
- * @return mixed
28
- * @deprecated since 2.2
29
- */
30
- abstract function getDescription();
31
-
32
- /**
33
- * This will return the short summary why this rule show up as issue
34
- *
35
- * @return string
36
- */
37
- abstract function getErrorReason();
38
-
39
- /**
40
- * This will return a short summary to show why this rule works
41
- * @return mixed
42
- */
43
- abstract function getSuccessReason();
44
-
45
- /**
46
- * @return array
47
- */
48
- public function getMiscData() {
49
- return array();
50
- }
51
-
52
- /**
53
- * @return mixed
54
- */
55
- abstract function check();
56
-
57
- /**
58
- * implement the revert function
59
- *
60
- * @return mixed
61
- */
62
- abstract function revert();
63
-
64
- /**
65
- * implement the process function
66
- * @return mixed
67
- */
68
- abstract function process();
69
-
70
- /**
71
- * @return mixed
72
- */
73
- abstract function getTitle();
74
-
75
- /**
76
- * @return mixed
77
- */
78
- public function ignore() {
79
- $setting = Settings::instance();
80
- $setting->addToIgnore( static::$slug );
81
- }
82
-
83
- /**
84
- *
85
- */
86
- public function restore() {
87
- $setting = Settings::instance();
88
- $setting->addToIssues( static::$slug );
89
- }
90
-
91
- /**
92
- * Return Service class
93
- * @return mixed
94
- */
95
- abstract function getService();
96
-
97
- /**
98
- * generate a nonce field
99
- */
100
- public function createNonceField() {
101
- wp_nonce_field( self::$slug, '_wdnonce' );
102
- }
103
-
104
- /**
105
- * @return mixed
106
- */
107
- abstract function addHooks();
108
-
109
- /**
110
- * @return false|int
111
- */
112
- public function verifyNonce() {
113
- if ( $_SERVER['REQUEST_METHOD'] != 'POST' ) {
114
- return false;
115
- }
116
-
117
- $nonce = HTTP_Helper::retrievePost( '_wdnonce' );
118
-
119
- return wp_verify_nonce( $nonce, self::$slug );
120
- }
121
-
122
- /**
123
- * @return bool
124
- */
125
- public function isIgnored() {
126
- $ignored = Settings::instance()->ignore;
127
-
128
- return in_array( static::$slug, $ignored );
129
- }
130
-
131
- /**
132
- * @return string
133
- */
134
- public function getCssClass() {
135
- if ( $this->isIgnored() ) {
136
- return '';
137
- }
138
-
139
- if ( $this->check() ) {
140
- return 'sui-success';
141
- }
142
-
143
- return 'sui-warning';
144
- }
145
-
146
- /**
147
- * @return array
148
- */
149
- public function behaviors() {
150
- return array(
151
- 'utils' => '\WP_Defender\Behavior\Utils'
152
- );
153
- }
154
-
155
- /**
156
- * A helper for tweak with security header, we need to check if the header is out or not
157
- *
158
- * @param $header
159
- * @param $somewhere
160
- *
161
- * @return bool
162
- */
163
- protected function maybeSubmitHeader( $header, $somewhere ) {
164
- if ( $somewhere == false ) {
165
- return true;
166
- }
167
- $list = headers_list();
168
- $match = false;
169
- foreach ( $list as $item ) {
170
- if ( stristr( $item, $header ) ) {
171
- $match = true;
172
- }
173
- }
174
-
175
- return $match;
176
- }
177
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/view/email/notification.php DELETED
@@ -1,366 +0,0 @@
1
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
- <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" style="background:#f3f3f3!important">
4
- <head>
5
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
6
- <meta name="viewport" content="width=device-width"><!-- Import Open Sans Webfont -->
7
- <link href="https://fonts.googleapis.com/css?family=Open+Sans:400,400i,600,600i,700,700i" rel="stylesheet">
8
- <title></title>
9
- <style>@media only screen {
10
- html {
11
- min-height: 100%;
12
- background: #f3f3f3
13
- }
14
- }
15
-
16
- @media only screen and (max-width: 615px) {
17
- .small-float-center {
18
- margin: 0 auto !important;
19
- float: none !important;
20
- text-align: center !important
21
- }
22
- }
23
-
24
- @media only screen and (max-width: 615px) {
25
- table.body img {
26
- width: auto;
27
- height: auto
28
- }
29
-
30
- table.body center {
31
- min-width: 0 !important
32
- }
33
-
34
- table.body .container {
35
- width: 95% !important
36
- }
37
-
38
- table.body .columns {
39
- height: auto !important;
40
- -moz-box-sizing: border-box;
41
- -webkit-box-sizing: border-box;
42
- box-sizing: border-box;
43
- padding-left: 15px !important;
44
- padding-right: 15px !important
45
- }
46
-
47
- th.small-12 {
48
- display: inline-block !important;
49
- width: 100% !important
50
- }
51
-
52
- table.menu {
53
- width: 100% !important
54
- }
55
-
56
- table.menu td, table.menu th {
57
- width: auto !important;
58
- display: inline-block !important
59
- }
60
-
61
- table.menu.vertical td, table.menu.vertical th {
62
- display: block !important
63
- }
64
-
65
- table.menu[align=center] {
66
- width: auto !important
67
- }
68
- }</style>
69
- <style type="text/css">@media only screen and (min-width: 615px) {
70
- h1 {
71
- padding-top: 40px !important
72
- }
73
-
74
- table.body .column.first, table.body .columns.first {
75
- padding-left: 60px !important
76
- }
77
-
78
- table.body .column.last, table.body .columns.last {
79
- padding-right: 60px !important
80
- }
81
-
82
- .article-block .article-block__heading {
83
- font-size: 15px !important;
84
- line-height: 20px !important;
85
- Margin: 20px 0 20px -15px !important;
86
- font-weight: 400 !important
87
- }
88
-
89
- .article-block .article-block__img {
90
- height: 90px !important;
91
- width: 130px !important
92
- }
93
- }
94
-
95
- @media only screen and (min-width: 450px) {
96
- span.whip-issue-tag {
97
- position: relative !important;
98
- left: 0 !important;
99
- transform: translateX(0) !important;
100
- display: inline-block !important
101
- }
102
- }
103
-
104
- @media only screen and (max-width: 450px) {
105
- h1.whip-orange:first-of-type {
106
- padding-top: 55px !important
107
- }
108
- }
109
-
110
- @media only screen {
111
- table.button:hover table td {
112
- background: #0092CA !important
113
- }
114
-
115
- table.button.secondary:hover table td {
116
- background: #6F6F6F !important
117
- }
118
-
119
- table.button.success:hover table td {
120
- background: #01A383 !important
121
- }
122
-
123
- table.button.warning:hover table td {
124
- background: #E1B40C !important
125
- }
126
-
127
- table.button.alert:hover table td {
128
- background: #D33F27 !important
129
- }
130
- }</style>
131
- </head>
132
- <body style="-moz-box-sizing:border-box;-ms-text-size-adjust:100%;-webkit-box-sizing:border-box;-webkit-text-size-adjust:100%;Margin:0;background:#f3f3f3!important;box-sizing:border-box;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0;min-width:100%;padding:0;text-align:left;width:100%!important">
133
- <table class="body"
134
- style="Margin:0;background:#f3f3f3!important;border-collapse:collapse;border-spacing:0;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;height:100%;line-height:25px;margin:0;padding:0;text-align:left;vertical-align:top;width:100%">
135
- <tr style="padding:0;text-align:left;vertical-align:top">
136
- <td class="center" align="center" valign="top"
137
- style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;hyphens:auto;line-height:25px;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
138
- <center data-parsed style="min-width:600px;width:100%">
139
- <table align="center" class="container view-in-browser float-center"
140
- style="Margin:0 auto;background:0 0;border-collapse:collapse;border-spacing:0;float:none;height:50px;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:600px">
141
- <tbody>
142
- <tr style="padding:0;text-align:left;vertical-align:top">
143
- <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;hyphens:auto;line-height:25px;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
144
- <div class="text-right" style="text-align:right"><a href="https://premium.wpmudev.org"
145
- style="Margin:0;color:#888;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:12px;font-weight:400;line-height:50px;margin:0;margin-right:10px;padding:0;text-align:right;text-decoration:none">View
146
- in browser</a></div>
147
- </td>
148
- </tr>
149
- </tbody>
150
- </table>
151
- <table align="center" class="container main-content float-center"
152
- style="Margin:0 auto;background:#fff;border-collapse:collapse;border-radius:4px;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:600px">
153
- <tbody>
154
- <tr style="padding:0;text-align:left;vertical-align:top">
155
- <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;hyphens:auto;line-height:25px;margin:0;padding:0;padding-bottom:55px!important;text-align:left;vertical-align:top;word-wrap:break-word">
156
- <div class="hero-image" style="height:150px"><img
157
- src="<?php echo wp_defender()->getPluginUrl() ?>assets/email-assets/img/Defender-widerec@2x.png"
158
- alt="Hero Image"
159
- style="-ms-interpolation-mode:bicubic;border-radius:4px 4px 0 0;clear:both;display:block;height:100%;max-width:100%;object-fit:cover;outline:0;text-decoration:none;width:auto">
160
- </div>
161
- <table class="row"
162
- style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%">
163
- <tbody>
164
- <tr style="padding:0;text-align:left;vertical-align:top">
165
- <th class="small-12 large-12 columns first last"
166
- style="Margin:0 auto;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0 auto;padding:0;padding-bottom:15px;padding-left:15px;padding-right:15px;text-align:left;width:585px">
167
- <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
168
- <tr style="padding:0;text-align:left;vertical-align:top">
169
- <th style="Margin:0;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0;padding:0;text-align:left">
170
- <h1 style="-webkit-font-smoothing:antialiased;Margin:0;Margin-bottom:10px;color:inherit;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:22px;font-smoothing:antialiased;font-weight:600;line-height:25px;margin:0;margin-bottom:30px;padding:0;padding-top:30px;text-align:left;word-wrap:normal">
171
- <?php printf( __( "Security tweak report for %s", "defender-security" ), $siteUrl ) ?>
172
- </h1>
173
- <p style="-webkit-font-smoothing:antialiased;Margin:0;Margin-bottom:10px;color:#333;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-smoothing:antialiased;font-weight:400;line-height:25px;margin:0;margin-bottom:30px;padding:0;text-align:left">
174
- <?php printf( __( "Hi %s,", "defender-security" ), $userName ) ?>
175
- </p>
176
- <p style="-webkit-font-smoothing:antialiased;Margin:0;Margin-bottom:10px;color:#333;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-smoothing:antialiased;font-weight:400;line-height:25px;margin:0;margin-bottom:30px;padding:0;text-align:left">
177
- <?php printf( __( "You have %d unresolved security tweaks on %s. We recommend you action what you can to prevent any issues, and ignore anything you don't want to fix up.", "defender-security" ), $count, $siteUrl ) ?>
178
- </p>
179
- </th>
180
- <th class="expander"
181
- style="Margin:0;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th>
182
- </tr>
183
- </table>
184
- </th>
185
- </tr>
186
- </tbody>
187
- </table>
188
- <table class="row"
189
- style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%">
190
- <tbody>
191
- <tr style="padding:0;text-align:left;vertical-align:top">
192
- <th class="small-12 large-12 columns first last"
193
- style="Margin:0 auto;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0 auto;padding:0;padding-bottom:15px;padding-left:15px;padding-right:15px;text-align:left;width:585px">
194
- <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
195
- <tr style="padding:0;text-align:left;vertical-align:top">
196
- <th style="Margin:0;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0;padding:0;text-align:left">
197
- <table class="wpmudev-table"
198
- style="border-collapse:separate;border-radius:4px;border-spacing:0;margin-bottom:10px;padding:0;text-align:left;vertical-align:top;width:100%">
199
- <tbody>
200
- <?php echo $issues ?>
201
- </tbody>
202
- </table>
203
- </th>
204
- <th class="expander"
205
- style="Margin:0;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th>
206
- </tr>
207
- </table>
208
- </th>
209
- </tr>
210
- </tbody>
211
- </table>
212
- <table class="row"
213
- style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%">
214
- <tbody>
215
- <tr style="padding:0;text-align:left;vertical-align:top">
216
- <th class="small-12 large-12 columns first last"
217
- style="Margin:0 auto;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0 auto;padding:0;padding-bottom:15px;padding-left:15px;padding-right:15px;text-align:left;width:585px">
218
- <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
219
- <tr style="padding:0;text-align:left;vertical-align:top">
220
- <th style="Margin:0;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0;padding:0;text-align:left">
221
- <table class="button btn-center"
222
- style="Margin:0 auto 30px!important;border-collapse:collapse;border-spacing:0;margin:0 0 30px 0;padding:0;text-align:left;vertical-align:top;width:auto">
223
- <tr style="padding:0;text-align:left;vertical-align:top">
224
- <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;hyphens:auto;line-height:25px;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
225
- <table style="border-collapse:collapse;border-radius:4px;border-spacing:0;overflow:hidden;padding:0;text-align:left;vertical-align:top;width:100%">
226
- <tr style="padding:0;text-align:left;vertical-align:top">
227
- <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;background:#17ABE3;border:none;border-collapse:collapse!important;color:#fff;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;hyphens:auto;line-height:25px;margin:0;padding:0;text-align:center;vertical-align:top;word-wrap:break-word">
228
- <a href="<?php echo $viewUrl ?>"
229
- style="Margin:0;border:0 solid #17ABE3;border-radius:4px;color:#fff;display:inline-block;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:15px;font-weight:400;line-height:25px;margin:0;min-width:275px;padding:8px 16px 8px 16px;text-align:center;text-decoration:none;text-transform:uppercase">
230
- <?php _e( "View All", "defender-security" ) ?>
231
- </a></td>
232
- </tr>
233
- </table>
234
- </td>
235
- </tr>
236
- </table>
237
- </th>
238
- <th class="expander"
239
- style="Margin:0;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th>
240
- </tr>
241
- </table>
242
- </th>
243
- </tr>
244
- </tbody>
245
- </table>
246
- <table class="row cheers"
247
- style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%">
248
- <tbody>
249
- <tr style="padding:0;text-align:left;vertical-align:top">
250
- <th class="small-12 large-12 columns first last"
251
- style="Margin:0 auto;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0 auto;padding:0;padding-bottom:15px;padding-left:15px;padding-right:15px;text-align:left;width:585px">
252
- <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
253
- <tr style="padding:0;text-align:left;vertical-align:top">
254
- <th style="Margin:0;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0;padding:0;text-align:left">
255
- <p style="-webkit-font-smoothing:antialiased;Margin:0;Margin-bottom:10px;color:#333;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:15px;font-smoothing:antialiased;font-weight:400;line-height:25px;margin:0;margin-bottom:30px;padding:0;text-align:left">
256
- <?php _e( "Stay safe,", "defender-security" ) ?>
257
- </p>
258
- <p style="-webkit-font-smoothing:antialiased;Margin:0;color:#333;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:15px;font-smoothing:antialiased;font-weight:400;line-height:25px;margin:0;padding:0;text-align:left">
259
- <?php _e( "Defender,", "defender-security" ) ?>
260
- </p>
261
- <p style="-webkit-font-smoothing:antialiased;Margin:0;color:#333;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:15px;font-smoothing:antialiased;font-weight:400;line-height:25px;margin:0;margin-bottom:30px;padding:0;text-align:left">
262
- <?php _e( "WPMU DEV Security Hero", "defender-security" ) ?></p>
263
- <th class="expander"
264
- style="Margin:0;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th>
265
- </tr>
266
- </table>
267
- </th>
268
- </tr>
269
- </tbody>
270
- </table>
271
- </td>
272
- </tr>
273
- </tbody>
274
- </table>
275
- <table align="center" class="container footer float-center"
276
- style="Margin:0 auto;background:0 0;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:600px">
277
- <tbody>
278
- <tr style="padding:0;text-align:left;vertical-align:top">
279
- <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;hyphens:auto;line-height:25px;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
280
- <table class="row"
281
- style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%">
282
- <tbody>
283
- <tr style="padding:0;text-align:left;vertical-align:top">
284
- <th class="small-12 large-12 columns first last"
285
- style="Margin:0 auto;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0 auto;padding:0;padding-bottom:15px;padding-left:15px;padding-right:15px;text-align:left;width:585px">
286
- <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
287
- <tr style="padding:0;text-align:left;vertical-align:top">
288
- <th style="Margin:0;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0;padding:0;text-align:left">
289
- <center data-parsed style="min-width:555px;width:100%"><img
290
- class="footer__logo float-center"
291
- src="<?php echo wp_defender()->getPluginUrl() ?>assets/email-assets/img/Blue-Copy@2x.png"
292
- alt="WPMUDEV Logo"
293
- align="center"
294
- style="-ms-interpolation-mode:bicubic;Margin:0 auto;clear:both;display:block;float:none;height:23px;margin:0 auto;max-width:100%;outline:0;padding-bottom:26px;padding-top:40px;text-align:center;text-decoration:none;width:auto">
295
- </center>
296
- <center data-parsed style="min-width:555px;width:100%"><span
297
- class="text-center footer__italic float-center"
298
- align="center"
299
- style="color:#666;display:block;font-size:14px;font-style:italic;line-height:20px;text-align:center;width:100%">Everything You Need For WordPress.</span>
300
- <span class="text-center footer__italic float-center"
301
- align="center"
302
- style="color:#666;display:block;font-size:14px;font-style:italic;line-height:20px;text-align:center;width:100%">One place, one low price, unlimited sites.</span>
303
- </center>
304
- <center data-parsed style="min-width:555px;width:100%"><span
305
- class="text-center footer__address float-center"
306
- align="center"
307
- style="color:#AAA;display:block;font-size:10px;line-height:30px;padding-top:30px;text-align:center;width:100%">INCSUB PO BOX 163, ALBERT PARK, VICTORIA.3206 AUSTRALIA</span>
308
- </center>
309
- <center data-parsed style="min-width:555px;width:100%">
310
- <table align="center"
311
- class="menu text-center footer__menu float-center"
312
- style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;padding-bottom:100px;text-align:center;vertical-align:top;width:auto!important">
313
- <tr style="padding:0;text-align:left;vertical-align:top">
314
- <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;hyphens:auto;line-height:25px;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
315
- <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
316
- <tr style="padding:0;text-align:left;vertical-align:top">
317
- <th class="menu-item float-center"
318
- style="Margin:0 auto;color:#000;float:none;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0 auto;padding:0;padding-right:10px;text-align:center">
319
- <a href="<?php echo network_admin_url('admin.php?page=wdf-hardener&view=notification') ?>"
320
- style="Margin:0;color:#888;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:14px;font-weight:400;line-height:30px;margin:0;padding:0;text-align:center;text-decoration:underline">Manage
321
- your email preferences</a></th>
322
- <th class="menu-item float-center"
323
- style="Margin:0 auto;color:#000;float:none;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0 auto;padding:0;padding-right:10px;text-align:center">
324
- <a href="<?php echo network_admin_url('admin.php?page=wdf-hardener&action=unsubscribe_notification') ?>"
325
- style="Margin:0;color:#888;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:14px;font-weight:400;line-height:30px;margin:0;padding:0;text-align:center;text-decoration:underline">Unsubscribe</a>
326
- </th>
327
- </tr>
328
- </table>
329
- </td>
330
- </tr>
331
- </table>
332
- </center>
333
- <table class="spacer"
334
- style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
335
- <tbody>
336
- <tr style="padding:0;text-align:left;vertical-align:top">
337
- <td height="96px"
338
- style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:96px;font-weight:400;hyphens:auto;line-height:96px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
339
- &#xA0;
340
- </td>
341
- </tr>
342
- </tbody>
343
- </table>
344
- </th>
345
- <th class="expander"
346
- style="Margin:0;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th>
347
- </tr>
348
- </table>
349
- </th>
350
- </tr>
351
- </tbody>
352
- </table>
353
- </td>
354
- </tr>
355
- </tbody>
356
- </table>
357
- </center>
358
- </td>
359
- </tr>
360
- </table><!-- prevent Gmail on iOS font size manipulation -->
361
- <div style="display:none;white-space:nowrap;font:15px courier;line-height:0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
362
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
363
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
364
- </div>
365
- </body>
366
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/view/layouts/layout.php DELETED
@@ -1,176 +0,0 @@
1
- <?php
2
- $countAll = $controller->getCount( 'issues' );
3
- $resolved = $controller->getCount( 'fixed' );
4
- $ignore = $controller->getCount( 'ignore' );
5
- $tooltips = __( "You don't have any outstanding security issues, nice work!", "defender-security" );
6
- $class = '';
7
- if ( $countAll == 1 ) {
8
- $tooltips = __( "You have one security tweak left to do. We recommend you action it, or ignore it if it's irrelevant.", "defender-security" );
9
- } elseif ( $countAll > 1 ) {
10
- $tooltips = sprintf( __( "You have %s security tweaks left to do. We recommend you take a look and action fixes, or ignore the issues if they are harmless.", "defender-security" ), $countAll );
11
- }
12
- $inlineHeroImage = strlen( wp_defender()->heroImage ) > 0 ? 'background-image: url(\'' . wp_defender()->heroImage . '\')' : null;
13
- ?>
14
- <div class="sui-wrap <?php echo \WP_Defender\Behavior\Utils::instance()->maybeHighContrast() ?>">
15
- <div id="wp-defender" class="wp-defender">
16
- <div class="hardener">
17
- <div class="sui-header">
18
- <h1 class="sui-header-title">
19
- <?php _e( "Security Tweaks", "defender-security" ) ?>
20
- </h1>
21
- <?php if ( wp_defender()->hideDocLinks === false ): ?>
22
- <div class="sui-actions-right">
23
- <div class="sui-actions-right">
24
- <a href="https://premium.wpmudev.org/docs/wpmu-dev-plugins/defender/#security-tweaks" target="_blank"
25
- class="sui-button sui-button-ghost">
26
- <i class="sui-icon-academy"></i> <?php _e( "View Documentation", "defender-security" ) ?>
27
- </a>
28
- </div>
29
- </div>
30
- <?php endif; ?>
31
- </div>
32
- <div class="sui-box sui-summary sui-summary-sm <?php echo \WP_Defender\Behavior\Utils::instance()->getSummaryClass() ?>">
33
- <div class="sui-summary-image-space"
34
- aria-hidden="true"
35
- style="<?php echo $inlineHeroImage ?>"></div>
36
-
37
- <div class="sui-summary-segment">
38
-
39
- <div class="sui-summary-details issues">
40
-
41
- <span class="sui-summary-large count-issues"><?php echo $countAll ?></span>
42
- <?php if ( $countAll > 0 ): ?>
43
- <span class="sui-tooltip sui-tooltip-top-left sui-tooltip-constrained"
44
- data-tooltip="<?php echo $tooltips ?>">
45
- <i aria-hidden="true" class="sui-icon-info sui-warning"></i>
46
- </span>
47
- <?php else: ?>
48
- <span class="sui-tooltip sui-tooltip-top-left sui-tooltip-constrained"
49
- data-tooltip="<?php echo $tooltips ?>">
50
- <i class="sui-icon-check-tick sui-success" aria-hidden="true"></i>
51
- </span>
52
- <?php endif; ?>
53
- <span class="sui-summary-sub"><?php _e( "Security issues", "defender-security" ) ?></span>
54
- </div>
55
-
56
- </div>
57
-
58
- <div class="sui-summary-segment">
59
- <ul class="sui-list">
60
-
61
- <li>
62
- <span class="sui-list-label"><?php _e( "Current PHP version", "defender-security" ) ?></span>
63
- <span class="sui-list-detail issues_wp">
64
- <?php echo phpversion() ?>
65
- </span>
66
- </li>
67
-
68
- <li>
69
- <span class="sui-list-label"><?php _e( "Current WordPress version", "defender-security" ) ?></span>
70
- <span class="sui-list-detail vuln_issues">
71
- <?php
72
- global $wp_version;
73
- echo $wp_version
74
- ?>
75
- </span>
76
- </li>
77
-
78
- </ul>
79
- </div>
80
-
81
- </div>
82
- <div class="sui-row-with-sidenav">
83
- <div class="sui-sidenav">
84
- <ul class="sui-vertical-tabs sui-sidenav-hide-md">
85
- <li class="sui-vertical-tab <?php echo \Hammer\Helper\HTTP_Helper::retrieve_get( 'view', false ) == false ? 'current' : null ?>">
86
- <a href="<?php echo network_admin_url( 'admin.php?page=wdf-hardener' ) ?>">
87
- <?php _e( "Issues", "defender-security" ) ?></a>
88
- <span class="sui-tag sui-tag-warning <?php echo $countAll ? '' : 'wd-hide' ?> count-issues"><?php echo $countAll ?></span>
89
- </li>
90
- <li class="sui-vertical-tab <?php echo $controller->isView( 'resolved' ) ? 'current' : null ?>">
91
- <a href="<?php echo network_admin_url( 'admin.php?page=wdf-hardener&view=resolved' ) ?>">
92
- <?php _e( "Resolved", "defender-security" ) ?></a>
93
- <span class="sui-tag count-resolved <?php echo $resolved ? '' : 'wd-hide' ?>"><?php echo $resolved ?></span>
94
- </li>
95
- <li class="sui-vertical-tab <?php echo $controller->isView( 'ignored' ) ? 'current' : null ?>">
96
- <a href="<?php echo network_admin_url( 'admin.php?page=wdf-hardener&view=ignored' ) ?>">
97
- <?php _e( "Ignored", "defender-security" ) ?></a>
98
- <span class="sui-tag count-ignored <?php echo $ignore ? '' : 'wd-hide' ?>"><?php echo $ignore ?></span>
99
- </li>
100
- <li class="sui-vertical-tab <?php echo $controller->isView( 'notification' ) ? 'current' : null ?>">
101
- <a href="<?php echo network_admin_url( 'admin.php?page=wdf-hardener&view=notification' ) ?>">
102
- <?php _e( "Notification", "defender-security" ) ?>
103
- </a>
104
- </li>
105
- </ul>
106
- <div class="sui-sidenav-hide-lg">
107
- <select class="sui-mobile-nav" style="display: none;">
108
- <option <?php selected( '', \Hammer\Helper\HTTP_Helper::retrieve_get( 'view' ) ) ?>
109
- value="<?php echo network_admin_url( 'admin.php?page=wdf-hardener' ) ?>"><?php _e( "Issues", "defender-security" ) ?></option>
110
- <option <?php selected( 'resolved', \Hammer\Helper\HTTP_Helper::retrieve_get( 'view' ) ) ?>
111
- value="<?php echo network_admin_url( 'admin.php?page=wdf-hardener&view=resolved' ) ?>"><?php _e( "Resolved", "defender-security" ) ?></option>
112
- <option <?php selected( 'ignored', \Hammer\Helper\HTTP_Helper::retrieve_get( 'view' ) ) ?>
113
- value="<?php echo network_admin_url( 'admin.php?page=wdf-hardener&view=ignored' ) ?>"><?php _e( "Ignored", "defender-security" ) ?></option>
114
- <option <?php selected( 'notification', \Hammer\Helper\HTTP_Helper::retrieve_get( 'view' ) ) ?>
115
- value="<?php echo network_admin_url( 'admin.php?page=wdf-hardener&view=notification' ) ?>">
116
- <?php _e( "Notification", "defender-security" ) ?>
117
- </option>
118
- </select>
119
- </div>
120
- </div>
121
- <div class="sui-box">
122
- <?php echo $contents ?>
123
- </div>
124
- </div>
125
- </div>
126
- <?php if ( wp_defender()->changeFooter ): ?>
127
- <div class="sui-footer"><?php echo wp_defender()->footerText ?></div>
128
- <?php else: ?>
129
- <div class="sui-footer">Made with <i class="sui-icon-heart"></i> by WPMU DEV</div>
130
- <?php endif; ?>
131
- <?php if ( wp_defender()->hideDocLinks == false ): ?>
132
- <?php if ( wp_defender()->isFree ): ?>
133
- <ul class="sui-footer-nav">
134
- <li><a href="https://profiles.wordpress.org/wpmudev#content-plugins" target="_blank">Free
135
- Plugins</a>
136
- </li>
137
- <li><a href="https://premium.wpmudev.org/features/" target="_blank">Membership</a></li>
138
- <li><a href="https://premium.wpmudev.org/roadmap/" target="_blank">Roadmap</a></li>
139
- <li><a href="https://wordpress.org/support/plugin/plugin-name" target="_blank">Support</a></li>
140
- <li><a href="https://premium.wpmudev.org/docs/" target="_blank">Docs</a></li>
141
- <li><a href="https://premium.wpmudev.org/hub/" target="_blank">The Hub</a></li>
142
- <li><a href="https://premium.wpmudev.org/terms-of-service/" target="_blank">Terms of Service</a>
143
- </li>
144
- <li><a href="https://incsub.com/privacy-policy/" target="_blank">Privacy Policy</a></li>
145
- </ul>
146
- <?php else: ?>
147
- <ul class="sui-footer-nav">
148
- <li><a href="https://premium.wpmudev.org/hub/" target="_blank">The Hub</a></li>
149
- <li><a href="https://premium.wpmudev.org/projects/category/plugins/" target="_blank">Plugins</a>
150
- </li>
151
- <li><a href="https://premium.wpmudev.org/roadmap/" target="_blank">Roadmap</a></li>
152
- <li><a href="https://premium.wpmudev.org/hub/support/" target="_blank">Support</a></li>
153
- <li><a href="https://premium.wpmudev.org/docs/" target="_blank">Docs</a></li>
154
- <li><a href="https://premium.wpmudev.org/hub/community/" target="_blank">Community</a></li>
155
- <li><a href="https://premium.wpmudev.org/terms-of-service/" target="_blank">Terms of Service</a>
156
- </li>
157
- <li><a href="https://incsub.com/privacy-policy/" target="_blank">Privacy Policy</a></li>
158
- </ul>
159
- <?php endif; ?>
160
- <ul class="sui-footer-social">
161
- <li><a href="https://www.facebook.com/wpmudev" target="_blank">
162
- <i class="sui-icon-social-facebook" aria-hidden="true"></i>
163
- <span class="sui-screen-reader-text">Facebook</span>
164
- </a></li>
165
- <li><a href="https://twitter.com/wpmudev" target="_blank">
166
- <i class="sui-icon-social-twitter" aria-hidden="true"></i></a>
167
- <span class="sui-screen-reader-text">Twitter</span>
168
- </li>
169
- <li><a href="https://www.instagram.com/wpmu_dev/" target="_blank">
170
- <i class="sui-icon-instagram" aria-hidden="true"></i>
171
- <span class="sui-screen-reader-text">Instagram</span>
172
- </a></li>
173
- </ul>
174
- <?php endif; ?>
175
- </div>
176
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/view/main.php DELETED
@@ -1,2 +0,0 @@
1
- <?php do_action('tweaks_footer'); ?>
2
- <div id="defender"></div>
 
 
app/module/hardener/view/rules/db-prefix.php DELETED
@@ -1,101 +0,0 @@
1
- <?php
2
- $checked = $controller->check();
3
- global $wpdb;
4
- $prefix = 'wp_' . uniqid();
5
- ?>
6
- <div id="db_prefix" class="sui-accordion-item <?php echo $controller->getCssClass() ?>">
7
- <div class="sui-accordion-item-header">
8
- <div class="sui-accordion-item-title">
9
- <i aria-hidden="true" class="<?php echo $checked ? 'sui-icon-check-tick sui-success'
10
- : 'sui-icon-warning-alert sui-warning' ?>"></i>
11
- <?php _e( "Database Prefix", "defender-security" ) ?>
12
- </div>
13
- <div class="sui-accordion-col-4">
14
- <button class="sui-button-icon sui-accordion-open-indicator" aria-label="Open item">
15
- <i class="sui-icon-chevron-down" aria-hidden="true"></i>
16
- </button>
17
- </div>
18
- </div>
19
- <div class="sui-accordion-item-body">
20
- <div class="sui-box">
21
- <div class="sui-box-body">
22
- <strong>
23
- <?php _e( "Overview", "defender-security" ) ?>
24
- </strong>
25
- <p>
26
- <?php _e( "When you first install WordPress on a new database, the default settings start with wp_ as the prefix to anything that gets stored in the tables. This makes it easier for hackers to perform SQL injection attacks if they find a code vulnerability. ", "defender-security" ) ?>
27
- </p>
28
- <?php if ( $checked ): ?>
29
- <div class="sui-notice sui-notice-success">
30
- <p><?php printf( __( "You're database prefix is set to <strong>%s</strong> and is unique, %s would be proud.", "defender-security" ), $wpdb->prefix, \WP_Defender\Behavior\Utils::instance()->getDisplayName() ) ?></p>
31
- </div>
32
- <?php else: ?>
33
- <strong>
34
- <?php _e( "Status", "defender-security" ) ?>
35
- </strong>
36
- <div class="sui-notice sui-notice-warning">
37
- <p>
38
- <?php _e( "Your database prefix is the default wp_ prefix.", "defender-security" ) ?>
39
- </p>
40
- </div>
41
- <p>
42
- <?php _e( "You’re currently using the default prefix, it’s much safer to change this to something random.", "defender-security" ) ?>
43
- </p>
44
- <strong>
45
- <?php _e( "How to fix", "defender-security" ) ?>
46
- </strong>
47
- <p>
48
- <?php _e( "It’s good practice to come up with a unique prefix to protect yourself from this. We’ve automatically generated a random prefix for you which will make it near impossible for hackers to guess, but feel free to choose your own. Alternately, you can ignore this tweak if you really want to keep the wp_ prefix at your own risk.", "defender-security" ) ?>
49
- </p>
50
- <div class="sui-border-frame">
51
- <div class="sui-form-field ">
52
- <label class="sui-label"><?php _e( "New database prefix", "defender-security" ) ?></label>
53
- <input type="text" value="<?php echo $prefix ?>" name="dbprefix" id="dbprefix"
54
- class="sui-form-control"/>
55
- </div>
56
- </div>
57
- <?php endif; ?>
58
- </div>
59
- <div class="sui-box-footer">
60
- <?php if ( $checked ): ?>
61
- <!-- <form method="post" class="hardener-frm rule-process">-->
62
- <!-- --><?php //$controller->createNonceField(); ?>
63
- <!-- <input type="hidden" name="action" value="processRevert"/>-->
64
- <!-- <input type="hidden" name="slug" value="--><?php //echo $controller::$slug ?><!--"/>-->
65
- <!-- <button class="sui-button" type="submit">-->
66
- <!-- <i class="sui-icon-undo" aria-hidden="true"></i>-->
67
- <!-- --><?php //_e( "Revert", "defender-security" ) ?><!--</button>-->
68
- <!-- </form>-->
69
- <?php else: ?>
70
- <div class="sui-actions-left">
71
- <?php $controller->showIgnoreForm() ?>
72
- </div>
73
- <div class="sui-actions-right">
74
- <form method="post" class="hardener-frm rule-process hardener-frm-process-xml-rpc">
75
- <?php $controller->createNonceField(); ?>
76
- <input type="hidden" name="dbprefix" value="<?php echo $prefix ?>"/>
77
- <input type="hidden" name="action" value="processHardener"/>
78
- <input type="hidden" name="slug" value="<?php echo $controller::$slug ?>"/>
79
- <button class="sui-button sui-button-blue" type="submit">
80
- <?php _e( "Update Prefix", "defender-security" ) ?></button>
81
- </form>
82
- </div>
83
- <?php endif; ?>
84
- </div>
85
- <?php if ( ! $checked ): ?>
86
- <div class="sui-center-box">
87
- <p>
88
- <?php _e( "Ensure you backup your database before performing this tweak.", "defender-security" ) ?>
89
- </p>
90
- </div>
91
- <?php endif; ?>
92
- </div>
93
- </div>
94
- </div>
95
- <script type="text/javascript">
96
- jQuery(function ($) {
97
- $('#dbprefix').keyup(function () {
98
- $('input[name="dbprefix"]').val($(this).val())
99
- })
100
- })
101
- </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/view/tweaks/csp/debug-bar.php DELETED
@@ -1,21 +0,0 @@
1
- <div id="defender-csp-debug">
2
- <div>
3
- <p>
4
- <?php _e( "You are in Test Mode. Use your browser developer console check if the security header directives are working as expected before publishing the change lives, or revert if they are causing issues.", "defender-security" ) ?>
5
- </p>
6
- <form method="post" action="<?php echo admin_url( 'admin-ajax.php' ) ?>">
7
- <input type="hidden" name="action" value="defender-csp-debug-cancel"/>
8
- <?php wp_nonce_field( 'defender-csp-debug-cancel' ) ?>
9
- <button type="submit">
10
- <?php _e( "Cancel", "defender-security" ) ?>
11
- </button>
12
- </form>
13
- <form method="post" action="<?php echo admin_url( 'admin-ajax.php' ) ?>">
14
- <input type="hidden" name="action" value="defender-csp-debug-apply">
15
- <?php wp_nonce_field( 'defender-csp-debug-apply' ) ?>
16
- <button type="submit" class="is-button-blue">
17
- <?php _e( "Apply", "defender-security" ) ?>
18
- </button>
19
- </form>
20
- </div>
21
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/hardener/view/tweaks/csp/notification-bar.php DELETED
@@ -1,16 +0,0 @@
1
- <div class="sui-wrap">
2
- <form method="post" action="<?php echo admin_url( 'admin-ajax.php' ) ?>">
3
- <?php wp_create_nonce( 'defender-csp-debug-staging' ) ?>
4
- <input type="hidden" name="action" value="defender-csp-debug-staging"/>
5
- <div class="sui-notice-top sui-notice-info sui-cant-dismiss defender-csp-debug-staging">
6
- <div class="sui-notice-content">
7
- <p>
8
- <?php _e( "The values have been added. You can now enforce the header or keep adjusting other directives. If you add values be sure to test before enforcing the header.", "defender-security" ) ?>
9
- </p>
10
- </div>
11
- <span class="sui-cnotice-dismiss">
12
- <button type="submit" class="sui-button-icon"><i class="sui-icon-check"></i></button>
13
- </span>
14
- </div>
15
- </form>
16
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/ip-lockout.php DELETED
@@ -1,51 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module;
7
-
8
- use Hammer\Base\Module;
9
- use WP_Defender\Module\IP_Lockout\Controller\Main;
10
- use WP_Defender\Module\IP_Lockout\Controller\Rest;
11
-
12
- class IP_Lockout extends Module {
13
- public function __construct() {
14
- $this->register_post_type();
15
- new Main();
16
- new Rest();
17
- }
18
-
19
- public function register_post_type() {
20
- register_post_type( 'wd_iplockout_log', array(
21
- 'labels' => array(
22
- 'name' => __( "Lockout Logs", "defender-security" ),
23
- 'singular_name' => __( "Lockout Log", "defender-security" )
24
- ),
25
- 'public' => false,
26
- 'show_ui' => false,
27
- 'show_in_menu' => false,
28
- 'capability_type' => array( 'wd_iplockout_log', 'wd_iplockout_logs' ),
29
- 'map_meta_cap' => true,
30
- 'hierarchical' => false,
31
- 'rewrite' => false,
32
- 'query_var' => false,
33
- 'supports' => array( '' ),
34
- ) );
35
- register_post_type( 'wd_ip_lockout', array(
36
- 'labels' => array(
37
- 'name' => __( "IP Lockouts", "defender-security" ),
38
- 'singular_name' => __( "IP Lockout", "defender-security" )
39
- ),
40
- 'public' => false,
41
- 'show_ui' => false,
42
- 'show_in_menu' => false,
43
- 'capability_type' => array( 'wd_ip_lockout', 'wd_ip_lockouts' ),
44
- 'map_meta_cap' => true,
45
- 'hierarchical' => false,
46
- 'rewrite' => false,
47
- 'query_var' => false,
48
- 'supports' => array( '' ),
49
- ) );
50
- }
51
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/ip-lockout/behavior/widget.php DELETED
@@ -1,91 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\IP_Lockout\Behavior;
7
-
8
- use Hammer\Base\Behavior;
9
- use WP_Defender\Behavior\Utils;
10
- use WP_Defender\Module\IP_Lockout\Model\Settings;
11
-
12
- class Widget extends Behavior {
13
- public function renderLockoutWidget() {
14
- $isOff = ! Settings::instance()->detect_404 && ! Settings::instance()->login_protection;
15
- ?>
16
- <div class="sui-box" id="lockoutSummary">
17
- <?php if ( ! $isOff ): ?>
18
- <div class="wd-overlay">
19
- <i class="sui-icon-loader sui-loading" aria-hidden="true"></i>
20
- </div>
21
- <input type="hidden" id="summaryNonce" value="<?php echo wp_create_nonce( 'lockoutSummaryData' ) ?>"/>
22
- <?php endif; ?>
23
- <div class="sui-box-header">
24
- <h3 class="sui-box-title">
25
- <i class="sui-icon-lock" aria-hidden="true"></i>
26
- <?php _e( "IP Lockouts", "defender-security" ) ?>
27
- </h3>
28
- </div>
29
- <div class="sui-box-body <?php echo ! $isOff ? 'no-padding-bottom' : null ?>">
30
- <p><?php _e( "Protect to your login area and have Defender automatically lockout any suspicious behaviour.", "defender-security" ) ?></p>
31
- <?php if ( $isOff ): ?>
32
- <form method="post" id="settings-frm" class="ip-frm">
33
- <?php wp_nonce_field( 'saveLockoutSettings' ) ?>
34
- <input type="hidden" name="action" value="saveLockoutSettings"/>
35
- <input type="hidden" name="login_protection" value="1"/>
36
- <input type="hidden" name="detect_404" value="1"/>
37
- <button type="submit" class="sui-button sui-button-blue">
38
- <?php esc_html_e( "Activate", "defender-security" ) ?>
39
- </button>
40
- </form>
41
- <?php else: ?>
42
- <div class="sui-field-list sui-flushed no-border">
43
- <div class="sui-field-list-body">
44
- <div class="sui-field-list-item">
45
- <label class="sui-field-list-item-label">
46
- <strong><?php _e( "Last lockout", "defender-security" ) ?></strong>
47
- </label>
48
- <span class="lastLockout">.</span>
49
- </div>
50
- <div class="sui-field-list-item">
51
- <label class="sui-field-list-item-label">
52
- <strong><?php _e( "Login lockouts this week", "defender-security" ) ?></strong>
53
- </label>
54
- <span class="loginLockoutThisWeek">.</span>
55
- </div>
56
- <div class="sui-field-list-item">
57
- <label class="sui-field-list-item-label">
58
- <strong><?php _e( "404 lockouts this week", "defender-security" ) ?></strong>
59
- </label>
60
- <span class="lockout404ThisWeek">.</span>
61
- </div>
62
- </div>
63
- </div>
64
- <?php endif; ?>
65
- </div>
66
- <?php if ( ! $isOff ): ?>
67
- <div class="sui-box-footer">
68
- <div class="sui-actions-left">
69
- <a href="<?php echo network_admin_url( 'admin.php?page=wdf-ip-lockout&view=logs', "defender-security"
70
- ) ?>"
71
- class="sui-button sui-button-ghost">
72
- <i class="sui-icon-eye" aria-hidden="true"></i>
73
- <?php _e( "View logs", "defender-security" ) ?>
74
- </a>
75
- </div>
76
- <div class="sui-actions-right">
77
- <p class="sui-p-small">
78
- <?php if ( Settings::instance()->ip_lockout_notification && Settings::instance()->login_lockout_notification ) {
79
- echo _e( "Lockout notifications are enabled", "defender-security" );
80
- } else {
81
- echo _e( "Lockout notifications are disabled", "defender-security" );
82
- }
83
- ?>
84
- </p>
85
- </div>
86
- </div>
87
- <?php endif; ?>
88
- </div>
89
- <?php
90
- }
91
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/ip-lockout/component/ip-api.php DELETED
@@ -1,218 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\IP_Lockout\Component;
7
-
8
- use Hammer\GeoIP\GeoIp;
9
- use Hammer\WP\Component;
10
- use WP_Defender\Behavior\Utils;
11
- use WP_Defender\Module\IP_Lockout\Model\Settings;
12
-
13
- class IP_API extends Component {
14
- public static function compareCIDR( $ip, $block ) {
15
- list ( $subnet, $bits ) = explode( '/', $block );
16
- if ( self::isV4( $ip ) && self::isV4( $subnet ) ) {
17
- return self::_compareCIDRV4( $ip, $block );
18
- } elseif ( self::isV6( $ip ) && self::isV6( $subnet ) && self::isV6Support() ) {
19
- return self::_compareCIDRV6( $ip, $block );
20
- }
21
-
22
- return false;
23
- }
24
-
25
- /**
26
- * @param $ip
27
- * @param $block
28
- *
29
- * @src http://stackoverflow.com/a/594134
30
- * @return bool
31
- */
32
- private static function _compareCIDRV4( $ip, $block ) {
33
- list ( $subnet, $bits ) = explode( '/', $block );
34
- $ip = ip2long( $ip );
35
- $subnet = ip2long( $subnet );
36
- $mask = - 1 << ( 32 - $bits );
37
- $subnet &= $mask; # nb: in case the supplied subnet wasn't correctly aligned
38
-
39
- return ( $ip & $mask ) == $subnet;
40
- }
41
-
42
- /**
43
- * @param $ip
44
- * @param $block
45
- *
46
- * @return bool
47
- */
48
- private static function _compareCIDRV6( $ip, $block ) {
49
- $ip = self::expandIPv6( $ip );
50
- $ip = inet_pton( $ip );
51
- $bIP = self::ineToBits( $ip );
52
- list ( $subnet, $bits ) = explode( '/', $block );
53
- $subnet = self::expandIPv6( $subnet );
54
- $subnet = inet_pton( $subnet );
55
- $bSubnet = self::ineToBits( $subnet );
56
-
57
- $ipNetBits = substr( $bIP, 0, $bits );
58
- $subnetBits = substr( $bSubnet, 0, $bits );
59
-
60
- return $ipNetBits === $subnetBits;
61
- }
62
-
63
- /**
64
- * @param $inet
65
- *
66
- * @src https://stackoverflow.com/a/7951507
67
- * @return string
68
- */
69
- private static function ineToBits( $inet ) {
70
- $unpacked = unpack( 'a16', $inet );
71
- $unpacked = str_split( $unpacked[1] );
72
- $binaryip = '';
73
- foreach ( $unpacked as $char ) {
74
- $binaryip .= str_pad( decbin( ord( $char ) ), 8, '0', STR_PAD_LEFT );
75
- }
76
-
77
- return $binaryip;
78
- }
79
-
80
- /**
81
- * @param $ip
82
- * @param $firstInRange
83
- * @param $lastInRange
84
- *
85
- * @return bool
86
- */
87
- public static function compareInRange( $ip, $firstInRange, $lastInRange ) {
88
- if ( self::isV4( $firstInRange ) && self::isV4( $lastInRange ) ) {
89
- return self::_compareV4InRange( $ip, $firstInRange, $lastInRange );
90
- } elseif ( self::isV6( $firstInRange ) && self::isV6( $lastInRange ) && self::isV6Support() ) {
91
- self::_compareV6InRange( $ip, $firstInRange, $lastInRange );
92
- }
93
-
94
- return false;
95
- }
96
-
97
- /**
98
- * @param $ip
99
- * @param $fistInRange
100
- * @param $lastInRange
101
- *
102
- * @return bool
103
- */
104
- private static function _compareV4InRange( $ip, $fistInRange, $lastInRange ) {
105
- $low = sprintf( "%u", ip2long( $fistInRange ) );
106
- $high = sprintf( "%u", ip2long( $lastInRange ) );
107
-
108
- $cip = sprintf( "%u", ip2long( $ip ) );
109
- if ( $high >= $cip && $cip >= $low ) {
110
- return true;
111
- }
112
-
113
- return false;
114
- }
115
-
116
- /**
117
- * @param $ip
118
- * @param $firstInRange
119
- * @param $lastInRange
120
- *
121
- * @return bool
122
- */
123
- private static function _compareV6InRange( $ip, $firstInRange, $lastInRange ) {
124
- $firstInRange = inet_pton( self::expandIPv6( $firstInRange ) );
125
- $lastInRange = inet_pton( self::expandIPv6( $lastInRange ) );
126
- $ip = inet_pton( self::expandIPv6( $ip ) );
127
-
128
- if ( ( strlen( $ip ) == strlen( $firstInRange ) )
129
- && ( $ip >= $firstInRange && $ip <= $lastInRange ) ) {
130
- return true;
131
- } else {
132
- return false;
133
- }
134
- }
135
-
136
- /**
137
- * Compare ip2 to ip1, true if ip2>ip1, false if not
138
- *
139
- * @param $ip1
140
- * @param $ip2
141
- *
142
- * @return bool
143
- */
144
- public static function compareIP( $ip1, $ip2 ) {
145
- if ( self::isV4( $ip1 ) && self::isV4( $ip2 ) ) {
146
- if ( sprintf( "%u", ip2long( $ip2 ) ) - sprintf( "%u", ip2long( $ip1 ) ) > 0 ) {
147
- return true;
148
- }
149
- } elseif ( self::isV6( $ip1 ) && self::isV6( $ip2 ) && self::isV6Support() ) {
150
- $ip1 = inet_pton( self::expandIPv6( $ip1 ) );
151
- $ip2 = inet_pton( self::expandIPv6( $ip2 ) );
152
-
153
- return $ip2 > $ip1;
154
- }
155
-
156
- return false;
157
- }
158
-
159
- /**
160
- * @return array|bool
161
- * @throws \MaxMind\Db\Reader\InvalidDatabaseException
162
- */
163
- public static function getCurrentCountry() {
164
- $settings = Settings::instance();
165
- if ( php_sapi_name() === 'cli' ) {
166
- //never catch if from cli
167
- return false;
168
- }
169
- if ( ! $settings->isGeoDBDownloaded() ) {
170
- return false;
171
- }
172
- $geoIP = new GeoIp( $settings->geoIP_db );
173
- $ip = Utils::instance()->getUserIp();
174
- if ( ! filter_var( $ip, FILTER_VALIDATE_IP ) ) {
175
- return false;
176
- }
177
- $country = $geoIP->ipToCountry( Utils::instance()->getUserIp() );
178
-
179
- return $country;
180
- }
181
-
182
- /**
183
- * @param $ip
184
- *
185
- * @return mixed
186
- */
187
- private static function isV4( $ip ) {
188
- return filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 );
189
- }
190
-
191
- /**
192
- * @param $ip
193
- *
194
- * @return mixed
195
- */
196
- private static function isV6( $ip ) {
197
- return filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 );
198
- }
199
-
200
- /**
201
- * @param $ip
202
- *
203
- * @return bool|string
204
- */
205
- public static function expandIPv6( $ip ) {
206
- $hex = unpack( "H*hex", inet_pton( $ip ) );
207
- $ip = substr( preg_replace( "/([A-f0-9]{4})/", "$1:", $hex['hex'] ), 0, - 1 );
208
-
209
- return $ip;
210
- }
211
-
212
- /**
213
- * @return bool
214
- */
215
- public static function isV6Support() {
216
- return defined( 'AF_INET6' );
217
- }
218
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/ip-lockout/component/login-listener.php DELETED
@@ -1,185 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\IP_Lockout\Component;
7
-
8
- use WP_Defender\Behavior\Utils;
9
- use WP_Defender\Controller;
10
- use WP_Defender\Module\IP_Lockout\Model\IP_Model;
11
- use WP_Defender\Module\IP_Lockout\Model\Log_Model;
12
- use WP_Defender\Module\IP_Lockout\Model\Settings;
13
-
14
- class Login_Listener extends Controller {
15
- public function __construct() {
16
- $settings = Settings::instance();
17
- if ( $settings->login_protection ) {
18
- $this->addAction( 'wp_login_failed', 'recordFailLogin', 9999 );
19
- $this->addFilter( 'authenticate', 'showAttemptLeft', 9999, 3 );
20
- $this->addAction( 'wp_login', 'clearAttemptStats', 10, 2 );
21
- }
22
- }
23
-
24
- /**
25
- * Record fail login as log into db
26
- *
27
- * @param $username
28
- */
29
- public function recordFailLogin( $username ) {
30
- if ( $_SERVER['REQUEST_METHOD'] == 'GET' ) {
31
- //do nothing as wp-login.php wil trigger the wp_signon for cookie login, can cause trouble
32
- return;
33
- }
34
- $settings = Settings::instance();
35
- //first check if the username is fail to ban
36
- $username = strtolower( $username );
37
- $model = IP_Model::init();
38
-
39
- if ( in_array( $username, $settings->getUsernameBlacklist() ) ) {
40
- return $this->lock( $model, $username, 'blacklist_uname' );
41
- }
42
- //log for the event
43
- $this->log( $username, Log_Model::AUTH_FAIL, sprintf( esc_html__( "Failed login attempt with username %s", "defender-security" ), $username ) );
44
-
45
- //calculate if this one out of threshold
46
- $window = strtotime( '- ' . $settings->login_protection_lockout_timeframe . ' seconds' );
47
- if ( $window < $model->lock_time ) {
48
- /**
49
- * Case if it just banned and the lockout duration too short, we use the locktime instead
50
- */
51
- $window = $model->lock_time;
52
- }
53
-
54
- $attempt = Log_Model::count( [
55
- 'ip' => Utils::instance()->getUserIp(),
56
- 'date' => [ 'compare' => '>', 'value' => $window ],
57
- 'type' => Log_Model::AUTH_FAIL,
58
- 'blog_id' => get_current_blog_id()
59
- ] );
60
- $model->attempt = $attempt;
61
- if ( $attempt >= $settings->login_protection_login_attempt ) {
62
- $scenario = $settings->login_protection_lockout_ban ? 'ban' : 'normal';
63
-
64
- return $this->lock( $model, $username, $scenario );
65
- }
66
- $model->save();
67
- }
68
-
69
- /**
70
- * Reset the attempt counter
71
- */
72
- public function clearAttemptStats() {
73
- $model = IP_Model::init();
74
- $model->attempt = 1;
75
- $model->save();
76
- }
77
-
78
- /**
79
- * @param $user
80
- * @param $username
81
- * @param $password
82
- *
83
- * @return mixed
84
- */
85
- public function showAttemptLeft( $user, $username, $password ) {
86
- if ( is_wp_error( $user ) && $_SERVER['REQUEST_METHOD'] == 'POST' && ! in_array( $user->get_error_code(), array(
87
- 'empty_username',
88
- 'empty_password'
89
- ) )
90
- ) {
91
- $model = IP_Model::init();
92
- $settings = Settings::instance();
93
- if ( in_array( $username, $settings->getUsernameBlacklist() ) ) {
94
- $user->add( 'def_warning', esc_html__( "You have been locked out by the administrator for attempting to login with a banned username", "defender-security" ) );
95
- } else {
96
- $attempt = $model->attempt + 1;
97
- //because the action authenticate trigger before wp_login_failed, so we need to add 1 for the attemt
98
- if ( $attempt >= $settings->login_protection_login_attempt ) {
99
- //show lockout message
100
- $user->add( 'def_warning', $settings->login_protection_lockout_message );
101
- } else {
102
- $user->add( 'def_warning', sprintf( esc_html__( "%d login attempts remaining", "defender-security" ), $settings->login_protection_login_attempt - $attempt ) );
103
- }
104
- }
105
- }
106
-
107
- return $user;
108
- }
109
-
110
- /**
111
- * @param IP_Model $model
112
- * @param $username
113
- * @param $scenario
114
- */
115
- private function lock( IP_Model $model, $username, $scenario ) {
116
- $settings = Settings::instance();
117
- if ( $scenario === 'blacklist_uname' ) {
118
- $model->lockout_message = esc_html__( "You have been locked out by the administrator for attempting to login with a banned username", "defender-security" );
119
- $model->status = IP_Model::STATUS_BLOCKED;
120
- $model->lock_time = time();
121
- $model->save();
122
-
123
- //add to blacklist
124
- Settings::instance()->addIpToList( $model->ip, 'blocklist' );
125
- $this->log( $username, Log_Model::AUTH_LOCK, sprintf( esc_html__( "Failed login attempt with a ban username %s", "defender-security" ), $username ) );
126
- } else {
127
- $model->status = IP_Model::STATUS_BLOCKED;
128
- $model->release_time = strtotime( '+ ' . $settings->login_protection_lockout_duration . ' ' . $settings->login_protection_lockout_duration_unit );
129
- $model->lockout_message = $settings->login_protection_lockout_message;
130
- $model->lock_time = time();
131
- $model->save();
132
- if ( $scenario === 'ban' ) {
133
- $settings->addIpToList( $model->ip, 'blocklist' );
134
- }
135
- $this->log( $username, Log_Model::AUTH_LOCK, __( "Lockout occurred: Too many failed login attempts", "defender-security" ) );
136
- }
137
- do_action( 'wd_login_lockout', $model, $scenario );
138
- if ( $settings->login_lockout_notification ) {
139
- $this->email( $model );
140
- }
141
- }
142
-
143
- /**
144
- * Log the event into db, we will use the data in logs page later
145
- *
146
- * @param $username
147
- * @param $type
148
- * @param $log
149
- */
150
- private function log( $username, $type, $log ) {
151
- $model = new Log_Model();
152
- $model->ip = Utils::instance()->getUserIp();
153
- $model->user_agent = isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : null;
154
- $model->log = $log;
155
- $model->date = time();
156
- $model->type = $type;
157
- $model->tried = $username;
158
- $model->save();
159
- }
160
-
161
- private function email( IP_Model $model ) {
162
- $settings = Settings::instance();
163
-
164
- if ( ! Login_Protection_Api::maybeSendNotification( 'login', $model, $settings ) ) {
165
- return;
166
- }
167
-
168
- $view = ( $settings->isBlacklist( $model->ip ) ) ? 'emails/login-username-ban' : 'emails/login-lockout';
169
- foreach ( $settings->receipts as $item ) {
170
- $content = $this->renderPartial( $view, array(
171
- 'admin' => $item['first_name'],
172
- 'ip' => $model->ip,
173
- 'logs_url' => apply_filters( 'report_email_logs_link', apply_filters( 'wp_defeder/iplockout/email_report_link', network_admin_url( "admin.php?page=wdf-ip-lockout&view=logs" ) ), $item['email'] ),
174
- 'report_url' => apply_filters( 'report_email_logs_link', network_admin_url( 'admin.php?page=wdf-ip-lockout&view=reporting' ), $item['email'] ),
175
- ), false );
176
- $no_reply_email = "noreply@" . parse_url( get_site_url(), PHP_URL_HOST );
177
- $no_reply_email = apply_filters( 'wd_lockout_noreply_email', $no_reply_email );
178
- $headers = array(
179
- 'From: Defender <' . $no_reply_email . '>',
180
- 'Content-Type: text/html; charset=UTF-8'
181
- );
182
- wp_mail( $item['email'], sprintf( __( "Login lockout alert for %s", "defender-security" ), network_site_url() ), $content, $headers );
183
- }
184
- }
185
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/ip-lockout/component/login-protection-api.php DELETED
@@ -1,644 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\IP_Lockout\Component;
7
-
8
- use Hammer\Helper\Log_Helper;
9
- use Hammer\WP\Component;
10
- use WP_Defender\Behavior\Utils;
11
- use WP_Defender\Module\IP_Lockout\Model\IP_Model;
12
- use WP_Defender\Module\IP_Lockout\Model\Log_Model;
13
- use WP_Defender\Module\IP_Lockout\Model\Settings;
14
-
15
- class Login_Protection_Api extends Component {
16
- const COUNT_TOTAL = 'wdCountTotals';
17
-
18
- /**
19
- * This function will be called when
20
- *
21
- * @param Log_Model $log
22
- * @param bool $force
23
- */
24
- public static function maybeLock( Log_Model $log, $force = false, $blacklist = false ) {
25
- //find record first
26
- $model = IP_Model::findOne( array(
27
- 'ip' => $log->ip
28
- ) );
29
-
30
- if ( is_object( $model ) && $model->status == IP_Model::STATUS_BLOCKED ) {
31
- //already locked, just return
32
- return;
33
- }
34
-
35
- $settings = Settings::instance();
36
- //find backward from log date, if there are only log & counter > max attempt, then lock
37
- $after = strtotime( '-' . $settings->login_protection_lockout_timeframe . ' seconds' );
38
- if ( is_object( $model ) ) {
39
- //recal release time, if after time smaller than lock time,then we will use last locktime for check
40
- if ( $after < $model->lock_time ) {
41
- $after = $model->lock_time;
42
- }
43
- }
44
-
45
- $attempt = Log_Model::count( array(
46
- 'ip' => $log->ip,
47
- 'type' => Log_Model::AUTH_FAIL,
48
- 'blog_id' => get_current_blog_id(),
49
- 'date' => array( 'compare' => '>', 'value' => $after )
50
- ) );
51
-
52
- if ( ! is_object( $model ) ) {
53
- //no record, create one
54
- $model = new IP_Model();
55
- $model->ip = $log->ip;
56
- $model->status = IP_Model::STATUS_NORMAL;
57
- }
58
- $model->attempt = $attempt;
59
- if ( $model->attempt >= $settings->login_protection_login_attempt || $force == true ) {
60
- $model->status = IP_Model::STATUS_BLOCKED;
61
- $model->release_time = strtotime( '+ ' . $settings->login_protection_lockout_duration . ' ' . $settings->login_protection_lockout_duration_unit );
62
- if ( $blacklist && $force ) {
63
- $model->lockout_message = esc_html__( "You have been locked out by the administrator for attempting to login with a banned username", "defender-security" );
64
- } else {
65
- $model->lockout_message = $settings->login_protection_lockout_message;
66
- }
67
- $model->lock_time = time();
68
- $model->save();
69
- //we need to create a log
70
- $lock_log = new Log_Model();
71
- $lock_log->type = Log_Model::AUTH_LOCK;
72
- $lock_log->date = time();
73
- $lock_log->ip = $log->ip;
74
- $lock_log->user_agent = $_SERVER['HTTP_USER_AGENT'];
75
- if ( $force && $blacklist ) {
76
- $lock_log->log = esc_html__( "Lockout occurred: Attempting to login with a banned username.", "defender-security" );
77
- } elseif ( ! empty( $log->tried ) ) {
78
- $lock_log->log = sprintf( esc_html__( "Lockout occurred: Too many failed login attempts for the username %s", "defender-security" ), $log->tried );
79
- } else {
80
- $lock_log->log = esc_html__( "Lockout occurred: Too many failed login attempts", "defender-security" );
81
- }
82
- $lock_log->save();
83
- //if fail2ban, we will add that IP to blacklist
84
- if ( $settings->login_protection_lockout_ban || $blacklist ) {
85
- $settings->addIpToList( $model->ip, 'blocklist' );
86
- }
87
-
88
- //trigger an action
89
- do_action( 'wd_login_lockout', $model, $force, $blacklist );
90
- } else {
91
- $model->save();
92
- }
93
- }
94
-
95
- /**
96
- * @param Log_Model $log
97
- */
98
- public static function maybe404Lock( Log_Model $log ) {
99
- //find record first
100
- $model = IP_Model::findOne( array(
101
- 'ip' => $log->ip
102
- ) );
103
-
104
- if ( is_object( $model ) && $model->status == IP_Model::STATUS_BLOCKED ) {
105
- //already locked, just return
106
- return;
107
- }
108
-
109
- $settings = Settings::instance();
110
- //find backward from log date, if there are only log & counter > max attempt, then lock
111
- $after = strtotime( '- ' . $settings->detect_404_timeframe . ' seconds' );
112
-
113
- if ( is_object( $model ) ) {
114
- //recal release time, if after time smaller than lock time,then we will use last locktime for check
115
- if ( $after < $model->lock_time_404 ) {
116
- $after = $model->lock_time_404;
117
- }
118
- }
119
- $logs = Log_Model::findAll( array(
120
- 'ip' => $log->ip,
121
- 'type' => Log_Model::ERROR_404,
122
- 'blog_id' => get_current_blog_id(),
123
- 'date' => array(
124
- 'compare' => '>',
125
- 'value' => $after
126
- )
127
- ) );
128
-
129
- if ( ! is_object( $model ) ) {
130
- //no record, create one
131
- $model = new IP_Model();
132
- $model->ip = $log->ip;
133
- $model->status = IP_Model::STATUS_NORMAL;
134
- }
135
-
136
- //filter out the extension
137
- $ignoresFileTypes = $settings->get404Ignorelist();
138
- foreach ( $logs as $k => $log ) {
139
- $ext = pathinfo( $log->log, PATHINFO_EXTENSION );
140
- if ( in_array( $ext, $ignoresFileTypes ) ) {
141
- unset( $logs[ $k ] );
142
- }
143
- }
144
-
145
- if ( count( $logs ) >= $settings->detect_404_threshold ) {
146
- //we need to check the extension
147
- $model->status = IP_Model::STATUS_BLOCKED;
148
- $model->release_time = strtotime( '+ ' . $settings->detect_404_lockout_duration . ' ' . $settings->detect_404_lockout_duration_unit );
149
- $model->lockout_message = $settings->detect_404_lockout_message;
150
- $model->lock_time_404 = time();
151
- $model->save();
152
- $lock_log = new Log_Model();
153
- $lock_log->type = Log_Model::LOCKOUT_404;
154
- $lock_log->date = time();
155
- $lock_log->ip = $log->ip;
156
- $lock_log->user_agent = $_SERVER['HTTP_USER_AGENT'];
157
- $uri = esc_url( $_SERVER['REQUEST_URI'] );
158
- $lock_log->log = sprintf( esc_html__( "Lockout occurred: Too many 404 requests for %s", "defender-security" ), $uri );
159
- $lock_log->save();
160
- //if fail2ban, we will add that IP to blacklist
161
- $isBlacklist = false;
162
- if ( $settings->detect_404_lockout_ban ) {
163
- $settings->addIpToList( $model->ip, 'blocklist' );
164
- $isBlacklist = true;
165
- }
166
- do_action( 'wd_404_lockout', $model, $uri, $isBlacklist );
167
- }
168
- }
169
-
170
- /**
171
- * @param null $time - unix timestamp
172
- *
173
- * @return int
174
- * @deprecated
175
- */
176
- public static function get404Lockouts( $time = null ) {
177
- $logs = Log_Model::count( array(
178
- 'type' => Log_Model::LOCKOUT_404,
179
- 'date' => array(
180
- 'compare' => '>=',
181
- 'value' => $time
182
- )
183
- ) );
184
-
185
- return $logs;
186
- }
187
-
188
- /**
189
- * @param null $time - unix timestamp
190
- *
191
- * @return int
192
- * @deprecated
193
- */
194
- public static function getLoginLockouts( $time = null ) {
195
- $logs = Log_Model::count( array(
196
- 'type' => Log_Model::AUTH_LOCK,
197
- 'date' => array(
198
- 'compare' => '>=',
199
- 'value' => $time
200
- )
201
- ) );
202
-
203
- return $logs;
204
- }
205
-
206
- /**
207
- * @param null $time - unix timestamp
208
- *
209
- * @return int
210
- * @deprecated
211
- */
212
- public static function getAllLockouts( $time = null ) {
213
- $logs = Log_Model::count( array(
214
- 'type' => array(
215
- Log_Model::LOCKOUT_404,
216
- Log_Model::AUTH_LOCK
217
- ),
218
- 'date' => array(
219
- 'compare' => '>=',
220
- 'value' => $time
221
- )
222
- ) );
223
-
224
- return $logs;
225
- }
226
-
227
- /**
228
- * @return Log_Model
229
- * @deprecated
230
- */
231
- public static function getLastLockout() {
232
- $log = Log_Model::findAll( array(
233
- 'type' => array(
234
- Log_Model::LOCKOUT_404,
235
- Log_Model::AUTH_LOCK
236
- )
237
- ), 'id', 'DESC', '0,1' );
238
- $log = array_shift( $log );
239
- if ( is_object( $log ) ) {
240
- return $log;
241
- }
242
-
243
- return null;
244
- }
245
-
246
- public static function time_since( $since ) {
247
- $since = time() - $since;
248
- if ( $since < 0 ) {
249
- $since = 0;
250
- }
251
- $chunks = array(
252
- array( 60 * 60 * 24 * 365, esc_html__( "year" ) ),
253
- array( 60 * 60 * 24 * 30, esc_html__( "month" ) ),
254
- array( 60 * 60 * 24 * 7, esc_html__( "week" ) ),
255
- array( 60 * 60 * 24, esc_html__( 'day' ) ),
256
- array( 60 * 60, esc_html__( "hour" ) ),
257
- array( 60, esc_html__( "minute" ) ),
258
- array( 1, esc_html__( "second" ) )
259
- );
260
-
261
- for ( $i = 0, $j = count( $chunks ); $i < $j; $i ++ ) {
262
- $seconds = $chunks[ $i ][0];
263
- $name = $chunks[ $i ][1];
264
- if ( ( $count = floor( $since / $seconds ) ) != 0 ) {
265
- break;
266
- }
267
- }
268
-
269
- $print = ( $count == 1 ) ? '1 ' . $name : "$count {$name}s";
270
-
271
- return $print;
272
- }
273
-
274
- /**
275
- * @return string
276
- */
277
- public static function getLogsActionsText( $log ) {
278
- $links = array();
279
- $settings = Settings::instance();
280
- $blacklist = $settings->getIpBlacklist();
281
- $whitelist = $settings->getIpWhitelist();
282
-
283
- $ip = Utils::instance()->getUserIp();
284
- $nonce = wp_create_nonce( 'lockoutIPAction' );
285
- if ( $ip != $log->ip ) {
286
- if ( ! in_array( $log->ip, $blacklist ) ) {
287
- $links[] = '<a data-nonce="' . $nonce . '" class="ip-action sui-button sui-button-red" data-type="blacklist" data-id="' . esc_attr( $log->id ) . '" data-ip="' . esc_attr( $log->ip ) . '" href="#"><i class="sui-icon-cross-close" aria-hidden="true"></i>' . __( "Ban IP", "defender-security" ) . '</a>';
288
- } else {
289
- $links[] = '<a data-nonce="' . $nonce . '" class="ip-action sui-button sui-button-blue" data-type="unblacklist" data-id="' . esc_attr( $log->id ) . '" data-ip="' . esc_attr( $log->ip ) . '" href="#">' . __( "Unban IP", "defender-security" ) . '</a>';
290
- }
291
- }
292
-
293
- if ( ! in_array( $log->ip, $whitelist ) ) {
294
- $links[] = '<a data-nonce="' . $nonce . '" class="ip-action sui-button sui-button-ghost" data-type="whitelist" data-id="' . esc_attr( $log->id ) . '" data-ip="' . esc_attr( $log->ip ) . '" href="#"><i class="sui-icon-check-tick" aria-hidden="true"></i>' . __( "Add Whitelist", "defender-security" ) . '</a>';
295
- } else {
296
- $links[] = '<a data-nonce="' . $nonce . '" class="ip-action sui-button sui-button-ghost" data-type="unwhitelist" data-id="' . esc_attr( $log->id ) . '" data-ip="' . esc_attr( $log->ip ) . '" href="#">' . __( "Unwhitelist", "defender-security" ) . '</a>';
297
- }
298
-
299
- return implode( '', $links );
300
- }
301
-
302
- /**
303
- * Validate import file is in right format and usable for IP Lockout
304
- *
305
- * @param $file
306
- *
307
- * @return array|bool
308
- */
309
- public static function verifyImportFile( $file ) {
310
- $fp = fopen( $file, 'r' );
311
- $data = array();
312
- while ( ( $line = fgetcsv( $fp ) ) !== false ) {
313
- if ( count( $line ) != 2 ) {
314
- return false;
315
- }
316
-
317
- if ( ! in_array( $line[1], array( 'allowlist', 'blocklist' ) ) ) {
318
- return false;
319
- }
320
-
321
- if ( Settings::instance()->validateIp( $line[0] ) == false ) {
322
- continue;
323
- }
324
-
325
- $data[] = $line;
326
-
327
- }
328
- fclose( $fp );
329
-
330
- return $data;
331
- }
332
-
333
- /**
334
- * @return bool
335
- */
336
- public static function isActive() {
337
- return Settings::instance()->login_protection && Settings::instance()->detect_404;
338
- }
339
-
340
- /**
341
- * @param bool $clearCron
342
- *
343
- * @return false|int
344
- * @deprecated 1.5
345
- */
346
- public static function getReportTime( $clearCron = true, $utc = true ) {
347
- if ( $clearCron ) {
348
- wp_clear_scheduled_hook( 'lockoutReportCron' );
349
- }
350
- $settings = Settings::instance();
351
- switch ( $settings->report_frequency ) {
352
- case '1':
353
- //check if the time is over or not, then send the date
354
- $timeString = date( 'Y-m-d' ) . ' ' . $settings->report_time . ':00';
355
- $nextTimeString = date( 'Y-m-d', strtotime( 'tomorrow' ) ) . ' ' . $settings->report_time . ':00';
356
- break;
357
- case '7':
358
- default:
359
- $timeString = date( 'Y-m-d', strtotime( $settings->report_day . ' this week' ) ) . ' ' . $settings->report_time . ':00';
360
- $nextTimeString = date( 'Y-m-d', strtotime( $settings->report_day . ' next week' ) ) . ' ' . $settings->report_time . ':00';
361
- break;
362
- case '30':
363
- $timeString = date( 'Y-m-d', strtotime( $settings->report_day . ' this month' ) ) . ' ' . $settings->report_time . ':00';
364
- $nextTimeString = date( 'Y-m-d', strtotime( $settings->report_day . ' next month' ) ) . ' ' . $settings->report_time . ':00';
365
- break;
366
- }
367
-
368
- $toUTC = Utils::instance()->localToUtc( $timeString );
369
- if ( $toUTC <= time() ) {
370
- if ( $utc ) {
371
- return Utils::instance()->localToUtc( $nextTimeString );
372
- } else {
373
- return strtotime( $timeString );
374
- }
375
- } else {
376
- if ( $utc ) {
377
- return $toUTC;
378
- } else {
379
- return strtotime( $timeString );
380
- }
381
- }
382
- }
383
-
384
- /**
385
- * Check if useragent is looks like from google
386
- *
387
- * @param string $userAgent
388
- *
389
- * @return bool
390
- */
391
- public static function isGoogleUA( $userAgent = '' ) {
392
- if ( empty( $userAgent ) ) {
393
- $userAgent = isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : null;
394
- }
395
- if ( function_exists( 'mb_strtolower' ) ) {
396
- $userAgent = mb_strtolower( $userAgent, 'UTF-8' );
397
- } else {
398
- $userAgent = strtolower( $userAgent );
399
- }
400
-
401
- if ( stristr( $userAgent, 'googlebot' ) !== false ) {
402
- return true;
403
- }
404
-
405
- return false;
406
- }
407
-
408
- /**
409
- * Check if IP is from google, base on https://support.google.com/webmasters/answer/80553?hl=en
410
- *
411
- * @param $ip
412
- *
413
- * @return bool
414
- */
415
- public static function isGoogleIP( $ip ) {
416
- $hostname = gethostbyaddr( $ip );
417
- //check if this hostname has googlebot or google.com
418
- if ( preg_match( '/\.googlebot|google\.com$/i', $hostname ) ) {
419
- $hosts = gethostbynamel( $hostname );
420
- //check if this match the oringal ip
421
- foreach ( $hosts as $host ) {
422
- if ( $ip == $host ) {
423
- return true;
424
- }
425
- }
426
- }
427
-
428
- return false;
429
- }
430
-
431
- /**
432
- * Check if IP is from Bing, base on https://www.bing.com/webmaster/help/how-to-verify-bingbot-3905dc26
433
- *
434
- * @param $ip
435
- */
436
- public static function isBingIP( $ip ) {
437
- $hostname = gethostbyaddr( $ip );
438
- if ( preg_match( '/\.msnbot|msn\.com$/i', $hostname ) ) {
439
- $hosts = gethostbynamel( $hostname );
440
- //check if this match the oringal ip
441
- foreach ( $hosts as $host ) {
442
- if ( $ip == $host ) {
443
- return true;
444
- }
445
- }
446
- }
447
-
448
- return false;
449
- }
450
-
451
- public static function isBingUA( $userAgent = '' ) {
452
- if ( empty( $userAgent ) ) {
453
- $userAgent = isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : null;
454
- }
455
- if ( function_exists( 'mb_strtolower' ) ) {
456
- $userAgent = mb_strtolower( $userAgent, 'UTF-8' );
457
- } else {
458
- $userAgent = strtolower( $userAgent );
459
- }
460
- //MSN Bot Useragent https://www.bing.com/webmaster/help/which-crawlers-does-bing-use-8c184ec0
461
- $msnUA = "Bingbot|MSNBot|MSNBot-Media|AdIdxBot|BingPreview";
462
-
463
- if ( preg_match( '/' . $msnUA . '/i', $userAgent ) ) {
464
- return true;
465
- }
466
-
467
- return false;
468
- }
469
-
470
- public static function maybeSendNotification( $type, $model, $settings ) {
471
- $lastSentKey = $type == 'login' ? 'lastSentLockout' : 'lastSent404';
472
- $stopTimeKey = $type == 'login' ? 'stopTimeLockout' : 'stopTime404';
473
- if ( $settings->cooldown_enabled ) {
474
- //check the last time,and check the status
475
- $lastSent = $model->getMeta( $lastSentKey );
476
- $stopTime = $model->getMeta( $stopTimeKey, false );
477
- $currentTime = apply_filters( 'wd_lockout_notification_current_time', time() );
478
- if ( $stopTime && $currentTime < $stopTime ) {
479
- //no further email
480
- return false;
481
- }
482
- //we need to check if we can lock
483
- if ( $lastSent == false ) {
484
- //no info, we need to init
485
- $lastSent = time();
486
- $model->updateMeta( $lastSentKey, $lastSent );
487
- }
488
- //we have last sent value here, now need to check the amount from now to last sent
489
- if ( $stopTime && $lastSent < $stopTime ) {
490
- $lastSent = $stopTime;
491
- }
492
-
493
- $count = Log_Model::count( array(
494
- 'type' => $type == 'login' ? Log_Model::AUTH_LOCK : Log_Model::LOCKOUT_404,
495
- 'blog_id' => get_current_blog_id(),
496
- 'date' => array(
497
- 'compare' => '>',
498
- 'value' => $lastSent
499
- )
500
- ) );
501
- //The number of lockouts before we turn off emails or for first attempt
502
- if ( ( '0' === $count ) || ( $count >= $settings->cooldown_number_lockout ) ) {
503
- $model->updateMeta( $stopTimeKey, strtotime( '+' . $settings->cooldown_period . ' hours' ) );
504
- $model->updateMeta( $lastSentKey, time() );
505
- }
506
- }
507
-
508
- return true;
509
- }
510
-
511
- /**
512
- *
513
- */
514
- public static function createTables() {
515
- global $wpdb;
516
-
517
- $charsetCollate = $wpdb->get_charset_collate();
518
- $tableName1 = $wpdb->base_prefix . 'defender_lockout';
519
- $tableName2 = $wpdb->base_prefix . 'defender_lockout_log';
520
- $sql = "CREATE TABLE IF NOT EXISTS `{$tableName1}` (
521
- `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
522
- `ip` varchar(255) DEFAULT NULL,
523
- `status` varchar(16) DEFAULT NULL,
524
- `lockout_message` text,
525
- `release_time` int(11) DEFAULT NULL,
526
- `lock_time` int(11) DEFAULT NULL,
527
- `lock_time_404` int(11) DEFAULT NULL,
528
- `attempt` int(11) DEFAULT NULL,
529
- `attempt_404` int(11) DEFAULT NULL,
530
- `meta` text,
531
- PRIMARY KEY (`id`)
532
- ) $charsetCollate;
533
- CREATE TABLE `{$tableName2}` (
534
- `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
535
- `log` text,
536
- `ip` varchar(255) DEFAULT NULL,
537
- `date` int(11) DEFAULT NULL,
538
- `type` varchar(16) DEFAULT NULL,
539
- `user_agent` varchar(255) DEFAULT NULL,
540
- `blog_id` int(11) DEFAULT NULL,
541
- `tried` VARCHAR (255),
542
- PRIMARY KEY (`id`)
543
- ) $charsetCollate;
544
- ";
545
- require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
546
- dbDelta( $sql );
547
- }
548
-
549
- public static function alterTableFor171() {
550
- global $wpdb;
551
- $tableName1 = $wpdb->base_prefix . 'defender_lockout_log';
552
- $tableName2 = $wpdb->base_prefix . 'defender_lockout';
553
- $check = "SHOW COLUMNS FROM {$tableName1} LIKE 'tried';";
554
- $check = $wpdb->get_col( $check );
555
- if ( count( $check ) == 0 ) {
556
- $sql = "ALTER TABLE " . $tableName1 . " ADD COLUMN `tried` VARCHAR(255);";
557
- $wpdb->query( $sql );
558
- }
559
- $check = "SHOW COLUMNS FROM {$tableName2} LIKE 'meta';";
560
- $check = $wpdb->get_col( $check );
561
- if ( count( $check ) == 0 ) {
562
- $sql = "ALTER TABLE " . $tableName2 . " ADD COLUMN `meta` text;";
563
- $wpdb->query( $sql );
564
- }
565
- }
566
-
567
- /**
568
- * @return array
569
- */
570
- public static function getIpsLocked() {
571
- return IP_Model::findAll( array(
572
- 'status' => IP_Model::STATUS_BLOCKED
573
- ) );
574
- }
575
-
576
- /**
577
- * @param $ip
578
- *
579
- * @return string|void
580
- */
581
- public static function getIPStatusText( $ip ) {
582
- if ( Settings::instance()->isWhitelist( $ip ) ) {
583
- return __( "Is allowlisted", "defender-security" );
584
- }
585
- if ( Settings::instance()->isBlacklist( $ip ) ) {
586
- return __( "Is blocklisted", "defender-security" );
587
- }
588
-
589
- $model = IP_Model::findOne( array(
590
- 'ip' => $ip
591
- ) );
592
- if ( ! is_object( $model ) ) {
593
- return __( "Not banned", "defender-security" );
594
- }
595
-
596
- if ( $model->status == IP_Model::STATUS_BLOCKED ) {
597
- return __( "Banned", "defender-security" );
598
- } elseif ( $model->status == IP_Model::STATUS_NORMAL ) {
599
- return __( "Not banned", "defender-security" );
600
- }
601
- }
602
-
603
- /**
604
- * @return bool
605
- */
606
- public static function checkIfTableExists() {
607
- global $wpdb;
608
- $tableName1 = $wpdb->base_prefix . 'defender_lockout';
609
- $tableName2 = $wpdb->base_prefix . 'defender_lockout_log';
610
- if ( $wpdb->get_var( "SHOW TABLES LIKE '$tableName1'" ) != $tableName1 ||
611
- $wpdb->get_var( "SHOW TABLES LIKE '$tableName2'" ) != $tableName2 ) {
612
- return false;
613
- }
614
-
615
- return true;
616
- }
617
-
618
- /**
619
- * @return bool
620
- */
621
- public static function downloadGeoIP() {
622
- $url = "http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.tar.gz";
623
- if ( ! function_exists( 'download_url' ) ) {
624
- require_once ABSPATH . 'wp-admin/includes/file.php';
625
- }
626
- $tmp = download_url( $url );
627
- if ( ! is_wp_error( $tmp ) ) {
628
- $phar = new \PharData( $tmp );
629
- $defPath = Utils::instance()->getDefUploadDir();
630
- $path = $defPath . DIRECTORY_SEPARATOR . 'maxmind';
631
- if ( ! is_dir( $path ) ) {
632
- mkdir( $path );
633
- }
634
- $phar->extractTo( $path, null, true );
635
- $settings = Settings::instance();
636
- $settings->geoIP_db = $path . DIRECTORY_SEPARATOR . $phar->current()->getFileName() . DIRECTORY_SEPARATOR . 'GeoLite2-Country.mmdb';
637
- $settings->save();
638
-
639
- return true;
640
- }
641
-
642
- return false;
643
- }
644
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/ip-lockout/component/logs-table.php DELETED
@@ -1,586 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\IP_Lockout\Component;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use Hammer\Helper\WP_Helper;
10
- use WP_Defender\Behavior\Utils;
11
- use WP_Defender\Module\IP_Lockout\Model\IP_Model;
12
- use WP_Defender\Module\IP_Lockout\Model\Log_Model;
13
-
14
- class Logs_Table extends \WP_List_Table {
15
- protected $from;
16
- protected $to;
17
-
18
- public function __construct( $args = array() ) {
19
- parent::__construct( array_merge( array(
20
- 'plural' => '',
21
- 'autoescape' => false,
22
- 'screen' => 'lockout_logs'
23
- ), $args ) );
24
-
25
- $date_format = 'm/d/Y';
26
- $this->from = Http_Helper::retrieveGet( 'date_from', date( $date_format, strtotime( 'today midnight', strtotime( '-14 days', current_time( 'timestamp' ) ) ) ) );
27
- $this->to = Http_Helper::retrieveGet( 'date_to', date( $date_format, current_time( 'timestamp' ) ) );
28
- }
29
-
30
- /**
31
- * @return array
32
- */
33
- function get_table_classes() {
34
- return array(
35
- 'list-table',
36
- //'hover-effect',
37
- 'logs',
38
- 'sui-table',
39
- 'sui-accordion'
40
- );
41
- }
42
-
43
- /**
44
- * @return array
45
- */
46
- function get_columns() {
47
- $columns = array(
48
- 'reason' => esc_html__( 'Details', "defender-security" ),
49
- 'date' => esc_html__( 'Time', "defender-security" ),
50
- 'action' => ''
51
- );
52
-
53
- return $columns;
54
- }
55
-
56
- protected function get_sortable_columns() {
57
- return array(
58
- //'reason' => array( 'log', true ),
59
- // 'date' => array( 'date', true ),
60
- // 'ip' => array( 'ip', true ),
61
- );
62
- }
63
-
64
- function prepare_items() {
65
- $paged = $this->get_pagenum();
66
- $per_page = 20;
67
- $offset = ( $paged - 1 ) * $per_page;
68
-
69
- $params = array(
70
- 'date' => array(
71
- 'compare' => 'between',
72
- 'from' => strtotime( 'midnight', strtotime( $this->from ) ),
73
- 'to' => strtotime( 'tomorrow', strtotime( $this->to ) )
74
- )
75
- );
76
-
77
- if ( ( $filter = Http_Helper::retrieveGet( 'type', null ) ) != null ) {
78
- $params['type'] = $filter;
79
- }
80
- if ( ( $ip = Http_Helper::retrieveGet( 'ip_address', null ) ) != null ) {
81
- $params['ip'] = $ip;
82
- }
83
-
84
- $logs = Log_Model::findAll( $params,
85
- HTTP_Helper::retrieveGet( 'orderby', 'id' ),
86
- HTTP_Helper::retrieveGet( 'order', 'desc' ),
87
- $offset . ',' . $per_page
88
- );
89
-
90
- $cache = WP_Helper::getArrayCache();
91
- $totalItems = $cache->get( Login_Protection_Api::COUNT_TOTAL, false );
92
-
93
- if ( $totalItems == false ) {
94
- $totalItems = Log_Model::count( $params );
95
- $cache->set( Login_Protection_Api::COUNT_TOTAL, $totalItems, 3600 );
96
- }
97
-
98
- $this->set_pagination_args( array(
99
- 'total_items' => $totalItems,
100
- 'total_pages' => ceil( $totalItems / $per_page ),
101
- 'per_page' => $per_page
102
- ) );
103
-
104
- $this->_column_headers = array( $this->get_columns(), array(), $this->get_sortable_columns() );
105
- $this->items = $logs;
106
- }
107
-
108
- /**
109
- * @param Log_Model $log
110
- *
111
- * @return string
112
- */
113
- public function column_action( Log_Model $log ) {
114
- return '<i class="dev-icon dev-icon-caret_down"></i>';
115
- }
116
-
117
- /**
118
- * @param Log_Model $log
119
- *
120
- * @return string
121
- */
122
- public function column_reason( Log_Model $log ) {
123
- $format = false;
124
- if ( $log->type == Log_Model::ERROR_404 ) {
125
- $format = true;
126
- }
127
- ob_start();
128
- ?>
129
- <label class="sui-checkbox">
130
- <input type="checkbox" class="single-select" name="ids[]" value="<?php echo $log->id ?>"/>
131
- <span aria-hidden="true"></span>
132
- </label>
133
- <span class="badge <?php echo $log->type == 'auth_lock' || $log->type == '404_lockout' ? 'locked' : null ?>"><?php echo $log->type == 'auth_fail' || $log->type == 'auth_lock' ? 'login' : '404' ?></span>
134
- <?php
135
- echo wp_trim_words( $log->get_log_text( $format ), 20 );
136
-
137
- return ob_get_clean();
138
- }
139
-
140
- /**
141
- * @param Log_Model $log
142
- *
143
- * @return string
144
- */
145
- public function column_date( Log_Model $log ) {
146
- return $log->get_date();
147
- }
148
-
149
- /**
150
- * @param Log_Model $log
151
- *
152
- * @return string
153
- */
154
- public function column_ip( Log_Model $log ) {
155
- $ip = Utils::instance()->getUserIp();
156
- if ( $ip == $log->get_ip() ) {
157
- return '<span tooltip="' . esc_attr( $ip ) . '" class="badge">' . __( "You", "defender-security" ) . '</span>';
158
- } else {
159
- return $log->get_ip();
160
- }
161
- }
162
-
163
- public function display() {
164
- $singular = $this->_args['singular'];
165
-
166
- $this->screen->render_screen_reader_content( 'heading_list' );
167
- ?>
168
- <div class="lockout-logs-container">
169
- <?php $this->display_tablenav( 'top' ); ?>
170
- <?php if ( $this->_pagination_args['total_items'] > 0 ): ?>
171
- <div class="lockout-logs-inner">
172
- <div class="lockout-logs-filter sui-pagination-filter">
173
- <form method="post">
174
- <div class="sui-row">
175
- <div class="sui-col">
176
- <div class="sui-form-field">
177
- <label class="sui-label">
178
- <?php _e( "Lockout Type", "defender-security" ) ?>
179
- </label>
180
- <select name="type">
181
- <option value=""><?php esc_html_e( "All", "defender-security" ) ?></option>
182
- <option <?php selected( \WP_Defender\Module\IP_Lockout\Model\Log_Model::AUTH_FAIL, \Hammer\Helper\HTTP_Helper::retrieveGet( 'filter' ) ) ?>
183
- value="<?php echo \WP_Defender\Module\IP_Lockout\Model\Log_Model::AUTH_FAIL ?>">
184
- <?php esc_html_e( "Failed login attempts", "defender-security" ) ?></option>
185
- <option <?php selected( \WP_Defender\Module\IP_Lockout\Model\Log_Model::AUTH_LOCK, \Hammer\Helper\HTTP_Helper::retrieveGet( 'filter' ) ) ?>
186
- value="<?php echo \WP_Defender\Module\IP_Lockout\Model\Log_Model::AUTH_LOCK ?>"><?php esc_html_e( "Login lockout", "defender-security" ) ?></option>
187
- <option <?php selected( \WP_Defender\Module\IP_Lockout\Model\Log_Model::ERROR_404, \Hammer\Helper\HTTP_Helper::retrieveGet( 'filter' ) ) ?>
188
- value="<?php echo \WP_Defender\Module\IP_Lockout\Model\Log_Model::ERROR_404 ?>"><?php esc_html_e( "404 error", "defender-security" ) ?></option>
189
- <option <?php selected( \WP_Defender\Module\IP_Lockout\Model\Log_Model::LOCKOUT_404, \Hammer\Helper\HTTP_Helper::retrieveGet( 'filter' ) ) ?>
190
- value="<?php echo \WP_Defender\Module\IP_Lockout\Model\Log_Model::LOCKOUT_404 ?>"><?php esc_html_e( "404 lockout", "defender-security" ) ?></option>
191
- </select>
192
- </div>
193
- </div>
194
- <div class="sui-col">
195
- <div class="sui-form-field">
196
- <label class="sui-label">
197
- <?php _e( "IP Address", "defender-security" ) ?>
198
- </label>
199
- <input name="ip_address" type="text" class="sui-form-control"
200
- placeholder="<?php esc_attr_e( "Enter an IP address", "defender-security" ) ?>">
201
- </div>
202
- </div>
203
- <div class="sui-col"></div>
204
- </div>
205
- <hr/>
206
- <div class="sui-row">
207
- <div class="sui-col">
208
- <button type="button" class="sui-button sui-button-ghost">
209
- <?php _e( "Clear Filters", "defender-security" ) ?>
210
- </button>
211
- </div>
212
- <div class="sui-col">
213
- <button type="submit" class="sui-button float-r">
214
- <i class="sui-icon-check" aria-hidden="true"></i>
215
- <?php _e( "Apply", "defender-security" ) ?>
216
- </button>
217
- </div>
218
- </div>
219
- </form>
220
- </div>
221
- <div class="sui-row sui-flushed">
222
- <table id="iplockout-table"
223
- class="<?php echo implode( ' ', $this->get_table_classes() ); ?>">
224
- <thead>
225
- <tr>
226
- <?php $this->print_column_headers(); ?>
227
- </tr>
228
- </thead>
229
-
230
- <tbody id="the-list"<?php
231
- if ( $singular ) {
232
- echo " data-wp-lists='list:$singular'";
233
- } ?>>
234
- <?php $this->display_rows_or_placeholder(); ?>
235
- </tbody>
236
- </table>
237
- </div>
238
- </div>
239
- <?php
240
- $this->display_tablenav( 'bottom' );
241
- ?>
242
- <?php else: ?>
243
- <div class="sui-row sui-flushed">
244
- <table class="sui-table no-border margin-bottom-20">
245
- <tr>
246
- <td>
247
- <div class="sui-notice">
248
- <p>
249
- <?php _e( "No lockout events have been logged within the selected time period.", "defender-security" ) ?>
250
- </p>
251
- </div>
252
- </td>
253
- </tr>
254
- </table>
255
- </div>
256
- <?php endif; ?>
257
- </div>
258
- <?php
259
- }
260
-
261
- /**
262
- * @param object $item
263
- */
264
- public function single_row( $item ) {
265
- $class = 'sui-accordion-item sui-warning ';
266
- if ( in_array( $item->type, array(
267
- Log_Model::AUTH_LOCK,
268
- Log_Model::AUTH_FAIL
269
- ) ) ) {
270
- $class .= 'log-login';
271
- } elseif ( in_array( $item->type, array(
272
- Log_Model::ERROR_404,
273
- Log_Model::ERROR_404_IGNORE,
274
- Log_Model::LOCKOUT_404
275
- ) ) ) {
276
- $class .= 'log-404';
277
- }
278
-
279
- if ( in_array( $item->type, array(
280
- Log_Model::LOCKOUT_404,
281
- Log_Model::AUTH_LOCK
282
- ) ) ) {
283
- $class .= ' lockout';
284
- }
285
- $class .= ' ';
286
- echo '<tr class="' . $class . '">';
287
- $this->single_row_columns( $item );
288
- echo '</tr>';
289
- echo '<tr class="sui-accordion-item-content">';
290
- echo $this->detailRow( $item );
291
- echo '<tr>';
292
- }
293
-
294
- /**
295
- * Generates the columns for a single row of the table
296
- *
297
- * @since 3.1.0
298
- *
299
- * @param object $item The current item
300
- */
301
- protected function single_row_columns( $item ) {
302
- list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();
303
- foreach ( $columns as $column_name => $column_display_name ) {
304
- $classes = "$column_name column-$column_name";
305
- if ( $primary === $column_name ) {
306
- $classes .= ' sui-table-item-title';
307
- }
308
-
309
- if ( in_array( $column_name, $hidden ) ) {
310
- $classes .= ' hidden';
311
- }
312
-
313
- // Comments column uses HTML in the display name with screen reader text.
314
- // Instead of using esc_attr(), we strip tags to get closer to a user-friendly string.
315
- $data = 'data-colname="' . wp_strip_all_tags( $column_display_name ) . '"';
316
-
317
- $attributes = "class='$classes' $data";
318
-
319
- if ( 'cb' === $column_name ) {
320
- echo '<th scope="row" class="check-column">';
321
- echo $this->column_cb( $item );
322
- echo '</th>';
323
- } elseif ( method_exists( $this, '_column_' . $column_name ) ) {
324
- echo call_user_func(
325
- array( $this, '_column_' . $column_name ),
326
- $item,
327
- $classes,
328
- $data,
329
- $primary
330
- );
331
- } elseif ( method_exists( $this, 'column_' . $column_name ) ) {
332
- echo "<td $attributes>";
333
- echo call_user_func( array( $this, 'column_' . $column_name ), $item );
334
- echo "</td>";
335
- } else {
336
- echo "<td $attributes>";
337
- echo $this->column_default( $item, $column_name );
338
- echo "</td>";
339
- }
340
- }
341
- }
342
-
343
- public function detailRow( $item ) {
344
-
345
- ?>
346
- <td colspan="<?php echo count( $this->get_columns() ) ?>">
347
- <div class="sui-box">
348
- <div class="sui-box-body">
349
- <div class="sui-row">
350
- <div class="sui-col">
351
- <p><strong><?php _e( "Description", "defender-security" ) ?></strong></p>
352
- <p><?php
353
- echo $item->get_log_text();
354
- ?></p>
355
- </div>
356
- <div class="sui-col">
357
- <p><strong><?php _e( "Type", "defender-security" ) ?></strong></p>
358
- <p>
359
- <a href=""><?php echo in_array( $item->type, array(
360
- Log_Model::ERROR_404,
361
- Log_Model::ERROR_404_IGNORE,
362
- Log_Model::LOCKOUT_404
363
- ) ) ? __( "404 error", "defender-security" ) : __( "Login failed", "defender-security" ) ?></a>
364
- </p>
365
- </div>
366
- </div>
367
- <div class="sui-row">
368
- <div class="sui-col">
369
- <p><strong><?php _e( "IP", "defender-security" ) ?></strong></p>
370
- <p><a href=""><?php
371
- echo $item->ip
372
- ?></a></p>
373
- </div>
374
- <div class="sui-col">
375
- <p><strong><?php _e( "Date/Time", "defender-security" ) ?></strong></p>
376
- <p><?php
377
- echo Utils::instance()->formatDateTime( $item->date )
378
- ?></p>
379
- </div>
380
- <div class="sui-col">
381
- <p><strong><?php _e( "Ban Status", "defender-security" ) ?></strong></p>
382
- <p><?php
383
- echo Login_Protection_Api::getIPStatusText( $item->ip )
384
- ?></p>
385
- </div>
386
- </div>
387
- <div class="sui-border-frame">
388
- <div>
389
- <?php
390
- echo Login_Protection_Api::getLogsActionsText( $item );
391
- ?>
392
- </div>
393
- <p>
394
- <?php _e( "Note: Make sure this IP is not a legitimate operation, banning the IP will result in being permanently locked out from accessing your website.", "defender-security" ) ?>
395
- </p>
396
- </div>
397
- </div>
398
- </div>
399
- </td>
400
- <?php
401
- }
402
-
403
- protected function display_tablenav( $which ) {
404
- ?>
405
- <div class="sui-row">
406
- <div class="sui-col-md-5">
407
- <?php if ( $which == 'top' ): ?>
408
- <small class="font-heavy"><?php _e( "Date range", "defender-security" ) ?></small>
409
- <div class="sui-date">
410
- <i class="sui-icon-calendar" aria-hidden="true"></i>
411
- <input name="date_from" id="wd_range_from" type="text"
412
- class="sui-form-control filterable"
413
- value="<?php echo esc_attr( $this->from . ' - ' . $this->to ) ?>">
414
- </div>
415
- <?php endif; ?>
416
- </div>
417
- <div class="sui-col">
418
- <div class="sui-pagination-wrap">
419
- <span class="sui-pagination-results">
420
- <?php printf( __( "%s results", "defender-security" ), $this->_pagination_args['total_items'] ) ?>
421
- </span>
422
- <ul class="sui-pagination">
423
- <?php $this->pagination( 'top' ) ?>
424
- </ul>
425
- <button rel="show-filter" data-target=".lockout-logs-filter"
426
- class="sui-button-icon sui-button-outlined sui-pagination-open-filter">
427
- <i class="sui-icon-filter" aria-hidden="true"></i>
428
- <span class="sui-screen-reader-text">Open search filters</span>
429
- </button>
430
- </div>
431
- </div>
432
- </div>
433
- <div class="sui-row">
434
- <div class="sui-col">
435
- <form id="bulk-action" class="ip-frm" method="post">
436
- <div class="bulk-action-bar">
437
- <label class="sui-checkbox apply-all">
438
- <input type="checkbox" id="apply-all"/>
439
- <span aria-hidden="true"></span>
440
- </label>
441
- <select name="type" class="sui-select-sm">
442
- <option value=""><?php _e( "Bulk action", "defender-security" ) ?></option>
443
- <option value="ban"><?php _e( "Ban", "defender-security" ) ?></option>
444
- <option value="whitelist"><?php _e( "Allowlist", "defender-security" ) ?></option>
445
- <option value="delete"><?php _e( "Delete", "defender-security" ) ?></option>
446
- </select>
447
- <input type="hidden" name="ids" class="ids"/>
448
- <input type="hidden" name="action" value="bulkAction"/>
449
- <?php wp_nonce_field( 'bulkAction' ) ?>
450
- <button type="submit" class="sui-button">
451
- <?php _e( "Bulk Update", "defender-security" ) ?>
452
- </button>
453
- </div>
454
- </form>
455
- </div>
456
- </div>
457
- <?php
458
- }
459
-
460
- /**
461
- * @param string $which
462
- */
463
- protected function pagination( $which ) {
464
- if ( empty( $this->_pagination_args ) ) {
465
- return;
466
- }
467
-
468
- $total_items = $this->_pagination_args['total_items'];
469
- $total_pages = $this->_pagination_args['total_pages'];
470
-
471
- if ( $total_items == 0 ) {
472
- return;
473
- }
474
-
475
- if ( $total_pages < 2 ) {
476
- return;
477
- }
478
-
479
- $links = array();
480
- $current_page = $this->get_pagenum();
481
- /**
482
- * if pages less than 7, display all
483
- * if larger than 7 we will get 3 previous page of current, current, and .., and, and previous, next, first, last links
484
- */
485
- $current_url = set_url_scheme( 'http://' . parse_url( get_site_url(), PHP_URL_HOST ) . $_SERVER['REQUEST_URI'] );
486
- $current_url = remove_query_arg( array( 'hotkeys_highlight_last', 'hotkeys_highlight_first' ), $current_url );
487
- $current_url = esc_url( $current_url );
488
-
489
- $radius = 2;
490
- if ( $current_page > 1 && $total_pages > $radius ) {
491
- $links['prev'] = sprintf( '<li><a data-paged="%s" class="lockout-nav " href="%s">%s</a></li>', $current_page - 1,
492
- add_query_arg( 'paged', $current_page - 1, $current_url ), '<i class="sui-icon-chevron-left" aria-hidden="true"></i>' );
493
- }
494
-
495
- for ( $i = 1; $i <= $total_pages; $i ++ ) {
496
- if ( ( $i >= 1 && $i <= $radius ) || ( $i > $current_page - 2 && $i < $current_page + 2 ) || ( $i <= $total_pages && $i > $total_pages - $radius ) ) {
497
- if ( $i == $current_page ) {
498
- $links[ $i ] = sprintf( '<li><a class="lockout-nav" href="#" data-paged="%s" disabled="">%s</a></li>', $i, $i );
499
- } else {
500
- $links[ $i ] = sprintf( '<li><a class="lockout-nav" data-paged="%s" href="%s">%s</a></li>', $i,
501
- add_query_arg( 'paged', $i, $current_url ), $i );
502
- }
503
- } elseif ( $i == $current_page - $radius || $i == $current_page + $radius ) {
504
- $links[ $i ] = '<li><a class="lockout-nav " href="#" disabled="">...</a></li>';
505
- }
506
- }
507
-
508
- if ( $current_page < $total_pages && $total_pages > $radius ) {
509
- $links['next'] = sprintf( '<li><a class="lockout-nav " data-paged="%s" href="%s">%s</a></li>', $current_page + 1,
510
- add_query_arg( 'paged', $current_page + 1, $current_url ), '<i class="sui-icon-chevron-right" aria-hidden="true"></i>' );
511
- }
512
- $output = join( "\n", $links );
513
- $this->_pagination = $output;
514
-
515
- echo $this->_pagination;
516
- }
517
-
518
- public function print_column_headers( $with_id = true ) {
519
- list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();
520
-
521
- $current_url = network_admin_url( 'admin.php?page=wdf-ip-lockout&view=logs' );
522
-
523
- if ( isset( $_GET['orderby'] ) ) {
524
- $current_orderby = $_GET['orderby'];
525
- } else {
526
- $current_orderby = '';
527
- }
528
-
529
- if ( isset( $_GET['order'] ) && 'desc' === $_GET['order'] ) {
530
- $current_order = 'desc';
531
- } else {
532
- $current_order = 'asc';
533
- }
534
-
535
- if ( ! empty( $columns['cb'] ) ) {
536
- static $cb_counter = 1;
537
- $columns['cb'] = '<label class="screen-reader-text" for="cb-select-all-' . $cb_counter . '">' . __( 'Select All' ) . '</label>'
538
- . '<input id="cb-select-all-' . $cb_counter . '" type="checkbox" />';
539
- $cb_counter ++;
540
- }
541
-
542
- foreach ( $columns as $column_key => $column_display_name ) {
543
- $class = array( 'manage-column', "column-$column_key" );
544
-
545
- if ( in_array( $column_key, $hidden ) ) {
546
- $class[] = 'hidden';
547
- }
548
-
549
- if ( 'cb' === $column_key ) {
550
- $class[] = 'check-column';
551
- } elseif ( in_array( $column_key, array( 'posts', 'comments', 'links' ) ) ) {
552
- $class[] = 'num';
553
- }
554
-
555
- if ( $column_key === $primary ) {
556
- $class[] = 'column-primary';
557
- }
558
-
559
- if ( isset( $sortable[ $column_key ] ) ) {
560
- list( $orderby, $desc_first ) = $sortable[ $column_key ];
561
-
562
- if ( $current_orderby === $orderby ) {
563
- $order = 'asc' === $current_order ? 'desc' : 'asc';
564
- $class[] = 'sorted';
565
- $class[] = $current_order;
566
- } else {
567
- $order = $desc_first ? 'desc' : 'asc';
568
- $class[] = 'sortable';
569
- $class[] = $desc_first ? 'asc' : 'desc';
570
- }
571
-
572
- $column_display_name = '<a href="' . esc_url( add_query_arg( compact( 'orderby', 'order' ), $current_url ) ) . '"><span>' . $column_display_name . '</span><span class="sorting-indicator"></span></a>';
573
- }
574
-
575
- $tag = ( 'cb' === $column_key ) ? 'td' : 'th';
576
- $scope = ( 'th' === $tag ) ? 'scope="col"' : '';
577
- $id = $with_id ? "id='$column_key'" : '';
578
-
579
- if ( ! empty( $class ) ) {
580
- $class = "class='" . join( ' ', $class ) . "'";
581
- }
582
-
583
- echo "<$tag $scope $id $class>$column_display_name</$tag>";
584
- }
585
- }
586
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/ip-lockout/component/notfound-listener.php DELETED
@@ -1,203 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\IP_Lockout\Component;
7
-
8
- use WP_Defender\Behavior\Utils;
9
- use WP_Defender\Controller;
10
- use WP_Defender\Module\IP_Lockout\Model\IP_Model;
11
- use WP_Defender\Module\IP_Lockout\Model\Log_Model;
12
- use WP_Defender\Module\IP_Lockout\Model\Settings;
13
-
14
- class Notfound_Listener extends Controller {
15
- public function __construct() {
16
- if ( Settings::instance()->detect_404 ) {
17
- $this->addAction( 'template_redirect', 'record404' );
18
- }
19
- }
20
-
21
- public function record404() {
22
- if ( ! is_404() ) {
23
- return;
24
- }
25
-
26
- if ( is_user_logged_in() && current_user_can( 'edit_posts' ) ) {
27
- //only track subscriber
28
- return;
29
- }
30
-
31
- //now check if this from google
32
- if ( Login_Protection_Api::isGoogleUA() && Login_Protection_Api::isGoogleIP( Utils::instance()->getUserIp() ) ) {
33
- return;
34
- }
35
-
36
- //or bing
37
- if ( Login_Protection_Api::isBingUA() && Login_Protection_Api::isBingIP( Utils::instance()->getUserIp() ) ) {
38
- return;
39
- }
40
-
41
- $settings = Settings::instance();
42
- if ( $settings->detect_404_logged == false && is_user_logged_in() ) {
43
- return;
44
- }
45
-
46
- $uri = $_SERVER['REQUEST_URI'];
47
-
48
- /**
49
- * Priorities
50
- * - Whitelist
51
- * extensions
52
- * files & folders
53
- * - Blacklist
54
- * extensions
55
- * files & folders
56
- * - attemps inside a window
57
- */
58
-
59
- $ext = pathinfo( $uri, PATHINFO_EXTENSION );
60
- if ( in_array( '.' . $ext, $settings->getDetect404IgnoredFiletypes() ) ) {
61
- //ext is whitelist, log and return
62
- $this->log( $uri, Log_Model::ERROR_404_IGNORE, sprintf( __( "Request for file %s which doesn't exist", "defender-security" ), $uri ) );
63
-
64
- return;
65
- }
66
- foreach ( $settings->get404Whitelist() as $pattern ) {
67
- $pattern = preg_quote( $pattern, '/' );
68
- if ( preg_match( '/' . $pattern . '$/', $uri ) ) {
69
- //whitelisted, just log and return
70
- return;
71
- }
72
- }
73
- $model = IP_Model::init();
74
- if ( in_array( '.' . $ext, $settings->getDetect404FiletypesBlacklist() ) ) {
75
- //block it
76
- $this->lock( $model, 'blacklist', $uri );
77
- $this->log(
78
- $uri,
79
- Log_Model::LOCKOUT_404,
80
- sprintf( __( 'Lockout occurred: Too many 404 requests for %s', "defender-security" ), $uri )
81
- );
82
-
83
- return;
84
- }
85
-
86
- foreach ( $settings->getDetect404Blacklist() as $pattern ) {
87
- $pattern = preg_quote( $pattern, '/' );
88
- if ( preg_match( '/' . $pattern . '$/', $uri ) ) {
89
- $this->lock( $model, 'blacklist', $uri );
90
- $this->log(
91
- $uri,
92
- Log_Model::LOCKOUT_404,
93
- sprintf( __( 'Lockout occurred: Too many 404 requests for %s', "defender-security" ), $uri )
94
- );
95
-
96
- return;
97
- }
98
- }
99
-
100
- $this->log(
101
- $uri,
102
- Log_Model::ERROR_404,
103
- sprintf( __( "Request for file %s which doesn't exist", "defender-security" ), $uri )
104
- );
105
- //now we need to count the attempt
106
- $window = strtotime( '- ' . $settings->detect_404_timeframe . ' seconds', time() );
107
- if ( $window < $model->lock_time ) {
108
- $window = $model->lock_time;
109
- }
110
- $attempts = Log_Model::count( [
111
- 'ip' => Utils::instance()->getUserIp(),
112
- 'type' => Log_Model::ERROR_404,
113
- 'date' => [ 'compare' => '>', 'value' => $window ]
114
- ] );
115
-
116
- if ( $attempts >= $settings->detect_404_threshold ) {
117
- //lock it
118
- $this->lock( $model, 'normal', $uri );
119
- $this->log(
120
- $uri,
121
- Log_Model::LOCKOUT_404,
122
- sprintf( __( 'Lockout occurred: Too many 404 requests for %s' ), $uri )
123
- );
124
- }
125
- }
126
-
127
- /**
128
- * @param IP_Model $model
129
- * @param $scenario
130
- * @param $uri
131
- */
132
- private function lock( IP_Model $model, $scenario = 'normal', $uri = '' ) {
133
- $settings = Settings::instance();
134
- if ( $settings->detect_404_lockout_ban == true ) {
135
- $scenario = 'blacklist';
136
- }
137
- $model->status = IP_Model::STATUS_BLOCKED;
138
- $model->lock_time = time();
139
- if ( $scenario == 'blacklist' ) {
140
- $model->release_time = strtotime( '+5 years', time() );
141
- } else {
142
- $model->release_time = strtotime( '+ ' . $settings->detect_404_lockout_duration . ' ' . $settings->detect_404_lockout_duration_unit );
143
- }
144
- $model->lockout_message = $settings->detect_404_lockout_message;
145
- $model->save();
146
- if ( $scenario == 'blacklist' ) {
147
- $settings->addIpToList( $model->ip, 'blocklist' );
148
- }
149
- $model->lock_time = time();
150
-
151
- do_action( 'wd_404_lockout', $model, $scenario );
152
- //Only ip_lockout_notification is enabled
153
- if ( isset( $settings->ip_lockout_notification ) && $settings->ip_lockout_notification ) {
154
- $this->email($model, $uri);
155
- }
156
- }
157
-
158
- /**
159
- * @param $uri
160
- * @param $scenario
161
- */
162
- private function log( $uri, $scenario, $text ) {
163
- $log = new Log_Model();
164
- $log->ip = Utils::instance()->getUserIp();
165
- $log->user_agent = isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : null;
166
- $log->log = $text;
167
- $log->date = time();
168
- $log->type = $scenario;
169
- $log->tried = $uri;
170
- $log->save();
171
- }
172
-
173
- /**
174
- * @param IP_Model $model
175
- * @param $uri
176
- */
177
- private function email( IP_Model $model, $uri ) {
178
- $settings = Settings::instance();
179
- Utils::instance()->log( 'Check to send 404 notification' );
180
- if ( ! Login_Protection_Api::maybeSendNotification( '404', $model, $settings ) ) {
181
- return;
182
- }
183
- Utils::instance()->log( 'Allow to send 404 notification' );
184
- $isBlacklisted = $settings->isBlacklist( $model->ip );
185
- Utils::instance()->log( sprintf( 'Recipients %d', count( $settings->receipts ) ) );
186
- Utils::instance()->log( $uri );
187
- foreach ( $settings->receipts as $item ) {
188
- $content = $this->renderPartial( $isBlacklisted == true ? 'emails/404-ban' : 'emails/404-lockout', array(
189
- 'admin' => $item['first_name'],
190
- 'ip' => $model->ip,
191
- 'uri' => $uri
192
- ), false );
193
- $no_reply_email = "noreply@" . parse_url( get_site_url(), PHP_URL_HOST );
194
- $no_reply_email = apply_filters( 'wd_lockout_noreply_email', $no_reply_email );
195
- $headers = array(
196
- 'From: Defender <' . $no_reply_email . '>',
197
- 'Content-Type: text/html; charset=UTF-8'
198
- );
199
- $ret = wp_mail( $item['email'], sprintf( __( "404 lockout alert for %s", "defender-security" ), network_site_url() ), $content, $headers );
200
- Utils::instance()->log( sprintf( 'Mail send result :%s', var_export( $ret, true ) ) );
201
- }
202
- }
203
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/ip-lockout/controller/main.php DELETED
@@ -1,467 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\IP_Lockout\Controller;
7
-
8
- use Hammer\Helper\HTTP_Helper;
9
- use Hammer\Helper\WP_Helper;
10
- use WP_Defender\Behavior\Utils;
11
- use WP_Defender\Controller;
12
- use WP_Defender\Module\IP_Lockout\Component\IP_API;
13
- use WP_Defender\Module\IP_Lockout\Component\Login_Listener;
14
- use WP_Defender\Module\IP_Lockout\Component\Login_Protection_Api;
15
- use WP_Defender\Module\IP_Lockout\Component\Notfound_Listener;
16
- use WP_Defender\Module\IP_Lockout\Model\IP_Model;
17
- use WP_Defender\Module\IP_Lockout\Model\Log_Model;
18
- use WP_Defender\Module\IP_Lockout\Model\Settings;
19
-
20
- class Main extends Controller {
21
- protected $slug = 'wdf-ip-lockout';
22
-
23
- /**
24
- * @return array
25
- */
26
- public function behaviors() {
27
- $behaviors = array(
28
- 'utils' => '\WP_Defender\Behavior\Utils',
29
- 'endpoints' => '\WP_Defender\Behavior\Endpoint',
30
- 'wpmudev' => '\WP_Defender\Behavior\WPMUDEV'
31
- );
32
- if ( wp_defender()->isFree == false ) {
33
- $behaviors['pro'] = '\WP_Defender\Module\IP_Lockout\Behavior\Pro\Reporting';
34
- }
35
-
36
- return $behaviors;
37
- }
38
-
39
- public function __construct() {
40
- $this->maybeLockouts();
41
-
42
- if ( $this->isNetworkActivate( wp_defender()->plugin_slug ) ) {
43
- $this->addAction( 'network_admin_menu', 'adminMenu' );
44
- } else {
45
- $this->addAction( 'admin_menu', 'adminMenu' );
46
- }
47
-
48
- if ( $this->isInPage() || $this->isDashboard() ) {
49
- $this->addAction( 'defender_enqueue_assets', 'scripts', 11 );
50
- }
51
-
52
- $this->maybeExport();
53
-
54
- if ( ! Login_Protection_Api::checkIfTableExists() ) {
55
- //no table logs, omething happen
56
- return;
57
- }
58
-
59
- $ip = $this->getUserIp();
60
- $settings = Settings::instance();
61
- if ( $settings->report && $this->hasMethod( 'lockoutReportCron' ) ) {
62
- //report
63
- $this->addAction( 'lockoutReportCron', 'lockoutReportCron' );
64
- }
65
-
66
- //cron for cleanup
67
- $nextCleanup = wp_next_scheduled( 'cleanUpOldLog' );
68
- if ( $nextCleanup === false || $nextCleanup > strtotime( '+90 minutes' ) ) {
69
- wp_clear_scheduled_hook( 'cleanUpOldLog' );
70
- wp_schedule_event( time(), 'hourly', 'cleanUpOldLog' );
71
- }
72
-
73
- $this->addAction( 'cleanUpOldLog', 'cleanUpOldLog' );
74
-
75
- if ( $settings->isWhitelist( $ip ) ) {
76
- return;
77
- }
78
-
79
- $arr = $this->defaultWhiteListIps();
80
-
81
- if ( in_array( $ip, $arr ) ) {
82
- return;
83
- }
84
-
85
- $loginListener = new Login_Listener();
86
- $notfoundListener = new Notfound_Listener();
87
- }
88
-
89
- private function defaultWhiteListIps() {
90
- return apply_filters( 'ip_lockout_default_whitelist_ip', array(
91
- '192.241.148.185',
92
- '104.236.132.222',
93
- '192.241.140.159',
94
- '192.241.228.89',
95
- '198.199.88.192',
96
- '54.197.28.242',
97
- '54.221.174.186',
98
- '54.236.233.244',
99
- '18.204.159.253',
100
- '66.135.60.59',
101
- '34.196.51.17',
102
- '52.57.5.20',
103
- '127.0.0.1',
104
- array_key_exists( 'SERVER_ADDR', $_SERVER ) ? $_SERVER['SERVER_ADDR'] : ( isset( $_SERVER['LOCAL_ADDR'] ) ? $_SERVER['LOCAL_ADDR'] : null )
105
- ) );
106
- }
107
-
108
- /**
109
- * Determine if an ip get lockout or not
110
- */
111
- public function maybeLockouts() {
112
- do_action( 'wd_before_lockout' );
113
- $settings = Settings::instance();
114
- $isTest = HTTP_Helper::retrieveGet( 'def-lockout-demo', false ) == 1;
115
- if ( $isTest ) {
116
- $message = null;
117
- $type = HTTP_Helper::retrieveGet( 'type' );
118
- switch ( $type ) {
119
- case 'login':
120
- $message = $settings->login_protection_lockout_message;
121
- break;
122
- case '404':
123
- $message = $settings->detect_404_lockout_message;
124
- break;
125
- case 'blocklist':
126
- $message = $settings->ip_lockout_message;
127
- break;
128
- default:
129
- $message = __( "Demo", "defender-security" );
130
- }
131
- $this->renderPartial( 'locked', array(
132
- 'message' => $message
133
- ) );
134
- die;
135
- }
136
-
137
- $ip = $this->getUserIp();
138
- $arr = $this->defaultWhiteListIps();
139
- $cache = WP_Helper::getCache();
140
- $temp_whitelist = $cache->get( 'staff_ips', [] );
141
- if ( $this->listenToStaffAccess() ) {
142
- //tmp whitelist this ip till the access end
143
- $temp_whitelist[] = $ip;
144
- $temp_whitelist = array_unique( $temp_whitelist );
145
- $temp_whitelist = array_filter( $temp_whitelist );
146
- $cache->set( 'staff_ips', $temp_whitelist, DAY_IN_SECONDS );
147
- Utils::instance()->log( sprintf( 'Temporary allowlist ip %s', $ip ), 'lockout' );
148
- }
149
- $arr = array_merge( $arr, $temp_whitelist );
150
-
151
- if ( in_array( $ip, $arr ) ) {
152
- return;
153
- }
154
-
155
- if ( $settings->isWhitelist( $ip ) ) {
156
- return;
157
- } elseif ( $settings->isBlacklist( $ip ) ) {
158
- if ( ! defined( 'DONOTCACHEPAGE' ) ) {
159
- define( 'DONOTCACHEPAGE', true );
160
- }
161
- header( 'HTTP/1.0 403 Forbidden' );
162
- header( 'Cache-Control: private' );
163
- $this->renderPartial( 'locked', array(
164
- 'message' => $settings->ip_lockout_message
165
- ) );
166
- die;
167
- } elseif ( $settings->isCountryBlacklist() ) {
168
- if ( ! defined( 'DONOTCACHEPAGE' ) ) {
169
- define( 'DONOTCACHEPAGE', true );
170
- }
171
- header( 'HTTP/1.0 403 Forbidden' );
172
- header( 'Cache-Control: private' );
173
- $this->renderPartial( 'locked', array(
174
- 'message' => $settings->ip_lockout_message
175
- ) );
176
- die;
177
- } else {
178
- if ( $settings->detect_404_logged == false && is_user_logged_in() ) {
179
- /**
180
- * We don't need to check the IP if:
181
- * the current user can logged in and no blacklisted,
182
- * the option detect_404_logged is disabled
183
- */
184
- return;
185
- }
186
-
187
- $model = IP_Model::findOne( array(
188
- 'ip' => $ip
189
- ) );
190
- if ( is_object( $model ) && $model->is_locked() ) {
191
- if ( ! defined( 'DONOTCACHEPAGE' ) ) {
192
- define( 'DONOTCACHEPAGE', true );
193
- }
194
- header( 'HTTP/1.0 403 Forbidden' );
195
- header( 'Cache-Control: private' );
196
- $this->renderPartial( 'locked', array(
197
- 'message' => $model->lockout_message
198
- ) );
199
- die;
200
- }
201
- }
202
- }
203
-
204
- public function listenToStaffAccess() {
205
- if ( defined( 'WPMUDEV_DISABLE_REMOTE_ACCESS' ) && constant( 'WPMUDEV_DISABLE_REMOTE_ACCESS' ) == true ) {
206
- return false;
207
- }
208
- if ( class_exists( 'WPMUDEV_Dashboard' ) && Utils::instance()->getAPIKey() && isset( $_REQUEST['wdpunkey'] ) ) {
209
- $access = \WPMUDEV_Dashboard::$site->get_option( 'remote_access' );
210
- Utils::instance()->log( var_export( $access, true ), 'settings' );
211
-
212
- return hash_equals( $_REQUEST['wdpunkey'], $access['key'] );
213
- }
214
-
215
- return false;
216
- }
217
-
218
- /**
219
- * cron for delete old log
220
- */
221
- public function cleanUpOldLog() {
222
- $timestamp = Utils::instance()->localToUtc( apply_filters( 'ip_lockout_logs_store_backward', '-' . Settings::instance()->storage_days . ' days' ) );
223
- Log_Model::deleteAll( array(
224
- 'date' => array(
225
- 'compare' => '<=',
226
- 'value' => $timestamp
227
- ),
228
- ), '0,1000' );
229
- }
230
-
231
- /**
232
- * After each log recorded, we will check if the threshold is met for a lockout
233
- *
234
- * @param Log_Model $log
235
- */
236
- public function updateIpStats( Log_Model $log ) {
237
-
238
- if ( $log->type == Log_Model::AUTH_FAIL ) {
239
- Login_Protection_Api::maybeLock( $log );
240
- } elseif ( $log->type == Log_Model::ERROR_404 ) {
241
- Login_Protection_Api::maybe404Lock( $log );
242
- }
243
- }
244
-
245
- /**
246
- * listener to process export Ips request
247
- */
248
- public function maybeExport() {
249
- if ( HTTP_Helper::retrieveGet( 'page' ) == 'wdf-ip-lockout' && HTTP_Helper::retrieveGet( 'view' ) == 'export' ) {
250
- if ( ! $this->checkPermission() ) {
251
- return;
252
- }
253
-
254
- if ( ! wp_verify_nonce( HTTP_Helper::retrieveGet( '_wpnonce' ), 'exportIPs' ) ) {
255
- return;
256
- }
257
- $setting = Settings::instance();
258
- $data = array();
259
- foreach ( $setting->getIpBlacklist() as $ip ) {
260
- $data[] = array(
261
- 'ip' => $ip,
262
- 'type' => 'blocklist'
263
- );
264
- }
265
- foreach ( $setting->getIpWhitelist() as $ip ) {
266
- $data[] = array(
267
- 'ip' => $ip,
268
- 'type' => 'allowlist'
269
- );
270
- }
271
- $fp = fopen( 'php://memory', 'w' );
272
- foreach ( $data as $fields ) {
273
- fputcsv( $fp, $fields );
274
- }
275
- $filename = 'wdf-ips-export-' . date( 'ymdHis' ) . '.csv';
276
- fseek( $fp, 0 );
277
- header( 'Content-Type: text/csv' );
278
- header( 'Content-Disposition: attachment; filename="' . $filename . '";' );
279
- // make php send the generated csv lines to the browser
280
- fpassthru( $fp );
281
- exit();
282
- }
283
- }
284
-
285
- /**
286
- * Add submit admin page
287
- */
288
- public function adminMenu() {
289
- $cap = is_multisite() ? 'manage_network_options' : 'manage_options';
290
- $action = "actionIndex";
291
- add_submenu_page( 'wp-defender', esc_html__( "Firewall", "defender-security" ), esc_html__( "Firewall", "defender-security" ), $cap, $this->slug, array(
292
- &$this,
293
- $action
294
- ) );
295
- }
296
-
297
- /**
298
- * queue scripts
299
- */
300
- public function scripts() {
301
- if ( $this->isInPage() ) {
302
- wp_enqueue_style( 'wpmudev-sui' );
303
- wp_enqueue_style( 'defender' );
304
- wp_register_script( 'defender-iplockout', wp_defender()->getPluginUrl() . 'assets/app/ip-lockout.js', array(
305
- 'def-vue',
306
- 'defender',
307
- 'wp-i18n'
308
- ), wp_defender()->version, true );
309
- //wp_register_script( 'iplockout', wp_defender()->getPluginUrl() . 'front/js/src/lockout.js', array(), wp_defender()->version, true );
310
- wp_set_script_translations( 'defender-iplockout', 'wpdef' );
311
- wp_localize_script( 'defender-iplockout', 'iplockout', $this->_scriptsData() );
312
- Utils::instance()->createTranslationJson( 'defender-iplockout' );
313
- wp_set_script_translations( 'defender-iplockout', 'wpdef', wp_defender()->getPluginPath() . 'languages' );
314
-
315
- wp_enqueue_media();
316
- wp_enqueue_script( 'def-momentjs', wp_defender()->getPluginUrl() . 'assets/js/vendor/moment/moment.min.js' );
317
- // wp_enqueue_style( 'def-daterangepicker', wp_defender()->getPluginUrl() . 'assets/js/vendor/daterangepicker/daterangepicker.css' );
318
- wp_enqueue_script( 'def-daterangepicker', wp_defender()->getPluginUrl() . 'assets/js/vendor/daterangepicker/daterangepicker.js' );
319
- wp_enqueue_script( 'defender-iplockout' );
320
- wp_enqueue_script( 'wpmudev-sui' );
321
- }
322
- }
323
-
324
- /**
325
- * Define all the data passing to view layer
326
- * @return array
327
- * @since 2.2
328
- */
329
- private function _scriptsData() {
330
- if ( ! $this->checkPermission() ) {
331
- return [];
332
- }
333
- $summaryData = Log_Model::getSummary();
334
- $model = Settings::instance()->export( array( 'cache', 'geoIP_db' ) );
335
- //base on view we will filter out the model data
336
- $model['country_blacklist'] = Settings::instance()->getCountryBlacklist();
337
- $model['country_whitelist'] = Settings::instance()->getCountryWhitelist();
338
- $host = parse_url( get_site_url(), PHP_URL_HOST );
339
- $host = str_replace( 'www.', '', $host );
340
- $host = explode( '.', $host );
341
- if ( is_array( $host ) ) {
342
- $host = array_shift( $host );
343
- } else {
344
- $host = null;
345
- }
346
- $settings = Settings::instance();
347
- $tz = get_option( 'gmt_offset' );
348
- if ( substr( $tz, 0, 1 ) == '-' ) {
349
- $tz = ' - ' . str_replace( '-', '', $tz );
350
- } else {
351
- $tz = ' + ' . $tz;
352
- }
353
- $current_country = IP_API::getCurrentCountry();
354
- $data = [
355
- 'nonces' => [
356
- 'fetchSummary' => wp_create_nonce( 'fetchSummary' ),
357
- 'updateSettings' => wp_create_nonce( 'updateSettings' ),
358
- 'downloadGeoDB' => wp_create_nonce( 'downloadGeoDB' ),
359
- 'importIPs' => wp_create_nonce( 'importIPs' ),
360
- 'exportIPs' => wp_create_nonce( 'exportIPs' ),
361
- 'queryLogs' => wp_create_nonce( 'queryLogs' ),
362
- 'bulkAction' => wp_create_nonce( 'bulkAction' ),
363
- 'toggleIpAction' => wp_create_nonce( 'toggleIpAction' ),
364
- 'emptyLogs' => wp_create_nonce( 'emptyLogs' ),
365
- 'queryLockedIps' => wp_create_nonce( 'queryLockedIps' ),
366
- 'ipAction' => wp_create_nonce( 'ipAction' ),
367
- 'exportAsCsv' => wp_create_nonce( 'exportAsCsv' )
368
- ],
369
- 'endpoints' => $this->getAllAvailableEndpoints( \WP_Defender\Module\IP_Lockout::getClassName() ),
370
- 'whitelabel' => $this->whiteLabelStatus(),
371
- 'highContrast' => $this->maybeHighContrast(),
372
- //'model' => $model,
373
- 'model' => [
374
- 'ip_lockout' => $settings->exportByKeys(
375
- [
376
- 'login_protection',
377
- 'login_protection_login_attempt',
378
- 'login_protection_lockout_timeframe',
379
- 'login_protection_lockout_ban',
380
- 'login_protection_lockout_duration',
381
- 'login_protection_lockout_duration_unit',
382
- 'login_protection_lockout_message',
383
- 'username_blacklist',
384
- ] ),
385
- 'nf_lockout' => $settings->exportByKeys( [
386
- 'detect_404',
387
- 'detect_404_threshold',
388
- 'detect_404_timeframe',
389
- 'detect_404_lockout_ban',
390
- 'detect_404_lockout_duration',
391
- 'detect_404_lockout_duration_unit',
392
- 'detect_404_lockout_message',
393
- 'detect_404_blacklist',
394
- 'detect_404_whitelist',
395
- 'detect_404_filetypes_blacklist',
396
- 'detect_404_ignored_filetypes',
397
- 'detect_404_logged',
398
- ] ),
399
- 'blacklist' => $settings->exportByKeys( [
400
- 'ip_blacklist',
401
- 'ip_whitelist',
402
- 'country_blacklist',
403
- 'country_whitelist',
404
- 'ip_lockout_message',
405
- ] ),
406
- 'notification' => $settings->exportByKeys( [
407
- 'login_lockout_notification',
408
- 'ip_lockout_notification',
409
- 'receipts',
410
- 'cooldown_enabled',
411
- 'cooldown_number_lockout',
412
- 'cooldown_period'
413
- ] ),
414
- 'settings' => $settings->exportByKeys( [
415
- 'storage_days'
416
- ] ),
417
- 'report' => $settings->exportByKeys( [
418
- 'report',
419
- 'report_receipts',
420
- 'report_frequency',
421
- 'report_day',
422
- 'report_time'
423
- ] )
424
- ],
425
- 'summaryData' => [
426
- 'ip' => [
427
- 'day' => $summaryData['loginLockoutToday'],
428
- 'week' => $summaryData['loginLockoutThisWeek'],
429
- ],
430
- 'nf' => [
431
- 'week' => $summaryData['lockout404ThisWeek'],
432
- 'day' => $summaryData['lockout404Today'],
433
- ],
434
- 'month' => $summaryData['lockoutThisMonth'],
435
- 'day' => $summaryData['lockoutToday'],
436
- 'lastLockout' => $summaryData['lastLockout']
437
- ],
438
- 'misc' => [
439
- 'geo_db_downloaded' => Settings::instance()->isGeoDBDownloaded(),
440
- 'current_country' => isset( $current_country['iso'] ) ? $current_country['iso'] : null,
441
- 'blacklist_countries' => array_merge( [ 'all' => __( "Block all", "defender-security" ) ], Utils::instance()->countriesList() ),
442
- 'whitelist_countries' => array_merge( [ 'all' => __( "Allow all", "defender-security" ) ], Utils::instance()->countriesList() ),
443
- 'days_of_weeks' => Utils::instance()->getDaysOfWeek(),
444
- 'times_of_days' => Utils::instance()->getTimes(),
445
- 'host' => $host,
446
- 'user_ip' => Utils::instance()->getUserIp(),
447
- 'geo_requirement' => version_compare( phpversion(), '5.4', '>=' ),
448
- 'tz' => $tz,
449
- 'current_time' => \WP_Defender\Behavior\Utils::instance()->formatDateTime( current_time( 'timestamp' ), false )
450
- ],
451
- 'table' => [
452
- 'date_from' => Http_Helper::retrieveGet( 'date_from', date( 'm/d/Y', strtotime( 'today midnight', strtotime( '-14 days', current_time( 'timestamp' ) ) ) ) ),
453
- 'date_to' => Http_Helper::retrieveGet( 'date_to', date( 'm/d/Y', current_time( 'timestamp' ) ) )
454
- ]
455
- ];
456
-
457
- return $data;
458
- }
459
-
460
- /**
461
- * Internal route
462
- */
463
- public function actionIndex() {
464
-
465
- return $this->render( 'main' );
466
- }
467
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/ip-lockout/controller/rest.php DELETED
@@ -1,450 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\IP_Lockout\Controller;
7
-
8
- use Hammer\Helper\Array_Helper;
9
- use Hammer\Helper\HTTP_Helper;
10
- use Hammer\Helper\WP_Helper;
11
- use WP_Defender\Behavior\Utils;
12
- use WP_Defender\Controller;
13
- use WP_Defender\Module\IP_Lockout;
14
- use WP_Defender\Module\IP_Lockout\Component\Login_Protection_Api;
15
- use WP_Defender\Module\IP_Lockout\Model\Log_Model;
16
- use WP_Defender\Module\IP_Lockout\Model\Settings;
17
-
18
- class Rest extends Controller {
19
- public function __construct() {
20
- $namespace = 'wp-defender/v1';
21
- $namespace .= '/lockout';
22
- $routes = [
23
- $namespace . '/updateSettings' => 'updateSettings',
24
- $namespace . '/downloadGeoDB' => 'downloadGeoDB',
25
- $namespace . '/importIPs' => 'importIPs',
26
- $namespace . '/exportIPs' => 'exportIPs',
27
- $namespace . '/queryLogs' => 'queryLogs',
28
- $namespace . '/bulkAction' => 'bulkAction',
29
- $namespace . '/toggleIpAction' => 'toggleIpAction',
30
- $namespace . '/emptyLogs' => 'emptyLogs',
31
- $namespace . '/queryLockedIps' => 'queryLockedIps',
32
- $namespace . '/ipAction' => 'ipAction',
33
- $namespace . '/exportAsCsv' => 'exportAsCsv'
34
- ];
35
-
36
- $this->registerEndpoints( $routes, IP_Lockout::getClassName() );
37
- }
38
-
39
- /**
40
- * Endpoint for toggle IP status, use in IP Banning->ban IPs
41
- */
42
- public function ipAction() {
43
- if ( ! $this->checkPermission() ) {
44
- return;
45
- }
46
-
47
- if ( ! wp_verify_nonce( HTTP_Helper::retrieveGet( '_wpnonce' ), 'ipAction' ) ) {
48
- return;
49
- }
50
-
51
- $ip = HTTP_Helper::retrievePost( 'ip' );
52
- $action = HTTP_Helper::retrievePost( 'behavior' );
53
- $model = IP_Lockout\Model\IP_Model::findOne( [
54
- 'ip' => $ip
55
- ] );
56
-
57
- if ( is_object( $model ) ) {
58
- if ( $action === 'unban' ) {
59
- $model->status = IP_Lockout\Model\IP_Model::STATUS_NORMAL;
60
- $model->save();
61
- } elseif ( $action === 'ban' ) {
62
- $model->status = IP_Lockout\Model\IP_Model::STATUS_BLOCKED;
63
- $model->save();
64
- }
65
- wp_send_json_success( [ 'data' => '' ] );
66
- }
67
- }
68
-
69
- /**
70
- * Endpoint to query locked IPs, use in IP Banning->ban IPs
71
- */
72
- public function queryLockedIps() {
73
- if ( ! $this->checkPermission() ) {
74
- return;
75
- }
76
-
77
- if ( ! wp_verify_nonce( HTTP_Helper::retrieveGet( '_wpnonce' ), 'queryLockedIps' ) ) {
78
- return;
79
- }
80
-
81
- $results = IP_Lockout\Model\IP_Model::queryLockedIp();
82
-
83
- wp_send_json_success( [
84
- 'ips_locked' => $results,
85
- ] );
86
- }
87
-
88
- /**
89
- * Endpoint for toggle IP blacklist or whitelist, use on logs item content
90
- */
91
- public function toggleIpAction() {
92
- if ( ! $this->checkPermission() ) {
93
- return;
94
- }
95
-
96
- if ( ! wp_verify_nonce( HTTP_Helper::retrieveGet( '_wpnonce' ), 'toggleIpAction' ) ) {
97
- return;
98
- }
99
-
100
- $ip = HTTP_Helper::retrievePost( 'ip', false );
101
- $type = HTTP_Helper::retrievePost( 'type' );
102
- $type = sanitize_key( $type );
103
-
104
- if ( $ip && filter_var( $ip, FILTER_VALIDATE_IP ) ) {
105
- if ( 'unwhitelist' === $type || 'unblacklist' === $type ) {
106
- $type = substr( $type, 2 );
107
- $type = 'whitelist' === $type ? 'allowlist' : 'blocklist';
108
- Settings::instance()->removeIpFromList( $ip, $type );
109
- wp_send_json_success( array(
110
- 'message' => sprintf( __( "IP %s has been removed from your %s. You can control your %s in <a href=\"%s\">IP Lockouts.</a>",
111
- "defender-security" ), $ip, $type, $type,
112
- network_admin_url( 'admin.php?page=wdf-ip-lockout&view=blocklist' ) ),
113
- ) );
114
- } else {
115
- $type = 'whitelist' === $type ? 'allowlist' : 'blocklist';
116
- Settings::instance()->addIpToList( $ip, $type );
117
- wp_send_json_success( array(
118
- 'message' => sprintf( __( "IP %s has been added to your %s You can control your %s in <a href=\"%s\">IP Lockouts.</a>",
119
- "defender-security" ), $ip, $type, $type,
120
- network_admin_url( 'admin.php?page=wdf-ip-lockout&view=blocklist' ) ),
121
- ) );
122
- }
123
-
124
- } else {
125
- wp_send_json_error( array(
126
- 'message' => __( "No record found", "defender-security" )
127
- ) );
128
- }
129
- }
130
-
131
- public function emptyLogs() {
132
- if ( ! $this->checkPermission() ) {
133
- return;
134
- }
135
-
136
- if ( ! wp_verify_nonce( HTTP_Helper::retrieveGet( '_wpnonce' ), 'emptyLogs' ) ) {
137
- return;
138
- }
139
-
140
- $perPage = 500;
141
- $count = Log_Model::deleteAll( array(), '0,' . $perPage );
142
- if ( $count == 0 ) {
143
- wp_send_json_success( array(
144
- 'message' => __( "Your logs have been successfully deleted.", "defender-security" )
145
- ) );
146
- }
147
-
148
- wp_send_json_error( array() );
149
- }
150
-
151
- /**
152
- *
153
- */
154
- public function bulkAction() {
155
- if ( ! $this->checkPermission() ) {
156
- return;
157
- }
158
-
159
- if ( ! wp_verify_nonce( HTTP_Helper::retrieveGet( '_wpnonce' ), 'bulkAction' ) ) {
160
- return;
161
- }
162
-
163
- $ids = HTTP_Helper::retrievePost( 'ids', [] );
164
- $type = HTTP_Helper::retrievePost( 'type' );
165
- $messages = '';
166
- $ips = [];
167
- if ( count( $ids ) && $type ) {
168
- $settings = Settings::instance();
169
- switch ( $type ) {
170
- case 'whitelist':
171
- foreach ( $ids as $id ) {
172
- $model = Log_Model::findByID( $id );
173
- $ips[] = $model->ip;
174
- $settings->addIpToList( $model->ip, 'allowlist' );
175
- }
176
- $messages = sprintf( __( "IP %s has been added to your allowlist. You can control your allowlist in <a href=\"%s\">IP Lockouts.</a>",
177
- "defender-security" ), implode( ',', $ips ),
178
- network_admin_url( 'admin.php?page=wdf-ip-lockout&view=blocklist' ) );
179
- break;
180
- case 'ban':
181
- foreach ( $ids as $id ) {
182
- $model = Log_Model::findByID( $id );
183
- $ips[] = $model->ip;
184
- $settings->addIpToList( $model->ip, 'blocklist' );
185
- }
186
- $messages = sprintf( __( "IP %s has been added to your blocklist You can control your blocklist in <a href=\"%s\">IP Lockouts.</a>",
187
- "defender-security" ), implode( ',', $ips ),
188
- network_admin_url( 'admin.php?page=wdf-ip-lockout&view=blocklist' ) );
189
- break;
190
- case 'delete':
191
- foreach ( $ids as $id ) {
192
- $model = Log_Model::findByID( $id );
193
- $ips[] = $model->ip;
194
- $model->delete();
195
- }
196
- $messages = sprintf( __( "IP %s has been deleted", "defender-security" ), implode( ',', $ips ) );
197
- break;
198
- default:
199
- //param not from the button on frontend, log it
200
- //error_log( sprintf( 'Unexpected value %s from IP %s', $type, Utils::instance()->getUserIp() ) );
201
- break;
202
- }
203
-
204
- wp_send_json_success( array(
205
- 'reload' => 1,
206
- 'message' => $messages
207
- ) );
208
- }
209
- }
210
-
211
- /**
212
- * Query the data
213
- */
214
- public function queryLogs() {
215
- if ( ! $this->checkPermission() ) {
216
- return;
217
- }
218
-
219
- if ( ! wp_verify_nonce( HTTP_Helper::retrieveGet( '_wpnonce' ), 'queryLogs' ) ) {
220
- return;
221
- }
222
- $data = $_POST;
223
- $filters = [
224
- 'dateFrom' => strtotime( 'midnight', strtotime( Array_Helper::getValue( $data, 'date_from' ) ) ),
225
- 'dateTo' => strtotime( 'tomorrow', strtotime( Array_Helper::getValue( $data, 'date_to' ) ) ),
226
- 'type' => Array_Helper::getValue( $data, 'type', false ),
227
- 'ip' => Array_Helper::getValue( $data, 'ip', false )
228
- ];
229
-
230
- $paged = Array_Helper::getValue( $data, 'paged', 1 );
231
- $orderBy = Array_Helper::getValue( $data, 'orderBy', 'id' );
232
- $order = Array_Helper::getValue( $data, 'order', 'DESC' );
233
-
234
- $pageSize = 20;
235
-
236
- list( $logs, $countAllLogs ) = Log_Model::queryLogs( $filters, $paged, $orderBy, $order, $pageSize );
237
- $ids = [];
238
- foreach ( $logs as $log ) {
239
- $log->date = $log->get_date();
240
- $log->statusText = Login_Protection_Api::getIPStatusText( $log->ip );
241
- $log->ip_status = $log->blackOrWhite();
242
- $log->is_mine = Utils::instance()->getUserIp() == $log->ip;
243
- $ids[] = $log->id;
244
- }
245
- $totalPages = ceil( $countAllLogs / $pageSize );
246
- wp_send_json_success( array(
247
- 'logs' => $logs,
248
- 'countAll' => $countAllLogs,
249
- 'totalPages' => $totalPages
250
- ) );
251
- }
252
-
253
- /**
254
- * Importing IPs from our exporter
255
- */
256
- public function importIPs() {
257
- if ( ! $this->checkPermission() ) {
258
- return;
259
- }
260
-
261
- $id = HTTP_Helper::retrievePost( 'id' );
262
- if ( ! is_object( get_post( $id ) ) ) {
263
- wp_send_json_error( array(
264
- 'message' => __( "Your file is invalid!", "defender-security" )
265
- ) );
266
- }
267
- $file = get_attached_file( $id );
268
-
269
- if ( ! is_file( $file ) ) {
270
- wp_send_json_error( array(
271
- 'message' => __( "Your file is invalid!", "defender-security" )
272
- ) );
273
- }
274
-
275
- if ( ! ( $data = Login_Protection_Api::verifyImportFile( $file ) ) ) {
276
- wp_send_json_error( array(
277
- 'message' => __( "Your file content is invalid!", "defender-security" )
278
- ) );
279
- }
280
-
281
- $settings = Settings::instance();
282
- //all good, start to import
283
-
284
- foreach ( $data as $line ) {
285
- $settings->addIpToList( $line[0], $line[1] );
286
- }
287
- wp_send_json_success( array(
288
- 'message' => __( "Your allowlist/blocklist has been successfully imported.", "defender-security" ),
289
- 'reload' => 1,
290
- 'blacklist' => $settings->getIpBlacklist(),
291
- 'whitelist' => $settings->getIpWhitelist()
292
- ) );
293
- }
294
-
295
- /**
296
- * Downloading GeoDB from maxmind
297
- */
298
- public function downloadGeoDB() {
299
- if ( ! $this->checkPermission() ) {
300
- return;
301
- }
302
-
303
- if ( ! wp_verify_nonce( HTTP_Helper::retrieveGet( '_wpnonce' ), 'downloadGeoDB' ) ) {
304
- return;
305
- }
306
-
307
- $license_key = HTTP_Helper::retrievePost( 'api_key' );
308
- $license_key = sanitize_text_field( $license_key );
309
- $url = "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&license_key=$license_key&suffix=tar.gz";
310
- $tmp = download_url( $url );
311
- if ( ! is_wp_error( $tmp ) ) {
312
- $phar = new \PharData( $tmp );
313
- $defPath = Utils::instance()->getDefUploadDir();
314
- $path = $defPath . DIRECTORY_SEPARATOR . 'maxmind';
315
- if ( ! is_dir( $path ) ) {
316
- mkdir( $path );
317
- }
318
- $phar->extractTo( $path, null, true );
319
- $settings = Settings::instance();
320
- $settings->geoIP_db = $path . DIRECTORY_SEPARATOR . $phar->current()->getFileName() . DIRECTORY_SEPARATOR . 'GeoLite2-Country.mmdb';
321
- $settings->save();
322
- wp_send_json_success( array(
323
- 'message' => __( "Database downloaded", "defender-security" )
324
- ) );
325
- } else {
326
- wp_send_json_error( [
327
- 'message' => $tmp->get_error_message()
328
- ] );
329
- }
330
- }
331
-
332
- /**
333
- * Update IP lockout settings, parameters sent via an ajax _POST request
334
- */
335
- public function updateSettings() {
336
- if ( ! $this->checkPermission() ) {
337
- return;
338
- }
339
-
340
- if ( ! wp_verify_nonce( HTTP_Helper::retrieveGet( '_wpnonce' ), 'updateSettings' ) ) {
341
- return;
342
- }
343
- $settings = Settings::instance();
344
- $lastSettings = clone $settings;
345
- $data = stripslashes( $_POST['data'] );
346
- $data = json_decode( $data, true );
347
-
348
- $settings->import( $data );
349
-
350
- if ( $settings->validate() ) {
351
- $settings->save();
352
- $faultIps = WP_Helper::getArrayCache()->get( 'faultIps', array() );
353
- $isBLSelf = WP_Helper::getArrayCache()->get( 'isBlacklistSelf', false );
354
- if ( $faultIps || $isBLSelf ) {
355
- $res = array(
356
- 'message' => sprintf( __( "Your settings have been updated, however some IPs were removed because invalid format, or you blocklist yourself",
357
- "defender-security" ), implode( ',', $faultIps ) ),
358
- 'reload' => 1
359
- );
360
- } else {
361
- $res = array( 'message' => __( "Your settings have been updated.", "defender-security" ), );
362
- }
363
- if ( ( $lastSettings->login_protection != $settings->login_protection )
364
- || ( $lastSettings->detect_404 != $settings->detect_404 )
365
- ) {
366
- if ( isset( $data['login_protection'] ) ) {
367
- if ( $data['login_protection'] == 1 ) {
368
- $status = __( "Login Protection has been activated.", "defender-security" );
369
- } else {
370
- $status = __( "Login Protection has been deactivated.", "defender-security" );
371
- }
372
- }
373
- if ( isset( $data['detect_404'] ) ) {
374
- if ( $data['detect_404'] == 1 ) {
375
- $status = __( "404 Detection has been activated.", "defender-security" );
376
- } else {
377
- $status = __( "404 Detection has been deactivated.", "defender-security" );
378
- }
379
- }
380
- //mean enabled or disabled, reload
381
- $res['reload'] = 1;
382
- if ( isset( $status ) && strlen( $status ) ) {
383
- $res['message'] = $status;
384
- }
385
- }
386
- if ( $this->hasMethod( 'scheduleReport' ) ) {
387
- $this->scheduleReport();
388
- }
389
- Utils::instance()->submitStatsToDev();
390
- $res['reload'] = 1;
391
- wp_send_json_success( $res );
392
- } else {
393
- wp_send_json_error( array(
394
- 'message' => implode( '<br/>', $settings->getErrors() )
395
- ) );
396
- }
397
- }
398
-
399
- /**
400
- * Csv exporter
401
- */
402
- public function exportAsCsv() {
403
- if ( ! $this->checkPermission() ) {
404
- return;
405
- }
406
-
407
- if ( ! wp_verify_nonce( HTTP_Helper::retrieveGet( '_wpnonce' ), 'exportAsCsv' ) ) {
408
- return;
409
- }
410
- $logs = Log_Model::findAll();
411
- $fp = fopen( 'php://memory', 'w' );
412
- $headers = array(
413
- __( 'Log', "defender-security" ),
414
- __( 'Date / Time', "defender-security" ),
415
- __( 'Type', "defender-security" ),
416
- __( 'IP address', "defender-security" ),
417
- __( 'Status', "defender-security" )
418
- );
419
- fputcsv( $fp, $headers );
420
- foreach ( $logs as $log ) {
421
- $item = array(
422
- $log->log,
423
- $log->get_date(),
424
- $log->get_type(),
425
- $log->ip,
426
- Login_Protection_Api::getIPStatusText( $log->ip )
427
- );
428
- fputcsv( $fp, $item );
429
- }
430
-
431
- $filename = 'wdf-lockout-logs-export-' . date( 'ymdHis' ) . '.csv';
432
- fseek( $fp, 0 );
433
- header( 'Content-Type: text/csv' );
434
- header( 'Content-Disposition: attachment; filename="' . $filename . '";' );
435
- // make php send the generated csv lines to the browser
436
- fpassthru( $fp );
437
- exit();
438
- }
439
-
440
- public function behaviors() {
441
- $behaviors = array(
442
- 'utils' => '\WP_Defender\Behavior\Utils',
443
- );
444
- if ( class_exists( 'WP_Defender\Module\IP_Lockout\Behavior\Pro\Reporting' ) ) {
445
- $behaviors['report'] = 'WP_Defender\Module\IP_Lockout\Behavior\Pro\Reporting';
446
- }
447
-
448
- return $behaviors;
449
- }
450
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/ip-lockout/model/ip-model-legacy.php DELETED
@@ -1,167 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Author: Hoang Ngo
5
- */
6
-
7
- namespace WP_Defender\Module\IP_Lockout\Model;
8
-
9
- use Hammer\WP\Model;
10
- use WP_Defender\Behavior\Utils;
11
-
12
- /**
13
- * Class IP_Model
14
- * @package WP_Defender\Module\IP_Lockout\Model
15
- * @deprecated 1.7
16
- */
17
- class IP_Model_Legacy extends Model {
18
- const STATUS_BLOCKED = 'blocked', STATUS_NORMAL = 'normal';
19
-
20
- static $post_type = 'wd_ip_lockout';
21
-
22
- public $id;
23
- public $ip;
24
- public $status;
25
- public $lockout_message;
26
- public $release_time;
27
- public $lock_time;
28
- public $lock_time_404;
29
- public $attempt;
30
- public $attempt_404;
31
-
32
- protected static function maps() {
33
- return array(
34
- 'id' => array(
35
- 'type' => 'wp',
36
- 'map' => 'ID'
37
- ),
38
- 'ip' => array(
39
- 'type' => 'meta',
40
- 'map' => 'ip'
41
- ),
42
- 'status' => array(
43
- 'type' => 'meta',
44
- 'map' => 'status'
45
- ),
46
- 'lockout_message' => array(
47
- 'type' => 'meta',
48
- 'map' => 'lockout_message'
49
- ),
50
- 'release_time' => array(
51
- 'type' => 'meta',
52
- 'map' => 'release_time'
53
- ),
54
- 'lock_time' => array(
55
- 'type' => 'meta',
56
- 'map' => 'lock_time'
57
- ),
58
- 'lock_time_404' => array(
59
- 'type' => 'meta',
60
- 'map' => 'lock_time_404'
61
- ),
62
- 'attempt' => array(
63
- 'type' => 'meta',
64
- 'map' => 'attempt'
65
- ),
66
- );
67
- }
68
-
69
-
70
- /**
71
- * @return bool
72
- */
73
- public function is_locked() {
74
- if ( $this->status == self::STATUS_BLOCKED ) {
75
- if ( $this->release_time < time() ) {
76
- //unlock it
77
- $this->attempt = 0;
78
- $this->status = self::STATUS_NORMAL;
79
- $this->save();
80
-
81
- return false;
82
- } else {
83
- return true;
84
- }
85
- }
86
-
87
- return false;
88
- }
89
-
90
-
91
- /**
92
- * @return array
93
- */
94
- public function events() {
95
- $that = $this;
96
-
97
- //becase we store all the logs in main blog, so in multisite we need to force to main when saving
98
- return array(
99
- self::EVENT_BEFORE_INSERT => array(
100
- array(
101
- function () use ( $that ) {
102
- if ( Utils::instance()->isActivatedSingle() == false ) {
103
- wp_defender()->global['oldBlog'] = get_current_blog_id();
104
- switch_to_blog( 1 );
105
- }
106
- }
107
- )
108
- ),
109
- self::EVENT_BEFORE_UPDATE => array(
110
- array(
111
- function () use ( $that ) {
112
- if ( Utils::instance()->isActivatedSingle() == false ) {
113
- wp_defender()->global['oldBlog'] = get_current_blog_id();
114
- switch_to_blog( 1 );
115
- }
116
- }
117
- )
118
- ),
119
- self::EVENT_AFTER_INSERT => array(
120
- array(
121
- function () use ( $that ) {
122
- if ( Utils::instance()->isActivatedSingle() == false ) {
123
- if ( isset( wp_defender()->global['oldBlog'] ) ) {
124
- switch_to_blog( wp_defender()->global['oldBlog'] );
125
- unset( wp_defender()->global['oldBlog'] );
126
- }
127
- }
128
- }
129
- )
130
- ),
131
- self::EVENT_AFTER_UPDATE => array(
132
- array(
133
- function () use ( $that ) {
134
- if ( Utils::instance()->isActivatedSingle() == false ) {
135
- if ( isset( wp_defender()->global['oldBlog'] ) ) {
136
- switch_to_blog( wp_defender()->global['oldBlog'] );
137
- unset( wp_defender()->global['oldBlog'] );
138
- }
139
- }
140
- }
141
- )
142
- ),
143
- self::EVENT_BEFORE_DELELTE => array(
144
- array(
145
- function () use ( $that ) {
146
- if ( Utils::instance()->isActivatedSingle() == false ) {
147
- wp_defender()->global['oldBlog'] = get_current_blog_id();
148
- switch_to_blog( 1 );
149
- }
150
- }
151
- )
152
- ),
153
- self::EVENT_AFTER_DELETE => array(
154
- array(
155
- function () use ( $that ) {
156
- if ( Utils::instance()->isActivatedSingle() == false ) {
157
- if ( isset( wp_defender()->global['oldBlog'] ) ) {
158
- switch_to_blog( wp_defender()->global['oldBlog'] );
159
- unset( wp_defender()->global['oldBlog'] );
160
- }
161
- }
162
- }
163
- )
164
- ),
165
- );
166
- }
167
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/ip-lockout/model/ip-model.php DELETED
@@ -1,151 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Author: Hoang Ngo
5
- */
6
-
7
- namespace WP_Defender\Module\IP_Lockout\Model;
8
-
9
- use Hammer\Base\DB_Model;
10
- use WP_Defender\Behavior\Utils;
11
-
12
- class IP_Model extends DB_Model {
13
- const STATUS_BLOCKED = 'blocked', STATUS_NORMAL = 'normal';
14
-
15
- protected static $tableName = 'defender_lockout';
16
-
17
- public $id;
18
- public $ip;
19
- public $status;
20
- public $lockout_message;
21
- public $release_time;
22
- public $lock_time;
23
- public $lock_time_404;
24
- public $attempt;
25
- public $attempt_404;
26
- public $meta;
27
-
28
- /**
29
- * @return bool
30
- */
31
- public function is_locked() {
32
- if ( $this->status == self::STATUS_BLOCKED ) {
33
- if ( $this->release_time < time() ) {
34
- //unlock it
35
- $this->attempt = 0;
36
- $this->status = self::STATUS_NORMAL;
37
- $this->save();
38
-
39
- return false;
40
- } else {
41
- return true;
42
- }
43
- }
44
-
45
- return false;
46
- }
47
-
48
- /**
49
- * Initiaize IP model if not exist, else return the current
50
- * @return IP_Model|null
51
- */
52
- public static function init() {
53
- $model = self::findOne( [ 'ip' => Utils::instance()->getUserIp() ] );
54
- if ( ! is_object( $model ) ) {
55
- $model = new IP_Model();
56
- //create new
57
- $model->ip = Utils::instance()->getUserIp();
58
- $model->status = IP_Model::STATUS_NORMAL;
59
- $model->save();
60
- }
61
-
62
- return $model;
63
- }
64
-
65
- /**
66
- * @param $key
67
- * @param null $default
68
- *
69
- * @return mixed|null
70
- */
71
- public function getMeta( $key, $default = null ) {
72
- $meta = $this->meta;
73
- if ( ! is_array( $meta ) ) {
74
- $meta = maybe_unserialize( $meta );
75
- }
76
-
77
- if ( ! is_array( $meta ) ) {
78
- $meta = array();
79
- }
80
-
81
- if ( isset( $meta[ $key ] ) ) {
82
- return $meta[ $key ];
83
- }
84
-
85
- return $default;
86
- }
87
-
88
- /**
89
- * @param $ip
90
- * @param $paged
91
- *
92
- * @return array
93
- */
94
- public static function queryLockedIp() {
95
- $params = array(
96
- 'status' => IP_Model::STATUS_BLOCKED
97
- );
98
-
99
- $results = IP_Model::findAllOnlyColumns( $params, [
100
- 'id',
101
- 'ip',
102
- 'status'
103
- ], 'lock_time', 'DESC' );
104
-
105
- return $results;
106
- }
107
-
108
- /**
109
- * @param $key
110
- * @param $value
111
- */
112
- public function updateMeta( $key, $value ) {
113
- $meta = $this->meta;
114
- if ( ! is_array( $meta ) ) {
115
- $meta = maybe_unserialize( $meta );
116
- }
117
-
118
- if ( ! is_array( $meta ) ) {
119
- $meta = array();
120
- }
121
-
122
- $meta[ $key ] = $value;
123
- $this->meta = serialize( $meta );
124
- $this->save();
125
- }
126
-
127
- public function events() {
128
- $that = $this;
129
-
130
- return array(
131
- self::EVENT_BEFORE_INSERT => array(
132
- array(
133
- function () use ( $that ) {
134
- if ( is_array( $that->meta ) ) {
135
- $that->meta = serialize( $that->meta );
136
- }
137
- }
138
- )
139
- ),
140
- self::EVENT_BEFORE_UPDATE => array(
141
- array(
142
- function () use ( $that ) {
143
- if ( is_array( $that->meta ) ) {
144
- $that->meta = serialize( $that->meta );
145
- }
146
- }
147
- )
148
- )
149
- );
150
- }
151
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/ip-lockout/model/log-model-legacy.php DELETED
@@ -1,166 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Author: Hoang Ngo
5
- */
6
-
7
- namespace WP_Defender\Module\IP_Lockout\Model;
8
-
9
- use Hammer\Helper\WP_Helper;
10
- use Hammer\WP\Model;
11
- use WP_Defender\Behavior\Utils;
12
- use WP_Defender\Module\IP_Lockout\Component\Login_Protection_Api;
13
- use WP_Defender\Module\IP_Lockout\Component\Logs_Table;
14
-
15
- /**
16
- * Class Log_Model_Legacy
17
- * @package WP_Defender\Module\IP_Lockout\Model
18
- * @deprecated 1.7
19
- */
20
- class Log_Model_Legacy extends Model {
21
- const AUTH_FAIL = 'auth_fail', AUTH_LOCK = 'auth_lock', ERROR_404 = '404_error', LOCKOUT_404 = '404_lockout', ERROR_404_IGNORE = '404_error_ignore';
22
- static $post_type = 'wd_iplockout_log';
23
-
24
- public $id;
25
- public $log;
26
- public $ip;
27
- public $date;
28
- public $user_agent;
29
- public $type;
30
- public $blog_id;
31
-
32
- protected static function maps() {
33
- return array(
34
- 'id' => array(
35
- 'type' => 'wp',
36
- 'map' => 'ID'
37
- ),
38
- 'log' => array(
39
- 'type' => 'meta',
40
- 'map' => 'log'
41
- ),
42
- 'ip' => array(
43
- 'type' => 'meta',
44
- 'map' => 'ip'
45
- ),
46
- 'date' => array(
47
- 'type' => 'meta',
48
- 'map' => 'date'
49
- ),
50
- 'type' => array(
51
- 'type' => 'meta',
52
- 'map' => 'type'
53
- ),
54
- 'user_agent' => array(
55
- 'type' => 'meta',
56
- 'map' => 'user_agent'
57
- ),
58
- 'blog_id' => array(
59
- 'type' => 'meta',
60
- 'map' => 'blog_id'
61
- ),
62
- );
63
- }
64
-
65
- /**
66
- * @return string
67
- */
68
- public function get_ip() {
69
- return esc_html( $this->ip );
70
- }
71
-
72
- /**
73
- * @return string
74
- */
75
- public function get_log_text( $format = false ) {
76
- if ( ! $format ) {
77
- return esc_html( $this->log );
78
- } else {
79
- $text = sprintf( __( "Request for file <span class='log-text-table' tooltip='%s'>%s</span> which doesn't exist", "defender-security" ), esc_attr( $this->log ), pathinfo( $this->log, PATHINFO_BASENAME ) );
80
-
81
- return $text;
82
- }
83
- }
84
-
85
- public function before_update() {
86
- $this->blog_id = get_current_blog_id();
87
- if ( Utils::instance()->isActivatedSingle() == false ) {
88
- switch_to_blog( 1 );
89
- }
90
- }
91
-
92
- public function before_insert() {
93
- $this->blog_id = get_current_blog_id();
94
- if ( Utils::instance()->isActivatedSingle() == false ) {
95
- switch_to_blog( 1 );
96
- }
97
- }
98
-
99
- /**
100
- * @return string
101
- */
102
- public function get_date() {
103
- return Utils::instance()->formatDateTime( date( 'Y-m-d H:i:s', $this->date ) );
104
- }
105
-
106
- /**
107
- * @return mixed|null
108
- */
109
- public function get_type() {
110
- $types = array(
111
- 'auth_fail' => __( "Failed login attempts", "defender-security" ),
112
- 'auth_lock' => __( "Login lockout", "defender-security" ),
113
- '404_error' => __( "404 error", "defender-security" ),
114
- '404_error_ignore' => __( "404 error", "defender-security" ),
115
- '404_lockout' => __( "404 lockout", "defender-security" )
116
- );
117
-
118
- if ( isset( $types[ $this->type ] ) ) {
119
- return $types[ $this->type ];
120
- }
121
-
122
- return null;
123
- }
124
-
125
- /**
126
- * @return array
127
- */
128
- public function events() {
129
- $that = $this;
130
-
131
- return array(
132
- self::EVENT_BEFORE_INSERT => array(
133
- array(
134
- function () use ( $that ) {
135
- $that->before_insert();
136
- }
137
- )
138
- ),
139
- self::EVENT_BEFORE_UPDATE => array(
140
- array(
141
- function () use ( $that ) {
142
- $that->before_update();
143
- }
144
- )
145
- ),
146
- self::EVENT_AFTER_INSERT => array(
147
- array(
148
- function () use ( $that ) {
149
- if ( Utils::instance()->isActivatedSingle() == false ) {
150
- switch_to_blog( $that->blog_id );
151
- }
152
- }
153
- )
154
- ),
155
- self::EVENT_AFTER_UPDATE => array(
156
- array(
157
- function () use ( $that ) {
158
- if ( Utils::instance()->isActivatedSingle() == false ) {
159
- switch_to_blog( $that->blog_id );
160
- }
161
- }
162
- )
163
- )
164
- );
165
- }
166
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/ip-lockout/model/log-model.php DELETED
@@ -1,281 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Author: Hoang Ngo
5
- */
6
-
7
- namespace WP_Defender\Module\IP_Lockout\Model;
8
-
9
- use Hammer\Base\DB_Model;
10
- use Hammer\Helper\Array_Helper;
11
- use WP_Defender\Behavior\Utils;
12
- use WP_Defender\Module\IP_Lockout\Component\Login_Protection_Api;
13
-
14
- class Log_Model extends DB_Model {
15
- const AUTH_FAIL = 'auth_fail', AUTH_LOCK = 'auth_lock', ERROR_404 = '404_error', LOCKOUT_404 = '404_lockout', ERROR_404_IGNORE = '404_error_ignore';
16
- protected static $tableName = 'defender_lockout_log';
17
-
18
- public $id;
19
- public $log;
20
- public $ip;
21
- public $date;
22
- public $user_agent;
23
- public $type;
24
- public $blog_id;
25
- public $tried;
26
-
27
- /**
28
- * A helper attribute for storing status text to output to frontend
29
- * This wont be save into db
30
- * @var
31
- */
32
- public $ip_status;
33
- public $is_mine;
34
- public $statusText;
35
- public $actionText;
36
-
37
- /**
38
- * @return string
39
- * @deprecated 2.2
40
- */
41
- public function get_ip() {
42
- return esc_html( $this->ip );
43
- }
44
-
45
- /**
46
- * @return string
47
- * @deprecated 2.2
48
- */
49
- public function get_log_text( $format = false ) {
50
- if ( ! $format ) {
51
- return esc_html( $this->log );
52
- } else {
53
- $text = sprintf( __( "Request for file <span class='log-text-table'>%s</span> which doesn't exist",
54
- "defender-security" ), esc_attr( $this->log ) );
55
-
56
- return $text;
57
- }
58
- }
59
-
60
- public function before_update() {
61
- $this->blog_id = get_current_blog_id();
62
- }
63
-
64
- public function before_insert() {
65
- $this->blog_id = get_current_blog_id();
66
- }
67
-
68
- /**
69
- * Get current status of this ip due to whitelist/blacklist data
70
- * @return string
71
- */
72
- public function blackOrWhite() {
73
- $settings = Settings::instance();
74
- if ( in_array( $this->ip, $settings->getIpWhitelist() ) ) {
75
- return 'whitelist';
76
- } elseif ( in_array( $this->ip, $settings->getIpBlacklist() ) ) {
77
- return 'blacklist';
78
- }
79
-
80
- return 'na';
81
- }
82
-
83
- /**
84
- * @return string
85
- */
86
- public function get_date() {
87
- if ( strtotime( '-24 hours' ) > $this->date ) {
88
- return Utils::instance()->formatDateTime( date( 'Y-m-d H:i:s', $this->date ) );
89
- } else {
90
- return Login_Protection_Api::time_since( $this->date ) . ' ' . __( "ago", "defender-security" );
91
- }
92
- }
93
-
94
- /**
95
- * @return mixed|null
96
- */
97
- public function get_type() {
98
- $types = array(
99
- 'auth_fail' => __( "Failed login attempts", "defender-security" ),
100
- 'auth_lock' => __( "Login lockout", "defender-security" ),
101
- '404_error' => __( "404 error", "defender-security" ),
102
- '404_error_ignore' => __( "404 error", "defender-security" ),
103
- '404_lockout' => __( "404 lockout", "defender-security" )
104
- );
105
-
106
- if ( isset( $types[ $this->type ] ) ) {
107
- return $types[ $this->type ];
108
- }
109
-
110
- return null;
111
- }
112
-
113
- /**
114
- * Return summary data
115
- * @param bool $for_hub
116
- *
117
- * @return array
118
- */
119
- public static function getSummary( $for_hub = false ) {
120
- $lockouts = Log_Model::findAll( array(
121
- 'type' => array(
122
- Log_Model::LOCKOUT_404,
123
- Log_Model::AUTH_LOCK
124
- ),
125
- 'date' => array(
126
- 'compare' => '>=',
127
- 'value' => strtotime( '-30 days', current_time( 'timestamp' ) )
128
- )
129
- ), 'id', 'DESC' );
130
-
131
- if ( count( $lockouts ) == 0 ) {
132
- $data = array(
133
- 'lastLockout' => __( "Never", "defender-security" ),
134
- 'lockoutToday' => 0,
135
- 'lockoutThisMonth' => 0,
136
- 'loginLockoutToday' => 0,
137
- 'loginLockoutThisWeek' => 0,
138
- 'lockout404Today' => 0,
139
- 'lockout404ThisWeek' => 0,
140
- 'lockoutLoginThisMonth' => 0,
141
- 'lockout404ThisMonth' => 0
142
- );
143
-
144
- return $data;
145
- }
146
-
147
- //init params
148
- $lastLockout = '';
149
- $lockoutToday = 0;
150
- $lockoutThisMonth = count( $lockouts );
151
- $loginLockoutToday = 0;
152
- $loginLockoutThisWeek = 0;
153
- $lockout404ThisWeek = 0;
154
- $lockout404Today = 0;
155
- $loginLockoutThisMonth = 0;
156
- $lockout404ThisMonth = 0;
157
- //time
158
- $todayMidnight = strtotime( '-24 hours', current_time( 'timestamp' ) );
159
- $firstThisWeek = strtotime( '-7 days', current_time( 'timestamp' ) );
160
- foreach ( $lockouts as $k => $log ) {
161
- //the other as DESC, so first will be last lockout
162
- if ( $k == 0 ) {
163
- $lastLockout = $for_hub
164
- ? date( 'Y-m-d H:i:s', $log->date )
165
- : Utils::instance()->formatDateTime( date( 'Y-m-d H:i:s', $log->date ) );
166
- }
167
-
168
- if ( $log->date > $todayMidnight ) {
169
- $lockoutToday ++;
170
- if ( $log->type == self::LOCKOUT_404 ) {
171
- $lockout404Today += 1;
172
- } else {
173
- $loginLockoutToday += 1;
174
- }
175
- }
176
-
177
- if ( $log->type == Log_Model::AUTH_LOCK && $log->date > $firstThisWeek ) {
178
- $loginLockoutThisWeek ++;
179
- } elseif ( $log->type == Log_Model::LOCKOUT_404 && $log->date > $firstThisWeek ) {
180
- $lockout404ThisWeek ++;
181
- }
182
-
183
- if ( $log->type === Log_Model::AUTH_LOCK ) {
184
- $loginLockoutThisMonth += 1;
185
- } elseif ( $log->type === Log_Model::LOCKOUT_404 ) {
186
- $lockout404ThisMonth += 1;
187
- }
188
- }
189
-
190
- $data = array(
191
- 'lastLockout' => $lastLockout,
192
- 'lockoutToday' => $lockoutToday,
193
- 'lockoutThisMonth' => $lockoutThisMonth,
194
- 'loginLockoutToday' => $loginLockoutToday,
195
- 'loginLockoutThisWeek' => $loginLockoutThisWeek,
196
- 'lockout404ThisWeek' => $lockout404ThisWeek,
197
- 'lockout404Today' => $lockout404Today,
198
- 'lockoutLoginThisMonth' => $loginLockoutThisMonth,
199
- 'lockout404ThisMonth' => $lockout404ThisMonth
200
- );
201
-
202
- return $data;
203
- }
204
-
205
- /**
206
- * Pulling the logs data, use in Logs tab
207
- * $filters will have those params
208
- * -date_from
209
- * -date_to
210
- * == Defaults is 7 days and always require
211
- * -type: optional
212
- * -ip: optional
213
- *
214
- * @param array $filters
215
- * @param int $paged
216
- * @param string $orderBy
217
- * @param string $order
218
- * @param int $pageSize
219
- *
220
- * @return Log_Model[]
221
- */
222
- public static function queryLogs(
223
- $filters = array(),
224
- $paged = 1,
225
- $orderBy = 'id',
226
- $order = 'DESC',
227
- $pageSize = 20
228
- ) {
229
- $params = [
230
- 'date' => [
231
- 'compare' => 'between',
232
- 'from' => Array_Helper::getValue( $filters, 'dateFrom', strtotime( '-7 days midnight' ) ),
233
- 'to' => Array_Helper::getValue( $filters, 'dateTo', strtotime( 'tomorrow' ) )
234
- ],
235
- ];
236
-
237
- if ( ( $filter = Array_Helper::getValue( $filters, 'type', null ) ) != null ) {
238
- $params['type'] = $filter;
239
- }
240
- if ( ( $ip = Array_Helper::getValue( $filters, 'ip', null ) ) != null ) {
241
- $params['ip'] = $ip;
242
- }
243
-
244
- $offset = ( $paged - 1 ) * $pageSize;
245
- $models = Log_Model::findAll( $params, $orderBy, $order, "$offset,$pageSize" );
246
- $count = Log_Model::count( $params );
247
-
248
- return [ $models, $count ];
249
- }
250
-
251
- /**
252
- * @return array
253
- */
254
- public function events() {
255
- $that = $this;
256
-
257
- return array(
258
- self::EVENT_BEFORE_INSERT => array(
259
- array(
260
- function () use ( $that ) {
261
- $that->before_insert();
262
- }
263
- )
264
- ),
265
- self::EVENT_BEFORE_UPDATE => array(
266
- array(
267
- function () use ( $that ) {
268
- $that->before_update();
269
- }
270
- )
271
- )
272
- );
273
- }
274
-
275
- /**
276
- * @return array
277
- */
278
- public function notSaveFields() {
279
- return array( 'statusText', 'actionText', 'ip_status', 'is_mine' );
280
- }
281
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/ip-lockout/model/settings.php DELETED
@@ -1,767 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\IP_Lockout\Model;
7
-
8
- use Hammer\GeoIP\GeoIp;
9
- use Hammer\Helper\HTTP_Helper;
10
- use Hammer\Helper\WP_Helper;
11
- use WP_Defender\Behavior\Utils;
12
- use WP_Defender\Module\IP_Lockout\Component\IP_API;
13
-
14
- class Settings extends \Hammer\WP\Settings {
15
- private static $_instance;
16
-
17
- public $login_protection = false;
18
- public $login_protection_login_attempt = 5;
19
- public $login_protection_lockout_timeframe = 300;
20
- public $login_protection_lockout_duration = 300;
21
- public $login_protection_lockout_duration_unit = 'seconds';
22
- public $login_protection_lockout_message = "You have been locked out due to too many invalid login attempts.";
23
- public $login_protection_ban_admin_brute = false;
24
- public $login_protection_lockout_ban = false;
25
- public $username_blacklist = '';
26
-
27
- public $detect_404 = false;
28
- public $detect_404_threshold = 20;
29
- public $detect_404_timeframe = 300;
30
- public $detect_404_lockout_duration = 300;
31
- public $detect_404_lockout_duration_unit = 'seconds';
32
- public $detect_404_whitelist;
33
- public $detect_404_blacklist;
34
- public $detect_404_ignored_filetypes;
35
- public $detect_404_filetypes_blacklist;
36
- public $detect_404_lockout_message = "You have been locked out due to too many attempts to access a file that doesn't exist.";
37
- public $detect_404_lockout_ban = false;
38
- public $detect_404_logged = true;
39
-
40
- public $ip_blacklist = array();
41
- public $ip_whitelist = array();
42
- public $ip_lockout_message = 'The administrator has blocked your IP from accessing this website.';
43
-
44
- public $country_blacklist = [];
45
- public $country_whitelist = [];
46
-
47
- public $login_lockout_notification = true;
48
- public $ip_lockout_notification = true;
49
-
50
- public $report = true;
51
- public $report_frequency = '7';
52
- public $report_day = 'sunday';
53
- public $report_time = '0:00';
54
-
55
- public $geoIP_db = null;
56
-
57
- public $storage_days = 30;
58
-
59
- public $receipts = array();
60
- public $report_receipts = array();
61
- public $lastReportSent;
62
-
63
- public $cooldown_enabled = false;
64
- public $cooldown_number_lockout = '3';
65
- public $cooldown_period = '24';
66
-
67
- public $cache = array();
68
-
69
- public function __construct( $id, $isMulti ) {
70
- if ( ( is_admin() || is_network_admin() ) && current_user_can( 'manage_options' ) ) {
71
- $user = wp_get_current_user();
72
- if ( is_object( $user ) ) {
73
- $this->receipts[] = array(
74
- 'first_name' => $user->display_name,
75
- 'email' => $user->user_email
76
- );
77
- $this->report_receipts[] = array(
78
- 'first_name' => $user->display_name,
79
- 'email' => $user->user_email
80
- );
81
- }
82
-
83
- $this->ip_whitelist = $this->getUserIp() . PHP_EOL;
84
- //default is weekly
85
- $this->report_day = strtolower( date( 'l' ) );
86
- $this->report_time = '4:00';
87
- }
88
- parent::__construct( $id, $isMulti );
89
- /**
90
- * Make sure those is boolen
91
- */
92
- $this->login_protection = ! ! $this->login_protection;
93
- $this->detect_404 = ! ! $this->detect_404;
94
- $this->login_protection_lockout_ban = ! ! $this->login_protection_lockout_ban;
95
- $this->detect_404_lockout_ban = ! ! $this->detect_404_lockout_ban;
96
- $this->report = ! ! $this->report;
97
- $this->detect_404_logged = ! ! $this->detect_404_logged;
98
-
99
- $times = Utils::instance()->getTimes();
100
- if ( ! isset( $times[ $this->report_time ] ) ) {
101
- $this->report_time = '4:00';
102
- }
103
- if ( ! is_array( $this->receipts ) ) {
104
- $this->receipts = [];
105
- }
106
- $this->receipts = array_values( $this->receipts );
107
- if ( ! is_array( $this->report_receipts ) ) {
108
- $this->report_receipts = [];
109
- }
110
- $this->report_receipts = array_values( $this->report_receipts );
111
- if ( is_string( $this->country_whitelist ) ) {
112
- $this->country_whitelist = explode( ',', $this->country_whitelist );
113
- $this->country_whitelist = ( array_values( array_filter( $this->country_whitelist ) ) );
114
- }
115
- if ( is_string( $this->country_blacklist ) ) {
116
- $this->country_blacklist = explode( ',', $this->country_blacklist );
117
- $this->country_blacklist = ( array_values( array_filter( $this->country_blacklist ) ) );
118
- }
119
- }
120
-
121
- /**
122
- * @return array
123
- */
124
- public function behaviors() {
125
- return array(
126
- 'utils' => '\WP_Defender\Behavior\Utils'
127
- );
128
- }
129
-
130
- /**
131
- * @return array
132
- */
133
- public function rules() {
134
- return array(
135
- [
136
- [
137
- 'login_protection_login_attempt',
138
- 'login_protection_lockout_timeframe',
139
- 'login_protection_lockout_duration',
140
- 'detect_404_threshold',
141
- 'detect_404_timeframe',
142
- 'detect_404_lockout_duration',
143
- 'storage_days',
144
- ],
145
- 'integer',
146
- ],
147
- );
148
- }
149
-
150
- /**
151
- * @return array
152
- */
153
- public function filters() {
154
- return [
155
- 'username_blacklist',
156
- 'login_protection_lockout_message',
157
- 'detect_404_ignored_filetypes',
158
- 'detect_404_filetypes_blacklist',
159
- 'detect_404_lockout_message',
160
- 'detect_404_whitelist',
161
- 'detect_404_blacklist',
162
- 'ip_lockout_message',
163
- 'ip_blacklist',
164
- 'ip_whitelist',
165
- 'ip_lockout_message',
166
- ];
167
- }
168
-
169
- /**
170
- * @return array
171
- */
172
- public function get404Whitelist() {
173
- $arr = array_filter( explode( PHP_EOL, $this->detect_404_whitelist ) );
174
- $arr = array_map( 'trim', $arr );
175
-
176
- return $arr;
177
- }
178
-
179
- /**
180
- * @return array
181
- */
182
- public function get404Ignorelist() {
183
- $arr = array_filter( explode( PHP_EOL, $this->detect_404_ignored_filetypes ) );
184
- $arr = array_map( 'trim', $arr );
185
- $arr = array_map( 'strtolower', $arr );
186
-
187
- return $arr;
188
- }
189
-
190
- /**
191
- * @return mixed
192
- */
193
- public function getDetect404Whitelist() {
194
- $arr = array_filter( explode( PHP_EOL, $this->detect_404_whitelist ) );
195
- $arr = array_map( 'trim', $arr );
196
-
197
- return $arr;
198
- }
199
-
200
- /**
201
- * @return mixed
202
- */
203
- public function getDetect404Blacklist() {
204
- $arr = array_filter( explode( PHP_EOL, $this->detect_404_blacklist ) );
205
- $arr = array_map( 'trim', $arr );
206
-
207
- return $arr;
208
- }
209
-
210
- /**
211
- * @return array
212
- */
213
- public function getIpBlacklist() {
214
- if ( is_array( $this->ip_blacklist ) ) {
215
- $arr = $this->ip_blacklist;
216
- } else {
217
- $arr = array_filter( explode( PHP_EOL, $this->ip_blacklist ) );
218
- }
219
- $arr = array_map( 'trim', $arr );
220
-
221
- return $arr;
222
- }
223
-
224
- /**
225
- * @return array
226
- */
227
- public function getDetect404IgnoredFiletypes() {
228
- $exts = explode( PHP_EOL, $this->detect_404_ignored_filetypes );
229
- $exts = array_map( 'trim', $exts );
230
- $exts = array_map( 'strtolower', $exts );
231
-
232
- return $exts;
233
- }
234
-
235
- /**
236
- * @return mixed
237
- */
238
- public function getDetect404FiletypesBlacklist() {
239
- $exts = explode( PHP_EOL, $this->detect_404_filetypes_blacklist );
240
- $exts = array_map( 'trim', $exts );
241
- $exts = array_map( 'strtolower', $exts );
242
-
243
- return $exts;
244
- }
245
-
246
- /**
247
- * @return array
248
- */
249
- public function getIpWhitelist() {
250
- //backward compatibility
251
- if ( is_array( $this->ip_whitelist ) ) {
252
- $arr = $this->ip_whitelist;
253
- } else {
254
- $arr = array_filter( explode( PHP_EOL, $this->ip_whitelist ) );
255
- }
256
- $arr = array_map( 'trim', $arr );
257
-
258
- return $arr;
259
- }
260
-
261
- /**
262
- * @return array
263
- */
264
- public function getCountryBlacklist() {
265
- if ( is_array( $this->country_blacklist ) ) {
266
- return $this->country_blacklist;
267
- }
268
- //fallback to older version than 2.2
269
- $arr = array_filter( explode( ',', $this->country_blacklist ) );
270
- $arr = array_map( 'trim', $arr );
271
-
272
- return $arr;
273
- }
274
-
275
- /**
276
- * @return array
277
- */
278
- public function getCountryWhitelist() {
279
- if ( is_array( $this->country_whitelist ) ) {
280
- return $this->country_whitelist;
281
- }
282
- //fallback to older version than 2.2
283
- $arr = array_filter( explode( ',', $this->country_whitelist ) );
284
- $arr = array_map( 'trim', $arr );
285
-
286
- return $arr;
287
- }
288
-
289
- /**
290
- * @param $ip
291
- *
292
- * @return bool
293
- */
294
- public function isWhitelist( $ip ) {
295
- $whitelist = $this->getIpWhitelist();
296
- $defaultWhitelist = apply_filters( 'ip_lockout_default_whitelist_ip', array() );
297
- $whitelist = array_merge( $whitelist, $defaultWhitelist );
298
- foreach ( $whitelist as $wip ) {
299
- if ( ! stristr( $wip, '-' ) && ! stristr( $wip, '/' ) && trim( $wip ) == $ip ) {
300
- return true;
301
- } elseif ( stristr( $wip, '-' ) ) {
302
- $ips = explode( '-', $wip );
303
- if ( IP_API::compareInRange( $ip, $ips[0], $ips[1] ) ) {
304
- return true;
305
- }
306
- } elseif ( stristr( $wip, '/' ) && IP_API::compareCIDR( $ip, $wip ) ) {
307
- return true;
308
- }
309
- }
310
-
311
- return false;
312
- }
313
-
314
- /**
315
- * @param $ip
316
- *
317
- * @return bool
318
- */
319
- public function isBlacklist( $ip ) {
320
- $blacklist = $this->getIpBlacklist();
321
- foreach ( $blacklist as $wip ) {
322
- if ( ! stristr( $wip, '-' ) && ! stristr( $wip, '/' ) && trim( $wip ) == $ip ) {
323
- return true;
324
- } elseif ( stristr( $wip, '-' ) ) {
325
- $ips = explode( '-', $wip );
326
- if ( IP_API::compareInRange( $ip, $ips[0], $ips[1] ) ) {
327
- return true;
328
- }
329
- } elseif ( stristr( $wip, '/' ) && IP_API::compareCIDR( $ip, $wip ) ) {
330
- return true;
331
- }
332
- }
333
-
334
- return false;
335
- }
336
-
337
- /**
338
- * Add IP to list
339
- *
340
- * @param $ip
341
- * @param string $list blocklist|allowlist
342
- * @since 2.3.2
343
- */
344
- public function addIpToList( $ip, $list ) {
345
- $ips = array();
346
- $type = '';
347
- if ( 'blocklist' === $list ) {
348
- $ips = $this->getIpBlacklist();
349
- $type = 'ip_blacklist';
350
- } elseif ( 'allowlist' === $list ) {
351
- $ips = $this->getIpWhitelist();
352
- $type = 'ip_whitelist';
353
- }
354
- if ( empty( $type ) ) {
355
- return;
356
- }
357
-
358
- $ips[] = $ip;
359
- $ips = array_unique( $ips );
360
- $this->$type = implode( PHP_EOL, $ips );
361
- $this->save();
362
- }
363
-
364
- /**
365
- * Remove IP from list
366
- *
367
- * @param $ip
368
- * @param string $list blocklist|allowlist
369
- * @since 2.3.2
370
- */
371
- public function removeIpFromList( $ip, $list ) {
372
- $ips = array();
373
- $type = '';
374
- if ( 'blocklist' === $list ) {
375
- $ips = $this->getIpBlacklist();
376
- $type = 'ip_blacklist';
377
- } elseif ( 'allowlist' === $list ) {
378
- $ips = $this->getIpWhitelist();
379
- $type = 'ip_whitelist';
380
- }
381
- if ( empty( $type ) ) {
382
- return;
383
- }
384
-
385
- $key = array_search( $ip, $ips );
386
- if ( $key !== false ) {
387
- unset( $ips[ $key ] );
388
- $ips = array_unique( $ips );
389
- $this->$type = implode( PHP_EOL, $ips );
390
- $this->save();
391
- }
392
- }
393
-
394
- /**
395
- * @param $ip
396
- * @param $range
397
- *
398
- * @return bool
399
- * @src http://stackoverflow.com/a/594134
400
- */
401
- function cidrMatch( $ip, $range ) {
402
- list ( $subnet, $bits ) = explode( '/', $range );
403
- $ip = ip2long( $ip );
404
- $subnet = ip2long( $subnet );
405
- $mask = - 1 << ( 32 - $bits );
406
- $subnet &= $mask; # nb: in case the supplied subnet wasn't correctly aligned
407
-
408
- return ( $ip & $mask ) == $subnet;
409
- }
410
-
411
- public function before_update() {
412
- //validate ips
413
- $remove_ips = array();
414
- $isSelf = false;
415
- if ( isset( $_POST['ip_blacklist'] ) ) {
416
- $blacklist = Http_Helper::retrievePost( 'ip_blacklist' );
417
- $blacklist = explode( PHP_EOL, $blacklist );
418
- foreach ( $blacklist as $k => $ip ) {
419
- $ip = trim( $ip );
420
- if ( $this->validateIp( $ip ) === false ) {
421
- unset( $blacklist[ $k ] );
422
- $remove_ips[] = $ip;
423
- } elseif ( $ip == $this->getUserIp() ) {
424
- $isSelf = true;
425
- }
426
- }
427
- $this->ip_blacklist = implode( PHP_EOL, $blacklist );
428
- }
429
-
430
- if ( isset( $_POST['ip_whitelist'] ) ) {
431
- $whitelist = Http_Helper::retrievePost( 'ip_whitelist' );
432
- $whitelist = explode( PHP_EOL, $whitelist );
433
- foreach ( $whitelist as $k => $ip ) {
434
- $ip = trim( $ip );
435
- if ( $this->validateIp( $ip ) === false ) {
436
- unset( $whitelist[ $k ] );
437
- $remove_ips[] = $ip;
438
- }
439
- }
440
- $this->ip_whitelist = implode( PHP_EOL, $whitelist );
441
- }
442
- $remove_ips = array_filter( $remove_ips );
443
-
444
- if ( ! empty( $remove_ips ) && count( $remove_ips ) ) {
445
- WP_Helper::getArrayCache()->set( 'faultIps', $remove_ips );
446
- WP_Helper::getArrayCache()->set( 'isBlacklistSelf', $isSelf );
447
- }
448
- }
449
-
450
- /**
451
- * $ip an be single ip, or a range like xxx.xxx.xxx.xxx - xxx.xxx.xxx.xxx or CIDR
452
- *
453
- * @param $ip
454
- *
455
- * @return bool
456
- */
457
- public function validateIp( $ip ) {
458
- if (
459
- ! stristr( $ip, '-' )
460
- && ! stristr( $ip, '/' )
461
- && filter_var( $ip, FILTER_VALIDATE_IP ) ) {
462
- //only ip, no -, no /
463
- return true;
464
- } elseif ( stristr( $ip, '-' ) ) {
465
- $ips = explode( '-', $ip );
466
- foreach ( $ips as $ip ) {
467
- if ( ! filter_var( $ip, FILTER_VALIDATE_IP ) ) {
468
- return false;
469
- }
470
- }
471
- if ( IP_API::compareIP( $ips[0], $ips[1] ) ) {
472
- return true;
473
- }
474
- } elseif ( stristr( $ip, '/' ) ) {
475
- list( $ip, $bits ) = explode( '/', $ip );
476
- if ( filter_var( $ip, FILTER_VALIDATE_IP ) && filter_var( $bits, FILTER_VALIDATE_INT ) ) {
477
- if ( $this->isIPV4( $ip ) && 0 <= $bits && $bits <= 32 ) {
478
- return true;
479
- } elseif ( $this->isIPV6( $ip ) && 0 <= $bits && $bits <= 128 && IP_API::isV6Support() ) {
480
- return true;
481
- }
482
- }
483
- }
484
-
485
- return false;
486
- }
487
-
488
- public function beforeValidate() {
489
- $emails = [];
490
- foreach ( $this->receipts as $receipt ) {
491
- if ( in_array( $receipt['email'], $emails ) ) {
492
- $this->addError( 'recipients', __( "Recipients' emails can't be duplicate", "defender-security" ) );
493
-
494
- return false;
495
- } else {
496
- $emails[] = $receipt['email'];
497
- }
498
- }
499
- }
500
-
501
- /**
502
- * @param $ip
503
- *
504
- * @return mixed
505
- */
506
- private function isIPV4( $ip ) {
507
- return filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 );
508
- }
509
-
510
- /**
511
- * @param $ip
512
- *
513
- * @return mixed
514
- */
515
- private function isIPV6( $ip ) {
516
- return filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 );
517
- }
518
-
519
- /**
520
- * @return array
521
- */
522
- public function events() {
523
- $that = $this;
524
-
525
- return array(
526
- self::EVENT_BEFORE_SAVE => array(
527
- array(
528
- function () use ( $that ) {
529
- $that->before_update();
530
-
531
- foreach ( $this->receipts as $k => &$receipt ) {
532
- $receipt = array_map( 'sanitize_text_field', $receipt );
533
- if ( ! filter_var( $receipt['email'], FILTER_VALIDATE_EMAIL ) ) {
534
- unset( $this->receipts[ $k ] );
535
- }
536
- }
537
-
538
- foreach ( $this->report_receipts as $k => &$receipt ) {
539
- $receipt = array_map( 'sanitize_text_field', $receipt );
540
- if ( ! filter_var( $receipt['email'], FILTER_VALIDATE_EMAIL ) ) {
541
- unset( $this->report_receipts[ $k ] );
542
- }
543
- }
544
-
545
- //need to turn off notification or report off if no recipients
546
- $this->receipts = array_filter( $this->receipts );
547
- if ( count( $this->receipts ) == 0 ) {
548
- $this->ip_lockout_notification = false;
549
- $this->login_lockout_notification = false;
550
- }
551
- $this->report_receipts = array_filter( $this->report_receipts );
552
- if ( count( $this->report_receipts ) == 0 ) {
553
- $this->report = false;
554
- }
555
- }
556
- )
557
- )
558
- );
559
- }
560
-
561
- /**
562
- * @return array|string
563
- */
564
- public function getUsernameBlacklist() {
565
- $usernames = $this->username_blacklist;
566
- $usernames = explode( PHP_EOL, $usernames );
567
- $usernames = array_map( 'trim', $usernames );
568
- $usernames = array_map( 'strtolower', $usernames );
569
- $usernames = array_filter( $usernames );
570
-
571
- return $usernames;
572
- }
573
-
574
- /**
575
- * @return bool
576
- */
577
- public function isGeoDBDownloaded() {
578
- if ( is_null( $this->geoIP_db ) || ! is_file( $this->geoIP_db ) ) {
579
- return false;
580
- }
581
-
582
- return true;
583
- }
584
-
585
- /**
586
- * @return bool
587
- */
588
- public function isCountryBlacklist() {
589
- //return if php less than 5.4
590
- if ( version_compare( phpversion(), '5.4', '<' ) ) {
591
- return false;
592
- }
593
- $country = IP_API::getCurrentCountry();
594
- if ( $country == false ) {
595
- return false;
596
- }
597
- //if this country is whitelisted, so we dont need to blacklist this
598
- if ( $this->isCountryWhitelist() ) {
599
- return false;
600
- }
601
-
602
- $blacklisted = $this->getCountryBlacklist();
603
- if ( empty( $blacklisted ) ) {
604
- return false;
605
- }
606
- if ( in_array( 'all', $blacklisted ) ) {
607
- return true;
608
- }
609
- if ( in_array( strtoupper( $country['iso'] ), $blacklisted ) ) {
610
- return true;
611
- }
612
-
613
- return false;
614
- }
615
-
616
- /**
617
- * @return bool
618
- */
619
- public function isCountryWhitelist() {
620
- $country = IP_API::getCurrentCountry();
621
- $whitelist = $this->getCountryWhitelist();
622
- if ( empty( $whitelist ) ) {
623
- return false;
624
- }
625
-
626
- if ( in_array( strtoupper( $country['iso'] ), $whitelist ) ) {
627
- return true;
628
- }
629
-
630
- return false;
631
- }
632
-
633
- /**
634
- * @return Settings
635
- */
636
- public static function instance() {
637
- if ( is_null( self::$_instance ) ) {
638
- $class = new Settings( 'wd_lockdown_settings',
639
- WP_Helper::is_network_activate( wp_defender()->plugin_slug ) );
640
- self::$_instance = $class;
641
- }
642
-
643
- return self::$_instance;
644
- }
645
-
646
-
647
- /**
648
- * Define labels for settings key, we will use it for HUB
649
- *
650
- * @param null $key
651
- *
652
- * @return array|mixed
653
- */
654
- public function labels( $key = null ) {
655
- $labels = [
656
- 'login_protection' => __( "Login Protection", "defender-security" ),
657
- 'login_protection_login_attempt' => __( "Login Protection - Threshold", "defender-security" ),
658
- 'login_protection_lockout_duration' => __( "Login Protection - Duration", "defender-security" ),
659
- 'login_protection_lockout_message' => __( "Login Protection - Lockout Message", "defender-security" ),
660
- 'username_blacklist' => __( "Login Protection - Banned Usernames", "defender-security" ),
661
- 'detect_404' => __( "404 Detection", "defender-security" ),
662
- 'detect_404_threshold' => __( "404 Detection - Threshold", "defender-security" ),
663
- 'detect_404_lockout_duration' => __( "404 Detection - Duration", "defender-security" ),
664
- 'detect_404_lockout_message' => __( "404 Detection - Lockout Message", "defender-security" ),
665
- 'detect_404_blacklist' => __( "404 Detection - Files & Folders Blacklist",
666
- "defender-security" ),
667
- 'detect_404_whitelist' => __( "404 Detection - Files & Folders Whitelist",
668
- "defender-security" ),
669
- 'detect_404_filetypes_blacklist' => __( "404 Detection - Filetypes & Extensions Whitelist",
670
- "defender-security" ),
671
- 'detect_404_ignored_filetypes' => __( "404 Detection - Filetypes & Extensions Blacklist",
672
- "defender-security" ),
673
- 'detect_404_logged' => __( "404 Detection - Monitor logged in users",
674
- "defender-security" ),
675
- 'ip_blacklist' => __( "IP Banning - IP Address Blacklist", "defender-security" ),
676
- 'ip_whitelist' => __( "IP Banning - IP Address Whitelist", "defender-security" ),
677
- 'country_blacklist' => __( "IP Banning - Country Whitelist", "defender-security" ),
678
- 'country_whitelist' => __( "IP Banning - Country Blacklist", "defender-security" ),
679
- 'ip_lockout_message' => __( "IP Banning - Lockout Message", "defender-security" ),
680
- 'login_lockout_notification' => __( "Emails - Login Protection Lockout", "defender-security" ),
681
- 'ip_lockout_notification' => __( "Emails - 404 Detection Lockout", "defender-security" ),
682
- 'receipts' => __( "Emails - Lockout Recipients", "defender-security" ),
683
- 'cooldown_enabled' => __( "Emails - Repeat Lockouts", "defender-security" ),
684
- 'cooldown_number_lockout' => __( "Emails - Repeat Lockouts Threshold", "defender-security" ),
685
- 'report' => __( "Reports - Scheduled Lockout Report", "defender-security" ),
686
- 'report_frequency' => __( "Reports - Frequency", "defender-security" ),
687
- 'report_receipts' => __( "Reports - Recipients", "defender-security" ),
688
- 'storage_days' => __( "Days to keep logs", "defender-security" ),
689
- ];
690
-
691
- if ( $key != null ) {
692
- return isset( $labels[ $key ] ) ? $labels[ $key ] : null;
693
- }
694
-
695
- return $labels;
696
- }
697
-
698
- /**
699
- * @return array
700
- */
701
- public function export_strings( $configs ) {
702
-
703
- return [
704
- __( 'Active', "defender-security" )
705
- ];
706
- }
707
-
708
- public function format_hub_data() {
709
- return [
710
- 'login_protection' => $this->login_protection ? __( 'Activate',
711
- "defender-security" ) : __( 'Inactivate',
712
- "defender-security" ),
713
- 'login_protection_login_attempt' => sprintf( __( '%d logins in %d seconds',
714
- "defender-security" ),
715
- $this->login_protection_login_attempt, $this->login_protection_lockout_timeframe ),
716
- 'login_protection_lockout_duration' => $this->login_protection_lockout_ban ? __( 'Permanent',
717
- "defender-security" ) : $this->login_protection_lockout_timeframe . ' ' . $this->login_protection_lockout_duration_unit,
718
- 'login_protection_lockout_message' => $this->login_protection_lockout_message,
719
- 'username_blacklist' => empty( $this->username_blacklist ) ? __( 'None',
720
- "defender-security" ) : $this->username_blacklist,
721
- 'detect_404' => $this->detect_404 ? __( 'Activate',
722
- "defender-security" ) : __( 'Inactivate',
723
- "defender-security" ),
724
- 'detect_404_threshold' => sprintf( __( '%d hits in %d seconds',
725
- "defender-security" ),
726
- $this->detect_404_threshold, $this->detect_404_timeframe ),
727
- 'detect_404_lockout_duration' => $this->detect_404_lockout_ban ? __( 'Permanent',
728
- "defender-security" ) : $this->detect_404_lockout_duration . ' ' . $this->detect_404_lockout_duration_unit,
729
- 'detect_404_lockout_message' => $this->detect_404_lockout_message,
730
- 'detect_404_blacklist' => empty( $this->detect_404_blacklist ) ? __( 'None',
731
- "defender-security" ) : $this->detect_404_blacklist,
732
- 'detect_404_whitelist' => empty( $this->detect_404_whitelist ) ? __( 'None',
733
- "defender-security" ) : $this->detect_404_whitelist,
734
- 'detect_404_filetypes_blacklist' => empty( $this->detect_404_filetypes_blacklist ) ? __( 'None',
735
- "defender-security" ) : $this->detect_404_filetypes_blacklist,
736
- 'detect_404_ignored_filetypes' => empty( $this->detect_404_ignored_filetypes ) ? __( 'None',
737
- "defender-security" ) : $this->detect_404_ignored_filetypes,
738
- 'detect_404_logged' => $this->detect_404_logged ? __( 'Yes',
739
- "defender-security" ) : __( 'No', "defender-security" ),
740
- 'ip_blacklist' => empty( $this->ip_blacklist ) ? __( 'None',
741
- "defender-security" ) : $this->ip_blacklist,
742
- 'country_blacklist' => empty( $this->country_blacklist ) ? __( 'None',
743
- "defender-security" ) : $this->country_blacklist,
744
- 'ip_lockout_message' => empty( $this->ip_lockout_message ) ? __( 'None',
745
- "defender-security" ) : $this->ip_lockout_message,
746
- 'login_lockout_notification' => $this->login_lockout_notification ? __( 'Activate',
747
- "defender-security" ) : __( 'Inactivate',
748
- "defender-security" ),
749
- 'ip_lockout_notification' => $this->ip_lockout_notification ? __( 'Activate',
750
- "defender-security" ) : __( 'Inactivate',
751
- "defender-security" ),
752
- 'receipts' => empty( $this->receipts ) ? __( 'None',
753
- "defender-security" ) : Utils::instance()->recipientsToString( $this->receipts ),
754
- 'cooldown_enabled' => $this->cooldown_enabled ? __( 'Yes',
755
- "defender-security" ) : __( 'No', "defender-security" ),
756
- 'cooldown_number_lockout' => $this->cooldown_number_lockout ? __( 'None',
757
- "defender-security" ) : $this->cooldown_number_lockout,
758
- 'report' => $this->report ? __( 'Activate',
759
- "defender-security" ) : __( 'Inactivate', "defender-security" ),
760
- 'report_frequency' => Utils::instance()->format_frequency_for_hub( $this->report_frequency,
761
- $this->report_day, $this->report_time ),
762
- 'report_receipts' => Utils::instance()->recipientsToString( $this->report_receipts ),
763
- 'storage_days' => sprintf( __( '%d days', "defender-security" ),
764
- $this->storage_days )
765
- ];
766
- }
767
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/ip-lockout/view/detect-404/enabled.php DELETED
@@ -1,196 +0,0 @@
1
- <div class="sui-box">
2
- <form method="post" id="settings-frm" class="ip-frm">
3
- <div class="sui-box-header">
4
- <h3 class="sui-box-title">
5
- <?php _e( "404 Detection", "defender-security" ) ?>
6
- </h3>
7
- </div>
8
- <div class="sui-box-body">
9
- <p>
10
- <?php
11
- _e("With 404 detection enabled, Defender will keep an eye out for IP addresses that repeatedly request pages on your website that don’t exist and then temporarily block them from accessing your site.","defender-security")
12
- ?>
13
- </p>
14
- <?php if ( ( $count = ( \WP_Defender\Module\IP_Lockout\Component\Login_Protection_Api::get404Lockouts( strtotime( '-24 hours', current_time( 'timestamp' ) ) ) ) ) > 0 ): ?>
15
- <div class="sui-notice sui-notice-error">
16
- <p>
17
- <?php echo sprintf( __( "There have been %d lockouts in the last 24 hours. <a href=\"%s\"><strong>View log</strong></a>.", "defender-security" ), $count, network_admin_url( 'admin.php?page=wdf-ip-lockout&view=logs' ) ) ?>
18
- </p>
19
- </div>
20
- <?php else: ?>
21
- <div class="sui-notice sui-notice-info">
22
- <p>
23
- <?php esc_html_e( "404 detection is enabled. There are no lockouts logged yet.", "defender-security" ) ?>
24
- </p>
25
- </div>
26
- <?php endif; ?>
27
- <div class="sui-box-settings-row">
28
- <div class="sui-box-settings-col-1">
29
- <span class="sui-settings-label"><?php esc_html_e( "Lockout threshold", "defender-security" ) ?></span>
30
- <span class="sui-description">
31
- <?php esc_html_e( "Specify how many 404 errors within a specific time period will trigger a lockout.", "defender-security" ) ?>
32
- </span>
33
- </div>
34
- <div class="sui-box-settings-col-2">
35
- <div class="sui-form-field">
36
- <input size="8" value="<?php echo $settings->detect_404_threshold ?>" type="text"
37
- class="sui-form-control sui-input-sm sui-field-has-suffix"
38
- id="detect_404_threshold"
39
- name="detect_404_threshold"/>
40
- <span class="sui-field-suffix sui-field-prefix"><?php esc_html_e( "404 errors within", "defender-security" ) ?></span>
41
- <input size="8" value="<?php echo $settings->detect_404_timeframe ?>"
42
- id="detect_404_timeframe"
43
- name="detect_404_timeframe" type="text"
44
- class="sui-form-control sui-input-sm sui-field-has-suffix">
45
- <span class="sui-field-suffix"><?php esc_html_e( "seconds", "defender-security" ) ?></span>
46
- </div>
47
- </div>
48
- </div>
49
- <div class="sui-box-settings-row">
50
- <div class="sui-box-settings-col-1">
51
- <span class="sui-settings-label"><?php esc_html_e( "Lockout time", "defender-security" ) ?></span>
52
- <span class="sui-description"><?php esc_html_e( "Choose how long you’d like to ban the locked out user for.", "defender-security" ) ?></span>
53
- </div>
54
- <div class="sui-box-settings-col-2">
55
- <div class="sui-side-tabs sui-tabs">
56
- <div data-tabs>
57
- <div rel="input_value" data-target="detect_404_lockout_ban" data-value="0"
58
- class="<?php echo $settings->detect_404_lockout_ban == 0 ? 'active' : null ?>"><?php _e( "Timeframe", "defender-security" ) ?></div>
59
- <div rel="input_value" data-target="detect_404_lockout_ban" data-value="1"
60
- class="<?php echo $settings->detect_404_lockout_ban == 1 ? 'active' : null ?>"><?php _e( "Permanent", "defender-security" ) ?></div>
61
- </div>
62
- <div data-panes>
63
- <div class="sui-tab-boxed <?php echo $settings->detect_404_lockout_ban == 0 ? 'active' : null ?>">
64
- <div class="sui-row">
65
- <div class="sui-col-md-3">
66
- <input value="<?php echo $settings->detect_404_lockout_duration ?>" size="8"
67
- name="detect_404_lockout_duration"
68
- id="detect_404_lockout_duration" type="text"
69
- class="sui-form-control"/>
70
- </div>
71
- <div class="sui-col-md-3">
72
- <select name="detect_404_lockout_duration_unit">
73
- <option <?php echo selected( 'seconds', $settings->detect_404_lockout_duration_unit ) ?>
74
- value="seconds"><?php _e( "Seconds", "defender-security" ) ?></option>
75
- <option <?php echo selected( 'minutes', $settings->detect_404_lockout_duration_unit ) ?>
76
- value="minutes"><?php _e( "Minutes", "defender-security" ) ?></option>
77
- <option <?php echo selected( 'hours', $settings->detect_404_lockout_duration_unit ) ?>
78
- value="hours"><?php _e( "Hours", "defender-security" ) ?></option>
79
- </select>
80
- </div>
81
- </div>
82
- </div>
83
- </div>
84
- </div>
85
- <input type="hidden" name="detect_404_lockout_ban" value="<?php echo $settings->detect_404_lockout_ban ?>"/>
86
- </div>
87
- </div>
88
- <div class="sui-box-settings-row">
89
- <div class="sui-box-settings-col-1">
90
- <span class="sui-settings-label"><?php esc_html_e( "Lockout message", "defender-security" ) ?></span>
91
- <span class="sui-description"><?php esc_html_e( "Customize the message locked out users will see.", "defender-security" ) ?></span>
92
- </div>
93
- <div class="sui-box-settings-col-2">
94
- <div class="sui-form-field">
95
- <textarea name="detect_404_lockout_message" class="sui-form-control"
96
- id="detect_404_lockout_message"><?php echo $settings->detect_404_lockout_message ?></textarea>
97
- <span class="sui-description">
98
- <?php echo sprintf( __( "This message will be displayed across your website during the lockout period. See a quick preview <a href=\"%s\">here</a>.", "defender-security" ), add_query_arg( array(
99
- 'def-lockout-demo' => 1,
100
- 'type' => '404'
101
- ), network_site_url() ) ) ?>
102
- </span>
103
- </div>
104
- </div>
105
- </div>
106
- <div class="sui-box-settings-row">
107
- <div class="sui-box-settings-col-1">
108
- <span class="sui-settings-label">
109
- <?php esc_html_e( "Whitelist", "defender-security" ) ?>
110
- </span>
111
- <span class="sui-description">
112
- <?php esc_html_e( "If you know a common file on your website is missing, you can record it here so it doesn't count towards a lockout record.", "defender-security" ) ?>
113
- </span>
114
- </div>
115
- <div class="sui-box-settings-col-2">
116
- <div class="sui-form-field">
117
- <textarea class="sui-form-control"
118
- id="detect_404_whitelist" name="detect_404_whitelist"
119
- rows="8"><?php echo $settings->detect_404_whitelist ?></textarea>
120
- <span class="sui-description">
121
- <?php esc_html_e( "You must list the full path beginning with a /.", "defender-security" ) ?>
122
- </span>
123
- </div>
124
- </div>
125
- </div>
126
- <div class="sui-box-settings-row">
127
- <div class="sui-box-settings-col-1">
128
- <span class="sui-settings-label">
129
- <?php esc_html_e( "Ignore file types", "defender-security" ) ?>
130
- </span>
131
- <span class="sui-description">
132
- <?php esc_html_e( "Choose which types of files you want to log errors for but not trigger a lockout.", "defender-security" ) ?>
133
- </span>
134
- </div>
135
- <div class="sui-box-settings-col-2">
136
- <div class="sui-form-field">
137
- <textarea class="sui-form-control"
138
- id="detect_404_ignored_filetypes" name="detect_404_ignored_filetypes"
139
- rows="8"><?php echo $settings->detect_404_ignored_filetypes ?></textarea>
140
- <span class="sui-description">
141
- <?php esc_html_e( "Defender will log the 404 error, but won’t lockout the user for these filetypes.", "defender-security" ) ?>
142
- </span>
143
- </div>
144
- </div>
145
- </div>
146
- <div class="sui-box-settings-row">
147
- <div class="sui-box-settings-col-1">
148
- <span class="sui-settings-label">
149
- <?php esc_html_e( "Exclusions", "defender-security" ) ?>
150
- </span>
151
- <span class="sui-description">
152
- <?php esc_html_e( "By default, Defender will monitor all interactions with your website but you can choose to disable 404 detection for specific areas of your site.", "defender-security" ) ?>
153
- </span>
154
- </div>
155
- <div class="sui-box-settings-col-2">
156
- <div class="sui-form-field">
157
- <input type="hidden" name="detect_404_logged" value="0"/>
158
- <label class="sui-toggle">
159
- <input id="detect_404_logged" <?php checked( 1, $settings->detect_404_logged ) ?>
160
- type="checkbox"
161
- name="detect_404_logged" value="1">
162
- <span class="sui-toggle-slider"></span>
163
- </label>
164
- <label for="detect_404_logged" class="sui-toggle-label">
165
- <?php _e( "Monitor 404s from logged in users", "defender-security" ) ?>
166
- </label>
167
- </div>
168
- </div>
169
- <?php wp_nonce_field( 'saveLockoutSettings' ) ?>
170
- <input type="hidden" name="action" value="saveLockoutSettings"/>
171
- </div>
172
- <div class="sui-box-settings-row">
173
- <div class="sui-box-settings-col-1">
174
- <span class="sui-settings-label">
175
- <?php _e( "Deactivate", "defender-security" ) ?>
176
- </span>
177
- <span class="sui-description">
178
- <?php esc_html_e( "If you no longer want to use this feature you can turn it off at any time.", "defender-security" ) ?>
179
- </span>
180
- </div>
181
- <div class="sui-box-settings-col-2">
182
- <button type="button" class="sui-button sui-button-ghost deactivate-404-lockout">
183
- <?php _e( "Deactivate", "defender-security" ) ?>
184
- </button>
185
- </div>
186
- </div>
187
- </div>
188
- <div class="sui-box-footer">
189
- <div class="sui-actions-right">
190
- <button type="submit" class="sui-button sui-button-blue">
191
- <i class="sui-icon-save" aria-hidden="true"></i>
192
- <?php _e( "Save Changes", "defender-security" ) ?></button>
193
- </div>
194
- </div>
195
- </form>
196
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/ip-lockout/view/emails/404-ban.php DELETED
@@ -1,694 +0,0 @@
1
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
- <html xmlns="http://www.w3.org/1999/xhtml">
3
-
4
- <head>
5
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
6
- <meta name="viewport" content="width=device-width">
7
- <title><?php _e( "New 404 Lockout", "defender-security" ) ?></title>
8
- <style>
9
- a.plugin-brand:hover {
10
- color: #e23717 !important;
11
- }
12
-
13
- table.top-content td a:hover {
14
- color: #ff5c28 !important;
15
- }
16
- </style>
17
- </head>
18
-
19
- <body
20
- style="-moz-box-sizing: border-box; -ms-text-size-adjust: 100%; -webkit-box-sizing: border-box; -webkit-text-size-adjust: 100%; Margin: 0; background-color: #e9ebe7; box-sizing: border-box; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0; min-width: 100%; padding: 0; text-align: left; width: 100% !important;">
21
- <style>
22
- @media only screen {
23
- html {
24
- min-height: 100%;
25
- background: #f3f3f3;
26
- }
27
- }
28
-
29
- @media only screen and (max-width: 596px) {
30
- .small-float-center {
31
- margin: 0 auto !important;
32
- float: none !important;
33
- text-align: center !important;
34
- }
35
-
36
- .small-text-center {
37
- text-align: center !important;
38
- }
39
-
40
- .small-text-left {
41
- text-align: left !important;
42
- }
43
-
44
- .small-text-right {
45
- text-align: right !important;
46
- }
47
- }
48
-
49
- @media only screen and (max-width: 596px) {
50
- .hide-for-large {
51
- display: block !important;
52
- width: auto !important;
53
- overflow: visible !important;
54
- max-height: none !important;
55
- font-size: inherit !important;
56
- line-height: inherit !important;
57
- }
58
- }
59
-
60
- @media only screen and (max-width: 596px) {
61
- table.body table.container .hide-for-large,
62
- table.body table.container .row.hide-for-large {
63
- display: table !important;
64
- width: 100% !important;
65
- }
66
- }
67
-
68
- @media only screen and (max-width: 596px) {
69
- table.body table.container .callout-inner.hide-for-large {
70
- display: table-cell !important;
71
- width: 100% !important;
72
- }
73
- }
74
-
75
- @media only screen and (max-width: 596px) {
76
- table.body table.container .show-for-large {
77
- display: none !important;
78
- width: 0;
79
- mso-hide: all;
80
- overflow: hidden;
81
- }
82
- }
83
-
84
- @media only screen and (max-width: 596px) {
85
- table.body img {
86
- width: auto;
87
- height: auto;
88
- }
89
-
90
- table.body center {
91
- min-width: 0 !important;
92
- }
93
-
94
- table.body .container {
95
- width: 95% !important;
96
- }
97
-
98
- table.body .columns,
99
- table.body .column {
100
- height: auto !important;
101
- -moz-box-sizing: border-box;
102
- -webkit-box-sizing: border-box;
103
- box-sizing: border-box;
104
- padding-left: 16px !important;
105
- padding-right: 16px !important;
106
- }
107
-
108
- table.body .columns .column,
109
- table.body .columns .columns,
110
- table.body .column .column,
111
- table.body .column .columns {
112
- padding-left: 0 !important;
113
- padding-right: 0 !important;
114
- }
115
-
116
- table.body .collapse .columns,
117
- table.body .collapse .column {
118
- padding-left: 0 !important;
119
- padding-right: 0 !important;
120
- }
121
-
122
- td.small-1,
123
- th.small-1 {
124
- display: inline-block !important;
125
- width: 8.33333% !important;
126
- }
127
-
128
- td.small-2,
129
- th.small-2 {
130
- display: inline-block !important;
131
- width: 16.66667% !important;
132
- }
133
-
134
- td.small-3,
135
- th.small-3 {
136
- display: inline-block !important;
137
- width: 25% !important;
138
- }
139
-
140
- td.small-4,
141
- th.small-4 {
142
- display: inline-block !important;
143
- width: 33.33333% !important;
144
- }
145
-
146
- td.small-5,
147
- th.small-5 {
148
- display: inline-block !important;
149
- width: 41.66667% !important;
150
- }
151
-
152
- td.small-6,
153
- th.small-6 {
154
- display: inline-block !important;
155
- width: 50% !important;
156
- }
157
-
158
- td.small-7,
159
- th.small-7 {
160
- display: inline-block !important;
161
- width: 58.33333% !important;
162
- }
163
-
164
- td.small-8,
165
- th.small-8 {
166
- display: inline-block !important;
167
- width: 66.66667% !important;
168
- }
169
-
170
- td.small-9,
171
- th.small-9 {
172
- display: inline-block !important;
173
- width: 75% !important;
174
- }
175
-
176
- td.small-10,
177
- th.small-10 {
178
- display: inline-block !important;
179
- width: 83.33333% !important;
180
- }
181
-
182
- td.small-11,
183
- th.small-11 {
184
- display: inline-block !important;
185
- width: 91.66667% !important;
186
- }
187
-
188
- td.small-12,
189
- th.small-12 {
190
- display: inline-block !important;
191
- width: 100% !important;
192
- }
193
-
194
- .columns td.small-12,
195
- .column td.small-12,
196
- .columns th.small-12,
197
- .column th.small-12 {
198
- display: block !important;
199
- width: 100% !important;
200
- }
201
-
202
- table.body td.small-offset-1,
203
- table.body th.small-offset-1 {
204
- margin-left: 8.33333% !important;
205
- Margin-left: 8.33333% !important;
206
- }
207
-
208
- table.body td.small-offset-2,
209
- table.body th.small-offset-2 {
210
- margin-left: 16.66667% !important;
211
- Margin-left: 16.66667% !important;
212
- }
213
-
214
- table.body td.small-offset-3,
215
- table.body th.small-offset-3 {
216
- margin-left: 25% !important;
217
- Margin-left: 25% !important;
218
- }
219
-
220
- table.body td.small-offset-4,
221
- table.body th.small-offset-4 {
222
- margin-left: 33.33333% !important;
223
- Margin-left: 33.33333% !important;
224
- }
225
-
226
- table.body td.small-offset-5,
227
- table.body th.small-offset-5 {
228
- margin-left: 41.66667% !important;
229
- Margin-left: 41.66667% !important;
230
- }
231
-
232
- table.body td.small-offset-6,
233
- table.body th.small-offset-6 {
234
- margin-left: 50% !important;
235
- Margin-left: 50% !important;
236
- }
237
-
238
- table.body td.small-offset-7,
239
- table.body th.small-offset-7 {
240
- margin-left: 58.33333% !important;
241
- Margin-left: 58.33333% !important;
242
- }
243
-
244
- table.body td.small-offset-8,
245
- table.body th.small-offset-8 {
246
- margin-left: 66.66667% !important;
247
- Margin-left: 66.66667% !important;
248
- }
249
-
250
- table.body td.small-offset-9,
251
- table.body th.small-offset-9 {
252
- margin-left: 75% !important;
253
- Margin-left: 75% !important;
254
- }
255
-
256
- table.body td.small-offset-10,
257
- table.body th.small-offset-10 {
258
- margin-left: 83.33333% !important;
259
- Margin-left: 83.33333% !important;
260
- }
261
-
262
- table.body td.small-offset-11,
263
- table.body th.small-offset-11 {
264
- margin-left: 91.66667% !important;
265
- Margin-left: 91.66667% !important;
266
- }
267
-
268
- table.body table.columns td.expander,
269
- table.body table.columns th.expander {
270
- display: none !important;
271
- }
272
-
273
- table.body .right-text-pad,
274
- table.body .text-pad-right {
275
- padding-left: 10px !important;
276
- }
277
-
278
- table.body .left-text-pad,
279
- table.body .text-pad-left {
280
- padding-right: 10px !important;
281
- }
282
-
283
- table.menu {
284
- width: 100% !important;
285
- }
286
-
287
- table.menu td,
288
- table.menu th {
289
- width: auto !important;
290
- display: inline-block !important;
291
- }
292
-
293
- table.menu.vertical td,
294
- table.menu.vertical th,
295
- table.menu.small-vertical td,
296
- table.menu.small-vertical th {
297
- display: block !important;
298
- }
299
-
300
- table.menu[align="center"] {
301
- width: auto !important;
302
- }
303
-
304
- table.button.small-expand,
305
- table.button.small-expanded {
306
- width: 100% !important;
307
- }
308
-
309
- table.button.small-expand table,
310
- table.button.small-expanded table {
311
- width: 100%;
312
- }
313
-
314
- table.button.small-expand table a,
315
- table.button.small-expanded table a {
316
- text-align: center !important;
317
- width: 100% !important;
318
- padding-left: 0 !important;
319
- padding-right: 0 !important;
320
- }
321
-
322
- table.button.small-expand center,
323
- table.button.small-expanded center {
324
- min-width: 0;
325
- }
326
- }
327
-
328
- @media screen and (max-width: 596px) {
329
- /* results list */
330
- table.results-list thead th {
331
- line-height: 34px !important;
332
- }
333
-
334
- /* top */
335
- table.top-content td {
336
- text-align: center !important;
337
- }
338
-
339
- /* related */
340
- table.related table.related-items .columns {
341
- padding-right: 0 !important;
342
- padding-bottom: 15px !important;
343
- padding-left: 0 !important;
344
- }
345
-
346
- table.related table.related-items .columns.last {
347
- padding-bottom: 0 !important;
348
- }
349
-
350
- table.related a.related-item .plugin-info {
351
- vertical-align: middle !important;
352
- }
353
-
354
- /* company info */
355
- table.company-info .columns {
356
- padding-right: 0 !important;
357
- padding-left: 0 !important;
358
- }
359
-
360
- table.company-info .columns.last {
361
- padding: 15px 0 0 !important;
362
- }
363
-
364
- table.company-info .logo,
365
- table.company-info .logo-link,
366
- table.company-info .logo img {
367
- text-align: left !important;
368
- }
369
- }
370
-
371
- @media screen and (max-width: 540px) {
372
- /* hero */
373
- table.hero table.hero-content {
374
- width: 100%;
375
- }
376
-
377
- table.hero td.hero-title h1,
378
- table.hero td.hero-title h2 {
379
- padding: 0 !important;
380
- text-align: center !important;
381
- }
382
-
383
- table.hero td.hero-image {
384
- display: none;
385
- }
386
- }
387
- </style>
388
-
389
- <table class="body"
390
- style="Margin: 0; background: #f3f3f3; background-color: #e9ebe7; border-collapse: collapse; border-spacing: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; height: 100%; line-height: 26px; margin: 0; padding: 0; text-align: left; vertical-align: top; width: 100%;">
391
- <tbody>
392
- <tr style="padding: 0; text-align: left; vertical-align: top;">
393
- <td class="center" align="center" valign="top"
394
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; text-align: left; vertical-align: top; word-wrap: break-word;">
395
-
396
- <center style="min-width: 600px; width: 100%;">
397
-
398
- <table class="container"
399
- style="Margin: 0 auto; background: #fefefe; background-color: #fff; border-collapse: collapse; border-spacing: 0; margin: 0 auto; padding: 0; text-align: inherit; vertical-align: top; width: 600px;">
400
- <tbody>
401
- <tr style="padding: 0; text-align: left; vertical-align: top;">
402
- <td style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; text-align: left; vertical-align: top; word-wrap: break-word;">
403
- <table class="wrapper hero" align="left"
404
- style="background-color: #e9ebe7; border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top; width: 100%;">
405
- <tbody>
406
- <tr style="padding: 0; text-align: left; vertical-align: top;">
407
- <td class="wrapper-inner hero-inner"
408
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 20px 0 0; text-align: left; vertical-align: top; word-wrap: break-word;">
409
-
410
- <table class="hero-content" align="left"
411
- style="border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top;">
412
- <tbody>
413
- <tr style="padding: 0; text-align: left; vertical-align: top;">
414
- <td class="hero-title"
415
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; padding-bottom: 18px; text-align: left; vertical-align: bottom; word-wrap: break-word;">
416
- <h2 style="Margin: 0; Margin-bottom: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 30px; font-weight: 700; line-height: 1em; margin: 0; margin-bottom: 0; padding: 0; padding-left: 9px; text-align: left; text-transform: uppercase; word-wrap: normal;">
417
- <?php esc_html_e( "Protected By", "defender-security" ) ?></h2>
418
- <h1 class="plugin-brand"
419
- style="Margin: 0; Margin-bottom: 0; color: #ff5c28; font-family: Helvetica, Arial, sans-serif; font-size: 60px; font-weight: 700; line-height: 1em; margin: 0; margin-bottom: 0; padding: 0; padding-left: 6px; text-align: left; text-transform: uppercase; word-wrap: normal;">
420
- <?php esc_html_e( "Defender!", "defender-security" ) ?></h1>
421
- </td>
422
- <td class="hero-image"
423
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; text-align: left; vertical-align: top; word-wrap: break-word;">
424
- <a href="https://premium.wpmudev.org/"
425
- style="Margin: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-weight: normal; line-height: 1.3; margin: 0; padding: 0; text-align: left; text-decoration: none;"><img
426
- src="<?php echo wp_defender()->getPluginUrl() ?>assets/email-images/hero-defender.png"
427
- alt="Defender"
428
- style="-ms-interpolation-mode: bicubic; border: none; clear: both; display: block; max-width: 100%; outline: none; text-decoration: none; width: auto;"></a>
429
- </td>
430
- </tr>
431
- </tbody>
432
- </table>
433
- <!-- end hero-content -->
434
-
435
- </td>
436
- </tr>
437
- </tbody>
438
- </table>
439
- <!-- end hero -->
440
-
441
- <table class="wrapper main" align="center"
442
- style="border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top; width: 100%;">
443
- <tbody>
444
- <tr style="padding: 0; text-align: left; vertical-align: top;">
445
- <td class="wrapper-inner main-inner"
446
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 40px; text-align: left; vertical-align: top; word-wrap: break-word;">
447
-
448
- <table class="main-intro"
449
- style="border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top;">
450
- <tbody>
451
- <tr style="padding: 0; text-align: left; vertical-align: top;">
452
- <td class="main-intro-content"
453
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; text-align: left; vertical-align: top; word-wrap: break-word;">
454
- <h3 style="Margin: 0; Margin-bottom: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 32px; font-weight: normal; line-height: 32px; margin: 0; margin-bottom: 0; padding: 0 0 28px; text-align: left; word-wrap: normal;">
455
- <?php printf( __( "Hi %s", "defender-security" ), $admin ) ?>
456
- ,</h3>
457
- <?php $setting = \WP_Defender\Module\IP_Lockout\Model\Settings::instance() ?>
458
- <?php $utils = \WP_Defender\Behavior\Utils::instance() ?>
459
- <p style="Margin: 0; Margin-bottom: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0; margin-bottom: 0; padding: 0 0 24px; text-align: left;">
460
- <?php printf( __( "We've just locked out the host <strong>%s</strong> from %s due to more than <strong>%s</strong> 404 requests for the file <strong>%s</strong>. They have been banned permanently.", "defender-security" ), $ip, network_site_url(), $setting->detect_404_threshold, $uri, $setting->detect_404_lockout_duration ) ?>
461
- </p>
462
- <p style="Margin: 0; Margin-bottom: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0; margin-bottom: 0; padding: 0 0 24px; text-align: left;">
463
- <?php printf( __( "You can view the full lockout logs <a href=\"%s\">here</a>", "defender-security" ), apply_filters( 'wp_defeder/iplockout/email_report_link', network_admin_url( "admin.php?page=wdf-ip-lockout&view=logs" ) ) ) ?>
464
- .</p>
465
- </td>
466
- </tr>
467
- </tbody>
468
- </table>
469
- <!-- end main-intro -->
470
-
471
- <table class="main-signature"
472
- style="border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top;">
473
- <tbody>
474
- <tr style="padding: 0; text-align: left; vertical-align: top;">
475
- <td class="main-signature-content"
476
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; text-align: left; vertical-align: top; word-wrap: break-word;">
477
- <p style="Margin: 0; Margin-bottom: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0; margin-bottom: 0; padding: 0 0 24px; text-align: left;">
478
- <?php esc_html_e( "Stay vigilant.", "defender-security" ) ?></p>
479
- <p class="last-item"
480
- style="Margin: 0; Margin-bottom: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0; margin-bottom: 0; padding: 0; text-align: left;">
481
- <strong><?php esc_html_e( "WP Defender", "defender-security" ) ?></strong>
482
- <br>
483
- <?php esc_html_e( "Security Hero", "defender-security" ) ?>
484
- <br/>
485
- <?php esc_html_e( "WPMU DEV", "defender-security" ) ?>
486
- </p>
487
- </td>
488
- </tr>
489
- </tbody>
490
- </table>
491
- <!-- end main-signature -->
492
-
493
- </td>
494
- </tr>
495
- </tbody>
496
- </table>
497
- <!-- end main -->
498
-
499
- <table class="related" align="center"
500
- style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; text-align: left; vertical-align: top; width: 100%;">
501
- <tbody>
502
- <tr style="padding: 0; text-align: left; vertical-align: top;">
503
- <td class="related-inner"
504
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; border-top: 2px solid #e9ebe7; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 15px 30px 15px 40px; text-align: left; vertical-align: top; word-wrap: break-word;">
505
- <table
506
- style="border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top;">
507
- <tbody>
508
- <tr style="padding: 0; text-align: left; vertical-align: top;">
509
- <td class="related-items-title brand" align="left"
510
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #3eb4e4; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; padding-bottom: 10px; text-align: left; vertical-align: top; word-wrap: break-word;">
511
- <?php esc_html_e( "Related plugins worth giving a try", "defender-security" ) ?>
512
- </td>
513
- </tr>
514
- <tr style="padding: 0; text-align: left; vertical-align: top;">
515
- <td style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; text-align: left; vertical-align: top; word-wrap: break-word;">
516
- <table class="related-items row collapse" align="center"
517
- style="border-collapse: collapse; border-spacing: 0; display: table; padding: 0; position: relative; text-align: left; vertical-align: top; width: 100%;">
518
- <tbody>
519
- <tr style="padding: 0; text-align: left; vertical-align: top;">
520
- <th class="small-12 large-6 columns first" align="left"
521
- valign="top"
522
- style="Margin: 0 auto; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0 auto; padding: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; text-align: left; width: 298px;">
523
- <a class="related-item plugin-link"
524
- href="https://premium.wpmudev.org/project/wp-hummingbird/"
525
- style="Margin: 0; color: #555555; display: table; font-family: Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 20px; margin: 0; padding: 0; text-align: left; text-decoration: none;">
526
- <img
527
- src="<?php echo wp_defender()->getPluginUrl() ?>assets/email-images/plugin-hummingbird.png"
528
- alt="Hummingbird" class="plugin-image"
529
- style="-ms-interpolation-mode: bicubic; border: none; clear: both; display: table-cell; max-width: 100%; outline: none; text-decoration: none; width: auto;">
530
- <span class="plugin-info"
531
- style="display: table-cell; padding-left: 10px; vertical-align: bottom;">
532
- <span><?php esc_html_e( "Optimize your site with", "defender-security" ) ?></span>
533
- <span class="plugin-title hummingbird"
534
- style="color: #febd30; display: block;"><strong><?php esc_html_e( "Hummingbird", "defender-security" ) ?></strong></span>
535
- </span>
536
- </a>
537
- </th>
538
- <th class="small-12 large-6 columns last" align="left"
539
- valign="top"
540
- style="Margin: 0 auto; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0 auto; padding: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; text-align: left; width: 298px;">
541
- <a class="related-item plugin-link"
542
- href="https://premium.wpmudev.org/project/snapshot/"
543
- style="Margin: 0; color: #555555; display: table; font-family: Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 20px; margin: 0; padding: 0; text-align: left; text-decoration: none;">
544
- <img
545
- src="<?php echo wp_defender()->getPluginUrl() ?>assets/email-images/plugin-snapshot.png"
546
- alt="Snapshot"
547
- class="plugin-image"
548
- style="-ms-interpolation-mode: bicubic; border: none; clear: both; display: table-cell; max-width: 100%; outline: none; text-decoration: none; width: auto;">
549
- <span class="plugin-info"
550
- style="display: table-cell; padding-left: 10px; vertical-align: bottom;">
551
- <span><?php esc_html_e( "Back up your hard work with", "defender-security" ) ?></span>
552
- <span class="plugin-title snapshot"
553
- style="color: #642486; display: block;"><strong><?php _e( "Snapshot", "defender-security" ) ?></strong></span>
554
- </span>
555
- </a>
556
- </th>
557
- <th class="expander"
558
- style="Margin: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0; padding: 0 !important; text-align: left; visibility: hidden; width: 0;"></th>
559
- </tr>
560
- </tbody>
561
- </table>
562
- </td>
563
- </tr>
564
- </tbody>
565
- </table>
566
- <!-- end related-inner -->
567
- </td>
568
- </tr>
569
- </tbody>
570
- </table>
571
- <!-- end related -->
572
-
573
- <!-- Preferences -->
574
- <table class="email-preferences" align="center" valign="middle"
575
- style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; text-align: left; vertical-align: top; width: 100%;">
576
- <tbody>
577
- <tr style="padding: 0; text-align: center; vertical-align: top;">
578
- <td class="email-preferences-inner"
579
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; border-top: 2px solid #e9ebe7; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 40px; text-align: left; vertical-align: top; word-wrap: break-word;">
580
- <table class="email-preferences-content row collapse" align="center"
581
- valign="top"
582
- style="border-collapse: collapse; border-spacing: 0; display: table; padding: 0; position: relative; text-align: center; vertical-align: top; width: 100%;">
583
- <tbody>
584
- <tr style="padding: 0; text-align: center; vertical-align: top;">
585
- <th class="small-12 large-8 columns first copy" align="center"
586
- style="Margin: 0 auto; color: #707070; font-family: Helvetica, Arial, sans-serif; font-size: 12px; font-weight: normal; line-height: 20px; margin: 0 auto; padding: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; text-align: left; width: 394.66667px;">
587
- <p style="Margin: 0; Margin-bottom: 0; color: #707070; font-family: Helvetica, Arial, sans-serif; font-size: 12px; font-weight: normal; line-height: 20px; margin: 0; margin-bottom: 0; padding: 0; text-align: center;">
588
- <?php printf( __( "<a href=\"%s\">Configure reporting preferences</a>", "defender-security" ), apply_filters( 'wp_defeder/iplockout/email_report_link', network_admin_url( "admin.php?page=wdf-ip-lockout&view=notification" ) ) ) ?>
589
- </p>
590
- </th>
591
- </tr>
592
- </tbody>
593
- </table>
594
- </td>
595
- </tr>
596
- </tbody>
597
- </table>
598
- <!-- End Preferences -->
599
-
600
- <table class="company-info" align="left" valign="middle"
601
- style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; text-align: left; vertical-align: top; width: 100%;">
602
- <tbody>
603
- <tr style="padding: 0; text-align: left; vertical-align: top;">
604
- <td class="company-info-inner"
605
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; border-top: 2px solid #e9ebe7; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 40px; text-align: left; vertical-align: top; word-wrap: break-word;">
606
- <table class="company-info-content row collapse" align="left" valign="top"
607
- style="border-collapse: collapse; border-spacing: 0; display: table; padding: 0; position: relative; text-align: left; vertical-align: top; width: 100%;">
608
- <tbody>
609
- <tr style="padding: 0; text-align: left; vertical-align: top;">
610
- <th class="small-12 large-8 columns first copy" align="left"
611
- style="Margin: 0 auto; color: #707070; font-family: Helvetica, Arial, sans-serif; font-size: 12px; font-weight: normal; line-height: 20px; margin: 0 auto; padding: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; text-align: left; width: 394.66667px;">
612
- <p style="Margin: 0; Margin-bottom: 0; color: #707070; font-family: Helvetica, Arial, sans-serif; font-size: 12px; font-weight: normal; line-height: 20px; margin: 0; margin-bottom: 0; padding: 0; text-align: left;">
613
- Copyright © Incsub, All rights reserved.</p>
614
- <p style="Margin: 0; Margin-bottom: 0; color: #707070; font-family: Helvetica, Arial, sans-serif; font-size: 12px; font-weight: normal; line-height: 20px; margin: 0; margin-bottom: 0; padding: 0; text-align: left;">
615
- Incsub PO box 163 Albert Park, Victoria 3206 Australia</p>
616
- </th>
617
- <th class="small-12 large-4 columns last logo" align="right"
618
- style="Margin: 0 auto; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0 auto; padding: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; text-align: right; width: 201.33333px;">
619
- <a href="https://premium.wpmudev.org" class="logo-link"
620
- style="Margin: 0; color: #555555; display: inline-block; font-family: Helvetica, Arial, sans-serif; font-weight: normal; line-height: 1.3; margin: 0; padding: 0; text-align: right; text-decoration: none;">
621
- <img
622
- src="<?php echo wp_defender()->getPluginUrl() ?>assets/email-images/wpmudev-logo.png"
623
- alt="WPMU DEV"
624
- style="-ms-interpolation-mode: bicubic; border: none; clear: both; display: inline-block; max-width: 100%; outline: none; text-align: right; text-decoration: none; width: auto;">
625
- </a>
626
- </th>
627
- <th class="expander"
628
- style="Margin: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0; padding: 0 !important; text-align: left; visibility: hidden; width: 0;"></th>
629
- </tr>
630
- </tbody>
631
- </table>
632
- </td>
633
- </tr>
634
- </tbody>
635
- </table>
636
- <!-- end company-info -->
637
-
638
- <table class="wrapper social" align="center"
639
- style="background-color: #e9ebe7; border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top; width: 100%;">
640
- <tbody>
641
- <tr style="padding: 0; text-align: left; vertical-align: top;">
642
- <td class="wrapper-inner social-inner"
643
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 40px 60px 20px; text-align: left; vertical-align: top; word-wrap: break-word;">
644
-
645
- <table class="social-content" align="center"
646
- style="border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top;">
647
- <tbody>
648
- <tr style="padding: 0; text-align: left; vertical-align: top;">
649
- <td class="social-content-inner"
650
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; text-align: center; vertical-align: top; word-wrap: break-word;">
651
- <a href="https://plus.google.com/+wpmuorg/" target="_blank"
652
- class="gplus"
653
- style="Margin: 0; color: #555555; display: inline-block; font-family: Helvetica, Arial, sans-serif; font-weight: normal; line-height: 1.3; margin: 0; margin-right: 4px; padding: 0; text-align: left; text-decoration: none;"><img
654
- src="<?php echo wp_defender()->getPluginUrl() ?>assets/email-images/icon-gplus.png"
655
- alt="WPMU DEV on Google+"
656
- style="-ms-interpolation-mode: bicubic; border: none; clear: both; display: block; max-width: 100%; outline: none; text-decoration: none; width: auto;"></a>
657
- <a href="https://twitter.com/wpmudev" target="_blank"
658
- class="twitter"
659
- style="Margin: 0; color: #555555; display: inline-block; font-family: Helvetica, Arial, sans-serif; font-weight: normal; line-height: 1.3; margin: 0; margin-right: 4px; padding: 0; text-align: left; text-decoration: none;"><img
660
- src="<?php echo wp_defender()->getPluginUrl() ?>assets/email-images/icon-twitter.png"
661
- alt="WPMU DEV on Twitter"
662
- style="-ms-interpolation-mode: bicubic; border: none; clear: both; display: block; max-width: 100%; outline: none; text-decoration: none; width: auto;"></a>
663
- <a href="https://www.facebook.com/wpmudev" target="_blank"
664
- class="facebook"
665
- style="Margin: 0; color: #555555; display: inline-block; font-family: Helvetica, Arial, sans-serif; font-weight: normal; line-height: 1.3; margin: 0; margin-right: 0; padding: 0; text-align: left; text-decoration: none;"><img
666
- src="<?php echo wp_defender()->getPluginUrl() ?>assets/email-images/icon-facebook.png"
667
- alt="WPMU DEV on Facebook"
668
- style="-ms-interpolation-mode: bicubic; border: none; clear: both; display: block; max-width: 100%; outline: none; text-decoration: none; width: auto;"></a>
669
- </td>
670
- </tr>
671
- </tbody>
672
- </table>
673
- <!-- end social-content -->
674
-
675
- </td>
676
- </tr>
677
- </tbody>
678
- </table>
679
- <!-- end top -->
680
- </td>
681
- </tr>
682
- </tbody>
683
- </table>
684
- <!-- end main container -->
685
-
686
- </center>
687
-
688
- </td>
689
- </tr>
690
- </tbody>
691
- </table>
692
- <!-- end body -->
693
- </body>
694
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/ip-lockout/view/emails/404-lockout.php DELETED
@@ -1,697 +0,0 @@
1
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
- <html xmlns="http://www.w3.org/1999/xhtml">
3
-
4
- <head>
5
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
6
- <meta name="viewport" content="width=device-width">
7
- <title><?php _e( "New 404 Lockout", "defender-security" ) ?></title>
8
- <style>
9
- a.plugin-brand:hover {
10
- color: #e23717 !important;
11
- }
12
-
13
- table.top-content td a:hover {
14
- color: #ff5c28 !important;
15
- }
16
- </style>
17
- </head>
18
-
19
- <body
20
- style="-moz-box-sizing: border-box; -ms-text-size-adjust: 100%; -webkit-box-sizing: border-box; -webkit-text-size-adjust: 100%; Margin: 0; background-color: #e9ebe7; box-sizing: border-box; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0; min-width: 100%; padding: 0; text-align: left; width: 100% !important;">
21
- <style>
22
- @media only screen {
23
- html {
24
- min-height: 100%;
25
- background: #f3f3f3;
26
- }
27
- }
28
-
29
- @media only screen and (max-width: 596px) {
30
- .small-float-center {
31
- margin: 0 auto !important;
32
- float: none !important;
33
- text-align: center !important;
34
- }
35
-
36
- .small-text-center {
37
- text-align: center !important;
38
- }
39
-
40
- .small-text-left {
41
- text-align: left !important;
42
- }
43
-
44
- .small-text-right {
45
- text-align: right !important;
46
- }
47
- }
48
-
49
- @media only screen and (max-width: 596px) {
50
- .hide-for-large {
51
- display: block !important;
52
- width: auto !important;
53
- overflow: visible !important;
54
- max-height: none !important;
55
- font-size: inherit !important;
56
- line-height: inherit !important;
57
- }
58
- }
59
-
60
- @media only screen and (max-width: 596px) {
61
- table.body table.container .hide-for-large,
62
- table.body table.container .row.hide-for-large {
63
- display: table !important;
64
- width: 100% !important;
65
- }
66
- }
67
-
68
- @media only screen and (max-width: 596px) {
69
- table.body table.container .callout-inner.hide-for-large {
70
- display: table-cell !important;
71
- width: 100% !important;
72
- }
73
- }
74
-
75
- @media only screen and (max-width: 596px) {
76
- table.body table.container .show-for-large {
77
- display: none !important;
78
- width: 0;
79
- mso-hide: all;
80
- overflow: hidden;
81
- }
82
- }
83
-
84
- @media only screen and (max-width: 596px) {
85
- table.body img {
86
- width: auto;
87
- height: auto;
88
- }
89
-
90
- table.body center {
91
- min-width: 0 !important;
92
- }
93
-
94
- table.body .container {
95
- width: 95% !important;
96
- }
97
-
98
- table.body .columns,
99
- table.body .column {
100
- height: auto !important;
101
- -moz-box-sizing: border-box;
102
- -webkit-box-sizing: border-box;
103
- box-sizing: border-box;
104
- padding-left: 16px !important;
105
- padding-right: 16px !important;
106
- }
107
-
108
- table.body .columns .column,
109
- table.body .columns .columns,
110
- table.body .column .column,
111
- table.body .column .columns {
112
- padding-left: 0 !important;
113
- padding-right: 0 !important;
114
- }
115
-
116
- table.body .collapse .columns,
117
- table.body .collapse .column {
118
- padding-left: 0 !important;
119
- padding-right: 0 !important;
120
- }
121
-
122
- td.small-1,
123
- th.small-1 {
124
- display: inline-block !important;
125
- width: 8.33333% !important;
126
- }
127
-
128
- td.small-2,
129
- th.small-2 {
130
- display: inline-block !important;
131
- width: 16.66667% !important;
132
- }
133
-
134
- td.small-3,
135
- th.small-3 {
136
- display: inline-block !important;
137
- width: 25% !important;
138
- }
139
-
140
- td.small-4,
141
- th.small-4 {
142
- display: inline-block !important;
143
- width: 33.33333% !important;
144
- }
145
-
146
- td.small-5,
147
- th.small-5 {
148
- display: inline-block !important;
149
- width: 41.66667% !important;
150
- }
151
-
152
- td.small-6,
153
- th.small-6 {
154
- display: inline-block !important;
155
- width: 50% !important;
156
- }
157
-
158
- td.small-7,
159
- th.small-7 {
160
- display: inline-block !important;
161
- width: 58.33333% !important;
162
- }
163
-
164
- td.small-8,
165
- th.small-8 {
166
- display: inline-block !important;
167
- width: 66.66667% !important;
168
- }
169
-
170
- td.small-9,
171
- th.small-9 {
172
- display: inline-block !important;
173
- width: 75% !important;
174
- }
175
-
176
- td.small-10,
177
- th.small-10 {
178
- display: inline-block !important;
179
- width: 83.33333% !important;
180
- }
181
-
182
- td.small-11,
183
- th.small-11 {
184
- display: inline-block !important;
185
- width: 91.66667% !important;
186
- }
187
-
188
- td.small-12,
189
- th.small-12 {
190
- display: inline-block !important;
191
- width: 100% !important;
192
- }
193
-
194
- .columns td.small-12,
195
- .column td.small-12,
196
- .columns th.small-12,
197
- .column th.small-12 {
198
- display: block !important;
199
- width: 100% !important;
200
- }
201
-
202
- table.body td.small-offset-1,
203
- table.body th.small-offset-1 {
204
- margin-left: 8.33333% !important;
205
- Margin-left: 8.33333% !important;
206
- }
207
-
208
- table.body td.small-offset-2,
209
- table.body th.small-offset-2 {
210
- margin-left: 16.66667% !important;
211
- Margin-left: 16.66667% !important;
212
- }
213
-
214
- table.body td.small-offset-3,
215
- table.body th.small-offset-3 {
216
- margin-left: 25% !important;
217
- Margin-left: 25% !important;
218
- }
219
-
220
- table.body td.small-offset-4,
221
- table.body th.small-offset-4 {
222
- margin-left: 33.33333% !important;
223
- Margin-left: 33.33333% !important;
224
- }
225
-
226
- table.body td.small-offset-5,
227
- table.body th.small-offset-5 {
228
- margin-left: 41.66667% !important;
229
- Margin-left: 41.66667% !important;
230
- }
231
-
232
- table.body td.small-offset-6,
233
- table.body th.small-offset-6 {
234
- margin-left: 50% !important;
235
- Margin-left: 50% !important;
236
- }
237
-
238
- table.body td.small-offset-7,
239
- table.body th.small-offset-7 {
240
- margin-left: 58.33333% !important;
241
- Margin-left: 58.33333% !important;
242
- }
243
-
244
- table.body td.small-offset-8,
245
- table.body th.small-offset-8 {
246
- margin-left: 66.66667% !important;
247
- Margin-left: 66.66667% !important;
248
- }
249
-
250
- table.body td.small-offset-9,
251
- table.body th.small-offset-9 {
252
- margin-left: 75% !important;
253
- Margin-left: 75% !important;
254
- }
255
-
256
- table.body td.small-offset-10,
257
- table.body th.small-offset-10 {
258
- margin-left: 83.33333% !important;
259
- Margin-left: 83.33333% !important;
260
- }
261
-
262
- table.body td.small-offset-11,
263
- table.body th.small-offset-11 {
264
- margin-left: 91.66667% !important;
265
- Margin-left: 91.66667% !important;
266
- }
267
-
268
- table.body table.columns td.expander,
269
- table.body table.columns th.expander {
270
- display: none !important;
271
- }
272
-
273
- table.body .right-text-pad,
274
- table.body .text-pad-right {
275
- padding-left: 10px !important;
276
- }
277
-
278
- table.body .left-text-pad,
279
- table.body .text-pad-left {
280
- padding-right: 10px !important;
281
- }
282
-
283
- table.menu {
284
- width: 100% !important;
285
- }
286
-
287
- table.menu td,
288
- table.menu th {
289
- width: auto !important;
290
- display: inline-block !important;
291
- }
292
-
293
- table.menu.vertical td,
294
- table.menu.vertical th,
295
- table.menu.small-vertical td,
296
- table.menu.small-vertical th {
297
- display: block !important;
298
- }
299
-
300
- table.menu[align="center"] {
301
- width: auto !important;
302
- }
303
-
304
- table.button.small-expand,
305
- table.button.small-expanded {
306
- width: 100% !important;
307
- }
308
-
309
- table.button.small-expand table,
310
- table.button.small-expanded table {
311
- width: 100%;
312
- }
313
-
314
- table.button.small-expand table a,
315
- table.button.small-expanded table a {
316
- text-align: center !important;
317
- width: 100% !important;
318
- padding-left: 0 !important;
319
- padding-right: 0 !important;
320
- }
321
-
322
- table.button.small-expand center,
323
- table.button.small-expanded center {
324
- min-width: 0;
325
- }
326
- }
327
-
328
- @media screen and (max-width: 596px) {
329
- /* results list */
330
- table.results-list thead th {
331
- line-height: 34px !important;
332
- }
333
-
334
- /* top */
335
- table.top-content td {
336
- text-align: center !important;
337
- }
338
-
339
- /* related */
340
- table.related table.related-items .columns {
341
- padding-right: 0 !important;
342
- padding-bottom: 15px !important;
343
- padding-left: 0 !important;
344
- }
345
-
346
- table.related table.related-items .columns.last {
347
- padding-bottom: 0 !important;
348
- }
349
-
350
- table.related a.related-item .plugin-info {
351
- vertical-align: middle !important;
352
- }
353
-
354
- /* company info */
355
- table.company-info .columns {
356
- padding-right: 0 !important;
357
- padding-left: 0 !important;
358
- }
359
-
360
- table.company-info .columns.last {
361
- padding: 15px 0 0 !important;
362
- }
363
-
364
- table.company-info .logo,
365
- table.company-info .logo-link,
366
- table.company-info .logo img {
367
- text-align: left !important;
368
- }
369
- }
370
-
371
- @media screen and (max-width: 540px) {
372
- /* hero */
373
- table.hero table.hero-content {
374
- width: 100%;
375
- }
376
-
377
- table.hero td.hero-title h1,
378
- table.hero td.hero-title h2 {
379
- padding: 0 !important;
380
- text-align: center !important;
381
- }
382
-
383
- table.hero td.hero-image {
384
- display: none;
385
- }
386
- }
387
- </style>
388
-
389
- <table class="body"
390
- style="Margin: 0; background: #f3f3f3; background-color: #e9ebe7; border-collapse: collapse; border-spacing: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; height: 100%; line-height: 26px; margin: 0; padding: 0; text-align: left; vertical-align: top; width: 100%;">
391
- <tbody>
392
- <tr style="padding: 0; text-align: left; vertical-align: top;">
393
- <td class="center" align="center" valign="top"
394
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; text-align: left; vertical-align: top; word-wrap: break-word;">
395
-
396
- <center style="min-width: 600px; width: 100%;">
397
-
398
- <table class="container"
399
- style="Margin: 0 auto; background: #fefefe; background-color: #fff; border-collapse: collapse; border-spacing: 0; margin: 0 auto; padding: 0; text-align: inherit; vertical-align: top; width: 600px;">
400
- <tbody>
401
- <tr style="padding: 0; text-align: left; vertical-align: top;">
402
- <td style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; text-align: left; vertical-align: top; word-wrap: break-word;">
403
- <table class="wrapper hero" align="left"
404
- style="background-color: #e9ebe7; border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top; width: 100%;">
405
- <tbody>
406
- <tr style="padding: 0; text-align: left; vertical-align: top;">
407
- <td class="wrapper-inner hero-inner"
408
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 20px 0 0; text-align: left; vertical-align: top; word-wrap: break-word;">
409
-
410
- <table class="hero-content" align="left"
411
- style="border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top;">
412
- <tbody>
413
- <tr style="padding: 0; text-align: left; vertical-align: top;">
414
- <td class="hero-title"
415
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; padding-bottom: 18px; text-align: left; vertical-align: bottom; word-wrap: break-word;">
416
- <h2 style="Margin: 0; Margin-bottom: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 30px; font-weight: 700; line-height: 1em; margin: 0; margin-bottom: 0; padding: 0; padding-left: 9px; text-align: left; text-transform: uppercase; word-wrap: normal;">
417
- <?php esc_html_e( "Protected By", "defender-security" ) ?></h2>
418
- <h1 class="plugin-brand"
419
- style="Margin: 0; Margin-bottom: 0; color: #ff5c28; font-family: Helvetica, Arial, sans-serif; font-size: 60px; font-weight: 700; line-height: 1em; margin: 0; margin-bottom: 0; padding: 0; padding-left: 6px; text-align: left; text-transform: uppercase; word-wrap: normal;">
420
- <?php esc_html_e( "Defender!", "defender-security" ) ?></h1>
421
- </td>
422
- <td class="hero-image"
423
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; text-align: left; vertical-align: top; word-wrap: break-word;">
424
- <a href="https://premium.wpmudev.org/"
425
- style="Margin: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-weight: normal; line-height: 1.3; margin: 0; padding: 0; text-align: left; text-decoration: none;"><img
426
- src="<?php echo wp_defender()->getPluginUrl() ?>assets/email-images/hero-defender.png"
427
- alt="Defender"
428
- style="-ms-interpolation-mode: bicubic; border: none; clear: both; display: block; max-width: 100%; outline: none; text-decoration: none; width: auto;"></a>
429
- </td>
430
- </tr>
431
- </tbody>
432
- </table>
433
- <!-- end hero-content -->
434
-
435
- </td>
436
- </tr>
437
- </tbody>
438
- </table>
439
- <!-- end hero -->
440
-
441
- <table class="wrapper main" align="center"
442
- style="border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top; width: 100%;">
443
- <tbody>
444
- <tr style="padding: 0; text-align: left; vertical-align: top;">
445
- <td class="wrapper-inner main-inner"
446
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 40px; text-align: left; vertical-align: top; word-wrap: break-word;">
447
-
448
- <table class="main-intro"
449
- style="border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top;">
450
- <tbody>
451
- <tr style="padding: 0; text-align: left; vertical-align: top;">
452
- <td class="main-intro-content"
453
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; text-align: left; vertical-align: top; word-wrap: break-word;">
454
- <h3 style="Margin: 0; Margin-bottom: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 32px; font-weight: normal; line-height: 32px; margin: 0; margin-bottom: 0; padding: 0 0 28px; text-align: left; word-wrap: normal;">
455
- <?php printf( __( "Hi %s", "defender-security" ), $admin ) ?>
456
- ,</h3>
457
- <?php $setting = \WP_Defender\Module\IP_Lockout\Model\Settings::instance() ?>
458
- <?php $utils = \WP_Defender\Behavior\Utils::instance() ?>
459
- <p style="Margin: 0; Margin-bottom: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0; margin-bottom: 0; padding: 0 0 24px; text-align: left;">
460
- <?php
461
- \WP_Defender\Behavior\Utils::instance()->log($uri);
462
- printf( __( "We've just locked out the host <strong>%s</strong> from %s due to more than <strong>%s</strong> 404 requests for the file <strong>%s</strong>. They have been locked out for <strong>%s %s.</strong>", "defender-security" ),
463
- $ip, network_site_url(), $setting->detect_404_threshold, $uri, $setting->detect_404_lockout_duration, $setting->detect_404_lockout_duration_unit ) ?>
464
- </p>
465
- <p style="Margin: 0; Margin-bottom: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0; margin-bottom: 0; padding: 0 0 24px; text-align: left;">
466
- <?php printf( __( "You can view the full lockout logs <a href=\"%s\">here</a>", "defender-security" ), apply_filters( 'wp_defeder/iplockout/email_report_link', network_admin_url( "admin.php?page=wdf-ip-lockout&view=logs" ) ) ) ?>
467
- .</p>
468
- </td>
469
- </tr>
470
- </tbody>
471
- </table>
472
- <!-- end main-intro -->
473
-
474
- <table class="main-signature"
475
- style="border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top;">
476
- <tbody>
477
- <tr style="padding: 0; text-align: left; vertical-align: top;">
478
- <td class="main-signature-content"
479
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; text-align: left; vertical-align: top; word-wrap: break-word;">
480
- <p style="Margin: 0; Margin-bottom: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0; margin-bottom: 0; padding: 0 0 24px; text-align: left;">
481
- <?php esc_html_e( "Stay vigilant.", "defender-security" ) ?></p>
482
- <p class="last-item"
483
- style="Margin: 0; Margin-bottom: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0; margin-bottom: 0; padding: 0; text-align: left;">
484
- <strong><?php esc_html_e( "WP Defender", "defender-security" ) ?></strong>
485
- <br>
486
- <?php esc_html_e( "Security Hero", "defender-security" ) ?>
487
- <br/>
488
- <?php esc_html_e( "WPMU DEV", "defender-security" ) ?>
489
- </p>
490
- </td>
491
- </tr>
492
- </tbody>
493
- </table>
494
- <!-- end main-signature -->
495
-
496
- </td>
497
- </tr>
498
- </tbody>
499
- </table>
500
- <!-- end main -->
501
-
502
- <table class="related" align="center"
503
- style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; text-align: left; vertical-align: top; width: 100%;">
504
- <tbody>
505
- <tr style="padding: 0; text-align: left; vertical-align: top;">
506
- <td class="related-inner"
507
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; border-top: 2px solid #e9ebe7; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 15px 30px 15px 40px; text-align: left; vertical-align: top; word-wrap: break-word;">
508
- <table
509
- style="border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top;">
510
- <tbody>
511
- <tr style="padding: 0; text-align: left; vertical-align: top;">
512
- <td class="related-items-title brand" align="left"
513
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #3eb4e4; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; padding-bottom: 10px; text-align: left; vertical-align: top; word-wrap: break-word;">
514
- <?php esc_html_e( "Related plugins worth giving a try", "defender-security" ) ?>
515
- </td>
516
- </tr>
517
- <tr style="padding: 0; text-align: left; vertical-align: top;">
518
- <td style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; text-align: left; vertical-align: top; word-wrap: break-word;">
519
- <table class="related-items row collapse" align="center"
520
- style="border-collapse: collapse; border-spacing: 0; display: table; padding: 0; position: relative; text-align: left; vertical-align: top; width: 100%;">
521
- <tbody>
522
- <tr style="padding: 0; text-align: left; vertical-align: top;">
523
- <th class="small-12 large-6 columns first" align="left"
524
- valign="top"
525
- style="Margin: 0 auto; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0 auto; padding: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; text-align: left; width: 298px;">
526
- <a class="related-item plugin-link"
527
- href="https://premium.wpmudev.org/project/wp-hummingbird/"
528
- style="Margin: 0; color: #555555; display: table; font-family: Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 20px; margin: 0; padding: 0; text-align: left; text-decoration: none;">
529
- <img
530
- src="<?php echo wp_defender()->getPluginUrl() ?>assets/email-images/plugin-hummingbird.png"
531
- alt="Hummingbird" class="plugin-image"
532
- style="-ms-interpolation-mode: bicubic; border: none; clear: both; display: table-cell; max-width: 100%; outline: none; text-decoration: none; width: auto;">
533
- <span class="plugin-info"
534
- style="display: table-cell; padding-left: 10px; vertical-align: bottom;">
535
- <span><?php esc_html_e( "Optimize your site with", "defender-security" ) ?></span>
536
- <span class="plugin-title hummingbird"
537
- style="color: #febd30; display: block;"><strong><?php esc_html_e( "Hummingbird", "defender-security" ) ?></strong></span>
538
- </span>
539
- </a>
540
- </th>
541
- <th class="small-12 large-6 columns last" align="left"
542
- valign="top"
543
- style="Margin: 0 auto; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0 auto; padding: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; text-align: left; width: 298px;">
544
- <a class="related-item plugin-link"
545
- href="https://premium.wpmudev.org/project/snapshot/"
546
- style="Margin: 0; color: #555555; display: table; font-family: Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 20px; margin: 0; padding: 0; text-align: left; text-decoration: none;">
547
- <img
548
- src="<?php echo wp_defender()->getPluginUrl() ?>assets/email-images/plugin-snapshot.png"
549
- alt="Snapshot"
550
- class="plugin-image"
551
- style="-ms-interpolation-mode: bicubic; border: none; clear: both; display: table-cell; max-width: 100%; outline: none; text-decoration: none; width: auto;">
552
- <span class="plugin-info"
553
- style="display: table-cell; padding-left: 10px; vertical-align: bottom;">
554
- <span><?php esc_html_e( "Back up your hard work with", "defender-security" ) ?></span>
555
- <span class="plugin-title snapshot"
556
- style="color: #642486; display: block;"><strong><?php _e( "Snapshot", "defender-security" ) ?></strong></span>
557
- </span>
558
- </a>
559
- </th>
560
- <th class="expander"
561
- style="Margin: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0; padding: 0 !important; text-align: left; visibility: hidden; width: 0;"></th>
562
- </tr>
563
- </tbody>
564
- </table>
565
- </td>
566
- </tr>
567
- </tbody>
568
- </table>
569
- <!-- end related-inner -->
570
- </td>
571
- </tr>
572
- </tbody>
573
- </table>
574
- <!-- end related -->
575
-
576
- <!-- Preferences -->
577
- <table class="email-preferences" align="center" valign="middle"
578
- style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; text-align: left; vertical-align: top; width: 100%;">
579
- <tbody>
580
- <tr style="padding: 0; text-align: center; vertical-align: top;">
581
- <td class="email-preferences-inner"
582
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; border-top: 2px solid #e9ebe7; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 40px; text-align: left; vertical-align: top; word-wrap: break-word;">
583
- <table class="email-preferences-content row collapse" align="center"
584
- valign="top"
585
- style="border-collapse: collapse; border-spacing: 0; display: table; padding: 0; position: relative; text-align: center; vertical-align: top; width: 100%;">
586
- <tbody>
587
- <tr style="padding: 0; text-align: center; vertical-align: top;">
588
- <th class="small-12 large-8 columns first copy" align="center"
589
- style="Margin: 0 auto; color: #707070; font-family: Helvetica, Arial, sans-serif; font-size: 12px; font-weight: normal; line-height: 20px; margin: 0 auto; padding: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; text-align: left; width: 394.66667px;">
590
- <p style="Margin: 0; Margin-bottom: 0; color: #707070; font-family: Helvetica, Arial, sans-serif; font-size: 12px; font-weight: normal; line-height: 20px; margin: 0; margin-bottom: 0; padding: 0; text-align: center;">
591
- <?php printf( __( "<a href=\"%s\">Configure reporting preferences</a>", "defender-security" ), apply_filters( 'wp_defeder/iplockout/email_report_link', network_admin_url( "admin.php?page=wdf-ip-lockout&view=notification" ) ) ) ?>
592
- </p>
593
- </th>
594
- </tr>
595
- </tbody>
596
- </table>
597
- </td>
598
- </tr>
599
- </tbody>
600
- </table>
601
- <!-- End Preferences -->
602
-
603
- <table class="company-info" align="left" valign="middle"
604
- style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; text-align: left; vertical-align: top; width: 100%;">
605
- <tbody>
606
- <tr style="padding: 0; text-align: left; vertical-align: top;">
607
- <td class="company-info-inner"
608
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; border-top: 2px solid #e9ebe7; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 40px; text-align: left; vertical-align: top; word-wrap: break-word;">
609
- <table class="company-info-content row collapse" align="left" valign="top"
610
- style="border-collapse: collapse; border-spacing: 0; display: table; padding: 0; position: relative; text-align: left; vertical-align: top; width: 100%;">
611
- <tbody>
612
- <tr style="padding: 0; text-align: left; vertical-align: top;">
613
- <th class="small-12 large-8 columns first copy" align="left"
614
- style="Margin: 0 auto; color: #707070; font-family: Helvetica, Arial, sans-serif; font-size: 12px; font-weight: normal; line-height: 20px; margin: 0 auto; padding: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; text-align: left; width: 394.66667px;">
615
- <p style="Margin: 0; Margin-bottom: 0; color: #707070; font-family: Helvetica, Arial, sans-serif; font-size: 12px; font-weight: normal; line-height: 20px; margin: 0; margin-bottom: 0; padding: 0; text-align: left;">
616
- Copyright © Incsub, All rights reserved.</p>
617
- <p style="Margin: 0; Margin-bottom: 0; color: #707070; font-family: Helvetica, Arial, sans-serif; font-size: 12px; font-weight: normal; line-height: 20px; margin: 0; margin-bottom: 0; padding: 0; text-align: left;">
618
- Incsub PO box 163 Albert Park, Victoria 3206 Australia</p>
619
- </th>
620
- <th class="small-12 large-4 columns last logo" align="right"
621
- style="Margin: 0 auto; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0 auto; padding: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; text-align: right; width: 201.33333px;">
622
- <a href="https://premium.wpmudev.org" class="logo-link"
623
- style="Margin: 0; color: #555555; display: inline-block; font-family: Helvetica, Arial, sans-serif; font-weight: normal; line-height: 1.3; margin: 0; padding: 0; text-align: right; text-decoration: none;">
624
- <img
625
- src="<?php echo wp_defender()->getPluginUrl() ?>assets/email-images/wpmudev-logo.png"
626
- alt="WPMU DEV"
627
- style="-ms-interpolation-mode: bicubic; border: none; clear: both; display: inline-block; max-width: 100%; outline: none; text-align: right; text-decoration: none; width: auto;">
628
- </a>
629
- </th>
630
- <th class="expander"
631
- style="Margin: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0; padding: 0 !important; text-align: left; visibility: hidden; width: 0;"></th>
632
- </tr>
633
- </tbody>
634
- </table>
635
- </td>
636
- </tr>
637
- </tbody>
638
- </table>
639
- <!-- end company-info -->
640
-
641
- <table class="wrapper social" align="center"
642
- style="background-color: #e9ebe7; border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top; width: 100%;">
643
- <tbody>
644
- <tr style="padding: 0; text-align: left; vertical-align: top;">
645
- <td class="wrapper-inner social-inner"
646
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 40px 60px 20px; text-align: left; vertical-align: top; word-wrap: break-word;">
647
-
648
- <table class="social-content" align="center"
649
- style="border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top;">
650
- <tbody>
651
- <tr style="padding: 0; text-align: left; vertical-align: top;">
652
- <td class="social-content-inner"
653
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; text-align: center; vertical-align: top; word-wrap: break-word;">
654
- <a href="https://plus.google.com/+wpmuorg/" target="_blank"
655
- class="gplus"
656
- style="Margin: 0; color: #555555; display: inline-block; font-family: Helvetica, Arial, sans-serif; font-weight: normal; line-height: 1.3; margin: 0; margin-right: 4px; padding: 0; text-align: left; text-decoration: none;"><img
657
- src="<?php echo wp_defender()->getPluginUrl() ?>assets/email-images/icon-gplus.png"
658
- alt="WPMU DEV on Google+"
659
- style="-ms-interpolation-mode: bicubic; border: none; clear: both; display: block; max-width: 100%; outline: none; text-decoration: none; width: auto;"></a>
660
- <a href="https://twitter.com/wpmudev" target="_blank"
661
- class="twitter"
662
- style="Margin: 0; color: #555555; display: inline-block; font-family: Helvetica, Arial, sans-serif; font-weight: normal; line-height: 1.3; margin: 0; margin-right: 4px; padding: 0; text-align: left; text-decoration: none;"><img
663
- src="<?php echo wp_defender()->getPluginUrl() ?>assets/email-images/icon-twitter.png"
664
- alt="WPMU DEV on Twitter"
665
- style="-ms-interpolation-mode: bicubic; border: none; clear: both; display: block; max-width: 100%; outline: none; text-decoration: none; width: auto;"></a>
666
- <a href="https://www.facebook.com/wpmudev" target="_blank"
667
- class="facebook"
668
- style="Margin: 0; color: #555555; display: inline-block; font-family: Helvetica, Arial, sans-serif; font-weight: normal; line-height: 1.3; margin: 0; margin-right: 0; padding: 0; text-align: left; text-decoration: none;"><img
669
- src="<?php echo wp_defender()->getPluginUrl() ?>assets/email-images/icon-facebook.png"
670
- alt="WPMU DEV on Facebook"
671
- style="-ms-interpolation-mode: bicubic; border: none; clear: both; display: block; max-width: 100%; outline: none; text-decoration: none; width: auto;"></a>
672
- </td>
673
- </tr>
674
- </tbody>
675
- </table>
676
- <!-- end social-content -->
677
-
678
- </td>
679
- </tr>
680
- </tbody>
681
- </table>
682
- <!-- end top -->
683
- </td>
684
- </tr>
685
- </tbody>
686
- </table>
687
- <!-- end main container -->
688
-
689
- </center>
690
-
691
- </td>
692
- </tr>
693
- </tbody>
694
- </table>
695
- <!-- end body -->
696
- </body>
697
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/ip-lockout/view/emails/login-lockout.php DELETED
@@ -1,697 +0,0 @@
1
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
- <html xmlns="http://www.w3.org/1999/xhtml">
3
-
4
- <head>
5
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
6
- <meta name="viewport" content="width=device-width">
7
- <title><?php _e( "New Login Lockout", "defender-security" ) ?></title>
8
- <style>
9
- a.plugin-brand:hover {
10
- color: #e23717 !important;
11
- }
12
-
13
- table.top-content td a:hover {
14
- color: #ff5c28 !important;
15
- }
16
- </style>
17
- </head>
18
-
19
- <body
20
- style="-moz-box-sizing: border-box; -ms-text-size-adjust: 100%; -webkit-box-sizing: border-box; -webkit-text-size-adjust: 100%; Margin: 0; background-color: #e9ebe7; box-sizing: border-box; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0; min-width: 100%; padding: 0; text-align: left; width: 100% !important;">
21
- <style>
22
- @media only screen {
23
- html {
24
- min-height: 100%;
25
- background: #f3f3f3;
26
- }
27
- }
28
-
29
- @media only screen and (max-width: 596px) {
30
- .small-float-center {
31
- margin: 0 auto !important;
32
- float: none !important;
33
- text-align: center !important;
34
- }
35
-
36
- .small-text-center {
37
- text-align: center !important;
38
- }
39
-
40
- .small-text-left {
41
- text-align: left !important;
42
- }
43
-
44
- .small-text-right {
45
- text-align: right !important;
46
- }
47
- }
48
-
49
- @media only screen and (max-width: 596px) {
50
- .hide-for-large {
51
- display: block !important;
52
- width: auto !important;
53
- overflow: visible !important;
54
- max-height: none !important;
55
- font-size: inherit !important;
56
- line-height: inherit !important;
57
- }
58
- }
59
-
60
- @media only screen and (max-width: 596px) {
61
- table.body table.container .hide-for-large,
62
- table.body table.container .row.hide-for-large {
63
- display: table !important;
64
- width: 100% !important;
65
- }
66
- }
67
-
68
- @media only screen and (max-width: 596px) {
69
- table.body table.container .callout-inner.hide-for-large {
70
- display: table-cell !important;
71
- width: 100% !important;
72
- }
73
- }
74
-
75
- @media only screen and (max-width: 596px) {
76
- table.body table.container .show-for-large {
77
- display: none !important;
78
- width: 0;
79
- mso-hide: all;
80
- overflow: hidden;
81
- }
82
- }
83
-
84
- @media only screen and (max-width: 596px) {
85
- table.body img {
86
- width: auto;
87
- height: auto;
88
- }
89
-
90
- table.body center {
91
- min-width: 0 !important;
92
- }
93
-
94
- table.body .container {
95
- width: 95% !important;
96
- }
97
-
98
- table.body .columns,
99
- table.body .column {
100
- height: auto !important;
101
- -moz-box-sizing: border-box;
102
- -webkit-box-sizing: border-box;
103
- box-sizing: border-box;
104
- padding-left: 16px !important;
105
- padding-right: 16px !important;
106
- }
107
-
108
- table.body .columns .column,
109
- table.body .columns .columns,
110
- table.body .column .column,
111
- table.body .column .columns {
112
- padding-left: 0 !important;
113
- padding-right: 0 !important;
114
- }
115
-
116
- table.body .collapse .columns,
117
- table.body .collapse .column {
118
- padding-left: 0 !important;
119
- padding-right: 0 !important;
120
- }
121
-
122
- td.small-1,
123
- th.small-1 {
124
- display: inline-block !important;
125
- width: 8.33333% !important;
126
- }
127
-
128
- td.small-2,
129
- th.small-2 {
130
- display: inline-block !important;
131
- width: 16.66667% !important;
132
- }
133
-
134
- td.small-3,
135
- th.small-3 {
136
- display: inline-block !important;
137
- width: 25% !important;
138
- }
139
-
140
- td.small-4,
141
- th.small-4 {
142
- display: inline-block !important;
143
- width: 33.33333% !important;
144
- }
145
-
146
- td.small-5,
147
- th.small-5 {
148
- display: inline-block !important;
149
- width: 41.66667% !important;
150
- }
151
-
152
- td.small-6,
153
- th.small-6 {
154
- display: inline-block !important;
155
- width: 50% !important;
156
- }
157
-
158
- td.small-7,
159
- th.small-7 {
160
- display: inline-block !important;
161
- width: 58.33333% !important;
162
- }
163
-
164
- td.small-8,
165
- th.small-8 {
166
- display: inline-block !important;
167
- width: 66.66667% !important;
168
- }
169
-
170
- td.small-9,
171
- th.small-9 {
172
- display: inline-block !important;
173
- width: 75% !important;
174
- }
175
-
176
- td.small-10,
177
- th.small-10 {
178
- display: inline-block !important;
179
- width: 83.33333% !important;
180
- }
181
-
182
- td.small-11,
183
- th.small-11 {
184
- display: inline-block !important;
185
- width: 91.66667% !important;
186
- }
187
-
188
- td.small-12,
189
- th.small-12 {
190
- display: inline-block !important;
191
- width: 100% !important;
192
- }
193
-
194
- .columns td.small-12,
195
- .column td.small-12,
196
- .columns th.small-12,
197
- .column th.small-12 {
198
- display: block !important;
199
- width: 100% !important;
200
- }
201
-
202
- table.body td.small-offset-1,
203
- table.body th.small-offset-1 {
204
- margin-left: 8.33333% !important;
205
- Margin-left: 8.33333% !important;
206
- }
207
-
208
- table.body td.small-offset-2,
209
- table.body th.small-offset-2 {
210
- margin-left: 16.66667% !important;
211
- Margin-left: 16.66667% !important;
212
- }
213
-
214
- table.body td.small-offset-3,
215
- table.body th.small-offset-3 {
216
- margin-left: 25% !important;
217
- Margin-left: 25% !important;
218
- }
219
-
220
- table.body td.small-offset-4,
221
- table.body th.small-offset-4 {
222
- margin-left: 33.33333% !important;
223
- Margin-left: 33.33333% !important;
224
- }
225
-
226
- table.body td.small-offset-5,
227
- table.body th.small-offset-5 {
228
- margin-left: 41.66667% !important;
229
- Margin-left: 41.66667% !important;
230
- }
231
-
232
- table.body td.small-offset-6,
233
- table.body th.small-offset-6 {
234
- margin-left: 50% !important;
235
- Margin-left: 50% !important;
236
- }
237
-
238
- table.body td.small-offset-7,
239
- table.body th.small-offset-7 {
240
- margin-left: 58.33333% !important;
241
- Margin-left: 58.33333% !important;
242
- }
243
-
244
- table.body td.small-offset-8,
245
- table.body th.small-offset-8 {
246
- margin-left: 66.66667% !important;
247
- Margin-left: 66.66667% !important;
248
- }
249
-
250
- table.body td.small-offset-9,
251
- table.body th.small-offset-9 {
252
- margin-left: 75% !important;
253
- Margin-left: 75% !important;
254
- }
255
-
256
- table.body td.small-offset-10,
257
- table.body th.small-offset-10 {
258
- margin-left: 83.33333% !important;
259
- Margin-left: 83.33333% !important;
260
- }
261
-
262
- table.body td.small-offset-11,
263
- table.body th.small-offset-11 {
264
- margin-left: 91.66667% !important;
265
- Margin-left: 91.66667% !important;
266
- }
267
-
268
- table.body table.columns td.expander,
269
- table.body table.columns th.expander {
270
- display: none !important;
271
- }
272
-
273
- table.body .right-text-pad,
274
- table.body .text-pad-right {
275
- padding-left: 10px !important;
276
- }
277
-
278
- table.body .left-text-pad,
279
- table.body .text-pad-left {
280
- padding-right: 10px !important;
281
- }
282
-
283
- table.menu {
284
- width: 100% !important;
285
- }
286
-
287
- table.menu td,
288
- table.menu th {
289
- width: auto !important;
290
- display: inline-block !important;
291
- }
292
-
293
- table.menu.vertical td,
294
- table.menu.vertical th,
295
- table.menu.small-vertical td,
296
- table.menu.small-vertical th {
297
- display: block !important;
298
- }
299
-
300
- table.menu[align="center"] {
301
- width: auto !important;
302
- }
303
-
304
- table.button.small-expand,
305
- table.button.small-expanded {
306
- width: 100% !important;
307
- }
308
-
309
- table.button.small-expand table,
310
- table.button.small-expanded table {
311
- width: 100%;
312
- }
313
-
314
- table.button.small-expand table a,
315
- table.button.small-expanded table a {
316
- text-align: center !important;
317
- width: 100% !important;
318
- padding-left: 0 !important;
319
- padding-right: 0 !important;
320
- }
321
-
322
- table.button.small-expand center,
323
- table.button.small-expanded center {
324
- min-width: 0;
325
- }
326
- }
327
-
328
- @media screen and (max-width: 596px) {
329
- /* results list */
330
- table.results-list thead th {
331
- line-height: 34px !important;
332
- }
333
-
334
- /* top */
335
- table.top-content td {
336
- text-align: center !important;
337
- }
338
-
339
- /* related */
340
- table.related table.related-items .columns {
341
- padding-right: 0 !important;
342
- padding-bottom: 15px !important;
343
- padding-left: 0 !important;
344
- }
345
-
346
- table.related table.related-items .columns.last {
347
- padding-bottom: 0 !important;
348
- }
349
-
350
- table.related a.related-item .plugin-info {
351
- vertical-align: middle !important;
352
- }
353
-
354
- /* company info */
355
- table.company-info .columns {
356
- padding-right: 0 !important;
357
- padding-left: 0 !important;
358
- }
359
-
360
- table.company-info .columns.last {
361
- padding: 15px 0 0 !important;
362
- }
363
-
364
- table.company-info .logo,
365
- table.company-info .logo-link,
366
- table.company-info .logo img {
367
- text-align: left !important;
368
- }
369
- }
370
-
371
- @media screen and (max-width: 540px) {
372
- /* hero */
373
- table.hero table.hero-content {
374
- width: 100%;
375
- }
376
-
377
- table.hero td.hero-title h1,
378
- table.hero td.hero-title h2 {
379
- padding: 0 !important;
380
- text-align: center !important;
381
- }
382
-
383
- table.hero td.hero-image {
384
- display: none;
385
- }
386
- }
387
- </style>
388
-
389
- <table class="body"
390
- style="Margin: 0; background: #f3f3f3; background-color: #e9ebe7; border-collapse: collapse; border-spacing: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; height: 100%; line-height: 26px; margin: 0; padding: 0; text-align: left; vertical-align: top; width: 100%;">
391
- <tbody>
392
- <tr style="padding: 0; text-align: left; vertical-align: top;">
393
- <td class="center" align="center" valign="top"
394
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; text-align: left; vertical-align: top; word-wrap: break-word;">
395
-
396
- <center style="min-width: 600px; width: 100%;">
397
-
398
- <table class="container"
399
- style="Margin: 0 auto; background: #fefefe; background-color: #fff; border-collapse: collapse; border-spacing: 0; margin: 0 auto; padding: 0; text-align: inherit; vertical-align: top; width: 600px;">
400
- <tbody>
401
- <tr style="padding: 0; text-align: left; vertical-align: top;">
402
- <td style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; text-align: left; vertical-align: top; word-wrap: break-word;">
403
- <table class="wrapper hero" align="left"
404
- style="background-color: #e9ebe7; border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top; width: 100%;">
405
- <tbody>
406
- <tr style="padding: 0; text-align: left; vertical-align: top;">
407
- <td class="wrapper-inner hero-inner"
408
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 20px 0 0; text-align: left; vertical-align: top; word-wrap: break-word;">
409
-
410
- <table class="hero-content" align="left"
411
- style="border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top;">
412
- <tbody>
413
- <tr style="padding: 0; text-align: left; vertical-align: top;">
414
- <td class="hero-title"
415
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; padding-bottom: 18px; text-align: left; vertical-align: bottom; word-wrap: break-word;">
416
- <h2 style="Margin: 0; Margin-bottom: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 30px; font-weight: 700; line-height: 1em; margin: 0; margin-bottom: 0; padding: 0; padding-left: 9px; text-align: left; text-transform: uppercase; word-wrap: normal;">
417
- <?php esc_html_e( "Protected By", "defender-security" ) ?></h2>
418
- <h1 class="plugin-brand"
419
- style="Margin: 0; Margin-bottom: 0; color: #ff5c28; font-family: Helvetica, Arial, sans-serif; font-size: 60px; font-weight: 700; line-height: 1em; margin: 0; margin-bottom: 0; padding: 0; padding-left: 6px; text-align: left; text-transform: uppercase; word-wrap: normal;">
420
- <?php esc_html_e( "Defender!", "defender-security" ) ?></h1>
421
- </td>
422
- <td class="hero-image"
423
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; text-align: left; vertical-align: top; word-wrap: break-word;">
424
- <a href="https://premium.wpmudev.org/"
425
- style="Margin: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-weight: normal; line-height: 1.3; margin: 0; padding: 0; text-align: left; text-decoration: none;"><img
426
- src="<?php echo wp_defender()->getPluginUrl() ?>assets/email-images/hero-defender.png"
427
- alt="Defender"
428
- style="-ms-interpolation-mode: bicubic; border: none; clear: both; display: block; max-width: 100%; outline: none; text-decoration: none; width: auto;"></a>
429
- </td>
430
- </tr>
431
- </tbody>
432
- </table>
433
- <!-- end hero-content -->
434
-
435
- </td>
436
- </tr>
437
- </tbody>
438
- </table>
439
- <!-- end hero -->
440
-
441
- <table class="wrapper main" align="center"
442
- style="border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top; width: 100%;">
443
- <tbody>
444
- <tr style="padding: 0; text-align: left; vertical-align: top;">
445
- <td class="wrapper-inner main-inner"
446
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 40px; text-align: left; vertical-align: top; word-wrap: break-word;">
447
-
448
- <table class="main-intro"
449
- style="border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top;">
450
- <tbody>
451
- <tr style="padding: 0; text-align: left; vertical-align: top;">
452
- <td class="main-intro-content"
453
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; text-align: left; vertical-align: top; word-wrap: break-word;">
454
- <h3 style="Margin: 0; Margin-bottom: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 32px; font-weight: normal; line-height: 32px; margin: 0; margin-bottom: 0; padding: 0 0 28px; text-align: left; word-wrap: normal;">
455
- <?php printf( __( "Hi %s,", "defender-security" ), $admin ) ?></h3>
456
- <?php $setting = \WP_Defender\Module\IP_Lockout\Model\Settings::instance() ?>
457
- <?php $utils = \WP_Defender\Behavior\Utils::instance() ?>
458
- <p style="Margin: 0; Margin-bottom: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0; margin-bottom: 0; padding: 0 0 24px; text-align: left;">
459
- <?php
460
- $lockout_duration = $setting->login_protection_lockout_ban == true ? __( "They have been banned permanently.", "defender-security" ) : sprintf( __( "They have been locked out for <strong>%s %s.</strong>", "defender-security" ), $setting->login_protection_lockout_duration, $setting->login_protection_lockout_duration_unit );
461
- printf( __( "We've just locked out the host <strong>%s</strong> from %s due to more than <strong>%s</strong> failed login attempts. %s", "defender-security" ), $ip, network_site_url(), $setting->login_protection_login_attempt, $lockout_duration
462
- ) ?>
463
- </p>
464
- <p style="Margin: 0; Margin-bottom: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0; margin-bottom: 0; padding: 0 0 24px; text-align: left;">
465
- <?php printf( __( "You can view the full lockout logs <a href=\"%s\">here</a>", "defender-security" ), $logs_url ) ?>
466
- .</p>
467
- </td>
468
- </tr>
469
- </tbody>
470
- </table>
471
- <!-- end main-intro -->
472
-
473
- <table class="main-signature"
474
- style="border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top;">
475
- <tbody>
476
- <tr style="padding: 0; text-align: left; vertical-align: top;">
477
- <td class="main-signature-content"
478
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; text-align: left; vertical-align: top; word-wrap: break-word;">
479
- <p style="Margin: 0; Margin-bottom: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0; margin-bottom: 0; padding: 0 0 24px; text-align: left;">
480
- <?php esc_html_e( "Stay vigilant.", "defender-security" ) ?></p>
481
- <p class="last-item"
482
- style="Margin: 0; Margin-bottom: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0; margin-bottom: 0; padding: 0; text-align: left;">
483
- <strong><?php esc_html_e( "WP Defender", "defender-security" ) ?></strong>
484
- <br>
485
- <?php esc_html_e( "Security Hero", "defender-security" ) ?>
486
- <br/>
487
- <?php esc_html_e( "WPMU DEV", "defender-security" ) ?>
488
- </p>
489
- </td>
490
- </tr>
491
- </tbody>
492
- </table>
493
- <!-- end main-signature -->
494
-
495
- </td>
496
- </tr>
497
- </tbody>
498
- </table>
499
- <!-- end main -->
500
-
501
- <table class="related" align="center"
502
- style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; text-align: left; vertical-align: top; width: 100%;">
503
- <tbody>
504
- <tr style="padding: 0; text-align: left; vertical-align: top;">
505
- <td class="related-inner"
506
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; border-top: 2px solid #e9ebe7; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 15px 30px 15px 40px; text-align: left; vertical-align: top; word-wrap: break-word;">
507
- <table
508
- style="border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top;">
509
- <tbody>
510
- <tr style="padding: 0; text-align: left; vertical-align: top;">
511
- <td class="related-items-title brand" align="left"
512
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #3eb4e4; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; padding-bottom: 10px; text-align: left; vertical-align: top; word-wrap: break-word;">
513
- <?php esc_html_e( "Related plugins worth giving a try", "defender-security" ) ?>
514
- </td>
515
- </tr>
516
- <tr style="padding: 0; text-align: left; vertical-align: top;">
517
- <td style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; text-align: left; vertical-align: top; word-wrap: break-word;">
518
- <table class="related-items row collapse" align="center"
519
- style="border-collapse: collapse; border-spacing: 0; display: table; padding: 0; position: relative; text-align: left; vertical-align: top; width: 100%;">
520
- <tbody>
521
- <tr style="padding: 0; text-align: left; vertical-align: top;">
522
- <th class="small-12 large-6 columns first" align="left"
523
- valign="top"
524
- style="Margin: 0 auto; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0 auto; padding: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; text-align: left; width: 298px;">
525
- <a class="related-item plugin-link"
526
- href="https://premium.wpmudev.org/project/wp-hummingbird/"
527
- style="Margin: 0; color: #555555; display: table; font-family: Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 20px; margin: 0; padding: 0; text-align: left; text-decoration: none;">
528
- <img
529
- src="<?php echo wp_defender()->getPluginUrl() ?>assets/email-images/plugin-hummingbird.png"
530
- alt="Hummingbird" class="plugin-image"
531
- style="-ms-interpolation-mode: bicubic; border: none; clear: both; display: table-cell; max-width: 100%; outline: none; text-decoration: none; width: auto;">
532
- <span class="plugin-info"
533
- style="display: table-cell; padding-left: 10px; vertical-align: bottom;">
534
- <span><?php esc_html_e( "Optimize your site with", "defender-security" ) ?></span>
535
- <span class="plugin-title hummingbird"
536
- style="color: #febd30; display: block;"><strong><?php esc_html_e( "Hummingbird", "defender-security" ) ?></strong></span>
537
- </span>
538
- </a>
539
- </th>
540
- <th class="small-12 large-6 columns last" align="left"
541
- valign="top"
542
- style="Margin: 0 auto; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0 auto; padding: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; text-align: left; width: 298px;">
543
- <a class="related-item plugin-link"
544
- href="https://premium.wpmudev.org/project/snapshot/"
545
- style="Margin: 0; color: #555555; display: table; font-family: Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 20px; margin: 0; padding: 0; text-align: left; text-decoration: none;">
546
- <img
547
- src="<?php echo wp_defender()->getPluginUrl() ?>assets/email-images/plugin-snapshot.png"
548
- alt="Snapshot"
549
- class="plugin-image"
550
- style="-ms-interpolation-mode: bicubic; border: none; clear: both; display: table-cell; max-width: 100%; outline: none; text-decoration: none; width: auto;">
551
- <span class="plugin-info"
552
- style="display: table-cell; padding-left: 10px; vertical-align: bottom;">
553
- <span><?php esc_html_e( "Back up your hard work with", "defender-security" ) ?></span>
554
- <span class="plugin-title snapshot"
555
- style="color: #642486; display: block;"><strong><?php _e( "Snapshot", "defender-security" ) ?></strong></span>
556
- </span>
557
- </a>
558
- </th>
559
- <th class="expander"
560
- style="Margin: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0; padding: 0 !important; text-align: left; visibility: hidden; width: 0;"></th>
561
- </tr>
562
- </tbody>
563
- </table>
564
- </td>
565
- </tr>
566
- </tbody>
567
- </table>
568
- <!-- end related-inner -->
569
- </td>
570
- </tr>
571
- </tbody>
572
- </table>
573
- <!-- end related -->
574
-
575
- <!-- Preferences -->
576
- <table class="email-preferences" align="center" valign="middle"
577
- style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; text-align: left; vertical-align: top; width: 100%;">
578
- <tbody>
579
- <tr style="padding: 0; text-align: center; vertical-align: top;">
580
- <td class="email-preferences-inner"
581
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; border-top: 2px solid #e9ebe7; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 40px; text-align: left; vertical-align: top; word-wrap: break-word;">
582
- <table class="email-preferences-content row collapse" align="center"
583
- valign="top"
584
- style="border-collapse: collapse; border-spacing: 0; display: table; padding: 0; position: relative; text-align: center; vertical-align: top; width: 100%;">
585
- <tbody>
586
- <tr style="padding: 0; text-align: center; vertical-align: top;">
587
- <th class="small-12 large-8 columns first copy" align="center"
588
- style="Margin: 0 auto; color: #707070; font-family: Helvetica, Arial, sans-serif; font-size: 12px; font-weight: normal; line-height: 20px; margin: 0 auto; padding: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; text-align: left; width: 394.66667px;">
589
- <p style="Margin: 0; Margin-bottom: 0; color: #707070; font-family: Helvetica, Arial, sans-serif; font-size: 12px; font-weight: normal; line-height: 20px; margin: 0; margin-bottom: 0; padding: 0; text-align: center;">
590
- <?php printf( __( "<a href=\"%s\">Configure reporting preferences</a>", "defender-security" ), apply_filters( 'wp_defeder/iplockout/email_report_link', network_admin_url( "admin.php?page=wdf-ip-lockout&view=notification" ) ) ) ?>
591
- </p>
592
- </th>
593
- </tr>
594
- </tbody>
595
- </table>
596
- </td>
597
- </tr>
598
- </tbody>
599
- </table>
600
- <!-- End Preferences -->
601
-
602
- <table class="company-info" align="left" valign="middle"
603
- style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; text-align: left; vertical-align: top; width: 100%;">
604
- <tbody>
605
- <tr style="padding: 0; text-align: left; vertical-align: top;">
606
- <td class="company-info-inner"
607
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; border-top: 2px solid #e9ebe7; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 40px; text-align: left; vertical-align: top; word-wrap: break-word;">
608
- <table class="company-info-content row collapse" align="left" valign="top"
609
- style="border-collapse: collapse; border-spacing: 0; display: table; padding: 0; position: relative; text-align: left; vertical-align: top; width: 100%;">
610
- <tbody>
611
- <tr style="padding: 0; text-align: left; vertical-align: top;">
612
- <th class="small-12 large-8 columns first copy" align="left"
613
- style="Margin: 0 auto; color: #707070; font-family: Helvetica, Arial, sans-serif; font-size: 12px; font-weight: normal; line-height: 20px; margin: 0 auto; padding: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; text-align: left; width: 394.66667px;">
614
- <p style="Margin: 0; Margin-bottom: 0; color: #707070; font-family: Helvetica, Arial, sans-serif; font-size: 12px; font-weight: normal; line-height: 20px; margin: 0; margin-bottom: 0; padding: 0; text-align: left;">
615
- Copyright © Incsub, All rights reserved.</p>
616
- <p style="Margin: 0; Margin-bottom: 0; color: #707070; font-family: Helvetica, Arial, sans-serif; font-size: 12px; font-weight: normal; line-height: 20px; margin: 0; margin-bottom: 0; padding: 0; text-align: left;">
617
- Incsub PO box 163 Albert Park, Victoria 3206 Australia</p>
618
- </th>
619
- <th class="small-12 large-4 columns last logo" align="right"
620
- style="Margin: 0 auto; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0 auto; padding: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; text-align: right; width: 201.33333px;">
621
- <a href="https://premium.wpmudev.org" class="logo-link"
622
- style="Margin: 0; color: #555555; display: inline-block; font-family: Helvetica, Arial, sans-serif; font-weight: normal; line-height: 1.3; margin: 0; padding: 0; text-align: right; text-decoration: none;">
623
- <img
624
- src="<?php echo wp_defender()->getPluginUrl() ?>assets/email-images/wpmudev-logo.png"
625
- alt="WPMU DEV"
626
- style="-ms-interpolation-mode: bicubic; border: none; clear: both; display: inline-block; max-width: 100%; outline: none; text-align: right; text-decoration: none; width: auto;">
627
- </a>
628
- </th>
629
- <th class="expander"
630
- style="Margin: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0; padding: 0 !important; text-align: left; visibility: hidden; width: 0;"></th>
631
- </tr>
632
- </tbody>
633
- </table>
634
- </td>
635
- </tr>
636
- </tbody>
637
- </table>
638
- <!-- end company-info -->
639
-
640
- <table class="wrapper social" align="center"
641
- style="background-color: #e9ebe7; border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top; width: 100%;">
642
- <tbody>
643
- <tr style="padding: 0; text-align: left; vertical-align: top;">
644
- <td class="wrapper-inner social-inner"
645
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 40px 60px 20px; text-align: left; vertical-align: top; word-wrap: break-word;">
646
-
647
- <table class="social-content" align="center"
648
- style="border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top;">
649
- <tbody>
650
- <tr style="padding: 0; text-align: left; vertical-align: top;">
651
- <td class="social-content-inner"
652
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; text-align: center; vertical-align: top; word-wrap: break-word;">
653
- <a href="https://plus.google.com/+wpmuorg/" target="_blank"
654
- class="gplus"
655
- style="Margin: 0; color: #555555; display: inline-block; font-family: Helvetica, Arial, sans-serif; font-weight: normal; line-height: 1.3; margin: 0; margin-right: 4px; padding: 0; text-align: left; text-decoration: none;"><img
656
- src="<?php echo wp_defender()->getPluginUrl() ?>assets/email-images/icon-gplus.png"
657
- alt="WPMU DEV on Google+"
658
- style="-ms-interpolation-mode: bicubic; border: none; clear: both; display: block; max-width: 100%; outline: none; text-decoration: none; width: auto;"></a>
659
- <a href="https://twitter.com/wpmudev" target="_blank"
660
- class="twitter"
661
- style="Margin: 0; color: #555555; display: inline-block; font-family: Helvetica, Arial, sans-serif; font-weight: normal; line-height: 1.3; margin: 0; margin-right: 4px; padding: 0; text-align: left; text-decoration: none;"><img
662
- src="<?php echo wp_defender()->getPluginUrl() ?>assets/email-images/icon-twitter.png"
663
- alt="WPMU DEV on Twitter"
664
- style="-ms-interpolation-mode: bicubic; border: none; clear: both; display: block; max-width: 100%; outline: none; text-decoration: none; width: auto;"></a>
665
- <a href="https://www.facebook.com/wpmudev" target="_blank"
666
- class="facebook"
667
- style="Margin: 0; color: #555555; display: inline-block; font-family: Helvetica, Arial, sans-serif; font-weight: normal; line-height: 1.3; margin: 0; margin-right: 0; padding: 0; text-align: left; text-decoration: none;"><img
668
- src="<?php echo wp_defender()->getPluginUrl() ?>assets/email-images/icon-facebook.png"
669
- alt="WPMU DEV on Facebook"
670
- style="-ms-interpolation-mode: bicubic; border: none; clear: both; display: block; max-width: 100%; outline: none; text-decoration: none; width: auto;"></a>
671
- </td>
672
- </tr>
673
- </tbody>
674
- </table>
675
- <!-- end social-content -->
676
-
677
- </td>
678
- </tr>
679
- </tbody>
680
- </table>
681
- <!-- end top -->
682
-
683
- <!-- end disclaimer -->
684
-
685
- </td>
686
- </tr>
687
- </tbody>
688
- </table>
689
- <!-- end main container -->
690
- </center>
691
- </td>
692
- </tr>
693
- </tbody>
694
- </table>
695
- <!-- end body -->
696
- </body>
697
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/ip-lockout/view/emails/login-username-ban.php DELETED
@@ -1,696 +0,0 @@
1
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
- <html xmlns="http://www.w3.org/1999/xhtml">
3
-
4
- <head>
5
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
6
- <meta name="viewport" content="width=device-width">
7
- <title><?php _e( "New Login Lockout", "defender-security" ) ?></title>
8
- <style>
9
- a.plugin-brand:hover {
10
- color: #e23717 !important;
11
- }
12
-
13
- table.top-content td a:hover {
14
- color: #ff5c28 !important;
15
- }
16
- </style>
17
- </head>
18
-
19
- <body
20
- style="-moz-box-sizing: border-box; -ms-text-size-adjust: 100%; -webkit-box-sizing: border-box; -webkit-text-size-adjust: 100%; Margin: 0; background-color: #e9ebe7; box-sizing: border-box; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0; min-width: 100%; padding: 0; text-align: left; width: 100% !important;">
21
- <style>
22
- @media only screen {
23
- html {
24
- min-height: 100%;
25
- background: #f3f3f3;
26
- }
27
- }
28
-
29
- @media only screen and (max-width: 596px) {
30
- .small-float-center {
31
- margin: 0 auto !important;
32
- float: none !important;
33
- text-align: center !important;
34
- }
35
-
36
- .small-text-center {
37
- text-align: center !important;
38
- }
39
-
40
- .small-text-left {
41
- text-align: left !important;
42
- }
43
-
44
- .small-text-right {
45
- text-align: right !important;
46
- }
47
- }
48
-
49
- @media only screen and (max-width: 596px) {
50
- .hide-for-large {
51
- display: block !important;
52
- width: auto !important;
53
- overflow: visible !important;
54
- max-height: none !important;
55
- font-size: inherit !important;
56
- line-height: inherit !important;
57
- }
58
- }
59
-
60
- @media only screen and (max-width: 596px) {
61
- table.body table.container .hide-for-large,
62
- table.body table.container .row.hide-for-large {
63
- display: table !important;
64
- width: 100% !important;
65
- }
66
- }
67
-
68
- @media only screen and (max-width: 596px) {
69
- table.body table.container .callout-inner.hide-for-large {
70
- display: table-cell !important;
71
- width: 100% !important;
72
- }
73
- }
74
-
75
- @media only screen and (max-width: 596px) {
76
- table.body table.container .show-for-large {
77
- display: none !important;
78
- width: 0;
79
- mso-hide: all;
80
- overflow: hidden;
81
- }
82
- }
83
-
84
- @media only screen and (max-width: 596px) {
85
- table.body img {
86
- width: auto;
87
- height: auto;
88
- }
89
-
90
- table.body center {
91
- min-width: 0 !important;
92
- }
93
-
94
- table.body .container {
95
- width: 95% !important;
96
- }
97
-
98
- table.body .columns,
99
- table.body .column {
100
- height: auto !important;
101
- -moz-box-sizing: border-box;
102
- -webkit-box-sizing: border-box;
103
- box-sizing: border-box;
104
- padding-left: 16px !important;
105
- padding-right: 16px !important;
106
- }
107
-
108
- table.body .columns .column,
109
- table.body .columns .columns,
110
- table.body .column .column,
111
- table.body .column .columns {
112
- padding-left: 0 !important;
113
- padding-right: 0 !important;
114
- }
115
-
116
- table.body .collapse .columns,
117
- table.body .collapse .column {
118
- padding-left: 0 !important;
119
- padding-right: 0 !important;
120
- }
121
-
122
- td.small-1,
123
- th.small-1 {
124
- display: inline-block !important;
125
- width: 8.33333% !important;
126
- }
127
-
128
- td.small-2,
129
- th.small-2 {
130
- display: inline-block !important;
131
- width: 16.66667% !important;
132
- }
133
-
134
- td.small-3,
135
- th.small-3 {
136
- display: inline-block !important;
137
- width: 25% !important;
138
- }
139
-
140
- td.small-4,
141
- th.small-4 {
142
- display: inline-block !important;
143
- width: 33.33333% !important;
144
- }
145
-
146
- td.small-5,
147
- th.small-5 {
148
- display: inline-block !important;
149
- width: 41.66667% !important;
150
- }
151
-
152
- td.small-6,
153
- th.small-6 {
154
- display: inline-block !important;
155
- width: 50% !important;
156
- }
157
-
158
- td.small-7,
159
- th.small-7 {
160
- display: inline-block !important;
161
- width: 58.33333% !important;
162
- }
163
-
164
- td.small-8,
165
- th.small-8 {
166
- display: inline-block !important;
167
- width: 66.66667% !important;
168
- }
169
-
170
- td.small-9,
171
- th.small-9 {
172
- display: inline-block !important;
173
- width: 75% !important;
174
- }
175
-
176
- td.small-10,
177
- th.small-10 {
178
- display: inline-block !important;
179
- width: 83.33333% !important;
180
- }
181
-
182
- td.small-11,
183
- th.small-11 {
184
- display: inline-block !important;
185
- width: 91.66667% !important;
186
- }
187
-
188
- td.small-12,
189
- th.small-12 {
190
- display: inline-block !important;
191
- width: 100% !important;
192
- }
193
-
194
- .columns td.small-12,
195
- .column td.small-12,
196
- .columns th.small-12,
197
- .column th.small-12 {
198
- display: block !important;
199
- width: 100% !important;
200
- }
201
-
202
- table.body td.small-offset-1,
203
- table.body th.small-offset-1 {
204
- margin-left: 8.33333% !important;
205
- Margin-left: 8.33333% !important;
206
- }
207
-
208
- table.body td.small-offset-2,
209
- table.body th.small-offset-2 {
210
- margin-left: 16.66667% !important;
211
- Margin-left: 16.66667% !important;
212
- }
213
-
214
- table.body td.small-offset-3,
215
- table.body th.small-offset-3 {
216
- margin-left: 25% !important;
217
- Margin-left: 25% !important;
218
- }
219
-
220
- table.body td.small-offset-4,
221
- table.body th.small-offset-4 {
222
- margin-left: 33.33333% !important;
223
- Margin-left: 33.33333% !important;
224
- }
225
-
226
- table.body td.small-offset-5,
227
- table.body th.small-offset-5 {
228
- margin-left: 41.66667% !important;
229
- Margin-left: 41.66667% !important;
230
- }
231
-
232
- table.body td.small-offset-6,
233
- table.body th.small-offset-6 {
234
- margin-left: 50% !important;
235
- Margin-left: 50% !important;
236
- }
237
-
238
- table.body td.small-offset-7,
239
- table.body th.small-offset-7 {
240
- margin-left: 58.33333% !important;
241
- Margin-left: 58.33333% !important;
242
- }
243
-
244
- table.body td.small-offset-8,
245
- table.body th.small-offset-8 {
246
- margin-left: 66.66667% !important;
247
- Margin-left: 66.66667% !important;
248
- }
249
-
250
- table.body td.small-offset-9,
251
- table.body th.small-offset-9 {
252
- margin-left: 75% !important;
253
- Margin-left: 75% !important;
254
- }
255
-
256
- table.body td.small-offset-10,
257
- table.body th.small-offset-10 {
258
- margin-left: 83.33333% !important;
259
- Margin-left: 83.33333% !important;
260
- }
261
-
262
- table.body td.small-offset-11,
263
- table.body th.small-offset-11 {
264
- margin-left: 91.66667% !important;
265
- Margin-left: 91.66667% !important;
266
- }
267
-
268
- table.body table.columns td.expander,
269
- table.body table.columns th.expander {
270
- display: none !important;
271
- }
272
-
273
- table.body .right-text-pad,
274
- table.body .text-pad-right {
275
- padding-left: 10px !important;
276
- }
277
-
278
- table.body .left-text-pad,
279
- table.body .text-pad-left {
280
- padding-right: 10px !important;
281
- }
282
-
283
- table.menu {
284
- width: 100% !important;
285
- }
286
-
287
- table.menu td,
288
- table.menu th {
289
- width: auto !important;
290
- display: inline-block !important;
291
- }
292
-
293
- table.menu.vertical td,
294
- table.menu.vertical th,
295
- table.menu.small-vertical td,
296
- table.menu.small-vertical th {
297
- display: block !important;
298
- }
299
-
300
- table.menu[align="center"] {
301
- width: auto !important;
302
- }
303
-
304
- table.button.small-expand,
305
- table.button.small-expanded {
306
- width: 100% !important;
307
- }
308
-
309
- table.button.small-expand table,
310
- table.button.small-expanded table {
311
- width: 100%;
312
- }
313
-
314
- table.button.small-expand table a,
315
- table.button.small-expanded table a {
316
- text-align: center !important;
317
- width: 100% !important;
318
- padding-left: 0 !important;
319
- padding-right: 0 !important;
320
- }
321
-
322
- table.button.small-expand center,
323
- table.button.small-expanded center {
324
- min-width: 0;
325
- }
326
- }
327
-
328
- @media screen and (max-width: 596px) {
329
- /* results list */
330
- table.results-list thead th {
331
- line-height: 34px !important;
332
- }
333
-
334
- /* top */
335
- table.top-content td {
336
- text-align: center !important;
337
- }
338
-
339
- /* related */
340
- table.related table.related-items .columns {
341
- padding-right: 0 !important;
342
- padding-bottom: 15px !important;
343
- padding-left: 0 !important;
344
- }
345
-
346
- table.related table.related-items .columns.last {
347
- padding-bottom: 0 !important;
348
- }
349
-
350
- table.related a.related-item .plugin-info {
351
- vertical-align: middle !important;
352
- }
353
-
354
- /* company info */
355
- table.company-info .columns {
356
- padding-right: 0 !important;
357
- padding-left: 0 !important;
358
- }
359
-
360
- table.company-info .columns.last {
361
- padding: 15px 0 0 !important;
362
- }
363
-
364
- table.company-info .logo,
365
- table.company-info .logo-link,
366
- table.company-info .logo img {
367
- text-align: left !important;
368
- }
369
- }
370
-
371
- @media screen and (max-width: 540px) {
372
- /* hero */
373
- table.hero table.hero-content {
374
- width: 100%;
375
- }
376
-
377
- table.hero td.hero-title h1,
378
- table.hero td.hero-title h2 {
379
- padding: 0 !important;
380
- text-align: center !important;
381
- }
382
-
383
- table.hero td.hero-image {
384
- display: none;
385
- }
386
- }
387
- </style>
388
-
389
- <table class="body"
390
- style="Margin: 0; background: #f3f3f3; background-color: #e9ebe7; border-collapse: collapse; border-spacing: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; height: 100%; line-height: 26px; margin: 0; padding: 0; text-align: left; vertical-align: top; width: 100%;">
391
- <tbody>
392
- <tr style="padding: 0; text-align: left; vertical-align: top;">
393
- <td class="center" align="center" valign="top"
394
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; text-align: left; vertical-align: top; word-wrap: break-word;">
395
-
396
- <center style="min-width: 600px; width: 100%;">
397
-
398
- <table class="container"
399
- style="Margin: 0 auto; background: #fefefe; background-color: #fff; border-collapse: collapse; border-spacing: 0; margin: 0 auto; padding: 0; text-align: inherit; vertical-align: top; width: 600px;">
400
- <tbody>
401
- <tr style="padding: 0; text-align: left; vertical-align: top;">
402
- <td style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; text-align: left; vertical-align: top; word-wrap: break-word;">
403
- <table class="wrapper hero" align="left"
404
- style="background-color: #e9ebe7; border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top; width: 100%;">
405
- <tbody>
406
- <tr style="padding: 0; text-align: left; vertical-align: top;">
407
- <td class="wrapper-inner hero-inner"
408
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 20px 0 0; text-align: left; vertical-align: top; word-wrap: break-word;">
409
-
410
- <table class="hero-content" align="left"
411
- style="border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top;">
412
- <tbody>
413
- <tr style="padding: 0; text-align: left; vertical-align: top;">
414
- <td class="hero-title"
415
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; padding-bottom: 18px; text-align: left; vertical-align: bottom; word-wrap: break-word;">
416
- <h2 style="Margin: 0; Margin-bottom: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 30px; font-weight: 700; line-height: 1em; margin: 0; margin-bottom: 0; padding: 0; padding-left: 9px; text-align: left; text-transform: uppercase; word-wrap: normal;">
417
- <?php esc_html_e( "Protected By", "defender-security" ) ?></h2>
418
- <h1 class="plugin-brand"
419
- style="Margin: 0; Margin-bottom: 0; color: #ff5c28; font-family: Helvetica, Arial, sans-serif; font-size: 60px; font-weight: 700; line-height: 1em; margin: 0; margin-bottom: 0; padding: 0; padding-left: 6px; text-align: left; text-transform: uppercase; word-wrap: normal;">
420
- <?php esc_html_e( "Defender!", "defender-security" ) ?></h1>
421
- </td>
422
- <td class="hero-image"
423
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; text-align: left; vertical-align: top; word-wrap: break-word;">
424
- <a href="https://premium.wpmudev.org/"
425
- style="Margin: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-weight: normal; line-height: 1.3; margin: 0; padding: 0; text-align: left; text-decoration: none;"><img
426
- src="<?php echo wp_defender()->getPluginUrl() ?>assets/email-images/hero-defender.png"
427
- alt="Defender"
428
- style="-ms-interpolation-mode: bicubic; border: none; clear: both; display: block; max-width: 100%; outline: none; text-decoration: none; width: auto;"></a>
429
- </td>
430
- </tr>
431
- </tbody>
432
- </table>
433
- <!-- end hero-content -->
434
-
435
- </td>
436
- </tr>
437
- </tbody>
438
- </table>
439
- <!-- end hero -->
440
-
441
- <table class="wrapper main" align="center"
442
- style="border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top; width: 100%;">
443
- <tbody>
444
- <tr style="padding: 0; text-align: left; vertical-align: top;">
445
- <td class="wrapper-inner main-inner"
446
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 40px; text-align: left; vertical-align: top; word-wrap: break-word;">
447
-
448
- <table class="main-intro"
449
- style="border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top;">
450
- <tbody>
451
- <tr style="padding: 0; text-align: left; vertical-align: top;">
452
- <td class="main-intro-content"
453
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; text-align: left; vertical-align: top; word-wrap: break-word;">
454
- <h3 style="Margin: 0; Margin-bottom: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 32px; font-weight: normal; line-height: 32px; margin: 0; margin-bottom: 0; padding: 0 0 28px; text-align: left; word-wrap: normal;">
455
- <?php printf( __( "Hi %s,", "defender-security" ), $admin ) ?></h3>
456
- <?php $setting = \WP_Defender\Module\IP_Lockout\Model\Settings::instance() ?>
457
- <?php $utils = \WP_Defender\Behavior\Utils::instance() ?>
458
- <p style="Margin: 0; Margin-bottom: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0; margin-bottom: 0; padding: 0 0 24px; text-align: left;">
459
- <?php
460
- $lockout_duration = $setting->login_protection_lockout_ban == true ? __( "They have been banned permanently.", "defender-security" ) : sprintf( __( "They have been locked out for <strong>%s seconds.</strong>", "defender-security" ), $setting->login_protection_lockout_duration );
461
- printf( __( "We've just locked out the host <strong>%s</strong> from %s due to attempting to login with a banned username. They have been banned permanently.", "defender-security" ), $ip, network_site_url() ) ?>
462
- </p>
463
- <p style="Margin: 0; Margin-bottom: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0; margin-bottom: 0; padding: 0 0 24px; text-align: left;">
464
- <?php printf( __( "You can view the full lockout logs <a href=\"%s\">here</a>", "defender-security" ), apply_filters( 'wp_defeder/iplockout/email_report_link', network_admin_url( "admin.php?page=wdf-ip-lockout&view=logs" ) ) ) ?>
465
- .</p>
466
- </td>
467
- </tr>
468
- </tbody>
469
- </table>
470
- <!-- end main-intro -->
471
-
472
- <table class="main-signature"
473
- style="border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top;">
474
- <tbody>
475
- <tr style="padding: 0; text-align: left; vertical-align: top;">
476
- <td class="main-signature-content"
477
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; text-align: left; vertical-align: top; word-wrap: break-word;">
478
- <p style="Margin: 0; Margin-bottom: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0; margin-bottom: 0; padding: 0 0 24px; text-align: left;">
479
- <?php esc_html_e( "Stay vigilant.", "defender-security" ) ?></p>
480
- <p class="last-item"
481
- style="Margin: 0; Margin-bottom: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0; margin-bottom: 0; padding: 0; text-align: left;">
482
- <strong><?php esc_html_e( "WP Defender", "defender-security" ) ?></strong>
483
- <br>
484
- <?php esc_html_e( "Security Hero", "defender-security" ) ?>
485
- <br/>
486
- <?php esc_html_e( "WPMU DEV", "defender-security" ) ?>
487
- </p>
488
- </td>
489
- </tr>
490
- </tbody>
491
- </table>
492
- <!-- end main-signature -->
493
-
494
- </td>
495
- </tr>
496
- </tbody>
497
- </table>
498
- <!-- end main -->
499
-
500
- <table class="related" align="center"
501
- style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; text-align: left; vertical-align: top; width: 100%;">
502
- <tbody>
503
- <tr style="padding: 0; text-align: left; vertical-align: top;">
504
- <td class="related-inner"
505
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; border-top: 2px solid #e9ebe7; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 15px 30px 15px 40px; text-align: left; vertical-align: top; word-wrap: break-word;">
506
- <table
507
- style="border-collapse: collapse; border-spacing: 0; padding: 0; text-align: left; vertical-align: top;">
508
- <tbody>
509
- <tr style="padding: 0; text-align: left; vertical-align: top;">
510
- <td class="related-items-title brand" align="left"
511
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #3eb4e4; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; padding-bottom: 10px; text-align: left; vertical-align: top; word-wrap: break-word;">
512
- <?php esc_html_e( "Related plugins worth giving a try", "defender-security" ) ?>
513
- </td>
514
- </tr>
515
- <tr style="padding: 0; text-align: left; vertical-align: top;">
516
- <td style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 0; text-align: left; vertical-align: top; word-wrap: break-word;">
517
- <table class="related-items row collapse" align="center"
518
- style="border-collapse: collapse; border-spacing: 0; display: table; padding: 0; position: relative; text-align: left; vertical-align: top; width: 100%;">
519
- <tbody>
520
- <tr style="padding: 0; text-align: left; vertical-align: top;">
521
- <th class="small-12 large-6 columns first" align="left"
522
- valign="top"
523
- style="Margin: 0 auto; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0 auto; padding: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; text-align: left; width: 298px;">
524
- <a class="related-item plugin-link"
525
- href="https://premium.wpmudev.org/project/wp-hummingbird/"
526
- style="Margin: 0; color: #555555; display: table; font-family: Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 20px; margin: 0; padding: 0; text-align: left; text-decoration: none;">
527
- <img
528
- src="<?php echo wp_defender()->getPluginUrl() ?>assets/email-images/plugin-hummingbird.png"
529
- alt="Hummingbird" class="plugin-image"
530
- style="-ms-interpolation-mode: bicubic; border: none; clear: both; display: table-cell; max-width: 100%; outline: none; text-decoration: none; width: auto;">
531
- <span class="plugin-info"
532
- style="display: table-cell; padding-left: 10px; vertical-align: bottom;">
533
- <span><?php esc_html_e( "Optimize your site with", "defender-security" ) ?></span>
534
- <span class="plugin-title hummingbird"
535
- style="color: #febd30; display: block;"><strong><?php esc_html_e( "Hummingbird", "defender-security" ) ?></strong></span>
536
- </span>
537
- </a>
538
- </th>
539
- <th class="small-12 large-6 columns last" align="left"
540
- valign="top"
541
- style="Margin: 0 auto; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0 auto; padding: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; text-align: left; width: 298px;">
542
- <a class="related-item plugin-link"
543
- href="https://premium.wpmudev.org/project/snapshot/"
544
- style="Margin: 0; color: #555555; display: table; font-family: Helvetica, Arial, sans-serif; font-size: 14px; font-weight: normal; line-height: 20px; margin: 0; padding: 0; text-align: left; text-decoration: none;">
545
- <img
546
- src="<?php echo wp_defender()->getPluginUrl() ?>assets/email-images/plugin-snapshot.png"
547
- alt="Snapshot"
548
- class="plugin-image"
549
- style="-ms-interpolation-mode: bicubic; border: none; clear: both; display: table-cell; max-width: 100%; outline: none; text-decoration: none; width: auto;">
550
- <span class="plugin-info"
551
- style="display: table-cell; padding-left: 10px; vertical-align: bottom;">
552
- <span><?php esc_html_e( "Back up your hard work with", "defender-security" ) ?></span>
553
- <span class="plugin-title snapshot"
554
- style="color: #642486; display: block;"><strong><?php _e( "Snapshot", "defender-security" ) ?></strong></span>
555
- </span>
556
- </a>
557
- </th>
558
- <th class="expander"
559
- style="Margin: 0; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; line-height: 26px; margin: 0; padding: 0 !important; text-align: left; visibility: hidden; width: 0;"></th>
560
- </tr>
561
- </tbody>
562
- </table>
563
- </td>
564
- </tr>
565
- </tbody>
566
- </table>
567
- <!-- end related-inner -->
568
- </td>
569
- </tr>
570
- </tbody>
571
- </table>
572
- <!-- end related -->
573
-
574
- <!-- Preferences -->
575
- <table class="email-preferences" align="center" valign="middle"
576
- style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; text-align: left; vertical-align: top; width: 100%;">
577
- <tbody>
578
- <tr style="padding: 0; text-align: center; vertical-align: top;">
579
- <td class="email-preferences-inner"
580
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; border-top: 2px solid #e9ebe7; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hyphens: auto; line-height: 26px; margin: 0; padding: 40px; text-align: left; vertical-align: top; word-wrap: break-word;">
581
- <table class="email-preferences-content row collapse" align="center"
582
- valign="top"
583
- style="border-collapse: collapse; border-spacing: 0; display: table; padding: 0; position: relative; text-align: center; vertical-align: top; width: 100%;">
584
- <tbody>
585
- <tr style="padding: 0; text-align: center; vertical-align: top;">
586
- <th class="small-12 large-8 columns first copy" align="center"
587
- style="Margin: 0 auto; color: #707070; font-family: Helvetica, Arial, sans-serif; font-size: 12px; font-weight: normal; line-height: 20px; margin: 0 auto; padding: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; text-align: left; width: 394.66667px;">
588
- <p style="Margin: 0; Margin-bottom: 0; color: #707070; font-family: Helvetica, Arial, sans-serif; font-size: 12px; font-weight: normal; line-height: 20px; margin: 0; margin-bottom: 0; padding: 0; text-align: center;">
589
- <?php printf( __( "<a href=\"%s\">Configure reporting preferences</a>", "defender-security" ), network_admin_url( "admin.php?page=wdf-ip-lockout&view=notification" ) ) ?>
590
- </p>
591
- </th>
592
- </tr>
593
- </tbody>
594
- </table>
595
- </td>
596
- </tr>
597
- </tbody>
598
- </table>
599
- <!-- End Preferences -->
600
-
601
- <table class="company-info" align="left" valign="middle"
602
- style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; text-align: left; vertical-align: top; width: 100%;">
603
- <tbody>
604
- <tr style="padding: 0; text-align: left; vertical-align: top;">
605
- <td class="company-info-inner"
606
- style="-moz-hyphens: auto; -webkit-hyphens: auto; Margin: 0; border-collapse: collapse !important; border-top: 2px solid #e9ebe7; color: #555555; font-family: Helvetica, Arial, sans-serif; font-size: 15px; font-weight: normal; hy