From 4d8a9c57623f261c7bbae183e7bb633ff8b684ad Mon Sep 17 00:00:00 2001 From: thanghv Date: Thu, 14 May 2020 00:57:25 +0700 Subject: [PATCH] Refactoring --- class/class-mainwp-child-branding.php | 6 +- class/class-mainwp-child-callable.php | 82 ++- class/class-mainwp-child-stats.php | 17 +- class/class-mainwp-child.php | 702 ++------------------------ class/class-mainwp-clone-install.php | 20 +- class/class-mainwp-connect.php | 464 +++++++++++++++++ class/class-mainwp-helper.php | 250 +++------ class/class-mainwp-keyword-links.php | 20 +- class/class-mainwp-utility.php | 213 ++++++++ 9 files changed, 909 insertions(+), 865 deletions(-) create mode 100644 class/class-mainwp-connect.php create mode 100644 class/class-mainwp-utility.php diff --git a/class/class-mainwp-child-branding.php b/class/class-mainwp-child-branding.php index c36c75c..ad73640 100644 --- a/class/class-mainwp-child-branding.php +++ b/class/class-mainwp-child-branding.php @@ -246,7 +246,7 @@ class MainWP_Child_Branding { $extra_setting['login_image'] = array(); } else { try { - $upload = $this->upload_image( $settings['child_login_image_url'] ); + $upload = $this->branding_upload_image( $settings['child_login_image_url'] ); if ( null !== $upload ) { $extra_setting['login_image'] = array( 'path' => $upload['path'], @@ -272,7 +272,7 @@ class MainWP_Child_Branding { $extra_setting['favico_image'] = array(); } else { try { - $upload = $this->upload_image( $settings['child_favico_image_url'] ); + $upload = $this->branding_upload_image( $settings['child_favico_image_url'] ); if ( null !== $upload ) { $extra_setting['favico_image'] = array( 'path' => $upload['path'], @@ -313,7 +313,7 @@ class MainWP_Child_Branding { return $information; } - public static function upload_image( $img_url ) { + public static function branding_upload_image( $img_url ) { include_once ABSPATH . 'wp-admin/includes/file.php'; add_filter( 'http_request_args', array( MainWP_Helper::get_class_name(), 'reject_unsafe_urls' ), 99, 2 ); diff --git a/class/class-mainwp-child-callable.php b/class/class-mainwp-child-callable.php index 55f5120..4d48d15 100644 --- a/class/class-mainwp-child-callable.php +++ b/class/class-mainwp-child-callable.php @@ -97,7 +97,45 @@ class MainWP_Child_Callable { } return self::$instance; } + + public function init_call_functions( $auth ) { + $callable = false; + $func_auth = false; + $callable_no_auth = false; + $func_no_auth = false; + + // check to execute mainwp child's callable functions. + if ( isset( $_POST['function'] ) ) { + $func = $_POST['function']; + $callable = $this->is_callable_function( $func ); + if ( $callable ) { + $func_auth = $func; + } + + if ( ! $callable ) { + $callable_no_auth = $this->is_callable_function_no_auth( $func ); + if ( $callable_no_auth ) { + $func_no_auth = $func; + } + } + } + + // Call the function required. + if ( $auth && isset( $_POST['function'] ) && $callable ) { + define( 'DOING_CRON', true ); + MainWP_Helper::handle_fatal_error(); + MainWP_Utility::fix_for_custom_themes(); + $this->call_function( $func_auth ); + } elseif ( isset( $_POST['function'] ) && $callable_no_auth ) { + define( 'DOING_CRON', true ); + MainWP_Utility::fix_for_custom_themes(); + $this->call_function_no_auth( $func_no_auth ); + } elseif ( isset( $_POST['function'] ) && isset( $_POST['mainwpsignature'] ) && ! $callable && ! $callable_no_auth ) { + MainWP_Helper::error( __( 'Required version has not been detected. Please, make sure that you are using the latest version of the MainWP Child plugin on your site.', 'mainwp-child' ) ); + } + } + public function is_callable_function( $func ) { if ( isset( $this->callableFunctions[ $func ] ) ) { return true; @@ -1060,7 +1098,7 @@ class MainWP_Child_Callable { } try { - $upload = MainWP_Helper::upload_file( $file_url, $dir, $filename ); + $upload = $this->uploader_upload_file( $file_url, $dir, $filename ); if ( null !== $upload ) { $information['success'] = true; } @@ -1070,6 +1108,48 @@ class MainWP_Child_Callable { mainwp_child_helper()->write( $information ); } + + public function uploader_upload_file( $file_url, $path, $file_name ) { + // to fix uploader extension rename htaccess file issue. + if ( '.htaccess' != $file_name && '.htpasswd' != $file_name ) { + $file_name = sanitize_file_name( $file_name ); + } + + $full_file_name = $path . DIRECTORY_SEPARATOR . $file_name; + + $response = wp_remote_get( + $file_url, + array( + 'timeout' => 10 * 60 * 60, + 'stream' => true, + 'filename' => $full_file_name, + ) + ); + + if ( is_wp_error( $response ) ) { + unlink( $full_file_name ); + throw new \Exception( 'Error: ' . $response->get_error_message() ); + } + + if ( 200 !== (int) wp_remote_retrieve_response_code( $response ) ) { + unlink( $full_file_name ); + throw new \Exception( 'Error 404: ' . trim( wp_remote_retrieve_response_message( $response ) ) ); + } + if ( '.phpfile.txt' === substr( $file_name, - 12 ) ) { + $new_file_name = substr( $file_name, 0, - 12 ) . '.php'; + $new_file_name = $path . DIRECTORY_SEPARATOR . $new_file_name; + $moved = rename( $full_file_name, $new_file_name ); + if ( $moved ) { + return array( 'path' => $new_file_name ); + } else { + unlink( $full_file_name ); + throw new \Exception( 'Error: Copy file.' ); + } + } + + return array( 'path' => $full_file_name ); + } + public function wordpress_seo() { \MainWP_WordPress_SEO::instance()->action(); } diff --git a/class/class-mainwp-child-stats.php b/class/class-mainwp-child-stats.php index b118055..cb45faf 100644 --- a/class/class-mainwp-child-stats.php +++ b/class/class-mainwp-child-stats.php @@ -38,7 +38,11 @@ class MainWP_Child_Stats { return self::$instance; } - // Show stats without login - only allowed while no account is added yet. + /** + * + * Show stats without login - only allowed while no account is added yet. + * + */ public function get_site_stats_no_auth( $information = array() ) { if ( get_option( 'mainwp_child_pubkey' ) ) { $hint = '
' . __( 'Hint: Go to the child site, deactivate and reactivate the MainWP Child plugin and try again.', 'mainwp-child' ); @@ -510,8 +514,6 @@ class MainWP_Child_Stats { public function update_external_settings() { - $update_htaccess = false; - if ( isset( $_POST['cloneSites'] ) ) { if ( '0' !== $_POST['cloneSites'] ) { $arr = json_decode( urldecode( $_POST['cloneSites'] ), 1 ); @@ -527,17 +529,10 @@ class MainWP_Child_Stats { if ( isset( $_POST['pluginDir'] ) ) { if ( get_option( 'mainwp_child_pluginDir' ) !== $_POST['pluginDir'] ) { - MainWP_Helper::update_option( 'mainwp_child_pluginDir', $_POST['pluginDir'], 'yes' ); - $update_htaccess = true; + MainWP_Helper::update_option( 'mainwp_child_pluginDir', $_POST['pluginDir'], 'yes' ); } } elseif ( false !== get_option( 'mainwp_child_pluginDir' ) ) { MainWP_Helper::update_option( 'mainwp_child_pluginDir', false, 'yes' ); - $update_htaccess = true; - } - - if ( $update_htaccess ) { - global $mainWPChild; - $mainWPChild->update_htaccess( true ); } } diff --git a/class/class-mainwp-child.php b/class/class-mainwp-child.php index 3826990..9541f42 100644 --- a/class/class-mainwp-child.php +++ b/class/class-mainwp-child.php @@ -55,15 +55,9 @@ class MainWP_Child { MainWP_Helper::update_option( 'mainwp_child_plugin_version', self::$version, 'yes' ); } - $this->check_other_auth(); + MainWP_Connect::instance()->check_other_auth(); - MainWP_Clone::get()->init(); - MainWP_Child_Server_Information::init(); - MainWP_Client_Report::instance()->init(); - MainWP_Child_Plugins_Check::instance(); - MainWP_Child_Themes_Check::instance(); - - $this->run_saved_snippets(); + $this->init_extensions(); if ( ! get_option( 'mainwp_child_pubkey' ) ) { MainWP_Child_Branding::instance()->save_branding_options( 'branding_disconnected', 'yes' ); @@ -74,7 +68,7 @@ class MainWP_Child { if ( defined( 'DOING_CRON' ) && DOING_CRON ) { if ( isset( $_GET['mainwp_child_run'] ) && ! empty( $_GET['mainwp_child_run'] ) ) { - add_action( 'init', array( $this, 'cron_active' ), PHP_INT_MAX ); + add_action( 'init', array( MainWP_Utility::get_class_name(), 'cron_active' ), PHP_INT_MAX ); } } } @@ -297,23 +291,6 @@ class MainWP_Child { MainWP_Helper::update_option( 'mainwp_child_update_version', $this->update_version, 'yes' ); } - public function cron_active() { - if ( ! defined( 'DOING_CRON' ) || ! DOING_CRON ) { - return; - } - if ( empty( $_GET['mainwp_child_run'] ) || 'test' !== $_GET['mainwp_child_run'] ) { - return; - } - session_write_close(); - header( 'Content-Type: text/html; charset=' . get_bloginfo( 'charset' ), true ); - header( 'X-Robots-Tag: noindex, nofollow', true ); - header( 'X-MainWP-Child-Version: ' . self::$version, true ); - nocache_headers(); - if ( 'test' == $_GET['mainwp_child_run'] ) { - die( 'MainWP Test' ); - } - die( '' ); - } public function admin_notice() { // Admin Notice... @@ -345,51 +322,10 @@ class MainWP_Child { load_plugin_textdomain( 'mainwp-child', false, dirname( dirname( plugin_basename( __FILE__ ) ) ) . '/languages/' ); } - public function check_other_auth() { - $auths = get_option( 'mainwp_child_auth' ); - - if ( ! $auths ) { - $auths = array(); - } - - if ( ! isset( $auths['last'] ) || $auths['last'] < mktime( 0, 0, 0, date( 'm' ), date( 'd' ), date( 'Y' ) ) ) { // phpcs:ignore -- local time. - // Generate code for today. - for ( $i = 0; $i < $this->maxHistory; $i ++ ) { - if ( ! isset( $auths[ $i + 1 ] ) ) { - continue; - } - - $auths[ $i ] = $auths[ $i + 1 ]; - } - $newI = $this->maxHistory + 1; - while ( isset( $auths[ $newI ] ) ) { - unset( $auths[ $newI ++ ] ); - } - $auths[ $this->maxHistory ] = md5( MainWP_Helper::rand_string( 14 ) ); - $auths['last'] = time(); - MainWP_Helper::update_option( 'mainwp_child_auth', $auths, 'yes' ); - } - } - - public function is_valid_auth( $key ) { - $auths = get_option( 'mainwp_child_auth' ); - if ( ! $auths ) { - return false; - } - for ( $i = 0; $i <= $this->maxHistory; $i ++ ) { - if ( isset( $auths[ $i ] ) && ( $auths[ $i ] === $key ) ) { - return true; - } - } - - return false; - } - public function template_redirect() { - $this->maintenance_alert_404(); + MainWP_Utility::instance()->maintenance_alert(); } - public function plugin_row_meta( $plugin_meta, $plugin_file ) { if ( $this->plugin_slug !== $plugin_file ) { return $plugin_meta; @@ -820,128 +756,6 @@ class MainWP_Child { return $this->maxHistory; } - public function mod_rewrite_rules( $pRules ) { - - $home_root = wp_parse_url( home_url() ); - if ( isset( $home_root['path'] ) ) { - $home_root = trailingslashit( $home_root['path'] ); - } else { - $home_root = '/'; - } - - $rules = "\n"; - $rules .= "RewriteEngine On\n"; - $rules .= "RewriteBase $home_root\n"; - - // add in the rules that don't redirect to WP's index.php (and thus shouldn't be handled by WP at all). - foreach ( $pRules as $match => $query ) { - // Apache 1.3 does not support the reluctant (non-greedy) modifier. - $match = str_replace( '.+?', '.+', $match ); - - $rules .= 'RewriteRule ^' . $match . ' ' . $home_root . $query . " [QSA,L]\n"; - } - - $rules .= "\n"; - - return $rules; - } - - public function update_htaccess( $hard = false ) { - if ( ! $hard && defined( 'DOING_CRON' ) && DOING_CRON ) { - return; - } - - if ( $hard ) { - include_once ABSPATH . '/wp-admin/includes/misc.php'; - - $home_path = ABSPATH; - $htaccess_file = $home_path . '.htaccess'; - if ( function_exists( 'save_mod_rewrite_rules' ) ) { - $rules = explode( "\n", '' ); - - insert_with_markers( $htaccess_file, 'MainWP', $rules ); - - } - } - } - - public function check_login() { - - if ( ! isset( $_POST['mainwpsignature'] ) || empty( $_POST['mainwpsignature'] ) ) { - return false; - } - - $file = ''; - if ( isset( $_REQUEST['f'] ) ) { - $file = $_REQUEST['f']; - } elseif ( isset( $_REQUEST['file'] ) ) { - $file = $_REQUEST['file']; - } elseif ( isset( $_REQUEST['fdl'] ) ) { - $file = $_REQUEST['fdl']; - } - - $auth = $this->auth( isset( $_POST['mainwpsignature'] ) ? rawurldecode( $_POST['mainwpsignature'] ) : '', isset( $_POST['function'] ) ? $_POST['function'] : rawurldecode( ( isset( $_REQUEST['where'] ) ? $_REQUEST['where'] : $file ) ), isset( $_POST['nonce'] ) ? $_POST['nonce'] : '', isset( $_POST['nossl'] ) ? $_POST['nossl'] : 0 ); - - if ( ! $auth ) { - MainWP_Helper::error( __( 'Authentication failed! Please deactivate and re-activate the MainWP Child plugin on this site.', 'mainwp-child' ) ); - } - - $auth_user = false; - if ( $auth ) { - // disable duo auth for mainwp. - remove_action( 'init', 'duo_verify_auth', 10 ); - - // Check if the user exists & is an administrator. - if ( isset( $_POST['function'] ) && isset( $_POST['user'] ) ) { - - $user = null; - - if ( isset( $_POST['alt_user'] ) && ! empty( $_POST['alt_user'] ) ) { - if ( $this->check_login_as( $_POST['alt_user'] ) ) { - $auth_user = $_POST['alt_user']; - $user = get_user_by( 'login', $auth_user ); - } - } - - // if not valid alternative admin. - if ( ! $user ) { - // check connected admin existed. - $user = get_user_by( 'login', $_POST['user'] ); - $auth_user = $_POST['user']; - } - - if ( ! $user ) { - MainWP_Helper::error( __( 'That administrator username was not found on this child site. Please verify that it is an existing administrator.', 'mainwp-child' ) ); - } - - if ( 10 != $user->wp_user_level && ( ! isset( $user->user_level ) || 10 != $user->user_level ) && ! $user->has_cap( 'level_10' ) ) { - MainWP_Helper::error( __( 'That user is not an administrator. Please use an administrator user to establish the connection.', 'mainwp-child' ) ); - } - - $this->login( $auth_user ); - } - - if ( isset( $_POST['function'] ) && 'visitPermalink' === $_POST['function'] ) { - - if ( empty( $auth_user ) ) { - $auth_user = $_POST['user']; - } - - if ( $this->login( $auth_user, true ) ) { - return; - } else { - exit(); - } - } - - // Redirect to the admin part if needed. - if ( isset( $_POST['admin'] ) && '1' === $_POST['admin'] ) { - wp_safe_redirect( get_option( 'siteurl' ) . '/wp-admin/' ); - die(); - } - } - } - public function parse_init() { if ( isset( $_REQUEST['cloneFunc'] ) ) { @@ -971,12 +785,10 @@ class MainWP_Child { MainWP_Helper::update_option( 'mainwp_child_fix_htaccess', 'yes', 'yes' ); } - $this->update_htaccess(); - // if login required. if ( isset( $_REQUEST['login_required'] ) && ( '1' === $_REQUEST['login_required'] ) && isset( $_REQUEST['user'] ) ) { - $valid_login_required = $this->parse_login_required(); - // retunr parse init if login required are not valid. + $valid_login_required = MainWP_Connect::instance()->parse_login_required(); + // return parse init if login required are not valid. if ( ! $valid_login_required ) { return; } @@ -991,11 +803,15 @@ class MainWP_Child { // Register does not require auth, so we register here. if ( isset( $_POST['function'] ) && 'register' === $_POST['function'] ) { define( 'DOING_CRON', true ); - self::fix_for_custom_themes(); - $this->register_site(); + MainWP_Utility::fix_for_custom_themes(); + MainWP_Connect::instance()->register_site(); // register the site. } - $auth = $this->auth( isset( $_POST['mainwpsignature'] ) ? $_POST['mainwpsignature'] : '', isset( $_POST['function'] ) ? $_POST['function'] : '', isset( $_POST['nonce'] ) ? $_POST['nonce'] : '', isset( $_POST['nossl'] ) ? $_POST['nossl'] : 0 ); + // if auth connect are not valid then exit or return. + if ( ! MainWP_Connect::instance()->parse_init_auth() ) + return; + + $auth = MainWP_Connect::instance()->auth( isset( $_POST['mainwpsignature'] ) ? $_POST['mainwpsignature'] : '', isset( $_POST['function'] ) ? $_POST['function'] : '', isset( $_POST['nonce'] ) ? $_POST['nonce'] : '', isset( $_POST['nossl'] ) ? $_POST['nossl'] : 0 ); if ( ! $auth && isset( $_POST['mainwpsignature'] ) ) { MainWP_Helper::error( __( 'Authentication failed! Please deactivate & re-activate the MainWP Child plugin on this site and try again.', 'mainwp-child' ) ); @@ -1018,7 +834,7 @@ class MainWP_Child { $user = null; if ( isset( $_POST['alt_user'] ) && ! empty( $_POST['alt_user'] ) ) { - if ( $this->check_login_as( $_POST['alt_user'] ) ) { + if ( MainWP_Connect::instance()->check_login_as( $_POST['alt_user'] ) ) { $auth_user = $_POST['alt_user']; $user = get_user_by( 'login', $auth_user ); } @@ -1039,7 +855,7 @@ class MainWP_Child { MainWP_Helper::error( __( 'Invalid user. Please verify that the user has administrator privileges.', 'mainwp-child' ) ); } - $this->login( $auth_user ); + MainWP_Connect::instance()->login( $auth_user ); } if ( isset( $_POST['function'] ) && 'visitPermalink' === $_POST['function'] ) { @@ -1048,7 +864,7 @@ class MainWP_Child { $auth_user = $_POST['user']; } - if ( $this->login( $auth_user, true ) ) { + if ( MainWP_Connect::instance()->login( $auth_user, true ) ) { return; } else { exit(); @@ -1063,315 +879,32 @@ class MainWP_Child { } // Init extensions. - $this->init_extensions(); + $this->parse_init_extensions(); global $_wp_submenu_nopriv; if ( null === $_wp_submenu_nopriv ) { $_wp_submenu_nopriv = array(); // phpcs:ignore -- to fix warning. } - $this->parse_callable_functions( $auth ); - $this->parse_keyword_links(); + MainWP_Child_Callable::get_instance()->init_call_functions( $auth ); + + MainWP_Keyword_Links::instance()->parse_init_keyword_links(); + } + + public function check_login() { + MainWP_Connect::instance()->check_login(); } - - private function parse_login_required() { - - global $current_user; - - $alter_login_required = false; - $username = rawurldecode( $_REQUEST['user'] ); - - if ( isset( $_REQUEST['alt_user'] ) && ! empty( $_REQUEST['alt_user'] ) ) { - $alter_login_required = $this->check_login_as( $_REQUEST['alt_user'] ); - - if ( $alter_login_required ) { - $username = rawurldecode( $_REQUEST['alt_user'] ); - } - } - - if ( is_user_logged_in() ) { - global $current_user; - if ( 10 !== $current_user->wp_user_level && ( ! isset( $current_user->user_level ) || 10 !== $current_user->user_level ) && ! current_user_can( 'level_10' ) ) { - do_action( 'wp_logout' ); - } - } - - $signature = rawurldecode( isset( $_REQUEST['mainwpsignature'] ) ? $_REQUEST['mainwpsignature'] : '' ); - $file = ''; - if ( isset( $_REQUEST['f'] ) ) { - $file = $_REQUEST['f']; - } elseif ( isset( $_REQUEST['file'] ) ) { - $file = $_REQUEST['file']; - } elseif ( isset( $_REQUEST['fdl'] ) ) { - $file = $_REQUEST['fdl']; - } - - $auth = $this->auth( $signature, rawurldecode( ( isset( $_REQUEST['where'] ) ? $_REQUEST['where'] : $file ) ), isset( $_REQUEST['nonce'] ) ? $_REQUEST['nonce'] : '', isset( $_REQUEST['nossl'] ) ? $_REQUEST['nossl'] : 0 ); - if ( ! $auth ) { - return; - } - - if ( ! is_user_logged_in() || $username !== $current_user->user_login ) { - if ( ! $this->login( $username ) ) { - return; - } - - global $current_user; - if ( 10 !== $current_user->wp_user_level && ( ! isset( $current_user->user_level ) || 10 !== $current_user->user_level ) && ! current_user_can( 'level_10' ) ) { - // if is not alternative admin login. - // it is connected admin login. - if ( ! $alter_login_required ) { - // log out if connected admin is not admin level 10. - do_action( 'wp_logout' ); - - return; - } - } - } - - if ( isset( $_REQUEST['fdl'] ) ) { - if ( stristr( $_REQUEST['fdl'], '..' ) ) { - return; - } - - $this->upload_file( $_REQUEST['fdl'], isset( $_REQUEST['foffset'] ) ? $_REQUEST['foffset'] : 0 ); - exit; - } - - $where = isset( $_REQUEST['where'] ) ? $_REQUEST['where'] : ''; - if ( isset( $_POST['f'] ) || isset( $_POST['file'] ) ) { - $file = ''; - if ( isset( $_POST['f'] ) ) { - $file = $_POST['f']; - } elseif ( isset( $_POST['file'] ) ) { - $file = $_POST['file']; - } - - $where = 'admin.php?page=mainwp_child_tab&tab=restore-clone'; - if ( '' === session_id() ) { - session_start(); - } - $_SESSION['file'] = $file; - $_SESSION['size'] = $_POST['size']; - } - - // to support open not wp-admin url. - $open_location = isset( $_REQUEST['open_location'] ) ? $_REQUEST['open_location'] : ''; - if ( ! empty( $open_location ) ) { - $open_location = base64_decode( $open_location ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode function is used for begin reasons. - $_vars = MainWP_Helper::parse_query( $open_location ); - $_path = wp_parse_url( $open_location, PHP_URL_PATH ); - if ( isset( $_vars['_mwpNoneName'] ) && isset( $_vars['_mwpNoneValue'] ) ) { - $_vars[ $_vars['_mwpNoneName'] ] = wp_create_nonce( $_vars['_mwpNoneValue'] ); - unset( $_vars['_mwpNoneName'] ); - unset( $_vars['_mwpNoneValue'] ); - $open_url = ''; - foreach ( $_vars as $key => $value ) { - $open_url .= $key . '=' . $value . '&'; - } - $open_url = rtrim( $open_url, '&' ); - $open_location = '/wp-admin/' . $_path . '?' . $open_url; - } else { - if ( strpos( $open_location, 'nonce=child_temp_nonce' ) !== false ) { - $open_location = str_replace( 'nonce=child_temp_nonce', 'nonce=' . wp_create_nonce( 'wp-ajax' ), $open_location ); - } - } - wp_safe_redirect( site_url() . $open_location ); - exit(); - } - - wp_safe_redirect( admin_url( $where ) ); - - exit(); + private function init_extensions() { + MainWP_Clone::get()->init(); + MainWP_Child_Server_Information::init(); + MainWP_Client_Report::instance()->init(); + MainWP_Child_Plugins_Check::instance(); + MainWP_Child_Themes_Check::instance(); + MainWP_Utility::instance()->run_saved_snippets(); } - - - private function parse_callable_functions( $auth ) { - $callable = false; - $func_auth = false; - - $callable_no_auth = false; - $func_no_auth = false; - - // check to execute mainwp child's callable functions. - if ( isset( $_POST['function'] ) ) { - $func = $_POST['function']; - $callable = MainWP_Child_Callable::get_instance()->is_callable_function( $func ); - if ( $callable ) { - $func_auth = $func; - } - - if ( ! $callable ) { - $callable_no_auth = MainWP_Child_Callable::get_instance()->is_callable_function_no_auth( $func ); - if ( $callable_no_auth ) { - $func_no_auth = $func; - } - } - } - - // Call the function required. - if ( $auth && isset( $_POST['function'] ) && $callable ) { - define( 'DOING_CRON', true ); - MainWP_Helper::handle_fatal_error(); - self::fix_for_custom_themes(); - MainWP_Child_Callable::get_instance()->call_function( $func_auth ); - } elseif ( isset( $_POST['function'] ) && $callable_no_auth ) { - define( 'DOING_CRON', true ); - self::fix_for_custom_themes(); - MainWP_Child_Callable::get_instance()->call_function_no_auth( $func_no_auth ); - } elseif ( isset( $_POST['function'] ) && isset( $_POST['mainwpsignature'] ) && ! $callable && ! $callable_no_auth ) { - MainWP_Helper::error( __( 'Required version has not been detected. Please, make sure that you are using the latest version of the MainWP Child plugin on your site.', 'mainwp-child' ) ); - } - } - - // Check to support login by alternative admin. - // return false will login by connected admin user. - // return true will try to login as alternative user. - public function check_login_as( $alter_login ) { - - if ( ! empty( $alter_login ) ) { - // check alternative admin existed. - $user = get_user_by( 'login', $alter_login ); - - if ( ! $user ) { - // That administrator username was not found on this child site. - return false; - } - - if ( 10 != $user->wp_user_level && ( ! isset( $user->user_level ) || 10 != $user->user_level ) && ! $user->has_cap( 'level_10' ) ) { - // That user is not an administrator. - return false; - } - - return true; // ok, will try to login by alternative user. - } - - return false; - } - - public function auth( $signature, $func, $nonce, $pNossl ) { - if ( empty( $signature ) || ! isset( $func ) || ( ! get_option( 'mainwp_child_pubkey' ) && ! get_option( 'mainwp_child_nossl_key' ) ) ) { - $auth = false; - } else { - $nossl = get_option( 'mainwp_child_nossl' ); - $serverNoSsl = ( isset( $pNossl ) && 1 === (int) $pNossl ); - - if ( ( 1 === (int) $nossl ) || $serverNoSsl ) { - $nossl_key = get_option( 'mainwp_child_nossl_key' ); - $auth = hash_equals( md5( $func . $nonce . $nossl_key ), base64_decode( $signature ) ); // // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode function is used for begin reasons. - } else { - $auth = openssl_verify( $func . $nonce, base64_decode( $signature ), base64_decode( get_option( 'mainwp_child_pubkey' ) ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode function is used for begin reasons. - if ( 1 !== $auth ) { - $auth = false; - } - } - } - - return $auth; - } - - // Login. - public function login( $username, $doAction = false ) { - global $current_user; - - // Logout if required. - if ( isset( $current_user->user_login ) ) { - if ( $current_user->user_login === $username ) { - - // to fix issue multi user session. - $user_id = wp_validate_auth_cookie(); - if ( $user_id && $user_id === $current_user->ID ) { - return true; - } - - wp_set_auth_cookie( $current_user->ID ); - return true; - } - do_action( 'wp_logout' ); - } - - $user = get_user_by( 'login', $username ); - if ( $user ) { - wp_set_current_user( $user->ID ); - wp_set_auth_cookie( $user->ID ); - if ( $doAction ) { - do_action( 'wp_login', $user->user_login ); - } - - return ( is_user_logged_in() && $current_user->user_login === $username ); - } - - return false; - } - - - // This will register the current wp - thus generating the public key etc. - public function register_site() { - global $current_user; - - $information = array(); - // Check if the user is valid & login. - if ( ! isset( $_POST['user'] ) || ! isset( $_POST['pubkey'] ) ) { - MainWP_Helper::error( __( 'Invalid request!', 'mainwp-child' ) ); - } - - // Already added - can't readd. Deactivate plugin. - if ( get_option( 'mainwp_child_pubkey' ) ) { - // set disconnect status to yes here, it will empty after reconnected. - MainWP_Child_Branding::instance()->save_branding_options( 'branding_disconnected', 'yes' ); - MainWP_Helper::error( __( 'Public key already set. Please deactivate & reactivate the MainWP Child plugin and try again.', 'mainwp-child' ) ); - } - - if ( '' != get_option( 'mainwp_child_uniqueId' ) ) { - if ( ! isset( $_POST['uniqueId'] ) || ( '' === $_POST['uniqueId'] ) ) { - MainWP_Helper::error( __( 'This child site is set to require a unique security ID. Please enter it before the connection can be established.', 'mainwp-child' ) ); - } elseif ( get_option( 'mainwp_child_uniqueId' ) !== $_POST['uniqueId'] ) { - MainWP_Helper::error( __( 'The unique security ID mismatch! Please correct it before the connection can be established.', 'mainwp-child' ) ); - } - } - - // Check SSL Requirement. - if ( ! MainWP_Helper::is_ssl_enabled() && ( ! defined( 'MAINWP_ALLOW_NOSSL_CONNECT' ) || ! MAINWP_ALLOW_NOSSL_CONNECT ) ) { - MainWP_Helper::error( __( 'SSL is required on the child site to set up a secure connection.', 'mainwp-child' ) ); - } - - // Login. - if ( isset( $_POST['user'] ) ) { - if ( ! $this->login( $_POST['user'] ) ) { - $hint_miss_user = __( 'That administrator username was not found on this child site. Please verify that it is an existing administrator.', 'mainwp-child' ) . '
' . __( 'Hint: Check if the administrator user exists on the child site, if not, you need to use an existing administrator.', 'mainwp-child' ); - MainWP_Helper::error( $hint_miss_user ); - } - - if ( 10 !== $current_user->wp_user_level && ( ! isset( $current_user->user_level ) || 10 !== $current_user->user_level ) && ! $current_user->has_cap( 'level_10' ) ) { - MainWP_Helper::error( __( 'That user is not an administrator. Please use an administrator user to establish the connection.', 'mainwp-child' ) ); - } - } - - MainWP_Helper::update_option( 'mainwp_child_pubkey', base64_encode( $_POST['pubkey'] ), 'yes' ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode function is used for begin reasons. - MainWP_Helper::update_option( 'mainwp_child_server', $_POST['server'] ); // Save the public key. - MainWP_Helper::update_option( 'mainwp_child_nonce', 0 ); // Save the nonce. - - MainWP_Helper::update_option( 'mainwp_child_nossl', ( '-1' === $_POST['pubkey'] || ! MainWP_Helper::is_ssl_enabled() ? 1 : 0 ), 'yes' ); - $information['nossl'] = ( '-1' === $_POST['pubkey'] || ! MainWP_Helper::is_ssl_enabled() ? 1 : 0 ); - if ( function_exists( 'random_bytes' ) ) { - $nossl_key = random_bytes( 32 ); - $nossl_key = bin2hex( $nossl_key ); - } else { - $nossl_key = uniqid( '', true ); - } - MainWP_Helper::update_option( 'mainwp_child_nossl_key', $nossl_key, 'yes' ); - $information['nosslkey'] = $nossl_key; - - $information['register'] = 'OK'; - $information['uniqueId'] = get_option( 'mainwp_child_uniqueId', '' ); - $information['user'] = $_POST['user']; - - MainWP_Child_Stats::get_instance()->get_site_stats( $information ); - } - - - private function init_extensions() { + + private function parse_init_extensions() { // Handle fatal errors for those init if needed. \MainWP_Child_IThemes_Security::instance()->ithemes_init(); \MainWP_Child_Updraft_Plus_Backups::instance()->updraftplus_init(); @@ -1389,166 +922,6 @@ class MainWP_Child { \MainWP_Child_WPvivid_BackupRestore::instance()->init(); } - private function parse_keyword_links() { - - if ( 1 === (int) get_option( 'mainwpKeywordLinks' ) ) { - new MainWP_Keyword_Links(); - if ( ! is_admin() ) { - add_filter( 'the_content', array( MainWP_Keyword_Links::instance(), 'filter_content' ), 100 ); - } - MainWP_Keyword_Links::instance()->update_htaccess(); - MainWP_Keyword_Links::instance()->redirect_cloak(); - } elseif ( 'yes' === get_option( 'mainwp_keyword_links_htaccess_set' ) ) { - MainWP_Keyword_Links::clear_htaccess(); - } - } - - public function maintenance_alert_404() { - if ( ! is_404() ) { - return; - } - - if ( 1 !== (int) get_option( 'mainwp_maintenance_opt_alert_404' ) ) { - return; - } - - $email = get_option( 'mainwp_maintenance_opt_alert_404_email' ); - - if ( empty( $email ) || ! preg_match( '/^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/is', $email ) ) { - return; - } - - // set status. - header( 'HTTP/1.1 404 Not Found' ); - header( 'Status: 404 Not Found' ); - - // site info. - $blog = get_bloginfo( 'name' ); - $site = get_bloginfo( 'url' ) . '/'; - $from_email = get_bloginfo( 'admin_email' ); - - // referrer. - if ( isset( $_SERVER['HTTP_REFERER'] ) ) { - $referer = MainWP_Helper::clean( $_SERVER['HTTP_REFERER'] ); - } else { - $referer = 'undefined'; - } - $protocol = isset( $_SERVER['HTTPS'] ) && strcasecmp( $_SERVER['HTTPS'], 'off' ) ? 'https://' : 'http://'; - // request URI. - if ( isset( $_SERVER['REQUEST_URI'] ) && isset( $_SERVER['HTTP_HOST'] ) ) { - $request = MainWP_Helper::clean( $protocol . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] ); - } else { - $request = 'undefined'; - } - // query string. - if ( isset( $_SERVER['QUERY_STRING'] ) ) { - $string = MainWP_Helper::clean( $_SERVER['QUERY_STRING'] ); - } else { - $string = 'undefined'; - } - // IP address. - if ( isset( $_SERVER['REMOTE_ADDR'] ) ) { - $address = MainWP_Helper::clean( $_SERVER['REMOTE_ADDR'] ); - } else { - $address = 'undefined'; - } - // user agent. - if ( isset( $_SERVER['HTTP_USER_AGENT'] ) ) { - $agent = MainWP_Helper::clean( $_SERVER['HTTP_USER_AGENT'] ); - } else { - $agent = 'undefined'; - } - // identity. - if ( isset( $_SERVER['REMOTE_IDENT'] ) ) { - $remote = MainWP_Helper::clean( $_SERVER['REMOTE_IDENT'] ); - } else { - $remote = 'undefined'; - } - // log time. - $time = MainWP_Helper::clean( date( 'F jS Y, h:ia', time() ) ); // phpcs:ignore -- local time. - - $mail = '
404 alert
' . - '
TIME: ' . $time . '
' . - '
*404: ' . $request . '
' . - '
SITE: ' . $site . '
' . - '
REFERRER: ' . $referer . '
' . - '
QUERY STRING: ' . $string . '
' . - '
REMOTE ADDRESS: ' . $address . '
' . - '
REMOTE IDENTITY: ' . $remote . '
' . - '
USER AGENT: ' . $agent . '
'; - wp_mail( - $email, - 'MainWP - 404 Alert: ' . $blog, - MainWP_Helper::format_email( $email, $mail ), - array( - 'content-type: text/html', - ) - ); - } - - public function upload_file( $file, $offset = 0 ) { - $dirs = MainWP_Helper::get_mainwp_dir( 'backup' ); - $backupdir = $dirs[0]; - - header( 'Content-Description: File Transfer' ); - - header( 'Content-Description: File Transfer' ); - if ( MainWP_Helper::ends_with( $file, '.tar.gz' ) ) { - header( 'Content-Type: application/x-gzip' ); - header( 'Content-Encoding: gzip' ); - } else { - header( 'Content-Type: application/octet-stream' ); - } - header( 'Content-Disposition: attachment; filename="' . basename( $file ) . '"' ); - header( 'Expires: 0' ); - header( 'Cache-Control: must-revalidate' ); - header( 'Pragma: public' ); - header( 'Content-Length: ' . filesize( $backupdir . $file ) ); - while ( ob_end_flush() ) {; // phpcs:ignore - } - $this->readfile_chunked( $backupdir . $file, $offset ); - } - - public function readfile_chunked( $filename, $offset ) { - $chunksize = 1024; // how many bytes per chunk? - $handle = fopen( $filename, 'rb' ); - if ( false === $handle ) { - return false; - } - - fseek( $handle, $offset ); - - while ( ! feof( $handle ) ) { - $buffer = fread( $handle, $chunksize ); - echo $buffer; - ob_flush(); - flush(); - $buffer = null; - } - - return fclose( $handle ); - } - - public function run_saved_snippets() { - $action = null; - if ( isset( $_POST['action'] ) ) { - $action = $_POST['action']; - } - - if ( 'run_snippet' === $action || 'save_snippet' === $action || 'delete_snippet' === $action ) { - return; - } // do not run saved snippets if in do action snippet - - if ( get_option( 'mainwp_ext_snippets_enabled' ) ) { - $snippets = get_option( 'mainwp_ext_code_snippets' ); - if ( is_array( $snippets ) && count( $snippets ) > 0 ) { - foreach ( $snippets as $code ) { - MainWP_Helper::execute_snippet( $code ); - } - } - } - } - /* * hook to deactivation child plugin action @@ -1613,13 +986,4 @@ class MainWP_Child { } } - public static function fix_for_custom_themes() { - if ( file_exists( ABSPATH . '/wp-admin/includes/screen.php' ) ) { - include_once ABSPATH . '/wp-admin/includes/screen.php'; - } - - if ( function_exists( 'et_register_updates_component' ) ) { - et_register_updates_component(); - } - } } diff --git a/class/class-mainwp-clone-install.php b/class/class-mainwp-clone-install.php index 7a3ed22..160ce7c 100644 --- a/class/class-mainwp-clone-install.php +++ b/class/class-mainwp-clone-install.php @@ -615,10 +615,8 @@ class MainWP_Clone_Install { return; } - global $mainWPChild; - if ( 'dl' === $_REQUEST['cloneFunc'] ) { - $mainWPChild->upload_file( $_REQUEST['f'] ); + MainWP_Utility::instance()->upload_file( $_REQUEST['f'] ); exit; } elseif ( 'deleteCloneBackup' === $_POST['cloneFunc'] ) { $dirs = MainWP_Helper::get_mainwp_dir( 'backup' ); @@ -726,4 +724,20 @@ class MainWP_Clone_Install { } return true; } + + + public function is_valid_auth( $key ) { + $auths = get_option( 'mainwp_child_auth' ); + if ( ! $auths ) { + return false; + } + for ( $i = 0; $i <= $this->maxHistory; $i ++ ) { + if ( isset( $auths[ $i ] ) && ( $auths[ $i ] === $key ) ) { + return true; + } + } + + return false; + } + } diff --git a/class/class-mainwp-connect.php b/class/class-mainwp-connect.php new file mode 100644 index 0000000..34d62b0 --- /dev/null +++ b/class/class-mainwp-connect.php @@ -0,0 +1,464 @@ +save_branding_options( 'branding_disconnected', 'yes' ); + MainWP_Helper::error( __( 'Public key already set. Please deactivate & reactivate the MainWP Child plugin and try again.', 'mainwp-child' ) ); + } + + if ( '' != get_option( 'mainwp_child_uniqueId' ) ) { + if ( ! isset( $_POST['uniqueId'] ) || ( '' === $_POST['uniqueId'] ) ) { + MainWP_Helper::error( __( 'This child site is set to require a unique security ID. Please enter it before the connection can be established.', 'mainwp-child' ) ); + } elseif ( get_option( 'mainwp_child_uniqueId' ) !== $_POST['uniqueId'] ) { + MainWP_Helper::error( __( 'The unique security ID mismatch! Please correct it before the connection can be established.', 'mainwp-child' ) ); + } + } + + // Check SSL Requirement. + if ( ! MainWP_Helper::is_ssl_enabled() && ( ! defined( 'MAINWP_ALLOW_NOSSL_CONNECT' ) || ! MAINWP_ALLOW_NOSSL_CONNECT ) ) { + MainWP_Helper::error( __( 'SSL is required on the child site to set up a secure connection.', 'mainwp-child' ) ); + } + + // Login. + if ( isset( $_POST['user'] ) ) { + if ( ! $this->login( $_POST['user'] ) ) { + $hint_miss_user = __( 'That administrator username was not found on this child site. Please verify that it is an existing administrator.', 'mainwp-child' ) . '
' . __( 'Hint: Check if the administrator user exists on the child site, if not, you need to use an existing administrator.', 'mainwp-child' ); + MainWP_Helper::error( $hint_miss_user ); + } + + if ( 10 !== $current_user->wp_user_level && ( ! isset( $current_user->user_level ) || 10 !== $current_user->user_level ) && ! $current_user->has_cap( 'level_10' ) ) { + MainWP_Helper::error( __( 'That user is not an administrator. Please use an administrator user to establish the connection.', 'mainwp-child' ) ); + } + } + + MainWP_Helper::update_option( 'mainwp_child_pubkey', base64_encode( $_POST['pubkey'] ), 'yes' ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode function is used for begin reasons. + MainWP_Helper::update_option( 'mainwp_child_server', $_POST['server'] ); // Save the public key. + MainWP_Helper::update_option( 'mainwp_child_nonce', 0 ); // Save the nonce. + + MainWP_Helper::update_option( 'mainwp_child_nossl', ( '-1' === $_POST['pubkey'] || ! MainWP_Helper::is_ssl_enabled() ? 1 : 0 ), 'yes' ); + $information['nossl'] = ( '-1' === $_POST['pubkey'] || ! MainWP_Helper::is_ssl_enabled() ? 1 : 0 ); + if ( function_exists( 'random_bytes' ) ) { + $nossl_key = random_bytes( 32 ); + $nossl_key = bin2hex( $nossl_key ); + } else { + $nossl_key = uniqid( '', true ); + } + MainWP_Helper::update_option( 'mainwp_child_nossl_key', $nossl_key, 'yes' ); + $information['nosslkey'] = $nossl_key; + + $information['register'] = 'OK'; + $information['uniqueId'] = get_option( 'mainwp_child_uniqueId', '' ); + $information['user'] = $_POST['user']; + + MainWP_Child_Stats::get_instance()->get_site_stats( $information ); + } + + + public function parse_init_auth() { + + $auth = $this->auth( isset( $_POST['mainwpsignature'] ) ? $_POST['mainwpsignature'] : '', isset( $_POST['function'] ) ? $_POST['function'] : '', isset( $_POST['nonce'] ) ? $_POST['nonce'] : '', isset( $_POST['nossl'] ) ? $_POST['nossl'] : 0 ); + + if ( ! $auth && isset( $_POST['mainwpsignature'] ) ) { + MainWP_Helper::error( __( 'Authentication failed! Please deactivate & re-activate the MainWP Child plugin on this site and try again.', 'mainwp-child' ) ); + } + + if ( ! $auth && isset( $_POST['function'] ) ) { + $func = $_POST['function']; + $callable = MainWP_Child_Callable::get_instance()->is_callable_function( $func ); + $callable_no_auth = MainWP_Child_Callable::get_instance()->is_callable_function_no_auth( $func ); + + if ( $callable && ! $callable_no_auth ) { + MainWP_Helper::error( __( 'Authentication failed! Please deactivate & re-activate the MainWP Child plugin on this site and try again.', 'mainwp-child' ) ); + } + } + + if ( $auth ) { + $auth_user = false; + // Check if the user exists & is an administrator. + if ( isset( $_POST['function'] ) && isset( $_POST['user'] ) ) { + + $user = null; + if ( isset( $_POST['alt_user'] ) && ! empty( $_POST['alt_user'] ) ) { + if ( $this->check_login_as( $_POST['alt_user'] ) ) { + $auth_user = $_POST['alt_user']; + $user = get_user_by( 'login', $auth_user ); + } + } + + // if alternative admin not existed. + if ( ! $user ) { + // check connected admin existed. + $user = get_user_by( 'login', $_POST['user'] ); + $auth_user = $_POST['user']; + } + + if ( ! $user ) { + MainWP_Helper::error( __( 'Unexising administrator username. Please verify that it is an existing administrator.', 'mainwp-child' ) ); + } + + if ( 10 != $user->wp_user_level && ( ! isset( $user->user_level ) || 10 != $user->user_level ) && ! $user->has_cap( 'level_10' ) ) { + MainWP_Helper::error( __( 'Invalid user. Please verify that the user has administrator privileges.', 'mainwp-child' ) ); + } + + $this->login( $auth_user ); + } + + if ( isset( $_POST['function'] ) && 'visitPermalink' === $_POST['function'] ) { + + if ( empty( $auth_user ) ) { + $auth_user = $_POST['user']; + } + + if ( $this->login( $auth_user, true ) ) { + return false; + } else { + exit(); + } + } + + // Redirect to the admin side if needed. + if ( isset( $_POST['admin'] ) && '1' === $_POST['admin'] ) { + wp_safe_redirect( get_option( 'siteurl' ) . '/wp-admin/' ); + die(); + } + } + + return true; + } + + + public function auth( $signature, $func, $nonce, $pNossl ) { + if ( empty( $signature ) || ! isset( $func ) || ( ! get_option( 'mainwp_child_pubkey' ) && ! get_option( 'mainwp_child_nossl_key' ) ) ) { + $auth = false; + } else { + $nossl = get_option( 'mainwp_child_nossl' ); + $serverNoSsl = ( isset( $pNossl ) && 1 === (int) $pNossl ); + + if ( ( 1 === (int) $nossl ) || $serverNoSsl ) { + $nossl_key = get_option( 'mainwp_child_nossl_key' ); + $auth = hash_equals( md5( $func . $nonce . $nossl_key ), base64_decode( $signature ) ); // // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode function is used for begin reasons. + } else { + $auth = openssl_verify( $func . $nonce, base64_decode( $signature ), base64_decode( get_option( 'mainwp_child_pubkey' ) ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode function is used for begin reasons. + if ( 1 !== $auth ) { + $auth = false; + } + } + } + + return $auth; + } + + public function parse_login_required() { + + global $current_user; + + $alter_login_required = false; + $username = rawurldecode( $_REQUEST['user'] ); + + if ( isset( $_REQUEST['alt_user'] ) && ! empty( $_REQUEST['alt_user'] ) ) { + $alter_login_required = MainWP_Connect::instance()->check_login_as( $_REQUEST['alt_user'] ); + if ( $alter_login_required ) { + $username = rawurldecode( $_REQUEST['alt_user'] ); + } + } + + if ( is_user_logged_in() ) { + global $current_user; + if ( 10 !== $current_user->wp_user_level && ( ! isset( $current_user->user_level ) || 10 !== $current_user->user_level ) && ! current_user_can( 'level_10' ) ) { + do_action( 'wp_logout' ); + } + } + + $signature = rawurldecode( isset( $_REQUEST['mainwpsignature'] ) ? $_REQUEST['mainwpsignature'] : '' ); + $file = ''; + if ( isset( $_REQUEST['f'] ) ) { + $file = $_REQUEST['f']; + } elseif ( isset( $_REQUEST['file'] ) ) { + $file = $_REQUEST['file']; + } elseif ( isset( $_REQUEST['fdl'] ) ) { + $file = $_REQUEST['fdl']; + } + + $auth = MainWP_Connect::instance()->auth( $signature, rawurldecode( ( isset( $_REQUEST['where'] ) ? $_REQUEST['where'] : $file ) ), isset( $_REQUEST['nonce'] ) ? $_REQUEST['nonce'] : '', isset( $_REQUEST['nossl'] ) ? $_REQUEST['nossl'] : 0 ); + + if ( ! $auth ) { + return; + } + + if ( ! is_user_logged_in() || $username !== $current_user->user_login ) { + if ( ! $this->login( $username ) ) { + return; + } + + global $current_user; + if ( 10 !== $current_user->wp_user_level && ( ! isset( $current_user->user_level ) || 10 !== $current_user->user_level ) && ! current_user_can( 'level_10' ) ) { + // if is not alternative admin login. + // it is connected admin login. + if ( ! $alter_login_required ) { + // log out if connected admin is not admin level 10. + do_action( 'wp_logout' ); + + return; + } + } + } + + if ( isset( $_REQUEST['fdl'] ) ) { + if ( stristr( $_REQUEST['fdl'], '..' ) ) { + return; + } + + MainWP_Utility::instance()->upload_file( $_REQUEST['fdl'], isset( $_REQUEST['foffset'] ) ? $_REQUEST['foffset'] : 0 ); + exit; + } + + $where = isset( $_REQUEST['where'] ) ? $_REQUEST['where'] : ''; + if ( isset( $_POST['f'] ) || isset( $_POST['file'] ) ) { + $file = ''; + if ( isset( $_POST['f'] ) ) { + $file = $_POST['f']; + } elseif ( isset( $_POST['file'] ) ) { + $file = $_POST['file']; + } + + $where = 'admin.php?page=mainwp_child_tab&tab=restore-clone'; + if ( '' === session_id() ) { + session_start(); + } + $_SESSION['file'] = $file; + $_SESSION['size'] = $_POST['size']; + } + + // to support open not wp-admin url. + $open_location = isset( $_REQUEST['open_location'] ) ? $_REQUEST['open_location'] : ''; + if ( ! empty( $open_location ) ) { + $open_location = base64_decode( $open_location ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode function is used for begin reasons. + $_vars = MainWP_Helper::parse_query( $open_location ); + $_path = wp_parse_url( $open_location, PHP_URL_PATH ); + if ( isset( $_vars['_mwpNoneName'] ) && isset( $_vars['_mwpNoneValue'] ) ) { + $_vars[ $_vars['_mwpNoneName'] ] = wp_create_nonce( $_vars['_mwpNoneValue'] ); + unset( $_vars['_mwpNoneName'] ); + unset( $_vars['_mwpNoneValue'] ); + $open_url = ''; + foreach ( $_vars as $key => $value ) { + $open_url .= $key . '=' . $value . '&'; + } + $open_url = rtrim( $open_url, '&' ); + $open_location = '/wp-admin/' . $_path . '?' . $open_url; + } else { + if ( strpos( $open_location, 'nonce=child_temp_nonce' ) !== false ) { + $open_location = str_replace( 'nonce=child_temp_nonce', 'nonce=' . wp_create_nonce( 'wp-ajax' ), $open_location ); + } + } + wp_safe_redirect( site_url() . $open_location ); + exit(); + } + + wp_safe_redirect( admin_url( $where ) ); + + exit(); + } + + public function check_login() { + + if ( ! isset( $_POST['mainwpsignature'] ) || empty( $_POST['mainwpsignature'] ) ) { + return false; + } + + $file = ''; + if ( isset( $_REQUEST['f'] ) ) { + $file = $_REQUEST['f']; + } elseif ( isset( $_REQUEST['file'] ) ) { + $file = $_REQUEST['file']; + } elseif ( isset( $_REQUEST['fdl'] ) ) { + $file = $_REQUEST['fdl']; + } + + $auth = $this->auth( isset( $_POST['mainwpsignature'] ) ? rawurldecode( $_POST['mainwpsignature'] ) : '', isset( $_POST['function'] ) ? $_POST['function'] : rawurldecode( ( isset( $_REQUEST['where'] ) ? $_REQUEST['where'] : $file ) ), isset( $_POST['nonce'] ) ? $_POST['nonce'] : '', isset( $_POST['nossl'] ) ? $_POST['nossl'] : 0 ); + + if ( ! $auth ) { + MainWP_Helper::error( __( 'Authentication failed! Please deactivate and re-activate the MainWP Child plugin on this site.', 'mainwp-child' ) ); + } + + $auth_user = false; + if ( $auth ) { + // disable duo auth for mainwp. + remove_action( 'init', 'duo_verify_auth', 10 ); + + // Check if the user exists & is an administrator. + if ( isset( $_POST['function'] ) && isset( $_POST['user'] ) ) { + + $user = null; + + if ( isset( $_POST['alt_user'] ) && ! empty( $_POST['alt_user'] ) ) { + if ( $this->check_login_as( $_POST['alt_user'] ) ) { + $auth_user = $_POST['alt_user']; + $user = get_user_by( 'login', $auth_user ); + } + } + + // if not valid alternative admin. + if ( ! $user ) { + // check connected admin existed. + $user = get_user_by( 'login', $_POST['user'] ); + $auth_user = $_POST['user']; + } + + if ( ! $user ) { + MainWP_Helper::error( __( 'That administrator username was not found on this child site. Please verify that it is an existing administrator.', 'mainwp-child' ) ); + } + + if ( 10 != $user->wp_user_level && ( ! isset( $user->user_level ) || 10 != $user->user_level ) && ! $user->has_cap( 'level_10' ) ) { + MainWP_Helper::error( __( 'That user is not an administrator. Please use an administrator user to establish the connection.', 'mainwp-child' ) ); + } + + $this->login( $auth_user ); + } + + if ( isset( $_POST['function'] ) && 'visitPermalink' === $_POST['function'] ) { + + if ( empty( $auth_user ) ) { + $auth_user = $_POST['user']; + } + + if ( $this->login( $auth_user, true ) ) { + return; + } else { + exit(); + } + } + + // Redirect to the admin part if needed. + if ( isset( $_POST['admin'] ) && '1' === $_POST['admin'] ) { + wp_safe_redirect( get_option( 'siteurl' ) . '/wp-admin/' ); + die(); + } + } + } + + /** + * + * Check to support login by alternative admin. + * Return false will login by connected admin user. + * Return true will try to login as alternative user. + * + * + */ + public function check_login_as( $alter_login ) { + + if ( ! empty( $alter_login ) ) { + // check alternative admin existed. + $user = get_user_by( 'login', $alter_login ); + + if ( ! $user ) { + // That administrator username was not found on this child site. + return false; + } + + if ( 10 != $user->wp_user_level && ( ! isset( $user->user_level ) || 10 != $user->user_level ) && ! $user->has_cap( 'level_10' ) ) { + // That user is not an administrator. + return false; + } + + return true; // ok, will try to login by alternative user. + } + + return false; + } + + // Login. + public function login( $username, $doAction = false ) { + global $current_user; + + // Logout if required. + if ( isset( $current_user->user_login ) ) { + if ( $current_user->user_login === $username ) { + + // to fix issue multi user session. + $user_id = wp_validate_auth_cookie(); + if ( $user_id && $user_id === $current_user->ID ) { + return true; + } + + wp_set_auth_cookie( $current_user->ID ); + return true; + } + do_action( 'wp_logout' ); + } + + $user = get_user_by( 'login', $username ); + if ( $user ) { + wp_set_current_user( $user->ID ); + wp_set_auth_cookie( $user->ID ); + if ( $doAction ) { + do_action( 'wp_login', $user->user_login ); + } + + return ( is_user_logged_in() && $current_user->user_login === $username ); + } + + return false; + } + + + public function check_other_auth() { + $auths = get_option( 'mainwp_child_auth' ); + + if ( ! $auths ) { + $auths = array(); + } + + if ( ! isset( $auths['last'] ) || $auths['last'] < mktime( 0, 0, 0, date( 'm' ), date( 'd' ), date( 'Y' ) ) ) { // phpcs:ignore -- local time. + // Generate code for today. + for ( $i = 0; $i < $this->maxHistory; $i ++ ) { + if ( ! isset( $auths[ $i + 1 ] ) ) { + continue; + } + + $auths[ $i ] = $auths[ $i + 1 ]; + } + $newI = $this->maxHistory + 1; + while ( isset( $auths[ $newI ] ) ) { + unset( $auths[ $newI ++ ] ); + } + $auths[ $this->maxHistory ] = md5( MainWP_Helper::rand_string( 14 ) ); + $auths['last'] = time(); + MainWP_Helper::update_option( 'mainwp_child_auth', $auths, 'yes' ); + } + } +} diff --git a/class/class-mainwp-helper.php b/class/class-mainwp-helper.php index cde7d6b..6f7e69f 100644 --- a/class/class-mainwp-helper.php +++ b/class/class-mainwp-helper.php @@ -26,7 +26,7 @@ class MainWP_Helper { public function write( $val ) { if ( isset( $_REQUEST['json_result'] ) && true == $_REQUEST['json_result'] ) : - $output = self::safe_json_encode( $val ); + $output = wp_json_encode( $val ); else : $output = serialize( $val ); // phpcs:ignore -- to compatible. endif; @@ -34,73 +34,10 @@ class MainWP_Helper { die( '' . base64_encode( $output ) . '' ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- to compatible with http encoding. } - public static function json_valid_check( $data ) { - - if ( is_array( $data ) ) { - $output = array(); - foreach ( $data as $key => $value ) { - if ( is_string( $key ) ) { - $id = self::json_convert_string( $key ); - } else { - $id = $key; - } - if ( is_array( $value ) || is_object( $value ) ) { - $output[ $id ] = self::json_valid_check( $value ); - } elseif ( is_string( $value ) ) { - $output[ $id ] = self::json_convert_string( $value ); - } else { - $output[ $id ] = $value; - } - } - } elseif ( is_object( $data ) ) { - $output = new stdClass(); - foreach ( $data as $key => $value ) { - if ( is_string( $key ) ) { - $id = self::json_convert_string( $key ); - } else { - $id = $key; - } - if ( is_array( $value ) || is_object( $value ) ) { - $output->$id = self::json_valid_check( $value ); - } elseif ( is_string( $value ) ) { - $output->$id = self::json_convert_string( $value ); - } else { - $output->$id = $value; - } - } - } elseif ( is_string( $data ) ) { - return self::json_convert_string( $data ); - } else { - return $data; - } - - return $output; - } - - public function json_convert_string( $str ) { - if ( function_exists( 'mb_convert_encoding' ) ) { - $encoding = mb_detect_encoding( $str, mb_detect_order(), true ); - if ( $encoding ) { - return mb_convert_encoding( $str, 'UTF-8', $encoding ); - } else { - return mb_convert_encoding( $str, 'UTF-8', 'UTF-8' ); - } - } - return $str; - } - - public static function safe_json_encode( $value, $options = 0, $depth = 512 ) { - $encoded = json_encode( $value, $options, $depth ); - if ( false === $encoded && ! empty( $value ) && JSON_ERROR_UTF8 == json_last_error() ) { - $encoded = json_encode( self::json_valid_check( $value ), $options, $depth ); - } - return $encoded; - } - public static function close_connection( $val = null ) { if ( isset( $_REQUEST['json_result'] ) && true == $_REQUEST['json_result'] ) : - $output = self::safe_json_encode( $val ); + $output = wp_json_encode( $val ); else : $output = serialize( $val ); // phpcs:ignore -- to compatible. endif; @@ -240,44 +177,10 @@ class MainWP_Helper { $local_img_url = $upload_dir['url'] . '/' . basename( $local_img_path ); // to fix issue re-create new attachment. - if ( $check_file_existed ) { - if ( file_exists( $local_img_path ) ) { - - if ( filesize( $local_img_path ) == filesize( $temporary_file ) ) { - $result = self::get_maybe_existed_attached_id( $local_img_url ); - if ( is_array( $result ) ) { - $attach = current( $result ); - if ( is_object( $attach ) ) { - if ( file_exists( $temporary_file ) ) { - unlink( $temporary_file ); - } - return array( - 'id' => $attach->ID, - 'url' => $local_img_url, - ); - } - } - } - } else { - $result = self::get_maybe_existed_attached_id( $filename, false ); - if ( is_array( $result ) ) { - $attach = current( $result ); - if ( is_object( $attach ) ) { - $basedir = $upload_dir['basedir']; - $baseurl = $upload_dir['baseurl']; - $local_img_path = str_replace( $baseurl, $basedir, $attach->guid ); - if ( file_exists( $local_img_path ) && ( filesize( $local_img_path ) == filesize( $temporary_file ) ) ) { - if ( file_exists( $temporary_file ) ) { - unlink( $temporary_file ); - } - return array( - 'id' => $attach->ID, - 'url' => $attach->guid, - ); - } - } - } - } + if ( $check_file_existed ) { + $result = self::check_media_file_existed( $upload_dir, $filename, $temporary_file, $local_img_path, $local_img_url ); + if ( ! empty( $result ) ) + return $result; } // file exists, do not overwrite, generate unique file name. @@ -288,42 +191,86 @@ class MainWP_Helper { } $moved = rename( $temporary_file, $local_img_path ); - if ( $moved ) { - $wp_filetype = wp_check_filetype( basename( $img_url ), null ); // Get the filetype to set the mimetype. - $attachment = array( - 'post_mime_type' => $wp_filetype['type'], - 'post_title' => isset( $img_data['title'] ) && ! empty( $img_data['title'] ) ? $img_data['title'] : preg_replace( '/\.[^.]+$/', '', basename( $img_url ) ), - 'post_content' => isset( $img_data['description'] ) && ! empty( $img_data['description'] ) ? $img_data['description'] : '', - 'post_excerpt' => isset( $img_data['caption'] ) && ! empty( $img_data['caption'] ) ? $img_data['caption'] : '', - 'post_status' => 'inherit', - 'guid' => $local_img_url, - ); - - // for post attachments, thumbnail. - if ( $parent_id ) { - $attachment['post_parent'] = $parent_id; - } - - $attach_id = wp_insert_attachment( $attachment, $local_img_path ); // Insert the image in the database. - require_once ABSPATH . 'wp-admin/includes/image.php'; - $attach_data = wp_generate_attachment_metadata( $attach_id, $local_img_path ); - wp_update_attachment_metadata( $attach_id, $attach_data ); // Update generated metadata. - if ( isset( $img_data['alt'] ) && ! empty( $img_data['alt'] ) ) { - update_post_meta( $attach_id, '_wp_attachment_image_alt', $img_data['alt'] ); - } - return array( - 'id' => $attach_id, - 'url' => $local_img_url, - ); + return self::insert_attachment_media( $img_data, $img_url, $parent_id, $local_img_path, $local_img_url ); } + } + if ( file_exists( $temporary_file ) ) { unlink( $temporary_file ); } - return null; } + + private static function check_media_file_existed( $upload_dir, $filename, $temporary_file, &$local_img_path, $local_img_url ){ + if ( file_exists( $local_img_path ) ) { + if ( filesize( $local_img_path ) == filesize( $temporary_file ) ) { + $result = self::get_maybe_existed_attached_id( $local_img_url ); + if ( is_array( $result ) ) { + $attach = current( $result ); + if ( is_object( $attach ) ) { + if ( file_exists( $temporary_file ) ) { + unlink( $temporary_file ); + } + return array( + 'id' => $attach->ID, + 'url' => $local_img_url, + ); + } + } + } + } else { + $result = self::get_maybe_existed_attached_id( $filename, false ); + if ( is_array( $result ) ) { + $attach = current( $result ); + if ( is_object( $attach ) ) { + $basedir = $upload_dir['basedir']; + $baseurl = $upload_dir['baseurl']; + $local_img_path = str_replace( $baseurl, $basedir, $attach->guid ); + if ( file_exists( $local_img_path ) && ( filesize( $local_img_path ) == filesize( $temporary_file ) ) ) { + if ( file_exists( $temporary_file ) ) { + unlink( $temporary_file ); + } + return array( + 'id' => $attach->ID, + 'url' => $attach->guid, + ); + } + } + } + } + } + + private static function insert_attachment_media( $img_data, $img_url, $parent_id, $local_img_path, $local_img_url ){ + + $wp_filetype = wp_check_filetype( basename( $img_url ), null ); // Get the filetype to set the mimetype. + $attachment = array( + 'post_mime_type' => $wp_filetype['type'], + 'post_title' => isset( $img_data['title'] ) && ! empty( $img_data['title'] ) ? $img_data['title'] : preg_replace( '/\.[^.]+$/', '', basename( $img_url ) ), + 'post_content' => isset( $img_data['description'] ) && ! empty( $img_data['description'] ) ? $img_data['description'] : '', + 'post_excerpt' => isset( $img_data['caption'] ) && ! empty( $img_data['caption'] ) ? $img_data['caption'] : '', + 'post_status' => 'inherit', + 'guid' => $local_img_url, + ); + + // for post attachments, thumbnail. + if ( $parent_id ) { + $attachment['post_parent'] = $parent_id; + } + + $attach_id = wp_insert_attachment( $attachment, $local_img_path ); // Insert the image in the database. + require_once ABSPATH . 'wp-admin/includes/image.php'; + $attach_data = wp_generate_attachment_metadata( $attach_id, $local_img_path ); + wp_update_attachment_metadata( $attach_id, $attach_data ); // Update generated metadata. + if ( isset( $img_data['alt'] ) && ! empty( $img_data['alt'] ) ) { + update_post_meta( $attach_id, '_wp_attachment_image_alt', $img_data['alt'] ); + } + return array( + 'id' => $attach_id, + 'url' => $local_img_url, + ); + } public static function get_maybe_existed_attached_id( $filename, $full_guid = true ) { global $wpdb; @@ -333,47 +280,6 @@ class MainWP_Helper { return $wpdb->get_results( $wpdb->prepare( "SELECT ID,guid FROM $wpdb->posts WHERE post_type = 'attachment' AND guid LIKE %s", '%/' . $wpdb->esc_like( $filename ) ) ); } - public static function upload_file( $file_url, $path, $file_name ) { - // to fix uploader extension rename htaccess file issue. - if ( '.htaccess' != $file_name && '.htpasswd' != $file_name ) { - $file_name = sanitize_file_name( $file_name ); - } - - $full_file_name = $path . DIRECTORY_SEPARATOR . $file_name; - - $response = wp_remote_get( - $file_url, - array( - 'timeout' => 10 * 60 * 60, - 'stream' => true, - 'filename' => $full_file_name, - ) - ); - - if ( is_wp_error( $response ) ) { - unlink( $full_file_name ); - throw new \Exception( 'Error: ' . $response->get_error_message() ); - } - - if ( 200 !== (int) wp_remote_retrieve_response_code( $response ) ) { - unlink( $full_file_name ); - throw new \Exception( 'Error 404: ' . trim( wp_remote_retrieve_response_message( $response ) ) ); - } - if ( '.phpfile.txt' === substr( $file_name, - 12 ) ) { - $new_file_name = substr( $file_name, 0, - 12 ) . '.php'; - $new_file_name = $path . DIRECTORY_SEPARATOR . $new_file_name; - $moved = rename( $full_file_name, $new_file_name ); - if ( $moved ) { - return array( 'path' => $new_file_name ); - } else { - unlink( $full_file_name ); - throw new \Exception( 'Error: Copy file.' ); - } - } - - return array( 'path' => $full_file_name ); - } - public static function get_mainwp_dir( $what = null, $dieOnError = true ) { $upload_dir = wp_upload_dir(); $dir = $upload_dir['basedir'] . DIRECTORY_SEPARATOR . 'mainwp' . DIRECTORY_SEPARATOR; diff --git a/class/class-mainwp-keyword-links.php b/class/class-mainwp-keyword-links.php index deef3ad..a1202da 100644 --- a/class/class-mainwp-keyword-links.php +++ b/class/class-mainwp-keyword-links.php @@ -68,6 +68,18 @@ class MainWP_Keyword_Links { $this->update_htaccess( true ); // force update } } + + public function parse_init_keyword_links() { + if ( 1 === (int) get_option( 'mainwpKeywordLinks' ) ) { + if ( ! is_admin() ) { + add_filter( 'the_content', array( $this, 'filter_content' ), 100 ); + } + $this->update_htaccess(); + $this->redirect_cloak(); + } elseif ( 'yes' === get_option( 'mainwp_keyword_links_htaccess_set' ) ) { + $this->clear_htaccess(); + } + } function mod_rewrite_rules( $pRules ) { $home_root = parse_url( home_url() ); @@ -776,17 +788,13 @@ class MainWP_Keyword_Links { } } - public function enable_stats() { - global $mainWPChild; - $result = array(); + public function enable_stats() { $enable_stats = intval( $_POST['enablestats'] ); if ( get_option( 'mainwp_kwl_enable_statistic' ) !== $enable_stats ) { if ( MainWP_Helper::update_option( 'mainwp_kwl_enable_statistic', $enable_stats ) ) { $return['status'] = 'SUCCESS'; - } - $mainWPChild->update_htaccess( true ); + } } - return $return; } diff --git a/class/class-mainwp-utility.php b/class/class-mainwp-utility.php new file mode 100644 index 0000000..fc54903 --- /dev/null +++ b/class/class-mainwp-utility.php @@ -0,0 +1,213 @@ + 0 ) { + foreach ( $snippets as $code ) { + MainWP_Helper::execute_snippet( $code ); + } + } + } + } + + public static function fix_for_custom_themes() { + if ( file_exists( ABSPATH . '/wp-admin/includes/screen.php' ) ) { + include_once ABSPATH . '/wp-admin/includes/screen.php'; + } + if ( function_exists( 'et_register_updates_component' ) ) { + et_register_updates_component(); + } + } + + /** + * + * To support maintenance alert + * + */ + public function maintenance_alert() { + if ( ! is_404() ) { + return; + } + + if ( 1 !== (int) get_option( 'mainwp_maintenance_opt_alert_404' ) ) { + return; + } + + $email = get_option( 'mainwp_maintenance_opt_alert_404_email' ); + + if ( empty( $email ) || ! preg_match( '/^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/is', $email ) ) { + return; + } + + // set status. + header( 'HTTP/1.1 404 Not Found' ); + header( 'Status: 404 Not Found' ); + + // site info. + $blog = get_bloginfo( 'name' ); + $site = get_bloginfo( 'url' ) . '/'; + $from_email = get_bloginfo( 'admin_email' ); + + // referrer. + if ( isset( $_SERVER['HTTP_REFERER'] ) ) { + $referer = MainWP_Helper::clean( $_SERVER['HTTP_REFERER'] ); + } else { + $referer = 'undefined'; + } + $protocol = isset( $_SERVER['HTTPS'] ) && strcasecmp( $_SERVER['HTTPS'], 'off' ) ? 'https://' : 'http://'; + // request URI. + if ( isset( $_SERVER['REQUEST_URI'] ) && isset( $_SERVER['HTTP_HOST'] ) ) { + $request = MainWP_Helper::clean( $protocol . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] ); + } else { + $request = 'undefined'; + } + // query string. + if ( isset( $_SERVER['QUERY_STRING'] ) ) { + $string = MainWP_Helper::clean( $_SERVER['QUERY_STRING'] ); + } else { + $string = 'undefined'; + } + // IP address. + if ( isset( $_SERVER['REMOTE_ADDR'] ) ) { + $address = MainWP_Helper::clean( $_SERVER['REMOTE_ADDR'] ); + } else { + $address = 'undefined'; + } + // user agent. + if ( isset( $_SERVER['HTTP_USER_AGENT'] ) ) { + $agent = MainWP_Helper::clean( $_SERVER['HTTP_USER_AGENT'] ); + } else { + $agent = 'undefined'; + } + // identity. + if ( isset( $_SERVER['REMOTE_IDENT'] ) ) { + $remote = MainWP_Helper::clean( $_SERVER['REMOTE_IDENT'] ); + } else { + $remote = 'undefined'; + } + // log time. + $time = MainWP_Helper::clean( date( 'F jS Y, h:ia', time() ) ); // phpcs:ignore -- local time. + + $mail = '
404 alert
' . + '
TIME: ' . $time . '
' . + '
*404: ' . $request . '
' . + '
SITE: ' . $site . '
' . + '
REFERRER: ' . $referer . '
' . + '
QUERY STRING: ' . $string . '
' . + '
REMOTE ADDRESS: ' . $address . '
' . + '
REMOTE IDENTITY: ' . $remote . '
' . + '
USER AGENT: ' . $agent . '
'; + wp_mail( + $email, + 'MainWP - 404 Alert: ' . $blog, + MainWP_Helper::format_email( $email, $mail ), + array( + 'content-type: text/html', + ) + ); + } + + public function cron_active() { + if ( ! defined( 'DOING_CRON' ) || ! DOING_CRON ) { + return; + } + if ( empty( $_GET['mainwp_child_run'] ) || 'test' !== $_GET['mainwp_child_run'] ) { + return; + } + session_write_close(); + header( 'Content-Type: text/html; charset=' . get_bloginfo( 'charset' ), true ); + header( 'X-Robots-Tag: noindex, nofollow', true ); + header( 'X-MainWP-Child-Version: ' . MainWP_Child::$version, true ); + nocache_headers(); + if ( 'test' == $_GET['mainwp_child_run'] ) { + die( 'MainWP Test' ); + } + die( '' ); + } + + + /** + * + * To support upload backup files. + * + */ + public function upload_file( $file, $offset = 0 ) { + $dirs = MainWP_Helper::get_mainwp_dir( 'backup' ); + $backupdir = $dirs[0]; + + header( 'Content-Description: File Transfer' ); + + header( 'Content-Description: File Transfer' ); + if ( MainWP_Helper::ends_with( $file, '.tar.gz' ) ) { + header( 'Content-Type: application/x-gzip' ); + header( 'Content-Encoding: gzip' ); + } else { + header( 'Content-Type: application/octet-stream' ); + } + header( 'Content-Disposition: attachment; filename="' . basename( $file ) . '"' ); + header( 'Expires: 0' ); + header( 'Cache-Control: must-revalidate' ); + header( 'Pragma: public' ); + header( 'Content-Length: ' . filesize( $backupdir . $file ) ); + while ( ob_end_flush() ) {; // phpcs:ignore + } + $this->readfile_chunked( $backupdir . $file, $offset ); + } + + public function readfile_chunked( $filename, $offset ) { + $chunksize = 1024; // how many bytes per chunk? + $handle = fopen( $filename, 'rb' ); + if ( false === $handle ) { + return false; + } + + fseek( $handle, $offset ); + + while ( ! feof( $handle ) ) { + $buffer = fread( $handle, $chunksize ); + echo $buffer; + ob_flush(); + flush(); + $buffer = null; + } + + return fclose( $handle ); + } + +}