ABSpath = $this->getABSPATH(); $this->get_options(); $this->get_admin_options(); $this->get_plugin_upgraded(); //call always, otherwise db version will not match anymore. if (is_multisite()) { $this->pro_url = 'https://really-simple-ssl.com/pro-multisite'; } else { $this->pro_url = 'https://really-simple-ssl.com/pro'; } register_deactivation_hook(dirname(__FILE__) . "/" . $this->plugin_filename, array($this, 'deactivate')); add_action( 'admin_init', array($this, 'add_privacy_info') ); add_action( 'admin_init', array($this, 'maybe_dismiss_review_notice') ); add_action( 'admin_init', array($this, 'insert_secure_cookie_settings'), 70 ); add_action( 'admin_init', array($this, 'recheck_certificate') ); add_action( "update_option_rlrsssl_options", array( $this, "maybe_clear_transients" ), 10, 3 ); add_action( 'wp_ajax_update_ssl_detection_overridden_option', array( $this, 'update_ssl_detection_overridden_option' ) ); // Only show deactivate popup when SSL has been enabled. if ($this->ssl_enabled) { add_action('admin_footer', array($this, 'deactivate_popup'), 40); } } static function this() { return self::$_this; } /** * @param $oldvalue * @param $newvalue * @param $option */ public function maybe_clear_transients($oldvalue, $newvalue, $option){ if ($oldvalue !== $newvalue ) { $this->clear_transients(); } } /** * Clear some transients */ public function clear_transients(){ delete_transient('rsssl_mixed_content_fixer_detected'); delete_transient('rsssl_plusone_count'); delete_transient('rsssl_remaining_task_count'); delete_transient( 'rsssl_can_use_curl_headers_check' ); delete_transient( 'rsssl_admin_notices' ); } /** * Add some privacy info, telling our users we aren't tracking them */ public function add_privacy_info() { if (!function_exists('wp_add_privacy_policy_content')) { return; } $content = sprintf( __('Really Simple SSL and Really Simple SSL add-ons do not process any personal identifiable information, so the GDPR does not apply to these plugins or usage of these plugins on your website. You can find our privacy policy here.', 'really-simple-ssl'), 'https://really-simple-ssl.com/privacy-statement/' ); wp_add_privacy_policy_content( 'Really Simple SSL', wp_kses_post(wpautop($content, false)) ); } /** * Check if current day falls within required date range. * * @return bool */ public function is_bf(){ if ( defined("rsssl_pro_version" ) ) { return false; } $start_day = 22; $end_day = 29; $current_year = date("Y");//e.g. 2021 $current_month = date("n");//e.g. 3 $current_day = date("j");//e.g. 4 if ( $current_year == 2021 && $current_month == 11 && $current_day >=$start_day && $current_day <= $end_day ) { return true; } else { return false; } } /** * Dismiss review notice of dismissed by the user */ public function maybe_dismiss_review_notice() { if (isset($_GET['rsssl_dismiss_review_notice'])){ $this->review_notice_shown = true; $this->save_options(); } } /** * Update SSL detection overridden option */ public function update_ssl_detection_overridden_option() { if ( ! rsssl_user_can_manage() ) return; if ( isset( $_POST['action'] ) && $_POST['action'] === 'update_ssl_detection_overridden_option' ) { if ( isset ( $_POST['override_ssl_checked'] ) && $_POST['override_ssl_checked'] !== false ) { update_option('rsssl_ssl_detection_overridden', true); } wp_die(); } } /** * Initializes the admin class * * @since 2.2 * * @access public * */ public function init() { if ( ! current_user_can('manage_options') && ! current_user_can('manage_security') ) return; $is_on_settings_page = $this->is_settings_page(); if (defined("RSSSL_FORCE_ACTIVATE") && RSSSL_FORCE_ACTIVATE) { $options = get_option('rlrsssl_options'); $options['ssl_enabled'] = true; update_option('rlrsssl_options', $options); } /* * check if we're one minute past the activation. Then flush rewrite rules * this way we lower the memory impact on activation * Flush should happen on shutdown, not on init, as often happens in other plugins * https://codex.wordpress.org/Function_Reference/flush_rewrite_rules * */ $activation_time = get_option('rsssl_flush_rewrite_rules'); $more_than_one_minute_ago = $activation_time < strtotime("-1 minute"); $less_than_2_minutes_ago = $activation_time > strtotime("-2 minute"); if (get_option('rsssl_flush_rewrite_rules') && $more_than_one_minute_ago && $less_than_2_minutes_ago){ delete_option('rsssl_flush_rewrite_rules'); add_action('shutdown', 'flush_rewrite_rules'); } $more_than_2_minute_ago = get_option('rsssl_flush_caches') < strtotime("-2 minute"); $less_than_5_minutes_ago = get_option('rsssl_flush_caches') > strtotime("-5 minute"); if (get_option('rsssl_flush_caches') && $more_than_2_minute_ago && $less_than_5_minutes_ago){ delete_option('rsssl_flush_caches'); add_action('shutdown', array( RSSSL()->rsssl_cache, 'flush' ) ); } // Set default progress toggle to remaining tasks if it hasn't been set if (!get_option('rsssl_all_tasks') && !get_option('rsssl_remaining_tasks') ) { update_option('rsssl_remaining_tasks', true); } /* Detect configuration when: - SSL activation just confirmed. - on settings page - No SSL detected */ //when configuration should run again if ($this->clicked_activate_ssl() || !$this->ssl_enabled || !$this->site_has_ssl || $is_on_settings_page || is_network_admin() || defined('RSSSL_DOING_SYSTEM_STATUS') ) { $this->detect_configuration(); if (is_multisite()) $this->build_domain_list();//has to come after clicked_activate_ssl, otherwise this domain won't get counted. //flush caches when just activated ssl //flush the permalinks if ($this->clicked_activate_ssl()) { if (!defined('RSSSL_NO_FLUSH') || !RSSSL_NO_FLUSH) { update_option('rsssl_flush_rewrite_rules', time()); } update_option('rsssl_flush_caches', time()); } if (!$this->wpconfig_ok()) { //if we were to activate ssl, this could result in a redirect loop. So warn first. add_action("admin_notices", array($this, 'show_notice_wpconfig_needs_fixes')); if (is_multisite()) add_action('network_admin_notices', array($this, 'show_notice_wpconfig_needs_fixes'), 10); $this->ssl_enabled = false; $this->save_options(); } elseif ($this->ssl_enabled) { add_action('admin_init', array($this, 'configure_ssl'), 20); } } add_action( 'admin_init', array( $this, 'check_upgrade' ), 10, 2 ); //when SSL is enabled, and not enabled by user, ask for activation. add_action("admin_notices", array($this, 'show_notice_activate_ssl'), 10 ); add_action('rsssl_activation_notice', array($this, 'ssl_detected'), 10); add_action('rsssl_activation_notice_inner', array($this, 'almost_ready_to_migrate'), 30); add_action('rsssl_activation_notice_footer', array($this, 'show_enable_ssl_button'), 50); //add the settings page for the plugin add_action('admin_enqueue_scripts', array($this, 'enqueue_assets')); //settings page, form and settings link in the plugins page add_filter( "option_page_capability_rlrsssl_options", array( $this, 'capability_check_wrapper') ); add_filter( "option_page_capability_rsssl_network_options", array( $this, 'capability_check_wrapper') ); add_action('admin_menu', array($this, 'add_settings_page'), 40); add_action('admin_init', array($this, 'create_form'), 40); add_action('admin_init', array($this, 'listen_for_deactivation'), 40); add_action( 'update_option_rlrsssl_options', array( $this, 'maybe_remove_highlight_from_url' ), 50 ); $plugin = rsssl_plugin; add_filter("plugin_action_links_$plugin", array($this, 'plugin_settings_link')); add_action( 'rocket_activation', array($this, 'removeHtaccessEdit' ) ); add_filter( 'before_rocket_htaccess_rules', array($this, 'add_htaccess_redirect_before_wp_rocket' ) ); //Add update notification to Settings admin menu add_action('admin_menu', array($this, 'rsssl_edit_admin_menu') ); //callbacks for the ajax dismiss buttons add_action('wp_ajax_dismiss_success_message', array($this, 'dismiss_success_message_callback')); add_action('wp_ajax_rsssl_dismiss_review_notice', array($this, 'dismiss_review_notice_callback')); add_action('wp_ajax_rsssl_dismiss_settings_notice', array($this, 'dismiss_settings_notice_callback')); add_action('wp_ajax_rsssl_update_task_toggle_option', array($this, 'update_task_toggle_option')); add_action('wp_ajax_rsssl_redirect_to_le_wizard', array($this, 'rsssl_redirect_to_le_wizard')); //handle notices add_action('admin_notices', array($this, 'show_notices')); //show review notice, only to free users if (!defined("rsssl_pro_version") && (!defined("rsssl_pp_version")) && (!defined("rsssl_soc_version")) && (!class_exists('RSSSL_PRO')) && (!is_multisite())) { add_action('admin_notices', array($this, 'show_leave_review_notice')); } } /** * Return capability for use in option_page_capability_ filter * @return string */ public function capability_check_wrapper() { return $this->capability; } public function check_upgrade() { $prev_version = get_option( 'rsssl_current_version', false ); if ( $prev_version && version_compare( $prev_version, '4.0', '<' ) ) { update_option('rsssl_remaining_tasks', true); } if ( $prev_version && version_compare( $prev_version, '4.0.10', '<=' ) ) { if (function_exists('is_wpe') && is_wpe()) { $this->wp_redirect = true; $this->htaccess_redirect = false; $this->save_options(); } } if ( $prev_version && version_compare( $prev_version, '5.1.3', '<=' ) ) { if ( get_option( 'rsssl_disable_ocsp' ) ) { $options = get_option( 'rsssl_options_lets-encrypt' ); $options['disable_ocsp'] = true; update_option( 'rsssl_options_lets-encrypt', $options ); delete_option('rsssl_disable_ocsp'); } } if ( $prev_version && version_compare( $prev_version, '5.3.0', '<=' ) ) { if ( file_exists($this->htaccess_file() ) && is_writable($this->htaccess_file() ) ) { $htaccess = file_get_contents( $this->htaccess_file() ); $pattern_start = "/rlrssslReallySimpleSSL rsssl_version\[.*.]/"; $pattern_end = "/rlrssslReallySimpleSSL/"; if ( preg_match_all( $pattern_start, $htaccess ) ) { $htaccess = preg_replace( $pattern_start, "Really Simple SSL Redirect " . rsssl_version, $htaccess ); $htaccess = preg_replace( $pattern_end, "Really Simple SSL Redirect", $htaccess ); file_put_contents( $this->htaccess_file(), $htaccess ); } } } // Add manage_security capability if ( $prev_version && version_compare( $prev_version, '5.3.3', '<' ) ) { rsssl_add_manage_security_capability(); } update_option( 'rsssl_current_version', rsssl_version ); } /** * Deactivate the plugin while keeping SSL * Activated when the 'uninstall_keep_ssl' button is clicked in the settings tab * */ public function listen_for_deactivation() { //check user role if (! rsssl_user_can_manage() ) return; //check nonce if (!isset($_GET['token']) || (!wp_verify_nonce($_GET['token'], 'rsssl_deactivate_plugin'))) return; //check for action if (isset($_GET["action"]) && $_GET["action"] == 'uninstall_keep_ssl') { //deactivate plugin, but don't revert to http. $plugin = $this->plugin_dir . "/" . $this->plugin_filename; $plugin = plugin_basename(trim($plugin)); if (is_multisite()) { $network_current = get_site_option('active_sitewide_plugins', array()); if (is_plugin_active_for_network($plugin)) { unset($network_current[$plugin]); } update_site_option('active_sitewide_plugins', $network_current); //remove plugin one by one on each site $sites = get_sites(); foreach ($sites as $site) { RSSSL()->rsssl_multisite->switch_to_blog_bw_compatible($site); $current = get_option('active_plugins', array()); $current = $this->remove_plugin_from_array($plugin, $current); update_option('active_plugins', $current); restore_current_blog(); //switches back to previous blog, not current, so we have to do it each loop } } else { $current = get_option('active_plugins', array()); $current = $this->remove_plugin_from_array($plugin, $current); update_option('active_plugins', $current); } wp_redirect(admin_url('plugins.php')); exit; } } /** * Remove the plugin from the active plugins array when called from listen_for_deactivation * * */ public function remove_plugin_from_array($plugin, $current) { $key = array_search($plugin, $current); if (false !== $key) { unset($current[$key]); } return $current; } /** * @Since 3.1 * * Check if site uses an htaccess.conf file, used in bitnami installations * */ public function uses_htaccess_conf() { $htaccess_conf_file = dirname(ABSPATH) . "/conf/htaccess.conf"; //conf/htaccess.conf can be outside of open basedir, return false if so $open_basedir = ini_get("open_basedir"); if (!empty($open_basedir)) return false; if (is_file($htaccess_conf_file) ) { return true; } else { return false; } } public function get_sites_bw_compatible() { global $wp_version; $sites = ($wp_version >= 4.6) ? get_sites() : wp_get_sites(); return $sites; } /** * The new get_sites function returns an object. * @param $site */ public function switch_to_blog_bw_compatible($site) { global $wp_version; if ($wp_version >= 4.6) { switch_to_blog($site->blog_id); } else { switch_to_blog($site['blog_id']); } } /** * checks if the user just clicked the "activate SSL" button. */ private function clicked_activate_ssl() { if ( ! rsssl_user_can_manage() ) return; if (isset($_POST['rsssl_do_activate_ssl'])) { $this->activate_ssl(); update_option('rsssl_activation_timestamp', time()); return true; } return false; } /** * If the user has clicked "recheck certificate, clear the cache for the certificate check. * @return void */ public function recheck_certificate(){ if (!rsssl_user_can_manage()) return; if (isset($_POST['rsssl_recheck_certificate']) || isset($_GET['rsssl_recheck_certificate'])) { delete_transient('rsssl_certinfo'); } } /** * Activate the SSL for this site */ public function activate_ssl() { $this->ssl_enabled = true; $this->wp_redirect = true; $this->set_siteurl_to_ssl(); $this->save_options(); } /** * Deactivate SSL for this site */ public function deactivate_ssl() { //only revert if SSL was enabled first. if ($this->ssl_enabled) { $this->ssl_enabled = false; $this->wp_redirect = false; $this->htaccess_redirect = false; $this->remove_ssl_from_siteurl(); $this->save_options(); } } /** * redirect to settings page */ public function redirect_to_settings_page($tab='configuration') { if (isset($_GET['page']) && $_GET['page'] == 'rlrsssl_really_simple_ssl') return; $url = add_query_arg( array( "page" => "rlrsssl_really_simple_ssl", "tab" => $tab, ), admin_url( "options-general.php" ) ); wp_redirect( $url ); exit; } /** * Check if the wp config configuration is ok for SSL activation * * @return bool */ public function wpconfig_ok() { if (($this->do_wpconfig_loadbalancer_fix || $this->no_server_variable || $this->wpconfig_siteurl_not_fixed) && !$this->wpconfig_is_writable()) { $result = false; } else { $result = true; } return apply_filters('rsssl_wpconfig_ok_check', $result); } /** This message is shown when SSL is not enabled by the user yet */ public function show_notice_activate_ssl() { //prevent showing the review on edit screen, as gutenberg removes the class which makes it editable. $screen = get_current_screen(); if ( $screen->base === 'post' ) return; if ($this->ssl_enabled) return; if (defined("RSSSL_DISMISS_ACTIVATE_SSL_NOTICE") && RSSSL_DISMISS_ACTIVATE_SSL_NOTICE) return; //for multisite, show only activate when a choice has been made to activate networkwide or per site. if (is_multisite() && !RSSSL()->rsssl_multisite->selected_networkwide_or_per_site) return; //on multisite, only show this message on the network admin. Per site activated sites have to go to the settings page. //otherwise sites that do not need SSL possibly get to see this message. if (is_multisite() && !is_network_admin()) return; //don't show in our Let's Encrypt wizard if (isset($_GET['tab']) && $_GET['tab']==='letsencrypt') return; if (!$this->wpconfig_ok()) return; if (!rsssl_user_can_manage()) return; do_action('rsssl_activation_notice'); } /** * Show a notice that the website is ready to migrate to SSL. */ public function ssl_detected() { ob_start(); do_action('rsssl_activation_notice_inner'); $content = ob_get_clean(); ob_start(); do_action('rsssl_activation_notice_footer'); $footer = ob_get_clean(); $class = apply_filters("rsssl_activation_notice_classes", "updated activate-ssl rsssl-pro-dismiss-notice"); $title = __("Almost ready to migrate to SSL!", "really-simple-ssl"); echo $this->notice_html( $class, $title, $content, $footer); } /** * Show almost ready to migrate notice */ public function almost_ready_to_migrate() { _e("Before you migrate, please check for: ", 'really-simple-ssl'); ?>

