PageRenderTime 46ms CodeModel.GetById 23ms app.highlight 10ms RepoModel.GetById 2ms app.codeStats 0ms

/wp-content/plugins/really-simple-ssl/class-admin.php

https://bitbucket.org/carloskikea/helpet
PHP | 2582 lines | 1602 code | 427 blank | 553 comment | 387 complexity | 6e7a5d1bfff3eb272f501b92aecef16c MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2defined('ABSPATH') or die("you do not have access to this page!");
   3
   4  class rsssl_admin extends rsssl_front_end {
   5
   6  private static $_this;
   7
   8  public $wpconfig_siteurl_not_fixed          = FALSE;
   9  public $no_server_variable                  = FALSE;
  10  public $errors                              = Array();
  11
  12  public $do_wpconfig_loadbalancer_fix        = FALSE;
  13  public $site_has_ssl                        = FALSE;
  14  public $ssl_enabled                         = FALSE;
  15
  16  //multisite variables
  17  public $sites                             = Array(); //for multisite, list of all activated sites.
  18
  19  //general settings
  20  public $capability                        = 'activate_plugins';
  21
  22  public $ssl_test_page_error;
  23  public $htaccess_test_success             = FALSE;
  24  public $plugin_version                    = rsssl_version; //deprecated, but used in pro plugin until 1.0.25
  25
  26  public $plugin_dir                        = "really-simple-ssl";
  27  public $plugin_filename                   = "rlrsssl-really-simple-ssl.php";
  28  public $ABSpath;
  29
  30  public $do_not_edit_htaccess              = FALSE;
  31  public $htaccess_redirect                 = FALSE;
  32  public $htaccess_warning_shown            = FALSE;
  33  public $ssl_success_message_shown         = FALSE;
  34  public $hsts                              = FALSE;
  35  public $debug							                = TRUE;
  36  public $debug_log;
  37
  38  public $plugin_conflict                   = ARRAY();
  39  public $plugin_db_version;
  40  public $plugin_upgraded;
  41  public $mixed_content_fixer_status        = "OK";
  42  public $ssl_type                          = "NA";
  43
  44  private $pro_url           = "https://www.really-simple-ssl.com/pro";
  45
  46  function __construct() {
  47    if ( isset( self::$_this ) )
  48        wp_die( sprintf( __( '%s is a singleton class and you cannot create a second instance.','really-simple-ssl' ), get_class( $this ) ) );
  49
  50    self::$_this = $this;
  51
  52    $this->ABSpath = $this->getABSPATH();
  53    $this->get_options();
  54    $this->get_admin_options();
  55
  56    $this->get_plugin_upgraded(); //call always, otherwise db version will not match anymore.
  57
  58    register_deactivation_hook(dirname( __FILE__ )."/".$this->plugin_filename, array($this,'deactivate') );
  59
  60
  61  }
  62
  63  static function this() {
  64    return self::$_this;
  65  }
  66
  67
  68  /**
  69   * Initializes the admin class
  70   *
  71   * @since  2.2
  72   *
  73   * @access public
  74   *
  75   */
  76
  77  public function init() {
  78    if (!current_user_can($this->capability)) return;
  79    $is_on_settings_page = $this->is_settings_page();
  80
  81    /*
  82      Detect configuration when:
  83      - SSL activation just confirmed.
  84      - on settings page
  85      - No SSL detected
  86    */
  87
  88    //when configuration should run again
  89    if ($this->clicked_activate_ssl() || !$this->ssl_enabled || !$this->site_has_ssl || $is_on_settings_page || is_network_admin()) {
  90
  91      if (is_multisite()) $this->build_domain_list();//has to come after clicked_activate_ssl, otherwise this domain won't get counted.
  92      $this->detect_configuration();
  93
  94      //flush caches when just activated ssl
  95      //flush the permalinks
  96      if ($this->clicked_activate_ssl()) {
  97        if (isset($_POST["rsssl_flush_rewrite_rules"])) {
  98          add_action( 'shutdown', 'flush_rewrite_rules');
  99        }
 100        add_action('admin_init', array(RSSSL()->rsssl_cache,'flush'),40);
 101      }
 102
 103      if (!$this->wpconfig_ok()) {
 104        //if we were to activate ssl, this could result in a redirect loop. So warn first.
 105        add_action("admin_notices", array($this, 'show_notice_wpconfig_needs_fixes'));
 106        if (is_multisite()) add_action('network_admin_notices', array($this, 'show_notice_wpconfig_needs_fixes'), 10);
 107
 108        $this->ssl_enabled = false;
 109        $this->save_options();
 110      } elseif ($this->ssl_enabled) {
 111        add_action('init',array($this,'configure_ssl'),20);
 112      }
 113    }
 114
 115    //when SSL is enabled, and not enabled by user, ask for activation.
 116    add_action("admin_notices", array($this, 'show_notice_activate_ssl'),10);
 117
 118    add_action('plugins_loaded', array($this,'check_plugin_conflicts'),30);
 119
 120    //add the settings page for the plugin
 121    add_action('admin_enqueue_scripts', array($this, 'enqueue_assets'));
 122    add_action('admin_init', array($this, 'load_translation'),20);
 123    add_action('rsssl_configuration_page', array($this, 'configuration_page_more'),10);
 124
 125    //settings page, form  and settings link in the plugins page
 126    add_action('admin_menu', array($this, 'add_settings_page'),40);
 127    add_action('admin_init', array($this, 'create_form'),40);
 128
 129    $plugin = rsssl_plugin;
 130    add_filter("plugin_action_links_$plugin", array($this,'plugin_settings_link'));
 131
 132    //check if the uninstallfile is safely renamed to php.
 133    $this->check_for_uninstall_file();
 134
 135    //callbacks for the ajax dismiss buttons
 136    add_action('wp_ajax_dismiss_htaccess_warning', array($this,'dismiss_htaccess_warning_callback') );
 137    add_action('wp_ajax_dismiss_success_message', array($this,'dismiss_success_message_callback') );
 138
 139    //handle notices
 140    add_action('admin_notices', array($this,'show_notices'));
 141  }
 142
 143
 144  //change deprecated function depending on version.
 145
 146  public function get_sites_bw_compatible(){
 147    global $wp_version;
 148    $sites = ($wp_version >= 4.6 ) ? get_sites() : wp_get_sites();
 149    return $sites;
 150  }
 151
 152  /*
 153        The new get_sites function returns an object.
 154
 155  */
 156
 157  public function switch_to_blog_bw_compatible($site){
 158
 159    global $wp_version;
 160    if ($wp_version >= 4.6 ) {
 161      switch_to_blog( $site->blog_id );
 162    } else {
 163      switch_to_blog( $site[ 'blog_id' ] );
 164    }
 165  }
 166
 167
 168  /*
 169    checks if the user just clicked the "activate SSL" button.
 170  */
 171
 172  private function clicked_activate_ssl() {
 173    if (!current_user_can($this->capability)) return;
 174    //if (!isset( $_POST['rsssl_nonce'] ) || !wp_verify_nonce( $_POST['rsssl_nonce'], 'rsssl_nonce' )) return false;
 175
 176    if (isset($_POST['rsssl_do_activate_ssl'])) {
 177      $this->activate_ssl();
 178      return true;
 179    }
 180
 181    return false;
 182  }
 183
 184
 185  /*
 186        Activate the SSL for this site
 187  */
 188
 189  public function activate_ssl(){
 190    $this->ssl_enabled = true;
 191    $this->wp_redirect = true;
 192
 193    $this->set_siteurl_to_ssl();
 194    $this->save_options();
 195  }
 196
 197  public function deactivate_ssl(){
 198    $this->ssl_enabled = false;
 199    $this->wp_redirect = false;
 200    $this->htaccess_redirect = false;
 201
 202    $this->remove_ssl_from_siteurl();
 203    $this->save_options();
 204  }
 205
 206
 207
 208  public function wpconfig_ok(){
 209    if (($this->do_wpconfig_loadbalancer_fix || $this->no_server_variable || $this->wpconfig_siteurl_not_fixed) && !$this->wpconfig_is_writable() ) {
 210      $result = false;
 211    } else {
 212      $result = true;
 213    }
 214
 215    return apply_filters('rsssl_wpconfig_ok_check', $result);
 216  }
 217
 218  /*
 219      This message is shown when no SSL is not enabled by the user yet
 220  */
 221
 222  public function show_notice_activate_ssl(){
 223    if ($this->ssl_enabled) return;
 224
 225    if (defined("RSSSL_DISMISS_ACTIVATE_SSL_NOTICE") && RSSSL_DISMISS_ACTIVATE_SSL_NOTICE) return;
 226
 227    //for multisite, show only activate when a choice has been made to activate networkwide or per site.
 228    if (is_multisite() && !RSSSL()->rsssl_multisite->selected_networkwide_or_per_site) return;
 229
 230    //on multistie, only show this message on the network admin. Per site activated sites have to go to the settings page.
 231    //otherwise sites that do not need SSL possibly get to see this message.
 232
 233    if (is_multisite() && !is_network_admin()) return;
 234
 235    if (!$this->wpconfig_ok()) return;
 236
 237    if (!current_user_can($this->capability)) return;
 238
 239    if (!$this->site_has_ssl) {
 240
 241      global $wp;
 242      $current_url = "https://".$_SERVER["HTTP_HOST"].$_SERVER["REQUEST_URI"];
 243      ?>
 244      <div id="message" class="error fade notice activate-ssl">
 245      <p><?php _e("No SSL was detected. If you do have an SSL certificate, try to reload this page over https by clicking this link:","really-simple-ssl");?>&nbsp;<a href="<?php echo $current_url?>"><?php _e("reload over https.","really-simple-ssl");?></a>
 246        <?php _e("You can check your certificate on","really-simple-ssl");?>&nbsp;<a target="_blank" href="https://www.ssllabs.com/ssltest/">Qualys SSL Labs</a>
 247      </p>
 248    </div>
 249    <?php } ?>
 250
 251    <div id="message" class="updated fade notice activate-ssl">
 252      <?php if ($this->site_has_ssl) {  ?>
 253      <h1><?php _e("Almost ready to migrate to SSL!","really-simple-ssl");?></h1>
 254      <?php } ?>
 255      <?php _e("Some things can't be done automatically. Before you migrate, please check for: ",'really-simple-ssl');?>
 256      <p>
 257        <ul>
 258          <li><?php _e('Http references in your .css and .js files: change any http:// into //','really-simple-ssl');?></li>
 259          <li><?php _e('Images, stylesheets or scripts from a domain without an SSL certificate: remove them or move to your own server.','really-simple-ssl');?></li><?php
 260
 261  $backup_link = "https://really-simple-ssl.com/knowledge-base/backing-up-your-site/";
 262  $link_open = '<a target="_blank" href="'.$backup_link.'">';
 263  $link_close = '</a>';
 264
 265            ?> <li> <?php printf(__("It is recommended to take a %sbackup%s of your site before activating SSL", 'really-simple-ssl'), $link_open, $link_close); ?> </li>
 266        </ul>
 267      </p>
 268      <?php $this->show_pro(); ?>
 269
 270      <?php RSSSL()->really_simple_ssl->show_enable_ssl_button();?>
 271    </div>
 272  <?php }
 273
 274
 275  /**
 276    * @since 2.3
 277    * Returns button to enable SSL.
 278  */
 279
 280  public function show_enable_ssl_button(){
 281    if ($this->site_has_ssl || (defined('rsssl_force_activate') && rsssl_force_activate)) {
 282    ?>
 283    <p>
 284    <form action="" method="post">
 285      <?php wp_nonce_field( 'rsssl_nonce', 'rsssl_nonce' );?>
 286      <div>
 287        <input type="checkbox" name="rsssl_flush_rewrite_rules" checked><label><?php _e("Flush rewrite rules on activation (deselect when you encounter errors)","really-simple-ssl")?></label>
 288      </div>
 289      <input type="submit" class='button button-primary' value="<?php _e("Go ahead, activate SSL!","really-simple-ssl");?>" id="rsssl_do_activate_ssl" name="rsssl_do_activate_ssl">
 290      <br><?php _e("You may need to login in again.", "really-simple-ssl")?>
 291    </form>
 292  </p>
 293    <?php
 294    }
 295  }
 296
 297  /**
 298    * @since 2.3
 299    * Shows option to buy pro
 300
 301  */
 302
 303  public function show_pro(){
 304    if ( !defined("rsssl_pro_version") ) {
 305    ?>
 306    <p><?php _e('You can also let the automatic scan of the pro version handle this for you, and get premium support, increased security with HSTS and more!','really-simple-ssl');?>&nbsp;<a target="_blank" href="<?php echo $this->pro_url;?>"><?php _e("Check out Really Simple SSL Premium","really-simple-ssl");?></a></p>
 307    <?php
 308  }
 309}
 310
 311
 312  public function wpconfig_is_writable() {
 313    $wpconfig_path = $this->find_wp_config_path();
 314    if (is_writable($wpconfig_path))
 315      return true;
 316    else
 317      return false;
 318  }
 319
 320  /*
 321  *     Check if the uninstall file is renamed to .php
 322  */
 323
 324  protected function check_for_uninstall_file() {
 325    if (file_exists(dirname( __FILE__ ) .  '/force-deactivate.php')) {
 326      $this->errors["DEACTIVATE_FILE_NOT_RENAMED"] = true;
 327    }
 328  }
 329
 330  /**
 331   * Get the options for this plugin
 332   *
 333   * @since  2.0
 334   *
 335   * @access public
 336   *
 337   */
 338
 339  public function get_admin_options(){
 340
 341    $options = get_option('rlrsssl_options');
 342    if (isset($options)) {
 343      $this->site_has_ssl                     = isset($options['site_has_ssl']) ? $options['site_has_ssl'] : FALSE;
 344      $this->hsts                             = isset($options['hsts']) ? $options['hsts'] : FALSE;
 345      $this->htaccess_warning_shown           = isset($options['htaccess_warning_shown']) ? $options['htaccess_warning_shown'] : FALSE;
 346      $this->ssl_success_message_shown        = isset($options['ssl_success_message_shown']) ? $options['ssl_success_message_shown'] : FALSE;
 347      $this->plugin_db_version                = isset($options['plugin_db_version']) ? $options['plugin_db_version'] : "1.0";
 348      $this->debug                            = isset($options['debug']) ? $options['debug'] : FALSE;
 349      $this->do_not_edit_htaccess             = isset($options['do_not_edit_htaccess']) ? $options['do_not_edit_htaccess'] : FALSE;
 350      $this->htaccess_redirect                = isset($options['htaccess_redirect']) ? $options['htaccess_redirect'] : FALSE;
 351      $this->switch_mixed_content_fixer_hook  = isset($options['switch_mixed_content_fixer_hook']) ? $options['switch_mixed_content_fixer_hook'] : FALSE;
 352      $this->debug_log                        = isset($options['debug_log']) ? $options['debug_log'] : $this->debug_log;
 353    }
 354
 355    if  (is_multisite()) {
 356      $network_options = get_site_option('rlrsssl_network_options');
 357      $network_htaccess_redirect  = isset($network_options["htaccess_redirect"]) ? $network_options["htaccess_redirect"] : false;
 358      $network_do_not_edit_htaccess  = isset($network_options["do_not_edit_htaccess"]) ? $network_options["do_not_edit_htaccess"] : false;
 359      /*
 360          If multiste, and networkwide, only the networkwide setting counts.
 361          if multisite, and per site, only the networkwide setting counts if it is true.
 362      */
 363      $ssl_enabled_networkwide = isset($network_options["ssl_enabled_networkwide"]) ? $network_options["ssl_enabled_networkwide"] : false;
 364      if ($ssl_enabled_networkwide) {
 365        $this->htaccess_redirect  = $network_htaccess_redirect;
 366        $this->do_not_edit_htaccess  = $network_do_not_edit_htaccess;
 367      } else {
 368        if ($network_do_not_edit_htaccess) $this->do_not_edit_htaccess  = $network_do_not_edit_htaccess;
 369        if ($network_htaccess_redirect) $this->htaccess_redirect  = $network_htaccess_redirect;
 370      }
 371    }
 372
 373    //if the define is true, it overrides the db setting.
 374    if (defined( 'RLRSSSL_DO_NOT_EDIT_HTACCESS')) {
 375      $this->do_not_edit_htaccess = RLRSSSL_DO_NOT_EDIT_HTACCESS;
 376    }
 377
 378  }
 379
 380  /**
 381   * Creates an array of all domains where the plugin is active AND SSL is active, only used for multisite.
 382   *
 383   * @since  2.1
 384   *
 385   * @access public
 386   *
 387   */
 388
 389  public function build_domain_list() {
 390    if (!is_multisite()) return;
 391    //create list of all activated sites with SSL
 392    $this->sites = array();
 393    $sites = $this->get_sites_bw_compatible();
 394    if ($this->debug) $this->trace_log("building domain list for multisite...");
 395    foreach ( $sites as $site ) {
 396        $this->switch_to_blog_bw_compatible($site);
 397        $options = get_option('rlrsssl_options');
 398
 399        $ssl_enabled = FALSE;
 400        if (isset($options)) {
 401          $site_has_ssl = isset($options['site_has_ssl']) ? $options['site_has_ssl'] : FALSE;
 402          $ssl_enabled = isset($options['ssl_enabled']) ? $options['ssl_enabled'] : $site_has_ssl;
 403        }
 404
 405        if (is_plugin_active(rsssl_plugin) && $ssl_enabled) {
 406          if ($this->debug) $this->trace_log("adding: ".home_url());
 407          $this->sites[] = home_url();
 408        }
 409        restore_current_blog(); //switches back to previous blog, not current, so we have to do it each loop
 410      }
 411
 412      $this->save_options();
 413  }
 414
 415  /**
 416   * check if the plugin was upgraded to a new version
 417   *
 418   * @since  2.1
 419   *
 420   * @access public
 421   *
 422   */
 423
 424  public function get_plugin_upgraded() {
 425  	if ($this->plugin_db_version!= rsssl_version) {
 426  		$this->plugin_db_version = rsssl_version;
 427  		$this->plugin_upgraded = true;
 428      $this->save_options();
 429  	}
 430    $this->plugin_upgraded = false;
 431  }
 432
 433  /**
 434   * Log events during plugin execution
 435   *
 436   * @since  2.1
 437   *
 438   * @access public
 439   *
 440   */
 441
 442  public function trace_log($msg) {
 443    if (!$this->debug) return;
 444    $this->debug_log = $this->debug_log."<br>".$msg;
 445    $this->debug_log = strstr($this->debug_log,'** Detecting configuration **');
 446    error_log($msg);
 447  }
 448
 449  /**
 450   * Configures the site for SSL
 451   *
 452   * @since  2.2
 453   *
 454   * @access public
 455   *
 456   */
 457
 458  public function configure_ssl() {
 459    if (!current_user_can($this->capability)) return;
 460
 461      $safe_mode = FALSE;
 462      if (defined('RSSSL_SAFE_MODE') && RSSSL_SAFE_MODE) $safe_mode = RSSSL_SAFE_MODE;
 463
 464      if (!current_user_can($this->capability)) return;
 465      $this->trace_log("** Configuring SSL **");
 466      if ($this->site_has_ssl) {
 467        //when one of the used server variables was found, test if the redirect works
 468
 469        if (RSSSL()->rsssl_server->uses_htaccess() && $this->ssl_type != "NA")
 470            $this->test_htaccess_redirect();
 471
 472        //in a configuration reverse proxy without a set server variable https, add code to wpconfig
 473        if ($this->do_wpconfig_loadbalancer_fix){
 474            $this->wpconfig_loadbalancer_fix();
 475        }
 476
 477        if ($this->no_server_variable)
 478            $this->wpconfig_server_variable_fix();
 479
 480        if (!$safe_mode) {
 481          $this->editHtaccess();
 482        }
 483
 484        if (!$safe_mode && $this->clicked_activate_ssl()) {
 485          $this->wp_redirect = TRUE;
 486          $this->save_options();
 487        }
 488
 489        if (!$safe_mode && $this->wpconfig_siteurl_not_fixed)
 490          $this->fix_siteurl_defines_in_wpconfig();
 491
 492        if (!$safe_mode) {
 493          $this->set_siteurl_to_ssl();
 494        }
 495
 496      }
 497  }
 498
 499
 500  /**
 501   * Check to see if we are on the settings page, action hook independent
 502   *
 503   * @since  2.1
 504   *
 505   * @access public
 506   *
 507   */
 508
 509  public function is_settings_page() {
 510    if (!isset($_SERVER['QUERY_STRING'])) return false;
 511
 512    parse_str($_SERVER['QUERY_STRING'], $params);
 513    if (array_key_exists("page", $params) && ($params["page"]=="rlrsssl_really_simple_ssl")) {
 514        return true;
 515    }
 516    return false;
 517  }
 518
 519  /**
 520   * Find the path to wp-config
 521   *
 522   * @since  2.1
 523   *
 524   * @access public
 525   *
 526   */
 527
 528  public function find_wp_config_path() {
 529    //limit nr of iterations to 20
 530    $i=0;
 531    $maxiterations = 20;
 532    $dir = dirname(__FILE__);
 533    do {
 534        $i++;
 535        if( file_exists($dir."/wp-config.php") ) {
 536            return $dir."/wp-config.php";
 537        }
 538    } while( ($dir = realpath("$dir/..")) && ($i<$maxiterations) );
 539    return null;
 540  }
 541
 542  /**
 543   * remove https from defined siteurl and homeurl in the wpconfig, if present
 544   *
 545   * @since  2.1
 546   *
 547   * @access public
 548   *
 549   */
 550
 551  public function remove_ssl_from_siteurl_in_wpconfig() {
 552    if (!current_user_can($this->capability)) return;
 553
 554      $wpconfig_path = $this->find_wp_config_path();
 555      if (!empty($wpconfig_path)) {
 556        $wpconfig = file_get_contents($wpconfig_path);
 557
 558        $homeurl_pos = strpos($wpconfig, "define('WP_HOME','https://");
 559        $siteurl_pos = strpos($wpconfig, "define('WP_SITEURL','https://");
 560
 561        if (($homeurl_pos !== false) || ($siteurl_pos !== false)) {
 562          if (is_writable($wpconfig_path)) {
 563            $search_array = array("define('WP_HOME','https://","define('WP_SITEURL','https://");
 564            $ssl_array = array("define('WP_HOME','http://","define('WP_SITEURL','http://");
 565            //now replace these urls
 566            $wpconfig = str_replace ($search_array , $ssl_array , $wpconfig);
 567            file_put_contents($wpconfig_path, $wpconfig);
 568          } else {
 569            $this->errors['wpconfig not writable'] = TRUE;
 570          }
 571        }
 572
 573      }
 574  }
 575
 576
 577
 578  /**
 579  *
 580  *     Checks if the wp config contains any defined siteurl and homeurl
 581  *
 582  *
 583  */
 584
 585  private function check_for_siteurl_in_wpconfig(){
 586
 587    $wpconfig_path = $this->find_wp_config_path();
 588
 589    if (empty($wpconfig_path)) return;
 590
 591    $wpconfig = file_get_contents($wpconfig_path);
 592    $homeurl_pattern = '/(define\(\s*\'WP_HOME\'\s*,\s*\'http\:\/\/)/';
 593    $siteurl_pattern = '/(define\(\s*\'WP_SITEURL\'\s*,\s*\'http\:\/\/)/';
 594
 595    $this->wpconfig_siteurl_not_fixed = FALSE;
 596    if (preg_match($homeurl_pattern, $wpconfig) || preg_match($siteurl_pattern, $wpconfig) ) {
 597        $this->wpconfig_siteurl_not_fixed = TRUE;
 598        $this->trace_log("siteurl or home url defines found in wpconfig");
 599    }
 600  }
 601
 602
 603  /**
 604   * Runs only when siteurl or homeurl define was found in the wpconfig, with the check_for_siteurl_in_wpconfig function
 605   * and only when wpconfig is writable.
 606   *
 607   * @since  2.1
 608   *
 609   * @access public
 610   *
 611   */
 612
 613  private function fix_siteurl_defines_in_wpconfig() {
 614      $wpconfig_path = $this->find_wp_config_path();
 615
 616      if (empty($wpconfig_path)) return;
 617
 618      $wpconfig = file_get_contents($wpconfig_path);
 619      $homeurl_pattern = '/(define\(\s*\'WP_HOME\'\s*,\s*\'http\:\/\/)/';
 620      $siteurl_pattern = '/(define\(\s*\'WP_SITEURL\'\s*,\s*\'http\:\/\/)/';
 621
 622      if (preg_match($homeurl_pattern, $wpconfig) || preg_match($siteurl_pattern, $wpconfig) ) {
 623        if (is_writable($wpconfig_path)) {
 624          $this->trace_log("wp config siteurl/homeurl edited.");
 625          $wpconfig = preg_replace($homeurl_pattern, "define('WP_HOME','https://", $wpconfig);
 626          $wpconfig = preg_replace($siteurl_pattern, "define('WP_SITEURL','https://", $wpconfig);
 627          file_put_contents($wpconfig_path, $wpconfig);
 628        }
 629        else {
 630          if ($this->debug) {$this->trace_log("not able to fix wpconfig siteurl/homeurl.");}
 631          //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.
 632          $this->wpconfig_siteurl_not_fixed = TRUE;
 633        }
 634      } else {
 635        if ($this->debug) {$this->trace_log("no siteurl/homeurl defines in wpconfig");}
 636      }
 637  }
 638
 639
 640  /**
 641   * Check if the wpconfig is already fixed
 642   *
 643   * @since  2.2
 644   *
 645   * @access public
 646   *
 647   */
 648
 649  public function wpconfig_has_fixes() {
 650    $wpconfig_path = $this->find_wp_config_path();
 651    if (empty($wpconfig_path)) return false;
 652    $wpconfig = file_get_contents($wpconfig_path);
 653
 654    //only one of two fixes possible.
 655    if (strpos($wpconfig, "//Begin Really Simple SSL Load balancing fix")!==FALSE ) {
 656      return true;
 657    }
 658
 659    if (strpos($wpconfig, "//Begin Really Simple SSL Server variable fix")!==FALSE ) {
 660      return true;
 661    }
 662
 663    return false;
 664  }
 665
 666
 667  /**
 668   * In case of load balancer without server https on, add fix in wp-config
 669   *
 670   * @since  2.1
 671   *
 672   * @access public
 673   *
 674   */
 675
 676
 677  public function wpconfig_loadbalancer_fix() {
 678      if (!current_user_can($this->capability)) return;
 679
 680      $wpconfig_path = $this->find_wp_config_path();
 681      if (empty($wpconfig_path)) return;
 682      $wpconfig = file_get_contents($wpconfig_path);
 683      $this->wpconfig_loadbalancer_fix_failed = FALSE;
 684      //only if loadbalancer AND NOT SERVER-HTTPS-ON should the following be added. (is_ssl = false)
 685      if (strpos($wpconfig, "//Begin Really Simple SSL Load balancing fix")===FALSE ) {
 686        if (is_writable($wpconfig_path)) {
 687          $rule  = "\n"."//Begin Really Simple SSL Load balancing fix"."\n";
 688          $rule .= '$server_opts = array("HTTP_CLOUDFRONT_FORWARDED_PROTO" => "https", "HTTP_CF_VISITOR"=>"https", "HTTP_X_FORWARDED_PROTO"=>"https", "HTTP_X_FORWARDED_SSL"=>"on", "HTTP_X_FORWARDED_SSL"=>"1");'."\n";
 689          $rule .= 'foreach( $server_opts as $option => $value ) {'."\n";
 690          $rule .=   'if ( (isset($_ENV["HTTPS"]) && ( "on" == $_ENV["HTTPS"] )) || (isset( $_SERVER[ $option ] ) && ( strpos( $_SERVER[ $option ], $value ) !== false )) ) {'."\n";
 691          $rule .=     '$_SERVER[ "HTTPS" ] = "on";'."\n";
 692          $rule .=     'break;'."\n";
 693          $rule .=   '}'."\n";
 694          $rule .= '}'."\n";
 695          $rule .= "//END Really Simple SSL"."\n";
 696
 697          $insert_after = "<?php";
 698          $pos = strpos($wpconfig, $insert_after);
 699          if ($pos !== false) {
 700              $wpconfig = substr_replace($wpconfig,$rule,$pos+1+strlen($insert_after),0);
 701          }
 702
 703          file_put_contents($wpconfig_path, $wpconfig);
 704          if ($this->debug) {$this->trace_log("wp config loadbalancer fix inserted");}
 705        } else {
 706          if ($this->debug) {$this->trace_log("wp config loadbalancer fix FAILED");}
 707          $this->wpconfig_loadbalancer_fix_failed = TRUE;
 708        }
 709      } else {
 710        if ($this->debug) {$this->trace_log("wp config loadbalancer fix already in place, great!");}
 711      }
 712      $this->save_options();
 713
 714  }
 715
 716
 717
 718    /**
 719     * Getting WordPress to recognize setup as being SSL when no https server variable is available
 720     *
 721     * @since  2.1
 722     *
 723     * @access public
 724     *
 725     */
 726
 727    public function wpconfig_server_variable_fix() {
 728      if (!current_user_can($this->capability)) return;
 729
 730      $wpconfig_path = $this->find_wp_config_path();
 731      if (empty($wpconfig_path)) return;
 732      $wpconfig = file_get_contents($wpconfig_path);
 733
 734      //check permissions
 735      if (!is_writable($wpconfig_path)) {
 736        if ($this->debug) $this->trace_log("wp-config.php not writable");
 737        return;
 738      }
 739
 740      //when more than one blog, first remove what we have
 741      if (is_multisite() && !RSSSL()->rsssl_multisite->is_multisite_subfolder_install() && !RSSSL()->rsssl_multisite->ssl_enabled_networkwide && count($this->sites)>1) {
 742        $wpconfig = preg_replace("/\/\/Begin\s?Really\s?Simple\s?SSL.*?\/\/END\s?Really\s?Simple\s?SSL/s", "", $wpconfig);
 743        $wpconfig = preg_replace("/\n+/","\n", $wpconfig);
 744        file_put_contents($wpconfig_path, $wpconfig);
 745      }
 746
 747      //now create new
 748
 749      //check if the fix is already there
 750      if (strpos($wpconfig, "//Begin Really Simple SSL Server variable fix")!==FALSE ) {
 751          if ($this->debug) {$this->trace_log("wp config server variable fix already in place, great!");}
 752          return;
 753      }
 754
 755      if ($this->debug) {$this->trace_log("Adding server variable to wpconfig");}
 756      $rule = $this->get_server_variable_fix_code();
 757
 758      $insert_after = "<?php";
 759      $pos = strpos($wpconfig, $insert_after);
 760      if ($pos !== false) {
 761          $wpconfig = substr_replace($wpconfig,$rule,$pos+1+strlen($insert_after),0);
 762      }
 763      file_put_contents($wpconfig_path, $wpconfig);
 764      if ($this->debug) $this->trace_log("wp config server variable fix inserted");
 765
 766      $this->save_options();
 767  }
 768
 769
 770protected function get_server_variable_fix_code(){
 771  if (is_multisite() && !RSSSL()->rsssl_multisite->ssl_enabled_networkwide && RSSSL()->rsssl_multisite->is_multisite_subfolder_install()) {
 772      if ($this->debug) $this->trace_log("per site activation on subfolder install, wp config server variable fix skipped");
 773      return "";
 774  }
 775
 776  if (is_multisite() && !RSSSL()->rsssl_multisite->ssl_enabled_networkwide && count($this->sites)==0) {
 777    if ($this->debug) $this->trace_log("no sites left with SSL, wp config server variable fix skipped");
 778    return "";
 779  }
 780
 781  if (is_multisite() && !RSSSL()->rsssl_multisite->ssl_enabled_networkwide) {
 782    $rule  = "\n"."//Begin Really Simple SSL Server variable fix"."\n";
 783    foreach ($this->sites as $domain ) {
 784        //remove http or https.
 785        if ($this->debug) {$this->trace_log("getting server variable rule for:".$domain);}
 786        $domain = preg_replace("/(http:\/\/|https:\/\/)/","",$domain);
 787
 788        //we excluded subfolders, so treat as domain
 789        //check only for domain without www, as the www variant is found as well with the no www search.
 790        $domain_no_www  = str_replace ( "www." , "" , $domain);
 791
 792        $rule .= 'if ( strpos($_SERVER["HTTP_HOST"], "'.$domain_no_www.'")!==FALSE ) {'."\n";
 793        $rule .= '   $_SERVER["HTTPS"] = "on";'."\n";
 794        $rule .= '}'."\n";
 795    }
 796    $rule .= "//END Really Simple SSL"."\n";
 797  } else {
 798    $rule  = "\n"."//Begin Really Simple SSL Server variable fix"."\n";
 799    $rule .= '$_SERVER["HTTPS"] = "on";'."\n";
 800    $rule .= "//END Really Simple SSL"."\n";
 801  }
 802
 803  return $rule;
 804}
 805
 806  /**
 807   * Removing changes made to the wpconfig
 808   *
 809   * @since  2.1
 810   *
 811   * @access public
 812   *
 813   */
 814
 815  public function remove_wpconfig_edit() {
 816
 817    $wpconfig_path = $this->find_wp_config_path();
 818    if (empty($wpconfig_path)) return;
 819    $wpconfig = file_get_contents($wpconfig_path);
 820
 821    //check for permissions
 822    if (!is_writable($wpconfig_path)) {
 823      if ($this->debug) $this->trace_log("could not remove wpconfig edits, wp-config.php not writable");
 824      $this->errors['wpconfig not writable'] = TRUE;
 825      return;
 826    }
 827
 828    //remove edits
 829    $wpconfig = preg_replace("/\/\/Begin\s?Really\s?Simple\s?SSL.*?\/\/END\s?Really\s?Simple\s?SSL/s", "", $wpconfig);
 830    $wpconfig = preg_replace("/\n+/","\n", $wpconfig);
 831    file_put_contents($wpconfig_path, $wpconfig);
 832
 833    //in multisite environment, with per site activation, re-add
 834    if (is_multisite() && ! RSSSL()->rsssl_multisite->ssl_enabled_networkwide) {
 835      if ($this->do_wpconfig_loadbalancer_fix)
 836        $this->wpconfig_loadbalancer_fix();
 837
 838      if ($this->no_server_variable)
 839        $this->wpconfig_server_variable_fix();
 840    }
 841
 842}
 843
 844  /**
 845   * Changes the siteurl and homeurl to https
 846   *
 847   * @since  2.0
 848   *
 849   * @access public
 850   *
 851   */
 852
 853  public function set_siteurl_to_ssl() {
 854      if (!current_user_can($this->capability)) return;
 855
 856      $this->trace_log("converting siteurl and homeurl to https");
 857
 858      $siteurl_ssl = str_replace ( "http://" , "https://" , get_option('siteurl'));
 859      $homeurl_ssl = str_replace ( "http://" , "https://" , get_option('home'));
 860      update_option('siteurl',$siteurl_ssl);
 861      update_option('home',$homeurl_ssl);
 862  }
 863
 864
 865
 866  /**
 867   * On de-activation, siteurl and homeurl are reset to http
 868   *
 869   * @since  2.0
 870   *
 871   * @access public
 872   *
 873   */
 874
 875  public function remove_ssl_from_siteurl() {
 876      $siteurl_no_ssl = str_replace ( "https://" , "http://" , get_option('siteurl'));
 877      $homeurl_no_ssl = str_replace ( "https://" , "http://" , get_option('home'));
 878      update_option('siteurl',$siteurl_no_ssl);
 879      update_option('home',$homeurl_no_ssl);
 880  }
 881
 882  /**
 883   * Save the plugin options
 884   *
 885   * @since  2.0
 886   *
 887   * @access public
 888   *
 889   */
 890
 891  public function save_options() {
 892    if (!current_user_can($this->capability)) return;
 893
 894    //any options added here should also be added to function options_validate()
 895    $options = array(
 896      'site_has_ssl'                      => $this->site_has_ssl,
 897      'hsts'                              => $this->hsts,
 898      'htaccess_warning_shown'            => $this->htaccess_warning_shown,
 899      'ssl_success_message_shown'         => $this->ssl_success_message_shown,
 900      'autoreplace_insecure_links'        => $this->autoreplace_insecure_links,
 901      'plugin_db_version'                 => $this->plugin_db_version,
 902      'debug'                             => $this->debug,
 903      'do_not_edit_htaccess'              => $this->do_not_edit_htaccess,
 904      'htaccess_redirect'                 => $this->htaccess_redirect,
 905      'ssl_enabled'                       => $this->ssl_enabled,
 906      'javascript_redirect'               => $this->javascript_redirect,
 907      'wp_redirect'                       => $this->wp_redirect,
 908      'switch_mixed_content_fixer_hook'   => $this->switch_mixed_content_fixer_hook,
 909    );
 910
 911    update_option('rlrsssl_options',$options);
 912  }
 913
 914  /**
 915   * Load the translation files
 916   *
 917   * @since  1.0
 918   *
 919   * @access public
 920   *
 921   */
 922
 923  public function load_translation()
 924  {
 925      load_plugin_textdomain('really-simple-ssl', FALSE, dirname(plugin_basename(__FILE__)).'/languages/');
 926  }
 927
 928  /**
 929   * Handles deactivation of this plugin
 930   *
 931   * @since  2.0
 932   *
 933   * @access public
 934   *
 935   */
 936
 937  public function deactivate($networkwide) {
 938    $this->remove_ssl_from_siteurl();
 939    $this->remove_ssl_from_siteurl_in_wpconfig();
 940
 941    $this->site_has_ssl                         = FALSE;
 942    $this->hsts                                 = FALSE;
 943    $this->htaccess_warning_shown               = FALSE;
 944    $this->ssl_success_message_shown            = FALSE;
 945    $this->autoreplace_insecure_links           = TRUE;
 946    $this->do_not_edit_htaccess                 = FALSE;
 947    $this->htaccess_redirect                    = FALSE;
 948    $this->javascript_redirect                  = FALSE;
 949    $this->wp_redirect                          = FALSE;
 950    $this->ssl_enabled                          = FALSE;
 951    $this->switch_mixed_content_fixer_hook      = FALSE;
 952
 953    $this->save_options();
 954
 955    //when on multisite, per site activation, recreate domain list for htaccess and wpconfig rewrite actions
 956    if (is_multisite()) {
 957      RSSSL()->rsssl_multisite->deactivate();
 958      if (!RSSSL()->rsssl_multisite->ssl_enabled_networkwide) $this->build_domain_list();
 959    }
 960
 961    $this->remove_wpconfig_edit();
 962    $this->removeHtaccessEdit();
 963  }
 964
 965
 966  /**
 967   * Checks if we are currently on SSL protocol, but extends standard wp with loadbalancer check.
 968   *
 969   * @since  2.0
 970   *
 971   * @access public
 972   *
 973   */
 974
 975  public function is_ssl_extended(){
 976    $server_var = FALSE;
 977		$server_opts = array(
 978      'HTTP_X_FORWARDED_PROTO'=>'https',
 979      'HTTP_CLOUDFRONT_FORWARDED_PROTO' => 'https',
 980      'HTTP_CF_VISITOR'=>'https',
 981      'HTTP_X_FORWARDED_SSL'=>'on',
 982      'HTTP_X_FORWARDED_SSL'=>'1'
 983    );
 984
 985		foreach( $server_opts as $option => $value ) {
 986			if ( (isset($_ENV['HTTPS']) && ( 'on' == $_ENV['HTTPS'] ))
 987        || (isset( $_SERVER[ $option ] ) && ( strpos( $_SERVER[ $option ], $value ) !== false ) )) {
 988				$server_var = TRUE;
 989				break;
 990			}
 991		}
 992
 993    if (is_ssl() || $server_var){
 994      return true;
 995    } else {
 996      return false;
 997    }
 998  }
 999
1000  /**
1001   * Checks for SSL by opening a test page in the plugin directory
1002   *
1003   * @since  2.0
1004   *
1005   * @access public
1006   *
1007   */
1008
1009   public function detect_configuration() {
1010     $this->trace_log("** Detecting configuration **");
1011     $this->trace_log("plugin version: ".rsssl_version);
1012     $old_ssl_setting = $this->site_has_ssl;
1013     $filecontents = "";
1014     //if current page is on SSL, we can assume SSL is available, even when an errormsg was returned
1015     if($this->is_ssl_extended()){
1016       $this->trace_log("Already on SSL, start detecting configuration");
1017       $this->site_has_ssl = TRUE;
1018     } else {
1019       //we're not on SSL, or no server vars were returned, so test with the test-page.
1020       //plugin url: domain.com/wp-content/etc
1021       $testpage_url = trailingslashit($this->test_url())."ssl-test-page.php";
1022       $this->trace_log("Opening testpage to check for SSL: ".$testpage_url);
1023
1024       $response = wp_remote_get( $testpage_url );
1025
1026       if( is_array($response) ) {
1027         $status = wp_remote_retrieve_response_code( $response );
1028         $filecontents = wp_remote_retrieve_body($response);
1029       }
1030
1031       $this->trace_log("test page url, enter in browser to check manually: ".$testpage_url);
1032
1033       if(!is_wp_error( $response ) && (strpos($filecontents, "#SSL TEST PAGE#") !== false)) {
1034         $this->site_has_ssl = TRUE;
1035         $this->trace_log("SSL test page loaded successfully");
1036       } else {
1037         $this->site_has_ssl = FALSE;
1038         $error = "";
1039         if (is_wp_error( $response ) ) $error = $response->get_error_message();
1040         $this->trace_log("No SSL detected. No certificate, or the testpage is blocked by security settings. The SSL testpage returned the error: ".$error);
1041       }
1042     }
1043
1044     if ($this->site_has_ssl) {
1045       //check the type of SSL, either by parsing the returned string, or by reading the server vars.
1046       if ((strpos($filecontents, "#CLOUDFRONT#") !== false) || (isset($_SERVER['HTTP_CLOUDFRONT_FORWARDED_PROTO']) && ($_SERVER['HTTP_CLOUDFRONT_FORWARDED_PROTO'] == 'https'))) {
1047         $this->ssl_type = "CLOUDFRONT";
1048       } elseif ((strpos($filecontents, "#CLOUDFLARE#") !== false) || (isset($_SERVER['HTTP_CF_VISITOR']) && ($_SERVER['HTTP_CF_VISITOR'] == 'https'))) {
1049         $this->ssl_type = "CLOUDFLARE";
1050       } elseif ((strpos($filecontents, "#LOADBALANCER#") !== false) || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https'))) {
1051         $this->ssl_type = "LOADBALANCER";
1052       } elseif ((strpos($filecontents, "#CDN#") !== false) || (isset($_SERVER['HTTP_X_FORWARDED_SSL']) && ($_SERVER['HTTP_X_FORWARDED_SSL'] == 'on' || $_SERVER['HTTP_X_FORWARDED_SSL'] == '1'))) {
1053         $this->ssl_type = "CDN";
1054       } elseif ((strpos($filecontents, "#SERVER-HTTPS-ON#") !== false) || (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on')) {
1055         $this->ssl_type = "SERVER-HTTPS-ON";
1056       } elseif ((strpos($filecontents, "#SERVER-HTTPS-1#") !== false) || (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == '1')) {
1057         $this->ssl_type = "SERVER-HTTPS-1";
1058       } elseif ((strpos($filecontents, "#SERVERPORT443#") !== false) || (isset($_SERVER['SERVER_PORT']) && ( '443' == $_SERVER['SERVER_PORT'] ))) {
1059         $this->ssl_type = "SERVERPORT443";
1060       } elseif ((strpos($filecontents, "#ENVHTTPS#") !== false) || (isset($_ENV['HTTPS']) && ( 'on' == $_ENV['HTTPS'] ))) {
1061          $this->ssl_type = "ENVHTTPS";
1062       } elseif ((strpos($filecontents, "#NO KNOWN SSL CONFIGURATION DETECTED#") !== false)) {
1063         //if we are here, SSL was detected, but without any known server variables set.
1064         //So we can use this info to set a server variable ourselfes.
1065         if (!$this->wpconfig_has_fixes()) {
1066           $this->no_server_variable = TRUE;
1067         }
1068         $this->trace_log("No server variable detected ");
1069         $this->ssl_type = "NA";
1070       } else {
1071         //no valid response, so set to NA
1072         $this->ssl_type = "NA";
1073       }
1074
1075       //check for is_ssl()
1076       if ( (!$this->is_ssl_extended() &&
1077            (strpos($filecontents, "#SERVER-HTTPS-ON#") === false) &&
1078            (strpos($filecontents, "#SERVER-HTTPS-1#") === false) &&
1079            (strpos($filecontents, "#SERVERPORT443#") === false)) || (!is_ssl() && $this->is_ssl_extended())) {
1080         //when is_ssl would return false, we should add some code to wp-config.php
1081         if (!$this->wpconfig_has_fixes()) {
1082           $this->trace_log("is_ssl() will return false: wp-config fix needed");
1083           $this->do_wpconfig_loadbalancer_fix = TRUE;
1084         }
1085       }
1086
1087 	    $this->trace_log("SSL type: ".$this->ssl_type);
1088     }
1089     $this->check_for_siteurl_in_wpconfig();
1090
1091     $this->save_options();
1092   }
1093
1094
1095  /**
1096   * Test if the htaccess redirect will work
1097   * This way, no redirect loops should occur.
1098   *
1099   * @since  2.1
1100   *
1101   * @access public
1102   *
1103   */
1104
1105   public function test_htaccess_redirect() {
1106     if (!current_user_can($this->capability)) return;
1107 	   if ($this->debug) {$this->trace_log("testing htaccess rules...");}
1108     $filecontents = "";
1109     $testpage_url = trailingslashit($this->test_url())."testssl/";
1110     switch ($this->ssl_type) {
1111     case "CLOUDFRONT":
1112         $testpage_url .= "cloudfront";
1113         break;
1114     case "CLOUDFLARE":
1115         $testpage_url .= "cloudflare";
1116         break;
1117     case "LOADBALANCER":
1118         $testpage_url .= "loadbalancer";
1119         break;
1120     case "CDN":
1121         $testpage_url .= "cdn";
1122         break;
1123     case "SERVER-HTTPS-ON":
1124         $testpage_url .= "serverhttpson";
1125         break;
1126     case "SERVER-HTTPS-1":
1127         $testpage_url .= "serverhttps1";
1128         break;
1129     case "SERVERPORT443":
1130         $testpage_url .= "serverport443";
1131         break;
1132     case "ENVHTTPS":
1133         $testpage_url .= "envhttps";
1134         break;
1135     }
1136
1137     $testpage_url .= ("/ssl-test-page.html");
1138
1139     $response = wp_remote_get( $testpage_url );
1140     if( is_array($response) ) {
1141       $status = wp_remote_retrieve_response_code( $response );
1142       $filecontents = wp_remote_retrieve_body($response);
1143     }
1144
1145     $this->trace_log("test page url, enter in browser to check manually: ".$testpage_url);
1146
1147     if (!is_wp_error( $response ) && (strpos($filecontents, "#SSL TEST PAGE#") !== false)) {
1148       $this->htaccess_test_success = TRUE;
1149 		   $this->trace_log("htaccess rules tested successfully.");
1150     } else {
1151       //.htaccess rewrite rule seems to be giving problems.
1152       $this->htaccess_test_success = FALSE;
1153       if (is_wp_error( $response )) {
1154         $this->trace_log("htaccess rules test failed with error: ".$response->get_error_message());
1155       } else {
1156         $this->trace_log("htaccess test rules failed. Set WordPress redirect in settings/SSL");
1157       }
1158     }
1159   }
1160
1161
1162  /**
1163   * Get an url with which we can test the SSL connection and htaccess redirect rules.
1164   *
1165   * @since  2.0
1166   *
1167   * @access public
1168   *
1169   */
1170
1171   public function test_url(){
1172     $plugin_url = str_replace("http://", "https://", trailingslashit(rsssl_url) );;
1173     $https_home_url = str_replace("http://", "https://", home_url());
1174
1175     //in some case we get a relative url here, so we check that.
1176     //we compare to urls replaced to https, in case one of them is still on http.
1177 	   if ( (strpos($plugin_url, "https://")===FALSE ) &&
1178          (strpos($plugin_url, $https_home_url)===FALSE)
1179        ) {
1180       //make sure we do not have a slash at the start
1181       $plugin_url = ltrim($plugin_url,"/");
1182       $plugin_url = trailingslashit(home_url()).$plugin_url;
1183     }
1184
1185     //for subdomains or domain mapping situations, we have to convert the plugin_url from main site to the subdomain url.
1186     if (is_multisite() && ( !is_main_site(get_current_blog_id()) ) && (! RSSSL()->rsssl_multisite->is_multisite_subfolder_install()) ) {
1187       $mainsiteurl = trailingslashit(str_replace("http://","https://",network_site_url()));
1188
1189       $home = trailingslashit($https_home_url);
1190       $plugin_url = str_replace($mainsiteurl, $home, $plugin_url);
1191
1192       //return http link if original url is http.
1193       //if (strpos(home_url(), "https://")===FALSE) $plugin_url = str_replace("https://","http://",$plugin_url);
1194     }
1195
1196     return $plugin_url;
1197   }
1198
1199
1200  /**
1201   * removes the added redirect to https rules to the .htaccess file.
1202   *
1203   * @since  2.0
1204   *
1205   * @access public
1206   *
1207   */
1208
1209  public function removeHtaccessEdit() {
1210      if(file_exists($this->ABSpath.".htaccess") && is_writable($this->ABSpath.".htaccess")){
1211        $htaccess = file_get_contents($this->ABSpath.".htaccess");
1212
1213
1214        //if multisite, per site activation and more than one blog remaining on ssl, remove condition for this site only
1215        //the domain list has been rebuilt already, so current site is already removed.
1216        if (is_multisite() && ! RSSSL()->rsssl_multisite->ssl_enabled_networkwide && count($this->sites)>0) {
1217          //remove http or https.
1218          $domain = preg_replace("/(http:\/\/|https:\/\/)/","",home_url());
1219          $pattern = "/#wpmu\srewritecond\s?".preg_quote($domain, "/")."\n.*?#end\swpmu\srewritecond\s?".preg_quote($domain, "/")."\n/s";
1220
1221          //only remove if the pattern is there at all
1222          if (preg_match($pattern, $htaccess)) $htaccess = preg_replace($pattern, "", $htaccess);
1223          //now replace any remaining "or" on the last condition.
1224          $pattern = "/(\[OR\])(?!.*(\[OR\]|#start).*?RewriteRule)/s";
1225          $htaccess = preg_replace($pattern, "", $htaccess,1);
1226
1227        } else {
1228          // remove everything
1229          $pattern = "/#\s?BEGIN\s?rlrssslReallySimpleSSL.*?#\s?END\s?rlrssslReallySimpleSSL/s";
1230          //only remove if the pattern is there at all
1231          if (preg_match($pattern, $htaccess)) $htaccess = preg_replace($pattern, "", $htaccess);
1232
1233        }
1234
1235        $htaccess = preg_replace("/\n+/","\n", $htaccess);
1236        file_put_contents($this->ABSpath.".htaccess", $htaccess);
1237        $this->save_options();
1238      } else {
1239        $this->errors['HTACCESS_NOT_WRITABLE'] = TRUE;
1240        if ($this->debug) $this->trace_log("could not remove rules from htaccess, file not writable");
1241      }
1242  }
1243
1244  public function get_htaccess_version() {
1245    if (!file_exists($this->ABSpath.".htaccess")) return false;
1246
1247    $htaccess = file_get_contents($this->ABSpath.".htaccess");
1248    $versionpos = strpos($htaccess, "rsssl_version");
1249
1250    if ($versionpos===false) {
1251      //no version found, so not .htaccess rules.
1252      return false;
1253    } else {
1254      //find closing marker of version
1255      $close = strpos($htaccess, "]", $versionpos);
1256      $version = substr($htaccess, $versionpos+14, $close-($versionpos+14));
1257      return $version;
1258    }
1259  }
1260
1261
1262  /*   deprecated   */
1263
1264  function htaccess_redirect_allowed(){
1265    if (is_multisite() && RSSSL()->rsssl_multisite->is_per_site_activated_multisite_subfolder_install()) {
1266      return false;
1267    } else {
1268      return true;
1269    }
1270  }
1271
1272
1273  /*
1274    Checks if the htaccess contains redirect rules, either actual redirect or a rsssl marker.
1275  */
1276
1277  public function htaccess_contains_redirect_rules() {
1278
1279    if (!file_exists($this->ABSpath.".htaccess")) {
1280      return false;
1281    }
1282
1283    $htaccess = file_get_contents($this->ABSpath.".htaccess");
1284
1285    $needle = "RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]";
1286    if(strpos($htaccess, $needle) !== FALSE || $this->contains_rsssl_rules()){
1287      return true;
1288    } else {
1289      $this->trace_log(".htaccess does not contain default Really Simple SSL redirect");
1290      return false;
1291    }
1292
1293  }
1294
1295
1296  /*
1297  *    Checks if the htaccess contains the Really Simple SSL comment.
1298  *
1299  */
1300
1301  public function contains_rsssl_rules() {
1302    if (!file_exists($this->ABSpath.".htaccess")) {
1303      return false;
1304    }
1305
1306    $htaccess = file_get_contents($this->ABSpath.".htaccess");
1307
1308    $check=null;
1309    preg_match("/BEGIN rlrssslReallySimpleSSL/", $htaccess, $check);
1310    if(count($check) === 0){
1311      return false;
1312    } else {
1313      return true;
1314    }
1315  }
1316
1317  /*
1318  *    Checks if a 301 redirect is set
1319  *    this is the case if either the wp_redirect is set, or the htaccess redirect is set.
1320  *
1321  */
1322
1323  public function has_301_redirect() {
1324    if ($this->wp_redirect) return true;
1325
1326    if (RSSSL()->rsssl_server->uses_htaccess() && $this->htaccess_contains_redirect_rules() ) {
1327      return true;
1328    }
1329
1330    return false;
1331  }
1332
1333  /**
1334   * Checks if the HSTS rule is already in the htaccess file
1335   * Set the hsts variable in the db accordingly. applies to preload version as well.
1336   *
1337   * @since  2.1
1338   *
1339   * @access public
1340   *
1341   */
1342
1343  public function contains_hsts() {
1344    if (!file_exists($this->ABSpath.".htaccess")) {
1345      $this->trace_log(".htaccess not found in ".$this->ABSpath);
1346      $result = $this->hsts; //just return the setting.
1347    } else {
1348      $htaccess = file_get_contents($this->ABSpath.".htaccess");
1349
1350      preg_match("/Strict-Transport-Security/", $htaccess, $check);
1351      if(count($check) === 0){
1352        $result = false;
1353      } else {
1354        $result = true;
1355      }
1356    }
1357
1358    return $result;
1359  }
1360
1361
1362  /**
1363   * Adds redirect to https rules to the .htaccess file.
1364   *
1365   * @since  2.0
1366   *
1367   * @access public
1368   *
1369   */
1370
1371  public function editHtaccess(){
1372      if (!current_user_can($this->capability)) return;
1373
1374      //check if htacces exists and  if htaccess is writable
1375      //update htaccess to redirect to ssl
1376
1377      $this->trace_log("checking if .htaccess can or should be edited...");
1378
1379      //does it exist?
1380      if (!file_exists($this->ABSpath.".htaccess")) {
1381        $this->trace_log(".htaccess not found.");
1382        return;
1383      }
1384
1385      //check if editing is blocked.
1386      if ($this->do_not_edit_htaccess) {
1387        $this->trace_log("Edit of .htaccess blocked by setting or define 'do not edit htaccess' in Really Simple SSL.");
1388        return;
1389      }
1390
1391      $htaccess = file_get_contents($this->ABSpath.".htaccess");
1392      if(!$this->htaccess_contains_redirect_rules()){
1393
1394        if (!is_writable($this->ABSpath.".htaccess")) {
1395          //set the wp redirect as fallback, because .htaccess couldn't be edited.
1396          if ($this->clicked_activate_ssl()) $this->wp_redirect = true;
1397          if (is_multisite()) {
1398            RSSSL()->rsssl_multisite->wp_redirect = true;
1399            RSSSL()->rsssl_multisite->save_options();
1400          }
1401          $this->save_options();
1402          $this->trace_log(".htaccess not writable.");
1403          return;
1404        }
1405
1406        $rules = $this->get_redirect_rules();
1407
1408        //insert rules before wordpress part.
1409        if (strlen($rules)>0) {
1410          $wptag = "# BEGIN WordPress";
1411          if (strpos($htaccess, $wptag)!==false) {
1412              $htaccess = str_replace($wptag, $rules.$wptag, $htaccess);
1413          } else {
1414              $htaccess = $htaccess.$rules;
1415          }
1416
1417          file_put_contents($this->ABSpath.".htaccess", $htaccess);
1418        }
1419
1420    } elseif ($this->is_settings_page() || is_network_admin()) {
1421
1422        if ($this->debug) {$this->trace_log("settings page, or network admin, updating htaccess...");}
1423
1424        if (!is_writable($this->ABSpath.".htaccess")) {
1425          if($this->debug) $this->trace_log(".htaccess not writable.");
1426          return;
1427        }
1428
1429	      $htaccess = preg_replace("/#\s?BEGIN\s?rlrssslReallySimpleSSL.*?#\s?END\s?rlrssslReallySimpleSSL/s", "", $htaccess);
1430        $htaccess = preg_replace("/\n+/","\n", $htaccess);
1431
1432        $rules = $this->get_redirect_rules();
1433
1434        //insert rules before WordPress part.
1435        $wptag = "# BEGIN WordPress";
1436        if (strpos($htaccess, $wptag)!==false) {
1437            $htaccess = str_replace($wptag, $rules.$wptag, $htaccess);
1438        } else {
1439            $htaccess = $htaccess.$rules;
1440        }
1441        file_put_contents($this->ABSpath.".htaccess", $htaccess);
1442
1443      }
1444  }
1445
1446  /**
1447  *
1448  *  @since 2.2
1449  *  Check if the mixed content fixer is functioning on the front end, by scanning the source of the homepage for the fixer comment.
1450  *
1451  */
1452
1453  public function mixed_content_fixer_detected(){
1454
1455    $status = 0;
1456    $web_source = "";
1457    //check if the mixed content fixer is active
1458    $response = wp_remote_get( home_url() );
1459
1460    if( is_array($response) ) {
1461      $status = wp_remote_retrieve_response_code( $response );
1462      $web_source = wp_remote_retrieve_body($response);
1463    }
1464
1465    if ($status!=200 || (strpos($web_source, "data-rsssl=") === false)) {
1466      $this->trace_log("Check for Mixed Content detection failed, http statuscode ".$status);
1467      return false;
1468    } else {
1469      $this->trace_log("Mixed content fixer was successfully detected on the front end.");
1470      return true;
1471    }
1472  }
1473
1474  /**
1475   * Create redirect rules for the .htaccess.
1476   *
1477   *…

Large files files are truncated, but you can click here to view the full file