PluginProbe
Adminify – White Label, Admin Menu Editor, Login Customizer / 4.0.2.5
Adminify – White Label, Admin Menu Editor, Login Customizer v4.0.2.5
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
← All changes | Inc/Admin/Frames/Init.php +25 -143 4.2.194.0.2.5 View file →
@@ -1,10 +1,8 @@
1 1 <?php
2 2
3 -namespace PXLBSAdminify\Inc\Admin\Frames;
3 +namespace WPAdminify\Inc\Admin\Frames;
4 4
5 -use PXLBSAdminify\Inc\Utils;
6 -
7 5 // no direct access allowed
8 6 if (!defined('ABSPATH')) {
9 7 exit;
10 8 }
@@ -32,24 +30,16 @@
32 30
33 31 public function __construct()
34 32 {
35 33
36 - if ( ! Utils::is_admin_page_request() ) {
37 - return;
38 - }
39 -
40 34 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);
35 + if ( is_iframe() ) {
36 + Frames::custom_plugin_change_reload();
47 37 }
48 38 return;
49 39 }
50 40
51 - if ( Utils::is_iframe() ) {
41 + if ( is_iframe() ) {
52 42 $this->frame = new Frames();
53 43 } else {
54 44 $this->admin = new Admin();
55 45 }
@@ -55,136 +45,36 @@
55 45 }
56 46
57 47 }
58 48
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 49 public function is_allowed() {
149 50
150 51 $not_allowed_urls = Admin::get_not_allowed_urls();
151 52
152 53 foreach ( $not_allowed_urls as $url_object ) {
54 +
153 55 if ( is_string( $url_object ) ) {
154 56
155 57 $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 - }
58 + if ( $url_object === $_SERVER['PHP_SELF'] ) $is_allowed = false; // not allowed
160 59
161 60 } else {
162 61
163 62 $is_allowed = false; // Scoped Default not allowed
164 63
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 - }
64 + if ( $url_object['url'] !== '*' && $url_object['url'] !== $_SERVER['PHP_SELF'] ) $is_allowed = true; // allowed
169 65
170 66 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 - }
67 + if ( ! $this->check_query_params( $url_object['query_params'] ) ) $is_allowed = true; // allowed
174 68 }
175 69
176 70 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 - }
71 + if ( ! $this->check_post_type( $url_object['post_type'] ) ) $is_allowed = true; // allowed
180 72 }
181 73
182 74 }
183 75
184 - if ( ! $is_allowed ) {
185 - return $is_allowed;
186 - }
76 + if ( ! $is_allowed ) return $is_allowed;
187 77
188 78 }
189 79
190 80 return true;
@@ -191,28 +81,17 @@
191 81
192 82 }
193 83
194 84 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 85
206 - // Pattern 2: Check for only keys in $_GET, no need to check their values
86 + // Pattern 1: Check for only keys in $_GET, no need to check their values
207 87 if (array_values($query_params) === $query_params) {
208 88 foreach ($query_params as $param) {
89 +
209 90 if ( substr($param, -1) === '!' ) {
210 91 $param = substr($param, 0, -1);
211 - // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only check, no state change.
212 92 if ( isset($_GET[$param]) ) return false; // The key exists in $_GET
213 93 } else {
214 - // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only check, no state change.
215 94 if ( ! isset($_GET[$param]) ) return false; // The key doesn't exist in $_GET
216 95 }
217 96
218 97 }
@@ -218,8 +97,18 @@
218 97 }
219 98 return true; // All keys exist
220 99 }
221 100
101 + // Pattern 2: Both keys and their values should check in $_GET
102 + if (array_keys($query_params) === $query_params) {
103 + foreach ($query_params as $key => $value) {
104 + if (!isset($_GET[$key]) || $_GET[$key] != $value) {
105 + return false; // Key doesn't exist or the value doesn't match
106 + }
107 + }
108 + return true; // All keys and values match
109 + }
110 +
222 111 // Pattern 3: A mix of key existence and key-value matching
223 112 foreach ($query_params as $key => $value) {
224 113 if (is_numeric($key)) {
225 114 // For numeric keys, we're checking only existence (Pattern 1 behavior)
@@ -224,18 +113,15 @@
224 113 if (is_numeric($key)) {
225 114 // For numeric keys, we're checking only existence (Pattern 1 behavior)
226 115 if ( substr($value, -1) === '!' ) {
227 116 $value = substr($value, 0, -1);
228 - // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only check, no state change.
229 117 if ( isset($_GET[$value]) ) return false; // The key exists in $_GET
230 118 } else {
231 - // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only check, no state change.
232 119 if ( ! isset($_GET[$value]) ) return false; // The key doesn't exist in $_GET
233 120 }
234 121 } else {
235 122 // 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) {
123 + if (!isset($_GET[$key]) || $_GET[$key] != $value) {
238 124 return false; // Key doesn't exist or value doesn't match
239 125 }
240 126 }
241 127 }
@@ -243,16 +129,12 @@
243 129 return true; // All conditions are met
244 130 }
245 131
246 132 function check_post_type($post_types) {
247 - // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only check, no state change.
248 133 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.
134 + return in_array( $_GET['post_type'], $post_types );
252 135 } 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 );
136 + return in_array( get_post_type( $_GET['post'] ), $post_types );
255 137 }
256 138 return in_array( 'post', $post_types );
257 139 }
258 140