PageRenderTime 58ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/wp-content/plugins/wordpress-https/wordpress-https.php

https://github.com/gregoryo/nycga2
PHP | 922 lines | 603 code | 98 blank | 221 comment | 259 complexity | 334995656e2c3987f6a146f55b8b99d4 MD5 | raw file
Possible License(s): AGPL-1.0, GPL-3.0, GPL-2.0, LGPL-2.1
  1. <?php
  2. /*
  3. Plugin Name: WordPress HTTPS
  4. Plugin URI: http://mvied.com/projects/wordpress-https/
  5. Description: WordPress HTTPS is intended to be an all-in-one solution to using SSL on WordPress sites.
  6. Author: Mike Ems
  7. Version: 1.9.2
  8. Author URI: http://mvied.com/
  9. */
  10. /**
  11. * Class for the WordPress plugin WordPress HTTPS
  12. *
  13. * @author Mike Ems
  14. * @package WordPressHTTPS
  15. * @copyright Copyright 2011
  16. *
  17. * @return object
  18. *
  19. */
  20. if ( !class_exists('WordPressHTTPS') ) {
  21. class WordPressHTTPS {
  22. /**
  23. * Plugin version
  24. *
  25. * @var int
  26. */
  27. var $plugin_version = '1.9.2';
  28. /**
  29. * Plugin URL
  30. *
  31. * @var string
  32. */
  33. var $plugin_url;
  34. /**
  35. * HTTP URL
  36. *
  37. * @var string
  38. */
  39. var $http_url;
  40. /**
  41. * HTTPS URL
  42. *
  43. * @var string
  44. */
  45. var $https_url;
  46. /**
  47. * Shared SSL
  48. *
  49. * @var boolean
  50. */
  51. var $shared_ssl = false;
  52. /**
  53. * Default options
  54. *
  55. * @var array
  56. */
  57. var $options_default = array(
  58. 'wordpress-https_internalurls' => 1, // Force internal URL's to HTTPS
  59. 'wordpress-https_externalurls' => 0, // Force external URL's to HTTPS
  60. 'wordpress-https_bypass' => 0, // Bypass option to check if external elements can be loaded via HTTPS
  61. 'wordpress-https_disable_autohttps'=> 0, // Prevents WordPress 3.0+ from making all links HTTPS when viewing a secure page.
  62. 'wordpress-https_exclusive_https'=> 0, // Exclusively force SSL on posts and pages with the `Force SSL` option checked.
  63. 'wordpress-https_frontpage'=> 0, // Force SSL on front page
  64. 'wordpress-https_sharedssl'=> 0, // Enable Shared SSL
  65. 'wordpress-https_sharedssl_admin' => 0, // Shared SSL for admin panel
  66. 'wordpress-https_sharedssl_host' => '', // Hostname for Shared SSL
  67. 'wordpress-https_external_urls' => array() // External URL's that are okay to rewrite to HTTPS
  68. );
  69. /**
  70. * Initialize plugin (PHP4)
  71. *
  72. * @param none
  73. * @return void
  74. */
  75. function WordPressHTTPS() {
  76. $argcv = func_get_args();
  77. call_user_func_array(array(&$this, '__construct'), $argcv);
  78. }
  79. /**
  80. * Initialize plugin (PHP5+)
  81. *
  82. * @param none
  83. * @return void
  84. */
  85. function __construct() {
  86. // Assign plugin_url
  87. if ( version_compare( get_bloginfo('version'), '2.8', '>=' ) ) {
  88. $this->plugin_url = plugins_url('', __FILE__);
  89. } else {
  90. $this->plugin_url = WP_PLUGIN_URL . '/' . plugin_basename(dirname(__FILE__));
  91. }
  92. // Assign HTTP URL
  93. $this->http_url = 'http://' . parse_url(get_option('home'), PHP_URL_HOST);
  94. // Assign HTTPS URL
  95. $this->https_url = $this->replace_http($this->http_url);
  96. // Shared SSL
  97. if ( get_option('wordpress-https_sharedssl') == 1 && get_option('wordpress-https_sharedssl_host') != '' ) {
  98. // Turn on Shared SSL
  99. $this->shared_ssl = true;
  100. // Assign HTTPS URL to Shared SSL Host
  101. $this->https_url = get_option('wordpress-https_sharedssl_host');
  102. // Prevent WordPress from causing a redirect loop
  103. remove_filter('template_redirect', 'redirect_canonical');
  104. // Remove Shared SSL authentication cookies on logout
  105. add_action('clear_auth_cookie', array(&$this, 'clear_auth_cookie'));
  106. }
  107. // Fix admin_url for Shared SSL login
  108. if ( $GLOBALS['pagenow'] == 'wp-login.php' && $this->shared_ssl && $this->is_ssl() ) {
  109. add_filter('admin_url', array(&$this, 'replace_http_url'));
  110. }
  111. // Filter site_url in admin panel when using Shared SSL
  112. if ( is_admin() && $this->shared_ssl && $this->is_ssl() ) {
  113. add_filter( 'site_url', array(&$this, 'replace_http_url'));
  114. }
  115. // Redirect login page if using Shared SSL. This is not pluggable due to the redirect methods used in wp-login.php
  116. if ( $GLOBALS['pagenow'] == 'wp-login.php' && $this->shared_ssl && !$this->is_ssl() && get_option('wordpress-https_sharedssl_admin') == 1 ) {
  117. $this->redirect('https');
  118. }
  119. // Start output buffering
  120. add_action('plugins_loaded', array(&$this, 'buffer_start'));
  121. if ( is_admin() ) {
  122. // Add admin menus
  123. add_action('admin_menu', array(&$this, 'menu'));
  124. // Load on plugins page
  125. if ( $GLOBALS['pagenow'] == 'plugins.php' ) {
  126. add_filter( 'plugin_row_meta', array(&$this, 'plugin_links'), 10, 2);
  127. }
  128. // Load on Settings page
  129. if ( @$_GET['page'] == 'wordpress-https' ) {
  130. wp_enqueue_script('jquery-form', $this->plugin_url . '/js/jquery.form.js', array('jquery'), '2.47', true);
  131. wp_enqueue_script('wordpress-https', $this->plugin_url . '/js/admin.php', array('jquery'), $this->plugin_version, true);
  132. wp_enqueue_style('wordpress-https', $this->plugin_url . '/css/admin.css', $this->plugin_version, true);
  133. if ( function_exists('add_thickbox') ) {
  134. add_thickbox();
  135. }
  136. }
  137. // Add 'Force SSL' checkbox to add/edit post pages
  138. if ( version_compare( get_bloginfo('version'), '2.8', '>' ) ) {
  139. add_action('post_submitbox_misc_actions', array(&$this, 'post_checkbox'));
  140. } else {
  141. add_action('post_submitbox_start', array(&$this, 'post_checkbox'));
  142. }
  143. add_action('save_post', array(&$this, 'post_save'));
  144. }
  145. // Check if the page needs to be redirected
  146. add_action('template_redirect', array(&$this, 'check_https'));
  147. // Filter HTTPS from links in WP 3.0+
  148. if ( get_option('wordpress-https_disable_autohttps') == 1 && !is_admin() && strpos(get_option('home'), 'https://') === false ) {
  149. add_filter('page_link', array(&$this, 'replace_https'));
  150. add_filter('post_link', array(&$this, 'replace_https'));
  151. add_filter('category_link', array(&$this, 'replace_https'));
  152. add_filter('get_archives_link', array(&$this, 'replace_https'));
  153. add_filter('tag_link', array(&$this, 'replace_https'));
  154. add_filter('search_link', array(&$this, 'replace_https'));
  155. add_filter('home_url', array(&$this, 'replace_https'));
  156. add_filter('bloginfo', array(&$this, 'bloginfo'), 10, 2);
  157. add_filter('bloginfo_url', array(&$this, 'bloginfo'), 10, 2);
  158. // If the whole site is not HTTPS, set links to the front-end to HTTP
  159. } else if ( is_admin() && $this->is_ssl() && strpos(get_option('home'), 'https://') === false ) {
  160. add_filter('page_link', array(&$this, 'replace_https'));
  161. add_filter('post_link', array(&$this, 'replace_https'));
  162. add_filter('category_link', array(&$this, 'replace_https'));
  163. add_filter('get_archives_link', array(&$this, 'replace_https'));
  164. add_filter('tag_link', array(&$this, 'replace_https'));
  165. add_filter('search_link', array(&$this, 'replace_https'));
  166. }
  167. // End output buffering
  168. //add_action('shutdown', array(&$this, 'buffer_end'));
  169. }
  170. /**
  171. * Operations performed when plugin is activated.
  172. *
  173. * @param none
  174. * @return void
  175. */
  176. function install() {
  177. // Set default options
  178. foreach ( $this->options_default as $option => $value ) {
  179. if ( get_option($option) === false ) {
  180. add_option($option, $value);
  181. }
  182. }
  183. }
  184. /**
  185. * Sets the authentication cookies based User ID.
  186. * Override for WordPress' pluggable function wp_set_auth_cookie
  187. *
  188. * The $remember parameter increases the time that the cookie will be kept. The
  189. * default the cookie is kept without remembering is two days. When $remember is
  190. * set, the cookies will be kept for 14 days or two weeks.
  191. *
  192. * @param int $user_id User ID
  193. * @param bool $remember Whether to remember the user or not
  194. * @param bool $secure Whether or not cookie is secure
  195. */
  196. function wp_set_auth_cookie($user_id, $remember = false, $secure = '') {
  197. if ( $remember ) {
  198. $expiration = $expire = time() + apply_filters('auth_cookie_expiration', 1209600, $user_id, $remember);
  199. } else {
  200. $expiration = time() + apply_filters('auth_cookie_expiration', 172800, $user_id, $remember);
  201. $expire = 0;
  202. }
  203. if ( $secure === '' ) {
  204. $secure = $this->is_ssl() ? true : false;
  205. }
  206. if ( $secure ) {
  207. $auth_cookie_name = SECURE_AUTH_COOKIE;
  208. $scheme = 'secure_auth';
  209. } else {
  210. $auth_cookie_name = AUTH_COOKIE;
  211. $scheme = 'auth';
  212. }
  213. $auth_cookie = wp_generate_auth_cookie($user_id, $expiration, $scheme);
  214. $logged_in_cookie = wp_generate_auth_cookie($user_id, $expiration, 'logged_in');
  215. do_action('set_auth_cookie', $auth_cookie, $expire, $expiration, $user_id, $scheme);
  216. do_action('set_logged_in_cookie', $logged_in_cookie, $expire, $expiration, $user_id, 'logged_in');
  217. // Cookie paths defined to accomodate Shared SSL
  218. $cookie_domain = '.' . parse_url($this->https_url, PHP_URL_HOST);
  219. $cookie_path = rtrim(parse_url($this->https_url, PHP_URL_PATH), '/') . COOKIEPATH;
  220. $cookie_path_site = rtrim(parse_url($this->https_url, PHP_URL_PATH), '/') . SITECOOKIEPATH;
  221. $cookie_path_plugins = rtrim(parse_url($this->https_url, PHP_URL_PATH), '/') . PLUGINS_COOKIE_PATH;
  222. $cookie_path_admin = $cookie_path_site . 'wp-admin';
  223. if ( $this->shared_ssl && $this->is_ssl() ) {
  224. setcookie($auth_cookie_name, $auth_cookie, $expire, $cookie_path_plugins, $cookie_domain, $secure, true);
  225. setcookie($auth_cookie_name, $auth_cookie, $expire, $cookie_path_admin, $cookie_domain, $secure, true);
  226. setcookie(LOGGED_IN_COOKIE, $logged_in_cookie, $expire, $cookie_path, $cookie_domain, false, true);
  227. if ( $cookie_path != $cookie_path_site )
  228. setcookie(LOGGED_IN_COOKIE, $logged_in_cookie, $expire, $cookie_path_site, $cookie_domain, false, true);
  229. } else {
  230. setcookie($auth_cookie_name, $auth_cookie, $expire, PLUGINS_COOKIE_PATH, COOKIE_DOMAIN, $secure, true);
  231. setcookie($auth_cookie_name, $auth_cookie, $expire, ADMIN_COOKIE_PATH, COOKIE_DOMAIN, $secure, true);
  232. setcookie(LOGGED_IN_COOKIE, $logged_in_cookie, $expire, COOKIEPATH, COOKIE_DOMAIN, $secure_logged_in_cookie, true);
  233. if ( COOKIEPATH != SITECOOKIEPATH )
  234. setcookie(LOGGED_IN_COOKIE, $logged_in_cookie, $expire, SITECOOKIEPATH, COOKIE_DOMAIN, $secure_logged_in_cookie, true);
  235. }
  236. }
  237. /**
  238. * Removes all of the cookies associated with authentication.
  239. *
  240. * @param none
  241. * @return void
  242. */
  243. function clear_auth_cookie() {
  244. // Cookie paths defined to accomodate Shared SSL
  245. $cookie_domain = '.' . parse_url($this->https_url, PHP_URL_HOST);
  246. $cookie_path = rtrim(parse_url($this->https_url, PHP_URL_PATH), '/') . COOKIEPATH;
  247. $cookie_path_site = rtrim(parse_url($this->https_url, PHP_URL_PATH), '/') . SITECOOKIEPATH;
  248. $cookie_path_plugins = rtrim(parse_url($this->https_url, PHP_URL_PATH), '/') . PLUGINS_COOKIE_PATH;
  249. $cookie_path_admin = $cookie_path_site . 'wp-admin';
  250. setcookie(AUTH_COOKIE, ' ', time() - 31536000, $cookie_path_admin, $cookie_domain);
  251. setcookie(AUTH_COOKIE, ' ', time() - 31536000, $cookie_path_plugins, $cookie_domain);
  252. setcookie(SECURE_AUTH_COOKIE, ' ', time() - 31536000, $cookie_path_admin, $cookie_domain);
  253. setcookie(SECURE_AUTH_COOKIE, ' ', time() - 31536000, $cookie_path_plugins, $cookie_domain);
  254. setcookie(LOGGED_IN_COOKIE, ' ', time() - 31536000, $cookie_path, $cookie_domain);
  255. setcookie(LOGGED_IN_COOKIE, ' ', time() - 31536000, $cookie_path_site, $cookie_domain);
  256. }
  257. /**
  258. * Checks if a user is logged in, if not it redirects them to the login page.
  259. *
  260. * @param none
  261. * @return void
  262. */
  263. function auth_redirect() {
  264. if ( $this->is_ssl() || force_ssl_admin() )
  265. $secure = true;
  266. else
  267. $secure = false;
  268. // If https is required and request is http, redirect
  269. if ( $secure && !$this->is_ssl() && false !== strpos($_SERVER['REQUEST_URI'], 'wp-admin') ) {
  270. $this->redirect('https');
  271. }
  272. if ( $user_id = wp_validate_auth_cookie( '', apply_filters( 'auth_redirect_scheme', '' ) ) ) {
  273. do_action('auth_redirect', $user_id);
  274. // If the user wants ssl but the session is not ssl, redirect.
  275. if ( !$secure && get_user_option('use_ssl', $user_id) && false !== strpos($_SERVER['REQUEST_URI'], 'wp-admin') ) {
  276. $this->redirect('https');
  277. }
  278. return; // The cookie is good so we're done
  279. }
  280. // The cookie is no good so force login
  281. nocache_headers();
  282. if ( $this->is_ssl() )
  283. $proto = 'https://';
  284. else
  285. $proto = 'http://';
  286. $redirect = ( strpos($_SERVER['REQUEST_URI'], '/options.php') && wp_get_referer() ) ? wp_get_referer() : $proto . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
  287. // Rewrite URL to Shared SSL URL
  288. if ( $this->shared_ssl && strpos($redirect, 'https://') !== false ) {
  289. $redirect = $this->replace_http_url( $redirect );
  290. }
  291. $login_url = wp_login_url($redirect);
  292. wp_redirect($login_url);
  293. exit();
  294. }
  295. /**
  296. * Process output buffer
  297. *
  298. * @param string $buffer
  299. * @return string $buffer
  300. */
  301. function process($buffer) {
  302. if ( $this->is_ssl() ) {
  303. // Fix the regular stuff
  304. if ( is_admin() ) {
  305. preg_match_all('/\<(script|link|img)[^>]+((http|https):\/\/[\/-\w\.#?=\+&;]+)[^>]+>/im', $buffer, $matches);
  306. } else {
  307. preg_match_all('/\<(script|link|img|input|form|embed|param)[^>]+((http|https):\/\/[\/-\w\.#?=\+&;]+)[^>]+>/im', $buffer, $matches);
  308. }
  309. $external_urls = get_option('wordpress-https_external_urls');
  310. for ($i = 0; $i<=sizeof($matches[0]); $i++) {
  311. $html = $matches[0][$i];
  312. $type = $matches[1][$i];
  313. $url = $matches[2][$i];
  314. $scheme = $matches[3][$i];
  315. if ( $type == 'img' || $type == 'script' || $type == 'embed' ||
  316. ( $type == 'link' && ( strpos($html, 'stylesheet') !== false || strpos($html, 'pingback') !== false ) ) ||
  317. ( $type == 'form' && ( strpos($html, 'loginform') !== false || strpos($html, 'wp-pass.php') !== false ) ) ||
  318. ( $type == 'input' && strpos($html, 'image') !== false ) ||
  319. ( $type == 'param' && strpos($html, 'movie') !== false )
  320. ) {
  321. if ( is_admin() && $type == 'img' ) {
  322. if ( strpos($url, $this->replace_http($this->http_url)) !== false && $this->shared_ssl ) {
  323. $buffer = str_replace($html, str_replace($url, $this->replace_http_url($url), $html), $buffer);
  324. }
  325. } else {
  326. if ( strpos($url, $this->http_url) !== false && get_option('wordpress-https_internalurls') == 1 ) {
  327. $buffer = str_replace($html, str_replace($url, $this->replace_http_url($url), $html), $buffer);
  328. } else if ( strpos($url, $this->replace_http($this->http_url)) !== false && $this->shared_ssl ) {
  329. $buffer = str_replace($html, str_replace($url, $this->replace_http_url($url), $html), $buffer);
  330. } else if ( $this->shared_ssl && get_option('wordpress-https_internalurls') == 1 && strpos($html, $this->http_url) !== false ) {
  331. $buffer = str_replace($html, str_replace($url, $this->replace_http_url($url), $html), $buffer);
  332. } else if ( strpos($url, $this->https_url) === false && strpos($url, 'https://') === false && get_option('wordpress-https_externalurls') == 1 ) {
  333. if ( get_option('wordpress-https_bypass') == 1 ) {
  334. $buffer = str_replace($html, str_replace($url, $this->replace_http($url), $html), $buffer);
  335. } else if ( in_array($url, $external_urls) || @file_get_contents($this->replace_http($url)) !== false ) {
  336. $buffer = str_replace($html, str_replace($url, $this->replace_http($url), $html), $buffer);
  337. // Cache this URL as available over HTTPS for future reference
  338. if ( !in_array($url, $external_urls) ) {
  339. $external_urls[] = $url;
  340. update_option('wordpress-https_external_urls', $external_urls);
  341. }
  342. }
  343. }
  344. }
  345. }
  346. }
  347. // Fix any CSS background images
  348. preg_match_all('/background: url\([\'"]?(http:\/\/[\/-\w\.#?=\+&;]+)[\'"]?\)/im', $buffer, $matches);
  349. for ($i = 0; $i<=sizeof($matches[0]); $i++) {
  350. $css = $matches[0][$i];
  351. $url = $matches[1][$i];
  352. $buffer = str_replace($css, str_replace($url, $this->replace_http_url($url), $css), $buffer);
  353. }
  354. // Look for any relative paths that should be udpated to the Shared SSL path
  355. if ( $this->shared_ssl ) {
  356. preg_match_all('/\<(script|link|img|input|form|embed|param|a)[^>]+[\'"](\/[\/-\w\.#?=\+&;]*)[^>]+>/im', $buffer, $matches);
  357. for ($i = 0; $i<=sizeof($matches[0]); $i++) {
  358. $html = $matches[0][$i];
  359. $type = $matches[1][$i];
  360. $url = $matches[2][$i];
  361. if ( $type != 'input' || ( $type == 'input' && strpos($html, 'image') !== false ) ) {
  362. $buffer = str_replace($html, str_replace($url, $this->https_url . $url, $html), $buffer);
  363. }
  364. }
  365. }
  366. }
  367. // Update anchor and form tags to appropriate URL's
  368. preg_match_all('/\<(a|form)[^>]+[\'"]((http|https):\/\/[\/-\w\.#?=\+&;]+)[^>]+>/im', $buffer, $matches);
  369. for ($i = 0; $i<=sizeof($matches[0]); $i++) {
  370. $html = $matches[0][$i];
  371. $type = $matches[1][$i];
  372. $url = $matches[2][$i];
  373. $scheme = $matches[3][$i];
  374. unset($force_ssl);
  375. $url_path = parse_url($url, PHP_URL_PATH);
  376. if ( $this->shared_ssl ) {
  377. $url_path = str_replace(parse_url($this->https_url, PHP_URL_PATH), '', $url_path);
  378. }
  379. $url_path = str_replace(parse_url(get_option('home'), PHP_URL_PATH), '', $url_path);
  380. if ( preg_match("/page_id=([\d]+)/", parse_url($url, PHP_URL_QUERY), $postID) == 1 ) {
  381. $post = $postID[1];
  382. } else if ( $post = get_page_by_path($url_path) ) {
  383. $post = $post->ID;
  384. } else if ( $url_path == '/' ) {
  385. if ( get_option('show_on_front') == 'posts' ) {
  386. $post = true;
  387. $force_ssl = (( get_option('wordpress-https_frontpage') == 1 ) ? true : false);
  388. } else {
  389. $post = get_option('page_on_front');
  390. }
  391. }
  392. if ( $post ) {
  393. $force_ssl = (( !isset($force_ssl) ) ? get_post_meta($post, 'force_ssl', true) : $force_ssl);
  394. if ( $force_ssl ) {
  395. $buffer = str_replace($html, str_replace($url, $this->replace_http_url($url), $html), $buffer);
  396. } else if ( get_option('wordpress-https_exclusive_https') == 1 ) {
  397. $buffer = str_replace($html, str_replace($this->https_url, $this->http_url, $html), $buffer);
  398. }
  399. }
  400. }
  401. // Fix any anchor or form tags that contain the HTTPS version of the regular domain when using Shared SSL
  402. if ( $this->shared_ssl && get_option('wordpress-https_internalurls') == 1 ) {
  403. $regex_url = preg_quote($this->replace_http($this->http_url));
  404. $regex_url = str_replace('/', '\/', $regex_url);
  405. preg_match_all('/\<(a|form)[^>]+(' . $regex_url . ')[^>]+>/im', $buffer, $matches);
  406. for ($i = 0; $i<=sizeof($matches[0]); $i++) {
  407. $html = $matches[0][$i];
  408. $type = $matches[1][$i];
  409. $url = $matches[2][$i];
  410. $buffer = str_replace($html, str_replace($url, $this->https_url, $html), $buffer);
  411. }
  412. }
  413. return $buffer;
  414. }
  415. /**
  416. * Checks if the current page is SSL
  417. *
  418. * @param none
  419. * @return bool
  420. */
  421. function is_ssl() {
  422. // Some extra checks for proxies and Shared SSL
  423. if ( isset($_SERVER['HTTP_X_URL_SCHEME']) && isset($_SERVER['HTTP_X_FORWARDED_SERVER']) && !is_ssl() && strpos($this->https_url, $_SERVER['HTTP_X_URL_SCHEME'] . '://' . $_SERVER['HTTP_X_FORWARDED_SERVER']) !== false ) {
  424. return true;
  425. } else if ( $this->shared_ssl && !is_ssl() && strpos($this->https_url, $_SERVER['HTTP_HOST']) !== false ) {
  426. return true;
  427. }
  428. return is_ssl();
  429. }
  430. /**
  431. * Checks if the current page needs to be redirected
  432. *
  433. * @param none
  434. * @return void
  435. */
  436. function check_https() {
  437. global $post;
  438. if ( is_front_page() && get_option('show_on_front') == 'posts' ) {
  439. if ( get_option('wordpress-https_frontpage') == 1 && !$this->is_ssl() ) {
  440. $this->redirect('https');
  441. } else if ( get_option('wordpress-https_frontpage') != 1 && get_option('wordpress-https_exclusive_https') == 1 && $this->is_ssl() ) {
  442. $this->redirect('http');
  443. }
  444. } else if ( ( is_single() || is_page() || is_front_page() || is_home() ) && $post->ID > 0 ) {
  445. $forceSSL = get_post_meta($post->ID, 'force_ssl', true);
  446. if ( !$this->is_ssl() && $forceSSL ) {
  447. $this->redirect('https');
  448. } else if ( get_option('wordpress-https_exclusive_https') == 1 && !$forceSSL ) {
  449. $this->redirect('http');
  450. }
  451. }
  452. }
  453. /**
  454. * Redirects page to HTTP or HTTPS accordingly
  455. *
  456. * @param string $scheme Either http or https
  457. * @return void
  458. */
  459. function redirect($scheme = 'https') {
  460. if ( !$this->is_ssl() && $scheme == 'https' ) {
  461. $url = parse_url($this->https_url);
  462. $url['scheme'] = $scheme;
  463. } else if ( $this->is_ssl() && $scheme == 'http' ) {
  464. $url = parse_url($this->http_url);
  465. $url['scheme'] = $scheme;
  466. } else {
  467. $url = false;
  468. }
  469. if ( $url ) {
  470. $destination = $url['scheme'] . '://' . $url['host'] . (( $this->shared_ssl ) ? $url['path'] : '') . $_SERVER['REQUEST_URI'];
  471. if ( function_exists('wp_redirect') ) {
  472. wp_redirect($destination, 301);
  473. } else {
  474. // End all output buffering and redirect
  475. while(@ob_end_clean());
  476. header("Location: " . $destination);
  477. }
  478. exit();
  479. }
  480. }
  481. /**
  482. * Add 'Force SSL' checkbox to add/edit post pages
  483. *
  484. * @param none
  485. * @return void
  486. */
  487. function post_checkbox() {
  488. global $post;
  489. wp_nonce_field(plugin_basename(__FILE__), 'wordpress-https');
  490. $checked = false;
  491. if ( $post->ID ) {
  492. $checked = get_post_meta($post->ID, 'force_ssl', true);
  493. }
  494. echo '<div class="misc-pub-section misc-pub-section-last" style="border-top: 1px solid #EEE;"><label>Force SSL: <input type="checkbox" value="1" name="force_ssl" id="force_ssl"'.(($checked) ? ' checked="checked"' : '').' /></label></div>';
  495. }
  496. /**
  497. * Save Force SSL option to post or page
  498. *
  499. * @param int $post_id
  500. * @return int $post_id
  501. */
  502. function post_save( $post_id ) {
  503. if ( array_key_exists('wordpress-https', $_POST) ) {
  504. if ( !wp_verify_nonce($_POST['wordpress-https'], plugin_basename(__FILE__))) {
  505. return $post_id;
  506. }
  507. if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) {
  508. return $post_id;
  509. }
  510. if ( $_POST['post_type'] == 'page' ) {
  511. if ( !current_user_can('edit_page', $post_id) ) {
  512. return $post_id;
  513. }
  514. } else {
  515. if ( !current_user_can('edit_post', $post_id) ) {
  516. return $post_id;
  517. }
  518. }
  519. $forceSSL = (( $_POST['force_ssl'] == 1 ) ? true : false);
  520. if ( $forceSSL ) {
  521. update_post_meta($post_id, 'force_ssl', 1);
  522. } else {
  523. delete_post_meta($post_id, 'force_ssl');
  524. }
  525. return $forceSSL;
  526. }
  527. return $post_id;
  528. }
  529. /**
  530. * Filters HTTPS urls from bloginfo function
  531. *
  532. * @param string $result
  533. * @param string $show
  534. * @return string $result
  535. */
  536. function bloginfo($result = '', $show = '') {
  537. if ( $show == 'stylesheet_url' || $show == 'template_url' || $show == 'wpurl' || $show == 'home' || $show == 'siteurl' || $show == 'url' ) {
  538. $result = $this->replace_https($result);
  539. }
  540. return $result;
  541. }
  542. /**
  543. * Add admin panel menu option
  544. *
  545. * @param none
  546. * @return void
  547. */
  548. function menu() {
  549. add_options_page('WordPress HTTPS Settings', 'WordPress HTTPS', 'manage_options', 'wordpress-https', array(&$this, 'settings'));
  550. }
  551. /**
  552. * Add plugin links to Manage Plugins page in admin panel
  553. *
  554. * @param array $links
  555. * @param string $file
  556. * @return array $links
  557. */
  558. function plugin_links($links, $file) {
  559. if ( strpos($file, basename( __FILE__)) === false ) {
  560. return $links;
  561. }
  562. $links[] = '<a href="' . site_url() . '/wp-admin/options-general.php?page=wordpress-https" title="WordPress HTTPS Settings">Settings</a>';
  563. $links[] = '<a href="http://wordpress.org/extend/plugins/wordpress-https/faq/" title="Frequently Asked Questions">FAQ</a>';
  564. $links[] = '<a href="http://wordpress.org/tags/wordpress-https#postform" title="Support">Support</a>';
  565. $links[] = '<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=N9NFVADLVUR7A" title="Support WordPress HTTPS development with a donation!">Donate</a>';
  566. return $links;
  567. }
  568. /**
  569. * Start output buffering
  570. *
  571. * @param none
  572. * @return void
  573. */
  574. function buffer_start() {
  575. if ( get_option('wordpress-https_externalurls') == 1 && get_option('wordpress-https_bypass') != 1 ) {
  576. @ini_set('allow_url_fopen', 1);
  577. }
  578. ob_start(array(&$this, 'process'));
  579. }
  580. /**
  581. * End output buffering
  582. *
  583. * @param none
  584. * @return void
  585. */
  586. function buffer_end() {
  587. ob_end_flush();
  588. }
  589. /**
  590. * Replaces HTTP URL to HTTPS URL
  591. *
  592. * @param string $string
  593. * @return string $string
  594. */
  595. function replace_http_url($string) {
  596. preg_match_all('/(http|https):\/\/[\/-\w\.#?=\+&;]+/im', $string, $url);
  597. $url = $url[0][0];
  598. // If URL matches home_url, but lacks www, add www
  599. if ( strpos(get_option('home'), '://www.') !== false && strpos($url, '://www.') === false && parse_url($url, PHP_URL_HOST) != NULL ) {
  600. $url_host = parse_url($url, PHP_URL_HOST);
  601. $url_host_www = 'www.' . $url_host;
  602. if ( strpos(get_option('home'), $url_host_www) !== false ) {
  603. $string = str_replace($url_host, $url_host_www, $string);
  604. }
  605. }
  606. // Replace the HTTPS version of the domain with $this->https_url for Shared SSL
  607. $string = str_replace($this->replace_http($this->http_url), $this->https_url, $string);
  608. $string = str_replace($this->http_url, $this->https_url, $string);
  609. return $string;
  610. }
  611. /**
  612. * Replace HTTPS with HTTP
  613. *
  614. * @param string $string
  615. * @return string $string
  616. */
  617. function replace_https($string) {
  618. return str_replace('https://', 'http://', $string);
  619. }
  620. /**
  621. * Replace HTTP with HTTPS
  622. *
  623. * @param string $string
  624. * @return string $string
  625. */
  626. function replace_http($string) {
  627. return str_replace('http://', 'https://', $string);
  628. }
  629. /**
  630. * Settings page in admin panel
  631. *
  632. * @param none
  633. * @return void
  634. */
  635. function settings() {
  636. if ( !current_user_can('manage_options') ) {
  637. wp_die( __('You do not have sufficient permissions to access this page.') );
  638. }
  639. if ( $_SERVER['REQUEST_METHOD'] === 'POST' ) {
  640. $errors = array();
  641. foreach ($this->options_default as $key => $default) {
  642. if ( !array_key_exists($key, $_POST) && $default == 0 ) {
  643. $_POST[$key] = 0;
  644. update_option($key, $_POST[$key]);
  645. } else {
  646. if ( $key == 'wordpress-https_sharedssl_host' ) {
  647. if ( isset($_POST[$key]) ) {
  648. $url = parse_url($_POST[$key]);
  649. }
  650. if ( sizeof($url) > 1 ) {
  651. $_POST[$key] = 'https://' . $url['host'] . @$url['path'];
  652. if ( substr($_POST[$key], -1, 1) == '/' ) {
  653. $_POST[$key] = substr($_POST[$key], 0, strlen($_POST[$key])-1);
  654. }
  655. } else if ( $_POST['wordpress-https_sharedssl'] == 1 ) {
  656. $errors[] = '<strong>Shared SSL Host</strong> - Invalid host.';
  657. update_option('wordpress-https_sharedssl', 0);
  658. }
  659. } else if ( $key == 'wordpress-https_sharedssl_admin' ) {
  660. if ( force_ssl_admin() || force_ssl_login() ) {
  661. $errors[] = '<strong>Shared SSL Admin</strong> - FORCE_SSL_ADMIN and FORCE_SSL_LOGIN can not be set to true in your wp-config.php.';
  662. $_POST[$key] = 0;
  663. }
  664. } else if ( $key == 'wordpress-https_externalurls' && @ini_get('allow_url_fopen') != 1 ) {
  665. $errors[] = '<strong>External HTTPS Elements</strong> - PHP configuration error: allow_url_fopen must be enabled.';
  666. $_POST[$key] = 0;
  667. } else if ( $key == 'wordpress-https_disable_autohttps' && version_compare(get_bloginfo('version'), '3.0', '<') ) {
  668. $_POST[$key] = 0;
  669. }
  670. update_option($key, $_POST[$key]);
  671. }
  672. }
  673. if ( array_key_exists('ajax', $_POST) ) {
  674. while(@ob_end_clean());
  675. ob_start();
  676. if ( sizeof( $errors ) > 0 ) {
  677. echo "<div class=\"error below-h2 fade\" id=\"message\">\n\t<ul>\n";
  678. foreach ( $errors as $error ) {
  679. echo "\t\t<li><p>".$error."</p></li>\n";
  680. }
  681. echo "\t</ul>\n</div>\n";
  682. } else {
  683. echo "<div class=\"updated below-h2 fade\" id=\"message\"><p>Settings saved.</p></div>\n";
  684. }
  685. exit();
  686. }
  687. }
  688. ?>
  689. <div class="wrap">
  690. <div id="icon-options-general" class="icon32"><br /></div>
  691. <h2>WordPress HTTPS Settings</h2>
  692. <?php
  693. if ( $_SERVER['REQUEST_METHOD'] === 'POST' ) {
  694. if ( sizeof( $errors ) > 0 ) {
  695. echo "<div class=\"error below-h2 fade\" id=\"message\">\n\t<ul>\n";
  696. foreach ( $errors as $error ) {
  697. echo "\t\t<li><p>".$error."</p></li>\n";
  698. }
  699. echo "\t</ul>\n</div>\n";
  700. } else {
  701. echo "\t\t<div class=\"updated below-h2 fade\" id=\"message\"><p>Settings saved.</p></div>\n";
  702. }
  703. } else {
  704. echo "\t<div id=\"message-wrap\"><div id=\"message-body\"></div></div>\n";
  705. }
  706. ?>
  707. <div id="wphttps-sidebar">
  708. <div class="wphttps-widget" id="wphttps-updates">
  709. <h3 class="wphttps-widget-title">Developer Updates</h3>
  710. <div class="wphttps-widget-content"><img alt="Loading..." src="<?php echo parse_url($this->plugin_url, PHP_URL_PATH); ?>/css/images/wpspin_light.gif" class="loading" id="updates-loading" /></div>
  711. </div>
  712. <div class="wphttps-widget" id="wphttps-support">
  713. <h3 class="wphttps-widget-title">Support</h3>
  714. <div class="wphttps-widget-content">
  715. <p>Have you tried everything and your website is still giving you partially encrypted errors?</p>
  716. <p>If you haven't already, check out the <a href="http://wordpress.org/extend/plugins/wordpress-https/faq/" target="_blank">Frequently Asked Questions</a>.</p>
  717. <p>Still not fixed? Having other problems? Please <a href="http://wordpress.org/tags/wordpress-https#postform" target="_blank">start a support topic</a> and I'll do my best to assist you.</p>
  718. </div>
  719. </div>
  720. <div class="wphttps-widget" id="wphttps-donate">
  721. <h3 class="wphttps-widget-title">Donate</h3>
  722. <div class="wphttps-widget-content">
  723. <p>If you found this plugin useful, or I've already helped you with your website, please considering buying me a <a href="http://en.wikipedia.org/wiki/Newcastle_Brown_Ale" target="_blank">beer</a> or two.</p>
  724. <p>Donations help alleviate the time spent developing and supporting this plugin and are greatly appreciated.</p>
  725. <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
  726. <input type="hidden" name="cmd" value="_s-xclick">
  727. <input type="hidden" name="hosted_button_id" value="N9NFVADLVUR7A">
  728. <input type="image" src="https://www.paypal.com/en_US/i/btn/btn_donate_SM.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
  729. <img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
  730. </form>
  731. </div>
  732. </div>
  733. </div>
  734. <div id="wphttps-main">
  735. <div id="post-body">
  736. <form name="form" id="wordpress-https" action="options-general.php?page=wordpress-https" method="post">
  737. <?php settings_fields('wordpress-https'); ?>
  738. <fieldset>
  739. <label for="wordpress-https_internalurls"><input name="wordpress-https_internalurls" type="checkbox" id="wordpress-https_internalurls" value="1"<?php echo ((get_option('wordpress-https_internalurls')) ? ' checked="checked"' : ''); ?> /> <strong>Internal HTTPS Elements</strong></label>
  740. <p>Force internal elements to HTTPS when viewing a secure page.</p>
  741. <p class="description">Fixes most partially encrypted errors.</p>
  742. </fieldset>
  743. <fieldset>
  744. <label for="wordpress-https_externalurls"><input name="wordpress-https_externalurls" type="checkbox" id="wordpress-https_externalurls" value="1"<?php echo ((get_option('wordpress-https_externalurls')) ? ' checked="checked"' : ''); ?> /> <strong>External HTTPS Elements</strong></label>
  745. <p>Attempt to automatically force external elements to HTTPS when viewing a secure page. External elements are any element not hosted on your domain.</p>
  746. <p class="description">Warning: This option checks that the external element can be loaded via HTTPS while the page is loading. Depending on the amount of external elements, this could affect the load times of your pages.</p>
  747. </fieldset>
  748. <fieldset>
  749. <label for="wordpress-https_bypass"><input name="wordpress-https_bypass" type="checkbox" id="wordpress-https_bypass" value="1"<?php echo ((get_option('wordpress-https_bypass')) ? ' checked="checked"' : ''); ?> /> <strong>Bypass External Check</strong></label>
  750. <p>Disable the option to check if an external element can be loaded over HTTPS.</p>
  751. <p class="description">Warning: Bypassing the HTTPS check for external elements may cause elements to not load at all. Only enable this option if you know that all external elements can be loaded over HTTPS.</p>
  752. </fieldset>
  753. <?php if ( version_compare(get_bloginfo('version'), '3.0', '>=') ) { ?>
  754. <fieldset>
  755. <label for="wordpress-https_disable_autohttps"><input name="wordpress-https_disable_autohttps" type="checkbox" id="wordpress-https_disable_autohttps" value="1"<?php echo ((get_option('wordpress-https_disable_autohttps')) ? ' checked="checked"' : ''); ?> /> <strong>Disable Automatic HTTPS</strong></label>
  756. <p>Prevents WordPress 3.0+ from making all links HTTPS when viewing a secure page.</p>
  757. <p class="description">When a page is viewed via HTTPS in WordPress 3.0+, all internal page, category and post links are forced to HTTPS. This option will disable that.</p>
  758. </fieldset>
  759. <?php } ?>
  760. <fieldset>
  761. <label for="wordpress-https_exclusive_https"><input name="wordpress-https_exclusive_https" type="checkbox" id="wordpress-https_exclusive_https" value="1"<?php echo ((get_option('wordpress-https_exclusive_https')) ? ' checked="checked"' : ''); ?> /> <strong>Force SSL Exclusively</strong></label>
  762. <p>Exclusively force SSL on posts and pages with the `Force SSL` option checked. All others are redirected to HTTP.</p>
  763. <p class="description">WordPress HTTPS adds a 'Force SSL' checkbox to each post and page right above the publish button (<a href="<?php echo $this->plugin_url; ?>/screenshot-2.png" class="thickbox">screenshot</a>). When selected, the post or page will be forced to HTTPS. With this option enabled, all posts and pages without 'Force SSL' checked will be redirected to HTTP.</p>
  764. </fieldset>
  765. <fieldset>
  766. <label for="wordpress-https_sharedssl"><input name="wordpress-https_sharedssl" type="checkbox" id="wordpress-https_sharedssl" value="1"<?php echo ((get_option('wordpress-https_sharedssl')) ? ' checked="checked"' : ''); ?> /> <strong>Shared SSL</strong></label>
  767. <p>Enable this option if you are using a Shared SSL certificate and your Shared SSL Host is something other than '<?php echo $this->replace_http($this->http_url); ?>/'.</p>
  768. <label><strong>Shared SSL Host</strong> <input name="wordpress-https_sharedssl_host" type="text" id="wordpress-https_sharedssl_host" value="<?php echo get_option('wordpress-https_sharedssl_host'); ?>" /></label>
  769. </fieldset>
  770. <fieldset>
  771. <label for="wordpress-https_sharedssl_admin"><input name="wordpress-https_sharedssl_admin" type="checkbox" id="wordpress-https_sharedssl_admin" value="1"<?php echo ((get_option('wordpress-https_sharedssl_admin')) ? ' checked="checked"' : ''); ?> /> <strong>Force Shared SSL Admin</strong></label>
  772. <p>Enable this option if you are using a Shared SSL certificate and you only want to access your admin panel over HTTPS.</p>
  773. <p class="description">Notice: FORCE_SSL_ADMIN and FORCE_SSL_LOGIN can not be set to true in your wp-config.php.</p>
  774. </fieldset>
  775. <?php if ( get_option('show_on_front') == 'posts' ) { ?>
  776. <fieldset>
  777. <label for="wordpress-https_frontpage"><input name="wordpress-https_frontpage" type="checkbox" id="wordpress-https_frontpage" value="1"<?php echo ((get_option('wordpress-https_frontpage')) ? ' checked="checked"' : ''); ?> /> <strong>HTTPS Front Page</strong></label>
  778. <p>It appears you are using your latest posts for your home page. If you would like that page to have SSL enforced, enable this option.</p>
  779. </fieldset>
  780. <?php } ?>
  781. <p class="button-controls">
  782. <input type="submit" name="Submit" value="Save Changes" class="button-primary" />
  783. <img alt="Waiting..." src="<?php echo parse_url($this->plugin_url, PHP_URL_PATH); ?>/css/images/wpspin_light.gif" class="waiting" id="submit-waiting" />
  784. </p>
  785. </form>
  786. </div>
  787. </div>
  788. <?php
  789. }
  790. } // End WordPressHTTPS Class
  791. }
  792. if ( class_exists('WordPressHTTPS') ) {
  793. $wordpress_https = new WordPressHTTPS();
  794. register_activation_hook( __FILE__, array(&$wordpress_https, 'install'));
  795. }
  796. // Use WordPress HTTPS wp_set_auth_cookie method for WordPress' wp_set_auth_cookie pluggable function if using Shared SSL
  797. if ( $wordpress_https->shared_ssl && !function_exists('wp_set_auth_cookie') ) {
  798. function wp_set_auth_cookie($user_id, $remember, $secure) {
  799. global $wordpress_https;
  800. return $wordpress_https->wp_set_auth_cookie($user_id, $remember, $secure);
  801. }
  802. }
  803. // Use WordPress HTTPS auth_redirect method for WordPress' auth_redirect pluggable function if using Shared SSL
  804. if ( $wordpress_https->shared_ssl && !function_exists('auth_redirect') ) {
  805. function auth_redirect() {
  806. global $wordpress_https;
  807. return $wordpress_https->auth_redirect();
  808. }
  809. }