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