PluginProbe
Adminify – White Label, Admin Menu Editor, Login Customizer / 4.2.15
Adminify – White Label, Admin Menu Editor, Login Customizer v4.2.15
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.15, at Inc/Admin/Frames/Init.php

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