PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 6.3
MainWP Dashboard: Self-hosted WordPress Management for Agencies v6.3
6.3 6.2.3 6.2.2 6.2.1 6.2 6.1.8 6.1.7 6.1.6 6.1.5 6.1.4 6.1.3 6.1.2 6.1.1 6.1 6.0.12 6.0.11 4.6.0.1 5.0 5.0.1 5.0.2 5.0.3 5.0.3.1 5.0.3.2 5.1 5.1.1 All 157 releases
← All changes | class/class-mainwp-system.php +92 -39 6.2 → 6.3 View file →
@@ -34,9 +34,9 @@
34 34 * Public static variable to hold the current plugin version.
35 35 *
36 36 * @var string Current plugin version.
37 37 */
38 - public static $version = '6.2'; // NOSONAR.
38 + public static $version = '6.3'; // NOSONAR.
39 39
40 40 /**
41 41 * Private static variable to hold the single instance of the class.
42 42 *
@@ -63,9 +63,9 @@
63 63 * Private variable to hold the check update version number.
64 64 *
65 65 * @var string The plugin current update version.
66 66 */
67 - private $check_ver_update = '0.0.5';
67 + private $check_ver_update = '0.0.8';
68 68
69 69 /**
70 70 * Private variable to hold the plugin slug (mainwp/mainwp.php)
71 71 *
@@ -239,8 +239,9 @@
239 239 MainWP_Bulk_Post::get_instance();
240 240
241 241 add_action( 'admin_init', array( &$this, 'admin_init' ), 20 );
242 242 add_action( 'admin_init', array( $this, 'hook_admin_update_check' ) );
243 + add_action( 'admin_init', array( $this, 'admin_init_update' ) );
243 244 add_action( 'after_setup_theme', array( &$this, 'after_setup_theme' ) );
244 245
245 246 add_action( 'init', array( &$this, 'parse_init' ) );
246 247 add_action( 'init', array( &$this, 'init_jobs' ) );
@@ -289,8 +290,9 @@
289 290 MainWP_Themes::init();
290 291 MainWP_Plugins::init();
291 292 MainWP_Updates_Overview::init();
292 293 MainWP_Client::init();
294 + MainWP_Knowledge_UI::init();
293 295 MainWP_Rest_Api_Page::init();
294 296 MainWP_Logger::instance();
295 297
296 298 if ( class_exists( '\MainWP\Dashboard\Module\Log\Log_Manage_Insights_Events_Page' ) ) {
@@ -401,8 +403,9 @@
401 403 'mainwp_show_language_updates',
402 404 'mainwp_logger_check_daily',
403 405 'mainwp_site_actions_notification_enable',
404 406 'mainwp_update_check_version',
407 + 'mainwp_admin_init_update_data',
405 408 'mainwp_setting_demo_mode_enabled',
406 409 'mainwp_log_wait_lasttime',
407 410 'mainwp_cron_license_deactivated_alert_lasttime',
408 411 'mainwp_updatescheck_is_running',
@@ -615,9 +618,9 @@
615 618 */
616 619 public static function is_mainwp_site_page() {
617 620 $is_page = false;
618 621 //phpcs:disable WordPress.Security.NonceVerification.Recommended
619 - if ( isset( $_GET['page'] ) && 'CostTrackerAdd' !== $_GET['page'] && ( ( ( isset( $_GET['id'] ) && ! empty( $_GET['id'] ) ) || ( isset( $_GET['dashboard'] ) && ! empty( $_GET['dashboard'] ) ) || ( isset( $_GET['updateid'] ) && ! empty( $_GET['updateid'] ) ) || ( isset( $_GET['monitor_wpid'] ) && ! empty( $_GET['monitor_wpid'] ) ) || ( isset( $_GET['emailsettingsid'] ) && ! empty( $_GET['emailsettingsid'] ) ) || ( isset( $_GET['scanid'] ) && ! empty( $_GET['scanid'] ) ) ) || ( 'ServerInformation' === $_GET['page'] || 'ServerInformationCron' === $_GET['page'] || 'ErrorLog' === $_GET['page'] || 'ActionLogs' === $_GET['page'] || 'PluginPrivacy' === $_GET['page'] || 'Settings' === $_GET['page'] || 'SettingsAdvanced' === $_GET['page'] || 'SettingsEmail' === $_GET['page'] || 'PremiumUpdates' === $_GET['page'] || 'MainWPTools' === $_GET['page'] || 'SettingsInsights' === $_GET['page'] || 'SettingsApiBackups' === $_GET['page'] || 'MonitoringSettings' === $_GET['page'] ) ) ) {
622 + if ( isset( $_GET['page'] ) && 'CostTrackerAdd' !== $_GET['page'] && ( ( ( isset( $_GET['id'] ) && ! empty( $_GET['id'] ) ) || ( isset( $_GET['dashboard'] ) && ! empty( $_GET['dashboard'] ) ) || ( isset( $_GET['knowledgeid'] ) && ! empty( $_GET['knowledgeid'] ) ) || ( isset( $_GET['updateid'] ) && ! empty( $_GET['updateid'] ) ) || ( isset( $_GET['monitor_wpid'] ) && ! empty( $_GET['monitor_wpid'] ) ) || ( isset( $_GET['emailsettingsid'] ) && ! empty( $_GET['emailsettingsid'] ) ) || ( isset( $_GET['scanid'] ) && ! empty( $_GET['scanid'] ) ) ) || ( 'ServerInformation' === $_GET['page'] || 'ServerInformationCron' === $_GET['page'] || 'ErrorLog' === $_GET['page'] || 'ActionLogs' === $_GET['page'] || 'PluginPrivacy' === $_GET['page'] || 'Settings' === $_GET['page'] || 'SettingsAdvanced' === $_GET['page'] || 'SettingsEmail' === $_GET['page'] || 'PremiumUpdates' === $_GET['page'] || 'MainWPTools' === $_GET['page'] || 'SettingsInsights' === $_GET['page'] || 'SettingsApiBackups' === $_GET['page'] || 'MonitoringSettings' === $_GET['page'] ) ) ) {
620 623 $is_page = true;
621 624 }
622 625 //phpcs:enable
623 626
@@ -730,17 +733,16 @@
730 733 */
731 734 public function parse_init() {
732 735 // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
733 736 if ( isset( $_GET['mwpdl'] ) && isset( $_GET['sig'] ) ) {
737 + if ( ! isset( $_REQUEST['mwpdl'] ) || ! is_string( $_REQUEST['mwpdl'] ) || ! is_string( $_GET['sig'] ) ) {
738 + return;
739 + }
734 740 $mwpDir = MainWP_System_Utility::get_mainwp_dir();
735 741 $mwpDir = $mwpDir[0];
736 742 $mwpdl = isset( $_REQUEST['mwpdl'] ) ? wp_unslash( $_REQUEST['mwpdl'] ) : '';
737 743 $file = trailingslashit( $mwpDir ) . rawurldecode( $mwpdl );
738 744
739 - if ( stristr( rawurldecode( $mwpdl ), '..' ) ) {
740 - return;
741 - }
742 -
743 745 $hasWPFileSystem = MainWP_System_Utility::get_wp_file_system();
744 746
745 747 /**
746 748 * WordPress files system object.
@@ -748,18 +750,19 @@
748 750 * @global object
749 751 */
750 752 global $wp_filesystem;
751 753 $sig_value = wp_unslash( $_GET['sig'] );
752 - $valid_sig = MainWP_System_Utility::valid_download_sig( $file, $sig_value );
754 + $valid_sig = ! stristr( rawurldecode( $mwpdl ), '..' ) && MainWP_System_Utility::valid_download_sig( $file, $sig_value );
753 755
754 - if ( ! $valid_sig ) {
755 - MainWP_Logger::instance()->debug( ' :: download :: invalid sig :: ' . base64_decode( $sig_value ) ); // phpcs:ignore -- for debug logging.
756 - }
757 -
758 756 if ( $hasWPFileSystem && $wp_filesystem->exists( $file ) && $valid_sig ) {
759 757 MainWP_System_Handler::instance()->upload_file( $file );
760 758 exit();
761 759 }
760 +
761 + status_header( 403 );
762 + header( 'Content-Type: text/plain; charset=utf-8' );
763 + echo 'Download link is invalid or expired.';
764 + exit();
762 765 } elseif ( isset( $_GET['page'] ) ) {
763 766 if ( MainWP_System_Utility::is_admin() && 'mainwp-setup' === $_GET['page'] ) {
764 767 MainWP_Setup_Wizard::get_instance();
765 768 }
@@ -791,19 +794,15 @@
791 794 * Method hook_admin_update_check()
792 795 */
793 796 public function hook_admin_update_check() {
794 797 $current_ver = $this->check_ver_update;
795 - $saved_ver = get_option( 'mainwp_update_check_version', false );
798 + $saved_ver = get_option( 'mainwp_update_check_version', '' );
796 799
797 - if ( false === $saved_ver ) {
798 - return;
799 - }
800 -
801 800 if ( version_compare( $saved_ver, $current_ver, '=' ) ) {
802 801 return;
803 802 }
804 803
805 - if ( version_compare( $saved_ver, '0.0.4', '<' ) ) {
804 + if ( ! empty( $saved_ver ) && version_compare( $saved_ver, '0.0.4', '<' ) ) {
806 805 $sched = wp_next_scheduled( 'mainwp_cronstats_action' );
807 806 if ( ! empty( $sched ) ) {
808 807 wp_unschedule_event( $sched, 'mainwp_cronstats_action' );
809 808 }
@@ -810,9 +809,9 @@
810 809 global $wpdb;
811 810 $wpdb->query( 'DELETE FROM ' . $wpdb->usermeta . ' WHERE meta_key = "mainwp_widgets_sorted_toplevel_page_mainwp_tab" OR meta_key="mainwp_settings_show_widgets"' );//phpcs:ignore -- safe.
812 811 }
813 812
814 - if ( version_compare( $saved_ver, '0.0.5', '<' ) ) {
813 + if ( ! empty( $saved_ver ) && version_compare( $saved_ver, '0.0.5', '<' ) ) {
815 814 $all_ext = MainWP_Extensions_View::get_available_extensions();
816 815 foreach ( $all_ext as $slug => $info ) {
817 816 $data = MainWP_Api_Manager::instance()->get_activation_info( $slug );
818 817 if ( is_array( $data ) && isset( $data['api_key'] ) ) {
@@ -823,12 +822,73 @@
823 822 }
824 823 update_option( 'mainwp_extensions_all_activation_cached', '' );
825 824 }
826 825
826 + if ( version_compare( $saved_ver, '0.0.8', '<' ) ) {
827 + static::handle_admin_perform_update( 'attempted_repair_primary_monitors' ); // init attempted repair.
828 + }
829 +
827 830 MainWP_Utility::update_option( 'mainwp_update_check_version', $current_ver );
828 831 }
829 832
833 +
830 834 /**
835 + * Method admin_init_update()
836 + */
837 + public function admin_init_update() {
838 + static::handle_admin_perform_update();
839 + }
840 +
841 +
842 + /**
843 + * Method handle_admin_perform_update()
844 + *
845 + * @param string $action Init action.
846 + */
847 + public function handle_admin_perform_update( $action = '' ) {
848 +
849 + $update_actions = get_option( 'mainwp_admin_init_update_data' );
850 +
851 + /**
852 + * Filters the update actions.
853 + *
854 + * @param array $update_actions The available update actions.
855 + * @param string $action The current update action.
856 + *
857 + * @since 6.2.1
858 + *
859 + * @return array The filtered update actions.
860 + */
861 + $update_actions = apply_filters( 'mainwp_admin_init_update_data', $update_actions, $action );
862 +
863 + if ( ! empty( $action ) ) {
864 + if ( ! is_array( $update_actions ) ) {
865 + $update_actions = array();
866 + }
867 + if ( 'attempted_repair_primary_monitors' === $action ) {
868 + $update_actions['attempted_repair_primary_monitors'] = 0;
869 + }
870 + }
871 +
872 + if ( is_array( $update_actions ) ) {
873 + $update = false;
874 + if ( isset( $update_actions['attempted_repair_primary_monitors'] ) ) {
875 + $result = MainWP_DB_Uptime_Monitoring::instance()->repair_missing_primary_monitors( $update_actions['attempted_repair_primary_monitors'] );
876 + if ( is_array( $result ) && ! empty( $result['attempted'] ) ) {
877 + $update_actions['attempted_repair_primary_monitors'] = $result['attempted'];
878 + } else {
879 + unset( $update_actions['attempted_repair_primary_monitors'] );
880 + }
881 + $update = true;
882 + }
883 +
884 + if ( $update ) {
885 + MainWP_Utility::update_option( 'mainwp_admin_init_update_data', $update_actions );
886 + }
887 + }
888 + }
889 +
890 + /**
831 891 * Method admin_init()
832 892 *
833 893 * Do nothing if current user is not an Admin else display the page.
834 894 *
@@ -916,8 +976,9 @@
916 976 'installedBulkSettingsManager' => is_plugin_active( 'mainwp-bulk-settings-manager/mainwp-bulk-settings-manager.php' ) ? 1 : 0,
917 977 'maximumSyncRequests' => ( get_option( 'mainwp_maximumSyncRequests' ) === false ) ? 8 : get_option( 'mainwp_maximumSyncRequests' ),
918 978 'maximumInstallUpdateRequests' => ( get_option( 'mainwp_maximumInstallUpdateRequests' ) === false ) ? 3 : get_option( 'mainwp_maximumInstallUpdateRequests' ),
919 979 'maximumUptimeMonitoringRequests' => (int) get_option( 'mainwp_maximum_uptime_monitoring_requests', 10 ),
980 + 'siteRemovalTimeout' => MainWP_Connect::get_site_removal_ajax_timeout_ms(),
920 981 '_wpnonce' => wp_create_nonce( 'mainwp-admin-nonce' ),
921 982 'quickThemeChangeNonce' => wp_create_nonce( 'mainwp_quick_theme_change' ),
922 983 'demoMode' => MainWP_Demo_Handle::is_demo_mode() ? 1 : 0,
923 984 'roll_ui_icon' => MainWP_Updates_Helper::get_roll_icon( '', true ),
@@ -972,8 +1033,9 @@
972 1033 remove_action( 'admin_notices', 'update_nag', 3 );
973 1034 }
974 1035 }
975 1036
1037 +
976 1038 /**
977 1039 * Method hook_wp_shutdown()
978 1040 */
979 1041 public function hook_wp_shutdown() {
@@ -1163,8 +1225,10 @@
1163 1225 wp_enqueue_script( 'mainwp-backups', MAINWP_PLUGIN_URL . 'assets/js/mainwp-backups.js', array(), $this->current_version, true );
1164 1226 wp_enqueue_script( 'mainwp-posts', MAINWP_PLUGIN_URL . 'assets/js/mainwp-posts.js', array(), $this->current_version, true );
1165 1227 wp_enqueue_script( 'mainwp-users', MAINWP_PLUGIN_URL . 'assets/js/mainwp-users.js', array(), $this->current_version, true );
1166 1228 wp_enqueue_script( 'mainwp-clients', MAINWP_PLUGIN_URL . 'assets/js/mainwp-clients.js', array(), $this->current_version, true );
1229 + wp_enqueue_script( 'mainwp-knowledge', MAINWP_PLUGIN_URL . 'assets/js/mainwp-knowledge.js', array( 'jquery', 'fomantic-ui' ), $this->current_version, true );
1230 + wp_localize_script( 'mainwp-knowledge', 'mainwpKnowledgeStrings', MainWP_Knowledge_UI::js_strings() );
1167 1231 wp_enqueue_script( 'mainwp-extensions', MAINWP_PLUGIN_URL . 'assets/js/mainwp-extensions.js', array(), $this->current_version, true );
1168 1232 wp_enqueue_script( 'moment' );
1169 1233 wp_enqueue_script( 'fomantic-ui', MAINWP_PLUGIN_URL . 'assets/js/fomantic-ui/fomantic-ui.js', array( 'jquery' ), $this->current_version, false );
1170 1234
@@ -1175,9 +1239,10 @@
1175 1239
1176 1240 wp_enqueue_script( 'datatables-natural-sorting', MAINWP_PLUGIN_URL . 'assets/js/sorting/natural.min.js', array( 'jquery', 'datatables' ), $this->current_version, true );
1177 1241
1178 1242 wp_enqueue_script( 'clipboard' );
1179 - wp_enqueue_script( 'mainwp-rest-api', MAINWP_PLUGIN_URL . 'assets/js/mainwp-rest-api.js', array(), time(), true );
1243 + wp_enqueue_script( 'mainwp-ai-client-setup', MAINWP_PLUGIN_URL . 'assets/js/mainwp-ai-client-setup.js', array(), $this->current_version, true );
1244 + wp_enqueue_script( 'mainwp-rest-api', MAINWP_PLUGIN_URL . 'assets/js/mainwp-rest-api.js', array( 'mainwp-ai-client-setup' ), time(), true );
1180 1245
1181 1246 if ( isset( $_GET['page'] ) && 'ManageGroups' === $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1182 1247 wp_enqueue_script( 'mainwp-groups', MAINWP_PLUGIN_URL . 'assets/js/mainwp-groups.js', array(), $this->current_version, true );
1183 1248 }
@@ -1268,9 +1333,9 @@
1268 1333 *
1269 1334 * @return array<string, array<int, mixed>> Command palette configuration.
1270 1335 */
1271 1336 private function get_command_palette_data() {
1272 - $registered_pages = $this->get_command_palette_registered_pages();
1337 + $registered_pages = $this->get_command_palette_registered_pages();
1273 1338 $registered_page_urls = array();
1274 1339
1275 1340 foreach ( $registered_pages as $slug => $page_data ) {
1276 1341 $registered_page_urls[ $slug ] = $page_data['url'];
@@ -1961,9 +2026,9 @@
1961 2026 <div class="ui large modal" id="mainwp-response-data-modal">
1962 2027 <i class="close icon"></i>
1963 2028 <div class="header"><?php esc_html_e( 'Child Site Response', 'mainwp' ); ?></div>
1964 2029 <div class="content">
1965 - <div class="ui info message"><?php esc_html_e( 'To see the response in a more readable way, you can copy it and paste it into some HTML render tool, such as Codepen.io.', 'mainwp' ); ?>
2030 + <div class="ui info message"><?php esc_html_e( 'This is the readable child/HTTP response from the failed request (status, headers snippet, and body when it is safe to show). Copy it for support if needed.', 'mainwp' ); ?>
1966 2031 </div>
1967 2032 </div>
1968 2033 <div class="scrolling content content-response" contenteditable="true"></div>
1969 2034 <div class="actions">
@@ -2070,8 +2135,9 @@
2070 2135 * @uses \MainWP\Dashboard\MainWP_Install::install()
2071 2136 */
2072 2137 public function update_install() {
2073 2138 MainWP_DB_Client::instance();
2139 + MainWP_DB_Knowledge::instance();
2074 2140 MainWP_DB_Site_Actions::instance();
2075 2141 MainWP_Install::instance()->install();
2076 2142 $this->check_to_updates();
2077 2143 }
@@ -2127,15 +2193,15 @@
2127 2193 /**
2128 2194 * Method get_selected_sites_with_allowed_sites.
2129 2195 *
2130 2196 * @param array $selected_ids Selected sites IDs.
2131 - * @param array $current_sites Current sites IDs.
2197 + * @param array $current_sites_ids Current sites IDs.
2132 2198 * @return array Not selected but in not allowed sites in current sites ids, and selected sites ids.
2133 2199 */
2134 2200 public static function get_selected_sites_with_allowed_sites( $selected_ids, $current_sites_ids = array() ) {
2135 2201
2136 - $allowed_sites = apply_filters( 'mainwp_currentuserallowedaccesssites', 'all' );
2137 - if ( 'all' === $allowed_sites ) {
2202 + $allowed_ids = MainWP_Abilities_Util::get_allowed_site_ids();
2203 + if ( 'all' === $allowed_ids ) {
2138 2204 return $selected_ids;
2139 2205 }
2140 2206
2141 2207 if ( ! is_array( $selected_ids ) ) {
@@ -2145,22 +2211,8 @@
2145 2211 if ( ! is_array( $current_sites_ids ) ) {
2146 2212 $current_sites_ids = array();
2147 2213 }
2148 2214
2149 - $allowed_sites = MainWP_DB::instance()->get_websites_for_current_user();
2150 - if ( empty( $allowed_sites ) ) {
2151 - return array();
2152 - }
2153 -
2154 - $allowed_ids = array_values(
2155 - array_map(
2156 - function ( $item ) {
2157 - return $item->id;
2158 - },
2159 - $allowed_sites
2160 - )
2161 - );
2162 -
2163 2215 $client_site_ids = array();
2164 2216 foreach ( $selected_ids as $id ) {
2165 2217 if ( in_array( $id, $allowed_ids ) ) {
2166 2218 $client_site_ids[] = $id;
@@ -2166,8 +2218,9 @@
2166 2218 $client_site_ids[] = $id;
2167 2219 }
2168 2220 }
2169 2221
2222 + // Team Control cannot remove memberships outside the caller's site grants.
2170 2223 foreach ( $current_sites_ids as $id ) {
2171 2224 if ( ! in_array( $id, $selected_ids ) && ! in_array( $id, $allowed_ids ) ) { // If it’s not in the allowed site IDs, the user is not permitted to change it.
2172 2225 $client_site_ids[] = $id; // keep this site ids.
2173 2226 }