rsssl_certificate->is_valid(); $activate_btn_disabled = !$certificate_valid ? 'disabled' : ''; $test_url = 'https://www.ssllabs.com/ssltest/analyze.html?d='.home_url(); if ( !$certificate_valid ) { $ajax_nonce = wp_create_nonce("really-simple-ssl"); ?>
type="submit" class='button button-primary' value="" id="rsssl_do_activate_ssl" name="rsssl_do_activate_ssl">
find_wp_config_path(); if (is_writable($wpconfig_path)) return true; else return false; } /** * Check if the uninstall file is renamed to .php * * @return string */ public function check_for_uninstall_file() { if (file_exists(dirname(__FILE__) . '/force-deactivate.php')) { return 'fail'; } return 'success'; } /** * Get the options for this plugin * * @since 2.0 * * @access public * */ public function get_admin_options() { $options = get_option('rlrsssl_options'); if (isset($options)) { $this->site_has_ssl = isset($options['site_has_ssl']) ? $options['site_has_ssl'] : FALSE; $this->hsts = isset($options['hsts']) ? $options['hsts'] : FALSE; $this->htaccess_warning_shown = isset($options['htaccess_warning_shown']) ? $options['htaccess_warning_shown'] : FALSE; $this->review_notice_shown = isset($options['review_notice_shown']) ? $options['review_notice_shown'] : FALSE; $this->ssl_success_message_shown = isset($options['ssl_success_message_shown']) ? $options['ssl_success_message_shown'] : FALSE; $this->plugin_db_version = isset($options['plugin_db_version']) ? $options['plugin_db_version'] : "1.0"; $this->do_not_edit_htaccess = isset($options['do_not_edit_htaccess']) ? $options['do_not_edit_htaccess'] : FALSE; $this->htaccess_redirect = isset($options['htaccess_redirect']) ? $options['htaccess_redirect'] : FALSE; $this->switch_mixed_content_fixer_hook = isset($options['switch_mixed_content_fixer_hook']) ? $options['switch_mixed_content_fixer_hook'] : FALSE; $this->dismiss_all_notices = isset($options['dismiss_all_notices']) ? $options['dismiss_all_notices'] : FALSE; $this->high_contrast = isset($options['high_contrast']) ? $options['high_contrast'] : FALSE; $this->debug_log = isset($options['debug_log']) ? $options['debug_log'] : $this->debug_log; $this->dismiss_review_notice = isset($options['dismiss_review_notice']) ? $options['dismiss_review_notice'] : $this->dismiss_review_notice; } if (is_multisite()) { $network_options = get_site_option('rlrsssl_network_options'); $network_htaccess_redirect = isset($network_options["htaccess_redirect"]) ? $network_options["htaccess_redirect"] : false; $network_do_not_edit_htaccess = isset($network_options["do_not_edit_htaccess"]) ? $network_options["do_not_edit_htaccess"] : false; /* If multiste, and networkwide, only the networkwide setting counts. if multisite, and per site, only the networkwide setting counts if it is true. */ $ssl_enabled_networkwide = isset($network_options["ssl_enabled_networkwide"]) ? $network_options["ssl_enabled_networkwide"] : false; if ($ssl_enabled_networkwide) { $this->htaccess_redirect = $network_htaccess_redirect; $this->do_not_edit_htaccess = $network_do_not_edit_htaccess; } else { if ($network_do_not_edit_htaccess) $this->do_not_edit_htaccess = $network_do_not_edit_htaccess; if ($network_htaccess_redirect) $this->htaccess_redirect = $network_htaccess_redirect; } } //if the define is true, it overrides the db setting. if (defined('RLRSSSL_DO_NOT_EDIT_HTACCESS')) { $this->do_not_edit_htaccess = RLRSSSL_DO_NOT_EDIT_HTACCESS; } } /** * Creates an array of all domains where the plugin is active AND SSL is active, only used for multisite. * * @since 2.1 * * @access public * */ public function build_domain_list() { if ( !is_multisite() ) return; $this->sites = get_transient('rsssl_domain_list'); if ( !$this->sites ) { //create list of all activated sites with SSL $this->sites = array(); $nr_of_sites = RSSSL()->rsssl_multisite->get_total_blog_count(); if ( $nr_of_sites <= 50 ) { $sites = RSSSL()->rsssl_multisite->get_sites_bw_compatible(0, $nr_of_sites); foreach ($sites as $site) { $this->switch_to_blog_bw_compatible($site); $options = get_option('rlrsssl_options'); $ssl_enabled = FALSE; if (isset($options)) { $site_has_ssl = isset($options['site_has_ssl']) ? $options['site_has_ssl'] : FALSE; $ssl_enabled = isset($options['ssl_enabled']) ? $options['ssl_enabled'] : $site_has_ssl; } if (is_plugin_active(rsssl_plugin) && $ssl_enabled) { $this->trace_log("- adding: " . home_url()); $this->sites[] = home_url(); } restore_current_blog(); //switches back to previous blog, not current, so we have to do it each loop } } set_transient('rsssl_domain_list', $this->sites, HOUR_IN_SECONDS); } } /** * check if the plugin was upgraded to a new version * * @since 2.1 * * @access public * */ public function get_plugin_upgraded() { if ($this->plugin_db_version != rsssl_version) { if ( $this->plugin_db_version !== '1.0' && version_compare( $this->plugin_db_version, '4.0.0', '<' ) ) { update_option('rsssl_upgraded_to_four', true); } if ( $this->plugin_db_version !== '1.0' ) { $dismiss_options = $this->get_notices_list( array( 'dismiss_on_upgrade' => true, ) ); foreach ($dismiss_options as $dismiss_option ) { update_option( "rsssl_" . $dismiss_option . "_dismissed" , true); } delete_transient( 'rsssl_plusone_count' ); } $this->plugin_db_version = rsssl_version; $this->save_options(); } } /** * Log events during plugin execution * * @param string $msg * * @since 2.1 * * @access public * */ public function trace_log( $msg ) { if (defined('RSSSL_DOING_SYSTEM_STATUS') || (defined('WP_DEBUG') && WP_DEBUG ) ) if ( $this->debug_log !== null ) { if ( strpos( $this->debug_log, $msg ) ) { return; } } $this->debug_log = $this->debug_log . "\n" . $msg; } /** * Configures the site for SSL * * @since 2.2 * * @access public * */ public function configure_ssl() { if (!rsssl_user_can_manage()) return; $safe_mode = FALSE; if (defined('RSSSL_SAFE_MODE') && RSSSL_SAFE_MODE) $safe_mode = RSSSL_SAFE_MODE; if (!rsssl_user_can_manage()) return; $this->trace_log("
" . "" . "SSL Configuration" . ""); if ($this->site_has_ssl) { //when one of the used server variables was found, test if the redirect works if (RSSSL()->rsssl_server->uses_htaccess() && $this->ssl_type != "NA") { $this->test_htaccess_redirect(); } //in a configuration reverse proxy without a set server variable https, add code to wpconfig if ($this->do_wpconfig_loadbalancer_fix) { $this->wpconfig_loadbalancer_fix(); } if ($this->no_server_variable) $this->wpconfig_server_variable_fix(); if (!$safe_mode) { $this->editHtaccess(); } if (!$safe_mode && $this->clicked_activate_ssl()) { $this->wp_redirect = TRUE; $this->save_options(); } if (!$safe_mode && $this->wpconfig_siteurl_not_fixed) $this->fix_siteurl_defines_in_wpconfig(); if (!$safe_mode) { $this->set_siteurl_to_ssl(); } if (!is_multisite()) { $this->redirect_to_settings_page(); } } } /** * Check to see if we are on the settings page, action hook independent * * @since 2.1 * * @access public * */ public function is_settings_page() { if (!isset($_SERVER['QUERY_STRING'])) return false; parse_str($_SERVER['QUERY_STRING'], $params); if (array_key_exists("page", $params) && ($params["page"] == "rlrsssl_really_simple_ssl")) { return true; } return false; } /** * Find the path to wp-config * * @since 2.1 * * @access public * */ public function find_wp_config_path() { //limit nr of iterations to 20 $i = 0; $maxiterations = 20; $dir = dirname(__FILE__); do { $i++; if (file_exists($dir . "/wp-config.php")) { return $dir . "/wp-config.php"; } } while (($dir = realpath("$dir/..")) && ($i < $maxiterations)); return null; } /** * remove https from defined siteurl and homeurl in the wpconfig, if present * * @since 2.1 * * @access public * */ public function remove_ssl_from_siteurl_in_wpconfig() { $wpconfig_path = $this->find_wp_config_path(); if (!empty($wpconfig_path)) { $wpconfig = file_get_contents($wpconfig_path); $homeurl_pos = strpos($wpconfig, "define('WP_HOME','https://"); $siteurl_pos = strpos($wpconfig, "define('WP_SITEURL','https://"); if (($homeurl_pos !== false) || ($siteurl_pos !== false)) { if (is_writable($wpconfig_path)) { $search_array = array("define('WP_HOME','https://", "define('WP_SITEURL','https://"); $ssl_array = array("define('WP_HOME','http://", "define('WP_SITEURL','http://"); //now replace these urls $wpconfig = str_replace($search_array, $ssl_array, $wpconfig); file_put_contents($wpconfig_path, $wpconfig); } else { $this->errors['wpconfig not writable'] = TRUE; } } } } /** * * Checks if the wp config contains any defined siteurl and homeurl * * */ private function check_for_siteurl_in_wpconfig() { $wpconfig_path = $this->find_wp_config_path(); if (empty($wpconfig_path)) return; $wpconfig = file_get_contents($wpconfig_path); $homeurl_pattern = '/(define\(\s*\'WP_HOME\'\s*,\s*\'http\:\/\/)/'; $siteurl_pattern = '/(define\(\s*\'WP_SITEURL\'\s*,\s*\'http\:\/\/)/'; $this->wpconfig_siteurl_not_fixed = FALSE; if (preg_match($homeurl_pattern, $wpconfig) || preg_match($siteurl_pattern, $wpconfig)) { $this->wpconfig_siteurl_not_fixed = TRUE; $this->trace_log("siteurl or home url defines found in wpconfig"); } } /** * Runs only when siteurl or homeurl define was found in the wpconfig, with the check_for_siteurl_in_wpconfig function * and only when wpconfig is writable. * * @since 2.1 * * @access public * */ private function fix_siteurl_defines_in_wpconfig() { $wpconfig_path = $this->find_wp_config_path(); if (empty($wpconfig_path)) return; $wpconfig = file_get_contents($wpconfig_path); $homeurl_pattern = '/(define\(\s*\'WP_HOME\'\s*,\s*\'http\:\/\/)/'; $siteurl_pattern = '/(define\(\s*\'WP_SITEURL\'\s*,\s*\'http\:\/\/)/'; if (preg_match($homeurl_pattern, $wpconfig) || preg_match($siteurl_pattern, $wpconfig)) { if (is_writable($wpconfig_path)) { $this->trace_log("wp config siteurl/homeurl edited."); $wpconfig = preg_replace($homeurl_pattern, "define('WP_HOME','https://", $wpconfig); $wpconfig = preg_replace($siteurl_pattern, "define('WP_SITEURL','https://", $wpconfig); file_put_contents($wpconfig_path, $wpconfig); } else { $this->trace_log("not able to fix wpconfig siteurl/homeurl."); //only when siteurl or homeurl is defined in wpconfig, and wpconfig is not writable is there a possible issue because we cannot edit the defined urls. $this->wpconfig_siteurl_not_fixed = TRUE; } } else { $this->trace_log("no siteurl/homeurl defines in wpconfig"); } } /** * Check if the wpconfig is already fixed * * @since 2.2 * * @access public * */ public function wpconfig_has_fixes() { $wpconfig_path = $this->find_wp_config_path(); if (empty($wpconfig_path)) return false; $wpconfig = file_get_contents($wpconfig_path); //only one of two fixes possible. if (strpos($wpconfig, "//Begin Really Simple SSL Load balancing fix") !== FALSE) { return true; } if (strpos($wpconfig, "//Begin Really Simple SSL Server variable fix") !== FALSE) { return true; } return false; } /** * In case of load balancer without server https on, add fix in wp-config * * @since 2.1 * * @access public * */ public function wpconfig_loadbalancer_fix() { if (!rsssl_user_can_manage()) return; $wpconfig_path = $this->find_wp_config_path(); if (empty($wpconfig_path)) return; $wpconfig = file_get_contents($wpconfig_path); $this->wpconfig_loadbalancer_fix_failed = FALSE; //only if loadbalancer AND NOT SERVER-HTTPS-ON should the following be added. (is_ssl = false) if (strpos($wpconfig, "//Begin Really Simple SSL Load balancing fix") === FALSE) { if (is_writable($wpconfig_path)) { $rule = "\n" . "//Begin Really Simple SSL Load balancing fix" . "\n"; $rule .= 'if ((isset($_ENV["HTTPS"]) && ("on" == $_ENV["HTTPS"]))' . "\n"; $rule .= '|| (isset($_SERVER["HTTP_X_FORWARDED_SSL"]) && (strpos($_SERVER["HTTP_X_FORWARDED_SSL"], "1") !== false))' . "\n"; $rule .= '|| (isset($_SERVER["HTTP_X_FORWARDED_SSL"]) && (strpos($_SERVER["HTTP_X_FORWARDED_SSL"], "on") !== false))' . "\n"; $rule .= '|| (isset($_SERVER["HTTP_CF_VISITOR"]) && (strpos($_SERVER["HTTP_CF_VISITOR"], "https") !== false))' . "\n"; $rule .= '|| (isset($_SERVER["HTTP_CLOUDFRONT_FORWARDED_PROTO"]) && (strpos($_SERVER["HTTP_CLOUDFRONT_FORWARDED_PROTO"], "https") !== false))' . "\n"; $rule .= '|| (isset($_SERVER["HTTP_X_FORWARDED_PROTO"]) && (strpos($_SERVER["HTTP_X_FORWARDED_PROTO"], "https") !== false))' . "\n"; $rule .= '|| (isset($_SERVER["HTTP_X_PROTO"]) && (strpos($_SERVER["HTTP_X_PROTO"], "SSL") !== false))' . "\n"; $rule .= ') {' . "\n"; $rule .= '$_SERVER["HTTPS"] = "on";' . "\n"; $rule .= '}' . "\n"; $rule .= "//END Really Simple SSL" . "\n"; $insert_after = "trace_log("wp config loadbalancer fix inserted"); } else { $this->trace_log("wp config loadbalancer fix FAILED"); $this->wpconfig_loadbalancer_fix_failed = TRUE; } } else { $this->trace_log("wp config loadbalancer fix already in place, great!"); } $this->save_options(); } /** * Getting WordPress to recognize setup as being SSL when no https server variable is available * * @since 2.1 * * @access public * */ public function wpconfig_server_variable_fix() { if (!rsssl_user_can_manage()) return; $wpconfig_path = $this->find_wp_config_path(); if (empty($wpconfig_path)) return; $wpconfig = file_get_contents($wpconfig_path); //check permissions if (!is_writable($wpconfig_path)) { $this->trace_log("wp-config.php not writable"); return; } //when more than one blog, first remove what we have if (is_multisite() && !RSSSL()->rsssl_multisite->is_multisite_subfolder_install() && !RSSSL()->rsssl_multisite->ssl_enabled_networkwide && count($this->sites) > 1) { $wpconfig = preg_replace("/\/\/Begin\s?Really\s?Simple\s?SSL.*?\/\/END\s?Really\s?Simple\s?SSL/s", "", $wpconfig); $wpconfig = preg_replace("/\n+/", "\n", $wpconfig); file_put_contents($wpconfig_path, $wpconfig); } //now create new //check if the fix is already there if (strpos($wpconfig, "//Begin Really Simple SSL Server variable fix") !== FALSE) { $this->trace_log("wp config server variable fix already in place, great!"); return; } $this->trace_log("Adding server variable to wpconfig"); $rule = $this->get_server_variable_fix_code(); $insert_after = "trace_log("wp config server variable fix inserted"); $this->save_options(); } /** * @return string * * Get code for server variable fix * * @access protected * */ protected function get_server_variable_fix_code() { if (is_multisite() && !RSSSL()->rsssl_multisite->ssl_enabled_networkwide && RSSSL()->rsssl_multisite->is_multisite_subfolder_install()) { $this->trace_log("per site activation on subfolder install, wp config server variable fix skipped"); return ""; } if (is_multisite() && !RSSSL()->rsssl_multisite->ssl_enabled_networkwide && count($this->sites) == 0) { $this->trace_log("no sites left with SSL, wp config server variable fix skipped"); return ""; } if ( is_multisite() && !RSSSL()->rsssl_multisite->ssl_enabled_networkwide ) { $rule = "\n" . "//Begin Really Simple SSL Server variable fix" . "\n"; foreach ($this->sites as $domain) { //remove http or https. $this->trace_log("getting server variable rule for:" . $domain); $domain = preg_replace("/(http:\/\/|https:\/\/)/", "", $domain); //we excluded subfolders, so treat as domain //check only for domain without www, as the www variant is found as well with the no www search. $domain_no_www = str_replace("www.", "", $domain); $rule .= 'if ( strpos($_SERVER["HTTP_HOST"], "' . $domain_no_www . '")!==FALSE ) {' . "\n"; $rule .= ' $_SERVER["HTTPS"] = "on";' . "\n"; $rule .= '}' . "\n"; } $rule .= "//END Really Simple SSL" . "\n"; } else { $rule = "\n" . "//Begin Really Simple SSL Server variable fix" . "\n"; $rule .= '$_SERVER["HTTPS"] = "on";' . "\n"; $rule .= "//END Really Simple SSL" . "\n"; } return $rule; } /** * Removing changes made to the wpconfig * * @since 2.1 * * @access public * */ public function remove_wpconfig_edit() { $wpconfig_path = $this->find_wp_config_path(); if (empty($wpconfig_path)) return; $wpconfig = file_get_contents($wpconfig_path); //check for permissions if (!is_writable($wpconfig_path)) { $this->trace_log("could not remove wpconfig edits, wp-config.php not writable"); $this->errors['wpconfig not writable'] = TRUE; return; } //remove edits $wpconfig = preg_replace("/\/\/Begin\s?Really\s?Simple\s?SSL.*?\/\/END\s?Really\s?Simple\s?SSL/s", "", $wpconfig); $wpconfig = preg_replace("/\n+/", "\n", $wpconfig); file_put_contents($wpconfig_path, $wpconfig); //in multisite environment, with per site activation, re-add if (is_multisite() && !RSSSL()->rsssl_multisite->ssl_enabled_networkwide) { if ($this->do_wpconfig_loadbalancer_fix) $this->wpconfig_loadbalancer_fix(); if ($this->no_server_variable) $this->wpconfig_server_variable_fix(); } } /** * Changes the siteurl and homeurl to https * * @since 2.0 * * @access public * */ public function set_siteurl_to_ssl() { $this->trace_log("converting siteurl and homeurl to https"); $siteurl_ssl = str_replace("http://", "https://", get_option('siteurl')); $homeurl_ssl = str_replace("http://", "https://", get_option('home')); update_option('siteurl', $siteurl_ssl); update_option('home', $homeurl_ssl); //RSSSL has it's own, more extensive mixed content fixer. update_option( 'https_migration_required', false ); } /** * On de-activation, siteurl and homeurl are reset to http * * @since 2.0 * * @access public * */ public function remove_ssl_from_siteurl() { $siteurl_no_ssl = str_replace("https://", "http://", get_option('siteurl')); $homeurl_no_ssl = str_replace("https://", "http://", get_option('home')); update_option('siteurl', $siteurl_no_ssl); update_option('home', $homeurl_no_ssl); } /** * Save the plugin options * * @since 2.0 * * @access public * */ public function save_options() { //any options added here should also be added to function options_validate() $options = array( 'site_has_ssl' => $this->site_has_ssl, 'hsts' => $this->hsts, 'htaccess_warning_shown' => $this->htaccess_warning_shown, 'review_notice_shown' => $this->review_notice_shown, 'ssl_success_message_shown' => $this->ssl_success_message_shown, 'autoreplace_insecure_links' => $this->autoreplace_insecure_links, 'plugin_db_version' => $this->plugin_db_version, 'do_not_edit_htaccess' => $this->do_not_edit_htaccess, 'htaccess_redirect' => $this->htaccess_redirect, 'ssl_enabled' => $this->ssl_enabled, 'javascript_redirect' => $this->javascript_redirect, 'wp_redirect' => $this->wp_redirect, 'switch_mixed_content_fixer_hook' => $this->switch_mixed_content_fixer_hook, 'dismiss_all_notices' => $this->dismiss_all_notices, 'high_contrast' => $this->high_contrast, 'dismiss_review_notice' => $this->dismiss_review_notice, ); update_option('rlrsssl_options', $options); } /** * Handles deactivation of this plugin * * @since 2.0 * * @access public * */ public function deactivate($networkwide) { if ( $this->ssl_enabled ) { $this->remove_ssl_from_siteurl(); $this->remove_ssl_from_siteurl_in_wpconfig(); $this->remove_secure_cookie_settings(); $this->site_has_ssl = FALSE; $this->hsts = FALSE; $this->htaccess_warning_shown = FALSE; $this->review_notice_shown = FALSE; $this->ssl_success_message_shown = FALSE; $this->autoreplace_insecure_links = TRUE; $this->do_not_edit_htaccess = FALSE; $this->htaccess_redirect = FALSE; $this->javascript_redirect = FALSE; $this->wp_redirect = FALSE; $this->ssl_enabled = FALSE; $this->switch_mixed_content_fixer_hook = FALSE; $this->dismiss_all_notices = FALSE; $this->high_contrast = FALSE; $this->dismiss_review_notice = FALSE; $this->save_options(); //when on multisite, per site activation, recreate domain list for htaccess and wpconfig rewrite actions if (is_multisite()) { RSSSL()->rsssl_multisite->deactivate(); } do_action("rsssl_deactivate"); $this->remove_wpconfig_edit(); $this->removeHtaccessEdit(); } } /** * remove secure cookie settings * * @since 4.0.10 * * @access public * */ public function remove_secure_cookie_settings() { if ( wp_doing_ajax() || !rsssl_user_can_manage()) return; if ( !$this->contains_secure_cookie_settings()) return; $wpconfig_path = $this->find_wp_config_path(); if ( !is_writable($wpconfig_path) ) return; if (!empty($wpconfig_path)) { $wpconfig = file_get_contents($wpconfig_path); $wpconfig = preg_replace("/\/\/Begin\s?Really\s?Simple\s?SSL\s?session\s?cookie\s?settings.*?\/\/END\s?Really\s?Simple\s?SSL/s", "", $wpconfig); $wpconfig = preg_replace("/\n+/","\n", $wpconfig); file_put_contents($wpconfig_path, $wpconfig); } } /** * Checks if we are currently on SSL protocol, but extends standard wp with loadbalancer check. * * @since 2.0 * * @access public * */ public function is_ssl_extended() { $server_var = FALSE; if ((isset($_ENV['HTTPS']) && ('on' == $_ENV['HTTPS'])) || (isset($_SERVER['HTTP_X_FORWARDED_SSL']) && (strpos($_SERVER['HTTP_X_FORWARDED_SSL'], '1') !== false)) || (isset($_SERVER['HTTP_X_FORWARDED_SSL']) && (strpos($_SERVER['HTTP_X_FORWARDED_SSL'], 'on') !== false)) || (isset($_SERVER['HTTP_CF_VISITOR']) && (strpos($_SERVER['HTTP_CF_VISITOR'], 'https') !== false)) || (isset($_SERVER['HTTP_CLOUDFRONT_FORWARDED_PROTO']) && (strpos($_SERVER['HTTP_CLOUDFRONT_FORWARDED_PROTO'], 'https') !== false)) || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && (strpos($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false)) || (isset($_SERVER['HTTP_X_PROTO']) && (strpos($_SERVER['HTTP_X_PROTO'], 'SSL') !== false)) ) { $server_var = TRUE; } if (is_ssl() || $server_var) { return true; } else { return false; } } /** * Checks for SSL by opening a test page in the plugin directory * * @since 2.0 * * @access public * */ public function detect_configuration() { $this->trace_log("Detecting configuration"); //if current page is on SSL, we can assume SSL is available, even when an errormsg was returned if ($this->is_ssl_extended()) { $this->site_has_ssl = TRUE; } else { //if certificate is valid $this->trace_log("Check SSL by retrieving SSL certificate info"); $this->site_has_ssl = RSSSL()->rsssl_certificate->is_valid(); } if ($this->site_has_ssl) { $filecontents = $this->get_test_page_contents(); //get filecontents to check .htaccess redirection method and wpconfig fix //check the type of SSL, either by parsing the returned string, or by reading the server vars. if ((strpos($filecontents, "#CLOUDFRONT#") !== false) || (isset($_SERVER['HTTP_CLOUDFRONT_FORWARDED_PROTO']) && ($_SERVER['HTTP_CLOUDFRONT_FORWARDED_PROTO'] == 'https'))) { $this->ssl_type = "CLOUDFRONT"; } elseif ((strpos($filecontents, "#CLOUDFLARE#") !== false) || (isset($_SERVER['HTTP_CF_VISITOR']) && (strpos($_SERVER["HTTP_CF_VISITOR"], "https") !== false))) { $this->ssl_type = "CLOUDFLARE"; } elseif ((strpos($filecontents, "#LOADBALANCER#") !== false) || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https'))) { $this->ssl_type = "LOADBALANCER"; } elseif ((strpos($filecontents, "#HTTP_X_PROTO#") !== false) || (isset($_SERVER['HTTP_X_PROTO']) && ($_SERVER['HTTP_X_PROTO'] == 'SSL'))) { $this->ssl_type = "HTTP_X_PROTO"; } elseif ((strpos($filecontents, "#HTTP_X_FORWARDED_SSL_ON#") !== false) || (isset($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on')) { $this->ssl_type = "HTTP_X_FORWARDED_SSL_ON"; } elseif ((strpos($filecontents, "#HTTP_X_FORWARDED_SSL_1#") !== false) || (isset($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] == '1')) { $this->ssl_type = "HTTP_X_FORWARDED_SSL_1"; } elseif ((strpos($filecontents, "#SERVER-HTTPS-ON#") !== false) || (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on')) { $this->ssl_type = "SERVER-HTTPS-ON"; } elseif ((strpos($filecontents, "#SERVER-HTTPS-1#") !== false) || (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == '1')) { $this->ssl_type = "SERVER-HTTPS-1"; } elseif ((strpos($filecontents, "#SERVERPORT443#") !== false) || (isset($_SERVER['SERVER_PORT']) && ('443' == $_SERVER['SERVER_PORT']))) { $this->ssl_type = "SERVERPORT443"; } elseif ((strpos($filecontents, "#ENVHTTPS#") !== false) || (isset($_ENV['HTTPS']) && ('on' == $_ENV['HTTPS']))) { $this->ssl_type = "ENVHTTPS"; } elseif ((strpos($filecontents, "#NO KNOWN SSL CONFIGURATION DETECTED#") !== false)) { //if we are here, SSL was detected, but without any known server variables set. //So we can use this info to set a server variable ourselves. if (!$this->wpconfig_has_fixes()) { $this->no_server_variable = TRUE; } $this->trace_log("No server variable detected "); $this->ssl_type = "NA"; } else { //no valid response, so set to NA $this->ssl_type = "NA"; } //check for is_ssl() if ((!$this->is_ssl_extended() && (strpos($filecontents, "#SERVER-HTTPS-ON#") === false) && (strpos($filecontents, "#SERVER-HTTPS-1#") === false) && (strpos($filecontents, "#SERVERPORT443#") === false)) || (!is_ssl() && $this->is_ssl_extended())) { //when is_ssl would return false, we should add some code to wp-config.php if (!$this->wpconfig_has_fixes()) { $this->trace_log("is_ssl() will return false: wp-config fix needed"); $this->do_wpconfig_loadbalancer_fix = TRUE; } } } $this->check_for_siteurl_in_wpconfig(); $this->save_options(); } /** * Test if the htaccess redirect will work * This way, no redirect loops should occur. * * @since 2.1 * * @access public * */ public function test_htaccess_redirect() { if (!rsssl_user_can_manage()) return; $this->htaccess_test_success = get_transient('rsssl_htaccess_test_success'); if (!$this->htaccess_test_success) { $this->trace_log("testing htaccess rules..."); $filecontents = ""; $testpage_url = trailingslashit($this->test_url()) . "testssl/"; switch ($this->ssl_type) { case "CLOUDFRONT": $testpage_url .= "cloudfront"; break; case "CLOUDFLARE": $testpage_url .= "cloudflare"; break; case "LOADBALANCER": $testpage_url .= "loadbalancer"; break; case "HTTP_X_PROTO": $testpage_url .= "serverhttpxproto"; break; case "HTTP_X_FORWARDED_SSL_ON": $testpage_url .= "serverhttpxforwardedsslon"; break; case "HTTP_X_FORWARDED_SSL_1": $testpage_url .= "serverhttpxforwardedssl1"; break; case "SERVER-HTTPS-ON": $testpage_url .= "serverhttpson"; break; case "SERVER-HTTPS-1": $testpage_url .= "serverhttps1"; break; case "SERVERPORT443": $testpage_url .= "serverport443"; break; case "ENVHTTPS": $testpage_url .= "envhttps"; break; default: $testpage_url .= "serverhttpson"; } $testpage_url .= ("/ssl-test-page.html"); $response = wp_remote_get($testpage_url); if (is_array($response)) { $status = wp_remote_retrieve_response_code($response); $filecontents = wp_remote_retrieve_body($response); } $this->trace_log("test page url, enter in browser to check manually: " . $testpage_url); if (!is_wp_error($response) && (strpos($filecontents, "#SSL TEST PAGE#") !== false)) { $htaccess_test_success = 'success'; $this->trace_log("htaccess rules tested successfully."); } else { //.htaccess rewrite rule seems to be giving problems. $htaccess_test_success = 'error'; if (is_wp_error($response)) { $this->trace_log("htaccess rules test failed with error: " . $response->get_error_message()); } else { $this->trace_log("htaccess test rules failed. Set WordPress redirect in settings/SSL"); } } if (empty($filecontents)) { $htaccess_test_success = 'no-response'; } set_transient('rsssl_htaccess_test_success', $this->htaccess_test_success, 600); } if ($htaccess_test_success == 'no-response'){ $this->htaccess_test_success = FALSE; } if ($htaccess_test_success == 'success'){ $this->htaccess_test_success = true; } if ($htaccess_test_success == 'error'){ $this->htaccess_test_success = FALSE; } } /** * Get an url with which we can test the SSL connection and htaccess redirect rules. * * @since 2.0 * * @access public * */ public function test_url() { $plugin_url = str_replace("http://", "https://", trailingslashit(rsssl_url)); $https_home_url = str_replace("http://", "https://", home_url()); //in some case we get a relative url here, so we check that. //we compare to urls replaced to https, in case one of them is still on http. if ((strpos($plugin_url, "https://") === FALSE) && (strpos($plugin_url, $https_home_url) === FALSE) ) { //make sure we do not have a slash at the start $plugin_url = ltrim($plugin_url, "/"); $plugin_url = trailingslashit(home_url()) . $plugin_url; } //for subdomains or domain mapping situations, we have to convert the plugin_url from main site to the subdomain url. if (is_multisite() && (!is_main_site(get_current_blog_id())) && (!RSSSL()->rsssl_multisite->is_multisite_subfolder_install())) { $mainsiteurl = trailingslashit(str_replace("http://", "https://", network_site_url())); $home = trailingslashit($https_home_url); $plugin_url = str_replace($mainsiteurl, $home, $plugin_url); //return http link if original url is http. //if (strpos(home_url(), "https://")===FALSE) $plugin_url = str_replace("https://","http://",$plugin_url); } return $plugin_url; } /** * removes the added redirect to https rules to the .htaccess file. * * @since 2.0 * * @access public * */ public function removeHtaccessEdit() { if (file_exists($this->htaccess_file()) && is_writable($this->htaccess_file())) { $htaccess = file_get_contents($this->htaccess_file()); //if multisite, per site activation and more than one blog remaining on ssl, remove condition for this site only //the domain list has been rebuilt already, so current site is already removed. if (is_multisite() && !RSSSL()->rsssl_multisite->ssl_enabled_networkwide && count($this->sites) > 0) { //remove http or https. $domain = preg_replace("/(http:\/\/|https:\/\/)/", "", home_url()); $pattern = "/#wpmu\srewritecond\s?" . preg_quote($domain, "/") . "\n.*?#end\swpmu\srewritecond\s?" . preg_quote($domain, "/") . "\n/s"; //only remove if the pattern is there at all if (preg_match($pattern, $htaccess)) $htaccess = preg_replace($pattern, "", $htaccess); //now replace any remaining "or" on the last condition. $pattern = "/(\[OR\])(?!.*(\[OR\]|#start).*?RewriteRule)/s"; $htaccess = preg_replace($pattern, "", $htaccess, 1); } else { // remove everything $pattern_old = "/#\s?BEGIN\s?rlrssslReallySimpleSSL.*?#\s?END\s?rlrssslReallySimpleSSL/s"; $pattern_new = "/#\s?BEGIN\s?Really Simple SSL Redirect.*?#\s?END\s?Really Simple SSL Redirect/s"; //only remove if the pattern is there at all if (preg_match($pattern_old, $htaccess)) $htaccess = preg_replace($pattern_old, "", $htaccess); if (preg_match($pattern_new, $htaccess)) $htaccess = preg_replace($pattern_new, "", $htaccess); } $htaccess = preg_replace("/\n+/", "\n", $htaccess); file_put_contents($this->htaccess_file(), $htaccess); $this->save_options(); } else { $this->errors['HTACCESS_NOT_WRITABLE'] = TRUE; $this->trace_log("could not remove rules from htaccess, file not writable"); } } /** * @return bool * * Check if the .htaccess redirect is allowed on this setup * * @since 2.0 * */ public function htaccess_redirect_allowed() { if (is_multisite() && RSSSL()->rsssl_multisite->is_per_site_activated_multisite_subfolder_install()) { return false; } if (RSSSL()->rsssl_server->uses_htaccess()) { return true; } else { return false; } } /** * @return bool * * Checks if the htaccess contains redirect rules, either actual redirect or a rsssl marker. * * @since 2.0 * */ public function htaccess_contains_redirect_rules() { if ( !file_exists($this->htaccess_file()) ) { return false; } $pattern = '/RewriteRule \^\(\.\*\)\$ https:\/\/%{HTTP_HOST}(\/\$1|%{REQUEST_URI}) (\[R=301,.*L\]|\[L,.*R=301\])/i'; $htaccess = file_get_contents($this->htaccess_file()); if ( preg_match( $pattern, $htaccess ) ) { return true; } else { $this->trace_log(".htaccess does not contain default Really Simple SSL redirect"); return false; } } /** * Checks if the htaccess contains the Really Simple SSL comment. * */ public function contains_rsssl_rules() { if (!file_exists($this->htaccess_file())) { return false; } $htaccess = file_get_contents($this->htaccess_file()); preg_match("/BEGIN rlrssslReallySimpleSSL/", $htaccess, $old); preg_match("/BEGIN Really Simple SSL Redirect/", $htaccess, $new); if ( count( $old ) === 0 && count( $new ) === 0 ) { return false; } else { return true; } } /** * @return bool * * Checks if a 301 redirect is set * this is the case if either the wp_redirect is set, or the htaccess redirect is set. * */ public function has_301_redirect() { if ($this->wp_redirect) return true; if (RSSSL()->rsssl_server->uses_htaccess() && $this->htaccess_contains_redirect_rules()) { return true; } return false; } /** * Checks if the HSTS rule is already in the htaccess file * Set the hsts variable in the db accordingly. applies to preload version as well. * * @since 2.1 * * @access public * */ public function contains_hsts() { if (!file_exists($this->htaccess_file())) { $this->trace_log(".htaccess not found in " . $this->ABSpath); $result = $this->hsts; //just return the setting. } else { $htaccess = file_get_contents($this->htaccess_file()); preg_match("/Strict-Transport-Security/", $htaccess, $check); if (count($check) === 0) { $result = false; } else { $result = true; } } return $result; } /** * returns list of recommended, but not active security headers for this site * returns empty array if no .htacces file exists * Uses cURL, fallback to .htaccess check upon cURL failure * @return array * * @since 4.0 * * @access public * */ public function get_recommended_security_headers() { $used_headers = array(); $not_used_headers = array(); $check_headers = apply_filters( 'rsssl_recommended_security_headers', array( array( 'name' => 'Upgrade Insecure Requests', 'pattern' => 'upgrade-insecure-requests', ), array( 'name' => 'X-XSS protection', 'pattern' => 'X-XSS-Protection', ), array( 'name' => 'X-Content Type Options', 'pattern' => 'X-Content-Type-Options', ), array( 'name' => 'Referrer-Policy', 'pattern' => 'Referrer-Policy', ), array( 'name' => 'X-Frame-Options', 'pattern' => 'X-Frame-Options', ), array( 'name' => 'Permissions-Policy', 'pattern' => 'Permissions-Policy', ), array( 'name' => 'HTTP Strict Transport Security', 'pattern' => 'Strict-Transport-Security', ), ) ); // cURL check $curl_check_done = get_transient('rsssl_can_use_curl_headers_check');//no, yes or false if ( !$curl_check_done ) { //set a default set_transient( 'rsssl_can_use_curl_headers_check', 'no', WEEK_IN_SECONDS ); if ( function_exists( 'curl_init' ) ) { $url = get_site_url(); $ch = curl_init(); $headers = []; curl_setopt( $ch, CURLOPT_URL, $url ); curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); curl_setopt( $ch, CURLOPT_TIMEOUT, 3 ); //timeout in seconds curl_setopt( $ch, CURLOPT_HEADERFUNCTION, function ( $curl, $header ) use ( &$headers ) { $len = strlen( $header ); $header = explode( ':', $header, 2 ); if ( count( $header ) < 2 ) // ignore invalid headers { return $len; } $headers[ strtolower( trim( $header[0] ) ) ][] = trim( $header[1] ); return $len; } ); curl_exec( $ch ); // Check if any headers have been found if ( ! empty( $headers ) && is_array( $headers ) ) { // Loop through each header and check if it's one of the recommended security headers. If so, add to used_headers array. foreach ( $headers as $name => $value ) { foreach ( $check_headers as $check_header ) { // If the pattern occurs in either the header name or value, it's a security header. if ( stripos( $name, $check_header['pattern'] ) !== false || stripos( $value[0], $check_header['pattern'] ) !== false ) { // Prevent duplicate entries if ( ! in_array( $check_header['name'], $used_headers ) ) { $used_headers[] = $check_header['name']; } } } } // Now check which headers are unused. Compare the used headers against the $check_headers array. foreach ( $check_headers as $header ) { if ( in_array( $header['name'], $used_headers ) ) { // Header is used, do not add to unused array continue; } else { // Header is not used. Add to not used array $not_used_headers[] = $header['name']; } } $curl_check_done = $not_used_headers; } else { $curl_check_done = 'no'; } } else { $curl_check_done = 'no'; } set_transient( 'rsssl_can_use_curl_headers_check', $curl_check_done, WEEK_IN_SECONDS ); } if ( $curl_check_done === 'no' ) { if (RSSSL()->rsssl_server->uses_htaccess() && file_exists($this->htaccess_file())) { $htaccess = file_get_contents($this->htaccess_file()); foreach ($check_headers as $check_header){ if ( !preg_match("/".$check_header['pattern']."/", $htaccess, $check) ) { $not_used_headers[] = $check_header['name']; } } } } else { $not_used_headers = $curl_check_done; } return $not_used_headers; } /** * Check if the recommended headers are enabled * * @return bool */ public function recommended_headers_enabled() { $unused_headers = $this->get_recommended_security_headers(); if ( empty( $unused_headers ) ) { return true; } return false; } /** * Adds redirect to https rules to the .htaccess file or htaccess.conf on Bitnami. * * @since 2.0 * * @access public * */ public function editHtaccess() { if (!rsssl_user_can_manage()) return; $this->trace_log("checking if .htaccess can or should be edited..."); //does it exist? if (!file_exists($this->htaccess_file()) ) { $this->trace_log(".htaccess not found."); return; } //check if editing is blocked. if ($this->do_not_edit_htaccess) { $this->trace_log("Edit of .htaccess blocked by setting or define 'do not edit htaccess' in Really Simple SSL."); return; } if ( !is_writable($this->htaccess_file()) ) { //set the wp redirect as fallback, because .htaccess couldn't be edited. if ($this->clicked_activate_ssl()) $this->wp_redirect = true; if (is_multisite()) { RSSSL()->rsssl_multisite->wp_redirect = true; RSSSL()->rsssl_multisite->save_options(); } $this->save_options(); $this->trace_log(".htaccess not writable."); return; } $htaccess = file_get_contents($this->htaccess_file()); $pattern_old = "/#\s?BEGIN\s?rlrssslReallySimpleSSL.*?#\s?END\s?rlrssslReallySimpleSSL/s"; $pattern_new = "/#\s?BEGIN\s?Really Simple SSL Redirect.*?#\s?END\s?Really Simple SSL Redirect/s"; $htaccess = preg_replace($pattern_old, "", $htaccess); $htaccess = preg_replace($pattern_new, "", $htaccess); $htaccess = preg_replace("/\n+/", "\n", $htaccess); // If using WP Rocket, .htaccess insertion is handled by before_rocket_htaccess_rules filter $rules = ''; if ( ! function_exists('rocket_clean_domain') ) { $rules = $this->get_redirect_rules(); } //insert rules before WordPress part. $wptag = "# BEGIN WordPress"; if ( strpos( $htaccess, $wptag ) !== false ) { $htaccess = str_replace( $wptag, $rules . $wptag, $htaccess ); } else { $htaccess = $htaccess . $rules; } file_put_contents($this->htaccess_file(), $htaccess); $this->maybe_flush_wprocket_htaccess(); } /** * Return .htaccess redirect when using WP Rocket * @return string */ public function add_htaccess_redirect_before_wp_rocket() { $this->detect_configuration(); return $this->get_redirect_rules(); } /** * Regenerate the wp rocket .htaccess rules */ public function maybe_flush_wprocket_htaccess(){ if ( wp_doing_ajax() || !$this->is_settings_page() || !$this->ssl_enabled || !current_user_can("activate_plugins") || $this->do_not_edit_htaccess ) return; if ( function_exists('flush_rocket_htaccess') ) { flush_rocket_htaccess(); } if ( function_exists('rocket_generate_config_file') ) { rocket_generate_config_file(); } } /** * * @since 2.2 * Check if the mixed content fixer is functioning on the front end, by scanning the source of the homepage for the fixer comment. * @access public * @return string $mixed_content_fixer_detected */ public function mixed_content_fixer_detected() { $status = 0; $mixed_content_fixer_detected = get_transient('rsssl_mixed_content_fixer_detected'); if (!$mixed_content_fixer_detected) { $web_source = ""; //check if the mixed content fixer is active $response = wp_remote_get(home_url()); if (!is_wp_error($response)) { if ( is_array( $response ) ) { $status = wp_remote_retrieve_response_code( $response ); $web_source = wp_remote_retrieve_body( $response ); } if ( $status != 200 ) { $mixed_content_fixer_detected = 'no-response'; } elseif ( strpos( $web_source, "data-rsssl=" ) === false ) { $mixed_content_fixer_detected = 'not-found'; } else { $mixed_content_fixer_detected = 'found'; } } if (is_wp_error($response)) { $mixed_content_fixer_detected = 'error'; $error = $response->get_error_message(); set_transient('rsssl_curl_error' , $error, 600); if (!empty($error) && (strpos($error, "cURL error") !== false) ) { $mixed_content_fixer_detected = 'curl-error'; } } if ($this->autoreplace_insecure_links == ! true) { $mixed_content_fixer_detected = 'not-enabled'; } set_transient('rsssl_mixed_content_fixer_detected', $mixed_content_fixer_detected, 600); } if ($mixed_content_fixer_detected === 'no-response'){ //Could not connect to website $this->trace_log("Could not connect to webpage to detect mixed content fixer"); $this->mixed_content_fixer_detected = FALSE; } if ($mixed_content_fixer_detected === 'not-found'){ //Mixed content fixer marker not found in the websource $this->trace_log("Mixed content marker not found in websource"); $this->mixed_content_fixer_detected = FALSE; } if ($mixed_content_fixer_detected === 'error'){ $this->trace_log("Mixed content marker not found: unknown error"); //Error encountered while retrieving the webpage. Fallback since most errors should be cURL errors $this->mixed_content_fixer_detected = FALSE; } if ($mixed_content_fixer_detected === 'curl-error'){ //Site has has a cURL error $this->trace_log("Mixed content fixer could not be detected: cURL error"); $this->mixed_content_fixer_detected = FALSE; } if ($mixed_content_fixer_detected === 'found'){ $this->trace_log("Mixed content fixer successfully detected"); //Mixed content fixer was successfully detected on the front end $this->mixed_content_fixer_detected = true; } if ($mixed_content_fixer_detected === 'not-enabled') { $this->trace_log("Mixed content fixer not enabled"); $this->mixed_content_fixer_detected = FALSE; } return $mixed_content_fixer_detected; } /** * Create redirect rules for the .htaccess. * @since 2.1 * * @access public * * @param bool $manual * * @return string */ public function get_redirect_rules($manual = false) { $this->trace_log("retrieving redirect rules"); //only add the redirect rules when a known type of SSL was detected. Otherwise, we use https. $rule = ""; //if the htaccess test was successfull, and we know the redirectype, edit if ($this->htaccess_redirect && ($manual || $this->htaccess_test_success) && $this->ssl_type != "NA") { $this->trace_log("starting insertion of .htaccess redirects."); $rule .= "" . "\n"; $rule .= "RewriteEngine on" . "\n"; $or = ""; if ($this->ssl_type == "SERVER-HTTPS-ON") { $rule .= "RewriteCond %{HTTPS} !=on [NC]" . "\n"; } elseif ($this->ssl_type == "SERVER-HTTPS-1") { $rule .= "RewriteCond %{HTTPS} !=1" . "\n"; } elseif ($this->ssl_type == "LOADBALANCER") { $rule .= "RewriteCond %{HTTP:X-Forwarded-Proto} !https" . "\n"; } elseif ($this->ssl_type == "HTTP_X_PROTO") { $rule .= "RewriteCond %{HTTP:X-Proto} !SSL" . "\n"; } elseif ($this->ssl_type == "CLOUDFLARE") { $rule .= "RewriteCond %{HTTP:CF-Visitor} '" . '"scheme":"http"' . "'" . "\n";//some concatenation to get the quotes right. } elseif ($this->ssl_type == "SERVERPORT443") { $rule .= "RewriteCond %{SERVER_PORT} !443" . "\n"; } elseif ($this->ssl_type == "CLOUDFRONT") { $rule .= "RewriteCond %{HTTP:CloudFront-Forwarded-Proto} !https" . "\n"; } elseif ($this->ssl_type == "HTTP_X_FORWARDED_SSL_ON") { $rule .= "RewriteCond %{HTTP:X-Forwarded-SSL} !on" . "\n"; } elseif ($this->ssl_type == "HTTP_X_FORWARDED_SSL_1") { $rule .= "RewriteCond %{HTTP:X-Forwarded-SSL} !=1" . "\n"; } elseif ($this->ssl_type == "ENVHTTPS") { $rule .= "RewriteCond %{ENV:HTTPS} !=on" . "\n"; } //if multisite, and NOT subfolder install (checked for in the detect_config function) //, add a condition so it only applies to sites where plugin is activated if (is_multisite() && !RSSSL()->rsssl_multisite->ssl_enabled_networkwide) { $this->trace_log("multisite, per site activation"); foreach ($this->sites as $domain) { $this->trace_log("adding condition for:" . $domain); //remove http or https. $domain = preg_replace("/(http:\/\/|https:\/\/)/", "", $domain); //We excluded subfolders, so treat as domain $domain_no_www = str_replace("www.", "", $domain); $domain_yes_www = "www." . $domain_no_www; $rule .= "#wpmu rewritecond " . $domain . "\n"; $rule .= "RewriteCond %{HTTP_HOST} ^" . preg_quote($domain_no_www, "/") . " [OR]" . "\n"; $rule .= "RewriteCond %{HTTP_HOST} ^" . preg_quote($domain_yes_www, "/") . " [OR]" . "\n"; $rule .= "#end wpmu rewritecond " . $domain . "\n"; } //now remove last [OR] if at least on one site the plugin was activated, so we have at least one condition if (count($this->sites) > 0) { $rule = strrev(implode("", explode(strrev("[OR]"), strrev($rule), 2))); } } else { $this->trace_log("single site or networkwide activation"); } //fastest cache compatibility if (class_exists('WpFastestCache')) { $rule .= "RewriteCond %{REQUEST_URI} !wp-content\/cache\/(all|wpfc-mobile-cache)" . "\n"; } //Exclude .well-known/acme-challenge for Let's Encrypt validation if ($this->has_acme_challenge_directory() && !$this->has_well_known_needle()) { $rule .= "RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/" . "\n"; } $rule .= "RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]" . "\n"; $rule .= "" . "\n"; } if (strlen($rule) > 0) { $rule = "\n" . "# BEGIN Really Simple SSL Redirect" . " " . rsssl_version . "\n" . $rule . "# END Really Simple SSL Redirect" . "\n"; } $rule = apply_filters("rsssl_htaccess_output", $rule); $rule = preg_replace("/\n+/", "\n", $rule); return $rule; } /** * Show warning when wpconfig could not be fixed * * @since 2.2 * * @access public * */ public function show_notice_wpconfig_needs_fixes() { //prevent showing the review on edit screen, as gutenberg removes the class which makes it editable. $screen = get_current_screen(); if ( $screen->base === 'post' ) return; ob_start(); if ($this->wpconfig_siteurl_not_fixed) { ?>

', ''); ?>

do_wpconfig_loadbalancer_fix) { ?>



//Begin Really Simple SSL Load balancing fix
if ((isset($_ENV["HTTPS"]) && ("on" == $_ENV["HTTPS"]))
|| (isset($_SERVER["HTTP_X_FORWARDED_SSL"]) && (strpos($_SERVER["HTTP_X_FORWARDED_SSL"], "1") !== false))
|| (isset($_SERVER["HTTP_X_FORWARDED_SSL"]) && (strpos($_SERVER["HTTP_X_FORWARDED_SSL"], "on") !== false))
|| (isset($_SERVER["HTTP_CF_VISITOR"]) && (strpos($_SERVER["HTTP_CF_VISITOR"], "https") !== false))
|| (isset($_SERVER["HTTP_CLOUDFRONT_FORWARDED_PROTO"]) && (strpos($_SERVER["HTTP_CLOUDFRONT_FORWARDED_PROTO"], "https") !== false))
|| (isset($_SERVER["HTTP_X_FORWARDED_PROTO"]) && (strpos($_SERVER["HTTP_X_FORWARDED_PROTO"], "https") !== false))
|| (isset($_SERVER["HTTP_X_PROTO"]) && (strpos($_SERVER["HTTP_X_PROTO"], "SSL") !== false))
) {
   $_SERVER["HTTPS"] = "on";
}
//END Really Simple SSL

', ''); ?>

no_server_variable) { ?>

', '');?>

notice_html( $class, $title, $content ); } /** * * @return bool * since 3.1 * Check if .well-known/acme-challenge directory exists * @access public */ public function has_acme_challenge_directory() { if (file_exists("$this->ABSpath.well-known/acme-challenge")) { return true; } return false; } /** * * @return bool * since 3.1 * Check if there are already .well-known rules in .htaccess file * @access public * */ public function has_well_known_needle() { $file = $this->htaccess_file(); if ( !file_exists($file) ) { return false; } $htaccess = file_get_contents( $file ); $well_known_needle = "RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/"; if (strpos($htaccess, $well_known_needle) !== false) { return true; } return false; } /** * Shows a notice, asking users for a review. */ public function show_leave_review_notice() { if ($this->dismiss_all_notices || is_multisite() && rsssl_multisite::this()->dismiss_all_notices) return; //prevent showing the review on edit screen, as gutenberg removes the class which makes it editable. $screen = get_current_screen(); if ( $screen->base === 'post' ) return; //this user has never had the review notice yet. if ($this->ssl_enabled && !get_option('rsssl_activation_timestamp')){ $month = rand ( 0, 11); $trigger_notice_date = time() + $month * MONTH_IN_SECONDS; update_option('rsssl_activation_timestamp', $trigger_notice_date); update_option('rsssl_before_review_notice_user', true); } if (!$this->review_notice_shown && get_option('rsssl_activation_timestamp') && get_option('rsssl_activation_timestamp') < strtotime("-1 month")) { add_action('admin_print_footer_scripts', array($this, 'insert_dismiss_review')); ?>
review-logo

',''); ?>

',''); ?>

- Rogier
base === 'post' ) return; //don't show admin notices on our own settings page: we have the warnings there if ( $this->is_settings_page() ) return; $notices = $this->get_notices_list( array('admin_notices'=>true) ); foreach ( $notices as $id => $notice ){ $notice = $notice['output']; $class = ( $notice['status'] !== 'completed' ) ? 'error' : 'updated'; echo $this->notice_html( $class.' '.$id, $notice['title'], $notice['msg'] ); } } /** * Insert some ajax script to dismiss the review notice, and stop nagging about it * * @since 3.0 * * @access public * * type: dismiss, later * */ public function insert_dismiss_review() { $ajax_nonce = wp_create_nonce("really-simple-ssl"); ?> ssl_success_message_shown = TRUE; $this->save_options(); wp_die(); } /** * Process the ajax dismissal of settings notice * * Since 3.1 * * @access public * */ public function dismiss_settings_notice_callback() { if (!rsssl_user_can_manage() ) return; if (!isset($_POST['token']) || (!wp_verify_nonce($_POST['token'], 'rsssl_nonce'))) { return; } if (isset($_POST['type'])) { $dismiss_type = sanitize_title( $_POST['type'] ); update_option( "rsssl_".$dismiss_type."_dismissed", true ); delete_transient( 'rsssl_plusone_count' ); } // count should be updated, therefore clear cache $this->clear_transients(); $data = array( 'tasks' => $this->get_remaining_tasks_count(), 'percentage' => $this->get_score_percentage(), ); $response = json_encode( $data ); header( "Content-Type: application/json" ); echo $response; exit; } /** * Process the ajax dismissal of the htaccess message. * * @since 2.1 * * @access public * */ public function dismiss_review_notice_callback() { $type = isset($_POST['type']) ? $_POST['type'] : false; if ($type === 'dismiss'){ $this->review_notice_shown = TRUE; } if ($type === 'later') { //Reset activation timestamp, notice will show again in one month. update_option('rsssl_activation_timestamp', time()); } $this->save_options(); wp_die(); // this is required to terminate immediately and return a proper response } /** * Adds the admin options page * * @since 2.0 * * @access public * */ public function add_settings_page() { if ( ! rsssl_user_can_manage() ) return; //hides the settings page if the hide menu for subsites setting is enabled if (is_multisite() && rsssl_multisite::this()->hide_menu_for_subsites && !is_super_admin()) return; global $rsssl_admin_page; $count = $this->count_plusones(); if ($count > 0 ) { $update_count = "$count"; } else { $update_count = ""; } $rsssl_admin_page = add_options_page( __("SSL settings", "really-simple-ssl"), //link title __("SSL", "really-simple-ssl") . $update_count, //page title $this->capability, //capability 'rlrsssl_really_simple_ssl', //url array($this, 'settings_page')); //function } /** * * @since 3.1.6 * * Add an update count to the WordPress admin Settings menu item * Doesn't work when the Admin Menu Editor plugin is active * */ public function rsssl_edit_admin_menu() { if (!rsssl_user_can_manage()) return; global $menu; $count = $this->count_plusones(); $menu_slug = 'options-general.php'; $menu_title = __('Settings'); foreach($menu as $index => $menu_item){ if (!isset($menu_item[2]) || !isset($menu_item[0])) continue; if ($menu_item[2]===$menu_slug){ $pattern = '/([1-9])<\/span><\/span>/i'; if (preg_match($pattern, $menu_item[0], $matches)){ if (isset($matches[1])) $count = intval($count) + intval($matches[1]); } $update_count = $count > 0 ? "$count":''; $menu[$index][0] = $menu_title . $update_count; } } } /** * Create tabs on the settings page * * @since 2.1 * * @access public * */ public function admin_tabs($current = 'configuration') { $tabs = array( 'configuration' => '', ); $tabs = apply_filters("rsssl_grid_tabs", $tabs); //allow the license tab to show up for older version, to allow for upgrading $legacy_tabs = apply_filters("rsssl_tabs", array()); if (isset($legacy_tabs['license'])) $tabs['license']= $legacy_tabs['license']; // Only show general tab if there are other tabs as well if (count($tabs) > 1) { $tabs['configuration'] = __("General", "really-simple-ssl"); } $high_contrast = $this->high_contrast ? 'rsssl-high-contrast' : ''; ?> false, 'premium_only' => false, 'dismiss_on_upgrade' => false, 'status' => 'open', //status can be "all" (all tasks, regardless of dismissed or open), "open" (not success/completed) or "completed" ); $args = wp_parse_args($args, $defaults); $cache_admin_notices = !$this->is_settings_page() && $args['admin_notices']; //if we're on the settings page, we need to clear the admin notices transient, because this list never gets requested on the settings page, and won'd get cleared otherwise if ($this->clicked_activate_ssl() || $this->is_settings_page() || isset($_GET['ssl_reload_https']) ) { delete_transient('rsssl_admin_notices'); } if ( $cache_admin_notices) { $cached_notices = get_transient('rsssl_admin_notices'); if ( $cached_notices ) return $cached_notices; } $htaccess_file = $this->uses_htaccess_conf() ? "htaccess.conf (/conf/htaccess.conf/)" : $htaccess_file = ".htaccess"; if ( $this->ssl_type != "NA" ) { $rules = $this->get_redirect_rules( true ); $arr_search = array( "<", ">", "\n" ); $arr_replace = array( "<", ">", "
" ); $rules = str_replace( $arr_search, $arr_replace, $rules ); $rules = substr($rules, 4, -4); } else { $rules = __( "No recommended redirect rules detected.", "really-simple-ssl" ) ; } $rules = '
' . $rules . '
'; $notice_defaults = array( 'condition' => array(), 'callback' => false, ); $curl_error = get_transient('rsssl_curl_error'); $current_plugin_folder = $this->get_current_rsssl_free_dirname(); //get expiry date, if we have one. $certinfo = get_transient('rsssl_certinfo'); $end_date = isset($certinfo['validTo_time_t']) ? $certinfo['validTo_time_t'] : false; $expiry_date = !empty($end_date) ? date( get_option('date_format'), $end_date ) : __("(Unknown)", "really-simple-ssl"); $test_url = 'https://www.ssllabs.com/ssltest/analyze.html?d='.home_url(); $notices = array( 'deactivation_file_detected' => array( 'callback' => 'RSSSL()->really_simple_ssl->check_for_uninstall_file', 'score' => 30, 'output' => array( 'fail' => array( 'title' => __("Major security issue!", "really-simple-ssl"), 'msg' => __("The 'force-deactivate.php' file has to be renamed to .txt. Otherwise your ssl can be deactivated by anyone on the internet.", "really-simple-ssl") .' '. ''.__("Check again", "really-simple-ssl").'', 'icon' => 'warning', 'admin_notice' => true, 'plusone' => true, ), ), ), 'non_default_plugin_folder' => array( 'callback' => 'RSSSL()->really_simple_ssl->uses_default_folder_name', 'score' => 30, 'output' => array( 'false' => array( 'msg' => sprintf(__("The Really Simple SSL plugin folder in the /wp-content/plugins/ directory has been renamed to %s. This might cause issues when deactivating, or with premium add-ons. To fix this you can rename the Really Simple SSL folder back to the default %s.", "really-simple-ssl"),"" . $current_plugin_folder . "" , "really-simple-ssl"), 'url' => 'https://really-simple-ssl.com/knowledge-base/why-you-should-use-the-default-plugin-folder-name-for-really-simple-ssl/', 'icon' => 'warning', 'admin_notice' => false, ), ), ), 'mixed_content_scan' => array( 'dismiss_on_upgrade' => true, 'condition' => array('rsssl_ssl_enabled'), 'callback' => '_true_', 'score' => 5, 'output' => array( 'true' => array( 'url' => 'https://really-simple-ssl.com/knowledge-base/how-to-track-down-mixed-content-or-insecure-content/', 'msg' => __("SSL is now activated. Check if your website is secure by following this article.", "really-simple-ssl"), 'icon' => 'open', 'dismissible' => true, 'plusone' => true, ), ), ), 'compatiblity_check' => array( 'condition' => array('rsssl_incompatible_premium_version'), 'callback' => '_true_', 'score' => 5, 'output' => array( 'true' => array( 'url' => 'https://really-simple-ssl.com/pro/', 'msg' => __( "Really Simple SSL pro is not up to date. Update Really Simple SSL pro to ensure compatibility.", "really-simple-ssl"), 'icon' => 'open', 'dismissible' => false, 'plusone' => true, ), ), ), 'google_analytics' => array( 'dismiss_on_upgrade' => true, 'callback' => '_true_', 'condition' => array('rsssl_ssl_enabled', 'rsssl_ssl_activation_time_no_longer_then_3_days_ago'), 'score' => 5, 'output' => array( 'true' => array( 'msg' => __("Remember to change your URLs in external services like Google Analytics, Search Console and others. This should prevent any data loss resulting from the switch to https.", "really-simple-ssl"), 'url' => 'https://really-simple-ssl.com/knowledge-base/how-to-setup-google-analytics-and-google-search-consolewebmaster-tools/', 'icon' => 'open', 'dismissible' => true, 'plusone' => true, ), ), ), 'upgraded_to_four' => array( 'callback' => 'RSSSL()->really_simple_ssl->upgraded_to_four', 'score' => 5, 'output' => array( 'true' => array( 'url' => __('https://really-simple-ssl.com/really-simple-ssl-4-a-new-dashboard'), 'msg' => __("Really Simple SSL 4.0. Learn more about our newest major release.", "really-simple-ssl"), 'icon' => 'open', 'dismissible' => true, 'plusone' => true, ), ), ), 'ssl_enabled' => array( 'callback' => 'rsssl_ssl_enabled', 'score' => 30, 'output' => array( 'true' => array( 'msg' =>__('SSL is enabled on your site.', 'really-simple-ssl'), 'icon' => 'success' ), 'false' => array( 'msg' => __('SSL is not enabled yet.', 'really-simple-ssl'), 'icon' => 'warning', 'plusone' => true, ), ), ), 'ssl_detected' => array( 'condition' => array('NOT rsssl_ssl_detection_overridden'), 'callback' => 'rsssl_ssl_detected', 'score' => 30, 'output' => array( 'fail' => array( 'url' => 'https://really-simple-ssl.com/wp-config-fix-needed', 'msg' => __("The wp-config.php file is not writable, and needs to be edited. Please set this file to writable.", "really-simple-ssl"), 'icon' => 'warning' ), 'no-ssl-detected' => array( 'title' => __("No SSL detected", "really-simple-ssl"), 'msg' => __("No SSL detected. Use the retry button to check again.", "really-simple-ssl"). '

"rlrsssl_really_simple_ssl", "tab" => "letsencrypt"),admin_url("options-general.php")) .'" type="submit" class="button button-default">'.__("Install SSL certificate", "really-simple-ssl").''. ' 
', 'icon' => 'warning', 'admin_notice' => false, 'dismissible' => $this->ssl_enabled ), 'no-response' => array( 'title' => __("Could not test certificate", "really-simple-ssl"), 'msg' => __("Automatic certificate detection is not possible on your server.", "really-simple-ssl"). '

