PluginProbe
Adminify – White Label, Admin Menu Editor, Login Customizer / 4.0.5.4
Adminify – White Label, Admin Menu Editor, Login Customizer v4.0.5.4
4.3.2 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 All 165 releases
← All changes | Libs/Addons.php +98 -167 4.1.174.0.5.4 View file →
@@ -41,21 +41,13 @@
41 41 $this->plugins_list = $this->plugins_list();
42 42
43 43 $this->includes();
44 44
45 - // Show Addons menu only on network admin for multisite, or on regular admin for single site
46 - if ( is_multisite() ) {
47 - add_action('network_admin_menu', array($this, 'admin_menu'), 1000);
48 - } else {
49 - add_action('admin_menu', array($this, 'admin_menu'), 1000);
50 - }
45 + add_action('admin_menu', array($this, 'admin_menu'), 1000);
46 + // add_action('network_admin_menu', array($this, 'admin_menu'), $this->menu_order);
51 47 add_action('wp_ajax_jltwp_adminify_addons_upgrade_plugin', array($this, 'jltwp_adminify_addons_upgrade_plugin'));
52 48 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'));
49 + add_action('plugins_loaded', array($this, 'maybe_replace_addons_path'), 1000); // 1000 is important
58 50 add_action( 'rest_api_init', array( $this , 'jltwp_adminify_addons_rest_routes') );
59 51 }
60 52
61 53 public function jltwp_adminify_addons_rest_routes() {
@@ -61,9 +53,10 @@
61 53 public function jltwp_adminify_addons_rest_routes() {
62 54 register_rest_route('adminify/v1', '/get-addons-list', array(
63 55 'methods' => 'GET',
64 56 'callback' => [$this, 'jltwp_adminify_get_addons_plugins_list'],
65 - 'permission_callback' => [$this, 'adminify_is_admin_user'],
57 + // 'permission_callback' => [$this, 'adminify_is_admin_user'],
58 + 'permission_callback' => '__return_true',
66 59 ));
67 60
68 61 register_rest_route('adminify/v1', '/install-addons', array(
69 62 'methods' => 'POST',
@@ -72,40 +65,26 @@
72 65 ));
73 66 }
74 67
75 68 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;
69 + return current_user_can('manage_options');
83 70 }
84 71
85 72 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));
73 + // Check user
74 + if ( ! current_user_can('manage_options') ) {
75 + return new WP_Error('forbidden', 'You are not allowed to do this.', array('status' => 403));
92 76 }
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));
77 +
78 + // Check nonce from header
79 + $nonce = $_SERVER['HTTP_X_WP_NONCE'] ?? '';
80 + if ( ! wp_verify_nonce($nonce, 'wp_rest') ) {
81 + return new WP_Error('rest_cookie_invalid_nonce', __('Invalid nonce.'), array('status' => 403));
95 82 }
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));
83 + if ( is_multisite() && ! is_super_admin() ) {
84 + return new WP_Error('not_allowed', 'Super admin only on multisite.', array('status' => 403));
98 85 }
99 86
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 87 return true;
109 88 }
110 89
111 90
@@ -134,122 +113,100 @@
134 113 }
135 114
136 115
137 116 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));
117 + $addons = $request->get_param('addons');
118 + if ( empty($addons) || !is_array($addons) ) {
119 + return new WP_Error('no_addons', 'No addons were selected.', array('status' => 400));
141 120 }
142 121
143 122 $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 ] ) ) {
123 + foreach( $addons as $key => $plugin ){
124 + if($plugins_list[$plugin]['status'] == "activated") continue;
125 + if($plugins_list[$plugin]['status'] == "installed") {
126 + $this->jltwp_adminify_activate_plugin_by_slug($plugin);
147 127 continue;
148 128 }
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 129 $params = [
157 130 'request_type' => 'rest',
158 - 'plugin' => $plugins_list[ $plugin ]['download_link'],
131 + 'plugin' => $plugins_list[$plugin]['download_link'],
159 132 ];
160 133
161 - $this->jltwp_adminify_addons_upgrade_plugin( $params );
134 + $this->jltwp_adminify_addons_upgrade_plugin($params);
162 135 }
163 -
164 - return rest_ensure_response(['message' => __('Addons processed.', 'adminify'), 'addons' => $addons]);
136 +
137 + return rest_ensure_response(['message' => 'Addons installed', 'addons' => $addons]);
165 138 }
166 139
167 140 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 141 $plugin_path = WP_PLUGIN_DIR . '/' . $slug;
190 142
191 - if ( ! is_dir( $plugin_path ) ) {
143 + if (!is_dir($plugin_path)) {
192 144 return;
193 145 }
194 146
195 - $installed_plugins = get_plugins( '/' . $slug );
196 - if ( empty( $installed_plugins ) ) {
147 + $plugin_files = glob("$plugin_path/*.php");
148 + if (!$plugin_files || empty($plugin_files)) {
197 149 return;
198 150 }
199 151
200 - $plugin_relative_path = $slug . '/' . key( $installed_plugins );
152 + $main_plugin_file = basename($plugin_files[0]);
153 + $plugin_relative_path = $slug . '/' . $main_plugin_file;
201 154
202 - if ( is_plugin_active( $plugin_relative_path ) ) {
155 + if (is_plugin_active($plugin_relative_path)) {
203 156 return;
204 157 }
205 158
206 - activate_plugin( $plugin_relative_path );
159 + activate_plugin($plugin_relative_path);
207 160 }
208 161
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',
162 + public function maybe_replace_addons_path() {
163 +
164 + $addons = [
165 + 'sidebar-generator/adminify-sidebar-generator.php' => 'adminify-sidebar-generator/adminify-sidebar-generator.php'
217 166 ];
218 - }
219 167
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 - }
168 + foreach ($addons as $old_plugin => $new_plugin) {
230 169
231 - $messages = [];
170 + $old_plugin_path = WP_PLUGIN_DIR . '/' . $old_plugin;
171 + $new_plugin_path = WP_PLUGIN_DIR . '/' . $new_plugin;
232 172
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 ) {
173 + // Both files exist, delete the old one
174 + if ( file_exists($old_plugin_path) && file_exists($new_plugin_path) ) {
175 + unlink(dirname($old_plugin_path));
236 176 continue;
237 177 }
238 178
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 - }
179 + // If the old file exists and the new file doesn't exist, rename the old file to the new file
180 + if ( file_exists($old_plugin_path) && !file_exists($new_plugin_path) ) {
246 181
247 - if ( empty($messages) ) {
248 - return;
182 + // check if the old plugin is active
183 + include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
184 +
185 + $is_active = is_plugin_active( $old_plugin );
186 +
187 + if ( $is_active ) {
188 + // Deactivate the old plugin
189 + deactivate_plugins( $old_plugin );
190 + // Rename the old plugin to the new plugin
191 + rename( dirname($old_plugin_path), dirname($new_plugin_path) );
192 +
193 + if ( file_exists($new_plugin_path) ) {
194 + // Clear the plugin cache
195 + wp_cache_delete( 'plugins', 'plugins' );
196 +
197 + // Activate the new plugin
198 + activate_plugin( $new_plugin );
199 + }
200 +
201 + } else {
202 + // Rename the old plugin to the new plugin
203 + rename( dirname($old_plugin_path), dirname($new_plugin_path) );
204 + }
205 + }
206 +
249 207 }
250 208
251 - echo '<div class="notice notice-warning"><p><strong>' . esc_html__('Adminify', 'adminify') . ':</strong> ' . esc_html(implode('<br>', $messages)) . '</p></div>';
252 209 }
253 210
254 211 /**
255 212 * Includes
@@ -257,18 +214,17 @@
257 214 * @author Jewel Theme <support@jeweltheme.com>
258 215 */
259 216 public function includes()
260 217 {
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';
218 + // if (!function_exists('install_plugin_install_status')) {
219 + // require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
220 + require_once(ABSPATH . '/wp-load.php');
221 + require_once(ABSPATH . 'wp-admin/includes/plugin-install.php');
222 + require_once(ABSPATH . 'wp-admin/includes/file.php');
223 + require_once(ABSPATH . 'wp-admin/includes/misc.php');
224 + require_once(ABSPATH . 'wp-admin/includes/plugin.php');
225 + require_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php');
226 + // }
271 227 }
272 228
273 229 /**
274 230 * Menu Items
@@ -327,13 +283,12 @@
327 283 if ( $this->is_eligible_for_coupon() ) {
328 284 // Get the coupon
329 285 $coupon = $this->maybe_create_and_get_coupon();
330 286 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'),
287 + echo sprintf(
288 + __('<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 289 esc_attr($coupon['code'])
335 - ) . '</h3> ';
290 + );
336 291 }
337 292 }
338 293
339 294 echo '<style>
@@ -419,9 +374,9 @@
419 374 ?>
420 375 <div class='wp-adminify-addons-header'>
421 376 <div class='wp-adminify-addons-title'>
422 377 <h2>
423 - <?php echo esc_html__('Add Ons for Adminify', 'adminify'); ?>
378 + <?php echo esc_html__('Add Ons for WP Adminify', 'adminify'); ?>
424 379 </h2>
425 380 <?php $this->jltwp_adminify_addons_check(); ?>
426 381 </div>
427 382 <div class='wp-adminify-addons-menu'>
@@ -631,12 +586,11 @@
631 586 if (!wp_verify_nonce($nonce, 'jltwp_adminify_addons_nonce')) {
632 587 wp_send_json_error(array('mess' => __('Nonce is invalid', 'adminify')));
633 588 }
634 589
635 - // Security check - only administrators can activate plugins
636 - if (!current_user_can('activate_plugins')) {
637 - wp_send_json_error(array('mess' => __('You do not have permission to perform this action.', 'adminify')));
638 - }
590 + // if ((is_multisite() && !is_network_admin()) || !current_user_can('install_plugins')) {
591 + // wp_send_json_error(array('mess' => __('Invalid access', 'adminify')));
592 + // }
639 593
640 594 $plugin = sanitize_text_field(wp_unslash($_POST['plugin']));
641 595 $plugin_links = array_values(wp_list_pluck($this->plugins_list, 'slug'));
642 596
@@ -716,9 +670,9 @@
716 670 require_once ABSPATH . 'wp-admin/includes/class-plugin-upgrader.php';
717 671
718 672 if($params == null){
719 673 $nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
720 -
674 +
721 675 if (!wp_verify_nonce($nonce, 'jltwp_adminify_addons_nonce')) {
722 676 wp_send_json_error(array('mess' => __('Nonce is invalid', 'adminify')));
723 677 }
724 678 $plugin = sanitize_text_field(wp_unslash($_POST['plugin']));
@@ -725,27 +679,18 @@
725 679 }else{
726 680 $plugin = $params['plugin'];
727 681 }
728 682
729 - // Security check - only administrators can install plugins
730 - if (!current_user_can('install_plugins')) {
731 - wp_send_json_error(array('mess' => __('You do not have permission to perform this action.', 'adminify')));
732 - }
733 -
683 + // if ((is_multisite() && !is_network_admin()) || !current_user_can('install_plugins')) {
684 + // wp_send_json_error(array('mess' => __('Invalid access', 'adminify')));
685 + // }
686 +
734 687 $plugin_slug = $this->get_the_plugin_slug( $plugin );
735 688
736 - if ( ! array_key_exists( $plugin_slug, $this->plugins_list ) ) {
689 + if ( ! array_key_exists( $plugin_slug, $this->plugins_list) ) {
737 690 wp_send_json_error(array('mess' => __('Invalid plugin', 'adminify')));
738 691 }
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 -
692 +
748 693 if($params == null){
749 694 $type = isset($_POST['type']) ? sanitize_text_field(wp_unslash($_POST['type'])) : 'install';
750 695 }else{
751 696 $type = 'install';
@@ -754,13 +699,9 @@
754 699 $upgrader = new \Plugin_Upgrader($skin);
755 700
756 701 if ('install' === $type) {
757 702
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 );
703 + $result = $upgrader->install($plugin);
763 704 if ($params == null){
764 705 if (empty($result) || empty($upgrader->result)) {
765 706 wp_send_json_error(
766 707 array(
@@ -819,21 +760,11 @@
819 760 }
820 761 }
821 762 } else {
822 763
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 );
764 + $is_active = is_plugin_active($plugin);
765 + $result = $upgrader->upgrade($plugin);
832 766
833 - $is_active = is_plugin_active( $trusted_plugin_file );
834 - $result = $upgrader->upgrade( $trusted_plugin_file );
835 -
836 767 if ($params == null){
837 768 if ( empty($result) || is_wp_error($result) ) {
838 769 wp_send_json_error(
839 770 array(
@@ -842,9 +773,9 @@
842 773 );
843 774 }
844 775 }
845 776
846 - $active_status = activate_plugin( $trusted_plugin_file );
777 + $active_status = activate_plugin($plugin);
847 778
848 779 if ($params == null){
849 780 if ( empty($active_status) || is_wp_error($active_status) ) {
850 781 wp_send_json_error(