Version Description
Latest Release = Released: 15th January, 2018 Release Notes
- (v.0) ADDED: 3x more Shield Wizards: Multi-factor Authentication, Core File Scanning, Unrecognised File Scanning.
- (v.0) ADDED: You can now use regular expressions for file exclusions in the 'Unrecognised File Scanner'.
- (v.0) CHANGED: File Scanner email notifications now link to the appropriate scanner wizard directly.
- (v.0) IMPROVED: Plugin options pages restyling.
- (v.0) IMPROVED: Plugin refactoring and improvements.
Download this release
Release Info
Developer | paultgoodchild |
Plugin | Shield Security for WordPress |
Version | 6.1.0 |
Comparing to | |
See all releases |
Code changes from version 6.0.0 to 6.1.0
- icwp-plugin-controller.php +9 -19
- icwp-wpsf.php +8 -104
- init.php +106 -0
- plugin-spec.php +2 -3
- readme.txt +21 -6
- resources/css/global-plugin.css +0 -72
- resources/css/plugin.css +237 -79
- resources/css/wizard.css +50 -1
- resources/images/banner-1500x500-transparent.png +0 -0
- resources/images/wand.png +0 -0
- resources/js/icwp-options.js +1 -0
- src/common/icwp-data.php +12 -1
- src/common/icwp-edd.php +3 -2
- src/common/icwp-foundation.php +1 -1
- src/common/icwp-ip.php +51 -14
- src/common/icwp-wpfunctions.php +13 -4
- src/config/feature-admin_access_restriction.php +2 -2
- src/config/feature-hack_protect.php +182 -135
- src/config/feature-login_protect.php +248 -222
- src/config/feature-plugin.php +321 -260
- src/features/admin_access_restriction.php +47 -43
- src/features/base.php +146 -10
- src/features/base_wpsf.php +1 -22
- src/features/hack_protect.php +54 -2
- src/features/license.php +1 -1
- src/features/login_protect.php +58 -9
- src/features/plugin.php +20 -34
- src/processors/admin_access_restriction.php +2 -2
- src/processors/base.php +2 -3
- src/processors/base_plugin.php +2 -1
- src/processors/base_wpsf.php +1 -0
- src/processors/email.php +49 -40
- src/processors/hack_protect.php +3 -3
- src/processors/hackprotect_corechecksumscan.php +13 -0
- src/processors/hackprotect_filecleanerscan.php +40 -23
- src/processors/hackprotect_wpvulnscan.php +1 -1
- src/processors/login_protect.php +2 -3
- src/processors/loginprotect_googleauthenticator.php +30 -8
- src/processors/loginprotect_intent.php +15 -18
- src/processors/loginprotect_intent_base.php +9 -6
- src/processors/loginprotect_twofactorauth.php +10 -40
- src/processors/plugin.php +0 -23
- src/processors/plugin_setupwizard.php +0 -830
- src/wizards/base.php +537 -0
- src/wizards/base_wpsf.php +127 -0
- src/wizards/hack_protect.php +346 -0
- src/wizards/login_protect.php +267 -0
- src/wizards/plugin.php +548 -0
- templates/html/plugin_badge.html +1 -1
- templates/php/feature-default.php +20 -4
- templates/php/index_footer.php +13 -1
- templates/php/index_header.php +11 -13
- templates/php/snippets/module-help-plugin.php +1 -1
- templates/php/snippets/module-help-template.php +4 -0
- templates/php/snippets/module-plugin-actions.php +2 -1
- templates/php/snippets/options_form.php +201 -159
- templates/php/snippets/plugin_badge.php +4 -2
- templates/php/snippets/state_summary.php +2 -13
- templates/twig/pages/base.twig +26 -17
- templates/twig/wizard/base_finish.twig +0 -7
- templates/twig/wizard/base_start.twig +0 -3
- templates/twig/wizard/pages/base.twig +19 -0
- templates/twig/wizard/pages/landing.twig +36 -0
- templates/twig/{pages → wizard/pages}/wizard.twig +15 -8
- templates/twig/wizard/slide-import_finished.twig +0 -7
- templates/twig/wizard/{base.twig → slides/common/base.twig} +7 -3
- templates/twig/wizard/slides/common/base_finish.twig +50 -0
- templates/twig/wizard/slides/common/base_start.twig +3 -0
- templates/twig/wizard/{slide-no_access.twig → slides/common/no_access.twig} +1 -1
- templates/twig/wizard/{slide-admin_access_restriction_verify.twig → slides/common/security_admin_verify.twig} +2 -2
- templates/twig/wizard/slides/importexport/finished.twig +6 -0
- templates/twig/wizard/{slide-import_options.twig → slides/importexport/import.twig} +4 -3
- templates/twig/wizard/{slide-import_start.twig → slides/importexport/start.twig} +5 -2
- templates/twig/wizard/slides/mfa/authemail.twig +69 -0
- templates/twig/wizard/slides/mfa/authga.twig +76 -0
- templates/twig/wizard/slides/mfa/finished.twig +6 -0
- templates/twig/wizard/slides/mfa/multiselect.twig +50 -0
- templates/twig/wizard/slides/mfa/start.twig +22 -0
- templates/twig/wizard/slides/ufc/config.twig +42 -0
- templates/twig/wizard/slides/ufc/exclusions.twig +53 -0
- templates/twig/wizard/slides/ufc/finished.twig +6 -0
- templates/twig/wizard/slides/ufc/scanresult.twig +50 -0
- templates/twig/wizard/slides/ufc/start.twig +18 -0
- templates/twig/wizard/slides/wcf/config.twig +36 -0
- templates/twig/wizard/slides/wcf/finished.twig +6 -0
- templates/twig/wizard/slides/wcf/scanresult.twig +64 -0
- templates/twig/wizard/slides/wcf/start.twig +16 -0
- templates/twig/wizard/{slide-admin_access_restriction.twig → slides/welcome/admin_access_restriction.twig} +1 -1
- templates/twig/wizard/{slide-audit_trail.twig → slides/welcome/audit_trail.twig} +1 -1
- templates/twig/wizard/{slide-comments_filter.twig → slides/welcome/comments_filter.twig} +1 -1
- templates/twig/wizard/{slide-how_shield_works.twig → slides/welcome/how_shield_works.twig} +1 -1
- templates/twig/wizard/slides/welcome/import.twig +1 -0
- templates/twig/wizard/slides/welcome/ip_detect.twig +40 -0
- templates/twig/wizard/{slide-ips.twig → slides/welcome/ips.twig} +1 -1
- templates/twig/wizard/{slide-license.twig → slides/welcome/license.twig} +1 -1
- templates/twig/wizard/{slide-login_protect.twig → slides/welcome/login_protect.twig} +1 -1
- templates/twig/wizard/{slide-optin.twig → slides/welcome/optin.twig} +1 -1
- templates/twig/wizard/{slide-thankyou.twig → slides/welcome/thankyou.twig} +2 -2
- templates/twig/wizard/{slide-welcome.twig → slides/welcome/welcome.twig} +1 -1
icwp-plugin-controller.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* Copyright (c)
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* "Shield" (formerly WordPress Simple Firewall) is distributed under the GNU
|
@@ -127,9 +127,10 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
|
|
127 |
private function __construct( $sRootFile ) {
|
128 |
self::$sRootFile = $sRootFile;
|
129 |
$this->checkMinimumRequirements();
|
130 |
-
|
131 |
$this->loadWpTrack();
|
132 |
$this->loadFactory(); // so we know it's loaded whenever we need it. Cuz we need it.
|
|
|
133 |
}
|
134 |
|
135 |
/**
|
@@ -138,7 +139,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
|
|
138 |
*/
|
139 |
private function readPluginSpecification() {
|
140 |
$aSpec = array();
|
141 |
-
$sContents = $this->
|
142 |
if ( !empty( $sContents ) ) {
|
143 |
$aSpec = json_decode( $sContents, true );
|
144 |
if ( empty( $aSpec ) ) {
|
@@ -256,13 +257,6 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
|
|
256 |
$this->loadAllFeatures( true, true );
|
257 |
}
|
258 |
|
259 |
-
/**
|
260 |
-
*/
|
261 |
-
public function onWpPluginsLoaded() {
|
262 |
-
$this->doLoadTextDomain();
|
263 |
-
$this->doRegisterHooks();
|
264 |
-
}
|
265 |
-
|
266 |
/**
|
267 |
*/
|
268 |
protected function doRegisterHooks() {
|
@@ -985,20 +979,13 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
|
|
985 |
return $this->getPluginSpec_Property( 'base_permissions' );
|
986 |
}
|
987 |
|
988 |
-
/**
|
989 |
-
* @return bool
|
990 |
-
*/
|
991 |
-
public function getUserCanBasePerms() {
|
992 |
-
return current_user_can( $this->getBasePermissions() );
|
993 |
-
}
|
994 |
-
|
995 |
/**
|
996 |
* @param bool $bCheckUserPerms - do we check the logged-in user permissions
|
997 |
* @return bool
|
998 |
*/
|
999 |
public function getIsValidAdminArea( $bCheckUserPerms = true ) {
|
1000 |
if ( $bCheckUserPerms && $this->loadWpTrack()->getWpActionHasFired( 'init' )
|
1001 |
-
&& !$this->
|
1002 |
return false;
|
1003 |
}
|
1004 |
|
@@ -1205,7 +1192,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
|
|
1205 |
* @return string
|
1206 |
*/
|
1207 |
public function getPluginUrl_AdminMainPage() {
|
1208 |
-
return $this->loadCorePluginFeatureHandler()->
|
1209 |
}
|
1210 |
|
1211 |
/**
|
@@ -1551,6 +1538,9 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
|
|
1551 |
}
|
1552 |
}
|
1553 |
}
|
|
|
|
|
|
|
1554 |
return $bSuccess;
|
1555 |
}
|
1556 |
|
1 |
<?php
|
2 |
/**
|
3 |
+
* Copyright (c) 2018 iControlWP <support@icontrolwp.com>
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* "Shield" (formerly WordPress Simple Firewall) is distributed under the GNU
|
127 |
private function __construct( $sRootFile ) {
|
128 |
self::$sRootFile = $sRootFile;
|
129 |
$this->checkMinimumRequirements();
|
130 |
+
$this->doRegisterHooks();
|
131 |
$this->loadWpTrack();
|
132 |
$this->loadFactory(); // so we know it's loaded whenever we need it. Cuz we need it.
|
133 |
+
$this->doLoadTextDomain();
|
134 |
}
|
135 |
|
136 |
/**
|
139 |
*/
|
140 |
private function readPluginSpecification() {
|
141 |
$aSpec = array();
|
142 |
+
$sContents = $this->loadDP()->readFileContentsUsingInclude( $this->getPathPluginSpec() );
|
143 |
if ( !empty( $sContents ) ) {
|
144 |
$aSpec = json_decode( $sContents, true );
|
145 |
if ( empty( $aSpec ) ) {
|
257 |
$this->loadAllFeatures( true, true );
|
258 |
}
|
259 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
260 |
/**
|
261 |
*/
|
262 |
protected function doRegisterHooks() {
|
979 |
return $this->getPluginSpec_Property( 'base_permissions' );
|
980 |
}
|
981 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
982 |
/**
|
983 |
* @param bool $bCheckUserPerms - do we check the logged-in user permissions
|
984 |
* @return bool
|
985 |
*/
|
986 |
public function getIsValidAdminArea( $bCheckUserPerms = true ) {
|
987 |
if ( $bCheckUserPerms && $this->loadWpTrack()->getWpActionHasFired( 'init' )
|
988 |
+
&& !$this->getMeetsBasePermissions() ) {
|
989 |
return false;
|
990 |
}
|
991 |
|
1192 |
* @return string
|
1193 |
*/
|
1194 |
public function getPluginUrl_AdminMainPage() {
|
1195 |
+
return $this->loadCorePluginFeatureHandler()->getUrl_AdminPage();
|
1196 |
}
|
1197 |
|
1198 |
/**
|
1538 |
}
|
1539 |
}
|
1540 |
}
|
1541 |
+
|
1542 |
+
do_action( $this->doPluginPrefix( 'run_processors' ) );
|
1543 |
+
|
1544 |
return $bSuccess;
|
1545 |
}
|
1546 |
|
icwp-wpsf.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
* Plugin Name: Shield Security
|
4 |
* Plugin URI: http://icwp.io/2f
|
5 |
* Description: Powerful, Easy-To-Use #1 Rated WordPress Security System
|
6 |
-
* Version: 6.
|
7 |
* Text Domain: wp-simple-firewall
|
8 |
* Domain Path: /languages/
|
9 |
* Author: iControlWP
|
@@ -11,13 +11,11 @@
|
|
11 |
*/
|
12 |
|
13 |
/**
|
14 |
-
* Copyright (c)
|
15 |
* All rights reserved.
|
16 |
-
*
|
17 |
* "Shield" (formerly WordPress Simple Firewall) is distributed under the GNU
|
18 |
* General Public License, Version 2, June 1991. Copyright (C) 1989, 1991 Free
|
19 |
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
|
20 |
-
*
|
21 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
22 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
23 |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
@@ -30,11 +28,6 @@
|
|
30 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
31 |
*/
|
32 |
|
33 |
-
if ( class_exists( 'ICWP_Wordpress_Simple_Firewall', false ) ) {
|
34 |
-
error_log( 'Attempting to load the Shield Plugin twice?' );
|
35 |
-
return;
|
36 |
-
}
|
37 |
-
|
38 |
if ( !defined( 'ICWP_DS' ) ) {
|
39 |
define( 'ICWP_DS', DIRECTORY_SEPARATOR );
|
40 |
}
|
@@ -50,100 +43,11 @@ if ( !function_exists( '_wpsf__' ) ) {
|
|
50 |
}
|
51 |
}
|
52 |
|
53 |
-
//
|
54 |
-
require_once( dirname( __FILE__ ).
|
55 |
-
require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'icwp-plugin-controller.php' );
|
56 |
-
|
57 |
-
class ICWP_Wordpress_Simple_Firewall extends ICWP_WPSF_Foundation {
|
58 |
-
|
59 |
-
/**
|
60 |
-
* @var ICWP_WPSF_Plugin_Controller
|
61 |
-
*/
|
62 |
-
protected static $oPluginController;
|
63 |
-
|
64 |
-
/**
|
65 |
-
* @param ICWP_WPSF_Plugin_Controller $oController
|
66 |
-
*/
|
67 |
-
protected function __construct( ICWP_WPSF_Plugin_Controller $oController ) {
|
68 |
-
|
69 |
-
// All core values of the plugin are derived from the values stored in this value object.
|
70 |
-
self::$oPluginController = $oController;
|
71 |
-
$this->getController()->loadAllFeatures();
|
72 |
-
add_filter( $oController->doPluginPrefix( 'plugin_update_message' ), array( $this, 'getPluginsListUpdateMessage' ) );
|
73 |
-
add_action( 'plugin_action_links', array( $this, 'onWpPluginActionLinks' ), 10, 4 );
|
74 |
-
}
|
75 |
-
|
76 |
-
/**
|
77 |
-
* @return ICWP_WPSF_Plugin_Controller
|
78 |
-
*/
|
79 |
-
public static function getController() {
|
80 |
-
return self::$oPluginController;
|
81 |
-
}
|
82 |
-
|
83 |
-
public function getPluginsListUpdateMessage( $sMessage ) {
|
84 |
-
return _wpsf__( 'Upgrade Now To Keep Your Firewall Up-To-Date With The Latest Features.' );
|
85 |
-
}
|
86 |
-
|
87 |
-
/**
|
88 |
-
* On the plugins listing page, hides the edit and deactivate links
|
89 |
-
* for this plugin based on permissions
|
90 |
-
* @param $aActionLinks
|
91 |
-
* @param $sPluginFile
|
92 |
-
* @return mixed
|
93 |
-
*/
|
94 |
-
public function onWpPluginActionLinks( $aActionLinks, $sPluginFile ) {
|
95 |
-
$oCon = $this->getController();
|
96 |
-
if ( !$oCon->getIsValidAdminArea() ) {
|
97 |
-
return $aActionLinks;
|
98 |
-
}
|
99 |
-
|
100 |
-
if ( $sPluginFile == $oCon->getPluginBaseFile() ) {
|
101 |
-
if ( !$oCon->getHasPermissionToManage() ) {
|
102 |
-
|
103 |
-
if ( array_key_exists( 'edit', $aActionLinks ) ) {
|
104 |
-
unset( $aActionLinks[ 'edit' ] );
|
105 |
-
}
|
106 |
-
if ( array_key_exists( 'deactivate', $aActionLinks ) ) {
|
107 |
-
unset( $aActionLinks[ 'deactivate' ] );
|
108 |
-
}
|
109 |
-
}
|
110 |
-
}
|
111 |
-
return $aActionLinks;
|
112 |
-
}
|
113 |
-
}
|
114 |
-
|
115 |
-
class ICWP_WPSF_Shield_Security extends ICWP_Wordpress_Simple_Firewall {
|
116 |
-
|
117 |
-
/**
|
118 |
-
* @var ICWP_Wordpress_Simple_Firewall
|
119 |
-
*/
|
120 |
-
protected static $oInstance = null;
|
121 |
-
|
122 |
-
/**
|
123 |
-
* @param ICWP_WPSF_Plugin_Controller $oController
|
124 |
-
* @return self
|
125 |
-
* @throws Exception
|
126 |
-
*/
|
127 |
-
public static function GetInstance( $oController = null ) {
|
128 |
-
if ( is_null( self::$oInstance ) ) {
|
129 |
-
if ( is_null( $oController ) || !( $oController instanceof ICWP_WPSF_Plugin_Controller ) ) {
|
130 |
-
throw new Exception( 'Trying to create a Shield Security instance without a valid Controller' );
|
131 |
-
}
|
132 |
-
self::$oInstance = new self( $oController );
|
133 |
-
}
|
134 |
-
return self::$oInstance;
|
135 |
-
}
|
136 |
-
}
|
137 |
-
|
138 |
-
global $oICWP_Wpsf;
|
139 |
|
140 |
-
|
141 |
-
|
142 |
-
$
|
143 |
-
|
144 |
-
catch ( Exception $oE ) {
|
145 |
-
if ( is_admin() ) {
|
146 |
-
error_log( 'Perhaps due to a failed upgrade, the Shield plugin failed to load certain component(s) - you should remove the plugin and reinstall.' );
|
147 |
-
error_log( $oE->getMessage() );
|
148 |
-
}
|
149 |
}
|
3 |
* Plugin Name: Shield Security
|
4 |
* Plugin URI: http://icwp.io/2f
|
5 |
* Description: Powerful, Easy-To-Use #1 Rated WordPress Security System
|
6 |
+
* Version: 6.1.0
|
7 |
* Text Domain: wp-simple-firewall
|
8 |
* Domain Path: /languages/
|
9 |
* Author: iControlWP
|
11 |
*/
|
12 |
|
13 |
/**
|
14 |
+
* Copyright (c) 2018 iControlWP <support@icontrolwp.com>
|
15 |
* All rights reserved.
|
|
|
16 |
* "Shield" (formerly WordPress Simple Firewall) is distributed under the GNU
|
17 |
* General Public License, Version 2, June 1991. Copyright (C) 1989, 1991 Free
|
18 |
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
|
|
|
19 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
20 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
21 |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
28 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29 |
*/
|
30 |
|
|
|
|
|
|
|
|
|
|
|
31 |
if ( !defined( 'ICWP_DS' ) ) {
|
32 |
define( 'ICWP_DS', DIRECTORY_SEPARATOR );
|
33 |
}
|
43 |
}
|
44 |
}
|
45 |
|
46 |
+
// makes it available to the extension also.
|
47 |
+
require_once( dirname( __FILE__ ).'/src/common/icwp-foundation.php' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
|
49 |
+
add_action( 'plugins_loaded', 'icwp_wpsf_init', 1 ); // use 0 for extensions to ensure hooks have been added.
|
50 |
+
function icwp_wpsf_init() {
|
51 |
+
$sRootFile = __FILE__;
|
52 |
+
require_once( dirname( __FILE__ ).'/init.php' );
|
|
|
|
|
|
|
|
|
|
|
53 |
}
|
init.php
ADDED
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/** @var string $sRootFile */
|
3 |
+
global $oICWP_Wpsf;
|
4 |
+
|
5 |
+
if ( isset( $oICWP_Wpsf ) ) {
|
6 |
+
error_log( 'Attempting to load the Shield Plugin twice?' );
|
7 |
+
return;
|
8 |
+
}
|
9 |
+
|
10 |
+
// By requiring this file here, we assume we wont need to require it anywhere else.
|
11 |
+
require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'icwp-plugin-controller.php' );
|
12 |
+
|
13 |
+
class ICWP_Wordpress_Simple_Firewall extends ICWP_WPSF_Foundation {
|
14 |
+
|
15 |
+
/**
|
16 |
+
* @var ICWP_WPSF_Plugin_Controller
|
17 |
+
*/
|
18 |
+
protected static $oPluginController;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* @param ICWP_WPSF_Plugin_Controller $oController
|
22 |
+
*/
|
23 |
+
protected function __construct( ICWP_WPSF_Plugin_Controller $oController ) {
|
24 |
+
|
25 |
+
// All core values of the plugin are derived from the values stored in this value object.
|
26 |
+
self::$oPluginController = $oController;
|
27 |
+
$this->getController()->loadAllFeatures();
|
28 |
+
add_filter( $oController->doPluginPrefix( 'plugin_update_message' ), array(
|
29 |
+
$this,
|
30 |
+
'getPluginsListUpdateMessage'
|
31 |
+
) );
|
32 |
+
add_action( 'plugin_action_links', array( $this, 'onWpPluginActionLinks' ), 10, 4 );
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* @return ICWP_WPSF_Plugin_Controller
|
37 |
+
*/
|
38 |
+
public static function getController() {
|
39 |
+
return self::$oPluginController;
|
40 |
+
}
|
41 |
+
|
42 |
+
public function getPluginsListUpdateMessage( $sMessage ) {
|
43 |
+
return _wpsf__( 'Upgrade Now To Keep Your Firewall Up-To-Date With The Latest Features.' );
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* On the plugins listing page, hides the edit and deactivate links
|
48 |
+
* for this plugin based on permissions
|
49 |
+
* @param $aActionLinks
|
50 |
+
* @param $sPluginFile
|
51 |
+
* @return mixed
|
52 |
+
*/
|
53 |
+
public function onWpPluginActionLinks( $aActionLinks, $sPluginFile ) {
|
54 |
+
$oCon = $this->getController();
|
55 |
+
if ( !$oCon->getIsValidAdminArea() ) {
|
56 |
+
return $aActionLinks;
|
57 |
+
}
|
58 |
+
|
59 |
+
if ( $sPluginFile == $oCon->getPluginBaseFile() ) {
|
60 |
+
if ( !$oCon->getHasPermissionToManage() ) {
|
61 |
+
|
62 |
+
if ( array_key_exists( 'edit', $aActionLinks ) ) {
|
63 |
+
unset( $aActionLinks[ 'edit' ] );
|
64 |
+
}
|
65 |
+
if ( array_key_exists( 'deactivate', $aActionLinks ) ) {
|
66 |
+
unset( $aActionLinks[ 'deactivate' ] );
|
67 |
+
}
|
68 |
+
}
|
69 |
+
}
|
70 |
+
return $aActionLinks;
|
71 |
+
}
|
72 |
+
}
|
73 |
+
|
74 |
+
class ICWP_WPSF_Shield_Security extends ICWP_Wordpress_Simple_Firewall {
|
75 |
+
|
76 |
+
/**
|
77 |
+
* @var ICWP_Wordpress_Simple_Firewall
|
78 |
+
*/
|
79 |
+
protected static $oInstance = null;
|
80 |
+
|
81 |
+
/**
|
82 |
+
* @param ICWP_WPSF_Plugin_Controller $oController
|
83 |
+
* @return self
|
84 |
+
* @throws Exception
|
85 |
+
*/
|
86 |
+
public static function GetInstance( $oController = null ) {
|
87 |
+
if ( is_null( self::$oInstance ) ) {
|
88 |
+
if ( is_null( $oController ) || !( $oController instanceof ICWP_WPSF_Plugin_Controller ) ) {
|
89 |
+
throw new Exception( 'Trying to create a Shield Security instance without a valid Controller' );
|
90 |
+
}
|
91 |
+
self::$oInstance = new self( $oController );
|
92 |
+
}
|
93 |
+
return self::$oInstance;
|
94 |
+
}
|
95 |
+
}
|
96 |
+
|
97 |
+
try {
|
98 |
+
$oICWP_Wpsf_Controller = ICWP_WPSF_Plugin_Controller::GetInstance( $sRootFile );
|
99 |
+
$oICWP_Wpsf = ICWP_WPSF_Shield_Security::GetInstance( $oICWP_Wpsf_Controller );
|
100 |
+
}
|
101 |
+
catch ( Exception $oE ) {
|
102 |
+
if ( is_admin() ) {
|
103 |
+
error_log( 'Perhaps due to a failed upgrade, the Shield plugin failed to load certain component(s) - you should remove the plugin and reinstall.' );
|
104 |
+
error_log( $oE->getMessage() );
|
105 |
+
}
|
106 |
+
}
|
plugin-spec.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
{
|
2 |
"properties": {
|
3 |
-
"version": "6.
|
4 |
"slug_parent": "icwp",
|
5 |
"slug_plugin": "wpsf",
|
6 |
"human_name": "Shield",
|
@@ -44,8 +44,7 @@
|
|
44 |
"plugin"
|
45 |
],
|
46 |
"js": [
|
47 |
-
"bootstrap.min"
|
48 |
-
"icwp-options"
|
49 |
]
|
50 |
},
|
51 |
"frontend": {
|
1 |
{
|
2 |
"properties": {
|
3 |
+
"version": "6.1.0",
|
4 |
"slug_parent": "icwp",
|
5 |
"slug_plugin": "wpsf",
|
6 |
"human_name": "Shield",
|
44 |
"plugin"
|
45 |
],
|
46 |
"js": [
|
47 |
+
"bootstrap.min"
|
|
|
48 |
]
|
49 |
},
|
50 |
"frontend": {
|
readme.txt
CHANGED
@@ -3,10 +3,10 @@ Contributors: onedollarplugin, paultgoodchild
|
|
3 |
Donate link: http://icwp.io/q
|
4 |
License: GPLv3
|
5 |
License URI: http://www.gnu.org/licenses/gpl.html
|
6 |
-
Tags: security, firewall, spam, scan, two-factor authentication, login, 2FA, ithemes, wordfence, better wp security, all-in-one, lockdown, hack
|
7 |
Requires at least: 3.5.0
|
8 |
Tested up to: 4.9
|
9 |
-
Stable tag: 6.
|
10 |
|
11 |
Protect your reputation, your customers' reputation, and your WordPress sites for free with Shield - the most powerful security system for WordPress
|
12 |
|
@@ -338,7 +338,25 @@ Technical support, and some newer options and features will not be available to
|
|
338 |
|
339 |
You can [go Pro for just $1/month](http://icwp.io/aa). Technical support is available to premium clients only.
|
340 |
|
341 |
-
= 6.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
342 |
*Released: 18th December, 2017*
|
343 |
|
344 |
* **(v.0)** ADDED: All-new Shield Welcome and Setup Wizard - more helpful guided wizards to come.
|
@@ -346,9 +364,6 @@ You can [go Pro for just $1/month](http://icwp.io/aa). Technical support is avai
|
|
346 |
* **(v.0)** ADDED: [**PRO**] In conjunction with import/export - Shield Security Network: automated options syncing.
|
347 |
* **(v.0)** CHANGED: Going forward, new features and options will [support only PHP 5.4+](http://icwp.io/au). Existing features will remain unaffected.
|
348 |
|
349 |
-
= 6.0.0 Series =
|
350 |
-
*Released: 18th December, 2017*
|
351 |
-
|
352 |
= 5.20.0 Series =
|
353 |
*Released: 11th December, 2017*
|
354 |
|
3 |
Donate link: http://icwp.io/q
|
4 |
License: GPLv3
|
5 |
License URI: http://www.gnu.org/licenses/gpl.html
|
6 |
+
Tags: security, firewall, protect, spam, scan, recaptcha, two-factor authentication, login, 2FA, ithemes, wordfence, better wp security, all-in-one, lockdown, hack
|
7 |
Requires at least: 3.5.0
|
8 |
Tested up to: 4.9
|
9 |
+
Stable tag: 6.1.0
|
10 |
|
11 |
Protect your reputation, your customers' reputation, and your WordPress sites for free with Shield - the most powerful security system for WordPress
|
12 |
|
338 |
|
339 |
You can [go Pro for just $1/month](http://icwp.io/aa). Technical support is available to premium clients only.
|
340 |
|
341 |
+
= 6.1.0 Latest Release =
|
342 |
+
*Released: 15th January, 2018* [Release Notes](http://icwp.io/ay)
|
343 |
+
|
344 |
+
* **(v.0)** ADDED: 3x more Shield Wizards: Multi-factor Authentication, Core File Scanning, Unrecognised File Scanning.
|
345 |
+
* **(v.0)** ADDED: You can now use regular expressions for file exclusions in the 'Unrecognised File Scanner'.
|
346 |
+
* **(v.0)** CHANGED: File Scanner email notifications now link to the appropriate scanner wizard directly.
|
347 |
+
* **(v.0)** IMPROVED: Plugin options pages restyling.
|
348 |
+
* **(v.0)** IMPROVED: Plugin refactoring and improvements.
|
349 |
+
|
350 |
+
= 6.1.0 Series =
|
351 |
+
*Released: 15th January, 2018*
|
352 |
+
|
353 |
+
* **(v.0)** ADDED: 3x more Shield Wizards: Multi-factor Authentication, Core File Scanning, Unrecognised File Scanning.
|
354 |
+
* **(v.0)** ADDED: You can now use regular expressions for file exclusions in the 'Unrecognised File Scanner'.
|
355 |
+
* **(v.0)** CHANGED: File Scanner email notifications now link to the appropriate scanner wizard directly.
|
356 |
+
* **(v.0)** IMPROVED: Plugin options pages restyling.
|
357 |
+
* **(v.0)** IMPROVED: Plugin refactoring and improvements.
|
358 |
+
|
359 |
+
= 6.0.0 Series =
|
360 |
*Released: 18th December, 2017*
|
361 |
|
362 |
* **(v.0)** ADDED: All-new Shield Welcome and Setup Wizard - more helpful guided wizards to come.
|
364 |
* **(v.0)** ADDED: [**PRO**] In conjunction with import/export - Shield Security Network: automated options syncing.
|
365 |
* **(v.0)** CHANGED: Going forward, new features and options will [support only PHP 5.4+](http://icwp.io/au). Existing features will remain unaffected.
|
366 |
|
|
|
|
|
|
|
367 |
= 5.20.0 Series =
|
368 |
*Released: 11th December, 2017*
|
369 |
|
resources/css/global-plugin.css
CHANGED
@@ -76,78 +76,6 @@ ul.nav-tabs li.active a {
|
|
76 |
.bootstrap-wpadmin .icwpTopLevelRow .icwpTopLevelSpan {
|
77 |
margin-left: 0;
|
78 |
}
|
79 |
-
#icwpOptionsTopPill {
|
80 |
-
}
|
81 |
-
#icwpOptionsTopPill > .nav-pills {
|
82 |
-
border-bottom: 1px dashed #999999;
|
83 |
-
padding-bottom: 10px;
|
84 |
-
}
|
85 |
-
#icwpOptionsTopPill > .nav-pills li {
|
86 |
-
width: 33.3%;
|
87 |
-
}
|
88 |
-
#icwpOptionsTopPill > .nav-pills li a {
|
89 |
-
background-color: rgba(0, 0, 0, 0.2);
|
90 |
-
text-shadow: 1px 0 0 rgba(255, 255, 255, 0.4);
|
91 |
-
color: #666666;
|
92 |
-
height: 50px;
|
93 |
-
}
|
94 |
-
#icwpOptionsTopPill > .nav-pills li a:hover {
|
95 |
-
background-color: rgba(38, 66, 1, 0.3);
|
96 |
-
}
|
97 |
-
#icwpOptionsTopPill > .nav-pills li a:focus {
|
98 |
-
box-shadow: none;
|
99 |
-
}
|
100 |
-
#icwpOptionsTopPill > .nav-pills li span.dashicons {
|
101 |
-
float: left;
|
102 |
-
height: 100%;
|
103 |
-
font-size: 48px;
|
104 |
-
display: block;
|
105 |
-
width: 62px;
|
106 |
-
}
|
107 |
-
#icwpOptionsTopPill > .nav-pills li.active a {
|
108 |
-
background-color: rgba(69, 119, 0, 1);
|
109 |
-
color: #ffffff;
|
110 |
-
text-shadow: 1px 0 0 rgba(0, 0, 0, 0.5);
|
111 |
-
}
|
112 |
-
#icwpOptionsTopPill > .nav-pills li a .title {
|
113 |
-
font-weight: bolder;
|
114 |
-
font-size: 18px;
|
115 |
-
line-height: 24px;
|
116 |
-
}
|
117 |
-
#icwpOptionsTopPill > .nav-pills li a .summary {
|
118 |
-
font-size: 16px;
|
119 |
-
line-height: 28px;
|
120 |
-
padding-left: 10px;
|
121 |
-
}
|
122 |
-
#icwpOptionsTopPill > .nav-pills li a.active {
|
123 |
-
}
|
124 |
-
#icwpOptionsTopPill > .tab-content {
|
125 |
-
background-color: transparent;
|
126 |
-
border: 1px solid transparent;
|
127 |
-
}
|
128 |
-
#icwpOptionsTopPill > .tab-content .content-help {
|
129 |
-
background-color: #fafafa;
|
130 |
-
padding: 10px 20px;
|
131 |
-
box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
|
132 |
-
margin: 5px;
|
133 |
-
}
|
134 |
-
#icwpOptionsTopPill .content-help h2 {
|
135 |
-
margin-bottom: 8px;
|
136 |
-
}
|
137 |
-
#icwpOptionsTopPill .content-help p,
|
138 |
-
#icwpOptionsTopPill .content-help li {
|
139 |
-
font-size: 14px;
|
140 |
-
}
|
141 |
-
#icwpOptionsTopPill .content-help dt {
|
142 |
-
border-bottom: 1px dotted rgba(0, 0, 0, 0.2);
|
143 |
-
font-size: 16px;
|
144 |
-
margin-bottom: 7px;
|
145 |
-
padding-bottom: 3px;
|
146 |
-
}
|
147 |
-
#icwpOptionsTopPill .content-help dd {
|
148 |
-
margin-bottom: 15px;
|
149 |
-
margin-left: 12px;
|
150 |
-
}
|
151 |
th.column-icwp_autoupdate, td.icwp_autoupdate, th#icwp_autoupdate {
|
152 |
text-align: center;
|
153 |
vertical-align: middle;
|
76 |
.bootstrap-wpadmin .icwpTopLevelRow .icwpTopLevelSpan {
|
77 |
margin-left: 0;
|
78 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
th.column-icwp_autoupdate, td.icwp_autoupdate, th#icwp_autoupdate {
|
80 |
text-align: center;
|
81 |
vertical-align: middle;
|
resources/css/plugin.css
CHANGED
@@ -29,7 +29,16 @@
|
|
29 |
.wrap .icon32 {
|
30 |
width: 32px;
|
31 |
}
|
32 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
.icwp-options-page ul.nav-tabs {
|
34 |
margin: 0;
|
35 |
}
|
@@ -51,7 +60,6 @@
|
|
51 |
border: 1px solid #dddddd;
|
52 |
border-top: 0 none;
|
53 |
}
|
54 |
-
|
55 |
.icwp-options-page .form-actions {
|
56 |
background-color: #d8d8d8;
|
57 |
border: 0 none;
|
@@ -62,13 +70,11 @@
|
|
62 |
.icwp-options-page .form-actions .btn {
|
63 |
padding: 16px 40px;
|
64 |
}
|
65 |
-
|
66 |
table.table-audit_trail {
|
67 |
border: 2px solid #777777;
|
68 |
margin-bottom: 40px;
|
69 |
width: auto;
|
70 |
}
|
71 |
-
|
72 |
table.table-audit_trail .cell-time {
|
73 |
width: 90px;
|
74 |
max-width: 90px;
|
@@ -93,14 +99,6 @@ table.table-audit_trail .cell-ip {
|
|
93 |
width: 200px;
|
94 |
max-width: 240px;
|
95 |
}
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
.bootstrap-wpadmin .page-header {
|
100 |
-
padding-bottom: 17px;
|
101 |
-
margin: 18px 0 0;
|
102 |
-
border-bottom: 1px solid transparent;
|
103 |
-
}
|
104 |
/* Form elements */
|
105 |
.bootstrap-wpadmin form fieldset {
|
106 |
width: 80%;
|
@@ -117,7 +115,7 @@ p.code-description {
|
|
117 |
}
|
118 |
/* Worpit promo */
|
119 |
#worpit_button {
|
120 |
-
background: url("../images/bright_squares.png") #
|
121 |
}
|
122 |
#worpit_button {
|
123 |
border: 1px solid #cccccc;
|
@@ -132,14 +130,13 @@ p.code-description {
|
|
132 |
height: 275px;
|
133 |
}
|
134 |
.row#developer_channel_promo #developer_channel_form {
|
135 |
-
border: 1px solid #
|
136 |
border-radius: 6px;
|
137 |
height: 315px; /* 275px + 20px-padding-x2 */
|
138 |
}
|
139 |
.row#developer_channel_promo #developer_channel_form h3 {
|
140 |
padding: 10px 20px;
|
141 |
}
|
142 |
-
|
143 |
.row.option_section_row {
|
144 |
margin-left: 0;
|
145 |
padding-bottom: 24px;
|
@@ -163,14 +160,12 @@ p.code-description {
|
|
163 |
|
164 |
.well.admin_access_restriction_form {
|
165 |
background-color: #fbfbfb;
|
166 |
-
border: 1px solid #
|
167 |
box-shadow: none;
|
168 |
}
|
169 |
-
|
170 |
.well.admin_access_restriction_form .form-actions {
|
171 |
background-color: #fbfbfb;
|
172 |
}
|
173 |
-
|
174 |
/** LESS PAGE **/
|
175 |
.enabled_section {
|
176 |
opacity: 1.0;
|
@@ -180,25 +175,25 @@ p.code-description {
|
|
180 |
}
|
181 |
/* BOOSTRAP SETTINGS PAGE STYLES */
|
182 |
|
|
|
|
|
|
|
183 |
/** Section summaries **/
|
184 |
-
.
|
185 |
-
margin: 10px 0 20px;
|
186 |
}
|
187 |
-
.
|
188 |
-
background-color: #
|
189 |
-
border
|
190 |
-
|
191 |
margin: 0;
|
192 |
-
padding:
|
193 |
}
|
194 |
-
.
|
195 |
-
margin:
|
196 |
-
font-family: 'Open Sans';
|
197 |
}
|
198 |
-
.
|
199 |
-webkit-touch-callout: none;
|
200 |
-webkit-user-select: none;
|
201 |
-
-khtml-user-select: none;
|
202 |
-moz-user-select: none;
|
203 |
-ms-user-select: none;
|
204 |
user-select: none;
|
@@ -212,46 +207,59 @@ p.code-description {
|
|
212 |
font-size: smaller;
|
213 |
font-style: italic;
|
214 |
}
|
215 |
-
.
|
216 |
-
border-bottom: 1px dashed
|
217 |
-
margin-bottom:
|
218 |
-
padding: 16px
|
|
|
219 |
}
|
220 |
-
.
|
221 |
-
border:
|
222 |
-
border-
|
|
|
223 |
box-sizing: border-box;
|
224 |
-
margin-left: 40px;
|
225 |
padding: 0;
|
226 |
-
|
227 |
-
.form-horizontal .item_group .control-group {
|
228 |
-
margin: 20px 20px 20px 0;
|
229 |
}
|
230 |
-
.
|
231 |
-
|
232 |
}
|
233 |
-
.
|
234 |
-
|
235 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
236 |
}
|
237 |
-
|
238 |
.row.option_row {
|
239 |
margin-bottom: 15px;
|
240 |
}
|
241 |
-
|
242 |
.overlay_container.disabled {
|
243 |
position: relative;
|
244 |
}
|
245 |
.option_overlay {
|
246 |
position: absolute;
|
247 |
-
background-color: rgba(0,0,0,0.2);
|
248 |
height: 100%;
|
249 |
width: 100%;
|
250 |
transition: background-color 0.5s ease;
|
251 |
z-index: 5;
|
252 |
}
|
253 |
.option_overlay:hover {
|
254 |
-
background-color: rgba(0,0,0,0.5);
|
255 |
}
|
256 |
.option_overlay .overlay_message {
|
257 |
display: none;
|
@@ -259,23 +267,28 @@ p.code-description {
|
|
259 |
.option_overlay .overlay_message:hover,
|
260 |
.option_overlay:hover .overlay_message {
|
261 |
display: block;
|
262 |
-
color: #
|
263 |
-
font-size:
|
264 |
margin: 25px auto auto auto;
|
265 |
padding: 0 20px;
|
266 |
width: auto;
|
267 |
-
background: rgba(255,255,255,0.8);
|
268 |
line-height: 50px;
|
269 |
text-align: center;
|
270 |
user-select: none;
|
271 |
}
|
272 |
-
|
|
|
|
|
273 |
.option_section {
|
274 |
-
background-color:
|
275 |
-
border: 1px dashed
|
276 |
border-radius: 4px;
|
277 |
padding: 8px 10px;
|
278 |
}
|
|
|
|
|
|
|
279 |
.option_section label {
|
280 |
background-color: transparent;
|
281 |
}
|
@@ -290,16 +303,13 @@ p.code-description {
|
|
290 |
}
|
291 |
.option_section:hover {
|
292 |
background-color: #ffffff;
|
293 |
-
border: 1px dashed #
|
294 |
-
cursor: pointer;
|
295 |
}
|
296 |
-
|
297 |
.option_section.active {
|
298 |
}
|
299 |
table.table th {
|
300 |
border-bottom: 1px solid #777777;
|
301 |
}
|
302 |
-
|
303 |
table.tbl_tbs_options {
|
304 |
width: 100%;
|
305 |
border: 1px solid transparent;
|
@@ -308,19 +318,16 @@ table.tbl_tbs_options tr td {
|
|
308 |
width: 49%;
|
309 |
border: 1px solid transparent;
|
310 |
}
|
311 |
-
|
312 |
select#hlt_bootstrap_option {
|
313 |
padding: 5px;
|
314 |
-
border-radius:6px 6px 6px 6px;
|
315 |
height: 30px;
|
316 |
width: 200px;
|
317 |
}
|
318 |
-
|
319 |
table#tbl_tbs_options_javascript td {
|
320 |
vertical-align: top;
|
321 |
width: 50%;
|
322 |
}
|
323 |
-
|
324 |
/** OPTIONS PAGES **/
|
325 |
.bootstrap-wpadmin > .row {
|
326 |
width: 960px;
|
@@ -330,13 +337,14 @@ table#tbl_tbs_options_javascript td {
|
|
330 |
label input[type=checkbox] {
|
331 |
height: 16px !important;
|
332 |
}
|
333 |
-
|
334 |
/** FEature summaries **/
|
335 |
.bootstrap-wpadmin .feature-summary-blocks {
|
336 |
text-align: center;
|
337 |
width: 100%;
|
338 |
margin-top: 20px;
|
339 |
-
box-shadow:
|
|
|
|
|
340 |
}
|
341 |
.feature-summary-blocks .feature-icon:before {
|
342 |
-webkit-font-smoothing: antialiased;
|
@@ -349,22 +357,20 @@ label input[type=checkbox] {
|
|
349 |
text-shadow: 1px 0 0 rgba(0, 0, 0, 0.4);
|
350 |
width: 100%;
|
351 |
}
|
352 |
-
|
353 |
.feature-summary-blocks .summary-state {
|
354 |
border: 1px solid transparent;
|
355 |
overflow: hidden;
|
356 |
text-align: center;
|
357 |
margin-bottom: -1px;
|
358 |
}
|
359 |
-
|
360 |
.feature-summary-blocks .summary-state.active-feature {
|
361 |
background-color: rgba(69, 119, 0, 1);
|
362 |
}
|
363 |
.feature-summary-blocks .summary-state.active-feature a {
|
364 |
-
color: rgba(255,255,255,1);
|
365 |
}
|
366 |
.feature-summary-blocks .summary-state.active-feature.state-off {
|
367 |
-
background-color: rgba(
|
368 |
}
|
369 |
.feature-summary-blocks .summary-state .popover {
|
370 |
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.4);
|
@@ -382,10 +388,10 @@ label input[type=checkbox] {
|
|
382 |
border-left: 1px solid transparent;
|
383 |
background-color: rgba(255, 255, 255, 0.8);
|
384 |
}
|
385 |
-
.feature-summary-blocks .summary-state:hover{
|
386 |
}
|
387 |
.feature-summary-blocks .summary-state a p {
|
388 |
-
text-shadow: 0 0 0 rgba(0,0,0, 0.6);
|
389 |
font-size: 12px;
|
390 |
margin: 0;
|
391 |
}
|
@@ -407,7 +413,7 @@ label input[type=checkbox] {
|
|
407 |
color: rgba(69, 119, 0, 1);
|
408 |
}
|
409 |
.feature-summary-blocks .state-off a {
|
410 |
-
color: rgba(
|
411 |
}
|
412 |
.feature-summary-blocks .state-on a:hover {
|
413 |
color: rgb(99, 150, 0);
|
@@ -415,14 +421,13 @@ label input[type=checkbox] {
|
|
415 |
.feature-summary-blocks .state-off a:hover {
|
416 |
color: rgba(207, 90, 0, 0.85);
|
417 |
}
|
418 |
-
|
419 |
.feature-summary-blocks .feature-summary-block.state-on {
|
420 |
-
background-color: rgba(
|
421 |
}
|
422 |
.feature-summary-blocks .feature-summary-block.state-off {
|
423 |
-
background-color: rgba(
|
424 |
}
|
425 |
-
#feature-plugin .feature-icon:before{
|
426 |
content: "\f111";
|
427 |
}
|
428 |
#feature-admin_access_restriction .feature-icon:before {
|
@@ -464,11 +469,9 @@ label input[type=checkbox] {
|
|
464 |
#feature-support .feature-icon:before {
|
465 |
content: "\f525";
|
466 |
}
|
467 |
-
|
468 |
input[type="email"] {
|
469 |
height: 28px;
|
470 |
}
|
471 |
-
|
472 |
.bootstrap-wpadmin .row .shield-free-block {
|
473 |
background-color: rgba(255, 255, 255, 0.7);
|
474 |
border: 1px solid rgba(0, 0, 0, 0.1);
|
@@ -476,4 +479,159 @@ input[type="email"] {
|
|
476 |
}
|
477 |
.bootstrap-wpadmin .row .shield-free-block p {
|
478 |
margin-bottom: 18px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
479 |
}
|
29 |
.wrap .icon32 {
|
30 |
width: 32px;
|
31 |
}
|
32 |
+
.bootstrap-wpadmin .page-header {
|
33 |
+
margin: 5px 0 15px;
|
34 |
+
padding-bottom: 0;
|
35 |
+
border-bottom: 1px solid transparent;
|
36 |
+
}
|
37 |
+
.bootstrap-wpadmin .page-header h2 small.feature-tagline {
|
38 |
+
font-size: 14px;
|
39 |
+
line-height: 10px;
|
40 |
+
letter-spacing: -0.5px;
|
41 |
+
}
|
42 |
.icwp-options-page ul.nav-tabs {
|
43 |
margin: 0;
|
44 |
}
|
60 |
border: 1px solid #dddddd;
|
61 |
border-top: 0 none;
|
62 |
}
|
|
|
63 |
.icwp-options-page .form-actions {
|
64 |
background-color: #d8d8d8;
|
65 |
border: 0 none;
|
70 |
.icwp-options-page .form-actions .btn {
|
71 |
padding: 16px 40px;
|
72 |
}
|
|
|
73 |
table.table-audit_trail {
|
74 |
border: 2px solid #777777;
|
75 |
margin-bottom: 40px;
|
76 |
width: auto;
|
77 |
}
|
|
|
78 |
table.table-audit_trail .cell-time {
|
79 |
width: 90px;
|
80 |
max-width: 90px;
|
99 |
width: 200px;
|
100 |
max-width: 240px;
|
101 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
102 |
/* Form elements */
|
103 |
.bootstrap-wpadmin form fieldset {
|
104 |
width: 80%;
|
115 |
}
|
116 |
/* Worpit promo */
|
117 |
#worpit_button {
|
118 |
+
background: url("../images/bright_squares.png") #efefef;
|
119 |
}
|
120 |
#worpit_button {
|
121 |
border: 1px solid #cccccc;
|
130 |
height: 275px;
|
131 |
}
|
132 |
.row#developer_channel_promo #developer_channel_form {
|
133 |
+
border: 1px solid #eeeeee;
|
134 |
border-radius: 6px;
|
135 |
height: 315px; /* 275px + 20px-padding-x2 */
|
136 |
}
|
137 |
.row#developer_channel_promo #developer_channel_form h3 {
|
138 |
padding: 10px 20px;
|
139 |
}
|
|
|
140 |
.row.option_section_row {
|
141 |
margin-left: 0;
|
142 |
padding-bottom: 24px;
|
160 |
|
161 |
.well.admin_access_restriction_form {
|
162 |
background-color: #fbfbfb;
|
163 |
+
border: 1px solid #cccccc;
|
164 |
box-shadow: none;
|
165 |
}
|
|
|
166 |
.well.admin_access_restriction_form .form-actions {
|
167 |
background-color: #fbfbfb;
|
168 |
}
|
|
|
169 |
/** LESS PAGE **/
|
170 |
.enabled_section {
|
171 |
opacity: 1.0;
|
175 |
}
|
176 |
/* BOOSTRAP SETTINGS PAGE STYLES */
|
177 |
|
178 |
+
.bootstrap-wpadmin .form-horizontal .form-actions {
|
179 |
+
padding-left: 200px;
|
180 |
+
}
|
181 |
/** Section summaries **/
|
182 |
+
.row_section_summary {
|
|
|
183 |
}
|
184 |
+
.row_section_summary div {
|
185 |
+
background-color: #f5f4f4;
|
186 |
+
border: 1px solid rgb(230, 226, 226);
|
187 |
+
border-width: 1px 0;
|
188 |
margin: 0;
|
189 |
+
padding: 0 20px 0 2px;
|
190 |
}
|
191 |
+
.row_section_summary p {
|
192 |
+
margin: 12px 20px;
|
|
|
193 |
}
|
194 |
+
.row_section_summary p.noselect {
|
195 |
-webkit-touch-callout: none;
|
196 |
-webkit-user-select: none;
|
|
|
197 |
-moz-user-select: none;
|
198 |
-ms-user-select: none;
|
199 |
user-select: none;
|
207 |
font-size: smaller;
|
208 |
font-style: italic;
|
209 |
}
|
210 |
+
.options-body legend {
|
211 |
+
border-bottom: 1px dashed transparent;
|
212 |
+
margin-bottom: 0;
|
213 |
+
padding: 16px 22px 12px;
|
214 |
+
width: 80%;
|
215 |
}
|
216 |
+
.option_row .item_group {
|
217 |
+
border-style: solid;
|
218 |
+
border-width: 1px 0;
|
219 |
+
border-color: rgb(230, 226, 226);
|
220 |
box-sizing: border-box;
|
|
|
221 |
padding: 0;
|
222 |
+
margin-top: -1px;
|
|
|
|
|
223 |
}
|
224 |
+
.option_row .item_group .control-group {
|
225 |
+
margin: 22px 20px;
|
226 |
}
|
227 |
+
.option_row .item_group .control-group .controls {
|
228 |
+
margin-left: 180px;
|
229 |
+
}
|
230 |
+
.option_row .item_group .control-group .control-label {
|
231 |
+
float: left;
|
232 |
+
width: 150px;
|
233 |
+
margin-top: 2px;
|
234 |
+
text-align: right;
|
235 |
+
}
|
236 |
+
.control-label .optname {
|
237 |
+
display: block;
|
238 |
+
}
|
239 |
+
.control-label .optlinks {
|
240 |
+
display: block;
|
241 |
+
margin-top: 5px;
|
242 |
+
}
|
243 |
+
.option_row .item_group.selected_item_group {
|
244 |
+
background-color: rgba(135, 232, 38, 0.03);
|
245 |
+
border-color: rgb(203, 232, 174);
|
246 |
}
|
|
|
247 |
.row.option_row {
|
248 |
margin-bottom: 15px;
|
249 |
}
|
|
|
250 |
.overlay_container.disabled {
|
251 |
position: relative;
|
252 |
}
|
253 |
.option_overlay {
|
254 |
position: absolute;
|
255 |
+
background-color: rgba(0, 0, 0, 0.2);
|
256 |
height: 100%;
|
257 |
width: 100%;
|
258 |
transition: background-color 0.5s ease;
|
259 |
z-index: 5;
|
260 |
}
|
261 |
.option_overlay:hover {
|
262 |
+
background-color: rgba(0, 0, 0, 0.5);
|
263 |
}
|
264 |
.option_overlay .overlay_message {
|
265 |
display: none;
|
267 |
.option_overlay .overlay_message:hover,
|
268 |
.option_overlay:hover .overlay_message {
|
269 |
display: block;
|
270 |
+
color: #333333;
|
271 |
+
font-size: 24px;
|
272 |
margin: 25px auto auto auto;
|
273 |
padding: 0 20px;
|
274 |
width: auto;
|
275 |
+
background: rgba(255, 255, 255, 0.8);
|
276 |
line-height: 50px;
|
277 |
text-align: center;
|
278 |
user-select: none;
|
279 |
}
|
280 |
+
.option_overlay:hover .overlay_message a:hover {
|
281 |
+
text-decoration: none;
|
282 |
+
}
|
283 |
.option_section {
|
284 |
+
background-color: transparent;
|
285 |
+
border: 1px dashed transparent;
|
286 |
border-radius: 4px;
|
287 |
padding: 8px 10px;
|
288 |
}
|
289 |
+
.option_section input[type=checkbox] {
|
290 |
+
margin-right: 5px;
|
291 |
+
}
|
292 |
.option_section label {
|
293 |
background-color: transparent;
|
294 |
}
|
303 |
}
|
304 |
.option_section:hover {
|
305 |
background-color: #ffffff;
|
306 |
+
border: 1px dashed #bbbbbb;
|
|
|
307 |
}
|
|
|
308 |
.option_section.active {
|
309 |
}
|
310 |
table.table th {
|
311 |
border-bottom: 1px solid #777777;
|
312 |
}
|
|
|
313 |
table.tbl_tbs_options {
|
314 |
width: 100%;
|
315 |
border: 1px solid transparent;
|
318 |
width: 49%;
|
319 |
border: 1px solid transparent;
|
320 |
}
|
|
|
321 |
select#hlt_bootstrap_option {
|
322 |
padding: 5px;
|
323 |
+
border-radius: 6px 6px 6px 6px;
|
324 |
height: 30px;
|
325 |
width: 200px;
|
326 |
}
|
|
|
327 |
table#tbl_tbs_options_javascript td {
|
328 |
vertical-align: top;
|
329 |
width: 50%;
|
330 |
}
|
|
|
331 |
/** OPTIONS PAGES **/
|
332 |
.bootstrap-wpadmin > .row {
|
333 |
width: 960px;
|
337 |
label input[type=checkbox] {
|
338 |
height: 16px !important;
|
339 |
}
|
|
|
340 |
/** FEature summaries **/
|
341 |
.bootstrap-wpadmin .feature-summary-blocks {
|
342 |
text-align: center;
|
343 |
width: 100%;
|
344 |
margin-top: 20px;
|
345 |
+
box-shadow: 1px 1px 2px 0 rgba(0, 0, 0, 0.2) inset;
|
346 |
+
border: 1px solid #ccc;
|
347 |
+
background: #f9f9f9;
|
348 |
}
|
349 |
.feature-summary-blocks .feature-icon:before {
|
350 |
-webkit-font-smoothing: antialiased;
|
357 |
text-shadow: 1px 0 0 rgba(0, 0, 0, 0.4);
|
358 |
width: 100%;
|
359 |
}
|
|
|
360 |
.feature-summary-blocks .summary-state {
|
361 |
border: 1px solid transparent;
|
362 |
overflow: hidden;
|
363 |
text-align: center;
|
364 |
margin-bottom: -1px;
|
365 |
}
|
|
|
366 |
.feature-summary-blocks .summary-state.active-feature {
|
367 |
background-color: rgba(69, 119, 0, 1);
|
368 |
}
|
369 |
.feature-summary-blocks .summary-state.active-feature a {
|
370 |
+
color: rgba(255, 255, 255, 1);
|
371 |
}
|
372 |
.feature-summary-blocks .summary-state.active-feature.state-off {
|
373 |
+
background-color: rgba(173, 84, 0, 0.85);
|
374 |
}
|
375 |
.feature-summary-blocks .summary-state .popover {
|
376 |
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.4);
|
388 |
border-left: 1px solid transparent;
|
389 |
background-color: rgba(255, 255, 255, 0.8);
|
390 |
}
|
391 |
+
.feature-summary-blocks .summary-state:hover {
|
392 |
}
|
393 |
.feature-summary-blocks .summary-state a p {
|
394 |
+
text-shadow: 0 0 0 rgba(0, 0, 0, 0.6);
|
395 |
font-size: 12px;
|
396 |
margin: 0;
|
397 |
}
|
413 |
color: rgba(69, 119, 0, 1);
|
414 |
}
|
415 |
.feature-summary-blocks .state-off a {
|
416 |
+
color: rgba(173, 84, 0, 0.85);
|
417 |
}
|
418 |
.feature-summary-blocks .state-on a:hover {
|
419 |
color: rgb(99, 150, 0);
|
421 |
.feature-summary-blocks .state-off a:hover {
|
422 |
color: rgba(207, 90, 0, 0.85);
|
423 |
}
|
|
|
424 |
.feature-summary-blocks .feature-summary-block.state-on {
|
425 |
+
background-color: rgba(102, 216, 45, 0.2);
|
426 |
}
|
427 |
.feature-summary-blocks .feature-summary-block.state-off {
|
428 |
+
background-color: rgba(239, 141, 49, 0.2);
|
429 |
}
|
430 |
+
#feature-plugin .feature-icon:before {
|
431 |
content: "\f111";
|
432 |
}
|
433 |
#feature-admin_access_restriction .feature-icon:before {
|
469 |
#feature-support .feature-icon:before {
|
470 |
content: "\f525";
|
471 |
}
|
|
|
472 |
input[type="email"] {
|
473 |
height: 28px;
|
474 |
}
|
|
|
475 |
.bootstrap-wpadmin .row .shield-free-block {
|
476 |
background-color: rgba(255, 255, 255, 0.7);
|
477 |
border: 1px solid rgba(0, 0, 0, 0.1);
|
479 |
}
|
480 |
.bootstrap-wpadmin .row .shield-free-block p {
|
481 |
margin-bottom: 18px;
|
482 |
+
}
|
483 |
+
#icwpOptionsTopPill {
|
484 |
+
}
|
485 |
+
#icwpOptionsTopPill > .nav-pills {
|
486 |
+
border-bottom: 1px dashed #999999;
|
487 |
+
padding-bottom: 10px;
|
488 |
+
}
|
489 |
+
#icwpOptionsTopPill > .nav-pills li {
|
490 |
+
width: 30.5%;
|
491 |
+
}
|
492 |
+
#icwpOptionsTopPill > .nav-pills li#icwpWizardPill {
|
493 |
+
width: 8%;
|
494 |
+
}
|
495 |
+
#icwpOptionsTopPill > .nav-pills li#icwpWizardPill .tooltip {
|
496 |
+
opacity: 1.0;
|
497 |
+
}
|
498 |
+
#icwpOptionsTopPill > .nav-pills li#icwpWizardPill .tooltip .tooltip-inner {
|
499 |
+
max-width: none;
|
500 |
+
font-size: 16px;
|
501 |
+
padding: 8px 12px;
|
502 |
+
}
|
503 |
+
#icwpOptionsTopPill > .nav-pills li#icwpWizardPill a {
|
504 |
+
background-size: 100%;
|
505 |
+
background-color: #1cbaf3;
|
506 |
+
background-repeat: no-repeat;
|
507 |
+
background-origin: content-box;
|
508 |
+
background-position: 0 4px;
|
509 |
+
}
|
510 |
+
#icwpOptionsTopPill > .nav-pills li a {
|
511 |
+
background-color: rgba(0, 0, 0, 0.2);
|
512 |
+
text-shadow: 1px 0 0 rgba(255, 255, 255, 0.4);
|
513 |
+
color: #666666;
|
514 |
+
height: 50px;
|
515 |
+
}
|
516 |
+
#icwpOptionsTopPill > .nav-pills li a:hover {
|
517 |
+
background-color: rgba(38, 66, 1, 0.3);
|
518 |
+
}
|
519 |
+
#icwpOptionsTopPill > .nav-pills li a:focus {
|
520 |
+
box-shadow: none;
|
521 |
+
}
|
522 |
+
#icwpOptionsTopPill > .nav-pills li span.dashicons {
|
523 |
+
float: left;
|
524 |
+
height: 100%;
|
525 |
+
font-size: 48px;
|
526 |
+
display: block;
|
527 |
+
width: 62px;
|
528 |
+
}
|
529 |
+
#icwpOptionsTopPill > .nav-pills li.active a {
|
530 |
+
background-color: rgba(69, 119, 0, 1);
|
531 |
+
color: #ffffff;
|
532 |
+
text-shadow: 1px 0 0 rgba(0, 0, 0, 0.5);
|
533 |
+
}
|
534 |
+
#icwpOptionsTopPill > .nav-pills li a .title {
|
535 |
+
font-weight: bolder;
|
536 |
+
font-size: 18px;
|
537 |
+
line-height: 24px;
|
538 |
+
}
|
539 |
+
#icwpOptionsTopPill > .nav-pills li a .summary {
|
540 |
+
font-size: 16px;
|
541 |
+
line-height: 28px;
|
542 |
+
padding-left: 10px;
|
543 |
+
}
|
544 |
+
#icwpOptionsTopPill > .nav-pills li a.active {
|
545 |
+
}
|
546 |
+
#icwpOptionsTopPill > .tab-content {
|
547 |
+
background-color: transparent;
|
548 |
+
border: 1px solid transparent;
|
549 |
+
}
|
550 |
+
#icwpOptionsTopPill > .tab-content .content-help {
|
551 |
+
background-color: #fafafa;
|
552 |
+
padding: 10px 20px;
|
553 |
+
box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
|
554 |
+
margin: 5px;
|
555 |
+
}
|
556 |
+
#icwpOptionsTopPill .content-help h2 {
|
557 |
+
margin-bottom: 8px;
|
558 |
+
}
|
559 |
+
#icwpOptionsTopPill .content-help p,
|
560 |
+
#icwpOptionsTopPill .content-help li {
|
561 |
+
font-size: 14px;
|
562 |
+
}
|
563 |
+
#icwpOptionsTopPill .content-help dt {
|
564 |
+
border-bottom: 1px dotted rgba(0, 0, 0, 0.2);
|
565 |
+
font-size: 16px;
|
566 |
+
margin-bottom: 7px;
|
567 |
+
padding-bottom: 3px;
|
568 |
+
}
|
569 |
+
#icwpOptionsTopPill .content-help dd {
|
570 |
+
margin-bottom: 15px;
|
571 |
+
margin-left: 12px;
|
572 |
+
}
|
573 |
+
.bootstrap-wpadmin .option_section_row .options-body {
|
574 |
+
}
|
575 |
+
.bootstrap-wpadmin .option_row .item_group {
|
576 |
+
margin-left: 0;
|
577 |
+
}
|
578 |
+
|
579 |
+
/* The switch - the box around the slider */
|
580 |
+
label.forcheckbox .summary {
|
581 |
+
vertical-align: top;
|
582 |
+
line-height: 20px;
|
583 |
+
margin-left: 7px;
|
584 |
+
}
|
585 |
+
.switch {
|
586 |
+
position: relative;
|
587 |
+
display: inline-block;
|
588 |
+
width: 40px;
|
589 |
+
height: 20px;
|
590 |
+
}
|
591 |
+
.bootstrap-wpadmin .switch .summary {
|
592 |
+
display: block;
|
593 |
+
}
|
594 |
+
/* Hide default HTML checkbox */
|
595 |
+
.bootstrap-wpadmin .switch input {display:none; !important;}
|
596 |
+
|
597 |
+
/* The slider */
|
598 |
+
.slider {
|
599 |
+
position: absolute;
|
600 |
+
cursor: pointer;
|
601 |
+
top: 0;
|
602 |
+
left: 0;
|
603 |
+
right: 0;
|
604 |
+
bottom: 0;
|
605 |
+
background-color: #ccc;
|
606 |
+
-webkit-transition: .1s;
|
607 |
+
transition: .1s;
|
608 |
+
}
|
609 |
+
.slider:before {
|
610 |
+
position: absolute;
|
611 |
+
content: "";
|
612 |
+
height: 16px;
|
613 |
+
width: 16px;
|
614 |
+
left: 2px;
|
615 |
+
bottom: 2px;
|
616 |
+
background-color: white;
|
617 |
+
-webkit-transition: .1s;
|
618 |
+
transition: .1s;
|
619 |
+
}
|
620 |
+
input:checked + .slider {
|
621 |
+
background-color: rgba(69, 119, 0, 1);
|
622 |
+
}
|
623 |
+
input:focus + .slider {
|
624 |
+
box-shadow: 0 0 1px rgba(69, 119, 0, 1);
|
625 |
+
}
|
626 |
+
input:checked + .slider:before {
|
627 |
+
-webkit-transform: translateX(20px);
|
628 |
+
-ms-transform: translateX(20px);
|
629 |
+
transform: translateX(20px);
|
630 |
+
}
|
631 |
+
/* Rounded sliders */
|
632 |
+
.slider.round {
|
633 |
+
border-radius: 3px;
|
634 |
+
}
|
635 |
+
.slider.round:before {
|
636 |
+
border-radius: 10%;
|
637 |
}
|
resources/css/wizard.css
CHANGED
@@ -47,10 +47,14 @@ body.wait {
|
|
47 |
.wizard p {
|
48 |
margin-bottom: 20px;
|
49 |
}
|
|
|
50 |
.wizard .body ul {
|
51 |
-
|
52 |
padding-left: 20px;
|
53 |
}
|
|
|
|
|
|
|
54 |
.wizard p.wizard-response {
|
55 |
padding: 10px 15px;
|
56 |
}
|
@@ -67,4 +71,49 @@ body.wait {
|
|
67 |
border: 1px solid #888;
|
68 |
height: 64px;
|
69 |
width: 64px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
}
|
47 |
.wizard p {
|
48 |
margin-bottom: 20px;
|
49 |
}
|
50 |
+
.wizard .body ol,
|
51 |
.wizard .body ul {
|
52 |
+
margin-bottom: 20px;
|
53 |
padding-left: 20px;
|
54 |
}
|
55 |
+
.wizard .body ul {
|
56 |
+
list-style: square inside none;
|
57 |
+
}
|
58 |
.wizard p.wizard-response {
|
59 |
padding: 10px 15px;
|
60 |
}
|
71 |
border: 1px solid #888;
|
72 |
height: 64px;
|
73 |
width: 64px;
|
74 |
+
}
|
75 |
+
.wizard .indent_slight {
|
76 |
+
margin-left: 26px;
|
77 |
+
}
|
78 |
+
|
79 |
+
.wizard_slot {
|
80 |
+
border: 1px solid #dddddd;
|
81 |
+
border-radius: 3px;
|
82 |
+
margin-top: 30px;
|
83 |
+
padding: 0 20px 20px;
|
84 |
+
}
|
85 |
+
.wizard_slot:hover {
|
86 |
+
background-color: #ffffff;
|
87 |
+
}
|
88 |
+
|
89 |
+
#GoProBtn {
|
90 |
+
width: 128px;
|
91 |
+
display: block;
|
92 |
+
margin: 5px auto 20px;
|
93 |
+
}
|
94 |
+
|
95 |
+
#FooterWizardBanner {
|
96 |
+
position: fixed;
|
97 |
+
bottom: 0;
|
98 |
+
height: 100px;
|
99 |
+
width: 100%;
|
100 |
+
}
|
101 |
+
#WizardTop {
|
102 |
+
height: 40px;
|
103 |
+
background-color: #fafafa;
|
104 |
+
background: linear-gradient(to top, rgba(250,250,250,0.95), rgba(250,250,250,0.7));
|
105 |
+
}
|
106 |
+
#WizardBanner {
|
107 |
+
height: 100px;
|
108 |
+
background-color: #eaffea;
|
109 |
+
border-top: 1px solid #bbbbbb;
|
110 |
+
padding-top: 10px;
|
111 |
+
text-align: center;
|
112 |
+
word-break: keep-all;
|
113 |
+
white-space: nowrap;
|
114 |
+
}
|
115 |
+
#WizardBanner p {
|
116 |
+
margin: 0;
|
117 |
+
line-height: 20px;
|
118 |
+
text-align: left;
|
119 |
}
|
resources/images/banner-1500x500-transparent.png
ADDED
Binary file
|
resources/images/wand.png
ADDED
Binary file
|
resources/js/icwp-options.js
CHANGED
@@ -1,5 +1,6 @@
|
|
1 |
jQuery( document ).ready(
|
2 |
function () {
|
|
|
3 |
|
4 |
var $oIcwpOptions = jQuery( 'div#icwp-options-form' );
|
5 |
|
1 |
jQuery( document ).ready(
|
2 |
function () {
|
3 |
+
return;
|
4 |
|
5 |
var $oIcwpOptions = jQuery( 'div#icwp-options-form' );
|
6 |
|
src/common/icwp-data.php
CHANGED
@@ -64,6 +64,17 @@ class ICWP_WPSF_DataProcessor extends ICWP_WPSF_Foundation {
|
|
64 |
return $aArray1;
|
65 |
}
|
66 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
/**
|
68 |
* @param string $sKey
|
69 |
* @param null $mDefault
|
@@ -485,10 +496,10 @@ class ICWP_WPSF_DataProcessor extends ICWP_WPSF_Foundation {
|
|
485 |
* @return bool
|
486 |
*/
|
487 |
public function setCookie( $sKey, $mValue, $nExpireLength = 3600, $sPath = null, $sDomain = null, $bSsl = false ) {
|
|
|
488 |
if ( function_exists( 'headers_sent' ) && headers_sent() ) {
|
489 |
return false;
|
490 |
}
|
491 |
-
$_COOKIE[ $sKey ] = $mValue;
|
492 |
return setcookie(
|
493 |
$sKey,
|
494 |
$mValue,
|
64 |
return $aArray1;
|
65 |
}
|
66 |
|
67 |
+
/**
|
68 |
+
* @param string $sKey
|
69 |
+
* @param null $mDefault
|
70 |
+
* @param bool $bTrim -automatically trim whitespace
|
71 |
+
* @return mixed|null
|
72 |
+
*/
|
73 |
+
public function cookie( $sKey, $mDefault = null, $bTrim = true ) {
|
74 |
+
$mVal = $this->FetchCookie( $sKey, $mDefault );
|
75 |
+
return ( $bTrim && is_scalar( $mVal ) ) ? trim( $mVal ) : $mVal;
|
76 |
+
}
|
77 |
+
|
78 |
/**
|
79 |
* @param string $sKey
|
80 |
* @param null $mDefault
|
496 |
* @return bool
|
497 |
*/
|
498 |
public function setCookie( $sKey, $mValue, $nExpireLength = 3600, $sPath = null, $sDomain = null, $bSsl = false ) {
|
499 |
+
$_COOKIE[ $sKey ] = $mValue;
|
500 |
if ( function_exists( 'headers_sent' ) && headers_sent() ) {
|
501 |
return false;
|
502 |
}
|
|
|
503 |
return setcookie(
|
504 |
$sKey,
|
505 |
$mValue,
|
src/common/icwp-edd.php
CHANGED
@@ -44,7 +44,7 @@ class ICWP_WPSF_Edd extends ICWP_WPSF_Foundation {
|
|
44 |
);
|
45 |
|
46 |
$mResponse = $this->loadFS()
|
47 |
-
->requestUrl( $sStoreUrl, $aParams );
|
48 |
|
49 |
$sResult = 'Unknown error communicating with license server';
|
50 |
if ( is_array( $mResponse ) && !empty( $mResponse[ 'body' ] ) ) {
|
@@ -92,7 +92,8 @@ class ICWP_WPSF_Edd extends ICWP_WPSF_Foundation {
|
|
92 |
'edd_action' => $sAction,
|
93 |
'license' => $sKey,
|
94 |
'item_id' => $sItemId,
|
95 |
-
'url' => $this->loadWp()->getWpUrl()
|
|
|
96 |
)
|
97 |
);
|
98 |
|
44 |
);
|
45 |
|
46 |
$mResponse = $this->loadFS()
|
47 |
+
->requestUrl( $sStoreUrl, $aParams, true );
|
48 |
|
49 |
$sResult = 'Unknown error communicating with license server';
|
50 |
if ( is_array( $mResponse ) && !empty( $mResponse[ 'body' ] ) ) {
|
92 |
'edd_action' => $sAction,
|
93 |
'license' => $sKey,
|
94 |
'item_id' => $sItemId,
|
95 |
+
'url' => $this->loadWp()->getWpUrl(),
|
96 |
+
'home_url' => $this->loadWp()->getHomeUrl()
|
97 |
)
|
98 |
);
|
99 |
|
src/common/icwp-foundation.php
CHANGED
@@ -254,7 +254,7 @@ class ICWP_WPSF_Foundation {
|
|
254 |
if ( !empty( $sTemplatePath ) ) {
|
255 |
self::$oRender->setTemplateRoot( $sTemplatePath );
|
256 |
}
|
257 |
-
return self::$oRender;
|
258 |
}
|
259 |
|
260 |
/**
|
254 |
if ( !empty( $sTemplatePath ) ) {
|
255 |
self::$oRender->setTemplateRoot( $sTemplatePath );
|
256 |
}
|
257 |
+
return ( clone self::$oRender );
|
258 |
}
|
259 |
|
260 |
/**
|
src/common/icwp-ip.php
CHANGED
@@ -9,14 +9,17 @@ if ( class_exists( 'ICWP_WPSF_Ip', false ) ) {
|
|
9 |
class ICWP_WPSF_Ip extends ICWP_WPSF_Foundation {
|
10 |
|
11 |
const IpifyEndpoint = 'https://api.ipify.org';
|
|
|
12 |
/**
|
13 |
* @var string
|
14 |
*/
|
15 |
private $sIp;
|
|
|
16 |
/**
|
17 |
* @var string
|
18 |
*/
|
19 |
private $sMyIp;
|
|
|
20 |
/**
|
21 |
* @var ICWP_WPSF_Ip
|
22 |
*/
|
@@ -244,6 +247,35 @@ class ICWP_WPSF_Ip extends ICWP_WPSF_Foundation {
|
|
244 |
return $this->sMyIp;
|
245 |
}
|
246 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
247 |
/**
|
248 |
* @return string|false
|
249 |
*/
|
@@ -261,22 +293,10 @@ class ICWP_WPSF_Ip extends ICWP_WPSF_Foundation {
|
|
261 |
|
262 |
$sMyIp = $bRemoteVerify ? $this->whatIsMyIp() : null;
|
263 |
|
264 |
-
$aAddressSourceOptions = array(
|
265 |
-
'REMOTE_ADDR',
|
266 |
-
'HTTP_CF_CONNECTING_IP',
|
267 |
-
'HTTP_X_FORWARDED_FOR',
|
268 |
-
'HTTP_X_FORWARDED',
|
269 |
-
'HTTP_X_REAL_IP',
|
270 |
-
'HTTP_X_SUCURI_CLIENTIP',
|
271 |
-
'HTTP_INCAP_CLIENT_IP',
|
272 |
-
'HTTP_FORWARDED',
|
273 |
-
'HTTP_CLIENT_IP'
|
274 |
-
);
|
275 |
-
|
276 |
$sIpToReturn = false;
|
277 |
$sSource = false;
|
278 |
-
$oDp = $this->
|
279 |
-
foreach ( $
|
280 |
|
281 |
$sIpToTest = $oDp->FetchServer( $sSource );
|
282 |
if ( empty( $sIpToTest ) ) {
|
@@ -300,6 +320,23 @@ class ICWP_WPSF_Ip extends ICWP_WPSF_Foundation {
|
|
300 |
);
|
301 |
}
|
302 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
303 |
/**
|
304 |
* @return string[]
|
305 |
*/
|
9 |
class ICWP_WPSF_Ip extends ICWP_WPSF_Foundation {
|
10 |
|
11 |
const IpifyEndpoint = 'https://api.ipify.org';
|
12 |
+
|
13 |
/**
|
14 |
* @var string
|
15 |
*/
|
16 |
private $sIp;
|
17 |
+
|
18 |
/**
|
19 |
* @var string
|
20 |
*/
|
21 |
private $sMyIp;
|
22 |
+
|
23 |
/**
|
24 |
* @var ICWP_WPSF_Ip
|
25 |
*/
|
247 |
return $this->sMyIp;
|
248 |
}
|
249 |
|
250 |
+
/**
|
251 |
+
* @param string $sVisitorIp
|
252 |
+
* @return string
|
253 |
+
*/
|
254 |
+
public function determineSourceFromIp( $sVisitorIp ) {
|
255 |
+
$oDp = $this->loadDP();
|
256 |
+
|
257 |
+
$sBestSource = null;
|
258 |
+
foreach ( $this->getIpSourceOptions() as $sSource ) {
|
259 |
+
|
260 |
+
$sIpToTest = $oDp->FetchServer( $sSource );
|
261 |
+
if ( empty( $sIpToTest ) ) {
|
262 |
+
continue;
|
263 |
+
}
|
264 |
+
|
265 |
+
// sometimes a comma-separated list is returned
|
266 |
+
$aIpAddresses = array_map( 'trim', explode( ',', $sIpToTest ) );
|
267 |
+
foreach ( $aIpAddresses as $sIp ) {
|
268 |
+
|
269 |
+
if ( $sVisitorIp == $sIp ) {
|
270 |
+
$sBestSource = $sSource;
|
271 |
+
break( 2 );
|
272 |
+
}
|
273 |
+
}
|
274 |
+
}
|
275 |
+
|
276 |
+
return $sBestSource;
|
277 |
+
}
|
278 |
+
|
279 |
/**
|
280 |
* @return string|false
|
281 |
*/
|
293 |
|
294 |
$sMyIp = $bRemoteVerify ? $this->whatIsMyIp() : null;
|
295 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
296 |
$sIpToReturn = false;
|
297 |
$sSource = false;
|
298 |
+
$oDp = $this->loadDP();
|
299 |
+
foreach ( $this->getIpSourceOptions() as $sSource ) {
|
300 |
|
301 |
$sIpToTest = $oDp->FetchServer( $sSource );
|
302 |
if ( empty( $sIpToTest ) ) {
|
320 |
);
|
321 |
}
|
322 |
|
323 |
+
/**
|
324 |
+
* @return string[]
|
325 |
+
*/
|
326 |
+
protected function getIpSourceOptions() {
|
327 |
+
return array(
|
328 |
+
'REMOTE_ADDR',
|
329 |
+
'HTTP_CF_CONNECTING_IP',
|
330 |
+
'HTTP_X_FORWARDED_FOR',
|
331 |
+
'HTTP_X_FORWARDED',
|
332 |
+
'HTTP_X_REAL_IP',
|
333 |
+
'HTTP_X_SUCURI_CLIENTIP',
|
334 |
+
'HTTP_INCAP_CLIENT_IP',
|
335 |
+
'HTTP_FORWARDED',
|
336 |
+
'HTTP_CLIENT_IP'
|
337 |
+
);
|
338 |
+
}
|
339 |
+
|
340 |
/**
|
341 |
* @return string[]
|
342 |
*/
|
src/common/icwp-wpfunctions.php
CHANGED
@@ -406,10 +406,10 @@ class ICWP_WPSF_WpFunctions extends ICWP_WPSF_Foundation {
|
|
406 |
public function doRedirect( $sUrl, $aQueryParams = array(), $bSafe = true, $bProtectAgainstInfiniteLoops = true ) {
|
407 |
$sUrl = empty( $aQueryParams ) ? $sUrl : add_query_arg( $aQueryParams, $sUrl );
|
408 |
|
409 |
-
$oDp = $this->
|
410 |
// we prevent any repetitive redirect loops
|
411 |
if ( $bProtectAgainstInfiniteLoops ) {
|
412 |
-
if ( $oDp->
|
413 |
return;
|
414 |
}
|
415 |
else {
|
@@ -420,7 +420,7 @@ class ICWP_WPSF_WpFunctions extends ICWP_WPSF_Foundation {
|
|
420 |
// based on: https://make.wordpress.org/plugins/2015/04/20/fixing-add_query_arg-and-remove_query_arg-usage/
|
421 |
// we now escape the URL to be absolutely sure since we can't guarantee the URL coming through there
|
422 |
$sUrl = esc_url_raw( $sUrl );
|
423 |
-
$bSafe ?
|
424 |
exit();
|
425 |
}
|
426 |
|
@@ -735,7 +735,7 @@ class ICWP_WPSF_WpFunctions extends ICWP_WPSF_Foundation {
|
|
735 |
* @return string
|
736 |
*/
|
737 |
public function getTimeStringForDisplay( $nTime = null, $bShowTime = true, $bShowDate = true ) {
|
738 |
-
$nTime = empty( $nTime ) ? $this->
|
739 |
|
740 |
$sFullTimeString = $bShowTime ? $this->getTimeFormat() : '';
|
741 |
if ( empty( $sFullTimeString ) ) {
|
@@ -747,6 +747,15 @@ class ICWP_WPSF_WpFunctions extends ICWP_WPSF_Foundation {
|
|
747 |
return date_i18n( $sFullTimeString, $this->getTimeAsGmtOffset( $nTime ) );
|
748 |
}
|
749 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
750 |
/**
|
751 |
* @param int $nTime
|
752 |
* @return int
|
406 |
public function doRedirect( $sUrl, $aQueryParams = array(), $bSafe = true, $bProtectAgainstInfiniteLoops = true ) {
|
407 |
$sUrl = empty( $aQueryParams ) ? $sUrl : add_query_arg( $aQueryParams, $sUrl );
|
408 |
|
409 |
+
$oDp = $this->loadDP();
|
410 |
// we prevent any repetitive redirect loops
|
411 |
if ( $bProtectAgainstInfiniteLoops ) {
|
412 |
+
if ( $oDp->cookie( 'icwp-isredirect' ) == 'yes' ) {
|
413 |
return;
|
414 |
}
|
415 |
else {
|
420 |
// based on: https://make.wordpress.org/plugins/2015/04/20/fixing-add_query_arg-and-remove_query_arg-usage/
|
421 |
// we now escape the URL to be absolutely sure since we can't guarantee the URL coming through there
|
422 |
$sUrl = esc_url_raw( $sUrl );
|
423 |
+
$bSafe ? wp_redirect( $sUrl ) : wp_redirect( $sUrl );
|
424 |
exit();
|
425 |
}
|
426 |
|
735 |
* @return string
|
736 |
*/
|
737 |
public function getTimeStringForDisplay( $nTime = null, $bShowTime = true, $bShowDate = true ) {
|
738 |
+
$nTime = empty( $nTime ) ? $this->loadDP()->time() : $nTime;
|
739 |
|
740 |
$sFullTimeString = $bShowTime ? $this->getTimeFormat() : '';
|
741 |
if ( empty( $sFullTimeString ) ) {
|
747 |
return date_i18n( $sFullTimeString, $this->getTimeAsGmtOffset( $nTime ) );
|
748 |
}
|
749 |
|
750 |
+
/**
|
751 |
+
* @param int|null $nTime
|
752 |
+
* @return string
|
753 |
+
*/
|
754 |
+
public function getTimeStampForDisplay( $nTime = null ) {
|
755 |
+
$nTime = empty( $nTime ) ? $this->loadDP()->time() : $nTime;
|
756 |
+
return date_i18n( DATE_RFC2822, $this->getTimeAsGmtOffset( $nTime ) );
|
757 |
+
}
|
758 |
+
|
759 |
/**
|
760 |
* @param int $nTime
|
761 |
* @return int
|
src/config/feature-admin_access_restriction.php
CHANGED
@@ -5,7 +5,7 @@
|
|
5 |
"name": "Security Admin",
|
6 |
"show_feature_menu_item": true,
|
7 |
"storage_key": "admin_access_restriction",
|
8 |
-
"tagline": "Protect your
|
9 |
"menu_title": "Security Admin",
|
10 |
"show_central": true,
|
11 |
"access_restricted": true,
|
@@ -207,7 +207,7 @@
|
|
207 |
],
|
208 |
"definitions": {
|
209 |
"help_video_id": "214855538",
|
210 |
-
"
|
211 |
"admin_access_options_to_restrict": {
|
212 |
"wpms_options": [
|
213 |
"admin_email",
|
5 |
"name": "Security Admin",
|
6 |
"show_feature_menu_item": true,
|
7 |
"storage_key": "admin_access_restriction",
|
8 |
+
"tagline": "Protect your Security Plugin, not just your WordPress site",
|
9 |
"menu_title": "Security Admin",
|
10 |
"show_central": true,
|
11 |
"access_restricted": true,
|
207 |
],
|
208 |
"definitions": {
|
209 |
"help_video_id": "214855538",
|
210 |
+
"security_admin_cookie_name": "icwp_wpsf_aakcook",
|
211 |
"admin_access_options_to_restrict": {
|
212 |
"wpms_options": [
|
213 |
"admin_email",
|
src/config/feature-hack_protect.php
CHANGED
@@ -1,233 +1,233 @@
|
|
1 |
{
|
2 |
-
"slug":
|
3 |
-
"properties":
|
4 |
-
"slug":
|
5 |
-
"name":
|
6 |
"show_feature_menu_item": true,
|
7 |
-
"storage_key":
|
8 |
-
"show_central":
|
9 |
-
"access_restricted":
|
10 |
-
"premium":
|
11 |
-
"order":
|
12 |
},
|
13 |
-
"sections":
|
14 |
{
|
15 |
-
"slug":
|
16 |
-
"primary":
|
17 |
-
"title":
|
18 |
"title_short": "Enable / Disable",
|
19 |
-
"summary":
|
20 |
"Purpose - The Hack Protection system is a set of tools to warn you and protect you against hacks on your site.",
|
21 |
"Recommendation - Keep the Hack Protection feature turned on."
|
22 |
]
|
23 |
},
|
24 |
{
|
25 |
-
"slug":
|
26 |
-
"title":
|
27 |
"title_short": "Vulnerability Scanner",
|
28 |
-
"summary":
|
29 |
"Purpose - Regularly scan your WordPress plugins and themes for known security vulnerabilities.",
|
30 |
"Recommendation - Ensure this is turned on and you will always know if any of your assets have known security vulnerabilities."
|
31 |
]
|
32 |
},
|
33 |
{
|
34 |
-
"slug":
|
35 |
-
"title":
|
36 |
"title_short": "Core File Scanner",
|
37 |
-
"summary":
|
38 |
"Purpose - Regularly scan your WordPress core files for changes compared to official WordPress files.",
|
39 |
"Recommendation - Keep the Core File Integrity Scanner feature turned on."
|
40 |
]
|
41 |
},
|
42 |
{
|
43 |
-
"slug":
|
44 |
-
"title":
|
45 |
"title_short": "Unrecognised Files Scanner",
|
46 |
-
"summary":
|
47 |
"Purpose - Scan your WordPress core folders for unrecognised files that don't belong.",
|
48 |
"Recommendation - Keep the Unrecognised Files Scanner feature turned on."
|
49 |
]
|
50 |
},
|
51 |
{
|
52 |
-
"slug":
|
53 |
"hidden": true
|
54 |
}
|
55 |
],
|
56 |
-
"options":
|
57 |
{
|
58 |
-
"key":
|
59 |
-
"section":
|
60 |
-
"default":
|
61 |
-
"type":
|
62 |
-
"link_info":
|
63 |
-
"link_blog":
|
64 |
-
"name":
|
65 |
-
"summary":
|
66 |
"description": "Checking/Un-Checking this option will completely turn on/off the whole Hack Protection feature"
|
67 |
},
|
68 |
{
|
69 |
-
"key":
|
70 |
-
"section":
|
71 |
-
"premium":
|
72 |
-
"default":
|
73 |
-
"type":
|
74 |
"value_options": [
|
75 |
{
|
76 |
"value_key": "disabled",
|
77 |
-
"text":
|
78 |
},
|
79 |
{
|
80 |
"value_key": "enabled_email",
|
81 |
-
"text":
|
82 |
},
|
83 |
{
|
84 |
"value_key": "enabled_no_email",
|
85 |
-
"text":
|
86 |
}
|
87 |
],
|
88 |
-
"link_info":
|
89 |
-
"link_blog":
|
90 |
-
"name":
|
91 |
-
"summary":
|
92 |
-
"description":
|
93 |
},
|
94 |
{
|
95 |
-
"key":
|
96 |
-
"section":
|
97 |
-
"premium":
|
98 |
-
"default":
|
99 |
-
"type":
|
100 |
-
"link_info":
|
101 |
-
"link_blog":
|
102 |
-
"name":
|
103 |
-
"summary":
|
104 |
"description": "When an update becomes available, automatically apply updates to items with known vulnerabilities."
|
105 |
},
|
106 |
{
|
107 |
-
"key":
|
108 |
-
"section":
|
109 |
-
"default":
|
110 |
-
"type":
|
111 |
"value_options": [
|
112 |
{
|
113 |
"value_key": "disabled",
|
114 |
-
"text":
|
115 |
},
|
116 |
{
|
117 |
"value_key": "enabled_admin",
|
118 |
-
"text":
|
119 |
},
|
120 |
{
|
121 |
"value_key": "enabled_securityadmin",
|
122 |
-
"text":
|
123 |
}
|
124 |
],
|
125 |
-
"link_info":
|
126 |
-
"link_blog":
|
127 |
-
"name":
|
128 |
-
"summary":
|
129 |
-
"description":
|
130 |
},
|
131 |
{
|
132 |
-
"key":
|
133 |
-
"section":
|
134 |
-
"default":
|
135 |
-
"type":
|
136 |
-
"link_info":
|
137 |
-
"link_blog":
|
138 |
-
"name":
|
139 |
-
"summary":
|
140 |
"description": "Compares all WordPress core files on your site against the official WordPress files. WordPress Core files should never be altered for any reason."
|
141 |
},
|
142 |
{
|
143 |
-
"key":
|
144 |
-
"section":
|
145 |
-
"default":
|
146 |
-
"type":
|
147 |
-
"link_info":
|
148 |
-
"link_blog":
|
149 |
-
"name":
|
150 |
-
"summary":
|
151 |
"description": "Attempts to automatically repair WordPress Core files with the official WordPress file data, for files that have been altered or are missing."
|
152 |
},
|
153 |
{
|
154 |
-
"key":
|
155 |
-
"section":
|
156 |
-
"default":
|
157 |
-
"type":
|
158 |
"value_options": [
|
159 |
{
|
160 |
"value_key": "disabled",
|
161 |
-
"text":
|
162 |
},
|
163 |
{
|
164 |
"value_key": "enabled_report_only",
|
165 |
-
"text":
|
166 |
},
|
167 |
{
|
168 |
"value_key": "enabled_delete_only",
|
169 |
-
"text":
|
170 |
},
|
171 |
{
|
172 |
"value_key": "enabled_delete_report",
|
173 |
-
"text":
|
174 |
}
|
175 |
],
|
176 |
-
"link_info":
|
177 |
-
"link_blog":
|
178 |
-
"name":
|
179 |
-
"summary":
|
180 |
-
"description":
|
181 |
},
|
182 |
{
|
183 |
-
"key":
|
184 |
-
"section":
|
185 |
-
"default":
|
186 |
-
"type":
|
187 |
-
"link_info":
|
188 |
-
"link_blog":
|
189 |
-
"name":
|
190 |
-
"summary":
|
191 |
"description": "The Uploads folder is primarily for media, but could be used to store nefarious files."
|
192 |
},
|
193 |
{
|
194 |
-
"key":
|
195 |
-
"section":
|
196 |
-
"default":
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
],
|
206 |
-
"type":
|
207 |
-
"link_info":
|
208 |
-
"link_blog":
|
209 |
-
"name":
|
210 |
-
"summary":
|
211 |
"description": "Take a new line for each file you wish to exclude from the scan. No commas are necessary."
|
212 |
},
|
213 |
{
|
214 |
-
"key":
|
215 |
"transferable": false,
|
216 |
-
"section":
|
217 |
-
"default":
|
218 |
}
|
219 |
],
|
220 |
"definitions": {
|
221 |
-
"plugin_vulnerabilities_data_source":
|
222 |
-
"notifications_cron_name":
|
223 |
-
"wpvulnscan_cron_name":
|
224 |
-
"corechecksum_cron_name":
|
225 |
-
"unrecognisedscan_cron_name":
|
226 |
-
"url_checksum_api":
|
227 |
-
"url_wordress_core_svn":
|
228 |
-
"url_wordress_core_svn_il8n":
|
229 |
-
"wpvulndb_api_url_root":
|
230 |
-
"corechecksum_exclusions":
|
231 |
"readme.html",
|
232 |
"license.txt",
|
233 |
"licens-sv_SE.txt",
|
@@ -238,10 +238,57 @@
|
|
238 |
"wp-admin/install.php",
|
239 |
"xmlrpc.php"
|
240 |
],
|
241 |
-
"corechecksum_autofix":
|
242 |
"wp-content/index.php",
|
243 |
"wp-content/plugins/index.php",
|
244 |
"wp-content/themes/index.php"
|
245 |
-
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
246 |
}
|
247 |
}
|
1 |
{
|
2 |
+
"slug": "hack_protect",
|
3 |
+
"properties": {
|
4 |
+
"slug": "hack_protect",
|
5 |
+
"name": "Hack Protection",
|
6 |
"show_feature_menu_item": true,
|
7 |
+
"storage_key": "hack_protect",
|
8 |
+
"show_central": true,
|
9 |
+
"access_restricted": true,
|
10 |
+
"premium": false,
|
11 |
+
"order": 70
|
12 |
},
|
13 |
+
"sections": [
|
14 |
{
|
15 |
+
"slug": "section_enable_plugin_feature_hack_protection_tools",
|
16 |
+
"primary": true,
|
17 |
+
"title": "Enable Plugin Feature: Hack Protection",
|
18 |
"title_short": "Enable / Disable",
|
19 |
+
"summary": [
|
20 |
"Purpose - The Hack Protection system is a set of tools to warn you and protect you against hacks on your site.",
|
21 |
"Recommendation - Keep the Hack Protection feature turned on."
|
22 |
]
|
23 |
},
|
24 |
{
|
25 |
+
"slug": "section_wpvuln_scan",
|
26 |
+
"title": "Vulnerability Scanner",
|
27 |
"title_short": "Vulnerability Scanner",
|
28 |
+
"summary": [
|
29 |
"Purpose - Regularly scan your WordPress plugins and themes for known security vulnerabilities.",
|
30 |
"Recommendation - Ensure this is turned on and you will always know if any of your assets have known security vulnerabilities."
|
31 |
]
|
32 |
},
|
33 |
{
|
34 |
+
"slug": "section_core_file_integrity_scan",
|
35 |
+
"title": "Core File Integrity Scanner",
|
36 |
"title_short": "Core File Scanner",
|
37 |
+
"summary": [
|
38 |
"Purpose - Regularly scan your WordPress core files for changes compared to official WordPress files.",
|
39 |
"Recommendation - Keep the Core File Integrity Scanner feature turned on."
|
40 |
]
|
41 |
},
|
42 |
{
|
43 |
+
"slug": "section_unrecognised_file_scan",
|
44 |
+
"title": "Unrecognised Files Scanner",
|
45 |
"title_short": "Unrecognised Files Scanner",
|
46 |
+
"summary": [
|
47 |
"Purpose - Scan your WordPress core folders for unrecognised files that don't belong.",
|
48 |
"Recommendation - Keep the Unrecognised Files Scanner feature turned on."
|
49 |
]
|
50 |
},
|
51 |
{
|
52 |
+
"slug": "section_non_ui",
|
53 |
"hidden": true
|
54 |
}
|
55 |
],
|
56 |
+
"options": [
|
57 |
{
|
58 |
+
"key": "enable_hack_protect",
|
59 |
+
"section": "section_enable_plugin_feature_hack_protection_tools",
|
60 |
+
"default": "Y",
|
61 |
+
"type": "checkbox",
|
62 |
+
"link_info": "http://icwp.io/wpsf38",
|
63 |
+
"link_blog": "http://icwp.io/9x",
|
64 |
+
"name": "Enable Hack Protection",
|
65 |
+
"summary": "Enable (or Disable) The Hack Protection Feature",
|
66 |
"description": "Checking/Un-Checking this option will completely turn on/off the whole Hack Protection feature"
|
67 |
},
|
68 |
{
|
69 |
+
"key": "enable_wpvuln_scan",
|
70 |
+
"section": "section_wpvuln_scan",
|
71 |
+
"premium": true,
|
72 |
+
"default": "enabled_email",
|
73 |
+
"type": "select",
|
74 |
"value_options": [
|
75 |
{
|
76 |
"value_key": "disabled",
|
77 |
+
"text": "Scan Disabled"
|
78 |
},
|
79 |
{
|
80 |
"value_key": "enabled_email",
|
81 |
+
"text": "Enabled - Send Email Notification"
|
82 |
},
|
83 |
{
|
84 |
"value_key": "enabled_no_email",
|
85 |
+
"text": "Enabled - No Email Notification"
|
86 |
}
|
87 |
],
|
88 |
+
"link_info": "http://icwp.io/ah",
|
89 |
+
"link_blog": "",
|
90 |
+
"name": "Vulnerability Scanner",
|
91 |
+
"summary": "Enable The Vulnerability Scanner",
|
92 |
+
"description": "Scan all your WordPress assets for known security vulnerabilities."
|
93 |
},
|
94 |
{
|
95 |
+
"key": "wpvuln_scan_autoupdate",
|
96 |
+
"section": "section_wpvuln_scan",
|
97 |
+
"premium": true,
|
98 |
+
"default": "N",
|
99 |
+
"type": "checkbox",
|
100 |
+
"link_info": "",
|
101 |
+
"link_blog": "",
|
102 |
+
"name": "Automatic Updates",
|
103 |
+
"summary": "Apply Updates Automatically To Vulnerable Plugins",
|
104 |
"description": "When an update becomes available, automatically apply updates to items with known vulnerabilities."
|
105 |
},
|
106 |
{
|
107 |
+
"key": "wpvuln_scan_display",
|
108 |
+
"section": "section_wpvuln_scan",
|
109 |
+
"default": "enabled_admin",
|
110 |
+
"type": "select",
|
111 |
"value_options": [
|
112 |
{
|
113 |
"value_key": "disabled",
|
114 |
+
"text": "Display Disabled"
|
115 |
},
|
116 |
{
|
117 |
"value_key": "enabled_admin",
|
118 |
+
"text": "Display Enabled"
|
119 |
},
|
120 |
{
|
121 |
"value_key": "enabled_securityadmin",
|
122 |
+
"text": "Display Only For Security Admins"
|
123 |
}
|
124 |
],
|
125 |
+
"link_info": "",
|
126 |
+
"link_blog": "",
|
127 |
+
"name": "Highlight Plugins",
|
128 |
+
"summary": "Highlight Vulnerable Plugins",
|
129 |
+
"description": "Vulnerable plugins will be highlighted on the main plugins page."
|
130 |
},
|
131 |
{
|
132 |
+
"key": "enable_core_file_integrity_scan",
|
133 |
+
"section": "section_core_file_integrity_scan",
|
134 |
+
"default": "Y",
|
135 |
+
"type": "checkbox",
|
136 |
+
"link_info": "http://icwp.io/wpsf36",
|
137 |
+
"link_blog": "http://icwp.io/wpsf37",
|
138 |
+
"name": "Core File Scanner",
|
139 |
+
"summary": "Daily Cron - Scans WordPress Core Files For Alterations",
|
140 |
"description": "Compares all WordPress core files on your site against the official WordPress files. WordPress Core files should never be altered for any reason."
|
141 |
},
|
142 |
{
|
143 |
+
"key": "attempt_auto_file_repair",
|
144 |
+
"section": "section_core_file_integrity_scan",
|
145 |
+
"default": "N",
|
146 |
+
"type": "checkbox",
|
147 |
+
"link_info": "http://icwp.io/wpsf36",
|
148 |
+
"link_blog": "http://icwp.io/wpsf37",
|
149 |
+
"name": "Auto Repair",
|
150 |
+
"summary": "Automatically Repair WordPress Core Files That Have Been Altered",
|
151 |
"description": "Attempts to automatically repair WordPress Core files with the official WordPress file data, for files that have been altered or are missing."
|
152 |
},
|
153 |
{
|
154 |
+
"key": "enable_unrecognised_file_cleaner_scan",
|
155 |
+
"section": "section_unrecognised_file_scan",
|
156 |
+
"default": "enabled_report_only",
|
157 |
+
"type": "select",
|
158 |
"value_options": [
|
159 |
{
|
160 |
"value_key": "disabled",
|
161 |
+
"text": "Scan Disabled"
|
162 |
},
|
163 |
{
|
164 |
"value_key": "enabled_report_only",
|
165 |
+
"text": "Email Report Only"
|
166 |
},
|
167 |
{
|
168 |
"value_key": "enabled_delete_only",
|
169 |
+
"text": "Automatically Delete Files"
|
170 |
},
|
171 |
{
|
172 |
"value_key": "enabled_delete_report",
|
173 |
+
"text": "Auto Delete Files and Email Report"
|
174 |
}
|
175 |
],
|
176 |
+
"link_info": "http://icwp.io/9y",
|
177 |
+
"link_blog": "http://icwp.io/95",
|
178 |
+
"name": "Unrecognised Files Scanner",
|
179 |
+
"summary": "Scans Core Directories For Unrecognised Files",
|
180 |
+
"description": "Scans for, and automatically deletes, any files in your core WordPress folders that are not part of your WordPress installation."
|
181 |
},
|
182 |
{
|
183 |
+
"key": "ufc_scan_uploads",
|
184 |
+
"section": "section_unrecognised_file_scan",
|
185 |
+
"default": "N",
|
186 |
+
"type": "checkbox",
|
187 |
+
"link_info": "http://icwp.io/95",
|
188 |
+
"link_blog": "",
|
189 |
+
"name": "Scan Uploads",
|
190 |
+
"summary": "Scan Uploads Folder For PHP and Javascript",
|
191 |
"description": "The Uploads folder is primarily for media, but could be used to store nefarious files."
|
192 |
},
|
193 |
{
|
194 |
+
"key": "ufc_exclusions",
|
195 |
+
"section": "section_unrecognised_file_scan",
|
196 |
+
"default": [
|
197 |
+
"error_log",
|
198 |
+
".htaccess",
|
199 |
+
".htpasswd",
|
200 |
+
".user.ini",
|
201 |
+
"php.ini",
|
202 |
+
"web.config",
|
203 |
+
"php_mail.log",
|
204 |
+
"mail.log"
|
205 |
],
|
206 |
+
"type": "array",
|
207 |
+
"link_info": "http://icwp.io/9z",
|
208 |
+
"link_blog": "http://icwp.io/95",
|
209 |
+
"name": "File Exclusions",
|
210 |
+
"summary": "Provide A List Of Files To Be Excluded From The Scan",
|
211 |
"description": "Take a new line for each file you wish to exclude from the scan. No commas are necessary."
|
212 |
},
|
213 |
{
|
214 |
+
"key": "wpvuln_notified_ids",
|
215 |
"transferable": false,
|
216 |
+
"section": "section_non_ui",
|
217 |
+
"default": []
|
218 |
}
|
219 |
],
|
220 |
"definitions": {
|
221 |
+
"plugin_vulnerabilities_data_source": "https://raw.githubusercontent.com/FernleafSystems/wp-plugin-vulnerabilities/master/vulnerabilities.yaml",
|
222 |
+
"notifications_cron_name": "plugin-vulnerabilities-notification",
|
223 |
+
"wpvulnscan_cron_name": "wpvulnscan-notification",
|
224 |
+
"corechecksum_cron_name": "core-checksum-notification",
|
225 |
+
"unrecognisedscan_cron_name": "unrecognised-scan-notification",
|
226 |
+
"url_checksum_api": "https://api.wordpress.org/core/checksums/1.0/",
|
227 |
+
"url_wordress_core_svn": "https://core.svn.wordpress.org/",
|
228 |
+
"url_wordress_core_svn_il8n": "https://svn.automattic.com/wordpress-i18n/",
|
229 |
+
"wpvulndb_api_url_root": "https://wpvulndb.com/api/v2/",
|
230 |
+
"corechecksum_exclusions": [
|
231 |
"readme.html",
|
232 |
"license.txt",
|
233 |
"licens-sv_SE.txt",
|
238 |
"wp-admin/install.php",
|
239 |
"xmlrpc.php"
|
240 |
],
|
241 |
+
"corechecksum_autofix": [
|
242 |
"wp-content/index.php",
|
243 |
"wp-content/plugins/index.php",
|
244 |
"wp-content/themes/index.php"
|
245 |
+
],
|
246 |
+
"wizards": {
|
247 |
+
"ufc": {
|
248 |
+
"title": "Manually Run Unrecognised File Scanner",
|
249 |
+
"desc": "Walks you through the scanning for unrecognised files present in your WordPress core installation.",
|
250 |
+
"min_user_permissions": "manage_options",
|
251 |
+
"steps": {
|
252 |
+
"start": {
|
253 |
+
"security_admin": false,
|
254 |
+
"title": "Start: Unrecognised File Scanner"
|
255 |
+
},
|
256 |
+
"exclusions": {
|
257 |
+
"title": "Exclude Files"
|
258 |
+
},
|
259 |
+
"scanresult": {
|
260 |
+
"title": "Scan Results"
|
261 |
+
},
|
262 |
+
"config": {
|
263 |
+
"title": "Setup Scan Automation"
|
264 |
+
},
|
265 |
+
"finished": {
|
266 |
+
"security_admin": false,
|
267 |
+
"title": "Finished: Unrecognised File Scanner"
|
268 |
+
}
|
269 |
+
}
|
270 |
+
},
|
271 |
+
"wcf": {
|
272 |
+
"title": "Manually Run WordPress Core File Scanner",
|
273 |
+
"desc": "Walks you through the scanning for unintended changes to your official WordPress core files.",
|
274 |
+
"min_user_permissions": "manage_options",
|
275 |
+
"steps": {
|
276 |
+
"start": {
|
277 |
+
"security_admin": false,
|
278 |
+
"title": "Start: WordPress Core File Scanner"
|
279 |
+
},
|
280 |
+
"scanresult": {
|
281 |
+
"title": "Scan Results"
|
282 |
+
},
|
283 |
+
"config": {
|
284 |
+
"title": "Setup Scan Automation"
|
285 |
+
},
|
286 |
+
"finished": {
|
287 |
+
"security_admin": false,
|
288 |
+
"title": "Finished: WordPress Core File Scanner"
|
289 |
+
}
|
290 |
+
}
|
291 |
+
}
|
292 |
+
}
|
293 |
}
|
294 |
}
|
src/config/feature-login_protect.php
CHANGED
@@ -1,181 +1,181 @@
|
|
1 |
{
|
2 |
-
"slug":
|
3 |
-
"properties":
|
4 |
-
"slug":
|
5 |
-
"name":
|
6 |
"show_feature_menu_item": true,
|
7 |
-
"storage_key":
|
8 |
-
"tagline":
|
9 |
-
"show_central":
|
10 |
-
"access_restricted":
|
11 |
-
"premium":
|
12 |
-
"order":
|
13 |
},
|
14 |
"admin_notices": {
|
15 |
"email-verification-sent": {
|
16 |
-
"once":
|
17 |
"valid_admin": true,
|
18 |
-
"type":
|
19 |
}
|
20 |
},
|
21 |
-
"sections":
|
22 |
{
|
23 |
-
"slug":
|
24 |
-
"primary":
|
25 |
-
"title":
|
26 |
"title_short": "Enable / Disable",
|
27 |
-
"summary":
|
28 |
"Purpose - Login Protection blocks all automated and brute force attempts to log in to your site.",
|
29 |
"Recommendation - Keep the Login Protection feature turned on."
|
30 |
]
|
31 |
},
|
32 |
{
|
33 |
-
"slug":
|
34 |
-
"title":
|
35 |
"title_short": "Brute Force",
|
36 |
-
"summary":
|
37 |
"Purpose - Blocks brute force hacking attacks against your login and registration pages.",
|
38 |
"Recommendation - Use of this feature is highly recommend."
|
39 |
]
|
40 |
},
|
41 |
{
|
42 |
-
"slug":
|
43 |
-
"title":
|
44 |
"title_short": "reCAPTCHA",
|
45 |
-
"summary":
|
46 |
"Purpose - Adds Google reCAPTCHA to the Login Forms.",
|
47 |
"Recommendation - Keep this turned on.",
|
48 |
"Note - You will need to register for Google reCAPTCHA keys and store them in the Shield 'Dashboard' settings."
|
49 |
]
|
50 |
},
|
51 |
{
|
52 |
-
"slug":
|
53 |
-
"title":
|
54 |
"title_short": "2-Factor Auth",
|
55 |
-
"summary":
|
56 |
"Purpose - Verifies the identity of users who log in to your site - i.e. they are who they say they are.",
|
57 |
"Recommendation - Use of this feature is highly recommend. However, if your host blocks email sending you may lock yourself out.",
|
58 |
"Note: You may combine multiple authentication factors for increased security."
|
59 |
]
|
60 |
},
|
61 |
{
|
62 |
-
"slug":
|
63 |
-
"title":
|
64 |
"title_short": "Rename wp-login.php",
|
65 |
-
"summary":
|
66 |
"Purpose - To hide your wp-login.php page from brute force attacks and hacking attempts - if your login page cannot be found, no-one can login.",
|
67 |
"Recommendation - This is not required for complete security and if your site has irregular or inconsistent configuration it may not work for you."
|
68 |
]
|
69 |
},
|
70 |
{
|
71 |
-
"slug":
|
72 |
-
"title":
|
73 |
"title_short": "Yubikey",
|
74 |
-
"summary":
|
75 |
"Purpose - Verifies the identity of users who log in to your site - i.e. they are who they say they are.",
|
76 |
"Recommendation - Use of this feature is highly recommend. Note: you must own the appropriate Yubikey hardware device."
|
77 |
]
|
78 |
},
|
79 |
{
|
80 |
-
"slug":
|
81 |
-
"title":
|
82 |
"title_short": "User Messages",
|
83 |
-
"summary":
|
84 |
"Purpose - Customize the messages shown to visitors.",
|
85 |
"Recommendation - Be sure to change the messages to suit your audience.",
|
86 |
"Hint - To reset any message to its default, enter the text exactly: default"
|
87 |
]
|
88 |
},
|
89 |
{
|
90 |
-
"slug":
|
91 |
"hidden": true
|
92 |
}
|
93 |
],
|
94 |
-
"options":
|
95 |
{
|
96 |
-
"key":
|
97 |
-
"section":
|
98 |
-
"default":
|
99 |
-
"type":
|
100 |
-
"link_info":
|
101 |
-
"link_blog":
|
102 |
-
"name":
|
103 |
-
"summary":
|
104 |
"description": "Checking/Un-Checking this option will completely turn on/off the whole Login Protection feature"
|
105 |
},
|
106 |
{
|
107 |
-
"key":
|
108 |
-
"section":
|
109 |
-
"premium":
|
110 |
-
"default":
|
111 |
-
"type":
|
112 |
-
"link_info":
|
113 |
-
"link_blog":
|
114 |
-
"name":
|
115 |
-
"summary":
|
116 |
"description": "Add Support For 3rd-Party Login, Register, and Password Reset Forms e.g. WooCommerce, Easy Digital Downloads."
|
117 |
},
|
118 |
{
|
119 |
-
"key":
|
120 |
-
"section":
|
121 |
-
"default":
|
122 |
-
"type":
|
123 |
-
"link_info":
|
124 |
-
"link_blog":
|
125 |
-
"name":
|
126 |
-
"summary":
|
127 |
"description": "Enable this if you need XML-RPC functionality e.g. if you use the WordPress iPhone/Android App."
|
128 |
},
|
129 |
{
|
130 |
-
"key":
|
131 |
-
"section":
|
132 |
-
"sensitive":
|
133 |
-
"default":
|
134 |
-
"type":
|
135 |
-
"link_info":
|
136 |
-
"link_blog":
|
137 |
-
"name":
|
138 |
-
"summary":
|
139 |
"description": "Creating a path here will disable your 'wp-login.php'. Only letters and numbers are permitted: abc123"
|
140 |
},
|
141 |
{
|
142 |
-
"key":
|
143 |
-
"section":
|
144 |
-
"default":
|
145 |
-
"type":
|
146 |
-
"link_info":
|
147 |
-
"link_blog":
|
148 |
-
"name":
|
149 |
-
"summary":
|
150 |
"description": "When enabled, all multi-factor authentication methods will be applied to a user login. Disable to only require one to pass."
|
151 |
},
|
152 |
{
|
153 |
-
"key":
|
154 |
-
"section":
|
155 |
-
"default":
|
156 |
-
"type":
|
157 |
-
"link_info":
|
158 |
-
"link_blog":
|
159 |
-
"name":
|
160 |
-
"summary":
|
161 |
"description": "When enabled, users will have the option to add Google Authenticator to their WordPress user profile."
|
162 |
},
|
163 |
{
|
164 |
-
"key":
|
165 |
-
"section":
|
166 |
-
"default":
|
167 |
-
"type":
|
168 |
-
"link_info":
|
169 |
-
"link_blog":
|
170 |
-
"name":
|
171 |
-
"summary":
|
172 |
"description": "All users will be required to verify their login by email-based two-factor authentication."
|
173 |
},
|
174 |
{
|
175 |
-
"key":
|
176 |
-
"section":
|
177 |
-
"type":
|
178 |
-
"default":
|
179 |
1,
|
180 |
2,
|
181 |
3,
|
@@ -184,197 +184,197 @@
|
|
184 |
"value_options": [
|
185 |
{
|
186 |
"value_key": 0,
|
187 |
-
"text":
|
188 |
},
|
189 |
{
|
190 |
"value_key": 1,
|
191 |
-
"text":
|
192 |
},
|
193 |
{
|
194 |
"value_key": 2,
|
195 |
-
"text":
|
196 |
},
|
197 |
{
|
198 |
"value_key": 3,
|
199 |
-
"text":
|
200 |
},
|
201 |
{
|
202 |
"value_key": 8,
|
203 |
-
"text":
|
204 |
}
|
205 |
],
|
206 |
-
"link_info":
|
207 |
-
"link_blog":
|
208 |
-
"name":
|
209 |
-
"summary":
|
210 |
-
"description":
|
211 |
},
|
212 |
{
|
213 |
-
"key":
|
214 |
-
"section":
|
215 |
-
"default":
|
216 |
-
"type":
|
217 |
-
"link_info":
|
218 |
-
"link_blog":
|
219 |
-
"name":
|
220 |
-
"summary":
|
221 |
"description": "Use Google reCAPTCHA on the login screen."
|
222 |
},
|
223 |
{
|
224 |
-
"key":
|
225 |
-
"section":
|
226 |
-
"premium":
|
227 |
-
"default":
|
228 |
-
"type":
|
229 |
"value_options": [
|
230 |
{
|
231 |
"value_key": "default",
|
232 |
-
"text":
|
233 |
},
|
234 |
{
|
235 |
"value_key": "light",
|
236 |
-
"text":
|
237 |
},
|
238 |
{
|
239 |
"value_key": "dark",
|
240 |
-
"text":
|
241 |
},
|
242 |
{
|
243 |
"value_key": "invisible",
|
244 |
-
"text":
|
245 |
}
|
246 |
],
|
247 |
-
"link_info":
|
248 |
-
"link_blog":
|
249 |
-
"name":
|
250 |
-
"summary":
|
251 |
-
"description":
|
252 |
},
|
253 |
{
|
254 |
-
"key":
|
255 |
-
"section":
|
256 |
-
"default":
|
257 |
-
"type":
|
258 |
-
"link_info":
|
259 |
-
"link_blog":
|
260 |
-
"name":
|
261 |
-
"summary":
|
262 |
"description": "Adds a dynamically (Javascript) generated checkbox to the login form that prevents bots using automated login techniques. Recommended: ON."
|
263 |
},
|
264 |
{
|
265 |
-
"key":
|
266 |
-
"section":
|
267 |
-
"default":
|
268 |
-
"type":
|
269 |
-
"link_info":
|
270 |
-
"link_blog":
|
271 |
-
"name":
|
272 |
-
"summary":
|
273 |
"description": "WordPress will process only ONE login attempt for every number of seconds specified. Zero (0) turns this off."
|
274 |
},
|
275 |
{
|
276 |
-
"key":
|
277 |
-
"section":
|
278 |
-
"default":
|
279 |
-
"type":
|
280 |
-
"link_info":
|
281 |
-
"link_blog":
|
282 |
-
"name":
|
283 |
-
"summary":
|
284 |
"description": "When enabled, settings in this section will also apply to new user registration and users trying to reset passwords."
|
285 |
},
|
286 |
{
|
287 |
-
"key":
|
288 |
-
"section":
|
289 |
-
"default":
|
290 |
-
"type":
|
291 |
-
"link_info":
|
292 |
-
"link_blog":
|
293 |
-
"name":
|
294 |
-
"summary":
|
295 |
"description": "Combined with your Yubikey API Key (below) this will form the basis of your Yubikey Authentication."
|
296 |
},
|
297 |
{
|
298 |
-
"key":
|
299 |
-
"section":
|
300 |
-
"sensitive":
|
301 |
-
"default":
|
302 |
-
"type":
|
303 |
-
"link_info":
|
304 |
-
"link_blog":
|
305 |
-
"name":
|
306 |
-
"summary":
|
307 |
"description": "Combined with your Yubikey API Key this will form the basis of your Yubikey Authentication."
|
308 |
},
|
309 |
{
|
310 |
-
"key":
|
311 |
-
"section":
|
312 |
-
"sensitive":
|
313 |
-
"default":
|
314 |
-
"type":
|
315 |
-
"link_info":
|
316 |
-
"link_blog":
|
317 |
-
"name":
|
318 |
-
"summary":
|
319 |
"description": "Combined with your Yubikey App ID this will form the basis of your Yubikey Authentication."
|
320 |
},
|
321 |
{
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
{
|
346 |
-
"key":
|
347 |
"transferable": false,
|
348 |
-
"section":
|
349 |
-
"default":
|
350 |
},
|
351 |
{
|
352 |
-
"key":
|
353 |
"transferable": false,
|
354 |
-
"sensitive":
|
355 |
-
"section":
|
356 |
},
|
357 |
{
|
358 |
-
"key":
|
359 |
"transferable": false,
|
360 |
-
"sensitive":
|
361 |
-
"section":
|
362 |
},
|
363 |
{
|
364 |
-
"key":
|
365 |
"transferable": false,
|
366 |
-
"section":
|
367 |
},
|
368 |
{
|
369 |
-
"key":
|
370 |
"transferable": false,
|
371 |
-
"value":
|
372 |
-
"section":
|
373 |
}
|
374 |
],
|
375 |
-
"definitions":
|
376 |
-
"login_intent_timeout":
|
377 |
-
"two_factor_auth_table_name":
|
378 |
"two_factor_auth_table_columns": [
|
379 |
"id",
|
380 |
"session_id",
|
@@ -384,6 +384,32 @@
|
|
384 |
"expired_at",
|
385 |
"created_at",
|
386 |
"deleted_at"
|
387 |
-
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
388 |
}
|
389 |
}
|
1 |
{
|
2 |
+
"slug": "login_protect",
|
3 |
+
"properties": {
|
4 |
+
"slug": "login_protect",
|
5 |
+
"name": "Login Protection",
|
6 |
"show_feature_menu_item": true,
|
7 |
+
"storage_key": "loginprotect",
|
8 |
+
"tagline": "Block brute force attacks and secure user identities with Two-Factor Authentication",
|
9 |
+
"show_central": true,
|
10 |
+
"access_restricted": true,
|
11 |
+
"premium": false,
|
12 |
+
"order": 40
|
13 |
},
|
14 |
"admin_notices": {
|
15 |
"email-verification-sent": {
|
16 |
+
"once": false,
|
17 |
"valid_admin": true,
|
18 |
+
"type": "warning"
|
19 |
}
|
20 |
},
|
21 |
+
"sections": [
|
22 |
{
|
23 |
+
"slug": "section_enable_plugin_feature_login_protection",
|
24 |
+
"primary": true,
|
25 |
+
"title": "Enable Plugin Feature: Login Protection",
|
26 |
"title_short": "Enable / Disable",
|
27 |
+
"summary": [
|
28 |
"Purpose - Login Protection blocks all automated and brute force attempts to log in to your site.",
|
29 |
"Recommendation - Keep the Login Protection feature turned on."
|
30 |
]
|
31 |
},
|
32 |
{
|
33 |
+
"slug": "section_brute_force_login_protection",
|
34 |
+
"title": "Brute Force Login Protection",
|
35 |
"title_short": "Brute Force",
|
36 |
+
"summary": [
|
37 |
"Purpose - Blocks brute force hacking attacks against your login and registration pages.",
|
38 |
"Recommendation - Use of this feature is highly recommend."
|
39 |
]
|
40 |
},
|
41 |
{
|
42 |
+
"slug": "section_recaptcha",
|
43 |
+
"title": "Google reCAPTCHA",
|
44 |
"title_short": "reCAPTCHA",
|
45 |
+
"summary": [
|
46 |
"Purpose - Adds Google reCAPTCHA to the Login Forms.",
|
47 |
"Recommendation - Keep this turned on.",
|
48 |
"Note - You will need to register for Google reCAPTCHA keys and store them in the Shield 'Dashboard' settings."
|
49 |
]
|
50 |
},
|
51 |
{
|
52 |
+
"slug": "section_multifactor_authentication",
|
53 |
+
"title": "Multi-Factor Authentication",
|
54 |
"title_short": "2-Factor Auth",
|
55 |
+
"summary": [
|
56 |
"Purpose - Verifies the identity of users who log in to your site - i.e. they are who they say they are.",
|
57 |
"Recommendation - Use of this feature is highly recommend. However, if your host blocks email sending you may lock yourself out.",
|
58 |
"Note: You may combine multiple authentication factors for increased security."
|
59 |
]
|
60 |
},
|
61 |
{
|
62 |
+
"slug": "section_rename_wplogin",
|
63 |
+
"title": "Rename WP Login Page",
|
64 |
"title_short": "Rename wp-login.php",
|
65 |
+
"summary": [
|
66 |
"Purpose - To hide your wp-login.php page from brute force attacks and hacking attempts - if your login page cannot be found, no-one can login.",
|
67 |
"Recommendation - This is not required for complete security and if your site has irregular or inconsistent configuration it may not work for you."
|
68 |
]
|
69 |
},
|
70 |
{
|
71 |
+
"slug": "section_yubikey_authentication",
|
72 |
+
"title": "Yubikey Authentication",
|
73 |
"title_short": "Yubikey",
|
74 |
+
"summary": [
|
75 |
"Purpose - Verifies the identity of users who log in to your site - i.e. they are who they say they are.",
|
76 |
"Recommendation - Use of this feature is highly recommend. Note: you must own the appropriate Yubikey hardware device."
|
77 |
]
|
78 |
},
|
79 |
{
|
80 |
+
"slug": "section_user_messages",
|
81 |
+
"title": "User Messages",
|
82 |
"title_short": "User Messages",
|
83 |
+
"summary": [
|
84 |
"Purpose - Customize the messages shown to visitors.",
|
85 |
"Recommendation - Be sure to change the messages to suit your audience.",
|
86 |
"Hint - To reset any message to its default, enter the text exactly: default"
|
87 |
]
|
88 |
},
|
89 |
{
|
90 |
+
"slug": "section_non_ui",
|
91 |
"hidden": true
|
92 |
}
|
93 |
],
|
94 |
+
"options": [
|
95 |
{
|
96 |
+
"key": "enable_login_protect",
|
97 |
+
"section": "section_enable_plugin_feature_login_protection",
|
98 |
+
"default": "N",
|
99 |
+
"type": "checkbox",
|
100 |
+
"link_info": "http://icwp.io/51",
|
101 |
+
"link_blog": "http://icwp.io/wpsf03",
|
102 |
+
"name": "Enable Login Protection",
|
103 |
+
"summary": "Enable (or Disable) The Login Protection Feature",
|
104 |
"description": "Checking/Un-Checking this option will completely turn on/off the whole Login Protection feature"
|
105 |
},
|
106 |
{
|
107 |
+
"key": "login_protect_3pty",
|
108 |
+
"section": "section_enable_plugin_feature_login_protection",
|
109 |
+
"premium": true,
|
110 |
+
"default": "N",
|
111 |
+
"type": "checkbox",
|
112 |
+
"link_info": "",
|
113 |
+
"link_blog": "",
|
114 |
+
"name": "3rd-Party Support",
|
115 |
+
"summary": "Support For 3rd-Party Plugins, e.g. WooCommerce",
|
116 |
"description": "Add Support For 3rd-Party Login, Register, and Password Reset Forms e.g. WooCommerce, Easy Digital Downloads."
|
117 |
},
|
118 |
{
|
119 |
+
"key": "enable_xmlrpc_compatibility",
|
120 |
+
"section": "section_enable_plugin_feature_login_protection",
|
121 |
+
"default": "Y",
|
122 |
+
"type": "checkbox",
|
123 |
+
"link_info": "http://icwp.io/9u",
|
124 |
+
"link_blog": "",
|
125 |
+
"name": "XML-RPC Compatibility",
|
126 |
+
"summary": "Allow Login Through XML-RPC To By-Pass Login Protection Rules",
|
127 |
"description": "Enable this if you need XML-RPC functionality e.g. if you use the WordPress iPhone/Android App."
|
128 |
},
|
129 |
{
|
130 |
+
"key": "rename_wplogin_path",
|
131 |
+
"section": "section_rename_wplogin",
|
132 |
+
"sensitive": true,
|
133 |
+
"default": "",
|
134 |
+
"type": "text",
|
135 |
+
"link_info": "http://icwp.io/5q",
|
136 |
+
"link_blog": "http://icwp.io/5r",
|
137 |
+
"name": "Rename WP Login",
|
138 |
+
"summary": "Rename The WordPress Login Page",
|
139 |
"description": "Creating a path here will disable your 'wp-login.php'. Only letters and numbers are permitted: abc123"
|
140 |
},
|
141 |
{
|
142 |
+
"key": "enable_chained_authentication",
|
143 |
+
"section": "section_multifactor_authentication",
|
144 |
+
"default": "N",
|
145 |
+
"type": "checkbox",
|
146 |
+
"link_info": "http://icwp.io/9r",
|
147 |
+
"link_blog": "http://icwp.io/84",
|
148 |
+
"name": "Multi-Factor Authentication",
|
149 |
+
"summary": "Require All Active Authentication Factors",
|
150 |
"description": "When enabled, all multi-factor authentication methods will be applied to a user login. Disable to only require one to pass."
|
151 |
},
|
152 |
{
|
153 |
+
"key": "enable_google_authenticator",
|
154 |
+
"section": "section_multifactor_authentication",
|
155 |
+
"default": "N",
|
156 |
+
"type": "checkbox",
|
157 |
+
"link_info": "http://icwp.io/shld7",
|
158 |
+
"link_blog": "http://icwp.io/shld6",
|
159 |
+
"name": "Enable Google Authenticator",
|
160 |
+
"summary": "Allow Users To Use Google Authenticator",
|
161 |
"description": "When enabled, users will have the option to add Google Authenticator to their WordPress user profile."
|
162 |
},
|
163 |
{
|
164 |
+
"key": "enable_email_authentication",
|
165 |
+
"section": "section_multifactor_authentication",
|
166 |
+
"default": "N",
|
167 |
+
"type": "checkbox",
|
168 |
+
"link_info": "http://icwp.io/3t",
|
169 |
+
"link_blog": "http://icwp.io/9q",
|
170 |
+
"name": "Enable Email Authentication",
|
171 |
+
"summary": "Two-Factor Login Authentication By Email",
|
172 |
"description": "All users will be required to verify their login by email-based two-factor authentication."
|
173 |
},
|
174 |
{
|
175 |
+
"key": "two_factor_auth_user_roles",
|
176 |
+
"section": "section_multifactor_authentication",
|
177 |
+
"type": "multiple_select",
|
178 |
+
"default": [
|
179 |
1,
|
180 |
2,
|
181 |
3,
|
184 |
"value_options": [
|
185 |
{
|
186 |
"value_key": 0,
|
187 |
+
"text": "Subscribers"
|
188 |
},
|
189 |
{
|
190 |
"value_key": 1,
|
191 |
+
"text": "Contributors"
|
192 |
},
|
193 |
{
|
194 |
"value_key": 2,
|
195 |
+
"text": "Authors"
|
196 |
},
|
197 |
{
|
198 |
"value_key": 3,
|
199 |
+
"text": "Editors"
|
200 |
},
|
201 |
{
|
202 |
"value_key": 8,
|
203 |
+
"text": "Administrators"
|
204 |
}
|
205 |
],
|
206 |
+
"link_info": "http://icwp.io/4v",
|
207 |
+
"link_blog": "",
|
208 |
+
"name": "Enforce - Email Authentication",
|
209 |
+
"summary": "All User Roles Subject To Email Authentication",
|
210 |
+
"description": "Enforces email-based authentication on all users with the selected roles. Note: This setting only applies to email authentication."
|
211 |
},
|
212 |
{
|
213 |
+
"key": "enable_google_recaptcha_login",
|
214 |
+
"section": "section_recaptcha",
|
215 |
+
"default": "N",
|
216 |
+
"type": "checkbox",
|
217 |
+
"link_info": "http://icwp.io/9m",
|
218 |
+
"link_blog": "http://icwp.io/shld5",
|
219 |
+
"name": "Google reCAPTCHA",
|
220 |
+
"summary": "Enable Google reCAPTCHA",
|
221 |
"description": "Use Google reCAPTCHA on the login screen."
|
222 |
},
|
223 |
{
|
224 |
+
"key": "google_recaptcha_style_login",
|
225 |
+
"section": "section_recaptcha",
|
226 |
+
"premium": true,
|
227 |
+
"default": "default",
|
228 |
+
"type": "select",
|
229 |
"value_options": [
|
230 |
{
|
231 |
"value_key": "default",
|
232 |
+
"text": "Default"
|
233 |
},
|
234 |
{
|
235 |
"value_key": "light",
|
236 |
+
"text": "Light Theme"
|
237 |
},
|
238 |
{
|
239 |
"value_key": "dark",
|
240 |
+
"text": "Dark Theme"
|
241 |
},
|
242 |
{
|
243 |
"value_key": "invisible",
|
244 |
+
"text": "Invisible reCAPTCHA"
|
245 |
}
|
246 |
],
|
247 |
+
"link_info": "",
|
248 |
+
"link_blog": "",
|
249 |
+
"name": "reCAPTCHA Style",
|
250 |
+
"summary": "How Google reCAPTCHA Will Be Displayed",
|
251 |
+
"description": "You can choose the reCAPTCHA display format that best suits your site, including the new Invisible Recaptcha."
|
252 |
},
|
253 |
{
|
254 |
+
"key": "enable_login_gasp_check",
|
255 |
+
"section": "section_brute_force_login_protection",
|
256 |
+
"default": "Y",
|
257 |
+
"type": "checkbox",
|
258 |
+
"link_info": "http://icwp.io/3r",
|
259 |
+
"link_blog": "http://icwp.io/9n",
|
260 |
+
"name": "G.A.S.P Protection",
|
261 |
+
"summary": "Use G.A.S.P. Protection To Prevent Login Attempts By Bots",
|
262 |
"description": "Adds a dynamically (Javascript) generated checkbox to the login form that prevents bots using automated login techniques. Recommended: ON."
|
263 |
},
|
264 |
{
|
265 |
+
"key": "login_limit_interval",
|
266 |
+
"section": "section_brute_force_login_protection",
|
267 |
+
"default": "10",
|
268 |
+
"type": "integer",
|
269 |
+
"link_info": "http://icwp.io/3q",
|
270 |
+
"link_blog": "http://icwp.io/9o",
|
271 |
+
"name": "Login Cooldown Interval",
|
272 |
+
"summary": "Limit login attempts to every X seconds",
|
273 |
"description": "WordPress will process only ONE login attempt for every number of seconds specified. Zero (0) turns this off."
|
274 |
},
|
275 |
{
|
276 |
+
"key": "enable_user_register_checking",
|
277 |
+
"section": "section_brute_force_login_protection",
|
278 |
+
"default": "Y",
|
279 |
+
"type": "checkbox",
|
280 |
+
"link_info": "http://icwp.io/9p",
|
281 |
+
"link_blog": "",
|
282 |
+
"name": "User Registration",
|
283 |
+
"summary": "Apply Brute Force Protection To User Registration And Lost Passwords",
|
284 |
"description": "When enabled, settings in this section will also apply to new user registration and users trying to reset passwords."
|
285 |
},
|
286 |
{
|
287 |
+
"key": "enable_yubikey",
|
288 |
+
"section": "section_yubikey_authentication",
|
289 |
+
"default": "N",
|
290 |
+
"type": "checkbox",
|
291 |
+
"link_info": "http://icwp.io/4f",
|
292 |
+
"link_blog": "http://icwp.io/9t",
|
293 |
+
"name": "Enable Yubikey Authentication",
|
294 |
+
"summary": "Turn On / Off Yubikey Authentication On This Site",
|
295 |
"description": "Combined with your Yubikey API Key (below) this will form the basis of your Yubikey Authentication."
|
296 |
},
|
297 |
{
|
298 |
+
"key": "yubikey_app_id",
|
299 |
+
"section": "section_yubikey_authentication",
|
300 |
+
"sensitive": true,
|
301 |
+
"default": "",
|
302 |
+
"type": "text",
|
303 |
+
"link_info": "http://icwp.io/4g",
|
304 |
+
"link_blog": "",
|
305 |
+
"name": "Yubikey App ID",
|
306 |
+
"summary": "Your Unique Yubikey App ID",
|
307 |
"description": "Combined with your Yubikey API Key this will form the basis of your Yubikey Authentication."
|
308 |
},
|
309 |
{
|
310 |
+
"key": "yubikey_api_key",
|
311 |
+
"section": "section_yubikey_authentication",
|
312 |
+
"sensitive": true,
|
313 |
+
"default": "",
|
314 |
+
"type": "text",
|
315 |
+
"link_info": "http://icwp.io/4g",
|
316 |
+
"link_blog": "",
|
317 |
+
"name": "Yubikey API Key",
|
318 |
+
"summary": "Your Unique Yubikey App API Key",
|
319 |
"description": "Combined with your Yubikey App ID this will form the basis of your Yubikey Authentication."
|
320 |
},
|
321 |
{
|
322 |
+
"key": "text_imahuman",
|
323 |
+
"section": "section_user_messages",
|
324 |
+
"premium": true,
|
325 |
+
"default": "default",
|
326 |
+
"type": "text",
|
327 |
+
"link_info": "",
|
328 |
+
"link_blog": "",
|
329 |
+
"name": "GASP Checkbox Text",
|
330 |
+
"summary": "The Message Displayed Next To The GASP Checkbox",
|
331 |
+
"description": "You can change the text displayed to the user beside the checkbox if you need a customized message."
|
332 |
+
},
|
333 |
+
{
|
334 |
+
"key": "text_pleasecheckbox",
|
335 |
+
"section": "section_user_messages",
|
336 |
+
"premium": true,
|
337 |
+
"default": "default",
|
338 |
+
"type": "text",
|
339 |
+
"link_info": "",
|
340 |
+
"link_blog": "",
|
341 |
+
"name": "GASP Alert Text",
|
342 |
+
"summary": "The Message Displayed If The User Doesn't Check The Box",
|
343 |
+
"description": "You can change the text displayed to the user in the alert message if they don't check the box."
|
344 |
+
},
|
345 |
{
|
346 |
+
"key": "email_can_send_verified_at",
|
347 |
"transferable": false,
|
348 |
+
"section": "section_non_ui",
|
349 |
+
"default": -1
|
350 |
},
|
351 |
{
|
352 |
+
"key": "gasp_key",
|
353 |
"transferable": false,
|
354 |
+
"sensitive": true,
|
355 |
+
"section": "section_non_ui"
|
356 |
},
|
357 |
{
|
358 |
+
"key": "two_factor_secret_key",
|
359 |
"transferable": false,
|
360 |
+
"sensitive": true,
|
361 |
+
"section": "section_non_ui"
|
362 |
},
|
363 |
{
|
364 |
+
"key": "two_factor_auth_table_created",
|
365 |
"transferable": false,
|
366 |
+
"section": "section_non_ui"
|
367 |
},
|
368 |
{
|
369 |
+
"key": "use_login_intent_page",
|
370 |
"transferable": false,
|
371 |
+
"value": true,
|
372 |
+
"section": "section_non_ui"
|
373 |
}
|
374 |
],
|
375 |
+
"definitions": {
|
376 |
+
"login_intent_timeout": 5,
|
377 |
+
"two_factor_auth_table_name": "login_auth",
|
378 |
"two_factor_auth_table_columns": [
|
379 |
"id",
|
380 |
"session_id",
|
384 |
"expired_at",
|
385 |
"created_at",
|
386 |
"deleted_at"
|
387 |
+
],
|
388 |
+
"wizards": {
|
389 |
+
"mfa": {
|
390 |
+
"title": "Configure Multi-Factor Login Authentication",
|
391 |
+
"desc": "Easily setup multi-factor login authentication, using Email and Google Authenticator.",
|
392 |
+
"min_user_permissions": "manage_options",
|
393 |
+
"steps": {
|
394 |
+
"start": {
|
395 |
+
"security_admin": false,
|
396 |
+
"title": "Start: Multi-Factor Authentication"
|
397 |
+
},
|
398 |
+
"authemail": {
|
399 |
+
"title": "Email Authentication"
|
400 |
+
},
|
401 |
+
"authga": {
|
402 |
+
"title": "Google Authenticator"
|
403 |
+
},
|
404 |
+
"multiselect": {
|
405 |
+
"title": "Select Multifactor Auth"
|
406 |
+
},
|
407 |
+
"finished": {
|
408 |
+
"security_admin": false,
|
409 |
+
"title": "Finished: Multi-Factor Authentication"
|
410 |
+
}
|
411 |
+
}
|
412 |
+
}
|
413 |
+
}
|
414 |
}
|
415 |
}
|
src/config/feature-plugin.php
CHANGED
@@ -1,460 +1,521 @@
|
|
1 |
{
|
2 |
-
"properties":
|
3 |
-
"slug":
|
4 |
-
"name":
|
5 |
"show_feature_menu_item": true,
|
6 |
-
"storage_key":
|
7 |
-
"tagline":
|
8 |
-
"show_central":
|
9 |
-
"access_restricted":
|
10 |
-
"premium":
|
11 |
-
"has_custom_actions":
|
12 |
-
"order":
|
13 |
},
|
14 |
"admin_notices": {
|
15 |
-
"override-forceoff":
|
16 |
-
"id":
|
17 |
-
"schedule":
|
18 |
"valid_admin": true,
|
19 |
-
"type":
|
20 |
},
|
21 |
-
"
|
22 |
-
"id":
|
23 |
-
"schedule":
|
24 |
"valid_admin": true,
|
25 |
-
"type":
|
26 |
},
|
27 |
-
"
|
28 |
-
"id":
|
29 |
-
"schedule":
|
30 |
"valid_admin": true,
|
31 |
-
"
|
|
|
32 |
},
|
33 |
-
"
|
34 |
-
"id":
|
35 |
-
"schedule":
|
36 |
"valid_admin": true,
|
37 |
-
"delay_days":
|
38 |
-
"type":
|
39 |
-
},
|
40 |
-
"allow-tracking": {
|
41 |
-
"id": "allow-tracking",
|
42 |
-
"schedule": "never",
|
43 |
-
"valid_admin": true,
|
44 |
-
"delay_days": 0,
|
45 |
-
"type": "promo"
|
46 |
},
|
47 |
"plugin-mailing-list-signup": {
|
48 |
-
"id":
|
49 |
-
"schedule":
|
50 |
"valid_admin": true,
|
51 |
-
"delay_days":
|
52 |
-
"type":
|
53 |
},
|
54 |
-
"rate-plugin":
|
55 |
-
"id":
|
56 |
-
"schedule":
|
57 |
"valid_admin": true,
|
58 |
-
"delay_days":
|
59 |
-
"type":
|
60 |
},
|
61 |
-
"translate-plugin":
|
62 |
-
"id":
|
63 |
-
"schedule":
|
64 |
"valid_admin": true,
|
65 |
-
"delay_days":
|
66 |
-
"type":
|
67 |
}
|
68 |
},
|
69 |
-
"sections":
|
70 |
{
|
71 |
-
"slug":
|
72 |
-
"primary":
|
73 |
-
"title":
|
74 |
"title_short": "Global Options"
|
75 |
},
|
76 |
{
|
77 |
-
"slug":
|
78 |
-
"title":
|
79 |
"title_short": "Plugin Defaults"
|
80 |
},
|
81 |
{
|
82 |
-
"slug":
|
83 |
-
"title":
|
84 |
"title_short": "Import / Export"
|
85 |
},
|
86 |
{
|
87 |
-
"slug":
|
88 |
-
"title":
|
89 |
"title_short": "General Options"
|
90 |
},
|
91 |
{
|
92 |
-
"slug":
|
93 |
-
"title":
|
94 |
"title_short": "Google"
|
95 |
},
|
96 |
{
|
97 |
-
"slug":
|
98 |
"hidden": true
|
99 |
}
|
100 |
],
|
101 |
-
"options":
|
102 |
{
|
103 |
-
"key":
|
104 |
-
"section":
|
105 |
-
"default":
|
106 |
-
"type":
|
107 |
-
"link_info":
|
108 |
-
"link_blog":
|
109 |
-
"name":
|
110 |
-
"summary":
|
111 |
"description": "Uncheck this option to disable all Shield features"
|
112 |
},
|
113 |
{
|
114 |
-
"key":
|
115 |
-
"section":
|
116 |
-
"default":
|
117 |
-
"type":
|
118 |
-
"link_info":
|
119 |
-
"link_blog":
|
120 |
-
"name":
|
121 |
-
"summary":
|
122 |
"description": "Allows us to gather information on statistics and features in-use across our client installations. This information is strictly anonymous and contains no personally, or otherwise, identifiable data."
|
123 |
},
|
124 |
{
|
125 |
-
"key":
|
126 |
-
"section":
|
127 |
-
"sensitive":
|
128 |
-
"type":
|
129 |
-
"default":
|
130 |
"value_options": [
|
131 |
{
|
132 |
"value_key": "AUTO_DETECT_IP",
|
133 |
-
"text":
|
134 |
},
|
135 |
{
|
136 |
"value_key": "REMOTE_ADDR",
|
137 |
-
"text":
|
138 |
},
|
139 |
{
|
140 |
"value_key": "HTTP_CF_CONNECTING_IP",
|
141 |
-
"text":
|
142 |
},
|
143 |
{
|
144 |
"value_key": "HTTP_X_FORWARDED_FOR",
|
145 |
-
"text":
|
146 |
},
|
147 |
{
|
148 |
"value_key": "HTTP_X_FORWARDED",
|
149 |
-
"text":
|
150 |
},
|
151 |
{
|
152 |
"value_key": "HTTP_X_REAL_IP",
|
153 |
-
"text":
|
154 |
},
|
155 |
{
|
156 |
"value_key": "HTTP_X_SUCURI_CLIENTIP",
|
157 |
-
"text":
|
158 |
},
|
159 |
{
|
160 |
"value_key": "HTTP_INCAP_CLIENT_IP",
|
161 |
-
"text":
|
162 |
},
|
163 |
{
|
164 |
"value_key": "HTTP_FORWARDED",
|
165 |
-
"text":
|
166 |
},
|
167 |
{
|
168 |
"value_key": "HTTP_CLIENT_IP",
|
169 |
-
"text":
|
170 |
}
|
171 |
],
|
172 |
-
"link_info":
|
173 |
-
"link_blog":
|
174 |
-
"name":
|
175 |
-
"summary":
|
176 |
-
"description":
|
177 |
},
|
178 |
{
|
179 |
-
"key":
|
180 |
-
"section":
|
181 |
-
"sensitive":
|
182 |
-
"default":
|
183 |
-
"type":
|
184 |
-
"link_info":
|
185 |
-
"link_blog":
|
186 |
-
"name":
|
187 |
-
"summary":
|
188 |
"description": "If this is empty, it will default to the blog admin email address."
|
189 |
},
|
190 |
{
|
191 |
-
"key":
|
192 |
-
"section":
|
193 |
-
"default":
|
194 |
-
"type":
|
195 |
-
"link_info":
|
196 |
-
"link_blog":
|
197 |
-
"name":
|
198 |
-
"summary":
|
199 |
"description": "Disable this option to hide certain plugin admin notices about available updates and post-update notices."
|
200 |
},
|
201 |
{
|
202 |
-
"key":
|
203 |
-
"section":
|
204 |
-
"default":
|
205 |
-
"type":
|
206 |
-
"link_info":
|
207 |
-
"link_blog":
|
208 |
-
"name":
|
209 |
-
"summary":
|
210 |
"description": "Enabling this option helps support the plugin by spreading the word about it on your website. The plugin badge also demonstrates to visitors that you take your website security seriously."
|
211 |
},
|
212 |
{
|
213 |
-
"key":
|
214 |
-
"section":
|
215 |
-
"default":
|
216 |
-
"type":
|
217 |
-
"link_info":
|
218 |
-
"link_blog":
|
219 |
-
"name":
|
220 |
-
"summary":
|
221 |
"description": "Careful: Removes all plugin options when you deactivate the plugin."
|
222 |
},
|
223 |
{
|
224 |
-
"key":
|
225 |
-
"section":
|
226 |
-
"premium":
|
227 |
-
"default":
|
228 |
-
"type":
|
229 |
-
"link_info":
|
230 |
-
"link_blog":
|
231 |
-
"name":
|
232 |
-
"summary":
|
233 |
"description": "Uncheck this box to completely disable import and export of options."
|
234 |
},
|
235 |
{
|
236 |
-
"key":
|
237 |
-
"section":
|
238 |
-
"default":
|
239 |
-
"type":
|
240 |
-
"link_info":
|
241 |
-
"link_blog":
|
242 |
-
"name":
|
243 |
-
"summary":
|
244 |
"description": "Supplying a valid site URL here will make this site an 'Options Slave' and will automatically import options daily."
|
245 |
},
|
246 |
{
|
247 |
-
"key":
|
248 |
-
"section":
|
249 |
"transferable": false,
|
250 |
-
"default":
|
251 |
-
"type":
|
252 |
-
"link_info":
|
253 |
-
"link_blog":
|
254 |
-
"name":
|
255 |
-
"summary":
|
256 |
-
"description":
|
257 |
},
|
258 |
{
|
259 |
-
"key":
|
260 |
-
"section":
|
261 |
-
"default":
|
262 |
-
"type":
|
263 |
-
"link_info":
|
264 |
-
"link_blog":
|
265 |
-
"name":
|
266 |
-
"summary":
|
267 |
"description": "When enabled, manual options saving will notify sites on the whitelist to export options from the Master site."
|
268 |
},
|
269 |
{
|
270 |
-
"key":
|
271 |
-
"section":
|
272 |
"transferable": false,
|
273 |
-
"
|
274 |
-
"
|
275 |
-
"
|
276 |
-
"
|
277 |
-
"
|
278 |
-
"
|
279 |
-
"
|
|
|
280 |
},
|
281 |
{
|
282 |
-
"key":
|
283 |
-
"section":
|
284 |
"transferable": false,
|
285 |
-
"default":
|
286 |
-
"type":
|
287 |
-
"link_info":
|
288 |
-
"link_blog":
|
289 |
-
"name":
|
290 |
-
"summary":
|
291 |
-
"description":
|
292 |
},
|
293 |
{
|
294 |
-
"key":
|
295 |
-
"section":
|
296 |
-
"premium":
|
297 |
-
"default":
|
298 |
-
"type":
|
299 |
"value_options": [
|
300 |
{
|
301 |
"value_key": "light",
|
302 |
-
"text":
|
303 |
},
|
304 |
{
|
305 |
"value_key": "dark",
|
306 |
-
"text":
|
307 |
},
|
308 |
{
|
309 |
"value_key": "invisible",
|
310 |
-
"text":
|
311 |
}
|
312 |
],
|
313 |
-
"link_info":
|
314 |
-
"link_blog":
|
315 |
-
"name":
|
316 |
-
"summary":
|
317 |
-
"description":
|
318 |
},
|
319 |
{
|
320 |
-
"key":
|
321 |
-
"section":
|
322 |
-
"sensitive":
|
323 |
-
"default":
|
324 |
-
"type":
|
325 |
-
"link_info":
|
326 |
-
"link_blog":
|
327 |
-
"name":
|
328 |
-
"summary":
|
329 |
"description": "Enter your Google reCAPTCHA secret key for use throughout the plugin."
|
330 |
},
|
331 |
{
|
332 |
-
"key":
|
333 |
-
"section":
|
334 |
-
"sensitive":
|
335 |
-
"default":
|
336 |
-
"type":
|
337 |
-
"link_info":
|
338 |
-
"link_blog":
|
339 |
-
"name":
|
340 |
-
"summary":
|
341 |
"description": "Enter your Google reCAPTCHA site key for use throughout the plugin."
|
342 |
},
|
343 |
{
|
344 |
-
"key":
|
345 |
"transferable": false,
|
346 |
-
"default":
|
347 |
-
"section":
|
348 |
},
|
349 |
{
|
350 |
-
"key":
|
351 |
"default": 0,
|
352 |
"section": "section_non_ui"
|
353 |
},
|
354 |
{
|
355 |
-
"key":
|
356 |
"transferable": false,
|
357 |
-
"section":
|
358 |
},
|
359 |
{
|
360 |
-
"key":
|
361 |
"transferable": false,
|
362 |
-
"section":
|
363 |
},
|
364 |
{
|
365 |
-
"key":
|
366 |
"transferable": false,
|
367 |
-
"section":
|
368 |
},
|
369 |
{
|
370 |
-
"key":
|
371 |
"transferable": false,
|
372 |
-
"section":
|
373 |
},
|
374 |
{
|
375 |
-
"key":
|
376 |
"transferable": false,
|
377 |
-
"sensitive":
|
378 |
-
"section":
|
379 |
-
"value":
|
380 |
},
|
381 |
{
|
382 |
-
"key":
|
383 |
"transferable": false,
|
384 |
-
"section":
|
385 |
-
"value":
|
386 |
}
|
387 |
],
|
388 |
-
"definitions":
|
389 |
-
"help_video_id":
|
390 |
-
"tracking_cron_handle":
|
391 |
-
"tracking_post_url":
|
392 |
"importexport_cron_name": "autoimport",
|
393 |
"active_plugin_features": [
|
394 |
{
|
395 |
-
"slug":
|
396 |
-
"storage_key":
|
397 |
"load_priority": 20
|
398 |
},
|
399 |
{
|
400 |
-
"slug":
|
401 |
-
"storage_key":
|
402 |
"load_priority": 13
|
403 |
},
|
404 |
{
|
405 |
-
"slug":
|
406 |
"storage_key": "loginprotect"
|
407 |
},
|
408 |
{
|
409 |
-
"slug":
|
410 |
"storage_key": "user_management"
|
411 |
},
|
412 |
{
|
413 |
-
"slug":
|
414 |
"storage_key": "commentsfilter"
|
415 |
},
|
416 |
{
|
417 |
-
"slug":
|
418 |
"storage_key": "autoupdates"
|
419 |
},
|
420 |
{
|
421 |
-
"slug":
|
422 |
"storage_key": "hack_protect"
|
423 |
},
|
424 |
{
|
425 |
-
"slug":
|
426 |
"storage_key": "headers"
|
427 |
},
|
428 |
{
|
429 |
-
"slug":
|
430 |
"storage_key": "lockdown"
|
431 |
},
|
432 |
{
|
433 |
-
"slug":
|
434 |
-
"storage_key":
|
435 |
"load_priority": 12
|
436 |
},
|
437 |
{
|
438 |
-
"slug":
|
439 |
-
"storage_key":
|
440 |
"load_priority": 11,
|
441 |
-
"hidden":
|
442 |
},
|
443 |
{
|
444 |
-
"slug":
|
445 |
-
"storage_key":
|
446 |
"load_priority": 11,
|
447 |
-
"hidden":
|
448 |
},
|
449 |
{
|
450 |
-
"slug":
|
451 |
-
"storage_key":
|
452 |
"load_priority": 10
|
453 |
},
|
454 |
{
|
455 |
-
"slug":
|
456 |
"storage_key": "email"
|
457 |
}
|
458 |
-
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
459 |
}
|
460 |
}
|
1 |
{
|
2 |
+
"properties": {
|
3 |
+
"slug": "plugin",
|
4 |
+
"name": "Dashboard",
|
5 |
"show_feature_menu_item": true,
|
6 |
+
"storage_key": "plugin",
|
7 |
+
"tagline": "Overview of the plugin settings",
|
8 |
+
"show_central": true,
|
9 |
+
"access_restricted": true,
|
10 |
+
"premium": false,
|
11 |
+
"has_custom_actions": true,
|
12 |
+
"order": 10
|
13 |
},
|
14 |
"admin_notices": {
|
15 |
+
"override-forceoff": {
|
16 |
+
"id": "override-forceoff",
|
17 |
+
"schedule": "conditions",
|
18 |
"valid_admin": true,
|
19 |
+
"type": "error"
|
20 |
},
|
21 |
+
"plugin-update-available": {
|
22 |
+
"id": "plugin-update-available",
|
23 |
+
"schedule": "version",
|
24 |
"valid_admin": true,
|
25 |
+
"type": "warning"
|
26 |
},
|
27 |
+
"wizard_welcome": {
|
28 |
+
"id": "wizard_welcome",
|
29 |
+
"schedule": "once",
|
30 |
"valid_admin": true,
|
31 |
+
"delay_days": 0,
|
32 |
+
"type": "promo"
|
33 |
},
|
34 |
+
"allow-tracking": {
|
35 |
+
"id": "allow-tracking",
|
36 |
+
"schedule": "never",
|
37 |
"valid_admin": true,
|
38 |
+
"delay_days": 0,
|
39 |
+
"type": "promo"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
},
|
41 |
"plugin-mailing-list-signup": {
|
42 |
+
"id": "plugin-mailing-list-signup",
|
43 |
+
"schedule": "once",
|
44 |
"valid_admin": true,
|
45 |
+
"delay_days": 15,
|
46 |
+
"type": "promo"
|
47 |
},
|
48 |
+
"rate-plugin": {
|
49 |
+
"id": "rate-plugin",
|
50 |
+
"schedule": "once",
|
51 |
"valid_admin": true,
|
52 |
+
"delay_days": 30,
|
53 |
+
"type": "promo"
|
54 |
},
|
55 |
+
"translate-plugin": {
|
56 |
+
"id": "translate-plugin",
|
57 |
+
"schedule": "once",
|
58 |
"valid_admin": true,
|
59 |
+
"delay_days": 45,
|
60 |
+
"type": "promo"
|
61 |
}
|
62 |
},
|
63 |
+
"sections": [
|
64 |
{
|
65 |
+
"slug": "section_global_security_options",
|
66 |
+
"primary": true,
|
67 |
+
"title": "Global Plugin Security Options",
|
68 |
"title_short": "Global Options"
|
69 |
},
|
70 |
{
|
71 |
+
"slug": "section_defaults",
|
72 |
+
"title": "Plugin Defaults",
|
73 |
"title_short": "Plugin Defaults"
|
74 |
},
|
75 |
{
|
76 |
+
"slug": "section_importexport",
|
77 |
+
"title": "Import / Export",
|
78 |
"title_short": "Import / Export"
|
79 |
},
|
80 |
{
|
81 |
+
"slug": "section_general_plugin_options",
|
82 |
+
"title": "General Plugin Options",
|
83 |
"title_short": "General Options"
|
84 |
},
|
85 |
{
|
86 |
+
"slug": "section_third_party_google",
|
87 |
+
"title": "Google",
|
88 |
"title_short": "Google"
|
89 |
},
|
90 |
{
|
91 |
+
"slug": "section_non_ui",
|
92 |
"hidden": true
|
93 |
}
|
94 |
],
|
95 |
+
"options": [
|
96 |
{
|
97 |
+
"key": "global_enable_plugin_features",
|
98 |
+
"section": "section_global_security_options",
|
99 |
+
"default": "Y",
|
100 |
+
"type": "checkbox",
|
101 |
+
"link_info": "",
|
102 |
+
"link_blog": "",
|
103 |
+
"name": "Enable Plugin Features",
|
104 |
+
"summary": "Global Plugin On/Off Switch",
|
105 |
"description": "Uncheck this option to disable all Shield features"
|
106 |
},
|
107 |
{
|
108 |
+
"key": "enable_tracking",
|
109 |
+
"section": "section_general_plugin_options",
|
110 |
+
"default": "N",
|
111 |
+
"type": "checkbox",
|
112 |
+
"link_info": "http://icwp.io/7i",
|
113 |
+
"link_blog": "",
|
114 |
+
"name": "Enable Information Gathering",
|
115 |
+
"summary": "Permit Anonymous Usage Information Gathering",
|
116 |
"description": "Allows us to gather information on statistics and features in-use across our client installations. This information is strictly anonymous and contains no personally, or otherwise, identifiable data."
|
117 |
},
|
118 |
{
|
119 |
+
"key": "visitor_address_source",
|
120 |
+
"section": "section_defaults",
|
121 |
+
"sensitive": false,
|
122 |
+
"type": "select",
|
123 |
+
"default": "AUTO_DETECT_IP",
|
124 |
"value_options": [
|
125 |
{
|
126 |
"value_key": "AUTO_DETECT_IP",
|
127 |
+
"text": "Automatically Detect Visitor IP"
|
128 |
},
|
129 |
{
|
130 |
"value_key": "REMOTE_ADDR",
|
131 |
+
"text": "REMOTE_ADDR"
|
132 |
},
|
133 |
{
|
134 |
"value_key": "HTTP_CF_CONNECTING_IP",
|
135 |
+
"text": "HTTP_CF_CONNECTING_IP"
|
136 |
},
|
137 |
{
|
138 |
"value_key": "HTTP_X_FORWARDED_FOR",
|
139 |
+
"text": "HTTP_X_FORWARDED_FOR"
|
140 |
},
|
141 |
{
|
142 |
"value_key": "HTTP_X_FORWARDED",
|
143 |
+
"text": "HTTP_X_FORWARDED"
|
144 |
},
|
145 |
{
|
146 |
"value_key": "HTTP_X_REAL_IP",
|
147 |
+
"text": "HTTP_X_REAL_IP"
|
148 |
},
|
149 |
{
|
150 |
"value_key": "HTTP_X_SUCURI_CLIENTIP",
|
151 |
+
"text": "HTTP_X_SUCURI_CLIENTIP"
|
152 |
},
|
153 |
{
|
154 |
"value_key": "HTTP_INCAP_CLIENT_IP",
|
155 |
+
"text": "HTTP_INCAP_CLIENT_IP"
|
156 |
},
|
157 |
{
|
158 |
"value_key": "HTTP_FORWARDED",
|
159 |
+
"text": "HTTP_FORWARDED"
|
160 |
},
|
161 |
{
|
162 |
"value_key": "HTTP_CLIENT_IP",
|
163 |
+
"text": "HTTP_CLIENT_IP"
|
164 |
}
|
165 |
],
|
166 |
+
"link_info": "",
|
167 |
+
"link_blog": "",
|
168 |
+
"name": "Visitor IP Address",
|
169 |
+
"summary": "Which Address Is Yours",
|
170 |
+
"description": "There are many way to detect visitor IP addresses. Please select yours from the list."
|
171 |
},
|
172 |
{
|
173 |
+
"key": "block_send_email_address",
|
174 |
+
"section": "section_defaults",
|
175 |
+
"sensitive": true,
|
176 |
+
"default": "",
|
177 |
+
"type": "email",
|
178 |
+
"link_info": "",
|
179 |
+
"link_blog": "",
|
180 |
+
"name": "Report Email",
|
181 |
+
"summary": "Where to send email reports",
|
182 |
"description": "If this is empty, it will default to the blog admin email address."
|
183 |
},
|
184 |
{
|
185 |
+
"key": "enable_upgrade_admin_notice",
|
186 |
+
"section": "section_general_plugin_options",
|
187 |
+
"default": "Y",
|
188 |
+
"type": "checkbox",
|
189 |
+
"link_info": "",
|
190 |
+
"link_blog": "",
|
191 |
+
"name": "In-Plugin Notices",
|
192 |
+
"summary": "Display Plugin Specific Notices",
|
193 |
"description": "Disable this option to hide certain plugin admin notices about available updates and post-update notices."
|
194 |
},
|
195 |
{
|
196 |
+
"key": "display_plugin_badge",
|
197 |
+
"section": "section_general_plugin_options",
|
198 |
+
"default": "N",
|
199 |
+
"type": "checkbox",
|
200 |
+
"link_info": "http://icwp.io/5v",
|
201 |
+
"link_blog": "http://icwp.io/wpsf20",
|
202 |
+
"name": "Show Plugin Badge",
|
203 |
+
"summary": "Display Plugin Badge On Your Site",
|
204 |
"description": "Enabling this option helps support the plugin by spreading the word about it on your website. The plugin badge also demonstrates to visitors that you take your website security seriously."
|
205 |
},
|
206 |
{
|
207 |
+
"key": "delete_on_deactivate",
|
208 |
+
"section": "section_defaults",
|
209 |
+
"default": "N",
|
210 |
+
"type": "checkbox",
|
211 |
+
"link_info": "",
|
212 |
+
"link_blog": "",
|
213 |
+
"name": "Delete Plugin Settings",
|
214 |
+
"summary": "Delete All Plugin Settings Upon Plugin Deactivation",
|
215 |
"description": "Careful: Removes all plugin options when you deactivate the plugin."
|
216 |
},
|
217 |
{
|
218 |
+
"key": "importexport_enable",
|
219 |
+
"section": "section_importexport",
|
220 |
+
"premium": true,
|
221 |
+
"default": "Y",
|
222 |
+
"type": "checkbox",
|
223 |
+
"link_info": "",
|
224 |
+
"link_blog": "",
|
225 |
+
"name": "Allow Import/Export",
|
226 |
+
"summary": "Allow Import Of Options To, And Export Of Options From, This Site",
|
227 |
"description": "Uncheck this box to completely disable import and export of options."
|
228 |
},
|
229 |
{
|
230 |
+
"key": "importexport_masterurl",
|
231 |
+
"section": "section_importexport",
|
232 |
+
"default": "",
|
233 |
+
"type": "text",
|
234 |
+
"link_info": "",
|
235 |
+
"link_blog": "",
|
236 |
+
"name": "Auto-Import URL",
|
237 |
+
"summary": "Automatically Import Options From This Site",
|
238 |
"description": "Supplying a valid site URL here will make this site an 'Options Slave' and will automatically import options daily."
|
239 |
},
|
240 |
{
|
241 |
+
"key": "importexport_whitelist",
|
242 |
+
"section": "section_importexport",
|
243 |
"transferable": false,
|
244 |
+
"default": [],
|
245 |
+
"type": "array",
|
246 |
+
"link_info": "",
|
247 |
+
"link_blog": "",
|
248 |
+
"name": "Export Whitelist",
|
249 |
+
"summary": "Whitelisted Sites Which Do Not Need The Secret Key To Export Options",
|
250 |
+
"description": "Each site on this list will be able to export options from this site without providing the secret key. Take a new line for each URL."
|
251 |
},
|
252 |
{
|
253 |
+
"key": "importexport_whitelist_notify",
|
254 |
+
"section": "section_importexport",
|
255 |
+
"default": "N",
|
256 |
+
"type": "checkbox",
|
257 |
+
"link_info": "",
|
258 |
+
"link_blog": "",
|
259 |
+
"name": "Notify Whitelist",
|
260 |
+
"summary": "Notify Sites On The Whitelist To Update Options From Master",
|
261 |
"description": "When enabled, manual options saving will notify sites on the whitelist to export options from the Master site."
|
262 |
},
|
263 |
{
|
264 |
+
"key": "importexport_secretkey",
|
265 |
+
"section": "section_importexport",
|
266 |
"transferable": false,
|
267 |
+
"sensitive": true,
|
268 |
+
"default": "",
|
269 |
+
"type": "noneditable_text",
|
270 |
+
"link_info": "",
|
271 |
+
"link_blog": "",
|
272 |
+
"name": "Secret Key",
|
273 |
+
"summary": "Import/Export Secret Key",
|
274 |
+
"description": "Keep this Secret Key private as it will allow the import and export of options."
|
275 |
},
|
276 |
{
|
277 |
+
"key": "unique_installation_id",
|
278 |
+
"section": "section_general_plugin_options",
|
279 |
"transferable": false,
|
280 |
+
"default": "",
|
281 |
+
"type": "noneditable_text",
|
282 |
+
"link_info": "",
|
283 |
+
"link_blog": "",
|
284 |
+
"name": "Installation ID",
|
285 |
+
"summary": "Unique Plugin Installation ID",
|
286 |
+
"description": "Keep this ID private."
|
287 |
},
|
288 |
{
|
289 |
+
"key": "google_recaptcha_style",
|
290 |
+
"section": "section_third_party_google",
|
291 |
+
"premium": true,
|
292 |
+
"default": "light",
|
293 |
+
"type": "select",
|
294 |
"value_options": [
|
295 |
{
|
296 |
"value_key": "light",
|
297 |
+
"text": "Light Theme"
|
298 |
},
|
299 |
{
|
300 |
"value_key": "dark",
|
301 |
+
"text": "Dark Theme"
|
302 |
},
|
303 |
{
|
304 |
"value_key": "invisible",
|
305 |
+
"text": "Invisible reCAPTCHA"
|
306 |
}
|
307 |
],
|
308 |
+
"link_info": "",
|
309 |
+
"link_blog": "",
|
310 |
+
"name": "reCAPTCHA Style",
|
311 |
+
"summary": "How Google reCAPTCHA Will Be Displayed By Default",
|
312 |
+
"description": "You can choose the reCAPTCHA display format that best suits your site, including the new Invisible Recaptcha."
|
313 |
},
|
314 |
{
|
315 |
+
"key": "google_recaptcha_site_key",
|
316 |
+
"section": "section_third_party_google",
|
317 |
+
"sensitive": true,
|
318 |
+
"default": "",
|
319 |
+
"type": "text",
|
320 |
+
"link_info": "http://icwp.io/shld5",
|
321 |
+
"link_blog": "",
|
322 |
+
"name": "reCAPTCHA Secret",
|
323 |
+
"summary": "Google reCAPTCHA Secret Key",
|
324 |
"description": "Enter your Google reCAPTCHA secret key for use throughout the plugin."
|
325 |
},
|
326 |
{
|
327 |
+
"key": "google_recaptcha_secret_key",
|
328 |
+
"section": "section_third_party_google",
|
329 |
+
"sensitive": true,
|
330 |
+
"default": "",
|
331 |
+
"type": "text",
|
332 |
+
"link_info": "http://icwp.io/shld5",
|
333 |
+
"link_blog": "",
|
334 |
+
"name": "reCAPTCHA Site Key",
|
335 |
+
"summary": "Google reCAPTCHA Site Key",
|
336 |
"description": "Enter your Google reCAPTCHA site key for use throughout the plugin."
|
337 |
},
|
338 |
{
|
339 |
+
"key": "tracking_last_sent_at",
|
340 |
"transferable": false,
|
341 |
+
"default": 0,
|
342 |
+
"section": "section_non_ui"
|
343 |
},
|
344 |
{
|
345 |
+
"key": "tracking_permission_set_at",
|
346 |
"default": 0,
|
347 |
"section": "section_non_ui"
|
348 |
},
|
349 |
{
|
350 |
+
"key": "installation_time",
|
351 |
"transferable": false,
|
352 |
+
"section": "section_non_ui"
|
353 |
},
|
354 |
{
|
355 |
+
"key": "importexport_secretkey_expires_at",
|
356 |
"transferable": false,
|
357 |
+
"section": "section_non_ui"
|
358 |
},
|
359 |
{
|
360 |
+
"key": "importexport_handshake_expires_at",
|
361 |
"transferable": false,
|
362 |
+
"section": "section_non_ui"
|
363 |
},
|
364 |
{
|
365 |
+
"key": "importexport_last_import_hash",
|
366 |
"transferable": false,
|
367 |
+
"section": "section_non_ui"
|
368 |
},
|
369 |
{
|
370 |
+
"key": "this_server_ip",
|
371 |
"transferable": false,
|
372 |
+
"sensitive": true,
|
373 |
+
"section": "section_non_ui",
|
374 |
+
"value": ""
|
375 |
},
|
376 |
{
|
377 |
+
"key": "this_server_ip_last_check_at",
|
378 |
"transferable": false,
|
379 |
+
"section": "section_non_ui",
|
380 |
+
"value": 0
|
381 |
}
|
382 |
],
|
383 |
+
"definitions": {
|
384 |
+
"help_video_id": "",
|
385 |
+
"tracking_cron_handle": "plugin_tracking_cron",
|
386 |
+
"tracking_post_url": "https://tracking.icontrolwp.com/track/plugin/shield",
|
387 |
"importexport_cron_name": "autoimport",
|
388 |
"active_plugin_features": [
|
389 |
{
|
390 |
+
"slug": "admin_access_restriction",
|
391 |
+
"storage_key": "admin_access_restriction",
|
392 |
"load_priority": 20
|
393 |
},
|
394 |
{
|
395 |
+
"slug": "firewall",
|
396 |
+
"storage_key": "firewall",
|
397 |
"load_priority": 13
|
398 |
},
|
399 |
{
|
400 |
+
"slug": "login_protect",
|
401 |
"storage_key": "loginprotect"
|
402 |
},
|
403 |
{
|
404 |
+
"slug": "user_management",
|
405 |
"storage_key": "user_management"
|
406 |
},
|
407 |
{
|
408 |
+
"slug": "comments_filter",
|
409 |
"storage_key": "commentsfilter"
|
410 |
},
|
411 |
{
|
412 |
+
"slug": "autoupdates",
|
413 |
"storage_key": "autoupdates"
|
414 |
},
|
415 |
{
|
416 |
+
"slug": "hack_protect",
|
417 |
"storage_key": "hack_protect"
|
418 |
},
|
419 |
{
|
420 |
+
"slug": "headers",
|
421 |
"storage_key": "headers"
|
422 |
},
|
423 |
{
|
424 |
+
"slug": "lockdown",
|
425 |
"storage_key": "lockdown"
|
426 |
},
|
427 |
{
|
428 |
+
"slug": "ips",
|
429 |
+
"storage_key": "ips",
|
430 |
"load_priority": 12
|
431 |
},
|
432 |
{
|
433 |
+
"slug": "statistics",
|
434 |
+
"storage_key": "statistics",
|
435 |
"load_priority": 11,
|
436 |
+
"hidden": false
|
437 |
},
|
438 |
{
|
439 |
+
"slug": "audit_trail",
|
440 |
+
"storage_key": "audit_trail",
|
441 |
"load_priority": 11,
|
442 |
+
"hidden": false
|
443 |
},
|
444 |
{
|
445 |
+
"slug": "license",
|
446 |
+
"storage_key": "license",
|
447 |
"load_priority": 10
|
448 |
},
|
449 |
{
|
450 |
+
"slug": "email",
|
451 |
"storage_key": "email"
|
452 |
}
|
453 |
+
],
|
454 |
+
"wizards": {
|
455 |
+
"welcome": {
|
456 |
+
"title": "Getting Started Setup Wizard",
|
457 |
+
"desc": "An introduction to this security plugin, helping you get setup and started quickly with the core features.",
|
458 |
+
"min_user_permissions": "manage_options",
|
459 |
+
"steps": {
|
460 |
+
"welcome": {
|
461 |
+
"security_admin": false,
|
462 |
+
"title": "Welcome"
|
463 |
+
},
|
464 |
+
"ip_detect": {
|
465 |
+
"title": "IP Detection"
|
466 |
+
},
|
467 |
+
"license": {
|
468 |
+
"title": "Go Pro"
|
469 |
+
},
|
470 |
+
"import": {
|
471 |
+
"title": "Import"
|
472 |
+
},
|
473 |
+
"admin_access_restriction": {
|
474 |
+
"title": "Security Admin"
|
475 |
+
},
|
476 |
+
"audit_trail": {
|
477 |
+
"title": "Audit Trail"
|
478 |
+
},
|
479 |
+
"ips": {
|
480 |
+
"title": "IP Blacklist"
|
481 |
+
},
|
482 |
+
"login_protect": {
|
483 |
+
"title": "Login Protection"
|
484 |
+
},
|
485 |
+
"comments_filter": {
|
486 |
+
"title": "Comment SPAM"
|
487 |
+
},
|
488 |
+
"how_shield_works": {
|
489 |
+
"title": "How Shield Works"
|
490 |
+
},
|
491 |
+
"optin": {
|
492 |
+
"title": "Join Us!"
|
493 |
+
},
|
494 |
+
"thankyou": {
|
495 |
+
"security_admin": false,
|
496 |
+
"title": "Thank You!"
|
497 |
+
}
|
498 |
+
}
|
499 |
+
},
|
500 |
+
"importexport": {
|
501 |
+
"title": "Options Import/Export Wizard",
|
502 |
+
"desc": "Walks you through the import and export of options, as well as configuring ongoing automated options-sync.",
|
503 |
+
"min_user_permissions": "manage_options",
|
504 |
+
"has_premium": true,
|
505 |
+
"steps": {
|
506 |
+
"start": {
|
507 |
+
"security_admin": false,
|
508 |
+
"title": "Start: Options Import"
|
509 |
+
},
|
510 |
+
"import": {
|
511 |
+
"title": "Run Options Import"
|
512 |
+
},
|
513 |
+
"finished": {
|
514 |
+
"security_admin": false,
|
515 |
+
"title": "Finished: Options Import"
|
516 |
+
}
|
517 |
+
}
|
518 |
+
}
|
519 |
+
}
|
520 |
}
|
521 |
}
|
src/features/admin_access_restriction.php
CHANGED
@@ -1,8 +1,10 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
if (
|
|
|
|
|
4 |
|
5 |
-
require_once( dirname(__FILE__).DIRECTORY_SEPARATOR.'base_wpsf.php' );
|
6 |
|
7 |
class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureHandler_BaseWpsf {
|
8 |
|
@@ -47,7 +49,7 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
47 |
$bSuccess = $this->checkAdminAccessKeySubmission();
|
48 |
if ( $bSuccess ) {
|
49 |
$this->setPermissionToSubmit( true );
|
50 |
-
$sResponseData[ 'html' ] = _wpsf__( 'Security Admin Access Key Accepted.' ).
|
51 |
}
|
52 |
else {
|
53 |
$sResponseData[ 'html' ] = $this->renderAdminAccessAjaxLoginForm( _wpsf__( 'Error - Invalid Key' ) );
|
@@ -72,16 +74,14 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
72 |
return $this->bHasPermissionToSubmit;
|
73 |
}
|
74 |
|
75 |
-
$oDp = $this->loadDataProcessor();
|
76 |
-
|
77 |
$this->bHasPermissionToSubmit = $fHasPermission;
|
78 |
-
if ( $this->getIsMainFeatureEnabled() )
|
79 |
|
80 |
$sAccessKey = $this->getOpt( 'admin_access_key' );
|
81 |
if ( !empty( $sAccessKey ) ) {
|
82 |
-
$
|
83 |
-
$sCookieValue = $oDp->
|
84 |
-
$this->bHasPermissionToSubmit = ( $sCookieValue === $
|
85 |
}
|
86 |
}
|
87 |
return $this->bHasPermissionToSubmit;
|
@@ -134,14 +134,13 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
134 |
|
135 |
/**
|
136 |
* TODO: Bug where if $sType is defined, it'll be set to 'wp' anyway
|
137 |
-
*
|
138 |
* @param string $sType - wp or wpms
|
139 |
* @return array
|
140 |
*/
|
141 |
public function getOptionsToRestrict( $sType = '' ) {
|
142 |
$sType = empty( $sType ) ? ( $this->loadWp()->isMultisite() ? 'wpms' : 'wp' ) : 'wp';
|
143 |
$aOptions = $this->getRestrictedOptions();
|
144 |
-
return ( isset( $aOptions[$sType.'_options'] ) && is_array( $aOptions[$sType.'_options'] ) ) ? $aOptions[$sType.'_options'] : array();
|
145 |
}
|
146 |
|
147 |
/**
|
@@ -151,7 +150,7 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
151 |
public function getOptionsPagesToRestrict( $sType = '' ) {
|
152 |
$sType = empty( $sType ) ? ( $this->loadWp()->isMultisite() ? 'wpms' : 'wp' ) : 'wp';
|
153 |
$aOptions = $this->getRestrictedOptions();
|
154 |
-
return ( isset( $aOptions[$sType.'_pages'] ) && is_array( $aOptions[$sType.'_pages'] ) ) ? $aOptions[$sType.'_pages'] : array();
|
155 |
}
|
156 |
|
157 |
/**
|
@@ -159,21 +158,19 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
159 |
protected function setAdminAccessCookie() {
|
160 |
$sAccessKey = $this->getOpt( 'admin_access_key' );
|
161 |
if ( !empty( $sAccessKey ) ) {
|
162 |
-
$
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
$sTimeout
|
169 |
-
);
|
170 |
}
|
171 |
}
|
172 |
|
173 |
/**
|
174 |
*/
|
175 |
protected function clearAdminAccessCookie() {
|
176 |
-
$this->loadDataProcessor()->setDeleteCookie( $this->
|
177 |
}
|
178 |
|
179 |
/**
|
@@ -189,8 +186,8 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
189 |
/**
|
190 |
* @return string
|
191 |
*/
|
192 |
-
public function
|
193 |
-
return $this->getDefinition( '
|
194 |
}
|
195 |
|
196 |
/**
|
@@ -253,7 +250,7 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
253 |
protected function loadStrings_SectionTitles( $aOptionsParams ) {
|
254 |
|
255 |
$sSectionSlug = $aOptionsParams[ 'slug' ];
|
256 |
-
switch( $sSectionSlug ) {
|
257 |
|
258 |
case 'section_enable_plugin_feature_admin_access_restriction' :
|
259 |
$sTitle = sprintf( _wpsf__( 'Enable Plugin Feature: %s' ), $this->getMainFeatureName() );
|
@@ -286,9 +283,9 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
286 |
default:
|
287 |
throw new Exception( sprintf( 'A section slug was defined but with no associated strings. Slug: "%s".', $sSectionSlug ) );
|
288 |
}
|
289 |
-
$aOptionsParams['title'] = $sTitle;
|
290 |
-
$aOptionsParams['summary'] = ( isset( $aSummary ) && is_array( $aSummary ) ) ? $aSummary : array();
|
291 |
-
$aOptionsParams['title_short'] = $sTitleShort;
|
292 |
return $aOptionsParams;
|
293 |
}
|
294 |
|
@@ -299,8 +296,8 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
299 |
*/
|
300 |
protected function loadStrings_Options( $aOptionsParams ) {
|
301 |
|
302 |
-
$sKey = $aOptionsParams['key'];
|
303 |
-
switch( $sKey ) {
|
304 |
|
305 |
case 'enable_admin_access_restriction' :
|
306 |
$sName = sprintf( _wpsf__( 'Enable %s' ), _wpsf__( 'Security Admin' ) );
|
@@ -314,27 +311,27 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
314 |
$sDescription = sprintf( _wpsf__( 'Careful: %s' ), _wpsf__( 'If you forget this, you could potentially lock yourself out from using this plugin.' ) );
|
315 |
break;
|
316 |
|
317 |
-
|
318 |
case 'admin_access_timeout' :
|
319 |
$sName = _wpsf__( 'Security Admin Timeout' );
|
320 |
$sSummary = _wpsf__( 'Specify An Automatic Timeout Interval For Security Admin Access' );
|
321 |
-
$sDescription = _wpsf__( 'This will automatically expire your Security Admin Session.')
|
322 |
-
|
323 |
-
|
|
|
324 |
break;
|
325 |
|
326 |
case 'admin_access_restrict_posts' :
|
327 |
$sName = _wpsf__( 'Pages' );
|
328 |
$sSummary = _wpsf__( 'Restrict Access To Key WordPress Posts And Pages Actions' );
|
329 |
$sDescription = sprintf( _wpsf__( 'Careful: %s' ), _wpsf__( 'This will restrict access to page/post creation, editing and deletion.' ) )
|
330 |
-
.'<br />'.sprintf(_wpsf__( 'Note: %s' ), sprintf( _wpsf__( 'Selecting "%s" will also restrict all other options.' ), _wpsf__('Edit') ) );
|
331 |
break;
|
332 |
|
333 |
case 'admin_access_restrict_plugins' :
|
334 |
$sName = _wpsf__( 'Plugins' );
|
335 |
$sSummary = _wpsf__( 'Restrict Access To Key WordPress Plugin Actions' );
|
336 |
$sDescription = sprintf( _wpsf__( 'Careful: %s' ), _wpsf__( 'This will restrict access to plugin installation, update, activation and deletion.' ) )
|
337 |
-
|
338 |
break;
|
339 |
|
340 |
case 'admin_access_restrict_options' :
|
@@ -359,7 +356,7 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
359 |
sprintf(
|
360 |
_wpsf__( 'Selecting "%s" will also restrict all other options.' ),
|
361 |
sprintf(
|
362 |
-
_wpsf__('%s and %s'),
|
363 |
_wpsf__( 'Activate' ),
|
364 |
_wpsf__( 'Edit Theme Options' )
|
365 |
)
|
@@ -371,9 +368,9 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
371 |
throw new Exception( sprintf( 'An option has been defined but without strings assigned to it. Option key: "%s".', $sKey ) );
|
372 |
}
|
373 |
|
374 |
-
$aOptionsParams['name'] = $sName;
|
375 |
-
$aOptionsParams['summary'] = $sSummary;
|
376 |
-
$aOptionsParams['description'] = $sDescription;
|
377 |
return $aOptionsParams;
|
378 |
}
|
379 |
|
@@ -396,7 +393,11 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
396 |
if ( in_array( 'activate_plugins', $aPluginsRestrictions ) ) {
|
397 |
$this->setOpt(
|
398 |
'admin_access_restrict_plugins',
|
399 |
-
array_unique( array_merge( $aPluginsRestrictions, array(
|
|
|
|
|
|
|
|
|
400 |
);
|
401 |
}
|
402 |
|
@@ -405,7 +406,11 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
405 |
if ( in_array( 'switch_themes', $aThemesRestrictions ) && in_array( 'edit_theme_options', $aThemesRestrictions ) ) {
|
406 |
$this->setOpt(
|
407 |
'admin_access_restrict_themes',
|
408 |
-
array_unique( array_merge( $aThemesRestrictions, array(
|
|
|
|
|
|
|
|
|
409 |
);
|
410 |
}
|
411 |
|
@@ -417,5 +422,4 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
417 |
);
|
418 |
}
|
419 |
}
|
420 |
-
}
|
421 |
-
endif;
|
1 |
<?php
|
2 |
|
3 |
+
if ( class_exists( 'ICWP_WPSF_FeatureHandler_AdminAccessRestriction' ) ) {
|
4 |
+
return;
|
5 |
+
}
|
6 |
|
7 |
+
require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'base_wpsf.php' );
|
8 |
|
9 |
class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureHandler_BaseWpsf {
|
10 |
|
49 |
$bSuccess = $this->checkAdminAccessKeySubmission();
|
50 |
if ( $bSuccess ) {
|
51 |
$this->setPermissionToSubmit( true );
|
52 |
+
$sResponseData[ 'html' ] = _wpsf__( 'Security Admin Access Key Accepted.' ).' '._wpsf__( 'Please wait' ).' ...';
|
53 |
}
|
54 |
else {
|
55 |
$sResponseData[ 'html' ] = $this->renderAdminAccessAjaxLoginForm( _wpsf__( 'Error - Invalid Key' ) );
|
74 |
return $this->bHasPermissionToSubmit;
|
75 |
}
|
76 |
|
|
|
|
|
77 |
$this->bHasPermissionToSubmit = $fHasPermission;
|
78 |
+
if ( $this->getIsMainFeatureEnabled() ) {
|
79 |
|
80 |
$sAccessKey = $this->getOpt( 'admin_access_key' );
|
81 |
if ( !empty( $sAccessKey ) ) {
|
82 |
+
$oDp = $this->loadDP();
|
83 |
+
$sCookieValue = $oDp->cookie( $this->getSecurityAdminCookieName() );
|
84 |
+
$this->bHasPermissionToSubmit = ( $sCookieValue === md5( $sAccessKey ) );
|
85 |
}
|
86 |
}
|
87 |
return $this->bHasPermissionToSubmit;
|
134 |
|
135 |
/**
|
136 |
* TODO: Bug where if $sType is defined, it'll be set to 'wp' anyway
|
|
|
137 |
* @param string $sType - wp or wpms
|
138 |
* @return array
|
139 |
*/
|
140 |
public function getOptionsToRestrict( $sType = '' ) {
|
141 |
$sType = empty( $sType ) ? ( $this->loadWp()->isMultisite() ? 'wpms' : 'wp' ) : 'wp';
|
142 |
$aOptions = $this->getRestrictedOptions();
|
143 |
+
return ( isset( $aOptions[ $sType.'_options' ] ) && is_array( $aOptions[ $sType.'_options' ] ) ) ? $aOptions[ $sType.'_options' ] : array();
|
144 |
}
|
145 |
|
146 |
/**
|
150 |
public function getOptionsPagesToRestrict( $sType = '' ) {
|
151 |
$sType = empty( $sType ) ? ( $this->loadWp()->isMultisite() ? 'wpms' : 'wp' ) : 'wp';
|
152 |
$aOptions = $this->getRestrictedOptions();
|
153 |
+
return ( isset( $aOptions[ $sType.'_pages' ] ) && is_array( $aOptions[ $sType.'_pages' ] ) ) ? $aOptions[ $sType.'_pages' ] : array();
|
154 |
}
|
155 |
|
156 |
/**
|
158 |
protected function setAdminAccessCookie() {
|
159 |
$sAccessKey = $this->getOpt( 'admin_access_key' );
|
160 |
if ( !empty( $sAccessKey ) ) {
|
161 |
+
$this->loadDP()
|
162 |
+
->setCookie(
|
163 |
+
$this->getSecurityAdminCookieName(),
|
164 |
+
md5( $sAccessKey ),
|
165 |
+
$this->getOpt( 'admin_access_timeout' )*60
|
166 |
+
);
|
|
|
|
|
167 |
}
|
168 |
}
|
169 |
|
170 |
/**
|
171 |
*/
|
172 |
protected function clearAdminAccessCookie() {
|
173 |
+
$this->loadDataProcessor()->setDeleteCookie( $this->getSecurityAdminCookieName() );
|
174 |
}
|
175 |
|
176 |
/**
|
186 |
/**
|
187 |
* @return string
|
188 |
*/
|
189 |
+
public function getSecurityAdminCookieName() {
|
190 |
+
return $this->getDefinition( 'security_admin_cookie_name' );
|
191 |
}
|
192 |
|
193 |
/**
|
250 |
protected function loadStrings_SectionTitles( $aOptionsParams ) {
|
251 |
|
252 |
$sSectionSlug = $aOptionsParams[ 'slug' ];
|
253 |
+
switch ( $sSectionSlug ) {
|
254 |
|
255 |
case 'section_enable_plugin_feature_admin_access_restriction' :
|
256 |
$sTitle = sprintf( _wpsf__( 'Enable Plugin Feature: %s' ), $this->getMainFeatureName() );
|
283 |
default:
|
284 |
throw new Exception( sprintf( 'A section slug was defined but with no associated strings. Slug: "%s".', $sSectionSlug ) );
|
285 |
}
|
286 |
+
$aOptionsParams[ 'title' ] = $sTitle;
|
287 |
+
$aOptionsParams[ 'summary' ] = ( isset( $aSummary ) && is_array( $aSummary ) ) ? $aSummary : array();
|
288 |
+
$aOptionsParams[ 'title_short' ] = $sTitleShort;
|
289 |
return $aOptionsParams;
|
290 |
}
|
291 |
|
296 |
*/
|
297 |
protected function loadStrings_Options( $aOptionsParams ) {
|
298 |
|
299 |
+
$sKey = $aOptionsParams[ 'key' ];
|
300 |
+
switch ( $sKey ) {
|
301 |
|
302 |
case 'enable_admin_access_restriction' :
|
303 |
$sName = sprintf( _wpsf__( 'Enable %s' ), _wpsf__( 'Security Admin' ) );
|
311 |
$sDescription = sprintf( _wpsf__( 'Careful: %s' ), _wpsf__( 'If you forget this, you could potentially lock yourself out from using this plugin.' ) );
|
312 |
break;
|
313 |
|
|
|
314 |
case 'admin_access_timeout' :
|
315 |
$sName = _wpsf__( 'Security Admin Timeout' );
|
316 |
$sSummary = _wpsf__( 'Specify An Automatic Timeout Interval For Security Admin Access' );
|
317 |
+
$sDescription = _wpsf__( 'This will automatically expire your Security Admin Session.' )
|
318 |
+
.' '._wpsf__( 'Does not apply until you enter the access key again.' )
|
319 |
+
.'<br />'.sprintf( _wpsf__( 'Default: %s minutes.' ), $this->getOptionsVo()
|
320 |
+
->getOptDefault( 'admin_access_timeout' ) );
|
321 |
break;
|
322 |
|
323 |
case 'admin_access_restrict_posts' :
|
324 |
$sName = _wpsf__( 'Pages' );
|
325 |
$sSummary = _wpsf__( 'Restrict Access To Key WordPress Posts And Pages Actions' );
|
326 |
$sDescription = sprintf( _wpsf__( 'Careful: %s' ), _wpsf__( 'This will restrict access to page/post creation, editing and deletion.' ) )
|
327 |
+
.'<br />'.sprintf( _wpsf__( 'Note: %s' ), sprintf( _wpsf__( 'Selecting "%s" will also restrict all other options.' ), _wpsf__( 'Edit' ) ) );
|
328 |
break;
|
329 |
|
330 |
case 'admin_access_restrict_plugins' :
|
331 |
$sName = _wpsf__( 'Plugins' );
|
332 |
$sSummary = _wpsf__( 'Restrict Access To Key WordPress Plugin Actions' );
|
333 |
$sDescription = sprintf( _wpsf__( 'Careful: %s' ), _wpsf__( 'This will restrict access to plugin installation, update, activation and deletion.' ) )
|
334 |
+
.'<br />'.sprintf( _wpsf__( 'Note: %s' ), sprintf( _wpsf__( 'Selecting "%s" will also restrict all other options.' ), _wpsf__( 'Activate' ) ) );
|
335 |
break;
|
336 |
|
337 |
case 'admin_access_restrict_options' :
|
356 |
sprintf(
|
357 |
_wpsf__( 'Selecting "%s" will also restrict all other options.' ),
|
358 |
sprintf(
|
359 |
+
_wpsf__( '%s and %s' ),
|
360 |
_wpsf__( 'Activate' ),
|
361 |
_wpsf__( 'Edit Theme Options' )
|
362 |
)
|
368 |
throw new Exception( sprintf( 'An option has been defined but without strings assigned to it. Option key: "%s".', $sKey ) );
|
369 |
}
|
370 |
|
371 |
+
$aOptionsParams[ 'name' ] = $sName;
|
372 |
+
$aOptionsParams[ 'summary' ] = $sSummary;
|
373 |
+
$aOptionsParams[ 'description' ] = $sDescription;
|
374 |
return $aOptionsParams;
|
375 |
}
|
376 |
|
393 |
if ( in_array( 'activate_plugins', $aPluginsRestrictions ) ) {
|
394 |
$this->setOpt(
|
395 |
'admin_access_restrict_plugins',
|
396 |
+
array_unique( array_merge( $aPluginsRestrictions, array(
|
397 |
+
'install_plugins',
|
398 |
+
'update_plugins',
|
399 |
+
'delete_plugins'
|
400 |
+
) ) )
|
401 |
);
|
402 |
}
|
403 |
|
406 |
if ( in_array( 'switch_themes', $aThemesRestrictions ) && in_array( 'edit_theme_options', $aThemesRestrictions ) ) {
|
407 |
$this->setOpt(
|
408 |
'admin_access_restrict_themes',
|
409 |
+
array_unique( array_merge( $aThemesRestrictions, array(
|
410 |
+
'install_themes',
|
411 |
+
'update_themes',
|
412 |
+
'delete_themes'
|
413 |
+
) ) )
|
414 |
);
|
415 |
}
|
416 |
|
422 |
);
|
423 |
}
|
424 |
}
|
425 |
+
}
|
|
src/features/base.php
CHANGED
@@ -70,6 +70,11 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
70 |
*/
|
71 |
protected $oProcessor;
|
72 |
|
|
|
|
|
|
|
|
|
|
|
73 |
/**
|
74 |
* @var string
|
75 |
*/
|
@@ -101,7 +106,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
101 |
|
102 |
$nRunPriority = isset( $aFeatureProperties[ 'load_priority' ] ) ? $aFeatureProperties[ 'load_priority' ] : 100;
|
103 |
// Handle any upgrades as necessary (only go near this if it's the admin area)
|
104 |
-
add_action( '
|
105 |
add_action( 'init', array( $this, 'onWpInit' ), 1 );
|
106 |
add_action( $this->prefix( 'import_options' ), array( $this, 'processImportOptions' ) );
|
107 |
add_action( $this->prefix( 'form_submit' ), array( $this, 'handleFormSubmit' ) );
|
@@ -185,9 +190,8 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
185 |
}
|
186 |
|
187 |
/**
|
188 |
-
* Added to WordPress 'plugins_loaded' hook
|
189 |
*/
|
190 |
-
public function
|
191 |
$this->getOptionsVo()
|
192 |
->setIsPremiumLicensed( $this->isPremium() );
|
193 |
|
@@ -242,6 +246,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
242 |
* A action added to WordPress 'init' hook
|
243 |
*/
|
244 |
public function onWpInit() {
|
|
|
245 |
$this->updateHandler();
|
246 |
$this->setupAjaxHandlers();
|
247 |
}
|
@@ -272,6 +277,15 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
272 |
str_replace( ' ', '', ucwords( str_replace( '_', ' ', $this->getFeatureSlug() ) ) );
|
273 |
}
|
274 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
275 |
/**
|
276 |
* @return ICWP_WPSF_OptionsVO
|
277 |
*/
|
@@ -343,7 +357,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
343 |
/**
|
344 |
* @return string
|
345 |
*/
|
346 |
-
public function
|
347 |
return $this->loadWp()
|
348 |
->getUrl_AdminPage(
|
349 |
$this->prefix( $this->getFeatureSlug() ),
|
@@ -683,16 +697,16 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
683 |
$oDp = $this->loadDataProcessor();
|
684 |
|
685 |
$bValid = $this->loadWp()->isAjax()
|
686 |
-
&& ( $this->prefix( $this->getFeatureSlug() ) == $oDp->
|
687 |
if ( $bValid ) {
|
688 |
$aItems = array_keys( $this->getBaseAjaxActionRenderData() );
|
689 |
foreach ( $aItems as $sKey ) {
|
690 |
if ( strpos( $sKey, 'icwp_' ) === 0 ) {
|
691 |
-
$bValid = $bValid && ( strlen( $oDp->
|
692 |
}
|
693 |
}
|
694 |
}
|
695 |
-
return $bValid && $this->checkNonceAction( $oDp->
|
696 |
}
|
697 |
|
698 |
/**
|
@@ -714,6 +728,21 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
714 |
|
715 |
protected function adminAjaxHandlers() {
|
716 |
add_action( 'wp_ajax_icwp_OptionsFormSave', array( $this, 'ajaxOptionsFormSave' ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
717 |
}
|
718 |
|
719 |
protected function frontEndAjaxHandlers() {
|
@@ -775,6 +804,21 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
775 |
return $sDefault;
|
776 |
}
|
777 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
778 |
/**
|
779 |
* @param $bSuccess
|
780 |
* @param array $aData
|
@@ -884,7 +928,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
884 |
}
|
885 |
|
886 |
$aOptParams[ 'rows' ] = count( $mCurrentVal ) + 2;
|
887 |
-
$mCurrentVal = implode( "\n", $mCurrentVal );
|
888 |
|
889 |
break;
|
890 |
|
@@ -1137,6 +1181,31 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
1137 |
protected function updateHandler() {
|
1138 |
}
|
1139 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1140 |
/**
|
1141 |
* @return boolean
|
1142 |
*/
|
@@ -1263,9 +1332,15 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
1263 |
'show_standard_options' => true,
|
1264 |
'show_content_actions' => $this->hasCustomActions(),
|
1265 |
'show_alt_content' => false,
|
|
|
|
|
1266 |
),
|
1267 |
'hrefs' => array(
|
1268 |
-
'go_pro'
|
|
|
|
|
|
|
|
|
1269 |
),
|
1270 |
'content' => array(
|
1271 |
'alt' => '',
|
@@ -1284,11 +1359,72 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
1284 |
return '<h3 style="margin: 10px 0 100px">'._wpsf__( 'No Actions For This Module' ).'</h3>';
|
1285 |
}
|
1286 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1287 |
/**
|
1288 |
* @return string
|
1289 |
*/
|
1290 |
protected function getContentHelp() {
|
1291 |
-
return $this->renderTemplate( 'snippets/module-help-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1292 |
}
|
1293 |
|
1294 |
/**
|
70 |
*/
|
71 |
protected $oProcessor;
|
72 |
|
73 |
+
/**
|
74 |
+
* @var ICWP_WPSF_Wizard_Base
|
75 |
+
*/
|
76 |
+
protected $oWizard;
|
77 |
+
|
78 |
/**
|
79 |
* @var string
|
80 |
*/
|
106 |
|
107 |
$nRunPriority = isset( $aFeatureProperties[ 'load_priority' ] ) ? $aFeatureProperties[ 'load_priority' ] : 100;
|
108 |
// Handle any upgrades as necessary (only go near this if it's the admin area)
|
109 |
+
add_action( $this->prefix( 'run_processors' ), array( $this, 'onRunProcessors' ), $nRunPriority );
|
110 |
add_action( 'init', array( $this, 'onWpInit' ), 1 );
|
111 |
add_action( $this->prefix( 'import_options' ), array( $this, 'processImportOptions' ) );
|
112 |
add_action( $this->prefix( 'form_submit' ), array( $this, 'handleFormSubmit' ) );
|
190 |
}
|
191 |
|
192 |
/**
|
|
|
193 |
*/
|
194 |
+
public function onRunProcessors() {
|
195 |
$this->getOptionsVo()
|
196 |
->setIsPremiumLicensed( $this->isPremium() );
|
197 |
|
246 |
* A action added to WordPress 'init' hook
|
247 |
*/
|
248 |
public function onWpInit() {
|
249 |
+
$this->runWizards();
|
250 |
$this->updateHandler();
|
251 |
$this->setupAjaxHandlers();
|
252 |
}
|
277 |
str_replace( ' ', '', ucwords( str_replace( '_', ' ', $this->getFeatureSlug() ) ) );
|
278 |
}
|
279 |
|
280 |
+
/**
|
281 |
+
* Override this and adapt per feature
|
282 |
+
* @return string
|
283 |
+
*/
|
284 |
+
protected function getWizardClassName() {
|
285 |
+
return ucwords( self::getConn()->getOptionStoragePrefix() ).'Wizard_'.
|
286 |
+
str_replace( ' ', '', ucwords( str_replace( '_', ' ', $this->getFeatureSlug() ) ) );
|
287 |
+
}
|
288 |
+
|
289 |
/**
|
290 |
* @return ICWP_WPSF_OptionsVO
|
291 |
*/
|
357 |
/**
|
358 |
* @return string
|
359 |
*/
|
360 |
+
public function getUrl_AdminPage() {
|
361 |
return $this->loadWp()
|
362 |
->getUrl_AdminPage(
|
363 |
$this->prefix( $this->getFeatureSlug() ),
|
697 |
$oDp = $this->loadDataProcessor();
|
698 |
|
699 |
$bValid = $this->loadWp()->isAjax()
|
700 |
+
&& ( $this->prefix( $this->getFeatureSlug() ) == $oDp->post( 'icwp_action_module', '' ) );
|
701 |
if ( $bValid ) {
|
702 |
$aItems = array_keys( $this->getBaseAjaxActionRenderData() );
|
703 |
foreach ( $aItems as $sKey ) {
|
704 |
if ( strpos( $sKey, 'icwp_' ) === 0 ) {
|
705 |
+
$bValid = $bValid && ( strlen( $oDp->post( $sKey, '' ) ) > 0 );
|
706 |
}
|
707 |
}
|
708 |
}
|
709 |
+
return $bValid && $this->checkNonceAction( $oDp->post( 'icwp_nonce' ), $oDp->post( 'icwp_nonce_action' ) );
|
710 |
}
|
711 |
|
712 |
/**
|
728 |
|
729 |
protected function adminAjaxHandlers() {
|
730 |
add_action( 'wp_ajax_icwp_OptionsFormSave', array( $this, 'ajaxOptionsFormSave' ) );
|
731 |
+
|
732 |
+
// TODO: move this to the wizard handler itself
|
733 |
+
if ( $this->getCanRunWizards() && $this->hasWizard() ) {
|
734 |
+
$oWiz = $this->getWizardHandler();
|
735 |
+
if ( !is_null( $oWiz ) ) {
|
736 |
+
add_action( $this->prefixWpAjax( 'WizardProcessStepSubmit' ), array(
|
737 |
+
$oWiz,
|
738 |
+
'ajaxWizardProcessStepSubmit'
|
739 |
+
) );
|
740 |
+
add_action( $this->prefixWpAjax( 'WizardRenderStep' ), array(
|
741 |
+
$oWiz,
|
742 |
+
'ajaxWizardRenderStep'
|
743 |
+
) );
|
744 |
+
}
|
745 |
+
}
|
746 |
}
|
747 |
|
748 |
protected function frontEndAjaxHandlers() {
|
804 |
return $sDefault;
|
805 |
}
|
806 |
|
807 |
+
/**
|
808 |
+
* @return ICWP_WPSF_Wizard_Base|null
|
809 |
+
*/
|
810 |
+
protected function getWizardHandler() {
|
811 |
+
if ( !isset( $this->oWizard ) ) {
|
812 |
+
include_once( self::getConn()->getPath_SourceFile( sprintf( 'wizards/%s.php', $this->getFeatureSlug() ) ) );
|
813 |
+
$sClassName = $this->getWizardClassName();
|
814 |
+
if ( !class_exists( $sClassName, false ) ) {
|
815 |
+
return null;
|
816 |
+
}
|
817 |
+
$this->oWizard = new $sClassName( $this );
|
818 |
+
}
|
819 |
+
return $this->oWizard;
|
820 |
+
}
|
821 |
+
|
822 |
/**
|
823 |
* @param $bSuccess
|
824 |
* @param array $aData
|
928 |
}
|
929 |
|
930 |
$aOptParams[ 'rows' ] = count( $mCurrentVal ) + 2;
|
931 |
+
$mCurrentVal = stripslashes( implode( "\n", $mCurrentVal ) );
|
932 |
|
933 |
break;
|
934 |
|
1181 |
protected function updateHandler() {
|
1182 |
}
|
1183 |
|
1184 |
+
/**
|
1185 |
+
*/
|
1186 |
+
protected function runWizards() {
|
1187 |
+
if ( $this->getCanRunWizards() && $this->isWizardPage() && $this->hasWizard() ) {
|
1188 |
+
$oWiz = $this->getWizardHandler();
|
1189 |
+
if ( $oWiz instanceof ICWP_WPSF_Wizard_Base ) {
|
1190 |
+
$oWiz->init();
|
1191 |
+
}
|
1192 |
+
}
|
1193 |
+
}
|
1194 |
+
|
1195 |
+
/**
|
1196 |
+
* @return bool
|
1197 |
+
*/
|
1198 |
+
protected function isModulePage() {
|
1199 |
+
return $this->loadDP()->query( 'page' ) == $this->prefix( $this->getFeatureSlug() );
|
1200 |
+
}
|
1201 |
+
|
1202 |
+
/**
|
1203 |
+
* @return bool
|
1204 |
+
*/
|
1205 |
+
protected function isWizardPage() {
|
1206 |
+
return ( $this->loadDP()->query( 'shield_action' ) == 'wizard' && $this->isModulePage() );
|
1207 |
+
}
|
1208 |
+
|
1209 |
/**
|
1210 |
* @return boolean
|
1211 |
*/
|
1332 |
'show_standard_options' => true,
|
1333 |
'show_content_actions' => $this->hasCustomActions(),
|
1334 |
'show_alt_content' => false,
|
1335 |
+
'can_wizard' => $this->getCanRunWizards(),
|
1336 |
+
'has_wizard' => $this->hasWizard(),
|
1337 |
),
|
1338 |
'hrefs' => array(
|
1339 |
+
'go_pro' => 'http://icwp.io/shieldgoprofeature',
|
1340 |
+
'img_wizard_wand' => $oCon->getPluginUrl_Image( 'wand.png' ),
|
1341 |
+
'wizard_link' => $this->getUrl_WizardLanding(),
|
1342 |
+
'wizard_landing' => $this->getUrl_WizardLanding(),
|
1343 |
+
'primary_wizard' => $this->getUrl_WizardPrimary(),
|
1344 |
),
|
1345 |
'content' => array(
|
1346 |
'alt' => '',
|
1359 |
return '<h3 style="margin: 10px 0 100px">'._wpsf__( 'No Actions For This Module' ).'</h3>';
|
1360 |
}
|
1361 |
|
1362 |
+
/**
|
1363 |
+
* @return bool
|
1364 |
+
*/
|
1365 |
+
public function getCanRunWizards() {
|
1366 |
+
return $this->loadDP()->getPhpVersionIsAtLeast( '5.4.0' );
|
1367 |
+
}
|
1368 |
+
|
1369 |
/**
|
1370 |
* @return string
|
1371 |
*/
|
1372 |
protected function getContentHelp() {
|
1373 |
+
return $this->renderTemplate( 'snippets/module-help-template.php', array( 'slug' => $this->getFeatureSlug() ) );
|
1374 |
+
}
|
1375 |
+
|
1376 |
+
/**
|
1377 |
+
* @return string|null
|
1378 |
+
*/
|
1379 |
+
protected function getPrimaryWizard() {
|
1380 |
+
return $this->hasWizard() ? key( $this->getWizardDefinitions() ) : null;
|
1381 |
+
}
|
1382 |
+
|
1383 |
+
/**
|
1384 |
+
* @uses nonce
|
1385 |
+
* @param string $sWizardSlug
|
1386 |
+
* @return string
|
1387 |
+
*/
|
1388 |
+
public function getUrl_Wizard( $sWizardSlug ) {
|
1389 |
+
return add_query_arg(
|
1390 |
+
array(
|
1391 |
+
'page' => $this->prefix( $this->getFeatureSlug() ),
|
1392 |
+
'shield_action' => 'wizard',
|
1393 |
+
'wizard' => $sWizardSlug,
|
1394 |
+
'nonwizard' => wp_create_nonce( 'wizard'.$sWizardSlug )
|
1395 |
+
),
|
1396 |
+
$this->loadWp()->getHomeUrl()
|
1397 |
+
);
|
1398 |
+
}
|
1399 |
+
|
1400 |
+
/**
|
1401 |
+
* @return string
|
1402 |
+
*/
|
1403 |
+
protected function getUrl_WizardLanding() {
|
1404 |
+
return $this->getUrl_Wizard( 'landing' );
|
1405 |
+
}
|
1406 |
+
|
1407 |
+
/**
|
1408 |
+
* @return string
|
1409 |
+
*/
|
1410 |
+
protected function getUrl_WizardPrimary() {
|
1411 |
+
$sPrimary = $this->getPrimaryWizard();
|
1412 |
+
return $this->getUrl_Wizard( $sPrimary );
|
1413 |
+
}
|
1414 |
+
|
1415 |
+
/**
|
1416 |
+
* @return array
|
1417 |
+
*/
|
1418 |
+
public function getWizardDefinitions() {
|
1419 |
+
$aW = $this->getDefinition( 'wizards' );
|
1420 |
+
return is_array( $aW ) ? $aW : array();
|
1421 |
+
}
|
1422 |
+
|
1423 |
+
/**
|
1424 |
+
* @return bool
|
1425 |
+
*/
|
1426 |
+
public function hasWizard() {
|
1427 |
+
return ( count( $this->getWizardDefinitions() ) > 0 );
|
1428 |
}
|
1429 |
|
1430 |
/**
|
src/features/base_wpsf.php
CHANGED
@@ -8,13 +8,6 @@ require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'base.php' );
|
|
8 |
|
9 |
class ICWP_WPSF_FeatureHandler_BaseWpsf extends ICWP_WPSF_FeatureHandler_Base {
|
10 |
|
11 |
-
/**
|
12 |
-
* @return bool
|
13 |
-
*/
|
14 |
-
public function getCanRunWizards() {
|
15 |
-
return $this->loadDP()->getPhpVersionIsAtLeast( '5.4.0' );
|
16 |
-
}
|
17 |
-
|
18 |
/**
|
19 |
* @return array
|
20 |
*/
|
@@ -95,7 +88,7 @@ class ICWP_WPSF_FeatureHandler_BaseWpsf extends ICWP_WPSF_FeatureHandler_Base {
|
|
95 |
'aar_must_supply_key_first' => _wpsf__( 'At some point you entered a Security Admin Access Key - to manage this plugin, you must supply it here first.' ),
|
96 |
'aar_to_manage_must_enter_key' => _wpsf__( 'To manage this plugin you must enter the access key.' ),
|
97 |
'aar_enter_access_key' => _wpsf__( 'Enter Access Key' ),
|
98 |
-
'aar_submit_access_key' => _wpsf__( 'Submit
|
99 |
)
|
100 |
);
|
101 |
$aData[ 'flags' ][ 'show_summary' ] = true;
|
@@ -110,20 +103,6 @@ class ICWP_WPSF_FeatureHandler_BaseWpsf extends ICWP_WPSF_FeatureHandler_Base {
|
|
110 |
return ( isset( $aStrings[ $sKey ] ) ? $aStrings[ $sKey ] : $sDefault );
|
111 |
}
|
112 |
|
113 |
-
/**
|
114 |
-
* @param string $sWizardSlug
|
115 |
-
* @return string
|
116 |
-
*/
|
117 |
-
public function getWizardUrl( $sWizardSlug ) {
|
118 |
-
return add_query_arg(
|
119 |
-
array(
|
120 |
-
'shield_action' => 'wizard',
|
121 |
-
'wizard' => $sWizardSlug
|
122 |
-
),
|
123 |
-
$this->getFeatureAdminPageUrl()
|
124 |
-
);
|
125 |
-
}
|
126 |
-
|
127 |
/**
|
128 |
* @return bool
|
129 |
*/
|
8 |
|
9 |
class ICWP_WPSF_FeatureHandler_BaseWpsf extends ICWP_WPSF_FeatureHandler_Base {
|
10 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
/**
|
12 |
* @return array
|
13 |
*/
|
88 |
'aar_must_supply_key_first' => _wpsf__( 'At some point you entered a Security Admin Access Key - to manage this plugin, you must supply it here first.' ),
|
89 |
'aar_to_manage_must_enter_key' => _wpsf__( 'To manage this plugin you must enter the access key.' ),
|
90 |
'aar_enter_access_key' => _wpsf__( 'Enter Access Key' ),
|
91 |
+
'aar_submit_access_key' => _wpsf__( 'Submit Security Admin Key' )
|
92 |
)
|
93 |
);
|
94 |
$aData[ 'flags' ][ 'show_summary' ] = true;
|
103 |
return ( isset( $aStrings[ $sKey ] ) ? $aStrings[ $sKey ] : $sDefault );
|
104 |
}
|
105 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
106 |
/**
|
107 |
* @return bool
|
108 |
*/
|
src/features/hack_protect.php
CHANGED
@@ -15,6 +15,14 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
|
|
15 |
return $this->getOpt( 'enable_unrecognised_file_cleaner_scan', 'disabled' );
|
16 |
}
|
17 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
/**
|
19 |
* @return array
|
20 |
*/
|
@@ -26,6 +34,17 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
|
|
26 |
return $aExclusions;
|
27 |
}
|
28 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
/**
|
30 |
*/
|
31 |
protected function doExtraSubmitProcessing() {
|
@@ -42,7 +61,10 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
|
|
42 |
foreach ( $this->getUfcFileExclusions() as $nKey => $sExclusion ) {
|
43 |
$sExclusion = $oFS->normalizeFilePathDS( trim( $sExclusion ) );
|
44 |
|
45 |
-
if (
|
|
|
|
|
|
|
46 |
$sExclusion = trim( preg_replace( '#[^\.0-9a-z_-]#i', '', $sExclusion ) );
|
47 |
}
|
48 |
|
@@ -51,7 +73,7 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
|
|
51 |
}
|
52 |
}
|
53 |
|
54 |
-
return $this->setOpt( 'ufc_exclusions', $aExclusions );
|
55 |
}
|
56 |
|
57 |
/**
|
@@ -88,6 +110,36 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
|
|
88 |
) );
|
89 |
}
|
90 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
/**
|
92 |
* @param int $nId
|
93 |
* @return $this
|
15 |
return $this->getOpt( 'enable_unrecognised_file_cleaner_scan', 'disabled' );
|
16 |
}
|
17 |
|
18 |
+
/**
|
19 |
+
* @param string $sOption
|
20 |
+
* @return $this
|
21 |
+
*/
|
22 |
+
public function setUfcOption( $sOption ) {
|
23 |
+
return $this->setOpt( 'enable_unrecognised_file_cleaner_scan', $sOption );
|
24 |
+
}
|
25 |
+
|
26 |
/**
|
27 |
* @return array
|
28 |
*/
|
34 |
return $aExclusions;
|
35 |
}
|
36 |
|
37 |
+
/**
|
38 |
+
* @param array $aExclusions
|
39 |
+
* @return $this
|
40 |
+
*/
|
41 |
+
public function setUfcFileExclusions( $aExclusions ) {
|
42 |
+
if ( !is_array( $aExclusions ) ) {
|
43 |
+
$aExclusions = array();
|
44 |
+
}
|
45 |
+
return $this->setOpt( 'ufc_exclusions', array_filter( array_map( 'trim', $aExclusions ) ) );
|
46 |
+
}
|
47 |
+
|
48 |
/**
|
49 |
*/
|
50 |
protected function doExtraSubmitProcessing() {
|
61 |
foreach ( $this->getUfcFileExclusions() as $nKey => $sExclusion ) {
|
62 |
$sExclusion = $oFS->normalizeFilePathDS( trim( $sExclusion ) );
|
63 |
|
64 |
+
if ( preg_match( '/^#(.+)#$/', $sExclusion, $aMatches ) ) { // it's regex
|
65 |
+
// ignore it
|
66 |
+
}
|
67 |
+
else if ( strpos( $sExclusion, '/' ) === false ) { // filename only
|
68 |
$sExclusion = trim( preg_replace( '#[^\.0-9a-z_-]#i', '', $sExclusion ) );
|
69 |
}
|
70 |
|
73 |
}
|
74 |
}
|
75 |
|
76 |
+
return $this->setOpt( 'ufc_exclusions', array_unique( $aExclusions ) );
|
77 |
}
|
78 |
|
79 |
/**
|
110 |
) );
|
111 |
}
|
112 |
|
113 |
+
/**
|
114 |
+
* @return bool
|
115 |
+
*/
|
116 |
+
public function isWcfScanAutoRepair() {
|
117 |
+
return $this->getOptIs( 'attempt_auto_file_repair', 'Y' );
|
118 |
+
}
|
119 |
+
|
120 |
+
/**
|
121 |
+
* @return bool
|
122 |
+
*/
|
123 |
+
public function isWcfScanEnabled() {
|
124 |
+
return $this->getOptIs( 'enable_core_file_integrity_scan', 'Y' );
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* @param bool $bEnabled
|
129 |
+
* @return $this
|
130 |
+
*/
|
131 |
+
public function setWcfScanEnabled( $bEnabled ) {
|
132 |
+
return $this->setOpt( 'enable_core_file_integrity_scan', $bEnabled ? 'Y' : 'N' );
|
133 |
+
}
|
134 |
+
|
135 |
+
/**
|
136 |
+
* @param bool $bEnabled
|
137 |
+
* @return $this
|
138 |
+
*/
|
139 |
+
public function setWcfScanAutoRepair( $bEnabled ) {
|
140 |
+
return $this->setOpt( 'attempt_auto_file_repair', $bEnabled ? 'Y' : 'N' );
|
141 |
+
}
|
142 |
+
|
143 |
/**
|
144 |
* @param int $nId
|
145 |
* @return $this
|
src/features/license.php
CHANGED
@@ -442,7 +442,7 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
|
|
442 |
* @return bool
|
443 |
*/
|
444 |
protected function isLastCheckExpired() {
|
445 |
-
return ( $this->
|
446 |
> $this->getDefinition( 'license_lack_check_expire_days' )*DAY_IN_SECONDS*( mt_rand( 20, 30 )/10 ) );
|
447 |
}
|
448 |
|
442 |
* @return bool
|
443 |
*/
|
444 |
protected function isLastCheckExpired() {
|
445 |
+
return ( $this->loadDP()->time() - $this->getLicenseLastCheckedAt()
|
446 |
> $this->getDefinition( 'license_lack_check_expire_days' )*DAY_IN_SECONDS*( mt_rand( 20, 30 )/10 ) );
|
447 |
}
|
448 |
|
src/features/login_protect.php
CHANGED
@@ -14,12 +14,11 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
|
|
14 |
public function onWpInit() {
|
15 |
parent::onWpInit();
|
16 |
|
17 |
-
$oDp = $this->
|
18 |
// User has clicked a link in their email to verify they can send email.
|
19 |
-
if ( $oDp->
|
20 |
-
if ( $
|
21 |
$this->setIfCanSendEmail( true )
|
22 |
-
->setBypassAdminProtection( true )
|
23 |
->savePluginOptions();
|
24 |
$this->loadWp()->redirectToLogin();
|
25 |
}
|
@@ -91,20 +90,32 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
|
|
91 |
}
|
92 |
|
93 |
/**
|
|
|
|
|
94 |
* @return boolean
|
95 |
*/
|
96 |
-
public function sendEmailVerifyCanSend() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
97 |
|
98 |
$aMessage = array(
|
99 |
_wpsf__( 'Before enabling 2-factor email authentication for your WordPress site, you must verify you can receive this email.' ),
|
100 |
_wpsf__( 'This verifies your website can send email and that your account can receive emails sent from your site.' ),
|
101 |
-
sprintf( _wpsf__( 'Verify
|
102 |
);
|
103 |
-
$sEmailSubject = sprintf( _wpsf__( 'Email Sending Verification For %s' ), $this->loadWp()
|
104 |
-
->getHomeUrl() );
|
105 |
|
106 |
$bResult = $this->getEmailProcessor()
|
107 |
-
->sendEmailTo(
|
108 |
return $bResult;
|
109 |
}
|
110 |
|
@@ -180,6 +191,13 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
|
|
180 |
return $this->prefix( $this->getDefinition( 'two_factor_auth_table_name' ), '_' );
|
181 |
}
|
182 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
183 |
/**
|
184 |
* @return string
|
185 |
*/
|
@@ -207,6 +225,13 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
|
|
207 |
return $this->getIfCanSendEmail() && $this->getIsEmailAuthenticationOptionOn();
|
208 |
}
|
209 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
210 |
/**
|
211 |
* @return bool
|
212 |
*/
|
@@ -253,6 +278,14 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
|
|
253 |
return $this->getOptIs( 'enable_chained_authentication', 'Y' );
|
254 |
}
|
255 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
256 |
/**
|
257 |
* @param bool $bCan
|
258 |
* @return $this
|
@@ -269,6 +302,22 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
|
|
269 |
return $this;
|
270 |
}
|
271 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
272 |
/**
|
273 |
* @return string
|
274 |
*/
|
14 |
public function onWpInit() {
|
15 |
parent::onWpInit();
|
16 |
|
17 |
+
$oDp = $this->loadDP();
|
18 |
// User has clicked a link in their email to verify they can send email.
|
19 |
+
if ( $oDp->query( 'wpsf-action' ) == 'emailsendverify' ) {
|
20 |
+
if ( $oDp->query( 'authkey' ) == $this->getCanEmailVerifyCode() ) {
|
21 |
$this->setIfCanSendEmail( true )
|
|
|
22 |
->savePluginOptions();
|
23 |
$this->loadWp()->redirectToLogin();
|
24 |
}
|
90 |
}
|
91 |
|
92 |
/**
|
93 |
+
* @param string $sEmail
|
94 |
+
* @param bool $bSendAsLink
|
95 |
* @return boolean
|
96 |
*/
|
97 |
+
public function sendEmailVerifyCanSend( $sEmail = null, $bSendAsLink = true ) {
|
98 |
+
|
99 |
+
if ( !$this->loadDP()->validEmail( $sEmail ) ) {
|
100 |
+
$sEmail = get_bloginfo( 'admin_email' );
|
101 |
+
}
|
102 |
+
|
103 |
+
if ( $bSendAsLink ) {
|
104 |
+
$sVerify = $this->generateCanSendEmailVerifyLink();
|
105 |
+
}
|
106 |
+
else {
|
107 |
+
$sVerify = $this->getCanEmailVerifyCode();
|
108 |
+
}
|
109 |
|
110 |
$aMessage = array(
|
111 |
_wpsf__( 'Before enabling 2-factor email authentication for your WordPress site, you must verify you can receive this email.' ),
|
112 |
_wpsf__( 'This verifies your website can send email and that your account can receive emails sent from your site.' ),
|
113 |
+
sprintf( _wpsf__( 'Verify Code: %s' ), $sVerify ),
|
114 |
);
|
115 |
+
$sEmailSubject = sprintf( _wpsf__( 'Email Sending Verification For %s' ), $this->loadWp()->getHomeUrl() );
|
|
|
116 |
|
117 |
$bResult = $this->getEmailProcessor()
|
118 |
+
->sendEmailTo( $sEmail, $sEmailSubject, $aMessage );
|
119 |
return $bResult;
|
120 |
}
|
121 |
|
191 |
return $this->prefix( $this->getDefinition( 'two_factor_auth_table_name' ), '_' );
|
192 |
}
|
193 |
|
194 |
+
/**
|
195 |
+
* @return string
|
196 |
+
*/
|
197 |
+
public function getCanEmailVerifyCode() {
|
198 |
+
return strtoupper( substr( $this->getTwoAuthSecretKey(), 4, 6 ) );
|
199 |
+
}
|
200 |
+
|
201 |
/**
|
202 |
* @return string
|
203 |
*/
|
225 |
return $this->getIfCanSendEmail() && $this->getIsEmailAuthenticationOptionOn();
|
226 |
}
|
227 |
|
228 |
+
/**
|
229 |
+
* @return bool
|
230 |
+
*/
|
231 |
+
public function getIsEnabledGoogleAuthenticator() {
|
232 |
+
return $this->getOptIs( 'enable_google_authenticator', 'Y' );
|
233 |
+
}
|
234 |
+
|
235 |
/**
|
236 |
* @return bool
|
237 |
*/
|
278 |
return $this->getOptIs( 'enable_chained_authentication', 'Y' );
|
279 |
}
|
280 |
|
281 |
+
/**
|
282 |
+
* @param bool $bIsChained
|
283 |
+
* @return $this
|
284 |
+
*/
|
285 |
+
public function setIsChainedAuth( $bIsChained ) {
|
286 |
+
return $this->setOpt( 'enable_chained_authentication', $bIsChained ? 'Y' : 'N' );
|
287 |
+
}
|
288 |
+
|
289 |
/**
|
290 |
* @param bool $bCan
|
291 |
* @return $this
|
302 |
return $this;
|
303 |
}
|
304 |
|
305 |
+
/**
|
306 |
+
* @param bool $bCan
|
307 |
+
* @return $this
|
308 |
+
*/
|
309 |
+
public function setEnabled2FaEmail( $bCan ) {
|
310 |
+
return $this->setOpt( 'enable_email_authentication', $bCan ? 'Y' : 'N' );
|
311 |
+
}
|
312 |
+
|
313 |
+
/**
|
314 |
+
* @param bool $bCan
|
315 |
+
* @return $this
|
316 |
+
*/
|
317 |
+
public function setEnabled2FaGoogleAuthenticator( $bCan ) {
|
318 |
+
return $this->setOpt( 'enable_google_authenticator', $bCan ? 'Y' : 'N' );
|
319 |
+
}
|
320 |
+
|
321 |
/**
|
322 |
* @return string
|
323 |
*/
|
src/features/plugin.php
CHANGED
@@ -28,22 +28,6 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
|
|
28 |
$this->getImportExportSecretKey();
|
29 |
}
|
30 |
|
31 |
-
protected function adminAjaxHandlers() {
|
32 |
-
parent::adminAjaxHandlers();
|
33 |
-
|
34 |
-
$oWizProc = $this->getWizardProcessor();
|
35 |
-
if ( !is_null( $oWizProc ) ) {
|
36 |
-
add_action( $this->prefixWpAjax( 'SetupWizardContent' ), array(
|
37 |
-
$this->getWizardProcessor(),
|
38 |
-
'ajaxSetupWizardContent'
|
39 |
-
) );
|
40 |
-
add_action( $this->prefixWpAjax( 'SetupWizardSteps' ), array(
|
41 |
-
$this->getWizardProcessor(),
|
42 |
-
'ajaxSetupWizardSteps'
|
43 |
-
) );
|
44 |
-
}
|
45 |
-
}
|
46 |
-
|
47 |
/**
|
48 |
* @return string
|
49 |
*/
|
@@ -59,8 +43,8 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
|
|
59 |
$aData = array(
|
60 |
'strings' => $this->getDisplayStrings(),
|
61 |
'hrefs' => array(
|
62 |
-
'wizard_welcome' => $bCanWizardWelcome ? $this->
|
63 |
-
'wizard_import' => $bCanWizardImport ? $this->
|
64 |
),
|
65 |
'flags' => array(
|
66 |
'can_php54' => $bCanWizard,
|
@@ -74,18 +58,6 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
|
|
74 |
return $this->renderTemplate( 'snippets/module-plugin-actions', $aData );
|
75 |
}
|
76 |
|
77 |
-
/**
|
78 |
-
* @return ICWP_WPSF_Processor_Plugin_SetupWizard|null
|
79 |
-
*/
|
80 |
-
protected function getWizardProcessor() {
|
81 |
-
if ( $this->loadDP()->getPhpVersionIsAtLeast( 5.4 ) ) {
|
82 |
-
/** @var ICWP_WPSF_Processor_Plugin $oP */
|
83 |
-
$oP = $this->getProcessor();
|
84 |
-
return $oP->getWizardProcessor();
|
85 |
-
}
|
86 |
-
return null;
|
87 |
-
}
|
88 |
-
|
89 |
/**
|
90 |
* @return ICWP_WPSF_Processor_Plugin_ImportExport
|
91 |
*/
|
@@ -149,7 +121,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
|
|
149 |
protected function setVisitorIp() {
|
150 |
$sIp = null;
|
151 |
$oIpService = $this->loadIpService();
|
152 |
-
$oDp = $this->
|
153 |
|
154 |
if ( !$this->isVisitorAddressSourceAutoDetect() ) {
|
155 |
|
@@ -168,8 +140,8 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
|
|
168 |
$sSource = $oIpService->setServerIpAddress( $this->getMyServerIp() )
|
169 |
->discoverViableRequestIpSource();
|
170 |
if ( !empty( $sSource ) ) {
|
171 |
-
$oIpService->setRequestIpAddress( $
|
172 |
-
$this->
|
173 |
}
|
174 |
}
|
175 |
}
|
@@ -181,6 +153,14 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
|
|
181 |
return $this->getOpt( 'visitor_address_source' );
|
182 |
}
|
183 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
184 |
/**
|
185 |
* @return string
|
186 |
*/
|
@@ -643,7 +623,13 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
|
|
643 |
)
|
644 |
);
|
645 |
$sBadgeText = apply_filters( 'icwp_shield_plugin_badge_text', $sBadgeText );
|
646 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
647 |
}
|
648 |
|
649 |
/**
|
28 |
$this->getImportExportSecretKey();
|
29 |
}
|
30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
31 |
/**
|
32 |
* @return string
|
33 |
*/
|
43 |
$aData = array(
|
44 |
'strings' => $this->getDisplayStrings(),
|
45 |
'hrefs' => array(
|
46 |
+
'wizard_welcome' => $bCanWizardWelcome ? $this->getUrl_Wizard( 'welcome' ) : 'javascript:{event.preventDefault();}',
|
47 |
+
'wizard_import' => $bCanWizardImport ? $this->getUrl_Wizard( 'import' ) : 'javascript:{event.preventDefault();}',
|
48 |
),
|
49 |
'flags' => array(
|
50 |
'can_php54' => $bCanWizard,
|
58 |
return $this->renderTemplate( 'snippets/module-plugin-actions', $aData );
|
59 |
}
|
60 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
61 |
/**
|
62 |
* @return ICWP_WPSF_Processor_Plugin_ImportExport
|
63 |
*/
|
121 |
protected function setVisitorIp() {
|
122 |
$sIp = null;
|
123 |
$oIpService = $this->loadIpService();
|
124 |
+
$oDp = $this->loadDP();
|
125 |
|
126 |
if ( !$this->isVisitorAddressSourceAutoDetect() ) {
|
127 |
|
140 |
$sSource = $oIpService->setServerIpAddress( $this->getMyServerIp() )
|
141 |
->discoverViableRequestIpSource();
|
142 |
if ( !empty( $sSource ) ) {
|
143 |
+
$oIpService->setRequestIpAddress( $oDp->FetchServer( $sSource ) );
|
144 |
+
$this->setVisitorAddressSource( $sSource );
|
145 |
}
|
146 |
}
|
147 |
}
|
153 |
return $this->getOpt( 'visitor_address_source' );
|
154 |
}
|
155 |
|
156 |
+
/**
|
157 |
+
* @param string $sSource
|
158 |
+
* @return $this
|
159 |
+
*/
|
160 |
+
public function setVisitorAddressSource( $sSource ) {
|
161 |
+
return $this->setOpt( 'visitor_address_source', $sSource );
|
162 |
+
}
|
163 |
+
|
164 |
/**
|
165 |
* @return string
|
166 |
*/
|
623 |
)
|
624 |
);
|
625 |
$sBadgeText = apply_filters( 'icwp_shield_plugin_badge_text', $sBadgeText );
|
626 |
+
$bNoFollow = apply_filters( 'icwp_shield_badge_relnofollow', false );
|
627 |
+
return sprintf( $sContents,
|
628 |
+
$bNoFollow ? 'rel="nofollow"' : '',
|
629 |
+
$oCon->getPluginUrl_Image( 'pluginlogo_32x32.png' ),
|
630 |
+
$oCon->getHumanName(),
|
631 |
+
$sBadgeText
|
632 |
+
);
|
633 |
}
|
634 |
|
635 |
/**
|
src/processors/admin_access_restriction.php
CHANGED
@@ -175,7 +175,7 @@ if ( !class_exists( 'ICWP_WPSF_Processor_AdminAccessRestriction', false ) ):
|
|
175 |
'hrefs' => array(
|
176 |
'setting_page' => sprintf(
|
177 |
'<a href="%s" title="%s">%s</a>',
|
178 |
-
$oFO->
|
179 |
_wpsf__( 'Admin Access Login' ),
|
180 |
sprintf( _wpsf__('Go here to manage settings and authenticate with the %s plugin.'), $this->getController()->getHumanName() )
|
181 |
)
|
@@ -210,7 +210,7 @@ if ( !class_exists( 'ICWP_WPSF_Processor_AdminAccessRestriction', false ) ):
|
|
210 |
'hrefs' => array(
|
211 |
'setting_page' => sprintf(
|
212 |
'<a href="%s" title="%s">%s</a>',
|
213 |
-
$oFO->
|
214 |
_wpsf__( 'Security Admin Login' ),
|
215 |
sprintf( _wpsf__('Go here to manage settings and authenticate with the %s plugin.'), $this->getController()->getHumanName() )
|
216 |
)
|
175 |
'hrefs' => array(
|
176 |
'setting_page' => sprintf(
|
177 |
'<a href="%s" title="%s">%s</a>',
|
178 |
+
$oFO->getUrl_AdminPage(),
|
179 |
_wpsf__( 'Admin Access Login' ),
|
180 |
sprintf( _wpsf__('Go here to manage settings and authenticate with the %s plugin.'), $this->getController()->getHumanName() )
|
181 |
)
|
210 |
'hrefs' => array(
|
211 |
'setting_page' => sprintf(
|
212 |
'<a href="%s" title="%s">%s</a>',
|
213 |
+
$oFO->getUrl_AdminPage(),
|
214 |
_wpsf__( 'Security Admin Login' ),
|
215 |
sprintf( _wpsf__('Go here to manage settings and authenticate with the %s plugin.'), $this->getController()->getHumanName() )
|
216 |
)
|
src/processors/base.php
CHANGED
@@ -122,7 +122,6 @@ abstract class ICWP_WPSF_Processor_Base extends ICWP_WPSF_Foundation {
|
|
122 |
}
|
123 |
|
124 |
/**
|
125 |
-
* Resets the object values to be re-used anew
|
126 |
*/
|
127 |
public function init() {
|
128 |
}
|
@@ -171,8 +170,8 @@ abstract class ICWP_WPSF_Processor_Base extends ICWP_WPSF_Foundation {
|
|
171 |
}
|
172 |
|
173 |
/**
|
174 |
-
* @param string
|
175 |
-
* @param mixed
|
176 |
* @param boolean $bStrict
|
177 |
* @return bool
|
178 |
*/
|
122 |
}
|
123 |
|
124 |
/**
|
|
|
125 |
*/
|
126 |
public function init() {
|
127 |
}
|
170 |
}
|
171 |
|
172 |
/**
|
173 |
+
* @param string $sKey
|
174 |
+
* @param mixed $mValueToTest
|
175 |
* @param boolean $bStrict
|
176 |
* @return bool
|
177 |
*/
|
src/processors/base_plugin.php
CHANGED
@@ -92,7 +92,7 @@ class ICWP_WPSF_Processor_BasePlugin extends ICWP_WPSF_Processor_BaseWpsf {
|
|
92 |
'no_setup' => _wpsf__( 'Unfortunately your site is running a PHP version that is too low to run the Setup Wizard. It needs to be PHP 5.4+' )
|
93 |
),
|
94 |
'hrefs' => array(
|
95 |
-
'wizard' => $bCanWizardWelcome ? $oFO->
|
96 |
),
|
97 |
'flags' => array(
|
98 |
'can_wizard' => $bCanWizardWelcome,
|
@@ -102,6 +102,7 @@ class ICWP_WPSF_Processor_BasePlugin extends ICWP_WPSF_Processor_BaseWpsf {
|
|
102 |
}
|
103 |
|
104 |
/**
|
|
|
105 |
* @see autoAddToAdminNotices()
|
106 |
* @param array $aAttr
|
107 |
* @throws Exception
|
92 |
'no_setup' => _wpsf__( 'Unfortunately your site is running a PHP version that is too low to run the Setup Wizard. It needs to be PHP 5.4+' )
|
93 |
),
|
94 |
'hrefs' => array(
|
95 |
+
'wizard' => $bCanWizardWelcome ? $oFO->getUrl_Wizard( 'welcome' ) : 'javascript:{event.preventDefault();}',
|
96 |
),
|
97 |
'flags' => array(
|
98 |
'can_wizard' => $bCanWizardWelcome,
|
102 |
}
|
103 |
|
104 |
/**
|
105 |
+
* removed
|
106 |
* @see autoAddToAdminNotices()
|
107 |
* @param array $aAttr
|
108 |
* @throws Exception
|
src/processors/base_wpsf.php
CHANGED
@@ -22,6 +22,7 @@ abstract class ICWP_WPSF_Processor_BaseWpsf extends ICWP_WPSF_Processor_Base {
|
|
22 |
* Resets the object values to be re-used anew
|
23 |
*/
|
24 |
public function init() {
|
|
|
25 |
$oFO = $this->getFeature();
|
26 |
add_filter( $oFO->prefix( 'collect_audit_trail' ), array( $this, 'audit_Collect' ) );
|
27 |
add_filter( $oFO->prefix( 'collect_stats' ), array( $this, 'stats_Collect' ) );
|
22 |
* Resets the object values to be re-used anew
|
23 |
*/
|
24 |
public function init() {
|
25 |
+
parent::init();
|
26 |
$oFO = $this->getFeature();
|
27 |
add_filter( $oFO->prefix( 'collect_audit_trail' ), array( $this, 'audit_Collect' ) );
|
28 |
add_filter( $oFO->prefix( 'collect_stats' ), array( $this, 'stats_Collect' ) );
|
src/processors/email.php
CHANGED
@@ -4,34 +4,39 @@ if ( class_exists( 'ICWP_WPSF_Processor_Email', false ) ) {
|
|
4 |
return;
|
5 |
}
|
6 |
|
7 |
-
require_once( dirname(__FILE__).DIRECTORY_SEPARATOR.'base_wpsf.php' );
|
8 |
|
9 |
class ICWP_WPSF_Processor_Email extends ICWP_WPSF_Processor_BaseWpsf {
|
10 |
|
11 |
const Slug = 'email';
|
12 |
-
|
13 |
protected $m_sRecipientAddress;
|
14 |
|
15 |
/**
|
16 |
* @var string
|
17 |
*/
|
18 |
static protected $sModeFile_EmailThrottled;
|
|
|
19 |
/**
|
20 |
* @var int
|
21 |
*/
|
22 |
-
static protected $nThrottleInterval = 1;
|
|
|
23 |
/**
|
24 |
* @var int
|
25 |
*/
|
26 |
protected $m_nEmailThrottleLimit;
|
|
|
27 |
/**
|
28 |
* @var int
|
29 |
*/
|
30 |
protected $m_nEmailThrottleTime;
|
|
|
31 |
/**
|
32 |
* @var int
|
33 |
*/
|
34 |
protected $m_nEmailThrottleCount;
|
|
|
35 |
/**
|
36 |
* @var boolean
|
37 |
*/
|
@@ -43,20 +48,22 @@ class ICWP_WPSF_Processor_Email extends ICWP_WPSF_Processor_BaseWpsf {
|
|
43 |
public function __construct( ICWP_WPSF_FeatureHandler_Email $oFeatureOptions ) {
|
44 |
parent::__construct( $oFeatureOptions );
|
45 |
}
|
46 |
-
|
47 |
public function init() {
|
48 |
parent::init();
|
49 |
self::$sModeFile_EmailThrottled = dirname( __FILE__ ).'/../mode.email_throttled';
|
50 |
}
|
51 |
|
52 |
-
public function run() {
|
|
|
53 |
|
54 |
/**
|
55 |
* @return array
|
56 |
*/
|
57 |
protected function getEmailHeader() {
|
58 |
return array(
|
59 |
-
_wpsf__('Hi !'),
|
|
|
60 |
);
|
61 |
}
|
62 |
|
@@ -64,16 +71,17 @@ class ICWP_WPSF_Processor_Email extends ICWP_WPSF_Processor_BaseWpsf {
|
|
64 |
* @return array
|
65 |
*/
|
66 |
protected function getEmailFooter() {
|
|
|
67 |
$sUrl = array(
|
68 |
-
'',
|
69 |
-
sprintf(
|
70 |
-
_wpsf__( 'This email was sent from the %s plugin, provided by %s.' ),
|
71 |
$this->getController()->getHumanName(),
|
72 |
-
|
|
|
73 |
),
|
74 |
-
'',
|
75 |
-
sprintf( _wpsf__( '
|
76 |
-
|
77 |
);
|
78 |
|
79 |
return apply_filters( 'icwp_shield_email_footer', $sUrl );
|
@@ -82,7 +90,7 @@ class ICWP_WPSF_Processor_Email extends ICWP_WPSF_Processor_BaseWpsf {
|
|
82 |
/**
|
83 |
* @param string $sEmailAddress
|
84 |
* @param string $sEmailSubject
|
85 |
-
* @param array
|
86 |
* @return boolean
|
87 |
* @uses wp_mail
|
88 |
*/
|
@@ -94,12 +102,6 @@ class ICWP_WPSF_Processor_Email extends ICWP_WPSF_Processor_BaseWpsf {
|
|
94 |
|
95 |
$sEmailTo = $this->verifyEmailAddress( $sEmailAddress );
|
96 |
|
97 |
-
$aHeaders = array(
|
98 |
-
'MIME-Version: 1.0',
|
99 |
-
'Content-type: text/html;',
|
100 |
-
'X-Mailer: PHP/'.phpversion()
|
101 |
-
);
|
102 |
-
|
103 |
$this->updateEmailThrottle();
|
104 |
// We make it appear to have "succeeded" if the throttle is applied.
|
105 |
if ( $this->fEmailIsThrottled ) {
|
@@ -108,15 +110,24 @@ class ICWP_WPSF_Processor_Email extends ICWP_WPSF_Processor_BaseWpsf {
|
|
108 |
|
109 |
$aMessage = array_merge( $this->getEmailHeader(), $aMessage, $this->getEmailFooter() );
|
110 |
|
111 |
-
|
|
|
112 |
|
113 |
// Remove our Filters for From
|
114 |
remove_filter( 'wp_mail_from', array( $this, 'setMailFrom' ), 100 );
|
115 |
remove_filter( 'wp_mail_from_name', array( $this, 'setMailFromName' ), 100 );
|
|
|
116 |
|
117 |
return $bSuccess;
|
118 |
}
|
119 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
120 |
/**
|
121 |
* @param string $sFrom
|
122 |
* @return string
|
@@ -132,7 +143,7 @@ class ICWP_WPSF_Processor_Email extends ICWP_WPSF_Processor_BaseWpsf {
|
|
132 |
if ( !$oDP->validEmail( $sFrom ) ) {
|
133 |
$aUrlParts = @parse_url( $this->loadWp()->getWpUrl() );
|
134 |
if ( !empty( $aUrlParts[ 'host' ] ) ) {
|
135 |
-
$sProposedFrom = 'wordpress@'
|
136 |
if ( $oDP->validEmail( $sProposedFrom ) ) {
|
137 |
$sFrom = $sProposedFrom;
|
138 |
}
|
@@ -158,9 +169,8 @@ class ICWP_WPSF_Processor_Email extends ICWP_WPSF_Processor_BaseWpsf {
|
|
158 |
|
159 |
/**
|
160 |
* Will send email to the default recipient setup in the object.
|
161 |
-
*
|
162 |
* @param string $sEmailSubject
|
163 |
-
* @param array
|
164 |
* @return boolean
|
165 |
*/
|
166 |
public function sendEmail( $sEmailSubject, $aMessage ) {
|
@@ -170,9 +180,7 @@ class ICWP_WPSF_Processor_Email extends ICWP_WPSF_Processor_BaseWpsf {
|
|
170 |
/**
|
171 |
* Whether we're throttled is dependent on 2 signals. The time interval has changed, or the there's a file
|
172 |
* system object telling us we're throttled.
|
173 |
-
*
|
174 |
* The file system object takes precedence.
|
175 |
-
*
|
176 |
* @return boolean
|
177 |
*/
|
178 |
protected function updateEmailThrottle() {
|
@@ -182,7 +190,7 @@ class ICWP_WPSF_Processor_Email extends ICWP_WPSF_Processor_BaseWpsf {
|
|
182 |
$this->setThrottledFile( false );
|
183 |
return $this->fEmailIsThrottled;
|
184 |
}
|
185 |
-
|
186 |
// Check that there is an email throttle file. If it exists and its modified time is greater than the
|
187 |
// current $this->m_nEmailThrottleTime it suggests another process has touched the file and updated it
|
188 |
// concurrently. So, we update our $this->m_nEmailThrottleTime accordingly.
|
@@ -192,19 +200,19 @@ class ICWP_WPSF_Processor_Email extends ICWP_WPSF_Processor_BaseWpsf {
|
|
192 |
$this->m_nEmailThrottleTime = $nModifiedTime;
|
193 |
}
|
194 |
}
|
195 |
-
|
196 |
-
if ( !isset($this->m_nEmailThrottleTime) || $this->m_nEmailThrottleTime > $this->time() ) {
|
197 |
$this->m_nEmailThrottleTime = $this->time();
|
198 |
}
|
199 |
-
if ( !isset($this->m_nEmailThrottleCount) ) {
|
200 |
$this->m_nEmailThrottleCount = 0;
|
201 |
}
|
202 |
-
|
203 |
// If $nNow is greater than throttle interval (1s) we turn off the file throttle and reset the count
|
204 |
$nDiff = $this->time() - $this->m_nEmailThrottleTime;
|
205 |
if ( $nDiff > self::$nThrottleInterval ) {
|
206 |
$this->m_nEmailThrottleTime = $this->time();
|
207 |
-
$this->m_nEmailThrottleCount = 1;
|
208 |
$this->setThrottledFile( false );
|
209 |
}
|
210 |
else if ( is_file( self::$sModeFile_EmailThrottled ) || ( $this->m_nEmailThrottleCount >= $this->getThrottleLimit() ) ) {
|
@@ -214,19 +222,19 @@ class ICWP_WPSF_Processor_Email extends ICWP_WPSF_Processor_BaseWpsf {
|
|
214 |
$this->m_nEmailThrottleCount++;
|
215 |
}
|
216 |
}
|
217 |
-
|
218 |
public function setThrottledFile( $infOn = false ) {
|
219 |
-
|
220 |
$this->fEmailIsThrottled = $infOn;
|
221 |
-
|
222 |
-
if ( $infOn && !is_file( self::$sModeFile_EmailThrottled ) && function_exists('touch') ) {
|
223 |
@touch( self::$sModeFile_EmailThrottled );
|
224 |
}
|
225 |
-
else if ( !$infOn && is_file(self::$sModeFile_EmailThrottled) ) {
|
226 |
@unlink( self::$sModeFile_EmailThrottled );
|
227 |
}
|
228 |
}
|
229 |
-
|
230 |
public function setDefaultRecipientAddress( $insEmailAddress ) {
|
231 |
$this->m_sRecipientAddress = $insEmailAddress;
|
232 |
}
|
@@ -236,7 +244,8 @@ class ICWP_WPSF_Processor_Email extends ICWP_WPSF_Processor_BaseWpsf {
|
|
236 |
* @return string
|
237 |
*/
|
238 |
public function verifyEmailAddress( $sEmailAddress = '' ) {
|
239 |
-
return $this->loadDataProcessor()
|
|
|
240 |
}
|
241 |
|
242 |
/**
|
@@ -245,7 +254,7 @@ class ICWP_WPSF_Processor_Email extends ICWP_WPSF_Processor_BaseWpsf {
|
|
245 |
public function getSiteName() {
|
246 |
return $this->loadWp()->getSiteName();
|
247 |
}
|
248 |
-
|
249 |
public function getThrottleLimit() {
|
250 |
if ( empty( $this->m_nEmailThrottleLimit ) ) {
|
251 |
$this->m_nEmailThrottleLimit = $this->getOption( 'send_email_throttle_limit' );
|
4 |
return;
|
5 |
}
|
6 |
|
7 |
+
require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'base_wpsf.php' );
|
8 |
|
9 |
class ICWP_WPSF_Processor_Email extends ICWP_WPSF_Processor_BaseWpsf {
|
10 |
|
11 |
const Slug = 'email';
|
12 |
+
|
13 |
protected $m_sRecipientAddress;
|
14 |
|
15 |
/**
|
16 |
* @var string
|
17 |
*/
|
18 |
static protected $sModeFile_EmailThrottled;
|
19 |
+
|
20 |
/**
|
21 |
* @var int
|
22 |
*/
|
23 |
+
static protected $nThrottleInterval = 1;
|
24 |
+
|
25 |
/**
|
26 |
* @var int
|
27 |
*/
|
28 |
protected $m_nEmailThrottleLimit;
|
29 |
+
|
30 |
/**
|
31 |
* @var int
|
32 |
*/
|
33 |
protected $m_nEmailThrottleTime;
|
34 |
+
|
35 |
/**
|
36 |
* @var int
|
37 |
*/
|
38 |
protected $m_nEmailThrottleCount;
|
39 |
+
|
40 |
/**
|
41 |
* @var boolean
|
42 |
*/
|
48 |
public function __construct( ICWP_WPSF_FeatureHandler_Email $oFeatureOptions ) {
|
49 |
parent::__construct( $oFeatureOptions );
|
50 |
}
|
51 |
+
|
52 |
public function init() {
|
53 |
parent::init();
|
54 |
self::$sModeFile_EmailThrottled = dirname( __FILE__ ).'/../mode.email_throttled';
|
55 |
}
|
56 |
|
57 |
+
public function run() {
|
58 |
+
}
|
59 |
|
60 |
/**
|
61 |
* @return array
|
62 |
*/
|
63 |
protected function getEmailHeader() {
|
64 |
return array(
|
65 |
+
_wpsf__( 'Hi !' ),
|
66 |
+
'',
|
67 |
);
|
68 |
}
|
69 |
|
71 |
* @return array
|
72 |
*/
|
73 |
protected function getEmailFooter() {
|
74 |
+
$oWp = $this->loadWp();
|
75 |
$sUrl = array(
|
76 |
+
'',
|
77 |
+
sprintf( _wpsf__( 'This email was sent from the %s Plugin v%s, on %s.' ),
|
|
|
78 |
$this->getController()->getHumanName(),
|
79 |
+
$this->getController()->getVersion(),
|
80 |
+
$this->loadWp()->getHomeUrl()
|
81 |
),
|
82 |
+
_wpsf__( 'Note: delays in receiving emails are caused by your website hosting and email providers.' ),
|
83 |
+
sprintf( _wpsf__( 'Time Sent: %s' ), $oWp->getTimeStampForDisplay( time() ) )
|
84 |
+
// sprintf( '<a href="%s"><strong>%s</strong></a>', 'http://icwp.io/shieldicontrolwpemailfooter', 'iControlWP - WordPress Management and Backup Protection For Professionals' )
|
85 |
);
|
86 |
|
87 |
return apply_filters( 'icwp_shield_email_footer', $sUrl );
|
90 |
/**
|
91 |
* @param string $sEmailAddress
|
92 |
* @param string $sEmailSubject
|
93 |
+
* @param array $aMessage
|
94 |
* @return boolean
|
95 |
* @uses wp_mail
|
96 |
*/
|
102 |
|
103 |
$sEmailTo = $this->verifyEmailAddress( $sEmailAddress );
|
104 |
|
|
|
|
|
|
|
|
|
|
|
|
|
105 |
$this->updateEmailThrottle();
|
106 |
// We make it appear to have "succeeded" if the throttle is applied.
|
107 |
if ( $this->fEmailIsThrottled ) {
|
110 |
|
111 |
$aMessage = array_merge( $this->getEmailHeader(), $aMessage, $this->getEmailFooter() );
|
112 |
|
113 |
+
add_filter( 'wp_mail_content_type', array( $this, 'setMailContentType' ), 100, 0 );
|
114 |
+
$bSuccess = wp_mail( $sEmailTo, $sEmailSubject, '<html>'.implode( "<br />", $aMessage ).'</html>' );
|
115 |
|
116 |
// Remove our Filters for From
|
117 |
remove_filter( 'wp_mail_from', array( $this, 'setMailFrom' ), 100 );
|
118 |
remove_filter( 'wp_mail_from_name', array( $this, 'setMailFromName' ), 100 );
|
119 |
+
remove_filter( 'wp_mail_content_type', array( $this, 'setMailContentType' ), 100 );
|
120 |
|
121 |
return $bSuccess;
|
122 |
}
|
123 |
|
124 |
+
/**
|
125 |
+
* @return string
|
126 |
+
*/
|
127 |
+
public function setMailContentType() {
|
128 |
+
return 'text/html';
|
129 |
+
}
|
130 |
+
|
131 |
/**
|
132 |
* @param string $sFrom
|
133 |
* @return string
|
143 |
if ( !$oDP->validEmail( $sFrom ) ) {
|
144 |
$aUrlParts = @parse_url( $this->loadWp()->getWpUrl() );
|
145 |
if ( !empty( $aUrlParts[ 'host' ] ) ) {
|
146 |
+
$sProposedFrom = 'wordpress@'.$aUrlParts[ 'host' ];
|
147 |
if ( $oDP->validEmail( $sProposedFrom ) ) {
|
148 |
$sFrom = $sProposedFrom;
|
149 |
}
|
169 |
|
170 |
/**
|
171 |
* Will send email to the default recipient setup in the object.
|
|
|
172 |
* @param string $sEmailSubject
|
173 |
+
* @param array $aMessage
|
174 |
* @return boolean
|
175 |
*/
|
176 |
public function sendEmail( $sEmailSubject, $aMessage ) {
|
180 |
/**
|
181 |
* Whether we're throttled is dependent on 2 signals. The time interval has changed, or the there's a file
|
182 |
* system object telling us we're throttled.
|
|
|
183 |
* The file system object takes precedence.
|
|
|
184 |
* @return boolean
|
185 |
*/
|
186 |
protected function updateEmailThrottle() {
|
190 |
$this->setThrottledFile( false );
|
191 |
return $this->fEmailIsThrottled;
|
192 |
}
|
193 |
+
|
194 |
// Check that there is an email throttle file. If it exists and its modified time is greater than the
|
195 |
// current $this->m_nEmailThrottleTime it suggests another process has touched the file and updated it
|
196 |
// concurrently. So, we update our $this->m_nEmailThrottleTime accordingly.
|
200 |
$this->m_nEmailThrottleTime = $nModifiedTime;
|
201 |
}
|
202 |
}
|
203 |
+
|
204 |
+
if ( !isset( $this->m_nEmailThrottleTime ) || $this->m_nEmailThrottleTime > $this->time() ) {
|
205 |
$this->m_nEmailThrottleTime = $this->time();
|
206 |
}
|
207 |
+
if ( !isset( $this->m_nEmailThrottleCount ) ) {
|
208 |
$this->m_nEmailThrottleCount = 0;
|
209 |
}
|
210 |
+
|
211 |
// If $nNow is greater than throttle interval (1s) we turn off the file throttle and reset the count
|
212 |
$nDiff = $this->time() - $this->m_nEmailThrottleTime;
|
213 |
if ( $nDiff > self::$nThrottleInterval ) {
|
214 |
$this->m_nEmailThrottleTime = $this->time();
|
215 |
+
$this->m_nEmailThrottleCount = 1; //we set to 1 assuming that this was called because we're about to send, or have just sent, an email.
|
216 |
$this->setThrottledFile( false );
|
217 |
}
|
218 |
else if ( is_file( self::$sModeFile_EmailThrottled ) || ( $this->m_nEmailThrottleCount >= $this->getThrottleLimit() ) ) {
|
222 |
$this->m_nEmailThrottleCount++;
|
223 |
}
|
224 |
}
|
225 |
+
|
226 |
public function setThrottledFile( $infOn = false ) {
|
227 |
+
|
228 |
$this->fEmailIsThrottled = $infOn;
|
229 |
+
|
230 |
+
if ( $infOn && !is_file( self::$sModeFile_EmailThrottled ) && function_exists( 'touch' ) ) {
|
231 |
@touch( self::$sModeFile_EmailThrottled );
|
232 |
}
|
233 |
+
else if ( !$infOn && is_file( self::$sModeFile_EmailThrottled ) ) {
|
234 |
@unlink( self::$sModeFile_EmailThrottled );
|
235 |
}
|
236 |
}
|
237 |
+
|
238 |
public function setDefaultRecipientAddress( $insEmailAddress ) {
|
239 |
$this->m_sRecipientAddress = $insEmailAddress;
|
240 |
}
|
244 |
* @return string
|
245 |
*/
|
246 |
public function verifyEmailAddress( $sEmailAddress = '' ) {
|
247 |
+
return $this->loadDataProcessor()
|
248 |
+
->validEmail( $sEmailAddress ) ? $sEmailAddress : $this->getPluginDefaultRecipientAddress();
|
249 |
}
|
250 |
|
251 |
/**
|
254 |
public function getSiteName() {
|
255 |
return $this->loadWp()->getSiteName();
|
256 |
}
|
257 |
+
|
258 |
public function getThrottleLimit() {
|
259 |
if ( empty( $this->m_nEmailThrottleLimit ) ) {
|
260 |
$this->m_nEmailThrottleLimit = $this->getOption( 'send_email_throttle_limit' );
|
src/processors/hack_protect.php
CHANGED
@@ -23,7 +23,7 @@ class ICWP_WPSF_Processor_HackProtect extends ICWP_WPSF_Processor_BaseWpsf {
|
|
23 |
// not probably necessary any longer since it's patched in the Core
|
24 |
add_filter( 'pre_comment_content', array( $this, 'secXss64kb' ), 0, 1 );
|
25 |
|
26 |
-
if ( $
|
27 |
$this->runChecksumScan();
|
28 |
}
|
29 |
if ( $oFO->isUfsEnabled() ) {
|
@@ -75,7 +75,7 @@ class ICWP_WPSF_Processor_HackProtect extends ICWP_WPSF_Processor_BaseWpsf {
|
|
75 |
/**
|
76 |
* @return ICWP_WPSF_Processor_HackProtect_CoreChecksumScan
|
77 |
*/
|
78 |
-
|
79 |
$oProc = $this->getSubProcessor( 'checksum' );
|
80 |
if ( is_null( $oProc ) ) {
|
81 |
require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'hackprotect_corechecksumscan.php' );
|
@@ -88,7 +88,7 @@ class ICWP_WPSF_Processor_HackProtect extends ICWP_WPSF_Processor_BaseWpsf {
|
|
88 |
/**
|
89 |
* @return ICWP_WPSF_Processor_HackProtect_FileCleanerScan
|
90 |
*/
|
91 |
-
|
92 |
$oProc = $this->getSubProcessor( 'cleaner' );
|
93 |
if ( is_null( $oProc ) ) {
|
94 |
require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'hackprotect_filecleanerscan.php' );
|
23 |
// not probably necessary any longer since it's patched in the Core
|
24 |
add_filter( 'pre_comment_content', array( $this, 'secXss64kb' ), 0, 1 );
|
25 |
|
26 |
+
if ( $oFO->isWcfScanEnabled() ) {
|
27 |
$this->runChecksumScan();
|
28 |
}
|
29 |
if ( $oFO->isUfsEnabled() ) {
|
75 |
/**
|
76 |
* @return ICWP_WPSF_Processor_HackProtect_CoreChecksumScan
|
77 |
*/
|
78 |
+
public function getSubProcessorChecksumScan() {
|
79 |
$oProc = $this->getSubProcessor( 'checksum' );
|
80 |
if ( is_null( $oProc ) ) {
|
81 |
require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'hackprotect_corechecksumscan.php' );
|
88 |
/**
|
89 |
* @return ICWP_WPSF_Processor_HackProtect_FileCleanerScan
|
90 |
*/
|
91 |
+
public function getSubProcessorFileCleanerScan() {
|
92 |
$oProc = $this->getSubProcessor( 'cleaner' );
|
93 |
if ( is_null( $oProc ) ) {
|
94 |
require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'hackprotect_filecleanerscan.php' );
|
src/processors/hackprotect_corechecksumscan.php
CHANGED
@@ -274,6 +274,19 @@ class ICWP_WPSF_Processor_HackProtect_CoreChecksumScan extends ICWP_WPSF_Process
|
|
274 |
. ' [<a href="http://icwp.io/moreinfochecksum">' . _wpsf__( 'More Info' ) . ']</a>';
|
275 |
}
|
276 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
277 |
$sRecipient = $this->getPluginDefaultRecipientAddress();
|
278 |
$sEmailSubject = sprintf( _wpsf__( 'Warning - %s' ), _wpsf__( 'Core WordPress Files(s) Discovered That May Have Been Modified.' ) );
|
279 |
$bSendSuccess = $this->getEmailProcessor()->sendEmailTo( $sRecipient, $sEmailSubject, $aContent );
|
274 |
. ' [<a href="http://icwp.io/moreinfochecksum">' . _wpsf__( 'More Info' ) . ']</a>';
|
275 |
}
|
276 |
|
277 |
+
$aContent[] = '';
|
278 |
+
|
279 |
+
/** @var ICWP_WPSF_FeatureHandler_HackProtect $oFO */
|
280 |
+
$oFO = $this->getFeature();
|
281 |
+
if ( $oFO->getCanRunWizards() ) {
|
282 |
+
$aContent[] = sprintf( '<a href="%s" target="_blank" style="%s">%s →</a>',
|
283 |
+
$oFO->getUrl_Wizard( 'wcf' ),
|
284 |
+
'border:1px solid;padding:20px;line-height:19px;margin:10px 20px;display:inline-block;text-align:center;width:290px;font-size:18px;',
|
285 |
+
_wpsf__( 'Run the scanner manually' )
|
286 |
+
);
|
287 |
+
$aContent[] = '';
|
288 |
+
}
|
289 |
+
|
290 |
$sRecipient = $this->getPluginDefaultRecipientAddress();
|
291 |
$sEmailSubject = sprintf( _wpsf__( 'Warning - %s' ), _wpsf__( 'Core WordPress Files(s) Discovered That May Have Been Modified.' ) );
|
292 |
$bSendSuccess = $this->getEmailProcessor()->sendEmailTo( $sRecipient, $sEmailSubject, $aContent );
|
src/processors/hackprotect_filecleanerscan.php
CHANGED
@@ -4,7 +4,7 @@ if ( class_exists( 'ICWP_WPSF_Processor_HackProtect_FileCleanerScan', false ) )
|
|
4 |
return;
|
5 |
}
|
6 |
|
7 |
-
require_once( dirname( __FILE__ )
|
8 |
|
9 |
class ICWP_WPSF_Processor_HackProtect_FileCleanerScan extends ICWP_WPSF_Processor_BaseWpsf {
|
10 |
|
@@ -19,17 +19,16 @@ class ICWP_WPSF_Processor_HackProtect_FileCleanerScan extends ICWP_WPSF_Processo
|
|
19 |
$this->setupChecksumCron();
|
20 |
|
21 |
if ( $this->loadWpUsers()->isUserAdmin() ) {
|
22 |
-
$oDp = $this->
|
23 |
|
24 |
-
if ( $oDp->
|
25 |
$this->runScan();
|
26 |
}
|
27 |
else {
|
28 |
-
$sAction = $oDp->
|
29 |
switch ( $sAction ) {
|
30 |
-
|
31 |
case 'delete_unrecognised_file':
|
32 |
-
$sPath = '/'
|
33 |
}
|
34 |
}
|
35 |
}
|
@@ -76,7 +75,7 @@ class ICWP_WPSF_Processor_HackProtect_FileCleanerScan extends ICWP_WPSF_Processo
|
|
76 |
$oFilter = new CleanerRecursiveFilterIterator( new RecursiveDirectoryIterator( $sUploadsDir ) );
|
77 |
$oRecursiveIterator = new RecursiveIteratorIterator( $oFilter );
|
78 |
|
79 |
-
$sBadExtensionsReg = '#^'
|
80 |
foreach ( $oRecursiveIterator as $oFsItem ) {
|
81 |
/** @var SplFileInfo $oFsItem */
|
82 |
|
@@ -147,7 +146,11 @@ class ICWP_WPSF_Processor_HackProtect_FileCleanerScan extends ICWP_WPSF_Processo
|
|
147 |
|
148 |
foreach ( $oFO->getUfcFileExclusions() as $sExclusion ) {
|
149 |
$sExclusion = $oFS->normalizeFilePathDS( $sExclusion );
|
150 |
-
|
|
|
|
|
|
|
|
|
151 |
$bExcluded = ( $sFileName == $sExclusion );
|
152 |
}
|
153 |
else {
|
@@ -178,17 +181,11 @@ class ICWP_WPSF_Processor_HackProtect_FileCleanerScan extends ICWP_WPSF_Processo
|
|
178 |
}
|
179 |
|
180 |
/**
|
181 |
-
* @throws Exception
|
182 |
*/
|
183 |
public function runScan() {
|
184 |
/** @var ICWP_WPSF_FeatureHandler_HackProtect $oFO */
|
185 |
$oFO = $this->getFeature();
|
186 |
-
|
187 |
-
$aDiscoveredFiles = $this->scanCore();
|
188 |
-
if ( $oFO->isUfsScanUploads() ) {
|
189 |
-
$aDiscoveredFiles = array_merge( $aDiscoveredFiles, $this->scanUploads() );
|
190 |
-
}
|
191 |
-
|
192 |
if ( !empty( $aDiscoveredFiles ) ) {
|
193 |
if ( $oFO->isUfsDeleteFiles() ) {
|
194 |
$this->deleteFiles( $aDiscoveredFiles );
|
@@ -199,6 +196,20 @@ class ICWP_WPSF_Processor_HackProtect_FileCleanerScan extends ICWP_WPSF_Processo
|
|
199 |
}
|
200 |
}
|
201 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
202 |
/**
|
203 |
* @param array $aFiles
|
204 |
* @return bool
|
@@ -209,14 +220,12 @@ class ICWP_WPSF_Processor_HackProtect_FileCleanerScan extends ICWP_WPSF_Processo
|
|
209 |
}
|
210 |
/** @var ICWP_WPSF_FeatureHandler_HackProtect $oFO */
|
211 |
$oFO = $this->getFeature();
|
212 |
-
|
213 |
-
$oWp = $this->loadWp();
|
214 |
-
$sHomeUrl = $oWp->getHomeUrl();
|
215 |
$aContent = array(
|
216 |
sprintf( _wpsf__( '%s detected files on your site which are not recognised.' ), $this->getController()
|
217 |
->getHumanName() ),
|
218 |
_wpsf__( 'This is part of the Hack Protection module for the WordPress Unrecognised File Scanner.' )
|
219 |
-
.
|
220 |
'',
|
221 |
sprintf( _wpsf__( 'Site Home URL - %s' ), sprintf( '<a href="%s" target="_blank">%s</a>', $sHomeUrl, $sHomeUrl ) ),
|
222 |
_wpsf__( 'The following files are considered "unrecognised" and should be examined:' ),
|
@@ -224,19 +233,28 @@ class ICWP_WPSF_Processor_HackProtect_FileCleanerScan extends ICWP_WPSF_Processo
|
|
224 |
);
|
225 |
|
226 |
foreach ( $aFiles as $sFile ) {
|
227 |
-
$aContent[] = ' - '
|
228 |
}
|
229 |
|
230 |
$aContent[] = '';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
231 |
if ( $oFO->isUfsDeleteFiles() ) {
|
232 |
$aContent[] = _wpsf__( 'We have already attempted to delete these files based on your current settings.' )
|
233 |
-
|
234 |
}
|
235 |
else {
|
236 |
$aContent[] = _wpsf__( 'You should review these files and remove them if required.' );
|
237 |
$aContent[] = _wpsf__( 'You can now add these file names to your exclusion list to no longer be warned about them.' );
|
238 |
$aContent[] = _wpsf__( 'Alternatively you can have the plugin attempt to delete these files automatically.' )
|
239 |
-
|
240 |
}
|
241 |
|
242 |
$sRecipient = $this->getPluginDefaultRecipientAddress();
|
@@ -249,7 +267,6 @@ class ICWP_WPSF_Processor_HackProtect_FileCleanerScan extends ICWP_WPSF_Processo
|
|
249 |
else {
|
250 |
$this->addToAuditEntry( sprintf( _wpsf__( 'Failed to send Unrecognised File Scan notification email alert to: %s' ), $sRecipient ) );
|
251 |
}
|
252 |
-
|
253 |
return $bSendSuccess;
|
254 |
}
|
255 |
|
4 |
return;
|
5 |
}
|
6 |
|
7 |
+
require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'base_wpsf.php' );
|
8 |
|
9 |
class ICWP_WPSF_Processor_HackProtect_FileCleanerScan extends ICWP_WPSF_Processor_BaseWpsf {
|
10 |
|
19 |
$this->setupChecksumCron();
|
20 |
|
21 |
if ( $this->loadWpUsers()->isUserAdmin() ) {
|
22 |
+
$oDp = $this->loadDP();
|
23 |
|
24 |
+
if ( $oDp->query( 'force_filecleanscan' ) == 1 ) {
|
25 |
$this->runScan();
|
26 |
}
|
27 |
else {
|
28 |
+
$sAction = $oDp->query( 'shield_action' );
|
29 |
switch ( $sAction ) {
|
|
|
30 |
case 'delete_unrecognised_file':
|
31 |
+
$sPath = '/'.trim( $oDp->FetchGet( 'repair_file_path' ) ); // "/" prevents esc_url() from prepending http.
|
32 |
}
|
33 |
}
|
34 |
}
|
75 |
$oFilter = new CleanerRecursiveFilterIterator( new RecursiveDirectoryIterator( $sUploadsDir ) );
|
76 |
$oRecursiveIterator = new RecursiveIteratorIterator( $oFilter );
|
77 |
|
78 |
+
$sBadExtensionsReg = '#^'.implode( '|', array( 'js', 'php', 'php5' ) ).'$#i';
|
79 |
foreach ( $oRecursiveIterator as $oFsItem ) {
|
80 |
/** @var SplFileInfo $oFsItem */
|
81 |
|
146 |
|
147 |
foreach ( $oFO->getUfcFileExclusions() as $sExclusion ) {
|
148 |
$sExclusion = $oFS->normalizeFilePathDS( $sExclusion );
|
149 |
+
|
150 |
+
if ( preg_match( '/^#(.+)#$/', $sExclusion, $aMatches ) ) { // it's regex
|
151 |
+
$bExcluded = @preg_match( stripslashes( $sExclusion ), $sFilePath );
|
152 |
+
}
|
153 |
+
else if ( strpos( $sExclusion, '/' ) === false ) { // filename only
|
154 |
$bExcluded = ( $sFileName == $sExclusion );
|
155 |
}
|
156 |
else {
|
181 |
}
|
182 |
|
183 |
/**
|
|
|
184 |
*/
|
185 |
public function runScan() {
|
186 |
/** @var ICWP_WPSF_FeatureHandler_HackProtect $oFO */
|
187 |
$oFO = $this->getFeature();
|
188 |
+
$aDiscoveredFiles = $this->discoverFiles();
|
|
|
|
|
|
|
|
|
|
|
189 |
if ( !empty( $aDiscoveredFiles ) ) {
|
190 |
if ( $oFO->isUfsDeleteFiles() ) {
|
191 |
$this->deleteFiles( $aDiscoveredFiles );
|
196 |
}
|
197 |
}
|
198 |
|
199 |
+
/**
|
200 |
+
* @return array
|
201 |
+
*/
|
202 |
+
public function discoverFiles() {
|
203 |
+
/** @var ICWP_WPSF_FeatureHandler_HackProtect $oFO */
|
204 |
+
$oFO = $this->getFeature();
|
205 |
+
|
206 |
+
$aDiscoveredFiles = $this->scanCore();
|
207 |
+
if ( $oFO->isUfsScanUploads() ) {
|
208 |
+
$aDiscoveredFiles = array_merge( $aDiscoveredFiles, $this->scanUploads() );
|
209 |
+
}
|
210 |
+
return $aDiscoveredFiles;
|
211 |
+
}
|
212 |
+
|
213 |
/**
|
214 |
* @param array $aFiles
|
215 |
* @return bool
|
220 |
}
|
221 |
/** @var ICWP_WPSF_FeatureHandler_HackProtect $oFO */
|
222 |
$oFO = $this->getFeature();
|
223 |
+
$sHomeUrl = $this->loadWp()->getHomeUrl();
|
|
|
|
|
224 |
$aContent = array(
|
225 |
sprintf( _wpsf__( '%s detected files on your site which are not recognised.' ), $this->getController()
|
226 |
->getHumanName() ),
|
227 |
_wpsf__( 'This is part of the Hack Protection module for the WordPress Unrecognised File Scanner.' )
|
228 |
+
.' [<a href="http://icwp.io/shieldmoreinfounrecognised">'._wpsf__( 'More Info' ).']</a>',
|
229 |
'',
|
230 |
sprintf( _wpsf__( 'Site Home URL - %s' ), sprintf( '<a href="%s" target="_blank">%s</a>', $sHomeUrl, $sHomeUrl ) ),
|
231 |
_wpsf__( 'The following files are considered "unrecognised" and should be examined:' ),
|
233 |
);
|
234 |
|
235 |
foreach ( $aFiles as $sFile ) {
|
236 |
+
$aContent[] = ' - '.$sFile;
|
237 |
}
|
238 |
|
239 |
$aContent[] = '';
|
240 |
+
if ( $oFO->getCanRunWizards() ) {
|
241 |
+
$aContent[] = sprintf( '<a href="%s" target="_blank" style="%s">%s →</a>',
|
242 |
+
$oFO->getUrl_Wizard( 'ufc' ),
|
243 |
+
'border:1px solid;padding:20px;line-height:19px;margin:10px 20px;display:inline-block;text-align:center;width:290px;font-size:18px;',
|
244 |
+
_wpsf__( 'Run the scanner manually' )
|
245 |
+
);
|
246 |
+
$aContent[] = '';
|
247 |
+
}
|
248 |
+
|
249 |
if ( $oFO->isUfsDeleteFiles() ) {
|
250 |
$aContent[] = _wpsf__( 'We have already attempted to delete these files based on your current settings.' )
|
251 |
+
.' '._wpsf__( 'But, you should always check these files to ensure everything is as you expect.' );
|
252 |
}
|
253 |
else {
|
254 |
$aContent[] = _wpsf__( 'You should review these files and remove them if required.' );
|
255 |
$aContent[] = _wpsf__( 'You can now add these file names to your exclusion list to no longer be warned about them.' );
|
256 |
$aContent[] = _wpsf__( 'Alternatively you can have the plugin attempt to delete these files automatically.' )
|
257 |
+
.' [<a href="http://icwp.io/shieldmoreinfounrecognised">'._wpsf__( 'More Info' ).']</a>';
|
258 |
}
|
259 |
|
260 |
$sRecipient = $this->getPluginDefaultRecipientAddress();
|
267 |
else {
|
268 |
$this->addToAuditEntry( sprintf( _wpsf__( 'Failed to send Unrecognised File Scan notification email alert to: %s' ), $sRecipient ) );
|
269 |
}
|
|
|
270 |
return $bSendSuccess;
|
271 |
}
|
272 |
|
src/processors/hackprotect_wpvulnscan.php
CHANGED
@@ -4,7 +4,7 @@ if ( class_exists( 'ICWP_WPSF_Processor_HackProtect_WpVulnScan', false ) ) {
|
|
4 |
return;
|
5 |
}
|
6 |
|
7 |
-
require_once( dirname( __FILE__ ).
|
8 |
|
9 |
class ICWP_WPSF_Processor_HackProtect_WpVulnScan extends ICWP_WPSF_Processor_BaseWpsf {
|
10 |
|
4 |
return;
|
5 |
}
|
6 |
|
7 |
+
require_once( dirname( __FILE__ ).'/base_wpsf.php' );
|
8 |
|
9 |
class ICWP_WPSF_Processor_HackProtect_WpVulnScan extends ICWP_WPSF_Processor_BaseWpsf {
|
10 |
|
src/processors/login_protect.php
CHANGED
@@ -17,7 +17,7 @@ class ICWP_WPSF_Processor_LoginProtect extends ICWP_WPSF_Processor_BaseWpsf {
|
|
17 |
|
18 |
// XML-RPC Compatibility
|
19 |
if ( $oWp->getIsXmlrpc() && $this->getIsOption( 'enable_xmlrpc_compatibility', 'Y' ) ) {
|
20 |
-
return
|
21 |
}
|
22 |
|
23 |
if ( $oFO->getIsCustomLoginPathEnabled() ) {
|
@@ -40,7 +40,6 @@ class ICWP_WPSF_Processor_LoginProtect extends ICWP_WPSF_Processor_BaseWpsf {
|
|
40 |
$this->getProcessorLoginIntent()->run();
|
41 |
|
42 |
add_filter( 'wp_login_errors', array( $this, 'addLoginMessage' ) );
|
43 |
-
return true;
|
44 |
}
|
45 |
|
46 |
/**
|
@@ -99,7 +98,7 @@ class ICWP_WPSF_Processor_LoginProtect extends ICWP_WPSF_Processor_BaseWpsf {
|
|
99 |
/**
|
100 |
* @return ICWP_WPSF_Processor_LoginProtect_Intent
|
101 |
*/
|
102 |
-
|
103 |
require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'loginprotect_intent.php' );
|
104 |
$oProc = new ICWP_WPSF_Processor_LoginProtect_Intent( $this->getFeature() );
|
105 |
return $oProc;
|
17 |
|
18 |
// XML-RPC Compatibility
|
19 |
if ( $oWp->getIsXmlrpc() && $this->getIsOption( 'enable_xmlrpc_compatibility', 'Y' ) ) {
|
20 |
+
return;
|
21 |
}
|
22 |
|
23 |
if ( $oFO->getIsCustomLoginPathEnabled() ) {
|
40 |
$this->getProcessorLoginIntent()->run();
|
41 |
|
42 |
add_filter( 'wp_login_errors', array( $this, 'addLoginMessage' ) );
|
|
|
43 |
}
|
44 |
|
45 |
/**
|
98 |
/**
|
99 |
* @return ICWP_WPSF_Processor_LoginProtect_Intent
|
100 |
*/
|
101 |
+
public function getProcessorLoginIntent() {
|
102 |
require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'loginprotect_intent.php' );
|
103 |
$oProc = new ICWP_WPSF_Processor_LoginProtect_Intent( $this->getFeature() );
|
104 |
return $oProc;
|
src/processors/loginprotect_googleauthenticator.php
CHANGED
@@ -54,17 +54,31 @@ class ICWP_WPSF_Processor_LoginProtect_GoogleAuthenticator extends ICWP_WPSF_Pro
|
|
54 |
);
|
55 |
|
56 |
if ( !$bValidatedProfile ) {
|
57 |
-
$
|
58 |
-
$aData['user_google_authenticator_secret'],
|
59 |
-
preg_replace( '#[^0-9a-z]#i', '', $oUser->get('user_login') )
|
60 |
-
.'@'.preg_replace( '#[^0-9a-z]#i', '', $this->loadWp()->getSiteName() )
|
61 |
-
);
|
62 |
-
$aData[ 'chart_url' ] = $sChartUrl;
|
63 |
}
|
64 |
|
65 |
echo $this->getFeature()->renderTemplate( 'snippets/user_profile_googleauthenticator.php', $aData );
|
66 |
}
|
67 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
/**
|
69 |
* The only thing we can do is REMOVE Google Authenticator from an account that is not our own
|
70 |
* But, only admins can do this. If Security Admin feature is enabled, then only they can do it.
|
@@ -130,7 +144,6 @@ class ICWP_WPSF_Processor_LoginProtect_GoogleAuthenticator extends ICWP_WPSF_Pro
|
|
130 |
* @param int $nSavingUserId
|
131 |
*/
|
132 |
public function handleUserProfileSubmit( $nSavingUserId ) {
|
133 |
-
$oDp = $this->loadDataProcessor();
|
134 |
$oWpUsers = $this->loadWpUsers();
|
135 |
$oWpNotices = $this->loadAdminNoticesProcessor();
|
136 |
|
@@ -142,7 +155,7 @@ class ICWP_WPSF_Processor_LoginProtect_GoogleAuthenticator extends ICWP_WPSF_Pro
|
|
142 |
|
143 |
$sMessageOtpInvalid = _wpsf__( 'One Time Password (OTP) was not valid.' ).' '._wpsf__( 'Please try again.' );
|
144 |
|
145 |
-
$sShieldTurnOff = $
|
146 |
if ( !empty( $sShieldTurnOff ) && $sShieldTurnOff == 'Y' ) {
|
147 |
|
148 |
if ( $bValidOtp ) {
|
@@ -312,6 +325,15 @@ class ICWP_WPSF_Processor_LoginProtect_GoogleAuthenticator extends ICWP_WPSF_Pro
|
|
312 |
* @return bool
|
313 |
*/
|
314 |
protected function processOtp( $oUser, $sOtpCode ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
315 |
$bValidOtp = false;
|
316 |
if ( !empty( $sOtpCode ) && preg_match( '#^[0-9]{6}$#', $sOtpCode ) ) {
|
317 |
$bValidOtp = $this->loadGoogleAuthenticatorProcessor()
|
54 |
);
|
55 |
|
56 |
if ( !$bValidatedProfile ) {
|
57 |
+
$aData[ 'chart_url' ] = $this->getGaRegisterChartUrl( $oUser );
|
|
|
|
|
|
|
|
|
|
|
58 |
}
|
59 |
|
60 |
echo $this->getFeature()->renderTemplate( 'snippets/user_profile_googleauthenticator.php', $aData );
|
61 |
}
|
62 |
|
63 |
+
/**
|
64 |
+
* @param WP_User $oUser
|
65 |
+
* @return string
|
66 |
+
*/
|
67 |
+
public function getGaRegisterChartUrl( $oUser ) {
|
68 |
+
if ( empty( $oUser ) ) {
|
69 |
+
$sUrl = '';
|
70 |
+
}
|
71 |
+
else {
|
72 |
+
$sUrl = $this->loadGoogleAuthenticatorProcessor()
|
73 |
+
->getGoogleQrChartUrl(
|
74 |
+
$this->getSecret( $oUser ),
|
75 |
+
preg_replace( '#[^0-9a-z]#i', '', $oUser->get( 'user_login' ) )
|
76 |
+
.'@'.preg_replace( '#[^0-9a-z]#i', '', $this->loadWp()->getSiteName() )
|
77 |
+
);
|
78 |
+
}
|
79 |
+
return $sUrl;
|
80 |
+
}
|
81 |
+
|
82 |
/**
|
83 |
* The only thing we can do is REMOVE Google Authenticator from an account that is not our own
|
84 |
* But, only admins can do this. If Security Admin feature is enabled, then only they can do it.
|
144 |
* @param int $nSavingUserId
|
145 |
*/
|
146 |
public function handleUserProfileSubmit( $nSavingUserId ) {
|
|
|
147 |
$oWpUsers = $this->loadWpUsers();
|
148 |
$oWpNotices = $this->loadAdminNoticesProcessor();
|
149 |
|
155 |
|
156 |
$sMessageOtpInvalid = _wpsf__( 'One Time Password (OTP) was not valid.' ).' '._wpsf__( 'Please try again.' );
|
157 |
|
158 |
+
$sShieldTurnOff = $this->loadDP()->post( 'shield_turn_off_google_authenticator' );
|
159 |
if ( !empty( $sShieldTurnOff ) && $sShieldTurnOff == 'Y' ) {
|
160 |
|
161 |
if ( $bValidOtp ) {
|
325 |
* @return bool
|
326 |
*/
|
327 |
protected function processOtp( $oUser, $sOtpCode ) {
|
328 |
+
return $this->validateGaCode( $oUser, $sOtpCode );
|
329 |
+
}
|
330 |
+
|
331 |
+
/**
|
332 |
+
* @param WP_User $oUser
|
333 |
+
* @param string $sOtpCode
|
334 |
+
* @return bool
|
335 |
+
*/
|
336 |
+
public function validateGaCode( $oUser, $sOtpCode ) {
|
337 |
$bValidOtp = false;
|
338 |
if ( !empty( $sOtpCode ) && preg_match( '#^[0-9]{6}$#', $sOtpCode ) ) {
|
339 |
$bValidOtp = $this->loadGoogleAuthenticatorProcessor()
|
src/processors/loginprotect_intent.php
CHANGED
@@ -4,7 +4,7 @@ if ( class_exists( 'ICWP_WPSF_Processor_LoginProtect_Intent', false ) ) {
|
|
4 |
return;
|
5 |
}
|
6 |
|
7 |
-
require_once( dirname(__FILE__).DIRECTORY_SEPARATOR.'base_wpsf.php' );
|
8 |
|
9 |
class ICWP_WPSF_Processor_LoginProtect_Intent extends ICWP_WPSF_Processor_BaseWpsf {
|
10 |
|
@@ -21,7 +21,7 @@ class ICWP_WPSF_Processor_LoginProtect_Intent extends ICWP_WPSF_Processor_BaseWp
|
|
21 |
|
22 |
$oLoginTracker = $this->getLoginTrack();
|
23 |
|
24 |
-
if ( $
|
25 |
$oLoginTracker->addFactorToTrack( ICWP_WPSF_Processor_LoginProtect_Track::Factor_Google_Authenticator );
|
26 |
$this->getProcessorGoogleAuthenticator()->run();
|
27 |
}
|
@@ -70,12 +70,12 @@ class ICWP_WPSF_Processor_LoginProtect_Intent extends ICWP_WPSF_Processor_BaseWp
|
|
70 |
$oFO = $this->getFeature();
|
71 |
|
72 |
if ( $this->userHasPendingLoginIntent() ) {
|
73 |
-
$oDp = $this->
|
74 |
|
75 |
$bIsLoginIntentSubmission = $oDp->FetchRequest( $oFO->getLoginIntentRequestFlag() ) == 1;
|
76 |
if ( $bIsLoginIntentSubmission ) {
|
77 |
|
78 |
-
if ( $oDp->
|
79 |
$this->loadWpUsers()->logoutUser(); // clears the login and login intent
|
80 |
$this->loadWp()->redirectToLogin();
|
81 |
return;
|
@@ -92,11 +92,11 @@ class ICWP_WPSF_Processor_LoginProtect_Intent extends ICWP_WPSF_Processor_BaseWp
|
|
92 |
|
93 |
if ( $bLoginIntentValidated ) {
|
94 |
$this->removeLoginIntent();
|
95 |
-
$sRedirect = $oDp->
|
96 |
$this->loadAdminNoticesProcessor()->addFlashMessage(
|
97 |
_wpsf__( 'Success' ).'! '._wpsf__( 'Thank you for authenticating your login.' ) );
|
98 |
if ( !empty( $sRedirect ) ) {
|
99 |
-
$this->loadWp()->doRedirect(
|
100 |
}
|
101 |
}
|
102 |
else {
|
@@ -144,7 +144,7 @@ class ICWP_WPSF_Processor_LoginProtect_Intent extends ICWP_WPSF_Processor_BaseWp
|
|
144 |
}
|
145 |
|
146 |
/**
|
147 |
-
* @param int
|
148 |
* @param null $oUser
|
149 |
*/
|
150 |
protected function setLoginIntentExpiration( $nExpirationTime, $oUser = null ) {
|
@@ -170,7 +170,7 @@ class ICWP_WPSF_Processor_LoginProtect_Intent extends ICWP_WPSF_Processor_BaseWp
|
|
170 |
$oF->prefix( 'login_intent_timeout' ),
|
171 |
$oF->getDefinition( 'login_intent_timeout' )
|
172 |
);
|
173 |
-
$this->setLoginIntentExpiration($this->time() + MINUTE_IN_SECONDS*$nTimeout, $oUser );
|
174 |
}
|
175 |
return $oUser;
|
176 |
}
|
@@ -226,16 +226,13 @@ class ICWP_WPSF_Processor_LoginProtect_Intent extends ICWP_WPSF_Processor_BaseWp
|
|
226 |
$sMessageType = 'warning';
|
227 |
}
|
228 |
|
229 |
-
$sRedirectTo = $this->
|
230 |
-
if ( empty( $sRedirectTo ) ) {
|
231 |
-
$sRedirectTo = rawurlencode( esc_url( $this->loadDataProcessor()->getRequestUri() ) );
|
232 |
-
}
|
233 |
|
234 |
$aDisplayData = array(
|
235 |
'strings' => array(
|
236 |
'cancel' => _wpsf__( 'Cancel Login' ),
|
237 |
'time_remaining' => _wpsf__( 'Time Remaining' ),
|
238 |
-
'calculating' => _wpsf__( 'Calculating' )
|
239 |
'seconds' => strtolower( _wpsf__( 'Seconds' ) ),
|
240 |
'login_expired' => _wpsf__( 'Login Expired' ),
|
241 |
'verify_my_login' => _wpsf__( 'Verify My Login' ),
|
@@ -273,7 +270,7 @@ class ICWP_WPSF_Processor_LoginProtect_Intent extends ICWP_WPSF_Processor_BaseWp
|
|
273 |
* @return ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth
|
274 |
*/
|
275 |
protected function getProcessorTwoFactor() {
|
276 |
-
require_once( dirname(__FILE__).DIRECTORY_SEPARATOR.'loginprotect_twofactorauth.php' );
|
277 |
/** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
|
278 |
$oFO = $this->getFeature();
|
279 |
$oProc = new ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth( $oFO );
|
@@ -284,7 +281,7 @@ class ICWP_WPSF_Processor_LoginProtect_Intent extends ICWP_WPSF_Processor_BaseWp
|
|
284 |
* @return ICWP_WPSF_Processor_LoginProtect_Yubikey
|
285 |
*/
|
286 |
protected function getProcessorYubikey() {
|
287 |
-
require_once( dirname(__FILE__).DIRECTORY_SEPARATOR.'loginprotect_yubikey.php' );
|
288 |
$oProc = new ICWP_WPSF_Processor_LoginProtect_Yubikey( $this->getFeature() );
|
289 |
return $oProc->setLoginTrack( $this->getLoginTrack() );
|
290 |
}
|
@@ -292,8 +289,8 @@ class ICWP_WPSF_Processor_LoginProtect_Intent extends ICWP_WPSF_Processor_BaseWp
|
|
292 |
/**
|
293 |
* @return ICWP_WPSF_Processor_LoginProtect_GoogleAuthenticator
|
294 |
*/
|
295 |
-
|
296 |
-
require_once( dirname(__FILE__).DIRECTORY_SEPARATOR.'loginprotect_googleauthenticator.php' );
|
297 |
$oProc = new ICWP_WPSF_Processor_LoginProtect_GoogleAuthenticator( $this->getFeature() );
|
298 |
return $oProc->setLoginTrack( $this->getLoginTrack() );
|
299 |
}
|
@@ -303,7 +300,7 @@ class ICWP_WPSF_Processor_LoginProtect_Intent extends ICWP_WPSF_Processor_BaseWp
|
|
303 |
*/
|
304 |
public function getLoginTrack() {
|
305 |
if ( !isset( $this->oLoginTrack ) ) {
|
306 |
-
require_once( dirname(__FILE__).DIRECTORY_SEPARATOR.'loginprotect_track.php' );
|
307 |
$this->oLoginTrack = new ICWP_WPSF_Processor_LoginProtect_Track();
|
308 |
}
|
309 |
return $this->oLoginTrack;
|
4 |
return;
|
5 |
}
|
6 |
|
7 |
+
require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'base_wpsf.php' );
|
8 |
|
9 |
class ICWP_WPSF_Processor_LoginProtect_Intent extends ICWP_WPSF_Processor_BaseWpsf {
|
10 |
|
21 |
|
22 |
$oLoginTracker = $this->getLoginTrack();
|
23 |
|
24 |
+
if ( $oFO->getIsEnabledGoogleAuthenticator() ) {
|
25 |
$oLoginTracker->addFactorToTrack( ICWP_WPSF_Processor_LoginProtect_Track::Factor_Google_Authenticator );
|
26 |
$this->getProcessorGoogleAuthenticator()->run();
|
27 |
}
|
70 |
$oFO = $this->getFeature();
|
71 |
|
72 |
if ( $this->userHasPendingLoginIntent() ) {
|
73 |
+
$oDp = $this->loadDP();
|
74 |
|
75 |
$bIsLoginIntentSubmission = $oDp->FetchRequest( $oFO->getLoginIntentRequestFlag() ) == 1;
|
76 |
if ( $bIsLoginIntentSubmission ) {
|
77 |
|
78 |
+
if ( $oDp->post( 'cancel' ) == 1 ) {
|
79 |
$this->loadWpUsers()->logoutUser(); // clears the login and login intent
|
80 |
$this->loadWp()->redirectToLogin();
|
81 |
return;
|
92 |
|
93 |
if ( $bLoginIntentValidated ) {
|
94 |
$this->removeLoginIntent();
|
95 |
+
$sRedirect = $oDp->post( 'redirect_to' );
|
96 |
$this->loadAdminNoticesProcessor()->addFlashMessage(
|
97 |
_wpsf__( 'Success' ).'! '._wpsf__( 'Thank you for authenticating your login.' ) );
|
98 |
if ( !empty( $sRedirect ) ) {
|
99 |
+
// $this->loadWp()->doRedirect( site_url( rawurldecode( $sRedirect ) ) );
|
100 |
}
|
101 |
}
|
102 |
else {
|
144 |
}
|
145 |
|
146 |
/**
|
147 |
+
* @param int $nExpirationTime
|
148 |
* @param null $oUser
|
149 |
*/
|
150 |
protected function setLoginIntentExpiration( $nExpirationTime, $oUser = null ) {
|
170 |
$oF->prefix( 'login_intent_timeout' ),
|
171 |
$oF->getDefinition( 'login_intent_timeout' )
|
172 |
);
|
173 |
+
$this->setLoginIntentExpiration( $this->time() + MINUTE_IN_SECONDS*$nTimeout, $oUser );
|
174 |
}
|
175 |
return $oUser;
|
176 |
}
|
226 |
$sMessageType = 'warning';
|
227 |
}
|
228 |
|
229 |
+
$sRedirectTo = rawurlencode( $this->loadDP()->getRequestUri() ); // not actually used
|
|
|
|
|
|
|
230 |
|
231 |
$aDisplayData = array(
|
232 |
'strings' => array(
|
233 |
'cancel' => _wpsf__( 'Cancel Login' ),
|
234 |
'time_remaining' => _wpsf__( 'Time Remaining' ),
|
235 |
+
'calculating' => _wpsf__( 'Calculating' ).' ...',
|
236 |
'seconds' => strtolower( _wpsf__( 'Seconds' ) ),
|
237 |
'login_expired' => _wpsf__( 'Login Expired' ),
|
238 |
'verify_my_login' => _wpsf__( 'Verify My Login' ),
|
270 |
* @return ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth
|
271 |
*/
|
272 |
protected function getProcessorTwoFactor() {
|
273 |
+
require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'loginprotect_twofactorauth.php' );
|
274 |
/** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
|
275 |
$oFO = $this->getFeature();
|
276 |
$oProc = new ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth( $oFO );
|
281 |
* @return ICWP_WPSF_Processor_LoginProtect_Yubikey
|
282 |
*/
|
283 |
protected function getProcessorYubikey() {
|
284 |
+
require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'loginprotect_yubikey.php' );
|
285 |
$oProc = new ICWP_WPSF_Processor_LoginProtect_Yubikey( $this->getFeature() );
|
286 |
return $oProc->setLoginTrack( $this->getLoginTrack() );
|
287 |
}
|
289 |
/**
|
290 |
* @return ICWP_WPSF_Processor_LoginProtect_GoogleAuthenticator
|
291 |
*/
|
292 |
+
public function getProcessorGoogleAuthenticator() {
|
293 |
+
require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'loginprotect_googleauthenticator.php' );
|
294 |
$oProc = new ICWP_WPSF_Processor_LoginProtect_GoogleAuthenticator( $this->getFeature() );
|
295 |
return $oProc->setLoginTrack( $this->getLoginTrack() );
|
296 |
}
|
300 |
*/
|
301 |
public function getLoginTrack() {
|
302 |
if ( !isset( $this->oLoginTrack ) ) {
|
303 |
+
require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'loginprotect_track.php' );
|
304 |
$this->oLoginTrack = new ICWP_WPSF_Processor_LoginProtect_Track();
|
305 |
}
|
306 |
return $this->oLoginTrack;
|
src/processors/loginprotect_intent_base.php
CHANGED
@@ -4,7 +4,7 @@ if ( class_exists( 'ICWP_WPSF_Processor_LoginProtect_IntentBase', false ) ) {
|
|
4 |
return;
|
5 |
}
|
6 |
|
7 |
-
require_once( dirname(__FILE__).DIRECTORY_SEPARATOR.'base_wpsf.php' );
|
8 |
|
9 |
abstract class ICWP_WPSF_Processor_LoginProtect_IntentBase extends ICWP_WPSF_Processor_BaseWpsf {
|
10 |
|
@@ -83,7 +83,10 @@ abstract class ICWP_WPSF_Processor_LoginProtect_IntentBase extends ICWP_WPSF_Pro
|
|
83 |
*/
|
84 |
protected function getSecret( WP_User $oUser ) {
|
85 |
$oWpUser = $this->loadWpUsers();
|
86 |
-
$sSecret = $oWpUser->getUserMeta(
|
|
|
|
|
|
|
87 |
if ( empty( $sSecret ) ) {
|
88 |
$this->resetSecret( $oUser );
|
89 |
}
|
@@ -102,10 +105,10 @@ abstract class ICWP_WPSF_Processor_LoginProtect_IntentBase extends ICWP_WPSF_Pro
|
|
102 |
|
103 |
/**
|
104 |
* @param WP_User $oUser
|
105 |
-
* @param bool
|
106 |
* @return $this
|
107 |
*/
|
108 |
-
|
109 |
$this->loadWpUsers()
|
110 |
->updateUserMeta(
|
111 |
$this->getFeature()->prefixOptionKey( $this->getStub().'_validated' ),
|
@@ -117,7 +120,7 @@ abstract class ICWP_WPSF_Processor_LoginProtect_IntentBase extends ICWP_WPSF_Pro
|
|
117 |
|
118 |
/**
|
119 |
* @param WP_User $oUser
|
120 |
-
* @param
|
121 |
* @return $this
|
122 |
*/
|
123 |
protected function setSecret( $oUser, $sNewSecret ) {
|
@@ -208,7 +211,7 @@ abstract class ICWP_WPSF_Processor_LoginProtect_IntentBase extends ICWP_WPSF_Pro
|
|
208 |
* @return string
|
209 |
*/
|
210 |
protected function fetchCodeFromRequest() {
|
211 |
-
return esc_attr( trim( $this->
|
212 |
}
|
213 |
|
214 |
/**
|
4 |
return;
|
5 |
}
|
6 |
|
7 |
+
require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'base_wpsf.php' );
|
8 |
|
9 |
abstract class ICWP_WPSF_Processor_LoginProtect_IntentBase extends ICWP_WPSF_Processor_BaseWpsf {
|
10 |
|
83 |
*/
|
84 |
protected function getSecret( WP_User $oUser ) {
|
85 |
$oWpUser = $this->loadWpUsers();
|
86 |
+
$sSecret = $oWpUser->getUserMeta(
|
87 |
+
$this->getFeature()->prefixOptionKey( $this->getStub().'_secret' ),
|
88 |
+
$oUser->ID
|
89 |
+
);
|
90 |
if ( empty( $sSecret ) ) {
|
91 |
$this->resetSecret( $oUser );
|
92 |
}
|
105 |
|
106 |
/**
|
107 |
* @param WP_User $oUser
|
108 |
+
* @param bool $bValidated set true for validated, false for invalidated
|
109 |
* @return $this
|
110 |
*/
|
111 |
+
public function setProfileValidated( $oUser, $bValidated = true ) {
|
112 |
$this->loadWpUsers()
|
113 |
->updateUserMeta(
|
114 |
$this->getFeature()->prefixOptionKey( $this->getStub().'_validated' ),
|
120 |
|
121 |
/**
|
122 |
* @param WP_User $oUser
|
123 |
+
* @param $sNewSecret
|
124 |
* @return $this
|
125 |
*/
|
126 |
protected function setSecret( $oUser, $sNewSecret ) {
|
211 |
* @return string
|
212 |
*/
|
213 |
protected function fetchCodeFromRequest() {
|
214 |
+
return esc_attr( trim( $this->loadDP()->FetchRequest( $this->getLoginFormParameter(), false, '' ) ) );
|
215 |
}
|
216 |
|
217 |
/**
|
src/processors/loginprotect_twofactorauth.php
CHANGED
@@ -160,38 +160,6 @@ class ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth extends ICWP_WPSF_Processor
|
|
160 |
return $this->loadWpUsers()->getUserMeta( $this->get2FaCodeUserMetaKey() );
|
161 |
}
|
162 |
|
163 |
-
/**
|
164 |
-
* Given the necessary components, creates the 2-factor verification link for giving to the user.
|
165 |
-
* @param string $sUser
|
166 |
-
* @param string $sSessionId
|
167 |
-
* @return string
|
168 |
-
*/
|
169 |
-
protected function generateTwoFactorVerifyLink( $sUser, $sSessionId ) {
|
170 |
-
$sUrl = $this->buildTwoFactorVerifyUrl( $sUser, $sSessionId );
|
171 |
-
return sprintf( '<a href="%s" target="_blank">%s</a>', $sUrl, $sUrl );
|
172 |
-
}
|
173 |
-
|
174 |
-
/**
|
175 |
-
* @param string $sUser
|
176 |
-
* @param string $sSessionId
|
177 |
-
* @return string
|
178 |
-
*/
|
179 |
-
protected function buildTwoFactorVerifyUrl( $sUser, $sSessionId ) {
|
180 |
-
/** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
|
181 |
-
$oFO = $this->getFeature();
|
182 |
-
$aQueryArgs = array(
|
183 |
-
$this->getLoginFormParameter() => $this->getSessionHashCode(),
|
184 |
-
$oFO->getLoginIntentRequestFlag() => 1,
|
185 |
-
'username' => rawurlencode( $sUser ),
|
186 |
-
'sessionid' => $sSessionId
|
187 |
-
);
|
188 |
-
$sRedirectTo = esc_url( $this->loadDataProcessor()->FetchPost( 'redirect_to' ) );
|
189 |
-
if ( !empty( $sRedirectTo ) ) {
|
190 |
-
$aQueryArgs[ 'redirect_to' ] = urlencode( $sRedirectTo );
|
191 |
-
}
|
192 |
-
return add_query_arg( $aQueryArgs, $this->loadWp()->getHomeUrl() );
|
193 |
-
}
|
194 |
-
|
195 |
/**
|
196 |
* @param WP_User $oUser
|
197 |
* @return boolean
|
@@ -201,21 +169,23 @@ class ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth extends ICWP_WPSF_Processor
|
|
201 |
$sEmail = $oUser->get( 'user_email' );
|
202 |
|
203 |
$aMessage = array(
|
204 |
-
_wpsf__( '
|
205 |
-
_wpsf__( '
|
|
|
|
|
206 |
sprintf( _wpsf__( 'Username: %s' ), $oUser->get( 'user_login' ) ),
|
207 |
sprintf( _wpsf__( 'IP Address: %s' ), $sIpAddress ),
|
208 |
-
_wpsf__( 'Use the following code in the Login Verification page.' ),
|
209 |
'',
|
210 |
-
|
|
|
211 |
'',
|
212 |
-
sprintf( '<a href="%s" target="_blank">%s</a>', 'http://icwp.io/96', _wpsf__( 'Why no login link?' ) ),
|
213 |
''
|
214 |
);
|
215 |
-
$sEmailSubject = sprintf( _wpsf__( 'Two-Factor Login Verification
|
216 |
-
->getHomeUrl() );
|
217 |
|
218 |
-
$bResult = $this->getEmailProcessor()
|
|
|
219 |
if ( $bResult ) {
|
220 |
$sAuditMessage = sprintf( _wpsf__( 'User "%s" was sent an email to verify their Identity using Two-Factor Login Auth for IP address "%s".' ), $oUser->get( 'user_login' ), $sIpAddress );
|
221 |
$this->addToAuditEntry( $sAuditMessage, 2, 'login_protect_two_factor_email_send' );
|
160 |
return $this->loadWpUsers()->getUserMeta( $this->get2FaCodeUserMetaKey() );
|
161 |
}
|
162 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
163 |
/**
|
164 |
* @param WP_User $oUser
|
165 |
* @return boolean
|
169 |
$sEmail = $oUser->get( 'user_email' );
|
170 |
|
171 |
$aMessage = array(
|
172 |
+
_wpsf__( 'Someone just attempted to login into your WordPress site.' ),
|
173 |
+
_wpsf__( 'Login for this user account requires verification.' ),
|
174 |
+
'',
|
175 |
+
sprintf( '<strong>%s</strong>', _wpsf__( 'Login Details' ) ),
|
176 |
sprintf( _wpsf__( 'Username: %s' ), $oUser->get( 'user_login' ) ),
|
177 |
sprintf( _wpsf__( 'IP Address: %s' ), $sIpAddress ),
|
|
|
178 |
'',
|
179 |
+
_wpsf__( 'Use the following code on the Login Verification page.' ),
|
180 |
+
sprintf( _wpsf__( 'Verification Code: %s' ), sprintf( '<strong>%s</strong>', $this->getSessionHashCode() ) ),
|
181 |
'',
|
182 |
+
sprintf( '(<a href="%s" target="_blank">%s</a>)', 'http://icwp.io/96', _wpsf__( 'Why no login link?' ) ),
|
183 |
''
|
184 |
);
|
185 |
+
$sEmailSubject = sprintf( _wpsf__( '[%s] Two-Factor Login Verification' ), $this->loadWp()->getSiteName() );
|
|
|
186 |
|
187 |
+
$bResult = $this->getEmailProcessor()
|
188 |
+
->sendEmailTo( $sEmail, $sEmailSubject, $aMessage );
|
189 |
if ( $bResult ) {
|
190 |
$sAuditMessage = sprintf( _wpsf__( 'User "%s" was sent an email to verify their Identity using Two-Factor Login Auth for IP address "%s".' ), $oUser->get( 'user_login' ), $sIpAddress );
|
191 |
$this->addToAuditEntry( $sAuditMessage, 2, 'login_protect_two_factor_email_send' );
|
src/processors/plugin.php
CHANGED
@@ -8,11 +8,6 @@ require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'base_plugin.php' );
|
|
8 |
|
9 |
class ICWP_WPSF_Processor_Plugin extends ICWP_WPSF_Processor_BasePlugin {
|
10 |
|
11 |
-
/**
|
12 |
-
* @var ICWP_WPSF_Processor_Plugin_SetupWizard
|
13 |
-
*/
|
14 |
-
protected $oSetupWizardProcessor;
|
15 |
-
|
16 |
/**
|
17 |
* @var ICWP_WPSF_Processor_Plugin_Badge
|
18 |
*/
|
@@ -54,13 +49,6 @@ class ICWP_WPSF_Processor_Plugin extends ICWP_WPSF_Processor_BasePlugin {
|
|
54 |
$this->getSubProcessorImportExport()->runAction();
|
55 |
}
|
56 |
break;
|
57 |
-
|
58 |
-
case 'wizard':
|
59 |
-
if ( $oDP->getPhpVersionIsAtLeast( 5.4 ) ) {
|
60 |
-
$this->getWizardProcessor()->run();
|
61 |
-
}
|
62 |
-
break;
|
63 |
-
|
64 |
default:
|
65 |
break;
|
66 |
}
|
@@ -83,17 +71,6 @@ class ICWP_WPSF_Processor_Plugin extends ICWP_WPSF_Processor_BasePlugin {
|
|
83 |
return $this->oBadgeProcessor;
|
84 |
}
|
85 |
|
86 |
-
/**
|
87 |
-
* @return ICWP_WPSF_Processor_Plugin_SetupWizard
|
88 |
-
*/
|
89 |
-
public function getWizardProcessor() {
|
90 |
-
if ( !isset( $this->oSetupWizardProcessor ) ) {
|
91 |
-
require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'plugin_setupwizard.php' );
|
92 |
-
$this->oSetupWizardProcessor = new ICWP_WPSF_Processor_Plugin_SetupWizard( $this->getFeature() );
|
93 |
-
}
|
94 |
-
return $this->oSetupWizardProcessor;
|
95 |
-
}
|
96 |
-
|
97 |
/**
|
98 |
* @return ICWP_WPSF_Processor_Plugin_Tracking
|
99 |
*/
|
8 |
|
9 |
class ICWP_WPSF_Processor_Plugin extends ICWP_WPSF_Processor_BasePlugin {
|
10 |
|
|
|
|
|
|
|
|
|
|
|
11 |
/**
|
12 |
* @var ICWP_WPSF_Processor_Plugin_Badge
|
13 |
*/
|
49 |
$this->getSubProcessorImportExport()->runAction();
|
50 |
}
|
51 |
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
default:
|
53 |
break;
|
54 |
}
|
71 |
return $this->oBadgeProcessor;
|
72 |
}
|
73 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
/**
|
75 |
* @return ICWP_WPSF_Processor_Plugin_Tracking
|
76 |
*/
|
src/processors/plugin_setupwizard.php
DELETED
@@ -1,830 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
if ( class_exists( 'ICWP_WPSF_Processor_Plugin_SetupWizard', false ) ) {
|
4 |
-
return;
|
5 |
-
}
|
6 |
-
|
7 |
-
require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'base_wpsf.php' );
|
8 |
-
|
9 |
-
/**
|
10 |
-
* @uses php 5.4+
|
11 |
-
* Class ICWP_WPSF_Processor_Plugin_SetupWizard
|
12 |
-
*/
|
13 |
-
class ICWP_WPSF_Processor_Plugin_SetupWizard extends ICWP_WPSF_Processor_BaseWpsf {
|
14 |
-
|
15 |
-
/**
|
16 |
-
* @var string
|
17 |
-
*/
|
18 |
-
private $sCurrentWizard;
|
19 |
-
|
20 |
-
/**
|
21 |
-
*/
|
22 |
-
public function run() {
|
23 |
-
add_action( 'init', array( $this, 'onWpInit' ), 0 );
|
24 |
-
}
|
25 |
-
|
26 |
-
public function onWpInit() {
|
27 |
-
if ( $this->loadWpUsers()->isUserAdmin() ) {
|
28 |
-
$this->loadWizard( (string)$this->loadDP()->query( 'wizard', '' ) );
|
29 |
-
}
|
30 |
-
}
|
31 |
-
|
32 |
-
/**
|
33 |
-
* @param string $sWizard
|
34 |
-
* @throws Exception
|
35 |
-
*/
|
36 |
-
protected function loadWizard( $sWizard ) {
|
37 |
-
|
38 |
-
$sContent = '';
|
39 |
-
$this->setCurrentWizard( $sWizard );
|
40 |
-
switch ( $sWizard ) {
|
41 |
-
case 'welcome':
|
42 |
-
$sContent = $this->renderWizardWelcome();
|
43 |
-
break;
|
44 |
-
case 'import':
|
45 |
-
$sContent = $this->renderWizardImport();
|
46 |
-
break;
|
47 |
-
default:
|
48 |
-
$this->loadWp()->redirectToAdmin();
|
49 |
-
break;
|
50 |
-
}
|
51 |
-
echo $sContent;
|
52 |
-
die();
|
53 |
-
}
|
54 |
-
|
55 |
-
/**
|
56 |
-
*/
|
57 |
-
public function ajaxSetupWizardSteps() {
|
58 |
-
$oDP = $this->loadDP();
|
59 |
-
|
60 |
-
$this->setCurrentWizard( $oDP->post( 'wizard_slug' ) );
|
61 |
-
$aNextStep = $this->getWizardNextStep( $oDP->post( 'wizard_steps' ), $oDP->post( 'current_index' ) );
|
62 |
-
|
63 |
-
return $this->getFeature()
|
64 |
-
->sendAjaxResponse(
|
65 |
-
true,
|
66 |
-
array( 'next_step' => $aNextStep )
|
67 |
-
);
|
68 |
-
}
|
69 |
-
|
70 |
-
public function ajaxSetupWizardContent() {
|
71 |
-
$oDP = $this->loadDP();
|
72 |
-
|
73 |
-
$this->loadAutoload(); // for Response
|
74 |
-
switch ( $oDP->post( 'wizard-step' ) ) {
|
75 |
-
|
76 |
-
case 'admin_access_restriction_verify':
|
77 |
-
$oResponse = $this->wizardSecurityAdminVerify();
|
78 |
-
break;
|
79 |
-
|
80 |
-
case 'license':
|
81 |
-
$oResponse = $this->wizardLicense();
|
82 |
-
break;
|
83 |
-
|
84 |
-
case 'import_options':
|
85 |
-
$oResponse = $this->wizardImportOptions();
|
86 |
-
break;
|
87 |
-
|
88 |
-
case 'admin_access_restriction':
|
89 |
-
$oResponse = $this->wizardSecurityAdmin();
|
90 |
-
break;
|
91 |
-
|
92 |
-
case 'audit_trail':
|
93 |
-
$oResponse = $this->wizardAuditTrail();
|
94 |
-
break;
|
95 |
-
|
96 |
-
case 'ips':
|
97 |
-
$oResponse = $this->wizardIps();
|
98 |
-
break;
|
99 |
-
|
100 |
-
case 'comments_filter':
|
101 |
-
$oResponse = $this->wizardCommentsFilter();
|
102 |
-
break;
|
103 |
-
|
104 |
-
case 'login_protect':
|
105 |
-
$oResponse = $this->wizardLoginProtect();
|
106 |
-
break;
|
107 |
-
|
108 |
-
case 'optin':
|
109 |
-
$oResponse = $this->wizardOptin();
|
110 |
-
break;
|
111 |
-
|
112 |
-
default:
|
113 |
-
$oResponse = new \FernleafSystems\Utilities\Response();
|
114 |
-
$oResponse->setSuccessful( false )
|
115 |
-
->setMessageText( _wpsf__( 'Unknown request' ) );
|
116 |
-
break;
|
117 |
-
}
|
118 |
-
|
119 |
-
$sMessage = $oResponse->getMessageText();
|
120 |
-
if ( $oResponse->successful() ) {
|
121 |
-
$sMessage .= '<br />'.sprintf( _wpsf__( 'Please click %s to continue.' ), _wpsf__( 'Next' ) );
|
122 |
-
}
|
123 |
-
else {
|
124 |
-
$sMessage = sprintf( '%s: %s', _wpsf__( 'Error' ), $sMessage );
|
125 |
-
}
|
126 |
-
|
127 |
-
$aData = $oResponse->getData();
|
128 |
-
$aData[ 'message' ] = $sMessage;
|
129 |
-
|
130 |
-
$this->getFeature()
|
131 |
-
->sendAjaxResponse( $oResponse->successful(), $aData );
|
132 |
-
}
|
133 |
-
|
134 |
-
/**
|
135 |
-
* @return string
|
136 |
-
* @throws Exception
|
137 |
-
*/
|
138 |
-
protected function renderWizardImport() {
|
139 |
-
return $this->renderWizard();
|
140 |
-
}
|
141 |
-
|
142 |
-
/**
|
143 |
-
* @return string
|
144 |
-
* @throws Exception
|
145 |
-
*/
|
146 |
-
protected function renderWizardWelcome() {
|
147 |
-
return $this->renderWizard();
|
148 |
-
}
|
149 |
-
|
150 |
-
/**
|
151 |
-
* @return string
|
152 |
-
* @throws Exception
|
153 |
-
*/
|
154 |
-
protected function renderWizard() {
|
155 |
-
/** @var ICWP_WPSF_FeatureHandler_Plugin $oFO */
|
156 |
-
$oFO = $this->getFeature();
|
157 |
-
$oCon = $this->getController();
|
158 |
-
|
159 |
-
$sMessage = $this->loadAdminNoticesProcessor()
|
160 |
-
->flushFlashMessage()
|
161 |
-
->getRawFlashMessageText();
|
162 |
-
|
163 |
-
$aDisplayData = array(
|
164 |
-
'strings' => array(
|
165 |
-
'welcome' => _wpsf__( 'Welcome' ),
|
166 |
-
'time_remaining' => _wpsf__( 'Time Remaining' ),
|
167 |
-
'calculating' => _wpsf__( 'Calculating' ).' ...',
|
168 |
-
'seconds' => strtolower( _wpsf__( 'Seconds' ) ),
|
169 |
-
'login_expired' => _wpsf__( 'Login Expired' ),
|
170 |
-
'verify_my_login' => _wpsf__( 'Verify My Login' ),
|
171 |
-
'more_info' => _wpsf__( 'More Info' ),
|
172 |
-
'what_is_this' => _wpsf__( 'What is this?' ),
|
173 |
-
'message' => $sMessage,
|
174 |
-
'page_title' => sprintf( _wpsf__( '%s Setup Wizard' ), $oCon->getHumanName() )
|
175 |
-
),
|
176 |
-
'data' => array(
|
177 |
-
'wizard_slug' => $this->getCurrentWizard(),
|
178 |
-
'wizard_steps' => json_encode( $this->determineWizardSteps() ),
|
179 |
-
'wizard_first_step' => json_encode( $this->getWizardFirstStep() ),
|
180 |
-
),
|
181 |
-
'hrefs' => array(
|
182 |
-
'form_action' => $this->loadDataProcessor()->getRequestUri(),
|
183 |
-
'css_bootstrap' => $oCon->getPluginUrl_Css( 'bootstrap3.min.css' ),
|
184 |
-
'css_pages' => $oCon->getPluginUrl_Css( 'pages.css' ),
|
185 |
-
'css_steps' => $oCon->getPluginUrl_Css( 'jquery.steps.css' ),
|
186 |
-
'css_fancybox' => $oCon->getPluginUrl_Css( 'jquery.fancybox.min.css' ),
|
187 |
-
'css_globalplugin' => $oCon->getPluginUrl_Css( 'global-plugin.css' ),
|
188 |
-
'css_wizard' => $oCon->getPluginUrl_Css( 'wizard.css' ),
|
189 |
-
'js_jquery' => $this->loadWpIncludes()->getUrl_Jquery(),
|
190 |
-
'js_bootstrap' => $oCon->getPluginUrl_Js( 'bootstrap3.min.js' ),
|
191 |
-
'js_fancybox' => $oCon->getPluginUrl_Js( 'jquery.fancybox.min.js' ),
|
192 |
-
'js_globalplugin' => $oCon->getPluginUrl_Js( 'global-plugin.js' ),
|
193 |
-
'js_steps' => $oCon->getPluginUrl_Js( 'jquery.steps.min.js' ),
|
194 |
-
'js_wizard' => $oCon->getPluginUrl_Js( 'wizard.js' ),
|
195 |
-
'shield_logo' => 'https://plugins.svn.wordpress.org/wp-simple-firewall/assets/banner-1544x500-transparent.png',
|
196 |
-
'what_is_this' => 'https://icontrolwp.freshdesk.com/support/solutions/articles/3000064840',
|
197 |
-
'favicon' => $oCon->getPluginUrl_Image( 'pluginlogo_24x24.png' ),
|
198 |
-
),
|
199 |
-
'ajax' => array(
|
200 |
-
'content' => $oFO->getBaseAjaxActionRenderData( 'SetupWizardContent' ),
|
201 |
-
'steps' => $oFO->getBaseAjaxActionRenderData( 'SetupWizardSteps' ),
|
202 |
-
'steps_as_json' => $oFO->getBaseAjaxActionRenderData( 'SetupWizardSteps', true ),
|
203 |
-
)
|
204 |
-
);
|
205 |
-
|
206 |
-
return $this->loadRenderer( $this->getController()->getPath_Templates() )
|
207 |
-
->setTemplate( 'pages/wizard.twig' )
|
208 |
-
->setRenderVars( $aDisplayData )
|
209 |
-
->setTemplateEngineTwig()
|
210 |
-
->render();
|
211 |
-
}
|
212 |
-
|
213 |
-
/**
|
214 |
-
* @return string[]
|
215 |
-
*/
|
216 |
-
protected function determineWizardSteps() {
|
217 |
-
|
218 |
-
switch ( $this->getCurrentWizard() ) {
|
219 |
-
case 'welcome':
|
220 |
-
$aSteps = $this->determineWizardSteps_Welcome();
|
221 |
-
break;
|
222 |
-
case 'import':
|
223 |
-
$aSteps = $this->determineWizardSteps_Import();
|
224 |
-
break;
|
225 |
-
default:
|
226 |
-
$aSteps = array();
|
227 |
-
break;
|
228 |
-
}
|
229 |
-
|
230 |
-
return $aSteps;
|
231 |
-
}
|
232 |
-
|
233 |
-
/**
|
234 |
-
* @return string[]
|
235 |
-
*/
|
236 |
-
private function determineWizardSteps_Import() {
|
237 |
-
/** @var ICWP_WPSF_FeatureHandler_Plugin $oFO */
|
238 |
-
$oFO = $this->getFeature();
|
239 |
-
|
240 |
-
// Special case: user doesn't meet even the basic plugin admin permissions
|
241 |
-
if ( !$oFO->getController()->getUserCanBasePerms() ) {
|
242 |
-
return array( 'no_access' );
|
243 |
-
}
|
244 |
-
|
245 |
-
$aStepsSlugs = array(
|
246 |
-
'import_start',
|
247 |
-
'import_options',
|
248 |
-
'import_finished',
|
249 |
-
);
|
250 |
-
|
251 |
-
return $aStepsSlugs;
|
252 |
-
}
|
253 |
-
|
254 |
-
/**
|
255 |
-
* @return string[]
|
256 |
-
*/
|
257 |
-
private function determineWizardSteps_Welcome() {
|
258 |
-
/** @var ICWP_WPSF_FeatureHandler_Plugin $oFO */
|
259 |
-
$oFO = $this->getFeature();
|
260 |
-
|
261 |
-
// Special case: user doesn't meet even the basic plugin admin permissions
|
262 |
-
if ( !$oFO->getController()->getUserCanBasePerms() ) {
|
263 |
-
return array( 'no_access' );
|
264 |
-
}
|
265 |
-
|
266 |
-
$aStepsSlugs = array( 'welcome' );
|
267 |
-
if ( !$oFO->isPremium() ) {
|
268 |
-
// $aStepsSlugs[] = 'license'; not showing it for now
|
269 |
-
}
|
270 |
-
|
271 |
-
if ( $oFO->isPremium() ) {
|
272 |
-
$aStepsSlugs[] = 'import_options';
|
273 |
-
}
|
274 |
-
|
275 |
-
if ( !$this->getController()->getModule( 'admin_access_restriction' )->getIsMainFeatureEnabled() ) {
|
276 |
-
$aStepsSlugs[] = 'admin_access_restriction';
|
277 |
-
}
|
278 |
-
|
279 |
-
/** @var ICWP_WPSF_FeatureHandler_AuditTrail $oModule */
|
280 |
-
$oModule = $this->getController()->getModule( 'audit_trail' );
|
281 |
-
if ( !$oModule->getIsMainFeatureEnabled() ) {
|
282 |
-
$aStepsSlugs[] = 'audit_trail';
|
283 |
-
}
|
284 |
-
|
285 |
-
if ( !$this->getController()->getModule( 'ips' )->getIsMainFeatureEnabled() ) {
|
286 |
-
$aStepsSlugs[] = 'ips';
|
287 |
-
}
|
288 |
-
|
289 |
-
/** @var ICWP_WPSF_FeatureHandler_LoginProtect $oModule */
|
290 |
-
$oModule = $this->getController()->getModule( 'login_protect' );
|
291 |
-
if ( !( $oModule->getIsMainFeatureEnabled() && $oModule->isEnabledGaspCheck() ) ) {
|
292 |
-
$aStepsSlugs[] = 'login_protect';
|
293 |
-
}
|
294 |
-
|
295 |
-
/** @var ICWP_WPSF_FeatureHandler_CommentsFilter $oModule */
|
296 |
-
$oModule = $this->getController()->getModule( 'comments_filter' );
|
297 |
-
if ( !( $oModule->getIsMainFeatureEnabled() && $oModule->isEnabledGaspCheck() ) ) {
|
298 |
-
$aStepsSlugs[] = 'comments_filter';
|
299 |
-
}
|
300 |
-
|
301 |
-
$aStepsSlugs[] = 'how_shield_works';
|
302 |
-
$aStepsSlugs[] = 'optin';
|
303 |
-
|
304 |
-
if ( !$oFO->isPremium() ) {
|
305 |
-
$aStepsSlugs[] = 'import_options';
|
306 |
-
}
|
307 |
-
|
308 |
-
$aStepsSlugs[] = 'thankyou';
|
309 |
-
return $aStepsSlugs;
|
310 |
-
}
|
311 |
-
|
312 |
-
/**
|
313 |
-
* @return array
|
314 |
-
*/
|
315 |
-
protected function getWizardFirstStep() {
|
316 |
-
return $this->getWizardNextStep( $this->determineWizardSteps(), -1 );
|
317 |
-
}
|
318 |
-
|
319 |
-
/**
|
320 |
-
* @param array $aAllSteps
|
321 |
-
* @param int $nCurrentStep
|
322 |
-
* @return array
|
323 |
-
*/
|
324 |
-
protected function getWizardNextStep( $aAllSteps, $nCurrentStep ) {
|
325 |
-
|
326 |
-
// The assumption here is that the step data exists!
|
327 |
-
$aStepData = $this->getWizardSteps()[ $aAllSteps[ $nCurrentStep + 1 ] ];
|
328 |
-
|
329 |
-
$bRestrictedAccess = !isset( $aStepData[ 'restricted_access' ] ) || $aStepData[ 'restricted_access' ];
|
330 |
-
try {
|
331 |
-
if ( !$bRestrictedAccess || $this->getController()->getHasPermissionToManage() ) {
|
332 |
-
$aData = $this->getRenderDataForStep( $aStepData[ 'slug' ] );
|
333 |
-
$aStepData[ 'content' ] = $this->renderWizardStep( $aStepData[ 'slug' ], $aData );
|
334 |
-
}
|
335 |
-
else {
|
336 |
-
$aStepData[ 'content' ] = $this->renderSecurityAdminVerifyWizardStep( $nCurrentStep );
|
337 |
-
}
|
338 |
-
}
|
339 |
-
catch ( Exception $oE ) {
|
340 |
-
$aStepData[ 'content' ] = 'Content could not be displayed due to error: '.$oE->getMessage();
|
341 |
-
}
|
342 |
-
|
343 |
-
return $aStepData;
|
344 |
-
}
|
345 |
-
|
346 |
-
/**
|
347 |
-
* @param int $nIndex
|
348 |
-
* @return string
|
349 |
-
* @throws Exception
|
350 |
-
*/
|
351 |
-
protected function renderSecurityAdminVerifyWizardStep( $nIndex ) {
|
352 |
-
return $this->renderWizardStep( 'admin_access_restriction_verify', array( 'current_index' => $nIndex ) );
|
353 |
-
}
|
354 |
-
|
355 |
-
/**
|
356 |
-
* @param string $sSlug
|
357 |
-
* @return array
|
358 |
-
*/
|
359 |
-
protected function getRenderDataForStep( $sSlug ) {
|
360 |
-
/** @var ICWP_WPSF_FeatureHandler_Plugin $oFO */
|
361 |
-
$oFO = $this->getFeature();
|
362 |
-
$oConn = $this->getController();
|
363 |
-
|
364 |
-
$aData = array(
|
365 |
-
'flags' => array(
|
366 |
-
'is_premium' => $oFO->isPremium()
|
367 |
-
),
|
368 |
-
'hrefs' => array(
|
369 |
-
'dashboard' => $oFO->getFeatureAdminPageUrl(),
|
370 |
-
'gopro' => 'http://icwp.io/ap',
|
371 |
-
),
|
372 |
-
'imgs' => array(),
|
373 |
-
);
|
374 |
-
|
375 |
-
$aAdd = array();
|
376 |
-
|
377 |
-
switch ( $sSlug ) {
|
378 |
-
case 'license':
|
379 |
-
break;
|
380 |
-
case 'import_options':
|
381 |
-
$aAdd = array(
|
382 |
-
'hrefs' => array(
|
383 |
-
'blog_importexport' => 'http://icwp.io/av'
|
384 |
-
),
|
385 |
-
'imgs' => array(
|
386 |
-
'shieldnetworkmini' => $oConn->getPluginUrl_Image( 'shield/shieldnetworkmini.png' ),
|
387 |
-
)
|
388 |
-
);
|
389 |
-
break;
|
390 |
-
|
391 |
-
case 'optin':
|
392 |
-
$oUser = $this->loadWpUsers()->getCurrentWpUser();
|
393 |
-
$aAdd = array(
|
394 |
-
'data' => array(
|
395 |
-
'name' => $oUser->first_name,
|
396 |
-
'user_email' => $oUser->user_email
|
397 |
-
)
|
398 |
-
);
|
399 |
-
break;
|
400 |
-
|
401 |
-
case 'no_access':
|
402 |
-
case 'thankyou':
|
403 |
-
break;
|
404 |
-
|
405 |
-
case 'how_shield_works':
|
406 |
-
$aAdd = array(
|
407 |
-
'imgs' => array(
|
408 |
-
'how_shield_works' => $oConn->getPluginUrl_Image( 'wizard/general-shield_where.png' ),
|
409 |
-
'modules' => $oConn->getPluginUrl_Image( 'wizard/general-shield_modules.png' ),
|
410 |
-
'options' => $oConn->getPluginUrl_Image( 'wizard/general-shield_options.png' ),
|
411 |
-
'help' => $oConn->getPluginUrl_Image( 'wizard/general-shield_help.png' ),
|
412 |
-
'actions' => $oConn->getPluginUrl_Image( 'wizard/general-shield_actions.png' ),
|
413 |
-
'module_onoff' => $oConn->getPluginUrl_Image( 'wizard/general-module_onoff.png' ),
|
414 |
-
'option_help' => $oConn->getPluginUrl_Image( 'wizard/general-option_help.png' ),
|
415 |
-
),
|
416 |
-
'headings' => array(
|
417 |
-
'how_shield_works' => _wpsf__( 'Where to find Shield' ),
|
418 |
-
'modules' => _wpsf__( 'Accessing Each Module' ),
|
419 |
-
'options' => _wpsf__( 'Accessing Options' ),
|
420 |
-
'help' => _wpsf__( 'Finding Help' ),
|
421 |
-
'actions' => _wpsf__( 'Actions (not Options)' ),
|
422 |
-
'module_onoff' => _wpsf__( 'Module On/Off Switch' ),
|
423 |
-
'option_help' => _wpsf__( 'Help For Each Option' ),
|
424 |
-
),
|
425 |
-
'captions' => array(
|
426 |
-
'how_shield_works' => _wpsf__( "You'll find the main Shield Security setting in the left-hand WordPress menu." ),
|
427 |
-
'modules' => _wpsf__( 'Shield is split up into independent modules for accessing the options of each feature.' ),
|
428 |
-
'options' => _wpsf__( 'When you load a module, you can access the options by clicking on the Options Panel link.' ),
|
429 |
-
'help' => _wpsf__( 'Each module also has a brief overview help section - there is more in-depth help available.' ),
|
430 |
-
'actions' => _wpsf__( 'Certain modules have extra actions and features, e.g. Audit Trail Viewer.' )
|
431 |
-
.' '._wpsf__( 'Note: Not all modules have the actions section' ),
|
432 |
-
'module_onoff' => _wpsf__( 'Each module has an Enable/Disable checkbox to turn on/off all processing for that module' ),
|
433 |
-
'option_help' => _wpsf__( 'To help you understand each option, most of them have a more info link, and/or a blog link, to read more' ),
|
434 |
-
),
|
435 |
-
);
|
436 |
-
break;
|
437 |
-
default:
|
438 |
-
break;
|
439 |
-
}
|
440 |
-
|
441 |
-
return $this->loadDP()->mergeArraysRecursive( $aData, $aAdd );
|
442 |
-
}
|
443 |
-
|
444 |
-
/**
|
445 |
-
* @param string $sSlug
|
446 |
-
* @param array $aRenderData
|
447 |
-
* @return string
|
448 |
-
* @throws Exception
|
449 |
-
*/
|
450 |
-
protected function renderWizardStep( $sSlug, $aRenderData = array() ) {
|
451 |
-
return $this->loadRenderer( $this->getController()->getPath_Templates() )
|
452 |
-
->setTemplate( sprintf( 'wizard/slide-%s.twig', $sSlug ) )
|
453 |
-
->setRenderVars( $aRenderData )
|
454 |
-
->setTemplateEngineTwig()
|
455 |
-
->render();
|
456 |
-
}
|
457 |
-
|
458 |
-
/**
|
459 |
-
* @return array[]
|
460 |
-
*/
|
461 |
-
private function getWizardSteps() {
|
462 |
-
$aStandard = array(
|
463 |
-
'import_start' => array(
|
464 |
-
'title' => _wpsf__( 'Start Import' ),
|
465 |
-
'slug' => 'import_start',
|
466 |
-
'content' => '',
|
467 |
-
'restricted_access' => false
|
468 |
-
),
|
469 |
-
'import_finished' => array(
|
470 |
-
'title' => _wpsf__( 'Import Finished' ),
|
471 |
-
'slug' => 'import_finished',
|
472 |
-
'content' => '',
|
473 |
-
'restricted_access' => false
|
474 |
-
),
|
475 |
-
'no_access' => array(
|
476 |
-
'title' => _wpsf__( 'No Access' ),
|
477 |
-
'slug' => 'no_access',
|
478 |
-
'content' => '',
|
479 |
-
'restricted_access' => false
|
480 |
-
),
|
481 |
-
'welcome' => array(
|
482 |
-
'title' => _wpsf__( 'Welcome' ),
|
483 |
-
'slug' => 'welcome',
|
484 |
-
'content' => '',
|
485 |
-
'restricted_access' => false,
|
486 |
-
),
|
487 |
-
'license' => array(
|
488 |
-
'title' => _wpsf__( 'Go Pro' ),
|
489 |
-
'slug' => 'license',
|
490 |
-
'content' => '',
|
491 |
-
),
|
492 |
-
'import_options' => array(
|
493 |
-
'title' => _wpsf__( 'Import' ),
|
494 |
-
'slug' => 'import_options',
|
495 |
-
'content' => '',
|
496 |
-
),
|
497 |
-
'admin_access_restriction' => array(
|
498 |
-
'title' => _wpsf__( 'Security Admin' ),
|
499 |
-
'slug' => 'admin_access_restriction',
|
500 |
-
'content' => '',
|
501 |
-
),
|
502 |
-
'audit_trail' => array(
|
503 |
-
'title' => _wpsf__( 'Audit Trail' ),
|
504 |
-
'slug' => 'audit_trail',
|
505 |
-
'content' => '',
|
506 |
-
),
|
507 |
-
'ips' => array(
|
508 |
-
'title' => _wpsf__( 'IP Blacklist' ),
|
509 |
-
'slug' => 'ips',
|
510 |
-
'content' => '',
|
511 |
-
),
|
512 |
-
'login_protect' => array(
|
513 |
-
'title' => _wpsf__( 'Login Protection' ),
|
514 |
-
'slug' => 'login_protect',
|
515 |
-
'content' => '',
|
516 |
-
),
|
517 |
-
'comments_filter' => array(
|
518 |
-
'title' => _wpsf__( 'Comment SPAM' ),
|
519 |
-
'slug' => 'comments_filter',
|
520 |
-
'content' => '',
|
521 |
-
),
|
522 |
-
'how_shield_works' => array(
|
523 |
-
'title' => _wpsf__( 'How Shield Works' ),
|
524 |
-
'slug' => 'how_shield_works',
|
525 |
-
'content' => '',
|
526 |
-
'restricted_access' => false,
|
527 |
-
),
|
528 |
-
'optin' => array(
|
529 |
-
'title' => _wpsf__( 'Join Us!' ),
|
530 |
-
'slug' => 'optin',
|
531 |
-
'content' => '',
|
532 |
-
),
|
533 |
-
'thankyou' => array(
|
534 |
-
'title' => _wpsf__( 'Thank You' ),
|
535 |
-
'slug' => 'thankyou',
|
536 |
-
'content' => '',
|
537 |
-
'restricted_access' => false,
|
538 |
-
)
|
539 |
-
);
|
540 |
-
|
541 |
-
return $aStandard;
|
542 |
-
}
|
543 |
-
|
544 |
-
/**
|
545 |
-
* @return \FernleafSystems\Utilities\Response
|
546 |
-
*/
|
547 |
-
private function wizardLicense() {
|
548 |
-
$sKey = $this->loadDP()->post( 'LicenseKey' );
|
549 |
-
|
550 |
-
$bSuccess = false;
|
551 |
-
if ( empty( $sKey ) ) {
|
552 |
-
$sMessage = 'License key was empty.';
|
553 |
-
}
|
554 |
-
else {
|
555 |
-
/** @var ICWP_WPSF_FeatureHandler_License $oModule */
|
556 |
-
$oModule = $this->getController()->getModule( 'license' );
|
557 |
-
try {
|
558 |
-
$oModule->activateOfficialLicense( $sKey, true );
|
559 |
-
if ( $oModule->hasValidWorkingLicense() ) {
|
560 |
-
$bSuccess = true;
|
561 |
-
$sMessage = _wpsf__( 'License key was accepted and installed successfully.' );
|
562 |
-
}
|
563 |
-
else {
|
564 |
-
$sMessage = _wpsf__( 'License key was not accepted.' );
|
565 |
-
}
|
566 |
-
}
|
567 |
-
catch ( Exception $oE ) {
|
568 |
-
$sMessage = _wpsf__( $oE->getMessage() );
|
569 |
-
}
|
570 |
-
}
|
571 |
-
|
572 |
-
$oResponse = new \FernleafSystems\Utilities\Response();
|
573 |
-
return $oResponse->setSuccessful( $bSuccess )
|
574 |
-
->setMessageText( $sMessage );
|
575 |
-
}
|
576 |
-
|
577 |
-
/**
|
578 |
-
* @return \FernleafSystems\Utilities\Response
|
579 |
-
*/
|
580 |
-
private function wizardImportOptions() {
|
581 |
-
/** @var ICWP_WPSF_FeatureHandler_Plugin $oFO */
|
582 |
-
$oFO = $this->getFeature();
|
583 |
-
$oDP = $this->loadDP();
|
584 |
-
|
585 |
-
$sMasterSiteUrl = $oDP->post( 'MasterSiteUrl' );
|
586 |
-
$sSecretKey = $oDP->post( 'MasterSiteSecretKey' );
|
587 |
-
$bEnabledNetwork = $oDP->post( 'ShieldNetworkCheck' ) === 'Y';
|
588 |
-
|
589 |
-
/** @var ICWP_WPSF_Processor_Plugin $oProc */
|
590 |
-
$oProc = $oFO->getProcessor();
|
591 |
-
$nCode = $oProc->getSubProcessorImportExport()
|
592 |
-
->runImport( $sMasterSiteUrl, $sSecretKey, $bEnabledNetwork, $sSiteResponse );
|
593 |
-
|
594 |
-
$aErrors = array(
|
595 |
-
_wpsf__( 'Options imported successfully to your site.' ), // success
|
596 |
-
_wpsf__( 'Secret key was empty.' ),
|
597 |
-
_wpsf__( 'Secret key was not 40 characters long.' ),
|
598 |
-
_wpsf__( 'Secret key contains invalid characters - it should be letters and numbers only.' ),
|
599 |
-
_wpsf__( 'Source site URL could not be parsed correctly.' ),
|
600 |
-
_wpsf__( 'Could not parse the response from the site.' )
|
601 |
-
.' '._wpsf__( 'Check the secret key is correct for the remote site.' ),
|
602 |
-
_wpsf__( 'Failure response returned from the site.' ),
|
603 |
-
sprintf( _wpsf__( 'Remote site responded with - %s' ), $sSiteResponse ),
|
604 |
-
_wpsf__( 'Data returned from the site was empty.' )
|
605 |
-
);
|
606 |
-
|
607 |
-
$sMessage = isset( $aErrors[ $nCode ] ) ? $aErrors[ $nCode ] : 'Unknown Error';
|
608 |
-
|
609 |
-
$oResponse = new \FernleafSystems\Utilities\Response();
|
610 |
-
return $oResponse->setSuccessful( $nCode === 0 )
|
611 |
-
->setMessageText( $sMessage );
|
612 |
-
}
|
613 |
-
|
614 |
-
/**
|
615 |
-
* @return \FernleafSystems\Utilities\Response
|
616 |
-
*/
|
617 |
-
private function wizardSecurityAdminVerify() {
|
618 |
-
$sKey = $this->loadDP()->post( 'AccessKey' );
|
619 |
-
|
620 |
-
$oResponse = new \FernleafSystems\Utilities\Response();
|
621 |
-
|
622 |
-
$bSuccess = false;
|
623 |
-
/** @var ICWP_WPSF_FeatureHandler_AdminAccessRestriction $oModule */
|
624 |
-
$oModule = $this->getController()->getModule( 'admin_access_restriction' );
|
625 |
-
|
626 |
-
$sMessage = '';
|
627 |
-
if ( empty( $sKey ) ) {
|
628 |
-
$sMessage = 'Security access key was empty.';
|
629 |
-
}
|
630 |
-
else if ( !$oModule->verifyAccessKey( $sKey ) ) {
|
631 |
-
$sMessage = _wpsf__( 'Security Admin Key was not correct.' );
|
632 |
-
}
|
633 |
-
else {
|
634 |
-
$bSuccess = true;
|
635 |
-
$oModule->setPermissionToSubmit( true );
|
636 |
-
$aData = array(
|
637 |
-
'rerender' => true
|
638 |
-
);
|
639 |
-
$oResponse->setData( $aData );
|
640 |
-
}
|
641 |
-
|
642 |
-
return $oResponse->setSuccessful( $bSuccess )
|
643 |
-
->setMessageText( $sMessage );
|
644 |
-
}
|
645 |
-
|
646 |
-
/**
|
647 |
-
* @return \FernleafSystems\Utilities\Response
|
648 |
-
*/
|
649 |
-
private function wizardSecurityAdmin() {
|
650 |
-
$oDP = $this->loadDP();
|
651 |
-
$sKey = $oDP->post( 'AccessKey' );
|
652 |
-
$sConfirm = $oDP->post( 'AccessKeyConfirm' );
|
653 |
-
|
654 |
-
$oResponse = new \FernleafSystems\Utilities\Response();
|
655 |
-
|
656 |
-
$bSuccess = false;
|
657 |
-
if ( empty( $sKey ) ) {
|
658 |
-
$sMessage = 'Security access key was empty.';
|
659 |
-
}
|
660 |
-
else if ( $sKey != $sConfirm ) {
|
661 |
-
$sMessage = 'Keys do not match.';
|
662 |
-
}
|
663 |
-
else {
|
664 |
-
/** @var ICWP_WPSF_FeatureHandler_AdminAccessRestriction $oModule */
|
665 |
-
$oModule = $this->getController()->getModule( 'admin_access_restriction' );
|
666 |
-
try {
|
667 |
-
$oModule->setNewAccessKeyManually( $sKey )
|
668 |
-
->setPermissionToSubmit( true );
|
669 |
-
$bSuccess = true;
|
670 |
-
$sMessage = _wpsf__( 'Security Admin setup was successful.' );
|
671 |
-
}
|
672 |
-
catch ( Exception $oE ) {
|
673 |
-
$sMessage = _wpsf__( $oE->getMessage() );
|
674 |
-
}
|
675 |
-
}
|
676 |
-
|
677 |
-
return $oResponse->setSuccessful( $bSuccess )
|
678 |
-
->setMessageText( $sMessage );
|
679 |
-
}
|
680 |
-
|
681 |
-
/**
|
682 |
-
* @return \FernleafSystems\Utilities\Response
|
683 |
-
*/
|
684 |
-
private function wizardAuditTrail() {
|
685 |
-
$bEnabled = $this->loadDP()->post( 'AuditTrailOption' ) === 'Y';
|
686 |
-
|
687 |
-
/** @var ICWP_WPSF_FeatureHandler_AdminAccessRestriction $oModule */
|
688 |
-
$oModule = $this->getController()->getModule( 'audit_trail' );
|
689 |
-
$oModule->setIsMainFeatureEnabled( $bEnabled )
|
690 |
-
->savePluginOptions();
|
691 |
-
|
692 |
-
$bSuccess = $oModule->getIsMainFeatureEnabled() === $bEnabled;
|
693 |
-
if ( $bSuccess ) {
|
694 |
-
$sMessage = sprintf( '%s has been %s.', _wpsf__( 'Audit Trail' ),
|
695 |
-
$oModule->getIsMainFeatureEnabled() ? _wpsf__( 'Enabled' ) : _wpsf__( 'Disabled' )
|
696 |
-
);
|
697 |
-
}
|
698 |
-
else {
|
699 |
-
$sMessage = sprintf( _wpsf__( '%s setting could not be changed at this time.' ), _wpsf__( 'Audit Trail' ) );
|
700 |
-
}
|
701 |
-
|
702 |
-
$oResponse = new \FernleafSystems\Utilities\Response();
|
703 |
-
return $oResponse->setSuccessful( $bSuccess )
|
704 |
-
->setMessageText( $sMessage );
|
705 |
-
}
|
706 |
-
|
707 |
-
/**
|
708 |
-
* @return \FernleafSystems\Utilities\Response
|
709 |
-
*/
|
710 |
-
private function wizardIps() {
|
711 |
-
|
712 |
-
$bEnabled = $this->loadDP()->post( 'IpManagerOption' ) === 'Y';
|
713 |
-
|
714 |
-
/** @var ICWP_WPSF_FeatureHandler_Ips $oModule */
|
715 |
-
$oModule = $this->getController()->getModule( 'ips' );
|
716 |
-
$oModule->setIsMainFeatureEnabled( $bEnabled )
|
717 |
-
->savePluginOptions();
|
718 |
-
|
719 |
-
$bSuccess = $oModule->getIsMainFeatureEnabled() === $bEnabled;
|
720 |
-
if ( $bSuccess ) {
|
721 |
-
$sMessage = sprintf( '%s has been %s.', _wpsf__( 'IP Manager' ),
|
722 |
-
$oModule->getIsMainFeatureEnabled() ? _wpsf__( 'Enabled' ) : _wpsf__( 'Disabled' )
|
723 |
-
);
|
724 |
-
}
|
725 |
-
else {
|
726 |
-
$sMessage = sprintf( _wpsf__( '%s setting could not be changed at this time.' ), _wpsf__( 'IP Manager' ) );
|
727 |
-
}
|
728 |
-
|
729 |
-
$oResponse = new \FernleafSystems\Utilities\Response();
|
730 |
-
return $oResponse->setSuccessful( $bSuccess )
|
731 |
-
->setMessageText( $sMessage );
|
732 |
-
}
|
733 |
-
|
734 |
-
/**
|
735 |
-
* @return \FernleafSystems\Utilities\Response
|
736 |
-
*/
|
737 |
-
private function wizardLoginProtect() {
|
738 |
-
|
739 |
-
$bEnabled = $this->loadDP()->post( 'LoginProtectOption' ) === 'Y';
|
740 |
-
|
741 |
-
/** @var ICWP_WPSF_FeatureHandler_LoginProtect $oModule */
|
742 |
-
$oModule = $this->getController()->getModule( 'login_protect' );
|
743 |
-
if ( $bEnabled ) { // we don't disable the whole module
|
744 |
-
$oModule->setIsMainFeatureEnabled( true );
|
745 |
-
}
|
746 |
-
$oModule->setEnabledGaspCheck( $bEnabled )
|
747 |
-
->savePluginOptions();
|
748 |
-
|
749 |
-
$bSuccess = $oModule->getIsMainFeatureEnabled() === $bEnabled;
|
750 |
-
if ( $bSuccess ) {
|
751 |
-
$sMessage = sprintf( '%s has been %s.', _wpsf__( 'Login Protection' ),
|
752 |
-
$oModule->getIsMainFeatureEnabled() ? _wpsf__( 'Enabled' ) : _wpsf__( 'Disabled' )
|
753 |
-
);
|
754 |
-
}
|
755 |
-
else {
|
756 |
-
$sMessage = sprintf( _wpsf__( '%s setting could not be changed at this time.' ), _wpsf__( 'Login Protection' ) );
|
757 |
-
}
|
758 |
-
|
759 |
-
$oResponse = new \FernleafSystems\Utilities\Response();
|
760 |
-
return $oResponse->setSuccessful( $bSuccess )
|
761 |
-
->setMessageText( $sMessage );
|
762 |
-
}
|
763 |
-
|
764 |
-
/**
|
765 |
-
* @return \FernleafSystems\Utilities\Response
|
766 |
-
*/
|
767 |
-
private function wizardOptin() {
|
768 |
-
$oDP = $this->loadDP();
|
769 |
-
|
770 |
-
$bEnabledTracking = $oDP->post( 'AnonymousOption', 'N', true ) === 'Y';
|
771 |
-
$bEnabledBadge = $oDP->post( 'BadgeOption', 'N', true ) === 'Y';
|
772 |
-
|
773 |
-
/** @var ICWP_WPSF_FeatureHandler_Plugin $oModule */
|
774 |
-
$oModule = $this->getController()->getModule( 'plugin' );
|
775 |
-
$oModule->setIsDisplayPluginBadge( $bEnabledBadge )
|
776 |
-
->setPluginTrackingPermission( $bEnabledTracking );
|
777 |
-
|
778 |
-
$sMessage = _wpsf__( 'Preferences have been saved.' );
|
779 |
-
|
780 |
-
$oResponse = new \FernleafSystems\Utilities\Response();
|
781 |
-
return $oResponse->setSuccessful( true )
|
782 |
-
->setMessageText( $sMessage );
|
783 |
-
}
|
784 |
-
|
785 |
-
/**
|
786 |
-
* @return \FernleafSystems\Utilities\Response
|
787 |
-
*/
|
788 |
-
private function wizardCommentsFilter() {
|
789 |
-
|
790 |
-
$bEnabled = $this->loadDP()->post( 'CommentsFilterOption' ) === 'Y';
|
791 |
-
|
792 |
-
/** @var ICWP_WPSF_FeatureHandler_CommentsFilter $oModule */
|
793 |
-
$oModule = $this->getController()->getModule( 'comments_filter' );
|
794 |
-
if ( $bEnabled ) { // we don't disable the whole module
|
795 |
-
$oModule->setIsMainFeatureEnabled( true );
|
796 |
-
}
|
797 |
-
$oModule->setEnabledGasp( $bEnabled )
|
798 |
-
->savePluginOptions();
|
799 |
-
|
800 |
-
$bSuccess = $oModule->getIsMainFeatureEnabled() === $bEnabled;
|
801 |
-
if ( $bSuccess ) {
|
802 |
-
$sMessage = sprintf( '%s has been %s.', _wpsf__( 'Comment SPAM Protection' ),
|
803 |
-
$oModule->getIsMainFeatureEnabled() ? _wpsf__( 'Enabled' ) : _wpsf__( 'Disabled' )
|
804 |
-
);
|
805 |
-
}
|
806 |
-
else {
|
807 |
-
$sMessage = sprintf( _wpsf__( '%s setting could not be changed at this time.' ), _wpsf__( 'Comment SPAM Protection' ) );
|
808 |
-
}
|
809 |
-
|
810 |
-
$oResponse = new \FernleafSystems\Utilities\Response();
|
811 |
-
return $oResponse->setSuccessful( $bSuccess )
|
812 |
-
->setMessageText( $sMessage );
|
813 |
-
}
|
814 |
-
|
815 |
-
/**
|
816 |
-
* @return string
|
817 |
-
*/
|
818 |
-
public function getCurrentWizard() {
|
819 |
-
return $this->sCurrentWizard;
|
820 |
-
}
|
821 |
-
|
822 |
-
/**
|
823 |
-
* @param string $sCurrentWizard
|
824 |
-
* @return $this
|
825 |
-
*/
|
826 |
-
public function setCurrentWizard( $sCurrentWizard ) {
|
827 |
-
$this->sCurrentWizard = $sCurrentWizard;
|
828 |
-
return $this;
|
829 |
-
}
|
830 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/wizards/base.php
ADDED
@@ -0,0 +1,537 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if ( class_exists( 'ICWP_WPSF_Wizard_Base', false ) ) {
|
4 |
+
return;
|
5 |
+
}
|
6 |
+
|
7 |
+
/**
|
8 |
+
* @uses php 5.4+
|
9 |
+
* Class ICWP_WPSF_Wizard_Base
|
10 |
+
*/
|
11 |
+
abstract class ICWP_WPSF_Wizard_Base extends ICWP_WPSF_Foundation {
|
12 |
+
|
13 |
+
/**
|
14 |
+
* @var string
|
15 |
+
*/
|
16 |
+
private $sCurrentWizard;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* @var ICWP_WPSF_FeatureHandler_Base
|
20 |
+
*/
|
21 |
+
protected $oModule;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* @param ICWP_WPSF_FeatureHandler_Base $oFeatureOptions
|
25 |
+
*/
|
26 |
+
public function __construct( ICWP_WPSF_FeatureHandler_Base $oFeatureOptions ) {
|
27 |
+
$this->oModule = $oFeatureOptions;
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
*/
|
32 |
+
public function init() {
|
33 |
+
add_action( 'wp_loaded', array( $this, 'onWpLoaded' ), 0 );
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Ensure to only ever process supported wizards
|
38 |
+
*/
|
39 |
+
public function ajaxWizardRenderStep() {
|
40 |
+
$oDP = $this->loadDP();
|
41 |
+
|
42 |
+
try {
|
43 |
+
$this->setCurrentWizard( $oDP->post( 'wizard_slug' ) );
|
44 |
+
if ( $this->getUserCan() ) {
|
45 |
+
$aNextStep = $this->buildNextStep(
|
46 |
+
$oDP->post( 'wizard_steps' ),
|
47 |
+
(int)$oDP->post( 'current_index' )
|
48 |
+
);
|
49 |
+
$this->getModCon()
|
50 |
+
->sendAjaxResponse(
|
51 |
+
true,
|
52 |
+
array( 'next_step' => $aNextStep )
|
53 |
+
);
|
54 |
+
}
|
55 |
+
else {
|
56 |
+
$this->loadWp()
|
57 |
+
->wpDie( 'Please login to run this wizard.' );
|
58 |
+
}
|
59 |
+
}
|
60 |
+
catch ( Exception $oE ) {
|
61 |
+
}
|
62 |
+
}
|
63 |
+
|
64 |
+
public function onWpLoaded() {
|
65 |
+
$sWizard = $this->loadDP()->query( 'wizard' );
|
66 |
+
try {
|
67 |
+
$this->setCurrentWizard( $sWizard );
|
68 |
+
|
69 |
+
$sDieMessage = 'Not Permitted';
|
70 |
+
if ( $this->getUserCan() ) {
|
71 |
+
if ( $this->verifyNonce() ) {
|
72 |
+
$this->loadWizard();
|
73 |
+
}
|
74 |
+
else {
|
75 |
+
$sDieMessage = 'Sorry, this link has expired.';
|
76 |
+
}
|
77 |
+
}
|
78 |
+
else {
|
79 |
+
$sDieMessage = 'Please login to run this wizard';
|
80 |
+
}
|
81 |
+
$this->loadWp()
|
82 |
+
->wpDie( $sDieMessage );
|
83 |
+
}
|
84 |
+
catch ( Exception $oE ) {
|
85 |
+
if ( $sWizard == 'landing' && $this->verifyNonce( 'landing' ) ) {
|
86 |
+
$this->loadWizardLanding();
|
87 |
+
}
|
88 |
+
}
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* @uses echo()
|
93 |
+
*/
|
94 |
+
protected function loadWizard() {
|
95 |
+
try {
|
96 |
+
$sContent = $this->renderWizard();
|
97 |
+
}
|
98 |
+
catch ( Exception $oE ) {
|
99 |
+
$sContent = $oE->getMessage();
|
100 |
+
}
|
101 |
+
echo $sContent;
|
102 |
+
die();
|
103 |
+
}
|
104 |
+
|
105 |
+
/**
|
106 |
+
* @uses echo()
|
107 |
+
*/
|
108 |
+
protected function loadWizardLanding() {
|
109 |
+
try {
|
110 |
+
$sContent = $this->loadRenderer( $this->getModCon()->getController()->getPath_Templates() )
|
111 |
+
->setTemplate( 'wizard/pages/landing.twig' )
|
112 |
+
->setRenderVars( $this->getRenderData_PageWizardLanding() )
|
113 |
+
->setTemplateEngineTwig()
|
114 |
+
->render();
|
115 |
+
}
|
116 |
+
catch ( Exception $oE ) {
|
117 |
+
$sContent = $oE->getMessage();
|
118 |
+
}
|
119 |
+
echo $sContent;
|
120 |
+
die();
|
121 |
+
}
|
122 |
+
|
123 |
+
/**
|
124 |
+
* @param string $sSlug
|
125 |
+
* @return bool
|
126 |
+
*/
|
127 |
+
protected function isSupportedWizard( $sSlug ) {
|
128 |
+
return in_array( $sSlug, $this->getSupportedWizards() );
|
129 |
+
}
|
130 |
+
|
131 |
+
/**
|
132 |
+
* @param string $sPerm
|
133 |
+
* @return bool
|
134 |
+
*/
|
135 |
+
protected function getUserCan( $sPerm = null ) {
|
136 |
+
if ( empty( $sPerm ) ) {
|
137 |
+
$sPerm = 'manage_options';
|
138 |
+
}
|
139 |
+
return $sPerm == 'none' || current_user_can( $sPerm );
|
140 |
+
}
|
141 |
+
|
142 |
+
/**
|
143 |
+
* @param string $sSlide
|
144 |
+
* @return bool
|
145 |
+
*/
|
146 |
+
protected function getUserCanSlide( $sSlide ) {
|
147 |
+
return $this->getUserCan();
|
148 |
+
}
|
149 |
+
|
150 |
+
/**
|
151 |
+
* @return string[] the array of wizard slugs supported
|
152 |
+
*/
|
153 |
+
protected function getSupportedWizards() {
|
154 |
+
return array_keys( $this->getModCon()->getWizardDefinitions() );
|
155 |
+
}
|
156 |
+
|
157 |
+
public function ajaxWizardProcessStepSubmit() {
|
158 |
+
$this->loadAutoload(); // for Response
|
159 |
+
$oResponse = $this->processWizardStep( $this->loadDP()->post( 'wizard-step' ) );
|
160 |
+
if ( !empty( $oResponse ) ) {
|
161 |
+
$this->sendWizardResponse( $oResponse );
|
162 |
+
}
|
163 |
+
}
|
164 |
+
|
165 |
+
/**
|
166 |
+
* @param string $sStep
|
167 |
+
* @return \FernleafSystems\Utilities\Response|null
|
168 |
+
*/
|
169 |
+
protected function processWizardStep( $sStep ) {
|
170 |
+
switch ( $sStep ) {
|
171 |
+
default:
|
172 |
+
$oResponse = null; // we don't process any steps we don't recognise.
|
173 |
+
break;
|
174 |
+
}
|
175 |
+
return $oResponse;
|
176 |
+
}
|
177 |
+
|
178 |
+
/**
|
179 |
+
* @param \FernleafSystems\Utilities\Response $oResponse
|
180 |
+
*/
|
181 |
+
protected function sendWizardResponse( $oResponse ) {
|
182 |
+
|
183 |
+
$sMessage = $oResponse->getMessageText();
|
184 |
+
if ( $oResponse->successful() ) {
|
185 |
+
$sMessage .= '<br />'.sprintf( 'Please click %s to continue.', __( 'Next Step' ) );
|
186 |
+
}
|
187 |
+
else {
|
188 |
+
$sMessage = sprintf( '%s: %s', __( 'Error' ), $sMessage );
|
189 |
+
}
|
190 |
+
|
191 |
+
$aData = $oResponse->getData();
|
192 |
+
$aData[ 'message' ] = $sMessage;
|
193 |
+
$oResponse->setData( $aData );
|
194 |
+
|
195 |
+
$this->getModCon()
|
196 |
+
->sendAjaxResponse( $oResponse->successful(), $aData );
|
197 |
+
}
|
198 |
+
|
199 |
+
/**
|
200 |
+
* @return string
|
201 |
+
* @throws Exception
|
202 |
+
*/
|
203 |
+
protected function renderWizard() {
|
204 |
+
return $this->loadRenderer( $this->getModCon()->getController()->getPath_Templates() )
|
205 |
+
->setTemplate( 'wizard/pages/wizard.twig' )
|
206 |
+
->setRenderVars( $this->getRenderData_PageWizard() )
|
207 |
+
->setTemplateEngineTwig()
|
208 |
+
->render();
|
209 |
+
}
|
210 |
+
|
211 |
+
/**
|
212 |
+
* @return array[]
|
213 |
+
*/
|
214 |
+
protected function getModuleWizardsForRender() {
|
215 |
+
/** @var ICWP_WPSF_FeatureHandler_Base $oFO */
|
216 |
+
$oFO = $this->getModCon();
|
217 |
+
$aWizards = $oFO->getWizardDefinitions();
|
218 |
+
foreach ( $aWizards as $sKey => &$aWizard ) {
|
219 |
+
$aWizard[ 'has_perm' ] = $this->getUserCan( $aWizard[ 'min_user_permissions' ] );
|
220 |
+
$aWizard[ 'url' ] = $oFO->getUrl_Wizard( $sKey );
|
221 |
+
$aWizard[ 'has_premium' ] = isset( $aWizard[ 'has_premium' ] ) && $aWizard[ 'has_premium' ];
|
222 |
+
}
|
223 |
+
return $aWizards;
|
224 |
+
}
|
225 |
+
|
226 |
+
/**
|
227 |
+
* @return array[]
|
228 |
+
*/
|
229 |
+
protected function getRenderData_PageWizardLanding() {
|
230 |
+
/** @var ICWP_WPSF_FeatureHandler_Base $oFO */
|
231 |
+
$oFO = $this->getModCon();
|
232 |
+
|
233 |
+
$aWizards = $this->getModuleWizardsForRender();
|
234 |
+
|
235 |
+
return $this->loadDP()->mergeArraysRecursive(
|
236 |
+
$this->getRenderData_TwigPageBase(),
|
237 |
+
array(
|
238 |
+
'strings' => array(
|
239 |
+
'page_title' => 'Select Your Wizard',
|
240 |
+
'premium_note' => 'Note: This uses features only available to Pro-licensed installations.'
|
241 |
+
),
|
242 |
+
'data' => array(
|
243 |
+
'mod_wizards_count' => count( $aWizards ),
|
244 |
+
'mod_wizards' => $aWizards
|
245 |
+
),
|
246 |
+
'hrefs' => array(
|
247 |
+
'dashboard' => $oFO->getUrl_AdminPage(),
|
248 |
+
'goprofooter' => 'http://icwp.io/goprofooter',
|
249 |
+
),
|
250 |
+
'ajax' => array(
|
251 |
+
'content' => $oFO->getBaseAjaxActionRenderData( 'WizardProcessStepSubmit' ),
|
252 |
+
'steps' => $oFO->getBaseAjaxActionRenderData( 'WizardRenderStep' ),
|
253 |
+
'steps_as_json' => $oFO->getBaseAjaxActionRenderData( 'WizardRenderStep', true ),
|
254 |
+
)
|
255 |
+
)
|
256 |
+
);
|
257 |
+
}
|
258 |
+
|
259 |
+
/**
|
260 |
+
* TODO: Abstract and move elsewhere - it's here because Wizards on the only consumer of twig templates
|
261 |
+
* @return array
|
262 |
+
*/
|
263 |
+
protected function getRenderData_TwigPageBase() {
|
264 |
+
$oCon = $this->getModCon()->getController();
|
265 |
+
return array(
|
266 |
+
'strings' => array(
|
267 |
+
'page_title' => 'Twig Page'
|
268 |
+
),
|
269 |
+
'data' => array(),
|
270 |
+
'hrefs' => array(
|
271 |
+
'form_action' => $this->loadDP()->getRequestUri(),
|
272 |
+
'css_bootstrap' => $oCon->getPluginUrl_Css( 'bootstrap3.min.css' ),
|
273 |
+
'css_pages' => $oCon->getPluginUrl_Css( 'pages.css' ),
|
274 |
+
'css_steps' => $oCon->getPluginUrl_Css( 'jquery.steps.css' ),
|
275 |
+
'css_fancybox' => $oCon->getPluginUrl_Css( 'jquery.fancybox.min.css' ),
|
276 |
+
'css_globalplugin' => $oCon->getPluginUrl_Css( 'global-plugin.css' ),
|
277 |
+
'css_wizard' => $oCon->getPluginUrl_Css( 'wizard.css' ),
|
278 |
+
'js_jquery' => $this->loadWpIncludes()->getUrl_Jquery(),
|
279 |
+
'js_bootstrap' => $oCon->getPluginUrl_Js( 'bootstrap3.min.js' ),
|
280 |
+
'js_fancybox' => $oCon->getPluginUrl_Js( 'jquery.fancybox.min.js' ),
|
281 |
+
'js_globalplugin' => $oCon->getPluginUrl_Js( 'global-plugin.js' ),
|
282 |
+
'js_steps' => $oCon->getPluginUrl_Js( 'jquery.steps.min.js' ),
|
283 |
+
'js_wizard' => $oCon->getPluginUrl_Js( 'wizard.js' ),
|
284 |
+
'plugin_banner' => $oCon->getPluginUrl_Image( 'banner-1500x500-transparent.png' ),
|
285 |
+
'favicon' => $oCon->getPluginUrl_Image( 'pluginlogo_24x24.png' ),
|
286 |
+
),
|
287 |
+
'ajax' => array(),
|
288 |
+
'flags' => array(
|
289 |
+
'is_premium' => $this->getModCon()->isPremium(),
|
290 |
+
)
|
291 |
+
);
|
292 |
+
}
|
293 |
+
|
294 |
+
/**
|
295 |
+
* @return array
|
296 |
+
*/
|
297 |
+
protected function getRenderData_PageWizard() {
|
298 |
+
/** @var ICWP_WPSF_FeatureHandler_Plugin $oFO */
|
299 |
+
$oFO = $this->getModCon();
|
300 |
+
return $this->loadDP()->mergeArraysRecursive(
|
301 |
+
$this->getRenderData_TwigPageBase(),
|
302 |
+
array(
|
303 |
+
'strings' => array(
|
304 |
+
'page_title' => $this->getPageTitle()
|
305 |
+
),
|
306 |
+
'data' => array(
|
307 |
+
'wizard_slug' => $this->getWizardSlug(),
|
308 |
+
'wizard_steps' => json_encode( $this->buildSteps() ),
|
309 |
+
'wizard_first_step' => json_encode( $this->getWizardFirstStep() ),
|
310 |
+
),
|
311 |
+
'hrefs' => array(
|
312 |
+
'dashboard' => $oFO->getUrl_AdminPage(),
|
313 |
+
'goprofooter' => 'http://icwp.io/goprofooter',
|
314 |
+
),
|
315 |
+
'ajax' => array(
|
316 |
+
'content' => $oFO->getBaseAjaxActionRenderData( 'WizardProcessStepSubmit' ),
|
317 |
+
'steps' => $oFO->getBaseAjaxActionRenderData( 'WizardRenderStep' ),
|
318 |
+
'steps_as_json' => $oFO->getBaseAjaxActionRenderData( 'WizardRenderStep', true ),
|
319 |
+
)
|
320 |
+
)
|
321 |
+
);
|
322 |
+
}
|
323 |
+
|
324 |
+
/**
|
325 |
+
* @return string
|
326 |
+
*/
|
327 |
+
protected function getPageTitle() {
|
328 |
+
return sprintf( _wpsf__( '%s Wizard' ), $this->getModCon()->getController()->getHumanName() );
|
329 |
+
}
|
330 |
+
|
331 |
+
/**
|
332 |
+
* @return string[]
|
333 |
+
*/
|
334 |
+
protected function buildSteps() {
|
335 |
+
return $this->getUserCan() ? $this->determineWizardSteps() : array( 'no_access' );
|
336 |
+
}
|
337 |
+
|
338 |
+
/**
|
339 |
+
* @throws Exception
|
340 |
+
*/
|
341 |
+
protected function determineWizardSteps() {
|
342 |
+
throw new Exception( sprintf( 'Could not determine wizard steps for current wizard: %s', $this->getWizardSlug() ) );
|
343 |
+
}
|
344 |
+
|
345 |
+
/**
|
346 |
+
* @return array
|
347 |
+
*/
|
348 |
+
protected function getWizardFirstStep() {
|
349 |
+
return $this->buildNextStep( $this->buildSteps(), -1 );
|
350 |
+
}
|
351 |
+
|
352 |
+
protected function getNextStepDefinition( $aStepsInThisInstance, $nCurrentStep ) {
|
353 |
+
}
|
354 |
+
|
355 |
+
/**
|
356 |
+
* @param array $aStepsInThisInstance
|
357 |
+
* @param int $nCurrentPos
|
358 |
+
* @return array
|
359 |
+
*/
|
360 |
+
protected function buildNextStep( $aStepsInThisInstance, $nCurrentPos ) {
|
361 |
+
$aNextStepDef = $this->getNextStep( $aStepsInThisInstance, $nCurrentPos );
|
362 |
+
|
363 |
+
try {
|
364 |
+
$aNextStepDef[ 'content' ] = $this->renderWizardStep( $aNextStepDef[ 'slug' ] );
|
365 |
+
}
|
366 |
+
catch ( Exception $oE ) {
|
367 |
+
$aNextStepDef[ 'content' ] = 'Content could not be displayed due to error: '.$oE->getMessage();
|
368 |
+
}
|
369 |
+
|
370 |
+
return $aNextStepDef;
|
371 |
+
}
|
372 |
+
|
373 |
+
/**
|
374 |
+
* @param array $aStepsInThisInstance
|
375 |
+
* @param int $nCurrentPos
|
376 |
+
* @return array
|
377 |
+
*/
|
378 |
+
protected function getNextStep( $aStepsInThisInstance, $nCurrentPos ) {
|
379 |
+
// The assumption here is that the step data exists!
|
380 |
+
$sNextStepKey = $aStepsInThisInstance[ $nCurrentPos + 1 ];
|
381 |
+
return $this->getStepsDefinition()[ $sNextStepKey ];
|
382 |
+
}
|
383 |
+
|
384 |
+
/**
|
385 |
+
* @param string $sStep
|
386 |
+
* @return array
|
387 |
+
*/
|
388 |
+
protected function getRenderData_Slide( $sStep ) {
|
389 |
+
return $this->loadDP()->mergeArraysRecursive(
|
390 |
+
$this->getRenderData_SlideBase(),
|
391 |
+
$this->getRenderData_SlideExtra( $sStep )
|
392 |
+
);
|
393 |
+
}
|
394 |
+
|
395 |
+
/**
|
396 |
+
* @return array
|
397 |
+
*/
|
398 |
+
protected function getRenderData_SlideBase() {
|
399 |
+
$oFO = $this->getModCon();
|
400 |
+
$aWizards = $this->getModuleWizardsForRender();
|
401 |
+
return array(
|
402 |
+
'flags' => array(
|
403 |
+
'is_premium' => $oFO->isPremium(),
|
404 |
+
'has_other_wizards' => false
|
405 |
+
),
|
406 |
+
'hrefs' => array(
|
407 |
+
'dashboard' => $oFO->getUrl_AdminPage(),
|
408 |
+
'gopro' => 'http://icwp.io/ap',
|
409 |
+
),
|
410 |
+
'imgs' => array(),
|
411 |
+
'data' => array(
|
412 |
+
'mod_wizards_count' => count( $aWizards ),
|
413 |
+
'mod_wizards' => $aWizards
|
414 |
+
),
|
415 |
+
);
|
416 |
+
}
|
417 |
+
|
418 |
+
/**
|
419 |
+
* @param string $sStep
|
420 |
+
* @return array
|
421 |
+
*/
|
422 |
+
protected function getRenderData_SlideExtra( $sStep ) {
|
423 |
+
return array();
|
424 |
+
}
|
425 |
+
|
426 |
+
/**
|
427 |
+
* @param string $sSlug
|
428 |
+
* @return string
|
429 |
+
* @throws Exception
|
430 |
+
*/
|
431 |
+
protected function renderWizardStep( $sSlug ) {
|
432 |
+
|
433 |
+
$sTemplateSlug = $sSlug;
|
434 |
+
if ( strpos( $sSlug, '/' ) === false ) {
|
435 |
+
$sBase = $this->isSlideCommon( $sSlug ) ? 'common' : $this->getWizardSlug();
|
436 |
+
$sTemplateSlug = sprintf( '%s/%s', $sBase, $sSlug );
|
437 |
+
}
|
438 |
+
|
439 |
+
return $this->loadRenderer( $this->getModCon()->getController()->getPath_Templates() )
|
440 |
+
->setTemplate( sprintf( 'wizard/slides/%s.twig', $sTemplateSlug ) )
|
441 |
+
->setRenderVars( $this->getRenderData_Slide( $sSlug ) )
|
442 |
+
->setTemplateEngineTwig()
|
443 |
+
->render();
|
444 |
+
}
|
445 |
+
|
446 |
+
/**
|
447 |
+
* @param string $sSlideSlug
|
448 |
+
* @return bool
|
449 |
+
*/
|
450 |
+
protected function isSlideCommon( $sSlideSlug ) {
|
451 |
+
return in_array( $sSlideSlug, [ 'no_access' ] );
|
452 |
+
}
|
453 |
+
|
454 |
+
/**
|
455 |
+
* @return array[]
|
456 |
+
*/
|
457 |
+
protected function getAllDefinedSteps() {
|
458 |
+
return $this->getWizard()[ 'steps' ];
|
459 |
+
}
|
460 |
+
|
461 |
+
/**
|
462 |
+
* @return array[]
|
463 |
+
*/
|
464 |
+
protected function getStepsDefinition() {
|
465 |
+
$aNoAccess = array(
|
466 |
+
'no_access' => array(
|
467 |
+
'title' => _wpsf__( 'No Access' ),
|
468 |
+
)
|
469 |
+
);
|
470 |
+
$aSteps = array_merge( $this->getAllDefinedSteps(), $aNoAccess );
|
471 |
+
foreach ( $aSteps as $sSlug => $aStep ) {
|
472 |
+
$aSteps[ $sSlug ][ 'slug' ] = $sSlug;
|
473 |
+
$aSteps[ $sSlug ][ 'content' ] = '';
|
474 |
+
}
|
475 |
+
return $aSteps;
|
476 |
+
}
|
477 |
+
|
478 |
+
/**
|
479 |
+
* @return string
|
480 |
+
*/
|
481 |
+
public function getWizardSlug() {
|
482 |
+
return $this->sCurrentWizard;
|
483 |
+
}
|
484 |
+
|
485 |
+
/**
|
486 |
+
* @return array
|
487 |
+
*/
|
488 |
+
public function getWizard() {
|
489 |
+
return $this->getModCon()->getWizardDefinitions()[ $this->getWizardSlug() ];
|
490 |
+
}
|
491 |
+
|
492 |
+
/**
|
493 |
+
* @param string $sKey
|
494 |
+
* @return array
|
495 |
+
*/
|
496 |
+
public function getWizardProperty( $sKey ) {
|
497 |
+
$aW = $this->getWizard();
|
498 |
+
return isset( $aW[ $sKey ] ) ? $aW[ $sKey ] : null;
|
499 |
+
}
|
500 |
+
|
501 |
+
/**
|
502 |
+
* @param string $sCurrentWizard
|
503 |
+
* @return $this
|
504 |
+
* @throws Exception
|
505 |
+
*/
|
506 |
+
public function setCurrentWizard( $sCurrentWizard ) {
|
507 |
+
if ( empty( $sCurrentWizard ) || !$this->isSupportedWizard( $sCurrentWizard ) ) {
|
508 |
+
throw new Exception( 'Not a supported wizard.' );
|
509 |
+
}
|
510 |
+
$this->sCurrentWizard = $sCurrentWizard;
|
511 |
+
return $this;
|
512 |
+
}
|
513 |
+
|
514 |
+
/**
|
515 |
+
* @return ICWP_WPSF_FeatureHandler_Base
|
516 |
+
*/
|
517 |
+
protected function getModCon() {
|
518 |
+
return $this->oModule;
|
519 |
+
}
|
520 |
+
|
521 |
+
/**
|
522 |
+
* @return ICWP_WPSF_Plugin_Controller
|
523 |
+
*/
|
524 |
+
protected function getPluginCon() {
|
525 |
+
return $this->getModCon()->getConn();
|
526 |
+
}
|
527 |
+
|
528 |
+
/**
|
529 |
+
* @return false|int
|
530 |
+
*/
|
531 |
+
protected function verifyNonce( $sWizard = null ) {
|
532 |
+
if ( is_null( $sWizard ) ) {
|
533 |
+
$sWizard = $this->getWizardSlug();
|
534 |
+
}
|
535 |
+
return wp_verify_nonce( $this->loadDP()->query( 'nonwizard' ), 'wizard'.$sWizard );
|
536 |
+
}
|
537 |
+
}
|
src/wizards/base_wpsf.php
ADDED
@@ -0,0 +1,127 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if ( class_exists( 'ICWP_WPSF_Wizard_Base', false ) ) {
|
4 |
+
return;
|
5 |
+
}
|
6 |
+
|
7 |
+
require_once( dirname( __FILE__ ).'/base.php' );
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Class ICWP_WPSF_Wizard_BaseWpsf
|
11 |
+
*/
|
12 |
+
abstract class ICWP_WPSF_Wizard_BaseWpsf extends ICWP_WPSF_Wizard_Base {
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @param string $sSlide
|
16 |
+
* @return bool
|
17 |
+
*/
|
18 |
+
protected function getUserCanSlide( $sSlide ) {
|
19 |
+
$aSlide = $this->getStepsDefinition()[ $sSlide ];
|
20 |
+
$bRestricted = !isset( $aSlide[ 'security_admin' ] ) || $aSlide[ 'security_admin' ];
|
21 |
+
return !$bRestricted || $this->getPluginCon()->getHasPermissionToManage();
|
22 |
+
}
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @param array $aStepsInThisInstance
|
26 |
+
* @param int $nCurrentPos
|
27 |
+
* @return array
|
28 |
+
*/
|
29 |
+
protected function getNextStep( $aStepsInThisInstance, $nCurrentPos ) {
|
30 |
+
$aNext = parent::getNextStep( $aStepsInThisInstance, $nCurrentPos );
|
31 |
+
if ( !$this->getUserCanSlide( $aNext[ 'slug' ] ) ) {
|
32 |
+
$aNext = $this->getStepsDefinition()[ 'security_admin_verify' ];
|
33 |
+
}
|
34 |
+
return $aNext;
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* @param string $sStep
|
39 |
+
* @return array
|
40 |
+
*/
|
41 |
+
protected function getRenderData_SlideExtra( $sStep ) {
|
42 |
+
|
43 |
+
switch ( $sStep ) {
|
44 |
+
case 'security_admin_verify':
|
45 |
+
$aAdditional = array( 'current_index' => $this->loadDP()->post( 'current_index' ) );
|
46 |
+
break;
|
47 |
+
default:
|
48 |
+
$aAdditional = parent::getRenderData_SlideExtra( $sStep );
|
49 |
+
break;
|
50 |
+
}
|
51 |
+
|
52 |
+
return $aAdditional;
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* @return array[]
|
57 |
+
*/
|
58 |
+
protected function getStepsDefinition() {
|
59 |
+
return array_merge(
|
60 |
+
parent::getStepsDefinition(),
|
61 |
+
array(
|
62 |
+
'security_admin_verify' => array(
|
63 |
+
'content' => '',
|
64 |
+
'slug' => 'security_admin_verify',
|
65 |
+
'title' => _wpsf__( 'Security Admin' ),
|
66 |
+
'security_admin' => false
|
67 |
+
)
|
68 |
+
)
|
69 |
+
);
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* @param string $sSlideSlug
|
74 |
+
* @return bool
|
75 |
+
*/
|
76 |
+
protected function isSlideCommon( $sSlideSlug ) {
|
77 |
+
return parent::isSlideCommon( $sSlideSlug ) || in_array( $sSlideSlug, [ 'security_admin_verify' ] );
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* @param string $sStep
|
82 |
+
* @return \FernleafSystems\Utilities\Response|null
|
83 |
+
*/
|
84 |
+
protected function processWizardStep( $sStep ) {
|
85 |
+
switch ( $sStep ) {
|
86 |
+
case 'security_admin_verify':
|
87 |
+
$oResponse = $this->wizardSecurityAdminVerify();
|
88 |
+
break;
|
89 |
+
default:
|
90 |
+
$oResponse = parent::processWizardStep( $sStep );
|
91 |
+
break;
|
92 |
+
}
|
93 |
+
return $oResponse;
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* @return \FernleafSystems\Utilities\Response
|
98 |
+
*/
|
99 |
+
private function wizardSecurityAdminVerify() {
|
100 |
+
$sKey = $this->loadDP()->post( 'AccessKey' );
|
101 |
+
|
102 |
+
$oResponse = new \FernleafSystems\Utilities\Response();
|
103 |
+
|
104 |
+
$bSuccess = false;
|
105 |
+
/** @var ICWP_WPSF_FeatureHandler_AdminAccessRestriction $oModule */
|
106 |
+
$oModule = $this->getPluginCon()->getModule( 'admin_access_restriction' );
|
107 |
+
|
108 |
+
$sMessage = '';
|
109 |
+
if ( empty( $sKey ) ) {
|
110 |
+
$sMessage = 'Security access key was empty.';
|
111 |
+
}
|
112 |
+
else if ( !$oModule->verifyAccessKey( $sKey ) ) {
|
113 |
+
$sMessage = _wpsf__( 'Security Admin Key was not correct.' );
|
114 |
+
}
|
115 |
+
else {
|
116 |
+
$bSuccess = true;
|
117 |
+
$oModule->setPermissionToSubmit( true );
|
118 |
+
$aData = array(
|
119 |
+
'rerender' => true
|
120 |
+
);
|
121 |
+
$oResponse->setData( $aData );
|
122 |
+
}
|
123 |
+
|
124 |
+
return $oResponse->setSuccessful( $bSuccess )
|
125 |
+
->setMessageText( $sMessage );
|
126 |
+
}
|
127 |
+
}
|
src/wizards/hack_protect.php
ADDED
@@ -0,0 +1,346 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if ( class_exists( 'ICWP_WPSF_Wizard_HackProtect', false ) ) {
|
4 |
+
return;
|
5 |
+
}
|
6 |
+
|
7 |
+
require_once( dirname( __FILE__ ).'/base_wpsf.php' );
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Class ICWP_WPSF_Wizard_HackProtect
|
11 |
+
*/
|
12 |
+
class ICWP_WPSF_Wizard_HackProtect extends ICWP_WPSF_Wizard_BaseWpsf {
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @return string
|
16 |
+
*/
|
17 |
+
protected function getPageTitle() {
|
18 |
+
return sprintf( _wpsf__( '%s Hack Protect Wizard' ), $this->getPluginCon()->getHumanName() );
|
19 |
+
}
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @param string $sStep
|
23 |
+
* @return \FernleafSystems\Utilities\Response|null
|
24 |
+
*/
|
25 |
+
protected function processWizardStep( $sStep ) {
|
26 |
+
switch ( $sStep ) {
|
27 |
+
case 'exclusions':
|
28 |
+
$oResponse = $this->process_Exclusions();
|
29 |
+
break;
|
30 |
+
case 'deletefiles':
|
31 |
+
$oResponse = $this->process_DeleteFiles();
|
32 |
+
break;
|
33 |
+
case 'restorefiles':
|
34 |
+
$oResponse = $this->process_RestoreFiles();
|
35 |
+
break;
|
36 |
+
case 'ufcconfig':
|
37 |
+
$oResponse = $this->process_UfcConfig();
|
38 |
+
break;
|
39 |
+
case 'wcfconfig':
|
40 |
+
$oResponse = $this->process_WcfConfig();
|
41 |
+
break;
|
42 |
+
default:
|
43 |
+
$oResponse = parent::processWizardStep( $sStep );
|
44 |
+
break;
|
45 |
+
}
|
46 |
+
return $oResponse;
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* @return \FernleafSystems\Utilities\Response
|
51 |
+
*/
|
52 |
+
private function process_Exclusions() {
|
53 |
+
/** @var ICWP_WPSF_FeatureHandler_HackProtect $oFO */
|
54 |
+
$oFO = $this->getModCon();
|
55 |
+
$oFO->setUfcFileExclusions( explode( "\n", $this->loadDP()->post( 'exclusions' ) ) );
|
56 |
+
|
57 |
+
$oResponse = new \FernleafSystems\Utilities\Response();
|
58 |
+
return $oResponse->setSuccessful( true )
|
59 |
+
->setMessageText( 'File exclusions list has been updated.' );
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* @return \FernleafSystems\Utilities\Response
|
64 |
+
*/
|
65 |
+
private function process_DeleteFiles() {
|
66 |
+
/** @var ICWP_WPSF_FeatureHandler_HackProtect $oFO */
|
67 |
+
$oFO = $this->getModCon();
|
68 |
+
|
69 |
+
$oResponse = new \FernleafSystems\Utilities\Response();
|
70 |
+
if ( $this->loadDP()->post( 'DeleteFiles' ) === 'Y' ) {
|
71 |
+
// First get the current setting and if necessary, modify it and then reset it.
|
72 |
+
$sDesiredOption = 'enabled_delete_only';
|
73 |
+
$sCurrentOption = $oFO->getUnrecognisedFileScannerOption();
|
74 |
+
if ( $sCurrentOption != $sDesiredOption ) {
|
75 |
+
$oFO->setUfcOption( $sDesiredOption );
|
76 |
+
}
|
77 |
+
|
78 |
+
/** @var ICWP_WPSF_Processor_HackProtect $oProc */
|
79 |
+
$oProc = $oFO->getProcessor();
|
80 |
+
$oProc->getSubProcessorFileCleanerScan()
|
81 |
+
->runScan();
|
82 |
+
$oFO->setUfcOption( $sCurrentOption )
|
83 |
+
->savePluginOptions();
|
84 |
+
|
85 |
+
$oResponse->setSuccessful( true );
|
86 |
+
$sMessage = 'If your filesystem permissions allowed it, the scanner will have deleted these files.';
|
87 |
+
}
|
88 |
+
else {
|
89 |
+
$oResponse->setSuccessful( false );
|
90 |
+
$sMessage = 'No attempt was made to delete any files since the checkbox was not checked.';
|
91 |
+
}
|
92 |
+
|
93 |
+
return $oResponse->setMessageText( $sMessage );
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* @return \FernleafSystems\Utilities\Response
|
98 |
+
*/
|
99 |
+
private function process_RestoreFiles() {
|
100 |
+
/** @var ICWP_WPSF_FeatureHandler_HackProtect $oFO */
|
101 |
+
$oFO = $this->getModCon();
|
102 |
+
|
103 |
+
if ( $this->loadDP()->post( 'RestoreFiles' ) === 'Y' ) {
|
104 |
+
/** @var ICWP_WPSF_Processor_HackProtect $oProc */
|
105 |
+
$oProc = $oFO->getProcessor();
|
106 |
+
$oProc->getSubProcessorChecksumScan()->doChecksumScan( true );
|
107 |
+
|
108 |
+
$sMessage = 'The scanner will have restore these files if your filesystem permissions allowed it.';
|
109 |
+
}
|
110 |
+
else {
|
111 |
+
$sMessage = 'No attempt was made to restore the files since the checkbox was not checked.';
|
112 |
+
}
|
113 |
+
|
114 |
+
$oResponse = new \FernleafSystems\Utilities\Response();
|
115 |
+
return $oResponse->setSuccessful( true )
|
116 |
+
->setMessageText( $sMessage );
|
117 |
+
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* @return \FernleafSystems\Utilities\Response
|
121 |
+
*/
|
122 |
+
private function process_UfcConfig() {
|
123 |
+
/** @var ICWP_WPSF_FeatureHandler_HackProtect $oFO */
|
124 |
+
$oFO = $this->getModCon();
|
125 |
+
|
126 |
+
$sSetting = $this->loadDP()->post( 'enable_scan' );
|
127 |
+
$oFO->setUfcOption( $sSetting )
|
128 |
+
->savePluginOptions();
|
129 |
+
|
130 |
+
$bSuccess = ( $sSetting == $oFO->getUnrecognisedFileScannerOption() );
|
131 |
+
|
132 |
+
if ( $bSuccess ) {
|
133 |
+
if ( $oFO->isUfsEnabled() ) {
|
134 |
+
$sMessage = 'Scanner automation has been enabled.';
|
135 |
+
}
|
136 |
+
else {
|
137 |
+
$sMessage = 'Scanner automation has been disabled.';
|
138 |
+
}
|
139 |
+
}
|
140 |
+
else {
|
141 |
+
$sMessage = 'There was a problem with saving this option. You may need to reload.';
|
142 |
+
}
|
143 |
+
|
144 |
+
$oResponse = new \FernleafSystems\Utilities\Response();
|
145 |
+
return $oResponse->setSuccessful( $bSuccess )
|
146 |
+
->setMessageText( $sMessage );
|
147 |
+
}
|
148 |
+
|
149 |
+
/**
|
150 |
+
* @return \FernleafSystems\Utilities\Response
|
151 |
+
*/
|
152 |
+
private function process_WcfConfig() {
|
153 |
+
/** @var ICWP_WPSF_FeatureHandler_HackProtect $oFO */
|
154 |
+
$oFO = $this->getModCon();
|
155 |
+
|
156 |
+
$sSetting = $this->loadDP()->post( 'enable_scan' );
|
157 |
+
|
158 |
+
$bEnabled = true;
|
159 |
+
$bRestore = false;
|
160 |
+
$bProcess = true;
|
161 |
+
switch ( $sSetting ) {
|
162 |
+
case 'enabled_report_only':
|
163 |
+
break;
|
164 |
+
case 'enabled_restore_report':
|
165 |
+
$bRestore = true;
|
166 |
+
break;
|
167 |
+
default:
|
168 |
+
$bProcess = false;
|
169 |
+
break;
|
170 |
+
}
|
171 |
+
|
172 |
+
$bSuccess = false;
|
173 |
+
if ( $bProcess ) {
|
174 |
+
|
175 |
+
$oFO->setWcfScanEnabled( $bEnabled )
|
176 |
+
->setWcfScanAutoRepair( $bRestore )
|
177 |
+
->savePluginOptions();
|
178 |
+
|
179 |
+
$bSuccess = ( $bEnabled == $oFO->isWcfScanEnabled() ) && ( $bRestore === $oFO->isWcfScanAutoRepair() );
|
180 |
+
|
181 |
+
if ( $bSuccess ) {
|
182 |
+
if ( $bEnabled ) {
|
183 |
+
$sMessage = 'Scanner automation has been enabled.';
|
184 |
+
}
|
185 |
+
else {
|
186 |
+
$sMessage = 'Scanner automation has been disabled.';
|
187 |
+
}
|
188 |
+
}
|
189 |
+
else {
|
190 |
+
$sMessage = 'There was a problem with saving this option. You may need to reload.';
|
191 |
+
}
|
192 |
+
}
|
193 |
+
else {
|
194 |
+
$sMessage = 'Scanner automation is unchanged because of failed request.';
|
195 |
+
}
|
196 |
+
|
197 |
+
$oResponse = new \FernleafSystems\Utilities\Response();
|
198 |
+
return $oResponse->setSuccessful( $bSuccess )
|
199 |
+
->setMessageText( $sMessage );
|
200 |
+
}
|
201 |
+
|
202 |
+
/**
|
203 |
+
* @return string[]
|
204 |
+
* @throws Exception
|
205 |
+
*/
|
206 |
+
protected function determineWizardSteps() {
|
207 |
+
|
208 |
+
switch ( $this->getWizardSlug() ) {
|
209 |
+
case 'wcf':
|
210 |
+
$aSteps = $this->determineWizardSteps_Wcf();
|
211 |
+
break;
|
212 |
+
case 'ufc':
|
213 |
+
$aSteps = $this->determineWizardSteps_Ufc();
|
214 |
+
break;
|
215 |
+
default:
|
216 |
+
parent::determineWizardSteps();
|
217 |
+
break;
|
218 |
+
}
|
219 |
+
return array_values( array_intersect( array_keys( $this->getAllDefinedSteps() ), $aSteps ) );
|
220 |
+
}
|
221 |
+
|
222 |
+
/**
|
223 |
+
* @return string[]
|
224 |
+
*/
|
225 |
+
private function determineWizardSteps_Wcf() {
|
226 |
+
/** @var ICWP_WPSF_FeatureHandler_HackProtect $oFO */
|
227 |
+
$oFO = $this->getModCon();
|
228 |
+
|
229 |
+
$aStepsSlugs = array(
|
230 |
+
'start',
|
231 |
+
'scanresult',
|
232 |
+
);
|
233 |
+
if ( !$oFO->isWcfScanEnabled() ) {
|
234 |
+
$aStepsSlugs[] = 'config';
|
235 |
+
}
|
236 |
+
$aStepsSlugs[] = 'finished';
|
237 |
+
return $aStepsSlugs;
|
238 |
+
}
|
239 |
+
|
240 |
+
/**
|
241 |
+
* @return string[]
|
242 |
+
*/
|
243 |
+
private function determineWizardSteps_Ufc() {
|
244 |
+
/** @var ICWP_WPSF_FeatureHandler_HackProtect $oFO */
|
245 |
+
$oFO = $this->getModCon();
|
246 |
+
|
247 |
+
$aStepsSlugs = array(
|
248 |
+
'start',
|
249 |
+
'exclusions',
|
250 |
+
'scanresult'
|
251 |
+
);
|
252 |
+
if ( !$oFO->isUfsEnabled() ) {
|
253 |
+
$aStepsSlugs[] = 'config';
|
254 |
+
}
|
255 |
+
$aStepsSlugs[] = 'finished';
|
256 |
+
return $aStepsSlugs;
|
257 |
+
}
|
258 |
+
|
259 |
+
/**
|
260 |
+
* @param string $sStep
|
261 |
+
* @return array
|
262 |
+
*/
|
263 |
+
protected function getRenderData_SlideExtra( $sStep ) {
|
264 |
+
/** @var ICWP_WPSF_FeatureHandler_HackProtect $oFO */
|
265 |
+
$oFO = $this->getModCon();
|
266 |
+
/** @var ICWP_WPSF_Processor_HackProtect $oProc */
|
267 |
+
$oProc = $oFO->getProcessor();
|
268 |
+
|
269 |
+
$aAdditional = array();
|
270 |
+
|
271 |
+
$sCurrentWiz = $this->getWizardSlug();
|
272 |
+
|
273 |
+
if ( $sCurrentWiz == 'ufc' ) {
|
274 |
+
switch ( $sStep ) {
|
275 |
+
|
276 |
+
case 'exclusions':
|
277 |
+
$aFiles = $oFO->getUfcFileExclusions();
|
278 |
+
$aAdditional[ 'data' ] = array(
|
279 |
+
'files' => array(
|
280 |
+
'count' => count( $aFiles ),
|
281 |
+
'has' => !empty( $aFiles ),
|
282 |
+
'list' => implode( "\n", array_map( 'stripslashes', $aFiles ) ),
|
283 |
+
)
|
284 |
+
);
|
285 |
+
break;
|
286 |
+
|
287 |
+
case 'scanresult':
|
288 |
+
$aFiles = $this->cleanAbsPath( $oProc->getSubProcessorFileCleanerScan()->discoverFiles() );
|
289 |
+
|
290 |
+
$aAdditional[ 'data' ] = array(
|
291 |
+
'files' => array(
|
292 |
+
'count' => count( $aFiles ),
|
293 |
+
'has' => !empty( $aFiles ),
|
294 |
+
'list' => $aFiles,
|
295 |
+
)
|
296 |
+
);
|
297 |
+
break;
|
298 |
+
}
|
299 |
+
}
|
300 |
+
else if ( $sCurrentWiz == 'wcf' ) {
|
301 |
+
|
302 |
+
switch ( $sStep ) {
|
303 |
+
case 'scanresult':
|
304 |
+
$aFiles = $oProc->getSubProcessorChecksumScan()->doChecksumScan( false );
|
305 |
+
$aChecksum = $this->cleanAbsPath( $aFiles[ 'checksum_mismatch' ] );
|
306 |
+
$aMissing = $this->cleanAbsPath( $aFiles[ 'missing' ] );
|
307 |
+
|
308 |
+
$aAdditional[ 'data' ] = array(
|
309 |
+
'files' => array(
|
310 |
+
'count' => count( $aChecksum ) + count( $aMissing ),
|
311 |
+
'has' => !empty( $aChecksum ) || !empty( $aMissing ),
|
312 |
+
'checksum' => array(
|
313 |
+
'count' => count( $aChecksum ),
|
314 |
+
'has' => !empty( $aChecksum ),
|
315 |
+
'list' => $aChecksum,
|
316 |
+
),
|
317 |
+
'missing' => array(
|
318 |
+
'count' => count( $aMissing ),
|
319 |
+
'has' => !empty( $aMissing ),
|
320 |
+
'list' => $aMissing,
|
321 |
+
)
|
322 |
+
)
|
323 |
+
);
|
324 |
+
break;
|
325 |
+
}
|
326 |
+
}
|
327 |
+
|
328 |
+
if ( empty( $aAdditional ) ) {
|
329 |
+
$aAdditional = parent::getRenderData_SlideExtra( $sStep );
|
330 |
+
}
|
331 |
+
return $aAdditional;
|
332 |
+
}
|
333 |
+
|
334 |
+
/**
|
335 |
+
* @param string[] $aFilePaths
|
336 |
+
* @return string[]
|
337 |
+
*/
|
338 |
+
private function cleanAbsPath( $aFilePaths ) {
|
339 |
+
return array_map(
|
340 |
+
function ( $sFile ) {
|
341 |
+
return str_replace( ABSPATH, '', $sFile );
|
342 |
+
},
|
343 |
+
$aFilePaths
|
344 |
+
);
|
345 |
+
}
|
346 |
+
}
|
src/wizards/login_protect.php
ADDED
@@ -0,0 +1,267 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if ( class_exists( 'ICWP_WPSF_Wizard_LoginProtect', false ) ) {
|
4 |
+
return;
|
5 |
+
}
|
6 |
+
|
7 |
+
require_once( dirname( __FILE__ ).'/base_wpsf.php' );
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Class ICWP_WPSF_Processor_LoginProtect_Wizard
|
11 |
+
*/
|
12 |
+
class ICWP_WPSF_Wizard_LoginProtect extends ICWP_WPSF_Wizard_BaseWpsf {
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @return string
|
16 |
+
*/
|
17 |
+
protected function getPageTitle() {
|
18 |
+
return sprintf( _wpsf__( '%s Multi-Factor Authentication Wizard' ), $this->getPluginCon()->getHumanName() );
|
19 |
+
}
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @param string $sStep
|
23 |
+
* @return \FernleafSystems\Utilities\Response|null
|
24 |
+
*/
|
25 |
+
protected function processWizardStep( $sStep ) {
|
26 |
+
switch ( $sStep ) {
|
27 |
+
case 'authemail':
|
28 |
+
$oResponse = $this->processAuthEmail();
|
29 |
+
break;
|
30 |
+
|
31 |
+
case 'authga':
|
32 |
+
$oResponse = $this->processAuthGa();
|
33 |
+
break;
|
34 |
+
|
35 |
+
case 'multiselect':
|
36 |
+
$oResponse = $this->processMultiSelect();
|
37 |
+
break;
|
38 |
+
|
39 |
+
default:
|
40 |
+
$oResponse = parent::processWizardStep( $sStep );
|
41 |
+
break;
|
42 |
+
}
|
43 |
+
return $oResponse;
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* @return \FernleafSystems\Utilities\Response
|
48 |
+
*/
|
49 |
+
private function processAuthEmail() {
|
50 |
+
/** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
|
51 |
+
$oFO = $this->getModCon();
|
52 |
+
$oDP = $this->loadDP();
|
53 |
+
|
54 |
+
$oResponse = new \FernleafSystems\Utilities\Response();
|
55 |
+
$oResponse->setSuccessful( false );
|
56 |
+
|
57 |
+
$sEmail = $oDP->post( 'email' );
|
58 |
+
$sCode = $oDP->post( 'code' );
|
59 |
+
$bFa = $oDP->post( 'Email2FAOption' ) === 'Y';
|
60 |
+
|
61 |
+
if ( !$oDP->validEmail( $sEmail ) ) {
|
62 |
+
$sMessage = _wpsf__( 'Invalid email address' );
|
63 |
+
}
|
64 |
+
else {
|
65 |
+
if ( empty( $sCode ) ) {
|
66 |
+
if ( $oFO->sendEmailVerifyCanSend( $sEmail, false ) ) {
|
67 |
+
$oResponse->setSuccessful( true );
|
68 |
+
$sMessage = 'Verification email sent - please check your email (including your SPAM)';
|
69 |
+
}
|
70 |
+
else {
|
71 |
+
$sMessage = 'Failed to send verification email';
|
72 |
+
}
|
73 |
+
}
|
74 |
+
else {
|
75 |
+
if ( $sCode == $oFO->getCanEmailVerifyCode() ) {
|
76 |
+
$oResponse->setSuccessful( true );
|
77 |
+
$sMessage = 'Email sending has been verified successfully.';
|
78 |
+
|
79 |
+
$oFO->setIfCanSendEmail( true );
|
80 |
+
|
81 |
+
if ( $bFa ) {
|
82 |
+
$oFO->setEnabled2FaEmail( true );
|
83 |
+
$sMessage .= ' '.'Email-based two factor authentication is now enabled.';
|
84 |
+
}
|
85 |
+
else {
|
86 |
+
$sMessage .= ' '.'Email-based two factor authentication is NOT enabled.';
|
87 |
+
}
|
88 |
+
}
|
89 |
+
else {
|
90 |
+
$sMessage = 'This does not appear to be the correct 6-digit code that was sent to you.'
|
91 |
+
.'Email-based two factor authentication option has not been updated.';
|
92 |
+
}
|
93 |
+
}
|
94 |
+
}
|
95 |
+
|
96 |
+
return $oResponse->setMessageText( $sMessage );
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* @return \FernleafSystems\Utilities\Response
|
101 |
+
*/
|
102 |
+
private function processAuthGa() {
|
103 |
+
/** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
|
104 |
+
$oFO = $this->getModCon();
|
105 |
+
$oDP = $this->loadDP();
|
106 |
+
|
107 |
+
$oResponse = new \FernleafSystems\Utilities\Response();
|
108 |
+
$oResponse->setSuccessful( false );
|
109 |
+
|
110 |
+
$sCode = $oDP->post( 'code' );
|
111 |
+
$bEnableGa = $oDP->post( 'enablega' ) === 'Y';
|
112 |
+
|
113 |
+
$sMessage = '';
|
114 |
+
if ( $sCode != 'ignore' ) {
|
115 |
+
|
116 |
+
if ( empty( $sCode ) ) {
|
117 |
+
$sMessage = _wpsf__( 'Code was empty.' );
|
118 |
+
}
|
119 |
+
else {
|
120 |
+
$oUser = $this->loadWpUsers()->getCurrentWpUser();
|
121 |
+
/** @var ICWP_WPSF_Processor_LoginProtect $oProc */
|
122 |
+
$oProc = $oFO->getProcessor();
|
123 |
+
$oProcGa = $oProc->getProcessorLoginIntent()
|
124 |
+
->getProcessorGoogleAuthenticator();
|
125 |
+
$bValidated = $oProcGa->validateGaCode( $oUser, $sCode );
|
126 |
+
|
127 |
+
if ( $bValidated ) {
|
128 |
+
$oProcGa->setProfileValidated( $oUser, true );
|
129 |
+
$sMessage = 'Google Authenticator was validated.';
|
130 |
+
$oResponse->setSuccessful( true );
|
131 |
+
}
|
132 |
+
else {
|
133 |
+
$sMessage = 'Could not validate - this does not appear to be the correct 6-digit code.';
|
134 |
+
$bEnableGa = false; // we don't enable GA on the site if the code was bad.
|
135 |
+
}
|
136 |
+
}
|
137 |
+
}
|
138 |
+
else {
|
139 |
+
$oResponse->setSuccessful( true );
|
140 |
+
}
|
141 |
+
|
142 |
+
if ( $bEnableGa ) {
|
143 |
+
$oFO->setEnabled2FaGoogleAuthenticator( true );
|
144 |
+
$sMessage .= ' '._wpsf__( 'Google Authenticator was enabled for the site.' );
|
145 |
+
}
|
146 |
+
|
147 |
+
return $oResponse->setMessageText( $sMessage );
|
148 |
+
}
|
149 |
+
|
150 |
+
/**
|
151 |
+
* @return \FernleafSystems\Utilities\Response
|
152 |
+
*/
|
153 |
+
private function processMultiSelect() {
|
154 |
+
/** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
|
155 |
+
$oFO = $this->getModCon();
|
156 |
+
|
157 |
+
$bEnabledMulti = $this->loadDP()->post( 'multiselect' ) === 'Y';
|
158 |
+
$oFO->setIsChainedAuth( $bEnabledMulti );
|
159 |
+
$sMessage = sprintf( _wpsf__( 'Multi-Factor Authentication was %s for the site.' ),
|
160 |
+
$bEnabledMulti ? _wpsf__( 'enabled' ) : _wpsf__( 'disabled' )
|
161 |
+
);
|
162 |
+
|
163 |
+
$oResponse = new \FernleafSystems\Utilities\Response();
|
164 |
+
return $oResponse->setSuccessful( true )
|
165 |
+
->setMessageText( $sMessage );
|
166 |
+
}
|
167 |
+
|
168 |
+
/**
|
169 |
+
* @return string[]
|
170 |
+
* @throws Exception
|
171 |
+
*/
|
172 |
+
protected function determineWizardSteps() {
|
173 |
+
|
174 |
+
switch ( $this->getWizardSlug() ) {
|
175 |
+
case 'mfa':
|
176 |
+
$aSteps = $this->determineWizardSteps_Mfa();
|
177 |
+
break;
|
178 |
+
default:
|
179 |
+
parent::determineWizardSteps();
|
180 |
+
break;
|
181 |
+
}
|
182 |
+
return array_values( array_intersect( array_keys( $this->getAllDefinedSteps() ), $aSteps ) );
|
183 |
+
}
|
184 |
+
|
185 |
+
/**
|
186 |
+
* @return string[]
|
187 |
+
*/
|
188 |
+
private function determineWizardSteps_Mfa() {
|
189 |
+
/** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
|
190 |
+
$oFO = $this->getModCon();
|
191 |
+
|
192 |
+
$aStepsSlugs = array( 'start' );
|
193 |
+
|
194 |
+
if ( !$oFO->getIfCanSendEmailVerified() || !$oFO->getIsEmailAuthenticationEnabled() ) {
|
195 |
+
$aStepsSlugs[] = 'authemail';
|
196 |
+
}
|
197 |
+
|
198 |
+
if ( !$oFO->getIsEnabledGoogleAuthenticator() ) {
|
199 |
+
$aStepsSlugs[] = 'authga';
|
200 |
+
}
|
201 |
+
|
202 |
+
$aStepsSlugs[] = 'multiselect';
|
203 |
+
$aStepsSlugs[] = 'finished';
|
204 |
+
return $aStepsSlugs;
|
205 |
+
}
|
206 |
+
|
207 |
+
/**
|
208 |
+
* @param string $sStep
|
209 |
+
* @return array
|
210 |
+
*/
|
211 |
+
protected function getRenderData_SlideExtra( $sStep ) {
|
212 |
+
/** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
|
213 |
+
$oFO = $this->getModCon();
|
214 |
+
|
215 |
+
$aAdditional = array();
|
216 |
+
|
217 |
+
switch ( $sStep ) {
|
218 |
+
|
219 |
+
case 'authemail':
|
220 |
+
$oUser = $this->loadWpUsers()->getCurrentWpUser();
|
221 |
+
$aAdditional = array(
|
222 |
+
'data' => array(
|
223 |
+
'name' => $oUser->first_name,
|
224 |
+
'user_email' => $oUser->user_email
|
225 |
+
)
|
226 |
+
);
|
227 |
+
break;
|
228 |
+
|
229 |
+
case 'authga':
|
230 |
+
$oUser = $this->loadWpUsers()->getCurrentWpUser();
|
231 |
+
/** @var ICWP_WPSF_Processor_LoginProtect $oProc */
|
232 |
+
$oProc = $oFO->getProcessor();
|
233 |
+
$oProcGa = $oProc->getProcessorLoginIntent()
|
234 |
+
->getProcessorGoogleAuthenticator();
|
235 |
+
$sGaUrl = $oProcGa->getGaRegisterChartUrl( $oUser );
|
236 |
+
$aAdditional = array(
|
237 |
+
'data' => array(
|
238 |
+
'name' => $oUser->first_name,
|
239 |
+
'user_email' => $oUser->user_email
|
240 |
+
),
|
241 |
+
'hrefs' => array(
|
242 |
+
'ga_chart' => $sGaUrl,
|
243 |
+
),
|
244 |
+
'flags' => array(
|
245 |
+
'has_ga' => $oProcGa->getCurrentUserHasValidatedProfile(),
|
246 |
+
)
|
247 |
+
);
|
248 |
+
break;
|
249 |
+
|
250 |
+
case 'multiselect':
|
251 |
+
$aAdditional = array(
|
252 |
+
'flags' => array(
|
253 |
+
'has_multiselect' => $oFO->isChainedAuth(),
|
254 |
+
)
|
255 |
+
);
|
256 |
+
break;
|
257 |
+
|
258 |
+
default:
|
259 |
+
break;
|
260 |
+
}
|
261 |
+
|
262 |
+
if ( empty( $aAdditional ) ) {
|
263 |
+
$aAdditional = parent::getRenderData_SlideExtra( $sStep );
|
264 |
+
}
|
265 |
+
return $aAdditional;
|
266 |
+
}
|
267 |
+
}
|
src/wizards/plugin.php
ADDED
@@ -0,0 +1,548 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if ( class_exists( 'ICWP_WPSF_Wizard_Plugin', false ) ) {
|
4 |
+
return;
|
5 |
+
}
|
6 |
+
|
7 |
+
require_once( dirname( __FILE__ ).'/base_wpsf.php' );
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Class ICWP_WPSF_Processor_LoginProtect_Wizard
|
11 |
+
*/
|
12 |
+
class ICWP_WPSF_Wizard_Plugin extends ICWP_WPSF_Wizard_BaseWpsf {
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @return string[]
|
16 |
+
*/
|
17 |
+
protected function getSupportedWizards() {
|
18 |
+
return array( 'welcome', 'importexport' );
|
19 |
+
}
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @return string
|
23 |
+
*/
|
24 |
+
protected function getPageTitle() {
|
25 |
+
return sprintf( _wpsf__( '%s Welcome Wizard' ), $this->getPluginCon()->getHumanName() );
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @param string $sStep
|
30 |
+
* @return \FernleafSystems\Utilities\Response|null
|
31 |
+
*/
|
32 |
+
protected function processWizardStep( $sStep ) {
|
33 |
+
switch ( $sStep ) {
|
34 |
+
|
35 |
+
case 'ip_detect':
|
36 |
+
$oResponse = $this->wizardIpDetect();
|
37 |
+
break;
|
38 |
+
|
39 |
+
case 'license':
|
40 |
+
$oResponse = $this->wizardLicense();
|
41 |
+
break;
|
42 |
+
|
43 |
+
case 'import':
|
44 |
+
$oResponse = $this->wizardImportOptions();
|
45 |
+
break;
|
46 |
+
|
47 |
+
case 'admin_access_restriction':
|
48 |
+
$oResponse = $this->wizardSecurityAdmin();
|
49 |
+
break;
|
50 |
+
|
51 |
+
case 'audit_trail':
|
52 |
+
$oResponse = $this->wizardAuditTrail();
|
53 |
+
break;
|
54 |
+
|
55 |
+
case 'ips':
|
56 |
+
$oResponse = $this->wizardIps();
|
57 |
+
break;
|
58 |
+
|
59 |
+
case 'comments_filter':
|
60 |
+
$oResponse = $this->wizardCommentsFilter();
|
61 |
+
break;
|
62 |
+
|
63 |
+
case 'login_protect':
|
64 |
+
$oResponse = $this->wizardLoginProtect();
|
65 |
+
break;
|
66 |
+
|
67 |
+
case 'optin':
|
68 |
+
$oResponse = $this->wizardOptin();
|
69 |
+
break;
|
70 |
+
|
71 |
+
default:
|
72 |
+
$oResponse = parent::processWizardStep( $sStep );
|
73 |
+
break;
|
74 |
+
}
|
75 |
+
return $oResponse;
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* @return string[]
|
80 |
+
* @throws Exception
|
81 |
+
*/
|
82 |
+
protected function determineWizardSteps() {
|
83 |
+
|
84 |
+
switch ( $this->getWizardSlug() ) {
|
85 |
+
case 'welcome':
|
86 |
+
$aSteps = $this->determineWizardSteps_Welcome();
|
87 |
+
break;
|
88 |
+
case 'importexport':
|
89 |
+
$aSteps = $this->determineWizardSteps_Import();
|
90 |
+
break;
|
91 |
+
default:
|
92 |
+
parent::determineWizardSteps();
|
93 |
+
break;
|
94 |
+
}
|
95 |
+
return array_values( array_intersect( array_keys( $this->getAllDefinedSteps() ), $aSteps ) );
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* @return string[]
|
100 |
+
*/
|
101 |
+
private function determineWizardSteps_Import() {
|
102 |
+
return array(
|
103 |
+
'start',
|
104 |
+
'import',
|
105 |
+
'finished',
|
106 |
+
);
|
107 |
+
}
|
108 |
+
|
109 |
+
/**
|
110 |
+
* @return string[]
|
111 |
+
*/
|
112 |
+
private function determineWizardSteps_Welcome() {
|
113 |
+
/** @var ICWP_WPSF_FeatureHandler_Plugin $oFO */
|
114 |
+
$oFO = $this->getModCon();
|
115 |
+
$oConn = $this->getPluginCon();
|
116 |
+
|
117 |
+
$aStepsSlugs = array(
|
118 |
+
'welcome',
|
119 |
+
'ip_detect'
|
120 |
+
);
|
121 |
+
// if ( !$oFO->isPremium() ) {
|
122 |
+
// $aStepsSlugs[] = 'license'; not showing it for now
|
123 |
+
// }
|
124 |
+
|
125 |
+
if ( $oFO->isPremium() ) {
|
126 |
+
$aStepsSlugs[] = 'import';
|
127 |
+
}
|
128 |
+
|
129 |
+
if ( !$oConn->getModule( 'admin_access_restriction' )->getIsMainFeatureEnabled() ) {
|
130 |
+
$aStepsSlugs[] = 'admin_access_restriction';
|
131 |
+
}
|
132 |
+
|
133 |
+
/** @var ICWP_WPSF_FeatureHandler_AuditTrail $oModule */
|
134 |
+
$oModule = $oConn->getModule( 'audit_trail' );
|
135 |
+
if ( !$oModule->getIsMainFeatureEnabled() ) {
|
136 |
+
$aStepsSlugs[] = 'audit_trail';
|
137 |
+
}
|
138 |
+
|
139 |
+
if ( !$oConn->getModule( 'ips' )->getIsMainFeatureEnabled() ) {
|
140 |
+
$aStepsSlugs[] = 'ips';
|
141 |
+
}
|
142 |
+
|
143 |
+
/** @var ICWP_WPSF_FeatureHandler_LoginProtect $oModule */
|
144 |
+
$oModule = $oConn->getModule( 'login_protect' );
|
145 |
+
if ( !( $oModule->getIsMainFeatureEnabled() && $oModule->isEnabledGaspCheck() ) ) {
|
146 |
+
$aStepsSlugs[] = 'login_protect';
|
147 |
+
}
|
148 |
+
|
149 |
+
/** @var ICWP_WPSF_FeatureHandler_CommentsFilter $oModule */
|
150 |
+
$oModule = $oConn->getModule( 'comments_filter' );
|
151 |
+
if ( !( $oModule->getIsMainFeatureEnabled() && $oModule->isEnabledGaspCheck() ) ) {
|
152 |
+
$aStepsSlugs[] = 'comments_filter';
|
153 |
+
}
|
154 |
+
|
155 |
+
$aStepsSlugs[] = 'how_shield_works';
|
156 |
+
$aStepsSlugs[] = 'optin';
|
157 |
+
|
158 |
+
if ( !$oFO->isPremium() ) {
|
159 |
+
$aStepsSlugs[] = 'import';
|
160 |
+
}
|
161 |
+
|
162 |
+
$aStepsSlugs[] = 'thankyou';
|
163 |
+
return $aStepsSlugs;
|
164 |
+
}
|
165 |
+
|
166 |
+
/**
|
167 |
+
* @param string $sStep
|
168 |
+
* @return array
|
169 |
+
*/
|
170 |
+
protected function getRenderData_SlideExtra( $sStep ) {
|
171 |
+
$oConn = $this->getPluginCon();
|
172 |
+
|
173 |
+
$aAdditional = array();
|
174 |
+
|
175 |
+
$sCurrentWiz = $this->getWizardSlug();
|
176 |
+
|
177 |
+
if ( $sCurrentWiz == 'welcome' ) {
|
178 |
+
|
179 |
+
switch ( $sStep ) {
|
180 |
+
case 'ip_detect':
|
181 |
+
$aAdditional = array(
|
182 |
+
'hrefs' => array(
|
183 |
+
'visitor_ip' => 'http://icwp.io/visitorip',
|
184 |
+
)
|
185 |
+
);
|
186 |
+
break;
|
187 |
+
case 'license':
|
188 |
+
break;
|
189 |
+
case 'import':
|
190 |
+
$aAdditional = array(
|
191 |
+
'hrefs' => array(
|
192 |
+
'blog_importexport' => 'http://icwp.io/av'
|
193 |
+
),
|
194 |
+
'imgs' => array(
|
195 |
+
'shieldnetworkmini' => $oConn->getPluginUrl_Image( 'shield/shieldnetworkmini.png' ),
|
196 |
+
)
|
197 |
+
);
|
198 |
+
break;
|
199 |
+
|
200 |
+
case 'optin':
|
201 |
+
$oUser = $this->loadWpUsers()->getCurrentWpUser();
|
202 |
+
$aAdditional = array(
|
203 |
+
'data' => array(
|
204 |
+
'name' => $oUser->first_name,
|
205 |
+
'user_email' => $oUser->user_email
|
206 |
+
)
|
207 |
+
);
|
208 |
+
break;
|
209 |
+
|
210 |
+
case 'thankyou':
|
211 |
+
break;
|
212 |
+
|
213 |
+
case 'how_shield_works':
|
214 |
+
$aAdditional = array(
|
215 |
+
'imgs' => array(
|
216 |
+
'how_shield_works' => $oConn->getPluginUrl_Image( 'wizard/general-shield_where.png' ),
|
217 |
+
'modules' => $oConn->getPluginUrl_Image( 'wizard/general-shield_modules.png' ),
|
218 |
+
'options' => $oConn->getPluginUrl_Image( 'wizard/general-shield_options.png' ),
|
219 |
+
'help' => $oConn->getPluginUrl_Image( 'wizard/general-shield_help.png' ),
|
220 |
+
'actions' => $oConn->getPluginUrl_Image( 'wizard/general-shield_actions.png' ),
|
221 |
+
'module_onoff' => $oConn->getPluginUrl_Image( 'wizard/general-module_onoff.png' ),
|
222 |
+
'option_help' => $oConn->getPluginUrl_Image( 'wizard/general-option_help.png' ),
|
223 |
+
),
|
224 |
+
'headings' => array(
|
225 |
+
'how_shield_works' => _wpsf__( 'Where to find Shield' ),
|
226 |
+
'modules' => _wpsf__( 'Accessing Each Module' ),
|
227 |
+
'options' => _wpsf__( 'Accessing Options' ),
|
228 |
+
'help' => _wpsf__( 'Finding Help' ),
|
229 |
+
'actions' => _wpsf__( 'Actions (not Options)' ),
|
230 |
+
'module_onoff' => _wpsf__( 'Module On/Off Switch' ),
|
231 |
+
'option_help' => _wpsf__( 'Help For Each Option' ),
|
232 |
+
),
|
233 |
+
'captions' => array(
|
234 |
+
'how_shield_works' => _wpsf__( "You'll find the main Shield Security setting in the left-hand WordPress menu." ),
|
235 |
+
'modules' => _wpsf__( 'Shield is split up into independent modules for accessing the options of each feature.' ),
|
236 |
+
'options' => _wpsf__( 'When you load a module, you can access the options by clicking on the Options Panel link.' ),
|
237 |
+
'help' => _wpsf__( 'Each module also has a brief overview help section - there is more in-depth help available.' ),
|
238 |
+
'actions' => _wpsf__( 'Certain modules have extra actions and features, e.g. Audit Trail Viewer.' )
|
239 |
+
.' '._wpsf__( 'Note: Not all modules have the actions section' ),
|
240 |
+
'module_onoff' => _wpsf__( 'Each module has an Enable/Disable checkbox to turn on/off all processing for that module' ),
|
241 |
+
'option_help' => _wpsf__( 'To help you understand each option, most of them have a more info link, and/or a blog link, to read more' ),
|
242 |
+
),
|
243 |
+
);
|
244 |
+
break;
|
245 |
+
default:
|
246 |
+
break;
|
247 |
+
}
|
248 |
+
}
|
249 |
+
else if ( $sCurrentWiz == 'importexport' ) {
|
250 |
+
switch ( $sStep ) {
|
251 |
+
case 'import':
|
252 |
+
$aAdditional = array(
|
253 |
+
'hrefs' => array(
|
254 |
+
'blog_importexport' => 'http://icwp.io/av'
|
255 |
+
),
|
256 |
+
'imgs' => array(
|
257 |
+
'shieldnetworkmini' => $oConn->getPluginUrl_Image( 'shield/shieldnetworkmini.png' ),
|
258 |
+
)
|
259 |
+
);
|
260 |
+
break;
|
261 |
+
|
262 |
+
default:
|
263 |
+
break;
|
264 |
+
}
|
265 |
+
}
|
266 |
+
|
267 |
+
if ( empty( $aAdditional ) ) {
|
268 |
+
$aAdditional = parent::getRenderData_SlideExtra( $sStep );
|
269 |
+
}
|
270 |
+
return $aAdditional;
|
271 |
+
}
|
272 |
+
|
273 |
+
/**
|
274 |
+
* @return \FernleafSystems\Utilities\Response
|
275 |
+
*/
|
276 |
+
private function wizardIpDetect() {
|
277 |
+
$oIps = $this->loadIpService();
|
278 |
+
$sIp = $this->loadDP()->post( 'ip' );
|
279 |
+
|
280 |
+
$oResponse = new \FernleafSystems\Utilities\Response();
|
281 |
+
$oResponse->setSuccessful( false );
|
282 |
+
if ( empty( $sIp ) ) {
|
283 |
+
$sMessage = 'IP address was empty.';
|
284 |
+
}
|
285 |
+
else if ( !$oIps->isValidIp_PublicRemote( $sIp ) ) {
|
286 |
+
$sMessage = 'The IP address supplied was not a valid public IP address.';
|
287 |
+
}
|
288 |
+
// else if ( $oIps->getIpVersion( $sIp ) != 4 ) {
|
289 |
+
// $sMessage = 'The IP address supplied was not a valid IP address.';
|
290 |
+
// }
|
291 |
+
else {
|
292 |
+
$sSource = $oIps->determineSourceFromIp( $sIp );
|
293 |
+
if ( empty( $sSource ) ) {
|
294 |
+
$sMessage = 'Strange, the address source could not be found from this IP.';
|
295 |
+
}
|
296 |
+
else {
|
297 |
+
/** @var ICWP_WPSF_FeatureHandler_Plugin $oModule */
|
298 |
+
$oModule = $this->getPluginCon()->getModule( 'plugin' );
|
299 |
+
$oModule->setVisitorAddressSource( $sSource )
|
300 |
+
->savePluginOptions();
|
301 |
+
$oResponse->setSuccessful( true );
|
302 |
+
$sMessage = _wpsf__( 'Success!' ).' '
|
303 |
+
.sprintf( '"%s" was found to be the best source of visitor IP addresses for your site.', $sSource );
|
304 |
+
}
|
305 |
+
}
|
306 |
+
|
307 |
+
return $oResponse->setMessageText( $sMessage );
|
308 |
+
}
|
309 |
+
|
310 |
+
/**
|
311 |
+
* @return \FernleafSystems\Utilities\Response
|
312 |
+
*/
|
313 |
+
private function wizardLicense() {
|
314 |
+
$sKey = $this->loadDP()->post( 'LicenseKey' );
|
315 |
+
|
316 |
+
$bSuccess = false;
|
317 |
+
if ( empty( $sKey ) ) {
|
318 |
+
$sMessage = 'License key was empty.';
|
319 |
+
}
|
320 |
+
else {
|
321 |
+
/** @var ICWP_WPSF_FeatureHandler_License $oModule */
|
322 |
+
$oModule = $this->getPluginCon()->getModule( 'license' );
|
323 |
+
try {
|
324 |
+
$oModule->activateOfficialLicense( $sKey, true );
|
325 |
+
if ( $oModule->hasValidWorkingLicense() ) {
|
326 |
+
$bSuccess = true;
|
327 |
+
$sMessage = _wpsf__( 'License key was accepted and installed successfully.' );
|
328 |
+
}
|
329 |
+
else {
|
330 |
+
$sMessage = _wpsf__( 'License key was not accepted.' );
|
331 |
+
}
|
332 |
+
}
|
333 |
+
catch ( Exception $oE ) {
|
334 |
+
$sMessage = _wpsf__( $oE->getMessage() );
|
335 |
+
}
|
336 |
+
}
|
337 |
+
|
338 |
+
$oResponse = new \FernleafSystems\Utilities\Response();
|
339 |
+
return $oResponse->setSuccessful( $bSuccess )
|
340 |
+
->setMessageText( $sMessage );
|
341 |
+
}
|
342 |
+
|
343 |
+
/**
|
344 |
+
* @return \FernleafSystems\Utilities\Response
|
345 |
+
*/
|
346 |
+
private function wizardImportOptions() {
|
347 |
+
/** @var ICWP_WPSF_FeatureHandler_Plugin $oFO */
|
348 |
+
$oFO = $this->getModCon();
|
349 |
+
$oDP = $this->loadDP();
|
350 |
+
|
351 |
+
$sMasterSiteUrl = $oDP->post( 'MasterSiteUrl' );
|
352 |
+
$sSecretKey = $oDP->post( 'MasterSiteSecretKey' );
|
353 |
+
$bEnabledNetwork = $oDP->post( 'ShieldNetworkCheck' ) === 'Y';
|
354 |
+
|
355 |
+
/** @var ICWP_WPSF_Processor_Plugin $oProc */
|
356 |
+
$oProc = $oFO->getProcessor();
|
357 |
+
$nCode = $oProc->getSubProcessorImportExport()
|
358 |
+
->runImport( $sMasterSiteUrl, $sSecretKey, $bEnabledNetwork, $sSiteResponse );
|
359 |
+
|
360 |
+
$aErrors = array(
|
361 |
+
_wpsf__( 'Options imported successfully to your site.' ), // success
|
362 |
+
_wpsf__( 'Secret key was empty.' ),
|
363 |
+
_wpsf__( 'Secret key was not 40 characters long.' ),
|
364 |
+
_wpsf__( 'Secret key contains invalid characters - it should be letters and numbers only.' ),
|
365 |
+
_wpsf__( 'Source site URL could not be parsed correctly.' ),
|
366 |
+
_wpsf__( 'Could not parse the response from the site.' )
|
367 |
+
.' '._wpsf__( 'Check the secret key is correct for the remote site.' ),
|
368 |
+
_wpsf__( 'Failure response returned from the site.' ),
|
369 |
+
sprintf( _wpsf__( 'Remote site responded with - %s' ), $sSiteResponse ),
|
370 |
+
_wpsf__( 'Data returned from the site was empty.' )
|
371 |
+
);
|
372 |
+
|
373 |
+
$sMessage = isset( $aErrors[ $nCode ] ) ? $aErrors[ $nCode ] : 'Unknown Error';
|
374 |
+
|
375 |
+
$oResponse = new \FernleafSystems\Utilities\Response();
|
376 |
+
return $oResponse->setSuccessful( $nCode === 0 )
|
377 |
+
->setMessageText( $sMessage );
|
378 |
+
}
|
379 |
+
|
380 |
+
/**
|
381 |
+
* @return \FernleafSystems\Utilities\Response
|
382 |
+
*/
|
383 |
+
private function wizardSecurityAdmin() {
|
384 |
+
$oDP = $this->loadDP();
|
385 |
+
$sKey = $oDP->post( 'AccessKey' );
|
386 |
+
$sConfirm = $oDP->post( 'AccessKeyConfirm' );
|
387 |
+
|
388 |
+
$oResponse = new \FernleafSystems\Utilities\Response();
|
389 |
+
|
390 |
+
$bSuccess = false;
|
391 |
+
if ( empty( $sKey ) ) {
|
392 |
+
$sMessage = 'Security access key was empty.';
|
393 |
+
}
|
394 |
+
else if ( $sKey != $sConfirm ) {
|
395 |
+
$sMessage = 'Keys do not match.';
|
396 |
+
}
|
397 |
+
else {
|
398 |
+
/** @var ICWP_WPSF_FeatureHandler_AdminAccessRestriction $oModule */
|
399 |
+
$oModule = $this->getPluginCon()->getModule( 'admin_access_restriction' );
|
400 |
+
try {
|
401 |
+
$oModule->setNewAccessKeyManually( $sKey )
|
402 |
+
->setPermissionToSubmit( true );
|
403 |
+
$bSuccess = true;
|
404 |
+
$sMessage = _wpsf__( 'Security Admin setup was successful.' );
|
405 |
+
}
|
406 |
+
catch ( Exception $oE ) {
|
407 |
+
$sMessage = _wpsf__( $oE->getMessage() );
|
408 |
+
}
|
409 |
+
}
|
410 |
+
|
411 |
+
return $oResponse->setSuccessful( $bSuccess )
|
412 |
+
->setMessageText( $sMessage );
|
413 |
+
}
|
414 |
+
|
415 |
+
/**
|
416 |
+
* @return \FernleafSystems\Utilities\Response
|
417 |
+
*/
|
418 |
+
private function wizardAuditTrail() {
|
419 |
+
$bEnabled = $this->loadDP()->post( 'AuditTrailOption' ) === 'Y';
|
420 |
+
|
421 |
+
/** @var ICWP_WPSF_FeatureHandler_AdminAccessRestriction $oModule */
|
422 |
+
$oModule = $this->getPluginCon()->getModule( 'audit_trail' );
|
423 |
+
$oModule->setIsMainFeatureEnabled( $bEnabled )
|
424 |
+
->savePluginOptions();
|
425 |
+
|
426 |
+
$bSuccess = $oModule->getIsMainFeatureEnabled() === $bEnabled;
|
427 |
+
if ( $bSuccess ) {
|
428 |
+
$sMessage = sprintf( '%s has been %s.', _wpsf__( 'Audit Trail' ),
|
429 |
+
$oModule->getIsMainFeatureEnabled() ? _wpsf__( 'Enabled' ) : _wpsf__( 'Disabled' )
|
430 |
+
);
|
431 |
+
}
|
432 |
+
else {
|
433 |
+
$sMessage = sprintf( _wpsf__( '%s setting could not be changed at this time.' ), _wpsf__( 'Audit Trail' ) );
|
434 |
+
}
|
435 |
+
|
436 |
+
$oResponse = new \FernleafSystems\Utilities\Response();
|
437 |
+
return $oResponse->setSuccessful( $bSuccess )
|
438 |
+
->setMessageText( $sMessage );
|
439 |
+
}
|
440 |
+
|
441 |
+
/**
|
442 |
+
* @return \FernleafSystems\Utilities\Response
|
443 |
+
*/
|
444 |
+
private function wizardIps() {
|
445 |
+
|
446 |
+
$bEnabled = $this->loadDP()->post( 'IpManagerOption' ) === 'Y';
|
447 |
+
|
448 |
+
/** @var ICWP_WPSF_FeatureHandler_Ips $oModule */
|
449 |
+
$oModule = $this->getPluginCon()->getModule( 'ips' );
|
450 |
+
$oModule->setIsMainFeatureEnabled( $bEnabled )
|
451 |
+
->savePluginOptions();
|
452 |
+
|
453 |
+
$bSuccess = $oModule->getIsMainFeatureEnabled() === $bEnabled;
|
454 |
+
if ( $bSuccess ) {
|
455 |
+
$sMessage = sprintf( '%s has been %s.', _wpsf__( 'IP Manager' ),
|
456 |
+
$oModule->getIsMainFeatureEnabled() ? _wpsf__( 'Enabled' ) : _wpsf__( 'Disabled' )
|
457 |
+
);
|
458 |
+
}
|
459 |
+
else {
|
460 |
+
$sMessage = sprintf( _wpsf__( '%s setting could not be changed at this time.' ), _wpsf__( 'IP Manager' ) );
|
461 |
+
}
|
462 |
+
|
463 |
+
$oResponse = new \FernleafSystems\Utilities\Response();
|
464 |
+
return $oResponse->setSuccessful( $bSuccess )
|
465 |
+
->setMessageText( $sMessage );
|
466 |
+
}
|
467 |
+
|
468 |
+
/**
|
469 |
+
* @return \FernleafSystems\Utilities\Response
|
470 |
+
*/
|
471 |
+
private function wizardLoginProtect() {
|
472 |
+
|
473 |
+
$bEnabled = $this->loadDP()->post( 'LoginProtectOption' ) === 'Y';
|
474 |
+
|
475 |
+
/** @var ICWP_WPSF_FeatureHandler_LoginProtect $oModule */
|
476 |
+
$oModule = $this->getPluginCon()->getModule( 'login_protect' );
|
477 |
+
if ( $bEnabled ) { // we don't disable the whole module
|
478 |
+
$oModule->setIsMainFeatureEnabled( true );
|
479 |
+
}
|
480 |
+
$oModule->setEnabledGaspCheck( $bEnabled )
|
481 |
+
->savePluginOptions();
|
482 |
+
|
483 |
+
$bSuccess = $oModule->getIsMainFeatureEnabled() === $bEnabled;
|
484 |
+
if ( $bSuccess ) {
|
485 |
+
$sMessage = sprintf( '%s has been %s.', _wpsf__( 'Login Protection' ),
|
486 |
+
$oModule->getIsMainFeatureEnabled() ? _wpsf__( 'Enabled' ) : _wpsf__( 'Disabled' )
|
487 |
+
);
|
488 |
+
}
|
489 |
+
else {
|
490 |
+
$sMessage = sprintf( _wpsf__( '%s setting could not be changed at this time.' ), _wpsf__( 'Login Protection' ) );
|
491 |
+
}
|
492 |
+
|
493 |
+
$oResponse = new \FernleafSystems\Utilities\Response();
|
494 |
+
return $oResponse->setSuccessful( $bSuccess )
|
495 |
+
->setMessageText( $sMessage );
|
496 |
+
}
|
497 |
+
|
498 |
+
/**
|
499 |
+
* @return \FernleafSystems\Utilities\Response
|
500 |
+
*/
|
501 |
+
private function wizardOptin() {
|
502 |
+
$oDP = $this->loadDP();
|
503 |
+
|
504 |
+
$bEnabledTracking = $oDP->post( 'AnonymousOption', 'N', true ) === 'Y';
|
505 |
+
$bEnabledBadge = $oDP->post( 'BadgeOption', 'N', true ) === 'Y';
|
506 |
+
|
507 |
+
/** @var ICWP_WPSF_FeatureHandler_Plugin $oModule */
|
508 |
+
$oModule = $this->getPluginCon()->getModule( 'plugin' );
|
509 |
+
$oModule->setIsDisplayPluginBadge( $bEnabledBadge )
|
510 |
+
->setPluginTrackingPermission( $bEnabledTracking );
|
511 |
+
|
512 |
+
$sMessage = _wpsf__( 'Preferences have been saved.' );
|
513 |
+
|
514 |
+
$oResponse = new \FernleafSystems\Utilities\Response();
|
515 |
+
return $oResponse->setSuccessful( true )
|
516 |
+
->setMessageText( $sMessage );
|
517 |
+
}
|
518 |
+
|
519 |
+
/**
|
520 |
+
* @return \FernleafSystems\Utilities\Response
|
521 |
+
*/
|
522 |
+
private function wizardCommentsFilter() {
|
523 |
+
|
524 |
+
$bEnabled = $this->loadDP()->post( 'CommentsFilterOption' ) === 'Y';
|
525 |
+
|
526 |
+
/** @var ICWP_WPSF_FeatureHandler_CommentsFilter $oModule */
|
527 |
+
$oModule = $this->getPluginCon()->getModule( 'comments_filter' );
|
528 |
+
if ( $bEnabled ) { // we don't disable the whole module
|
529 |
+
$oModule->setIsMainFeatureEnabled( true );
|
530 |
+
}
|
531 |
+
$oModule->setEnabledGasp( $bEnabled )
|
532 |
+
->savePluginOptions();
|
533 |
+
|
534 |
+
$bSuccess = $oModule->getIsMainFeatureEnabled() === $bEnabled;
|
535 |
+
if ( $bSuccess ) {
|
536 |
+
$sMessage = sprintf( '%s has been %s.', _wpsf__( 'Comment SPAM Protection' ),
|
537 |
+
$oModule->getIsMainFeatureEnabled() ? _wpsf__( 'Enabled' ) : _wpsf__( 'Disabled' )
|
538 |
+
);
|
539 |
+
}
|
540 |
+
else {
|
541 |
+
$sMessage = sprintf( _wpsf__( '%s setting could not be changed at this time.' ), _wpsf__( 'Comment SPAM Protection' ) );
|
542 |
+
}
|
543 |
+
|
544 |
+
$oResponse = new \FernleafSystems\Utilities\Response();
|
545 |
+
return $oResponse->setSuccessful( $bSuccess )
|
546 |
+
->setMessageText( $sMessage );
|
547 |
+
}
|
548 |
+
}
|
templates/html/plugin_badge.html
CHANGED
@@ -37,7 +37,7 @@
|
|
37 |
font-size: 12px;
|
38 |
line-height: 17px;
|
39 |
padding-left: 43px;
|
40 |
-
|
41 |
-webkit-transition: opacity 1s; /* Safari */
|
42 |
transition: opacity 1s;
|
43 |
}
|
37 |
font-size: 12px;
|
38 |
line-height: 17px;
|
39 |
padding-left: 43px;
|
40 |
+
letter-spacing: 0;
|
41 |
-webkit-transition: opacity 1s; /* Safari */
|
42 |
transition: opacity 1s;
|
43 |
}
|
templates/php/feature-default.php
CHANGED
@@ -1,8 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
1 |
<div class="row icwpTopLevelRow">
|
2 |
<div class="icwpTopLevelSpan <?php echo $flags[ 'show_ads' ] ? 'span11' : 'span11'; ?>" id="icwpOptionsTopPill">
|
3 |
|
4 |
<ul class="nav nav-pills">
|
5 |
-
<li>
|
6 |
<a href="#icwpPillOptions" data-toggle="pill">
|
7 |
<span class="dashicons dashicons-admin-settings"> </span>
|
8 |
<div class="title"><?php echo $strings[ 'options_title' ]; ?></div>
|
@@ -27,10 +32,21 @@
|
|
27 |
</a>
|
28 |
</li>
|
29 |
<?php endif; ?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
</ul>
|
31 |
<div class="tab-content">
|
32 |
-
<div class="tab-pane"
|
33 |
-
id="icwpPillOptions">
|
34 |
<?php echo $flags[ 'show_standard_options' ] ? $options_form : ''; ?>
|
35 |
<?php echo $flags[ 'show_alt_content' ] ? $content[ 'alt' ] : ''; ?>
|
36 |
</div>
|
@@ -44,7 +60,7 @@
|
|
44 |
<div class="content-help"><?php echo $content[ 'help' ]; ?></div>
|
45 |
</div>
|
46 |
<?php endif; ?>
|
47 |
-
<div class="tab-pane
|
48 |
<h3 style="text-align: center">↑ <?php echo 'Select Desired Section Above'; ?> ↑</h3>
|
49 |
</div>
|
50 |
</div>
|
1 |
+
<style>
|
2 |
+
#icwpOptionsTopPill > .nav-pills li#icwpWizardPill a {
|
3 |
+
background-image: url("<?php echo $hrefs['img_wizard_wand'];?>");
|
4 |
+
}
|
5 |
+
</style>
|
6 |
<div class="row icwpTopLevelRow">
|
7 |
<div class="icwpTopLevelSpan <?php echo $flags[ 'show_ads' ] ? 'span11' : 'span11'; ?>" id="icwpOptionsTopPill">
|
8 |
|
9 |
<ul class="nav nav-pills">
|
10 |
+
<li class="active">
|
11 |
<a href="#icwpPillOptions" data-toggle="pill">
|
12 |
<span class="dashicons dashicons-admin-settings"> </span>
|
13 |
<div class="title"><?php echo $strings[ 'options_title' ]; ?></div>
|
32 |
</a>
|
33 |
</li>
|
34 |
<?php endif; ?>
|
35 |
+
<?php if ( $flags[ 'has_wizard' ] ) : ?>
|
36 |
+
<?php if ( $flags[ 'can_wizard' ] ) : ?>
|
37 |
+
<li id="icwpWizardPill">
|
38 |
+
<a href="<?php echo $hrefs[ 'wizard_link' ]; ?>"
|
39 |
+
title="Launch Guided Walk-Through Wizards" target="_blank"> </a>
|
40 |
+
</li>
|
41 |
+
<?php else: ?>
|
42 |
+
<li id="icwpWizardPill">
|
43 |
+
<a href="#" title="Wizards are not available as your PHP version is too old."> </a>
|
44 |
+
</li>
|
45 |
+
<?php endif; ?>
|
46 |
+
<?php endif; ?>
|
47 |
</ul>
|
48 |
<div class="tab-content">
|
49 |
+
<div class="tab-pane active" id="icwpPillOptions">
|
|
|
50 |
<?php echo $flags[ 'show_standard_options' ] ? $options_form : ''; ?>
|
51 |
<?php echo $flags[ 'show_alt_content' ] ? $content[ 'alt' ] : ''; ?>
|
52 |
</div>
|
60 |
<div class="content-help"><?php echo $content[ 'help' ]; ?></div>
|
61 |
</div>
|
62 |
<?php endif; ?>
|
63 |
+
<div class="tab-pane" id="icwpPillSelect">
|
64 |
<h3 style="text-align: center">↑ <?php echo 'Select Desired Section Above'; ?> ↑</h3>
|
65 |
</div>
|
66 |
</div>
|
templates/php/index_footer.php
CHANGED
@@ -1,2 +1,14 @@
|
|
1 |
</div><!-- / bootstrap-wpadmin -->
|
2 |
-
</div><!-- / wrap -->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
</div><!-- / bootstrap-wpadmin -->
|
2 |
+
</div><!-- / wrap -->
|
3 |
+
|
4 |
+
<script type="text/javascript">
|
5 |
+
jQuery( 'a.feature-icon' ).popover( {
|
6 |
+
placement: 'left',
|
7 |
+
trigger: 'hover',
|
8 |
+
html: true
|
9 |
+
} );
|
10 |
+
jQuery( 'li#icwpWizardPill a' ).tooltip( {
|
11 |
+
placement: 'top',
|
12 |
+
trigger: 'hover focus'
|
13 |
+
} );
|
14 |
+
</script>
|
templates/php/index_header.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
$sBaseDirName = dirname( __FILE__ ).DIRECTORY_SEPARATOR;
|
3 |
-
include_once( $sBaseDirName.'widgets
|
4 |
<div class="wrap">
|
5 |
<div class="bootstrap-wpadmin <?php echo isset( $sFeatureSlug ) ? $sFeatureSlug : ''; ?> icwp-options-page">
|
6 |
|
@@ -8,17 +8,15 @@ include_once( $sBaseDirName.'widgets'.DIRECTORY_SEPARATOR.'icwp_widgets.php' );
|
|
8 |
<div class="span11">
|
9 |
<div class="page-header">
|
10 |
<h2>
|
11 |
-
<
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
data-featherlight="#<?php echo $help_video[ 'display_id' ]; ?>">Help Video</a>
|
21 |
-
<?php endif; ?>
|
22 |
</h2>
|
23 |
</div>
|
24 |
<?php
|
@@ -29,7 +27,7 @@ include_once( $sBaseDirName.'widgets'.DIRECTORY_SEPARATOR.'icwp_widgets.php' );
|
|
29 |
</div>
|
30 |
<div class="span1">
|
31 |
<?php if ( isset( $flags[ 'show_summary' ] ) && $flags[ 'show_summary' ] ) : ?>
|
32 |
-
<?php include_once( $sBaseDirName.'snippets
|
33 |
<?php endif; ?>
|
34 |
</div>
|
35 |
</div>
|
1 |
<?php
|
2 |
$sBaseDirName = dirname( __FILE__ ).DIRECTORY_SEPARATOR;
|
3 |
+
include_once( $sBaseDirName.'widgets/icwp_widgets.php' ); ?>
|
4 |
<div class="wrap">
|
5 |
<div class="bootstrap-wpadmin <?php echo isset( $sFeatureSlug ) ? $sFeatureSlug : ''; ?> icwp-options-page">
|
6 |
|
8 |
<div class="span11">
|
9 |
<div class="page-header">
|
10 |
<h2>
|
11 |
+
<a id="pluginlogo_32" class="header-icon32" href="http://icwp.io/2k" target="_blank"></a>
|
12 |
+
<span class="feature-headline"><?php echo $sPageTitle; ?></span>
|
13 |
+
<?php if ( $help_video[ 'show' ] ) : ?>
|
14 |
+
<a href="#" class="btn btn-success"
|
15 |
+
data-featherlight="#<?php echo $help_video[ 'display_id' ]; ?>">Help Video</a>
|
16 |
+
<?php endif; ?>
|
17 |
+
<?php if ( !empty( $sTagline ) ) : ?>
|
18 |
+
<small class="feature-tagline">- <?php echo $sTagline; ?></small>
|
19 |
+
<?php endif; ?>
|
|
|
|
|
20 |
</h2>
|
21 |
</div>
|
22 |
<?php
|
27 |
</div>
|
28 |
<div class="span1">
|
29 |
<?php if ( isset( $flags[ 'show_summary' ] ) && $flags[ 'show_summary' ] ) : ?>
|
30 |
+
<?php include_once( $sBaseDirName.'snippets/state_summary.php' ); ?>
|
31 |
<?php endif; ?>
|
32 |
</div>
|
33 |
</div>
|
templates/php/snippets/module-help-plugin.php
CHANGED
@@ -15,7 +15,7 @@
|
|
15 |
<p>Basically you select the IP address from the list that represents your own, personal
|
16 |
public IP address.
|
17 |
</p>
|
18 |
-
<p>Don't know your IP address? Go
|
19 |
(<a href="http://icwp.io/an" target="_blank">We've done it for you</a> ;)
|
20 |
</p>
|
21 |
<p>With this result, you should be able to select the correct item from the list. The higher up the
|
15 |
<p>Basically you select the IP address from the list that represents your own, personal
|
16 |
public IP address.
|
17 |
</p>
|
18 |
+
<p>Don't know your IP address? Go here:
|
19 |
(<a href="http://icwp.io/an" target="_blank">We've done it for you</a> ;)
|
20 |
</p>
|
21 |
<p>With this result, you should be able to select the correct item from the list. The higher up the
|
templates/php/snippets/module-help-template.php
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
if ( isset( $slug ) ) {
|
3 |
+
include_once( dirname( __FILE__ ).sprintf( '/module-help-%s.php', $slug ) );
|
4 |
+
}
|
templates/php/snippets/module-plugin-actions.php
CHANGED
@@ -12,7 +12,8 @@
|
|
12 |
because you're running your website on old, outdated, non-maintained software. And if you're PHP
|
13 |
is this far out-of-date, you gotta wonder what else on your webhost needs some important upgrades.
|
14 |
</p>
|
15 |
-
<p>Website security
|
|
|
16 |
<p>Note: As Shield Security is further developed, more and more features will require higher versions of PHP.</p>
|
17 |
</div>
|
18 |
<?php endif; ?>
|
12 |
because you're running your website on old, outdated, non-maintained software. And if you're PHP
|
13 |
is this far out-of-date, you gotta wonder what else on your webhost needs some important upgrades.
|
14 |
</p>
|
15 |
+
<p>Website security covers many areas, and running your webhost/server on up-to-date software is
|
16 |
+
a critical one of these areas.</p>
|
17 |
<p>Note: As Shield Security is further developed, more and more features will require higher versions of PHP.</p>
|
18 |
</div>
|
19 |
<?php endif; ?>
|
templates/php/snippets/options_form.php
CHANGED
@@ -4,8 +4,10 @@
|
|
4 |
|
5 |
<ul class="nav nav-tabs">
|
6 |
<?php foreach ( $aAllOptions as $sOptionSection ) : ?>
|
7 |
-
<li class="<?php echo $sOptionSection['primary'] ? 'active' : '' ?>">
|
8 |
-
<a href="#<?php echo $sOptionSection['slug'] ?>" data-toggle="tab"
|
|
|
|
|
9 |
</li>
|
10 |
<?php endforeach; ?>
|
11 |
</ul>
|
@@ -13,174 +15,195 @@
|
|
13 |
<div class="tab-content">
|
14 |
<?php foreach ( $aAllOptions as $sOptionSection ) : ?>
|
15 |
|
16 |
-
<div class="tab-pane fade <?php echo $sOptionSection['primary'] ? 'active in primary_section' : 'non_primary_section'; ?>"
|
17 |
-
id="<?php echo $sOptionSection['slug'] ?>">
|
18 |
-
<div class="row option_section_row <?php echo $sOptionSection['primary'] ? 'primary_section' : 'non_primary_section'; ?>"
|
19 |
-
id="row-<?php echo $sOptionSection['slug']; ?>">
|
20 |
-
<div class="
|
21 |
-
<fieldset>
|
22 |
<legend>
|
23 |
-
<?php echo $sOptionSection['title']; ?>
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
<a href="<?php echo $sOptionSection['help_video_url']; ?>"
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
<span class="dashicons dashicons-controls-play"></span> Help Video
|
33 |
</a>
|
34 |
</div>
|
35 |
-
|
36 |
</legend>
|
37 |
|
38 |
-
|
39 |
-
|
40 |
-
<div class="
|
41 |
-
<?php foreach( $sOptionSection['summary'] as $sItem ) : ?>
|
42 |
<p class="noselect"><?php echo $sItem; ?></p>
|
43 |
<?php endforeach; ?>
|
44 |
</div>
|
45 |
</div>
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
<a href="<?php echo $hrefs['go_pro']; ?>" target="_blank">
|
68 |
-
A Pro Feature</a>
|
69 |
-
</div>
|
70 |
</div>
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
|
|
|
|
|
|
82 |
<?php endif; ?>
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
<
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
<?php echo $
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
<?php
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
181 |
</div>
|
182 |
-
|
183 |
-
</fieldset>
|
184 |
</div>
|
185 |
</div>
|
186 |
</div>
|
@@ -189,9 +212,28 @@
|
|
189 |
|
190 |
<div class="form-actions">
|
191 |
<input type="hidden" name="<?php echo $var_prefix; ?>feature_slug" value="<?php echo $feature_slug; ?>" />
|
192 |
-
<input type="hidden" name="<?php echo $var_prefix; ?>all_options_input"
|
|
|
193 |
<input type="hidden" name="<?php echo $var_prefix; ?>plugin_form_submit" value="Y" />
|
194 |
-
<button type="submit" class="btn btn-success btn-large icwp-form-button"
|
|
|
195 |
</div>
|
196 |
</form>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
197 |
</div>
|
4 |
|
5 |
<ul class="nav nav-tabs">
|
6 |
<?php foreach ( $aAllOptions as $sOptionSection ) : ?>
|
7 |
+
<li class="<?php echo $sOptionSection[ 'primary' ] ? 'active' : '' ?>">
|
8 |
+
<a href="#<?php echo $sOptionSection[ 'slug' ] ?>" data-toggle="tab">
|
9 |
+
<?php echo $sOptionSection[ 'title_short' ]; ?>
|
10 |
+
</a>
|
11 |
</li>
|
12 |
<?php endforeach; ?>
|
13 |
</ul>
|
15 |
<div class="tab-content">
|
16 |
<?php foreach ( $aAllOptions as $sOptionSection ) : ?>
|
17 |
|
18 |
+
<div class="tab-pane fade <?php echo $sOptionSection[ 'primary' ] ? 'active in primary_section' : 'non_primary_section'; ?>"
|
19 |
+
id="<?php echo $sOptionSection[ 'slug' ] ?>">
|
20 |
+
<div class="row-fluid option_section_row <?php echo $sOptionSection[ 'primary' ] ? 'primary_section' : 'non_primary_section'; ?>"
|
21 |
+
id="row-<?php echo $sOptionSection[ 'slug' ]; ?>">
|
22 |
+
<div class="span12 options-body">
|
|
|
23 |
<legend>
|
24 |
+
<?php echo $sOptionSection[ 'title' ]; ?>
|
25 |
+
<?php if ( !empty( $sOptionSection[ 'help_video_url' ] ) ) : ?>
|
26 |
+
<div style="float:right;">
|
27 |
+
|
28 |
+
<a href="<?php echo $sOptionSection[ 'help_video_url' ]; ?>"
|
29 |
+
class="btn"
|
30 |
+
data-featherlight-iframe-height="454"
|
31 |
+
data-featherlight-iframe-width="772"
|
32 |
+
data-featherlight="iframe">
|
33 |
<span class="dashicons dashicons-controls-play"></span> Help Video
|
34 |
</a>
|
35 |
</div>
|
36 |
+
<?php endif; ?>
|
37 |
</legend>
|
38 |
|
39 |
+
<?php if ( !empty( $sOptionSection[ 'summary' ] ) ) : ?>
|
40 |
+
<div class="row-fluid row_section_summary">
|
41 |
+
<div class="span12">
|
42 |
+
<?php foreach ( $sOptionSection[ 'summary' ] as $sItem ) : ?>
|
43 |
<p class="noselect"><?php echo $sItem; ?></p>
|
44 |
<?php endforeach; ?>
|
45 |
</div>
|
46 |
</div>
|
47 |
+
<?php endif; ?>
|
48 |
+
|
49 |
+
<?php foreach ( $sOptionSection[ 'options' ] as $nKeyRow => $aOption ) :
|
50 |
+
$sOptionKey = $aOption[ 'key' ];
|
51 |
+
$sFullOptionKey = $var_prefix.$sOptionKey;
|
52 |
+
$mOptValue = $aOption[ 'value' ];
|
53 |
+
$sOptionType = $aOption[ 'type' ];
|
54 |
+
$bEnabled = $aOption[ 'enabled' ];
|
55 |
+
$sDisabledText = $bEnabled ? '' : 'disabled="Disabled"';
|
56 |
+
?>
|
57 |
+
<div class="row-fluid option_row row_number_<?php echo $nKeyRow; ?>">
|
58 |
+
<div class="item_group span12
|
59 |
+
<?php echo $bEnabled ? 'enabled' : 'disabled overlay_container' ?>
|
60 |
+
<?php echo ( $mOptValue == 'Y' || $mOptValue != $aOption[ 'default' ] ) ? 'selected_item_group' : ''; ?>"
|
61 |
+
id="span_<?php echo $sFullOptionKey; ?>">
|
62 |
+
|
63 |
+
<?php if ( !$bEnabled ) : ?>
|
64 |
+
<div class="option_overlay">
|
65 |
+
<div class="overlay_message">
|
66 |
+
<a href="<?php echo $hrefs[ 'go_pro' ]; ?>" target="_blank">
|
67 |
+
This is a premium feature</a>
|
|
|
|
|
|
|
68 |
</div>
|
69 |
+
</div>
|
70 |
+
<?php endif; ?>
|
71 |
+
|
72 |
+
<div class="control-group">
|
73 |
+
<label class="control-label" for="<?php echo $sFullOptionKey; ?>">
|
74 |
+
<span class="optname"><?php echo $aOption[ 'name' ]; ?></span>
|
75 |
+
<?php if ( !empty( $aOption[ 'link_info' ] ) ) : ?>
|
76 |
+
<span class="optlinks">
|
77 |
+
[
|
78 |
+
<a href="<?php echo $aOption[ 'link_info' ]; ?>"
|
79 |
+
target="_blank"><?php echo $strings[ 'more_info' ]; ?></a>
|
80 |
+
<?php if ( !empty( $aOption[ 'link_blog' ] ) ) : ?>
|
81 |
+
| <a href="<?php echo $aOption[ 'link_blog' ]; ?>"
|
82 |
+
target="_blank"><?php echo $strings[ 'blog' ]; ?></a>
|
83 |
<?php endif; ?>
|
84 |
+
]
|
85 |
+
</span>
|
86 |
+
<?php endif; ?>
|
87 |
+
</label>
|
88 |
+
<div class="controls">
|
89 |
+
<div class="option_section <?php echo ( $mOptValue == 'Y' ) ? 'selected_item' : ''; ?>"
|
90 |
+
id="option_section_<?php echo $sFullOptionKey; ?>">
|
91 |
+
|
92 |
+
<label class="for<?php echo $sOptionType; ?>">
|
93 |
+
<?php if ( $sOptionType == 'checkbox' ) : ?>
|
94 |
+
<span class="switch">
|
95 |
+
<input type="checkbox"
|
96 |
+
name="<?php echo $sFullOptionKey; ?>"
|
97 |
+
id="<?php echo $sFullOptionKey; ?>"
|
98 |
+
value="Y" <?php echo ( $mOptValue == 'Y' ) ? 'checked="checked"' : ''; ?>
|
99 |
+
<?php echo $sDisabledText; ?> />
|
100 |
+
<span class="slider round"></span>
|
101 |
+
</span>
|
102 |
+
<span class="summary"><?php echo $aOption[ 'summary' ]; ?></span>
|
103 |
+
|
104 |
+
<?php elseif ( $sOptionType == 'text' ) : ?>
|
105 |
+
|
106 |
+
<p><?php echo $aOption[ 'summary' ]; ?></p>
|
107 |
+
<textarea name="<?php echo $sFullOptionKey; ?>"
|
108 |
+
id="<?php echo $sFullOptionKey; ?>"
|
109 |
+
placeholder="<?php echo $mOptValue; ?>"
|
110 |
+
rows="<?php echo $aOption[ 'rows' ]; ?>"
|
111 |
+
class="span5" <?php echo $sDisabledText; ?>><?php echo $mOptValue; ?></textarea>
|
112 |
+
|
113 |
+
<?php elseif ( $sOptionType == 'noneditable_text' ) : ?>
|
114 |
+
|
115 |
+
<p><?php echo $aOption[ 'summary' ]; ?></p>
|
116 |
+
<input type="text" readonly
|
117 |
+
value="<?php echo $mOptValue; ?>" class="span5" />
|
118 |
+
|
119 |
+
<?php elseif ( $sOptionType == 'password' ) : ?>
|
120 |
+
|
121 |
+
<p><?php echo $aOption[ 'summary' ]; ?></p>
|
122 |
+
<input type="password" name="<?php echo $sFullOptionKey; ?>"
|
123 |
+
id="<?php echo $sFullOptionKey; ?>"
|
124 |
+
value="<?php echo $mOptValue; ?>"
|
125 |
+
placeholder="<?php echo $mOptValue; ?>"
|
126 |
+
class="span5" <?php echo $sDisabledText; ?> />
|
127 |
+
|
128 |
+
<?php elseif ( $sOptionType == 'email' ) : ?>
|
129 |
+
|
130 |
+
<p><?php echo $aOption[ 'summary' ]; ?></p>
|
131 |
+
<input type="email" name="<?php echo $sFullOptionKey; ?>"
|
132 |
+
id="<?php echo $sFullOptionKey; ?>"
|
133 |
+
value="<?php echo $mOptValue; ?>"
|
134 |
+
placeholder="<?php echo $mOptValue; ?>"
|
135 |
+
class="span5" <?php echo $sDisabledText; ?> />
|
136 |
+
|
137 |
+
<?php elseif ( $sOptionType == 'select' ) : ?>
|
138 |
+
|
139 |
+
<p><?php echo $aOption[ 'summary' ]; ?></p>
|
140 |
+
<select name="<?php echo $sFullOptionKey; ?>"
|
141 |
+
id="<?php echo $sFullOptionKey; ?>"
|
142 |
+
<?php echo $sDisabledText; ?> >
|
143 |
+
<?php foreach ( $aOption[ 'value_options' ] as $sOptionValue => $sOptionValueName ) : ?>
|
144 |
+
<option value="<?php echo $sOptionValue; ?>"
|
145 |
+
id="<?php echo $sFullOptionKey; ?>_<?php echo $sOptionValue; ?>"
|
146 |
+
<?php echo ( $sOptionValue == $mOptValue ) ? 'selected="selected"' : ''; ?>
|
147 |
+
><?php echo $sOptionValueName; ?></option>
|
148 |
+
<?php endforeach; ?>
|
149 |
+
</select>
|
150 |
+
|
151 |
+
<?php elseif ( $sOptionType == 'multiple_select' ) : ?>
|
152 |
+
|
153 |
+
<p><?php echo $aOption[ 'summary' ]; ?></p>
|
154 |
+
<select name="<?php echo $sFullOptionKey; ?>[]"
|
155 |
+
id="<?php echo $sFullOptionKey; ?>"
|
156 |
+
multiple="multiple" multiple
|
157 |
+
size="<?php echo count( $aOption[ 'value_options' ] ); ?>"
|
158 |
+
<?php echo $sDisabledText; ?> >
|
159 |
+
<?php foreach ( $aOption[ 'value_options' ] as $sOptionValue => $sOptionValueName ) : ?>
|
160 |
+
<option value="<?php echo $sOptionValue; ?>"
|
161 |
+
id="<?php echo $sFullOptionKey; ?>_<?php echo $sOptionValue; ?>"
|
162 |
+
<?php echo in_array( $sOptionValue, $mOptValue ) ? 'selected="selected"' : ''; ?>
|
163 |
+
><?php echo $sOptionValueName; ?></option>
|
164 |
+
<?php endforeach; ?>
|
165 |
+
</select>
|
166 |
+
|
167 |
+
<?php elseif ( $sOptionType == 'array' ) : ?>
|
168 |
+
|
169 |
+
<p><?php echo $aOption[ 'summary' ]; ?></p>
|
170 |
+
<textarea name="<?php echo $sFullOptionKey; ?>"
|
171 |
+
id="<?php echo $sFullOptionKey; ?>"
|
172 |
+
placeholder="<?php echo $mOptValue; ?>"
|
173 |
+
rows="<?php echo $aOption[ 'rows' ]; ?>"
|
174 |
+
class="span5" <?php echo $sDisabledText; ?>><?php echo $mOptValue; ?></textarea>
|
175 |
+
|
176 |
+
<?php elseif ( $sOptionType == 'comma_separated_lists' ) : ?>
|
177 |
+
|
178 |
+
<p><?php echo $aOption[ 'summary' ]; ?></p>
|
179 |
+
<textarea name="<?php echo $sFullOptionKey; ?>"
|
180 |
+
id="<?php echo $sFullOptionKey; ?>"
|
181 |
+
placeholder="<?php echo $mOptValue; ?>"
|
182 |
+
rows="<?php echo $aOption[ 'rows' ]; ?>"
|
183 |
+
class="span5" <?php echo $sDisabledText; ?> ><?php echo $mOptValue; ?></textarea>
|
184 |
+
|
185 |
+
<?php elseif ( $sOptionType == 'integer' ) : ?>
|
186 |
+
|
187 |
+
<p><?php echo $aOption[ 'summary' ]; ?></p>
|
188 |
+
<input type="text" name="<?php echo $sFullOptionKey; ?>"
|
189 |
+
id="<?php echo $sFullOptionKey; ?>"
|
190 |
+
value="<?php echo $mOptValue; ?>"
|
191 |
+
placeholder="<?php echo $mOptValue; ?>"
|
192 |
+
class="span5" <?php echo $sDisabledText; ?> />
|
193 |
+
|
194 |
+
<?php else : ?>
|
195 |
+
ERROR: Should never reach this point.
|
196 |
+
<?php endif; ?>
|
197 |
+
|
198 |
+
</label>
|
199 |
+
<p class="help-block"><?php echo $aOption[ 'description' ]; ?></p>
|
200 |
+
<div style="clear:both"></div>
|
201 |
+
</div>
|
202 |
+
</div><!-- controls -->
|
203 |
+
</div><!-- control-group -->
|
204 |
+
</div>
|
205 |
</div>
|
206 |
+
<?php endforeach; ?>
|
|
|
207 |
</div>
|
208 |
</div>
|
209 |
</div>
|
212 |
|
213 |
<div class="form-actions">
|
214 |
<input type="hidden" name="<?php echo $var_prefix; ?>feature_slug" value="<?php echo $feature_slug; ?>" />
|
215 |
+
<input type="hidden" name="<?php echo $var_prefix; ?>all_options_input"
|
216 |
+
value="<?php echo $all_options_input; ?>" />
|
217 |
<input type="hidden" name="<?php echo $var_prefix; ?>plugin_form_submit" value="Y" />
|
218 |
+
<button type="submit" class="btn btn-success btn-large icwp-form-button"
|
219 |
+
name="submit"><?php _wpsf_e( 'Save All Settings' ); ?></button>
|
220 |
</div>
|
221 |
</form>
|
222 |
+
<div class="pull-right well">
|
223 |
+
<h5 style="margin-bottom: 10px;">Options Legend</h5>
|
224 |
+
<label class="forcheckbox">
|
225 |
+
<span class="switch">
|
226 |
+
<input type="checkbox" name="legend" id="legend" value="Y" checked="checked" disabled="disabled">
|
227 |
+
<span class="slider round"></span>
|
228 |
+
</span>
|
229 |
+
<span class="summary">Option is turned on / enabled</span>
|
230 |
+
</label>
|
231 |
+
<label class="forcheckbox">
|
232 |
+
<span class="switch">
|
233 |
+
<input type="checkbox" name="legend" id="legend" value="Y" disabled="disabled">
|
234 |
+
<span class="slider round"></span>
|
235 |
+
</span>
|
236 |
+
<span class="summary">Option is turned off / disabled</span>
|
237 |
+
</label>
|
238 |
+
</div>
|
239 |
</div>
|
templates/php/snippets/plugin_badge.php
CHANGED
@@ -37,7 +37,7 @@
|
|
37 |
font-size: 12px;
|
38 |
line-height: 17px;
|
39 |
padding-left: 43px;
|
40 |
-
|
41 |
-webkit-transition: opacity 1s; /* Safari */
|
42 |
transition: opacity 1s;
|
43 |
}
|
@@ -80,7 +80,9 @@
|
|
80 |
</style>
|
81 |
<div id="icwpWpsfSiteBadge">
|
82 |
<a id="icwpWpsfCloseButton">x</a>
|
83 |
-
<a href="http://icwp.io/wpsecurityfirewall" target="_blank"
|
|
|
|
|
84 |
<img src="%s" alt="%s Logo" />
|
85 |
<div class="badge-text">%s</div>
|
86 |
</a>
|
37 |
font-size: 12px;
|
38 |
line-height: 17px;
|
39 |
padding-left: 43px;
|
40 |
+
letter-spacing: 0;
|
41 |
-webkit-transition: opacity 1s; /* Safari */
|
42 |
transition: opacity 1s;
|
43 |
}
|
80 |
</style>
|
81 |
<div id="icwpWpsfSiteBadge">
|
82 |
<a id="icwpWpsfCloseButton">x</a>
|
83 |
+
<a href="http://icwp.io/wpsecurityfirewall" target="_blank"
|
84 |
+
title="This site is protected by the Shield Security plugin."
|
85 |
+
%s>
|
86 |
<img src="%s" alt="%s Logo" />
|
87 |
<div class="badge-text">%s</div>
|
88 |
</a>
|
templates/php/snippets/state_summary.php
CHANGED
@@ -3,10 +3,7 @@ if ( empty( $aSummaryData ) ) {
|
|
3 |
return;
|
4 |
} ?>
|
5 |
|
6 |
-
<div class="feature-summary-blocks
|
7 |
-
<?php echo $aSummary[ 'active' ] ? 'active-feature' : ''; ?>
|
8 |
-
state-<?php echo $aSummary[ 'enabled' ] ? 'on' : 'off'; ?>"
|
9 |
-
>
|
10 |
<?php foreach ( $aSummaryData as $nKey => $aSummary ) : ?>
|
11 |
<div class="summary-state state-<?php echo $aSummary[ 'enabled' ] ? 'on' : 'off'; ?> <?php echo $aSummary[ 'active' ] ? 'active-feature' : ''; ?> "
|
12 |
id="feature-<?php echo $aSummary[ 'slug' ]; ?>">
|
@@ -18,12 +15,4 @@ if ( empty( $aSummaryData ) ) {
|
|
18 |
</div>
|
19 |
<?php endforeach; ?>
|
20 |
<div style="clear: both"></div>
|
21 |
-
</div>
|
22 |
-
<script type="text/javascript">
|
23 |
-
jQuery( 'a.feature-icon' ).popover( {
|
24 |
-
placement: 'left',
|
25 |
-
trigger: 'hover',
|
26 |
-
html: true
|
27 |
-
} );
|
28 |
-
// jQuery( '#feature-plugin a.feature-icon' ).popover( 'show' );
|
29 |
-
</script>
|
3 |
return;
|
4 |
} ?>
|
5 |
|
6 |
+
<div class="feature-summary-blocks">
|
|
|
|
|
|
|
7 |
<?php foreach ( $aSummaryData as $nKey => $aSummary ) : ?>
|
8 |
<div class="summary-state state-<?php echo $aSummary[ 'enabled' ] ? 'on' : 'off'; ?> <?php echo $aSummary[ 'active' ] ? 'active-feature' : ''; ?> "
|
9 |
id="feature-<?php echo $aSummary[ 'slug' ]; ?>">
|
15 |
</div>
|
16 |
<?php endforeach; ?>
|
17 |
<div style="clear: both"></div>
|
18 |
+
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
templates/twig/pages/base.twig
CHANGED
@@ -25,27 +25,36 @@
|
|
25 |
</head>
|
26 |
{% block body %}
|
27 |
<body>
|
28 |
-
|
29 |
-
{% block body_content_header %}
|
30 |
-
<div class="row">
|
31 |
-
<div class="col-md-4 col-md-offset-4">
|
32 |
-
<img id="ShieldLogo" class="img-responsive" src="{{ hrefs.shield_logo }}" />
|
33 |
-
</div>
|
34 |
-
</div>
|
35 |
-
{% endblock %}
|
36 |
-
{% block body_content_main %}
|
37 |
-
<div class="row">
|
38 |
-
<div class="col-md-4 col-md-offset-4"></div>
|
39 |
-
</div>
|
40 |
{% endblock %}
|
41 |
-
|
42 |
-
|
43 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
</div>
|
45 |
{% endblock %}
|
|
|
46 |
{% block body_footer %}
|
47 |
{% endblock %}
|
48 |
-
|
49 |
-
|
|
|
|
|
50 |
{% endblock %}
|
51 |
</html>
|
25 |
</head>
|
26 |
{% block body %}
|
27 |
<body>
|
28 |
+
{% block body_header %}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
{% endblock %}
|
30 |
+
|
31 |
+
{% block body_content %}
|
32 |
+
<div class="container-fluid">
|
33 |
+
{% block body_content_header %}
|
34 |
+
<div class="row">
|
35 |
+
<div class="col-lg-3 col-lg-offset-4 col-md-4 col-md-offset-4 col-sm-4 col-sm-offset-4">
|
36 |
+
<img id="ShieldLogo" class="img-responsive" src="{{ hrefs.plugin_banner }}" />
|
37 |
+
</div>
|
38 |
+
</div>
|
39 |
+
{% endblock %}
|
40 |
+
{% block body_content_main %}
|
41 |
+
<div class="row">
|
42 |
+
<div class="col-md-4 col-md-offset-4"></div>
|
43 |
+
</div>
|
44 |
+
{% endblock %}
|
45 |
+
{% block body_content_footer %}
|
46 |
+
<div class="row">
|
47 |
+
<div class="col-md-4 col-md-offset-4"></div>
|
48 |
+
</div>
|
49 |
+
{% endblock %}
|
50 |
</div>
|
51 |
{% endblock %}
|
52 |
+
|
53 |
{% block body_footer %}
|
54 |
{% endblock %}
|
55 |
+
|
56 |
+
{% block body_footer_scripts %}
|
57 |
+
{% endblock %}
|
58 |
+
</body>
|
59 |
{% endblock %}
|
60 |
</html>
|
templates/twig/wizard/base_finish.twig
DELETED
@@ -1,7 +0,0 @@
|
|
1 |
-
{% extends 'wizard/base.twig' %}
|
2 |
-
|
3 |
-
{% block slide_header_next %}{% endblock %}
|
4 |
-
{% block slide_footer %}
|
5 |
-
<hr />
|
6 |
-
<a href="{{ hrefs.dashboard }}" class="btn btn-default">⇐ Return To The Shield WordPress Dashboard</a>
|
7 |
-
{% endblock %}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
templates/twig/wizard/base_start.twig
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
{% extends 'wizard/base.twig' %}
|
2 |
-
|
3 |
-
{% block slide_header_previous %}{% endblock %}
|
|
|
|
|
|
templates/twig/wizard/pages/base.twig
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% extends 'pages/base.twig' %}
|
2 |
+
|
3 |
+
{% block body_footer %}
|
4 |
+
{% if not flags.is_premium %}
|
5 |
+
<div id="FooterWizardBanner" class="container-fluid">
|
6 |
+
<div class="row"><div id="WizardTop" class="span12"></div></div>
|
7 |
+
|
8 |
+
<div id="WizardBanner" class="row">
|
9 |
+
<div class="col-lg-4 col-lg-offset-4 col-md-5 col-md-offset-3 col-sm-7 col-sm-offset-1 col-xs-9">
|
10 |
+
<p>Support future development and get extra Shield features:
|
11 |
+
<br />Vulnerability Scanner; Options Import; Email Support+more.</p>
|
12 |
+
</div>
|
13 |
+
<div class="col-lg-1 col-md-2 col-sm-2 col-xs-1">
|
14 |
+
<a href="{{ hrefs.goprofooter }}" target="_blank" class="btn btn-default">Go Pro Today →</a>
|
15 |
+
</div>
|
16 |
+
</div>
|
17 |
+
</div>
|
18 |
+
{% endif %}
|
19 |
+
{% endblock %}
|
templates/twig/wizard/pages/landing.twig
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% extends 'wizard/pages/base.twig' %}
|
2 |
+
|
3 |
+
{% block head_stylesheets %}
|
4 |
+
{{ parent() }}
|
5 |
+
<link rel="stylesheet" href="{{ hrefs.css_wizard }}" />
|
6 |
+
{% endblock %}
|
7 |
+
|
8 |
+
{% block head_scripts %}
|
9 |
+
{{ parent() }}
|
10 |
+
{% endblock %}
|
11 |
+
|
12 |
+
{% block body_content_main %}
|
13 |
+
<div class="row">
|
14 |
+
<div class="col-md-4 col-md-offset-4">
|
15 |
+
<p>This module comes with {{ data.mod_wizards_count }} Wizard(s).</p>
|
16 |
+
<p>Please click the link below of the Guided Wizard you'd like to launch.</p>
|
17 |
+
</div>
|
18 |
+
</div>
|
19 |
+
<div class="row">
|
20 |
+
<div class="col-md-2"></div>
|
21 |
+
{% for wizard in data.mod_wizards %}
|
22 |
+
<div class="col-md-4">
|
23 |
+
<div class="wizard_slot">
|
24 |
+
<div><h3>{{ wizard.title }}</h3></div>
|
25 |
+
<div>
|
26 |
+
<p>{{ wizard.desc }}</p>
|
27 |
+
{% if wizard.has_premium %}
|
28 |
+
<p>{{ strings.premium_note }}</p>
|
29 |
+
{% endif %}
|
30 |
+
</div>
|
31 |
+
<div><a class="btn btn-info" href="{{ wizard.url }}">Launch Wizard</a></div>
|
32 |
+
</div>
|
33 |
+
</div>
|
34 |
+
{% endfor %}
|
35 |
+
</div>
|
36 |
+
{% endblock %}
|
templates/twig/{pages → wizard/pages}/wizard.twig
RENAMED
@@ -1,4 +1,4 @@
|
|
1 |
-
{% extends 'pages/base.twig' %}
|
2 |
|
3 |
{% block head_stylesheets %}
|
4 |
{{ parent() }}
|
@@ -23,7 +23,7 @@
|
|
23 |
</div>
|
24 |
{% endblock %}
|
25 |
|
26 |
-
{% block
|
27 |
<script type="text/javascript">
|
28 |
|
29 |
jQuery( document ).ready( function ( $ ) {
|
@@ -157,10 +157,6 @@ var iCWP_WPSF_Wizard_FormHandler = new function () {
|
|
157 |
|
158 |
jQuery.post( '{{ ajax.content.ajaxurl }}', $oForm.serialize(),
|
159 |
function ( oResponse ) {
|
160 |
-
var sMessage = 'Unknown Error';
|
161 |
-
if ( undefined !== oResponse.data ) {
|
162 |
-
sMessage = oResponse.data.message;
|
163 |
-
}
|
164 |
|
165 |
if ( oResponse.success ) {
|
166 |
$oResponseField.removeClass( 'bg-danger' )
|
@@ -171,12 +167,23 @@ var iCWP_WPSF_Wizard_FormHandler = new function () {
|
|
171 |
.addClass( 'bg-danger' );
|
172 |
$oSubmitButton.prop( 'disabled', false );
|
173 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
174 |
$oResponseField.html( sMessage );
|
175 |
|
176 |
-
if (
|
177 |
-
&& oResponse.data.rerender === true ) {
|
178 |
iCWP_WPSF_Wizard_FormHandler.reRenderCurrent();
|
179 |
}
|
|
|
|
|
180 |
}
|
181 |
).always(
|
182 |
function () {
|
1 |
+
{% extends 'wizard/pages/base.twig' %}
|
2 |
|
3 |
{% block head_stylesheets %}
|
4 |
{{ parent() }}
|
23 |
</div>
|
24 |
{% endblock %}
|
25 |
|
26 |
+
{% block body_footer_scripts %}
|
27 |
<script type="text/javascript">
|
28 |
|
29 |
jQuery( document ).ready( function ( $ ) {
|
157 |
|
158 |
jQuery.post( '{{ ajax.content.ajaxurl }}', $oForm.serialize(),
|
159 |
function ( oResponse ) {
|
|
|
|
|
|
|
|
|
160 |
|
161 |
if ( oResponse.success ) {
|
162 |
$oResponseField.removeClass( 'bg-danger' )
|
167 |
.addClass( 'bg-danger' );
|
168 |
$oSubmitButton.prop( 'disabled', false );
|
169 |
}
|
170 |
+
|
171 |
+
var bRerender = false;
|
172 |
+
var sMessage = 'Unknown Error';
|
173 |
+
if ( undefined !== oResponse.data ) {
|
174 |
+
|
175 |
+
if ( undefined !== oResponse.data.rerender && oResponse.data.rerender === true ) {
|
176 |
+
bRerender = true;
|
177 |
+
}
|
178 |
+
sMessage = oResponse.data.message;
|
179 |
+
}
|
180 |
$oResponseField.html( sMessage );
|
181 |
|
182 |
+
if ( bRerender ) {
|
|
|
183 |
iCWP_WPSF_Wizard_FormHandler.reRenderCurrent();
|
184 |
}
|
185 |
+
|
186 |
+
jQuery( $oForm ).trigger( 'icwpWizardFormSubmit', oResponse.success );
|
187 |
}
|
188 |
).always(
|
189 |
function () {
|
templates/twig/wizard/slide-import_finished.twig
DELETED
@@ -1,7 +0,0 @@
|
|
1 |
-
{% extends 'wizard/base_finish.twig' %}
|
2 |
-
|
3 |
-
{% block slide_body %}
|
4 |
-
<h3>Finished: Shield Options Import Wizard</h3>
|
5 |
-
<p>This is the end of the Shield Security Network/Import Wizard. Click the link below to return to the main
|
6 |
-
WordPress dashboard.</p>
|
7 |
-
{% endblock %}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
templates/twig/wizard/{base.twig → slides/common/base.twig}
RENAMED
@@ -4,12 +4,12 @@
|
|
4 |
{% block slide_header_nav %}
|
5 |
<div class="container-fluid">
|
6 |
<div class="row">
|
7 |
-
<div class="col-md-6">
|
8 |
{% block slide_header_previous %}
|
9 |
<button class="btn btn-default btn-block ButtonPreviousSlide">← Previous Step </button>
|
10 |
{% endblock %}
|
11 |
</div>
|
12 |
-
<div class="col-md-6">
|
13 |
{% block slide_header_next %}
|
14 |
<button class="btn btn-info btn-block ButtonNextSlide">Next Step →</button>
|
15 |
{% endblock %}
|
@@ -21,7 +21,11 @@
|
|
21 |
{% endblock %}
|
22 |
</div>
|
23 |
<div class="slide-body">
|
24 |
-
{% block slide_body %}
|
|
|
|
|
|
|
|
|
25 |
</div>
|
26 |
<div class="slide-footer">
|
27 |
{% block slide_footer %}
|
4 |
{% block slide_header_nav %}
|
5 |
<div class="container-fluid">
|
6 |
<div class="row">
|
7 |
+
<div class="col-md-6 col-sm-6 col-xs-6">
|
8 |
{% block slide_header_previous %}
|
9 |
<button class="btn btn-default btn-block ButtonPreviousSlide">← Previous Step </button>
|
10 |
{% endblock %}
|
11 |
</div>
|
12 |
+
<div class="col-md-6 col-sm-6 col-xs-6">
|
13 |
{% block slide_header_next %}
|
14 |
<button class="btn btn-info btn-block ButtonNextSlide">Next Step →</button>
|
15 |
{% endblock %}
|
21 |
{% endblock %}
|
22 |
</div>
|
23 |
<div class="slide-body">
|
24 |
+
{% block slide_body %}
|
25 |
+
{% block slide_body_top %}{% endblock %}
|
26 |
+
{% block slide_body_middle %}{% endblock %}
|
27 |
+
{% block slide_body_bottom %}{% endblock %}
|
28 |
+
{% endblock %}
|
29 |
</div>
|
30 |
<div class="slide-footer">
|
31 |
{% block slide_footer %}
|
templates/twig/wizard/slides/common/base_finish.twig
ADDED
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% extends 'wizard/slides/common/base.twig' %}
|
2 |
+
|
3 |
+
{% block slide_header_next %}{% endblock %}
|
4 |
+
|
5 |
+
{% block slide_body_middle %}
|
6 |
+
|
7 |
+
<h3>Next Steps?</h3>
|
8 |
+
|
9 |
+
{% if data.mod_wizards_count > 1 %}
|
10 |
+
<h4>All Wizards In This Module</h4>
|
11 |
+
<ul>
|
12 |
+
{% for wizard in data.mod_wizards %}
|
13 |
+
<li><a href="{{ wizard.url }}">{{ wizard.title }}</a></li>
|
14 |
+
{% endfor %}
|
15 |
+
</ul>
|
16 |
+
{% endif %}
|
17 |
+
|
18 |
+
{% block slide_body_middle_gopro %}
|
19 |
+
{% if not flags.is_premium %}
|
20 |
+
<h4>Go Further With Pro :)</h4>
|
21 |
+
<p>We've added many advantages to the Pro version, and we've made it available for every budget
|
22 |
+
for just $1/month - the most affordable Security plugin available today!</p>
|
23 |
+
<p>With your support, we'll continue our work and bring you ever-more powerful security features.</p>
|
24 |
+
<p>This is what you get for going Pro:</p>
|
25 |
+
<ul>
|
26 |
+
<li>Simple (+automatic) options import/export between all your websites</li>
|
27 |
+
<li>Vulnerability Scanner - daily scans/alerts for security vulnerabilities</li>
|
28 |
+
<li>Exclusive customer support</li>
|
29 |
+
<li>3rd-Party Plugin integration including WooCommerce, BuddyPress etc.</li>
|
30 |
+
<li>Unlimited audit trail</li>
|
31 |
+
<li>Invisible Google reCAPTCHA</li>
|
32 |
+
<li>Customize visitor messages</li>
|
33 |
+
<li>(coming soon) Mobile Push Notifications</li>
|
34 |
+
<li>(coming soon) White Labelling</li>
|
35 |
+
<li>(coming soon) Refined options for 2-Factor Authentication</li>
|
36 |
+
</ul>
|
37 |
+
<a href="{{ hrefs.gopro }}" target="_blank" class="btn btn-success" id="GoProBtn">Go Pro Today!</a>
|
38 |
+
{% endif %}
|
39 |
+
{% endblock %}
|
40 |
+
|
41 |
+
{% endblock %}
|
42 |
+
|
43 |
+
{% block slide_body_bottom %}
|
44 |
+
<p>Click the button below to return to the main WordPress dashboard.</p>
|
45 |
+
{% endblock %}
|
46 |
+
|
47 |
+
{% block slide_footer %}
|
48 |
+
<hr />
|
49 |
+
<a href="{{ hrefs.dashboard }}" class="btn btn-default">⇐ Return To The Shield WordPress Dashboard</a>
|
50 |
+
{% endblock %}
|
templates/twig/wizard/slides/common/base_start.twig
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
{% extends 'wizard/slides/common/base.twig' %}
|
2 |
+
|
3 |
+
{% block slide_header_previous %}{% endblock %}
|
templates/twig/wizard/{slide-no_access.twig → slides/common/no_access.twig}
RENAMED
@@ -1,4 +1,4 @@
|
|
1 |
-
{% extends 'wizard/base.twig' %}
|
2 |
|
3 |
{% block slide_header_nav %}{% endblock %}
|
4 |
|
1 |
+
{% extends 'wizard/slides/common/base.twig' %}
|
2 |
|
3 |
{% block slide_header_nav %}{% endblock %}
|
4 |
|
templates/twig/wizard/{slide-admin_access_restriction_verify.twig → slides/common/security_admin_verify.twig}
RENAMED
@@ -1,4 +1,4 @@
|
|
1 |
-
{% extends 'wizard/base.twig' %}
|
2 |
|
3 |
{% block slide_body %}
|
4 |
|
@@ -7,7 +7,7 @@
|
|
7 |
|
8 |
<h4>Supply Security Admin Access Key</h4>
|
9 |
<form class="form-horizontal icwp-wizard-form">
|
10 |
-
<input name="wizard-step" value="
|
11 |
<input name="current_index" value="{{ current_index }}" type="hidden" />
|
12 |
<div class="form-group">
|
13 |
<label class="col-md-4 control-label" for="AccessKey">Access Key</label>
|
1 |
+
{% extends 'wizard/slides/common/base.twig' %}
|
2 |
|
3 |
{% block slide_body %}
|
4 |
|
7 |
|
8 |
<h4>Supply Security Admin Access Key</h4>
|
9 |
<form class="form-horizontal icwp-wizard-form">
|
10 |
+
<input name="wizard-step" value="security_admin_verify" type="hidden" />
|
11 |
<input name="current_index" value="{{ current_index }}" type="hidden" />
|
12 |
<div class="form-group">
|
13 |
<label class="col-md-4 control-label" for="AccessKey">Access Key</label>
|
templates/twig/wizard/slides/importexport/finished.twig
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% extends 'wizard/slides/common/base_finish.twig' %}
|
2 |
+
|
3 |
+
{% block slide_body_top %}
|
4 |
+
<h3>Finished: Shield Options Import Wizard</h3>
|
5 |
+
<p>This is the end of the Shield Security Network/Import Wizard.</p>
|
6 |
+
{% endblock %}
|
templates/twig/wizard/{slide-import_options.twig → slides/importexport/import.twig}
RENAMED
@@ -1,4 +1,4 @@
|
|
1 |
-
{% extends 'wizard/base.twig' %}
|
2 |
|
3 |
{% block slide_body %}
|
4 |
<h3>Build Your Shield Security Network</h3>
|
@@ -10,9 +10,10 @@
|
|
10 |
before proceeding.</p>
|
11 |
|
12 |
<h4>Import Options</h4>
|
13 |
-
<p><strong>Warning</strong>: If successful, on this site will be overwritten by
|
|
|
14 |
<form class="form-horizontal icwp-wizard-form">
|
15 |
-
<input name="wizard-step" value="
|
16 |
|
17 |
<div class="form-group">
|
18 |
<label class="col-md-4 control-label" for="MasterSiteUrl">Master Site URL</label>
|
1 |
+
{% extends 'wizard/slides/common/base.twig' %}
|
2 |
|
3 |
{% block slide_body %}
|
4 |
<h3>Build Your Shield Security Network</h3>
|
10 |
before proceeding.</p>
|
11 |
|
12 |
<h4>Import Options</h4>
|
13 |
+
<p><strong>Warning</strong>: If successful, all options on this site will be overwritten by
|
14 |
+
those from the source.</p>
|
15 |
<form class="form-horizontal icwp-wizard-form">
|
16 |
+
<input name="wizard-step" value="import" type="hidden" />
|
17 |
|
18 |
<div class="form-group">
|
19 |
<label class="col-md-4 control-label" for="MasterSiteUrl">Master Site URL</label>
|
templates/twig/wizard/{slide-import_start.twig → slides/importexport/start.twig}
RENAMED
@@ -1,4 +1,4 @@
|
|
1 |
-
{% extends 'wizard/base_start.twig' %}
|
2 |
|
3 |
{% block slide_body %}
|
4 |
|
@@ -7,6 +7,10 @@
|
|
7 |
your sites.</p>
|
8 |
<p>You can, of course, simply use this as an ad-hoc import tool, but much more powerful is to create a
|
9 |
<strong>Shield Network</strong>.</p>
|
|
|
|
|
|
|
|
|
10 |
<h4>What is a Shield Network?</h4>
|
11 |
<p>A Shield Network is where all your Shield Security sites are connected to a Master Site, from which they will
|
12 |
derive their configuration. If you change settings on the Master Site, these will get propagated to the child sites.</p>
|
@@ -21,6 +25,5 @@
|
|
21 |
<li>If you select to create the network, this site's URL will be added to the sync white list of the Master
|
22 |
site, to allow for automated syncing.</li>
|
23 |
</ul>
|
24 |
-
<p> </p>
|
25 |
<p>Right, let's get to it. Click 'Next Step' above to start your import.
|
26 |
{% endblock %}
|
1 |
+
{% extends 'wizard/slides/common/base_start.twig' %}
|
2 |
|
3 |
{% block slide_body %}
|
4 |
|
7 |
your sites.</p>
|
8 |
<p>You can, of course, simply use this as an ad-hoc import tool, but much more powerful is to create a
|
9 |
<strong>Shield Network</strong>.</p>
|
10 |
+
<h4>What about simple options import?</h4>
|
11 |
+
<p>This is easily done. Move to the next step and enter the information for the site you want
|
12 |
+
to export from i.e. its URL and its secret key. Options will then be imported directly into this site.</p>
|
13 |
+
<p>If you want to keep your site options "synced" with the export site, read on...</p>
|
14 |
<h4>What is a Shield Network?</h4>
|
15 |
<p>A Shield Network is where all your Shield Security sites are connected to a Master Site, from which they will
|
16 |
derive their configuration. If you change settings on the Master Site, these will get propagated to the child sites.</p>
|
25 |
<li>If you select to create the network, this site's URL will be added to the sync white list of the Master
|
26 |
site, to allow for automated syncing.</li>
|
27 |
</ul>
|
|
|
28 |
<p>Right, let's get to it. Click 'Next Step' above to start your import.
|
29 |
{% endblock %}
|
templates/twig/wizard/slides/mfa/authemail.twig
ADDED
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% extends 'wizard/slides/common/base.twig' %}
|
2 |
+
|
3 |
+
{% block slide_body %}
|
4 |
+
|
5 |
+
<h3>Setup Email-Based Authentication</h3>
|
6 |
+
<p>Email-based authentication involves you receiving an email to the address attached to your WordPress
|
7 |
+
user account. This email will contain a 6-digit code which you'll need to put into the
|
8 |
+
login confirmation page.</p>
|
9 |
+
<p>The tricky thing with email is that WordPress sites are terrible for sending emails, as most domains
|
10 |
+
and webhosting aren't configured properly for sending email reliably.</p>
|
11 |
+
<p>This means if you set this up and you don't get the email, you'll be locked out. So, before enabling
|
12 |
+
email-based authentication, we'll send you a test email first and ask you to verify that you got it.</p>
|
13 |
+
|
14 |
+
<h4>Email Sending Confirmation</h4>
|
15 |
+
<p>Click the button below to confirm your email address, to which we'll send a confirmation email.</p>
|
16 |
+
<form class="form-horizontal icwp-wizard-form" id>
|
17 |
+
<input name="wizard-step" value="authemail" type="hidden" />
|
18 |
+
|
19 |
+
<div class="form-group">
|
20 |
+
<label class="col-md-4 control-label" for="email">Your Email</label>
|
21 |
+
<div class="col-md-8">
|
22 |
+
<input type="email" class="form-control" name="email" placeholder="{{ data.user_email }}"
|
23 |
+
value="{{ data.user_email }}">
|
24 |
+
</div>
|
25 |
+
</div>
|
26 |
+
|
27 |
+
<div class="form-group stage-verificationcode" style="display: none;">
|
28 |
+
<label class="col-md-4 control-label" for="code">Verification Code</label>
|
29 |
+
<div class="col-md-8">
|
30 |
+
<input type="text" class="form-control" name="code"
|
31 |
+
maxlength="6" minlength="6" placeholder="" value="">
|
32 |
+
</div>
|
33 |
+
</div>
|
34 |
+
|
35 |
+
<div class="form-group stage-verificationcode" style="display: none;">
|
36 |
+
<label class="col-md-4 control-label" for="Email2FAOption">Turn On Email 2FA</label>
|
37 |
+
<div class="col-md-8">
|
38 |
+
<label for="Email2FAOption">
|
39 |
+
<input type="checkbox" value="Y" name="Email2FAOption" id="Email2FAOption">
|
40 |
+
Check to turn on Email-based 2 Factor Authentication
|
41 |
+
</label>
|
42 |
+
<span id="helpBlock" class="help-block">
|
43 |
+
When enabled, each time you login you'll get an email with a 2-factor authentication code.
|
44 |
+
You will need this code to log into your WordPress site. If your site
|
45 |
+
has problems in the future with emails, this could present a problem.
|
46 |
+
Emails not being received are the responsibility
|
47 |
+
of your WordPress site and your email provider. Shield uses the standard WordPress email
|
48 |
+
functionality and if it doesn't work, you'll need to check with your host.
|
49 |
+
</span>
|
50 |
+
</div>
|
51 |
+
</div>
|
52 |
+
|
53 |
+
<div class="form-group">
|
54 |
+
<div class="col-md-offset-4 col-md-8">
|
55 |
+
<button type="submit" class="btn btn-primary">Send Info</button>
|
56 |
+
</div>
|
57 |
+
</div>
|
58 |
+
</form>
|
59 |
+
|
60 |
+
<script type="text/javascript">
|
61 |
+
jQuery( document ).on( 'icwpWizardFormSubmit', function ( event, bSuccess ) {
|
62 |
+
if ( bSuccess ) {
|
63 |
+
var $oForm = jQuery( event.target );
|
64 |
+
jQuery( '.stage-verificationcode', $oForm ).slideDown();
|
65 |
+
jQuery( 'button[type=submit]', $oForm ).prop( 'disabled', false );
|
66 |
+
}
|
67 |
+
} );
|
68 |
+
</script>
|
69 |
+
{% endblock %}
|
templates/twig/wizard/slides/mfa/authga.twig
ADDED
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% extends 'wizard/slides/common/base.twig' %}
|
2 |
+
|
3 |
+
{% block slide_body %}
|
4 |
+
|
5 |
+
<h3>Setup Google Authenticator</h3>
|
6 |
+
<p>Google Authenticator is a popular choice for 2FA. It has 1 drawback, however - if you'll lose
|
7 |
+
your phone or reset it, you lose all your 2FA login codes.</p>
|
8 |
+
<p>There is a solution to this and we <strong>strongly recommend</strong> that you do it: .</p>
|
9 |
+
<p>Once you're ready to proceed with Google Authenticator, please scan the barcode below, and enter
|
10 |
+
code to confirm.</p>
|
11 |
+
<p>Note: Turning on Google Authenticator for your user account will make the option available
|
12 |
+
to turn it on for all users on the site.</p>
|
13 |
+
|
14 |
+
<h4>Register Google Authenticator On Your Account</h4>
|
15 |
+
|
16 |
+
{% if flags.has_ga %}
|
17 |
+
<p>It looks like Google Authenticator is already configured for your WordPress account so
|
18 |
+
no need to set that up again.</p>
|
19 |
+
{% else %}
|
20 |
+
<p>Scan the barcode below and enter the 6-digit code to register.</p>
|
21 |
+
{% endif %}
|
22 |
+
|
23 |
+
<form class="form-horizontal icwp-wizard-form" id>
|
24 |
+
<input name="wizard-step" value="authga" type="hidden" />
|
25 |
+
|
26 |
+
{% if flags.has_ga %}
|
27 |
+
<input name="code" value="ignore" type="hidden" />
|
28 |
+
|
29 |
+
<div class="form-group stage-verificationcode">
|
30 |
+
<label class="col-md-4 control-label" for="enablega">Turn On Google Authenticator</label>
|
31 |
+
<div class="col-md-8">
|
32 |
+
<div class="radio">
|
33 |
+
<label>
|
34 |
+
<input type="radio" name="enablega" id="enablegaOn" value="Y" checked>
|
35 |
+
Enable Google Authenticator
|
36 |
+
</label>
|
37 |
+
</div>
|
38 |
+
<div class="radio">
|
39 |
+
<label>
|
40 |
+
<input type="radio" name="enablega" id="enablegaOff" value="N">
|
41 |
+
Disable Google Authenticator
|
42 |
+
</label>
|
43 |
+
</div>
|
44 |
+
|
45 |
+
<span id="helpBlock" class="help-block">
|
46 |
+
When enabled, this will allow any users of this site to configure and
|
47 |
+
use Google Authenticator on their WordPress accounts.
|
48 |
+
</span>
|
49 |
+
</div>
|
50 |
+
</div>
|
51 |
+
{% else %}
|
52 |
+
<input name="enablega" value="Y" type="hidden" />
|
53 |
+
|
54 |
+
<div class="form-group">
|
55 |
+
<label class="col-md-4 control-label">Scan your unique code</label>
|
56 |
+
<div class="col-md-8">
|
57 |
+
<img src="{{ hrefs.ga_chart }}" />
|
58 |
+
</div>
|
59 |
+
</div>
|
60 |
+
|
61 |
+
<div class="form-group">
|
62 |
+
<label class="col-md-4 control-label" for="code">Authenticator Code</label>
|
63 |
+
<div class="col-md-8">
|
64 |
+
<input type="text" class="form-control" name="code"
|
65 |
+
maxlength="6" minlength="6" placeholder="" value="">
|
66 |
+
</div>
|
67 |
+
</div>
|
68 |
+
{% endif %}
|
69 |
+
|
70 |
+
<div class="form-group">
|
71 |
+
<div class="col-md-offset-4 col-md-8">
|
72 |
+
<button type="submit" class="btn btn-primary">Configure Google Authenticator</button>
|
73 |
+
</div>
|
74 |
+
</div>
|
75 |
+
</form>
|
76 |
+
{% endblock %}
|
templates/twig/wizard/slides/mfa/finished.twig
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% extends 'wizard/slides/common/base_finish.twig' %}
|
2 |
+
|
3 |
+
{% block slide_body_top %}
|
4 |
+
<h3>Finished: Multi-Factor Authentication Setup</h3>
|
5 |
+
<p>This is the end of the Shield Security Multi-Factor Authentication Setup Wizard.</p>
|
6 |
+
{% endblock %}
|
templates/twig/wizard/slides/mfa/multiselect.twig
ADDED
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% extends 'wizard/slides/common/base.twig' %}
|
2 |
+
|
3 |
+
{% block slide_body %}
|
4 |
+
|
5 |
+
<h3>Configure Multi-Factor or Two-Factor Authentication</h3>
|
6 |
+
<p>As we outlined on the first slide in this wizard, if you have a password and 1 extra factor,
|
7 |
+
you have what is known as "Two-Factor Authentication".</p>
|
8 |
+
<p>But if you have more than 1 extra factor, you have what is called
|
9 |
+
"Multi-Factor Authentication".</p>
|
10 |
+
<p>You have a choice between either of these, now that you've configured other login factors.</p>
|
11 |
+
<p>You can either set that <strong>all extra login factors</strong> are required when a user logs on.
|
12 |
+
Or you can set that <strong>only 1 extra login factor</strong> is required.</p>
|
13 |
+
<p>The balance here of course is between an easier user experience, or harder site security.
|
14 |
+
The choice is yours.</p>
|
15 |
+
|
16 |
+
<h4>Configure Factor Requirements</h4>
|
17 |
+
|
18 |
+
<form class="form-horizontal icwp-wizard-form" id>
|
19 |
+
<input name="wizard-step" value="multiselect" type="hidden" />
|
20 |
+
|
21 |
+
<div class="form-group stage-verificationcode">
|
22 |
+
<label class="col-md-4 control-label" for="multiselect">Configure Multi-Factor Authentication</label>
|
23 |
+
<div class="col-md-8">
|
24 |
+
<div class="radio">
|
25 |
+
<label>
|
26 |
+
<input type="radio" name="multiselect" id="multiselectOn" value="Y" checked>
|
27 |
+
Turn On Multi-Factor (all factors required)
|
28 |
+
</label>
|
29 |
+
</div>
|
30 |
+
<div class="radio">
|
31 |
+
<label>
|
32 |
+
<input type="radio" name="multiselect" id="multiselectOff" value="N">
|
33 |
+
Turn Off Multi-Factor (only 1 extra factor)
|
34 |
+
</label>
|
35 |
+
</div>
|
36 |
+
|
37 |
+
<span id="helpBlock" class="help-block">
|
38 |
+
Think of turning multi-factor <em>on</em> as "requiring all configured factors".
|
39 |
+
<br/>And think of turning multi-factor <em>off</em> as "requiring just 1 of your extra factors".
|
40 |
+
</span>
|
41 |
+
</div>
|
42 |
+
</div>
|
43 |
+
|
44 |
+
<div class="form-group">
|
45 |
+
<div class="col-md-offset-4 col-md-8">
|
46 |
+
<button type="submit" class="btn btn-primary">Configure Multi-Factor</button>
|
47 |
+
</div>
|
48 |
+
</div>
|
49 |
+
</form>
|
50 |
+
{% endblock %}
|
templates/twig/wizard/slides/mfa/start.twig
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% extends 'wizard/slides/common/base_start.twig' %}
|
2 |
+
|
3 |
+
{% block slide_body %}
|
4 |
+
|
5 |
+
<h3>Multi-Factor Authentication Wizard</h3>
|
6 |
+
<p>What is Multi-Factor / Two-Factor Authentication?</p>
|
7 |
+
<p>Simply put, it is the addition of an extra piece of information (or "factor") during your login.
|
8 |
+
It helps prevent anyone gaining access to your account with just your password.</p>
|
9 |
+
<p>This can take various forms, and you've probably seen it in other places. Some examples include:</p>
|
10 |
+
<ul>
|
11 |
+
<li>A memorable question, e.g. What is your favourite color</li>
|
12 |
+
<li>Google Authenticator - you supply a random 6-digit code</li>
|
13 |
+
<li>Email - you get an email with a link or a code to verify</li>
|
14 |
+
<li>SMS - you get text message with a code to verify</li>
|
15 |
+
</ul>
|
16 |
+
<p>Hopefully you see the pattern - there's a extra piece of information that you must
|
17 |
+
supply along with your password. This is your extra "factor".</p>
|
18 |
+
<p>If you have a password + 1 other factor, this is called Two-Factor Authentication</p>
|
19 |
+
<p>If you have a password + 2 or more other factors, this is called Multi-Factor Authentication</p>
|
20 |
+
<p>The Shield Security plugin lets you setup multiple login factors, and the simplest
|
21 |
+
of which is <strong>email</strong>. This wizard will walk you through setup of these extra factors.</p>
|
22 |
+
{% endblock %}
|
templates/twig/wizard/slides/ufc/config.twig
ADDED
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% extends 'wizard/slides/common/base.twig' %}
|
2 |
+
|
3 |
+
{% block slide_body %}
|
4 |
+
<h3>Turn On Automatic Unrecognised File Scanner</h3>
|
5 |
+
<p>It looks like the unrecognised file scanner isn't set to run automatically.</p>
|
6 |
+
<p>Now that you've setup your file exclusions, we recommend the final option
|
7 |
+
- automatically delete discovered files and send an email report.</p>
|
8 |
+
<p>You can adjust this using the settings below.</p>
|
9 |
+
|
10 |
+
<form class="form-horizontal icwp-wizard-form">
|
11 |
+
<input name="wizard-step" value="ufcconfig" type="hidden" />
|
12 |
+
<div class="form-group">
|
13 |
+
<label class="col-md-4 control-label" for="enable_scan">Enable Automatic Scanning</label>
|
14 |
+
<div class="col-md-8">
|
15 |
+
<div class="radio">
|
16 |
+
<label>
|
17 |
+
<input type="radio" name="enable_scan" id="EnableScanReport" value="enabled_report_only">
|
18 |
+
Send email report only
|
19 |
+
</label>
|
20 |
+
</div>
|
21 |
+
<div class="radio">
|
22 |
+
<label>
|
23 |
+
<input type="radio" name="enable_scan" id="EnableScanDelete" value="enabled_delete_only">
|
24 |
+
Automatically delete discovered files
|
25 |
+
</label>
|
26 |
+
</div>
|
27 |
+
<div class="radio">
|
28 |
+
<label>
|
29 |
+
<input type="radio" name="enable_scan" id="EnableScanDeleteReport" value="enabled_delete_report">
|
30 |
+
Automatically delete discovered files and send email report<br/>(<em>recommended</em>)
|
31 |
+
</label>
|
32 |
+
</div>
|
33 |
+
</div>
|
34 |
+
</div>
|
35 |
+
|
36 |
+
<div class="form-group">
|
37 |
+
<div class="col-md-offset-4 col-md-8">
|
38 |
+
<button type="submit" class="btn btn-primary">Set Automatic Scan</button>
|
39 |
+
</div>
|
40 |
+
</div>
|
41 |
+
</form>
|
42 |
+
{% endblock %}
|
templates/twig/wizard/slides/ufc/exclusions.twig
ADDED
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% extends 'wizard/slides/common/base.twig' %}
|
2 |
+
|
3 |
+
{% block slide_body %}
|
4 |
+
|
5 |
+
<h3>Unrecognised File Scanner - File Exclusions</h3>
|
6 |
+
<p>Every website is different, so there are often many different types of files present on web hosts
|
7 |
+
that are perfectly legitimate.</p>
|
8 |
+
<p>Since we can't account for all these possibilities, we provide you with the option
|
9 |
+
to add your own list of excluded files, that the scanner will then ignore.</p>
|
10 |
+
<p>In the box provided below, simply add each file name you want to ignore. If you
|
11 |
+
don't know what to put in here just now, or you don't want to add any further exclusions, simply move
|
12 |
+
to the next step to run the scanner.</p>
|
13 |
+
<p>Note: You can easily come back to this step and add files if the scanner picks anything up
|
14 |
+
that you then want to ignore. You can do this as often as you like.</p>
|
15 |
+
<p>Please use the list of files below to tell the file scanner which files it should completely ignore:</p>
|
16 |
+
<form class="form-horizontal icwp-wizard-form" id>
|
17 |
+
<input name="wizard-step" value="exclusions" type="hidden" />
|
18 |
+
|
19 |
+
<div class="form-group">
|
20 |
+
<label class="col-md-4 control-label" for="email">Excluded Files List</label>
|
21 |
+
<div class="col-md-8">
|
22 |
+
<textarea class="form-control" name="exclusions" rows="{{ data.files.count + 2 }}"
|
23 |
+
placeholder="{{ data.files.list }}">{{ data.files.list }}</textarea>
|
24 |
+
<span id="helpBlock" class="help-block">
|
25 |
+
Take a <strong>new line</strong> for each file name.
|
26 |
+
<br/>Note: You may also use regular expressions - if you don't know what this is,
|
27 |
+
that's no problem, then please use normal file names and ignore the following guidance.
|
28 |
+
<br/>Regular expressions must <strong>start and end</strong> with a "hash" character
|
29 |
+
i.e. <code>#</code>
|
30 |
+
<br />You must escape special characters.
|
31 |
+
<br />An example: <code>#\.log#</code>
|
32 |
+
<br />This will match the following files:
|
33 |
+
<code>test.log</code>, <code>text.log.txt</code>, <code>.log.ini</code>
|
34 |
+
</span>
|
35 |
+
</div>
|
36 |
+
</div>
|
37 |
+
|
38 |
+
<div class="form-group">
|
39 |
+
<div class="col-md-offset-4 col-md-8">
|
40 |
+
<button type="submit" class="btn btn-primary">Update File Exclusions</button>
|
41 |
+
</div>
|
42 |
+
</div>
|
43 |
+
</form>
|
44 |
+
|
45 |
+
<script type="text/javascript">
|
46 |
+
jQuery( document ).on( 'icwpWizardFormSubmit', function ( event, bSuccess ) {
|
47 |
+
if ( bSuccess ) {
|
48 |
+
var $oForm = jQuery( event.target );
|
49 |
+
jQuery( 'button[type=submit]', $oForm ).prop( 'disabled', false );
|
50 |
+
}
|
51 |
+
} );
|
52 |
+
</script>
|
53 |
+
{% endblock %}
|
templates/twig/wizard/slides/ufc/finished.twig
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% extends 'wizard/slides/common/base_finish.twig' %}
|
2 |
+
|
3 |
+
{% block slide_body_top %}
|
4 |
+
<h3>Finished: Unrecognised File Scanner</h3>
|
5 |
+
<p>This is the end of Shield Security's Unrecognised File Scanner Wizard.</p>
|
6 |
+
{% endblock %}
|
templates/twig/wizard/slides/ufc/scanresult.twig
ADDED
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% extends 'wizard/slides/common/base.twig' %}
|
2 |
+
|
3 |
+
{% block slide_body %}
|
4 |
+
|
5 |
+
<h3>Unrecognised File Scanner Results</h3>
|
6 |
+
{% if data.files.has %}
|
7 |
+
<div class="indent_slight">
|
8 |
+
<p>A total of {{ data.files.count }} file(s) were discovered.</p>
|
9 |
+
<ul>
|
10 |
+
{% for file in data.files.list %}
|
11 |
+
<li><code class="filepath">{{ file }}</code></li>
|
12 |
+
{% endfor %}
|
13 |
+
</ul>
|
14 |
+
</div>
|
15 |
+
<p>To have the scanner delete the files listed above, use the confirmation form below.</p>
|
16 |
+
<p><strong>Important</strong>: Remember it is not the job of the scanner to determine
|
17 |
+
whether you need these files on your website. This is <em>your role</em>.
|
18 |
+
We can only show you what's there. If you have doubts, please discuss
|
19 |
+
this with your web hosting provider.
|
20 |
+
</p>
|
21 |
+
<form class="form-horizontal icwp-wizard-form">
|
22 |
+
<input name="wizard-step" value="deletefiles" type="hidden" />
|
23 |
+
<div class="form-group">
|
24 |
+
<label class="col-md-4 control-label" for="DeleteFiles">Delete Detected Files</label>
|
25 |
+
<div class="col-md-8">
|
26 |
+
<label for="DeleteFiles">
|
27 |
+
<input type="checkbox" value="Y" name="DeleteFiles" id="DeleteFiles">
|
28 |
+
Check to delete the unrecognised files.
|
29 |
+
</label>
|
30 |
+
<span id="helpBlock" class="help-block">
|
31 |
+
If there are files on this list that you do not want to delete, please go back
|
32 |
+
a step in the wizard and add them to your exclusions list.
|
33 |
+
<br />For security reasons, the scanner <strong>does not</strong>
|
34 |
+
currently support individual selection of files to delete.
|
35 |
+
</span>
|
36 |
+
</div>
|
37 |
+
</div>
|
38 |
+
|
39 |
+
<div class="form-group">
|
40 |
+
<div class="col-md-offset-4 col-md-8">
|
41 |
+
<button type="submit" class="btn btn-warning">Delete Unrecognised Files</button>
|
42 |
+
</div>
|
43 |
+
</div>
|
44 |
+
</form>
|
45 |
+
|
46 |
+
{% else %}
|
47 |
+
<p>There were no files discovered in the scan.</p>
|
48 |
+
<p>This could be because there are none, or your exclusions list is ensuring they're ignored.</p>
|
49 |
+
{% endif %}
|
50 |
+
{% endblock %}
|
templates/twig/wizard/slides/ufc/start.twig
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% extends 'wizard/slides/common/base_start.twig' %}
|
2 |
+
|
3 |
+
{% block slide_body %}
|
4 |
+
|
5 |
+
<h3>Start Unrecognised File Scanner</h3>
|
6 |
+
<p>What is the Unrecognised File Scanner?</p>
|
7 |
+
<p>Where the Core File Scanner is preoccupied with finding any official
|
8 |
+
WordPress files that are corrupt, the Unrecognised File Scanner is focused on
|
9 |
+
discovering all the other files on your web hosting that are not part of a
|
10 |
+
standard WordPress Installation.</p>
|
11 |
+
<p>Why are these files important?</p>
|
12 |
+
<p>They could perfectly fine, or they could be script files that a hacker has deployed on your hosting
|
13 |
+
to access your site or corrupt your WordPress installation in some way.</p>
|
14 |
+
<p><strong>Important Note: this scanner cannot direct you whether you should delete or keep these files,
|
15 |
+
it can only tell you that they exist. It is up to you to determine if they're okay.</strong>
|
16 |
+
</p>
|
17 |
+
<p>If you're in doubt, please discuss any results with your hosting provider.</p>
|
18 |
+
{% endblock %}
|
templates/twig/wizard/slides/wcf/config.twig
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% extends 'wizard/slides/common/base.twig' %}
|
2 |
+
|
3 |
+
{% block slide_body %}
|
4 |
+
<h3>Turn On Automatic WordPress Core File Scanner</h3>
|
5 |
+
<p>It looks like the WordPress Core File scanner isn't set to run automatically.</p>
|
6 |
+
<p>We recommend the final option
|
7 |
+
- automatically restore any discovered files and send an email report.</p>
|
8 |
+
<p>You can adjust this using the settings below.</p>
|
9 |
+
|
10 |
+
<form class="form-horizontal icwp-wizard-form">
|
11 |
+
<input name="wizard-step" value="wcfconfig" type="hidden" />
|
12 |
+
<div class="form-group">
|
13 |
+
<label class="col-md-4 control-label" for="enable_scan">Enable Automatic Scanning</label>
|
14 |
+
<div class="col-md-8">
|
15 |
+
<div class="radio">
|
16 |
+
<label>
|
17 |
+
<input type="radio" name="enable_scan" id="EnableScanReport" value="enabled_report_only">
|
18 |
+
Scan WordPress Core files and send email report
|
19 |
+
</label>
|
20 |
+
</div>
|
21 |
+
<div class="radio">
|
22 |
+
<label>
|
23 |
+
<input type="radio" name="enable_scan" id="EnableScanDeleteReport" value="enabled_restore_report">
|
24 |
+
Scan and automatically restore any discovered files and send email report<br/>(<em>recommended</em>)
|
25 |
+
</label>
|
26 |
+
</div>
|
27 |
+
</div>
|
28 |
+
</div>
|
29 |
+
|
30 |
+
<div class="form-group">
|
31 |
+
<div class="col-md-offset-4 col-md-8">
|
32 |
+
<button type="submit" class="btn btn-primary">Set Automatic Scan</button>
|
33 |
+
</div>
|
34 |
+
</div>
|
35 |
+
</form>
|
36 |
+
{% endblock %}
|
templates/twig/wizard/slides/wcf/finished.twig
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% extends 'wizard/slides/common/base_finish.twig' %}
|
2 |
+
|
3 |
+
{% block slide_body_top %}
|
4 |
+
<h3>Finished: WordPress Core File Scanner</h3>
|
5 |
+
<p>This is the end of Shield Security's WordPress Core File Scanner Wizard.</p>
|
6 |
+
{% endblock %}
|
templates/twig/wizard/slides/wcf/scanresult.twig
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% extends 'wizard/slides/common/base.twig' %}
|
2 |
+
|
3 |
+
{% block slide_body %}
|
4 |
+
|
5 |
+
<h3>WordPress Core File Scanner Results</h3>
|
6 |
+
{% if data.files.has %}
|
7 |
+
<p>A total of {{ data.files.count }} file(s) were discovered.</p>
|
8 |
+
<div class="indent_slight">
|
9 |
+
{% if data.files.checksum.has %}
|
10 |
+
<h4>Modified Core Files: {{ data.files.checksum.count }}</h4>
|
11 |
+
<ul>
|
12 |
+
{% for file in data.files.checksum.list %}
|
13 |
+
<li><code class="filepath">{{ file }}</code></li>
|
14 |
+
{% endfor %}
|
15 |
+
</ul>
|
16 |
+
{% endif %}
|
17 |
+
</div>
|
18 |
+
|
19 |
+
<div class="indent_slight">
|
20 |
+
{% if data.files.missing.has %}
|
21 |
+
<h4>Missing Core Files: {{ data.files.missing.count }}</h4>
|
22 |
+
<ul>
|
23 |
+
{% for file in data.files.missing.list %}
|
24 |
+
<li><code class="filepath">{{ file }}</code></li>
|
25 |
+
{% endfor %}
|
26 |
+
</ul>
|
27 |
+
{% endif %}
|
28 |
+
</div>
|
29 |
+
|
30 |
+
<p>To replace the files listed above with the official versions taken
|
31 |
+
directly from WordPress.org, use the confirmation form below.</p>
|
32 |
+
<p><strong>Important</strong>: Remember it is not the job of the scanner to determine
|
33 |
+
whether you need to replace these files on your website. This is <em>your role</em>.
|
34 |
+
We can only show you what's there. If you have doubts, please discuss
|
35 |
+
this with your web hosting provider or developers.
|
36 |
+
</p>
|
37 |
+
<form class="form-horizontal icwp-wizard-form">
|
38 |
+
<input name="wizard-step" value="restorefiles" type="hidden" />
|
39 |
+
<div class="form-group">
|
40 |
+
<label class="col-md-4 control-label" for="RestoreFiles">Replace Modified Files</label>
|
41 |
+
<div class="col-md-8">
|
42 |
+
<label for="RestoreFiles">
|
43 |
+
<input type="checkbox" value="Y" name="RestoreFiles" id="RestoreFiles">
|
44 |
+
Check to replace all of the modified files.
|
45 |
+
</label>
|
46 |
+
<span id="helpBlock" class="help-block">
|
47 |
+
If you are unsure about whether you can restore these files to official
|
48 |
+
WordPress originals, please discuss the results of this scan with your
|
49 |
+
web host/developer.
|
50 |
+
</span>
|
51 |
+
</div>
|
52 |
+
</div>
|
53 |
+
|
54 |
+
<div class="form-group">
|
55 |
+
<div class="col-md-offset-4 col-md-8">
|
56 |
+
<button type="submit" class="btn btn-warning">Replace Files</button>
|
57 |
+
</div>
|
58 |
+
</div>
|
59 |
+
</form>
|
60 |
+
|
61 |
+
{% else %}
|
62 |
+
<p>There were no modified files discovered in the scan.</p>
|
63 |
+
{% endif %}
|
64 |
+
{% endblock %}
|
templates/twig/wizard/slides/wcf/start.twig
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% extends 'wizard/slides/common/base_start.twig' %}
|
2 |
+
|
3 |
+
{% block slide_body %}
|
4 |
+
<h3>Start: WordPress Core File Scanner</h3>
|
5 |
+
<p>What is the WordPress Core File Scanner?</p>
|
6 |
+
<p>The purpose of this scanner is to detect potentially malicious or
|
7 |
+
unintended changes to any of the Core WordPress files.
|
8 |
+
This is quite different to the Unrecognised File Scanner, which aims to detect
|
9 |
+
the presence of files that are not part of the official set of WordPress core files.</p>
|
10 |
+
<p>Why is this important?</p>
|
11 |
+
<p>Your site may already be compromised and you wouldn't know it by glancing at which core
|
12 |
+
files are installed on your site. The only way to know if your core WordPress files
|
13 |
+
have been modified in any way is to compare them against the official files.</p>
|
14 |
+
<p>This scanner will do exactly that and report to you any files it finds to be different.</p>
|
15 |
+
<p>If you're in doubt about the results, please discuss the findings with your hosting provider.</p>
|
16 |
+
{% endblock %}
|
templates/twig/wizard/{slide-admin_access_restriction.twig → slides/welcome/admin_access_restriction.twig}
RENAMED
@@ -1,4 +1,4 @@
|
|
1 |
-
{% extends 'wizard/base.twig' %}
|
2 |
|
3 |
{% block slide_body %}
|
4 |
|
1 |
+
{% extends 'wizard/slides/common/base.twig' %}
|
2 |
|
3 |
{% block slide_body %}
|
4 |
|
templates/twig/wizard/{slide-audit_trail.twig → slides/welcome/audit_trail.twig}
RENAMED
@@ -1,4 +1,4 @@
|
|
1 |
-
{% extends 'wizard/base.twig' %}
|
2 |
|
3 |
{% block slide_body %}
|
4 |
|
1 |
+
{% extends 'wizard/slides/common/base.twig' %}
|
2 |
|
3 |
{% block slide_body %}
|
4 |
|
templates/twig/wizard/{slide-comments_filter.twig → slides/welcome/comments_filter.twig}
RENAMED
@@ -1,4 +1,4 @@
|
|
1 |
-
{% extends 'wizard/base.twig' %}
|
2 |
|
3 |
{% block slide_body %}
|
4 |
|
1 |
+
{% extends 'wizard/slides/common/base.twig' %}
|
2 |
|
3 |
{% block slide_body %}
|
4 |
|
templates/twig/wizard/{slide-how_shield_works.twig → slides/welcome/how_shield_works.twig}
RENAMED
@@ -1,4 +1,4 @@
|
|
1 |
-
{% extends 'wizard/base.twig' %}
|
2 |
|
3 |
{% block slide_body %}
|
4 |
|
1 |
+
{% extends 'wizard/slides/common/base.twig' %}
|
2 |
|
3 |
{% block slide_body %}
|
4 |
|
templates/twig/wizard/slides/welcome/import.twig
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
{% extends 'wizard/slides/importexport/import.twig' %}
|
templates/twig/wizard/slides/welcome/ip_detect.twig
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% extends 'wizard/slides/common/base.twig' %}
|
2 |
+
|
3 |
+
{% block slide_body %}
|
4 |
+
|
5 |
+
<h3>IP Detection</h3>
|
6 |
+
<p>All websites and webhosts are configured differently. This makes certain things a bit tricky
|
7 |
+
to automate.</p>
|
8 |
+
<p>An important example of this is detecting the correct IP address of a website visitor.</p>
|
9 |
+
<p>We try to do this automatically for you, of course, but sometimes a server configuration
|
10 |
+
can be... unexpected. So, to ensure we use the method that works best on your server,
|
11 |
+
we're going to ask you to help us.</p>
|
12 |
+
<p>It's easy, and works by you telling us what your IP address is, so we can match it against all the possibilities
|
13 |
+
that your webhost server presents to us. When we find a match, we'll have found the best way to detect visitor IPs
|
14 |
+
for your particular web hosting.</p>
|
15 |
+
<p>It involves 2 simple steps. Here goes ...</p>
|
16 |
+
|
17 |
+
<h4>Steps To Find Best Source For Visitor IP Address</h4>
|
18 |
+
<h5>Step 1: Find <em>your</em> current IP address</h5>
|
19 |
+
<p><a href="{{ hrefs.visitor_ip }}" target="_blank">Click here</a>
|
20 |
+
to open up a new page that will tell you your current IP Address.</p>
|
21 |
+
<h5>Step 2: Tell us your IP address</h5>
|
22 |
+
<p>Copy and paste the IP address from Step 1 into the text box below and click submit.</p>
|
23 |
+
|
24 |
+
<form class="form-horizontal icwp-wizard-form">
|
25 |
+
<input name="wizard-step" value="ip_detect" type="hidden" />
|
26 |
+
<div class="form-group">
|
27 |
+
<label class="col-md-4 control-label" for="ip">My IP Address:</label>
|
28 |
+
<div class="col-md-8">
|
29 |
+
<input type="text" class="form-control" maxlength="32" size="32"
|
30 |
+
name="ip" id="ip" placeholder="123.456.789.012">
|
31 |
+
</div>
|
32 |
+
</div>
|
33 |
+
<div class="form-group">
|
34 |
+
<div class="col-md-offset-4 col-md-8">
|
35 |
+
<button type="submit" class="btn btn-primary">Submit: This Is My IP</button>
|
36 |
+
</div>
|
37 |
+
</div>
|
38 |
+
</form>
|
39 |
+
|
40 |
+
{% endblock %}
|
templates/twig/wizard/{slide-ips.twig → slides/welcome/ips.twig}
RENAMED
@@ -1,4 +1,4 @@
|
|
1 |
-
{% extends 'wizard/base.twig' %}
|
2 |
|
3 |
{% block slide_body %}
|
4 |
|
1 |
+
{% extends 'wizard/slides/common/base.twig' %}
|
2 |
|
3 |
{% block slide_body %}
|
4 |
|
templates/twig/wizard/{slide-license.twig → slides/welcome/license.twig}
RENAMED
@@ -1,4 +1,4 @@
|
|
1 |
-
{% extends 'wizard/base.twig' %}
|
2 |
|
3 |
{% block slide_body %}
|
4 |
|
1 |
+
{% extends 'wizard/slides/common/base.twig' %}
|
2 |
|
3 |
{% block slide_body %}
|
4 |
|
templates/twig/wizard/{slide-login_protect.twig → slides/welcome/login_protect.twig}
RENAMED
@@ -1,4 +1,4 @@
|
|
1 |
-
{% extends 'wizard/base.twig' %}
|
2 |
|
3 |
{% block slide_body %}
|
4 |
|
1 |
+
{% extends 'wizard/slides/common/base.twig' %}
|
2 |
|
3 |
{% block slide_body %}
|
4 |
|
templates/twig/wizard/{slide-optin.twig → slides/welcome/optin.twig}
RENAMED
@@ -1,4 +1,4 @@
|
|
1 |
-
{% extends 'wizard/base.twig' %}
|
2 |
|
3 |
{% block slide_body %}
|
4 |
|
1 |
+
{% extends 'wizard/slides/common/base.twig' %}
|
2 |
|
3 |
{% block slide_body %}
|
4 |
|
templates/twig/wizard/{slide-thankyou.twig → slides/welcome/thankyou.twig}
RENAMED
@@ -1,6 +1,6 @@
|
|
1 |
-
{% extends 'wizard/base_finish.twig' %}
|
2 |
|
3 |
-
{% block
|
4 |
|
5 |
<h3>Thank You!</h3>
|
6 |
<p>You've done it! This is the just scratching the surface of Shield Security and the options you have available.</p>
|
1 |
+
{% extends 'wizard/slides/common/base_finish.twig' %}
|
2 |
|
3 |
+
{% block slide_body_top %}
|
4 |
|
5 |
<h3>Thank You!</h3>
|
6 |
<p>You've done it! This is the just scratching the surface of Shield Security and the options you have available.</p>
|
templates/twig/wizard/{slide-welcome.twig → slides/welcome/welcome.twig}
RENAMED
@@ -1,4 +1,4 @@
|
|
1 |
-
{% extends 'wizard/base_start.twig' %}
|
2 |
|
3 |
{% block slide_body %}
|
4 |
|
1 |
+
{% extends 'wizard/slides/common/base_start.twig' %}
|
2 |
|
3 |
{% block slide_body %}
|
4 |
|