"rlrsssl_really_simple_ssl", "tab" => "letsencrypt"),admin_url("options-general.php")) .'" type="submit" class="button button-default">'.__("Install SSL certificate", "really-simple-ssl").''. ' '.__("Check manually", "really-simple-ssl").'
', 'icon' => 'warning', 'admin_notice' => false, 'dismissible' => true, ), 'ssl-detected' => array( 'msg' => __('An SSL certificate was detected on your site.', 'really-simple-ssl'), 'icon' => 'success' ), 'about-to-expire' => array( 'title' => __("Your SSL certificate will expire soon.", "really-simple-ssl"), 'msg' => sprintf(__("SSL certificate will expire on %s.","really-simple-ssl"), $expiry_date).' '.__("If your hosting provider auto-renews your certificate, no action is required. Alternatively, you have the option to generate an SSL certificate with Really Simple SSL.","really-simple-ssl").' '. sprintf(__("Depending on your hosting provider, %smanual installation%s may be required.", "really-simple-ssl"),'',''). '

"rlrsssl_really_simple_ssl", "tab" => "letsencrypt"),admin_url("options-general.php")) .'" type="submit" class="button button-default">'.__("Install SSL certificate", "really-simple-ssl").''. ' 
', 'icon' => 'warning', 'admin_notice' => false, ), ), ), 'mixed_content_fixer_detected' => array( 'condition' => array('rsssl_ssl_enabled'), 'callback' => 'RSSSL()->really_simple_ssl->mixed_content_fixer_detected', 'score' => 10, 'output' => array( 'found' => array( 'msg' =>__('Mixed content fixer was successfully detected on the front-end.', 'really-simple-ssl'), 'icon' => 'success' ), 'no-response' => array( 'url' => 'https://really-simple-ssl.com/knowledge-base/how-to-fix-no-response-from-webpage-warning/', 'msg' => __('Really Simple SSL has received no response from the webpage.', 'really-simple-ssl'), 'icon' => 'open', 'dismissible' => true, 'plusone' => true ), 'not-found' => array( 'url' => "https://really-simple-ssl.com/knowledge-base/how-to-check-if-the-mixed-content-fixer-is-active/", 'msg' => __('The mixed content fixer is active, but was not detected on the frontpage.', "really-simple-ssl"), 'icon' => 'open', 'dismissible' => true ), 'error' => array( 'msg' =>__('Error occurred when retrieving the webpage.', 'really-simple-ssl'), 'icon' => 'open', 'dismissible' => true ), 'not-enabled' => array( 'url' => $this->generate_enable_link($setting_name = 'autoreplace_insecure_links', $type='free'), 'msg' =>__('Mixed content fixer not enabled. Enable the option to fix mixed content on your site.', 'really-simple-ssl'), 'icon' => 'open', 'dismissible' => true ), 'curl-error' => array( 'url' => 'https://really-simple-ssl.com/knowledge-base/curl-errors/', 'msg' =>sprintf(__("The mixed content fixer could not be detected due to a cURL error: %s. cURL errors are often caused by an outdated version of PHP or cURL and don't affect the front-end of your site. Contact your hosting provider for a fix.", 'really-simple-ssl'), "" . $curl_error . ""), 'icon' => 'open', 'dismissible' => true, ), ), ), 'wordpress_redirect' => array( 'condition' => array('rsssl_ssl_enabled', 'NOT RSSSL()->really_simple_ssl->htaccess_redirect_allowed'), 'callback' => 'RSSSL()->really_simple_ssl->has_301_redirect', 'score' => 10, 'output' => array( 'true' => array( 'msg' => __('301 redirect to https set.', 'really-simple-ssl'), 'icon' => 'success' ), 'false' => array( 'msg' => __('No 301 redirect is set. Enable the WordPress 301 redirect in the settings to get a 301 permanent redirect.', 'really-simple-ssl'), 'icon' => 'open' ), ) ), 'check_redirect' => array( 'condition' => array('rsssl_ssl_enabled' , 'RSSSL()->really_simple_ssl->htaccess_redirect_allowed', 'NOT is_multisite'), 'callback' => 'rsssl_check_redirect', 'score' => 10, 'output' => array( 'htaccess-redirect-set' => array( 'msg' =>__('301 redirect to https set: .htaccess redirect.', 'really-simple-ssl') , 'icon' => 'success' ), 'wp-redirect-to-htaccess' => array( 'url' => $this->generate_enable_link($setting_name = 'wp-redirect-to-htaccess', $type='free'), 'msg' => __('WordPress 301 redirect enabled. We recommend to enable a 301 .htaccess redirect.', 'really-simple-ssl'), 'icon' => 'open', 'plusone' => RSSSL()->rsssl_server->uses_htaccess(), 'dismissible' => true, ), 'no-redirect-set' => array( 'msg' => __('Enable a .htaccess redirect or WordPress redirect in the settings to create a 301 redirect.', 'really-simple-ssl') , 'icon' => 'open', 'dismissible' => false ), 'htaccess-not-writeable' => array( 'url' => 'https://really-simple-ssl.com/knowledge-base/manually-insert-htaccess-redirect-http-to-https/', 'msg' => sprintf(__('The %s file is not writable. You can either use the WordPress redirect, add the rules manually, or set the file to %swritable%s.', 'really-simple-ssl'), $htaccess_file, '', ''), 'icon' => 'warning', 'dismissible' => true ), 'htaccess-rules-test-failed' => array( 'url' => 'https://really-simple-ssl.com/knowledge-base/manually-insert-htaccess-redirect-http-to-https/', 'msg' => __('The .htaccess redirect rules selected by this plugin failed in the test. Set manually or dismiss to leave on WordPress redirect.', 'really-simple-ssl') . $rules, 'icon' => 'warning', 'dismissible' => true, 'plusone'=>true, ), ), ), 'elementor' => array( 'condition' => array( 'rsssl_ssl_activation_time_no_longer_then_3_days_ago'), 'callback' => 'rsssl_uses_elementor', 'score' => 5, 'output' => array( 'true' => array( 'url' => 'https://really-simple-ssl.com/knowledge-base/how-to-fix-mixed-content-in-elementor-after-moving-to-ssl/', 'msg' => __("Your site uses Elementor. This can require some additional steps before getting the secure lock.", "really-simple-ssl"), 'icon' => 'open', 'dismissible' => true ), ), ), 'divi' => array( 'condition' => array( 'rsssl_ssl_activation_time_no_longer_then_3_days_ago'), 'callback' => 'rsssl_uses_divi', 'score' => 5, 'output' => array( 'true' => array( 'url' => "https://really-simple-ssl.com/knowledge-base/mixed-content-when-using-divi-theme/", 'msg' => __("Your site uses Divi. This can require some additional steps before getting the secure lock.", "really-simple-ssl"), 'icon' => 'open', 'dismissible' => true ), ), ), 'secure_cookies_set' => array( 'condition' => array( 'rsssl_ssl_enabled', 'RSSSL()->really_simple_ssl->can_apply_networkwide', ), 'callback' => 'RSSSL()->really_simple_ssl->secure_cookie_settings_status', 'score' => 5, 'output' => array( 'set' => array( 'msg' =>__('HttpOnly Secure cookies have been set automatically!', 'really-simple-ssl'), 'icon' => 'success', 'url' => 'https://really-simple-ssl.com/secure-cookies-with-httponly-secure-and-use_only_cookies/', ), 'not-set' => array( 'msg' => __('HttpOnly Secure cookies not set.', 'really-simple-ssl'), 'icon' => 'warning', 'dismissible' => true, 'plusone' => true, 'url' => 'https://really-simple-ssl.com/secure-cookies-with-httponly-secure-and-use_only_cookies/', ), 'wpconfig-not-writable' => array( 'msg' => __("To set the httponly secure cookie settings, your wp-config.php has to be edited, but the file is not writable.","really-simple-ssl").' '.__("Add the following lines of code to your wp-config.php.","really-simple-ssl") . "

