PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 5.3.1
Defender Security – Malware Scanner, Login Security & Firewall v5.3.1
6.3.0 6.2.3 6.2.4 6.2.0 6.2.1 6.2.2 6.1.0 5.3.1 5.4.0 5.4.1 5.5.0 5.5.1 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.8.0 5.8.1 5.9.0 6.0.0 6.0.1 3.0.1 3.1.0 All 141 releases
defender-security / src / model / setting / class-mask-login.php

class-mask-login.php in Defender Security – Malware Scanner, Login Security & Firewall 5.3.1, at src/model/setting/class-mask-login.php

298 lines 6.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Handles the Mask Login settings.
4 *
5 * @package WP_Defender\Model\Setting
6 */
7
8 namespace WP_Defender\Model\Setting;
9
10 use Calotes\Model\Setting;
11
12 /**
13 * Model for Mask Login settings.
14 */
15 class Mask_Login extends Setting {
16
17 /**
18 * Option name.
19 *
20 * @var string
21 */
22 protected $table = 'wd_masking_login_settings';
23 /**
24 * The URL we use to replace tradition wp-admin.
25 *
26 * @var string
27 * @defender_property
28 * @sanitize_mask_url
29 */
30 public $mask_url = '';
31
32 /**
33 * Enable to redirect if user visit to tradition wp-admin or wp-login.php.
34 *
35 * @var string
36 * @defender_property
37 */
38 public $redirect_traffic = 'off';
39
40 /**
41 * The URL to redirect.
42 *
43 * @var string
44 * @defender_property
45 * @sanitize sanitize_text_field
46 */
47 public $redirect_traffic_url = '';
48
49 /**
50 * The page/post id to redirect.
51 *
52 * @var int
53 * @defender_property
54 */
55 public $redirect_traffic_page_id;
56
57 /**
58 * Main switch of this function.
59 *
60 * @var bool
61 * @defender_property
62 */
63 public $enabled = false;
64
65 /**
66 * The ticket so anyone with this can bypass the mask login, we'll need this in certain cases.
67 * Todo: need if express_tickets are not saved?
68 *
69 * @var array
70 */
71 public $express_tickets = array();
72
73 /**
74 * Backward compatibility with older version.
75 *
76 * @var array
77 */
78 protected $mapping = array(
79 'express_tickets' => 'otps',
80 );
81
82 /**
83 * Define settings labels.
84 *
85 * @return array
86 */
87 public function labels() {
88 return array(
89 'enabled' => self::get_module_name(),
90 'mask_url' => esc_html__( 'Masking URL', 'defender-security' ),
91 'redirect_traffic' => esc_html__( 'Redirect traffic', 'defender-security' ),
92 'redirect_traffic_url' => esc_html__( 'Redirection URL', 'defender-security' ),
93 'redirect_traffic_page_id' => esc_html__(
94 'Select the page or post your default login URLs will redirect to',
95 'defender-security'
96 ),
97 );
98 }
99
100 /**
101 * Checks if the mask login is active.
102 *
103 * @return bool Returns true if the mask login is active, false otherwise.
104 */
105 public function is_active() {
106 return apply_filters(
107 'wd_mask_login_enable',
108 $this->enabled && ! $this->is_mask_url_empty() && ! $this->is_mask_url_page_post_exists()
109 );
110 }
111
112 /**
113 * Returns the new login URL based on the mask URL and the given domain.
114 *
115 * @param string|null $domain The domain to use for the URL. If null, the current site URL will be used.
116 *
117 * @return string The new login URL. Returns an empty string if the mask URL is empty.
118 */
119 public function get_new_login_url( $domain = null ) {
120 if ( empty( $this->mask_url ) ) {
121 return '';
122 }
123
124 if ( null === $domain ) {
125 $domain = site_url();
126 }
127
128 return $domain . '/' . ltrim( $this->get_mask_url(), '/' );
129 }
130
131 /**
132 * Retrieves the redirect URL based on the provided redirect traffic URL.
133 *
134 * @return string The redirect URL. Returns an empty string if the redirect traffic URL is empty.
135 */
136 public function get_redirect_url(): string {
137 if ( empty( $this->redirect_traffic_url ) ) {
138 return '';
139 }
140
141 return 'url' === $this->is_url_or_slug()
142 ? $this->redirect_traffic_url
143 : untrailingslashit( get_home_url( get_current_blog_id() ) ) . '/' . ltrim(
144 $this->redirect_traffic_url,
145 '/'
146 );
147 }
148
149 /**
150 * Check the entered string is URL or slug of the internal link.
151 *
152 * @return string
153 */
154 public function is_url_or_slug(): string {
155 $regex = '/^(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[\d]{1,5})?(\/.*)?$/i';
156
157 if ( preg_match( $regex, $this->redirect_traffic_url ) ) {
158 return 'url';
159 } else {
160 return 'slug';
161 }
162 }
163
164 /**
165 * Custom validate:
166 * 1. No forbidden URL
167 * 2. No conflict with current post/page slug
168 * 3. Mask URl should not same with redirect URL
169 *
170 * @return void
171 */
172 protected function after_validate(): void {
173 if ( ! empty( $this->mask_url ) ) {
174 /**
175 * Filter forbidden slugs.
176 *
177 * @since 3.8.0
178 */
179 $forbidden = apply_filters(
180 'wd_login_forbidden_slugs',
181 array(
182 'login',
183 'wp-admin',
184 'admin',
185 'dashboard',
186 'wp-login',
187 'wp-login.php',
188 // For change '.' to '-'.
189 'wp-login-php',
190 )
191 );
192 // Remove the double slash.
193 $this->mask_url = ltrim( $this->mask_url, '/\\' );
194 if ( in_array( $this->mask_url, $forbidden, true ) ) {
195 $this->errors[] = esc_html__(
196 'The slug you have provided cannot be used for masking your login area. Please try a new one.',
197 'defender-security'
198 );
199 } elseif ( $this->is_mask_url_page_post_exists() ) {
200 $this->errors[] = esc_html__(
201 'A page already exists at this URL. Please enter a unique URL for your login area.',
202 'defender-security'
203 );
204 } elseif ( $this->mask_url === $this->redirect_traffic_url ) {
205 $this->errors[] = esc_html__( 'Redirect URL must different from Login URL', 'defender-security' );
206 }
207 }
208 }
209
210 /**
211 * Check if Mask URL slug is empty.
212 *
213 * @return bool
214 * @since 3.12.0
215 */
216 public function is_mask_url_empty(): bool {
217 return '' === ltrim( $this->mask_url, '/\\' );
218 }
219
220 /**
221 * Check if page/post already exists for the Mask URL.
222 *
223 * @return bool
224 * @since 3.12.0
225 */
226 public function is_mask_url_page_post_exists(): bool {
227 $mask_url = ltrim( $this->mask_url, '/\\' );
228 if ( empty( $mask_url ) ) {
229 return false;
230 }
231
232 $found = false;
233 if ( is_multisite() ) {
234 $offset = 0;
235 $limit = 100;
236 while ( $blog_ids = get_sites( // phpcs:ignore Generic.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition
237 array(
238 'fields' => 'ids',
239 'number' => $limit,
240 'offset' => $offset,
241 )
242 ) ) {
243 if ( is_array( $blog_ids ) ) {
244 foreach ( $blog_ids as $blog_id ) {
245 switch_to_blog( $blog_id );
246
247 $found = is_object( get_page_by_path( $mask_url, OBJECT, array( 'post', 'page' ) ) );
248
249 restore_current_blog();
250
251 if ( true === $found ) {
252 break 2;
253 }
254 }
255 }
256 $offset += $limit;
257 }
258 } else {
259 $found = is_object( get_page_by_path( $mask_url, OBJECT, array( 'post', 'page' ) ) );
260 }
261
262 return $found;
263 }
264
265 /**
266 * Retrieves the name of the Mask Login Area module.
267 *
268 * @return string The name of the Mask Login Area module.
269 */
270 public static function get_module_name(): string {
271 return esc_html__( 'Mask Login Area', 'defender-security' );
272 }
273
274 /**
275 * Check if the permalink structure is empty.
276 *
277 * @return bool
278 */
279 public function is_permalink_structure_empty(): bool {
280 $permalink_structure = get_option( 'permalink_structure' );
281
282 return empty( $permalink_structure );
283 }
284
285 /**
286 * Retrieves the mask URL based on the permalink structure option.
287 *
288 * @return string The mask URL.
289 */
290 public function get_mask_url(): string {
291 if ( $this->is_permalink_structure_empty() ) {
292 return '?' . $this->mask_url;
293 } else {
294 return $this->mask_url;
295 }
296 }
297 }
298