PluginProbe
Adminify – White Label, Admin Menu Editor, Login Customizer / 4.1.3
Adminify – White Label, Admin Menu Editor, Login Customizer v4.1.3
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 | Libs/Addons.php +86 -150 4.1.174.1.3 View file →
@@ -49,13 +49,9 @@
49 49 add_action('admin_menu', array($this, 'admin_menu'), 1000);
50 50 }
51 51 add_action('wp_ajax_jltwp_adminify_addons_upgrade_plugin', array($this, 'jltwp_adminify_addons_upgrade_plugin'));
52 52 add_action('wp_ajax_jltwp_adminify_addons_activate_plugin', array($this, 'jltwp_adminify_addons_activate_plugin'));
53 - // Notify the site admin when a renamed legacy addon is detected
54 - // alongside its replacement. Per WordPress.org plugin guidelines,
55 - // we must not deactivate or activate plugins automatically; the
56 - // user has to perform the swap themselves from the Plugins screen.
57 - add_action('admin_notices', array($this, 'maybe_renamed_addon_notice'));
53 + add_action('plugins_loaded', array($this, 'maybe_replace_addons_path'), 1000); // 1000 is important
58 54 add_action( 'rest_api_init', array( $this , 'jltwp_adminify_addons_rest_routes') );
59 55 }
60 56
61 57 public function jltwp_adminify_addons_rest_routes() {
@@ -72,40 +68,26 @@
72 68 ));
73 69 }
74 70
75 71 public function adminify_is_admin_user() {
76 - if ( is_multisite() && ! is_super_admin() ) {
77 - return new \WP_Error('rest_forbidden', __('You are not allowed to access this resource.', 'adminify'), array('status' => 403));
78 - }
79 - if ( ! current_user_can('manage_options') ) {
80 - return new \WP_Error('rest_forbidden', __('You are not allowed to access this resource.', 'adminify'), array('status' => 403));
81 - }
82 - return true;
72 + return current_user_can('manage_options');
83 73 }
84 74
85 75 public function adminify_verify_nonce_and_permissions() {
86 - // The install-addons endpoint may both install AND activate
87 - // addons depending on each addon's current status, so the
88 - // caller must hold BOTH capabilities. On multisite this also
89 - // requires super admin.
90 - if ( is_multisite() && ! is_super_admin() ) {
91 - return new \WP_Error('rest_forbidden', __('Super admin required.', 'adminify'), array('status' => 403));
76 + // Check user
77 + if ( ! current_user_can('manage_options') ) {
78 + return new WP_Error('forbidden', 'You are not allowed to do this.', array('status' => 403));
92 79 }
93 - if ( ! current_user_can('install_plugins') ) {
94 - return new \WP_Error('rest_forbidden', __('You are not allowed to install plugins.', 'adminify'), array('status' => 403));
80 +
81 + // Check nonce from header
82 + $nonce = $_SERVER['HTTP_X_WP_NONCE'] ?? '';
83 + if ( ! wp_verify_nonce($nonce, 'wp_rest') ) {
84 + return new WP_Error('rest_cookie_invalid_nonce', __('Invalid nonce.'), array('status' => 403));
95 85 }
96 - if ( ! current_user_can('activate_plugins') ) {
97 - return new \WP_Error('rest_forbidden', __('You are not allowed to activate plugins.', 'adminify'), array('status' => 403));
86 + if ( is_multisite() && ! is_super_admin() ) {
87 + return new WP_Error('not_allowed', 'Super admin only on multisite.', array('status' => 403));
98 88 }
99 89
100 - // Nonce check from header. Sanitize and unslash before verifying.
101 - $nonce = isset($_SERVER['HTTP_X_WP_NONCE'])
102 - ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_WP_NONCE'] ) )
103 - : '';
104 - if ( ! wp_verify_nonce( $nonce, 'wp_rest' ) ) {
105 - return new \WP_Error('rest_cookie_invalid_nonce', __('Invalid nonce.', 'adminify'), array('status' => 403));
106 - }
107 -
108 90 return true;
109 91 }
110 92
111 93
@@ -134,122 +116,100 @@
134 116 }
135 117
136 118
137 119 public function jltwp_adminify_install_addons( $request ) {
138 - $addons = $request->get_param('addons');
139 - if ( empty($addons) || ! is_array($addons) ) {
140 - return new \WP_Error('no_addons', __('No addons were selected.', 'adminify'), array('status' => 400));
120 + $addons = $request->get_param('addons');
121 + if ( empty($addons) || !is_array($addons) ) {
122 + return new WP_Error('no_addons', 'No addons were selected.', array('status' => 400));
141 123 }
142 124
143 125 $plugins_list = $this->jltwp_adminify_get_addons_plugins_list()->data;
144 - foreach( $addons as $key => $plugin ) {
145 - $plugin = sanitize_key( $plugin );
146 - if ( ! isset( $plugins_list[ $plugin ] ) ) {
126 + foreach( $addons as $key => $plugin ){
127 + if($plugins_list[$plugin]['status'] == "activated") continue;
128 + if($plugins_list[$plugin]['status'] == "installed") {
129 + $this->jltwp_adminify_activate_plugin_by_slug($plugin);
147 130 continue;
148 131 }
149 - if ( $plugins_list[ $plugin ]['status'] === 'activated' ) {
150 - continue;
151 - }
152 - if ( $plugins_list[ $plugin ]['status'] === 'installed' ) {
153 - $this->jltwp_adminify_activate_plugin_by_slug( $plugin );
154 - continue;
155 - }
156 132 $params = [
157 133 'request_type' => 'rest',
158 - 'plugin' => $plugins_list[ $plugin ]['download_link'],
134 + 'plugin' => $plugins_list[$plugin]['download_link'],
159 135 ];
160 136
161 - $this->jltwp_adminify_addons_upgrade_plugin( $params );
137 + $this->jltwp_adminify_addons_upgrade_plugin($params);
162 138 }
163 -
164 - return rest_ensure_response(['message' => __('Addons processed.', 'adminify'), 'addons' => $addons]);
139 +
140 + return rest_ensure_response(['message' => 'Addons installed', 'addons' => $addons]);
165 141 }
166 142
167 143 function jltwp_adminify_activate_plugin_by_slug($slug) {
168 - // Activation requires the activate_plugins capability in
169 - // addition to whatever capability gated the calling endpoint.
170 - // On multisite, activation must be performed by a super admin.
171 - if ( is_multisite() && ! is_super_admin() ) {
172 - return new \WP_Error( 'rest_forbidden', __( 'Super admin required to activate plugins.', 'adminify' ), array( 'status' => 403 ) );
173 - }
174 - if ( ! current_user_can( 'activate_plugins' ) ) {
175 - return new \WP_Error( 'rest_forbidden', __( 'You are not allowed to activate plugins.', 'adminify' ), array( 'status' => 403 ) );
176 - }
177 -
178 - // Reject any slug containing path separators / traversal so
179 - // $slug cannot escape WP_PLUGIN_DIR.
180 - if ( ! is_string( $slug ) || $slug === '' || strpbrk( $slug, "/\\" ) !== false || strpos( $slug, '..' ) !== false ) {
181 - return new \WP_Error( 'invalid_slug', __( 'Invalid plugin slug.', 'adminify' ), array( 'status' => 400 ) );
182 - }
183 -
184 - // Slug must be present in the trusted addons list.
185 - if ( ! array_key_exists( $slug, (array) $this->plugins_list ) ) {
186 - return new \WP_Error( 'invalid_slug', __( 'Invalid plugin slug.', 'adminify' ), array( 'status' => 400 ) );
187 - }
188 -
189 144 $plugin_path = WP_PLUGIN_DIR . '/' . $slug;
190 145
191 - if ( ! is_dir( $plugin_path ) ) {
146 + if (!is_dir($plugin_path)) {
192 147 return;
193 148 }
194 149
195 - $installed_plugins = get_plugins( '/' . $slug );
196 - if ( empty( $installed_plugins ) ) {
150 + $plugin_files = glob("$plugin_path/*.php");
151 + if (!$plugin_files || empty($plugin_files)) {
197 152 return;
198 153 }
199 154
200 - $plugin_relative_path = $slug . '/' . key( $installed_plugins );
155 + $main_plugin_file = basename($plugin_files[0]);
156 + $plugin_relative_path = $slug . '/' . $main_plugin_file;
201 157
202 - if ( is_plugin_active( $plugin_relative_path ) ) {
158 + if (is_plugin_active($plugin_relative_path)) {
203 159 return;
204 160 }
205 161
206 - activate_plugin( $plugin_relative_path );
162 + activate_plugin($plugin_relative_path);
207 163 }
208 164
209 - /**
210 - * Map of legacy addon slugs that have been renamed to a new slug.
211 - *
212 - * @return array<string,string>
213 - */
214 - protected function renamed_addons_map() {
215 - return [
216 - 'sidebar-generator/adminify-sidebar-generator.php' => 'adminify-sidebar-generator/adminify-sidebar-generator.php',
165 + public function maybe_replace_addons_path() {
166 +
167 + $addons = [
168 + 'sidebar-generator/adminify-sidebar-generator.php' => 'adminify-sidebar-generator/adminify-sidebar-generator.php'
217 169 ];
218 - }
219 170
220 - /**
221 - * Show a non-blocking admin notice if a legacy (renamed) addon is
222 - * still installed. We never deactivate or activate plugins on the
223 - * user's behalf; the notice points them to the Plugins screen so
224 - * they can perform the swap themselves.
225 - */
226 - public function maybe_renamed_addon_notice() {
227 - if ( ! current_user_can('activate_plugins') ) {
228 - return;
229 - }
171 + foreach ($addons as $old_plugin => $new_plugin) {
230 172
231 - $messages = [];
173 + $old_plugin_path = WP_PLUGIN_DIR . '/' . $old_plugin;
174 + $new_plugin_path = WP_PLUGIN_DIR . '/' . $new_plugin;
232 175
233 - foreach ($this->renamed_addons_map() as $old_plugin => $new_plugin) {
234 - $old_exists = file_exists(WP_PLUGIN_DIR . '/' . $old_plugin);
235 - if ( ! $old_exists ) {
176 + // Both files exist, delete the old one
177 + if ( file_exists($old_plugin_path) && file_exists($new_plugin_path) ) {
178 + unlink(dirname($old_plugin_path));
236 179 continue;
237 180 }
238 181
239 - $messages[] = sprintf(
240 - /* translators: 1: old plugin slug, 2: new plugin slug */
241 - esc_html__('"%1$s" has been renamed to "%2$s". Please deactivate and remove the old version, then install the new one from the Adminify Addons screen.', 'adminify'),
242 - esc_html(dirname($old_plugin)),
243 - esc_html(dirname($new_plugin))
244 - );
245 - }
182 + // If the old file exists and the new file doesn't exist, rename the old file to the new file
183 + if ( file_exists($old_plugin_path) && !file_exists($new_plugin_path) ) {
246 184
247 - if ( empty($messages) ) {
248 - return;
185 + // check if the old plugin is active
186 + include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
187 +
188 + $is_active = is_plugin_active( $old_plugin );
189 +
190 + if ( $is_active ) {
191 + // Deactivate the old plugin
192 + deactivate_plugins( $old_plugin );
193 + // Rename the old plugin to the new plugin
194 + rename( dirname($old_plugin_path), dirname($new_plugin_path) );
195 +
196 + if ( file_exists($new_plugin_path) ) {
197 + // Clear the plugin cache
198 + wp_cache_delete( 'plugins', 'plugins' );
199 +
200 + // Activate the new plugin
201 + activate_plugin( $new_plugin );
202 + }
203 +
204 + } else {
205 + // Rename the old plugin to the new plugin
206 + rename( dirname($old_plugin_path), dirname($new_plugin_path) );
207 + }
208 + }
209 +
249 210 }
250 211
251 - echo '<div class="notice notice-warning"><p><strong>' . esc_html__('Adminify', 'adminify') . ':</strong> ' . esc_html(implode('<br>', $messages)) . '</p></div>';
252 212 }
253 213
254 214 /**
255 215 * Includes
@@ -257,18 +217,17 @@
257 217 * @author Jewel Theme <support@jeweltheme.com>
258 218 */
259 219 public function includes()
260 220 {
261 - // wp-load.php must never be required from within a plugin: the
262 - // plugin already runs inside WordPress. The wp-admin includes
263 - // below are required for plugin install/upgrade APIs used by
264 - // this class and are loaded with require_once immediately
265 - // before the functions from each file are called.
266 - require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
267 - require_once ABSPATH . 'wp-admin/includes/file.php';
268 - require_once ABSPATH . 'wp-admin/includes/misc.php';
269 - require_once ABSPATH . 'wp-admin/includes/plugin.php';
270 - require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
221 + // if (!function_exists('install_plugin_install_status')) {
222 + // require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
223 + require_once(ABSPATH . '/wp-load.php');
224 + require_once(ABSPATH . 'wp-admin/includes/plugin-install.php');
225 + require_once(ABSPATH . 'wp-admin/includes/file.php');
226 + require_once(ABSPATH . 'wp-admin/includes/misc.php');
227 + require_once(ABSPATH . 'wp-admin/includes/plugin.php');
228 + require_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php');
229 + // }
271 230 }
272 231
273 232 /**
274 233 * Menu Items
@@ -327,13 +286,12 @@
327 286 if ( $this->is_eligible_for_coupon() ) {
328 287 // Get the coupon
329 288 $coupon = $this->maybe_create_and_get_coupon();
330 289 if (!empty($coupon) && !empty($coupon['code'])) {
331 - echo '<h3>' . sprintf(
332 - /* translators: %s: Coupon code */
333 - esc_html__('Coupon Code: <strong style="color: red">%s</strong> Redeem this coupon code to get free access to all our premium addons (Except Admin Bar Editor, RoleMaster Suite and Master Addons). Learn how to <a href="https://wpadminify.com/redeem-addons-using-coupon-code/" target="_blank">redeem coupon code?</a>', 'adminify'),
290 + echo sprintf(
291 + __('<h3>Coupon Code: <strong style="color: red">%s</strong> Redeem this coupon code to get free access to all our premium addons (Except Admin Bar Editor, RoleMaster Suite and Master Addons). Learn how to <a href="https://wpadminify.com/redeem-addons-using-coupon-code/" target="_blank">redeem coupon code?</a></h3> ', 'adminify'),
334 292 esc_attr($coupon['code'])
335 - ) . '</h3> ';
293 + );
336 294 }
337 295 }
338 296
339 297 echo '<style>
@@ -419,9 +377,9 @@
419 377 ?>
420 378 <div class='wp-adminify-addons-header'>
421 379 <div class='wp-adminify-addons-title'>
422 380 <h2>
423 - <?php echo esc_html__('Add Ons for Adminify', 'adminify'); ?>
381 + <?php echo esc_html__('Add Ons for WP Adminify', 'adminify'); ?>
424 382 </h2>
425 383 <?php $this->jltwp_adminify_addons_check(); ?>
426 384 </div>
427 385 <div class='wp-adminify-addons-menu'>
@@ -732,20 +690,12 @@
732 690 }
733 691
734 692 $plugin_slug = $this->get_the_plugin_slug( $plugin );
735 693
736 - if ( ! array_key_exists( $plugin_slug, $this->plugins_list ) ) {
694 + if ( ! array_key_exists( $plugin_slug, $this->plugins_list) ) {
737 695 wp_send_json_error(array('mess' => __('Invalid plugin', 'adminify')));
738 696 }
739 -
740 - // Replace the user-supplied $plugin value with values derived
741 - // from our trusted internal addons list, so that arbitrary
742 - // input never reaches Plugin_Upgrader::install()/upgrade() or
743 - // activate_plugin().
744 - $trusted_install_source = isset($this->plugins_list[$plugin_slug]['download_link'])
745 - ? $this->plugins_list[$plugin_slug]['download_link']
746 - : '';
747 -
697 +
748 698 if($params == null){
749 699 $type = isset($_POST['type']) ? sanitize_text_field(wp_unslash($_POST['type'])) : 'install';
750 700 }else{
751 701 $type = 'install';
@@ -754,13 +704,9 @@
754 704 $upgrader = new \Plugin_Upgrader($skin);
755 705
756 706 if ('install' === $type) {
757 707
758 - if ( empty( $trusted_install_source ) ) {
759 - wp_send_json_error(array('mess' => __('Invalid plugin', 'adminify')));
760 - }
761 -
762 - $result = $upgrader->install( $trusted_install_source );
708 + $result = $upgrader->install($plugin);
763 709 if ($params == null){
764 710 if (empty($result) || empty($upgrader->result)) {
765 711 wp_send_json_error(
766 712 array(
@@ -819,21 +765,11 @@
819 765 }
820 766 }
821 767 } else {
822 768
823 - // Resolve the trusted plugin file path from the validated
824 - // slug instead of trusting the raw $_POST value, so that
825 - // is_plugin_active(), Plugin_Upgrader::upgrade() and
826 - // activate_plugin() never receive attacker-supplied paths.
827 - $installed_plugins = get_plugins( '/' . $plugin_slug );
828 - if ( empty( $installed_plugins ) ) {
829 - wp_send_json_error(array('mess' => __('Plugin not installed.', 'adminify')));
830 - }
831 - $trusted_plugin_file = $plugin_slug . '/' . key( $installed_plugins );
769 + $is_active = is_plugin_active($plugin);
770 + $result = $upgrader->upgrade($plugin);
832 771
833 - $is_active = is_plugin_active( $trusted_plugin_file );
834 - $result = $upgrader->upgrade( $trusted_plugin_file );
835 -
836 772 if ($params == null){
837 773 if ( empty($result) || is_wp_error($result) ) {
838 774 wp_send_json_error(
839 775 array(
@@ -842,9 +778,9 @@
842 778 );
843 779 }
844 780 }
845 781
846 - $active_status = activate_plugin( $trusted_plugin_file );
782 + $active_status = activate_plugin($plugin);
847 783
848 784 if ($params == null){
849 785 if ( empty($active_status) || is_wp_error($active_status) ) {
850 786 wp_send_json_error(