//Begin Really Simple SSL session cookie settings
  @ini_set('session.cookie_httponly', true);
  @ini_set('session.cookie_secure', true);
  @ini_set('session.use_only_cookies', true);
//END Really Simple SSL cookie settings

".__("Or set your wp-config.php to writable and reload this page.", "really-simple-ssl"), 'icon' => 'warning', 'dismissible' => true, 'plusone' => true, 'url' => 'https://really-simple-ssl.com/secure-cookies-with-httponly-secure-and-use_only_cookies/', ) ), ), 'recommended_security_headers_not_set' => array( 'callback' => 'RSSSL()->really_simple_ssl->recommended_headers_enabled', 'condition' => array('rsssl_ssl_enabled'), 'score' => 5, 'output' => array( 'false' => array( 'msg' => __("The following recommended security headers are not detected:", "really-simple-ssl") ."
". implode('
', $this->get_recommended_security_headers() ) . "
", 'url' => 'https://really-simple-ssl.com/everything-you-need-to-know-about-security-headers', 'icon' => 'premium', 'dismissible' => false, ), 'true' => array( 'msg' => __("Recommended security headers enabled.", "really-simple-ssl"), 'icon' => 'success', ), ), ), 'pro_upsell' => array( 'callback' => '_true_', 'score' => 5, 'output' => array( 'true' => array( 'msg' => __("Improve security with Really Simple SSL Pro.", "really-simple-ssl"), 'url' => 'https://really-simple-ssl.com/pro', 'icon' => 'premium', 'dismissible' => false, ), ), ), 'uses_wp_engine' => array( 'condition' => array('rsssl_uses_wp_engine'), 'callback' => '_true_', 'score' => 5, 'output' => array( 'true' => array( 'msg' =>__('Due to a recent update by WP Engine, we have changed your settings automatically to adapt.', 'really-simple-ssl'), 'url' => 'https://really-simple-ssl.com/really-simple-ssl-adapts-to-recent-wp-engine-changes/', 'icon' => 'open', 'dismissible' => true ), ), ), 'beta_5_addon_active' => array( 'condition' => array('rsssl_beta_5_addon_active'), 'callback' => '_true_', 'score' => 5, 'output' => array( 'true' => array( 'msg' =>__('You have the Really Simple SSL Let\'s Encrypt beta add-on activated. This functionality has now been integrated in core, so you can deactivate the add-on.', 'really-simple-ssl'), 'icon' => 'open', 'dismissible' => true ), ), ), 'duplicate-ssl-plugins' => array( 'condition' => array('rsssl_detected_duplicate_ssl_plugin'), 'callback' => '_true_', 'plus_one' => true, 'output' => array( 'true' => array( 'msg' => sprintf(__( 'We have detected the %s plugin on your website.', 'really-simple-ssl' ),rsssl_detected_duplicate_ssl_plugin(true)).' '.__( 'As Really Simple SSL handles all the functionality this plugin provides, we recommend to disable this plugin to prevent unexpected behaviour.', 'really-simple-ssl' ), 'icon' => 'warning', 'dismissible' => true, 'plusone' => true, ), ), ), 'bf_notice' => array( 'condition' => array( 'RSSSL()->really_simple_ssl->is_bf' ), 'callback' => '_true_', 'plus_one' => true, 'output' => array( 'true' => array( 'msg' => __( "Black Friday sale! Get 40% Off Really Simple SSL Pro", 'really-simple-ssl' ) , 'icon' => 'premium', 'url' => 'https://really-simple-ssl.com/pro/', 'dismissible' => true, 'plusone' => true, ), ), ), ); //on multisite, don't show the notice on subsites. if ( is_multisite() && !is_network_admin() ) { unset($notices['secure_cookies_set']); } $notices = apply_filters('rsssl_notices', $notices); foreach ($notices as $id => $notice) { $notices[$id] = wp_parse_args($notice, $notice_defaults); } /** * If a list of notices that should be dismissed on upgrade is requested */ if ( $args['dismiss_on_upgrade'] ) { $output = array(); foreach( $notices as $key => $notice ) { if ( isset($notice['dismiss_on_upgrade']) && $notice['dismiss_on_upgrade'] ) { $output[] = $key; } } return $output; } /** * Filter out notice that do not apply, or are dismissed */ foreach ( $notices as $id => $notice ) { if (get_option( "rsssl_" . $id . "_dismissed" )) { unset($notices[$id]); continue; } $func = $notice['callback']; $output = $this->validate_function($func); //check if all notices should be dismissed if ( ( isset( $notice['output'][$output]['dismissible'] ) && $notice['output'][$output]['dismissible'] && ( $this->dismiss_all_notices || is_multisite() && rsssl_multisite::this()->dismiss_all_notices ) ) ) { unset($notices[$id]); continue; } if ( !isset($notice['output'][ $output ]) ) { unset($notices[$id]); continue; } else { $notices[$id]['output'] = $notice['output'][ $output ]; } $notices[$id]['output']['status'] = ( $notices[$id]['output']['icon'] !== 'success') ? 'open' : 'completed'; if ( $args['status'] === 'open' && ($notices[$id]['output']['status'] === 'completed' ) ){ unset($notices[$id]); continue; } $condition_functions = $notice['condition']; foreach ( $condition_functions as $func ) { $condition = $this->validate_function($func, true); if ( ! $condition ) { unset($notices[$id]); } } } //if only admin_notices are required, filter out the rest. if ( $args['admin_notices'] ) { foreach ( $notices as $id => $notice ) { if (!isset($notice['output']['admin_notice']) || !$notice['output']['admin_notice']){ unset( $notices[$id]); } } set_transient('rsssl_admin_notices', $notices, DAY_IN_SECONDS ); } //sort so warnings are on top $warnings = array(); $open = array(); $other = array(); foreach ($notices as $key => $notice){ if (!isset($notice['output']['icon'])) continue; if ($notice['output']['icon']==='warning') { $warnings[$key] = $notice; } else if ($notice['output']['icon']==='open') { $open[$key] = $notice; } else { $other[$key] = $notice; } } $notices = $warnings + $open + $other; //add plus ones, but not when in admin notice if ( !$args['admin_notices'] ) { foreach ( $notices as $key => $notice ) { if ( isset( $notice['output']['url'] ) ) { $url = $notice['output']['url']; $target = ''; if ( strpos( $url, 'https://really-simple-ssl.com' ) !== false ) { $info = __( '%sMore info%s', 'really-simple-ssl' ); $target = 'target="_blank"'; } else { $info = __( '%sEnable%s', 'really-simple-ssl' ); } $notices[ $key ]['output']['msg'] .= ' ' . sprintf( $info, '', '' ); } if ( isset( $notice['output']['plusone'] ) && $notice['output']['plusone'] ) { $plusone = "1"; $notices[ $key ]['output']['msg'] .= $plusone; } } } //if we only want a list of premium notices if ( $args['premium_only'] ) { foreach ($notices as $key => $notice){ if ( !isset($notice['output']['icon']) || $notice['output']['icon'] !== 'premium' ) { unset($notices[$key]); } } } return $notices; } /** * Count number of premium notices we have in the list. * @return int */ public function get_lowest_possible_task_count(){ $premium_notices = $this->get_notices_list(array('premium_only'=>true)); return count($premium_notices) ; } /** * Get output of function, in format 'function', or 'class()->sub()->function' * @param string $func * @param bool $is_condition // if the check is a condition, which should return a boolean * @return string|bool */ private function validate_function($func, $is_condition = false ){ $invert = false; if (strpos($func, 'NOT ') !== FALSE ) { $func = str_replace('NOT ', '', $func); $invert = true; } if ( $func === '_true_') { $output = true; } else if ( $func === '_false_' ) { $output = false; } else { if ( preg_match( '/(.*)\(\)\-\>(.*)->(.*)/i', $func, $matches)) { $base = $matches[1]; $class = $matches[2]; $function = $matches[3]; $output = call_user_func( array( $base()->{$class}, $function ) ); } else { $output = $func(); } if ( $invert ) { $output = !$output; } } //stringyfy booleans if (!$is_condition) { if ( $output === false || $output === 0 ) { $output = 'false'; } if ( $output === true || $output === 1 ) { $output = 'true'; } } return sanitize_text_field($output); } /** * Calculate the percentage completed in the dashboard progress section * Determine max score by adding $notice['score'] to the $max_score variable * Determine actual score by adding $notice['score'] of each item with a 'success' output to $actual_score * @return int * * @since 4.0 * */ public function get_score_percentage() { if ( ! rsssl_user_can_manage() ) { return 0; } $max_score = 0; $actual_score = 0; $notices = $this->get_notices_list(array( 'status' => 'all', )); foreach ( $notices as $id => $notice ) { if (isset( $notice['score'] )) { // Only items matching condition will show in the dashboard. Only use these to determine max count. $max_score = $max_score + intval( $notice['score'] ); $success = ( isset( $notice['output']['icon'] ) && ( $notice['output']['icon'] === 'success' ) ) ? true : false; if ( $success ) { // If the output is success, task is completed. Add to actual count. $actual_score = $actual_score + intval( $notice['score'] ); } } } if ($max_score>0) { $score = $actual_score / $max_score; } else { $score = 0; } $score = $score * 100; $score = intval( round( $score ) ); return $score; } /** * Generate an enable link for the specific setting, redirects to settings page and highlights the setting. * * @param string $setting_name * @param string $type * * @return string */ public function generate_enable_link($setting_name, $type = 'free' ) { if ( is_network_admin() ) { $page = "really-simple-ssl"; $wp_page = network_admin_url('settings.php' ); } else { $page = "rlrsssl_really_simple_ssl"; $wp_page = admin_url('options-general.php'); } $args = array( "page" => $page, "highlight" => $setting_name ); if ( $type === 'premium' && !is_network_admin() ) { $args['tab'] = 'premium'; } return add_query_arg($args, $wp_page); } /** * @param $id * @param $notice * * Generate a notice row in the configuration dashboard tab * * @since 3.2 * */ private function notice_row($id, $notice){ if (!rsssl_user_can_manage()) return; if (!isset($notice['output'])) { return; } $msg = $notice['output']['msg']; $icon_type = $notice['output']['icon']; // Do not show completed tasks if remaining tasks are selected. if ($icon_type === 'success' && !get_option('rsssl_all_tasks') && get_option('rsssl_remaining_tasks')) return; $icon = $this->icon($icon_type); $dismiss = (isset($notice['output']['dismissible']) && $notice['output']['dismissible']) ? $this->rsssl_dismiss_button() : ''; ?> is_settings_page() ? false : true; $count = get_transient( 'rsssl_plusone_count' ); if ( !$cache || ($count === false) ) { $count = 0; $notices = $this->get_notices_list(); foreach ( $notices as $id => $notice ) { $success = ( isset( $notice['output']['icon'] ) && ( $notice['output']['icon'] === 'success' ) ) ? true : false; if ( ! $success && isset( $notice['output']['plusone'] ) && $notice['output']['plusone'] ) { $count++; } } set_transient( 'rsssl_plusone_count', $count, WEEK_IN_SECONDS ); } return $count; } /** * Build the settings page * * @since 2.0 * * @access public * */ public function general_grid(){ $grid_items = array( 'progress' =>array( 'title' => __("Your progress", "really-simple-ssl"), 'header' => rsssl_template_path . 'progress-header.php', 'content' => rsssl_template_path . 'progress.php', 'footer' => rsssl_template_path . 'progress-footer.php', 'class' => 'regular rsssl-progress', 'type' => 'all', ), 'settings' => array( 'title' => __("Settings", "really-simple-ssl"), 'content' => rsssl_template_path . 'settings.php', 'footer' => rsssl_template_path . 'settings-footer.php', 'class' => 'small settings', 'type' => 'settings', ), 'tipstricks' => array( 'title' => __("Tips & Tricks", "really-simple-ssl"), 'header' => '', 'content' => rsssl_template_path . 'tips-tricks.php', 'footer' => rsssl_template_path . 'tips-tricks-footer.php', 'class' => 'small', 'type' => 'popular', ), 'plugins' => array( 'title' => __("Our plugins", "really-simple-ssl"), 'header' => rsssl_template_path . 'our-plugins-header.php', 'content' => rsssl_template_path . 'other-plugins.php', 'class' => 'half-height no-border no-background upsell-grid-container', 'can_hide' => false, ), 'support' => array( 'title' => __("Support forum", "really-simple-ssl"), 'header' => '', 'content' => rsssl_template_path . 'support.php', 'footer' => rsssl_template_path . 'support-footer.php', 'type' => 'tasks', 'class' => 'half-height', ), ); return apply_filters( 'rsssl_grid_items', $grid_items ); } /** * Save the task toggle option * @since 4.0 */ public function update_task_toggle_option() { if (!isset($_POST['token']) || (!wp_verify_nonce($_POST['token'], 'rsssl_nonce'))) { return; } if (!isset($_POST["action"]) && $_POST["action"] ==! 'rsssl_update_task_toggle_option') return; if (!isset($_POST['alltasks']) || (!isset($_POST['remainingtasks']) ) ) return; if ($_POST['alltasks'] === 'checked') { update_option('rsssl_all_tasks', true); } else { update_option('rsssl_all_tasks', false); } if ($_POST['remainingtasks'] === 'checked') { update_option('rsssl_remaining_tasks', true); } else { update_option('rsssl_remaining_tasks', false); } wp_die(); } /** * Get count of all tasks * @return int */ public function get_all_task_count() { if ( ! rsssl_user_can_manage() ) { return 0; } $count = count($this->get_notices_list( array( 'status' => 'all' ) )); return $count; } /** * @return int * * Get the remaining open task count, shown in the progress header * */ public function get_remaining_tasks_count() { if ( ! rsssl_user_can_manage() ) { return 0; } $cache = !$this->is_settings_page(); $count = get_transient( 'rsssl_remaining_task_count' ); if ( !$cache || $count === false ) { $count = count($this->get_notices_list( array( 'status' => 'open' ) ) ); set_transient( 'rsssl_remaining_task_count', $count, DAY_IN_SECONDS ); } return $count; } /** * Get status link for plugin, depending on installed, or premium availability * @param $item * * @return string */ public function get_status_link($item){ if (!defined($item['constant_free']) && !defined($item['constant_premium'])) { $args = array( "s" => $item['search'], "tab" => "search", "type" => "term" ); $admin_url= is_multisite() ? network_admin_url('plugin-install.php') : admin_url('plugin-install.php'); $link = add_query_arg( $args, $admin_url ); $status = ''.__('Install', 'really-simple-ssl').''; } elseif (isset($item['constant_premium']) && !defined($item['constant_premium'])) { $link = $item['website']; $status = ''.__('Upgrade to pro', 'really-simple-ssl').''; } else { $status = __( "Installed", "really-simple-ssl" ); } return $status; } /** * Render the settings page */ public function settings_page() { if (!rsssl_user_can_manage()) return; $tab = isset( $_GET['tab']) ? sanitize_title($_GET['tab']) : 'configuration'; $this->admin_tabs($tab ); $high_contrast = $this->high_contrast ? 'rsssl-high-contrast' : ''; ?>
render_grid($this->general_grid()); do_action("rsssl_configuration_page"); break; } do_action("show_tab_{$tab}"); do_action("rsssl_show_tab_{$tab}"); ?>
get_template('grid-container.php', rsssl_path . 'grid/'); $element = $this->get_template('grid-element.php', rsssl_path . 'grid/'); $output = ''; $defaults = array( 'title' => '', 'header' => rsssl_template_path . 'header.php', 'content' => '', 'footer' => '', 'class' => '', 'type' => 'plugins', 'can_hide' => true, 'instructions' => false, ); foreach ($grid as $index => $grid_item) { $grid_item = wp_parse_args($grid_item, $defaults); $footer = $this->get_template_part($grid_item, 'footer', $index); $content = $this->get_template_part($grid_item, 'content', $index); $header = $this->get_template_part($grid_item, 'header', $index); $instructions = $grid_item['instructions'] ? ''.__("Instructions manual", "really-simple-ssl").'' : ''; // Add form if type is settings $form_open = ''; $form_close = ''; if ( $grid_item['type'] === 'scan' ) { $form_open = '
'; $form_close = '
'; } elseif ( $grid_item['type'] === 'settings' ) { if ( is_network_admin() ) { $form_open = '
'.wp_nonce_field('rsssl_ms_settings_update', 'rsssl_ms_nonce'); $form_close = '
'; } else { $form_open = '
'; $form_close = '
'; } } $block = str_replace(array('{class}', '{title}', '{header}', '{content}', '{footer}', '{instructions}', '{form_open}','{form_close}'), array($grid_item['class'], $grid_item['title'], $header, $content, $footer, $instructions, $form_open, $form_close), $element); $output .= $block; } echo str_replace('{content}', $output, $container); } /** * Render grid item based on template * @param array $grid_item * @param string $key * @oaram string $index * * @return string */ public function get_template_part($grid_item, $key, $index) { if ( !isset($grid_item[$key]) || !$grid_item[$key] ) { $template_part = ''; } else { if ( strpos( $grid_item[ $key ], '.php' ) !== false && file_exists($grid_item[ $key ]) ) { ob_start(); require $grid_item[ $key ]; $template_part = ob_get_clean(); } else { $template_part = ''; } } return apply_filters("rsssl_template_part_".$key.'_'.$index, $template_part, $grid_item); } /** * Returns a success, error or warning image for the settings page * * @since 2.0 * * @access public * * @param string $type the type of image * * @return string */ public function icon($type) { if ($type == 'success') { return "".__("Completed", "really-simple-ssl").""; } elseif ($type == "warning") { return "".__("Warning", "really-simple-ssl").""; } elseif ($type == "open") { return "".__("Open", "really-simple-ssl").""; } elseif ($type == "premium") { return "".__("Premium", "really-simple-ssl").""; } } /** * * Add a dismiss button which will dismiss the nearest . Used on 'Configuration' dashboard page * * @since 3.1.6 * @return string * */ public function rsssl_dismiss_button() { $html = "