really-simple-ssl
Last commit date
assets
1 month ago
core
1 month ago
languages
1 month ago
lets-encrypt
1 month ago
lib
1 month ago
mailer
1 month ago
modal
1 month ago
placeholders
1 month ago
progress
1 month ago
security
1 month ago
settings
1 month ago
testssl
1 month ago
upgrade
1 month ago
.wp-env.json
1 month ago
SECURITY.md
1 month ago
class-admin.php
1 month ago
class-cache.php
1 month ago
class-certificate.php
1 month ago
class-front-end.php
1 month ago
class-installer.php
1 month ago
class-mixed-content-fixer.php
1 month ago
class-multisite.php
1 month ago
class-server.php
1 month ago
class-site-health.php
1 month ago
class-wp-cli.php
1 month ago
compatibility.php
1 month ago
force-deactivate.txt
1 month ago
functions.php
1 month ago
index.php
1 month ago
readme.txt
1 month ago
rector.php
1 month ago
rlrsssl-really-simple-ssl.php
1 month ago
rsssl-auto-loader.php
1 month ago
sbom.json.gz
1 month ago
ssl-test-page.php
1 month ago
system-status.php
1 month ago
uninstall.php
1 month ago
upgrade.php
1 month ago
class-mixed-content-fixer.php
186 lines
| 1 | <?php |
| 2 | defined('ABSPATH') or die("you do not have access to this page!"); |
| 3 | |
| 4 | if (!class_exists('rsssl_admin_mixed_content_fixer')) { |
| 5 | class rsssl_mixed_content_fixer |
| 6 | { |
| 7 | private static $_this; |
| 8 | public $http_urls = array(); |
| 9 | public $mixed_content_fixer = false; |
| 10 | public $hide_wordpress_version = false; |
| 11 | |
| 12 | function __construct() |
| 13 | { |
| 14 | if (isset(self::$_this)) wp_die(); |
| 15 | |
| 16 | self::$_this = $this; |
| 17 | $this->mixed_content_fixer = is_ssl() && rsssl_get_option('mixed_content_fixer', true ); |
| 18 | $this->hide_wordpress_version = rsssl_get_option('hide_wordpress_version' ); |
| 19 | if ( !is_admin() && ($this->mixed_content_fixer || $this->hide_wordpress_version )) { |
| 20 | $this->handle_output_buffer(); |
| 21 | } else if ( is_admin() && is_ssl() && rsssl_get_option("admin_mixed_content_fixer") ) { |
| 22 | $this->mixed_content_fixer = true; |
| 23 | $this->handle_output_buffer(); |
| 24 | } |
| 25 | } |
| 26 | |
| 27 | static function this() |
| 28 | { |
| 29 | return self::$_this; |
| 30 | } |
| 31 | |
| 32 | /** |
| 33 | * |
| 34 | * add action hooks at the start and at the end of the WP process. |
| 35 | * |
| 36 | * @since 2.3 |
| 37 | * |
| 38 | * @access public |
| 39 | * |
| 40 | */ |
| 41 | |
| 42 | public function handle_output_buffer() |
| 43 | { |
| 44 | /* Do not fix mixed content when call is coming from wp_api or from xmlrpc */ |
| 45 | if (defined('JSON_REQUEST') && JSON_REQUEST) return; |
| 46 | if (defined('XMLRPC_REQUEST') && XMLRPC_REQUEST) return; |
| 47 | |
| 48 | $this->build_url_list(); |
| 49 | |
| 50 | if ( is_admin() ) { |
| 51 | add_action("admin_init", array($this, "start_buffer"), 100); |
| 52 | add_action("shutdown", array($this, "end_buffer"), 999); |
| 53 | } else { |
| 54 | if ( rsssl_get_option("switch_mixed_content_fixer_hook") || (defined('RSSSL_CONTENT_FIXER_ON_INIT') && RSSSL_CONTENT_FIXER_ON_INIT)) { |
| 55 | add_action("init", array($this, "start_buffer")); |
| 56 | } else { |
| 57 | add_action("template_redirect", array($this, "start_buffer")); |
| 58 | } |
| 59 | |
| 60 | add_action("shutdown", array($this, "end_buffer"), 999); |
| 61 | } |
| 62 | } |
| 63 | |
| 64 | |
| 65 | /** |
| 66 | * Apply the mixed content fixer. |
| 67 | * |
| 68 | * @since 2.3 |
| 69 | * |
| 70 | * @access public |
| 71 | * |
| 72 | */ |
| 73 | |
| 74 | public function filter_buffer($buffer) |
| 75 | { |
| 76 | if ( $this->mixed_content_fixer ) { |
| 77 | $buffer = $this->replace_insecure_links($buffer); |
| 78 | } |
| 79 | return apply_filters("rsssl_fixer_output", $buffer ); |
| 80 | } |
| 81 | |
| 82 | /** |
| 83 | * Start buffering the output |
| 84 | * |
| 85 | * @since 2.0 |
| 86 | * |
| 87 | * @access public |
| 88 | * |
| 89 | */ |
| 90 | |
| 91 | public function start_buffer() |
| 92 | { |
| 93 | ob_start(array($this, "filter_buffer")); |
| 94 | } |
| 95 | |
| 96 | /** |
| 97 | * Flush the output buffer |
| 98 | * |
| 99 | * @since 2.0 |
| 100 | * |
| 101 | * @access public |
| 102 | * |
| 103 | */ |
| 104 | public function end_buffer() |
| 105 | { |
| 106 | // Only flush if buffer level is above zlib's level. |
| 107 | if (function_exists('wp_ob_end_flush_all')) { |
| 108 | wp_ob_end_flush_all(); |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | /** |
| 113 | * Creates an array of insecure links that should be https and an array of secure links to replace with |
| 114 | * |
| 115 | * @since 2.0 |
| 116 | * |
| 117 | * @access public |
| 118 | * |
| 119 | */ |
| 120 | |
| 121 | public function build_url_list() |
| 122 | { |
| 123 | $home = str_replace("https://", "http://", get_option('home') ); |
| 124 | $root = str_replace("://www.", "://", $home); |
| 125 | $www = str_replace("://", "://www.", $root); |
| 126 | |
| 127 | //for the escaped version, we only replace the home_url, not it's www or non www counterpart, as it is most likely not used |
| 128 | $escaped_home = str_replace("/", "\/", $home); |
| 129 | $this->http_urls = array( |
| 130 | $www, |
| 131 | $root, |
| 132 | $escaped_home, |
| 133 | "src='http://", |
| 134 | 'src="http://', |
| 135 | ); |
| 136 | } |
| 137 | |
| 138 | /** |
| 139 | * Just before the page is sent to the visitor's browser, all homeurl links are replaced with https. |
| 140 | * |
| 141 | * @since 1.0 |
| 142 | * |
| 143 | * @access public |
| 144 | * |
| 145 | */ |
| 146 | |
| 147 | public function replace_insecure_links($str) |
| 148 | { |
| 149 | //skip if file is xml |
| 150 | if ( strpos( $str, "<?xml" ) === 0 ) { |
| 151 | return $str; |
| 152 | } |
| 153 | |
| 154 | $search_array = apply_filters('rlrsssl_replace_url_args', $this->http_urls); |
| 155 | $ssl_array = str_replace(array("http://", "http:\/\/"), array("https://", "https:\/\/"), $search_array); |
| 156 | $str = str_replace($search_array, $ssl_array, $str); |
| 157 | |
| 158 | //replace all http links except hyperlinks |
| 159 | //all tags with src attr are already fixed by str_replace |
| 160 | $pattern = array( |
| 161 | '/url\([\'"]?\K(http:\/\/)(?=[^)]+)/i', |
| 162 | '/<link [^>]*?href=[\'"]\K(http:\/\/)(?=[^\'"]+)/i', |
| 163 | '/<meta property="og:image" [^>]*?content=[\'"]\K(http:\/\/)(?=[^\'"]+)/i', |
| 164 | '/<form [^>]*?action=[\'"]\K(http:\/\/)(?=[^\'"]+)/i', |
| 165 | ); |
| 166 | |
| 167 | $str = preg_replace($pattern, 'https://', $str); |
| 168 | |
| 169 | /* handle multiple images in srcset */ |
| 170 | $str = preg_replace_callback('/<img[^\>]*[^\>\S]+srcset=[\'"]\K((?:[^"\'\s,]+\s*(?:\s+\d+[wx])(?:,\s*)?)+)["\']/', array($this, 'replace_src_set'), $str); |
| 171 | return str_replace("<body", '<body data-rsssl=1', $str); |
| 172 | } |
| 173 | |
| 174 | /** |
| 175 | * Helper function |
| 176 | * |
| 177 | * */ |
| 178 | |
| 179 | public function replace_src_set($matches) { |
| 180 | return str_replace("http://", "https://", $matches[0]); |
| 181 | } |
| 182 | |
| 183 | } |
| 184 | } |
| 185 | |
| 186 |