PluginProbe
Adminify – White Label, Admin Menu Editor, Login Customizer / 4.2.19
Adminify – White Label, Admin Menu Editor, Login Customizer v4.2.19
4.3.1 4.3.0 4.2.26 4.2.25 4.2.24 4.2.23 4.2.22 4.2.21 4.2.20 4.2.19 4.2.18 4.2.17 4.2.16 4.2.15 4.2.14 4.2.13 4.2.12 4.2.11 4.2.10 4.2.9 4.2.8 4.2.7 4.2.6 4.2.5 4.1.17 All 164 releases
adminify / Inc / Admin / Frames / Init.php

Init.php in Adminify – White Label, Admin Menu Editor, Login Customizer 4.2.19, at Inc/Admin/Frames/Init.php

262 lines 10.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace PXLBSAdminify\Inc\Admin\Frames;
4
5 use PXLBSAdminify\Inc\Utils;
6
7 // no direct access allowed
8 if (!defined('ABSPATH')) {
9 exit;
10 }
11 /**
12 * WP Adminify
13 * Init Class
14 *
15 * @author Jewel Theme <support@jeweltheme.com>
16 */
17
18 if (!class_exists('Init')) {
19 class Init
20 {
21 public static $instance;
22 public $admin;
23 public $frame;
24
25 public static function instance()
26 {
27 if (is_null(self::$instance)) {
28 self::$instance = new self();
29 }
30 return self::$instance;
31 }
32
33 public function __construct()
34 {
35
36 if ( ! Utils::is_admin_page_request() ) {
37 return;
38 }
39
40 if ( ! $this->is_allowed() ) {
41 if ( Utils::is_iframe() ) {
42 $http_host = isset($_SERVER['HTTP_HOST']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_HOST'])) : '';
43 $request_uri = isset($_SERVER['REQUEST_URI']) ? esc_url_raw(wp_unslash($_SERVER['REQUEST_URI'])) : '';
44 $scheme = empty($_SERVER['HTTPS']) ? 'http' : 'https';
45 $actual_link = $scheme . '://' . $http_host . $request_uri;
46 Frames::custom_plugin_change_reload($actual_link);
47 }
48 return;
49 }
50
51 if ( Utils::is_iframe() ) {
52 $this->frame = new Frames();
53 } else {
54 $this->admin = new Admin();
55 }
56
57 }
58
59 /**
60 * Get the relative admin path without subdirectory prefix
61 * Handles root, subdirectory, subdomain, and multisite installations
62 *
63 * @return string Normalized path (e.g., /wp-admin/edit.php)
64 */
65 private function get_normalized_admin_path() {
66 $php_self = isset($_SERVER['PHP_SELF']) ? sanitize_text_field(wp_unslash($_SERVER['PHP_SELF'])) : '';
67
68 // Method 1: Use WordPress native function to get subdirectory path
69 // site_url() returns full URL including subdirectory
70 // e.g., https://example.com/blog or https://example.com
71 $site_url_path = wp_parse_url( site_url(), PHP_URL_PATH );
72
73 // Remove subdirectory prefix if exists
74 if ( ! empty( $site_url_path ) && $site_url_path !== '/' ) {
75 // Ensure path starts with subdirectory
76 if ( strpos( $php_self, $site_url_path ) === 0 ) {
77 $php_self = substr( $php_self, strlen( $site_url_path ) );
78 }
79 }
80
81 // Ensure path starts with /
82 if ( empty( $php_self ) || $php_self[0] !== '/' ) {
83 $php_self = '/' . $php_self;
84 }
85
86 return $php_self;
87 }
88
89 /**
90 * Check if current path matches the blocked URL pattern
91 * Supports exact match and ends-with matching for subdirectory compatibility
92 *
93 * @param string $blocked_url The URL pattern to check against
94 * @return bool True if current path matches the blocked URL
95 */
96 private function matches_blocked_url( $blocked_url ) {
97 $current_path = $this->get_normalized_admin_path();
98
99 // Exact match (normalized)
100 if ( $current_path === $blocked_url ) {
101 return true;
102 }
103
104 // Fallback: ends-with check for edge cases
105 // e.g., /wp-admin/customize.php should match even if normalization fails
106 $php_self = isset($_SERVER['PHP_SELF']) ? sanitize_text_field(wp_unslash($_SERVER['PHP_SELF'])) : '';
107 if ( $this->url_ends_with( $php_self, $blocked_url ) ) {
108 return true;
109 }
110
111 return false;
112 }
113
114 /**
115 * Check if a URL ends with a specific path
116 * Useful for subdirectory WordPress installs
117 *
118 * @param string $url Full URL or path to check
119 * @param string $ending The ending pattern to match
120 * @return bool
121 */
122 private function url_ends_with( $url, $ending ) {
123 $ending_length = strlen( $ending );
124 if ( $ending_length === 0 ) {
125 return true;
126 }
127 return substr( $url, -$ending_length ) === $ending;
128 }
129
130 /**
131 * Get WordPress installation context for debugging
132 *
133 * @return array Installation details
134 */
135 public function get_install_context() {
136 return [
137 'is_multisite' => is_multisite(),
138 'is_subdomain' => defined( 'SUBDOMAIN_INSTALL' ) && SUBDOMAIN_INSTALL,
139 'site_url' => site_url(),
140 'home_url' => home_url(),
141 'admin_url' => admin_url(),
142 'subdirectory' => wp_parse_url( site_url(), PHP_URL_PATH ) ?: '/',
143 'php_self' => isset($_SERVER['PHP_SELF']) ? sanitize_text_field(wp_unslash($_SERVER['PHP_SELF'])) : '',
144 'normalized_path' => $this->get_normalized_admin_path(),
145 ];
146 }
147
148 public function is_allowed() {
149
150 $not_allowed_urls = Admin::get_not_allowed_urls();
151
152 foreach ( $not_allowed_urls as $url_object ) {
153 if ( is_string( $url_object ) ) {
154
155 $is_allowed = true; // Scoped Default allowed
156 // Use normalized path matching for subdirectory compatibility
157 if ( $this->matches_blocked_url( $url_object ) ) {
158 $is_allowed = false; // not allowed
159 }
160
161 } else {
162
163 $is_allowed = false; // Scoped Default not allowed
164
165 // Use normalized path matching for subdirectory compatibility
166 if ( $url_object['url'] !== '*' && ! $this->matches_blocked_url( $url_object['url'] ) ) {
167 $is_allowed = true; // allowed
168 }
169
170 if ( ! $is_allowed && array_key_exists( 'query_params', $url_object ) ) {
171 if ( ! $this->check_query_params( $url_object['query_params'] ) ) {
172 $is_allowed = true; // allowed
173 }
174 }
175
176 if ( ! $is_allowed && array_key_exists( 'post_type', $url_object ) ) {
177 if ( ! $this->check_post_type( $url_object['post_type'] ) ) {
178 $is_allowed = true; // allowed
179 }
180 }
181
182 }
183
184 if ( ! $is_allowed ) {
185 return $is_allowed;
186 }
187
188 }
189
190 return true;
191
192 }
193
194 function check_query_params($query_params) {
195 // Pattern 1: Both keys and their values should check in $_GET
196 if (array_keys($query_params) === $query_params) {
197 foreach ($query_params as $key => $value) {
198 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only check, no state change.
199 if (!isset($_GET[$key]) || sanitize_text_field(wp_unslash($_GET[$key])) != $value) {
200 return false; // Key doesn't exist or the value doesn't match
201 }
202 }
203 return true; // All keys and values match
204 }
205
206 // Pattern 2: Check for only keys in $_GET, no need to check their values
207 if (array_values($query_params) === $query_params) {
208 foreach ($query_params as $param) {
209 if ( substr($param, -1) === '!' ) {
210 $param = substr($param, 0, -1);
211 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only check, no state change.
212 if ( isset($_GET[$param]) ) return false; // The key exists in $_GET
213 } else {
214 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only check, no state change.
215 if ( ! isset($_GET[$param]) ) return false; // The key doesn't exist in $_GET
216 }
217
218 }
219 return true; // All keys exist
220 }
221
222 // Pattern 3: A mix of key existence and key-value matching
223 foreach ($query_params as $key => $value) {
224 if (is_numeric($key)) {
225 // For numeric keys, we're checking only existence (Pattern 1 behavior)
226 if ( substr($value, -1) === '!' ) {
227 $value = substr($value, 0, -1);
228 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only check, no state change.
229 if ( isset($_GET[$value]) ) return false; // The key exists in $_GET
230 } else {
231 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only check, no state change.
232 if ( ! isset($_GET[$value]) ) return false; // The key doesn't exist in $_GET
233 }
234 } else {
235 // For associative keys, we check for both key and value (Pattern 2 behavior)
236 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only check, no state change.
237 if (!isset($_GET[$key]) || sanitize_text_field(wp_unslash($_GET[$key])) != $value) {
238 return false; // Key doesn't exist or value doesn't match
239 }
240 }
241 }
242
243 return true; // All conditions are met
244 }
245
246 function check_post_type($post_types) {
247 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only check, no state change.
248 if ( isset( $_GET['post_type'] ) ) {
249 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only check, no state change.
250 return in_array( sanitize_text_field( wp_unslash( $_GET['post_type'] ) ), $post_types );
251 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only check, no state change.
252 } else if ( isset( $_GET['post'] ) ) {
253 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only check, no state change.
254 return in_array( get_post_type( absint( wp_unslash( $_GET['post'] ) ) ), $post_types );
255 }
256 return in_array( 'post', $post_types );
257 }
258
259 }
260
261 }
262