PluginProbe ʕ •ᴥ•ʔ
WP Force SSL & HTTPS SSL Redirect / 1.66
WP Force SSL & HTTPS SSL Redirect v1.66
trunk 1.4 1.5 1.55 1.56 1.57 1.60 1.65 1.66 1.67 1.68 1.69
wp-force-ssl / wp-force-ssl.php
wp-force-ssl Last commit date
css 4 years ago img 4 years ago inc 2 years ago js 4 years ago wf-flyout 4 years ago index.php 6 years ago license.txt 6 years ago readme.txt 2 years ago wp-force-ssl.php 2 years ago
wp-force-ssl.php
1210 lines
1 <?php
2 /*
3 Plugin Name: WP Force SSL
4 Plugin URI: https://wpforcessl.com/
5 Description: Redirect all traffic from HTTP to HTTPS and fix other SSL issues.
6 Author: WebFactory Ltd
7 Author URI: https://www.webfactoryltd.com/
8 Version: 1.66
9 Text Domain: wp-force-ssl
10 Requires at least: 4.6
11 Requires PHP: 5.2
12 Tested up to: 6.5
13
14 Copyright 2019 - 2024 WebFactory Ltd (email: support@webfactoryltd.com)
15
16 This program is free software; you can redistribute it and/or modify
17 it under the terms of the GNU General Public License, version 2, as
18 published by the Free Software Foundation.
19
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28 */
29
30
31 // if the file is called directly
32 if (!defined('ABSPATH')) {
33 exit('You are not allowed to access this file directly.');
34 }
35
36 require_once dirname(__FILE__) . '/inc/wp-force-ssl-status-tests.php';
37 require_once dirname(__FILE__) . '/inc/wp-force-ssl-utility.php';
38 require_once dirname(__FILE__) . '/wf-flyout/wf-flyout.php';
39 new wf_flyout(__FILE__);
40
41 define('WPFSSL_OPTIONS_KEY', 'wpfssl_options');
42 define('WPFSSL_META_KEY', 'wpfssl_meta');
43
44
45 // start up the engine
46 class wpForceSSL
47 {
48 protected static $instance = false;
49 public $options = array();
50 public $version = 0;
51 public $plugin_url = '';
52 public $plugin_dir = '';
53 public $meta = array();
54
55
56 /**
57 * Check if minimum WP and PHP versions are available
58 * Register all hooks for the plugin
59 *
60 * @since 1.5
61 *
62 * @return null
63 *
64 */
65 private function __construct()
66 {
67 $this->get_plugin_version();
68
69 if (false === $this->check_wp_version(4.6)) {
70 return false;
71 }
72
73 $this->options = get_option(WPFSSL_OPTIONS_KEY, array());
74 $default = array(
75 'wpfs_ssl' => 'yes',
76 'wpfs_hsts' => 'no',
77 'wpfs_expect_ct' => 'no',
78 'wpfs_adminbar_menu' => 'yes',
79 'wpfs_dashboard_widget' => 'yes'
80 );
81 $this->options = array_merge($default, $this->options);
82
83 $this->plugin_url = plugin_dir_url(__FILE__);
84 $this->plugin_dir = plugin_dir_path(__FILE__);
85 $this->meta = $this->get_meta();
86
87 if ($this->options['wpfs_ssl'] == 'yes') {
88 add_action('template_redirect', array($this, 'wpfs_core'));
89 }
90 if ($this->options['wpfs_hsts'] == 'yes') {
91 add_action('send_headers', array($this, 'to_strict_transport_security'));
92 }
93 if ($this->options['wpfs_expect_ct'] == 'yes') {
94 add_action('send_headers', array($this, 'enable_expect_ct'));
95 }
96
97 add_action('admin_menu', array($this, 'add_settings_page'));
98 add_action('admin_head', array($this, 'cleanup_enqueues'), 99999);
99 add_action('wp_before_admin_bar_render', array($this, 'admin_bar'));
100 add_filter('admin_footer_text', array($this, 'admin_footer_text'));
101 add_action('admin_print_scripts', array($this, 'remove_admin_notices'));
102 add_action('admin_enqueue_scripts', array($this, 'admin_scripts'));
103 add_action('wp_dashboard_setup', array($this, 'add_widget'));
104
105 add_filter('plugin_action_links_' . plugin_basename(__FILE__), array($this, 'plugin_action_links'));
106 add_filter('plugin_row_meta', array($this, 'plugin_meta_links'), 10, 2);
107
108 // ajax hooks for the settings, and SSL certificate test
109 add_action('wp_ajax_wpfs_save_settting', array($this, 'ajax_save_setting'));
110 add_action('wp_ajax_wpfs_test_ssl', array($this, 'ajax_check_ssl'));
111 add_action('wp_ajax_wpfs_run_tests', array($this, 'ajax_run_tests'));
112 add_action('wp_ajax_wpfs_dismiss_notice', array($this, 'ajax_dismiss_notice'));
113 } // __construct
114
115
116 /**
117 * Get plugin meta data, create if not existent
118 *
119 * @since 1.5
120 *
121 * @return array plugin meta
122 *
123 */
124 public function get_meta()
125 {
126 $meta = get_option(WPFSSL_META_KEY, array());
127 $default = array(
128 'first_version' => $this->get_plugin_version(),
129 'first_install' => time(),
130 'hide_welcome_pointer' => false
131 );
132
133 $meta = array_merge($default, $meta);
134 if (sizeof($default) != sizeof($meta)) {
135 update_option(WPFSSL_META_KEY, $meta);
136 }
137
138 return $meta;
139 } // get_meta
140
141
142 /**
143 * Dismiss notice via AJAX call
144 *
145 * @return null
146 */
147 function ajax_dismiss_notice()
148 {
149 check_ajax_referer('wpfs_dismiss_notice');
150
151 if (!current_user_can('administrator')) {
152 wp_send_json_error('You are not allowed to run this action.');
153 }
154
155 $notice_name = trim(sanitize_text_field(@$_GET['notice_name']));
156
157 if ($notice_name != 'welcome') {
158 wp_send_json_error('Unknown notice');
159 } else {
160 $this->meta['hide_welcome_pointer'] = true;
161 update_option(WPFSSL_META_KEY, $this->meta);
162 wp_send_json_success();
163 }
164 } // ajax_dismiss_notice
165
166
167 /**
168 * Get plugin version
169 *
170 * @since 1.5
171 *
172 * @return string plugin version
173 *
174 */
175 public function get_plugin_version()
176 {
177 $plugin_data = get_file_data(__FILE__, array('version' => 'Version'), 'plugin');
178 $this->version = $plugin_data['version'];
179
180 return $plugin_data['version'];
181 } // get_plugin_version
182
183
184 /**
185 * Return instance, create if not already existing
186 *
187 * @since 1.5
188 *
189 * @return object wpForceSLL instance
190 *
191 */
192 public static function get_instance()
193 {
194 if (false == is_a(self::$instance, 'wpForceSSL')) {
195 self::$instance = new self;
196 }
197
198 return self::$instance;
199 } // get_instance
200
201
202 /**
203 * Run websites tests
204 *
205 * @return null
206 */
207 function ajax_run_tests()
208 {
209 global $wp_force_ssl_tests;
210
211 check_ajax_referer('run_tests_nonce_action');
212 if (!current_user_can('administrator')) {
213 wp_send_json_error('You are not allowed to run this action.');
214 }
215
216 if (isset($_REQUEST['force']) && (bool) $_REQUEST['force'] === true) {
217 $nocache = true;
218 } else {
219 $nocache = false;
220 }
221
222 $res = $wp_force_ssl_tests->get_tests_results($nocache);
223 if (is_wp_error($res)) {
224 wp_send_json_error($res->get_error_message());
225 } else {
226 wp_send_json_success($res);
227 }
228 } // ajax_run_tool
229
230
231 /**
232 * Enqueue admin scripts
233 *
234 * @since 1.5
235 *
236 * @return null
237 *
238 */
239 public function admin_scripts($hook)
240 {
241 $meta = $this->get_meta();
242 $pointers = array();
243
244 if (!$meta['hide_welcome_pointer'] && !$this->is_plugin_page() && current_user_can('administrator')) {
245 $pointers['_nonce_dismiss_pointer'] = wp_create_nonce('wpfs_dismiss_notice');
246 $pointers['welcome'] = array('target' => '#menu-settings', 'edge' => 'left', 'align' => 'right', 'content' => 'Thank you for installing the <b style="font-weight: 800;">WP Force SSL</b> plugin!<br>Open <a href="' . admin_url('options-general.php?page=wpfs-settings') . '">Settings - WP Force SSL</a> to access SSL settings.');
247
248 wp_enqueue_style('wp-pointer');
249
250 wp_enqueue_script('wp-force-ssl-pointers', $this->plugin_url . 'js/wpfs-pointers.js', array('jquery'), $this->version, true);
251 wp_enqueue_script('wp-pointer');
252 wp_localize_script('wp-pointer', 'wp_force_ssl_pointers', $pointers);
253 }
254
255 if (false == $this->is_plugin_page()) {
256 return;
257 }
258
259 wp_enqueue_style('wpfs-style', $this->plugin_url . 'css/wpfs-style.css', null, $this->version);
260 wp_enqueue_style('wpfs-sweetalert2-style', $this->plugin_url . 'css/sweetalert2.min.css', null, $this->version);
261 wp_enqueue_style('wp-jquery-ui-dialog');
262
263 wp_enqueue_script('jquery-ui-tabs');
264 wp_enqueue_script('jquery-ui-core');
265 wp_enqueue_script('jquery-ui-position');
266 wp_enqueue_script('jquery-ui-dialog');
267
268 wp_enqueue_script('wpfs-sweetalert2', $this->plugin_url . 'js/sweetalert2.min.js', array('jquery'), $this->version, true);
269 wp_enqueue_script('wpfs-script', $this->plugin_url . 'js/wpfs-script.js', array('jquery'), $this->version, true);
270
271 wp_localize_script('wpfs-script', 'wpfs', array(
272 'ajaxurl' => admin_url('admin-ajax.php'),
273 'loading_icon_url' => plugins_url('img/wp-ssl.png', __FILE__),
274 'testing' => __('Testing. Please wait ...', 'wp-force-ssl'),
275 'saving' => __('Saving. Please wait ...', 'wp-force-ssl'),
276 'test_success' => __('Test Completed Successfully', 'wp-force-ssl'),
277 'test_failed' => __('Test Failed', 'wp-force-ssl'),
278 'home_url' => get_home_url(),
279 'save_success' => __('Settings saved', 'wp-force-ssl'),
280 'undocumented_error' => __('An undocumented error has occurred. Please refresh the page and try again.', 'wp-force-ssl'),
281 'documented_error' => __('An error has occurred.', 'wp-force-ssl'),
282 'nonce_save_settings' => wp_create_nonce('save_settting_nonce_action'),
283 'nonce_test_ssl' => wp_create_nonce('test_ssl_nonce_action'),
284 'nonce_run_tests' => wp_create_nonce('run_tests_nonce_action')
285 ));
286
287 $this->cleanup_enqueues();
288 } // admin_scripts
289
290
291 /**
292 * Load text domain
293 *
294 * @since 1.5
295 *
296 * @return null
297 *
298 */
299 static function plugins_loaded()
300 {
301 load_plugin_textdomain('wp-force-ssl');
302 } // plugins_loaded
303
304
305 /**
306 * Register menu page
307 *
308 * @since 1.5
309 *
310 * @return null
311 *
312 */
313 public function add_settings_page()
314 {
315 global $wp_force_ssl_tests;
316 $test_results = $wp_force_ssl_tests->count_statuses();
317
318 add_options_page(
319 __('WP Force SSL', 'wp-force-ssl'),
320 __('WP Force SSL', 'wp-force-ssl') . ($test_results['fail'] ? sprintf(' <span class="wfssl-failed-tests awaiting-mod">%d</span>', $test_results['fail']) : ''),
321 'administrator',
322 'wpfs-settings',
323 array($this, 'settings_page_content')
324 );
325 } // add_settings_page
326
327
328 /**
329 * Shows admin top menu entry
330 *
331 * @since 1.6
332 *
333 * @return null
334 *
335 */
336 function admin_bar()
337 {
338 if (!is_admin()) {
339 return;
340 }
341
342 global $wp_admin_bar, $wp_force_ssl_tests;
343
344 $test_results = $wp_force_ssl_tests->count_statuses();
345 $plugin_name = __('WP Force SSL', 'wp-force-ssl');
346 $plugin_logo = esc_url($this->plugin_url) . 'img/wp-force-ssl-icon.png';
347
348 if (
349 'yes' != $this->options['wpfs_adminbar_menu'] ||
350 false === current_user_can('administrator') ||
351 false === apply_filters('wp_force_ssl_show_admin_bar', true)
352 ) {
353 return;
354 }
355
356 $title = '<div class="wfssl-adminbar-icon" style="display:inline-block;"><img style="height: 22px; padding: 4px; margin-bottom: -10px; filter: invert(1) brightness(1.2) grayscale(1);" src="' . $plugin_logo . '" alt="' . $plugin_name . '" title="' . $plugin_name . '"></div> <span class="ab-label">' . $plugin_name . '</span>';
357 if ($test_results['fail']) {
358 $title .= sprintf(' <span class="wfssl-failed-tests awaiting-mod" style="display: inline-block;vertical-align: top;box-sizing: border-box;margin: 1px 0 -1px 2px; padding: 0 5px; min-width: 18px;height: 18px; border-radius: 9px;background-color: #d63638; color: #fff; font-size: 11px; line-height: 1.6; text-align: center; z-index: 26;vertical-align: text-bottom;">%d</span>', $test_results['fail']);
359 }
360
361 $wp_admin_bar->add_node(array(
362 'id' => 'wfssl-ab',
363 'title' => $title,
364 'href' => admin_url('options-general.php?page=wpfs-settings'),
365 'parent' => '',
366 ));
367
368 $wp_admin_bar->add_node(array(
369 'id' => 'wfssl-status',
370 'title' => 'Status',
371 'href' => admin_url('options-general.php?page=wpfs-settings#tab_status'),
372 'parent' => 'wfssl-ab'
373 ));
374
375 $wp_admin_bar->add_node(array(
376 'id' => 'wfssl-settings',
377 'title' => 'Settings',
378 'href' => admin_url('options-general.php?page=wpfs-settings#tab_settings'),
379 'parent' => 'wfssl-ab'
380 ));
381
382 $wp_admin_bar->add_node(array(
383 'id' => 'wfssl-scanner',
384 'title' => 'Content Scanner',
385 'href' => admin_url('options-general.php?page=wpfs-settings#tab_scanner'),
386 'parent' => 'wfssl-ab'
387 ));
388
389 $wp_admin_bar->add_node(array(
390 'id' => 'wfssl-snapshots',
391 'title' => 'SSL Certificate',
392 'href' => admin_url('options-general.php?page=wpfs-settings#tab_ssl'),
393 'parent' => 'wfssl-ab'
394 ));
395 } // admin_bar
396
397
398 // add widget to dashboard
399 function add_widget()
400 {
401 if (current_user_can('administrator') && $this->options['wpfs_dashboard_widget'] == 'yes') {
402 add_meta_box('wpfssl_status', 'WP Force SSL Status', array($this, 'widget_content'), 'dashboard', 'side', 'high');
403 }
404 } // add_widget
405
406
407 // render dashboard widget
408 function widget_content()
409 {
410 global $wp_force_ssl_tests;
411 $widget_html = '';
412
413 $tests = $wp_force_ssl_tests->get_tests_results(false);
414 if (is_wp_error($tests)) {
415 wpForceSSL_Utility::wp_kses_wf('<p>Unable to get test results. Sorry :(<br>Open <a href="' . admin_url('options-general.php?page=wpfs-settings#tab_status') . '">WP Force SSL</a> plugin to contact support.</p>');
416 return;
417 }
418
419 $widget_html .= '<style>';
420 $widget_html .= '#wpfssl_status .inside { padding: 0; margin: 0; }';
421 $widget_html .= '#wpfssl_status table td { max-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; border-top: 1px solid #f0f0f1; }';
422 $widget_html .= '#wpfssl_status table { border: none; }';
423 $widget_html .= '#wpfssl_status td .wpfssl-show-hover { color: #dcdcde; display: none; }';
424 $widget_html .= '#wpfssl_status td:hover .wpfssl-show-hover { display: inline; }';
425 $widget_html .= '#wpfssl_status p { padding: 0 12px 12px 12px; }';
426 $widget_html .= '#wpfssl_status .wpfssl-status-fail { border-left: 5px solid #d63638; }';
427 $widget_html .= '#wpfssl_status .wpfssl-status-warning { border-left: 5px solid #ffaa39; }';
428 $widget_html .= '#wpfssl_status .wpfssl-status-pass { border-left: 5px solid #42972d; }';
429 $widget_html .= '</style>';
430
431 $widget_html .= '<table class="striped widefat">';
432 for ($i = 0; $i < 7; $i++) {
433 $widget_html .= '<tr>';
434 $widget_html .= '<td class="wpfssl-status-' . $tests[$i]['status'] . '">' . $tests[$i]['title'] . '<span class="wpfssl-show-hover"> | <a href="' . admin_url('options-general.php?page=wpfs-settings#tab_status') . '">View Details</a></span></td>';
435 $widget_html .= '</tr>';
436 } // for
437 $widget_html .= '</table>';
438
439 $widget_html .= '<p>View all <b>' . sizeof($tests) . ' tests</b>, detailed test explanations, and how to fix problems in the <a href="' . admin_url('options-general.php?page=wpfs-settings#tab_status') . '">WP Force SSL</a> plugin settings.</p>';
440
441 wpForceSSL_Utility::wp_kses_wf($widget_html);
442 } // widget_content
443
444
445 // fix for aggressive plugins that include their CSS on all pages
446 function cleanup_enqueues()
447 {
448 if (!$this->is_plugin_page()) {
449 return;
450 }
451
452 wp_dequeue_style('uiStyleSheet');
453 wp_dequeue_style('wpcufpnAdmin');
454 wp_dequeue_style('unifStyleSheet');
455 wp_dequeue_style('wpcufpn_codemirror');
456 wp_dequeue_style('wpcufpn_codemirrorTheme');
457 wp_dequeue_style('collapse-admin-css');
458 wp_dequeue_style('jquery-ui-css');
459 wp_dequeue_style('tribe-common-admin');
460 wp_dequeue_style('file-manager__jquery-ui-css');
461 wp_dequeue_style('file-manager__jquery-ui-css-theme');
462 wp_dequeue_style('wpmegmaps-jqueryui');
463 wp_dequeue_style('wp-botwatch-css');
464 wp_dequeue_style('njt-filebird-admin');
465 wp_dequeue_style('ihc_jquery-ui.min.css');
466 wp_dequeue_style('badgeos-juqery-autocomplete-css');
467 wp_dequeue_style('mainwp');
468 wp_dequeue_style('mainwp-responsive-layouts');
469 wp_dequeue_style('jquery-ui-style');
470 wp_dequeue_style('additional_style');
471 wp_dequeue_style('wobd-jqueryui-style');
472 wp_dequeue_style('wpdp-style3');
473 wp_dequeue_style('jquery_smoothness_ui');
474 wp_dequeue_style('uap_main_admin_style');
475 wp_dequeue_style('uap_font_awesome');
476 wp_dequeue_style('uap_jquery-ui.min.css');
477 } // cleanup_enqueues
478
479
480 /**
481 * Add links to plugin's description in plugins table
482 *
483 * @param array $links Initial list of links.
484 * @param string $file Basename of current plugin.
485 *
486 * @return array
487 */
488 function plugin_meta_links($links, $file)
489 {
490 if ($file !== plugin_basename(__FILE__)) {
491 return $links;
492 }
493
494 $support_link = '<a target="_blank" href="https://wordpress.org/support/plugin/wp-force-ssl/" title="Get help">Support</a>';
495 $home_link = '<a target="_blank" href="https://wpforcessl.com/?ref=wpfssl-free" title="Plugin Homepage">Plugin Homepage</a>';
496
497 $links[] = $support_link;
498 $links[] = $home_link;
499
500 return $links;
501 } // plugin_meta_links
502
503
504 /**
505 * Add action links to plugins table, left part
506 *
507 * @param array $links Initial list of links.
508 *
509 * @return array
510 */
511 function plugin_action_links($links)
512 {
513 $settings_link = '<a href="' . admin_url('options-general.php?page=wpfs-settings') . '" title="Configure SSL settings">Configure SSL</a>';
514 $buy_link = '<a href="' . admin_url('options-general.php?page=wpfs-settings#open-pro-dialog') . '" title="Buy the PRO version"><b>Buy PRO</b></a>';
515
516 array_unshift($links, $buy_link);
517 array_unshift($links, $settings_link);
518
519 return $links;
520 } // plugin_action_links
521
522
523 /**
524 * Remove all WP notices on WPSSL page
525 *
526 * @return null
527 */
528 function remove_admin_notices()
529 {
530 if (!$this->is_plugin_page()) {
531 return false;
532 }
533
534 global $wp_filter;
535 unset($wp_filter['user_admin_notices'], $wp_filter['admin_notices']);
536 } // remove_admin_notices
537
538
539 /**
540 * Main function for displaying plugin's admin page
541 *
542 * @return null
543 */
544 function settings_page_content()
545 {
546 // double check for admin privileges
547 if (!current_user_can('administrator')) {
548 wp_die('Sorry, you are not allowed to access this page.');
549 }
550
551 echo '<header>';
552 echo '<img id="logo-icon" src="' . esc_url($this->plugin_url) . 'img/wp-force-ssl-logo.png" title="WP Force SSL" alt="WP Force SSL" />';
553 echo '</header>';
554
555 echo '<div id="wfssl-notifications">';
556 echo '</div>';
557
558 echo '<div class="wfssl-container-left">';
559 echo '<div id="wfssl-tabs" class="ui-tabs" style="display: none;">';
560 $tabs = array();
561
562 $tabs[] = array('id' => 'tab_status', 'class' => 'wfssl-tab', 'label' => 'Status', 'callback' => 'tab_status');
563 $tabs[] = array('id' => 'tab_settings', 'class' => 'wfssl-tab', 'label' => 'Settings', 'callback' => 'tab_settings');
564 $tabs[] = array('id' => 'tab_scanner', 'class' => 'wfssl-tab', 'label' => 'Content Scanner', 'callback' => 'tab_scanner');
565 $tabs[] = array('id' => 'tab_ssl', 'class' => 'wfssl-tab', 'label' => 'SSL Certificate', 'callback' => 'tab_ssl');
566 $tabs[] = array('id' => 'tab_support', 'class' => 'wfssl-tab', 'label' => 'Support', 'callback' => 'tab_support');
567 $tabs[] = array('id' => 'tab_pro', 'class' => 'wfssl-tab wfssl-tab-pro', 'label' => 'PRO', 'callback' => '');
568
569 echo '<nav>';
570 echo '<div class="wfssl-container">';
571 echo '<ul class="wfssl-main-tab">';
572 foreach ($tabs as $tab) {
573 echo '<li id="button-' . esc_attr($tab['id']) . '" class="' . esc_attr($tab['class']) . '"><a href="#' . esc_attr($tab['id']) . '">' . esc_attr($tab['label']) . '</a></li>';
574 }
575 echo '</ul>';
576 echo '</div>'; // container
577 echo '</nav>';
578
579 // tabs
580 echo '<div class="wfssl-container">';
581
582 foreach ($tabs as $tab) {
583 if (is_callable(array($this, $tab['callback']))) {
584 echo '<div id="' . esc_attr($tab['id']) . '" class="wfssl-tab-content">';
585 call_user_func(array($this, $tab['callback']));
586 echo '</div>';
587 }
588 }
589
590 echo '</div>'; // wfssl-container
591 echo '</div>';
592 echo '</div>'; // wfssl-container-left
593
594 echo '<div class="wfssl-container wfssl-container-right">';
595 echo '<div class="sidebar-box pro-ad-box">
596 <p class="text-center"><a href="https://wpforcessl.com/?ref=wpfssl-free-sidebar-box" target="_blank">
597 <img src="' . esc_url($this->plugin_url) . 'img/wp-force-ssl-logo.png" alt="WP Force SSL PRO" title="WP Force SSL PRO"></a><br><b>PRO version</b> is here! Grab the launch discount - <b>all prices are LIFETIME!</b></p>
598 <ul class="plain-list">
599 <li>15+ Options to Fine-Tune Your SSL</li>
600 <li>Mixed Content Scanner + Fixer</li>
601 <li>Real-Time SSL &amp; Site monitoring (via our SaaS)</li>
602 <li>Generate &amp; Install Free SSL Certificate</li>
603 <li>Licenses &amp; Sites Manager (remote SaaS dashboard)</li>
604 <li>White-label Mode + Complete Codeless Plugin Rebranding</li>
605 <li>Email support from plugin developers</li>
606 </ul>
607
608 <p class="text-center"><a href="#" class="open-pro-dialog button button-buy" data-pro-feature="sidebar-box">Get PRO Now</a></p>
609 </div>';
610 echo '<div class="sidebar-box" style="margin-top: 35px;">
611 <p>Please <a href="https://wordpress.org/support/plugin/wp-force-ssl/reviews/#new-post" target="_blank">rate the plugin �
612
613
614
615
616 </a> to <b>keep it up-to-date &amp; maintained</b>. It only takes a second to rate. Thank you! 👋</p>
617 </div>';
618 echo '</div>'; // wfssl-container-right
619
620 wpForceSSL_Utility::wp_kses_wf($this->pro_dialog());
621 } // settings_page_content
622
623
624 function tab_support()
625 {
626 echo '<div style="overflow: auto;">
627 <div class="wfssl-box">
628 <h3>Support</h3>
629 <p>Support for the free version is available only via the <a href="https://wordpress.org/support/plugin/wp-force-ssl/" target="_blank">WP repo support forum</a>. If you need email support please <a href="#" class="open-pro-dialog" data-pro-feature="support">upgrade to PRO</a>.</p>';
630 echo '</div>';
631 echo '</div>';
632 echo '<h3>FAQ</h3>
633 <div class="wfssl-accordion-wfssl-accordion-tabs">
634 <div class="wfssl-accordion-tab">
635 <input type="checkbox" id="faq1">
636 <label class="wfssl-accordion-tab-label wfssl-fs-18 wfssl-font" for="faq1">Will WP Force SSL slow down my site?</label>
637 <div class="wfssl-accordion-tab-content">
638 Absolutely not. Everything the plugin does happens in the admin. Nothing is loaded, added, or processed on the front-end so you can rest assured there is no impact on the performance of your site.
639 </div>
640 </div>
641
642 <div class="wfssl-accordion-tab">
643 <input type="checkbox" id="faq8">
644 <label class="wfssl-accordion-tab-label wfssl-fs-18 wfssl-font" for="faq8">I just moved my site to another address, will WP Force SSL help?</label>
645 <div class="wfssl-accordion-tab-content">
646 Definitely! Especially if you moved from HTTP to HTTPS. The plugin will make sure to properly redirect all your content, check your SSL certificate, and add other security features.
647 </div>
648 </div>
649
650 <div class="wfssl-accordion-tab d-none">
651 <input type="checkbox" id="faq2">
652 <label class="wfssl-accordion-tab-label wfssl-fs-18 wfssl-font" for="faq2">Can you install an SSL certificate for me?</label>
653 <div class="wfssl-accordion-tab-content">
654 Sorry, at the moment we can\'t. The automatic SSL certificate installation feature is on our to-do and will be available in one of the future versions.
655 </div>
656 </div>
657
658 <div class="wfssl-accordion-tab">
659 <input type="checkbox" id="faq11">
660 <label class="wfssl-accordion-tab-label wfssl-fs-18 wfssl-font" for="faq11">What are the requirements for running SSL on a site?</label>
661 <div class="wfssl-accordion-tab-content">There are many but a short answer is "A valid SSL certificate". Please head over to the <a href="#" data-tab="0" class="change-tab">Status</a> tab and see the results. The tests were made specifically to see if a site is ready for SSL.
662 </div>
663 </div>
664
665 <div class="wfssl-accordion-tab">
666 <input type="checkbox" id="faq4">
667 <label class="wfssl-accordion-tab-label wfssl-fs-18 wfssl-font" for="faq4">Is WP Force SSL dangerous for my site?</label>
668 <div class="wfssl-accordion-tab-content">
669 No, definitely not! The plugin does not make any permanent changes to your site so even if it comes to a worst-case scenario you can just disable the plugin and that will undo all changes.
670 </div>
671 </div>
672
673 <div class="wfssl-accordion-tab d-none">
674 <input type="checkbox" id="faq5">
675 <label class="wfssl-accordion-tab-label wfssl-fs-18 wfssl-font" for="faq5">Can you generate/get an SSL certificate for me?</label>
676 <div class="wfssl-accordion-tab-content">
677 At the moment no. Sorry. We are already working on a feature that will automatically get a certificate from Let\'s Encrypt and install it on your site but it\'s not ready yet.
678 </div>
679 </div>
680
681 <div class="wfssl-accordion-tab">
682 <input type="checkbox" id="faq7">
683 <label class="wfssl-accordion-tab-label wfssl-fs-18 wfssl-font" for="faq7">Will WP Force SSL modify my files, database or any content?</label>
684 <div class="wfssl-accordion-tab-content">
685 It will not automatically modify anything. If anything needs permanent changes you\'ll be prompted to double-confirm the change. However, on 90% of sites, all changes are done on the fly so they are not permanent. Disabling the plugin undoes all changes.
686 </div>
687 </div>
688
689 <div class="wfssl-accordion-tab">
690 <input type="checkbox" id="faq6">
691 <label class="wfssl-accordion-tab-label wfssl-fs-18 wfssl-font" for="faq6">When I buy PRO can I manage my licenses and change sites?</label>
692 <div class="wfssl-accordion-tab-content">
693 Certainly! Purchases, sites, licenses & SSL monitors are managed in the <a href="https://dashboard.wpforcessl.com/" target="_blank">WP Force SSL Dashboard</a>. It\'s a central place to manage all your sites. You can move the licenses (change sites/domains) as much as you need. There are no limits.
694 </div>
695 </div>
696 </div>';
697 } // tab_support
698
699
700 function tab_status()
701 {
702 echo '<div id="status_progress_wrapper" class="wfssl-progress" style="display:none;">
703 <div id="status_progress" class="bar orange" style="width:0%">
704 <div id="status_progress_text" class="wfssl-progress-text"></div>
705 </div>
706 </div>
707
708 <div id="status_tasks" class="wfssl-labels" style="display:none;">
709 <div class="status-tasks status-tasks-selected">All tasks</div>
710 <div class="status-tasks-remaining">Remaining tasks</div>
711 </div>
712
713 <div id="test-results-wrapper">
714 <div class="loading-wrapper">
715 <img class="wfssl_flicker" src="' . esc_url($this->plugin_url) . 'img/wp-force-ssl-icon.png' . '" alt="Loading. Please wait." title="Loading. Please wait.">
716 <p>Loading. Please wait.</p>
717 </div>
718 </div>';
719 echo '<div class="button button-primary run-tests" style="float: right; display:none;">Run Tests Again</div>';
720 } // tab_status
721
722
723 function tab_settings()
724 {
725 echo '<form id="wpfs_form"><table class="form-table" id="settings-table">';
726
727 echo '<tr><td>
728 <label for="wpfs_ssl">Redirect HTTP requests to HTTPS</label>
729 <small>Visitors will be automatically redirected from HTTP to HTTPS for all pages, posts and other WP content. The 301 redirect status is used. Files that are outside of WP, or accessed directly will still be served via HTTP.</small>
730 </td><td>';
731 wpForceSSL_Utility::create_toogle_switch('wpfs_ssl', array('saved_value' => ($this->options['wpfs_ssl'] == 'yes' ? true : false)));
732 echo '</td></tr>';
733
734 echo '<tr><td>
735 <label for="fix_frontend_mixed_content_fixer">Fix mixed content on frontend<span class="pro-feature open-pro-dialog">PRO</span></label>
736 <small>Fix mixed content on the frontend on the fly (files and/or database is not changed) by replacing <code>http://</code> with <code>https://</code> for linked resources.</small>
737 </td><td>';
738 wpForceSSL_Utility::create_toogle_switch('fix_frontend_mixed_content_fixer', array('class' => 'open-pro-dialog', 'saved_value' => false));
739 echo '</td></tr>';
740
741 echo '<tr><td>
742 <label for="fix_backend_mixed_content_fixer">Fix mixed content on backend (in WP admin)<span class="pro-feature open-pro-dialog">PRO</span></label>
743 <small>Fix mixed content in the backend (WP admin) on the fly (files and/or database is not changed) by replacing <code>http://</code> with <code>https://</code> for linked resources</small>
744 </td><td>';
745 wpForceSSL_Utility::create_toogle_switch('fix_backend_mixed_content_fixer', array('class' => 'open-pro-dialog', 'saved_value' => false));
746 echo '</td></tr>';
747
748 echo '<tr><td>
749 <label for="wpfs_hsts">Enable HSTS</label>
750 <small>HSTS (HTTP Strict Transport Security) is a header sent by your website to your visitors\' browser telling it to only use HTTPS to connect to the website. If someone tried to perform a man-in-the-middle attack and redirect the visitor to their own malicious version of the domain the browser will refuse to load the website via HTTP and force them to show a valid SSL certificate for the domain, which they will not have and thus the attack will fail.</small>
751 </td><td>';
752 wpForceSSL_Utility::create_toogle_switch('wpfs_hsts', array('saved_value' => ($this->options['wpfs_hsts'] == 'yes' ? true : false)));
753 echo '</td></tr>';
754
755 echo '<tr><td>
756 <label for="force_secure_cookies">Force Secure Cookies<span class="pro-feature open-pro-dialog">PRO</span></label>
757 <small>Cookies are small packets of data stored on your computer by the websites you visit so it remembers information like your logged in state. Most times this information is sensitive, so you should enable this option to harden the way cookies are exchanged with by your browser and to prevent anyone else from reading them.</small>
758 </td><td>';
759 wpForceSSL_Utility::create_toogle_switch('force_secure_cookies', array('class' => 'open-pro-dialog', 'saved_value' => false));
760 echo '</td></tr>';
761
762 echo '<tr><td>
763 <label for="htaccess_301_redirect">Redirect HTTP to HTTPS requests via .htaccess<span class="pro-feature open-pro-dialog">PRO</span></label>
764 <small>Redirect all <code>http://</code> requests to <code>https://</code> via .htaccess as soon as the request is received. This is slighly faster than PHP redirect but if your server does not use .htaccess you can use the PHP redirect option too.</small>
765 </td><td>';
766 wpForceSSL_Utility::create_toogle_switch('htaccess_301_redirect', array('class' => 'open-pro-dialog', 'saved_value' => false));
767 echo '</td></tr>';
768
769 echo '<tr><td>
770 <label for="xss_protection">Cross-site scripting (X-XSS) protection<span class="pro-feature open-pro-dialog">PRO</span></label>
771 <small>Protects your site from cross-site scripting attacks. If a cross-site scripting attack is detected, the browser will automatically block those requests.</small>
772 </td><td>';
773 wpForceSSL_Utility::create_toogle_switch('xss_protection', array('class' => 'open-pro-dialog', 'saved_value' => false));
774 echo '</td></tr>';
775
776 echo '<tr><td>
777 <label for="x_content_options">X-Content-Type Options<span class="pro-feature open-pro-dialog">PRO</span></label>
778 <small>This header prevents MIME-sniffing, which is used to disguise the content type of malicious files being uploaded to the website.</small>
779 </td><td>';
780 wpForceSSL_Utility::create_toogle_switch('x_content_options', array('class' => 'open-pro-dialog', 'saved_value' => false));
781 echo '</td></tr>';
782
783 echo '<tr><td>
784 <label for="referrer_policy">Referrer Policy<span class="pro-feature open-pro-dialog">PRO</span></label>
785 <small>To prevent data leakage, only send referrer information when navigating to the same protocol (HTTPS -&gt; HTTPS) and not when downgrading (HTTPS -&gt; HTTP).</small>
786 </td><td>';
787 wpForceSSL_Utility::create_toogle_switch('referrer_policy', array('class' => 'open-pro-dialog', 'saved_value' => false));
788 echo '</td></tr>';
789
790 echo '<tr><td>
791 <label for="wpfs_expect_ct">Expect CT</label>
792 <small>Enables the Expect-CT header, requesting that the browser check that the certificate for that site appears in public CT logs.</small>
793 </td><td>';
794 wpForceSSL_Utility::create_toogle_switch('wpfs_expect_ct', array('saved_value' => ($this->options['wpfs_expect_ct'] == 'yes' ? true : false)));
795 echo '</td></tr>';
796
797 echo '<tr><td>
798 <label for="x_frame_options">X-Frame Options<span class="pro-feature open-pro-dialog">PRO</span></label>
799 <small>This header prevents your site from being loaded in an iFrame on other domains. This is used to prevent clickjacking attacks. Be sure to enable this option!</small>
800 </td><td>';
801 wpForceSSL_Utility::create_toogle_switch('x_frame_options', array('class' => 'open-pro-dialog', 'saved_value' => false));
802 echo '</td></tr>';
803
804 echo '<tr><td>
805 <label for="permissions_policy">Permissions Policy<span class="pro-feature open-pro-dialog">PRO</span></label>
806 <small>The Permissions Policy allows you to specify which browser resources to allow on your site (i.e. microphone, webcam, etc.).</small>
807 </td><td>';
808 wpForceSSL_Utility::create_toogle_switch('permissions_policy', array('class' => 'open-pro-dialog', 'saved_value' => false));
809 echo '</td></tr>';
810
811 echo '<tr><td>
812 <label for="wpfs_adminbar_menu">Show WP Force SSL menu to administrators in admin bar</label>
813 <small>When enabled an extra menu will be shown to admins in the admin topbar. Don\'t forget to reload the page after saving to see the change.</small>
814 </td><td>';
815 wpForceSSL_Utility::create_toogle_switch('wpfs_adminbar_menu', array('saved_value' => ($this->options['wpfs_adminbar_menu'] == 'yes' ? true : false)));
816 echo '</td></tr>';
817
818 echo '<tr><td>
819 <label for="wpfs_dashboard_widget">Show WP Force SSL widget to administrators in admin dashboard</label>
820 <small>When enabled a widget with status details will be shown to admins in the admin dashboard.</small>
821 </td><td>';
822 wpForceSSL_Utility::create_toogle_switch('wpfs_dashboard_widget', array('saved_value' => ($this->options['wpfs_dashboard_widget'] == 'yes' ? true : false)));
823 echo '</td></tr>';
824
825 echo '</table></form>';
826
827 echo '<p><a href="#" class="button button-primary save-ssl-options">' . __('Save Settings', 'wp-force-ssl') . '</a></p>';
828 } //tab_settings
829
830
831 function tab_scanner()
832 {
833 echo '<div id="scanner_progress_wrapper" class="wfssl-progress" style="display:none;">
834 <div id="scanner_progress" class="bar">
835 <div id="scanner_progress_text" class="wfssl-progress-text"></div>
836 </div>
837 </div>';
838 $posts = get_posts(array('post_type' => get_post_types(array('public' => true)), 'numberposts' => 1000));
839 echo '<div class="scanner-stats">Total pages to scan: ' . esc_html(number_format(count($posts))) . '</div>';
840 echo '<a href="#" class="open-pro-dialog" data-pro-feature="content-scanner"><img class="scanner-preview" src="' . esc_url($this->plugin_url . 'img/content-scanner.jpg') . '" /></a>';
841
842 echo '<div id="start-scanner" data-pro-feature="start-scanning" class="button button-primary open-pro-dialog">Start Scanning</div>';
843 } //tab_scanner
844
845
846 function tab_ssl()
847 {
848 echo '<h2>SSL Certificate Information</h2>';
849 echo '<div id="ssl_cert_details" class="wfssl-box">';
850 echo 'Loading certificate information ...<span class="wfssl-green wfssl_rotating dashicons dashicons-update"></span>';
851 echo '</div>';
852 echo '<div class="clear"></div>';
853
854 echo '<h2>Real-Time SSL &amp; Site Monitoring<span class="pro-feature">PRO</span></h2>';
855 echo '<div id="wfssl_cert_email" class="wfssl-box">';
856 echo '<span class="wfssl-red dashicons dashicons-dismiss"></span>';
857 echo '<p>Real-time site &amp; SSL certificate monitoring is a <a href="#" data-pro-feature="ssl-monitor-text" class="open-pro-dialog">PRO</a> feature powered by our SaaS that will help you and your clients sleep better. It monitors over 20 common errors related to SSL that can happen at any time. Forgot to renew your certificate? No problem, you\'ll get notified on time. Forgot to change certificate after switching the domain or server? Again, not a problem. You\'ll get notified.</p>';
858 echo '<label for="ssl-monitor-toggle">Enable Monitoring</label> &nbsp; ';
859 wpForceSSL_Utility::create_toogle_switch('ssl-monitor-toggle', array('class' => 'open-pro-dialog', 'saved_value' => false));
860 echo '<div id="wfssl-cert-expiration-email-box">';
861 echo '<input id="cert_expiration_email" name="cert_expiration_email" class="wfssl-cert-expiration-email-input open-pro-dialog" data-pro-feature="ssl-monitor-email" type="text" placeholder="Email for notifications" value="" style="height:32px; width:353px; background-color: #fff; margin-bottom: 20px;"><br>';
862 echo '<div class="button button-primary open-pro-dialog" data-pro-feature="ssl-monitor-save">Save &amp; Enable Monitoring</div>';
863 echo '</div>';
864 echo '</div>';
865
866 echo '<div class="clear"></div>';
867 echo '<h2>Generate Free SSL Certificate<span class="pro-feature">PRO</span></h2>';
868 echo '<div id="wfssl_cert_generate" class="wfssl-box">';
869 echo '<p>Use this <a href="#" data-pro-feature="generate-ssl-cert-text" class="open-pro-dialog">PRO</a> tool to generate a free Let\'s Encrypt certificate. The certificate will be renewed automatically as long as WP Force SSL is active on the website. All you need is an email address, no other personal information or payment is necessary.</p>';
870 echo '<div class="button button-primary open-pro-dialog" data-pro-feature="generate-ssl-cert">Generate Free SSL Certificate</div>';
871 echo '</div>';
872 } // tab_ssl
873
874
875 /**
876 * Perform the redirect to HTTPS if loaded over HTTP
877 *
878 * @since 1.5
879 *
880 * @return null
881 *
882 */
883 public function wpfs_core()
884 {
885 if (!is_ssl()) {
886 wp_safe_redirect('https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], 301);
887 exit();
888 }
889 } // wpfs_core
890
891
892 /**
893 * Check if minimal WP version required by WP Force SSL is used
894 *
895 * @since 1.5
896 *
897 * @return bool
898 *
899 */
900 public function check_wp_version($min_version)
901 {
902 if (!version_compare(get_bloginfo('version'), $min_version, '>=')) {
903 add_action('admin_notices', array($this, 'notice_min_wp_version'));
904 return false;
905 } else {
906 return true;
907 }
908 } // check_wp_version
909
910
911 /**
912 * Display error message if WP version is too low
913 *
914 * @since 1.5
915 *
916 * @return null
917 *
918 */
919 public function notice_min_wp_version()
920 {
921 echo '<div class="error"><p>' . sprintf(__('WP Force SSL plugin <b>requires WordPress version 4.6</b> or higher to function properly. You are using WordPress version %s. Please <a href="%s">update it</a>.', 'wp-force-ssl'), get_bloginfo('version'), admin_url('update-core.php')) . '</p></div>';
922 } // notice_min_wp_version_error
923
924
925 /**
926 * Send the HTTP Strict Transport Security (HSTS) header.
927 *
928 * @since 1.5
929 *
930 * @return null
931 */
932 public function to_strict_transport_security()
933 {
934 header('Strict-Transport-Security: max-age=31536000; includeSubDomains; preload');
935 } // to_strict_transport_security
936
937
938 /**
939 * Send the Expect CT header.
940 *
941 * @since 1.5
942 *
943 * @return null
944 */
945 public function enable_expect_ct()
946 {
947 header('Expect-CT: max-age=5184000, enforce');
948 } // enable_expect_ct
949
950
951 /**
952 * Save plugin settings received via AJAX
953 *
954 * @since 1.5
955 *
956 * @return null
957 */
958 public function ajax_save_setting()
959 {
960 check_ajax_referer('save_settting_nonce_action');
961
962 $wpfs_ssl = isset($_POST['wpfs_ssl']) ? 'yes' : 'no';
963 $wpfs_hsts = isset($_POST['wpfs_hsts']) ? 'yes' : 'no';
964 $wpfs_expect_ct = isset($_POST['wpfs_expect_ct']) ? 'yes' : 'no';
965 $wpfs_adminbar_menu = isset($_POST['wpfs_adminbar_menu']) ? 'yes' : 'no';
966 $wpfs_dashboard_widget = isset($_POST['wpfs_dashboard_widget']) ? 'yes' : 'no';
967
968 $wpfs_settings = array(
969 'wpfs_ssl' => $wpfs_ssl,
970 'wpfs_hsts' => $wpfs_hsts,
971 'wpfs_expect_ct' => $wpfs_expect_ct,
972 'wpfs_adminbar_menu' => $wpfs_adminbar_menu,
973 'wpfs_dashboard_widget' => $wpfs_dashboard_widget
974 );
975 update_option(WPFSSL_OPTIONS_KEY, $wpfs_settings);
976
977 wp_send_json_success();
978 } // ajax_save_setting
979
980
981 /**
982 * Check SSL Certificate by performing a request to home_url over https and send back a json response
983 *
984 * @since 1.5
985 *
986 * @return null
987 */
988 public function ajax_check_ssl()
989 {
990 global $wp_force_ssl_tests;
991
992 check_ajax_referer('test_ssl_nonce_action');
993
994 if (isset($_REQUEST['force']) && (bool)$_REQUEST['force'] === true) {
995 $nocache = true;
996 } else {
997 $nocache = false;
998 }
999 $status = $wp_force_ssl_tests->get_ssl_status($nocache);
1000
1001 wp_send_json_success($status);
1002 } // check_ssl
1003
1004 /**
1005 * Check if currently on WP Force SSL settings page
1006 *
1007 * @since 1.5
1008 *
1009 * @return bool is on WP Force SSL settings page
1010 */
1011 public function is_plugin_page()
1012 {
1013 $current_screen = get_current_screen();
1014 if ($current_screen->id === 'settings_page_wpfs-settings') {
1015 return true;
1016 } else {
1017 return false;
1018 }
1019 } // is_plugin_page
1020
1021
1022 /**
1023 * Change admin footer text to show plugin information
1024 *
1025 * @since 1.5
1026 *
1027 * @param string $text_org original footer text
1028 *
1029 * @return string footer text html
1030 */
1031 public function admin_footer_text($text_org)
1032 {
1033 if (false === $this->is_plugin_page()) {
1034 return $text_org;
1035 }
1036
1037 $text = '<i><a target="_blank" href="https://wpforcessl.com/?ref=wpfssl-free">WP Force SSL</a> v' . $this->version . ' by <a href="https://www.webfactoryltd.com/" title="' . __('Visit our site to get more great plugins', 'wp-force-ssl') . '" target="_blank">WebFactory Ltd</a>.';
1038 $text .= ' Please <a target="_blank" href="https://wordpress.org/support/plugin/wp-force-ssl/reviews/#new-post" title="' . __('Rate the plugin', 'wp-force-ssl') . '">' . __('Rate the plugin �
1039
1040
1041
1042
1043 ', 'wp-force-ssl') . '</a>.</i> ';
1044 return $text;
1045 } // admin_footer_text
1046
1047
1048 function pro_dialog()
1049 {
1050 $out = '';
1051
1052 $out .= '<div id="wpfssl-pro-dialog" style="display: none;" title="WP Force SSL PRO is here!"><span class="ui-helper-hidden-accessible"><input type="text"/></span>';
1053
1054 $out .= '<div class="center logo"><a href="https://wpforcessl.com/?ref=wpfssl-free-pricing-table" target="_blank"><img src="' . $this->plugin_url . 'img/wp-force-ssl-logo.png' . '" alt="WP Force SSL PRO" title="WP Force SSL PRO"></a><br>';
1055
1056 $out .= '<span>Limited PRO Launch Discount - <b>all prices are LIFETIME</b>! Pay once &amp; use forever!</span>';
1057 $out .= '</div>';
1058
1059 $out .= '<table id="wpfssl-pro-table">';
1060 $out .= '<tr>';
1061 $out .= '<td class="center">Lifetime Personal License</td>';
1062 $out .= '<td class="center">Lifetime Team License</td>';
1063 $out .= '<td class="center">Lifetime Agency License</td>';
1064 $out .= '</tr>';
1065
1066 $out .= '<tr class="prices">';
1067 $out .= '<td class="center"><del>$49 /year</del><br><span>$59</span> <b>/lifetime</b></td>';
1068 $out .= '<td class="center"><del>$89 /year</del><br><span>$89</span> <b>/lifetime</b></td>';
1069 $out .= '<td class="center"><del>$199 /year</del><br><span>$119</span> <b>/lifetime</b></td>';
1070 $out .= '</tr>';
1071
1072 $out .= '<tr>';
1073 $out .= '<td><span class="dashicons dashicons-yes"></span><b>1 Site License</b></td>';
1074 $out .= '<td><span class="dashicons dashicons-yes"></span><b>5 Sites License</b></td>';
1075 $out .= '<td><span class="dashicons dashicons-yes"></span><b>100 Sites License</b></td>';
1076 $out .= '</tr>';
1077
1078 $out .= '<tr>';
1079 $out .= '<td><span class="dashicons dashicons-yes"></span>All Plugin Features</td>';
1080 $out .= '<td><span class="dashicons dashicons-yes"></span>All Plugin Features</td>';
1081 $out .= '<td><span class="dashicons dashicons-yes"></span>All Plugin Features</td>';
1082 $out .= '</tr>';
1083
1084 $out .= '<tr>';
1085 $out .= '<td><span class="dashicons dashicons-yes"></span>Lifetime Updates &amp; Support</td>';
1086 $out .= '<td><span class="dashicons dashicons-yes"></span>Lifetime Updates &amp; Support</td>';
1087 $out .= '<td><span class="dashicons dashicons-yes"></span>Lifetime Updates &amp; Support</td>';
1088 $out .= '</tr>';
1089
1090 $out .= '<tr>';
1091 $out .= '<td><span class="dashicons dashicons-yes"></span>Content Scanner</td>';
1092 $out .= '<td><span class="dashicons dashicons-yes"></span>Content Scanner</td>';
1093 $out .= '<td><span class="dashicons dashicons-yes"></span>Content Scanner</td>';
1094 $out .= '</tr>';
1095
1096 $out .= '<tr>';
1097 $out .= '<td><span class="dashicons dashicons-yes"></span>Real-Time SSL &amp; Site Monitoring</td>';
1098 $out .= '<td><span class="dashicons dashicons-yes"></span>Real-Time SSL &amp; Site Monitoring</td>';
1099 $out .= '<td><span class="dashicons dashicons-yes"></span>Real-Time SSL &amp; Site Monitoring</td>';
1100 $out .= '</tr>';
1101
1102 $out .= '<tr>';
1103 $out .= '<td><span class="dashicons dashicons-yes"></span>Free SSL Certificate Generating</td>';
1104 $out .= '<td><span class="dashicons dashicons-yes"></span>Free SSL Certificate Generating</td>';
1105 $out .= '<td><span class="dashicons dashicons-yes"></span>Free SSL Certificate Generating</td>';
1106 $out .= '</tr>';
1107
1108 $out .= '<tr>';
1109 $out .= '<td><span class="dashicons dashicons-no"></span>Licenses &amp; Sites Manager</td>';
1110 $out .= '<td><span class="dashicons dashicons-yes"></span>Licenses &amp; Sites Manager</td>';
1111 $out .= '<td><span class="dashicons dashicons-yes"></span>Licenses &amp; Sites Manager</td>';
1112 $out .= '</tr>';
1113
1114 $out .= '<tr>';
1115 $out .= '<td><span class="dashicons dashicons-no"></span>White-label Mode</td>';
1116 $out .= '<td><span class="dashicons dashicons-yes"></span>White-label Mode</td>';
1117 $out .= '<td><span class="dashicons dashicons-yes"></span>White-label Mode</td>';
1118 $out .= '</tr>';
1119
1120 $out .= '<tr>';
1121 $out .= '<td><span class="dashicons dashicons-no"></span>Full Plugin Rebranding</td>';
1122 $out .= '<td><span class="dashicons dashicons-no"></span>Full Plugin Rebranding</td>';
1123 $out .= '<td><span class="dashicons dashicons-yes"></span>Full Plugin Rebranding</td>';
1124 $out .= '</tr>';
1125
1126 $out .= '<tr>';
1127 $out .= '<td><a class="button button-buy" data-href-org="https://wpforcessl.com/buy/?product=personal-launch&ref=pricing-table" href="https://wpforcessl.com/buy/?product=personal-launch&ref=pricing-table" target="_blank">Lifetime License<br>$59 -&gt; BUY NOW</a>
1128 <br>or <a class="button-buy" data-href-org="https://wpforcessl.com/buy/?product=personal-monthly&ref=pricing-table" href="https://wpforcessl.com/buy/?product=personal-monthly&ref=pricing-table" target="_blank">only $6.99 <small>/month</small></a></td>';
1129 $out .= '<td><a class="button button-buy" data-href-org="https://wpforcessl.com/buy/?product=team-launch&ref=pricing-table" href="https://wpforcessl.com/buy/?product=team-launch&ref=pricing-table" target="_blank">Lifetime License<br>$69 -&gt; BUY NOW</a></td>';
1130 $out .= '<td><a class="button button-buy" data-href-org="https://wpforcessl.com/buy/?product=agency-launch&ref=pricing-table" href="https://wpforcessl.com/buy/?product=agency-launch&ref=pricing-table" target="_blank">Lifetime License<br>$119 -&gt; BUY NOW</a></td>';
1131 $out .= '</tr>';
1132
1133 $out .= '</table>';
1134
1135 $out .= '<div class="center footer"><b>100% No-Risk Money Back Guarantee!</b> If you don\'t like the plugin over the next 7 days, we will happily refund 100% of your money. No questions asked! Payments are processed by our merchant of records - <a href="https://paddle.com/" target="_blank">Paddle</a>.</div></div>';
1136
1137 return $out;
1138 } // pro_dialog
1139
1140
1141 /**
1142 * Clean-up on delete
1143 *
1144 * @since 1.5
1145 *
1146 * @return null
1147 */
1148 public static function uninstall()
1149 {
1150 delete_option(WPFSSL_OPTIONS_KEY);
1151 delete_option(WPFSSL_META_KEY);
1152 } // uninstall
1153
1154
1155 /**
1156 * Reset on deactivate
1157 *
1158 * @return null
1159 */
1160 public static function deactivate()
1161 {
1162 $meta = get_option(WPFSSL_META_KEY, array());
1163 $meta['hide_welcome_pointer'] = false;
1164 update_option(WPFSSL_META_KEY, $meta);
1165 } // deactivate
1166
1167
1168 /**
1169 * Disabled; we use singleton pattern so magic functions need to be disabled.
1170 *
1171 * @since 1.5
1172 *
1173 * @return null
1174 */
1175 private function __clone()
1176 {
1177 }
1178
1179
1180 /**
1181 * Disabled; we use singleton pattern so magic functions need to be disabled.
1182 *
1183 * @since 1.5
1184 *
1185 * @return null
1186 */
1187 public function __sleep()
1188 {
1189 }
1190
1191
1192 /**
1193 * Disabled; we use singleton pattern so magic functions need to be disabled.
1194 *
1195 * @since 1.5
1196 *
1197 * @return null
1198 */
1199 public function __wakeup()
1200 {
1201 }
1202 // end class
1203 }
1204
1205
1206 $wpfs = wpForceSSL::get_instance();
1207 add_action('plugins_loaded', array($wpfs, 'plugins_loaded'));
1208 register_deactivation_hook(__FILE__, array('wpForceSSL', 'deactivate'));
1209 register_uninstall_hook(__FILE__, array('wpForceSSL', 'uninstall'));
1210