Version Description
- ADDED: Better admin notifications for events such as options saving etc.
- CHANGE: Some plugin styling to highlight features and options better.
- FIXED: Small bug with options default values.
Download this release
Release Info
Developer | paultgoodchild |
Plugin | Shield Security for WordPress |
Version | 3.5.5 |
Comparing to | |
See all releases |
Code changes from version 3.0.0 to 3.5.5
- icwp-plugin-controller.php +479 -0
- icwp-wpsf-main.php +343 -396
- icwp-wpsf.php +34 -87
- languages/wp-simple-firewall-es_ES.mo +0 -0
- languages/wp-simple-firewall-fr_FR.mo +0 -0
- languages/wp-simple-firewall-pt_BR.mo +0 -0
- mode.login_throttled +0 -0
- readme.txt +79 -5
- resources/css/global-plugin.css +33 -0
- resources/css/plugin.css +37 -1
- resources/js/bootstrap.min.js +6 -0
- src/config/feature-admin_access_restriction.txt +48 -0
- src/config/feature-audit_trail.txt +75 -0
- src/config/feature-autoupdates.txt +108 -0
- src/config/feature-comments_filter.txt +172 -0
- src/config/feature-email.txt +34 -0
- src/config/feature-firewall.txt +155 -0
- src/config/feature-lockdown.txt +66 -0
- src/config/feature-logging.txt +27 -0
- src/config/feature-login_protect.txt +182 -0
- src/config/feature-plugin.txt +94 -0
- src/config/feature-user_management.txt +102 -0
- src/icwp-base-processor.php +0 -384
- src/icwp-data-processor.php +481 -408
- src/icwp-foundation.php +44 -0
- src/icwp-import-base-processor.php +0 -84
- src/icwp-import-wpf2-processor.php +0 -147
- src/icwp-options-vo.php +373 -0
- src/icwp-optionshandler-admin_access_restriction.php +134 -92
- src/icwp-optionshandler-audit_trail.php +150 -0
- src/icwp-optionshandler-autoupdates.php +146 -176
- src/icwp-optionshandler-base.php +750 -849
- src/icwp-optionshandler-comments_filter.php +318 -214
- src/icwp-optionshandler-email.php +53 -35
- src/icwp-optionshandler-firewall.php +177 -222
- src/icwp-optionshandler-lockdown.php +88 -110
- src/icwp-optionshandler-logging.php +51 -27
- src/icwp-optionshandler-login_protect.php +212 -218
- src/icwp-optionshandler-plugin.php +119 -69
- src/icwp-optionshandler-privacy_protect.php +9 -15
- src/icwp-optionshandler-user_management.php +140 -58
- src/{icwp-processor-adminaccessrestriction.php → icwp-processor-admin_access_restriction.php} +9 -4
- src/icwp-processor-audit_trail.php +225 -0
- src/icwp-processor-audit_trail_plugins.php +93 -0
- src/icwp-processor-audit_trail_posts.php +136 -0
- src/icwp-processor-audit_trail_themes.php +74 -0
- src/icwp-processor-audit_trail_users.php +160 -0
- src/icwp-processor-audit_trail_wordpress.php +84 -0
- src/icwp-processor-autoupdates.php +25 -21
- src/icwp-processor-base.php +333 -0
- src/{icwp-basedb-processor.php → icwp-processor-basedb.php} +126 -51
- src/icwp-processor-comments_filter.php +100 -0
- src/{icwp-processor-commentsfilter.php → icwp-processor-commentsfilter_antibotspam.php} +61 -258
- src/icwp-processor-commentsfilter_humanspam.php +309 -0
- src/icwp-processor-email.php +5 -5
- src/icwp-processor-firewall.php +8 -26
- src/icwp-processor-lockdown.php +108 -104
- src/icwp-processor-logging.php +11 -12
- src/icwp-processor-login_protect.php +225 -0
- src/icwp-processor-loginprotect.php +0 -1030
- src/icwp-processor-loginprotect_cooldown.php +111 -0
- src/icwp-processor-loginprotect_gasp.php +169 -0
- src/icwp-processor-loginprotect_twofactorauth.php +548 -0
- src/icwp-processor-loginprotect_yubikey.php +167 -0
- src/icwp-processor-plugin.php +205 -11
- src/icwp-processor-privacyprotect.php +9 -17
- src/{icwp-processor-usermanagement.php → icwp-processor-user_management.php} +221 -66
- src/icwp-processor-usermanagement_adminloginnotification.php +79 -0
- src/icwp-processor-yaml.php +65 -0
- src/icwp-pure-base.php +303 -876
- src/icwp-wpfilesystem.php +290 -242
- src/icwp-wpfunctions.php +494 -199
- src/lib/yaml/Spyc.php +1147 -0
- views/icwp-wpsf-access_restricted_index.php +20 -21
- views/icwp-wpsf-audit_trail_viewer_index.php +126 -0
- views/icwp-wpsf-changlog_summary.php +118 -0
- views/icwp-wpsf-config-options-table.php +1 -1
- views/icwp-wpsf-config_autoupdates_index.php +2 -2
- views/icwp-wpsf-config_header.php +9 -9
- views/icwp-wpsf-config_plugin_index.php +4 -247
- views/icwp-wpsf-config_summary.php +128 -0
- views/icwp-wpsf-config_user_management_index.php +3 -1
- views/{icwp_wpsf_firewall_log_index.php → icwp-wpsf-firewall_log_index.php} +1 -1
- views/{icwp_wpsf_privacy_protect_log_index.php → icwp-wpsf-privacy_protect_log_index.php} +1 -1
- views/icwp_options_helper.php +59 -51
- views/icwp_wpsf_index.php +1 -1
- views/include_js.php +1 -1
- views/snippets/admin_notice_mailchimp.php +18 -0
- views/snippets/admin_notice_override.php +4 -0
- views/snippets/admin_notice_plugin_upgraded.php +6 -0
- views/snippets/admin_notice_translate_plugin.php +11 -0
icwp-plugin-controller.php
ADDED
@@ -0,0 +1,479 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
+
* All rights reserved.
|
5 |
+
*
|
6 |
+
* "WordPress Simple Firewall" is distributed under the GNU General Public License, Version 2,
|
7 |
+
* June 1991. Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin
|
8 |
+
* St, Fifth Floor, Boston, MA 02110, USA
|
9 |
+
*
|
10 |
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
11 |
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
12 |
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
13 |
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
14 |
+
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
15 |
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
16 |
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
17 |
+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
18 |
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
19 |
+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
20 |
+
*/
|
21 |
+
|
22 |
+
require_once(dirname(__FILE__).ICWP_DS.'src'.ICWP_DS.'icwp-foundation.php');
|
23 |
+
class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
|
24 |
+
|
25 |
+
/**
|
26 |
+
* @var ICWP_WPSF_Spec
|
27 |
+
*/
|
28 |
+
private static $oPluginSpec;
|
29 |
+
|
30 |
+
/**
|
31 |
+
* @const string
|
32 |
+
*/
|
33 |
+
const ViewDir = 'views';
|
34 |
+
|
35 |
+
/**
|
36 |
+
* @const string
|
37 |
+
*/
|
38 |
+
const SrcDir = 'src';
|
39 |
+
|
40 |
+
/**
|
41 |
+
* @var string
|
42 |
+
*/
|
43 |
+
protected static $fLoggingEnabled;
|
44 |
+
|
45 |
+
/**
|
46 |
+
* @var string
|
47 |
+
*/
|
48 |
+
private $sPluginUrl;
|
49 |
+
|
50 |
+
/**
|
51 |
+
* @var string
|
52 |
+
*/
|
53 |
+
private $sPluginBaseFile;
|
54 |
+
|
55 |
+
/**
|
56 |
+
* @var ICWP_WPSF_Plugin_Controller
|
57 |
+
*/
|
58 |
+
public static $oInstance;
|
59 |
+
|
60 |
+
/**
|
61 |
+
* @param ICWP_WPSF_Spec $oPluginSpec
|
62 |
+
* @return ICWP_WPSF_Plugin_Controller
|
63 |
+
*/
|
64 |
+
public static function GetInstance( $oPluginSpec ) {
|
65 |
+
if ( !isset( self::$oInstance ) ) {
|
66 |
+
self::$oInstance = new self( $oPluginSpec );
|
67 |
+
}
|
68 |
+
return self::$oInstance;
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* @param ICWP_WPSF_Spec $oPluginSpec
|
73 |
+
*/
|
74 |
+
private function __construct( $oPluginSpec ) {
|
75 |
+
if ( empty( self::$oPluginSpec ) ) {
|
76 |
+
self::$oPluginSpec = $oPluginSpec;
|
77 |
+
add_action( 'plugins_loaded', array( $this, 'onWpPluginsLoaded' ) );
|
78 |
+
add_action( 'shutdown', array( $this, 'onWpShutdown' ) );
|
79 |
+
}
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Hooked to 'plugins_loaded'
|
84 |
+
*/
|
85 |
+
public function onWpPluginsLoaded() {
|
86 |
+
if ( $this->getIsValidAdminArea() ) {
|
87 |
+
add_action( 'admin_notices', array( $this, 'onWpAdminNotices' ) );
|
88 |
+
add_action( 'network_admin_notices', array( $this, 'onWpAdminNotices' ) );
|
89 |
+
add_filter( 'all_plugins', array( $this, 'filter_hidePluginFromTableList' ) );
|
90 |
+
add_filter( 'site_transient_update_plugins', array( $this, 'filter_hidePluginUpdatesFromUI' ) );
|
91 |
+
add_action( 'in_plugin_update_message-'.$this->getPluginBaseFile(), array( $this, 'onWpPluginUpdateMessage' ) );
|
92 |
+
}
|
93 |
+
$this->doPluginFormSubmit();
|
94 |
+
$this->doLoadTextDomain();
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
*/
|
99 |
+
public function onWpAdminNotices() {
|
100 |
+
// Do we have admin priviledges?
|
101 |
+
if ( !$this->getIsValidAdminArea() ) {
|
102 |
+
return true;
|
103 |
+
}
|
104 |
+
$aAdminNotices = apply_filters( $this->doPluginPrefix( 'admin_notices' ), array() );
|
105 |
+
if ( empty( $aAdminNotices ) || !is_array( $aAdminNotices ) ) {
|
106 |
+
return;
|
107 |
+
}
|
108 |
+
foreach( $aAdminNotices as $sAdminNotice ) {
|
109 |
+
echo $sAdminNotice;
|
110 |
+
}
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Displays a message in the plugins listing when a plugin has an update available.
|
115 |
+
*/
|
116 |
+
public function onWpPluginUpdateMessage() {
|
117 |
+
$sMessage = apply_filters( $this->doPluginPrefix( 'plugin_update_message' ), '' );
|
118 |
+
if ( empty( $sMessage ) ) {
|
119 |
+
$sMessage = '';
|
120 |
+
}
|
121 |
+
else {
|
122 |
+
$sMessage = sprintf(
|
123 |
+
'<div class="%s plugin_update_message">%s</div>',
|
124 |
+
$this->getPluginPrefix(),
|
125 |
+
$sMessage
|
126 |
+
);
|
127 |
+
}
|
128 |
+
echo $sMessage;
|
129 |
+
}
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Hooked to 'shutdown'
|
133 |
+
*/
|
134 |
+
public function onWpShutdown() {
|
135 |
+
do_action( $this->doPluginPrefix( 'plugin_shutdown' ) );
|
136 |
+
}
|
137 |
+
|
138 |
+
/**
|
139 |
+
* Added to a WordPress filter ('all_plugins') which will remove this particular plugin from the
|
140 |
+
* list of all plugins based on the "plugin file" name.
|
141 |
+
*
|
142 |
+
* @param array $aPlugins
|
143 |
+
* @return array
|
144 |
+
*/
|
145 |
+
public function filter_hidePluginFromTableList( $aPlugins ) {
|
146 |
+
|
147 |
+
$fHide = apply_filters( $this->doPluginPrefix( 'hide_plugin' ), false );
|
148 |
+
|
149 |
+
if ( !$fHide ) {
|
150 |
+
return $aPlugins;
|
151 |
+
}
|
152 |
+
|
153 |
+
$sPluginBaseFileName = $this->getPluginBaseFile();
|
154 |
+
if ( isset( $aPlugins[$sPluginBaseFileName] ) ) {
|
155 |
+
unset( $aPlugins[$sPluginBaseFileName] );
|
156 |
+
}
|
157 |
+
return $aPlugins;
|
158 |
+
}
|
159 |
+
|
160 |
+
/**
|
161 |
+
* Added to the WordPress filter ('site_transient_update_plugins') in order to remove visibility of updates
|
162 |
+
* from the WordPress Admin UI.
|
163 |
+
*
|
164 |
+
* In order to ensure that WordPress still checks for plugin updates it will not remove this plugin from
|
165 |
+
* the list of plugins if DOING_CRON is set to true.
|
166 |
+
*
|
167 |
+
* @uses $this->fHeadless if the plugin is headless, it is hidden
|
168 |
+
* @param StdClass $oPlugins
|
169 |
+
* @return StdClass
|
170 |
+
*/
|
171 |
+
public function filter_hidePluginUpdatesFromUI( $oPlugins ) {
|
172 |
+
|
173 |
+
if ( $this->loadWpFunctionsProcessor()->getIsCron() ) {
|
174 |
+
return $oPlugins;
|
175 |
+
}
|
176 |
+
|
177 |
+
if ( ! apply_filters( $this->doPluginPrefix( 'hide_plugin_updates' ), false ) ) {
|
178 |
+
return $oPlugins;
|
179 |
+
}
|
180 |
+
|
181 |
+
if ( isset( $oPlugins->response[ $this->getPluginBaseFile() ] ) ) {
|
182 |
+
unset( $oPlugins->response[ $this->getPluginBaseFile() ] );
|
183 |
+
}
|
184 |
+
return $oPlugins;
|
185 |
+
}
|
186 |
+
|
187 |
+
/**
|
188 |
+
* @return string
|
189 |
+
*/
|
190 |
+
public function getAdminMenuTitle() {
|
191 |
+
return self::$oPluginSpec->getAdminMenuTitle();;
|
192 |
+
}
|
193 |
+
|
194 |
+
/**
|
195 |
+
* @return string
|
196 |
+
*/
|
197 |
+
public function getBasePermissions() {
|
198 |
+
return self::$oPluginSpec->getBasePermissions();
|
199 |
+
}
|
200 |
+
|
201 |
+
/**
|
202 |
+
* @param bool $fCheckUserPermissions
|
203 |
+
* @return bool
|
204 |
+
*/
|
205 |
+
public function getIsValidAdminArea( $fCheckUserPermissions = true ) {
|
206 |
+
if ( $fCheckUserPermissions && !current_user_can( $this->getBasePermissions() ) ) {
|
207 |
+
return false;
|
208 |
+
}
|
209 |
+
|
210 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
211 |
+
if ( !$oWp->isMultisite() && is_admin() ) {
|
212 |
+
return true;
|
213 |
+
}
|
214 |
+
else if ( $oWp->isMultisite() && $this->getIsWpmsNetworkAdminOnly() && is_network_admin() ) {
|
215 |
+
return true;
|
216 |
+
}
|
217 |
+
return false;
|
218 |
+
}
|
219 |
+
|
220 |
+
/**
|
221 |
+
*/
|
222 |
+
protected function doLoadTextDomain() {
|
223 |
+
return load_plugin_textdomain(
|
224 |
+
$this->getTextDomain(),
|
225 |
+
false,
|
226 |
+
plugin_basename( $this->getPath_Languages() )
|
227 |
+
);
|
228 |
+
}
|
229 |
+
|
230 |
+
protected function doPluginFormSubmit() {
|
231 |
+
if ( !$this->getIsPluginFormSubmit() ) {
|
232 |
+
return false;
|
233 |
+
}
|
234 |
+
|
235 |
+
// do all the plugin feature/options saving
|
236 |
+
do_action( $this->doPluginPrefix( 'form_submit' ) );
|
237 |
+
|
238 |
+
if ( $this->getIsPage_PluginAdmin() ) {
|
239 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
240 |
+
$oWp->doRedirect( $oWp->getUrl_CurrentAdminPage() );
|
241 |
+
return true;
|
242 |
+
}
|
243 |
+
}
|
244 |
+
|
245 |
+
/**
|
246 |
+
* @param string $sSuffix
|
247 |
+
* @param string $sGlue
|
248 |
+
* @return string
|
249 |
+
*/
|
250 |
+
public function doPluginPrefix( $sSuffix = '', $sGlue = '-' ) {
|
251 |
+
$sPrefix = $this->getPluginPrefix( $sGlue );
|
252 |
+
|
253 |
+
if ( $sSuffix == $sPrefix || strpos( $sSuffix, $sPrefix.$sGlue ) === 0 ) { //it already has the full prefix
|
254 |
+
return $sSuffix;
|
255 |
+
}
|
256 |
+
|
257 |
+
return sprintf( '%s%s%s', $sPrefix, empty($sSuffix)? '' : $sGlue, empty($sSuffix)? '' : $sSuffix );
|
258 |
+
}
|
259 |
+
|
260 |
+
/**
|
261 |
+
* @param string $sSuffix
|
262 |
+
* @return string
|
263 |
+
*/
|
264 |
+
public function doPluginOptionPrefix( $sSuffix = '' ) {
|
265 |
+
return $this->doPluginPrefix( $sSuffix, '_' );
|
266 |
+
}
|
267 |
+
|
268 |
+
/**
|
269 |
+
* @param string
|
270 |
+
* @return string
|
271 |
+
*/
|
272 |
+
public function getOptionStoragePrefix() {
|
273 |
+
return $this->getPluginPrefix( '_' ).'_';
|
274 |
+
}
|
275 |
+
|
276 |
+
/**
|
277 |
+
* @param string
|
278 |
+
* @return string
|
279 |
+
*/
|
280 |
+
public function getPluginPrefix( $sGlue = '-' ) {
|
281 |
+
return sprintf( '%s%s%s', $this->getParentSlug(), $sGlue, $this->getPluginSlug() );
|
282 |
+
}
|
283 |
+
|
284 |
+
/**
|
285 |
+
* @return string
|
286 |
+
*/
|
287 |
+
public function getHumanName() {
|
288 |
+
return self::$oPluginSpec->getHumanName();
|
289 |
+
}
|
290 |
+
|
291 |
+
/**
|
292 |
+
* @return string
|
293 |
+
*/
|
294 |
+
public function getIsLoggingEnabled() {
|
295 |
+
return self::$oPluginSpec->getIsLoggingEnabled();
|
296 |
+
}
|
297 |
+
|
298 |
+
/**
|
299 |
+
* @return bool
|
300 |
+
*/
|
301 |
+
protected function getIsPage_PluginAdmin() {
|
302 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
303 |
+
return ( strpos( $oWp->getCurrentWpAdminPage(), $this->getPluginPrefix() ) === 0 );
|
304 |
+
}
|
305 |
+
|
306 |
+
/**
|
307 |
+
* @return bool
|
308 |
+
*/
|
309 |
+
protected function getIsPluginFormSubmit() {
|
310 |
+
if ( empty( $_POST ) && empty( $_GET ) ) {
|
311 |
+
return false;
|
312 |
+
}
|
313 |
+
|
314 |
+
$aFormSubmitOptions = array(
|
315 |
+
$this->doPluginOptionPrefix( 'plugin_form_submit' ),
|
316 |
+
'icwp_link_action'
|
317 |
+
);
|
318 |
+
|
319 |
+
$oDp = $this->loadDataProcessor();
|
320 |
+
foreach( $aFormSubmitOptions as $sOption ) {
|
321 |
+
if ( !is_null( $oDp->FetchRequest( $sOption ) ) ) {
|
322 |
+
return true;
|
323 |
+
}
|
324 |
+
}
|
325 |
+
return false;
|
326 |
+
}
|
327 |
+
|
328 |
+
/**
|
329 |
+
* @return string
|
330 |
+
*/
|
331 |
+
public function getIsWpmsNetworkAdminOnly() {
|
332 |
+
return self::$oPluginSpec->getIsWpmsNetworkAdminOnly();
|
333 |
+
}
|
334 |
+
|
335 |
+
/**
|
336 |
+
* @return string
|
337 |
+
*/
|
338 |
+
public function getParentSlug() {
|
339 |
+
return self::$oPluginSpec->getParentSlug();
|
340 |
+
}
|
341 |
+
|
342 |
+
/**
|
343 |
+
* This is the path to the main plugin file relative to the WordPress plugins directory.
|
344 |
+
*
|
345 |
+
* @return string
|
346 |
+
*/
|
347 |
+
public function getPluginBaseFile() {
|
348 |
+
if ( !isset( $this->sPluginBaseFile ) ) {
|
349 |
+
$this->sPluginBaseFile = plugin_basename( $this->getRootFile() );
|
350 |
+
}
|
351 |
+
return $this->sPluginBaseFile;
|
352 |
+
}
|
353 |
+
|
354 |
+
/**
|
355 |
+
* @return string
|
356 |
+
*/
|
357 |
+
public function getPluginSlug() {
|
358 |
+
return self::$oPluginSpec->getPluginSlug();
|
359 |
+
}
|
360 |
+
|
361 |
+
/**
|
362 |
+
* @param string $sPath
|
363 |
+
* @return string
|
364 |
+
*/
|
365 |
+
public function getPluginUrl( $sPath = '' ) {
|
366 |
+
if ( empty( $this->sPluginUrl ) ) {
|
367 |
+
$this->sPluginUrl = plugins_url( '/', $this->getRootFile() );
|
368 |
+
}
|
369 |
+
return $this->sPluginUrl.$sPath;
|
370 |
+
}
|
371 |
+
|
372 |
+
/**
|
373 |
+
* @param string $sCss
|
374 |
+
* @return string
|
375 |
+
*/
|
376 |
+
public function getPluginUrl_Css( $sCss ) {
|
377 |
+
return $this->getPluginUrl( 'resources/css/'.$sCss );
|
378 |
+
}
|
379 |
+
|
380 |
+
/**
|
381 |
+
* @param string $sImage
|
382 |
+
* @return string
|
383 |
+
*/
|
384 |
+
public function getPluginUrl_Image( $sImage ) {
|
385 |
+
return $this->getPluginUrl( 'resources/images/'.$sImage );
|
386 |
+
}
|
387 |
+
|
388 |
+
/**
|
389 |
+
* @param string $sJs
|
390 |
+
* @return string
|
391 |
+
*/
|
392 |
+
public function getPluginUrl_Js( $sJs ) {
|
393 |
+
return $this->getPluginUrl( 'resources/js/'.$sJs );
|
394 |
+
}
|
395 |
+
|
396 |
+
/**
|
397 |
+
* @param string $sFeature
|
398 |
+
* @return string
|
399 |
+
*/
|
400 |
+
public function getPluginUrl_AdminPage( $sFeature = '' ) {
|
401 |
+
return network_admin_url( sprintf( 'admin.php?page=%s', $this->doPluginPrefix( $sFeature ) ) );
|
402 |
+
}
|
403 |
+
|
404 |
+
/**
|
405 |
+
* get the root directory for the plugin with the trailing slash
|
406 |
+
*
|
407 |
+
* @return string
|
408 |
+
*/
|
409 |
+
public function getPath_Languages() {
|
410 |
+
return $this->getRootDir().'languages'.ICWP_DS;
|
411 |
+
}
|
412 |
+
|
413 |
+
/**
|
414 |
+
* get the root directory for the plugin with the trailing slash
|
415 |
+
*
|
416 |
+
* @return string
|
417 |
+
*/
|
418 |
+
public function getRootDir() {
|
419 |
+
return dirname( $this->getRootFile() ).ICWP_DS;
|
420 |
+
}
|
421 |
+
|
422 |
+
/**
|
423 |
+
* @return string
|
424 |
+
*/
|
425 |
+
public function getRootFile() {
|
426 |
+
return self::$oPluginSpec->getRootFile();
|
427 |
+
}
|
428 |
+
|
429 |
+
/**
|
430 |
+
* Get the directory for the plugin source files with the trailing slash
|
431 |
+
*
|
432 |
+
* @param string $sSourceFile
|
433 |
+
* @return string
|
434 |
+
*/
|
435 |
+
public function getSourceDir( $sSourceFile = '' ) {
|
436 |
+
return $this->getRootDir().self::SrcDir.ICWP_DS.$sSourceFile;
|
437 |
+
}
|
438 |
+
|
439 |
+
/**
|
440 |
+
* @return string
|
441 |
+
*/
|
442 |
+
public function getTextDomain() {
|
443 |
+
return self::$oPluginSpec->getTextDomain();
|
444 |
+
}
|
445 |
+
|
446 |
+
/**
|
447 |
+
* @return string
|
448 |
+
*/
|
449 |
+
public function getVersion() {
|
450 |
+
return self::$oPluginSpec->getVersion();
|
451 |
+
}
|
452 |
+
|
453 |
+
/**
|
454 |
+
* get the directory for the plugin view with the trailing slash
|
455 |
+
*
|
456 |
+
* @return string
|
457 |
+
*/
|
458 |
+
public function getViewDir() {
|
459 |
+
return $this->getRootDir().self::ViewDir.ICWP_DS;
|
460 |
+
}
|
461 |
+
|
462 |
+
/**
|
463 |
+
* Retrieve the full path to the plugin view
|
464 |
+
*
|
465 |
+
* @param string $sView
|
466 |
+
* @return string
|
467 |
+
*/
|
468 |
+
public function getViewPath( $sView ) {
|
469 |
+
return $this->getViewDir().$sView.'.php';
|
470 |
+
}
|
471 |
+
|
472 |
+
/**
|
473 |
+
* @param string $sSnippet
|
474 |
+
* @return string
|
475 |
+
*/
|
476 |
+
public function getViewSnippet( $sSnippet ) {
|
477 |
+
return $this->getViewDir().'snippets'.ICWP_DS.$sSnippet.'.php';
|
478 |
+
}
|
479 |
+
}
|
icwp-wpsf-main.php
CHANGED
@@ -1,5 +1,4 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
/**
|
4 |
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
5 |
* All rights reserved.
|
@@ -21,459 +20,407 @@
|
|
21 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
22 |
*/
|
23 |
|
24 |
-
require_once( dirname(__FILE__).'
|
25 |
-
require_once( dirname(__FILE__).'/src/icwp-data-processor.php' );
|
26 |
-
|
27 |
-
if ( !function_exists( '_wpsf_e' ) ) {
|
28 |
-
function _wpsf_e( $insStr ) {
|
29 |
-
_e( $insStr, 'wp-simple-firewall' );
|
30 |
-
}
|
31 |
-
}
|
32 |
-
if ( !function_exists( '_wpsf__' ) ) {
|
33 |
-
function _wpsf__( $insStr ) {
|
34 |
-
return __( $insStr, 'wp-simple-firewall' );
|
35 |
-
}
|
36 |
-
}
|
37 |
|
38 |
if ( !class_exists('ICWP_Wordpress_Simple_Firewall') ):
|
39 |
|
40 |
-
class ICWP_Wordpress_Simple_Firewall extends
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
public function onWpActivatePlugin() {
|
105 |
-
$this->loadAllFeatures( true, true );
|
106 |
-
}
|
107 |
-
|
108 |
-
/**
|
109 |
-
* @param bool $fRecreate
|
110 |
-
* @param bool $fFullBuild
|
111 |
-
* @return bool
|
112 |
-
*/
|
113 |
-
protected function loadAllFeatures( $fRecreate = false, $fFullBuild = false ) {
|
114 |
-
foreach( $this->oPluginVo->getFeatures() as $sFeature ) {
|
115 |
-
$fSuccess = $this->loadFeatureHandler( $sFeature, $fRecreate, $fFullBuild );
|
116 |
}
|
117 |
-
return $fSuccess;
|
118 |
-
}
|
119 |
|
120 |
-
|
121 |
-
|
122 |
-
return false;
|
123 |
}
|
124 |
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
|
|
|
|
|
|
130 |
}
|
131 |
-
$sSourceFile = $this->oPluginVo->getSourceDir().'icwp-optionshandler-'.$sFeatureSlug.'.php'; // e.g. icwp-optionshandler-plugin.php
|
132 |
-
$sClassName = 'ICWP_WPSF_FeatureHandler_'.$sFeatureName; // e.g. ICWP_WPSF_FeatureHandler_Plugin
|
133 |
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
140 |
}
|
141 |
-
return $this->{$sOptionsVarName};
|
142 |
-
}
|
143 |
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
}
|
153 |
|
154 |
-
|
155 |
-
|
156 |
-
* @return array $aItems
|
157 |
-
*/
|
158 |
-
public function filter_addExtraAdminMenuItems( $aItems ) {
|
159 |
-
$aItems[ _wpsf__('Firewall Log' ) ] = array( 'Firewall Log', $this->getSubmenuId('firewall_log'), array( $this, 'onDisplayAll' ) );
|
160 |
-
return $aItems;
|
161 |
-
}
|
162 |
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
*/
|
167 |
-
public function onDisplayAll() {
|
168 |
|
169 |
-
|
170 |
-
$
|
171 |
-
return;
|
172 |
-
}
|
173 |
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
case 'privacy_protect_log' :
|
183 |
-
$this->onDisplayPrivacyProtectLog();
|
184 |
-
break;
|
185 |
-
case 'firewall_log' :
|
186 |
-
$this->onDisplayFirewallLog();
|
187 |
-
break;
|
188 |
-
default:
|
189 |
-
$this->getFeatureHandler_MainPlugin()->displayFeatureConfigPage();
|
190 |
-
break;
|
191 |
}
|
192 |
-
}
|
193 |
-
|
194 |
-
/**
|
195 |
-
* @param string $sSubmenu
|
196 |
-
* @return array
|
197 |
-
*/
|
198 |
-
protected function getBaseDisplayData( $sSubmenu = '' ) {
|
199 |
-
$aBaseData = parent::getBaseDisplayData( $sSubmenu );
|
200 |
-
$aBaseData['aMainOptions'] = $this->oPluginOptions->getPluginOptionsValues();
|
201 |
-
return $aBaseData;
|
202 |
-
}
|
203 |
|
204 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
205 |
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
$this->display( $this->doPluginPrefix( 'privacy_protect_log_index', '_' ), $aData );
|
212 |
-
}
|
213 |
|
214 |
-
|
|
|
|
|
|
|
215 |
|
216 |
-
|
217 |
-
|
218 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
219 |
|
220 |
-
|
221 |
-
$aLogData = $oLoggingProcessor->getLogs( true );
|
222 |
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
}
|
231 |
|
232 |
-
|
233 |
-
parent::onWpAdminInit();
|
234 |
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
$this->updateVersionUserMeta();
|
240 |
-
if ( $this->isShowMarketing() ) {
|
241 |
-
wp_redirect( $this->getUrl_PluginDashboard() );
|
242 |
-
}
|
243 |
-
else {
|
244 |
-
wp_redirect( network_admin_url( $_POST['redirect_page'] ) );
|
245 |
-
}
|
246 |
}
|
247 |
|
248 |
-
$
|
249 |
-
if ( $
|
250 |
-
$
|
251 |
-
wp_redirect( network_admin_url( $_POST['redirect_page'] ) );
|
252 |
}
|
253 |
|
254 |
-
$
|
255 |
-
|
256 |
-
$
|
257 |
-
|
|
|
|
|
|
|
|
|
258 |
}
|
259 |
-
}
|
260 |
|
261 |
-
|
262 |
-
* @return bool
|
263 |
-
*/
|
264 |
-
protected function isShowMarketing() {
|
265 |
-
return apply_filters( $this->doPluginPrefix( 'show_marketing' ), true );
|
266 |
-
}
|
267 |
|
268 |
-
|
269 |
-
|
270 |
-
}
|
271 |
|
272 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
273 |
|
274 |
-
|
275 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
276 |
}
|
277 |
|
278 |
-
|
279 |
-
|
280 |
-
$sRedirectPage = 'index.php';
|
281 |
-
ob_start(); ?>
|
282 |
-
<style>
|
283 |
-
a#fromIcwp { padding: 0 5px; border-bottom: 1px dashed rgba(0,0,0,0.1); color: blue; font-weight: bold; }
|
284 |
-
</style>
|
285 |
-
<form id="IcwpTranslationsNotice" method="post" action="admin.php?page=<?php echo $this->getSubmenuId('firewall'); ?>&<?php echo $sMetaFlag; ?>=1">
|
286 |
-
<input type="hidden" value="<?php echo $sRedirectPage; ?>" name="redirect_page" id="redirect_page">
|
287 |
-
<input type="hidden" value="1" name="<?php echo $sMetaFlag; ?>" id="<?php echo $sMetaFlag; ?>">
|
288 |
-
<h4 style="margin:10px 0 3px;">
|
289 |
-
<?php _wpsf_e( 'Would you like to help translate the WordPress Simple Firewall into your language?' ); ?>
|
290 |
-
<?php printf( _wpsf__( 'Head over to: %s' ), '<a href="http://translate.icontrolwp.com" target="_blank">translate.icontrolwp.com</a>' ); ?>
|
291 |
-
</h4>
|
292 |
-
<input type="submit" value="<?php _wpsf_e( 'Dismiss this notice' ); ?>" name="submit" class="button" style="float:left; margin-bottom:10px;">
|
293 |
-
<div style="clear:both;"></div>
|
294 |
-
</form>
|
295 |
-
<?php
|
296 |
-
$sNotice = ob_get_contents();
|
297 |
-
ob_end_clean();
|
298 |
-
return $sNotice;
|
299 |
-
}
|
300 |
|
301 |
-
|
|
|
|
|
302 |
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
|
|
|
|
|
|
307 |
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
<style>a#fromIcwp { padding: 0 5px; border-bottom: 1px dashed rgba(0,0,0,0.1); color: blue; font-weight: bold; }</style>
|
313 |
-
<form id="IcwpUpdateNotice" method="post" action="admin.php?page=<?php echo $this->getSubmenuId('firewall'); ?>&<?php echo $sMetaFlag; ?>=1">
|
314 |
-
<input type="hidden" value="<?php echo $sRedirectPage; ?>" name="redirect_page" id="redirect_page">
|
315 |
-
<input type="hidden" value="1" name="<?php echo $sMetaFlag; ?>" id="<?php echo $sMetaFlag; ?>">
|
316 |
-
<p>
|
317 |
-
<?php _wpsf_e( 'Note: WordPress Simple Firewall plugin does not automatically turn on when you install/update.' ); ?>
|
318 |
-
<?php printf( _wpsf__( 'There may also be %simportant updates to read about%s.' ), '<a href="http://icwp.io/27" id="fromIcwp" title="'._wpsf__( 'WordPress Simple Firewall' ).'" target="_blank">', '</a>' ); ?>
|
319 |
-
</p>
|
320 |
-
</h4>
|
321 |
-
<input type="submit" value="<?php _wpsf_e( 'Okay, show me the dashboard' ); ?>" name="submit" class="button" style="float:left; margin-bottom:10px;">
|
322 |
-
<div style="clear:both;"></div>
|
323 |
-
</form>
|
324 |
-
<?php
|
325 |
-
$sNotice = ob_get_contents();
|
326 |
-
ob_end_clean();
|
327 |
-
return $sNotice;
|
328 |
-
}
|
329 |
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
|
|
334 |
|
335 |
-
|
336 |
-
|
337 |
-
|
|
|
|
|
338 |
}
|
339 |
-
$sMetaFlag = $this->doPluginPrefix( 'hide_mailing_list_signup' );
|
340 |
-
|
341 |
-
ob_start(); ?>
|
342 |
-
<!-- Begin MailChimp Signup Form -->
|
343 |
-
<div id="mc_embed_signup">
|
344 |
-
<form class="form form-inline" action="http://hostliketoast.us2.list-manage1.com/subscribe/post?u=e736870223389e44fb8915c9a&id=0e1d527259" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
|
345 |
-
<p>The WordPress Simple Firewall team has launched a education initiative to raise awareness of WordPress security and to provide further help with the WordPress Simple Firewall plugin. Get Involved here:</p>
|
346 |
-
<input type="text" value="" name="EMAIL" class="required email" id="mce-EMAIL" placeholder="Your Email" />
|
347 |
-
<input type="text" value="" name="FNAME" class="" id="mce-FNAME" placeholder="Your Name" />
|
348 |
-
<input type="hidden" value="<?php echo $nDays; ?>" name="DAYS" class="" id="mce-DAYS" />
|
349 |
-
<input type="submit" value="Get The News" name="subscribe" id="mc-embedded-subscribe" class="button" />
|
350 |
-
<a href="<?php echo $this->getUrl_PluginDashboard().'&'.$sMetaFlag.'=1';?>">Dismiss</a>
|
351 |
-
<div id="mce-responses" class="clear">
|
352 |
-
<div class="response" id="mce-error-response" style="display:none"></div>
|
353 |
-
<div class="response" id="mce-success-response" style="display:none"></div>
|
354 |
-
</div> <!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups-->
|
355 |
-
<div style="position: absolute; left: -5000px;"><input type="text" name="b_e736870223389e44fb8915c9a_0e1d527259" tabindex="-1" value=""></div>
|
356 |
-
<div class="clear"></div>
|
357 |
-
</form>
|
358 |
-
</div>
|
359 |
-
|
360 |
-
<!--End mc_embed_signup-->
|
361 |
-
<?php
|
362 |
-
$sNotice = ob_get_contents();
|
363 |
-
ob_end_clean();
|
364 |
-
return $sNotice;
|
365 |
-
}
|
366 |
|
367 |
-
|
368 |
-
|
369 |
-
if ( !empty( $sAdminFeedbackNotice ) ) {
|
370 |
-
$sNotice = '<p>'.$sAdminFeedbackNotice.'</p>';
|
371 |
-
return $sNotice;
|
372 |
-
$this->oPluginOptions->setOpt( 'feedback_admin_notice', '' );
|
373 |
}
|
374 |
-
}
|
375 |
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
|
|
|
|
390 |
}
|
391 |
-
return round( ( time() - $nTimeInstalled ) / DAY_IN_SECONDS );
|
392 |
-
}
|
393 |
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
403 |
|
404 |
-
|
405 |
-
|
406 |
-
|
|
|
|
|
407 |
}
|
408 |
-
}
|
409 |
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
|
|
430 |
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
|
|
476 |
}
|
477 |
-
}
|
478 |
|
479 |
endif;
|
|
|
|
|
|
1 |
<?php
|
|
|
2 |
/**
|
3 |
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
* All rights reserved.
|
20 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
21 |
*/
|
22 |
|
23 |
+
require_once( dirname(__FILE__).ICWP_DS.'src'.ICWP_DS.'icwp-pure-base.php' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
|
25 |
if ( !class_exists('ICWP_Wordpress_Simple_Firewall') ):
|
26 |
|
27 |
+
class ICWP_Wordpress_Simple_Firewall extends ICWP_Pure_Base_V6 {
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @var ICWP_WPSF_FeatureHandler_Plugin
|
31 |
+
*/
|
32 |
+
protected $oFeatureHandlerPlugin;
|
33 |
+
/**
|
34 |
+
* @var ICWP_WPSF_FeatureHandler_AdminAccessRestriction
|
35 |
+
*/
|
36 |
+
protected $oFeatureHandlerAdminAccessRestriction;
|
37 |
+
/**
|
38 |
+
* @var ICWP_WPSF_FeatureHandler_Firewall
|
39 |
+
*/
|
40 |
+
protected $oFeatureHandlerFirewall;
|
41 |
+
/**
|
42 |
+
* @var ICWP_WPSF_FeatureHandler_LoginProtect
|
43 |
+
*/
|
44 |
+
protected $oFeatureHandlerLoginProtect;
|
45 |
+
|
46 |
+
/**
|
47 |
+
* @var ICWP_WPSF_FeatureHandler_PrivacyProtect
|
48 |
+
*/
|
49 |
+
protected $oFeatureHandlerPrivacyProtect;
|
50 |
+
|
51 |
+
/**
|
52 |
+
* @var ICWP_WPSF_FeatureHandler_AuditTrail
|
53 |
+
*/
|
54 |
+
protected $oFeatureHandlerAuditTrail;
|
55 |
+
|
56 |
+
/**
|
57 |
+
* @var ICWP_WPSF_FeatureHandler_CommentsFilter
|
58 |
+
*/
|
59 |
+
protected $oFeatureHandlerCommentsFilter;
|
60 |
+
|
61 |
+
/**
|
62 |
+
* @var ICWP_WPSF_FeatureHandler_Lockdown
|
63 |
+
*/
|
64 |
+
protected $oFeatureHandlerLockdown;
|
65 |
+
|
66 |
+
/**
|
67 |
+
* @var ICWP_WPSF_FeatureHandler_Autoupdates
|
68 |
+
*/
|
69 |
+
protected $oFeatureHandlerAutoupdates;
|
70 |
+
|
71 |
+
/**
|
72 |
+
* @var ICWP_WPSF_FeatureHandler_Email
|
73 |
+
*/
|
74 |
+
protected $oFeatureHandlerEmail;
|
75 |
+
|
76 |
+
/**
|
77 |
+
* @var ICWP_WPSF_FeatureHandler_Logging
|
78 |
+
*/
|
79 |
+
protected $oFeatureHandlerLogging;
|
80 |
+
|
81 |
+
/**
|
82 |
+
*/
|
83 |
+
public function __construct( ICWP_WPSF_Plugin_Controller $oPluginVo ) {
|
84 |
+
parent::__construct( $oPluginVo );
|
85 |
+
|
86 |
+
$this->loadAllFeatures();
|
87 |
+
add_filter( $this->doPluginPrefix( 'has_permission_to_view' ), array( $this, 'hasPermissionToView' ) );
|
88 |
+
add_filter( $this->doPluginPrefix( 'has_permission_to_submit' ), array( $this, 'hasPermissionToSubmit' ) );
|
89 |
+
add_filter( $this->doPluginPrefix( 'plugin_update_message' ), array( $this, 'getPluginsListUpdateMessage' ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
90 |
}
|
|
|
|
|
91 |
|
92 |
+
public function onWpActivatePlugin() {
|
93 |
+
$this->loadAllFeatures( true, true );
|
|
|
94 |
}
|
95 |
|
96 |
+
/**
|
97 |
+
* @return ICWP_WPSF_FeatureHandler_Plugin
|
98 |
+
*/
|
99 |
+
protected function loadCorePluginFeature() {
|
100 |
+
if ( isset( $this->oPluginOptions ) ) {
|
101 |
+
return $this->oPluginOptions;
|
102 |
+
}
|
103 |
+
return $this->loadFeatureHandler( 'plugin' );
|
104 |
}
|
|
|
|
|
105 |
|
106 |
+
/**
|
107 |
+
* @param bool $fRecreate
|
108 |
+
* @param bool $fFullBuild
|
109 |
+
* @return bool
|
110 |
+
*/
|
111 |
+
protected function loadAllFeatures( $fRecreate = false, $fFullBuild = false ) {
|
112 |
+
|
113 |
+
$oMainPluginFeature = $this->loadCorePluginFeature();
|
114 |
+
$aPluginFeatures = $oMainPluginFeature->getActivePluginFeatures();
|
115 |
+
|
116 |
+
$fSuccess = true;
|
117 |
+
foreach( $aPluginFeatures as $sSlug => $sStorageKey ) {
|
118 |
+
try {
|
119 |
+
$this->loadFeatureHandler( $sSlug, $fRecreate, $fFullBuild );
|
120 |
+
$fSuccess = true;
|
121 |
+
}
|
122 |
+
catch( Exception $oE ) {
|
123 |
+
wp_die( $oE->getMessage() );
|
124 |
+
}
|
125 |
+
}
|
126 |
+
return $fSuccess;
|
127 |
}
|
|
|
|
|
128 |
|
129 |
+
/**
|
130 |
+
* @param string $sFeatureSlug
|
131 |
+
* @param bool $fRecreate
|
132 |
+
* @param bool $fFullBuild
|
133 |
+
* @return mixed
|
134 |
+
* @throws Exception
|
135 |
+
*/
|
136 |
+
protected function loadFeatureHandler( $sFeatureSlug, $fRecreate = false, $fFullBuild = false ) {
|
|
|
137 |
|
138 |
+
$sFeatureName = str_replace( ' ', '', ucwords( str_replace( '_', ' ', $sFeatureSlug ) ) );
|
139 |
+
$sOptionsVarName = sprintf( 'oFeatureHandler%s', $sFeatureName ); // e.g. oFeatureHandlerOptions
|
|
|
|
|
|
|
|
|
|
|
|
|
140 |
|
141 |
+
if ( isset( $this->{$sOptionsVarName} ) ) {
|
142 |
+
return $this->{$sOptionsVarName};
|
143 |
+
}
|
|
|
|
|
144 |
|
145 |
+
$sSourceFile = $this->getController()->getSourceDir( sprintf( 'icwp-optionshandler-%s.php', $sFeatureSlug ) ); // e.g. icwp-optionshandler-plugin.php
|
146 |
+
$sClassName = sprintf( 'ICWP_WPSF_FeatureHandler_%s', $sFeatureName ); // e.g. ICWP_WPSF_FeatureHandler_Plugin
|
|
|
|
|
147 |
|
148 |
+
require_once( $sSourceFile );
|
149 |
+
if ( $fRecreate || !isset( $this->{$sOptionsVarName} ) ) {
|
150 |
+
$this->{$sOptionsVarName} = new $sClassName( $this->getController() );
|
151 |
+
}
|
152 |
+
if ( $fFullBuild ) {
|
153 |
+
$this->{$sOptionsVarName}->buildOptions();
|
154 |
+
}
|
155 |
+
return $this->{$sOptionsVarName};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
156 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
157 |
|
158 |
+
/**
|
159 |
+
* @param array $aItems
|
160 |
+
* @return array $aItems
|
161 |
+
*/
|
162 |
+
public function filter_addExtraAdminMenuItems( $aItems ) {
|
163 |
+
$aItems[ _wpsf__('Firewall Log' ) ] = array( 'Firewall Log', $this->doPluginPrefix('firewall_log'), array( $this, 'onDisplayAll' ) );
|
164 |
+
// $aItems[ _wpsf__('Audit Trail Viewer' ) ] = array( 'Audit Trail Viewer', $this->doPluginPrefix('audit_trail_viewer'), array( $this, 'onDisplayAll' ) );
|
165 |
+
return $aItems;
|
166 |
+
}
|
167 |
|
168 |
+
/**
|
169 |
+
* Displaying all views now goes through this central function and we work out
|
170 |
+
* what to display based on the name of current hook/filter being processed.
|
171 |
+
*/
|
172 |
+
public function onDisplayAll() {
|
|
|
|
|
173 |
|
174 |
+
if ( !$this->hasPermissionToView() ) {
|
175 |
+
$this->onDisplayAccessKeyRequest();
|
176 |
+
return;
|
177 |
+
}
|
178 |
|
179 |
+
// Just to ensure the nag bar disappears if/when they visit the dashboard
|
180 |
+
// regardless of clicking the button.
|
181 |
+
$this->updateVersionUserMeta();
|
182 |
+
|
183 |
+
$sPrefix = str_replace(' ', '-', strtolower( $this->getController()->getAdminMenuTitle() ) ) .'_page_'.$this->getPluginPrefix().'-';
|
184 |
+
$sCurrent = str_replace( $sPrefix, '', current_filter() );
|
185 |
+
|
186 |
+
switch( $sCurrent ) {
|
187 |
+
case 'privacy_protect_log' :
|
188 |
+
$this->onDisplayPrivacyProtectLog();
|
189 |
+
break;
|
190 |
+
case 'firewall_log' :
|
191 |
+
$this->onDisplayFirewallLog();
|
192 |
+
break;
|
193 |
+
case 'audit_trail_viewer' :
|
194 |
+
$this->onDisplayAuditTrailViewer();
|
195 |
+
break;
|
196 |
+
default:
|
197 |
+
$this->getFeatureHandler_MainPlugin()->displayFeatureConfigPage();
|
198 |
+
break;
|
199 |
+
}
|
200 |
+
}
|
201 |
|
202 |
+
protected function onDisplayPrivacyProtectLog() {
|
|
|
203 |
|
204 |
+
$oPrivacyProcessor = $this->getProcessor_PrivacyProtect();
|
205 |
+
$aData = array(
|
206 |
+
'urlrequests_log' => $oPrivacyProcessor->getLogs( true )
|
207 |
+
);
|
208 |
+
$aData = array_merge( $this->getBaseDisplayData(), $aData );
|
209 |
+
$this->display( $this->doPluginPrefix( 'privacy_protect_log_index' ), $aData );
|
210 |
+
}
|
|
|
211 |
|
212 |
+
protected function onDisplayFirewallLog() {
|
|
|
213 |
|
214 |
+
$oFirewallHandler = $this->loadFeatureHandler( 'firewall' );
|
215 |
+
if ( $oFirewallHandler instanceof ICWP_WPSF_FeatureHandler_Firewall ) {
|
216 |
+
$aIpWhitelist = $oFirewallHandler->getOpt( 'ips_whitelist' );
|
217 |
+
$aIpBlacklist = $oFirewallHandler->getOpt( 'ips_blacklist' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
218 |
}
|
219 |
|
220 |
+
$oLoggingProcessor = $this->getProcessor_Logging();
|
221 |
+
if ( $oLoggingProcessor instanceof ICWP_WPSF_Processor_Logging ) {
|
222 |
+
$aLogData = $oLoggingProcessor->getLogs( true );
|
|
|
223 |
}
|
224 |
|
225 |
+
$aData = array(
|
226 |
+
'sFeatureName' => _wpsf__('Firewall Log'),
|
227 |
+
'firewall_log' => $aLogData,
|
228 |
+
'ip_whitelist' => isset( $aIpWhitelist['ips'] )? $aIpWhitelist['ips'] : array(),
|
229 |
+
'ip_blacklist' => isset( $aIpBlacklist['ips'] )? $aIpBlacklist['ips'] : array(),
|
230 |
+
);
|
231 |
+
$aData = array_merge( $this->getBaseDisplayData(), $aData );
|
232 |
+
$this->display( $this->doPluginPrefix( 'firewall_log_index' ), $aData );
|
233 |
}
|
|
|
234 |
|
235 |
+
protected function onDisplayAuditTrailViewer() {
|
|
|
|
|
|
|
|
|
|
|
236 |
|
237 |
+
$oAuditTrail = $this->getProcessor_AuditTrail();
|
238 |
+
$aAuditData = $oAuditTrail->getAllAuditEntries();
|
|
|
239 |
|
240 |
+
$aAuditDataUsers = array();
|
241 |
+
$aAuditDataPlugins = array();
|
242 |
+
$aAuditDataThemes = array();
|
243 |
+
$aAuditDataWordpress = array();
|
244 |
+
$aAuditDataPosts = array();
|
245 |
+
foreach( $aAuditData as $aAudit ) {
|
246 |
+
if ( $aAudit['context'] == 'users' ) {
|
247 |
+
$aAuditDataUsers[] = $aAudit;
|
248 |
+
}
|
249 |
+
if ( $aAudit['context'] == 'plugins' ) {
|
250 |
+
$aAuditDataPlugins[] = $aAudit;
|
251 |
+
}
|
252 |
+
if ( $aAudit['context'] == 'themes' ) {
|
253 |
+
$aAuditDataThemes[] = $aAudit;
|
254 |
+
}
|
255 |
+
if ( $aAudit['context'] == 'wordpress' ) {
|
256 |
+
$aAuditDataWordpress[] = $aAudit;
|
257 |
+
}
|
258 |
+
if ( $aAudit['context'] == 'posts' ) {
|
259 |
+
$aAuditDataPosts[] = $aAudit;
|
260 |
+
}
|
261 |
+
}
|
262 |
|
263 |
+
$aData = array(
|
264 |
+
'sFeatureName' => _wpsf__('Audit Trail Viewer'),
|
265 |
+
'aAuditDataUsers' => $aAuditDataUsers,
|
266 |
+
'aAuditDataPlugins' => $aAuditDataPlugins,
|
267 |
+
'aAuditDataThemes' => $aAuditDataThemes,
|
268 |
+
'aAuditDataWordpress' => $aAuditDataWordpress,
|
269 |
+
'aAuditDataPosts' => $aAuditDataPosts
|
270 |
+
);
|
271 |
+
$aData = array_merge( $this->getBaseDisplayData(), $aData );
|
272 |
+
$this->display( $this->doPluginPrefix( 'audit_trail_viewer_index' ), $aData );
|
273 |
}
|
274 |
|
275 |
+
public function onWpAdminInit() {
|
276 |
+
parent::onWpAdminInit();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
277 |
|
278 |
+
if ( $this->getController()->getIsValidAdminArea() ) {
|
279 |
+
$oDp = $this->loadDataProcessor();
|
280 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
281 |
|
282 |
+
$sRedirect = $oDp->FetchPost( 'redirect_page' );
|
283 |
+
$sRedirect = empty( $sRedirect ) ? $this->getController()->getPluginUrl_AdminPage() : $sRedirect;
|
284 |
+
//Someone clicked the button to acknowledge the update
|
285 |
+
if ( $oDp->FetchRequest( $this->doPluginPrefix( 'hide_update_notice' ) ) == 1 ) {
|
286 |
+
$this->updateVersionUserMeta();
|
287 |
+
$oWp->doRedirect( $sRedirect );
|
288 |
+
}
|
289 |
|
290 |
+
if ( $oDp->FetchRequest( $this->doPluginPrefix( 'hide_translation_notice' ) ) == 1 ) {
|
291 |
+
$this->updateTranslationNoticeShownUserMeta();
|
292 |
+
$oWp->doRedirect( $sRedirect );
|
293 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
294 |
|
295 |
+
if ( $oDp->FetchRequest( $this->doPluginPrefix( 'hide_mailing_list_signup' ) ) == 1 ) {
|
296 |
+
$this->updateMailingListSignupShownUserMeta();
|
297 |
+
}
|
298 |
+
}
|
299 |
+
}
|
300 |
|
301 |
+
/**
|
302 |
+
* @return bool
|
303 |
+
*/
|
304 |
+
protected function isShowMarketing() {
|
305 |
+
return apply_filters( $this->doPluginPrefix( 'show_marketing' ), true );
|
306 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
307 |
|
308 |
+
public function getPluginsListUpdateMessage( $sMessage ) {
|
309 |
+
return _wpsf__( 'Upgrade Now To Keep Your Firewall Up-To-Date With The Latest Features.' );
|
|
|
|
|
|
|
|
|
310 |
}
|
|
|
311 |
|
312 |
+
/**
|
313 |
+
* @return bool
|
314 |
+
*/
|
315 |
+
protected function getShowAdminNotices() {
|
316 |
+
return $this->loadCorePluginFeature()->getOpt( 'enable_upgrade_admin_notice' ) == 'Y';
|
317 |
+
}
|
318 |
|
319 |
+
/**
|
320 |
+
* @return int
|
321 |
+
*/
|
322 |
+
protected function getInstallationDays() {
|
323 |
+
$nTimeInstalled = $this->loadCorePluginFeature()->getOpt( 'installation_time' );
|
324 |
+
if ( empty($nTimeInstalled) ) {
|
325 |
+
return 0;
|
326 |
+
}
|
327 |
+
return round( ( time() - $nTimeInstalled ) / DAY_IN_SECONDS );
|
328 |
}
|
|
|
|
|
329 |
|
330 |
+
protected function getAdminBarNodes() {
|
331 |
+
return array(); //disabled for now
|
332 |
+
$aMenu = array(
|
333 |
+
'id' => $this->doPluginOptionPrefix( 'admin_menu' ),
|
334 |
+
'title' => '<span class="pluginlogo_16"> </span>'._wpsf__('Firewall').'',
|
335 |
+
'href' => 'bob',
|
336 |
+
);
|
337 |
+
return array( $aMenu );
|
338 |
+
}
|
339 |
+
|
340 |
+
public function onWpDeactivatePlugin() {
|
341 |
+
if ( $this->getFeatureHandler_MainPlugin()->getOpt( 'delete_on_deactivate' ) == 'Y' && current_user_can( $this->getController()->getBasePermissions() ) ) {
|
342 |
+
do_action( $this->doPluginPrefix( 'delete_plugin' ) );
|
343 |
+
}
|
344 |
+
}
|
345 |
|
346 |
+
/**
|
347 |
+
* @return ICWP_WPSF_FeatureHandler_Plugin|null
|
348 |
+
*/
|
349 |
+
public function getFeatureHandler_MainPlugin() {
|
350 |
+
return $this->loadFeatureHandler( 'plugin' );
|
351 |
}
|
|
|
352 |
|
353 |
+
/**
|
354 |
+
* @return ICWP_WPSF_FeatureHandler_AdminAccessRestriction|null
|
355 |
+
*/
|
356 |
+
public function getFeatureHandler_AdminAccessRestriction() {
|
357 |
+
return $this->loadFeatureHandler( 'admin_access_restriction' );
|
358 |
+
}
|
359 |
|
360 |
+
/**
|
361 |
+
* @return ICWP_WPSF_FeatureHandler_AdminAccessRestriction|null
|
362 |
+
*/
|
363 |
+
public function getProcessor_AdminAccessRestriction() {
|
364 |
+
return $this->getFeatureHandler_AdminAccessRestriction()->getProcessor();
|
365 |
+
}
|
366 |
|
367 |
+
/**
|
368 |
+
* @return ICWP_WPSF_Processor_Firewall|null
|
369 |
+
*/
|
370 |
+
public function getProcessor_Firewall() {
|
371 |
+
$this->loadFeatureHandler( 'firewall' );
|
372 |
+
return $this->oFeatureHandlerFirewall->getProcessor();
|
373 |
+
}
|
374 |
|
375 |
+
/**
|
376 |
+
* @return ICWP_WPSF_Processor_LoginProtect|null
|
377 |
+
*/
|
378 |
+
public function getProcessor_LoginProtect() {
|
379 |
+
$this->loadFeatureHandler( 'login_protect' );
|
380 |
+
return $this->oFeatureHandlerLoginProtect->getProcessor();
|
381 |
+
}
|
382 |
|
383 |
+
/**
|
384 |
+
* @return ICWP_WPSF_Processor_Autoupdates|null
|
385 |
+
*/
|
386 |
+
public function getProcessor_Autoupdates() {
|
387 |
+
$this->loadFeatureHandler( 'autoupdates' );
|
388 |
+
return $this->oFeatureHandlerAutoupdates->getProcessor();
|
389 |
+
}
|
390 |
|
391 |
+
/**
|
392 |
+
* @return ICWP_WPSF_Processor_PrivacyProtect|null
|
393 |
+
*/
|
394 |
+
public function getProcessor_PrivacyProtect() {
|
395 |
+
$this->loadFeatureHandler( 'privacy_protect' );
|
396 |
+
return $this->oFeatureHandlerPrivacyProtect->getProcessor();
|
397 |
+
}
|
398 |
|
399 |
+
/**
|
400 |
+
* @return ICWP_WPSF_Processor_AuditTrail|null
|
401 |
+
*/
|
402 |
+
public function getProcessor_AuditTrail() {
|
403 |
+
$this->loadFeatureHandler( 'audit_trail' );
|
404 |
+
return $this->oFeatureHandlerAuditTrail->getProcessor();
|
405 |
+
}
|
406 |
|
407 |
+
/**
|
408 |
+
* @return ICWP_WPSF_Processor_Logging|null
|
409 |
+
*/
|
410 |
+
public function getProcessor_Logging() {
|
411 |
+
$this->loadFeatureHandler( 'logging' );
|
412 |
+
return $this->oFeatureHandlerLogging->getProcessor();
|
413 |
+
}
|
414 |
|
415 |
+
/**
|
416 |
+
* @return ICWP_WPSF_Processor_Email|null
|
417 |
+
*/
|
418 |
+
public function getProcessor_Email() {
|
419 |
+
return $this->oFeatureHandlerEmail->getEmailProcessor();
|
420 |
+
}
|
421 |
}
|
|
|
422 |
|
423 |
endif;
|
424 |
+
|
425 |
+
require_once( 'icwp-plugin-controller.php');
|
426 |
+
$oICWP_Wpsf = new ICWP_Wordpress_Simple_Firewall( ICWP_WPSF_Plugin_Controller::GetInstance( ICWP_WPSF_Spec::GetInstance() ) );
|
icwp-wpsf.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
* Plugin Name: WordPress Simple Firewall
|
4 |
* Plugin URI: http://icwp.io/2f
|
5 |
* Description: A Simple WordPress Firewall
|
6 |
-
* Version: 3.
|
7 |
* Text Domain: wp-simple-firewall
|
8 |
* Author: iControlWP
|
9 |
* Author URI: http://icwp.io/2e
|
@@ -13,8 +13,7 @@
|
|
13 |
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
14 |
* All rights reserved.
|
15 |
*
|
16 |
-
* "WordPress Simple Firewall" is
|
17 |
-
* distributed under the GNU General Public License, Version 2,
|
18 |
* June 1991. Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin
|
19 |
* St, Fifth Floor, Boston, MA 02110, USA
|
20 |
*
|
@@ -30,9 +29,21 @@
|
|
30 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
31 |
*/
|
32 |
|
33 |
-
|
|
|
|
|
34 |
|
35 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
|
37 |
/**
|
38 |
* @const string
|
@@ -47,77 +58,60 @@ class ICWP_Wordpress_Simple_Firewall_Plugin {
|
|
47 |
/**
|
48 |
* @var string
|
49 |
*/
|
50 |
-
|
51 |
-
|
52 |
-
/**
|
53 |
-
* @var string
|
54 |
-
*/
|
55 |
-
private static $sParentSlug = 'icwp';
|
56 |
|
57 |
/**
|
58 |
* @var string
|
59 |
*/
|
60 |
-
private static $
|
61 |
|
62 |
/**
|
63 |
* @var string
|
64 |
*/
|
65 |
-
private static $
|
66 |
|
67 |
/**
|
68 |
* @var string
|
69 |
*/
|
70 |
-
private static $
|
71 |
|
72 |
/**
|
73 |
* @var string
|
74 |
*/
|
75 |
-
private static $
|
76 |
|
77 |
/**
|
78 |
* @var string
|
79 |
*/
|
80 |
-
private static $
|
81 |
|
82 |
/**
|
83 |
* @var string
|
84 |
*/
|
85 |
-
private static $
|
86 |
|
87 |
/**
|
88 |
* @var string
|
89 |
*/
|
90 |
-
private static $
|
91 |
|
92 |
/**
|
93 |
* @var string
|
94 |
*/
|
95 |
-
private static $
|
96 |
|
97 |
/**
|
98 |
* @var string
|
99 |
*/
|
100 |
-
private static $
|
101 |
-
'plugin',
|
102 |
-
'logging',
|
103 |
-
'email',
|
104 |
-
'admin_access_restriction',
|
105 |
-
'firewall',
|
106 |
-
'login_protect',
|
107 |
-
'user_management',
|
108 |
-
'comments_filter',
|
109 |
-
// 'privacy_protect',
|
110 |
-
'autoupdates',
|
111 |
-
'lockdown'
|
112 |
-
);
|
113 |
|
114 |
/**
|
115 |
-
* @var
|
116 |
*/
|
117 |
public static $oInstance;
|
118 |
|
119 |
/**
|
120 |
-
* @return
|
121 |
*/
|
122 |
public static function GetInstance() {
|
123 |
if ( !isset( self::$oInstance ) ) {
|
@@ -129,9 +123,7 @@ class ICWP_Wordpress_Simple_Firewall_Plugin {
|
|
129 |
/**
|
130 |
*/
|
131 |
private function __construct() {
|
132 |
-
|
133 |
-
self::$sRootFile = __FILE__;
|
134 |
-
}
|
135 |
}
|
136 |
|
137 |
/**
|
@@ -149,34 +141,17 @@ class ICWP_Wordpress_Simple_Firewall_Plugin {
|
|
149 |
}
|
150 |
|
151 |
/**
|
152 |
-
* @param string
|
153 |
-
* @return string
|
154 |
-
*/
|
155 |
-
public function getFullPluginPrefix( $sGlue = '-' ) {
|
156 |
-
return sprintf( '%s%s%s', self::$sParentSlug, $sGlue, self::$sPluginSlug );
|
157 |
-
}
|
158 |
-
|
159 |
-
/**
|
160 |
-
* @param string
|
161 |
-
* @return string
|
162 |
-
*/
|
163 |
-
public function getFeatures() {
|
164 |
-
return self::$aFeatures;
|
165 |
-
}
|
166 |
-
|
167 |
-
/**
|
168 |
-
* @param string
|
169 |
* @return string
|
170 |
*/
|
171 |
-
public function
|
172 |
-
return
|
173 |
}
|
174 |
|
175 |
/**
|
176 |
* @return string
|
177 |
*/
|
178 |
-
public function
|
179 |
-
return self::$
|
180 |
}
|
181 |
|
182 |
/**
|
@@ -200,15 +175,6 @@ class ICWP_Wordpress_Simple_Firewall_Plugin {
|
|
200 |
return self::$sPluginSlug;
|
201 |
}
|
202 |
|
203 |
-
/**
|
204 |
-
* get the root directory for the plugin with the trailing slash
|
205 |
-
*
|
206 |
-
* @return string
|
207 |
-
*/
|
208 |
-
public function getRootDir() {
|
209 |
-
return dirname( $this->getRootFile() ).ICWP_DS;
|
210 |
-
}
|
211 |
-
|
212 |
/**
|
213 |
* @return string
|
214 |
*/
|
@@ -216,15 +182,6 @@ class ICWP_Wordpress_Simple_Firewall_Plugin {
|
|
216 |
return self::$sRootFile;
|
217 |
}
|
218 |
|
219 |
-
/**
|
220 |
-
* get the directory for the plugin view with the trailing slash
|
221 |
-
*
|
222 |
-
* @return string
|
223 |
-
*/
|
224 |
-
public function getSourceDir() {
|
225 |
-
return $this->getRootDir().self::SrcDir.ICWP_DS;
|
226 |
-
}
|
227 |
-
|
228 |
/**
|
229 |
* @return string
|
230 |
*/
|
@@ -238,15 +195,5 @@ class ICWP_Wordpress_Simple_Firewall_Plugin {
|
|
238 |
public function getVersion() {
|
239 |
return self::$sVersion;
|
240 |
}
|
241 |
-
|
242 |
-
/**
|
243 |
-
* get the directory for the plugin view with the trailing slash
|
244 |
-
*
|
245 |
-
* @return string
|
246 |
-
*/
|
247 |
-
public function getViewDir() {
|
248 |
-
return $this->getRootDir().self::ViewDir.ICWP_DS;
|
249 |
-
}
|
250 |
}
|
251 |
-
|
252 |
-
$oICWP_Wpsf = new ICWP_Wordpress_Simple_Firewall( ICWP_Wordpress_Simple_Firewall_Plugin::GetInstance() );
|
3 |
* Plugin Name: WordPress Simple Firewall
|
4 |
* Plugin URI: http://icwp.io/2f
|
5 |
* Description: A Simple WordPress Firewall
|
6 |
+
* Version: 3.5.5
|
7 |
* Text Domain: wp-simple-firewall
|
8 |
* Author: iControlWP
|
9 |
* Author URI: http://icwp.io/2e
|
13 |
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
14 |
* All rights reserved.
|
15 |
*
|
16 |
+
* "WordPress Simple Firewall" is distributed under the GNU General Public License, Version 2,
|
|
|
17 |
* June 1991. Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin
|
18 |
* St, Fifth Floor, Boston, MA 02110, USA
|
19 |
*
|
29 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
30 |
*/
|
31 |
|
32 |
+
if ( !defined('ICWP_DS') ) {
|
33 |
+
define( 'ICWP_DS', DIRECTORY_SEPARATOR );
|
34 |
+
}
|
35 |
|
36 |
+
if ( !function_exists( '_wpsf_e' ) ) {
|
37 |
+
function _wpsf_e( $insStr ) {
|
38 |
+
_e( $insStr, 'wp-simple-firewall' );
|
39 |
+
}
|
40 |
+
}
|
41 |
+
if ( !function_exists( '_wpsf__' ) ) {
|
42 |
+
function _wpsf__( $insStr ) {
|
43 |
+
return __( $insStr, 'wp-simple-firewall' );
|
44 |
+
}
|
45 |
+
}
|
46 |
+
class ICWP_WPSF_Spec {
|
47 |
|
48 |
/**
|
49 |
* @const string
|
58 |
/**
|
59 |
* @var string
|
60 |
*/
|
61 |
+
protected static $fLoggingEnabled = true;
|
|
|
|
|
|
|
|
|
|
|
62 |
|
63 |
/**
|
64 |
* @var string
|
65 |
*/
|
66 |
+
private static $sVersion = '3.5.5';
|
67 |
|
68 |
/**
|
69 |
* @var string
|
70 |
*/
|
71 |
+
private static $sParentSlug = 'icwp';
|
72 |
|
73 |
/**
|
74 |
* @var string
|
75 |
*/
|
76 |
+
private static $sPluginSlug = 'wpsf';
|
77 |
|
78 |
/**
|
79 |
* @var string
|
80 |
*/
|
81 |
+
private static $sRootFile;
|
82 |
|
83 |
/**
|
84 |
* @var string
|
85 |
*/
|
86 |
+
private static $sHumanName = 'WordPress Simple Firewall';
|
87 |
|
88 |
/**
|
89 |
* @var string
|
90 |
*/
|
91 |
+
private static $sMenuTitleName = 'Simple Firewall';
|
92 |
|
93 |
/**
|
94 |
* @var string
|
95 |
*/
|
96 |
+
private static $sTextDomain = 'wp-simple-firewall';
|
97 |
|
98 |
/**
|
99 |
* @var string
|
100 |
*/
|
101 |
+
private static $sBasePermissions = 'manage_options';
|
102 |
|
103 |
/**
|
104 |
* @var string
|
105 |
*/
|
106 |
+
private static $sWpmsNetworkAdminOnly = true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
107 |
|
108 |
/**
|
109 |
+
* @var ICWP_WPSF_Spec
|
110 |
*/
|
111 |
public static $oInstance;
|
112 |
|
113 |
/**
|
114 |
+
* @return ICWP_WPSF_Spec
|
115 |
*/
|
116 |
public static function GetInstance() {
|
117 |
if ( !isset( self::$oInstance ) ) {
|
123 |
/**
|
124 |
*/
|
125 |
private function __construct() {
|
126 |
+
self::$sRootFile = __FILE__;
|
|
|
|
|
127 |
}
|
128 |
|
129 |
/**
|
141 |
}
|
142 |
|
143 |
/**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
144 |
* @return string
|
145 |
*/
|
146 |
+
public function getHumanName() {
|
147 |
+
return self::$sHumanName;
|
148 |
}
|
149 |
|
150 |
/**
|
151 |
* @return string
|
152 |
*/
|
153 |
+
public function getIsLoggingEnabled() {
|
154 |
+
return self::$fLoggingEnabled;
|
155 |
}
|
156 |
|
157 |
/**
|
175 |
return self::$sPluginSlug;
|
176 |
}
|
177 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
178 |
/**
|
179 |
* @return string
|
180 |
*/
|
182 |
return self::$sRootFile;
|
183 |
}
|
184 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
185 |
/**
|
186 |
* @return string
|
187 |
*/
|
195 |
public function getVersion() {
|
196 |
return self::$sVersion;
|
197 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
198 |
}
|
199 |
+
require_once( 'icwp-wpsf-main.php' );
|
|
languages/wp-simple-firewall-es_ES.mo
CHANGED
Binary file
|
languages/wp-simple-firewall-fr_FR.mo
ADDED
Binary file
|
languages/wp-simple-firewall-pt_BR.mo
CHANGED
Binary file
|
mode.login_throttled
DELETED
File without changes
|
readme.txt
CHANGED
@@ -3,10 +3,10 @@ Contributors: paultgoodchild, dlgoodchild
|
|
3 |
Donate link: http://icwp.io/q
|
4 |
License: GPLv3
|
5 |
License URI: http://www.gnu.org/licenses/gpl.html
|
6 |
-
Tags: WordPress Firewall, protection, whitelist, blacklist, two-factor authentication, GASP, comment spam, automatic updates, lockdown, login, hack, login
|
7 |
Requires at least: 3.2.0
|
8 |
-
Tested up to:
|
9 |
-
Stable tag: 3.
|
10 |
|
11 |
Complete and Simple WordPress Security. Unrestricted, Easy, No Premium Features.
|
12 |
|
@@ -225,9 +225,83 @@ You can either manually upgrade, or WordPress will handle it in due course.
|
|
225 |
|
226 |
== Changelog ==
|
227 |
|
228 |
-
|
229 |
|
230 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
231 |
|
232 |
= 3.0.0 =
|
233 |
|
3 |
Donate link: http://icwp.io/q
|
4 |
License: GPLv3
|
5 |
License URI: http://www.gnu.org/licenses/gpl.html
|
6 |
+
Tags: WordPress Firewall, audit trail, protection, whitelist, blacklist, two-factor authentication, GASP, comment spam, automatic updates, lockdown, login, hack, login
|
7 |
Requires at least: 3.2.0
|
8 |
+
Tested up to: 4.0
|
9 |
+
Stable tag: 3.5.5
|
10 |
|
11 |
Complete and Simple WordPress Security. Unrestricted, Easy, No Premium Features.
|
12 |
|
225 |
|
226 |
== Changelog ==
|
227 |
|
228 |
+
* KNOWN ISSUE: Login Protection logs are not being properly created.
|
229 |
|
230 |
+
= 4.0.0 =
|
231 |
+
|
232 |
+
* ADDED: New Feature - Audit Trail ( Coming Soon! )
|
233 |
+
|
234 |
+
= 3.5.5 =
|
235 |
+
|
236 |
+
* ADDED: Better admin notifications for events such as options saving etc.
|
237 |
+
* CHANGE: Some plugin styling to highlight features and options better.
|
238 |
+
* FIXED: Small bug with options default values.
|
239 |
+
|
240 |
+
= 3.5.3 =
|
241 |
+
|
242 |
+
* ADDED: A warning message on the WordPress admin if the "forceOff" override is active.
|
243 |
+
* CHANGED: The 'forceOff' system is now temporary - i.e. it doesn't save the configuration, and so once this file is removed, the plugin returns to the settings specified.
|
244 |
+
* CHANGED: The 'forceOn' option is now removed.
|
245 |
+
* FIXED: Problems with certain hosting environments reading in files with the ".yaml" extension - [support ref](https://wordpress.org/support/topic/yaml-breaks-plugin)
|
246 |
+
* FIXED: Small issue where when the file system paths change, some variables don't update properly.
|
247 |
+
|
248 |
+
= 3.5.0 =
|
249 |
+
|
250 |
+
* CHANGED: Plugin features are now configured [using YAML](https://github.com/mustangostang/spyc/) - no more in-PHP configuration.
|
251 |
+
* REMOVED: A few options from User Sessions Management as they were unnecessary.
|
252 |
+
* CHANGED: Database storing tables now have consistent naming.
|
253 |
+
* FIXED: Issue with User Sessions Management where '0' was specified for session length, resulting in lock out.
|
254 |
+
* FIXED: Firewall log gathering.
|
255 |
+
* FIXED: Various PHP warning notices.
|
256 |
+
|
257 |
+
= 3.4.0 =
|
258 |
+
|
259 |
+
* ADDED: Option to limit number of simultaneous sessions per WordPress user login name (User Management section)
|
260 |
+
|
261 |
+
= 3.3.0 =
|
262 |
+
|
263 |
+
* ADDED: Option to send notification when an administrator user logs in successfully (under User Management menu).
|
264 |
+
* CHANGED: Refactoring for how GET and POST data is retrieved
|
265 |
+
|
266 |
+
= 3.2.1 =
|
267 |
+
|
268 |
+
* FIXED: Custom Comment Filter message problem when using more than one substitution. [ref](http://wordpress.org/support/topic/warning-sprintf-too-few-arguments-in-hometnrastropublic_htmlwpwp-conten?replies=8#post-5927337)
|
269 |
+
|
270 |
+
= 3.2.0 =
|
271 |
+
|
272 |
+
* ADDED: Options to allow by-pass XML-RPC so as to be compatible with WordPress iPhone/Android apps.
|
273 |
+
* UPDATED: Login screen message when you're forced logged-out due to 2-factor auth failure on IP or cookie.
|
274 |
+
* CHANGED: Tweaked method for setting admin access protection on/off
|
275 |
+
* CHANGED: comment filtering code refactoring.
|
276 |
+
* FIXED: Options that were "multiple selects" weren't saving correctly
|
277 |
+
|
278 |
+
= 3.1.5 =
|
279 |
+
|
280 |
+
* FIX: Where some comments would fail GASP comment token checking.
|
281 |
+
|
282 |
+
= 3.1.4 =
|
283 |
+
|
284 |
+
* FIX: Logout URL parameters are now generated correctly so that the correct messages are shown.
|
285 |
+
* CHANGED: small optimizations and code refactoring.
|
286 |
+
* UPDATED: a few translation files based on the latest available contributions.
|
287 |
+
|
288 |
+
= 3.1.3 =
|
289 |
+
|
290 |
+
* FIX: issue with login cooldown timeouts not being updated where admin access restriction is in place.
|
291 |
+
|
292 |
+
= 3.1.2 =
|
293 |
+
|
294 |
+
* FIX: auto-updates feature not loading
|
295 |
+
* FIX: simplified implementation of login protection feature to reduce possibility for bugs/lock-outs
|
296 |
+
* FIX: auto-forwarding for wp-login.php was preventing user logout
|
297 |
+
|
298 |
+
= 3.1.0 =
|
299 |
+
|
300 |
+
* ADDED: option to check the logged-in user session only on WordPress admin pages (now the default setting)
|
301 |
+
* ADDED: option to auto-forward to the WordPress dashboard when you go to wp-login.php and you're already logged in.
|
302 |
+
* ADDED: message to login screen when no user session is found
|
303 |
+
* CHANGED: does not verify session when performing AJAX request. (need to build appropriate AJAX response)
|
304 |
+
* FIX: for wp_login action not passing second argument
|
305 |
|
306 |
= 3.0.0 =
|
307 |
|
resources/css/global-plugin.css
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
@CHARSET "ISO-8859-1";
|
2 |
+
|
3 |
+
.wrap .icwp-admin-notice {
|
4 |
+
padding: 13px 20px;
|
5 |
+
border: 1px solid rgba(240, 165, 4, 0.56);
|
6 |
+
background-color: rgba(255, 227, 167, 0.25);
|
7 |
+
border-right-width: 5px;
|
8 |
+
border-left-width: 5px;
|
9 |
+
}
|
10 |
+
|
11 |
+
.wrap .icwp-admin-notice p {
|
12 |
+
text-shadow: -1px -1px 0px rgba(255,255,255,0.4);
|
13 |
+
}
|
14 |
+
.wrap .icwp-admin-notice.updated p {
|
15 |
+
color: rgba(155, 107, 5, 1);
|
16 |
+
}
|
17 |
+
.wrap .icwp-admin-notice form {
|
18 |
+
margin: 0;
|
19 |
+
}
|
20 |
+
.wrap .icwp-admin-notice .button {
|
21 |
+
margin: 10px 0 7px;
|
22 |
+
}
|
23 |
+
.wrap .icwp-admin-notice .button:hover {
|
24 |
+
text-decoration: none;
|
25 |
+
}
|
26 |
+
|
27 |
+
.wrap .error.icwp-admin-notice {
|
28 |
+
border-color: rgba(240, 51, 4, 0.56);
|
29 |
+
background-color: rgba(255, 185, 167, 0.25);
|
30 |
+
}
|
31 |
+
.wrap .error.icwp-admin-notice h3 {
|
32 |
+
color: rgba(199, 41, 0, 1);
|
33 |
+
}
|
resources/css/plugin.css
CHANGED
@@ -20,6 +20,9 @@
|
|
20 |
vertical-align: middle;
|
21 |
width: 48px;
|
22 |
}
|
|
|
|
|
|
|
23 |
.wrap .icon32 {
|
24 |
width: 32px;
|
25 |
}
|
@@ -30,6 +33,7 @@
|
|
30 |
}
|
31 |
/* Form elements */
|
32 |
.bootstrap-wpadmin form fieldset {
|
|
|
33 |
}
|
34 |
.bootstrap-wpadmin .label {
|
35 |
vertical-align: baseline !important;
|
@@ -66,6 +70,38 @@ p.code-description {
|
|
66 |
padding: 10px 20px;
|
67 |
}
|
68 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
69 |
/** LESS PAGE **/
|
70 |
.enabled_section {
|
71 |
opacity: 1.0;
|
@@ -84,7 +120,7 @@ p.code-description {
|
|
84 |
.form-horizontal legend {
|
85 |
border-bottom: 1px dashed #aaa;
|
86 |
margin-bottom: 8px;
|
87 |
-
margin-top:
|
88 |
}
|
89 |
.form-horizontal .item_group .control-group {
|
90 |
margin-bottom: 0;
|
20 |
vertical-align: middle;
|
21 |
width: 48px;
|
22 |
}
|
23 |
+
.plugin_update_message {
|
24 |
+
color: #dd3333;
|
25 |
+
}
|
26 |
.wrap .icon32 {
|
27 |
width: 32px;
|
28 |
}
|
33 |
}
|
34 |
/* Form elements */
|
35 |
.bootstrap-wpadmin form fieldset {
|
36 |
+
width: 80%;
|
37 |
}
|
38 |
.bootstrap-wpadmin .label {
|
39 |
vertical-align: baseline !important;
|
70 |
padding: 10px 20px;
|
71 |
}
|
72 |
|
73 |
+
.row.option_section_row {
|
74 |
+
margin-left: 0px;
|
75 |
+
}
|
76 |
+
.row.option_section_row.primary_section {
|
77 |
+
background-color: #f9f9f9;
|
78 |
+
border: 1px solid transparent;
|
79 |
+
box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.2);
|
80 |
+
margin-bottom: 20px;
|
81 |
+
padding-bottom: 30px;
|
82 |
+
}
|
83 |
+
/*
|
84 |
+
.row.option_section_row.primary_section > div {
|
85 |
+
background-color: #f9f9f9;
|
86 |
+
border: 1px solid #ddd;
|
87 |
+
margin-bottom: 30px;
|
88 |
+
margin-top: 10px;
|
89 |
+
padding: 5px 30px 30px;
|
90 |
+
}
|
91 |
+
.row.option_section_row.non_primary_section > div {
|
92 |
+
margin-left: 0px;
|
93 |
+
}*/
|
94 |
+
|
95 |
+
.well.admin_access_restriction_form {
|
96 |
+
background-color: #fbfbfb;
|
97 |
+
border: 1px solid #ccc;
|
98 |
+
box-shadow: none;
|
99 |
+
}
|
100 |
+
|
101 |
+
.well.admin_access_restriction_form .form-actions {
|
102 |
+
background-color: #fbfbfb;
|
103 |
+
}
|
104 |
+
|
105 |
/** LESS PAGE **/
|
106 |
.enabled_section {
|
107 |
opacity: 1.0;
|
120 |
.form-horizontal legend {
|
121 |
border-bottom: 1px dashed #aaa;
|
122 |
margin-bottom: 8px;
|
123 |
+
margin-top: 10px;
|
124 |
}
|
125 |
.form-horizontal .item_group .control-group {
|
126 |
margin-bottom: 0;
|
resources/js/bootstrap.min.js
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*!
|
2 |
+
* Bootstrap.js by @fat & @mdo
|
3 |
+
* Copyright 2012 Twitter, Inc.
|
4 |
+
* http://www.apache.org/licenses/LICENSE-2.0.txt
|
5 |
+
*/
|
6 |
+
!function(e){"use strict";e(function(){e.support.transition=function(){var e=function(){var e=document.createElement("bootstrap"),t={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},n;for(n in t)if(e.style[n]!==undefined)return t[n]}();return e&&{end:e}}()})}(window.jQuery),!function(e){"use strict";var t='[data-dismiss="alert"]',n=function(n){e(n).on("click",t,this.close)};n.prototype.close=function(t){function s(){i.trigger("closed").remove()}var n=e(this),r=n.attr("data-target"),i;r||(r=n.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,"")),i=e(r),t&&t.preventDefault(),i.length||(i=n.hasClass("alert")?n:n.parent()),i.trigger(t=e.Event("close"));if(t.isDefaultPrevented())return;i.removeClass("in"),e.support.transition&&i.hasClass("fade")?i.on(e.support.transition.end,s):s()};var r=e.fn.alert;e.fn.alert=function(t){return this.each(function(){var r=e(this),i=r.data("alert");i||r.data("alert",i=new n(this)),typeof t=="string"&&i[t].call(r)})},e.fn.alert.Constructor=n,e.fn.alert.noConflict=function(){return e.fn.alert=r,this},e(document).on("click.alert.data-api",t,n.prototype.close)}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.button.defaults,n)};t.prototype.setState=function(e){var t="disabled",n=this.$element,r=n.data(),i=n.is("input")?"val":"html";e+="Text",r.resetText||n.data("resetText",n[i]()),n[i](r[e]||this.options[e]),setTimeout(function(){e=="loadingText"?n.addClass(t).attr(t,t):n.removeClass(t).removeAttr(t)},0)},t.prototype.toggle=function(){var e=this.$element.closest('[data-toggle="buttons-radio"]');e&&e.find(".active").removeClass("active"),this.$element.toggleClass("active")};var n=e.fn.button;e.fn.button=function(n){return this.each(function(){var r=e(this),i=r.data("button"),s=typeof n=="object"&&n;i||r.data("button",i=new t(this,s)),n=="toggle"?i.toggle():n&&i.setState(n)})},e.fn.button.defaults={loadingText:"loading..."},e.fn.button.Constructor=t,e.fn.button.noConflict=function(){return e.fn.button=n,this},e(document).on("click.button.data-api","[data-toggle^=button]",function(t){var n=e(t.target);n.hasClass("btn")||(n=n.closest(".btn")),n.button("toggle")})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.$indicators=this.$element.find(".carousel-indicators"),this.options=n,this.options.pause=="hover"&&this.$element.on("mouseenter",e.proxy(this.pause,this)).on("mouseleave",e.proxy(this.cycle,this))};t.prototype={cycle:function(t){return t||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(e.proxy(this.next,this),this.options.interval)),this},getActiveIndex:function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},to:function(t){var n=this.getActiveIndex(),r=this;if(t>this.$items.length-1||t<0)return;return this.sliding?this.$element.one("slid",function(){r.to(t)}):n==t?this.pause().cycle():this.slide(t>n?"next":"prev",e(this.$items[t]))},pause:function(t){return t||(this.paused=!0),this.$element.find(".next, .prev").length&&e.support.transition.end&&(this.$element.trigger(e.support.transition.end),this.cycle(!0)),clearInterval(this.interval),this.interval=null,this},next:function(){if(this.sliding)return;return this.slide("next")},prev:function(){if(this.sliding)return;return this.slide("prev")},slide:function(t,n){var r=this.$element.find(".item.active"),i=n||r[t](),s=this.interval,o=t=="next"?"left":"right",u=t=="next"?"first":"last",a=this,f;this.sliding=!0,s&&this.pause(),i=i.length?i:this.$element.find(".item")[u](),f=e.Event("slide",{relatedTarget:i[0],direction:o});if(i.hasClass("active"))return;this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid",function(){var t=e(a.$indicators.children()[a.getActiveIndex()]);t&&t.addClass("active")}));if(e.support.transition&&this.$element.hasClass("slide")){this.$element.trigger(f);if(f.isDefaultPrevented())return;i.addClass(t),i[0].offsetWidth,r.addClass(o),i.addClass(o),this.$element.one(e.support.transition.end,function(){i.removeClass([t,o].join(" ")).addClass("active"),r.removeClass(["active",o].join(" ")),a.sliding=!1,setTimeout(function(){a.$element.trigger("slid")},0)})}else{this.$element.trigger(f);if(f.isDefaultPrevented())return;r.removeClass("active"),i.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return s&&this.cycle(),this}};var n=e.fn.carousel;e.fn.carousel=function(n){return this.each(function(){var r=e(this),i=r.data("carousel"),s=e.extend({},e.fn.carousel.defaults,typeof n=="object"&&n),o=typeof n=="string"?n:s.slide;i||r.data("carousel",i=new t(this,s)),typeof n=="number"?i.to(n):o?i[o]():s.interval&&i.pause().cycle()})},e.fn.carousel.defaults={interval:5e3,pause:"hover"},e.fn.carousel.Constructor=t,e.fn.carousel.noConflict=function(){return e.fn.carousel=n,this},e(document).on("click.carousel.data-api","[data-slide], [data-slide-to]",function(t){var n=e(this),r,i=e(n.attr("data-target")||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,"")),s=e.extend({},i.data(),n.data()),o;i.carousel(s),(o=n.attr("data-slide-to"))&&i.data("carousel").pause().to(o).cycle(),t.preventDefault()})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.collapse.defaults,n),this.options.parent&&(this.$parent=e(this.options.parent)),this.options.toggle&&this.toggle()};t.prototype={constructor:t,dimension:function(){var e=this.$element.hasClass("width");return e?"width":"height"},show:function(){var t,n,r,i;if(this.transitioning||this.$element.hasClass("in"))return;t=this.dimension(),n=e.camelCase(["scroll",t].join("-")),r=this.$parent&&this.$parent.find("> .accordion-group > .in");if(r&&r.length){i=r.data("collapse");if(i&&i.transitioning)return;r.collapse("hide"),i||r.data("collapse",null)}this.$element[t](0),this.transition("addClass",e.Event("show"),"shown"),e.support.transition&&this.$element[t](this.$element[0][n])},hide:function(){var t;if(this.transitioning||!this.$element.hasClass("in"))return;t=this.dimension(),this.reset(this.$element[t]()),this.transition("removeClass",e.Event("hide"),"hidden"),this.$element[t](0)},reset:function(e){var t=this.dimension();return this.$element.removeClass("collapse")[t](e||"auto")[0].offsetWidth,this.$element[e!==null?"addClass":"removeClass"]("collapse"),this},transition:function(t,n,r){var i=this,s=function(){n.type=="show"&&i.reset(),i.transitioning=0,i.$element.trigger(r)};this.$element.trigger(n);if(n.isDefaultPrevented())return;this.transitioning=1,this.$element[t]("in"),e.support.transition&&this.$element.hasClass("collapse")?this.$element.one(e.support.transition.end,s):s()},toggle:function(){this[this.$element.hasClass("in")?"hide":"show"]()}};var n=e.fn.collapse;e.fn.collapse=function(n){return this.each(function(){var r=e(this),i=r.data("collapse"),s=e.extend({},e.fn.collapse.defaults,r.data(),typeof n=="object"&&n);i||r.data("collapse",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.collapse.defaults={toggle:!0},e.fn.collapse.Constructor=t,e.fn.collapse.noConflict=function(){return e.fn.collapse=n,this},e(document).on("click.collapse.data-api","[data-toggle=collapse]",function(t){var n=e(this),r,i=n.attr("data-target")||t.preventDefault()||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,""),s=e(i).data("collapse")?"toggle":n.data();n[e(i).hasClass("in")?"addClass":"removeClass"]("collapsed"),e(i).collapse(s)})}(window.jQuery),!function(e){"use strict";function r(){e(".dropdown-backdrop").remove(),e(t).each(function(){i(e(this)).removeClass("open")})}function i(t){var n=t.attr("data-target"),r;n||(n=t.attr("href"),n=n&&/#/.test(n)&&n.replace(/.*(?=#[^\s]*$)/,"")),r=n&&e(n);if(!r||!r.length)r=t.parent();return r}var t="[data-toggle=dropdown]",n=function(t){var n=e(t).on("click.dropdown.data-api",this.toggle);e("html").on("click.dropdown.data-api",function(){n.parent().removeClass("open")})};n.prototype={constructor:n,toggle:function(t){var n=e(this),s,o;if(n.is(".disabled, :disabled"))return;return s=i(n),o=s.hasClass("open"),r(),o||("ontouchstart"in document.documentElement&&e('<div class="dropdown-backdrop"/>').insertBefore(e(this)).on("click",r),s.toggleClass("open")),n.focus(),!1},keydown:function(n){var r,s,o,u,a,f;if(!/(38|40|27)/.test(n.keyCode))return;r=e(this),n.preventDefault(),n.stopPropagation();if(r.is(".disabled, :disabled"))return;u=i(r),a=u.hasClass("open");if(!a||a&&n.keyCode==27)return n.which==27&&u.find(t).focus(),r.click();s=e("[role=menu] li:not(.divider):visible a",u);if(!s.length)return;f=s.index(s.filter(":focus")),n.keyCode==38&&f>0&&f--,n.keyCode==40&&f<s.length-1&&f++,~f||(f=0),s.eq(f).focus()}};var s=e.fn.dropdown;e.fn.dropdown=function(t){return this.each(function(){var r=e(this),i=r.data("dropdown");i||r.data("dropdown",i=new n(this)),typeof t=="string"&&i[t].call(r)})},e.fn.dropdown.Constructor=n,e.fn.dropdown.noConflict=function(){return e.fn.dropdown=s,this},e(document).on("click.dropdown.data-api",r).on("click.dropdown.data-api",".dropdown form",function(e){e.stopPropagation()}).on("click.dropdown.data-api",t,n.prototype.toggle).on("keydown.dropdown.data-api",t+", [role=menu]",n.prototype.keydown)}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.options=n,this.$element=e(t).delegate('[data-dismiss="modal"]',"click.dismiss.modal",e.proxy(this.hide,this)),this.options.remote&&this.$element.find(".modal-body").load(this.options.remote)};t.prototype={constructor:t,toggle:function(){return this[this.isShown?"hide":"show"]()},show:function(){var t=this,n=e.Event("show");this.$element.trigger(n);if(this.isShown||n.isDefaultPrevented())return;this.isShown=!0,this.escape(),this.backdrop(function(){var n=e.support.transition&&t.$element.hasClass("fade");t.$element.parent().length||t.$element.appendTo(document.body),t.$element.show(),n&&t.$element[0].offsetWidth,t.$element.addClass("in").attr("aria-hidden",!1),t.enforceFocus(),n?t.$element.one(e.support.transition.end,function(){t.$element.focus().trigger("shown")}):t.$element.focus().trigger("shown")})},hide:function(t){t&&t.preventDefault();var n=this;t=e.Event("hide"),this.$element.trigger(t);if(!this.isShown||t.isDefaultPrevented())return;this.isShown=!1,this.escape(),e(document).off("focusin.modal"),this.$element.removeClass("in").attr("aria-hidden",!0),e.support.transition&&this.$element.hasClass("fade")?this.hideWithTransition():this.hideModal()},enforceFocus:function(){var t=this;e(document).on("focusin.modal",function(e){t.$element[0]!==e.target&&!t.$element.has(e.target).length&&t.$element.focus()})},escape:function(){var e=this;this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.modal",function(t){t.which==27&&e.hide()}):this.isShown||this.$element.off("keyup.dismiss.modal")},hideWithTransition:function(){var t=this,n=setTimeout(function(){t.$element.off(e.support.transition.end),t.hideModal()},500);this.$element.one(e.support.transition.end,function(){clearTimeout(n),t.hideModal()})},hideModal:function(){var e=this;this.$element.hide(),this.backdrop(function(){e.removeBackdrop(),e.$element.trigger("hidden")})},removeBackdrop:function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},backdrop:function(t){var n=this,r=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var i=e.support.transition&&r;this.$backdrop=e('<div class="modal-backdrop '+r+'" />').appendTo(document.body),this.$backdrop.click(this.options.backdrop=="static"?e.proxy(this.$element[0].focus,this.$element[0]):e.proxy(this.hide,this)),i&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in");if(!t)return;i?this.$backdrop.one(e.support.transition.end,t):t()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),e.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(e.support.transition.end,t):t()):t&&t()}};var n=e.fn.modal;e.fn.modal=function(n){return this.each(function(){var r=e(this),i=r.data("modal"),s=e.extend({},e.fn.modal.defaults,r.data(),typeof n=="object"&&n);i||r.data("modal",i=new t(this,s)),typeof n=="string"?i[n]():s.show&&i.show()})},e.fn.modal.defaults={backdrop:!0,keyboard:!0,show:!0},e.fn.modal.Constructor=t,e.fn.modal.noConflict=function(){return e.fn.modal=n,this},e(document).on("click.modal.data-api",'[data-toggle="modal"]',function(t){var n=e(this),r=n.attr("href"),i=e(n.attr("data-target")||r&&r.replace(/.*(?=#[^\s]+$)/,"")),s=i.data("modal")?"toggle":e.extend({remote:!/#/.test(r)&&r},i.data(),n.data());t.preventDefault(),i.modal(s).one("hide",function(){n.focus()})})}(window.jQuery),!function(e){"use strict";var t=function(e,t){this.init("tooltip",e,t)};t.prototype={constructor:t,init:function(t,n,r){var i,s,o,u,a;this.type=t,this.$element=e(n),this.options=this.getOptions(r),this.enabled=!0,o=this.options.trigger.split(" ");for(a=o.length;a--;)u=o[a],u=="click"?this.$element.on("click."+this.type,this.options.selector,e.proxy(this.toggle,this)):u!="manual"&&(i=u=="hover"?"mouseenter":"focus",s=u=="hover"?"mouseleave":"blur",this.$element.on(i+"."+this.type,this.options.selector,e.proxy(this.enter,this)),this.$element.on(s+"."+this.type,this.options.selector,e.proxy(this.leave,this)));this.options.selector?this._options=e.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},getOptions:function(t){return t=e.extend({},e.fn[this.type].defaults,this.$element.data(),t),t.delay&&typeof t.delay=="number"&&(t.delay={show:t.delay,hide:t.delay}),t},enter:function(t){var n=e.fn[this.type].defaults,r={},i;this._options&&e.each(this._options,function(e,t){n[e]!=t&&(r[e]=t)},this),i=e(t.currentTarget)[this.type](r).data(this.type);if(!i.options.delay||!i.options.delay.show)return i.show();clearTimeout(this.timeout),i.hoverState="in",this.timeout=setTimeout(function(){i.hoverState=="in"&&i.show()},i.options.delay.show)},leave:function(t){var n=e(t.currentTarget)[this.type](this._options).data(this.type);this.timeout&&clearTimeout(this.timeout);if(!n.options.delay||!n.options.delay.hide)return n.hide();n.hoverState="out",this.timeout=setTimeout(function(){n.hoverState=="out"&&n.hide()},n.options.delay.hide)},show:function(){var t,n,r,i,s,o,u=e.Event("show");if(this.hasContent()&&this.enabled){this.$element.trigger(u);if(u.isDefaultPrevented())return;t=this.tip(),this.setContent(),this.options.animation&&t.addClass("fade"),s=typeof this.options.placement=="function"?this.options.placement.call(this,t[0],this.$element[0]):this.options.placement,t.detach().css({top:0,left:0,display:"block"}),this.options.container?t.appendTo(this.options.container):t.insertAfter(this.$element),n=this.getPosition(),r=t[0].offsetWidth,i=t[0].offsetHeight;switch(s){case"bottom":o={top:n.top+n.height,left:n.left+n.width/2-r/2};break;case"top":o={top:n.top-i,left:n.left+n.width/2-r/2};break;case"left":o={top:n.top+n.height/2-i/2,left:n.left-r};break;case"right":o={top:n.top+n.height/2-i/2,left:n.left+n.width}}this.applyPlacement(o,s),this.$element.trigger("shown")}},applyPlacement:function(e,t){var n=this.tip(),r=n[0].offsetWidth,i=n[0].offsetHeight,s,o,u,a;n.offset(e).addClass(t).addClass("in"),s=n[0].offsetWidth,o=n[0].offsetHeight,t=="top"&&o!=i&&(e.top=e.top+i-o,a=!0),t=="bottom"||t=="top"?(u=0,e.left<0&&(u=e.left*-2,e.left=0,n.offset(e),s=n[0].offsetWidth,o=n[0].offsetHeight),this.replaceArrow(u-r+s,s,"left")):this.replaceArrow(o-i,o,"top"),a&&n.offset(e)},replaceArrow:function(e,t,n){this.arrow().css(n,e?50*(1-e/t)+"%":"")},setContent:function(){var e=this.tip(),t=this.getTitle();e.find(".tooltip-inner")[this.options.html?"html":"text"](t),e.removeClass("fade in top bottom left right")},hide:function(){function i(){var t=setTimeout(function(){n.off(e.support.transition.end).detach()},500);n.one(e.support.transition.end,function(){clearTimeout(t),n.detach()})}var t=this,n=this.tip(),r=e.Event("hide");this.$element.trigger(r);if(r.isDefaultPrevented())return;return n.removeClass("in"),e.support.transition&&this.$tip.hasClass("fade")?i():n.detach(),this.$element.trigger("hidden"),this},fixTitle:function(){var e=this.$element;(e.attr("title")||typeof e.attr("data-original-title")!="string")&&e.attr("data-original-title",e.attr("title")||"").attr("title","")},hasContent:function(){return this.getTitle()},getPosition:function(){var t=this.$element[0];return e.extend({},typeof t.getBoundingClientRect=="function"?t.getBoundingClientRect():{width:t.offsetWidth,height:t.offsetHeight},this.$element.offset())},getTitle:function(){var e,t=this.$element,n=this.options;return e=t.attr("data-original-title")||(typeof n.title=="function"?n.title.call(t[0]):n.title),e},tip:function(){return this.$tip=this.$tip||e(this.options.template)},arrow:function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},validate:function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},enable:function(){this.enabled=!0},disable:function(){this.enabled=!1},toggleEnabled:function(){this.enabled=!this.enabled},toggle:function(t){var n=t?e(t.currentTarget)[this.type](this._options).data(this.type):this;n.tip().hasClass("in")?n.hide():n.show()},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}};var n=e.fn.tooltip;e.fn.tooltip=function(n){return this.each(function(){var r=e(this),i=r.data("tooltip"),s=typeof n=="object"&&n;i||r.data("tooltip",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.tooltip.Constructor=t,e.fn.tooltip.defaults={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},e.fn.tooltip.noConflict=function(){return e.fn.tooltip=n,this}}(window.jQuery),!function(e){"use strict";var t=function(e,t){this.init("popover",e,t)};t.prototype=e.extend({},e.fn.tooltip.Constructor.prototype,{constructor:t,setContent:function(){var e=this.tip(),t=this.getTitle(),n=this.getContent();e.find(".popover-title")[this.options.html?"html":"text"](t),e.find(".popover-content")[this.options.html?"html":"text"](n),e.removeClass("fade top bottom left right in")},hasContent:function(){return this.getTitle()||this.getContent()},getContent:function(){var e,t=this.$element,n=this.options;return e=(typeof n.content=="function"?n.content.call(t[0]):n.content)||t.attr("data-content"),e},tip:function(){return this.$tip||(this.$tip=e(this.options.template)),this.$tip},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}});var n=e.fn.popover;e.fn.popover=function(n){return this.each(function(){var r=e(this),i=r.data("popover"),s=typeof n=="object"&&n;i||r.data("popover",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.popover.Constructor=t,e.fn.popover.defaults=e.extend({},e.fn.tooltip.defaults,{placement:"right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),e.fn.popover.noConflict=function(){return e.fn.popover=n,this}}(window.jQuery),!function(e){"use strict";function t(t,n){var r=e.proxy(this.process,this),i=e(t).is("body")?e(window):e(t),s;this.options=e.extend({},e.fn.scrollspy.defaults,n),this.$scrollElement=i.on("scroll.scroll-spy.data-api",r),this.selector=(this.options.target||(s=e(t).attr("href"))&&s.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.$body=e("body"),this.refresh(),this.process()}t.prototype={constructor:t,refresh:function(){var t=this,n;this.offsets=e([]),this.targets=e([]),n=this.$body.find(this.selector).map(function(){var n=e(this),r=n.data("target")||n.attr("href"),i=/^#\w/.test(r)&&e(r);return i&&i.length&&[[i.position().top+(!e.isWindow(t.$scrollElement.get(0))&&t.$scrollElement.scrollTop()),r]]||null}).sort(function(e,t){return e[0]-t[0]}).each(function(){t.offsets.push(this[0]),t.targets.push(this[1])})},process:function(){var e=this.$scrollElement.scrollTop()+this.options.offset,t=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,n=t-this.$scrollElement.height(),r=this.offsets,i=this.targets,s=this.activeTarget,o;if(e>=n)return s!=(o=i.last()[0])&&this.activate(o);for(o=r.length;o--;)s!=i[o]&&e>=r[o]&&(!r[o+1]||e<=r[o+1])&&this.activate(i[o])},activate:function(t){var n,r;this.activeTarget=t,e(this.selector).parent(".active").removeClass("active"),r=this.selector+'[data-target="'+t+'"],'+this.selector+'[href="'+t+'"]',n=e(r).parent("li").addClass("active"),n.parent(".dropdown-menu").length&&(n=n.closest("li.dropdown").addClass("active")),n.trigger("activate")}};var n=e.fn.scrollspy;e.fn.scrollspy=function(n){return this.each(function(){var r=e(this),i=r.data("scrollspy"),s=typeof n=="object"&&n;i||r.data("scrollspy",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.scrollspy.Constructor=t,e.fn.scrollspy.defaults={offset:10},e.fn.scrollspy.noConflict=function(){return e.fn.scrollspy=n,this},e(window).on("load",function(){e('[data-spy="scroll"]').each(function(){var t=e(this);t.scrollspy(t.data())})})}(window.jQuery),!function(e){"use strict";var t=function(t){this.element=e(t)};t.prototype={constructor:t,show:function(){var t=this.element,n=t.closest("ul:not(.dropdown-menu)"),r=t.attr("data-target"),i,s,o;r||(r=t.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,""));if(t.parent("li").hasClass("active"))return;i=n.find(".active:last a")[0],o=e.Event("show",{relatedTarget:i}),t.trigger(o);if(o.isDefaultPrevented())return;s=e(r),this.activate(t.parent("li"),n),this.activate(s,s.parent(),function(){t.trigger({type:"shown",relatedTarget:i})})},activate:function(t,n,r){function o(){i.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),t.addClass("active"),s?(t[0].offsetWidth,t.addClass("in")):t.removeClass("fade"),t.parent(".dropdown-menu")&&t.closest("li.dropdown").addClass("active"),r&&r()}var i=n.find("> .active"),s=r&&e.support.transition&&i.hasClass("fade");s?i.one(e.support.transition.end,o):o(),i.removeClass("in")}};var n=e.fn.tab;e.fn.tab=function(n){return this.each(function(){var r=e(this),i=r.data("tab");i||r.data("tab",i=new t(this)),typeof n=="string"&&i[n]()})},e.fn.tab.Constructor=t,e.fn.tab.noConflict=function(){return e.fn.tab=n,this},e(document).on("click.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(t){t.preventDefault(),e(this).tab("show")})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.typeahead.defaults,n),this.matcher=this.options.matcher||this.matcher,this.sorter=this.options.sorter||this.sorter,this.highlighter=this.options.highlighter||this.highlighter,this.updater=this.options.updater||this.updater,this.source=this.options.source,this.$menu=e(this.options.menu),this.shown=!1,this.listen()};t.prototype={constructor:t,select:function(){var e=this.$menu.find(".active").attr("data-value");return this.$element.val(this.updater(e)).change(),this.hide()},updater:function(e){return e},show:function(){var t=e.extend({},this.$element.position(),{height:this.$element[0].offsetHeight});return this.$menu.insertAfter(this.$element).css({top:t.top+t.height,left:t.left}).show(),this.shown=!0,this},hide:function(){return this.$menu.hide(),this.shown=!1,this},lookup:function(t){var n;return this.query=this.$element.val(),!this.query||this.query.length<this.options.minLength?this.shown?this.hide():this:(n=e.isFunction(this.source)?this.source(this.query,e.proxy(this.process,this)):this.source,n?this.process(n):this)},process:function(t){var n=this;return t=e.grep(t,function(e){return n.matcher(e)}),t=this.sorter(t),t.length?this.render(t.slice(0,this.options.items)).show():this.shown?this.hide():this},matcher:function(e){return~e.toLowerCase().indexOf(this.query.toLowerCase())},sorter:function(e){var t=[],n=[],r=[],i;while(i=e.shift())i.toLowerCase().indexOf(this.query.toLowerCase())?~i.indexOf(this.query)?n.push(i):r.push(i):t.push(i);return t.concat(n,r)},highlighter:function(e){var t=this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&");return e.replace(new RegExp("("+t+")","ig"),function(e,t){return"<strong>"+t+"</strong>"})},render:function(t){var n=this;return t=e(t).map(function(t,r){return t=e(n.options.item).attr("data-value",r),t.find("a").html(n.highlighter(r)),t[0]}),t.first().addClass("active"),this.$menu.html(t),this},next:function(t){var n=this.$menu.find(".active").removeClass("active"),r=n.next();r.length||(r=e(this.$menu.find("li")[0])),r.addClass("active")},prev:function(e){var t=this.$menu.find(".active").removeClass("active"),n=t.prev();n.length||(n=this.$menu.find("li").last()),n.addClass("active")},listen:function(){this.$element.on("focus",e.proxy(this.focus,this)).on("blur",e.proxy(this.blur,this)).on("keypress",e.proxy(this.keypress,this)).on("keyup",e.proxy(this.keyup,this)),this.eventSupported("keydown")&&this.$element.on("keydown",e.proxy(this.keydown,this)),this.$menu.on("click",e.proxy(this.click,this)).on("mouseenter","li",e.proxy(this.mouseenter,this)).on("mouseleave","li",e.proxy(this.mouseleave,this))},eventSupported:function(e){var t=e in this.$element;return t||(this.$element.setAttribute(e,"return;"),t=typeof this.$element[e]=="function"),t},move:function(e){if(!this.shown)return;switch(e.keyCode){case 9:case 13:case 27:e.preventDefault();break;case 38:e.preventDefault(),this.prev();break;case 40:e.preventDefault(),this.next()}e.stopPropagation()},keydown:function(t){this.suppressKeyPressRepeat=~e.inArray(t.keyCode,[40,38,9,13,27]),this.move(t)},keypress:function(e){if(this.suppressKeyPressRepeat)return;this.move(e)},keyup:function(e){switch(e.keyCode){case 40:case 38:case 16:case 17:case 18:break;case 9:case 13:if(!this.shown)return;this.select();break;case 27:if(!this.shown)return;this.hide();break;default:this.lookup()}e.stopPropagation(),e.preventDefault()},focus:function(e){this.focused=!0},blur:function(e){this.focused=!1,!this.mousedover&&this.shown&&this.hide()},click:function(e){e.stopPropagation(),e.preventDefault(),this.select(),this.$element.focus()},mouseenter:function(t){this.mousedover=!0,this.$menu.find(".active").removeClass("active"),e(t.currentTarget).addClass("active")},mouseleave:function(e){this.mousedover=!1,!this.focused&&this.shown&&this.hide()}};var n=e.fn.typeahead;e.fn.typeahead=function(n){return this.each(function(){var r=e(this),i=r.data("typeahead"),s=typeof n=="object"&&n;i||r.data("typeahead",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.typeahead.defaults={source:[],items:8,menu:'<ul class="typeahead dropdown-menu"></ul>',item:'<li><a href="#"></a></li>',minLength:1},e.fn.typeahead.Constructor=t,e.fn.typeahead.noConflict=function(){return e.fn.typeahead=n,this},e(document).on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(t){var n=e(this);if(n.data("typeahead"))return;n.typeahead(n.data())})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.options=e.extend({},e.fn.affix.defaults,n),this.$window=e(window).on("scroll.affix.data-api",e.proxy(this.checkPosition,this)).on("click.affix.data-api",e.proxy(function(){setTimeout(e.proxy(this.checkPosition,this),1)},this)),this.$element=e(t),this.checkPosition()};t.prototype.checkPosition=function(){if(!this.$element.is(":visible"))return;var t=e(document).height(),n=this.$window.scrollTop(),r=this.$element.offset(),i=this.options.offset,s=i.bottom,o=i.top,u="affix affix-top affix-bottom",a;typeof i!="object"&&(s=o=i),typeof o=="function"&&(o=i.top()),typeof s=="function"&&(s=i.bottom()),a=this.unpin!=null&&n+this.unpin<=r.top?!1:s!=null&&r.top+this.$element.height()>=t-s?"bottom":o!=null&&n<=o?"top":!1;if(this.affixed===a)return;this.affixed=a,this.unpin=a=="bottom"?r.top-n:null,this.$element.removeClass(u).addClass("affix"+(a?"-"+a:""))};var n=e.fn.affix;e.fn.affix=function(n){return this.each(function(){var r=e(this),i=r.data("affix"),s=typeof n=="object"&&n;i||r.data("affix",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.affix.Constructor=t,e.fn.affix.defaults={offset:0},e.fn.affix.noConflict=function(){return e.fn.affix=n,this},e(window).on("load",function(){e('[data-spy="affix"]').each(function(){var t=e(this),n=t.data();n.offset=n.offset||{},n.offsetBottom&&(n.offset.bottom=n.offsetBottom),n.offsetTop&&(n.offset.top=n.offsetTop),t.affix(n)})})}(window.jQuery);
|
src/config/feature-admin_access_restriction.txt
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
---
|
2 |
+
slug: 'admin_access_restriction'
|
3 |
+
properties:
|
4 |
+
name: 'Admin Access Restriction'
|
5 |
+
show_feature_menu_item: true
|
6 |
+
storage_key: 'admin_access_restriction' # should correspond exactly to that in the plugin.yaml
|
7 |
+
# Options Sections
|
8 |
+
sections:
|
9 |
+
-
|
10 |
+
slug: 'section_enable_plugin_feature_admin_access_restriction'
|
11 |
+
primary: true
|
12 |
+
-
|
13 |
+
slug: 'section_admin_access_restriction_settings'
|
14 |
+
primary: false
|
15 |
+
-
|
16 |
+
slug: 'section_non_ui'
|
17 |
+
hidden: true
|
18 |
+
|
19 |
+
# Define Options
|
20 |
+
options:
|
21 |
+
-
|
22 |
+
key: 'enable_admin_access_restriction'
|
23 |
+
section: 'section_enable_plugin_feature_admin_access_restriction'
|
24 |
+
default: 'N'
|
25 |
+
type: 'checkbox'
|
26 |
+
link_info: 'http://icwp.io/40'
|
27 |
+
link_blog: 'http://icwp.io/wpsf02'
|
28 |
+
-
|
29 |
+
key: 'admin_access_key'
|
30 |
+
section: 'section_admin_access_restriction_settings'
|
31 |
+
default: ''
|
32 |
+
type: 'password'
|
33 |
+
link_info: 'http://icwp.io/42'
|
34 |
+
link_blog: ''
|
35 |
+
-
|
36 |
+
key: 'admin_access_timeout'
|
37 |
+
section: 'section_admin_access_restriction_settings'
|
38 |
+
default: 30
|
39 |
+
type: 'integer'
|
40 |
+
link_info: 'http://icwp.io/41'
|
41 |
+
link_blog: ''
|
42 |
+
-
|
43 |
+
key: 'current_plugin_version'
|
44 |
+
section: 'section_non_ui'
|
45 |
+
-
|
46 |
+
key: 'admin_access_key_cookie_name'
|
47 |
+
section: 'section_non_ui'
|
48 |
+
value: 'icwp_wpsf_aakcook'
|
src/config/feature-audit_trail.txt
ADDED
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
---
|
2 |
+
slug: 'audit_trail'
|
3 |
+
properties:
|
4 |
+
name: 'Audit Trail'
|
5 |
+
show_feature_menu_item: true
|
6 |
+
storage_key: 'audit_trail' # should correspond exactly to that in the plugin.yaml
|
7 |
+
# Options Sections
|
8 |
+
sections:
|
9 |
+
-
|
10 |
+
slug: 'section_enable_plugin_feature_audit_trail'
|
11 |
+
primary: true
|
12 |
+
-
|
13 |
+
slug: 'section_enable_audit_contexts'
|
14 |
+
-
|
15 |
+
slug: 'section_non_ui'
|
16 |
+
hidden: true
|
17 |
+
|
18 |
+
# Define Options and assign to section slug
|
19 |
+
options:
|
20 |
+
-
|
21 |
+
key: 'enable_audit_trail'
|
22 |
+
section: 'section_enable_plugin_feature_audit_trail'
|
23 |
+
default: 'N'
|
24 |
+
type: 'checkbox'
|
25 |
+
link_info: ''
|
26 |
+
link_blog: ''
|
27 |
+
-
|
28 |
+
key: 'enable_audit_context_users'
|
29 |
+
section: 'section_enable_audit_contexts'
|
30 |
+
default: 'Y'
|
31 |
+
type: 'checkbox'
|
32 |
+
link_info: ''
|
33 |
+
link_blog: ''
|
34 |
+
-
|
35 |
+
key: 'enable_audit_context_plugins'
|
36 |
+
section: 'section_enable_audit_contexts'
|
37 |
+
default: 'Y'
|
38 |
+
type: 'checkbox'
|
39 |
+
link_info: ''
|
40 |
+
link_blog: ''
|
41 |
+
-
|
42 |
+
key: 'enable_audit_context_themes'
|
43 |
+
section: 'section_enable_audit_contexts'
|
44 |
+
default: 'Y'
|
45 |
+
type: 'checkbox'
|
46 |
+
link_info: ''
|
47 |
+
link_blog: ''
|
48 |
+
-
|
49 |
+
key: 'enable_audit_context_posts'
|
50 |
+
section: 'section_enable_audit_contexts'
|
51 |
+
default: 'Y'
|
52 |
+
type: 'checkbox'
|
53 |
+
link_info: ''
|
54 |
+
link_blog: ''
|
55 |
+
-
|
56 |
+
key: 'enable_audit_context_wordpress'
|
57 |
+
section: 'section_enable_audit_contexts'
|
58 |
+
default: 'Y'
|
59 |
+
type: 'checkbox'
|
60 |
+
link_info: ''
|
61 |
+
link_blog: ''
|
62 |
+
-
|
63 |
+
key: 'enable_audit_context_wpsf'
|
64 |
+
section: 'section_enable_audit_contexts'
|
65 |
+
default: 'Y'
|
66 |
+
type: 'checkbox'
|
67 |
+
link_info: ''
|
68 |
+
link_blog: ''
|
69 |
+
-
|
70 |
+
key: 'current_plugin_version'
|
71 |
+
section: 'section_non_ui'
|
72 |
+
-
|
73 |
+
key: 'audit_trail_table_name'
|
74 |
+
section: 'section_non_ui'
|
75 |
+
value: 'audit_trail'
|
src/config/feature-autoupdates.txt
ADDED
@@ -0,0 +1,108 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
---
|
2 |
+
slug: 'autoupdates'
|
3 |
+
properties:
|
4 |
+
name: 'Automatic Updates'
|
5 |
+
show_feature_menu_item: true
|
6 |
+
storage_key: 'autoupdates' # should correspond exactly to that in the plugin.yaml
|
7 |
+
# Options Sections
|
8 |
+
sections:
|
9 |
+
-
|
10 |
+
slug: 'section_enable_plugin_feature_automatic_updates_control'
|
11 |
+
primary: true
|
12 |
+
-
|
13 |
+
slug: 'section_disable_all_wordpress_automatic_updates'
|
14 |
+
-
|
15 |
+
slug: 'section_automatic_plugin_self_update'
|
16 |
+
-
|
17 |
+
slug: 'section_automatic_updates_for_wordpress_components'
|
18 |
+
-
|
19 |
+
slug: 'section_automatic_update_email_notifications'
|
20 |
+
-
|
21 |
+
slug: 'section_non_ui'
|
22 |
+
hidden: true
|
23 |
+
|
24 |
+
# Define Options and assign to section slug
|
25 |
+
options:
|
26 |
+
-
|
27 |
+
key: 'enable_autoupdates'
|
28 |
+
section: 'section_enable_plugin_feature_automatic_updates_control'
|
29 |
+
default: 'Y'
|
30 |
+
type: 'checkbox'
|
31 |
+
link_info: 'http://icwp.io/3w'
|
32 |
+
link_blog: ''
|
33 |
+
-
|
34 |
+
key: 'enable_autoupdate_disable_all'
|
35 |
+
section: 'section_disable_all_wordpress_automatic_updates'
|
36 |
+
default: 'N'
|
37 |
+
type: 'checkbox'
|
38 |
+
link_info: 'http://icwp.io/3v'
|
39 |
+
link_blog: ''
|
40 |
+
-
|
41 |
+
key: 'autoupdate_plugin_self'
|
42 |
+
section: 'section_automatic_plugin_self_update'
|
43 |
+
default: 'Y'
|
44 |
+
type: 'checkbox'
|
45 |
+
link_info: 'http://icwp.io/3u'
|
46 |
+
link_blog: ''
|
47 |
+
-
|
48 |
+
key: 'autoupdate_core'
|
49 |
+
section: 'section_automatic_updates_for_wordpress_components'
|
50 |
+
default: 'core_minor'
|
51 |
+
type: 'select'
|
52 |
+
value_options:
|
53 |
+
-
|
54 |
+
value_key: 'core_never'
|
55 |
+
text: 'Never'
|
56 |
+
-
|
57 |
+
value_key: 'core_minor'
|
58 |
+
text: 'Minor Versions Only'
|
59 |
+
-
|
60 |
+
value_key: 'core_major'
|
61 |
+
text: 'Major and Minor Versions'
|
62 |
+
link_info: 'http://icwp.io/3x'
|
63 |
+
link_blog: ''
|
64 |
+
-
|
65 |
+
key: 'enable_autoupdate_plugins'
|
66 |
+
section: 'section_automatic_updates_for_wordpress_components'
|
67 |
+
default: 'N'
|
68 |
+
type: 'checkbox'
|
69 |
+
link_info: ''
|
70 |
+
link_blog: ''
|
71 |
+
-
|
72 |
+
key: 'enable_autoupdate_themes'
|
73 |
+
section: 'section_automatic_updates_for_wordpress_components'
|
74 |
+
default: 'N'
|
75 |
+
type: 'checkbox'
|
76 |
+
link_info: ''
|
77 |
+
link_blog: ''
|
78 |
+
-
|
79 |
+
key: 'enable_autoupdate_translations'
|
80 |
+
section: 'section_automatic_updates_for_wordpress_components'
|
81 |
+
default: 'Y'
|
82 |
+
type: 'checkbox'
|
83 |
+
link_info: ''
|
84 |
+
link_blog: ''
|
85 |
+
-
|
86 |
+
key: 'enable_autoupdate_ignore_vcs'
|
87 |
+
section: 'section_automatic_updates_for_wordpress_components'
|
88 |
+
default: 'N'
|
89 |
+
type: 'checkbox'
|
90 |
+
link_info: ''
|
91 |
+
link_blog: ''
|
92 |
+
-
|
93 |
+
key: 'enable_upgrade_notification_email'
|
94 |
+
section: 'section_automatic_update_email_notifications'
|
95 |
+
default: ''
|
96 |
+
type: 'checkbox'
|
97 |
+
link_info: ''
|
98 |
+
link_blog: ''
|
99 |
+
-
|
100 |
+
key: 'override_email_address'
|
101 |
+
section: 'section_automatic_update_email_notifications'
|
102 |
+
default: ''
|
103 |
+
type: 'email'
|
104 |
+
link_info: ''
|
105 |
+
link_blog: ''
|
106 |
+
-
|
107 |
+
key: 'current_plugin_version'
|
108 |
+
section: 'section_non_ui'
|
src/config/feature-comments_filter.txt
ADDED
@@ -0,0 +1,172 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
---
|
2 |
+
slug: 'comments_filter'
|
3 |
+
properties:
|
4 |
+
name: 'Comments Filter'
|
5 |
+
show_feature_menu_item: true
|
6 |
+
storage_key: 'commentsfilter' # should correspond exactly to that in the plugin.yaml
|
7 |
+
# Options Sections
|
8 |
+
sections:
|
9 |
+
-
|
10 |
+
slug: 'section_enable_plugin_feature_spam_comments_protection_filter'
|
11 |
+
primary: true
|
12 |
+
-
|
13 |
+
slug: 'section_enable_human_comment_spam_protection_filter'
|
14 |
+
-
|
15 |
+
slug: 'section_enable_automatic_bot_comment_spam_protection_filter'
|
16 |
+
-
|
17 |
+
slug: 'section_customize_messages_shown_to_user'
|
18 |
+
-
|
19 |
+
slug: 'section_non_ui'
|
20 |
+
hidden: true
|
21 |
+
|
22 |
+
# Define Options and assign to section slug
|
23 |
+
options:
|
24 |
+
-
|
25 |
+
key: 'enable_comments_filter'
|
26 |
+
section: 'section_enable_plugin_feature_spam_comments_protection_filter'
|
27 |
+
default: 'N'
|
28 |
+
type: 'checkbox'
|
29 |
+
link_info: 'http://icwp.io/3z'
|
30 |
+
link_blog: 'http://icwp.io/wpsf04'
|
31 |
+
-
|
32 |
+
key: 'enable_comments_human_spam_filter'
|
33 |
+
section: 'section_enable_human_comment_spam_protection_filter'
|
34 |
+
default: 'N'
|
35 |
+
type: 'checkbox'
|
36 |
+
link_info: 'http://icwp.io/57'
|
37 |
+
link_blog: ''
|
38 |
+
-
|
39 |
+
key: 'enable_comments_human_spam_filter_items'
|
40 |
+
section: 'section_enable_human_comment_spam_protection_filter'
|
41 |
+
type: 'multiple_select'
|
42 |
+
default:
|
43 |
+
- 'author_name'
|
44 |
+
- 'author_email'
|
45 |
+
- 'comment_content'
|
46 |
+
- 'url'
|
47 |
+
- 'ip_address'
|
48 |
+
- 'user_agent'
|
49 |
+
value_options:
|
50 |
+
-
|
51 |
+
value_key: 'author_name'
|
52 |
+
text: 'Author Name'
|
53 |
+
-
|
54 |
+
value_key: 'author_email'
|
55 |
+
text: 'Author Email'
|
56 |
+
-
|
57 |
+
value_key: 'comment_content'
|
58 |
+
text: 'Comment Content'
|
59 |
+
-
|
60 |
+
value_key: 'url'
|
61 |
+
text: 'URL'
|
62 |
+
-
|
63 |
+
value_key: 'ip_address'
|
64 |
+
text: 'IP Address'
|
65 |
+
-
|
66 |
+
value_key: 'user_agent'
|
67 |
+
text: 'Browser User Agent'
|
68 |
+
|
69 |
+
link_info: 'http://icwp.io/58'
|
70 |
+
link_blog: ''
|
71 |
+
-
|
72 |
+
key: 'comments_default_action_human_spam'
|
73 |
+
section: 'section_enable_human_comment_spam_protection_filter'
|
74 |
+
default: 'spam'
|
75 |
+
type: 'select'
|
76 |
+
value_options:
|
77 |
+
-
|
78 |
+
value_key: 0
|
79 |
+
text: 'Mark As Pending Moderation'
|
80 |
+
-
|
81 |
+
value_key: 'spam'
|
82 |
+
text: 'Mark As SPAM'
|
83 |
+
-
|
84 |
+
value_key: 'trash'
|
85 |
+
text: 'Move To Trash'
|
86 |
+
-
|
87 |
+
value_key: 'reject'
|
88 |
+
text: 'Reject And Redirect'
|
89 |
+
-
|
90 |
+
key: 'enable_comments_gasp_protection'
|
91 |
+
section: 'section_enable_automatic_bot_comment_spam_protection_filter'
|
92 |
+
default: 'Y'
|
93 |
+
type: 'checkbox'
|
94 |
+
link_info: 'http://icwp.io/3n'
|
95 |
+
link_blog: 'http://icwp.io/2n'
|
96 |
+
-
|
97 |
+
key: 'enable_comments_gasp_protection_for_logged_in'
|
98 |
+
section: 'section_enable_automatic_bot_comment_spam_protection_filter'
|
99 |
+
default: 'N'
|
100 |
+
type: 'checkbox'
|
101 |
+
link_info: ''
|
102 |
+
link_blog: ''
|
103 |
+
-
|
104 |
+
key: 'comments_default_action_spam_bot'
|
105 |
+
section: 'section_enable_automatic_bot_comment_spam_protection_filter'
|
106 |
+
default: 'trash'
|
107 |
+
type: 'select'
|
108 |
+
value_options:
|
109 |
+
-
|
110 |
+
value_key: 0
|
111 |
+
text: 'Mark As Pending Moderation'
|
112 |
+
-
|
113 |
+
value_key: 'spam'
|
114 |
+
text: 'Mark As SPAM'
|
115 |
+
-
|
116 |
+
value_key: 'trash'
|
117 |
+
text: 'Move To Trash'
|
118 |
+
-
|
119 |
+
value_key: 'reject'
|
120 |
+
text: 'Reject And Redirect'
|
121 |
+
|
122 |
+
link_info: 'http://icwp.io/3x'
|
123 |
+
link_blog: ''
|
124 |
+
-
|
125 |
+
key: 'comments_cooldown_interval'
|
126 |
+
section: 'section_enable_automatic_bot_comment_spam_protection_filter'
|
127 |
+
default: 30
|
128 |
+
type: 'integer'
|
129 |
+
link_info: 'http://icwp.io/3o'
|
130 |
+
link_blog: ''
|
131 |
+
-
|
132 |
+
key: 'comments_token_expire_interval'
|
133 |
+
section: 'section_enable_automatic_bot_comment_spam_protection_filter'
|
134 |
+
default: 600
|
135 |
+
type: 'integer'
|
136 |
+
link_info: 'http://icwp.io/3o'
|
137 |
+
link_blog: ''
|
138 |
+
-
|
139 |
+
key: 'custom_message_checkbox'
|
140 |
+
section: 'section_customize_messages_shown_to_user'
|
141 |
+
default: "I'm not a spammer"
|
142 |
+
type: 'text'
|
143 |
+
link_info: 'http://icwp.io/3p'
|
144 |
+
link_blog: ''
|
145 |
+
-
|
146 |
+
key: 'custom_message_alert'
|
147 |
+
section: 'section_customize_messages_shown_to_user'
|
148 |
+
default: "Please check the box to confirm you're not a spammer"
|
149 |
+
type: 'text'
|
150 |
+
link_info: 'http://icwp.io/3p'
|
151 |
+
link_blog: ''
|
152 |
+
-
|
153 |
+
key: 'custom_message_comment_wait'
|
154 |
+
section: 'section_customize_messages_shown_to_user'
|
155 |
+
default: "Please wait %s seconds before posting your comment"
|
156 |
+
type: 'text'
|
157 |
+
link_info: 'http://icwp.io/3p'
|
158 |
+
link_blog: ''
|
159 |
+
-
|
160 |
+
key: 'custom_message_comment_reload'
|
161 |
+
section: 'section_customize_messages_shown_to_user'
|
162 |
+
default: "Please reload this page to post a comment"
|
163 |
+
type: 'text'
|
164 |
+
link_info: 'http://icwp.io/3p'
|
165 |
+
link_blog: ''
|
166 |
+
-
|
167 |
+
key: 'current_plugin_version'
|
168 |
+
section: 'section_non_ui'
|
169 |
+
-
|
170 |
+
key: 'spambot_comments_filter_table_name'
|
171 |
+
section: 'section_non_ui'
|
172 |
+
value: 'spambot_comments_filter'
|
src/config/feature-email.txt
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
---
|
2 |
+
slug: 'email'
|
3 |
+
properties:
|
4 |
+
name: 'Email'
|
5 |
+
show_feature_menu_item: false
|
6 |
+
storage_key: 'email' # should correspond exactly to that in the plugin.yaml
|
7 |
+
# Options Sections
|
8 |
+
sections:
|
9 |
+
-
|
10 |
+
slug: 'section_email_options'
|
11 |
+
primary: true
|
12 |
+
-
|
13 |
+
slug: 'section_non_ui'
|
14 |
+
hidden: true
|
15 |
+
|
16 |
+
# Define Options
|
17 |
+
options:
|
18 |
+
-
|
19 |
+
key: 'block_send_email_address'
|
20 |
+
section: 'section_email_options'
|
21 |
+
default: ''
|
22 |
+
type: 'email'
|
23 |
+
link_info: ''
|
24 |
+
link_blog: ''
|
25 |
+
-
|
26 |
+
key: 'send_email_throttle_limit'
|
27 |
+
section: 'section_email_options'
|
28 |
+
default: 10
|
29 |
+
type: 'integer'
|
30 |
+
link_info: ''
|
31 |
+
link_blog: ''
|
32 |
+
-
|
33 |
+
key: 'current_plugin_version'
|
34 |
+
section: 'section_non_ui'
|
src/config/feature-firewall.txt
ADDED
@@ -0,0 +1,155 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
---
|
2 |
+
slug: 'firewall'
|
3 |
+
properties:
|
4 |
+
name: 'Firewall'
|
5 |
+
show_feature_menu_item: true
|
6 |
+
storage_key: 'firewall' # should correspond exactly to that in the plugin.yaml
|
7 |
+
# Options Sections
|
8 |
+
sections:
|
9 |
+
-
|
10 |
+
slug: 'section_enable_plugin_feature_wordpress_firewall'
|
11 |
+
primary: true
|
12 |
+
-
|
13 |
+
slug: 'section_firewall_blocking_options'
|
14 |
+
-
|
15 |
+
slug: 'section_choose_firewall_block_response'
|
16 |
+
-
|
17 |
+
slug: 'section_whitelist'
|
18 |
+
-
|
19 |
+
slug: 'section_blacklist'
|
20 |
+
-
|
21 |
+
slug: 'section_firewall_logging'
|
22 |
+
-
|
23 |
+
slug: 'section_non_ui'
|
24 |
+
hidden: true
|
25 |
+
|
26 |
+
# Define Options
|
27 |
+
options:
|
28 |
+
-
|
29 |
+
key: 'enable_firewall'
|
30 |
+
section: 'section_enable_plugin_feature_wordpress_firewall'
|
31 |
+
default: 'N'
|
32 |
+
type: 'checkbox'
|
33 |
+
link_info: 'http://icwp.io/43'
|
34 |
+
link_blog: 'http://icwp.io/wpsf01'
|
35 |
+
-
|
36 |
+
key: 'include_cookie_checks'
|
37 |
+
section: 'section_firewall_blocking_options'
|
38 |
+
default: 'N'
|
39 |
+
type: 'checkbox'
|
40 |
+
link_info: ''
|
41 |
+
link_blog: ''
|
42 |
+
-
|
43 |
+
key: 'block_dir_traversal'
|
44 |
+
section: 'section_firewall_blocking_options'
|
45 |
+
default: 'Y'
|
46 |
+
type: 'checkbox'
|
47 |
+
link_info: ''
|
48 |
+
link_blog: ''
|
49 |
+
-
|
50 |
+
key: 'block_sql_queries'
|
51 |
+
section: 'section_firewall_blocking_options'
|
52 |
+
default: 'Y'
|
53 |
+
type: 'checkbox'
|
54 |
+
link_info: ''
|
55 |
+
link_blog: ''
|
56 |
+
-
|
57 |
+
key: 'block_wordpress_terms'
|
58 |
+
section: 'section_firewall_blocking_options'
|
59 |
+
default: 'N'
|
60 |
+
type: 'checkbox'
|
61 |
+
link_info: ''
|
62 |
+
link_blog: ''
|
63 |
+
-
|
64 |
+
key: 'block_field_truncation'
|
65 |
+
section: 'section_firewall_blocking_options'
|
66 |
+
default: 'Y'
|
67 |
+
type: 'checkbox'
|
68 |
+
link_info: ''
|
69 |
+
link_blog: ''
|
70 |
+
-
|
71 |
+
key: 'block_php_code'
|
72 |
+
section: 'section_firewall_blocking_options'
|
73 |
+
default: 'N'
|
74 |
+
type: 'checkbox'
|
75 |
+
link_info: ''
|
76 |
+
link_blog: ''
|
77 |
+
-
|
78 |
+
key: 'block_exe_file_uploads'
|
79 |
+
section: 'section_firewall_blocking_options'
|
80 |
+
default: 'N'
|
81 |
+
type: 'checkbox'
|
82 |
+
link_info: ''
|
83 |
+
link_blog: ''
|
84 |
+
-
|
85 |
+
key: 'block_response'
|
86 |
+
section: 'section_choose_firewall_block_response'
|
87 |
+
default: 'redirect_die_message'
|
88 |
+
type: 'select'
|
89 |
+
value_options:
|
90 |
+
-
|
91 |
+
value_key: 'redirect_die_message'
|
92 |
+
text: 'Die With Message'
|
93 |
+
-
|
94 |
+
value_key: 'redirect_die'
|
95 |
+
text: 'Die'
|
96 |
+
-
|
97 |
+
value_key: 'redirect_home'
|
98 |
+
text: 'Redirect To Home Page'
|
99 |
+
-
|
100 |
+
value_key: 'redirect_404'
|
101 |
+
text: 'Return 404'
|
102 |
+
link_info: ''
|
103 |
+
link_blog: ''
|
104 |
+
-
|
105 |
+
key: 'block_send_email'
|
106 |
+
section: 'section_choose_firewall_block_response'
|
107 |
+
default: 'N'
|
108 |
+
type: 'checkbox'
|
109 |
+
link_info: ''
|
110 |
+
link_blog: ''
|
111 |
+
-
|
112 |
+
key: 'ips_whitelist'
|
113 |
+
section: 'section_whitelist'
|
114 |
+
default: ''
|
115 |
+
type: 'ip_addresses'
|
116 |
+
link_info: ''
|
117 |
+
link_blog: ''
|
118 |
+
-
|
119 |
+
key: 'page_params_whitelist'
|
120 |
+
section: 'section_whitelist'
|
121 |
+
default: ''
|
122 |
+
type: 'comma_separated_lists'
|
123 |
+
link_info: 'http://icwp.io/2a'
|
124 |
+
link_blog: ''
|
125 |
+
-
|
126 |
+
key: 'whitelist_admins'
|
127 |
+
section: 'section_whitelist'
|
128 |
+
default: 'N'
|
129 |
+
type: 'checkbox'
|
130 |
+
link_info: ''
|
131 |
+
link_blog: ''
|
132 |
+
-
|
133 |
+
key: 'ignore_search_engines'
|
134 |
+
section: 'section_whitelist'
|
135 |
+
default: 'N'
|
136 |
+
type: 'checkbox'
|
137 |
+
link_info: ''
|
138 |
+
link_blog: ''
|
139 |
+
-
|
140 |
+
key: 'ips_blacklist'
|
141 |
+
section: 'section_blacklist'
|
142 |
+
default: ''
|
143 |
+
type: 'ip_addresses'
|
144 |
+
link_info: ''
|
145 |
+
link_blog: ''
|
146 |
+
-
|
147 |
+
key: 'enable_firewall_log'
|
148 |
+
section: 'section_firewall_logging'
|
149 |
+
default: 'N'
|
150 |
+
type: 'checkbox'
|
151 |
+
link_info: ''
|
152 |
+
link_blog: ''
|
153 |
+
-
|
154 |
+
key: 'current_plugin_version'
|
155 |
+
section: 'section_non_ui'
|
src/config/feature-lockdown.txt
ADDED
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
---
|
2 |
+
slug: 'lockdown'
|
3 |
+
properties:
|
4 |
+
name: 'Lockdown'
|
5 |
+
show_feature_menu_item: true
|
6 |
+
storage_key: 'lockdown' # should correspond exactly to that in the plugin.yaml
|
7 |
+
# Options Sections
|
8 |
+
sections:
|
9 |
+
-
|
10 |
+
slug: 'section_enable_plugin_feature_wordpress_lockdown'
|
11 |
+
primary: true
|
12 |
+
-
|
13 |
+
slug: 'section_permission_access_options'
|
14 |
+
-
|
15 |
+
slug: 'section_wordpress_obscurity_options'
|
16 |
+
-
|
17 |
+
slug: 'section_non_ui'
|
18 |
+
hidden: true
|
19 |
+
|
20 |
+
# Define Options
|
21 |
+
options:
|
22 |
+
-
|
23 |
+
key: 'enable_lockdown'
|
24 |
+
section: 'section_enable_plugin_feature_wordpress_lockdown'
|
25 |
+
default: 'N'
|
26 |
+
type: 'checkbox'
|
27 |
+
link_info: 'http://icwp.io/4r'
|
28 |
+
link_blog: ''
|
29 |
+
-
|
30 |
+
key: 'disable_file_editing'
|
31 |
+
section: 'section_permission_access_options'
|
32 |
+
default: 'N'
|
33 |
+
type: 'checkbox'
|
34 |
+
link_info: 'http://icwp.io/4q'
|
35 |
+
link_blog: ''
|
36 |
+
-
|
37 |
+
key: 'force_ssl_login'
|
38 |
+
section: 'section_permission_access_options'
|
39 |
+
default: 'N'
|
40 |
+
type: 'checkbox'
|
41 |
+
link_info: 'http://icwp.io/4s'
|
42 |
+
link_blog: ''
|
43 |
+
-
|
44 |
+
key: 'force_ssl_admin'
|
45 |
+
section: 'section_permission_access_options'
|
46 |
+
default: 'N'
|
47 |
+
type: 'checkbox'
|
48 |
+
link_info: 'http://icwp.io/4t'
|
49 |
+
link_blog: ''
|
50 |
+
-
|
51 |
+
key: 'mask_wordpress_version'
|
52 |
+
section: 'section_wordpress_obscurity_options'
|
53 |
+
default: ''
|
54 |
+
type: 'text'
|
55 |
+
link_info: 'http://icwp.io/43'
|
56 |
+
link_blog: ''
|
57 |
+
-
|
58 |
+
key: 'hide_wordpress_generator_tag'
|
59 |
+
section: 'section_wordpress_obscurity_options'
|
60 |
+
default: 'N'
|
61 |
+
type: 'checkbox'
|
62 |
+
link_info: ''
|
63 |
+
link_blog: ''
|
64 |
+
-
|
65 |
+
key: 'current_plugin_version'
|
66 |
+
section: 'section_non_ui'
|
src/config/feature-logging.txt
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
---
|
2 |
+
slug: 'logging'
|
3 |
+
properties:
|
4 |
+
name: 'Logging'
|
5 |
+
show_feature_menu_item: false
|
6 |
+
storage_key: 'logging' # should correspond exactly to that in the plugin.yaml
|
7 |
+
# Options Sections
|
8 |
+
sections:
|
9 |
+
-
|
10 |
+
slug: 'section_non_ui'
|
11 |
+
hidden: true
|
12 |
+
|
13 |
+
# Define Options
|
14 |
+
options:
|
15 |
+
-
|
16 |
+
key: 'enable_logging'
|
17 |
+
section: 'section_non_ui'
|
18 |
+
type: 'boolean'
|
19 |
+
default: true
|
20 |
+
-
|
21 |
+
key: 'general_logging_table_name'
|
22 |
+
section: 'section_non_ui'
|
23 |
+
type: 'text'
|
24 |
+
value: 'general_logging'
|
25 |
+
-
|
26 |
+
key: 'current_plugin_version'
|
27 |
+
section: 'section_non_ui'
|
src/config/feature-login_protect.txt
ADDED
@@ -0,0 +1,182 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
---
|
2 |
+
slug: 'login_protect'
|
3 |
+
properties:
|
4 |
+
name: 'Login Protection'
|
5 |
+
show_feature_menu_item: true
|
6 |
+
storage_key: 'loginprotect' # should correspond exactly to that in the plugin.yaml
|
7 |
+
# Options Sections
|
8 |
+
sections:
|
9 |
+
-
|
10 |
+
slug: 'section_enable_plugin_feature_login_protection'
|
11 |
+
primary: true
|
12 |
+
-
|
13 |
+
slug: 'section_bypass_login_protection'
|
14 |
+
-
|
15 |
+
slug: 'section_two_factor_authentication'
|
16 |
+
-
|
17 |
+
slug: 'section_brute_force_login_protection'
|
18 |
+
-
|
19 |
+
slug: 'section_yubikey_authentication'
|
20 |
+
-
|
21 |
+
slug: 'section_login_logging'
|
22 |
+
-
|
23 |
+
slug: 'section_non_ui'
|
24 |
+
hidden: true
|
25 |
+
|
26 |
+
# Define Options
|
27 |
+
options:
|
28 |
+
-
|
29 |
+
key: 'enable_login_protect'
|
30 |
+
section: 'section_enable_plugin_feature_login_protection'
|
31 |
+
default: 'N'
|
32 |
+
type: 'checkbox'
|
33 |
+
link_info: 'http://icwp.io/51'
|
34 |
+
link_blog: 'http://icwp.io/wpsf03'
|
35 |
+
-
|
36 |
+
key: 'enable_xmlrpc_compatibility'
|
37 |
+
section: 'section_bypass_login_protection'
|
38 |
+
default: 'Y'
|
39 |
+
type: 'checkbox'
|
40 |
+
link_info: ''
|
41 |
+
link_blog: ''
|
42 |
+
-
|
43 |
+
key: 'ips_whitelist'
|
44 |
+
section: 'section_bypass_login_protection'
|
45 |
+
default: ''
|
46 |
+
type: 'ip_addresses'
|
47 |
+
link_info: 'http://icwp.io/52'
|
48 |
+
link_blog: ''
|
49 |
+
-
|
50 |
+
key: 'two_factor_auth_user_roles'
|
51 |
+
section: 'section_two_factor_authentication'
|
52 |
+
type: 'multiple_select'
|
53 |
+
default:
|
54 |
+
- 1
|
55 |
+
- 2
|
56 |
+
- 3
|
57 |
+
- 8
|
58 |
+
value_options:
|
59 |
+
-
|
60 |
+
value_key: 0
|
61 |
+
text: 'Subscribers'
|
62 |
+
-
|
63 |
+
value_key: 1
|
64 |
+
text: 'Contributors'
|
65 |
+
-
|
66 |
+
value_key: 2
|
67 |
+
text: 'Authors'
|
68 |
+
-
|
69 |
+
value_key: 3
|
70 |
+
text: 'Editors'
|
71 |
+
-
|
72 |
+
value_key: 8
|
73 |
+
text: 'Administrators'
|
74 |
+
link_info: 'http://icwp.io/4v'
|
75 |
+
link_blog: ''
|
76 |
+
-
|
77 |
+
key: 'enable_two_factor_auth_by_ip'
|
78 |
+
section: 'section_two_factor_authentication'
|
79 |
+
default: 'N'
|
80 |
+
type: 'checkbox'
|
81 |
+
link_info: 'http://icwp.io/3s'
|
82 |
+
link_blog: ''
|
83 |
+
-
|
84 |
+
key: 'enable_two_factor_auth_by_cookie'
|
85 |
+
section: 'section_two_factor_authentication'
|
86 |
+
default: 'N'
|
87 |
+
type: 'checkbox'
|
88 |
+
link_info: 'http://icwp.io/3t'
|
89 |
+
link_blog: ''
|
90 |
+
-
|
91 |
+
key: 'enable_two_factor_bypass_on_email_fail'
|
92 |
+
section: 'section_two_factor_authentication'
|
93 |
+
default: 'N'
|
94 |
+
type: 'checkbox'
|
95 |
+
link_info: ''
|
96 |
+
link_blog: ''
|
97 |
+
-
|
98 |
+
key: 'login_limit_interval'
|
99 |
+
section: 'section_brute_force_login_protection'
|
100 |
+
default: '10'
|
101 |
+
type: 'integer'
|
102 |
+
link_info: 'http://icwp.io/3q'
|
103 |
+
link_blog: ''
|
104 |
+
-
|
105 |
+
key: 'enable_login_gasp_check'
|
106 |
+
section: 'section_brute_force_login_protection'
|
107 |
+
default: 'Y'
|
108 |
+
type: 'checkbox'
|
109 |
+
link_info: 'http://icwp.io/3r'
|
110 |
+
link_blog: ''
|
111 |
+
-
|
112 |
+
key: 'enable_prevent_remote_post'
|
113 |
+
section: 'section_brute_force_login_protection'
|
114 |
+
default: 'Y'
|
115 |
+
type: 'checkbox'
|
116 |
+
link_info: 'http://icwp.io/4n'
|
117 |
+
link_blog: ''
|
118 |
+
-
|
119 |
+
key: 'enable_yubikey'
|
120 |
+
section: 'section_yubikey_authentication'
|
121 |
+
default: 'N'
|
122 |
+
type: 'checkbox'
|
123 |
+
link_info: 'http://icwp.io/4f'
|
124 |
+
link_blog: ''
|
125 |
+
-
|
126 |
+
key: 'yubikey_app_id'
|
127 |
+
section: 'section_yubikey_authentication'
|
128 |
+
default: ''
|
129 |
+
type: 'text'
|
130 |
+
link_info: 'http://icwp.io/4g'
|
131 |
+
link_blog: ''
|
132 |
+
-
|
133 |
+
key: 'yubikey_api_key'
|
134 |
+
section: 'section_yubikey_authentication'
|
135 |
+
default: ''
|
136 |
+
type: 'text'
|
137 |
+
link_info: 'http://icwp.io/4g'
|
138 |
+
link_blog: ''
|
139 |
+
-
|
140 |
+
key: 'yubikey_unique_keys'
|
141 |
+
section: 'section_yubikey_authentication'
|
142 |
+
default: ''
|
143 |
+
type: 'yubikey_unique_keys'
|
144 |
+
link_info: 'http://icwp.io/4h'
|
145 |
+
link_blog: ''
|
146 |
+
-
|
147 |
+
key: 'enable_login_protect_log'
|
148 |
+
section: 'section_login_logging'
|
149 |
+
hidden: true
|
150 |
+
default: 'N'
|
151 |
+
type: 'checkbox'
|
152 |
+
link_info: 'http://icwp.io/4h'
|
153 |
+
link_blog: ''
|
154 |
+
-
|
155 |
+
key: 'current_plugin_version'
|
156 |
+
section: 'section_non_ui'
|
157 |
+
-
|
158 |
+
key: 'gasp_key'
|
159 |
+
section: 'section_non_ui'
|
160 |
+
-
|
161 |
+
key: 'two_factor_secret_key'
|
162 |
+
section: 'section_non_ui'
|
163 |
+
-
|
164 |
+
key: 'last_login_time'
|
165 |
+
section: 'section_non_ui'
|
166 |
+
-
|
167 |
+
key: 'last_login_time_file_path'
|
168 |
+
section: 'section_non_ui'
|
169 |
+
-
|
170 |
+
key: 'log_category'
|
171 |
+
section: 'section_non_ui'
|
172 |
+
-
|
173 |
+
key: 'two_factor_auth_table_name'
|
174 |
+
section: 'section_non_ui'
|
175 |
+
value: 'login_auth'
|
176 |
+
-
|
177 |
+
key: 'two_factor_auth_cookie_name'
|
178 |
+
section: 'section_non_ui'
|
179 |
+
value: 'wpsf_auth'
|
180 |
+
-
|
181 |
+
key: 'two_factor_auth_table_created'
|
182 |
+
section: 'section_non_ui'
|
src/config/feature-plugin.txt
ADDED
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
---
|
2 |
+
slug: 'plugin'
|
3 |
+
properties:
|
4 |
+
name: 'Dashboard'
|
5 |
+
show_feature_menu_item: true
|
6 |
+
storage_key: 'plugin' # should correspond exactly to that in the plugin.yaml
|
7 |
+
# Options Sections
|
8 |
+
sections:
|
9 |
+
-
|
10 |
+
slug: 'section_general_plugin_options'
|
11 |
+
primary: true
|
12 |
+
-
|
13 |
+
slug: 'section_non_ui'
|
14 |
+
hidden: true
|
15 |
+
|
16 |
+
# Define Options
|
17 |
+
options:
|
18 |
+
-
|
19 |
+
key: 'block_send_email_address'
|
20 |
+
section: 'section_general_plugin_options'
|
21 |
+
default: ''
|
22 |
+
type: 'email'
|
23 |
+
link_info: ''
|
24 |
+
link_blog: ''
|
25 |
+
-
|
26 |
+
key: 'enable_upgrade_admin_notice'
|
27 |
+
section: 'section_general_plugin_options'
|
28 |
+
default: 'Y'
|
29 |
+
type: 'checkbox'
|
30 |
+
link_info: ''
|
31 |
+
link_blog: ''
|
32 |
+
-
|
33 |
+
key: 'delete_on_deactivate'
|
34 |
+
section: 'section_general_plugin_options'
|
35 |
+
default: 'N'
|
36 |
+
type: 'checkbox'
|
37 |
+
link_info: ''
|
38 |
+
link_blog: ''
|
39 |
+
-
|
40 |
+
key: 'current_plugin_version'
|
41 |
+
section: 'section_non_ui'
|
42 |
+
-
|
43 |
+
key: 'secret_key'
|
44 |
+
section: 'section_non_ui'
|
45 |
+
-
|
46 |
+
key: 'installation_time'
|
47 |
+
section: 'section_non_ui'
|
48 |
+
-
|
49 |
+
key: 'feedback_admin_notice'
|
50 |
+
section: 'section_non_ui'
|
51 |
+
-
|
52 |
+
key: 'update_success_tracker'
|
53 |
+
section: 'section_non_ui'
|
54 |
+
-
|
55 |
+
key: 'capability_can_disk_write'
|
56 |
+
section: 'section_non_ui'
|
57 |
+
-
|
58 |
+
key: 'capability_can_remote_get'
|
59 |
+
section: 'section_non_ui'
|
60 |
+
-
|
61 |
+
key: 'active_plugin_features'
|
62 |
+
section: 'section_non_ui'
|
63 |
+
value:
|
64 |
+
-
|
65 |
+
slug: 'admin_access_restriction'
|
66 |
+
storage_key: 'admin_access_restriction'
|
67 |
+
-
|
68 |
+
slug: 'firewall'
|
69 |
+
storage_key: 'firewall'
|
70 |
+
-
|
71 |
+
slug: 'login_protect'
|
72 |
+
storage_key: 'loginprotect'
|
73 |
+
-
|
74 |
+
slug: 'user_management'
|
75 |
+
storage_key: 'user_management'
|
76 |
+
-
|
77 |
+
slug: 'comments_filter'
|
78 |
+
storage_key: 'commentsfilter'
|
79 |
+
-
|
80 |
+
slug: 'autoupdates'
|
81 |
+
storage_key: 'autoupdates'
|
82 |
+
-
|
83 |
+
slug: 'lockdown'
|
84 |
+
storage_key: 'lockdown'
|
85 |
+
-
|
86 |
+
slug: 'audit_trail'
|
87 |
+
storage_key: 'audit_trail'
|
88 |
+
hidden: true
|
89 |
+
-
|
90 |
+
slug: 'email'
|
91 |
+
storage_key: 'email'
|
92 |
+
-
|
93 |
+
slug: 'logging'
|
94 |
+
storage_key: 'logging'
|
src/config/feature-user_management.txt
ADDED
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
---
|
2 |
+
slug: 'user_management'
|
3 |
+
properties:
|
4 |
+
name: 'User Management'
|
5 |
+
show_feature_menu_item: true
|
6 |
+
storage_key: 'user_management' # should correspond exactly to that in the plugin.yaml
|
7 |
+
# Options Sections
|
8 |
+
sections:
|
9 |
+
-
|
10 |
+
slug: 'section_enable_plugin_feature_user_accounts_management'
|
11 |
+
primary: true
|
12 |
+
-
|
13 |
+
slug: 'section_bypass_user_accounts_management'
|
14 |
+
-
|
15 |
+
slug: 'section_admin_login_notification'
|
16 |
+
-
|
17 |
+
slug: 'section_user_session_management'
|
18 |
+
-
|
19 |
+
slug: 'section_non_ui'
|
20 |
+
hidden: true
|
21 |
+
|
22 |
+
# Define Options
|
23 |
+
options:
|
24 |
+
-
|
25 |
+
key: 'enable_user_management'
|
26 |
+
section: 'section_enable_plugin_feature_user_accounts_management'
|
27 |
+
default: 'N'
|
28 |
+
type: 'checkbox'
|
29 |
+
link_info: ''
|
30 |
+
link_blog: ''
|
31 |
+
-
|
32 |
+
key: 'enable_xmlrpc_compatibility'
|
33 |
+
section: 'section_bypass_user_accounts_management'
|
34 |
+
default: 'Y'
|
35 |
+
type: 'checkbox'
|
36 |
+
link_info: ''
|
37 |
+
link_blog: ''
|
38 |
+
-
|
39 |
+
key: 'enable_admin_login_email_notification'
|
40 |
+
section: 'section_admin_login_notification'
|
41 |
+
default: ''
|
42 |
+
type: 'email'
|
43 |
+
link_info: 'http://icwp.io/3u'
|
44 |
+
link_blog: ''
|
45 |
+
-
|
46 |
+
key: 'session_timeout_interval'
|
47 |
+
section: 'section_user_session_management'
|
48 |
+
default: '2'
|
49 |
+
type: 'integer'
|
50 |
+
link_info: 'http://icwp.io/3x'
|
51 |
+
link_blog: ''
|
52 |
+
-
|
53 |
+
key: 'session_idle_timeout_interval'
|
54 |
+
section: 'section_user_session_management'
|
55 |
+
default: '0'
|
56 |
+
type: 'integer'
|
57 |
+
link_info: ''
|
58 |
+
link_blog: ''
|
59 |
+
-
|
60 |
+
key: 'session_lock_location'
|
61 |
+
section: 'section_user_session_management'
|
62 |
+
default: 'N'
|
63 |
+
type: 'checkbox'
|
64 |
+
link_info: ''
|
65 |
+
link_blog: ''
|
66 |
+
-
|
67 |
+
key: 'session_username_concurrent_limit'
|
68 |
+
section: 'section_user_session_management'
|
69 |
+
default: '0'
|
70 |
+
type: 'integer'
|
71 |
+
link_info: ''
|
72 |
+
link_blog: ''
|
73 |
+
-
|
74 |
+
key: 'session_check_admin_area_only'
|
75 |
+
hidden: true
|
76 |
+
section: 'section_user_session_management'
|
77 |
+
default: 'Y'
|
78 |
+
type: 'checkbox'
|
79 |
+
link_info: ''
|
80 |
+
link_blog: ''
|
81 |
+
-
|
82 |
+
key: 'session_auto_forward_to_admin_area'
|
83 |
+
hidden: true
|
84 |
+
section: 'section_user_session_management'
|
85 |
+
default: 'Y'
|
86 |
+
type: 'checkbox'
|
87 |
+
link_info: ''
|
88 |
+
link_blog: ''
|
89 |
+
-
|
90 |
+
key: 'current_plugin_version'
|
91 |
+
section: 'section_non_ui'
|
92 |
+
-
|
93 |
+
key: 'user_sessions_table_name'
|
94 |
+
section: 'section_non_ui'
|
95 |
+
value: 'user_management'
|
96 |
+
-
|
97 |
+
key: 'user_session_cookie_name'
|
98 |
+
section: 'section_non_ui'
|
99 |
+
value: 'wpsf_sesh_id'
|
100 |
+
-
|
101 |
+
key: 'user_management_table_created'
|
102 |
+
section: 'section_non_ui'
|
src/icwp-base-processor.php
DELETED
@@ -1,384 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
-
* All rights reserved.
|
5 |
-
*
|
6 |
-
* Version: 2013-08-27-B
|
7 |
-
*
|
8 |
-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
9 |
-
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
10 |
-
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
11 |
-
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
12 |
-
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
13 |
-
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
14 |
-
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
15 |
-
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
16 |
-
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
17 |
-
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
18 |
-
*
|
19 |
-
*/
|
20 |
-
|
21 |
-
if ( !class_exists('ICWP_BaseProcessor_V3') ):
|
22 |
-
|
23 |
-
class ICWP_BaseProcessor_V3 {
|
24 |
-
|
25 |
-
const PcreDelimiter = '/';
|
26 |
-
const LOG_MESSAGE_LEVEL_INFO = 0;
|
27 |
-
const LOG_MESSAGE_LEVEL_WARNING = 1;
|
28 |
-
const LOG_MESSAGE_LEVEL_CRITICAL = 2;
|
29 |
-
|
30 |
-
const LOG_CATEGORY_DEFAULT = 0;
|
31 |
-
const LOG_CATEGORY_FIREWALL = 1;
|
32 |
-
const LOG_CATEGORY_LOGINPROTECT = 2;
|
33 |
-
|
34 |
-
/**
|
35 |
-
* @var array
|
36 |
-
*/
|
37 |
-
protected $m_aLog;
|
38 |
-
/**
|
39 |
-
* @var array
|
40 |
-
*/
|
41 |
-
protected $m_aLogMessages;
|
42 |
-
|
43 |
-
/**
|
44 |
-
* @var long
|
45 |
-
*/
|
46 |
-
protected static $nRequestIp;
|
47 |
-
/**
|
48 |
-
* @var long
|
49 |
-
*/
|
50 |
-
protected static $nRequestPostId;
|
51 |
-
/**
|
52 |
-
* @var integer
|
53 |
-
*/
|
54 |
-
protected static $nRequestTimestamp;
|
55 |
-
|
56 |
-
/**
|
57 |
-
* @var array
|
58 |
-
*/
|
59 |
-
protected $aOptions;
|
60 |
-
|
61 |
-
/**
|
62 |
-
* @var ICWP_WPSF_FeatureHandler_Base
|
63 |
-
*/
|
64 |
-
protected $oFeatureOptions;
|
65 |
-
|
66 |
-
public function __construct( ICWP_WPSF_FeatureHandler_Base $oFeatureOptions ) {
|
67 |
-
$this->oFeatureOptions = $oFeatureOptions;
|
68 |
-
$this->reset();
|
69 |
-
}
|
70 |
-
|
71 |
-
/**
|
72 |
-
* Resets the object values to be re-used anew
|
73 |
-
*/
|
74 |
-
public function reset() {
|
75 |
-
if ( !isset( self::$nRequestIp ) ) {
|
76 |
-
self::$nRequestIp = $this->getVisitorIpAddress();
|
77 |
-
}
|
78 |
-
if ( !isset( self::$nRequestTimestamp ) ) {
|
79 |
-
self::$nRequestTimestamp = time();
|
80 |
-
}
|
81 |
-
$this->resetLog();
|
82 |
-
}
|
83 |
-
|
84 |
-
/**
|
85 |
-
* Override to set what this processor does when it's "run"
|
86 |
-
*/
|
87 |
-
public function run() { }
|
88 |
-
|
89 |
-
/**
|
90 |
-
*/
|
91 |
-
public function deleteStore() {
|
92 |
-
delete_option( $this->constructStorageKey() );
|
93 |
-
}
|
94 |
-
|
95 |
-
/**
|
96 |
-
*
|
97 |
-
* @param array $aOptions
|
98 |
-
*/
|
99 |
-
public function setOptions( &$aOptions ) {
|
100 |
-
$this->aOptions = $aOptions;
|
101 |
-
}
|
102 |
-
|
103 |
-
/**
|
104 |
-
* @param $sOptionKey
|
105 |
-
* @param bool $mDefault
|
106 |
-
* @return bool
|
107 |
-
*/
|
108 |
-
public function getOption( $sOptionKey, $mDefault = false ) {
|
109 |
-
if ( !isset( $this->aOptions ) ) {
|
110 |
-
$this->aOptions = $this->oFeatureOptions->getPluginOptionsValues();
|
111 |
-
}
|
112 |
-
return isset( $this->aOptions[$sOptionKey] )? $this->aOptions[$sOptionKey] : $mDefault;
|
113 |
-
}
|
114 |
-
|
115 |
-
/**
|
116 |
-
* @param $sKey
|
117 |
-
* @param mixed $mValueToTest
|
118 |
-
* @param boolean $fStrict
|
119 |
-
* @return bool
|
120 |
-
*/
|
121 |
-
public function getIsOption( $sKey, $mValueToTest, $fStrict = false ) {
|
122 |
-
$mOptionValue = $this->getOption($sKey);
|
123 |
-
return $fStrict? $mOptionValue === $mValueToTest : $mOptionValue == $mValueToTest;
|
124 |
-
}
|
125 |
-
|
126 |
-
/**
|
127 |
-
* @return bool|long
|
128 |
-
*/
|
129 |
-
public function getRequestPostId() {
|
130 |
-
if ( !isset( self::$nRequestPostId ) ) {
|
131 |
-
global $post;
|
132 |
-
if ( empty( $post ) ) {
|
133 |
-
return false;
|
134 |
-
}
|
135 |
-
self::$nRequestPostId = $post->ID;
|
136 |
-
}
|
137 |
-
return self::$nRequestPostId;
|
138 |
-
}
|
139 |
-
|
140 |
-
/**
|
141 |
-
* Resets the log
|
142 |
-
*/
|
143 |
-
public function resetLog() {
|
144 |
-
$this->m_aLogMessages = array();
|
145 |
-
}
|
146 |
-
|
147 |
-
/**
|
148 |
-
* @return bool
|
149 |
-
*/
|
150 |
-
public function getIsLogging() {
|
151 |
-
return false;
|
152 |
-
}
|
153 |
-
|
154 |
-
/**
|
155 |
-
* Should return false when logging is disabled.
|
156 |
-
*
|
157 |
-
* @return false|array - false when logging is disabled, array with log data otherwise
|
158 |
-
* @see ICWP_WPSF_BaseProcessor::getLogData()
|
159 |
-
*/
|
160 |
-
public function flushLogData() {
|
161 |
-
if ( !$this->getIsLogging() ) {
|
162 |
-
return false;
|
163 |
-
}
|
164 |
-
return false;
|
165 |
-
}
|
166 |
-
|
167 |
-
/**
|
168 |
-
* Builds and returns the full log.
|
169 |
-
*
|
170 |
-
* @return array (associative)
|
171 |
-
*/
|
172 |
-
public function getLogData() {
|
173 |
-
|
174 |
-
if ( $this->getIsLogging() ) {
|
175 |
-
$this->m_aLog = array( 'messages' => serialize( $this->m_aLogMessages ) );
|
176 |
-
}
|
177 |
-
else {
|
178 |
-
$this->m_aLog = false;
|
179 |
-
}
|
180 |
-
|
181 |
-
return $this->m_aLog;
|
182 |
-
}
|
183 |
-
|
184 |
-
/**
|
185 |
-
* @return array
|
186 |
-
*/
|
187 |
-
public function getLogMessages() {
|
188 |
-
if ( !is_array( $this->m_aLogMessages ) ) {
|
189 |
-
$this->m_aLogMessages = array();
|
190 |
-
}
|
191 |
-
return $this->m_aLogMessages;
|
192 |
-
}
|
193 |
-
|
194 |
-
/**
|
195 |
-
* @param string $sLogMessage
|
196 |
-
* @param integer $sMessageType
|
197 |
-
*/
|
198 |
-
public function writeLog( $sLogMessage = '', $sMessageType = self::LOG_MESSAGE_LEVEL_INFO ) {
|
199 |
-
if ( !is_array( $this->m_aLogMessages ) ) {
|
200 |
-
$this->resetLog();
|
201 |
-
}
|
202 |
-
$this->m_aLogMessages[] = array( $sMessageType, $sLogMessage );
|
203 |
-
}
|
204 |
-
/**
|
205 |
-
* @param string $insLogMessage
|
206 |
-
*/
|
207 |
-
public function logInfo( $insLogMessage ) {
|
208 |
-
$this->writeLog( $insLogMessage, self::LOG_MESSAGE_LEVEL_INFO );
|
209 |
-
}
|
210 |
-
/**
|
211 |
-
* @param string $insLogMessage
|
212 |
-
*/
|
213 |
-
public function logWarning( $insLogMessage ) {
|
214 |
-
$this->writeLog( $insLogMessage, self::LOG_MESSAGE_LEVEL_WARNING );
|
215 |
-
}
|
216 |
-
/**
|
217 |
-
* @param string $insLogMessage
|
218 |
-
*/
|
219 |
-
public function logCritical( $insLogMessage ) {
|
220 |
-
$this->writeLog( $insLogMessage, self::LOG_MESSAGE_LEVEL_CRITICAL );
|
221 |
-
}
|
222 |
-
|
223 |
-
/**
|
224 |
-
* @param boolean $infAsLong - visitor IP Address as IP2Long
|
225 |
-
* @return integer - visitor IP Address as IP2Long
|
226 |
-
*/
|
227 |
-
public function getVisitorIpAddress( $infAsLong = true ) {
|
228 |
-
require_once( dirname(__FILE__).'/icwp-data-processor.php' );
|
229 |
-
return ICWP_WPSF_DataProcessor::GetVisitorIpAddress( $infAsLong );
|
230 |
-
}
|
231 |
-
|
232 |
-
/**
|
233 |
-
* @param array $inaIpList
|
234 |
-
* @param integer $innIpAddress
|
235 |
-
* @return boolean
|
236 |
-
*/
|
237 |
-
public function isIpOnlist( $inaIpList, $innIpAddress = '', &$outsLabel = '' ) {
|
238 |
-
|
239 |
-
if ( empty( $innIpAddress ) || !isset( $inaIpList['ips'] ) ) {
|
240 |
-
return false;
|
241 |
-
}
|
242 |
-
|
243 |
-
$outsLabel = '';
|
244 |
-
foreach( $inaIpList['ips'] as $mWhitelistAddress ) {
|
245 |
-
|
246 |
-
$aIps = $this->parseIpAddress( $mWhitelistAddress );
|
247 |
-
if ( count( $aIps ) === 1 ) { //not a range
|
248 |
-
if ( $innIpAddress == $aIps[0] ) {
|
249 |
-
$outsLabel = $inaIpList['meta'][ md5( $mWhitelistAddress ) ];
|
250 |
-
return true;
|
251 |
-
}
|
252 |
-
}
|
253 |
-
else if ( count( $aIps ) == 2 ) {
|
254 |
-
if ( $aIps[0] <= $innIpAddress && $innIpAddress <= $aIps[1] ) {
|
255 |
-
$outsLabel = $inaIpList['meta'][ md5( $mWhitelistAddress ) ];
|
256 |
-
return true;
|
257 |
-
}
|
258 |
-
}
|
259 |
-
}
|
260 |
-
return false;
|
261 |
-
}
|
262 |
-
|
263 |
-
/**
|
264 |
-
* @param string $insIpAddress - an IP or IP address range in LONG format.
|
265 |
-
* @return array - with 1 ip address, or 2 addresses if it is a range.
|
266 |
-
*/
|
267 |
-
protected function parseIpAddress( $insIpAddress ) {
|
268 |
-
|
269 |
-
$aIps = array();
|
270 |
-
|
271 |
-
if ( empty($insIpAddress) ) {
|
272 |
-
return $aIps;
|
273 |
-
}
|
274 |
-
|
275 |
-
// offset=1 in the case that it's a range and the first number is negative on 32-bit systems
|
276 |
-
$mPos = strpos( $insIpAddress, '-', 1 );
|
277 |
-
|
278 |
-
if ( $mPos === false ) { //plain IP address
|
279 |
-
$aIps[] = $insIpAddress;
|
280 |
-
}
|
281 |
-
else {
|
282 |
-
//we remove the first character in case this is '-'
|
283 |
-
$aParts = array( substr( $insIpAddress, 0, 1 ), substr( $insIpAddress, 1 ) );
|
284 |
-
list( $sStart, $sEnd ) = explode( '-', $aParts[1], 2 );
|
285 |
-
$aIps[] = $aParts[0].$sStart;
|
286 |
-
$aIps[] = $sEnd;
|
287 |
-
}
|
288 |
-
return $aIps;
|
289 |
-
}
|
290 |
-
|
291 |
-
/**
|
292 |
-
* @return ICWP_WPSF_EmailProcessor
|
293 |
-
*/
|
294 |
-
public function getEmailProcessor() {
|
295 |
-
return $this->oFeatureOptions->getEmailProcessor();
|
296 |
-
}
|
297 |
-
|
298 |
-
/**
|
299 |
-
* @return ICWP_WPSF_LoggingProcessor
|
300 |
-
*/
|
301 |
-
public function getLoggingProcessor() {
|
302 |
-
return $this->oFeatureOptions->getLoggingProcessor();
|
303 |
-
}
|
304 |
-
|
305 |
-
/**
|
306 |
-
* Checks the $inaData contains valid key values as laid out in $inaChecks
|
307 |
-
*
|
308 |
-
* @param array $aData
|
309 |
-
* @param array $inaChecks
|
310 |
-
* @return boolean
|
311 |
-
*/
|
312 |
-
protected function validateParameters( $aData, $inaChecks ) {
|
313 |
-
|
314 |
-
if ( !is_array( $aData ) ) {
|
315 |
-
return false;
|
316 |
-
}
|
317 |
-
|
318 |
-
foreach( $inaChecks as $sCheck ) {
|
319 |
-
if ( !array_key_exists( $sCheck, $aData ) || empty( $aData[ $sCheck ] ) ) {
|
320 |
-
return false;
|
321 |
-
}
|
322 |
-
}
|
323 |
-
return true;
|
324 |
-
}
|
325 |
-
|
326 |
-
/**
|
327 |
-
* @return string
|
328 |
-
*/
|
329 |
-
protected function constructStorageKey() {
|
330 |
-
return sprintf( '%s%s_processor', $this->oFeatureOptions->getOptionStoragePrefix(), $this->oFeatureOptions->getFeatureSlug() );
|
331 |
-
}
|
332 |
-
|
333 |
-
/**
|
334 |
-
* Override this to provide custom cleanup.
|
335 |
-
*/
|
336 |
-
public function deleteAndCleanUp() {
|
337 |
-
$this->deleteStore();
|
338 |
-
}
|
339 |
-
|
340 |
-
/**
|
341 |
-
*/
|
342 |
-
protected function loadDataProcessor() {
|
343 |
-
if ( !class_exists( 'ICWP_WPSF_DataProcessor' ) ) {
|
344 |
-
require_once( dirname(__FILE__) . '/icwp-data-processor.php' );
|
345 |
-
}
|
346 |
-
}
|
347 |
-
|
348 |
-
/**
|
349 |
-
* @return ICWP_WpFilesystem_WPSF
|
350 |
-
*/
|
351 |
-
protected function loadFileSystemProcessor() {
|
352 |
-
require_once( dirname(__FILE__) . '/icwp-wpfilesystem.php' );
|
353 |
-
return ICWP_WpFilesystem_WPSF::GetInstance();
|
354 |
-
}
|
355 |
-
|
356 |
-
/**
|
357 |
-
* @return ICWP_WpFunctions_WPSF
|
358 |
-
*/
|
359 |
-
protected function loadWpFunctionsProcessor() {
|
360 |
-
require_once( dirname(__FILE__) . '/icwp-wpfunctions.php' );
|
361 |
-
return ICWP_WpFunctions_WPSF::GetInstance();
|
362 |
-
}
|
363 |
-
|
364 |
-
/**
|
365 |
-
* @return ICWP_Stats_WPSF
|
366 |
-
*/
|
367 |
-
protected function loadWpsfStatsProcessor() {
|
368 |
-
require_once( dirname(__FILE__) . '/icwp-wpsf-stats.php' );
|
369 |
-
}
|
370 |
-
|
371 |
-
/**
|
372 |
-
* @param $sStatKey
|
373 |
-
*/
|
374 |
-
protected function doStatIncrement( $sStatKey ) {
|
375 |
-
$this->loadWpsfStatsProcessor();
|
376 |
-
ICWP_Stats_WPSF::DoStatIncrement( $sStatKey );
|
377 |
-
}
|
378 |
-
}
|
379 |
-
|
380 |
-
endif;
|
381 |
-
|
382 |
-
if ( !class_exists('ICWP_WPSF_BaseProcessor') ):
|
383 |
-
class ICWP_WPSF_BaseProcessor extends ICWP_BaseProcessor_V3 { }
|
384 |
-
endif;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/icwp-data-processor.php
CHANGED
@@ -3,8 +3,6 @@
|
|
3 |
/**
|
4 |
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
5 |
* All rights reserved.
|
6 |
-
*
|
7 |
-
* Version: 2013-08-27-A
|
8 |
*
|
9 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
10 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
@@ -19,474 +17,549 @@
|
|
19 |
*
|
20 |
*/
|
21 |
|
22 |
-
if ( !class_exists('
|
23 |
-
|
24 |
-
class
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
}
|
44 |
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
continue;
|
66 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
else {
|
68 |
-
|
69 |
-
return $infAsLong? ip2long( self::$sIpAddress ) : self::$sIpAddress;
|
70 |
}
|
71 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
72 |
}
|
73 |
-
return false;
|
74 |
-
}
|
75 |
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
}
|
86 |
-
|
87 |
-
static public function ExtractIpAddresses( $insAddresses = '' ) {
|
88 |
-
|
89 |
-
$aRawAddresses = array();
|
90 |
-
|
91 |
-
if ( empty( $insAddresses ) ) {
|
92 |
-
return $aRawAddresses;
|
93 |
}
|
94 |
-
$aRawList = array_map( 'trim', explode( "\n", $insAddresses ) );
|
95 |
|
96 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
97 |
|
98 |
-
|
99 |
-
|
100 |
-
if ( empty( $sRawAddressLine ) ) {
|
101 |
-
continue;
|
102 |
}
|
103 |
-
|
104 |
-
|
105 |
-
$
|
106 |
-
|
107 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
108 |
}
|
109 |
-
|
110 |
-
}
|
111 |
-
return self::Add_New_Raw_Ips( array(), $aRawAddresses );
|
112 |
-
}
|
113 |
-
|
114 |
-
static public function ExtractCommaSeparatedList( $insRawList = '' ) {
|
115 |
-
|
116 |
-
$aRawList = array();
|
117 |
-
if ( empty( $insRawList ) ) {
|
118 |
-
return $aRawList;
|
119 |
}
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
|
|
|
|
|
|
|
|
134 |
continue;
|
135 |
}
|
136 |
-
$
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
|
|
143 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
144 |
}
|
145 |
-
|
146 |
-
$aParams = empty( $aParts[1] )? array() : explode( ',', $aParts[1] );
|
147 |
-
$aNewList[ $aParts[0] ] = $aParams;
|
148 |
}
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
166 |
return $inaCurrent;
|
167 |
}
|
168 |
-
|
169 |
-
if ( !array_key_exists( 'ips', $inaCurrent ) ) {
|
170 |
-
$inaCurrent['ips'] = array();
|
171 |
-
}
|
172 |
-
if ( !array_key_exists( 'meta', $inaCurrent ) ) {
|
173 |
-
$inaCurrent['meta'] = array();
|
174 |
-
}
|
175 |
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
182 |
}
|
183 |
-
$inaCurrent['meta'][ md5( $mVerifiedIp ) ] = $sLabel;
|
184 |
-
$outnNewAdded++;
|
185 |
}
|
186 |
-
}
|
187 |
-
return $inaCurrent;
|
188 |
-
}
|
189 |
-
|
190 |
-
/**
|
191 |
-
* @param array $inaCurrent
|
192 |
-
* @param array $inaRawAddresses - should be a plain numerical array of IPv4 addresses
|
193 |
-
* @return array:
|
194 |
-
*/
|
195 |
-
public static function Remove_Raw_Ips( $inaCurrent, $inaRawAddresses ) {
|
196 |
-
if ( empty( $inaRawAddresses ) ) {
|
197 |
return $inaCurrent;
|
198 |
}
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
if ( $
|
210 |
-
|
211 |
}
|
212 |
-
|
213 |
-
|
214 |
-
unset( $inaCurrent['ips'][$mKey] );
|
215 |
-
unset( $inaCurrent['meta'][ md5( $mVerifiedIp ) ] );
|
216 |
}
|
217 |
}
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
return
|
231 |
}
|
232 |
-
}
|
233 |
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
}
|
243 |
-
|
244 |
-
public static function Verify_Ip_Address( $insIpAddress ) {
|
245 |
-
if ( self::$fUseFilter ) {
|
246 |
-
if ( filter_var( $insIpAddress, FILTER_VALIDATE_IP ) ) {
|
247 |
-
return ip2long( $insIpAddress );
|
248 |
}
|
|
|
|
|
|
|
|
|
|
|
249 |
}
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
return ip2long( $insIpAddress );
|
260 |
-
}
|
261 |
}
|
262 |
-
return false;
|
263 |
-
}
|
264 |
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
269 |
|
270 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
271 |
return false;
|
272 |
}
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
// 'UnwindFetchor',
|
293 |
-
// 'urlresolver',
|
294 |
-
// 'Butterfly',
|
295 |
-
// 'TweetmemeBot'
|
296 |
-
// );
|
297 |
-
//
|
298 |
-
// $aCrawlers = array(
|
299 |
-
// 'Google' => 'Google',
|
300 |
-
// 'msnbot' => 'MSN',
|
301 |
-
// 'Rambler' => 'Rambler',
|
302 |
-
// 'Yahoo' => 'Yahoo',
|
303 |
-
// 'AbachoBOT' => 'AbachoBOT',
|
304 |
-
// 'accoona' => 'Accoona',
|
305 |
-
// 'AcoiRobot' => 'AcoiRobot',
|
306 |
-
// 'ASPSeek' => 'ASPSeek',
|
307 |
-
// 'CrocCrawler' => 'CrocCrawler',
|
308 |
-
// 'Dumbot' => 'Dumbot',
|
309 |
-
// 'FAST-WebCrawler' => 'FAST-WebCrawler',
|
310 |
-
// 'GeonaBot' => 'GeonaBot',
|
311 |
-
// 'Gigabot' => 'Gigabot',
|
312 |
-
// 'Lycos' => 'Lycos spider',
|
313 |
-
// 'MSRBOT' => 'MSRBOT',
|
314 |
-
// 'Scooter' => 'Altavista robot',
|
315 |
-
// 'AltaVista' => 'Altavista robot',
|
316 |
-
// 'IDBot' => 'ID-Search Bot',
|
317 |
-
// 'eStyle' => 'eStyle Bot',
|
318 |
-
// 'Scrubby' => 'Scrubby robot'
|
319 |
-
// );
|
320 |
-
|
321 |
-
return array_key_exists( $sUserAgent, $aCrawlers );
|
322 |
-
}
|
323 |
-
|
324 |
-
/**
|
325 |
-
* The only ranges currently accepted are a.b.c.d-f.g.h.j
|
326 |
-
* @param string $insIpAddressRange
|
327 |
-
* @return string|boolean
|
328 |
-
*/
|
329 |
-
public static function Verify_Ip_Range( $insIpAddressRange ) {
|
330 |
-
|
331 |
-
list( $sIpRangeStart, $sIpRangeEnd ) = explode( '-', $insIpAddressRange, 2 );
|
332 |
-
|
333 |
-
if ( $sIpRangeStart == $sIpRangeEnd ) {
|
334 |
-
return self::Verify_Ip_Address( $sIpRangeStart );
|
335 |
-
}
|
336 |
-
else if ( self::Verify_Ip_Address( $sIpRangeStart ) && self::Verify_Ip_Address( $sIpRangeEnd ) ) {
|
337 |
-
$nStart = ip2long( $sIpRangeStart );
|
338 |
-
$nEnd = ip2long( $sIpRangeEnd );
|
339 |
-
|
340 |
-
// do our best to order it
|
341 |
-
if (
|
342 |
-
( $nStart > 0 && $nEnd > 0 && $nStart > $nEnd )
|
343 |
-
|| ( $nStart < 0 && $nEnd < 0 && $nStart > $nEnd )
|
344 |
-
) {
|
345 |
-
$nTemp = $nStart;
|
346 |
-
$nStart = $nEnd;
|
347 |
-
$nEnd = $nTemp;
|
348 |
}
|
349 |
-
return $
|
350 |
}
|
351 |
-
return false;
|
352 |
-
}
|
353 |
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
360 |
}
|
361 |
-
$
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
}
|
366 |
-
|
367 |
-
$aKeys[$nIndex] = array( $aParts[0] => $aParts[1] );
|
368 |
}
|
369 |
-
return $aKeys;
|
370 |
-
}
|
371 |
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
static public function GenerateRandomString( $innLength = 10, $infBeginLetter = false ) {
|
378 |
-
$aChars = array( 'abcdefghijkmnopqrstuvwxyz' );
|
379 |
-
$aChars[] = 'ABCDEFGHJKLMNPQRSTUVWXYZ';
|
380 |
-
|
381 |
-
$sCharset = implode( '', $aChars );
|
382 |
-
if ( $infBeginLetter ) {
|
383 |
-
$sPassword = $sCharset[ ( rand() % strlen( $sCharset ) ) ];
|
384 |
}
|
385 |
-
|
386 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
387 |
}
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
|
|
|
|
|
|
392 |
}
|
393 |
-
return $sPassword;
|
394 |
-
}
|
395 |
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
if ( function_exists( 'filter_input' ) && defined( 'INPUT_SERVER' ) ) {
|
402 |
-
$sPossible = filter_input( INPUT_SERVER, $sKey );
|
403 |
-
if ( !empty( $sPossible ) ) {
|
404 |
-
return $sPossible;
|
405 |
-
}
|
406 |
}
|
407 |
-
return self::ArrayFetch( $_SERVER, $sKey );
|
408 |
-
}
|
409 |
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
if (
|
418 |
-
return $
|
419 |
}
|
|
|
420 |
}
|
421 |
-
return self::ArrayFetch( $_ENV, $sKey );
|
422 |
-
}
|
423 |
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
}
|
|
|
436 |
}
|
437 |
-
return $mFetchVal;
|
438 |
-
}
|
439 |
-
/**
|
440 |
-
* @param string $insKey
|
441 |
-
* @return mixed|null
|
442 |
-
*/
|
443 |
-
public static function FetchGet( $insKey ) {
|
444 |
-
if ( function_exists( 'filter_input' ) && defined( 'INPUT_GET' ) ) {
|
445 |
-
return filter_input( INPUT_GET, $insKey );
|
446 |
-
}
|
447 |
-
return self::ArrayFetch( $_GET, $insKey );
|
448 |
-
}
|
449 |
-
/**
|
450 |
-
* @param string $insKey The $_POST key
|
451 |
-
* @return mixed|null
|
452 |
-
*/
|
453 |
-
public static function FetchPost( $insKey ) {
|
454 |
-
if ( function_exists( 'filter_input' ) && defined( 'INPUT_POST' ) ) {
|
455 |
-
return filter_input( INPUT_POST, $insKey );
|
456 |
-
}
|
457 |
-
return self::ArrayFetch( $_POST, $insKey );
|
458 |
-
}
|
459 |
-
/**
|
460 |
-
* @param string $insKey The $_POST key
|
461 |
-
* @param mixed $mDefault
|
462 |
-
* @return mixed|null
|
463 |
-
*/
|
464 |
-
public static function FetchCookie( $insKey, $mDefault = null ) {
|
465 |
-
if ( function_exists( 'filter_input' ) && defined( 'INPUT_COOKIE' ) ) {
|
466 |
-
return filter_input( INPUT_COOKIE, $insKey );
|
467 |
-
}
|
468 |
-
return self::ArrayFetch( $_COOKIE, $insKey, $mDefault );
|
469 |
-
}
|
470 |
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
480 |
}
|
481 |
-
|
482 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
483 |
}
|
484 |
-
return $inaArray[$insKey];
|
485 |
}
|
486 |
-
}
|
487 |
-
|
488 |
endif;
|
489 |
|
490 |
if ( !class_exists('ICWP_WPSF_DataProcessor') ):
|
491 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
492 |
endif;
|
3 |
/**
|
4 |
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
5 |
* All rights reserved.
|
|
|
|
|
6 |
*
|
7 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
8 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
17 |
*
|
18 |
*/
|
19 |
|
20 |
+
if ( !class_exists('ICWP_WPSF_DataProcessor_V3') ):
|
21 |
+
|
22 |
+
class ICWP_WPSF_DataProcessor_V3 {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var ICWP_WPSF_DataProcessor_V3
|
26 |
+
*/
|
27 |
+
protected static $oInstance = NULL;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @var bool
|
31 |
+
*/
|
32 |
+
public static $fUseFilterInput = false;
|
33 |
+
|
34 |
+
/**
|
35 |
+
* @var string
|
36 |
+
*/
|
37 |
+
protected static $sIpAddress;
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @var integer
|
41 |
+
*/
|
42 |
+
protected static $nRequestTime;
|
43 |
+
|
44 |
+
/**
|
45 |
+
* @return int
|
46 |
+
*/
|
47 |
+
public static function GetRequestTime() {
|
48 |
+
if ( empty( self::$nRequestTime ) ) {
|
49 |
+
self::$nRequestTime = time();
|
50 |
+
}
|
51 |
+
return self::$nRequestTime;
|
52 |
}
|
53 |
|
54 |
+
/**
|
55 |
+
* Cloudflare compatible.
|
56 |
+
*
|
57 |
+
* @param boolean $fAsLong
|
58 |
+
* @return bool|integer - visitor IP Address as IP2Long
|
59 |
+
*/
|
60 |
+
public static function GetVisitorIpAddress( $fAsLong = true ) {
|
61 |
+
|
62 |
+
if ( !empty( self::$sIpAddress ) ) {
|
63 |
+
return $fAsLong? ip2long( self::$sIpAddress ) : self::$sIpAddress;
|
64 |
+
}
|
65 |
+
|
66 |
+
$aAddressSourceOptions = array(
|
67 |
+
'HTTP_CF_CONNECTING_IP',
|
68 |
+
'HTTP_CLIENT_IP',
|
69 |
+
'HTTP_X_FORWARDED_FOR',
|
70 |
+
'HTTP_X_FORWARDED',
|
71 |
+
'HTTP_FORWARDED',
|
72 |
+
'REMOTE_ADDR'
|
73 |
+
);
|
74 |
+
$fCanUseFilter = function_exists( 'filter_var' ) && defined( 'FILTER_FLAG_NO_PRIV_RANGE' ) && defined( 'FILTER_FLAG_IPV4' );
|
75 |
+
|
76 |
+
foreach( $aAddressSourceOptions as $sOption ) {
|
77 |
+
|
78 |
+
$sIpAddressToTest = self::FetchServer( $sOption );
|
79 |
+
if ( empty( $sIpAddressToTest ) ) {
|
80 |
continue;
|
81 |
}
|
82 |
+
|
83 |
+
$aIpAddresses = explode( ',', $sIpAddressToTest ); //sometimes a comma-separated list is returned
|
84 |
+
foreach( $aIpAddresses as $sIpAddress ) {
|
85 |
+
|
86 |
+
if ( $fCanUseFilter && !self::IsAddressInPublicIpRange( $sIpAddress ) ) {
|
87 |
+
continue;
|
88 |
+
}
|
89 |
+
else {
|
90 |
+
self::$sIpAddress = $sIpAddress;
|
91 |
+
return $fAsLong? ip2long( self::$sIpAddress ) : self::$sIpAddress;
|
92 |
+
}
|
93 |
+
}
|
94 |
+
}
|
95 |
+
return false;
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* For now will return true when it's a valid IPv4 or IPv6 address and you have access to filter_var()
|
100 |
+
*
|
101 |
+
* otherwise, if it's Ipv6 it'll return false always or will attempt to manually parse IPv4.
|
102 |
+
*
|
103 |
+
* @param string
|
104 |
+
* @return boolean
|
105 |
+
*/
|
106 |
+
public static function GetIsValidIpAddress( $sIpAddress ) {
|
107 |
+
if ( function_exists('filter_var') && defined('FILTER_VALIDATE_IP') && defined('FILTER_FLAG_IPV4') && defined('FILTER_FLAG_IPV6') ) {
|
108 |
+
|
109 |
+
if ( filter_var( $sIpAddress, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ) {
|
110 |
+
return true;
|
111 |
+
}
|
112 |
else {
|
113 |
+
return filter_var( $sIpAddress, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 );
|
|
|
114 |
}
|
115 |
}
|
116 |
+
|
117 |
+
if ( preg_match( '/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\z/', $sIpAddress ) ) { //It's a valid IPv4 format, now check components
|
118 |
+
$aParts = explode( '.', $sIpAddress );
|
119 |
+
foreach ( $aParts as $sPart ) {
|
120 |
+
$sPart = intval( $sPart );
|
121 |
+
if ( $sPart < 0 || $sPart > 255 ) {
|
122 |
+
return false;
|
123 |
+
}
|
124 |
+
}
|
125 |
+
return true;
|
126 |
+
}
|
127 |
+
|
128 |
+
return false;
|
129 |
}
|
|
|
|
|
130 |
|
131 |
+
/**
|
132 |
+
* Assumes a valid IPv4 address is provided as we're only testing for a whether the IP is public or not.
|
133 |
+
*
|
134 |
+
* @param string $sIpAddress
|
135 |
+
* @uses filter_var
|
136 |
+
* @return boolean
|
137 |
+
*/
|
138 |
+
public static function IsAddressInPublicIpRange( $sIpAddress ) {
|
139 |
+
return function_exists('filter_var') && filter_var( $sIpAddress, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
140 |
}
|
|
|
141 |
|
142 |
+
/**
|
143 |
+
* @param string $sAddresses
|
144 |
+
* @return Ambigous|array|unknown
|
145 |
+
*/
|
146 |
+
static public function ExtractIpAddresses( $sAddresses = '' ) {
|
147 |
+
|
148 |
+
$aRawAddresses = array();
|
149 |
|
150 |
+
if ( empty( $sAddresses ) ) {
|
151 |
+
return $aRawAddresses;
|
|
|
|
|
152 |
}
|
153 |
+
$aRawList = array_map( 'trim', explode( "\n", $sAddresses ) );
|
154 |
+
|
155 |
+
foreach( $aRawList as $sKey => $sRawAddressLine ) {
|
156 |
+
|
157 |
+
if ( empty( $sRawAddressLine ) ) {
|
158 |
+
continue;
|
159 |
+
}
|
160 |
+
|
161 |
+
// Each line can have a Label which is the IP separated with a space.
|
162 |
+
$aParts = explode( ' ', $sRawAddressLine, 2 );
|
163 |
+
if ( count( $aParts ) == 1 ) {
|
164 |
+
$aParts[] = '';
|
165 |
+
}
|
166 |
+
$aRawAddresses[ $aParts[0] ] = trim( $aParts[1] );
|
167 |
}
|
168 |
+
return self::Add_New_Raw_Ips( array(), $aRawAddresses );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
169 |
}
|
170 |
+
|
171 |
+
/**
|
172 |
+
* @param string $sRawList
|
173 |
+
* @return array
|
174 |
+
*/
|
175 |
+
static public function ExtractCommaSeparatedList( $sRawList = '' ) {
|
176 |
+
|
177 |
+
$aRawList = array();
|
178 |
+
if ( empty( $sRawList ) ) {
|
179 |
+
return $aRawList;
|
180 |
+
}
|
181 |
+
|
182 |
+
$aRawList = array_map( 'trim', preg_split( '/\r\n|\r|\n/', $sRawList ) );
|
183 |
+
$aNewList = array();
|
184 |
+
$fHadStar = false;
|
185 |
+
foreach( $aRawList as $sKey => $sRawLine ) {
|
186 |
+
|
187 |
+
if ( empty( $sRawLine ) ) {
|
188 |
continue;
|
189 |
}
|
190 |
+
$sRawLine = str_replace( ' ', '', $sRawLine );
|
191 |
+
$aParts = explode( ',', $sRawLine, 2 );
|
192 |
+
// we only permit 1x line beginning with *
|
193 |
+
if ( $aParts[0] == '*' ) {
|
194 |
+
if ( $fHadStar ) {
|
195 |
+
continue;
|
196 |
+
}
|
197 |
+
$fHadStar = true;
|
198 |
}
|
199 |
+
else {
|
200 |
+
//If there's only 1 item on the line, we assume it to be a global
|
201 |
+
// parameter rule
|
202 |
+
if ( count( $aParts ) == 1 || empty( $aParts[1] ) ) { // there was no comma in this line in the first place
|
203 |
+
array_unshift( $aParts, '*' );
|
204 |
+
}
|
205 |
+
}
|
206 |
+
|
207 |
+
$aParams = empty( $aParts[1] )? array() : explode( ',', $aParts[1] );
|
208 |
+
$aNewList[ $aParts[0] ] = $aParams;
|
209 |
}
|
210 |
+
return $aNewList;
|
|
|
|
|
211 |
}
|
212 |
+
|
213 |
+
/**
|
214 |
+
* Given a list of new IPv4 address ($inaNewRawAddresses) it'll add them to the existing list
|
215 |
+
* ($inaCurrent) where they're not already found
|
216 |
+
*
|
217 |
+
* @param array $inaCurrent - the list to which to add the new addresses
|
218 |
+
* @param array $inaNewRawAddresses - the new IPv4 addresses
|
219 |
+
* @param int $outnNewAdded - the count of newly added IPs
|
220 |
+
* @return unknown|Ambigous <multitype:multitype: , string>
|
221 |
+
*/
|
222 |
+
public static function Add_New_Raw_Ips( $inaCurrent, $inaNewRawAddresses, &$outnNewAdded = 0 ) {
|
223 |
+
|
224 |
+
$outnNewAdded = 0;
|
225 |
+
|
226 |
+
if ( empty( $inaNewRawAddresses ) ) {
|
227 |
+
return $inaCurrent;
|
228 |
+
}
|
229 |
+
|
230 |
+
if ( !array_key_exists( 'ips', $inaCurrent ) ) {
|
231 |
+
$inaCurrent['ips'] = array();
|
232 |
+
}
|
233 |
+
if ( !array_key_exists( 'meta', $inaCurrent ) ) {
|
234 |
+
$inaCurrent['meta'] = array();
|
235 |
+
}
|
236 |
+
|
237 |
+
foreach( $inaNewRawAddresses as $sRawIpAddress => $sLabel ) {
|
238 |
+
$mVerifiedIp = self::Verify_Ip( $sRawIpAddress );
|
239 |
+
if ( $mVerifiedIp !== false && !in_array( $mVerifiedIp, $inaCurrent['ips'] ) ) {
|
240 |
+
$inaCurrent['ips'][] = $mVerifiedIp;
|
241 |
+
if ( empty($sLabel) ) {
|
242 |
+
$sLabel = 'no label';
|
243 |
+
}
|
244 |
+
$inaCurrent['meta'][ md5( $mVerifiedIp ) ] = $sLabel;
|
245 |
+
$outnNewAdded++;
|
246 |
+
}
|
247 |
+
}
|
248 |
return $inaCurrent;
|
249 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
250 |
|
251 |
+
/**
|
252 |
+
* @param array $inaCurrent
|
253 |
+
* @param array $inaRawAddresses - should be a plain numerical array of IPv4 addresses
|
254 |
+
* @return array:
|
255 |
+
*/
|
256 |
+
public static function Remove_Raw_Ips( $inaCurrent, $inaRawAddresses ) {
|
257 |
+
if ( empty( $inaRawAddresses ) ) {
|
258 |
+
return $inaCurrent;
|
259 |
+
}
|
260 |
+
|
261 |
+
if ( !array_key_exists( 'ips', $inaCurrent ) ) {
|
262 |
+
$inaCurrent['ips'] = array();
|
263 |
+
}
|
264 |
+
if ( !array_key_exists( 'meta', $inaCurrent ) ) {
|
265 |
+
$inaCurrent['meta'] = array();
|
266 |
+
}
|
267 |
+
|
268 |
+
foreach( $inaRawAddresses as $sRawIpAddress ) {
|
269 |
+
$mVerifiedIp = self::Verify_Ip( $sRawIpAddress );
|
270 |
+
if ( $mVerifiedIp === false ) {
|
271 |
+
continue;
|
272 |
+
}
|
273 |
+
$mKey = array_search( $mVerifiedIp, $inaCurrent['ips'] );
|
274 |
+
if ( $mKey !== false ) {
|
275 |
+
unset( $inaCurrent['ips'][$mKey] );
|
276 |
+
unset( $inaCurrent['meta'][ md5( $mVerifiedIp ) ] );
|
277 |
}
|
|
|
|
|
278 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
279 |
return $inaCurrent;
|
280 |
}
|
281 |
+
|
282 |
+
/**
|
283 |
+
* @param string $sIpAddress
|
284 |
+
* @return bool|int|string
|
285 |
+
*/
|
286 |
+
public static function Verify_Ip( $sIpAddress ) {
|
287 |
+
|
288 |
+
$sAddress = self::Clean_Ip( $sIpAddress );
|
289 |
+
|
290 |
+
// Now, determine if this is an IP range, or just a plain IP address.
|
291 |
+
if ( strpos( $sAddress, '-' ) === false ) { //plain IP address
|
292 |
+
return self::Verify_Ip_Address( $sAddress );
|
293 |
}
|
294 |
+
else {
|
295 |
+
return self::Verify_Ip_Range( $sAddress );
|
|
|
|
|
296 |
}
|
297 |
}
|
298 |
+
|
299 |
+
/**
|
300 |
+
* @param string $insRawAddress
|
301 |
+
* @return mixed
|
302 |
+
*/
|
303 |
+
public static function Clean_Ip( $insRawAddress ) {
|
304 |
+
$insRawAddress = preg_replace( '/[a-z\s]/i', '', $insRawAddress );
|
305 |
+
$insRawAddress = str_replace( '.', 'PERIOD', $insRawAddress );
|
306 |
+
$insRawAddress = str_replace( '-', 'HYPEN', $insRawAddress );
|
307 |
+
$insRawAddress = preg_replace( '/[^a-z0-9]/i', '', $insRawAddress );
|
308 |
+
$insRawAddress = str_replace( 'PERIOD', '.', $insRawAddress );
|
309 |
+
$insRawAddress = str_replace( 'HYPEN', '-', $insRawAddress );
|
310 |
+
return $insRawAddress;
|
311 |
}
|
|
|
312 |
|
313 |
+
/**
|
314 |
+
* Taken from http://www.phacks.net/detecting-search-engine-bot-and-web-spiders/
|
315 |
+
*/
|
316 |
+
public static function IsSearchEngineBot() {
|
317 |
+
|
318 |
+
$sUserAgent = self::FetchServer( 'HTTP_USER_AGENT' );
|
319 |
+
if ( empty( $sUserAgent ) ) {
|
320 |
+
return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
321 |
}
|
322 |
+
|
323 |
+
$sBots = 'Googlebot|bingbot|Twitterbot|Baiduspider|ia_archiver|R6_FeedFetcher|NetcraftSurveyAgent'
|
324 |
+
.'|Sogou web spider|Yahoo! Slurp|facebookexternalhit|PrintfulBot|msnbot|UnwindFetchor|urlresolver|Butterfly|TweetmemeBot';
|
325 |
+
|
326 |
+
return ( preg_match( "/$sBots/", $sUserAgent ) > 0 );
|
327 |
}
|
328 |
+
|
329 |
+
/**
|
330 |
+
* Returns IP Address as long if verified.
|
331 |
+
*
|
332 |
+
* @param string $sIpAddress
|
333 |
+
* @return bool|int
|
334 |
+
*/
|
335 |
+
public static function Verify_Ip_Address( $sIpAddress ) {
|
336 |
+
return self::GetIsValidIpAddress( $sIpAddress ) ? ip2long( $sIpAddress ) : false;
|
|
|
|
|
337 |
}
|
|
|
|
|
338 |
|
339 |
+
/**
|
340 |
+
* The only ranges currently accepted are a.b.c.d-f.g.h.j
|
341 |
+
*
|
342 |
+
* @param string $sIpAddressRange
|
343 |
+
* @return string|boolean
|
344 |
+
*/
|
345 |
+
public static function Verify_Ip_Range( $sIpAddressRange ) {
|
346 |
+
|
347 |
+
list( $sIpRangeStart, $sIpRangeEnd ) = explode( '-', $sIpAddressRange, 2 );
|
348 |
+
|
349 |
+
if ( $sIpRangeStart == $sIpRangeEnd ) {
|
350 |
+
return self::Verify_Ip_Address( $sIpRangeStart );
|
351 |
+
}
|
352 |
+
else if ( self::Verify_Ip_Address( $sIpRangeStart ) && self::Verify_Ip_Address( $sIpRangeEnd ) ) {
|
353 |
+
$nStart = ip2long( $sIpRangeStart );
|
354 |
+
$nEnd = ip2long( $sIpRangeEnd );
|
355 |
|
356 |
+
// do our best to order it
|
357 |
+
if (
|
358 |
+
( $nStart > 0 && $nEnd > 0 && $nStart > $nEnd )
|
359 |
+
|| ( $nStart < 0 && $nEnd < 0 && $nStart > $nEnd )
|
360 |
+
) {
|
361 |
+
$nTemp = $nStart;
|
362 |
+
$nStart = $nEnd;
|
363 |
+
$nEnd = $nTemp;
|
364 |
+
}
|
365 |
+
return $nStart.'-'.$nEnd;
|
366 |
+
}
|
367 |
return false;
|
368 |
}
|
369 |
+
|
370 |
+
/**
|
371 |
+
* @param $sRawKeys
|
372 |
+
* @return array
|
373 |
+
*/
|
374 |
+
public static function CleanYubikeyUniqueKeys( $sRawKeys ) {
|
375 |
+
$aKeys = explode( "\n", $sRawKeys );
|
376 |
+
foreach( $aKeys as $nIndex => $sUsernameKey ) {
|
377 |
+
if ( empty( $sUsernameKey ) ) {
|
378 |
+
unset( $aKeys[$nIndex] );
|
379 |
+
continue;
|
380 |
+
}
|
381 |
+
$aParts = array_map( 'trim', explode( ',', $sUsernameKey ) );
|
382 |
+
if ( empty( $aParts[0] ) || empty( $aParts[1] ) || strlen( $aParts[1] ) < 12 ) {
|
383 |
+
unset( $aKeys[$nIndex] );
|
384 |
+
continue;
|
385 |
+
}
|
386 |
+
$aParts[1] = substr( $aParts[1], 0, 12 );
|
387 |
+
$aKeys[$nIndex] = array( $aParts[0] => $aParts[1] );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
388 |
}
|
389 |
+
return $aKeys;
|
390 |
}
|
|
|
|
|
391 |
|
392 |
+
/**
|
393 |
+
* @param integer $nLength
|
394 |
+
* @param boolean $fBeginLetter
|
395 |
+
* @return string
|
396 |
+
*/
|
397 |
+
static public function GenerateRandomString( $nLength = 10, $fBeginLetter = false ) {
|
398 |
+
$aChars = array( 'abcdefghijkmnopqrstuvwxyz' );
|
399 |
+
$aChars[] = 'ABCDEFGHJKLMNPQRSTUVWXYZ';
|
400 |
+
|
401 |
+
$sCharset = implode( '', $aChars );
|
402 |
+
if ( $fBeginLetter ) {
|
403 |
+
$sPassword = $sCharset[ ( rand() % strlen( $sCharset ) ) ];
|
404 |
+
}
|
405 |
+
else {
|
406 |
+
$sPassword = '';
|
407 |
}
|
408 |
+
$sCharset .= '023456789';
|
409 |
+
|
410 |
+
for ( $i = $fBeginLetter? 1 : 0; $i < $nLength; $i++ ) {
|
411 |
+
$sPassword .= $sCharset[ ( rand() % strlen( $sCharset ) ) ];
|
412 |
}
|
413 |
+
return $sPassword;
|
|
|
414 |
}
|
|
|
|
|
415 |
|
416 |
+
/**
|
417 |
+
* @return bool
|
418 |
+
*/
|
419 |
+
static public function GetIsRequestPost() {
|
420 |
+
return ( self::GetRequestMethod() == 'post' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
421 |
}
|
422 |
+
|
423 |
+
/**
|
424 |
+
* Returns the current request method as an all-lower-case string
|
425 |
+
*
|
426 |
+
* @return bool|string
|
427 |
+
*/
|
428 |
+
static public function GetRequestMethod() {
|
429 |
+
$sRequestMethod = self::FetchServer( 'REQUEST_METHOD' );
|
430 |
+
return ( empty( $sRequestMethod ) ? false : strtolower( $sRequestMethod ) );
|
431 |
}
|
432 |
+
|
433 |
+
/**
|
434 |
+
* @return string|null
|
435 |
+
*/
|
436 |
+
static public function GetScriptName() {
|
437 |
+
$sScriptName = self::FetchServer( 'SCRIPT_NAME' );
|
438 |
+
return !empty( $sScriptName )? $sScriptName : self::FetchServer( 'PHP_SELF' );
|
439 |
}
|
|
|
|
|
440 |
|
441 |
+
/**
|
442 |
+
* @return bool
|
443 |
+
*/
|
444 |
+
static public function GetUseFilterInput() {
|
445 |
+
return self::$fUseFilterInput && function_exists( 'filter_input' );
|
|
|
|
|
|
|
|
|
|
|
446 |
}
|
|
|
|
|
447 |
|
448 |
+
/**
|
449 |
+
* @param array $aArray
|
450 |
+
* @param string $sKey The array key to fetch
|
451 |
+
* @param mixed $mDefault
|
452 |
+
* @return mixed|null
|
453 |
+
*/
|
454 |
+
public static function ArrayFetch( &$aArray, $sKey, $mDefault = null ) {
|
455 |
+
if ( empty( $aArray ) || !isset( $aArray[$sKey] ) ) {
|
456 |
+
return $mDefault;
|
457 |
}
|
458 |
+
return $aArray[$sKey];
|
459 |
}
|
|
|
|
|
460 |
|
461 |
+
/**
|
462 |
+
* @param string $sKey The $_COOKIE key
|
463 |
+
* @param mixed $mDefault
|
464 |
+
* @return mixed|null
|
465 |
+
*/
|
466 |
+
public static function FetchCookie( $sKey, $mDefault = null ) {
|
467 |
+
if ( self::GetUseFilterInput() && defined( 'INPUT_COOKIE' ) ) {
|
468 |
+
$mPossible = filter_input( INPUT_COOKIE, $sKey );
|
469 |
+
if ( !empty( $mPossible ) ) {
|
470 |
+
return $mPossible;
|
471 |
+
}
|
472 |
}
|
473 |
+
return self::ArrayFetch( $_COOKIE, $sKey, $mDefault );
|
474 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
475 |
|
476 |
+
/**
|
477 |
+
* @param string $sKey
|
478 |
+
* @param mixed $mDefault
|
479 |
+
* @return mixed|null
|
480 |
+
*/
|
481 |
+
public static function FetchEnv( $sKey, $mDefault = null ) {
|
482 |
+
if ( self::GetUseFilterInput() && defined( 'INPUT_ENV' ) ) {
|
483 |
+
$sPossible = filter_input( INPUT_ENV, $sKey );
|
484 |
+
if ( !empty( $sPossible ) ) {
|
485 |
+
return $sPossible;
|
486 |
+
}
|
487 |
+
}
|
488 |
+
return self::ArrayFetch( $_ENV, $sKey, $mDefault );
|
489 |
+
}
|
490 |
+
/**
|
491 |
+
* @param string $sKey
|
492 |
+
* @param mixed $mDefault
|
493 |
+
* @return mixed|null
|
494 |
+
*/
|
495 |
+
public static function FetchGet( $sKey, $mDefault = null ) {
|
496 |
+
if ( self::GetUseFilterInput() && defined( 'INPUT_GET' ) ) {
|
497 |
+
$mPossible = filter_input( INPUT_GET, $sKey );
|
498 |
+
if ( !empty( $mPossible ) ) {
|
499 |
+
return $mPossible;
|
500 |
+
}
|
501 |
+
}
|
502 |
+
return self::ArrayFetch( $_GET, $sKey, $mDefault );
|
503 |
+
}
|
504 |
+
/**
|
505 |
+
* @param string $sKey The $_POST key
|
506 |
+
* @param mixed $mDefault
|
507 |
+
* @return mixed|null
|
508 |
+
*/
|
509 |
+
public static function FetchPost( $sKey, $mDefault = null ) {
|
510 |
+
if ( self::GetUseFilterInput() && defined( 'INPUT_POST' ) ) {
|
511 |
+
$mPossible = filter_input( INPUT_POST, $sKey );
|
512 |
+
if ( !empty( $mPossible ) ) {
|
513 |
+
return $mPossible;
|
514 |
+
}
|
515 |
+
}
|
516 |
+
return self::ArrayFetch( $_POST, $sKey, $mDefault );
|
517 |
+
}
|
518 |
+
/**
|
519 |
+
* @param string $sKey
|
520 |
+
* @param boolean $infIncludeCookie
|
521 |
+
* @param mixed $mDefault
|
522 |
+
* @return mixed|null
|
523 |
+
*/
|
524 |
+
public static function FetchRequest( $sKey, $infIncludeCookie = true, $mDefault = null ) {
|
525 |
+
$mFetchVal = self::FetchPost( $sKey );
|
526 |
+
if ( is_null( $mFetchVal ) ) {
|
527 |
+
$mFetchVal = self::FetchGet( $sKey );
|
528 |
+
if ( is_null( $mFetchVal && $infIncludeCookie ) ) {
|
529 |
+
$mFetchVal = self::FetchCookie( $sKey );
|
530 |
+
}
|
531 |
+
}
|
532 |
+
return is_null( $mFetchVal )? $mDefault : $mFetchVal;
|
533 |
}
|
534 |
+
|
535 |
+
/**
|
536 |
+
* @param string $sKey
|
537 |
+
* @param mixed $mDefault
|
538 |
+
* @return mixed|null
|
539 |
+
*/
|
540 |
+
public static function FetchServer( $sKey, $mDefault = null ) {
|
541 |
+
if ( self::GetUseFilterInput() && defined( 'INPUT_SERVER' ) ) {
|
542 |
+
$sPossible = filter_input( INPUT_SERVER, $sKey );
|
543 |
+
if ( !empty( $sPossible ) ) {
|
544 |
+
return $sPossible;
|
545 |
+
}
|
546 |
+
}
|
547 |
+
return self::ArrayFetch( $_SERVER, $sKey, $mDefault );
|
548 |
}
|
|
|
549 |
}
|
|
|
|
|
550 |
endif;
|
551 |
|
552 |
if ( !class_exists('ICWP_WPSF_DataProcessor') ):
|
553 |
+
|
554 |
+
class ICWP_WPSF_DataProcessor extends ICWP_WPSF_DataProcessor_V3 {
|
555 |
+
/**
|
556 |
+
* @return ICWP_WPSF_DataProcessor
|
557 |
+
*/
|
558 |
+
public static function GetInstance() {
|
559 |
+
if ( is_null( self::$oInstance ) ) {
|
560 |
+
self::$oInstance = new self();
|
561 |
+
}
|
562 |
+
return self::$oInstance;
|
563 |
+
}
|
564 |
+
}
|
565 |
endif;
|
src/icwp-foundation.php
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class ICWP_WPSF_Foundation {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @return ICWP_WPSF_DataProcessor
|
7 |
+
*/
|
8 |
+
public function loadDataProcessor() {
|
9 |
+
require_once( 'icwp-data-processor.php' );
|
10 |
+
return ICWP_WPSF_DataProcessor::GetInstance();
|
11 |
+
}
|
12 |
+
|
13 |
+
/**
|
14 |
+
* @return ICWP_WPSF_WpFilesystem
|
15 |
+
*/
|
16 |
+
public function loadFileSystemProcessor() {
|
17 |
+
require_once( 'icwp-wpfilesystem.php' );
|
18 |
+
return ICWP_WPSF_WpFilesystem::GetInstance();
|
19 |
+
}
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @return ICWP_WPSF_WpFunctions
|
23 |
+
*/
|
24 |
+
public function loadWpFunctionsProcessor() {
|
25 |
+
require_once( 'icwp-wpfunctions.php' );
|
26 |
+
return ICWP_WPSF_WpFunctions::GetInstance();
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @return ICWP_WPSF_YamlProcessor
|
31 |
+
*/
|
32 |
+
public function loadYamlProcessor() {
|
33 |
+
require_once( 'icwp-processor-yaml.php' );
|
34 |
+
return ICWP_WPSF_YamlProcessor::GetInstance();
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* @return ICWP_Stats_WPSF
|
39 |
+
*/
|
40 |
+
public function loadStatsProcessor() {
|
41 |
+
require_once( 'icwp-wpsf-stats.php' );
|
42 |
+
}
|
43 |
+
|
44 |
+
}
|
src/icwp-import-base-processor.php
DELETED
@@ -1,84 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
-
* All rights reserved.
|
5 |
-
*
|
6 |
-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
7 |
-
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
8 |
-
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
9 |
-
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
10 |
-
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
11 |
-
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
12 |
-
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
13 |
-
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
14 |
-
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
15 |
-
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
-
*
|
17 |
-
*/
|
18 |
-
|
19 |
-
require_once( dirname(__FILE__).'/icwp-base-processor.php' );
|
20 |
-
require_once( dirname(__FILE__).'/icwp-data-processor.php' );
|
21 |
-
|
22 |
-
if ( !class_exists('ICWP_ImportBaseProcessor') ):
|
23 |
-
|
24 |
-
class ICWP_ImportBaseProcessor extends ICWP_WPSF_BaseProcessor {
|
25 |
-
|
26 |
-
/**
|
27 |
-
* The options prefix used by the target plugin
|
28 |
-
* @var string
|
29 |
-
*/
|
30 |
-
protected $m_sOptionPrefix;
|
31 |
-
|
32 |
-
/**
|
33 |
-
* The value of all the options of the source plugin (keys of the options map array)
|
34 |
-
* @var array
|
35 |
-
*/
|
36 |
-
protected $m_aSourceValues;
|
37 |
-
|
38 |
-
/**
|
39 |
-
* An associative array of option keys from the source plugin mapped to the keys of the target plugin
|
40 |
-
* @var unknown_type
|
41 |
-
*/
|
42 |
-
protected $m_aOptionsMap;
|
43 |
-
|
44 |
-
public function __construct( $sTargetOptionPrefix = '' ) {
|
45 |
-
$this->m_sOptionPrefix = $sTargetOptionPrefix;
|
46 |
-
}
|
47 |
-
|
48 |
-
public function runImport() {
|
49 |
-
$this->populateSourceOptions();
|
50 |
-
$this->mapOptionsToTarget();
|
51 |
-
}
|
52 |
-
|
53 |
-
protected function mapOptionsToTarget() { }
|
54 |
-
|
55 |
-
/**
|
56 |
-
* Uses the keys from the Options Map array and populates the source value array with the database values.
|
57 |
-
*/
|
58 |
-
protected function populateSourceOptions() {
|
59 |
-
foreach( $this->m_aOptionsMap as $sOptionName => $sTarget ) {
|
60 |
-
$this->m_aSourceValues[ $sOptionName ] = get_option( $sOptionName );
|
61 |
-
}
|
62 |
-
}
|
63 |
-
|
64 |
-
/**
|
65 |
-
* Updates the target plugin options with the values (using the options prefix)
|
66 |
-
*
|
67 |
-
* @param string $insKey
|
68 |
-
* @param string|mixed $inmValue
|
69 |
-
*/
|
70 |
-
protected function updateTargetOption( $insKey, $inmValue ) {
|
71 |
-
$fResult = update_option( $this->m_sOptionPrefix.$insKey, $inmValue );
|
72 |
-
}
|
73 |
-
|
74 |
-
/**
|
75 |
-
* Gets the target plugin option value for the key (using the options prefix)
|
76 |
-
*
|
77 |
-
* @param string $insKey
|
78 |
-
*/
|
79 |
-
protected function getTargetOption( $insKey ) {
|
80 |
-
return get_option( $this->m_sOptionPrefix.$insKey );
|
81 |
-
}
|
82 |
-
}
|
83 |
-
|
84 |
-
endif;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/icwp-import-wpf2-processor.php
DELETED
@@ -1,147 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
-
* All rights reserved.
|
5 |
-
*
|
6 |
-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
7 |
-
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
8 |
-
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
9 |
-
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
10 |
-
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
11 |
-
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
12 |
-
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
13 |
-
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
14 |
-
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
15 |
-
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
-
*/
|
17 |
-
|
18 |
-
require_once( dirname(__FILE__).'/icwp-import-base-processor.php' );
|
19 |
-
|
20 |
-
if ( !class_exists('ICWP_ImportWpf2Processor') ):
|
21 |
-
|
22 |
-
class ICWP_ImportWpf2Processor extends ICWP_ImportBaseProcessor {
|
23 |
-
|
24 |
-
/**
|
25 |
-
* @var ICWP_WPSF_FeatureHandler_Plugin
|
26 |
-
*/
|
27 |
-
protected $m_oWpsfOptions;
|
28 |
-
/**
|
29 |
-
* @var ICWP_WPSF_FeatureHandler_Firewall
|
30 |
-
*/
|
31 |
-
protected $m_oFirewallOptions;
|
32 |
-
|
33 |
-
public function __construct( $inoPluginOptions, $inoFirewallOptions ) {
|
34 |
-
|
35 |
-
$this->m_oWpsfOptions = $inoPluginOptions;
|
36 |
-
$this->m_oFirewallOptions = $inoFirewallOptions;
|
37 |
-
|
38 |
-
$this->m_aOptionsMap = array(
|
39 |
-
'WP_firewall_redirect_page' => 'block_response',
|
40 |
-
'WP_firewall_email_enable' => 'block_send_email',
|
41 |
-
/* 'WP_firewall_email_type' => '', unused */
|
42 |
-
'WP_firewall_email_address' => 'block_send_email_address',
|
43 |
-
'WP_firewall_exclude_directory' => 'block_dir_traversal',
|
44 |
-
'WP_firewall_exclude_queries' => 'block_sql_queries',
|
45 |
-
'WP_firewall_exclude_terms' => 'block_wordpress_terms',
|
46 |
-
'WP_firewall_exclude_spaces' => 'block_field_truncation',
|
47 |
-
'WP_firewall_exclude_file' => 'block_exe_file_uploads',
|
48 |
-
'WP_firewall_exclude_http' => 'block_leading_schema',
|
49 |
-
'WP_firewall_whitelisted_ip' => 'ips_whitelist',
|
50 |
-
'WP_firewall_whitelisted_page' => 'page_params_whitelist',
|
51 |
-
'WP_firewall_whitelisted_variable' => 'page_params_whitelist',
|
52 |
-
/* 'WP_firewall_plugin_url' => '', unused */
|
53 |
-
/* 'WP_firewall_default_whitelisted_page' => '', unused */
|
54 |
-
/* 'WP_firewall_previous_attack_var' => '', unused */
|
55 |
-
/* 'WP_firewall_previous_attack_ip' => '', unused */
|
56 |
-
/* 'WP_firewall_email_limit' => '', unused */
|
57 |
-
);
|
58 |
-
}
|
59 |
-
|
60 |
-
protected function mapOptionsToTarget() {
|
61 |
-
|
62 |
-
$aPluginOptions = array(
|
63 |
-
'block_send_email_address'
|
64 |
-
);
|
65 |
-
|
66 |
-
$aFirewallOptions = array(
|
67 |
-
'block_response',
|
68 |
-
'block_send_email',
|
69 |
-
'block_send_email_address',
|
70 |
-
'block_dir_traversal',
|
71 |
-
'block_sql_queries',
|
72 |
-
'block_wordpress_terms',
|
73 |
-
'block_field_truncation',
|
74 |
-
'block_exe_file_uploads',
|
75 |
-
'block_leading_schema',
|
76 |
-
'ips_whitelist',
|
77 |
-
'page_params_whitelist',
|
78 |
-
'page_params_whitelist'
|
79 |
-
);
|
80 |
-
|
81 |
-
//redirect option
|
82 |
-
if ( $this->m_aSourceValues[ 'WP_firewall_redirect_page' ] == 'homepage' ) {
|
83 |
-
$this->m_oFirewallOptions->setOpt( $this->m_aOptionsMap['WP_firewall_redirect_page'], 'redirect_home' );
|
84 |
-
// $this->updateTargetOption( $this->m_aOptionsMap['WP_firewall_redirect_page'], 'redirect_home' );
|
85 |
-
}
|
86 |
-
else if ( $this->m_aSourceValues[ 'WP_firewall_redirect_page' ] == '404page' ) {
|
87 |
-
$this->m_oFirewallOptions->setOpt( $this->m_aOptionsMap['WP_firewall_redirect_page'], 'redirect_404' );
|
88 |
-
// $this->updateTargetOption( $this->m_aOptionsMap['WP_firewall_redirect_page'], 'redirect_404' );
|
89 |
-
}
|
90 |
-
|
91 |
-
//Email enable
|
92 |
-
if ( $this->m_aSourceValues[ 'WP_firewall_email_enable' ] == 'enable' ) {
|
93 |
-
$this->m_oFirewallOptions->setOpt( $this->m_aOptionsMap['WP_firewall_email_enable'], 'Y' );
|
94 |
-
// $this->updateTargetOption( $this->m_aOptionsMap['WP_firewall_email_enable'], 'Y' );
|
95 |
-
}
|
96 |
-
else { // actually the WPF2 doesn't give the option to turn off email(!)
|
97 |
-
$this->m_oFirewallOptions->setOpt( $this->m_aOptionsMap['WP_firewall_email_enable'], 'N' );
|
98 |
-
// $this->updateTargetOption( $this->m_aOptionsMap['WP_firewall_email_enable'], 'N' );
|
99 |
-
}
|
100 |
-
|
101 |
-
//Email address
|
102 |
-
$this->m_oWpsfOptions->setOpt( $this->m_aOptionsMap['WP_firewall_email_address'], $this->m_aSourceValues[ 'WP_firewall_email_address' ] );
|
103 |
-
// $this->updateTargetOption( $this->m_aOptionsMap['WP_firewall_email_address'], $this->m_aSourceValues[ 'WP_firewall_email_address' ] );
|
104 |
-
|
105 |
-
//Firewall block options - uses 'allow' to signify the block is in place. :|
|
106 |
-
$sTargetValue = ( $this->m_aSourceValues[ 'WP_firewall_exclude_directory' ] == 'allow' )? 'Y' : 'N';
|
107 |
-
$this->m_oFirewallOptions->setOpt( $this->m_aOptionsMap['WP_firewall_exclude_directory'], $sTargetValue );
|
108 |
-
// $this->updateTargetOption( $this->m_aOptionsMap['WP_firewall_exclude_directory'], $sTargetValue );
|
109 |
-
$sTargetValue = ( $this->m_aSourceValues[ 'WP_firewall_exclude_queries' ] == 'allow' )? 'Y' : 'N';
|
110 |
-
$this->m_oFirewallOptions->setOpt( $this->m_aOptionsMap['WP_firewall_exclude_queries'], $sTargetValue );
|
111 |
-
// $this->updateTargetOption( $this->m_aOptionsMap['WP_firewall_exclude_queries'], $sTargetValue );
|
112 |
-
$sTargetValue = ( $this->m_aSourceValues[ 'WP_firewall_exclude_terms' ] == 'allow' )? 'Y' : 'N';
|
113 |
-
$this->m_oFirewallOptions->setOpt( $this->m_aOptionsMap['WP_firewall_exclude_terms'], $sTargetValue );
|
114 |
-
// $this->updateTargetOption( $this->m_aOptionsMap['WP_firewall_exclude_terms'], $sTargetValue );
|
115 |
-
$sTargetValue = ( $this->m_aSourceValues[ 'WP_firewall_exclude_spaces' ] == 'allow' )? 'Y' : 'N';
|
116 |
-
$this->m_oFirewallOptions->setOpt( $this->m_aOptionsMap['WP_firewall_exclude_spaces'], $sTargetValue );
|
117 |
-
// $this->updateTargetOption( $this->m_aOptionsMap['WP_firewall_exclude_spaces'], $sTargetValue );
|
118 |
-
$sTargetValue = ( $this->m_aSourceValues[ 'WP_firewall_exclude_file' ] == 'allow' )? 'Y' : 'N';
|
119 |
-
$this->m_oFirewallOptions->setOpt( $this->m_aOptionsMap['WP_firewall_exclude_file'], $sTargetValue );
|
120 |
-
// $this->updateTargetOption( $this->m_aOptionsMap['WP_firewall_exclude_file'], $sTargetValue );
|
121 |
-
$sTargetValue = ( $this->m_aSourceValues[ 'WP_firewall_exclude_http' ] == 'allow' )? 'Y' : 'N';
|
122 |
-
$this->m_oFirewallOptions->setOpt( $this->m_aOptionsMap['WP_firewall_exclude_http'], $sTargetValue );
|
123 |
-
// $this->updateTargetOption( $this->m_aOptionsMap['WP_firewall_exclude_http'], $sTargetValue );
|
124 |
-
|
125 |
-
// Cookie checking - WPF2 does this by default
|
126 |
-
// $this->updateTargetOption( 'include_cookie_checks', 'Y' );
|
127 |
-
$this->m_oFirewallOptions->setOpt( 'include_cookie_checks', 'Y' );
|
128 |
-
|
129 |
-
// Whitelisted IPs
|
130 |
-
$aSourceIps = maybe_unserialize( $this->m_aSourceValues[ 'WP_firewall_whitelisted_ip' ] );
|
131 |
-
$aNewList = array();
|
132 |
-
foreach( $aSourceIps as $sIp ) {
|
133 |
-
$aNewList[ $sIp ] = '';
|
134 |
-
}
|
135 |
-
$aTargetIpWhitelist = $this->m_oFirewallOptions->getOpt( $this->m_aOptionsMap['WP_firewall_whitelisted_ip'] );
|
136 |
-
if ( empty( $aTargetIpWhitelist ) ) {
|
137 |
-
$aTargetIpWhitelist = array();
|
138 |
-
}
|
139 |
-
$this->m_oFirewallOptions->setOpt( $this->m_aOptionsMap['WP_firewall_whitelisted_ip'], ICWP_WPSF_DataProcessor::Add_New_Raw_Ips( $aTargetIpWhitelist, $aNewList ) );
|
140 |
-
// $this->updateTargetOption( $this->m_aOptionsMap['WP_firewall_whitelisted_ip'], ICWP_WPSF_DataProcessor::Add_New_Raw_Ips( $aTargetIpWhitelist, $aNewList ) );
|
141 |
-
|
142 |
-
// Whitelisted Pages and Vars... maybe later :|
|
143 |
-
}
|
144 |
-
|
145 |
-
}
|
146 |
-
|
147 |
-
endif;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/icwp-options-vo.php
ADDED
@@ -0,0 +1,373 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class ICWP_WPSF_OptionsVO extends ICWP_WPSF_Foundation {
|
3 |
+
|
4 |
+
/**
|
5 |
+
* @var array
|
6 |
+
*/
|
7 |
+
protected $aOptionsValues;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* @var array
|
11 |
+
*/
|
12 |
+
protected $aRawOptionsConfigData;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @var boolean
|
16 |
+
*/
|
17 |
+
protected $fNeedSave;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var string
|
21 |
+
*/
|
22 |
+
protected $aOptionsKeys;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var string
|
26 |
+
*/
|
27 |
+
protected $sOptionsStorageKey;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @var string
|
31 |
+
*/
|
32 |
+
protected $sOptionsName;
|
33 |
+
|
34 |
+
/**
|
35 |
+
* @param string $sOptionsName
|
36 |
+
*/
|
37 |
+
public function __construct( $sOptionsName ) {
|
38 |
+
$this->sOptionsName = $sOptionsName;
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* @return bool
|
43 |
+
*/
|
44 |
+
public function doOptionsSave() {
|
45 |
+
$this->cleanOptions();
|
46 |
+
if ( !$this->getNeedSave() ) {
|
47 |
+
return true;
|
48 |
+
}
|
49 |
+
$oWpFunc = $this->loadWpFunctionsProcessor();
|
50 |
+
$this->setNeedSave( false );
|
51 |
+
return $oWpFunc->updateOption( $this->getOptionsStorageKey(), $this->getAllOptionsValues() );
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* @return bool
|
56 |
+
*/
|
57 |
+
public function doOptionsDelete() {
|
58 |
+
$oWpFunc = $this->loadWpFunctionsProcessor();
|
59 |
+
return $oWpFunc->deleteOption( $this->getOptionsStorageKey() );
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* @return array
|
64 |
+
*/
|
65 |
+
public function getAllOptionsValues() {
|
66 |
+
return $this->loadOptionsValuesFromStorage();
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* @param $sProperty
|
71 |
+
* @return null|mixed
|
72 |
+
*/
|
73 |
+
public function getFeatureProperty( $sProperty ) {
|
74 |
+
$aRawConfig = $this->getRawData_FullFeatureConfig();
|
75 |
+
return ( isset( $aRawConfig['properties'] ) && isset( $aRawConfig['properties'][$sProperty] ) ) ? $aRawConfig['properties'][$sProperty] : null;
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* @param string $sKey
|
80 |
+
* @return boolean
|
81 |
+
*/
|
82 |
+
public function getIsOptionKey( $sKey ) {
|
83 |
+
return in_array( $sKey, $this->getOptionsKeys() );
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Determines whether the given option key is a valid option
|
88 |
+
*
|
89 |
+
* @param string
|
90 |
+
* @return boolean
|
91 |
+
*/
|
92 |
+
public function getIsValidOptionKey( $sOptionKey ) {
|
93 |
+
return in_array( $sOptionKey, $this->getOptionsKeys() );
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* @return array
|
98 |
+
*/
|
99 |
+
public function getLegacyOptionsConfigData() {
|
100 |
+
|
101 |
+
$aRawData = $this->getRawData_FullFeatureConfig();
|
102 |
+
$aLegacyData = array();
|
103 |
+
|
104 |
+
foreach( $aRawData['sections'] as $nPosition => $aRawSection ) {
|
105 |
+
|
106 |
+
if ( isset( $aRawSection['hidden'] ) && $aRawSection['hidden'] ) {
|
107 |
+
continue;
|
108 |
+
}
|
109 |
+
|
110 |
+
$aLegacySection = array();
|
111 |
+
$aLegacySection['section_primary'] = isset( $aRawSection['primary'] ) && $aRawSection['primary'];
|
112 |
+
$aLegacySection['section_slug'] = $aRawSection['slug'];
|
113 |
+
$aLegacySection['section_options'] = array();
|
114 |
+
foreach( $this->getRawData_AllOptions() as $aRawOption ) {
|
115 |
+
|
116 |
+
if ( $aRawOption['section'] != $aRawSection['slug'] ) {
|
117 |
+
continue;
|
118 |
+
}
|
119 |
+
|
120 |
+
if ( isset( $aRawOption['hidden'] ) && $aRawOption['hidden'] ) {
|
121 |
+
continue;
|
122 |
+
}
|
123 |
+
|
124 |
+
$aLegacyRawOption = array();
|
125 |
+
$aLegacyRawOption['key'] = $aRawOption['key'];
|
126 |
+
$aLegacyRawOption['value'] = ''; //value
|
127 |
+
$aLegacyRawOption['default'] = $aRawOption['default'];
|
128 |
+
$aLegacyRawOption['type'] = $aRawOption['type'];
|
129 |
+
|
130 |
+
$aLegacyRawOption['value_options'] = array();
|
131 |
+
if ( in_array( $aLegacyRawOption['type'], array( 'select', 'multiple_select' ) ) ) {
|
132 |
+
foreach( $aRawOption['value_options'] as $aValueOptions ) {
|
133 |
+
$aLegacyRawOption['value_options'][ $aValueOptions['value_key'] ] = $aValueOptions['text'];
|
134 |
+
}
|
135 |
+
}
|
136 |
+
|
137 |
+
$aLegacyRawOption['info_link'] = isset( $aRawOption['link_info'] ) ? $aRawOption['link_info'] : '';
|
138 |
+
$aLegacyRawOption['blog_link'] = isset( $aRawOption['link_blog'] ) ? $aRawOption['link_blog'] : '';
|
139 |
+
$aLegacySection['section_options'][] = $aLegacyRawOption;
|
140 |
+
}
|
141 |
+
|
142 |
+
if ( count( $aLegacySection['section_options'] ) > 0 ) {
|
143 |
+
$aLegacyData[ $nPosition ] = $aLegacySection;
|
144 |
+
}
|
145 |
+
}
|
146 |
+
return $aLegacyData;
|
147 |
+
}
|
148 |
+
|
149 |
+
/**
|
150 |
+
* @return string
|
151 |
+
*/
|
152 |
+
public function getNeedSave() {
|
153 |
+
return $this->fNeedSave;
|
154 |
+
}
|
155 |
+
|
156 |
+
/**
|
157 |
+
* @param string $sOptionKey
|
158 |
+
* @param mixed $mDefault
|
159 |
+
* @return mixed
|
160 |
+
*/
|
161 |
+
public function getOpt( $sOptionKey, $mDefault = false ) {
|
162 |
+
$aOptionsValues = $this->getAllOptionsValues();
|
163 |
+
if ( !isset( $aOptionsValues[ $sOptionKey ] ) ) {
|
164 |
+
$this->setOpt( $sOptionKey, $this->getOptDefault( $sOptionKey, $mDefault ), true );
|
165 |
+
}
|
166 |
+
return $this->aOptionsValues[ $sOptionKey ];
|
167 |
+
}
|
168 |
+
|
169 |
+
/**
|
170 |
+
* @param string $sOptionKey
|
171 |
+
* @param mixed $mDefault
|
172 |
+
* @return mixed|null
|
173 |
+
*/
|
174 |
+
public function getOptDefault( $sOptionKey, $mDefault = null ) {
|
175 |
+
$aOptions = $this->getRawData_AllOptions();
|
176 |
+
foreach( $aOptions as $aOption ) {
|
177 |
+
if ( $aOption['key'] == $sOptionKey ) {
|
178 |
+
if ( isset( $aOption['value'] ) ) {
|
179 |
+
return $aOption['value'];
|
180 |
+
}
|
181 |
+
else if ( isset( $aOption['default'] ) ) {
|
182 |
+
return $aOption['default'];
|
183 |
+
}
|
184 |
+
}
|
185 |
+
}
|
186 |
+
return $mDefault;
|
187 |
+
}
|
188 |
+
|
189 |
+
/**
|
190 |
+
* @param $sKey
|
191 |
+
* @param mixed $mValueToTest
|
192 |
+
* @param boolean $fStrict
|
193 |
+
* @return bool
|
194 |
+
*/
|
195 |
+
public function getOptIs( $sKey, $mValueToTest, $fStrict = false ) {
|
196 |
+
$mOptionValue = $this->getOpt( $sKey );
|
197 |
+
return $fStrict? $mOptionValue === $mValueToTest : $mOptionValue == $mValueToTest;
|
198 |
+
}
|
199 |
+
|
200 |
+
/**
|
201 |
+
* @return string
|
202 |
+
*/
|
203 |
+
public function getOptionsKeys() {
|
204 |
+
if ( !isset( $this->aOptionsKeys ) ) {
|
205 |
+
$this->aOptionsKeys = array();
|
206 |
+
foreach( $this->getRawData_AllOptions() as $aOption ) {
|
207 |
+
$this->aOptionsKeys[] = $aOption['key'];
|
208 |
+
}
|
209 |
+
}
|
210 |
+
return $this->aOptionsKeys;
|
211 |
+
}
|
212 |
+
|
213 |
+
/**
|
214 |
+
* @return string
|
215 |
+
*/
|
216 |
+
public function getOptionsStorageKey() {
|
217 |
+
return $this->sOptionsStorageKey;
|
218 |
+
}
|
219 |
+
|
220 |
+
/**
|
221 |
+
* @return array
|
222 |
+
*/
|
223 |
+
public function getRawData_FullFeatureConfig() {
|
224 |
+
if ( empty( $this->aRawOptionsConfigData ) ) {
|
225 |
+
$this->aRawOptionsConfigData = $this->readYamlConfiguration( $this->sOptionsName );
|
226 |
+
}
|
227 |
+
return $this->aRawOptionsConfigData;
|
228 |
+
}
|
229 |
+
|
230 |
+
/**
|
231 |
+
* Return the section of the Raw config that is the "options" key only.
|
232 |
+
*
|
233 |
+
* @return array
|
234 |
+
*/
|
235 |
+
protected function getRawData_AllOptions() {
|
236 |
+
$aAllRawOptions = $this->getRawData_FullFeatureConfig();
|
237 |
+
return isset( $aAllRawOptions['options'] ) ? $aAllRawOptions['options'] : array();
|
238 |
+
}
|
239 |
+
|
240 |
+
/**
|
241 |
+
* Return the section of the Raw config that is the "options" key only.
|
242 |
+
*
|
243 |
+
* @param string $sOptionKey
|
244 |
+
* @return array
|
245 |
+
*/
|
246 |
+
public function getRawData_SingleOption( $sOptionKey ) {
|
247 |
+
$aAllRawOptions = $this->getRawData_AllOptions();
|
248 |
+
foreach( $aAllRawOptions as $aOption ) {
|
249 |
+
if ( $sOptionKey == $aOption['key'] ) {
|
250 |
+
return $aOption;
|
251 |
+
}
|
252 |
+
}
|
253 |
+
return null;
|
254 |
+
}
|
255 |
+
|
256 |
+
/**
|
257 |
+
* @param string $sOptionKey
|
258 |
+
* @return boolean
|
259 |
+
*/
|
260 |
+
public function resetOptToDefault( $sOptionKey ) {
|
261 |
+
return $this->setOpt( $sOptionKey, $this->getOptDefault( $sOptionKey ), true );
|
262 |
+
}
|
263 |
+
|
264 |
+
/**
|
265 |
+
* @param string $sKey
|
266 |
+
*/
|
267 |
+
public function setOptionsStorageKey( $sKey ) {
|
268 |
+
$this->sOptionsStorageKey = $sKey;
|
269 |
+
}
|
270 |
+
|
271 |
+
/**
|
272 |
+
* @param boolean $fNeed
|
273 |
+
*/
|
274 |
+
public function setNeedSave( $fNeed ) {
|
275 |
+
$this->fNeedSave = $fNeed;
|
276 |
+
}
|
277 |
+
|
278 |
+
/**
|
279 |
+
* @param string $sOptionKey
|
280 |
+
* @param mixed $mValue
|
281 |
+
* @param boolean $fForce
|
282 |
+
* @return mixed
|
283 |
+
*/
|
284 |
+
public function setOpt( $sOptionKey, $mValue, $fForce = false ) {
|
285 |
+
|
286 |
+
if ( $fForce || $this->getOpt( $sOptionKey ) !== $mValue ) {
|
287 |
+
$this->setNeedSave( true );
|
288 |
+
|
289 |
+
//Load the config and do some pre-set verification where possible. This will slowly grow.
|
290 |
+
$aOption = $this->getRawData_SingleOption( $sOptionKey );
|
291 |
+
if ( !empty( $aOption['type'] ) ) {
|
292 |
+
if ( $aOption['type'] == 'boolean' && !is_bool( $mValue ) ) {
|
293 |
+
return $this->resetOptToDefault( $sOptionKey );
|
294 |
+
}
|
295 |
+
}
|
296 |
+
|
297 |
+
$this->aOptionsValues[ $sOptionKey ] = $mValue;
|
298 |
+
}
|
299 |
+
return true;
|
300 |
+
}
|
301 |
+
|
302 |
+
/**
|
303 |
+
* @param string $sOptionKey
|
304 |
+
* @return mixed
|
305 |
+
*/
|
306 |
+
public function unsetOpt( $sOptionKey ) {
|
307 |
+
|
308 |
+
unset( $this->aOptionsValues[$sOptionKey] );
|
309 |
+
$this->setNeedSave( true );
|
310 |
+
return true;
|
311 |
+
}
|
312 |
+
|
313 |
+
/** PRIVATE STUFF */
|
314 |
+
|
315 |
+
/**
|
316 |
+
*/
|
317 |
+
private function cleanOptions() {
|
318 |
+
if ( empty( $this->aOptionsValues ) || !is_array( $this->aOptionsValues ) ) {
|
319 |
+
return;
|
320 |
+
}
|
321 |
+
foreach( $this->aOptionsValues as $sKey => $mValue ) {
|
322 |
+
if ( !$this->getIsValidOptionKey( $sKey ) ) {
|
323 |
+
$this->setNeedSave( true );
|
324 |
+
unset( $this->aOptionsValues[$sKey] );
|
325 |
+
}
|
326 |
+
}
|
327 |
+
}
|
328 |
+
|
329 |
+
/**
|
330 |
+
* @param boolean $fReload
|
331 |
+
* @return array
|
332 |
+
* @throws Exception
|
333 |
+
*/
|
334 |
+
private function loadOptionsValuesFromStorage( $fReload = false ) {
|
335 |
+
|
336 |
+
if ( $fReload || empty( $this->aOptionsValues ) ) {
|
337 |
+
|
338 |
+
$sStorageKey = $this->getOptionsStorageKey();
|
339 |
+
if ( empty( $sStorageKey ) ) {
|
340 |
+
throw new Exception( 'Options Storage Key Is Empty' );
|
341 |
+
}
|
342 |
+
|
343 |
+
$oWpFunc = $this->loadWpFunctionsProcessor();
|
344 |
+
$this->aOptionsValues = $oWpFunc->getOption( $sStorageKey, array() );
|
345 |
+
if ( empty( $this->aOptionsValues ) ) {
|
346 |
+
$this->aOptionsValues = array();
|
347 |
+
$this->setNeedSave( true );
|
348 |
+
}
|
349 |
+
}
|
350 |
+
return $this->aOptionsValues;
|
351 |
+
}
|
352 |
+
|
353 |
+
/**
|
354 |
+
* @param string $sName
|
355 |
+
* @return array
|
356 |
+
* @throws Exception
|
357 |
+
*/
|
358 |
+
private function readYamlConfiguration( $sName ) {
|
359 |
+
$oFs = $this->loadFileSystemProcessor();
|
360 |
+
|
361 |
+
$aConfig = array();
|
362 |
+
$sConfigFile = dirname( __FILE__ ). sprintf( ICWP_DS.'config'.ICWP_DS.'feature-%s.txt', $sName );
|
363 |
+
$sContents = $oFs->getFileContent( $sConfigFile );
|
364 |
+
if ( !empty( $sContents ) ) {
|
365 |
+
$oYaml = $this->loadYamlProcessor();
|
366 |
+
$aConfig = $oYaml->parseYamlString( $sContents );
|
367 |
+
if ( is_null( $aConfig ) ) {
|
368 |
+
throw new Exception( 'YAML parser could not load to process the options configuration.' );
|
369 |
+
}
|
370 |
+
}
|
371 |
+
return $aConfig;
|
372 |
+
}
|
373 |
+
}
|
src/icwp-optionshandler-admin_access_restriction.php
CHANGED
@@ -21,16 +21,6 @@ if ( !class_exists('ICWP_WPSF_FeatureHandler_AdminAccessRestriction') ):
|
|
21 |
|
22 |
class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureHandler_Base {
|
23 |
|
24 |
-
/**
|
25 |
-
* @const integer
|
26 |
-
*/
|
27 |
-
const Default_AccessKeyTimeout = 30;
|
28 |
-
|
29 |
-
/**
|
30 |
-
* @var string
|
31 |
-
*/
|
32 |
-
const AdminAccessKeyCookieName = 'icwp_wpsf_aakcook';
|
33 |
-
|
34 |
private $fHasPermissionToSubmit;
|
35 |
|
36 |
/**
|
@@ -41,7 +31,6 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
41 |
public function __construct( $oPluginVo ) {
|
42 |
$this->sFeatureName = _wpsf__('Admin Access');
|
43 |
$this->sFeatureSlug = 'admin_access_restriction';
|
44 |
-
$this->fShowFeatureMenuItem = true;
|
45 |
parent::__construct( $oPluginVo );
|
46 |
|
47 |
add_filter( $this->doPluginPrefix( 'has_permission_to_submit' ), array( $this, 'doCheckHasPermissionToSubmit' ) );
|
@@ -53,135 +42,183 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
53 |
*/
|
54 |
protected function loadFeatureProcessor() {
|
55 |
if ( !isset( $this->oFeatureProcessor ) ) {
|
56 |
-
require_once(
|
57 |
$this->oFeatureProcessor = new ICWP_WPSF_Processor_AdminAccessRestriction( $this );
|
58 |
}
|
59 |
return $this->oFeatureProcessor;
|
60 |
}
|
61 |
|
62 |
/**
|
63 |
-
*
|
|
|
64 |
*/
|
65 |
public function doCheckHasPermissionToSubmit( $fHasPermission = true ) {
|
66 |
|
67 |
-
|
68 |
-
|
69 |
-
if (
|
70 |
-
$
|
71 |
-
if ( $sAccessKeyRequest === $this->getOpt( 'admin_access_key' ) ) {
|
72 |
-
$this->setPermissionToSubmit( true );
|
73 |
-
wp_safe_redirect( network_admin_url() );
|
74 |
-
}
|
75 |
}
|
76 |
|
77 |
if ( isset( $this->fHasPermissionToSubmit ) ) {
|
78 |
return $this->fHasPermissionToSubmit;
|
79 |
}
|
|
|
|
|
|
|
80 |
$this->fHasPermissionToSubmit = $fHasPermission;
|
81 |
if ( $this->getIsMainFeatureEnabled() ) {
|
|
|
82 |
$sAccessKey = $this->getOpt( 'admin_access_key' );
|
83 |
if ( !empty( $sAccessKey ) ) {
|
84 |
-
$
|
85 |
-
$
|
86 |
-
$
|
87 |
-
$this->fHasPermissionToSubmit = $sCookieValue === $sHash;
|
88 |
}
|
89 |
}
|
90 |
return $this->fHasPermissionToSubmit;
|
91 |
}
|
92 |
|
93 |
/**
|
94 |
-
*
|
95 |
*/
|
96 |
-
|
97 |
-
$
|
98 |
-
if (
|
99 |
-
|
|
|
|
|
|
|
100 |
}
|
|
|
101 |
|
102 |
-
|
103 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
}
|
105 |
}
|
106 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
107 |
/**
|
108 |
* @param bool $fPermission
|
109 |
*/
|
110 |
protected function setPermissionToSubmit( $fPermission = false ) {
|
111 |
if ( $fPermission ) {
|
112 |
-
$this->
|
113 |
-
$sValue = md5( $this->getOpt( 'admin_access_key' ).ICWP_WPSF_DataProcessor::GetVisitorIpAddress() );
|
114 |
-
$sTimeout = $this->getOpt( 'admin_access_timeout' ) * 60;
|
115 |
-
$_COOKIE[ self::AdminAccessKeyCookieName ] = $sValue;
|
116 |
-
setcookie( self::AdminAccessKeyCookieName, $sValue, time()+$sTimeout, COOKIEPATH, COOKIE_DOMAIN, false );
|
117 |
}
|
118 |
else {
|
119 |
-
|
120 |
-
setcookie( self::AdminAccessKeyCookieName, "", time()-3600, COOKIEPATH, COOKIE_DOMAIN, false );
|
121 |
}
|
122 |
}
|
123 |
|
124 |
/**
|
125 |
-
* @return bool
|
126 |
*/
|
127 |
-
protected function
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
'enable_admin_access_restriction',
|
136 |
-
'',
|
137 |
-
'N',
|
138 |
-
'checkbox',
|
139 |
-
_wpsf__( 'Enable Access Key' ),
|
140 |
-
_wpsf__( 'Enforce Admin Access Restriction' ),
|
141 |
-
_wpsf__( 'Enable this with great care and consideration. When this Access Key option is enabled, you must specify a key below and use it to gain access to this plugin.' ),
|
142 |
-
'<a href="http://icwp.io/40" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
143 |
-
.' | <a href="http://icwp.io/wpsf02" target="_blank">'._wpsf__( 'blog' ).'</a>'
|
144 |
-
),
|
145 |
-
array(
|
146 |
-
'admin_access_key',
|
147 |
-
'',
|
148 |
-
'',
|
149 |
-
'password',
|
150 |
-
_wpsf__( 'Admin Access Key' ),
|
151 |
-
_wpsf__( 'Specify Your Plugin Access Key' ),
|
152 |
-
_wpsf__( 'If you forget this, you could potentially lock yourself out from using this plugin.' )
|
153 |
-
.' <strong>'._wpsf__( 'Leave it blank to not update it' ).'</strong>',
|
154 |
-
'<a href="http://icwp.io/42" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
155 |
-
),
|
156 |
-
array(
|
157 |
-
'admin_access_timeout',
|
158 |
-
'',
|
159 |
-
self::Default_AccessKeyTimeout,
|
160 |
-
'integer',
|
161 |
-
_wpsf__( 'Access Key Timeout' ),
|
162 |
-
_wpsf__( 'Specify A Timeout For Plugin Admin Access' ),
|
163 |
-
_wpsf__( 'This will automatically expire your WordPress Simple Firewall session. Does not apply until you enter the access key again.').'<br />'.sprintf(_wpsf__( 'Default: %s minutes.' ), self::Default_AccessKeyTimeout ),
|
164 |
-
'<a href="http://icwp.io/41" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
165 |
-
)
|
166 |
-
)
|
167 |
-
);
|
168 |
-
}
|
169 |
-
$aOptionsDefinitions = array(
|
170 |
-
$aAccessKey
|
171 |
-
);
|
172 |
-
return $aOptionsDefinitions;
|
173 |
}
|
174 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
175 |
/**
|
176 |
* This is the point where you would want to do any options verification
|
177 |
*/
|
178 |
protected function doPrePluginOptionsSave() {
|
179 |
-
|
180 |
-
if ( $this->getOpt( '
|
181 |
-
$this->
|
182 |
}
|
183 |
-
|
184 |
-
$
|
|
|
|
|
|
|
|
|
|
|
185 |
if ( empty( $sAccessKey ) ) {
|
186 |
$this->setOpt( 'enable_admin_access_restriction', 'N' );
|
187 |
}
|
@@ -189,6 +226,11 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
189 |
|
190 |
protected function updateHandler() {
|
191 |
parent::updateHandler();
|
|
|
|
|
|
|
|
|
|
|
192 |
if ( version_compare( $this->getVersion(), '3.0.0', '<' ) ) {
|
193 |
$aAllOptions = apply_filters( $this->doPluginPrefix( 'aggregate_all_plugin_options' ), array() );
|
194 |
$this->setOpt( 'enable_admin_access_restriction', $aAllOptions['enable_admin_access_restriction'] );
|
21 |
|
22 |
class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureHandler_Base {
|
23 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
private $fHasPermissionToSubmit;
|
25 |
|
26 |
/**
|
31 |
public function __construct( $oPluginVo ) {
|
32 |
$this->sFeatureName = _wpsf__('Admin Access');
|
33 |
$this->sFeatureSlug = 'admin_access_restriction';
|
|
|
34 |
parent::__construct( $oPluginVo );
|
35 |
|
36 |
add_filter( $this->doPluginPrefix( 'has_permission_to_submit' ), array( $this, 'doCheckHasPermissionToSubmit' ) );
|
42 |
*/
|
43 |
protected function loadFeatureProcessor() {
|
44 |
if ( !isset( $this->oFeatureProcessor ) ) {
|
45 |
+
require_once( $this->getController()->getSourceDir( sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) ) );
|
46 |
$this->oFeatureProcessor = new ICWP_WPSF_Processor_AdminAccessRestriction( $this );
|
47 |
}
|
48 |
return $this->oFeatureProcessor;
|
49 |
}
|
50 |
|
51 |
/**
|
52 |
+
* @param bool $fHasPermission
|
53 |
+
* @return bool
|
54 |
*/
|
55 |
public function doCheckHasPermissionToSubmit( $fHasPermission = true ) {
|
56 |
|
57 |
+
// We don't use setPermissionToSubmit() here because of timing with headers - we just for now manually
|
58 |
+
// checking POST for the submission of the key and if it fits, we say "yes"
|
59 |
+
if ( $this->checkAdminAccessKeySubmission() ) {
|
60 |
+
$this->fHasPermissionToSubmit = true;
|
|
|
|
|
|
|
|
|
61 |
}
|
62 |
|
63 |
if ( isset( $this->fHasPermissionToSubmit ) ) {
|
64 |
return $this->fHasPermissionToSubmit;
|
65 |
}
|
66 |
+
|
67 |
+
$oDp = $this->loadDataProcessor();
|
68 |
+
|
69 |
$this->fHasPermissionToSubmit = $fHasPermission;
|
70 |
if ( $this->getIsMainFeatureEnabled() ) {
|
71 |
+
|
72 |
$sAccessKey = $this->getOpt( 'admin_access_key' );
|
73 |
if ( !empty( $sAccessKey ) ) {
|
74 |
+
$sHash = md5( $sAccessKey );
|
75 |
+
$sCookieValue = $oDp->FetchCookie( $this->getAdminAccessKeyCookieName() );
|
76 |
+
$this->fHasPermissionToSubmit = ( $sCookieValue === $sHash );
|
|
|
77 |
}
|
78 |
}
|
79 |
return $this->fHasPermissionToSubmit;
|
80 |
}
|
81 |
|
82 |
/**
|
|
|
83 |
*/
|
84 |
+
protected function setAdminAccessCookie() {
|
85 |
+
$sAccessKey = $this->getOpt( 'admin_access_key' );
|
86 |
+
if ( !empty( $sAccessKey ) ) {
|
87 |
+
$sValue = md5( $sAccessKey );
|
88 |
+
$sTimeout = $this->getOpt( 'admin_access_timeout' ) * 60;
|
89 |
+
$_COOKIE[ $this->getAdminAccessKeyCookieName() ] = $sValue;
|
90 |
+
setcookie( $this->getAdminAccessKeyCookieName(), $sValue, time()+$sTimeout, COOKIEPATH, COOKIE_DOMAIN, false );
|
91 |
}
|
92 |
+
}
|
93 |
|
94 |
+
/**
|
95 |
+
*/
|
96 |
+
protected function clearAdminAccessCookie() {
|
97 |
+
unset( $_COOKIE[ $this->getAdminAccessKeyCookieName() ] );
|
98 |
+
setcookie( $this->getAdminAccessKeyCookieName(), "", time()-3600, COOKIEPATH, COOKIE_DOMAIN, false );
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
*/
|
103 |
+
protected function doExtraSubmitProcessing() {
|
104 |
+
// We should only use setPermissionToSubmit() here, before any headers elsewhere are sent out.
|
105 |
+
if ( $this->checkAdminAccessKeySubmission() ) {
|
106 |
+
$this->setPermissionToSubmit( true );
|
107 |
+
wp_safe_redirect( network_admin_url() );
|
108 |
}
|
109 |
}
|
110 |
|
111 |
+
/**
|
112 |
+
* @return string
|
113 |
+
*/
|
114 |
+
public function getAdminAccessKeyCookieName() {
|
115 |
+
return $this->getOpt( 'admin_access_key_cookie_name' );
|
116 |
+
}
|
117 |
+
|
118 |
/**
|
119 |
* @param bool $fPermission
|
120 |
*/
|
121 |
protected function setPermissionToSubmit( $fPermission = false ) {
|
122 |
if ( $fPermission ) {
|
123 |
+
$this->setAdminAccessCookie();
|
|
|
|
|
|
|
|
|
124 |
}
|
125 |
else {
|
126 |
+
$this->clearAdminAccessCookie();
|
|
|
127 |
}
|
128 |
}
|
129 |
|
130 |
/**
|
131 |
+
* @return bool
|
132 |
*/
|
133 |
+
protected function checkAdminAccessKeySubmission() {
|
134 |
+
$oDp = $this->loadDataProcessor();
|
135 |
+
|
136 |
+
$sAccessKeyRequest = $oDp->FetchPost( $this->doPluginPrefix( 'admin_access_key_request', '_' ) );
|
137 |
+
if ( empty( $sAccessKeyRequest ) ) {
|
138 |
+
return false;
|
139 |
+
}
|
140 |
+
return $this->getOpt( 'admin_access_key' ) === md5( $sAccessKeyRequest );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
141 |
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
* @param array $aOptionsParams
|
145 |
+
* @return array
|
146 |
+
* @throws Exception
|
147 |
+
*/
|
148 |
+
protected function loadStrings_SectionTitles( $aOptionsParams ) {
|
149 |
+
|
150 |
+
$sSectionSlug = $aOptionsParams['section_slug'];
|
151 |
+
switch( $aOptionsParams['section_slug'] ) {
|
152 |
+
|
153 |
+
case 'section_enable_plugin_feature_admin_access_restriction' :
|
154 |
+
$sTitle = sprintf( _wpsf__( 'Enable Plugin Feature: %s' ), _wpsf__('Admin Access Restriction') );
|
155 |
+
break;
|
156 |
+
|
157 |
+
case 'section_admin_access_restriction_settings' :
|
158 |
+
$sTitle = _wpsf__( 'Admin Access Restriction Settings' );
|
159 |
+
break;
|
160 |
+
|
161 |
+
default:
|
162 |
+
throw new Exception( sprintf( 'A section slug was defined but with no associated strings. Slug: "%s".', $sSectionSlug ) );
|
163 |
+
}
|
164 |
+
$aOptionsParams['section_title'] = $sTitle;
|
165 |
+
return $aOptionsParams;
|
166 |
+
}
|
167 |
+
|
168 |
+
/**
|
169 |
+
* @param array $aOptionsParams
|
170 |
+
* @return array
|
171 |
+
* @throws Exception
|
172 |
+
*/
|
173 |
+
protected function loadStrings_Options( $aOptionsParams ) {
|
174 |
+
|
175 |
+
$sKey = $aOptionsParams['key'];
|
176 |
+
switch( $sKey ) {
|
177 |
+
|
178 |
+
case 'enable_admin_access_restriction' :
|
179 |
+
$sName = sprintf( _wpsf__( 'Enable Plugin Feature: %s' ), _wpsf__('Admin Access') );
|
180 |
+
$sSummary = _wpsf__( 'Enforce Admin Access Restriction' );
|
181 |
+
$sDescription = _wpsf__( 'Enable this with great care and consideration. When this Access Key option is enabled, you must specify a key below and use it to gain access to this plugin.' );
|
182 |
+
break;
|
183 |
+
|
184 |
+
case 'admin_access_key' :
|
185 |
+
$sName = _wpsf__( 'Admin Access Key' );
|
186 |
+
$sSummary = _wpsf__( 'Provide/Update Admin Access Key' );
|
187 |
+
$sDescription = sprintf( _wpsf__( 'Careful: %s' ), _wpsf__( 'If you forget this, you could potentially lock yourself out from using this plugin.' ) );
|
188 |
+
break;
|
189 |
+
|
190 |
+
case 'admin_access_timeout' :
|
191 |
+
$sName = _wpsf__( 'Admin Access Timeout' );
|
192 |
+
$sSummary = _wpsf__( 'Specify An Automatic Timeout Interval For Admin Access' );
|
193 |
+
$sDescription = _wpsf__( 'This will automatically expire your WordPress Simple Firewall session. Does not apply until you enter the access key again.')
|
194 |
+
.'<br />'.sprintf( _wpsf__( 'Default: %s minutes.' ), $this->getOptionsVo()->getOptDefault( 'admin_access_timeout' ) );
|
195 |
+
break;
|
196 |
+
|
197 |
+
default:
|
198 |
+
throw new Exception( sprintf( 'An option has been defined but without strings assigned to it. Option key: "%s".', $sKey ) );
|
199 |
+
}
|
200 |
+
|
201 |
+
$aOptionsParams['name'] = $sName;
|
202 |
+
$aOptionsParams['summary'] = $sSummary;
|
203 |
+
$aOptionsParams['description'] = $sDescription;
|
204 |
+
return $aOptionsParams;
|
205 |
+
}
|
206 |
+
|
207 |
/**
|
208 |
* This is the point where you would want to do any options verification
|
209 |
*/
|
210 |
protected function doPrePluginOptionsSave() {
|
211 |
+
|
212 |
+
if ( $this->getOpt( 'admin_access_timeout' ) < 1 ) {
|
213 |
+
$this->getOptionsVo()->resetOptToDefault( 'admin_access_timeout' );
|
214 |
}
|
215 |
+
|
216 |
+
$sNotificationEmail = $this->getOpt( 'enable_admin_login_email_notification' );
|
217 |
+
if ( !empty( $sNotificationEmail ) && !is_email( $sNotificationEmail ) ) {
|
218 |
+
$this->setOpt( 'enable_admin_login_email_notification', '' );
|
219 |
+
}
|
220 |
+
|
221 |
+
$sAccessKey = $this->getOpt( 'admin_access_key' );
|
222 |
if ( empty( $sAccessKey ) ) {
|
223 |
$this->setOpt( 'enable_admin_access_restriction', 'N' );
|
224 |
}
|
226 |
|
227 |
protected function updateHandler() {
|
228 |
parent::updateHandler();
|
229 |
+
|
230 |
+
if ( $this->getVersion() == '0.0' ) {
|
231 |
+
return;
|
232 |
+
}
|
233 |
+
|
234 |
if ( version_compare( $this->getVersion(), '3.0.0', '<' ) ) {
|
235 |
$aAllOptions = apply_filters( $this->doPluginPrefix( 'aggregate_all_plugin_options' ), array() );
|
236 |
$this->setOpt( 'enable_admin_access_restriction', $aAllOptions['enable_admin_access_restriction'] );
|
src/icwp-optionshandler-audit_trail.php
ADDED
@@ -0,0 +1,150 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
+
* All rights reserved.
|
5 |
+
*
|
6 |
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
7 |
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
8 |
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
9 |
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
10 |
+
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
11 |
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
12 |
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
13 |
+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
14 |
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
15 |
+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
+
*/
|
17 |
+
|
18 |
+
require_once( dirname(__FILE__).'/icwp-optionshandler-base.php' );
|
19 |
+
|
20 |
+
if ( !class_exists('ICWP_WPSF_FeatureHandler_AuditTrail_V1') ):
|
21 |
+
|
22 |
+
class ICWP_WPSF_FeatureHandler_AuditTrail_V1 extends ICWP_WPSF_FeatureHandler_Base {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var ICWP_WPSF_Processor_AuditTrail
|
26 |
+
*/
|
27 |
+
protected $oFeatureProcessor;
|
28 |
+
|
29 |
+
public function __construct( $oPluginVo ) {
|
30 |
+
$this->sFeatureName = _wpsf__('Audit Trail');
|
31 |
+
$this->sFeatureSlug = 'audit_trail';
|
32 |
+
parent::__construct( $oPluginVo );
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* @return ICWP_WPSF_Processor_Autoupdates|null
|
37 |
+
*/
|
38 |
+
protected function loadFeatureProcessor() {
|
39 |
+
if ( !isset( $this->oFeatureProcessor ) ) {
|
40 |
+
require_once( $this->getController()->getSourceDir( sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) ) );
|
41 |
+
$this->oFeatureProcessor = new ICWP_WPSF_Processor_AuditTrail( $this );
|
42 |
+
}
|
43 |
+
return $this->oFeatureProcessor;
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* @return bool|void
|
48 |
+
*/
|
49 |
+
public function doExtraSubmitProcessing() { }
|
50 |
+
|
51 |
+
public function doPrePluginOptionsSave() {}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* @return string
|
55 |
+
*/
|
56 |
+
public function getAuditTrailTableName() {
|
57 |
+
return $this->doPluginPrefix( $this->getOpt( 'audit_trail_table_name' ), '_' );
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* @param array $aOptionsParams
|
62 |
+
* @return array
|
63 |
+
* @throws Exception
|
64 |
+
*/
|
65 |
+
protected function loadStrings_SectionTitles( $aOptionsParams ) {
|
66 |
+
|
67 |
+
$sSectionSlug = $aOptionsParams['section_slug'];
|
68 |
+
switch( $sSectionSlug ) {
|
69 |
+
|
70 |
+
case 'section_enable_plugin_feature_audit_trail' :
|
71 |
+
$sTitle = sprintf( _wpsf__( 'Enable Plugin Feature: %s' ), $this->getMainFeatureName() );
|
72 |
+
break;
|
73 |
+
|
74 |
+
case 'section_enable_audit_contexts' :
|
75 |
+
$sTitle = _wpsf__( 'Enable Audit Contexts' );
|
76 |
+
break;
|
77 |
+
|
78 |
+
default:
|
79 |
+
throw new Exception( sprintf( 'A section slug was defined but with no associated strings. Slug: "%s".', $sSectionSlug ) );
|
80 |
+
}
|
81 |
+
$aOptionsParams['section_title'] = $sTitle;
|
82 |
+
return $aOptionsParams;
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* @param array $aOptionsParams
|
87 |
+
* @return array
|
88 |
+
* @throws Exception
|
89 |
+
*/
|
90 |
+
protected function loadStrings_Options( $aOptionsParams ) {
|
91 |
+
|
92 |
+
$sKey = $aOptionsParams['key'];
|
93 |
+
switch( $sKey ) {
|
94 |
+
|
95 |
+
case 'enable_audit_trail' :
|
96 |
+
$sName = sprintf( _wpsf__( 'Enable %s' ), $this->getMainFeatureName() );
|
97 |
+
$sSummary = sprintf( _wpsf__( 'Enable (or Disable) The %s Feature' ), $this->getMainFeatureName() );
|
98 |
+
$sDescription = sprintf( _wpsf__( 'Checking/Un-Checking this option will completely turn on/off the whole %s feature.' ), $this->getMainFeatureName() );
|
99 |
+
break;
|
100 |
+
|
101 |
+
case 'enable_audit_context_users' :
|
102 |
+
$sName = _wpsf__( 'Users And Logins' );
|
103 |
+
$sSummary = sprintf( _wpsf__( 'Enable Audit Context - %s' ), _wpsf__( 'Users And Logins' ) );
|
104 |
+
$sDescription = _wpsf__( 'When this context is enabled, the audit trail will track user activity and significant events such as user login etc.' );
|
105 |
+
break;
|
106 |
+
|
107 |
+
case 'enable_audit_context_plugins' :
|
108 |
+
$sName = _wpsf__( 'Plugins' );
|
109 |
+
$sSummary = sprintf( _wpsf__( 'Enable Audit Context - %s' ), _wpsf__( 'Plugins' ) );
|
110 |
+
$sDescription = _wpsf__( 'When this context is enabled, the audit trail will track user activity and significant events such as user login etc.' );
|
111 |
+
break;
|
112 |
+
|
113 |
+
case 'enable_audit_context_themes' :
|
114 |
+
$sName = _wpsf__( 'Themes' );
|
115 |
+
$sSummary = sprintf( _wpsf__( 'Enable Audit Context - %s' ), _wpsf__( 'Themes' ) );
|
116 |
+
$sDescription = _wpsf__( 'When this context is enabled, the audit trail will track user activity and significant events such as user login etc.' );
|
117 |
+
break;
|
118 |
+
|
119 |
+
case 'enable_audit_context_posts' :
|
120 |
+
$sName = _wpsf__( 'Posts And Pages' );
|
121 |
+
$sSummary = sprintf( _wpsf__( 'Enable Audit Context - %s' ), _wpsf__( 'Posts And Pages' ) );
|
122 |
+
$sDescription = _wpsf__( 'When this context is enabled, the audit trail will track user activity and significant events such as user login etc.' );
|
123 |
+
break;
|
124 |
+
|
125 |
+
case 'enable_audit_context_wordpress' :
|
126 |
+
$sName = _wpsf__( 'WordPress And Settings' );
|
127 |
+
$sSummary = sprintf( _wpsf__( 'Enable Audit Context - %s' ), _wpsf__( 'WordPress And Settings' ) );
|
128 |
+
$sDescription = _wpsf__( 'When this context is enabled, the audit trail will track user activity and significant events such as user login etc.' );
|
129 |
+
break;
|
130 |
+
|
131 |
+
case 'enable_audit_context_wpsf' :
|
132 |
+
$sName = _wpsf__( 'Simple Firewall' );
|
133 |
+
$sSummary = sprintf( _wpsf__( 'Enable Audit Context - %s' ), _wpsf__( 'Simple Firewall' ) );
|
134 |
+
$sDescription = _wpsf__( 'When this context is enabled, the audit trail will track user activity and significant events such as user login etc.' );
|
135 |
+
break;
|
136 |
+
|
137 |
+
default:
|
138 |
+
throw new Exception( sprintf( 'An option has been defined but without strings assigned to it. Option key: "%s".', $sKey ) );
|
139 |
+
}
|
140 |
+
|
141 |
+
$aOptionsParams['name'] = $sName;
|
142 |
+
$aOptionsParams['summary'] = $sSummary;
|
143 |
+
$aOptionsParams['description'] = $sDescription;
|
144 |
+
return $aOptionsParams;
|
145 |
+
}
|
146 |
+
}
|
147 |
+
|
148 |
+
endif;
|
149 |
+
|
150 |
+
class ICWP_WPSF_FeatureHandler_AuditTrail extends ICWP_WPSF_FeatureHandler_AuditTrail_V1 { }
|
src/icwp-optionshandler-autoupdates.php
CHANGED
@@ -17,193 +17,163 @@
|
|
17 |
|
18 |
require_once( dirname(__FILE__).'/icwp-optionshandler-base.php' );
|
19 |
|
20 |
-
if ( !class_exists('
|
21 |
|
22 |
-
class
|
23 |
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
|
|
|
|
42 |
}
|
43 |
-
return $this->oFeatureProcessor;
|
44 |
-
}
|
45 |
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
|
|
|
|
|
|
|
|
53 |
}
|
54 |
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
61 |
}
|
62 |
-
}
|
63 |
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
'',
|
76 |
-
'
|
77 |
-
'
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
'
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
_wpsf__( '
|
94 |
-
_wpsf__( '
|
95 |
-
_wpsf__( '
|
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 |
-
_wpsf__( '
|
130 |
-
_wpsf__( '
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
'',
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
'enable_autoupdate_plugins',
|
144 |
-
'',
|
145 |
-
'N',
|
146 |
-
'checkbox',
|
147 |
-
_wpsf__( 'Plugins' ),
|
148 |
-
_wpsf__( 'Automatically Update Plugins' ),
|
149 |
-
_wpsf__( 'Note: Automatic updates for plugins are disabled on WordPress by default.' )
|
150 |
-
),
|
151 |
-
array(
|
152 |
-
'enable_autoupdate_themes',
|
153 |
-
'',
|
154 |
-
'N',
|
155 |
-
'checkbox',
|
156 |
-
_wpsf__( 'Themes' ),
|
157 |
-
_wpsf__( 'Automatically Update Themes' ),
|
158 |
-
_wpsf__( 'Note: Automatic updates for themes are disabled on WordPress by default.' )
|
159 |
-
),
|
160 |
-
array(
|
161 |
-
'enable_autoupdate_ignore_vcs',
|
162 |
-
'',
|
163 |
-
'N',
|
164 |
-
'checkbox',
|
165 |
-
_wpsf__( 'Ignore Version Control' ),
|
166 |
-
_wpsf__( 'Ignore Version Control Systems Such As GIT and SVN' ),
|
167 |
-
_wpsf__( 'If you use SVN or GIT and WordPress detects it, automatic updates are disabled by default. Check this box to ignore version control systems and allow automatic updates.' )
|
168 |
-
)
|
169 |
-
)
|
170 |
-
);
|
171 |
-
|
172 |
-
$aAutoupdateEmail = array(
|
173 |
-
'section_title' => _wpsf__('Automatic Update Email Notifications'),
|
174 |
-
'section_options' => array(
|
175 |
-
array(
|
176 |
-
'enable_upgrade_notification_email',
|
177 |
-
'',
|
178 |
-
'Y',
|
179 |
-
'checkbox',
|
180 |
-
_wpsf__( 'Send Report Email' ),
|
181 |
-
_wpsf__( 'Send email notices after automatic updates' ),
|
182 |
-
_wpsf__( 'You can turn on/off email notices from automatic updates by un/checking this box.' )
|
183 |
-
),
|
184 |
-
array(
|
185 |
-
'override_email_address',
|
186 |
-
'',
|
187 |
-
'',
|
188 |
-
'email',
|
189 |
-
_wpsf__( 'Report Email Address' ),
|
190 |
-
_wpsf__( 'Where to send upgrade notification reports' ),
|
191 |
-
_wpsf__( 'If this is empty, it will default to the Site admin email address' )
|
192 |
-
)
|
193 |
-
)
|
194 |
-
);
|
195 |
-
|
196 |
-
$aOptionsDefinitions = array(
|
197 |
-
$aAutoupdatesBase,
|
198 |
-
$aAutoupdateAll,
|
199 |
-
$aAutoupdatePlugin,
|
200 |
-
$aAutoupdateComponents,
|
201 |
-
$aAutoupdateEmail
|
202 |
-
);
|
203 |
-
return $aOptionsDefinitions;
|
204 |
}
|
205 |
-
}
|
206 |
|
207 |
endif;
|
208 |
|
209 |
-
class ICWP_WPSF_FeatureHandler_Autoupdates extends
|
17 |
|
18 |
require_once( dirname(__FILE__).'/icwp-optionshandler-base.php' );
|
19 |
|
20 |
+
if ( !class_exists('ICWP_WPSF_FeatureHandler_Autoupdates_V3') ):
|
21 |
|
22 |
+
class ICWP_WPSF_FeatureHandler_Autoupdates_V3 extends ICWP_WPSF_FeatureHandler_Base {
|
23 |
|
24 |
+
/**
|
25 |
+
* @var ICWP_WPSF_Processor_Autoupdates
|
26 |
+
*/
|
27 |
+
protected $oFeatureProcessor;
|
28 |
|
29 |
+
public function __construct( $oPluginVo ) {
|
30 |
+
$this->sFeatureName = _wpsf__('Automatic Updates');
|
31 |
+
$this->sFeatureSlug = 'autoupdates';
|
32 |
+
parent::__construct( $oPluginVo );
|
33 |
+
}
|
34 |
|
35 |
+
/**
|
36 |
+
* @return ICWP_WPSF_Processor_Autoupdates|null
|
37 |
+
*/
|
38 |
+
protected function loadFeatureProcessor() {
|
39 |
+
if ( !isset( $this->oFeatureProcessor ) ) {
|
40 |
+
require_once( $this->getController()->getSourceDir( sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) ) );
|
41 |
+
$this->oFeatureProcessor = new ICWP_WPSF_Processor_Autoupdates( $this );
|
42 |
+
}
|
43 |
+
return $this->oFeatureProcessor;
|
44 |
}
|
|
|
|
|
45 |
|
46 |
+
/**
|
47 |
+
* @return bool|void
|
48 |
+
*/
|
49 |
+
protected function doExtraSubmitProcessing() {
|
50 |
+
// Force run automatic updates
|
51 |
+
$oDp = $this->loadDataProcessor();
|
52 |
+
if ( $oDp->FetchGet( 'force_run_auto_updates' ) == 'now' ) {
|
53 |
+
$oProc = $this->getProcessor();
|
54 |
+
$oProc->setForceRunAutoupdates( true );
|
55 |
+
return;
|
56 |
+
}
|
57 |
}
|
58 |
|
59 |
+
/**
|
60 |
+
* @param array $aOptionsParams
|
61 |
+
* @return array
|
62 |
+
* @throws Exception
|
63 |
+
*/
|
64 |
+
protected function loadStrings_SectionTitles( $aOptionsParams ) {
|
65 |
+
|
66 |
+
$sSectionSlug = $aOptionsParams['section_slug'];
|
67 |
+
switch( $sSectionSlug ) {
|
68 |
+
|
69 |
+
case 'section_enable_plugin_feature_automatic_updates_control' :
|
70 |
+
$sTitle = sprintf( _wpsf__( 'Enable Plugin Feature: %s' ), $this->getMainFeatureName() );
|
71 |
+
break;
|
72 |
+
|
73 |
+
case 'section_disable_all_wordpress_automatic_updates' :
|
74 |
+
$sTitle = _wpsf__('Disable ALL WordPress Automatic Updates');
|
75 |
+
break;
|
76 |
+
|
77 |
+
case 'section_automatic_plugin_self_update' :
|
78 |
+
$sTitle = _wpsf__('Automatic Plugin Self-Update');
|
79 |
+
break;
|
80 |
+
|
81 |
+
case 'section_automatic_updates_for_wordpress_components' :
|
82 |
+
$sTitle = _wpsf__('Automatic Updates For WordPress Components');
|
83 |
+
break;
|
84 |
+
|
85 |
+
case 'section_automatic_update_email_notifications' :
|
86 |
+
$sTitle = _wpsf__('Automatic Update Email Notifications');
|
87 |
+
break;
|
88 |
+
|
89 |
+
default:
|
90 |
+
throw new Exception( sprintf( 'A section slug was defined but with no associated strings. Slug: "%s".', $sSectionSlug ) );
|
91 |
+
}
|
92 |
+
$aOptionsParams['section_title'] = $sTitle;
|
93 |
+
return $aOptionsParams;
|
94 |
}
|
|
|
95 |
|
96 |
+
/**
|
97 |
+
* @param array $aOptionsParams
|
98 |
+
* @return array
|
99 |
+
* @throws Exception
|
100 |
+
*/
|
101 |
+
protected function loadStrings_Options( $aOptionsParams ) {
|
102 |
+
|
103 |
+
$sKey = $aOptionsParams['key'];
|
104 |
+
switch( $sKey ) {
|
105 |
+
|
106 |
+
case 'enable_autoupdates' :
|
107 |
+
$sName = sprintf( _wpsf__( 'Enable %s' ), $this->getMainFeatureName() );
|
108 |
+
$sSummary = sprintf( _wpsf__( 'Enable (or Disable) The %s Feature' ), $this->getMainFeatureName() );
|
109 |
+
$sDescription = sprintf( _wpsf__( 'Checking/Un-Checking this option will completely turn on/off the whole %s feature.' ), $this->getMainFeatureName() );
|
110 |
+
break;
|
111 |
+
|
112 |
+
case 'enable_autoupdate_disable_all' :
|
113 |
+
$sName = _wpsf__( 'Disable All' );
|
114 |
+
$sSummary = _wpsf__( 'Completely Disable WordPress Automatic Updates' );
|
115 |
+
$sDescription = _wpsf__( 'When selected, regardless of any other settings, all WordPress automatic updates on this site will be completely disabled!' );
|
116 |
+
break;
|
117 |
+
|
118 |
+
case 'autoupdate_plugin_self' :
|
119 |
+
$sName = _wpsf__( 'Auto Update Plugin' );
|
120 |
+
$sSummary = _wpsf__( 'Always Automatically Update This Plugin' );
|
121 |
+
$sDescription = _wpsf__( 'Regardless of any component settings below, automatically update the WordPress Simple Firewall plugin.' );
|
122 |
+
break;
|
123 |
+
|
124 |
+
case 'autoupdate_core' :
|
125 |
+
$sName = _wpsf__( 'WordPress Core Updates' );
|
126 |
+
$sSummary = _wpsf__( 'Decide how the WordPress Core will automatically update, if at all' );
|
127 |
+
$sDescription = _wpsf__( 'At least automatically upgrading minor versions is recommended (and is the WordPress default).' );
|
128 |
+
break;
|
129 |
+
|
130 |
+
case 'enable_autoupdate_translations' :
|
131 |
+
$sName = _wpsf__( 'Translations' );
|
132 |
+
$sSummary = _wpsf__( 'Automatically Update Translations' );
|
133 |
+
$sDescription = _wpsf__( 'Note: Automatic updates for translations are enabled on WordPress by default.' );
|
134 |
+
break;
|
135 |
+
|
136 |
+
case 'enable_autoupdate_plugins' :
|
137 |
+
$sName = _wpsf__( 'Plugins' );
|
138 |
+
$sSummary = _wpsf__( 'Automatically Update Plugins' );
|
139 |
+
$sDescription = _wpsf__( 'Note: Automatic updates for plugins are disabled on WordPress by default.' );
|
140 |
+
break;
|
141 |
+
|
142 |
+
case 'enable_autoupdate_themes' :
|
143 |
+
$sName = _wpsf__( 'Themes' );
|
144 |
+
$sSummary = _wpsf__( 'Automatically Update Themes' );
|
145 |
+
$sDescription = _wpsf__( 'Note: Automatic updates for themes are disabled on WordPress by default.' );
|
146 |
+
break;
|
147 |
+
|
148 |
+
case 'enable_autoupdate_ignore_vcs' :
|
149 |
+
$sName = _wpsf__( 'Ignore Version Control' );
|
150 |
+
$sSummary = _wpsf__( 'Ignore Version Control Systems Such As GIT and SVN' );
|
151 |
+
$sDescription = _wpsf__( 'If you use SVN or GIT and WordPress detects it, automatic updates are disabled by default. Check this box to ignore version control systems and allow automatic updates.' );
|
152 |
+
break;
|
153 |
+
|
154 |
+
case 'enable_upgrade_notification_email' :
|
155 |
+
$sName = _wpsf__( 'Send Report Email' );
|
156 |
+
$sSummary = _wpsf__( 'Send email notices after automatic updates' );
|
157 |
+
$sDescription = _wpsf__( 'You can turn on/off email notices from automatic updates by un/checking this box.' );
|
158 |
+
break;
|
159 |
+
|
160 |
+
case 'override_email_address' :
|
161 |
+
$sName = _wpsf__( 'Report Email Address' );
|
162 |
+
$sSummary = _wpsf__( 'Where to send upgrade notification reports' );
|
163 |
+
$sDescription = _wpsf__( 'If this is empty, it will default to the Site Admin email address' );
|
164 |
+
break;
|
165 |
+
|
166 |
+
default:
|
167 |
+
throw new Exception( sprintf( 'An option has been defined but without strings assigned to it. Option key: "%s".', $sKey ) );
|
168 |
+
}
|
169 |
+
|
170 |
+
$aOptionsParams['name'] = $sName;
|
171 |
+
$aOptionsParams['summary'] = $sSummary;
|
172 |
+
$aOptionsParams['description'] = $sDescription;
|
173 |
+
return $aOptionsParams;
|
174 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
175 |
}
|
|
|
176 |
|
177 |
endif;
|
178 |
|
179 |
+
class ICWP_WPSF_FeatureHandler_Autoupdates extends ICWP_WPSF_FeatureHandler_Autoupdates_V3 { }
|
src/icwp-optionshandler-base.php
CHANGED
@@ -3,8 +3,6 @@
|
|
3 |
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
-
* Version: 2013-11-15-V1
|
7 |
-
*
|
8 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
9 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
10 |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
@@ -17,985 +15,888 @@
|
|
17 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
18 |
*/
|
19 |
|
|
|
20 |
if ( !class_exists('ICWP_WPSF_FeatureHandler_Base_V2') ):
|
21 |
|
22 |
-
class ICWP_WPSF_FeatureHandler_Base_V2 {
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
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 |
-
add_filter( $this->doPluginPrefix( 'aggregate_all_plugin_options' ), array( $this, 'aggregateOptionsValues' ) );
|
122 |
-
}
|
123 |
-
|
124 |
-
public function override() {
|
125 |
-
|
126 |
-
$oWpFs = $this->loadFileSystemProcessor();
|
127 |
-
if ( $oWpFs->exists( path_join( $this->oPluginVo->getRootDir(), 'forceOff') ) ) {
|
128 |
-
$this->setIsMainFeatureEnabled( false );
|
129 |
-
}
|
130 |
-
else if ( $oWpFs->exists( path_join( $this->oPluginVo->getRootDir(), 'forceOn') ) ) {
|
131 |
-
$this->setIsMainFeatureEnabled( true );
|
132 |
}
|
133 |
-
}
|
134 |
-
|
135 |
-
public function onWpPluginsLoaded() {
|
136 |
-
$this->load();
|
137 |
-
}
|
138 |
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
/**
|
147 |
-
* Hooked to the plugin's main plugin_shutdown action
|
148 |
-
*/
|
149 |
-
public function action_doFeatureShutdown() {
|
150 |
-
$this->savePluginOptions();
|
151 |
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
|
158 |
-
|
159 |
-
|
160 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
161 |
}
|
162 |
|
163 |
-
|
164 |
-
|
165 |
-
|
|
|
|
|
166 |
}
|
167 |
|
168 |
-
|
169 |
-
|
|
|
|
|
170 |
|
171 |
-
|
172 |
-
|
173 |
-
* @return null
|
174 |
-
*/
|
175 |
-
protected function loadFeatureProcessor() {
|
176 |
-
return null;
|
177 |
-
}
|
178 |
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
/**
|
187 |
-
* @return ICWP_WPSF_FeatureHandler_Email
|
188 |
-
*/
|
189 |
-
public static function GetEmailHandler() {
|
190 |
-
if ( is_null( self::$oEmailHandler ) ) {
|
191 |
-
self::$oEmailHandler = new ICWP_WPSF_FeatureHandler_Email( ICWP_Wordpress_Simple_Firewall_Plugin::GetInstance() );
|
192 |
}
|
193 |
-
return self::$oEmailHandler;
|
194 |
-
}
|
195 |
-
|
196 |
-
/**
|
197 |
-
* @return ICWP_WPSF_EmailProcessor
|
198 |
-
*/
|
199 |
-
public function getEmailProcessor() {
|
200 |
-
return $this->GetEmailHandler()->getProcessor();
|
201 |
-
}
|
202 |
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
|
|
|
|
|
|
209 |
}
|
210 |
-
return self::$oLoggingHandler;
|
211 |
-
}
|
212 |
-
|
213 |
-
/**
|
214 |
-
* @return ICWP_WPSF_LoggingProcessor
|
215 |
-
*/
|
216 |
-
public function getLoggingProcessor() {
|
217 |
-
return $this->GetLoggingHandler()->getProcessor();
|
218 |
-
}
|
219 |
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
}
|
226 |
-
|
227 |
-
/**
|
228 |
-
* @return mixed
|
229 |
-
*/
|
230 |
-
public function getIsMainFeatureEnabled() {
|
231 |
-
$this->override();
|
232 |
-
return $this->getOpt( 'enable_'.$this->getFeatureSlug() ) == 'Y';
|
233 |
-
}
|
234 |
-
|
235 |
-
/**
|
236 |
-
* @return mixed
|
237 |
-
*/
|
238 |
-
protected function getMainFeatureName() {
|
239 |
-
return $this->sFeatureName;
|
240 |
-
}
|
241 |
-
|
242 |
-
/**
|
243 |
-
* @return string
|
244 |
-
*/
|
245 |
-
public function getPluginBaseFile() {
|
246 |
-
if ( !isset( self::$sPluginBaseFile ) ) {
|
247 |
-
self::$sPluginBaseFile = plugin_basename( $this->oPluginVo->getRootFile() );
|
248 |
}
|
249 |
-
return self::$sPluginBaseFile;
|
250 |
-
}
|
251 |
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
/**
|
260 |
-
* with trailing slash
|
261 |
-
*/
|
262 |
-
public function getResourcesDir() {
|
263 |
-
$this->oPluginVo->getRootDir().'resources'.ICWP_DS;
|
264 |
-
}
|
265 |
-
|
266 |
-
/**
|
267 |
-
*
|
268 |
-
*/
|
269 |
-
public function filter_flushFeatureLogs( $aLogs ) {
|
270 |
-
if ( $this->getIsMainFeatureEnabled() ) {
|
271 |
-
$aFeatureLogs = $this->getProcessor()->flushLogData();
|
272 |
-
if ( !empty( $aFeatureLogs ) ) {
|
273 |
-
$aLogs = array_merge( $aLogs, $aFeatureLogs );
|
274 |
}
|
|
|
275 |
}
|
276 |
-
return $aLogs;
|
277 |
-
}
|
278 |
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
if ( !$this->fShowFeatureMenuItem || empty( $this->sFeatureName ) ) {
|
285 |
-
return $aItems;
|
286 |
}
|
287 |
-
$sMenuPageTitle = $this->oPluginVo->getHumanName().' - '.$this->getMainFeatureName();
|
288 |
-
$aItems[ $sMenuPageTitle ] = array(
|
289 |
-
$this->getMainFeatureName(),
|
290 |
-
$this->sFeatureSlug,
|
291 |
-
array( $this, 'displayFeatureConfigPage' )
|
292 |
-
);
|
293 |
-
return $aItems;
|
294 |
-
}
|
295 |
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
|
|
|
|
303 |
}
|
304 |
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
return $aSummaryData;
|
312 |
-
}
|
313 |
-
|
314 |
-
/**
|
315 |
-
* A action added to WordPress 'plugins_loaded' hook
|
316 |
-
*/
|
317 |
-
public function onWpInit() {
|
318 |
-
$this->updateHandler();
|
319 |
-
}
|
320 |
-
|
321 |
-
/**
|
322 |
-
* @return bool
|
323 |
-
*/
|
324 |
-
public function hasPluginManageRights() {
|
325 |
-
if ( !current_user_can( $this->oPluginVo->getBasePermissions() ) ) {
|
326 |
-
return false;
|
327 |
}
|
328 |
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
return true;
|
335 |
}
|
336 |
-
return false;
|
337 |
-
}
|
338 |
-
|
339 |
-
/**
|
340 |
-
* @return string
|
341 |
-
*/
|
342 |
-
public function getVersion() {
|
343 |
-
$sVersion = $this->getOpt( self::PluginVersionKey );
|
344 |
-
return empty( $sVersion )? '0.0' : $sVersion;
|
345 |
-
}
|
346 |
-
|
347 |
-
/**
|
348 |
-
* Gets the array of all possible options keys
|
349 |
-
*
|
350 |
-
* @return array
|
351 |
-
*/
|
352 |
-
public function getOptionsKeys() {
|
353 |
-
$this->setOptionsKeys();
|
354 |
-
return $this->aOptionsKeys;
|
355 |
-
}
|
356 |
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
|
|
|
|
|
|
363 |
}
|
364 |
-
$this->buildOptions();
|
365 |
-
}
|
366 |
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
* @return boolean
|
372 |
-
*/
|
373 |
-
public function getIsOptionKey( $sOptionKey ) {
|
374 |
-
$this->setOptionsKeys();
|
375 |
-
return ( in_array( $sOptionKey, $this->aOptionsKeys ) );
|
376 |
-
}
|
377 |
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
* @param string $insKey
|
382 |
-
* @param mixed $inmValue
|
383 |
-
* @return boolean
|
384 |
-
*/
|
385 |
-
public function setOpt( $insKey, $inmValue ) {
|
386 |
|
387 |
-
|
388 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
389 |
}
|
390 |
|
391 |
-
|
392 |
-
|
|
|
|
|
|
|
393 |
}
|
394 |
|
395 |
-
|
396 |
-
|
|
|
|
|
|
|
397 |
}
|
398 |
-
$this->m_aOptionsValues[ $insKey ] = $inmValue;
|
399 |
-
$this->fNeedSave = true;
|
400 |
-
return true;
|
401 |
-
}
|
402 |
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
if ( !isset( $this->m_aOptionsValues ) ) {
|
409 |
-
$this->loadStoredOptionsValues();
|
410 |
}
|
411 |
-
return ( isset( $this->m_aOptionsValues[ $sOptionKey ] )? $this->m_aOptionsValues[ $sOptionKey ] : false );
|
412 |
-
}
|
413 |
-
|
414 |
-
/**
|
415 |
-
* Retrieves the full array of options->values
|
416 |
-
*
|
417 |
-
* @return array
|
418 |
-
*/
|
419 |
-
public function getOptions() {
|
420 |
-
$this->buildOptions();
|
421 |
-
return $this->aOptions;
|
422 |
-
}
|
423 |
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
return $this->m_aOptionsValues;
|
432 |
-
}
|
433 |
-
|
434 |
-
/**
|
435 |
-
* Saves the options to the WordPress Options store.
|
436 |
-
*
|
437 |
-
* It will also update the stored plugin options version.
|
438 |
-
*/
|
439 |
-
public function savePluginOptions() {
|
440 |
-
|
441 |
-
$this->doPrePluginOptionsSave();
|
442 |
-
$this->cleanOptions();
|
443 |
-
$this->updateOptionsVersion();
|
444 |
-
if ( !$this->fNeedSave ) {
|
445 |
-
return true;
|
446 |
}
|
447 |
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
foreach( $this->m_aOptionsValues as $sKey => $mValue ) {
|
459 |
-
if ( !$this->getIsOptionKey( $sKey ) ) {
|
460 |
-
unset( $this->m_aOptionsValues[$sKey] );
|
461 |
}
|
|
|
462 |
}
|
463 |
-
}
|
464 |
-
|
465 |
-
public function collateAllFormInputsForAllOptions() {
|
466 |
-
|
467 |
-
if ( !isset( $this->aOptions ) ) {
|
468 |
-
$this->buildOptions();
|
469 |
-
}
|
470 |
-
|
471 |
-
$aToJoin = array();
|
472 |
-
foreach ( $this->aOptions as $aOptionsSection ) {
|
473 |
|
474 |
-
|
475 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
476 |
}
|
477 |
-
foreach ( $aOptionsSection['section_options'] as $aOption ) {
|
478 |
-
list($sKey, $fill1, $fill2, $sType) = $aOption;
|
479 |
-
$aToJoin[] = $sType.':'.$sKey;
|
480 |
-
}
|
481 |
-
}
|
482 |
-
return implode( self::CollateSeparator, $aToJoin );
|
483 |
-
}
|
484 |
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
if ( empty( $this->m_aOptionsValues ) ) {
|
493 |
-
$this->buildOptions(); // set the defaults
|
494 |
}
|
495 |
-
}
|
496 |
-
|
497 |
-
/**
|
498 |
-
* @param $aAggregatedOptions
|
499 |
-
* @return array
|
500 |
-
*/
|
501 |
-
public function aggregateOptionsValues( $aAggregatedOptions ) {
|
502 |
-
return array_merge( $aAggregatedOptions, $this->loadStoredOptionsValues() );
|
503 |
-
}
|
504 |
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
if ( empty( $this->m_aOptionsValues ) ) {
|
513 |
-
$this->fNeedSave = true;
|
514 |
}
|
515 |
-
}
|
516 |
-
return $this->m_aOptionsValues;
|
517 |
-
}
|
518 |
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
|
|
523 |
|
524 |
-
|
525 |
-
$this->aNonUiOptions = array( self::PluginVersionKey );
|
526 |
-
$aNonUiOptions = $this->getNonUiOptions();
|
527 |
-
if ( !empty( $aNonUiOptions ) || is_array( $aNonUiOptions ) ) {
|
528 |
-
$this->aNonUiOptions = array_merge( $this->aNonUiOptions, $aNonUiOptions );
|
529 |
}
|
530 |
-
}
|
531 |
-
|
532 |
-
/**
|
533 |
-
* @return array
|
534 |
-
*/
|
535 |
-
protected function getOptionsDefinitions() {
|
536 |
-
$aMisc = array(
|
537 |
-
'section_title' => 'Miscellaneous Plugin Options',
|
538 |
-
'section_options' => array(
|
539 |
-
array(
|
540 |
-
'delete_on_deactivate',
|
541 |
-
'',
|
542 |
-
'N',
|
543 |
-
'checkbox',
|
544 |
-
'Delete Plugin Settings',
|
545 |
-
'Delete All Plugin Settings Upon Plugin Deactivation',
|
546 |
-
'Careful: Removes all plugin options when you deactivite the plugin.'
|
547 |
-
),
|
548 |
-
),
|
549 |
-
);
|
550 |
-
$aOptionsDefinitions = array(
|
551 |
-
$aMisc
|
552 |
-
);
|
553 |
-
return $aOptionsDefinitions;
|
554 |
-
}
|
555 |
-
|
556 |
-
/**
|
557 |
-
* @return array
|
558 |
-
*/
|
559 |
-
protected function getNonUiOptions() {
|
560 |
-
return array();
|
561 |
-
}
|
562 |
-
|
563 |
-
/**
|
564 |
-
* Will initiate the plugin options structure for use by the UI builder.
|
565 |
-
*
|
566 |
-
* It will also fill in $this->m_aOptionsValues with defaults where appropriate.
|
567 |
-
*
|
568 |
-
* It doesn't set any values, just populates the array created in buildOptions()
|
569 |
-
* with values stored.
|
570 |
-
*
|
571 |
-
* It has to handle the conversion of stored values to data to be displayed to the user.
|
572 |
-
*/
|
573 |
-
public function buildOptions() {
|
574 |
-
|
575 |
-
$this->defineOptions();
|
576 |
-
$this->loadStoredOptionsValues();
|
577 |
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
|
|
583 |
}
|
584 |
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
|
|
|
|
|
|
|
|
590 |
|
591 |
-
|
592 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
593 |
}
|
594 |
-
$mCurrentOptionVal = $this->getOpt( $sOptionKey );
|
595 |
|
596 |
-
|
597 |
-
$mCurrentOptionVal = '';
|
598 |
-
}
|
599 |
-
else if ( $sOptionType == 'ip_addresses' ) {
|
600 |
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
|
|
606 |
}
|
607 |
-
|
608 |
-
else if ( $sOptionType == 'yubikey_unique_keys' ) {
|
609 |
|
610 |
-
if ( empty( $mCurrentOptionVal ) ) {
|
611 |
$mCurrentOptionVal = '';
|
612 |
}
|
613 |
-
else {
|
614 |
-
|
615 |
-
|
616 |
-
$
|
|
|
|
|
|
|
617 |
}
|
618 |
-
$mCurrentOptionVal = implode( "\n", $aDisplay );
|
619 |
}
|
620 |
-
|
621 |
-
else if ( $sOptionType == 'comma_separated_lists' ) {
|
622 |
|
623 |
-
|
624 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
625 |
}
|
626 |
-
else {
|
627 |
-
|
628 |
-
|
629 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
630 |
}
|
631 |
-
$mCurrentOptionVal = implode( "\n", $aNewValues );
|
632 |
}
|
633 |
-
|
634 |
-
$aOptionParams[1] = $mCurrentOptionVal;
|
635 |
-
}
|
636 |
-
}
|
637 |
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
$this->aOptionsKeys[] = $sOption;
|
642 |
-
if ( !$this->getOpt( $sOption ) ) {
|
643 |
-
$this->setOpt( $sOption, '' );
|
644 |
}
|
645 |
-
}
|
646 |
-
}
|
647 |
-
}
|
648 |
-
|
649 |
-
/**
|
650 |
-
* This is the point where you would want to do any options verification
|
651 |
-
*/
|
652 |
-
protected function doPrePluginOptionsSave() { }
|
653 |
|
654 |
-
|
655 |
-
|
656 |
-
protected function updateOptionsVersion() {
|
657 |
-
$this->setOpt( self::PluginVersionKey, $this->oPluginVo->getVersion() );
|
658 |
-
}
|
659 |
|
660 |
-
|
661 |
-
|
662 |
-
*/
|
663 |
-
public function deletePluginOptions() {
|
664 |
-
if ( apply_filters( $this->doPluginPrefix( 'has_permission_to_submit' ), true ) ) {
|
665 |
-
$oWpFunc = $this->loadWpFunctions();
|
666 |
-
$oWpFunc->deleteOption( $this->sOptionsStoreKey );
|
667 |
|
668 |
-
|
|
|
|
|
|
|
|
|
|
|
669 |
|
670 |
-
|
671 |
-
|
|
|
|
|
|
|
672 |
}
|
673 |
-
}
|
674 |
|
675 |
-
|
|
|
|
|
|
|
676 |
|
677 |
-
|
678 |
-
|
679 |
-
|
|
|
680 |
}
|
681 |
-
foreach( $inaIpList['ips'] as $sAddress ) {
|
682 |
-
// offset=1 in the case that it's a range and the first number is negative on 32-bit systems
|
683 |
-
$mPos = strpos( $sAddress, '-', 1 );
|
684 |
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
$
|
691 |
-
|
692 |
-
$sDisplayText = long2ip( $aParts[0].$nStart ) .'-'. long2ip( $nEnd );
|
693 |
}
|
694 |
-
$sLabel = $inaIpList['meta'][ md5($sAddress) ];
|
695 |
-
$sLabel = trim( $sLabel, '()' );
|
696 |
-
$aDisplay[] = $sDisplayText . ' ('.$sLabel.')';
|
697 |
-
}
|
698 |
-
return $aDisplay;
|
699 |
-
}
|
700 |
-
|
701 |
-
/**
|
702 |
-
*
|
703 |
-
*/
|
704 |
-
public function handleFormSubmit() {
|
705 |
-
if ( !apply_filters( $this->doPluginPrefix( 'has_permission_to_submit' ), true ) ) {
|
706 |
-
// TODO: manage how we react to prohibited submissions
|
707 |
-
return false;
|
708 |
}
|
709 |
|
710 |
-
|
711 |
-
check_admin_referer( $this->oPluginVo->getFullPluginPrefix() );
|
712 |
-
|
713 |
-
$this->loadDataProcessor();
|
714 |
-
$sAllOptions = ICWP_WPSF_DataProcessor::FetchPost( $this->doPluginPrefix( 'all_options_input', '_' ) );
|
715 |
-
|
716 |
-
if ( empty( $sAllOptions ) ) {
|
717 |
-
return true;
|
718 |
-
}
|
719 |
|
720 |
-
|
721 |
-
|
722 |
-
|
|
|
|
|
|
|
|
|
723 |
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
731 |
}
|
732 |
-
$this->loadDataProcessor();
|
733 |
-
$this->loadStoredOptionsValues();
|
734 |
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
|
740 |
-
|
741 |
-
continue;
|
742 |
-
}
|
743 |
|
744 |
-
$
|
745 |
-
|
746 |
|
747 |
-
if (
|
748 |
continue;
|
749 |
}
|
750 |
-
|
751 |
-
$
|
752 |
-
}
|
753 |
-
else if ( $sOptionType == 'integer' ) { //if it was a integer, and it's null, it means '0'
|
754 |
-
$sOptionValue = 0;
|
755 |
}
|
756 |
}
|
757 |
-
|
|
|
758 |
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
|
764 |
-
|
765 |
-
|
766 |
-
}
|
767 |
-
$sOptionValue = md5( $sTempValue );
|
768 |
-
}
|
769 |
-
else if ( $sOptionType == 'ip_addresses' ) { //ip addresses are textareas, where each is separated by newline
|
770 |
-
$sOptionValue = ICWP_WPSF_DataProcessor::ExtractIpAddresses( $sOptionValue );
|
771 |
-
}
|
772 |
-
else if ( $sOptionType == 'yubikey_unique_keys' ) { //ip addresses are textareas, where each is separated by newline and are 12 chars long
|
773 |
-
$sOptionValue = ICWP_WPSF_DataProcessor::CleanYubikeyUniqueKeys( $sOptionValue );
|
774 |
-
}
|
775 |
-
else if ( $sOptionType == 'email' && function_exists( 'is_email' ) && !is_email( $sOptionValue ) ) {
|
776 |
-
$sOptionValue = '';
|
777 |
-
}
|
778 |
-
else if ( $sOptionType == 'comma_separated_lists' ) {
|
779 |
-
$sOptionValue = ICWP_WPSF_DataProcessor::ExtractCommaSeparatedList( $sOptionValue );
|
780 |
-
}
|
781 |
}
|
782 |
-
$this->setOpt( $sOptionKey, $sOptionValue );
|
783 |
-
}
|
784 |
-
return $this->savePluginOptions();
|
785 |
-
}
|
786 |
|
787 |
-
|
788 |
-
|
789 |
-
|
790 |
-
* Called upon construction and after plugin options are initialized.
|
791 |
-
*/
|
792 |
-
protected function updateHandler() {
|
793 |
-
if ( version_compare( $this->getVersion(), '3.0.0', '<' ) ) {
|
794 |
-
$oWpFunctions = $this->loadWpFunctions();
|
795 |
-
$sKey = $this->doPluginPrefix( $this->getFeatureSlug().'_processor', '_' );
|
796 |
-
$oWpFunctions->deleteOption( $sKey );
|
797 |
}
|
798 |
-
}
|
799 |
-
|
800 |
-
/**
|
801 |
-
* @return boolean
|
802 |
-
*/
|
803 |
-
public function hasEncryptOption() {
|
804 |
-
return function_exists( 'md5' );
|
805 |
-
// return extension_loaded( 'mcrypt' );
|
806 |
-
}
|
807 |
|
808 |
-
|
809 |
-
|
810 |
-
|
811 |
-
|
|
|
812 |
|
813 |
-
|
814 |
-
|
815 |
-
|
816 |
-
* @param $sKey
|
817 |
-
* @return string
|
818 |
-
*/
|
819 |
-
protected function prefixOptionKey( $sKey ) {
|
820 |
-
return $this->doPluginPrefix( $sKey, '_' );
|
821 |
-
}
|
822 |
|
823 |
-
|
824 |
-
|
825 |
-
|
826 |
-
|
827 |
-
|
828 |
-
|
829 |
-
*/
|
830 |
-
public function doPluginPrefix( $sSuffix = '', $sGlue = '-' ) {
|
831 |
-
$sPrefix = $this->oPluginVo->getFullPluginPrefix( $sGlue );
|
832 |
|
833 |
-
|
834 |
-
|
|
|
|
|
835 |
}
|
836 |
|
837 |
-
|
838 |
-
}
|
839 |
|
840 |
-
|
841 |
-
|
842 |
-
|
843 |
-
|
844 |
-
|
845 |
-
|
846 |
-
|
|
|
|
|
847 |
|
848 |
-
|
849 |
-
|
850 |
-
|
851 |
-
|
852 |
-
*/
|
853 |
-
protected function processIpFilter( $insExistingListKey, $insFilterName ) {
|
854 |
-
$aFilterIps = apply_filters( $insFilterName, array() );
|
855 |
-
if ( empty( $aFilterIps ) ) {
|
856 |
-
return false;
|
857 |
-
}
|
858 |
|
859 |
-
|
860 |
-
|
861 |
-
|
862 |
-
|
863 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
864 |
}
|
865 |
-
|
866 |
-
|
867 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
868 |
}
|
869 |
-
$aNewIps[ $sIP ] = $sLabel;
|
870 |
}
|
871 |
|
872 |
-
|
873 |
-
|
874 |
-
|
875 |
-
|
876 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
877 |
|
878 |
-
|
879 |
-
|
880 |
-
|
881 |
-
|
882 |
-
|
883 |
-
|
884 |
-
|
|
|
|
|
|
|
|
|
|
|
885 |
|
886 |
-
|
887 |
-
|
888 |
-
|
|
|
|
|
889 |
|
890 |
-
|
891 |
-
$
|
892 |
-
|
|
|
|
|
|
|
893 |
}
|
894 |
|
895 |
-
|
896 |
-
|
897 |
-
|
898 |
-
);
|
899 |
-
$aData = array_merge( $this->getBaseDisplayData(), $aData );
|
900 |
-
$this->display( $aData );
|
901 |
-
}
|
902 |
-
|
903 |
-
public function getIsCurrentPageConfig() {
|
904 |
-
$oWpFunctions = $this->loadWpFunctions();
|
905 |
-
return $oWpFunctions->getCurrentWpAdminPage() == $this->doPluginPrefix( $this->sFeatureSlug );
|
906 |
-
}
|
907 |
|
908 |
-
|
909 |
-
|
910 |
-
|
911 |
-
|
912 |
-
'requested_page' => $this->doPluginPrefix( $this->sFeatureSlug )
|
913 |
-
);
|
914 |
-
$aData = array_merge( $this->getBaseDisplayData(), $aData );
|
915 |
-
$this->display( $aData, 'access_restricted_index' );
|
916 |
-
}
|
917 |
|
918 |
-
|
919 |
-
|
920 |
-
|
921 |
-
|
922 |
-
|
923 |
-
|
924 |
-
|
925 |
-
|
926 |
-
|
927 |
-
|
928 |
-
|
929 |
-
)
|
930 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
931 |
|
932 |
-
|
933 |
-
|
934 |
-
|
935 |
-
|
936 |
-
return apply_filters( $this->doPluginPrefix( 'show_marketing' ), true );
|
937 |
-
}
|
938 |
|
939 |
-
|
940 |
-
|
941 |
-
|
942 |
-
* @return bool
|
943 |
-
*/
|
944 |
-
protected function display( $inaData = array(), $sView = '' ) {
|
945 |
|
946 |
-
|
947 |
-
$
|
948 |
-
$
|
949 |
-
|
950 |
-
$sFile = $oWpFs->exists( $sCustomViewSource ) ? $sCustomViewSource : $sNormalViewSource;
|
951 |
-
}
|
952 |
-
else {
|
953 |
-
$sFile = $this->oPluginVo->getViewDir().$this->doPluginPrefix( $sView ).'.php';
|
954 |
-
}
|
955 |
|
956 |
-
|
957 |
-
|
958 |
-
return false;
|
959 |
}
|
960 |
|
961 |
-
|
962 |
-
|
|
|
|
|
|
|
|
|
963 |
}
|
964 |
|
965 |
-
|
966 |
-
|
967 |
-
|
968 |
-
|
969 |
-
|
970 |
-
|
971 |
-
return true;
|
972 |
-
}
|
973 |
-
|
974 |
-
protected function loadDataProcessor() {
|
975 |
-
if ( !class_exists('ICWP_WPSF_DataProcessor') ) {
|
976 |
-
require_once( dirname(__FILE__).'/icwp-data-processor.php' );
|
977 |
}
|
978 |
-
}
|
979 |
|
980 |
-
|
981 |
-
|
982 |
-
|
983 |
-
|
984 |
-
|
985 |
-
}
|
986 |
-
|
987 |
-
/**
|
988 |
-
* @return ICWP_WpFilesystem_WPSF
|
989 |
-
*/
|
990 |
-
protected function loadFileSystemProcessor() {
|
991 |
-
if ( !class_exists('ICWP_WpFilesystem_WPSF') ) {
|
992 |
-
require_once( dirname(__FILE__) . '/icwp-wpfilesystem.php' );
|
993 |
}
|
994 |
-
return ICWP_WpFilesystem_WPSF::GetInstance();
|
995 |
}
|
996 |
|
997 |
-
}
|
998 |
-
|
999 |
endif;
|
1000 |
|
1001 |
-
class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_FeatureHandler_Base_V2 { }
|
3 |
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
* All rights reserved.
|
5 |
*
|
|
|
|
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
7 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
8 |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
15 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
*/
|
17 |
|
18 |
+
require_once( 'icwp-options-vo.php' );
|
19 |
if ( !class_exists('ICWP_WPSF_FeatureHandler_Base_V2') ):
|
20 |
|
21 |
+
abstract class ICWP_WPSF_FeatureHandler_Base_V2 extends ICWP_WPSF_Foundation {
|
22 |
+
|
23 |
+
/**
|
24 |
+
* @var ICWP_WPSF_Plugin_Controller
|
25 |
+
*/
|
26 |
+
protected $oPluginController;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @var ICWP_WPSF_OptionsVO
|
30 |
+
*/
|
31 |
+
protected $oOptions;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* @var string
|
35 |
+
*/
|
36 |
+
const CollateSeparator = '--SEP--';
|
37 |
+
/**
|
38 |
+
* @var string
|
39 |
+
*/
|
40 |
+
const PluginVersionKey = 'current_plugin_version';
|
41 |
+
|
42 |
+
/**
|
43 |
+
* @var boolean
|
44 |
+
*/
|
45 |
+
protected $fPluginDeleting = false;
|
46 |
+
|
47 |
+
/**
|
48 |
+
* @var string
|
49 |
+
*/
|
50 |
+
protected $sOptionsStoreKey;
|
51 |
+
|
52 |
+
/**
|
53 |
+
* @var string
|
54 |
+
*/
|
55 |
+
protected $sFeatureName;
|
56 |
+
|
57 |
+
/**
|
58 |
+
* @var string
|
59 |
+
*/
|
60 |
+
protected $sFeatureSlug;
|
61 |
+
|
62 |
+
/**
|
63 |
+
* @var string
|
64 |
+
*/
|
65 |
+
protected static $sPluginBaseFile;
|
66 |
+
|
67 |
+
/**
|
68 |
+
* @var ICWP_WPSF_FeatureHandler_Email
|
69 |
+
*/
|
70 |
+
protected static $oEmailHandler;
|
71 |
+
|
72 |
+
/**
|
73 |
+
* @var ICWP_WPSF_FeatureHandler_Email
|
74 |
+
*/
|
75 |
+
protected static $oLoggingHandler;
|
76 |
+
|
77 |
+
/**
|
78 |
+
* @var ICWP_WPSF_Processor_Base
|
79 |
+
*/
|
80 |
+
protected $oFeatureProcessor;
|
81 |
+
|
82 |
+
/**
|
83 |
+
* @var boolean
|
84 |
+
*/
|
85 |
+
protected $fOverrideState;
|
86 |
+
|
87 |
+
public function __construct( $oPluginController, $sOptionsStoreKey = null ) {
|
88 |
+
if ( empty( $oPluginController ) ) {
|
89 |
+
throw new Exception();
|
90 |
+
}
|
91 |
+
$this->oPluginController = $oPluginController;
|
92 |
+
$this->sOptionsStoreKey = $this->prefixOptionKey(
|
93 |
+
( is_null( $sOptionsStoreKey ) ? $this->getFeatureSlug() : $sOptionsStoreKey )
|
94 |
+
.'_options'
|
95 |
+
);
|
96 |
+
|
97 |
+
// Handle any upgrades as necessary (only go near this if it's the admin area)
|
98 |
+
add_action( 'plugins_loaded', array( $this, 'onWpPluginsLoaded' ) );
|
99 |
+
add_action( 'init', array( $this, 'onWpInit' ), 1 );
|
100 |
+
add_action( $this->doPluginPrefix( 'form_submit' ), array( $this, 'handleFormSubmit' ) );
|
101 |
+
add_filter( $this->doPluginPrefix( 'filter_plugin_submenu_items' ), array( $this, 'filter_addPluginSubMenuItem' ) );
|
102 |
+
add_filter( $this->doPluginPrefix( 'get_feature_summary_data' ), array( $this, 'filter_getFeatureSummaryData' ) );
|
103 |
+
add_filter( $this->doPluginPrefix( 'flush_logs' ), array( $this, 'filter_flushFeatureLogs' ) );
|
104 |
+
add_action( $this->doPluginPrefix( 'plugin_shutdown' ), array( $this, 'action_doFeatureShutdown' ) );
|
105 |
+
add_action( $this->doPluginPrefix( 'delete_plugin' ), array( $this, 'deletePluginOptions' ) );
|
106 |
+
add_filter( $this->doPluginPrefix( 'aggregate_all_plugin_options' ), array( $this, 'aggregateOptionsValues' ) );
|
107 |
+
}
|
108 |
+
|
109 |
+
/**
|
110 |
+
* A action added to WordPress 'plugins_loaded' hook
|
111 |
+
*/
|
112 |
+
public function onWpPluginsLoaded() {
|
113 |
+
|
114 |
+
if ( $this->getIsMainFeatureEnabled() ) {
|
115 |
+
$oProcessor = $this->getProcessor();
|
116 |
+
if ( is_object( $oProcessor ) && $oProcessor instanceof ICWP_WPSF_Processor_Base ) {
|
117 |
+
$oProcessor->run();
|
118 |
+
}
|
119 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
120 |
}
|
|
|
|
|
|
|
|
|
|
|
121 |
|
122 |
+
/**
|
123 |
+
* A action added to WordPress 'init' hook
|
124 |
+
*/
|
125 |
+
public function onWpInit() {
|
126 |
+
$this->updateHandler();
|
127 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
|
129 |
+
/**
|
130 |
+
* Override this and adapt per feature
|
131 |
+
* @return null
|
132 |
+
*/
|
133 |
+
abstract protected function loadFeatureProcessor();
|
134 |
|
135 |
+
/**
|
136 |
+
* @return ICWP_WPSF_OptionsVO
|
137 |
+
*/
|
138 |
+
public function getOptionsVo() {
|
139 |
+
if ( !isset( $this->oOptions ) ) {
|
140 |
+
$this->oOptions = new ICWP_WPSF_OptionsVO( $this->getFeatureSlug() );
|
141 |
+
$this->oOptions->setOptionsStorageKey( $this->getOptionsStorageKey() );
|
142 |
+
}
|
143 |
+
return $this->oOptions;
|
144 |
}
|
145 |
|
146 |
+
/**
|
147 |
+
* @return bool
|
148 |
+
*/
|
149 |
+
public function getIsUpgrading() {
|
150 |
+
return $this->getVersion() != $this->getController()->getVersion();
|
151 |
}
|
152 |
|
153 |
+
/**
|
154 |
+
* Hooked to the plugin's main plugin_shutdown action
|
155 |
+
*/
|
156 |
+
public function action_doFeatureShutdown() {
|
157 |
|
158 |
+
if ( ! $this->fPluginDeleting ) {
|
159 |
+
$this->savePluginOptions();
|
|
|
|
|
|
|
|
|
|
|
160 |
|
161 |
+
if ( $this->getController()->getIsLoggingEnabled() ) {
|
162 |
+
$aLogData = apply_filters( $this->doPluginPrefix( 'flush_logs' ), array() );
|
163 |
+
$oLoggingProcessor = $this->getLoggingProcessor();
|
164 |
+
$oLoggingProcessor->addDataToWrite( $aLogData );
|
165 |
+
$oLoggingProcessor->commitData();
|
166 |
+
}
|
167 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
168 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
169 |
|
170 |
+
/**
|
171 |
+
* @return string
|
172 |
+
*/
|
173 |
+
protected function getOptionsStorageKey() {
|
174 |
+
if ( !isset( $this->sOptionsStoreKey ) ) {
|
175 |
+
// not ideal as it doesn't take into account custom storage keys as when passed into the constructor
|
176 |
+
$this->sOptionsStoreKey = $this->prefixOptionKey( $this->getFeatureSlug().'_options' );
|
177 |
+
}
|
178 |
+
return $this->sOptionsStoreKey;
|
179 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
180 |
|
181 |
+
/**
|
182 |
+
* @return ICWP_WPSF_Processor_Base
|
183 |
+
*/
|
184 |
+
public function getProcessor() {
|
185 |
+
return $this->loadFeatureProcessor();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
186 |
}
|
|
|
|
|
187 |
|
188 |
+
/**
|
189 |
+
* @return ICWP_WPSF_FeatureHandler_Email
|
190 |
+
*/
|
191 |
+
public function getEmailHandler() {
|
192 |
+
if ( is_null( self::$oEmailHandler ) ) {
|
193 |
+
self::$oEmailHandler = new ICWP_WPSF_FeatureHandler_Email( $this->getController() );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
194 |
}
|
195 |
+
return self::$oEmailHandler;
|
196 |
}
|
|
|
|
|
197 |
|
198 |
+
/**
|
199 |
+
* @return ICWP_WPSF_Processor_Email
|
200 |
+
*/
|
201 |
+
public function getEmailProcessor() {
|
202 |
+
return $this->getEmailHandler()->getProcessor();
|
|
|
|
|
203 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
204 |
|
205 |
+
/**
|
206 |
+
* @return ICWP_WPSF_FeatureHandler_Logging
|
207 |
+
*/
|
208 |
+
public function getLoggingHandler() {
|
209 |
+
if ( is_null( self::$oLoggingHandler ) ) {
|
210 |
+
require_once( 'icwp-optionshandler-logging.php' );
|
211 |
+
self::$oLoggingHandler = new ICWP_WPSF_FeatureHandler_Logging( $this->getController() );
|
212 |
+
}
|
213 |
+
return self::$oLoggingHandler;
|
214 |
}
|
215 |
|
216 |
+
/**
|
217 |
+
* @return ICWP_WPSF_Processor_Logging
|
218 |
+
*/
|
219 |
+
public function getLoggingProcessor() {
|
220 |
+
return $this->getLoggingHandler()->getProcessor();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
221 |
}
|
222 |
|
223 |
+
/**
|
224 |
+
* @param $fEnable
|
225 |
+
*/
|
226 |
+
public function setIsMainFeatureEnabled( $fEnable ) {
|
227 |
+
$this->setOpt( 'enable_'.$this->getFeatureSlug(), $fEnable ? 'Y' : 'N' );
|
|
|
228 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
229 |
|
230 |
+
/**
|
231 |
+
* @return mixed
|
232 |
+
*/
|
233 |
+
public function getIsMainFeatureEnabled() {
|
234 |
+
$fOverride = $this->getIfOverride();
|
235 |
+
if ( $fOverride ) {
|
236 |
+
return !$fOverride;
|
237 |
+
}
|
238 |
+
return $this->getOptIs( 'enable_'.$this->getFeatureSlug(), 'Y' ) || $this->getOptIs( 'enable_'.$this->getFeatureSlug(), true, true ) ;
|
239 |
}
|
|
|
|
|
240 |
|
241 |
+
/**
|
242 |
+
* Returns true if you're overriding OFF. We don't do override ON any more (as of 3.5.1)
|
243 |
+
*/
|
244 |
+
public function getIfOverride() {
|
|
|
|
|
|
|
|
|
|
|
|
|
245 |
|
246 |
+
if ( !is_null( $this->fOverrideState ) ) {
|
247 |
+
return $this->fOverrideState;
|
248 |
+
}
|
|
|
|
|
|
|
|
|
|
|
249 |
|
250 |
+
$oWpFs = $this->loadFileSystemProcessor();
|
251 |
+
if ( $oWpFs->fileExistsInDir( 'forceOff', $this->getController()->getRootDir(), false ) ) {
|
252 |
+
$this->fOverrideState = true;
|
253 |
+
}
|
254 |
+
else {
|
255 |
+
$this->fOverrideState = false;
|
256 |
+
}
|
257 |
+
return $this->fOverrideState;
|
258 |
}
|
259 |
|
260 |
+
/**
|
261 |
+
* @return string
|
262 |
+
*/
|
263 |
+
protected function getMainFeatureName() {
|
264 |
+
return $this->sFeatureName;
|
265 |
}
|
266 |
|
267 |
+
/**
|
268 |
+
* @return string
|
269 |
+
*/
|
270 |
+
public function getPluginBaseFile() {
|
271 |
+
return $this->getController()->getPluginBaseFile();
|
272 |
}
|
|
|
|
|
|
|
|
|
273 |
|
274 |
+
/**
|
275 |
+
* @return string
|
276 |
+
*/
|
277 |
+
public function getFeatureSlug() {
|
278 |
+
return $this->sFeatureSlug;
|
|
|
|
|
279 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
280 |
|
281 |
+
/**
|
282 |
+
* With trailing slash
|
283 |
+
* @param string $sSourceFile
|
284 |
+
* @return string
|
285 |
+
*/
|
286 |
+
public function getResourcesDir( $sSourceFile = '' ) {
|
287 |
+
return $this->getController()->getRootDir().'resources'.ICWP_DS.ltrim( $sSourceFile, ICWP_DS );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
288 |
}
|
289 |
|
290 |
+
/**
|
291 |
+
* @param array $aLogs
|
292 |
+
* @return array
|
293 |
+
*/
|
294 |
+
public function filter_flushFeatureLogs( $aLogs ) {
|
295 |
+
if ( $this->getIsMainFeatureEnabled() ) {
|
296 |
+
$aFeatureLogs = $this->getProcessor()->flushLogData();
|
297 |
+
if ( !empty( $aFeatureLogs ) ) {
|
298 |
+
$aLogs = array_merge( $aLogs, $aFeatureLogs );
|
299 |
+
}
|
|
|
|
|
|
|
300 |
}
|
301 |
+
return $aLogs;
|
302 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
303 |
|
304 |
+
/**
|
305 |
+
* @param array $aItems
|
306 |
+
* @return array
|
307 |
+
*/
|
308 |
+
public function filter_addPluginSubMenuItem( $aItems ) {
|
309 |
+
$sName = $this->getMainFeatureName();
|
310 |
+
if ( !$this->getIfShowFeatureMenuItem() || empty( $sName ) ) {
|
311 |
+
return $aItems;
|
312 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
313 |
|
314 |
+
$sMenuPageTitle = $this->getController()->getHumanName().' - '.$sName;
|
315 |
+
$aItems[ $sMenuPageTitle ] = array(
|
316 |
+
$sName,
|
317 |
+
$this->doPluginPrefix( $this->getFeatureSlug() ),
|
318 |
+
array( $this, 'displayFeatureConfigPage' )
|
319 |
+
);
|
320 |
+
return $aItems;
|
|
|
|
|
321 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
322 |
|
323 |
+
/**
|
324 |
+
* @param array $aSummaryData
|
325 |
+
* @return array
|
326 |
+
*/
|
327 |
+
public function filter_getFeatureSummaryData( $aSummaryData ) {
|
328 |
+
if ( !$this->getIfShowFeatureMenuItem() ) {
|
329 |
+
return $aSummaryData;
|
|
|
|
|
330 |
}
|
|
|
|
|
|
|
331 |
|
332 |
+
$aSummaryData[] = array(
|
333 |
+
$this->getIsMainFeatureEnabled(),
|
334 |
+
$this->getMainFeatureName(),
|
335 |
+
$this->doPluginPrefix( $this->getFeatureSlug() )
|
336 |
+
);
|
337 |
|
338 |
+
return $aSummaryData;
|
|
|
|
|
|
|
|
|
339 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
340 |
|
341 |
+
/**
|
342 |
+
* @return bool
|
343 |
+
*/
|
344 |
+
public function hasPluginManageRights() {
|
345 |
+
if ( !current_user_can( $this->getController()->getBasePermissions() ) ) {
|
346 |
+
return false;
|
347 |
}
|
348 |
|
349 |
+
$oWpFunc = $this->loadWpFunctionsProcessor();
|
350 |
+
if ( is_admin() && !$oWpFunc->isMultisite() ) {
|
351 |
+
return true;
|
352 |
+
}
|
353 |
+
else if ( is_network_admin() && $oWpFunc->isMultisite() ) {
|
354 |
+
return true;
|
355 |
+
}
|
356 |
+
return false;
|
357 |
+
}
|
358 |
|
359 |
+
/**
|
360 |
+
* @return boolean
|
361 |
+
*/
|
362 |
+
public function getIfShowFeatureMenuItem() {
|
363 |
+
return $this->getOptionsVo()->getFeatureProperty( 'show_feature_menu_item' );
|
364 |
+
}
|
365 |
+
|
366 |
+
/**
|
367 |
+
* @param string $sOptionKey
|
368 |
+
* @param mixed $mDefault
|
369 |
+
* @return mixed
|
370 |
+
*/
|
371 |
+
public function getOpt( $sOptionKey, $mDefault = false ) {
|
372 |
+
return $this->getOptionsVo()->getOpt( $sOptionKey, $mDefault );
|
373 |
+
}
|
374 |
+
|
375 |
+
/**
|
376 |
+
* @param string $sOptionKey
|
377 |
+
* @param mixed $mValueToTest
|
378 |
+
* @param boolean $fStrict
|
379 |
+
* @return bool
|
380 |
+
*/
|
381 |
+
public function getOptIs( $sOptionKey, $mValueToTest, $fStrict = false ) {
|
382 |
+
$mOptionValue = $this->getOptionsVo()->getOpt( $sOptionKey );
|
383 |
+
return $fStrict? $mOptionValue === $mValueToTest : $mOptionValue == $mValueToTest;
|
384 |
+
}
|
385 |
+
|
386 |
+
/**
|
387 |
+
* Retrieves the full array of options->values
|
388 |
+
*
|
389 |
+
* @return array
|
390 |
+
*/
|
391 |
+
public function getOptions() {
|
392 |
+
return $this->buildOptions();
|
393 |
+
}
|
394 |
+
|
395 |
+
/**
|
396 |
+
* @return string
|
397 |
+
*/
|
398 |
+
public function getVersion() {
|
399 |
+
$sVersion = $this->getOpt( self::PluginVersionKey );
|
400 |
+
return empty( $sVersion )? '0.0' : $sVersion;
|
401 |
+
}
|
402 |
+
|
403 |
+
/**
|
404 |
+
* Sets the value for the given option key
|
405 |
+
*
|
406 |
+
* @param string $sOptionKey
|
407 |
+
* @param mixed $mValue
|
408 |
+
* @return boolean
|
409 |
+
*/
|
410 |
+
public function setOpt( $sOptionKey, $mValue ) {
|
411 |
+
return $this->getOptionsVo()->setOpt( $sOptionKey, $mValue );
|
412 |
+
}
|
413 |
+
|
414 |
+
/**
|
415 |
+
* Saves the options to the WordPress Options store.
|
416 |
+
*
|
417 |
+
* It will also update the stored plugin options version.
|
418 |
+
*/
|
419 |
+
public function savePluginOptions() {
|
420 |
+
$this->doPrePluginOptionsSave();
|
421 |
+
$this->updateOptionsVersion();
|
422 |
+
$this->getOptionsVo()->doOptionsSave();
|
423 |
+
}
|
424 |
+
|
425 |
+
/**
|
426 |
+
* @param $aAggregatedOptions
|
427 |
+
* @return array
|
428 |
+
*/
|
429 |
+
public function aggregateOptionsValues( $aAggregatedOptions ) {
|
430 |
+
return array_merge( $aAggregatedOptions, $this->getOptionsVo()->getAllOptionsValues() );
|
431 |
+
}
|
432 |
+
|
433 |
+
/**
|
434 |
+
* Will initiate the plugin options structure for use by the UI builder.
|
435 |
+
*
|
436 |
+
* It doesn't set any values, just populates the array created in buildOptions()
|
437 |
+
* with values stored.
|
438 |
+
*
|
439 |
+
* It has to handle the conversion of stored values to data to be displayed to the user.
|
440 |
+
*/
|
441 |
+
public function buildOptions() {
|
442 |
+
|
443 |
+
$aOptions = $this->getOptionsVo()->getLegacyOptionsConfigData();
|
444 |
+
foreach ( $aOptions as $nSectionKey => $aOptionsSection ) {
|
445 |
+
|
446 |
+
if ( empty( $aOptionsSection ) || !isset( $aOptionsSection['section_options'] ) ) {
|
447 |
+
continue;
|
448 |
}
|
|
|
449 |
|
450 |
+
foreach ( $aOptionsSection['section_options'] as $nKey => $aOptionParams ) {
|
|
|
|
|
|
|
451 |
|
452 |
+
$sOptionKey = $aOptionParams['key'];
|
453 |
+
$sOptionDefault = $aOptionParams['default'];
|
454 |
+
$sOptionType = $aOptionParams['type'];
|
455 |
+
|
456 |
+
if ( $this->getOpt( $sOptionKey ) === false ) {
|
457 |
+
$this->setOpt( $sOptionKey, $sOptionDefault );
|
458 |
}
|
459 |
+
$mCurrentOptionVal = $this->getOpt( $sOptionKey );
|
|
|
460 |
|
461 |
+
if ( $sOptionType == 'password' && !empty( $mCurrentOptionVal ) ) {
|
462 |
$mCurrentOptionVal = '';
|
463 |
}
|
464 |
+
else if ( $sOptionType == 'ip_addresses' ) {
|
465 |
+
|
466 |
+
if ( empty( $mCurrentOptionVal ) ) {
|
467 |
+
$mCurrentOptionVal = '';
|
468 |
+
}
|
469 |
+
else {
|
470 |
+
$mCurrentOptionVal = implode( "\n", $this->convertIpListForDisplay( $mCurrentOptionVal ) );
|
471 |
}
|
|
|
472 |
}
|
473 |
+
else if ( $sOptionType == 'yubikey_unique_keys' ) {
|
|
|
474 |
|
475 |
+
if ( empty( $mCurrentOptionVal ) ) {
|
476 |
+
$mCurrentOptionVal = '';
|
477 |
+
}
|
478 |
+
else {
|
479 |
+
$aDisplay = array();
|
480 |
+
foreach( $mCurrentOptionVal as $aParts ) {
|
481 |
+
$aDisplay[] = key($aParts) .', '. reset($aParts);
|
482 |
+
}
|
483 |
+
$mCurrentOptionVal = implode( "\n", $aDisplay );
|
484 |
+
}
|
485 |
}
|
486 |
+
else if ( $sOptionType == 'comma_separated_lists' ) {
|
487 |
+
|
488 |
+
if ( empty( $mCurrentOptionVal ) ) {
|
489 |
+
$mCurrentOptionVal = '';
|
490 |
+
}
|
491 |
+
else {
|
492 |
+
$aNewValues = array();
|
493 |
+
foreach( $mCurrentOptionVal as $sPage => $aParams ) {
|
494 |
+
$aNewValues[] = $sPage.', '. implode( ", ", $aParams );
|
495 |
+
}
|
496 |
+
$mCurrentOptionVal = implode( "\n", $aNewValues );
|
497 |
}
|
|
|
498 |
}
|
499 |
+
$aOptionParams['value'] = $mCurrentOptionVal;
|
|
|
|
|
|
|
500 |
|
501 |
+
// Build strings
|
502 |
+
$aParamsWithStrings = $this->loadStrings_Options( $aOptionParams );
|
503 |
+
$aOptionsSection['section_options'][$nKey] = $aParamsWithStrings;
|
|
|
|
|
|
|
504 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
505 |
|
506 |
+
$aOptions[$nSectionKey] = $this->loadStrings_SectionTitles( $aOptionsSection );
|
507 |
+
}
|
|
|
|
|
|
|
508 |
|
509 |
+
return $aOptions;
|
510 |
+
}
|
|
|
|
|
|
|
|
|
|
|
511 |
|
512 |
+
/**
|
513 |
+
* @param $aOptionsParams
|
514 |
+
*/
|
515 |
+
protected function loadStrings_Options( $aOptionsParams ) {
|
516 |
+
return $aOptionsParams;
|
517 |
+
}
|
518 |
|
519 |
+
/**
|
520 |
+
* @param $aOptionsParams
|
521 |
+
*/
|
522 |
+
protected function loadStrings_SectionTitles( $aOptionsParams ) {
|
523 |
+
return $aOptionsParams;
|
524 |
}
|
|
|
525 |
|
526 |
+
/**
|
527 |
+
* This is the point where you would want to do any options verification
|
528 |
+
*/
|
529 |
+
protected function doPrePluginOptionsSave() { }
|
530 |
|
531 |
+
/**
|
532 |
+
*/
|
533 |
+
protected function updateOptionsVersion() {
|
534 |
+
$this->setOpt( self::PluginVersionKey, $this->getController()->getVersion() );
|
535 |
}
|
|
|
|
|
|
|
536 |
|
537 |
+
/**
|
538 |
+
* Deletes all the options including direct save.
|
539 |
+
*/
|
540 |
+
public function deletePluginOptions() {
|
541 |
+
if ( apply_filters( $this->doPluginPrefix( 'has_permission_to_submit' ), true ) ) {
|
542 |
+
$this->getOptionsVo()->doOptionsDelete();
|
543 |
+
$this->fPluginDeleting = true;
|
|
|
544 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
545 |
}
|
546 |
|
547 |
+
protected function convertIpListForDisplay( $inaIpList = array() ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
548 |
|
549 |
+
$aDisplay = array();
|
550 |
+
if ( empty( $inaIpList ) || empty( $inaIpList['ips'] ) ) {
|
551 |
+
return $aDisplay;
|
552 |
+
}
|
553 |
+
foreach( $inaIpList['ips'] as $sAddress ) {
|
554 |
+
// offset=1 in the case that it's a range and the first number is negative on 32-bit systems
|
555 |
+
$mPos = strpos( $sAddress, '-', 1 );
|
556 |
|
557 |
+
if ( $mPos === false ) { //plain IP address
|
558 |
+
$sDisplayText = long2ip( $sAddress );
|
559 |
+
}
|
560 |
+
else {
|
561 |
+
//we remove the first character in case this is '-'
|
562 |
+
$aParts = array( substr( $sAddress, 0, 1 ), substr( $sAddress, 1 ) );
|
563 |
+
list( $nStart, $nEnd ) = explode( '-', $aParts[1], 2 );
|
564 |
+
$sDisplayText = long2ip( $aParts[0].$nStart ) .'-'. long2ip( $nEnd );
|
565 |
+
}
|
566 |
+
$sLabel = $inaIpList['meta'][ md5($sAddress) ];
|
567 |
+
$sLabel = trim( $sLabel, '()' );
|
568 |
+
$aDisplay[] = $sDisplayText . ' ('.$sLabel.')';
|
569 |
+
}
|
570 |
+
return $aDisplay;
|
571 |
}
|
|
|
|
|
572 |
|
573 |
+
/**
|
574 |
+
* @return string
|
575 |
+
*/
|
576 |
+
protected function collateAllFormInputsForAllOptions() {
|
577 |
|
578 |
+
$aOptions = $this->getOptions();
|
|
|
|
|
579 |
|
580 |
+
$aToJoin = array();
|
581 |
+
foreach ( $aOptions as $aOptionsSection ) {
|
582 |
|
583 |
+
if ( empty( $aOptionsSection ) ) {
|
584 |
continue;
|
585 |
}
|
586 |
+
foreach ( $aOptionsSection['section_options'] as $aOption ) {
|
587 |
+
$aToJoin[] = $aOption['type'].':'.$aOption['key'];
|
|
|
|
|
|
|
588 |
}
|
589 |
}
|
590 |
+
return implode( self::CollateSeparator, $aToJoin );
|
591 |
+
}
|
592 |
|
593 |
+
/**
|
594 |
+
*/
|
595 |
+
public function handleFormSubmit() {
|
596 |
+
$fVerified = $this->verifyFormSubmit();
|
597 |
+
|
598 |
+
if ( !$fVerified ) {
|
599 |
+
return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
600 |
}
|
|
|
|
|
|
|
|
|
601 |
|
602 |
+
$this->doSaveStandardOptions();
|
603 |
+
$this->doExtraSubmitProcessing();
|
604 |
+
return true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
605 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
606 |
|
607 |
+
protected function verifyFormSubmit() {
|
608 |
+
if ( !apply_filters( $this->doPluginPrefix( 'has_permission_to_submit' ), true ) ) {
|
609 |
+
// TODO: manage how we react to prohibited submissions
|
610 |
+
return false;
|
611 |
+
}
|
612 |
|
613 |
+
// Now verify this is really a valid submission.
|
614 |
+
return check_admin_referer( $this->getController()->getPluginPrefix() );
|
615 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
616 |
|
617 |
+
/**
|
618 |
+
* @return bool
|
619 |
+
*/
|
620 |
+
protected function doSaveStandardOptions() {
|
621 |
+
$oDp = $this->loadDataProcessor();
|
622 |
+
$sAllOptions = $oDp->FetchPost( $this->prefixOptionKey( 'all_options_input' ) );
|
|
|
|
|
|
|
623 |
|
624 |
+
if ( empty( $sAllOptions ) ) {
|
625 |
+
return true;
|
626 |
+
}
|
627 |
+
$this->updatePluginOptionsFromSubmit( $sAllOptions ); //it also saves
|
628 |
}
|
629 |
|
630 |
+
protected function doExtraSubmitProcessing() { }
|
|
|
631 |
|
632 |
+
/**
|
633 |
+
* @param string $sAllOptionsInput - comma separated list of all the input keys to be processed from the $_POST
|
634 |
+
* @return void|boolean
|
635 |
+
*/
|
636 |
+
public function updatePluginOptionsFromSubmit( $sAllOptionsInput ) {
|
637 |
+
if ( empty( $sAllOptionsInput ) ) {
|
638 |
+
return;
|
639 |
+
}
|
640 |
+
$oDp = $this->loadDataProcessor();
|
641 |
|
642 |
+
$aAllInputOptions = explode( self::CollateSeparator, $sAllOptionsInput );
|
643 |
+
foreach ( $aAllInputOptions as $sInputKey ) {
|
644 |
+
$aInput = explode( ':', $sInputKey );
|
645 |
+
list( $sOptionType, $sOptionKey ) = $aInput;
|
|
|
|
|
|
|
|
|
|
|
|
|
646 |
|
647 |
+
$sOptionValue = $oDp->FetchPost( $this->prefixOptionKey( $sOptionKey ) );
|
648 |
+
if ( is_null( $sOptionValue ) ) {
|
649 |
+
|
650 |
+
if ( $sOptionType == 'text' || $sOptionType == 'email' ) { //if it was a text box, and it's null, don't update anything
|
651 |
+
continue;
|
652 |
+
}
|
653 |
+
else if ( $sOptionType == 'checkbox' ) { //if it was a checkbox, and it's null, it means 'N'
|
654 |
+
$sOptionValue = 'N';
|
655 |
+
}
|
656 |
+
else if ( $sOptionType == 'integer' ) { //if it was a integer, and it's null, it means '0'
|
657 |
+
$sOptionValue = 0;
|
658 |
+
}
|
659 |
+
}
|
660 |
+
else { //handle any pre-processing we need to.
|
661 |
+
|
662 |
+
if ( $sOptionType == 'text' || $sOptionType == 'email' ) {
|
663 |
+
$sOptionValue = trim( $sOptionValue );
|
664 |
+
}
|
665 |
+
if ( $sOptionType == 'integer' ) {
|
666 |
+
$sOptionValue = intval( $sOptionValue );
|
667 |
+
}
|
668 |
+
else if ( $sOptionType == 'password' && $this->hasEncryptOption() ) { //md5 any password fields
|
669 |
+
$sTempValue = trim( $sOptionValue );
|
670 |
+
if ( empty( $sTempValue ) ) {
|
671 |
+
continue;
|
672 |
+
}
|
673 |
+
$sOptionValue = md5( $sTempValue );
|
674 |
+
}
|
675 |
+
else if ( $sOptionType == 'ip_addresses' ) { //ip addresses are textareas, where each is separated by newline
|
676 |
+
$sOptionValue = $oDp->ExtractIpAddresses( $sOptionValue );
|
677 |
+
}
|
678 |
+
else if ( $sOptionType == 'yubikey_unique_keys' ) { //ip addresses are textareas, where each is separated by newline and are 12 chars long
|
679 |
+
$sOptionValue = $oDp->CleanYubikeyUniqueKeys( $sOptionValue );
|
680 |
+
}
|
681 |
+
else if ( $sOptionType == 'email' && function_exists( 'is_email' ) && !is_email( $sOptionValue ) ) {
|
682 |
+
$sOptionValue = '';
|
683 |
+
}
|
684 |
+
else if ( $sOptionType == 'comma_separated_lists' ) {
|
685 |
+
$sOptionValue = $oDp->ExtractCommaSeparatedList( $sOptionValue );
|
686 |
+
}
|
687 |
+
else if ( $sOptionType == 'multiple_select' ) {
|
688 |
+
}
|
689 |
+
}
|
690 |
+
$this->setOpt( $sOptionKey, $sOptionValue );
|
691 |
}
|
692 |
+
return $this->savePluginOptions();
|
693 |
+
}
|
694 |
+
|
695 |
+
/**
|
696 |
+
* Should be over-ridden by each new class to handle upgrades.
|
697 |
+
*
|
698 |
+
* Called upon construction and after plugin options are initialized.
|
699 |
+
*/
|
700 |
+
protected function updateHandler() {
|
701 |
+
if ( version_compare( $this->getVersion(), '3.0.0', '<' ) ) {
|
702 |
+
$oWpFunctions = $this->loadWpFunctionsProcessor();
|
703 |
+
$sKey = $this->doPluginPrefix( $this->getFeatureSlug().'_processor', '_' );
|
704 |
+
$oWpFunctions->deleteOption( $sKey );
|
705 |
}
|
|
|
706 |
}
|
707 |
|
708 |
+
/**
|
709 |
+
* @return boolean
|
710 |
+
*/
|
711 |
+
public function hasEncryptOption() {
|
712 |
+
return function_exists( 'md5' );
|
713 |
+
// return extension_loaded( 'mcrypt' );
|
714 |
+
}
|
715 |
+
|
716 |
+
/**
|
717 |
+
* Prefixes an option key only if it's needed
|
718 |
+
*
|
719 |
+
* @param $sKey
|
720 |
+
* @return string
|
721 |
+
*/
|
722 |
+
public function prefixOptionKey( $sKey ) {
|
723 |
+
return $this->doPluginPrefix( $sKey, '_' );
|
724 |
+
}
|
725 |
+
|
726 |
+
/**
|
727 |
+
* Will prefix and return any string with the unique plugin prefix.
|
728 |
+
*
|
729 |
+
* @param string $sSuffix
|
730 |
+
* @param string $sGlue
|
731 |
+
* @return string
|
732 |
+
*/
|
733 |
+
public function doPluginPrefix( $sSuffix = '', $sGlue = '-' ) {
|
734 |
+
return $this->getController()->doPluginPrefix( $sSuffix, $sGlue );
|
735 |
+
}
|
736 |
+
|
737 |
+
/**
|
738 |
+
* @param string
|
739 |
+
* @return string
|
740 |
+
*/
|
741 |
+
public function getOptionStoragePrefix() {
|
742 |
+
return $this->getController()->getOptionStoragePrefix();
|
743 |
+
}
|
744 |
+
|
745 |
+
/**
|
746 |
+
* @param string $insExistingListKey
|
747 |
+
* @param string $insFilterName
|
748 |
+
* @return array|false
|
749 |
+
*/
|
750 |
+
protected function processIpFilter( $insExistingListKey, $insFilterName ) {
|
751 |
+
$aFilterIps = apply_filters( $insFilterName, array() );
|
752 |
+
if ( empty( $aFilterIps ) ) {
|
753 |
+
return false;
|
754 |
+
}
|
755 |
|
756 |
+
$aNewIps = array();
|
757 |
+
foreach( $aFilterIps as $mKey => $sValue ) {
|
758 |
+
if ( is_string( $mKey ) ) { //it's the IP
|
759 |
+
$sIP = $mKey;
|
760 |
+
$sLabel = $sValue;
|
761 |
+
}
|
762 |
+
else { //it's not an associative array, so the value is the IP
|
763 |
+
$sIP = $sValue;
|
764 |
+
$sLabel = '';
|
765 |
+
}
|
766 |
+
$aNewIps[ $sIP ] = $sLabel;
|
767 |
+
}
|
768 |
|
769 |
+
// now add and store the new IPs
|
770 |
+
$aExistingIpList = $this->getOpt( $insExistingListKey );
|
771 |
+
if ( !is_array( $aExistingIpList ) ) {
|
772 |
+
$aExistingIpList = array();
|
773 |
+
}
|
774 |
|
775 |
+
$oDp = $this->loadDataProcessor();
|
776 |
+
$nNewAddedCount = 0;
|
777 |
+
$aNewList = $oDp->Add_New_Raw_Ips( $aExistingIpList, $aNewIps, $nNewAddedCount );
|
778 |
+
if ( $nNewAddedCount > 0 ) {
|
779 |
+
$this->setOpt( $insExistingListKey, $aNewList );
|
780 |
+
}
|
781 |
}
|
782 |
|
783 |
+
/**
|
784 |
+
*/
|
785 |
+
public function displayFeatureConfigPage( ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
786 |
|
787 |
+
if ( !apply_filters( $this->doPluginPrefix( 'has_permission_to_view' ), true ) ) {
|
788 |
+
$this->displayViewAccessRestrictedPage();
|
789 |
+
return;
|
790 |
+
}
|
|
|
|
|
|
|
|
|
|
|
791 |
|
792 |
+
// $aPluginSummaryData = apply_filters( $this->doPluginPrefix( 'get_feature_summary_data' ), array() );
|
793 |
+
$aData = array(
|
794 |
+
'aSummaryData' => isset( $aPluginSummaryData ) ? $aPluginSummaryData : array()
|
795 |
+
);
|
796 |
+
$aData = array_merge( $this->getBaseDisplayData(), $aData );
|
797 |
+
$this->display( $aData );
|
798 |
+
}
|
799 |
+
|
800 |
+
/**
|
801 |
+
* @return bool
|
802 |
+
*/
|
803 |
+
public function getIsCurrentPageConfig() {
|
804 |
+
$oWpFunctions = $this->loadWpFunctionsProcessor();
|
805 |
+
return $oWpFunctions->getCurrentWpAdminPage() == $this->doPluginPrefix( $this->getFeatureSlug() );
|
806 |
+
}
|
807 |
+
|
808 |
+
/**
|
809 |
+
*/
|
810 |
+
public function displayViewAccessRestrictedPage( ) {
|
811 |
+
$aData = $this->getBaseDisplayData();
|
812 |
+
$this->display( $aData, 'access_restricted_index' );
|
813 |
+
}
|
814 |
+
|
815 |
+
/**
|
816 |
+
* @return array
|
817 |
+
*/
|
818 |
+
protected function getBaseDisplayData() {
|
819 |
+
return array(
|
820 |
+
'var_prefix' => $this->getController()->getOptionStoragePrefix(),
|
821 |
+
'sPluginName' => $this->getController()->getHumanName(),
|
822 |
+
'sFeatureName' => $this->getMainFeatureName(),
|
823 |
+
'fShowAds' => $this->getIsShowMarketing(),
|
824 |
+
'nonce_field' => $this->getController()->getPluginPrefix(),
|
825 |
+
'sFeatureSlug' => $this->doPluginPrefix( $this->getFeatureSlug() ),
|
826 |
+
'form_action' => 'admin.php?page='.$this->doPluginPrefix( $this->getFeatureSlug() ),
|
827 |
+
'nOptionsPerRow' => 1,
|
828 |
+
|
829 |
+
'aAllOptions' => $this->getOptions(),
|
830 |
+
'all_options_input' => $this->collateAllFormInputsForAllOptions()
|
831 |
+
);
|
832 |
+
}
|
833 |
+
|
834 |
+
/**
|
835 |
+
* @return boolean
|
836 |
+
*/
|
837 |
+
protected function getIsShowMarketing() {
|
838 |
+
return apply_filters( $this->doPluginPrefix( 'show_marketing' ), true );
|
839 |
+
}
|
840 |
+
|
841 |
+
/**
|
842 |
+
* @param array $aData
|
843 |
+
* @param string $sView
|
844 |
+
* @return bool
|
845 |
+
*/
|
846 |
+
protected function display( $aData = array(), $sView = '' ) {
|
847 |
+
|
848 |
+
if ( empty( $sView ) ) {
|
849 |
+
$oWpFs = $this->loadFileSystemProcessor();
|
850 |
+
$sCustomViewSource = $this->getController()->getViewPath( $this->doPluginPrefix( 'config_'.$this->getFeatureSlug().'_index' ) );
|
851 |
+
$sNormalViewSource = $this->getController()->getViewPath( $this->doPluginPrefix( 'config_index' ) );
|
852 |
+
$sFile = $oWpFs->exists( $sCustomViewSource ) ? $sCustomViewSource : $sNormalViewSource;
|
853 |
+
}
|
854 |
+
else {
|
855 |
+
$sFile = $this->getController()->getViewPath( $this->doPluginPrefix( $sView ) );
|
856 |
+
}
|
857 |
|
858 |
+
if ( !is_file( $sFile ) ) {
|
859 |
+
echo "View not found: ".$sFile;
|
860 |
+
return false;
|
861 |
+
}
|
|
|
|
|
862 |
|
863 |
+
if ( count( $aData ) > 0 ) {
|
864 |
+
extract( $aData, EXTR_PREFIX_ALL, $this->getController()->getParentSlug() ); //slug being 'icwp'
|
865 |
+
}
|
|
|
|
|
|
|
866 |
|
867 |
+
ob_start();
|
868 |
+
include( $sFile );
|
869 |
+
$sContents = ob_get_contents();
|
870 |
+
ob_end_clean();
|
|
|
|
|
|
|
|
|
|
|
871 |
|
872 |
+
echo $sContents;
|
873 |
+
return true;
|
|
|
874 |
}
|
875 |
|
876 |
+
/**
|
877 |
+
* @param string $sSnippet
|
878 |
+
* @return string
|
879 |
+
*/
|
880 |
+
public function getViewSnippet( $sSnippet = '' ) {
|
881 |
+
return $this->getController()->getViewSnippet( $sSnippet );
|
882 |
}
|
883 |
|
884 |
+
/**
|
885 |
+
* @param $sStatKey
|
886 |
+
*/
|
887 |
+
public function doStatIncrement( $sStatKey ) {
|
888 |
+
$this->loadStatsProcessor();
|
889 |
+
ICWP_Stats_WPSF::DoStatIncrement( $sStatKey );
|
|
|
|
|
|
|
|
|
|
|
|
|
890 |
}
|
|
|
891 |
|
892 |
+
/**
|
893 |
+
* @return ICWP_WPSF_Plugin_Controller
|
894 |
+
*/
|
895 |
+
public function getController() {
|
896 |
+
return $this->oPluginController;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
897 |
}
|
|
|
898 |
}
|
899 |
|
|
|
|
|
900 |
endif;
|
901 |
|
902 |
+
abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_FeatureHandler_Base_V2 { }
|
src/icwp-optionshandler-comments_filter.php
CHANGED
@@ -21,11 +21,8 @@ if ( !class_exists('ICWP_WPSF_FeatureHandler_CommentsFilter') ):
|
|
21 |
|
22 |
class ICWP_WPSF_FeatureHandler_CommentsFilter extends ICWP_WPSF_FeatureHandler_Base {
|
23 |
|
24 |
-
const DefaultCommentCooldown = 30; //seconds.
|
25 |
-
const DefaultCommentExpire = 600; //seconds.
|
26 |
-
|
27 |
/**
|
28 |
-
* @var
|
29 |
*/
|
30 |
protected $oFeatureProcessor;
|
31 |
|
@@ -36,188 +33,323 @@ class ICWP_WPSF_FeatureHandler_CommentsFilter extends ICWP_WPSF_FeatureHandler_B
|
|
36 |
}
|
37 |
|
38 |
/**
|
39 |
-
* @return
|
40 |
*/
|
41 |
protected function loadFeatureProcessor() {
|
42 |
if ( !isset( $this->oFeatureProcessor ) ) {
|
43 |
-
require_once(
|
44 |
-
$this->oFeatureProcessor = new
|
45 |
}
|
46 |
return $this->oFeatureProcessor;
|
47 |
}
|
48 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
/**
|
50 |
* @return array
|
51 |
*/
|
52 |
protected function getOptionsDefinitions() {
|
53 |
|
54 |
-
$aBase = array(
|
55 |
-
'section_title' => sprintf( _wpsf__( 'Enable Plugin Feature: %s' ), _wpsf__('SPAM Comments Protection Filter') ),
|
56 |
-
'section_options' => array(
|
57 |
-
array(
|
58 |
-
'enable_comments_filter',
|
59 |
-
'',
|
60 |
-
'N',
|
61 |
-
'checkbox',
|
62 |
-
_wpsf__( 'Enable Comments Filter' ),
|
63 |
-
_wpsf__( 'Enable (or Disable) The SPAM Comments Protection Filter Feature' ),
|
64 |
-
sprintf( _wpsf__( 'Checking/Un-Checking this option will completely turn on/off the whole %s feature.' ), _wpsf__('SPAM Comments Protection Filter') ),
|
65 |
-
'<a href="http://icwp.io/3z" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
66 |
-
.' | <a href="http://icwp.io/wpsf04" target="_blank">'._wpsf__( 'blog' ).'</a>'
|
67 |
-
)
|
68 |
-
)
|
69 |
-
);
|
70 |
-
|
71 |
-
$aHumanSpam = array(
|
72 |
-
'section_title' => sprintf( _wpsf__( '%s Comment SPAM Protection Filter' ), _wpsf__('Human') ),
|
73 |
-
'section_options' => array(
|
74 |
-
array(
|
75 |
-
'enable_comments_human_spam_filter',
|
76 |
-
'',
|
77 |
-
'N',
|
78 |
-
'checkbox',
|
79 |
-
_wpsf__( 'Human SPAM Filter' ),
|
80 |
-
_wpsf__( 'Enable (or Disable) The Human SPAM Filter Feature.' ),
|
81 |
-
_wpsf__( 'Scans the content of WordPress comments for keywords that are indicative of SPAM and marks the comment according to your preferred setting below.' ),
|
82 |
-
'<a href="http://icwp.io/57" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
83 |
-
),
|
84 |
-
array(
|
85 |
-
'enable_comments_human_spam_filter_items',
|
86 |
-
'',
|
87 |
-
$this->getHumanSpamFilterItems( true ),
|
88 |
-
$this->getHumanSpamFilterItems(),
|
89 |
-
_wpsf__( 'Comment Filter Items' ),
|
90 |
-
_wpsf__( 'Select The Items To Scan For SPAM' ),
|
91 |
-
_wpsf__( 'When a user submits a comment, only the selected parts of the comment data will be scanned for SPAM content.' ).' '.sprintf( _wpsf__('Recommended: %s'), _wpsf__('All') ),
|
92 |
-
'<a href="http://icwp.io/58" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
93 |
-
),
|
94 |
-
array(
|
95 |
-
'comments_default_action_human_spam',
|
96 |
-
'',
|
97 |
-
'spam',
|
98 |
-
$this->getSpamHandlingResponses(),
|
99 |
-
_wpsf__( 'Default SPAM Action' ),
|
100 |
-
_wpsf__( 'How To Categorise Comments When Identified To Be SPAM' ),
|
101 |
-
sprintf( _wpsf__( 'When a comment is detected as being SPAM from %s, the comment will be categorised based on this setting.' ), '<span style"text-decoration:underline;">'._wpsf__('a human commenter').'</span>' ),
|
102 |
-
'<a href="http://icwp.io/59" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
103 |
-
)
|
104 |
-
),
|
105 |
-
);
|
106 |
-
|
107 |
-
$aGasp = array(
|
108 |
-
'section_title' => sprintf( _wpsf__( '%s Comment SPAM Protection Filter' ), _wpsf__('Automatic Bot') ),
|
109 |
-
'section_options' => array(
|
110 |
-
array(
|
111 |
-
'enable_comments_gasp_protection',
|
112 |
-
'',
|
113 |
-
'Y',
|
114 |
-
'checkbox',
|
115 |
-
_wpsf__( 'GASP Protection' ),
|
116 |
-
_wpsf__( 'Add Growmap Anti Spambot Protection to your comments' ),
|
117 |
-
_wpsf__( 'Taking the lead from the original GASP plugin for WordPress, we have extended it to include advanced spam-bot protection.' ),
|
118 |
-
'<a href="http://icwp.io/3n" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
119 |
-
.' | <a href="http://icwp.io/2n" target="_blank">'._wpsf__( 'blog' ).'</a>'
|
120 |
-
),
|
121 |
-
array(
|
122 |
-
'comments_default_action_spam_bot',
|
123 |
-
'',
|
124 |
-
'trash',
|
125 |
-
$this->getSpamHandlingResponses(),
|
126 |
-
_wpsf__( 'Default SPAM Action' ),
|
127 |
-
_wpsf__( 'How To Categorise Comments When Identified To Be SPAM' ),
|
128 |
-
sprintf( _wpsf__( 'When a comment is detected as being SPAM from %s, the comment will be categorised based on this setting.' ), '<span style"text-decoration:underline;">'._wpsf__('an automatic bot').'</span>' ),
|
129 |
-
'<a href="http://icwp.io/59" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
130 |
-
),
|
131 |
-
array(
|
132 |
-
'enable_comments_gasp_protection_for_logged_in',
|
133 |
-
'',
|
134 |
-
'N',
|
135 |
-
'checkbox',
|
136 |
-
_wpsf__( 'Include Logged-In Users' ),
|
137 |
-
_wpsf__( 'You may also enable GASP for logged in users' ),
|
138 |
-
_wpsf__( 'Since logged-in users would be expected to be vetted already, this is off by default.' )
|
139 |
-
),
|
140 |
-
array(
|
141 |
-
'comments_cooldown_interval',
|
142 |
-
'',
|
143 |
-
'30',
|
144 |
-
'integer',
|
145 |
-
_wpsf__( 'Comments Cooldown' ),
|
146 |
-
_wpsf__( 'Limit posting comments to X seconds after the page has loaded' ),
|
147 |
-
_wpsf__( "By forcing a comments cooldown period, you restrict a Spambot's ability to post mutliple times to your posts." ),
|
148 |
-
'<a href="http://icwp.io/3o" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
149 |
-
),
|
150 |
-
array(
|
151 |
-
'comments_token_expire_interval',
|
152 |
-
'',
|
153 |
-
'600',
|
154 |
-
'integer',
|
155 |
-
_wpsf__( 'Comment Token Expire' ),
|
156 |
-
_wpsf__( 'A visitor has X seconds within which to post a comment' ),
|
157 |
-
_wpsf__( "Default: 600 seconds (10 minutes). Each visitor is given a unique 'Token' so they can comment. This restricts spambots, but we need to force these tokens to expire and at the same time not bother the visitors." ),
|
158 |
-
'<a href="http://icwp.io/3o" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
159 |
-
|
160 |
-
)
|
161 |
-
)
|
162 |
-
);
|
163 |
-
|
164 |
-
$aCustomMessages = array(
|
165 |
-
'section_title' => sprintf( _wpsf__( 'Customize Messages Shown To User' ), _wpsf__('Automatic Bot') ),
|
166 |
-
'section_options' => array(
|
167 |
-
array(
|
168 |
-
'custom_message_checkbox',
|
169 |
-
'',
|
170 |
-
_wpsf__( "I'm not a spammer" ),
|
171 |
-
'text',
|
172 |
-
_wpsf__( 'Custom Checkbox Message' ),
|
173 |
-
_wpsf__( 'If you want a custom checkbox message, please provide this here' ),
|
174 |
-
_wpsf__( "You can customise the message beside the checkbox." )
|
175 |
-
.'<br />'.sprintf( _wpsf__( 'Default Message: %s' ), _wpsf__("Please check the box to confirm you're not a spammer") ),
|
176 |
-
'<a href="http://icwp.io/3p" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
177 |
-
),
|
178 |
-
array(
|
179 |
-
'custom_message_alert',
|
180 |
-
'',
|
181 |
-
_wpsf__( "Please check the box to confirm you're not a spammer" ),
|
182 |
-
'text',
|
183 |
-
_wpsf__( 'Custom Alert Message' ),
|
184 |
-
_wpsf__( 'If you want a custom alert message, please provide this here' ),
|
185 |
-
_wpsf__( "This alert message is displayed when a visitor attempts to submit a comment without checking the box." )
|
186 |
-
.'<br />'.sprintf( _wpsf__( 'Default Message: %s' ), _wpsf__("Please check the box to confirm you're not a spammer") ),
|
187 |
-
'<a href="http://icwp.io/3p" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
188 |
-
),
|
189 |
-
array(
|
190 |
-
'custom_message_comment_wait',
|
191 |
-
'',
|
192 |
-
_wpsf__( "Please wait %s seconds before posting your comment" ),
|
193 |
-
'text',
|
194 |
-
_wpsf__( 'Custom Wait Message' ),
|
195 |
-
_wpsf__( 'If you want a custom submit-button wait message, please provide this here.' ),
|
196 |
-
_wpsf__( "Where you see the '%s' this will be the number of seconds. You must ensure you include 1, and only 1, of these." )
|
197 |
-
.'<br />'.sprintf( _wpsf__( 'Default Message: %s' ), _wpsf__('Please wait %s seconds before posting your comment') ),
|
198 |
-
'<a href="http://icwp.io/3p" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
199 |
-
),
|
200 |
-
array(
|
201 |
-
'custom_message_comment_reload',
|
202 |
-
'',
|
203 |
-
_wpsf__( "Please reload this page to post a comment" ),
|
204 |
-
'text',
|
205 |
-
_wpsf__( 'Custom Reload Message' ),
|
206 |
-
_wpsf__( 'If you want a custom message when the comment token has expired, please provide this here.' ),
|
207 |
-
_wpsf__( 'This message is displayed on the submit-button when the comment token is expired' )
|
208 |
-
.'<br />'.sprintf( _wpsf__( 'Default Message: %s' ), _wpsf__("Please reload this page to post a comment") ),
|
209 |
-
'<a href="http://icwp.io/3p" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
210 |
-
)
|
211 |
-
)
|
212 |
-
);
|
213 |
-
|
214 |
-
$aOptionsDefinitions = array(
|
215 |
-
$aBase,
|
216 |
-
$aHumanSpam,
|
217 |
-
$aGasp,
|
218 |
-
$aCustomMessages
|
219 |
-
);
|
220 |
-
return $aOptionsDefinitions;
|
221 |
}
|
222 |
|
223 |
/**
|
@@ -225,58 +357,30 @@ class ICWP_WPSF_FeatureHandler_CommentsFilter extends ICWP_WPSF_FeatureHandler_B
|
|
225 |
*/
|
226 |
protected function doPrePluginOptionsSave() {
|
227 |
|
228 |
-
|
229 |
-
|
230 |
-
$nCommentCooldown = 0;
|
231 |
}
|
232 |
|
233 |
-
|
234 |
-
|
235 |
-
$nCommentTokenExpire = 0;
|
236 |
}
|
237 |
|
238 |
-
if ( $
|
239 |
-
$
|
240 |
-
$
|
241 |
}
|
242 |
-
$this->setOpt( 'comments_cooldown_interval', $nCommentCooldown );
|
243 |
-
$this->setOpt( 'comments_token_expire_interval', $nCommentTokenExpire );
|
244 |
|
245 |
$aCommentsFilters = $this->getOpt( 'enable_comments_human_spam_filter_items' );
|
246 |
-
if ( empty($aCommentsFilters) || !is_array( $aCommentsFilters ) ) {
|
247 |
-
$this->
|
248 |
}
|
249 |
}
|
250 |
|
251 |
/**
|
252 |
-
* @return
|
253 |
-
*/
|
254 |
-
protected function getSpamHandlingResponses() {
|
255 |
-
return array( 'select',
|
256 |
-
array( 0, _wpsf__( 'Mark As Pending Moderation' ) ),
|
257 |
-
array( 'spam', _wpsf__( 'Mark As SPAM' ) ),
|
258 |
-
array( 'trash', _wpsf__( 'Move To Trash' ) ),
|
259 |
-
array( 'reject', _wpsf__( 'Reject And Redirect' ) )
|
260 |
-
);
|
261 |
-
}
|
262 |
-
|
263 |
-
/**
|
264 |
-
*
|
265 |
*/
|
266 |
-
|
267 |
-
$
|
268 |
-
'author_name' => _wpsf__('Author Name'),
|
269 |
-
'author_email' => _wpsf__('Author Email'),
|
270 |
-
'comment_content' => _wpsf__('Comment Content'),
|
271 |
-
'url' => _wpsf__('URL'),
|
272 |
-
'ip_address' => _wpsf__('IP Address'),
|
273 |
-
'user_agent' => _wpsf__('Browser User Agent')
|
274 |
-
);
|
275 |
-
if ( $fAsDefaults ) {
|
276 |
-
unset($aFilterItems['type']);
|
277 |
-
return array_keys($aFilterItems);
|
278 |
-
}
|
279 |
-
return $aFilterItems;
|
280 |
}
|
281 |
}
|
282 |
|
21 |
|
22 |
class ICWP_WPSF_FeatureHandler_CommentsFilter extends ICWP_WPSF_FeatureHandler_Base {
|
23 |
|
|
|
|
|
|
|
24 |
/**
|
25 |
+
* @var ICWP_WPSF_Processor_CommentsFilter
|
26 |
*/
|
27 |
protected $oFeatureProcessor;
|
28 |
|
33 |
}
|
34 |
|
35 |
/**
|
36 |
+
* @return ICWP_WPSF_Processor_CommentsFilter|null
|
37 |
*/
|
38 |
protected function loadFeatureProcessor() {
|
39 |
if ( !isset( $this->oFeatureProcessor ) ) {
|
40 |
+
require_once( $this->getController()->getSourceDir().sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) );
|
41 |
+
$this->oFeatureProcessor = new ICWP_WPSF_Processor_CommentsFilter( $this );
|
42 |
}
|
43 |
return $this->oFeatureProcessor;
|
44 |
}
|
45 |
|
46 |
+
/**
|
47 |
+
* @param array $aOptionsParams
|
48 |
+
* @return array
|
49 |
+
* @throws Exception
|
50 |
+
*/
|
51 |
+
protected function loadStrings_SectionTitles( $aOptionsParams ) {
|
52 |
+
|
53 |
+
$sSectionSlug = $aOptionsParams['section_slug'];
|
54 |
+
switch( $aOptionsParams['section_slug'] ) {
|
55 |
+
|
56 |
+
case 'section_enable_plugin_feature_spam_comments_protection_filter' :
|
57 |
+
$sTitle = sprintf( _wpsf__( 'Enable Plugin Feature: %s' ), _wpsf__('SPAM Comments Protection Filter') );
|
58 |
+
break;
|
59 |
+
|
60 |
+
case 'section_enable_human_comment_spam_protection_filter' :
|
61 |
+
$sTitle = sprintf( _wpsf__( '%s Comment SPAM Protection Filter' ), _wpsf__('Human') );
|
62 |
+
break;
|
63 |
+
|
64 |
+
case 'section_enable_automatic_bot_comment_spam_protection_filter' :
|
65 |
+
$sTitle = sprintf( _wpsf__( '%s Comment SPAM Protection Filter' ), _wpsf__('Automatic Bot') );
|
66 |
+
break;
|
67 |
+
|
68 |
+
case 'section_customize_messages_shown_to_user' :
|
69 |
+
$sTitle = _wpsf__( 'Customize Messages Shown To User' );
|
70 |
+
break;
|
71 |
+
|
72 |
+
default:
|
73 |
+
throw new Exception( sprintf( 'A section slug was defined but with no associated strings. Slug: "%s".', $sSectionSlug ) );
|
74 |
+
}
|
75 |
+
$aOptionsParams['section_title'] = $sTitle;
|
76 |
+
return $aOptionsParams;
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* @param array $aOptionsParams
|
81 |
+
* @return array
|
82 |
+
* @throws Exception
|
83 |
+
*/
|
84 |
+
protected function loadStrings_Options( $aOptionsParams ) {
|
85 |
+
|
86 |
+
$sKey = $aOptionsParams['key'];
|
87 |
+
switch( $sKey ) {
|
88 |
+
|
89 |
+
case 'enable_comments_filter' :
|
90 |
+
$sName = sprintf( _wpsf__( 'Enable %s' ), _wpsf__('Comments Filter') );
|
91 |
+
$sSummary = _wpsf__( 'Enable (or Disable) The SPAM Comments Protection Filter Feature' );
|
92 |
+
$sDescription = sprintf( _wpsf__( 'Checking/Un-Checking this option will completely turn on/off the whole %s feature.' ), _wpsf__('SPAM Comments Protection Filter') );
|
93 |
+
break;
|
94 |
+
|
95 |
+
case 'enable_comments_human_spam_filter' :
|
96 |
+
$sName = _wpsf__( 'Human SPAM Filter' );
|
97 |
+
$sSummary = _wpsf__( 'Enable (or Disable) The Human SPAM Filter Feature.' );
|
98 |
+
$sDescription = _wpsf__( 'Scans the content of WordPress comments for keywords that are indicative of SPAM and marks the comment according to your preferred setting below.' );
|
99 |
+
break;
|
100 |
+
|
101 |
+
case 'enable_comments_human_spam_filter_items' :
|
102 |
+
$sName = _wpsf__( 'Comment Filter Items' );
|
103 |
+
$sSummary = _wpsf__( 'Select The Items To Scan For SPAM' );
|
104 |
+
$sDescription = _wpsf__( 'When a user submits a comment, only the selected parts of the comment data will be scanned for SPAM content.' ).' '.sprintf( _wpsf__('Recommended: %s'), _wpsf__('All') );
|
105 |
+
break;
|
106 |
+
|
107 |
+
case 'comments_default_action_human_spam' :
|
108 |
+
$sName = _wpsf__( 'Default SPAM Action' );
|
109 |
+
$sSummary = _wpsf__( 'How To Categorise Comments When Identified To Be SPAM' );
|
110 |
+
$sDescription = sprintf( _wpsf__( 'When a comment is detected as being SPAM from %s, the comment will be categorised based on this setting.' ), '<span style"text-decoration:underline;">'._wpsf__('a human commenter').'</span>' );
|
111 |
+
break;
|
112 |
+
|
113 |
+
case 'enable_comments_gasp_protection' :
|
114 |
+
$sName = _wpsf__( 'GASP Protection' );
|
115 |
+
$sSummary = _wpsf__( 'Add Growmap Anti Spambot Protection to your comments' );
|
116 |
+
$sDescription = _wpsf__( 'Taking the lead from the original GASP plugin for WordPress, we have extended it to include advanced spam-bot protection.' );
|
117 |
+
break;
|
118 |
+
|
119 |
+
case 'comments_default_action_spam_bot' :
|
120 |
+
$sName = _wpsf__( 'Default SPAM Action' );
|
121 |
+
$sSummary = _wpsf__( 'How To Categorise Comments When Identified To Be SPAM' );
|
122 |
+
$sDescription = sprintf( _wpsf__( 'When a comment is detected as being SPAM from %s, the comment will be categorised based on this setting.' ), '<span style"text-decoration:underline;">'._wpsf__('an automatic bot').'</span>' );
|
123 |
+
break;
|
124 |
+
|
125 |
+
case 'enable_comments_gasp_protection_for_logged_in' :
|
126 |
+
$sName = _wpsf__( 'Include Logged-In Users' );
|
127 |
+
$sSummary = _wpsf__( 'You may also enable GASP for logged in users' );
|
128 |
+
$sDescription = _wpsf__( 'Since logged-in users would be expected to be vetted already, this is off by default.' );
|
129 |
+
break;
|
130 |
+
|
131 |
+
case 'comments_cooldown_interval' :
|
132 |
+
$sName = _wpsf__( 'Comments Cooldown' );
|
133 |
+
$sSummary = _wpsf__( 'Limit posting comments to X seconds after the page has loaded' );
|
134 |
+
$sDescription = _wpsf__( "By forcing a comments cooldown period, you restrict a Spambot's ability to post multiple times to your posts." );
|
135 |
+
break;
|
136 |
+
|
137 |
+
case 'comments_token_expire_interval' :
|
138 |
+
$sName = _wpsf__( 'Comment Token Expire' );
|
139 |
+
$sSummary = _wpsf__( 'A visitor has X seconds within which to post a comment' );
|
140 |
+
$sDescription = _wpsf__( "Default: 600 seconds (10 minutes). Each visitor is given a unique 'Token' so they can comment. This restricts spambots, but we need to force these tokens to expire and at the same time not bother the visitors." );
|
141 |
+
break;
|
142 |
+
|
143 |
+
case 'custom_message_checkbox' :
|
144 |
+
$sName = _wpsf__( 'Custom Checkbox Message' );
|
145 |
+
$sSummary = _wpsf__( 'If you want a custom checkbox message, please provide this here' );
|
146 |
+
$sDescription = _wpsf__( "You can customise the message beside the checkbox." )
|
147 |
+
.'<br />'.sprintf( _wpsf__( 'Default Message: %s' ), _wpsf__("Please check the box to confirm you're not a spammer") );
|
148 |
+
break;
|
149 |
+
|
150 |
+
case 'custom_message_alert' :
|
151 |
+
$sName = _wpsf__( 'Custom Alert Message' );
|
152 |
+
$sSummary = _wpsf__( 'If you want a custom alert message, please provide this here' );
|
153 |
+
$sDescription = _wpsf__( "This alert message is displayed when a visitor attempts to submit a comment without checking the box." )
|
154 |
+
.'<br />'.sprintf( _wpsf__( 'Default Message: %s' ), _wpsf__("Please check the box to confirm you're not a spammer") );
|
155 |
+
break;
|
156 |
+
|
157 |
+
case 'custom_message_comment_wait' :
|
158 |
+
$sName = _wpsf__( 'Custom Wait Message' );
|
159 |
+
$sSummary = _wpsf__( 'If you want a custom submit-button wait message, please provide this here.' );
|
160 |
+
$sDescription = _wpsf__( "Where you see the '%s' this will be the number of seconds. You must ensure you include 1, and only 1, of these." )
|
161 |
+
.'<br />'.sprintf( _wpsf__( 'Default Message: %s' ), _wpsf__('Please wait %s seconds before posting your comment') );
|
162 |
+
break;
|
163 |
+
|
164 |
+
case 'custom_message_comment_reload' :
|
165 |
+
$sName = _wpsf__( 'Custom Reload Message' );
|
166 |
+
$sSummary = _wpsf__( 'If you want a custom message when the comment token has expired, please provide this here.' );
|
167 |
+
$sDescription = _wpsf__( 'This message is displayed on the submit-button when the comment token is expired' )
|
168 |
+
.'<br />'.sprintf( _wpsf__( 'Default Message: %s' ), _wpsf__("Please reload this page to post a comment") );
|
169 |
+
break;
|
170 |
+
|
171 |
+
default:
|
172 |
+
throw new Exception( sprintf( 'An option has been defined but without strings assigned to it. Option key: "%s".', $sKey ) );
|
173 |
+
}
|
174 |
+
|
175 |
+
$aOptionsParams['name'] = $sName;
|
176 |
+
$aOptionsParams['summary'] = $sSummary;
|
177 |
+
$aOptionsParams['description'] = $sDescription;
|
178 |
+
return $aOptionsParams;
|
179 |
+
}
|
180 |
+
|
181 |
/**
|
182 |
* @return array
|
183 |
*/
|
184 |
protected function getOptionsDefinitions() {
|
185 |
|
186 |
+
// $aBase = array(
|
187 |
+
// 'section_title' => sprintf( _wpsf__( 'Enable Plugin Feature: %s' ), _wpsf__('SPAM Comments Protection Filter') ),
|
188 |
+
// 'section_options' => array(
|
189 |
+
// array(
|
190 |
+
// 'enable_comments_filter',
|
191 |
+
// '',
|
192 |
+
// 'N',
|
193 |
+
// 'checkbox',
|
194 |
+
// sprintf( _wpsf__( 'Enable %s' ), _wpsf__('Comments Filter') ),
|
195 |
+
// _wpsf__( 'Enable (or Disable) The SPAM Comments Protection Filter Feature' ),
|
196 |
+
// sprintf( _wpsf__( 'Checking/Un-Checking this option will completely turn on/off the whole %s feature.' ), _wpsf__('SPAM Comments Protection Filter') ),
|
197 |
+
// '<a href="http://icwp.io/3z" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
198 |
+
// .' | <a href="http://icwp.io/wpsf04" target="_blank">'._wpsf__( 'blog' ).'</a>'
|
199 |
+
// )
|
200 |
+
// )
|
201 |
+
// );
|
202 |
+
//
|
203 |
+
// $aHumanSpam = array(
|
204 |
+
// 'section_title' => sprintf( _wpsf__( '%s Comment SPAM Protection Filter' ), _wpsf__('Human') ),
|
205 |
+
// 'section_options' => array(
|
206 |
+
// array(
|
207 |
+
// 'enable_comments_human_spam_filter',
|
208 |
+
// '',
|
209 |
+
// 'N',
|
210 |
+
// 'checkbox',
|
211 |
+
// _wpsf__( 'Human SPAM Filter' ),
|
212 |
+
// _wpsf__( 'Enable (or Disable) The Human SPAM Filter Feature.' ),
|
213 |
+
// _wpsf__( 'Scans the content of WordPress comments for keywords that are indicative of SPAM and marks the comment according to your preferred setting below.' ),
|
214 |
+
// '<a href="http://icwp.io/57" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
215 |
+
// ),
|
216 |
+
// array(
|
217 |
+
// 'enable_comments_human_spam_filter_items',
|
218 |
+
// '',
|
219 |
+
// $this->getHumanSpamFilterItems( true ),
|
220 |
+
// $this->getHumanSpamFilterItems(),
|
221 |
+
// _wpsf__( 'Comment Filter Items' ),
|
222 |
+
// _wpsf__( 'Select The Items To Scan For SPAM' ),
|
223 |
+
// _wpsf__( 'When a user submits a comment, only the selected parts of the comment data will be scanned for SPAM content.' ).' '.sprintf( _wpsf__('Recommended: %s'), _wpsf__('All') ),
|
224 |
+
// '<a href="http://icwp.io/58" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
225 |
+
// ),
|
226 |
+
// array(
|
227 |
+
// 'comments_default_action_human_spam',
|
228 |
+
// '',
|
229 |
+
// 'spam',
|
230 |
+
// $this->getSpamHandlingResponses(),
|
231 |
+
// _wpsf__( 'Default SPAM Action' ),
|
232 |
+
// _wpsf__( 'How To Categorise Comments When Identified To Be SPAM' ),
|
233 |
+
// sprintf( _wpsf__( 'When a comment is detected as being SPAM from %s, the comment will be categorised based on this setting.' ), '<span style"text-decoration:underline;">'._wpsf__('a human commenter').'</span>' ),
|
234 |
+
// '<a href="http://icwp.io/59" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
235 |
+
// )
|
236 |
+
// ),
|
237 |
+
// );
|
238 |
+
//
|
239 |
+
// $aGasp = array(
|
240 |
+
// 'section_title' => sprintf( _wpsf__( '%s Comment SPAM Protection Filter' ), _wpsf__('Automatic Bot') ),
|
241 |
+
// 'section_options' => array(
|
242 |
+
// array(
|
243 |
+
// 'enable_comments_gasp_protection',
|
244 |
+
// '',
|
245 |
+
// 'Y',
|
246 |
+
// 'checkbox',
|
247 |
+
// _wpsf__( 'GASP Protection' ),
|
248 |
+
// _wpsf__( 'Add Growmap Anti Spambot Protection to your comments' ),
|
249 |
+
// _wpsf__( 'Taking the lead from the original GASP plugin for WordPress, we have extended it to include advanced spam-bot protection.' ),
|
250 |
+
// '<a href="http://icwp.io/3n" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
251 |
+
// .' | <a href="http://icwp.io/2n" target="_blank">'._wpsf__( 'blog' ).'</a>'
|
252 |
+
// ),
|
253 |
+
// array(
|
254 |
+
// 'comments_default_action_spam_bot',
|
255 |
+
// '',
|
256 |
+
// 'trash',
|
257 |
+
// $this->getSpamHandlingResponses(),
|
258 |
+
// _wpsf__( 'Default SPAM Action' ),
|
259 |
+
// _wpsf__( 'How To Categorise Comments When Identified To Be SPAM' ),
|
260 |
+
// sprintf( _wpsf__( 'When a comment is detected as being SPAM from %s, the comment will be categorised based on this setting.' ), '<span style"text-decoration:underline;">'._wpsf__('an automatic bot').'</span>' ),
|
261 |
+
// '<a href="http://icwp.io/59" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
262 |
+
// ),
|
263 |
+
// array(
|
264 |
+
// 'enable_comments_gasp_protection_for_logged_in',
|
265 |
+
// '',
|
266 |
+
// 'N',
|
267 |
+
// 'checkbox',
|
268 |
+
// _wpsf__( 'Include Logged-In Users' ),
|
269 |
+
// _wpsf__( 'You may also enable GASP for logged in users' ),
|
270 |
+
// _wpsf__( 'Since logged-in users would be expected to be vetted already, this is off by default.' )
|
271 |
+
// ),
|
272 |
+
// array(
|
273 |
+
// 'comments_cooldown_interval',
|
274 |
+
// '',
|
275 |
+
// '30',
|
276 |
+
// 'integer',
|
277 |
+
// _wpsf__( 'Comments Cooldown' ),
|
278 |
+
// _wpsf__( 'Limit posting comments to X seconds after the page has loaded' ),
|
279 |
+
// _wpsf__( "By forcing a comments cooldown period, you restrict a Spambot's ability to post mutliple times to your posts." ),
|
280 |
+
// '<a href="http://icwp.io/3o" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
281 |
+
// ),
|
282 |
+
// array(
|
283 |
+
// 'comments_token_expire_interval',
|
284 |
+
// '',
|
285 |
+
// '600',
|
286 |
+
// 'integer',
|
287 |
+
// _wpsf__( 'Comment Token Expire' ),
|
288 |
+
// _wpsf__( 'A visitor has X seconds within which to post a comment' ),
|
289 |
+
// _wpsf__( "Default: 600 seconds (10 minutes). Each visitor is given a unique 'Token' so they can comment. This restricts spambots, but we need to force these tokens to expire and at the same time not bother the visitors." ),
|
290 |
+
// '<a href="http://icwp.io/3o" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
291 |
+
//
|
292 |
+
// )
|
293 |
+
// )
|
294 |
+
// );
|
295 |
+
//
|
296 |
+
// $aCustomMessages = array(
|
297 |
+
// 'section_title' => sprintf( _wpsf__( 'Customize Messages Shown To User' ), _wpsf__('Automatic Bot') ),
|
298 |
+
// 'section_options' => array(
|
299 |
+
// array(
|
300 |
+
// 'custom_message_checkbox',
|
301 |
+
// '',
|
302 |
+
// _wpsf__( "I'm not a spammer" ),
|
303 |
+
// 'text',
|
304 |
+
// _wpsf__( 'Custom Checkbox Message' ),
|
305 |
+
// _wpsf__( 'If you want a custom checkbox message, please provide this here' ),
|
306 |
+
// _wpsf__( "You can customise the message beside the checkbox." )
|
307 |
+
// .'<br />'.sprintf( _wpsf__( 'Default Message: %s' ), _wpsf__("Please check the box to confirm you're not a spammer") ),
|
308 |
+
// '<a href="http://icwp.io/3p" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
309 |
+
// ),
|
310 |
+
// array(
|
311 |
+
// 'custom_message_alert',
|
312 |
+
// '',
|
313 |
+
// _wpsf__( "Please check the box to confirm you're not a spammer" ),
|
314 |
+
// 'text',
|
315 |
+
// _wpsf__( 'Custom Alert Message' ),
|
316 |
+
// _wpsf__( 'If you want a custom alert message, please provide this here' ),
|
317 |
+
// _wpsf__( "This alert message is displayed when a visitor attempts to submit a comment without checking the box." )
|
318 |
+
// .'<br />'.sprintf( _wpsf__( 'Default Message: %s' ), _wpsf__("Please check the box to confirm you're not a spammer") ),
|
319 |
+
// '<a href="http://icwp.io/3p" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
320 |
+
// ),
|
321 |
+
// array(
|
322 |
+
// 'custom_message_comment_wait',
|
323 |
+
// '',
|
324 |
+
// _wpsf__( "Please wait %s seconds before posting your comment" ),
|
325 |
+
// 'text',
|
326 |
+
// _wpsf__( 'Custom Wait Message' ),
|
327 |
+
// _wpsf__( 'If you want a custom submit-button wait message, please provide this here.' ),
|
328 |
+
// _wpsf__( "Where you see the '%s' this will be the number of seconds. You must ensure you include 1, and only 1, of these." )
|
329 |
+
// .'<br />'.sprintf( _wpsf__( 'Default Message: %s' ), _wpsf__('Please wait %s seconds before posting your comment') ),
|
330 |
+
// '<a href="http://icwp.io/3p" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
331 |
+
// ),
|
332 |
+
// array(
|
333 |
+
// 'custom_message_comment_reload',
|
334 |
+
// '',
|
335 |
+
// _wpsf__( "Please reload this page to post a comment" ),
|
336 |
+
// 'text',
|
337 |
+
// _wpsf__( 'Custom Reload Message' ),
|
338 |
+
// _wpsf__( 'If you want a custom message when the comment token has expired, please provide this here.' ),
|
339 |
+
// _wpsf__( 'This message is displayed on the submit-button when the comment token is expired' )
|
340 |
+
// .'<br />'.sprintf( _wpsf__( 'Default Message: %s' ), _wpsf__("Please reload this page to post a comment") ),
|
341 |
+
// '<a href="http://icwp.io/3p" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
342 |
+
// )
|
343 |
+
// )
|
344 |
+
// );
|
345 |
+
//
|
346 |
+
// $aOptionsDefinitions = array(
|
347 |
+
// $aBase,
|
348 |
+
// $aHumanSpam,
|
349 |
+
// $aGasp,
|
350 |
+
// $aCustomMessages
|
351 |
+
// );
|
352 |
+
// return $aOptionsDefinitions;
|
353 |
}
|
354 |
|
355 |
/**
|
357 |
*/
|
358 |
protected function doPrePluginOptionsSave() {
|
359 |
|
360 |
+
if ( $this->getOpt( 'comments_cooldown_interval' ) < 0 ) {
|
361 |
+
$this->getOptionsVo()->resetOptToDefault( 'comments_cooldown_interval' );
|
|
|
362 |
}
|
363 |
|
364 |
+
if ( $this->getOpt( 'comments_token_expire_interval' ) < 0 ) {
|
365 |
+
$this->getOptionsVo()->resetOptToDefault( 'comments_token_expire_interval' );
|
|
|
366 |
}
|
367 |
|
368 |
+
if ( $this->getOpt( 'comments_token_expire_interval' ) != 0 && $this->getOpt( 'comments_cooldown_interval' ) > $this->getOpt( 'comments_token_expire_interval' ) ) {
|
369 |
+
$this->getOptionsVo()->resetOptToDefault( 'comments_cooldown_interval' );
|
370 |
+
$this->getOptionsVo()->resetOptToDefault( 'comments_token_expire_interval' );
|
371 |
}
|
|
|
|
|
372 |
|
373 |
$aCommentsFilters = $this->getOpt( 'enable_comments_human_spam_filter_items' );
|
374 |
+
if ( empty( $aCommentsFilters ) || !is_array( $aCommentsFilters ) ) {
|
375 |
+
$this->getOptionsVo()->resetOptToDefault( 'enable_comments_human_spam_filter_items' );
|
376 |
}
|
377 |
}
|
378 |
|
379 |
/**
|
380 |
+
* @return string
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
381 |
*/
|
382 |
+
public function getCommentsFilterTableName() {
|
383 |
+
return $this->doPluginPrefix( $this->getOpt( 'spambot_comments_filter_table_name' ), '_' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
384 |
}
|
385 |
}
|
386 |
|
src/icwp-optionshandler-email.php
CHANGED
@@ -22,7 +22,7 @@ if ( !class_exists('ICWP_WPSF_FeatureHandler_Email') ):
|
|
22 |
class ICWP_WPSF_FeatureHandler_Email extends ICWP_WPSF_FeatureHandler_Base {
|
23 |
|
24 |
/**
|
25 |
-
* @var
|
26 |
*/
|
27 |
protected $oFeatureProcessor;
|
28 |
|
@@ -32,55 +32,73 @@ class ICWP_WPSF_FeatureHandler_Email extends ICWP_WPSF_FeatureHandler_Base {
|
|
32 |
public function __construct( $oPluginVo ) {
|
33 |
$this->sFeatureName = _wpsf__('Email');
|
34 |
$this->sFeatureSlug = 'email';
|
35 |
-
$this->fShowFeatureMenuItem = false;
|
36 |
parent::__construct( $oPluginVo );
|
37 |
}
|
38 |
|
39 |
/**
|
40 |
-
* @return
|
41 |
*/
|
42 |
protected function loadFeatureProcessor() {
|
43 |
if ( !isset( $this->oFeatureProcessor ) ) {
|
44 |
-
require_once(
|
45 |
-
$this->oFeatureProcessor = new
|
46 |
}
|
47 |
return $this->oFeatureProcessor;
|
48 |
}
|
49 |
|
50 |
/**
|
|
|
51 |
* @return array
|
|
|
52 |
*/
|
53 |
-
protected function
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
'send_email_throttle_limit',
|
68 |
-
'',
|
69 |
-
'10',
|
70 |
-
'integer',
|
71 |
-
_wpsf__( 'Email Throttle Limit' ),
|
72 |
-
_wpsf__( 'Limit Emails Per Second' ),
|
73 |
-
_wpsf__( 'You throttle emails sent by this plugin by limiting the number of emails sent every second. This is useful in case you get hit by a bot attack. Zero (0) turns this off. Suggested: 10' )
|
74 |
-
)
|
75 |
-
)
|
76 |
-
);
|
77 |
-
|
78 |
-
$aOptionsDefinitions = array(
|
79 |
-
$aEmail
|
80 |
-
);
|
81 |
-
return $aOptionsDefinitions;
|
82 |
}
|
83 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
84 |
/**
|
85 |
* This is the point where you would want to do any options verification
|
86 |
*/
|
22 |
class ICWP_WPSF_FeatureHandler_Email extends ICWP_WPSF_FeatureHandler_Base {
|
23 |
|
24 |
/**
|
25 |
+
* @var ICWP_WPSF_Processor_Email
|
26 |
*/
|
27 |
protected $oFeatureProcessor;
|
28 |
|
32 |
public function __construct( $oPluginVo ) {
|
33 |
$this->sFeatureName = _wpsf__('Email');
|
34 |
$this->sFeatureSlug = 'email';
|
|
|
35 |
parent::__construct( $oPluginVo );
|
36 |
}
|
37 |
|
38 |
/**
|
39 |
+
* @return ICWP_WPSF_Processor_Email|null
|
40 |
*/
|
41 |
protected function loadFeatureProcessor() {
|
42 |
if ( !isset( $this->oFeatureProcessor ) ) {
|
43 |
+
require_once( $this->getController()->getSourceDir( sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) ) );
|
44 |
+
$this->oFeatureProcessor = new ICWP_WPSF_Processor_Email( $this );
|
45 |
}
|
46 |
return $this->oFeatureProcessor;
|
47 |
}
|
48 |
|
49 |
/**
|
50 |
+
* @param array $aOptionsParams
|
51 |
* @return array
|
52 |
+
* @throws Exception
|
53 |
*/
|
54 |
+
protected function loadStrings_SectionTitles( $aOptionsParams ) {
|
55 |
+
|
56 |
+
$sSectionSlug = $aOptionsParams['section_slug'];
|
57 |
+
switch( $aOptionsParams['section_slug'] ) {
|
58 |
+
|
59 |
+
case 'section_email_options' :
|
60 |
+
$sTitle = _wpsf__( 'Email Options' );
|
61 |
+
break;
|
62 |
+
|
63 |
+
default:
|
64 |
+
throw new Exception( sprintf( 'A section slug was defined but with no associated strings. Slug: "%s".', $sSectionSlug ) );
|
65 |
+
}
|
66 |
+
$aOptionsParams['section_title'] = $sTitle;
|
67 |
+
return $aOptionsParams;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* @param array $aOptionsParams
|
72 |
+
* @return array
|
73 |
+
* @throws Exception
|
74 |
+
*/
|
75 |
+
protected function loadStrings_Options( $aOptionsParams ) {
|
76 |
+
|
77 |
+
$sKey = $aOptionsParams['key'];
|
78 |
+
switch( $sKey ) {
|
79 |
+
|
80 |
+
case 'block_send_email_address' :
|
81 |
+
$sName = _wpsf__( 'Report Email' );
|
82 |
+
$sSummary = _wpsf__( 'Where to send email reports' );
|
83 |
+
$sDescription = _wpsf__( 'If this is empty, it will default to the blog admin email address.' );
|
84 |
+
break;
|
85 |
+
|
86 |
+
case 'send_email_throttle_limit' :
|
87 |
+
$sName = _wpsf__( 'Email Throttle Limit' );
|
88 |
+
$sSummary = _wpsf__( 'Limit Emails Per Second' );
|
89 |
+
$sDescription = _wpsf__( 'You throttle emails sent by this plugin by limiting the number of emails sent every second. This is useful in case you get hit by a bot attack. Zero (0) turns this off. Suggested: 10' );
|
90 |
+
break;
|
91 |
+
|
92 |
+
default:
|
93 |
+
throw new Exception( sprintf( 'An option has been defined but without strings assigned to it. Option key: "%s".', $sKey ) );
|
94 |
+
}
|
95 |
+
|
96 |
+
$aOptionsParams['name'] = $sName;
|
97 |
+
$aOptionsParams['summary'] = $sSummary;
|
98 |
+
$aOptionsParams['description'] = $sDescription;
|
99 |
+
return $aOptionsParams;
|
100 |
+
}
|
101 |
+
|
102 |
/**
|
103 |
* This is the point where you would want to do any options verification
|
104 |
*/
|
src/icwp-optionshandler-firewall.php
CHANGED
@@ -22,7 +22,7 @@ if ( !class_exists('ICWP_WPSF_FeatureHandler_Firewall') ):
|
|
22 |
class ICWP_WPSF_FeatureHandler_Firewall extends ICWP_WPSF_FeatureHandler_Base {
|
23 |
|
24 |
/**
|
25 |
-
* @var
|
26 |
*/
|
27 |
protected $oFeatureProcessor;
|
28 |
|
@@ -33,12 +33,12 @@ class ICWP_WPSF_FeatureHandler_Firewall extends ICWP_WPSF_FeatureHandler_Base {
|
|
33 |
}
|
34 |
|
35 |
/**
|
36 |
-
* @return
|
37 |
*/
|
38 |
protected function loadFeatureProcessor() {
|
39 |
if ( !isset( $this->oFeatureProcessor ) ) {
|
40 |
-
require_once(
|
41 |
-
$this->oFeatureProcessor = new
|
42 |
}
|
43 |
return $this->oFeatureProcessor;
|
44 |
}
|
@@ -75,235 +75,188 @@ class ICWP_WPSF_FeatureHandler_Firewall extends ICWP_WPSF_FeatureHandler_Base {
|
|
75 |
}
|
76 |
|
77 |
/**
|
|
|
78 |
* @return array
|
|
|
79 |
*/
|
80 |
-
protected function
|
81 |
-
|
82 |
-
|
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 |
-
_wpsf__( 'Directory Traversals' ),
|
115 |
-
_wpsf__( 'Block Directory Traversals' ),
|
116 |
-
_wpsf__( 'This will block directory traversal paths in in application parameters (e.g. ../, ../../etc/passwd, etc.).' )
|
117 |
-
),
|
118 |
-
array(
|
119 |
-
'block_sql_queries',
|
120 |
-
'',
|
121 |
-
'Y',
|
122 |
-
'checkbox',
|
123 |
-
_wpsf__( 'SQL Queries' ),
|
124 |
-
_wpsf__( 'Block SQL Queries' ),
|
125 |
-
_wpsf__( 'This will block sql in application parameters (e.g. union select, concat(, /**/, etc.).' )
|
126 |
-
),
|
127 |
-
array(
|
128 |
-
'block_wordpress_terms',
|
129 |
-
'',
|
130 |
-
'N',
|
131 |
-
'checkbox',
|
132 |
-
_wpsf__( 'WordPress Terms' ),
|
133 |
-
_wpsf__( 'Block WordPress Specific Terms' ),
|
134 |
-
_wpsf__( 'This will block WordPress specific terms in application parameters (wp_, user_login, etc.).' )
|
135 |
-
),
|
136 |
-
array(
|
137 |
-
'block_field_truncation',
|
138 |
-
'',
|
139 |
-
'Y',
|
140 |
-
'checkbox',
|
141 |
-
_wpsf__( 'Field Truncation' ),
|
142 |
-
_wpsf__( 'Block Field Truncation Attacks' ),
|
143 |
-
_wpsf__( 'This will block field truncation attacks in application parameters.' )
|
144 |
-
),
|
145 |
-
array(
|
146 |
-
'block_php_code',
|
147 |
-
'',
|
148 |
-
'N',
|
149 |
-
'checkbox',
|
150 |
-
_wpsf__( 'PHP Code' ),
|
151 |
-
sprintf( _wpsf__( 'Block %s' ), _wpsf__( 'PHP Code Includes' ) ),
|
152 |
-
_wpsf__( 'This will block any data that appears to try and include PHP files.' )
|
153 |
-
.'<br />'. _wpsf__( 'Will probably block saving within the Plugin/Theme file editors.' )
|
154 |
-
),
|
155 |
-
array(
|
156 |
-
'block_exe_file_uploads',
|
157 |
-
'',
|
158 |
-
'N',
|
159 |
-
'checkbox',
|
160 |
-
_wpsf__( 'Exe File Uploads' ),
|
161 |
-
_wpsf__( 'Block Executable File Uploads' ),
|
162 |
-
_wpsf__( 'This will block executable file uploads (.php, .exe, etc.).' )
|
163 |
-
),
|
164 |
-
array(
|
165 |
-
'block_leading_schema',
|
166 |
-
'',
|
167 |
-
'N',
|
168 |
-
'checkbox',
|
169 |
-
_wpsf__( 'Leading Schemas' ),
|
170 |
-
_wpsf__( 'Block Leading Schemas (HTTPS / HTTP)' ),
|
171 |
-
_wpsf__( 'This will block leading schemas http:// and https:// in application parameters (off by default; may cause problems with other plugins).' )
|
172 |
-
)
|
173 |
-
),
|
174 |
-
);
|
175 |
-
$aRedirectOptions = array( 'select',
|
176 |
-
array( 'redirect_die_message', _wpsf__( 'Die With Message' ) ),
|
177 |
-
array( 'redirect_die', _wpsf__( 'Die' ) ),
|
178 |
-
array( 'redirect_home', _wpsf__( 'Redirect To Home Page' ) ),
|
179 |
-
array( 'redirect_404', _wpsf__( 'Return 404' ) ),
|
180 |
-
);
|
181 |
-
$aBlockSection = array(
|
182 |
-
'section_title' => _wpsf__( 'Choose Firewall Block Response' ),
|
183 |
-
'section_options' => array(
|
184 |
-
array(
|
185 |
-
'block_response',
|
186 |
-
'',
|
187 |
-
'none',
|
188 |
-
$aRedirectOptions,
|
189 |
-
_wpsf__( 'Block Response' ),
|
190 |
-
_wpsf__( 'Choose how the firewall responds when it blocks a request' ),
|
191 |
-
_wpsf__( 'We recommend dying with a message so you know what might have occurred when the firewall blocks you' )
|
192 |
-
),
|
193 |
-
array(
|
194 |
-
'block_send_email',
|
195 |
-
'',
|
196 |
-
'N',
|
197 |
-
'checkbox',
|
198 |
-
_wpsf__( 'Send Email Report' ),
|
199 |
-
_wpsf__( 'When a visitor is blocked the firewall will send an email to the configured email address' ),
|
200 |
-
_wpsf__( 'Use with caution - if you get hit by automated bots you may send out too many emails and you could get blocked by your host' )
|
201 |
-
)
|
202 |
-
)
|
203 |
-
);
|
204 |
-
|
205 |
-
$aWhitelistSection = array(
|
206 |
-
'section_title' => _wpsf__( 'Whitelists - IPs, Pages, Parameters, and Users that by-pass the Firewall' ),
|
207 |
-
'section_options' => array(
|
208 |
-
array(
|
209 |
-
'ips_whitelist',
|
210 |
-
'',
|
211 |
-
'',
|
212 |
-
'ip_addresses',
|
213 |
-
_wpsf__( 'Whitelist IP Addresses' ),
|
214 |
-
_wpsf__( 'Choose IP Addresses that are never subjected to Firewall Rules' ),
|
215 |
-
sprintf( _wpsf__( 'Take a new line per address. Your IP address is: %s' ), '<span class="code">'.$this->getVisitorIpAddress( false ).'</span>' )
|
216 |
-
),
|
217 |
-
array(
|
218 |
-
'page_params_whitelist',
|
219 |
-
'',
|
220 |
-
'',
|
221 |
-
'comma_separated_lists',
|
222 |
-
_wpsf__( 'Whitelist Parameters' ),
|
223 |
-
_wpsf__( 'Detail pages and parameters that are whitelisted (ignored by the firewall)' ),
|
224 |
-
_wpsf__( 'This should be used with caution and you should only provide parameter names that you must have excluded' )
|
225 |
-
.' '.sprintf( _wpsf__( '%sHelp%s' ), '[<a href="http://icwp.io/2a" target="_blank">', '</a>]' )
|
226 |
-
),
|
227 |
-
array(
|
228 |
-
'whitelist_admins',
|
229 |
-
'',
|
230 |
-
'N',
|
231 |
-
'checkbox',
|
232 |
-
sprintf( _wpsf__( 'Ignore %s' ), _wpsf__( 'Administrators' ) ),
|
233 |
-
_wpsf__( 'Ignore users logged in as Administrator' ),
|
234 |
-
_wpsf__( 'Authenticated administrator users will not be processed by the firewall' )
|
235 |
-
),
|
236 |
-
array(
|
237 |
-
'ignore_search_engines',
|
238 |
-
'',
|
239 |
-
'N',
|
240 |
-
'checkbox',
|
241 |
-
sprintf( _wpsf__( 'Ignore %s' ), _wpsf__( 'Search Engines' ) ),
|
242 |
-
_wpsf__( 'Ignore Search Engine Bots' ),
|
243 |
-
_wpsf__( 'When selected, the firewall will try to recognise search engine spiders/bots and not apply firewall rules to them' )
|
244 |
-
)
|
245 |
-
)
|
246 |
-
);
|
247 |
-
|
248 |
-
$aBlacklistSection = array(
|
249 |
-
'section_title' => _wpsf__( 'Choose IP Addresses To Blacklist' ),
|
250 |
-
'section_options' => array(
|
251 |
-
array(
|
252 |
-
'ips_blacklist',
|
253 |
-
'',
|
254 |
-
'',
|
255 |
-
'ip_addresses',
|
256 |
-
_wpsf__( 'Blacklist IP Addresses' ),
|
257 |
-
_wpsf__( 'Choose IP Addresses that are always blocked from accessing the site' ),
|
258 |
-
_wpsf__( 'Take a new line per address. Each IP Address must be valid and will be checked' )
|
259 |
-
)
|
260 |
-
)
|
261 |
-
);
|
262 |
-
$aMisc = array(
|
263 |
-
'section_title' => _wpsf__( 'Logging Options' ),
|
264 |
-
'section_options' => array(
|
265 |
-
array(
|
266 |
-
'enable_firewall_log',
|
267 |
-
'',
|
268 |
-
'N',
|
269 |
-
'checkbox',
|
270 |
-
_wpsf__( 'Firewall Logging' ),
|
271 |
-
_wpsf__( 'Turn on Firewall Log' ),
|
272 |
-
_wpsf__( 'Will log every visit to the site and how the firewall processes it. Not recommended to leave on unless you want to debug something and check the firewall is working as you expect' )
|
273 |
-
)
|
274 |
-
)
|
275 |
-
);
|
276 |
-
|
277 |
-
$aOptionsDefinitions = array(
|
278 |
-
$aFirewallBase,
|
279 |
-
$aBlockSection,
|
280 |
-
$aWhitelistSection,
|
281 |
-
$aBlacklistSection,
|
282 |
-
$aBlockTypesSection,
|
283 |
-
$aMisc
|
284 |
-
);
|
285 |
-
return $aOptionsDefinitions;
|
286 |
}
|
287 |
|
288 |
/**
|
289 |
-
* @
|
|
|
|
|
290 |
*/
|
291 |
-
|
292 |
-
|
293 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
294 |
}
|
295 |
-
$this->loadDataProcessor();
|
296 |
|
297 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
298 |
$oLoggingProcessor = $this->getLoggingProcessor();
|
299 |
$oLoggingProcessor->recreateTable();
|
300 |
return true;
|
301 |
}
|
302 |
|
303 |
-
$this->addRawIpsToFirewallList( 'ips_whitelist', array(
|
304 |
-
$this->removeRawIpsFromFirewallList( 'ips_whitelist', array(
|
305 |
-
$this->addRawIpsToFirewallList( 'ips_blacklist', array(
|
306 |
-
$this->removeRawIpsFromFirewallList( 'ips_blacklist', array(
|
307 |
|
308 |
return true;
|
309 |
}
|
@@ -325,7 +278,8 @@ class ICWP_WPSF_FeatureHandler_Firewall extends ICWP_WPSF_FeatureHandler_Base {
|
|
325 |
foreach( $inaNewIps as $sAddress ) {
|
326 |
$aNewList[ $sAddress ] = '';
|
327 |
}
|
328 |
-
$this->
|
|
|
329 |
}
|
330 |
|
331 |
public function removeRawIpsFromFirewallList( $insListName, $inaRemoveIps ) {
|
@@ -337,7 +291,8 @@ class ICWP_WPSF_FeatureHandler_Firewall extends ICWP_WPSF_FeatureHandler_Base {
|
|
337 |
if ( empty( $aIplist ) || empty( $inaRemoveIps ) ) {
|
338 |
return;
|
339 |
}
|
340 |
-
$this->
|
|
|
341 |
}
|
342 |
|
343 |
}
|
22 |
class ICWP_WPSF_FeatureHandler_Firewall extends ICWP_WPSF_FeatureHandler_Base {
|
23 |
|
24 |
/**
|
25 |
+
* @var ICWP_WPSF_Processor_Firewall
|
26 |
*/
|
27 |
protected $oFeatureProcessor;
|
28 |
|
33 |
}
|
34 |
|
35 |
/**
|
36 |
+
* @return ICWP_WPSF_Processor_Firewall|null
|
37 |
*/
|
38 |
protected function loadFeatureProcessor() {
|
39 |
if ( !isset( $this->oFeatureProcessor ) ) {
|
40 |
+
require_once( $this->getController()->getSourceDir( sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) ) );
|
41 |
+
$this->oFeatureProcessor = new ICWP_WPSF_Processor_Firewall( $this );
|
42 |
}
|
43 |
return $this->oFeatureProcessor;
|
44 |
}
|
75 |
}
|
76 |
|
77 |
/**
|
78 |
+
* @param array $aOptionsParams
|
79 |
* @return array
|
80 |
+
* @throws Exception
|
81 |
*/
|
82 |
+
protected function loadStrings_SectionTitles( $aOptionsParams ) {
|
83 |
+
|
84 |
+
$sSectionSlug = $aOptionsParams['section_slug'];
|
85 |
+
switch( $aOptionsParams['section_slug'] ) {
|
86 |
+
|
87 |
+
case 'section_enable_plugin_feature_wordpress_firewall' :
|
88 |
+
$sTitle = sprintf( _wpsf__( 'Enable Plugin Feature: %s' ), $this->getMainFeatureName() );
|
89 |
+
break;
|
90 |
+
|
91 |
+
case 'section_firewall_blocking_options' :
|
92 |
+
$sTitle = _wpsf__('Firewall Blocking Options');
|
93 |
+
break;
|
94 |
+
|
95 |
+
case 'section_choose_firewall_block_response' :
|
96 |
+
$sTitle = _wpsf__('Choose Firewall Block Response');
|
97 |
+
break;
|
98 |
+
|
99 |
+
case 'section_whitelist' :
|
100 |
+
$sTitle = _wpsf__('Whitelists - IPs, Pages, Parameters, and Users that by-pass the Firewall');
|
101 |
+
break;
|
102 |
+
|
103 |
+
case 'section_blacklist' :
|
104 |
+
$sTitle = _wpsf__('Choose IP Addresses To Blacklist');
|
105 |
+
break;
|
106 |
+
|
107 |
+
case 'section_firewall_logging' :
|
108 |
+
$sTitle = _wpsf__('Firewall Logging Options');
|
109 |
+
break;
|
110 |
+
|
111 |
+
default:
|
112 |
+
throw new Exception( sprintf( 'A section slug was defined but with no associated strings. Slug: "%s".', $sSectionSlug ) );
|
113 |
+
}
|
114 |
+
$aOptionsParams['section_title'] = $sTitle;
|
115 |
+
return $aOptionsParams;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
116 |
}
|
117 |
|
118 |
/**
|
119 |
+
* @param array $aOptionsParams
|
120 |
+
* @return array
|
121 |
+
* @throws Exception
|
122 |
*/
|
123 |
+
protected function loadStrings_Options( $aOptionsParams ) {
|
124 |
+
|
125 |
+
$oDp = $this->loadDataProcessor();
|
126 |
+
$sKey = $aOptionsParams['key'];
|
127 |
+
|
128 |
+
switch( $sKey ) {
|
129 |
+
|
130 |
+
case 'enable_firewall' :
|
131 |
+
$sName = sprintf( _wpsf__( 'Enable %s' ), $this->getMainFeatureName() );
|
132 |
+
$sSummary = sprintf( _wpsf__( 'Enable (or Disable) The %s Feature' ), $this->getMainFeatureName() );
|
133 |
+
$sDescription = sprintf( _wpsf__( 'Checking/Un-Checking this option will completely turn on/off the whole %s feature.' ), $this->getMainFeatureName() );
|
134 |
+
break;
|
135 |
+
|
136 |
+
case 'include_cookie_checks' :
|
137 |
+
$sName = _wpsf__( 'Include Cookies' );
|
138 |
+
$sSummary = _wpsf__( 'Also Test Cookie Values In Firewall Tests' );
|
139 |
+
$sDescription = _wpsf__( 'The firewall tests GET and POST, but with this option checked it will also COOKIE values.' );
|
140 |
+
break;
|
141 |
+
|
142 |
+
case 'block_dir_traversal' :
|
143 |
+
$sName = _wpsf__( 'Directory Traversals' );
|
144 |
+
$sSummary = _wpsf__( 'Block Directory Traversals' );
|
145 |
+
$sDescription = _wpsf__( 'This will block directory traversal paths in in application parameters (e.g. ../, ../../etc/passwd, etc.).' );
|
146 |
+
break;
|
147 |
+
|
148 |
+
case 'block_sql_queries' :
|
149 |
+
$sName = _wpsf__( 'SQL Queries' );
|
150 |
+
$sSummary = _wpsf__( 'Block SQL Queries' );
|
151 |
+
$sDescription = _wpsf__( 'This will block sql in application parameters (e.g. union select, concat(, /**/, etc.).' );
|
152 |
+
break;
|
153 |
+
|
154 |
+
case 'block_wordpress_terms' :
|
155 |
+
$sName = _wpsf__( 'WordPress Terms' );
|
156 |
+
$sSummary = _wpsf__( 'Block WordPress Specific Terms' );
|
157 |
+
$sDescription = _wpsf__( 'This will block WordPress specific terms in application parameters (wp_, user_login, etc.).' );
|
158 |
+
break;
|
159 |
+
|
160 |
+
case 'block_field_truncation' :
|
161 |
+
$sName = _wpsf__( 'Field Truncation' );
|
162 |
+
$sSummary = _wpsf__( 'Block Field Truncation Attacks' );
|
163 |
+
$sDescription = _wpsf__( 'This will block field truncation attacks in application parameters.' );
|
164 |
+
break;
|
165 |
+
|
166 |
+
case 'block_php_code' :
|
167 |
+
$sName = _wpsf__( 'PHP Code' );
|
168 |
+
$sSummary = sprintf( _wpsf__( 'Block %s' ), _wpsf__( 'PHP Code Includes' ) );
|
169 |
+
$sDescription = _wpsf__( 'This will block any data that appears to try and include PHP files.' )
|
170 |
+
.'<br />'. _wpsf__( 'Will probably block saving within the Plugin/Theme file editors.' );
|
171 |
+
break;
|
172 |
+
|
173 |
+
case 'block_exe_file_uploads' :
|
174 |
+
$sName = _wpsf__( 'Exe File Uploads' );
|
175 |
+
$sSummary = _wpsf__( 'Block Executable File Uploads' );
|
176 |
+
$sDescription = _wpsf__( 'This will block executable file uploads (.php, .exe, etc.).' );
|
177 |
+
break;
|
178 |
+
|
179 |
+
case 'block_leading_schema' :
|
180 |
+
$sName = _wpsf__( 'Leading Schemas' );
|
181 |
+
$sSummary = _wpsf__( 'Block Leading Schemas (HTTPS / HTTP)' );
|
182 |
+
$sDescription = _wpsf__( 'This will block leading schemas http:// and https:// in application parameters (off by default; may cause problems with other plugins).' );
|
183 |
+
break;
|
184 |
+
|
185 |
+
case 'block_response' :
|
186 |
+
$sName = _wpsf__( 'Block Response' );
|
187 |
+
$sSummary = _wpsf__( 'Choose how the firewall responds when it blocks a request' );
|
188 |
+
$sDescription = _wpsf__( 'We recommend dying with a message so you know what might have occurred when the firewall blocks you' );
|
189 |
+
break;
|
190 |
+
|
191 |
+
case 'block_send_email' :
|
192 |
+
$sName = _wpsf__( 'Send Email Report' );
|
193 |
+
$sSummary = _wpsf__( 'When a visitor is blocked the firewall will send an email to the configured email address' );
|
194 |
+
$sDescription = _wpsf__( 'Use with caution - if you get hit by automated bots you may send out too many emails and you could get blocked by your host' );
|
195 |
+
break;
|
196 |
+
|
197 |
+
case 'ips_whitelist' :
|
198 |
+
$sName = _wpsf__( 'Whitelist IP Addresses' );
|
199 |
+
$sSummary = _wpsf__( 'Choose IP Addresses that are never subjected to Firewall Rules' );
|
200 |
+
$sDescription = _wpsf__( 'Take a new line per address.' )
|
201 |
+
.'<br />'.sprintf( _wpsf__( 'Your IP address is: %s' ), '<span class="code">'.( $oDp->GetVisitorIpAddress( false ) ).'</span>' );
|
202 |
+
break;
|
203 |
+
|
204 |
+
case 'page_params_whitelist' :
|
205 |
+
$sName = _wpsf__( 'Whitelist Parameters' );
|
206 |
+
$sSummary = _wpsf__( 'Detail pages and parameters that are whitelisted (ignored by the firewall)' );
|
207 |
+
$sDescription = _wpsf__( 'This should be used with caution and you should only provide parameter names that you must have excluded' );
|
208 |
+
break;
|
209 |
+
|
210 |
+
case 'whitelist_admins' :
|
211 |
+
$sName = sprintf( _wpsf__( 'Ignore %s' ), _wpsf__( 'Administrators' ) );
|
212 |
+
$sSummary = sprintf( _wpsf__( 'Ignore %s' ), _wpsf__( 'Administrators' ) );
|
213 |
+
$sDescription = _wpsf__( 'Authenticated administrator users will not be processed by the firewall rules.' );
|
214 |
+
break;
|
215 |
+
|
216 |
+
case 'ignore_search_engines' :
|
217 |
+
$sName = sprintf( _wpsf__( 'Ignore %s' ), _wpsf__( 'Search Engines' ) );
|
218 |
+
$sSummary = _wpsf__( 'Ignore Search Engine Bot Traffic' );
|
219 |
+
$sDescription = _wpsf__( 'The firewall will try to recognise search engine spiders/bots and not apply firewall rules to them.' );
|
220 |
+
break;
|
221 |
+
|
222 |
+
case 'ips_blacklist' :
|
223 |
+
$sName = _wpsf__( 'Blacklist IP Addresses' );
|
224 |
+
$sSummary = _wpsf__( 'Choose IP Addresses that are always blocked from accessing the site' );
|
225 |
+
$sDescription = _wpsf__( 'Take a new line per address. Each IP Address must be valid and will be checked.' );
|
226 |
+
break;
|
227 |
+
|
228 |
+
case 'enable_firewall_log' :
|
229 |
+
$sName = _wpsf__( 'Firewall Logging' );
|
230 |
+
$sSummary = _wpsf__( 'Turn on Firewall Log' );
|
231 |
+
$sDescription = _wpsf__( 'Will log every visit to the site and how the firewall processes it. Not recommended to leave on unless you want to debug something and check the firewall is working as you expect' );
|
232 |
+
break;
|
233 |
+
|
234 |
+
default:
|
235 |
+
throw new Exception( sprintf( 'An option has been defined but without strings assigned to it. Option key: "%s".', $sKey ) );
|
236 |
}
|
|
|
237 |
|
238 |
+
$aOptionsParams['name'] = $sName;
|
239 |
+
$aOptionsParams['summary'] = $sSummary;
|
240 |
+
$aOptionsParams['description'] = $sDescription;
|
241 |
+
return $aOptionsParams;
|
242 |
+
}
|
243 |
+
|
244 |
+
/**
|
245 |
+
* @return bool
|
246 |
+
*/
|
247 |
+
protected function doExtraSubmitProcessing() {
|
248 |
+
$oDp = $this->loadDataProcessor();
|
249 |
+
|
250 |
+
if ( $oDp->FetchPost( 'clear_log_submit' ) ) {
|
251 |
$oLoggingProcessor = $this->getLoggingProcessor();
|
252 |
$oLoggingProcessor->recreateTable();
|
253 |
return true;
|
254 |
}
|
255 |
|
256 |
+
$this->addRawIpsToFirewallList( 'ips_whitelist', array( $oDp->FetchGet( 'whiteip' ) ) );
|
257 |
+
$this->removeRawIpsFromFirewallList( 'ips_whitelist', array( $oDp->FetchGet( 'unwhiteip' ) ) );
|
258 |
+
$this->addRawIpsToFirewallList( 'ips_blacklist', array( $oDp->FetchGet( 'blackip' ) ) );
|
259 |
+
$this->removeRawIpsFromFirewallList( 'ips_blacklist', array( $oDp->FetchGet( 'unblackip' ) ) );
|
260 |
|
261 |
return true;
|
262 |
}
|
278 |
foreach( $inaNewIps as $sAddress ) {
|
279 |
$aNewList[ $sAddress ] = '';
|
280 |
}
|
281 |
+
$oDp = $this->loadDataProcessor();
|
282 |
+
$this->setOpt( $insListName, $oDp->Add_New_Raw_Ips( $aIplist, $aNewList ) );
|
283 |
}
|
284 |
|
285 |
public function removeRawIpsFromFirewallList( $insListName, $inaRemoveIps ) {
|
291 |
if ( empty( $aIplist ) || empty( $inaRemoveIps ) ) {
|
292 |
return;
|
293 |
}
|
294 |
+
$oDp = $this->loadDataProcessor();
|
295 |
+
$this->setOpt( $insListName, $oDp->Remove_Raw_Ips( $aIplist, $inaRemoveIps ) );
|
296 |
}
|
297 |
|
298 |
}
|
src/icwp-optionshandler-lockdown.php
CHANGED
@@ -22,7 +22,7 @@ if ( !class_exists('ICWP_WPSF_FeatureHandler_Lockdown') ):
|
|
22 |
class ICWP_WPSF_FeatureHandler_Lockdown extends ICWP_WPSF_FeatureHandler_Base {
|
23 |
|
24 |
/**
|
25 |
-
* @var
|
26 |
*/
|
27 |
protected $oFeatureProcessor;
|
28 |
|
@@ -36,12 +36,12 @@ class ICWP_WPSF_FeatureHandler_Lockdown extends ICWP_WPSF_FeatureHandler_Base {
|
|
36 |
}
|
37 |
|
38 |
/**
|
39 |
-
* @return
|
40 |
*/
|
41 |
protected function loadFeatureProcessor() {
|
42 |
if ( !isset( $this->oFeatureProcessor ) ) {
|
43 |
-
require_once(
|
44 |
-
$this->oFeatureProcessor = new
|
45 |
}
|
46 |
return $this->oFeatureProcessor;
|
47 |
}
|
@@ -62,115 +62,94 @@ class ICWP_WPSF_FeatureHandler_Lockdown extends ICWP_WPSF_FeatureHandler_Base {
|
|
62 |
}
|
63 |
|
64 |
/**
|
|
|
65 |
* @return array
|
|
|
66 |
*/
|
67 |
-
protected function
|
68 |
-
|
69 |
-
$
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
)
|
82 |
-
|
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 |
-
_wpsf__( '
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
_wpsf__( 'Remove a meta tag from your WordPress pages that publicly displays that your site is WordPress and its current version.' )
|
144 |
-
)
|
145 |
-
)
|
146 |
-
);
|
147 |
-
|
148 |
-
$aOptionsDefinitions = array(
|
149 |
-
$aBase,
|
150 |
-
$aAccess,
|
151 |
-
$aObscurity
|
152 |
-
);
|
153 |
-
return $aOptionsDefinitions;
|
154 |
-
|
155 |
-
if ( false && $this->getCanDoAuthSalts() ) {
|
156 |
-
$this->aOptions[] = array(
|
157 |
-
'section_title' => _wpsf__( 'Security Actions' ),
|
158 |
-
'section_options' => array(
|
159 |
-
array(
|
160 |
-
'action_reset_auth_salts',
|
161 |
-
'',
|
162 |
-
'N',
|
163 |
-
'checkbox',
|
164 |
-
_wpsf__( 'Reset Auth Keys/Salts' ),
|
165 |
-
_wpsf__( 'Reset WordPress Authentication Keys and Salts' ),
|
166 |
-
_wpsf__( 'Selecting this will reset the WordPress Authentication Keys and Salts in your wp-config.php file.' )
|
167 |
-
.'<br /><strong>'._wpsf__( 'Note: This will log you and all other users out of their current session.' ).'</strong>'
|
168 |
-
)
|
169 |
-
)
|
170 |
-
);
|
171 |
}
|
|
|
|
|
|
|
|
|
|
|
172 |
}
|
173 |
-
|
174 |
protected function getCanDoAuthSalts() {
|
175 |
$oWpFs = $this->loadFileSystemProcessor();
|
176 |
|
@@ -190,7 +169,6 @@ class ICWP_WPSF_FeatureHandler_Lockdown extends ICWP_WPSF_FeatureHandler_Base {
|
|
190 |
$mResult = $oWpFs->getCanReadWriteFile( $sWpConfigPath );
|
191 |
return !empty( $mResult );
|
192 |
}
|
193 |
-
|
194 |
}
|
195 |
|
196 |
endif;
|
22 |
class ICWP_WPSF_FeatureHandler_Lockdown extends ICWP_WPSF_FeatureHandler_Base {
|
23 |
|
24 |
/**
|
25 |
+
* @var ICWP_WPSF_Processor_Lockdown
|
26 |
*/
|
27 |
protected $oFeatureProcessor;
|
28 |
|
36 |
}
|
37 |
|
38 |
/**
|
39 |
+
* @return ICWP_WPSF_Processor_Lockdown|null
|
40 |
*/
|
41 |
protected function loadFeatureProcessor() {
|
42 |
if ( !isset( $this->oFeatureProcessor ) ) {
|
43 |
+
require_once( $this->getController()->getSourceDir( sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) ) );
|
44 |
+
$this->oFeatureProcessor = new ICWP_WPSF_Processor_Lockdown( $this );
|
45 |
}
|
46 |
return $this->oFeatureProcessor;
|
47 |
}
|
62 |
}
|
63 |
|
64 |
/**
|
65 |
+
* @param array $aOptionsParams
|
66 |
* @return array
|
67 |
+
* @throws Exception
|
68 |
*/
|
69 |
+
protected function loadStrings_SectionTitles( $aOptionsParams ) {
|
70 |
+
|
71 |
+
$sSectionSlug = $aOptionsParams['section_slug'];
|
72 |
+
switch( $aOptionsParams['section_slug'] ) {
|
73 |
+
|
74 |
+
case 'section_enable_plugin_feature_wordpress_lockdown' :
|
75 |
+
$sTitle = sprintf( _wpsf__( 'Enable Plugin Feature: %s' ), $this->getMainFeatureName() );
|
76 |
+
break;
|
77 |
+
|
78 |
+
case 'section_permission_access_options' :
|
79 |
+
$sTitle = _wpsf__('Permissions and Access Options');
|
80 |
+
break;
|
81 |
+
|
82 |
+
case 'section_wordpress_obscurity_options' :
|
83 |
+
$sTitle = _wpsf__('WordPress Obscurity Options');
|
84 |
+
break;
|
85 |
+
|
86 |
+
default:
|
87 |
+
throw new Exception( sprintf( 'A section slug was defined but with no associated strings. Slug: "%s".', $sSectionSlug ) );
|
88 |
+
}
|
89 |
+
$aOptionsParams['section_title'] = $sTitle;
|
90 |
+
return $aOptionsParams;
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* @param array $aOptionsParams
|
95 |
+
* @return array
|
96 |
+
* @throws Exception
|
97 |
+
*/
|
98 |
+
protected function loadStrings_Options( $aOptionsParams ) {
|
99 |
+
|
100 |
+
$sKey = $aOptionsParams['key'];
|
101 |
+
switch( $sKey ) {
|
102 |
+
|
103 |
+
case 'enable_lockdown' :
|
104 |
+
$sName = sprintf( _wpsf__( 'Enable %s' ), $this->getMainFeatureName() );
|
105 |
+
$sSummary = sprintf( _wpsf__( 'Enable (or Disable) The %s Feature' ), $this->getMainFeatureName() );
|
106 |
+
$sDescription = sprintf( _wpsf__( 'Checking/Un-Checking this option will completely turn on/off the whole %s feature.' ), $this->getMainFeatureName() );
|
107 |
+
break;
|
108 |
+
|
109 |
+
case 'disable_file_editing' :
|
110 |
+
$sName = _wpsf__( 'Disable File Editing' );
|
111 |
+
$sSummary = _wpsf__( 'Disable Ability To Edit Files From Within WordPress' );
|
112 |
+
$sDescription = _wpsf__( 'Removes the option to directly edit any files from within the WordPress admin area.' )
|
113 |
+
.'<br />'._wpsf__( 'Equivalent to setting "DISALLOW_FILE_EDIT" to TRUE.' );
|
114 |
+
break;
|
115 |
+
|
116 |
+
case 'force_ssl_login' :
|
117 |
+
$sName = _wpsf__( 'Force SSL Login' );
|
118 |
+
$sSummary = _wpsf__( 'Forces Login Form To Be Submitted Over SSL' );
|
119 |
+
$sDescription = _wpsf__( 'Please only enable this option if you have a valid SSL certificate installed.' )
|
120 |
+
.'<br />'._wpsf__( 'Equivalent to setting FORCE_SSL_LOGIN to TRUE.' );
|
121 |
+
break;
|
122 |
+
|
123 |
+
case 'force_ssl_admin' :
|
124 |
+
$sName = _wpsf__( 'Force SSL Admin' );
|
125 |
+
$sSummary = _wpsf__( 'Forces WordPress Admin Dashboard To Be Delivered Over SSL' );
|
126 |
+
$sDescription = _wpsf__( 'Please only enable this option if you have a valid SSL certificate installed.' )
|
127 |
+
.'<br />'._wpsf__( 'Equivalent to setting "FORCE_SSL_ADMIN" to TRUE.' );
|
128 |
+
break;
|
129 |
+
|
130 |
+
case 'mask_wordpress_version' :
|
131 |
+
$sName = _wpsf__( 'Mask WordPress Version' );
|
132 |
+
$sSummary = _wpsf__( 'Prevents Public Display Of Your WordPress Version' );
|
133 |
+
$sDescription = _wpsf__( 'Enter how you would like your WordPress version displayed publicly. Leave blank to disable this feature.' )
|
134 |
+
.'<br />'._wpsf__( 'Warning: This may interfere with WordPress plugins that rely on the $wp_version variable.' );
|
135 |
+
break;
|
136 |
+
|
137 |
+
case 'hide_wordpress_generator_tag' :
|
138 |
+
$sName = _wpsf__( 'WP Generator Tag' );
|
139 |
+
$sSummary = _wpsf__( 'Remove WP Generator Meta Tag' );
|
140 |
+
$sDescription = _wpsf__( 'Remove a meta tag from your WordPress pages that publicly displays that your site is WordPress and its current version.' );
|
141 |
+
break;
|
142 |
+
|
143 |
+
default:
|
144 |
+
throw new Exception( sprintf( 'An option has been defined but without strings assigned to it. Option key: "%s".', $sKey ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
145 |
}
|
146 |
+
|
147 |
+
$aOptionsParams['name'] = $sName;
|
148 |
+
$aOptionsParams['summary'] = $sSummary;
|
149 |
+
$aOptionsParams['description'] = $sDescription;
|
150 |
+
return $aOptionsParams;
|
151 |
}
|
152 |
+
|
153 |
protected function getCanDoAuthSalts() {
|
154 |
$oWpFs = $this->loadFileSystemProcessor();
|
155 |
|
169 |
$mResult = $oWpFs->getCanReadWriteFile( $sWpConfigPath );
|
170 |
return !empty( $mResult );
|
171 |
}
|
|
|
172 |
}
|
173 |
|
174 |
endif;
|
src/icwp-optionshandler-logging.php
CHANGED
@@ -22,7 +22,7 @@ if ( !class_exists('ICWP_WPSF_FeatureHandler_Logging') ):
|
|
22 |
class ICWP_WPSF_FeatureHandler_Logging extends ICWP_WPSF_FeatureHandler_Base {
|
23 |
|
24 |
/**
|
25 |
-
* @var
|
26 |
*/
|
27 |
protected $oFeatureProcessor;
|
28 |
|
@@ -32,50 +32,74 @@ class ICWP_WPSF_FeatureHandler_Logging extends ICWP_WPSF_FeatureHandler_Base {
|
|
32 |
public function __construct( $oPluginVo ) {
|
33 |
$this->sFeatureName = _wpsf__('Logging');
|
34 |
$this->sFeatureSlug = 'logging';
|
35 |
-
$this->fShowFeatureMenuItem = false;
|
36 |
parent::__construct( $oPluginVo );
|
37 |
}
|
38 |
|
39 |
/**
|
40 |
-
* @return
|
41 |
*/
|
42 |
protected function loadFeatureProcessor() {
|
|
|
43 |
if ( !isset( $this->oFeatureProcessor ) ) {
|
44 |
-
require_once(
|
45 |
-
$this->oFeatureProcessor = new
|
46 |
}
|
47 |
return $this->oFeatureProcessor;
|
48 |
}
|
49 |
|
50 |
/**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
* @return array
|
|
|
52 |
*/
|
53 |
-
protected function
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
)
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
$
|
70 |
-
|
71 |
-
|
72 |
-
return $aOptionsDefinitions;
|
73 |
}
|
74 |
|
75 |
/**
|
76 |
-
*
|
77 |
*/
|
78 |
-
|
|
|
|
|
79 |
}
|
80 |
|
81 |
endif;
|
22 |
class ICWP_WPSF_FeatureHandler_Logging extends ICWP_WPSF_FeatureHandler_Base {
|
23 |
|
24 |
/**
|
25 |
+
* @var ICWP_WPSF_Processor_Logging
|
26 |
*/
|
27 |
protected $oFeatureProcessor;
|
28 |
|
32 |
public function __construct( $oPluginVo ) {
|
33 |
$this->sFeatureName = _wpsf__('Logging');
|
34 |
$this->sFeatureSlug = 'logging';
|
|
|
35 |
parent::__construct( $oPluginVo );
|
36 |
}
|
37 |
|
38 |
/**
|
39 |
+
* @return ICWP_WPSF_Processor_Logging|null
|
40 |
*/
|
41 |
protected function loadFeatureProcessor() {
|
42 |
+
|
43 |
if ( !isset( $this->oFeatureProcessor ) ) {
|
44 |
+
require_once( $this->getController()->getSourceDir( sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) ) );
|
45 |
+
$this->oFeatureProcessor = new ICWP_WPSF_Processor_Logging( $this );
|
46 |
}
|
47 |
return $this->oFeatureProcessor;
|
48 |
}
|
49 |
|
50 |
/**
|
51 |
+
* @param array $aOptionsParams
|
52 |
+
* @return array
|
53 |
+
* @throws Exception
|
54 |
+
*/
|
55 |
+
protected function loadStrings_SectionTitles( $aOptionsParams ) {
|
56 |
+
|
57 |
+
$sSectionSlug = $aOptionsParams['section_slug'];
|
58 |
+
switch( $aOptionsParams['section_slug'] ) {
|
59 |
+
|
60 |
+
case 'section_logging_options' :
|
61 |
+
$sTitle = sprintf( _wpsf__( 'Enable Plugin Feature: %s' ), _wpsf__('Logging') );
|
62 |
+
break;
|
63 |
+
|
64 |
+
default:
|
65 |
+
throw new Exception( sprintf( 'A section slug was defined but with no associated strings. Slug: "%s".', $sSectionSlug ) );
|
66 |
+
}
|
67 |
+
$aOptionsParams['section_title'] = $sTitle;
|
68 |
+
return $aOptionsParams;
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* @param array $aOptionsParams
|
73 |
* @return array
|
74 |
+
* @throws Exception
|
75 |
*/
|
76 |
+
protected function loadStrings_Options( $aOptionsParams ) {
|
77 |
+
|
78 |
+
$sKey = $aOptionsParams['key'];
|
79 |
+
switch( $sKey ) {
|
80 |
+
|
81 |
+
case 'enable_logging' :
|
82 |
+
$sName = sprintf( _wpsf__( 'Enable %s' ), $this->getMainFeatureName() );
|
83 |
+
$sSummary = sprintf( _wpsf__( 'Enable (or Disable) The %s Feature' ), $this->getMainFeatureName() );
|
84 |
+
$sDescription = sprintf( _wpsf__( 'Checking/Un-Checking this option will completely turn on/off the whole %s feature.' ), $this->getMainFeatureName() );
|
85 |
+
break;
|
86 |
+
|
87 |
+
default:
|
88 |
+
throw new Exception( sprintf( 'An option has been defined but without strings assigned to it. Option key: "%s".', $sKey ) );
|
89 |
+
}
|
90 |
+
|
91 |
+
$aOptionsParams['name'] = $sName;
|
92 |
+
$aOptionsParams['summary'] = $sSummary;
|
93 |
+
$aOptionsParams['description'] = $sDescription;
|
94 |
+
return $aOptionsParams;
|
|
|
95 |
}
|
96 |
|
97 |
/**
|
98 |
+
* @return string
|
99 |
*/
|
100 |
+
public function getGeneralLoggingTableName() {
|
101 |
+
return $this->doPluginPrefix( $this->getOpt( 'general_logging_table_name' ), '_' );
|
102 |
+
}
|
103 |
}
|
104 |
|
105 |
endif;
|
src/icwp-optionshandler-login_protect.php
CHANGED
@@ -20,9 +20,9 @@ require_once( dirname(__FILE__).'/icwp-optionshandler-base.php' );
|
|
20 |
if ( !class_exists('ICWP_WPSF_FeatureHandler_LoginProtect') ):
|
21 |
|
22 |
class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Base {
|
23 |
-
|
24 |
/**
|
25 |
-
* @var
|
26 |
*/
|
27 |
protected $oFeatureProcessor;
|
28 |
|
@@ -33,17 +33,22 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
|
|
33 |
}
|
34 |
|
35 |
/**
|
36 |
-
* @return
|
37 |
*/
|
38 |
protected function loadFeatureProcessor() {
|
39 |
if ( !isset( $this->oFeatureProcessor ) ) {
|
40 |
-
require_once(
|
41 |
-
$this->oFeatureProcessor = new
|
42 |
}
|
43 |
return $this->oFeatureProcessor;
|
44 |
}
|
45 |
|
46 |
public function doPrePluginOptionsSave() {
|
|
|
|
|
|
|
|
|
|
|
47 |
$aIpWhitelist = $this->getOpt( 'ips_whitelist' );
|
48 |
if ( $aIpWhitelist === false ) {
|
49 |
$aIpWhitelist = '';
|
@@ -56,237 +61,181 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
|
|
56 |
$this->setOpt( 'two_factor_auth_user_roles', $this->getTwoFactorUserAuthRoles( true ) );
|
57 |
}
|
58 |
|
59 |
-
|
|
|
|
|
60 |
}
|
61 |
|
62 |
/**
|
|
|
63 |
* @return array
|
|
|
64 |
*/
|
65 |
-
protected function
|
66 |
-
$aOptionsBase = array(
|
67 |
-
'section_title' => sprintf( _wpsf__( 'Enable Plugin Feature: %s' ), _wpsf__('Login Protection') ),
|
68 |
-
'section_options' => array(
|
69 |
-
array(
|
70 |
-
'enable_login_protect',
|
71 |
-
'',
|
72 |
-
'N',
|
73 |
-
'checkbox',
|
74 |
-
_wpsf__( 'Enable Login Protect' ),
|
75 |
-
_wpsf__( 'Enable (or Disable) The Login Protection Feature' ),
|
76 |
-
sprintf( _wpsf__( 'Checking/Un-Checking this option will completely turn on/off the whole %s feature.' ), _wpsf__('Login Protection') ),
|
77 |
-
'<a href="http://icwp.io/51" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
78 |
-
.' | <a href="http://icwp.io/wpsf03" target="_blank">'._wpsf__( 'blog' ).'</a>'
|
79 |
-
)
|
80 |
-
),
|
81 |
-
);
|
82 |
-
$aWhitelist = array(
|
83 |
-
'section_title' => _wpsf__( 'Whitelist IPs that by-pass Login Protect' ),
|
84 |
-
'section_options' => array(
|
85 |
-
array(
|
86 |
-
'ips_whitelist',
|
87 |
-
'',
|
88 |
-
'',
|
89 |
-
'ip_addresses',
|
90 |
-
_wpsf__( 'Whitelist IP Addresses' ),
|
91 |
-
_wpsf__( 'Specify IP Addresses that by-pass all Login Protect rules' ),
|
92 |
-
sprintf( _wpsf__( 'Take a new line per address. Your IP address is: %s' ), '<span class="code">'.$this->getVisitorIpAddress( false ).'</span>' ),
|
93 |
-
'<a href="http://icwp.io/52" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
94 |
-
)
|
95 |
-
)
|
96 |
-
);
|
97 |
|
98 |
-
$
|
99 |
-
|
100 |
-
'section_options' => array(
|
101 |
-
array(
|
102 |
-
'two_factor_auth_user_roles',
|
103 |
-
'',
|
104 |
-
$this->getTwoFactorUserAuthRoles( true ), // default is Contributors, Authors, Editors and Administrators
|
105 |
-
$this->getTwoFactorUserAuthRoles(),
|
106 |
-
_wpsf__( 'Two-Factor Auth User Roles' ),
|
107 |
-
_wpsf__( 'All User Roles Subject To Two-Factor Authentication' ),
|
108 |
-
_wpsf__( 'Select which types of users/roles will be subject to two-factor login authentication.' ),
|
109 |
-
'<a href="http://icwp.io/4v" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
110 |
-
),
|
111 |
-
array(
|
112 |
-
'enable_two_factor_auth_by_ip',
|
113 |
-
'',
|
114 |
-
'N',
|
115 |
-
'checkbox',
|
116 |
-
sprintf( _wpsf__( 'Two-Factor Authentication (%s)' ), _wpsf__('IP') ),
|
117 |
-
sprintf( _wpsf__( 'Two-Factor Login Authentication By %s' ), _wpsf__('IP Address') ),
|
118 |
-
_wpsf__( 'All users will be required to authenticate their logins by email-based two-factor authentication when logging in from a new IP address' ),
|
119 |
-
'<a href="http://icwp.io/3s" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
120 |
-
),
|
121 |
-
array(
|
122 |
-
'enable_two_factor_auth_by_cookie',
|
123 |
-
'',
|
124 |
-
'N',
|
125 |
-
'checkbox',
|
126 |
-
sprintf( _wpsf__( 'Two-Factor Authentication (%s)' ), _wpsf__('Cookie') ),
|
127 |
-
sprintf( _wpsf__( 'Two-Factor Login Authentication By %s' ), _wpsf__('Cookie') ),
|
128 |
-
_wpsf__( 'This will restrict all user login sessions to a single browser. Use this if your users have dynamic IP addresses.' ),
|
129 |
-
'<a href="http://icwp.io/3t" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
130 |
-
),
|
131 |
-
array(
|
132 |
-
'enable_two_factor_bypass_on_email_fail',
|
133 |
-
'',
|
134 |
-
'N',
|
135 |
-
'checkbox',
|
136 |
-
_wpsf__( 'By-Pass On Failure' ),
|
137 |
-
_wpsf__( 'If Sending Verification Email Sending Fails, Two-Factor Login Authentication Is Ignored' ),
|
138 |
-
_wpsf__( 'If you enable two-factor authentication and sending the email with the verification link fails, turning this setting on will by-pass the verification step. Use with caution' )
|
139 |
-
)
|
140 |
-
)
|
141 |
-
);
|
142 |
-
$aLoginProtect = array(
|
143 |
-
'section_title' => _wpsf__( 'Login Protection Options' ),
|
144 |
-
'section_options' => array(
|
145 |
-
array(
|
146 |
-
'login_limit_interval',
|
147 |
-
'',
|
148 |
-
'10',
|
149 |
-
'integer',
|
150 |
-
_wpsf__('Login Cooldown Interval'),
|
151 |
-
_wpsf__('Limit login attempts to every X seconds'),
|
152 |
-
_wpsf__('WordPress will process only ONE login attempt for every number of seconds specified. Zero (0) turns this off. Suggested: 5'),
|
153 |
-
'<a href="http://icwp.io/3q" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
154 |
-
),
|
155 |
-
array(
|
156 |
-
'enable_login_gasp_check',
|
157 |
-
'',
|
158 |
-
'Y',
|
159 |
-
'checkbox',
|
160 |
-
_wpsf__( 'G.A.S.P Protection' ),
|
161 |
-
_wpsf__( 'Use G.A.S.P. Protection To Prevent Login Attempts By Bots' ),
|
162 |
-
_wpsf__( 'Adds a dynamically (Javascript) generated checkbox to the login form that prevents bots using automated login techniques. Recommended: ON' ),
|
163 |
-
'<a href="http://icwp.io/3r" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
164 |
-
),
|
165 |
-
array(
|
166 |
-
'enable_prevent_remote_post',
|
167 |
-
'',
|
168 |
-
'Y',
|
169 |
-
'checkbox',
|
170 |
-
_wpsf__( 'Prevent Remote Login' ),
|
171 |
-
_wpsf__( 'Prevents Remote Login Attempts From Other Locations' ),
|
172 |
-
_wpsf__( 'Prevents any login attempts that do not originate from your website. This prevent bots from attempting to login remotely. Recommended: ON' ),
|
173 |
-
'<a href="http://icwp.io/4n" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
174 |
-
)
|
175 |
-
)
|
176 |
-
);
|
177 |
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
array(
|
182 |
-
'enable_yubikey',
|
183 |
-
'',
|
184 |
-
'N',
|
185 |
-
'checkbox',
|
186 |
-
_wpsf__('Enable Yubikey Authentication'),
|
187 |
-
_wpsf__('Turn On / Off Yubikey Authentication On This Site'),
|
188 |
-
_wpsf__('Combined with your Yubikey API Key (below) this will form the basis of your Yubikey Authentication'),
|
189 |
-
'<a href="http://icwp.io/4f" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
190 |
-
),
|
191 |
-
array(
|
192 |
-
'yubikey_app_id',
|
193 |
-
'',
|
194 |
-
'',
|
195 |
-
'text',
|
196 |
-
_wpsf__('Yubikey App ID'),
|
197 |
-
_wpsf__('Your Unique Yubikey App ID'),
|
198 |
-
_wpsf__('Combined with your Yubikey API Key (below) this will form the basis of your Yubikey Authentication')
|
199 |
-
. _wpsf__( 'Please review the [more info] link on how to get your own Yubikey App ID and API Key.' ),
|
200 |
-
'<a href="http://icwp.io/4g" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
201 |
-
),
|
202 |
-
array(
|
203 |
-
'yubikey_api_key',
|
204 |
-
'',
|
205 |
-
'',
|
206 |
-
'text',
|
207 |
-
_wpsf__( 'Yubikey API Key' ),
|
208 |
-
_wpsf__( 'Your Unique Yubikey App API Key' ),
|
209 |
-
_wpsf__( 'Combined with your Yubikey App ID (above) this will form the basis of your Yubikey Authentication.' )
|
210 |
-
. _wpsf__( 'Please review the [more info] link on how to get your own Yubikey App ID and API Key.' ),
|
211 |
-
'<a href="http://icwp.io/4g" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
212 |
-
),
|
213 |
-
array(
|
214 |
-
'yubikey_unique_keys',
|
215 |
-
'',
|
216 |
-
'',
|
217 |
-
'yubikey_unique_keys',
|
218 |
-
_wpsf__( 'Yubikey Unique Keys' ),
|
219 |
-
_wpsf__( 'Permitted Username - Yubikey Pairs For This Site' ),
|
220 |
-
'<strong>'. sprintf( _wpsf__( 'Format: %s' ), 'Username,Yubikey').'</strong>'
|
221 |
-
.'<br />- '. _wpsf__( 'Provide Username<->Yubikey Pairs that are usable on this site.')
|
222 |
-
.'<br />- '. _wpsf__( 'If a Username if not assigned a Yubikey, Yubikey Authentication is OFF for that user.')
|
223 |
-
.'<br />- '. _wpsf__( 'Each [Username,Key] pair should be separated by a new line: you only need to provide the first 12 characters of the yubikey.' ),
|
224 |
-
'<a href="http://icwp.io/4h" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
225 |
-
),
|
226 |
-
/*
|
227 |
-
array(
|
228 |
-
'enable_yubikey_only',
|
229 |
-
'',
|
230 |
-
'N',
|
231 |
-
'checkbox',
|
232 |
-
_wpsf__('Enable Yubikey Only'),
|
233 |
-
_wpsf__('Turn On / Off Yubikey Only Authentication'),
|
234 |
-
_wpsf__('Yubikey Only Authentication is where you can login into your WordPress site with just a Yubikey OTP.')
|
235 |
-
.'<br />- '. _wpsf__("You don't need to enter a username or a password, just a valid Yubikey OTP.")
|
236 |
-
.'<br />- '. _wpsf__("Check your list of Yubikeys as only 1 WordPress username may be assigned to a given Yubikey ID (but you may have multiple Yubikeys for a given username)."),
|
237 |
-
sprintf( _wpsf__( '%smore info%s' ), '<a href="http://icwp.io/4f" target="_blank">', '</a>' )
|
238 |
-
),*/
|
239 |
-
)
|
240 |
-
);
|
241 |
-
|
242 |
-
$aLoggingSection = array(
|
243 |
-
'section_title' => _wpsf__( 'Logging Options' ),
|
244 |
-
'section_options' => array(
|
245 |
-
array(
|
246 |
-
'enable_login_protect_log',
|
247 |
-
'',
|
248 |
-
'N',
|
249 |
-
'checkbox',
|
250 |
-
_wpsf__( 'Login Protect Logging' ),
|
251 |
-
_wpsf__( 'Turn on a detailed Login Protect Log' ),
|
252 |
-
_wpsf__( 'Will log every event related to login protection and how it is processed. Not recommended to leave on unless you want to debug something and check the login protection is working as you expect.' )
|
253 |
-
)
|
254 |
-
)
|
255 |
-
);
|
256 |
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
266 |
}
|
267 |
|
268 |
/**
|
|
|
269 |
* @return array
|
|
|
270 |
*/
|
271 |
-
protected function
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
)
|
276 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
277 |
}
|
278 |
|
279 |
/**
|
280 |
* @return bool|void
|
281 |
*/
|
282 |
-
public function
|
283 |
-
$fSuccess = parent::handleFormSubmit();
|
284 |
-
if ( !$fSuccess ) {
|
285 |
-
return;
|
286 |
-
}
|
287 |
-
|
288 |
// When they've clicked to terminate all logged in authenticated users.
|
289 |
-
|
|
|
290 |
$oProc = $this->getProcessor();
|
291 |
$oProc->doTerminateAllVerifiedLogins();
|
292 |
return;
|
@@ -309,11 +258,20 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
|
|
309 |
if ( $fAsDefaults ) {
|
310 |
unset($aTwoAuthRoles['type']);
|
311 |
unset($aTwoAuthRoles[0]);
|
312 |
-
return array_keys($aTwoAuthRoles);
|
313 |
}
|
314 |
return $aTwoAuthRoles;
|
315 |
}
|
316 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
317 |
/**
|
318 |
* @return string
|
319 |
*/
|
@@ -334,6 +292,20 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
|
|
334 |
return $sKey;
|
335 |
}
|
336 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
337 |
/**
|
338 |
* @return string
|
339 |
*/
|
@@ -345,6 +317,28 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
|
|
345 |
}
|
346 |
return $sKey;
|
347 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
348 |
}
|
349 |
|
350 |
endif;
|
20 |
if ( !class_exists('ICWP_WPSF_FeatureHandler_LoginProtect') ):
|
21 |
|
22 |
class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Base {
|
23 |
+
|
24 |
/**
|
25 |
+
* @var ICWP_WPSF_Processor_LoginProtect
|
26 |
*/
|
27 |
protected $oFeatureProcessor;
|
28 |
|
33 |
}
|
34 |
|
35 |
/**
|
36 |
+
* @return ICWP_WPSF_Processor_LoginProtect|null
|
37 |
*/
|
38 |
protected function loadFeatureProcessor() {
|
39 |
if ( !isset( $this->oFeatureProcessor ) ) {
|
40 |
+
require_once( $this->getController()->getSourceDir( sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) ) );
|
41 |
+
$this->oFeatureProcessor = new ICWP_WPSF_Processor_LoginProtect( $this );
|
42 |
}
|
43 |
return $this->oFeatureProcessor;
|
44 |
}
|
45 |
|
46 |
public function doPrePluginOptionsSave() {
|
47 |
+
|
48 |
+
if ( $this->getOpt( 'login_limit_interval' ) < 0 ) {
|
49 |
+
$this->getOptionsVo()->resetOptToDefault( 'login_limit_interval' );
|
50 |
+
}
|
51 |
+
|
52 |
$aIpWhitelist = $this->getOpt( 'ips_whitelist' );
|
53 |
if ( $aIpWhitelist === false ) {
|
54 |
$aIpWhitelist = '';
|
61 |
$this->setOpt( 'two_factor_auth_user_roles', $this->getTwoFactorUserAuthRoles( true ) );
|
62 |
}
|
63 |
|
64 |
+
// ensures they have values
|
65 |
+
$this->setKeys();
|
66 |
+
$this->getLastLoginTimeFilePath();
|
67 |
}
|
68 |
|
69 |
/**
|
70 |
+
* @param array $aOptionsParams
|
71 |
* @return array
|
72 |
+
* @throws Exception
|
73 |
*/
|
74 |
+
protected function loadStrings_SectionTitles( $aOptionsParams ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
|
76 |
+
$sSectionSlug = $aOptionsParams['section_slug'];
|
77 |
+
switch( $aOptionsParams['section_slug'] ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
|
79 |
+
case 'section_enable_plugin_feature_login_protection' :
|
80 |
+
$sTitle = sprintf( _wpsf__( 'Enable Plugin Feature: %s' ), $this->getMainFeatureName() );
|
81 |
+
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
82 |
|
83 |
+
case 'section_bypass_login_protection' :
|
84 |
+
$sTitle = _wpsf__('By-Pass Login Protection');
|
85 |
+
break;
|
86 |
+
|
87 |
+
case 'section_two_factor_authentication' :
|
88 |
+
$sTitle = _wpsf__('Two-Factor Authentication');
|
89 |
+
break;
|
90 |
+
|
91 |
+
case 'section_brute_force_login_protection' :
|
92 |
+
$sTitle = _wpsf__('Brute Force Login Protection');
|
93 |
+
break;
|
94 |
+
|
95 |
+
case 'section_yubikey_authentication' :
|
96 |
+
$sTitle = _wpsf__('Yubikey Authentication');
|
97 |
+
break;
|
98 |
+
|
99 |
+
case 'section_login_logging' :
|
100 |
+
$sTitle = _wpsf__('Logging');
|
101 |
+
break;
|
102 |
+
|
103 |
+
default:
|
104 |
+
throw new Exception( sprintf( 'A section slug was defined but with no associated strings. Slug: "%s".', $sSectionSlug ) );
|
105 |
+
}
|
106 |
+
$aOptionsParams['section_title'] = $sTitle;
|
107 |
+
return $aOptionsParams;
|
108 |
}
|
109 |
|
110 |
/**
|
111 |
+
* @param array $aOptionsParams
|
112 |
* @return array
|
113 |
+
* @throws Exception
|
114 |
*/
|
115 |
+
protected function loadStrings_Options( $aOptionsParams ) {
|
116 |
+
|
117 |
+
$oDp = $this->loadDataProcessor();
|
118 |
+
$sKey = $aOptionsParams['key'];
|
119 |
+
switch( $sKey ) {
|
120 |
+
|
121 |
+
case 'enable_login_protect' :
|
122 |
+
$sName = sprintf( _wpsf__( 'Enable %s' ), $this->getMainFeatureName() );
|
123 |
+
$sSummary = sprintf( _wpsf__( 'Enable (or Disable) The %s Feature' ), $this->getMainFeatureName() );
|
124 |
+
$sDescription = sprintf( _wpsf__( 'Checking/Un-Checking this option will completely turn on/off the whole %s feature.' ), $this->getMainFeatureName() );
|
125 |
+
break;
|
126 |
+
|
127 |
+
case 'enable_xmlrpc_compatibility' :
|
128 |
+
$sName = _wpsf__( 'XML-RPC Compatibility' );
|
129 |
+
$sSummary = _wpsf__( 'Allow Login Through XML-RPC To By-Pass Login Protection Rules' );
|
130 |
+
$sDescription = _wpsf__( 'Enable this if you need XML-RPC functionality e.g. if you use the WordPress iPhone/Android App.' );
|
131 |
+
break;
|
132 |
+
|
133 |
+
case 'ips_whitelist' :
|
134 |
+
$sName = _wpsf__( 'Whitelist IP Addresses' );
|
135 |
+
$sSummary = _wpsf__( 'Specify IP Addresses that by-pass all Login Protect rules' );
|
136 |
+
$sDescription = sprintf(
|
137 |
+
_wpsf__( 'Take a new line per address. Your IP address is: %s' ),
|
138 |
+
'<span class="code">'.( $oDp->GetVisitorIpAddress( false ) ).'</span>'
|
139 |
+
);
|
140 |
+
break;
|
141 |
+
|
142 |
+
case 'two_factor_auth_user_roles' :
|
143 |
+
$sName = _wpsf__( 'Two-Factor Auth User Roles' );
|
144 |
+
$sSummary = _wpsf__( 'All User Roles Subject To Two-Factor Authentication' );
|
145 |
+
$sDescription = _wpsf__( 'Select which types of users/roles will be subject to two-factor login authentication.' );
|
146 |
+
break;
|
147 |
+
|
148 |
+
case 'enable_two_factor_auth_by_ip' :
|
149 |
+
$sName = sprintf( _wpsf__( 'Two-Factor Authentication (%s)' ), _wpsf__('IP') );
|
150 |
+
$sSummary = sprintf( _wpsf__( 'Two-Factor Login Authentication By %s' ), _wpsf__('IP Address') );
|
151 |
+
$sDescription = _wpsf__( 'All users will be required to authenticate their login by email-based two-factor authentication, when logging in from a new IP address' );
|
152 |
+
break;
|
153 |
+
|
154 |
+
case 'enable_two_factor_auth_by_cookie' :
|
155 |
+
$sName = sprintf( _wpsf__( 'Two-Factor Authentication (%s)' ), _wpsf__('Cookie') );
|
156 |
+
$sSummary = sprintf( _wpsf__( 'Two-Factor Login Authentication By %s' ), _wpsf__('Cookie') );
|
157 |
+
$sDescription = _wpsf__( 'This will restrict all user login sessions to a single browser. Use this if your users have dynamic IP addresses.' );
|
158 |
+
break;
|
159 |
+
|
160 |
+
case 'enable_two_factor_bypass_on_email_fail' :
|
161 |
+
$sName = _wpsf__( 'By-Pass On Failure' );
|
162 |
+
$sSummary = _wpsf__( 'If Sending Verification Email Sending Fails, Two-Factor Login Authentication Is Ignored' );
|
163 |
+
$sDescription = _wpsf__( 'If you enable two-factor authentication and sending the email with the verification link fails, turning this setting on will by-pass the verification step. Use with caution.' );
|
164 |
+
break;
|
165 |
+
|
166 |
+
case 'login_limit_interval' :
|
167 |
+
$sName = _wpsf__('Login Cooldown Interval');
|
168 |
+
$sSummary = _wpsf__('Limit login attempts to every X seconds');
|
169 |
+
$sDescription = _wpsf__( 'WordPress will process only ONE login attempt for every number of seconds specified.' )
|
170 |
+
.'<br />'._wpsf__( 'Zero (0) turns this off.' )
|
171 |
+
.' '.sprintf( _wpsf__( 'Default: "%s".' ), $this->getOptionsVo()->getOptDefault( 'login_limit_interval' ) );
|
172 |
+
break;
|
173 |
+
|
174 |
+
case 'enable_login_gasp_check' :
|
175 |
+
$sName = _wpsf__( 'G.A.S.P Protection' );
|
176 |
+
$sSummary = _wpsf__( 'Use G.A.S.P. Protection To Prevent Login Attempts By Bots' );
|
177 |
+
$sDescription = _wpsf__( 'Adds a dynamically (Javascript) generated checkbox to the login form that prevents bots using automated login techniques. Recommended: ON' );
|
178 |
+
break;
|
179 |
+
|
180 |
+
case 'enable_prevent_remote_post' :
|
181 |
+
$sName = _wpsf__( 'Prevent Remote Login' );
|
182 |
+
$sSummary = _wpsf__( 'Prevents Remote Login Attempts From Anywhere Except Your Site' );
|
183 |
+
$sDescription = _wpsf__( 'Prevents any login attempts that do not originate from your website. This prevent bots from attempting to login remotely. Recommended: ON' );
|
184 |
+
break;
|
185 |
+
|
186 |
+
case 'enable_yubikey' :
|
187 |
+
$sName = _wpsf__('Enable Yubikey Authentication');
|
188 |
+
$sSummary = _wpsf__('Turn On / Off Yubikey Authentication On This Site');
|
189 |
+
$sDescription = _wpsf__('Combined with your Yubikey API Key (below) this will form the basis of your Yubikey Authentication');
|
190 |
+
break;
|
191 |
+
|
192 |
+
case 'yubikey_app_id' :
|
193 |
+
$sName = _wpsf__( 'Yubikey App ID' );
|
194 |
+
$sSummary = _wpsf__( 'Your Unique Yubikey App ID' );
|
195 |
+
$sDescription = _wpsf__( 'Combined with your Yubikey API Key this will form the basis of your Yubikey Authentication' )
|
196 |
+
. _wpsf__( 'Please review the info link on how to obtain your own Yubikey App ID and API Key.' );
|
197 |
+
break;
|
198 |
+
|
199 |
+
case 'yubikey_api_key' :
|
200 |
+
$sName = _wpsf__( 'Yubikey API Key' );
|
201 |
+
$sSummary = _wpsf__( 'Your Unique Yubikey App API Key' );
|
202 |
+
$sDescription = _wpsf__( 'Combined with your Yubikey App ID this will form the basis of your Yubikey Authentication.' )
|
203 |
+
. _wpsf__( 'Please review the info link on how to get your own Yubikey App ID and API Key.' );
|
204 |
+
break;
|
205 |
+
|
206 |
+
case 'yubikey_unique_keys' :
|
207 |
+
$sName = _wpsf__( 'Yubikey Unique Keys' );
|
208 |
+
$sSummary = _wpsf__( 'Permitted "Username - Yubikey" Pairs For This Site' );
|
209 |
+
$sDescription = '<strong>'. sprintf( _wpsf__( 'Format: %s' ), 'Username,Yubikey' ).'</strong>'
|
210 |
+
.'<br />- '. _wpsf__( 'Provide Username<->Yubikey Pairs that are usable for this site.')
|
211 |
+
.'<br />- '. _wpsf__( 'If a Username if not assigned a Yubikey, Yubikey Authentication is OFF for that user.' )
|
212 |
+
.'<br />- '. _wpsf__( 'Each [Username,Key] pair should be separated by a new line: you only need to provide the first 12 characters of the yubikey.' );
|
213 |
+
break;
|
214 |
+
|
215 |
+
case 'enable_login_protect_log' :
|
216 |
+
$sName = _wpsf__( 'Login Protect Logging' );
|
217 |
+
$sSummary = _wpsf__( 'Turn on a detailed Login Protect Log' );
|
218 |
+
$sDescription = _wpsf__( 'Will log every event related to login protection and how it is processed. ' )
|
219 |
+
.'<br />'. _wpsf__( 'Not recommended to leave on unless you want to debug something and check the login protection is working as you expect.' );
|
220 |
+
break;
|
221 |
+
|
222 |
+
default:
|
223 |
+
throw new Exception( sprintf( 'An option has been defined but without strings assigned to it. Option key: "%s".', $sKey ) );
|
224 |
+
}
|
225 |
+
|
226 |
+
$aOptionsParams['name'] = $sName;
|
227 |
+
$aOptionsParams['summary'] = $sSummary;
|
228 |
+
$aOptionsParams['description'] = $sDescription;
|
229 |
+
return $aOptionsParams;
|
230 |
}
|
231 |
|
232 |
/**
|
233 |
* @return bool|void
|
234 |
*/
|
235 |
+
public function doExtraSubmitProcessing() {
|
|
|
|
|
|
|
|
|
|
|
236 |
// When they've clicked to terminate all logged in authenticated users.
|
237 |
+
$oDp = $this->loadDataProcessor();
|
238 |
+
if ( $oDp->FetchPost( 'terminate-all-logins' ) ) {
|
239 |
$oProc = $this->getProcessor();
|
240 |
$oProc->doTerminateAllVerifiedLogins();
|
241 |
return;
|
258 |
if ( $fAsDefaults ) {
|
259 |
unset($aTwoAuthRoles['type']);
|
260 |
unset($aTwoAuthRoles[0]);
|
261 |
+
return array_keys( $aTwoAuthRoles );
|
262 |
}
|
263 |
return $aTwoAuthRoles;
|
264 |
}
|
265 |
|
266 |
+
/**
|
267 |
+
* @return string
|
268 |
+
*/
|
269 |
+
public function getLastLoginTimeFilePath() {
|
270 |
+
// we always update it (but it wont need saved because we compare)
|
271 |
+
$this->setOpt( 'last_login_time_file_path', $this->getController()->getRootDir().'mode.login_throttled' );
|
272 |
+
return $this->getOpt( 'last_login_time_file_path' );
|
273 |
+
}
|
274 |
+
|
275 |
/**
|
276 |
* @return string
|
277 |
*/
|
292 |
return $sKey;
|
293 |
}
|
294 |
|
295 |
+
/**
|
296 |
+
* @return string
|
297 |
+
*/
|
298 |
+
public function getTwoFactorAuthTableName() {
|
299 |
+
return $this->doPluginPrefix( $this->getOpt( 'two_factor_auth_table_name' ), '_' );
|
300 |
+
}
|
301 |
+
|
302 |
+
/**
|
303 |
+
* @return string
|
304 |
+
*/
|
305 |
+
public function getTwoFactorAuthCookieName() {
|
306 |
+
return $this->getOpt( 'two_factor_auth_cookie_name' );
|
307 |
+
}
|
308 |
+
|
309 |
/**
|
310 |
* @return string
|
311 |
*/
|
317 |
}
|
318 |
return $sKey;
|
319 |
}
|
320 |
+
|
321 |
+
/**
|
322 |
+
* @param string $sType can be either 'ip' or 'cookie'. If empty, both are checked looking for either.
|
323 |
+
* @return bool
|
324 |
+
*/
|
325 |
+
public function getIsTwoFactorAuthOn( $sType = '' ) {
|
326 |
+
|
327 |
+
$fIp = $this->getOptIs( 'enable_two_factor_auth_by_ip', 'Y' );
|
328 |
+
$fCookie = $this->getOptIs( 'enable_two_factor_auth_by_cookie', 'Y' );
|
329 |
+
|
330 |
+
switch( $sType ) {
|
331 |
+
case 'ip':
|
332 |
+
return $fIp;
|
333 |
+
break;
|
334 |
+
case 'cookie':
|
335 |
+
return $fCookie;
|
336 |
+
break;
|
337 |
+
default:
|
338 |
+
return $fIp || $fCookie;
|
339 |
+
break;
|
340 |
+
}
|
341 |
+
}
|
342 |
}
|
343 |
|
344 |
endif;
|
src/icwp-optionshandler-plugin.php
CHANGED
@@ -21,10 +21,8 @@ if ( !class_exists('ICWP_WPSF_FeatureHandler_Plugin') ):
|
|
21 |
|
22 |
class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_Base {
|
23 |
|
24 |
-
const Default_AccessKeyTimeout = 30;
|
25 |
-
|
26 |
/**
|
27 |
-
* @var
|
28 |
*/
|
29 |
protected $oFeatureProcessor;
|
30 |
|
@@ -38,16 +36,54 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_Base {
|
|
38 |
}
|
39 |
|
40 |
/**
|
41 |
-
* @return
|
42 |
*/
|
43 |
protected function loadFeatureProcessor() {
|
44 |
if ( !isset( $this->oFeatureProcessor ) ) {
|
45 |
-
require_once(
|
46 |
-
$this->oFeatureProcessor = new
|
47 |
}
|
48 |
return $this->oFeatureProcessor;
|
49 |
}
|
50 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
/**
|
52 |
* @return mixed
|
53 |
*/
|
@@ -75,8 +111,6 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_Base {
|
|
75 |
$aPluginSummaryData = apply_filters( $this->doPluginPrefix( 'get_feature_summary_data' ), array() );
|
76 |
|
77 |
$aData = array(
|
78 |
-
'aAllOptions' => $this->getOptions(),
|
79 |
-
'all_options_input' => $this->collateAllFormInputsForAllOptions(),
|
80 |
'aSummaryData' => $aPluginSummaryData
|
81 |
);
|
82 |
$aData = array_merge( $this->getBaseDisplayData(), $aData );
|
@@ -85,12 +119,16 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_Base {
|
|
85 |
|
86 |
/**
|
87 |
* Hooked to 'deactivate_plugin' and can be used to interrupt the deactivation of this plugin.
|
88 |
-
*
|
|
|
89 |
*/
|
90 |
-
public function onWpHookDeactivatePlugin( $
|
91 |
-
if ( strpos( $this->
|
92 |
if ( !apply_filters( $this->doPluginPrefix( 'has_permission_to_submit' ), true ) ) {
|
93 |
-
wp_die(
|
|
|
|
|
|
|
94 |
}
|
95 |
}
|
96 |
}
|
@@ -108,76 +146,68 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_Base {
|
|
108 |
}
|
109 |
|
110 |
/**
|
|
|
111 |
* @return array
|
|
|
112 |
*/
|
113 |
-
protected function
|
114 |
-
$aGeneral = array(
|
115 |
-
'section_title' => _wpsf__( 'General Plugin Options' ),
|
116 |
-
'section_options' => array(
|
117 |
-
array(
|
118 |
-
'block_send_email_address',
|
119 |
-
'',
|
120 |
-
'',
|
121 |
-
'email',
|
122 |
-
_wpsf__( 'Report Email' ),
|
123 |
-
_wpsf__( 'Where to send email reports from the Firewall' ),
|
124 |
-
_wpsf__( 'If this is empty, it will default to the blog admin email address' )
|
125 |
-
),
|
126 |
-
array(
|
127 |
-
'enable_upgrade_admin_notice',
|
128 |
-
'',
|
129 |
-
'Y',
|
130 |
-
'checkbox',
|
131 |
-
_wpsf__( 'Plugin Notices' ),
|
132 |
-
_wpsf__( 'Display Notices For Updates' ),
|
133 |
-
_wpsf__( 'Disable this option to hide certain plugin admin notices about available updates and post-update notices' )
|
134 |
-
),
|
135 |
-
array(
|
136 |
-
'delete_on_deactivate',
|
137 |
-
'',
|
138 |
-
'N',
|
139 |
-
'checkbox',
|
140 |
-
_wpsf__( 'Delete Plugin Settings' ),
|
141 |
-
_wpsf__( 'Delete All Plugin Settings Upon Plugin Deactivation' ),
|
142 |
-
_wpsf__( 'Careful: Removes all plugin options when you deactivate the plugin' )
|
143 |
-
)
|
144 |
-
)
|
145 |
-
);
|
146 |
|
147 |
-
$
|
148 |
-
|
149 |
-
|
150 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
151 |
}
|
152 |
|
153 |
/**
|
|
|
154 |
* @return array
|
|
|
155 |
*/
|
156 |
-
protected function
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
'
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
166 |
}
|
167 |
-
|
168 |
/**
|
169 |
* This is the point where you would want to do any options verification
|
170 |
*/
|
171 |
protected function doPrePluginOptionsSave() {
|
172 |
-
|
173 |
-
if ( $this->getOpt( 'admin_access_key_timeout' ) <= 0 ) {
|
174 |
-
$this->setOpt( 'admin_access_key_timeout', self::Default_AccessKeyTimeout );
|
175 |
-
}
|
176 |
-
|
177 |
-
$sAccessKey = $this->getOpt( 'admin_access_key');
|
178 |
-
if ( empty( $sAccessKey ) ) {
|
179 |
-
$this->setOpt( 'enable_admin_access_restriction', 'N' );
|
180 |
-
}
|
181 |
|
182 |
$this->setOpt( 'enable_logging', 'Y' );
|
183 |
|
@@ -189,10 +219,30 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_Base {
|
|
189 |
|
190 |
protected function updateHandler() {
|
191 |
parent::updateHandler();
|
|
|
|
|
|
|
|
|
|
|
192 |
if ( version_compare( $this->getVersion(), '3.0.0', '<' ) ) {
|
193 |
$aAllOptions = apply_filters( $this->doPluginPrefix( 'aggregate_all_plugin_options' ), array() );
|
194 |
$this->setOpt( 'block_send_email_address', $aAllOptions['block_send_email_address'] );
|
195 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
196 |
}
|
197 |
}
|
198 |
|
21 |
|
22 |
class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_Base {
|
23 |
|
|
|
|
|
24 |
/**
|
25 |
+
* @var ICWP_WPSF_Processor_Plugin
|
26 |
*/
|
27 |
protected $oFeatureProcessor;
|
28 |
|
36 |
}
|
37 |
|
38 |
/**
|
39 |
+
* @return ICWP_WPSF_Processor_Plugin|null
|
40 |
*/
|
41 |
protected function loadFeatureProcessor() {
|
42 |
if ( !isset( $this->oFeatureProcessor ) ) {
|
43 |
+
require_once( $this->getController()->getSourceDir().'icwp-processor-plugin.php' );
|
44 |
+
$this->oFeatureProcessor = new ICWP_WPSF_Processor_Plugin( $this );
|
45 |
}
|
46 |
return $this->oFeatureProcessor;
|
47 |
}
|
48 |
|
49 |
+
/**
|
50 |
+
*/
|
51 |
+
public function doClearAdminFeedback() {
|
52 |
+
$this->setOpt( 'feedback_admin_notice', array() );
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* @param string $sMessage
|
57 |
+
*/
|
58 |
+
public function doAddAdminFeedback( $sMessage ) {
|
59 |
+
$aFeedback = $this->getOpt( 'feedback_admin_notice', array() );
|
60 |
+
$aFeedback[] = $sMessage;
|
61 |
+
$this->setOpt( 'feedback_admin_notice', $aFeedback );
|
62 |
+
}
|
63 |
+
|
64 |
+
public function doExtraSubmitProcessing() {
|
65 |
+
$this->doAddAdminFeedback( sprintf( _wpsf__( '%s Plugin options updated successfully.' ), $this->getController()->getHumanName() ) );
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* @return array
|
70 |
+
*/
|
71 |
+
public function getActivePluginFeatures() {
|
72 |
+
$aActiveFeatures = $this->getOptionsVo()->getRawData_SingleOption( 'active_plugin_features' );
|
73 |
+
$aPluginFeatures = array();
|
74 |
+
if ( empty( $aActiveFeatures['value'] ) || !is_array( $aActiveFeatures['value'] ) ) {
|
75 |
+
return $aPluginFeatures;
|
76 |
+
}
|
77 |
+
|
78 |
+
foreach( $aActiveFeatures['value'] as $aFeature ) {
|
79 |
+
if ( isset( $aFeature['hidden'] ) && $aFeature['hidden'] ) {
|
80 |
+
continue;
|
81 |
+
}
|
82 |
+
$aPluginFeatures[ $aFeature['slug'] ] = $aFeature['storage_key'];
|
83 |
+
}
|
84 |
+
return $aPluginFeatures;
|
85 |
+
}
|
86 |
+
|
87 |
/**
|
88 |
* @return mixed
|
89 |
*/
|
111 |
$aPluginSummaryData = apply_filters( $this->doPluginPrefix( 'get_feature_summary_data' ), array() );
|
112 |
|
113 |
$aData = array(
|
|
|
|
|
114 |
'aSummaryData' => $aPluginSummaryData
|
115 |
);
|
116 |
$aData = array_merge( $this->getBaseDisplayData(), $aData );
|
119 |
|
120 |
/**
|
121 |
* Hooked to 'deactivate_plugin' and can be used to interrupt the deactivation of this plugin.
|
122 |
+
*
|
123 |
+
* @param string $sPlugin
|
124 |
*/
|
125 |
+
public function onWpHookDeactivatePlugin( $sPlugin ) {
|
126 |
+
if ( strpos( $this->getController()->getRootFile(), $sPlugin ) !== false ) {
|
127 |
if ( !apply_filters( $this->doPluginPrefix( 'has_permission_to_submit' ), true ) ) {
|
128 |
+
wp_die(
|
129 |
+
_wpsf__( 'Sorry, you do not have permission to disable this plugin.')
|
130 |
+
. _wpsf__( 'You need to authenticate first.' )
|
131 |
+
);
|
132 |
}
|
133 |
}
|
134 |
}
|
146 |
}
|
147 |
|
148 |
/**
|
149 |
+
* @param array $aOptionsParams
|
150 |
* @return array
|
151 |
+
* @throws Exception
|
152 |
*/
|
153 |
+
protected function loadStrings_SectionTitles( $aOptionsParams ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
154 |
|
155 |
+
$sSectionSlug = $aOptionsParams['section_slug'];
|
156 |
+
switch( $aOptionsParams['section_slug'] ) {
|
157 |
+
|
158 |
+
case 'section_general_plugin_options' :
|
159 |
+
$sTitle = _wpsf__( 'General Plugin Options' );
|
160 |
+
break;
|
161 |
+
|
162 |
+
default:
|
163 |
+
throw new Exception( sprintf( 'A section slug was defined but with no associated strings. Slug: "%s".', $sSectionSlug ) );
|
164 |
+
}
|
165 |
+
$aOptionsParams['section_title'] = $sTitle;
|
166 |
+
return $aOptionsParams;
|
167 |
}
|
168 |
|
169 |
/**
|
170 |
+
* @param array $aOptionsParams
|
171 |
* @return array
|
172 |
+
* @throws Exception
|
173 |
*/
|
174 |
+
protected function loadStrings_Options( $aOptionsParams ) {
|
175 |
+
|
176 |
+
$sKey = $aOptionsParams['key'];
|
177 |
+
switch( $sKey ) {
|
178 |
+
|
179 |
+
case 'block_send_email_address' :
|
180 |
+
$sName = _wpsf__( 'Report Email' );
|
181 |
+
$sSummary = _wpsf__( 'Where to send email reports' );
|
182 |
+
$sDescription = sprintf( _wpsf__( 'If this is empty, it will default to the blog admin email address: %s' ), '<br /><strong>'.get_bloginfo('admin_email').'</strong>' );
|
183 |
+
break;
|
184 |
+
|
185 |
+
case 'enable_upgrade_admin_notice' :
|
186 |
+
$sName = _wpsf__( 'Plugin Notices' );
|
187 |
+
$sSummary = _wpsf__( 'Display Notices For Updates' );
|
188 |
+
$sDescription = _wpsf__( 'Disable this option to hide certain plugin admin notices about available updates and post-update notices' );
|
189 |
+
break;
|
190 |
+
|
191 |
+
case 'delete_on_deactivate' :
|
192 |
+
$sName = _wpsf__( 'Delete Plugin Settings' );
|
193 |
+
$sSummary = _wpsf__( 'Delete All Plugin Settings Upon Plugin Deactivation' );
|
194 |
+
$sDescription = _wpsf__( 'Careful: Removes all plugin options when you deactivate the plugin' );
|
195 |
+
break;
|
196 |
+
|
197 |
+
default:
|
198 |
+
throw new Exception( sprintf( 'An option has been defined but without strings assigned to it. Option key: "%s".', $sKey ) );
|
199 |
+
}
|
200 |
+
|
201 |
+
$aOptionsParams['name'] = $sName;
|
202 |
+
$aOptionsParams['summary'] = $sSummary;
|
203 |
+
$aOptionsParams['description'] = $sDescription;
|
204 |
+
return $aOptionsParams;
|
205 |
}
|
206 |
+
|
207 |
/**
|
208 |
* This is the point where you would want to do any options verification
|
209 |
*/
|
210 |
protected function doPrePluginOptionsSave() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
211 |
|
212 |
$this->setOpt( 'enable_logging', 'Y' );
|
213 |
|
219 |
|
220 |
protected function updateHandler() {
|
221 |
parent::updateHandler();
|
222 |
+
|
223 |
+
if ( $this->getVersion() == '0.0' ) {
|
224 |
+
return;
|
225 |
+
}
|
226 |
+
|
227 |
if ( version_compare( $this->getVersion(), '3.0.0', '<' ) ) {
|
228 |
$aAllOptions = apply_filters( $this->doPluginPrefix( 'aggregate_all_plugin_options' ), array() );
|
229 |
$this->setOpt( 'block_send_email_address', $aAllOptions['block_send_email_address'] );
|
230 |
}
|
231 |
+
|
232 |
+
// clean out old database tables as we've changed the naming prefix going forward.
|
233 |
+
if ( version_compare( $this->getVersion(), '3.5.0', '<' ) ) {
|
234 |
+
$aOldTables = array(
|
235 |
+
'icwp_wpsf_log',
|
236 |
+
'icwp_login_auth',
|
237 |
+
'icwp_comments_filter',
|
238 |
+
'icwp_user_management'
|
239 |
+
);
|
240 |
+
global $wpdb;
|
241 |
+
foreach( $aOldTables as $sTable ) {
|
242 |
+
$sQuery = sprintf( 'DROP TABLE IF EXISTS `%s%s`', $wpdb->prefix, $sTable ) ;
|
243 |
+
$wpdb->query( $sQuery );
|
244 |
+
}
|
245 |
+
}
|
246 |
}
|
247 |
}
|
248 |
|
src/icwp-optionshandler-privacy_protect.php
CHANGED
@@ -22,7 +22,7 @@ if ( !class_exists('ICWP_WPSF_FeatureHandler_PrivacyProtect') ):
|
|
22 |
class ICWP_WPSF_FeatureHandler_PrivacyProtect extends ICWP_WPSF_FeatureHandler_Base {
|
23 |
|
24 |
/**
|
25 |
-
* @var
|
26 |
*/
|
27 |
protected $oFeatureProcessor;
|
28 |
|
@@ -33,25 +33,23 @@ class ICWP_WPSF_FeatureHandler_PrivacyProtect extends ICWP_WPSF_FeatureHandler_B
|
|
33 |
}
|
34 |
|
35 |
/**
|
36 |
-
* @return
|
37 |
*/
|
38 |
protected function loadFeatureProcessor() {
|
39 |
if ( !isset( $this->oFeatureProcessor ) ) {
|
40 |
-
require_once(
|
41 |
-
$this->oFeatureProcessor = new
|
42 |
}
|
43 |
return $this->oFeatureProcessor;
|
44 |
}
|
45 |
|
46 |
-
public function doPrePluginOptionsSave() { }
|
47 |
-
|
48 |
/**
|
49 |
* @return array
|
50 |
*/
|
51 |
protected function getOptionsDefinitions() {
|
52 |
|
53 |
$aOptionsBase = array(
|
54 |
-
'section_title' => _wpsf__( 'Enable Privacy Protection' ),
|
55 |
'section_options' => array(
|
56 |
array(
|
57 |
'enable_privacy_protect',
|
@@ -63,7 +61,7 @@ class ICWP_WPSF_FeatureHandler_PrivacyProtect extends ICWP_WPSF_FeatureHandler_B
|
|
63 |
_wpsf__( 'Regardless of any other settings, this option will turn off the Privacy Protection feature, or enable your selected Privacy Protection options' ),
|
64 |
'<a href="http://icwp.io/3y" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
65 |
)
|
66 |
-
)
|
67 |
);
|
68 |
$aFurtherOptions = array(
|
69 |
'section_title' => _wpsf__( 'Data Filtering and Logging Options' ),
|
@@ -108,13 +106,9 @@ class ICWP_WPSF_FeatureHandler_PrivacyProtect extends ICWP_WPSF_FeatureHandler_B
|
|
108 |
return $aOptionsDefinitions;
|
109 |
}
|
110 |
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
}
|
115 |
-
$this->loadDataProcessor();
|
116 |
-
|
117 |
-
if ( ICWP_WPSF_DataProcessor::FetchPost( 'clear_log_submit' ) ) {
|
118 |
$oLoggingProcessor = $this->getLoggingProcessor();
|
119 |
$oLoggingProcessor->recreateTable();
|
120 |
return true;
|
22 |
class ICWP_WPSF_FeatureHandler_PrivacyProtect extends ICWP_WPSF_FeatureHandler_Base {
|
23 |
|
24 |
/**
|
25 |
+
* @var ICWP_WPSF_Processor_PrivacyProtect
|
26 |
*/
|
27 |
protected $oFeatureProcessor;
|
28 |
|
33 |
}
|
34 |
|
35 |
/**
|
36 |
+
* @return ICWP_WPSF_Processor_PrivacyProtect|null
|
37 |
*/
|
38 |
protected function loadFeatureProcessor() {
|
39 |
if ( !isset( $this->oFeatureProcessor ) ) {
|
40 |
+
require_once( $this->getController()->getSourceDir( sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) ) );
|
41 |
+
$this->oFeatureProcessor = new ICWP_WPSF_Processor_PrivacyProtect( $this );
|
42 |
}
|
43 |
return $this->oFeatureProcessor;
|
44 |
}
|
45 |
|
|
|
|
|
46 |
/**
|
47 |
* @return array
|
48 |
*/
|
49 |
protected function getOptionsDefinitions() {
|
50 |
|
51 |
$aOptionsBase = array(
|
52 |
+
'section_title' => sprintf( _wpsf__( 'Enable Plugin Feature: %s' ), _wpsf__('Privacy Protection') ),
|
53 |
'section_options' => array(
|
54 |
array(
|
55 |
'enable_privacy_protect',
|
61 |
_wpsf__( 'Regardless of any other settings, this option will turn off the Privacy Protection feature, or enable your selected Privacy Protection options' ),
|
62 |
'<a href="http://icwp.io/3y" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
63 |
)
|
64 |
+
)
|
65 |
);
|
66 |
$aFurtherOptions = array(
|
67 |
'section_title' => _wpsf__( 'Data Filtering and Logging Options' ),
|
106 |
return $aOptionsDefinitions;
|
107 |
}
|
108 |
|
109 |
+
protected function doExtraSubmitProcessing() {
|
110 |
+
$oDp = $this->loadDataProcessor();
|
111 |
+
if ( $oDp->FetchPost( 'clear_log_submit' ) ) {
|
|
|
|
|
|
|
|
|
112 |
$oLoggingProcessor = $this->getLoggingProcessor();
|
113 |
$oLoggingProcessor->recreateTable();
|
114 |
return true;
|
src/icwp-optionshandler-user_management.php
CHANGED
@@ -20,6 +20,8 @@ require_once( dirname(__FILE__).'/icwp-optionshandler-base.php' );
|
|
20 |
if ( !class_exists('ICWP_WPSF_FeatureHandler_UserManagement') ):
|
21 |
|
22 |
class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_Base {
|
|
|
|
|
23 |
|
24 |
/**
|
25 |
* @var ICWP_WPSF_Processor_UserManagement
|
@@ -37,12 +39,29 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
|
|
37 |
*/
|
38 |
protected function loadFeatureProcessor() {
|
39 |
if ( !isset( $this->oFeatureProcessor ) ) {
|
40 |
-
require_once(
|
41 |
$this->oFeatureProcessor = new ICWP_WPSF_Processor_UserManagement( $this );
|
42 |
}
|
43 |
return $this->oFeatureProcessor;
|
44 |
}
|
45 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
46 |
/**
|
47 |
*/
|
48 |
public function displayFeatureConfigPage( ) {
|
@@ -59,74 +78,137 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
|
|
59 |
$aData = array_merge( $this->getBaseDisplayData(), $aData );
|
60 |
$this->display( $aData );
|
61 |
}
|
62 |
-
|
63 |
-
public function doPrePluginOptionsSave() { }
|
64 |
|
65 |
/**
|
|
|
66 |
* @return array
|
|
|
67 |
*/
|
68 |
-
protected function
|
69 |
-
$aOptionsBase = array(
|
70 |
-
'section_title' => sprintf( _wpsf__( 'Enable Plugin Feature: %s' ), _wpsf__('User Accounts Management') ),
|
71 |
-
'section_options' => array(
|
72 |
-
array(
|
73 |
-
'enable_user_management',
|
74 |
-
'',
|
75 |
-
'N',
|
76 |
-
'checkbox',
|
77 |
-
_wpsf__( 'Enable User Accounts Management' ),
|
78 |
-
_wpsf__( 'Enable (or Disable) The User Accounts Management Feature' ),
|
79 |
-
sprintf( _wpsf__( 'Checking/Un-Checking this option will completely turn on/off the whole %s feature.' ), _wpsf__('User Accounts Management') ),
|
80 |
-
)
|
81 |
-
),
|
82 |
-
);
|
83 |
|
84 |
-
$
|
85 |
-
|
86 |
-
'section_options' => array(
|
87 |
-
array(
|
88 |
-
'session_timeout_interval',
|
89 |
-
'',
|
90 |
-
'2',
|
91 |
-
'integer',
|
92 |
-
_wpsf__( 'Session Timeout' ),
|
93 |
-
_wpsf__( 'Specify How Many Days After Login To Automatically Force Re-Login' ),
|
94 |
-
sprintf( _wpsf__( 'WordPress default is 2 days, or 14 days if you check the "Remember Me" box.' ), '<span class="code">'.$this->getVisitorIpAddress( false ).'</span>' )
|
95 |
-
),
|
96 |
-
array(
|
97 |
-
'session_idle_timeout_interval',
|
98 |
-
'',
|
99 |
-
'0',
|
100 |
-
'integer',
|
101 |
-
_wpsf__( 'Idle Timeout' ),
|
102 |
-
_wpsf__( 'Specify How Many Hours After Inactivity To Automatically Logout User' ),
|
103 |
-
_wpsf__( 'If the user is inactive for the number of hours specified, they will be forcefully logged out next time they return.' )
|
104 |
-
),
|
105 |
-
array(
|
106 |
-
'session_lock_location',
|
107 |
-
'',
|
108 |
-
'N',
|
109 |
-
'checkbox',
|
110 |
-
_wpsf__( 'Lock To Location' ),
|
111 |
-
_wpsf__( 'Locks A User Session To IP address' ),
|
112 |
-
_wpsf__( 'Restricts login to any account to a location as determined by IP address.' )
|
113 |
-
)
|
114 |
-
)
|
115 |
-
);
|
116 |
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
122 |
}
|
123 |
|
124 |
/**
|
|
|
125 |
* @return array
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
*/
|
127 |
-
|
128 |
-
$
|
129 |
-
return $aNonUiOptions;
|
130 |
}
|
131 |
}
|
132 |
|
20 |
if ( !class_exists('ICWP_WPSF_FeatureHandler_UserManagement') ):
|
21 |
|
22 |
class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_Base {
|
23 |
+
|
24 |
+
const UserManagementTableName = 'user_management';
|
25 |
|
26 |
/**
|
27 |
* @var ICWP_WPSF_Processor_UserManagement
|
39 |
*/
|
40 |
protected function loadFeatureProcessor() {
|
41 |
if ( !isset( $this->oFeatureProcessor ) ) {
|
42 |
+
require_once( $this->getController()->getSourceDir( sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) ) );
|
43 |
$this->oFeatureProcessor = new ICWP_WPSF_Processor_UserManagement( $this );
|
44 |
}
|
45 |
return $this->oFeatureProcessor;
|
46 |
}
|
47 |
|
48 |
+
/**
|
49 |
+
*/
|
50 |
+
public function doPrePluginOptionsSave() {
|
51 |
+
|
52 |
+
if ( !is_email( $this->getOpt( 'enable_admin_login_email_notification' ) ) ) {
|
53 |
+
$this->getOptionsVo()->resetOptToDefault( 'enable_admin_login_email_notification' );
|
54 |
+
}
|
55 |
+
|
56 |
+
if ( $this->getOpt( 'session_username_concurrent_limit' ) < 0 ) {
|
57 |
+
$this->getOptionsVo()->resetOptToDefault( 'session_username_concurrent_limit' );
|
58 |
+
}
|
59 |
+
|
60 |
+
if ( $this->getOpt( 'session_timeout_interval' ) < 1 ) {
|
61 |
+
$this->getOptionsVo()->resetOptToDefault( 'session_timeout_interval' );
|
62 |
+
}
|
63 |
+
}
|
64 |
+
|
65 |
/**
|
66 |
*/
|
67 |
public function displayFeatureConfigPage( ) {
|
78 |
$aData = array_merge( $this->getBaseDisplayData(), $aData );
|
79 |
$this->display( $aData );
|
80 |
}
|
|
|
|
|
81 |
|
82 |
/**
|
83 |
+
* @param array $aOptionsParams
|
84 |
* @return array
|
85 |
+
* @throws Exception
|
86 |
*/
|
87 |
+
protected function loadStrings_SectionTitles( $aOptionsParams ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
|
89 |
+
$sSectionSlug = $aOptionsParams['section_slug'];
|
90 |
+
switch( $aOptionsParams['section_slug'] ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
|
92 |
+
case 'section_enable_plugin_feature_user_accounts_management' :
|
93 |
+
$sTitle = sprintf( _wpsf__( 'Enable Plugin Feature: %s' ), $this->getMainFeatureName() );
|
94 |
+
break;
|
95 |
+
|
96 |
+
case 'section_bypass_user_accounts_management' :
|
97 |
+
$sTitle = _wpsf__('By-Pass User Accounts Management');
|
98 |
+
break;
|
99 |
+
|
100 |
+
case 'section_admin_login_notification' :
|
101 |
+
$sTitle = _wpsf__('Admin Login Notification');
|
102 |
+
break;
|
103 |
+
|
104 |
+
case 'section_user_session_management' :
|
105 |
+
$sTitle = _wpsf__('User Session Management');
|
106 |
+
break;
|
107 |
+
|
108 |
+
case 'section_automatic_update_email_notifications' :
|
109 |
+
$sTitle = _wpsf__('Automatic Update Email Notifications');
|
110 |
+
break;
|
111 |
+
|
112 |
+
default:
|
113 |
+
throw new Exception( sprintf( 'A section slug was defined but with no associated strings. Slug: "%s".', $sSectionSlug ) );
|
114 |
+
}
|
115 |
+
$aOptionsParams['section_title'] = $sTitle;
|
116 |
+
return $aOptionsParams;
|
117 |
}
|
118 |
|
119 |
/**
|
120 |
+
* @param array $aOptionsParams
|
121 |
* @return array
|
122 |
+
* @throws Exception
|
123 |
+
*/
|
124 |
+
protected function loadStrings_Options( $aOptionsParams ) {
|
125 |
+
|
126 |
+
$sKey = $aOptionsParams['key'];
|
127 |
+
switch( $sKey ) {
|
128 |
+
|
129 |
+
case 'enable_user_management' :
|
130 |
+
$sName = sprintf( _wpsf__( 'Enable %s' ), $this->getMainFeatureName() );
|
131 |
+
$sSummary = sprintf( _wpsf__( 'Enable (or Disable) The %s Feature' ), $this->getMainFeatureName() );
|
132 |
+
$sDescription = sprintf( _wpsf__( 'Checking/Un-Checking this option will completely turn on/off the whole %s feature.' ), $this->getMainFeatureName() );
|
133 |
+
break;
|
134 |
+
|
135 |
+
case 'enable_xmlrpc_compatibility' :
|
136 |
+
$sName = _wpsf__( 'XML-RPC Compatibility' );
|
137 |
+
$sSummary = _wpsf__( 'Allow Login Through XML-RPC To By-Pass Accounts Management Rules' );
|
138 |
+
$sDescription = _wpsf__( 'Enable this if you need XML-RPC functionality e.g. if you use the WordPress iPhone/Android App.' );
|
139 |
+
break;
|
140 |
+
|
141 |
+
case 'enable_admin_login_email_notification' :
|
142 |
+
$sName = _wpsf__( 'Admin Login Notification Email' );
|
143 |
+
$sSummary = _wpsf__( 'Send An Notification Email When Administrator Logs In' );
|
144 |
+
$sDescription = _wpsf__( 'If you would like to be notified every time an administrator user logs into this WordPress site, enter a notification email address.' )
|
145 |
+
.'<br />'._wpsf__( 'No email address - No Notification.' );
|
146 |
+
break;
|
147 |
+
|
148 |
+
case 'session_timeout_interval' :
|
149 |
+
$sName = _wpsf__( 'Session Timeout' );
|
150 |
+
$sSummary = _wpsf__( 'Specify How Many Days After Login To Automatically Force Re-Login' );
|
151 |
+
$sDescription = _wpsf__( 'WordPress default is 2 days, or 14 days if you check the "Remember Me" box.' )
|
152 |
+
.'<br />'. sprintf( _wpsf__( 'This cannot be less than %s.' ), '"<strong>1</strong>"' )
|
153 |
+
.'<br />'. sprintf( _wpsf__( 'Default: %s.' ), '"<strong>'.$this->getOptionsVo()->getOptDefault('session_timeout_interval').'</strong>"' );
|
154 |
+
break;
|
155 |
+
|
156 |
+
case 'session_idle_timeout_interval' :
|
157 |
+
$sName = _wpsf__( 'Idle Timeout' );
|
158 |
+
$sSummary = _wpsf__( 'Specify How Many Hours After Inactivity To Automatically Logout User' );
|
159 |
+
$sDescription = _wpsf__( 'If the user is inactive for the number of hours specified, they will be forcefully logged out next time they return.' )
|
160 |
+
.'<br />'. sprintf( _wpsf__( 'Set to %s to turn off this option.' ), '"<strong>0</strong>"' );
|
161 |
+
break;
|
162 |
+
|
163 |
+
case 'session_lock_location' :
|
164 |
+
$sName = _wpsf__( 'Lock To Location' );
|
165 |
+
$sSummary = _wpsf__( 'Locks A User Session To IP address' );
|
166 |
+
$sDescription = _wpsf__( 'When selected, a session is restricted to the same IP address as when the user logged in.' )
|
167 |
+
.' '._wpsf__( "If a logged-in user's IP address changes, the session will be invalidated and they'll be forced to re-login to WordPress." );
|
168 |
+
break;
|
169 |
+
|
170 |
+
case 'session_username_concurrent_limit' :
|
171 |
+
$sName = _wpsf__( 'Max Simultaneous Sessions' );
|
172 |
+
$sSummary = _wpsf__( 'Limit Simultaneous Sessions For The Same Username' );
|
173 |
+
$sDescription = _wpsf__( 'The number provided here is the maximum number of simultaneous, distinct, sessions allowed for any given username.' )
|
174 |
+
.'<br />'._wpsf__( "Zero (0) will allow unlimited simultaneous sessions." );
|
175 |
+
break;
|
176 |
+
|
177 |
+
case 'session_check_admin_area_only' :
|
178 |
+
$sName = _wpsf__( 'Check Admin Area Only' );
|
179 |
+
$sSummary = _wpsf__( 'Perform Session Checking For Logged In Users Only In Admin Area' );
|
180 |
+
$sDescription = _wpsf__( 'When selected, session timeouts will only be checked on visits to the WordPress admin area.' );
|
181 |
+
break;
|
182 |
+
|
183 |
+
case 'session_auto_forward_to_admin_area' :
|
184 |
+
$sName = _wpsf__( 'Auto Redirect To Admin' );
|
185 |
+
$sSummary = _wpsf__( 'Automatically Redirect To WP Admin When Valid Session Detected' );
|
186 |
+
$sDescription = _wpsf__( 'When selected, users will be automatically forwarded to the WordPress admin screen when they visit wp-login.php.' )
|
187 |
+
.'<br />'. _wpsf__( 'It removes the extra step to get to the admin screen for already-authenticated users.' );
|
188 |
+
break;
|
189 |
+
|
190 |
+
default:
|
191 |
+
throw new Exception( sprintf( 'An option has been defined but without strings assigned to it. Option key: "%s".', $sKey ) );
|
192 |
+
}
|
193 |
+
|
194 |
+
$aOptionsParams['name'] = $sName;
|
195 |
+
$aOptionsParams['summary'] = $sSummary;
|
196 |
+
$aOptionsParams['description'] = $sDescription;
|
197 |
+
return $aOptionsParams;
|
198 |
+
}
|
199 |
+
|
200 |
+
/**
|
201 |
+
* @return string
|
202 |
+
*/
|
203 |
+
public function getUserSessionsTableName() {
|
204 |
+
return $this->doPluginPrefix( $this->getOpt( 'user_sessions_table_name' ), '_' );
|
205 |
+
}
|
206 |
+
|
207 |
+
/**
|
208 |
+
* @return string
|
209 |
*/
|
210 |
+
public function getUserSessionCookieName() {
|
211 |
+
return $this->getOpt( 'user_session_cookie_name' );
|
|
|
212 |
}
|
213 |
}
|
214 |
|
src/{icwp-processor-adminaccessrestriction.php → icwp-processor-admin_access_restriction.php}
RENAMED
@@ -15,11 +15,16 @@
|
|
15 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
*/
|
17 |
|
18 |
-
require_once( dirname(__FILE__).'/icwp-base
|
19 |
|
20 |
if ( !class_exists('ICWP_WPSF_Processor_AdminAccessRestriction') ):
|
21 |
|
22 |
-
class ICWP_WPSF_Processor_AdminAccessRestriction extends
|
|
|
|
|
|
|
|
|
|
|
23 |
|
24 |
/**
|
25 |
* @var string
|
@@ -34,8 +39,8 @@ class ICWP_WPSF_Processor_AdminAccessRestriction extends ICWP_WPSF_BaseProcessor
|
|
34 |
}
|
35 |
|
36 |
public function run() {
|
37 |
-
|
38 |
-
if ( ! $this->oFeatureOptions->getIsUpgrading() ) {
|
39 |
$this->sOptionRegexPattern = '/^'. $this->oFeatureOptions->getOptionStoragePrefix() . '.*_options$/';
|
40 |
add_filter( 'pre_update_option', array( $this, 'blockOptionsSaves' ), 1, 3 );
|
41 |
}
|
15 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
*/
|
17 |
|
18 |
+
require_once( dirname(__FILE__).'/icwp-processor-base.php' );
|
19 |
|
20 |
if ( !class_exists('ICWP_WPSF_Processor_AdminAccessRestriction') ):
|
21 |
|
22 |
+
class ICWP_WPSF_Processor_AdminAccessRestriction extends ICWP_WPSF_Processor_Base {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var ICWP_WPSF_FeatureHandler_AdminAccessRestriction
|
26 |
+
*/
|
27 |
+
protected $oFeatureOptions;
|
28 |
|
29 |
/**
|
30 |
* @var string
|
39 |
}
|
40 |
|
41 |
public function run() {
|
42 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
43 |
+
if ( ! $this->oFeatureOptions->getIsUpgrading() && ! $oWp->getIsLoginRequest() ) {
|
44 |
$this->sOptionRegexPattern = '/^'. $this->oFeatureOptions->getOptionStoragePrefix() . '.*_options$/';
|
45 |
add_filter( 'pre_update_option', array( $this, 'blockOptionsSaves' ), 1, 3 );
|
46 |
}
|
src/icwp-processor-audit_trail.php
ADDED
@@ -0,0 +1,225 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
+
* All rights reserved.
|
5 |
+
*
|
6 |
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
7 |
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
8 |
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
9 |
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
10 |
+
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
11 |
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
12 |
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
13 |
+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
14 |
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
15 |
+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
+
*/
|
17 |
+
|
18 |
+
require_once( dirname(__FILE__).'/icwp-processor-basedb.php' );
|
19 |
+
|
20 |
+
if ( !class_exists('ICWP_WPSF_Processor_AuditTrail_V1') ):
|
21 |
+
|
22 |
+
class ICWP_WPSF_Processor_AuditTrail_V1 extends ICWP_WPSF_BaseDbProcessor {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var ICWP_WPSF_FeatureHandler_AuditTrail
|
26 |
+
*/
|
27 |
+
protected $oFeatureOptions;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @param ICWP_WPSF_FeatureHandler_AuditTrail $oFeatureOptions
|
31 |
+
*/
|
32 |
+
public function __construct( ICWP_WPSF_FeatureHandler_AuditTrail $oFeatureOptions ) {
|
33 |
+
parent::__construct( $oFeatureOptions, $oFeatureOptions->getAuditTrailTableName() );
|
34 |
+
add_action( $this->oFeatureOptions->doPluginPrefix( 'plugin_shutdown' ), array( $this, 'commitAuditTrial' ) );
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
*/
|
39 |
+
public function run() {
|
40 |
+
|
41 |
+
if ( $this->getIsOption( 'enable_audit_context_users', 'Y' ) ) {
|
42 |
+
require_once( 'icwp-processor-audit_trail_users.php' );
|
43 |
+
$oUsers = new ICWP_WPSF_Processor_AuditTrail_Users( $this->oFeatureOptions );
|
44 |
+
$oUsers->run();
|
45 |
+
}
|
46 |
+
|
47 |
+
if ( $this->getIsOption( 'enable_audit_context_plugins', 'Y' ) ) {
|
48 |
+
require_once( 'icwp-processor-audit_trail_plugins.php' );
|
49 |
+
$oUsers = new ICWP_WPSF_Processor_AuditTrail_Plugins( $this->oFeatureOptions );
|
50 |
+
$oUsers->run();
|
51 |
+
}
|
52 |
+
|
53 |
+
if ( $this->getIsOption( 'enable_audit_context_themes', 'Y' ) ) {
|
54 |
+
require_once( 'icwp-processor-audit_trail_themes.php' );
|
55 |
+
$oUsers = new ICWP_WPSF_Processor_AuditTrail_Themes( $this->oFeatureOptions );
|
56 |
+
$oUsers->run();
|
57 |
+
}
|
58 |
+
|
59 |
+
if ( $this->getIsOption( 'enable_audit_context_wordpress', 'Y' ) ) {
|
60 |
+
require_once( 'icwp-processor-audit_trail_wordpress.php' );
|
61 |
+
$oUsers = new ICWP_WPSF_Processor_AuditTrail_Wordpress( $this->oFeatureOptions );
|
62 |
+
$oUsers->run();
|
63 |
+
}
|
64 |
+
|
65 |
+
if ( $this->getIsOption( 'enable_audit_context_posts', 'Y' ) ) {
|
66 |
+
require_once( 'icwp-processor-audit_trail_posts.php' );
|
67 |
+
$oUsers = new ICWP_WPSF_Processor_AuditTrail_Posts( $this->oFeatureOptions );
|
68 |
+
$oUsers->run();
|
69 |
+
}
|
70 |
+
// if ( $this->getIsOption( 'enable_audit_context_wpsf', 'Y' ) ) {
|
71 |
+
// require_once( 'icwp-processor-audit_trail_wpsf.php' );
|
72 |
+
// $oUsers = new ICWP_WPSF_Processor_AuditTrail_Wpsf( $this->oFeatureOptions );
|
73 |
+
// $oUsers->run();
|
74 |
+
// }
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* @return array|bool
|
79 |
+
*/
|
80 |
+
public function getAllAuditEntries() {
|
81 |
+
return array_reverse( $this->selectAllFromTable() );
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
*/
|
86 |
+
public function commitAuditTrial() {
|
87 |
+
$aEntries = $this->getAuditTrailEntries()->getAuditTrailEntries( true );
|
88 |
+
if ( empty( $aEntries ) || !is_array( $aEntries ) ) {
|
89 |
+
return;
|
90 |
+
}
|
91 |
+
|
92 |
+
foreach( $aEntries as $aEntry ) {
|
93 |
+
$this->insertIntoTable( $aEntry );
|
94 |
+
}
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* @return ICWP_WPSF_AuditTrail_Entries
|
99 |
+
*/
|
100 |
+
protected function getAuditTrailEntries() {
|
101 |
+
return ICWP_WPSF_AuditTrail_Entries::GetInstance();
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* @return string
|
106 |
+
*/
|
107 |
+
protected function getCreateTableSql() {
|
108 |
+
$sSqlTables = "
|
109 |
+
CREATE TABLE IF NOT EXISTS `%s` (
|
110 |
+
`id` INT(11) NOT NULL AUTO_INCREMENT,
|
111 |
+
`wp_username` VARCHAR(255) NOT NULL DEFAULT 'none',
|
112 |
+
`context` VARCHAR(25) NOT NULL DEFAULT 'none',
|
113 |
+
`event` VARCHAR(25) NOT NULL DEFAULT 'none',
|
114 |
+
`category` INT(3) NOT NULL DEFAULT '0',
|
115 |
+
`message` TEXT,
|
116 |
+
`created_at` INT(15) NOT NULL DEFAULT '0',
|
117 |
+
`deleted_at` INT(15) NOT NULL DEFAULT '0',
|
118 |
+
PRIMARY KEY (`id`)
|
119 |
+
) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
|
120 |
+
|
121 |
+
return sprintf( $sSqlTables, $this->getTableName() );
|
122 |
+
}
|
123 |
+
}
|
124 |
+
|
125 |
+
endif;
|
126 |
+
|
127 |
+
if ( !class_exists('ICWP_WPSF_Processor_AuditTrail') ):
|
128 |
+
class ICWP_WPSF_Processor_AuditTrail extends ICWP_WPSF_Processor_AuditTrail_V1 { }
|
129 |
+
endif;
|
130 |
+
|
131 |
+
class ICWP_WPSF_AuditTrail_Entries {
|
132 |
+
|
133 |
+
/**
|
134 |
+
* @var ICWP_WPSF_AuditTrail_Entries
|
135 |
+
*/
|
136 |
+
protected static $oInstance = NULL;
|
137 |
+
|
138 |
+
/**
|
139 |
+
* @return ICWP_WPSF_AuditTrail_Entries
|
140 |
+
*/
|
141 |
+
public static function GetInstance() {
|
142 |
+
if ( is_null( self::$oInstance ) ) {
|
143 |
+
self::$oInstance = new self();
|
144 |
+
}
|
145 |
+
return self::$oInstance;
|
146 |
+
}
|
147 |
+
|
148 |
+
/**
|
149 |
+
* @var array
|
150 |
+
*/
|
151 |
+
protected $aEntries;
|
152 |
+
|
153 |
+
public function add( $sContext, $sEvent, $nCategory, $sMessage = '' ) {
|
154 |
+
$oDp = $this->loadDataProcessor();
|
155 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
156 |
+
$oCurrentUser = $oWp->getCurrentWpUser();
|
157 |
+
$aNewEntry = array(
|
158 |
+
'created_at' => $oDp->GetRequestTime(),
|
159 |
+
'wp_username' => empty( $oCurrentUser ) ? 'unknown' : $oCurrentUser->get( 'user_login' ),
|
160 |
+
'context' => $sContext,
|
161 |
+
'event' => $sEvent,
|
162 |
+
'category' => $nCategory,
|
163 |
+
'message' => $sMessage,
|
164 |
+
);
|
165 |
+
$aEntries = $this->getAuditTrailEntries();
|
166 |
+
$aEntries[] = $aNewEntry;
|
167 |
+
$this->aEntries = $aEntries;
|
168 |
+
}
|
169 |
+
|
170 |
+
/**
|
171 |
+
* For use inside the object
|
172 |
+
*
|
173 |
+
* @return array
|
174 |
+
*/
|
175 |
+
protected function & getEntries() {
|
176 |
+
if ( !isset( $this->aEntries ) ) {
|
177 |
+
$this->aEntries = array();
|
178 |
+
}
|
179 |
+
return $this->aEntries;
|
180 |
+
}
|
181 |
+
|
182 |
+
/**
|
183 |
+
* @param boolean $fFlush
|
184 |
+
* @return array
|
185 |
+
*/
|
186 |
+
public function getAuditTrailEntries( $fFlush = false ) {
|
187 |
+
if ( !isset( $this->aEntries ) ) {
|
188 |
+
$this->aEntries = array();
|
189 |
+
}
|
190 |
+
$aEntries = $this->aEntries;
|
191 |
+
if ( $fFlush ) {
|
192 |
+
$this->aEntries = array();
|
193 |
+
}
|
194 |
+
return $aEntries;
|
195 |
+
}
|
196 |
+
|
197 |
+
|
198 |
+
/**
|
199 |
+
* @return ICWP_WPSF_DataProcessor
|
200 |
+
*/
|
201 |
+
public function loadDataProcessor() {
|
202 |
+
if ( !class_exists('ICWP_WPSF_DataProcessor') ) {
|
203 |
+
require_once( dirname(__FILE__).'/icwp-data-processor.php' );
|
204 |
+
}
|
205 |
+
return ICWP_WPSF_DataProcessor::GetInstance();
|
206 |
+
}
|
207 |
+
|
208 |
+
/**
|
209 |
+
* @return ICWP_WPSF_WpFilesystem
|
210 |
+
*/
|
211 |
+
public function loadFileSystemProcessor() {
|
212 |
+
if ( !class_exists('ICWP_WPSF_WpFilesystem') ) {
|
213 |
+
require_once( dirname(__FILE__) . '/icwp-wpfilesystem.php' );
|
214 |
+
}
|
215 |
+
return ICWP_WPSF_WpFilesystem::GetInstance();
|
216 |
+
}
|
217 |
+
|
218 |
+
/**
|
219 |
+
* @return ICWP_WPSF_WpFunctions
|
220 |
+
*/
|
221 |
+
public function loadWpFunctionsProcessor() {
|
222 |
+
require_once( dirname(__FILE__) . '/icwp-wpfunctions.php' );
|
223 |
+
return ICWP_WPSF_WpFunctions::GetInstance();
|
224 |
+
}
|
225 |
+
}
|
src/icwp-processor-audit_trail_plugins.php
ADDED
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
+
* All rights reserved.
|
5 |
+
*
|
6 |
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
7 |
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
8 |
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
9 |
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
10 |
+
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
11 |
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
12 |
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
13 |
+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
14 |
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
15 |
+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
+
*/
|
17 |
+
|
18 |
+
require_once( dirname(__FILE__).'/icwp-processor-base.php' );
|
19 |
+
|
20 |
+
if ( !class_exists('ICWP_WPSF_Processor_AuditTrail_Plugins') ):
|
21 |
+
|
22 |
+
class ICWP_WPSF_Processor_AuditTrail_Plugins extends ICWP_WPSF_Processor_Base {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var ICWP_WPSF_FeatureHandler_AuditTrail
|
26 |
+
*/
|
27 |
+
protected $oFeatureOptions;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @param ICWP_WPSF_FeatureHandler_AuditTrail $oFeatureOptions
|
31 |
+
*/
|
32 |
+
public function __construct( ICWP_WPSF_FeatureHandler_AuditTrail $oFeatureOptions ) {
|
33 |
+
parent::__construct( $oFeatureOptions );
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
*/
|
38 |
+
public function run() {
|
39 |
+
|
40 |
+
if ( $this->getIsOption( 'enable_audit_context_plugins', 'Y' ) ) {
|
41 |
+
add_action( 'deactivated_plugin', array( $this, 'auditDeactivatedPlugin' ) );
|
42 |
+
add_action( 'activated_plugin', array( $this, 'auditActivatedPlugin' ) );
|
43 |
+
}
|
44 |
+
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* @param string $sPlugin
|
49 |
+
* @return bool
|
50 |
+
*/
|
51 |
+
public function auditActivatedPlugin( $sPlugin ) {
|
52 |
+
|
53 |
+
if ( empty( $sPlugin ) ) {
|
54 |
+
return false;
|
55 |
+
}
|
56 |
+
|
57 |
+
$oAuditTrail = $this->getAuditTrailEntries();
|
58 |
+
$oAuditTrail->add(
|
59 |
+
'plugins',
|
60 |
+
'plugin_activated',
|
61 |
+
1,
|
62 |
+
sprintf( _wpsf__( 'Plugin "%s" was activated.' ), $sPlugin )
|
63 |
+
);
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* @param string $sPlugin
|
68 |
+
* @return bool
|
69 |
+
*/
|
70 |
+
public function auditDeactivatedPlugin( $sPlugin ) {
|
71 |
+
|
72 |
+
if ( empty( $sPlugin ) ) {
|
73 |
+
return false;
|
74 |
+
}
|
75 |
+
|
76 |
+
$oAuditTrail = $this->getAuditTrailEntries();
|
77 |
+
$oAuditTrail->add(
|
78 |
+
'plugins',
|
79 |
+
'plugin_deactivated',
|
80 |
+
1,
|
81 |
+
sprintf( _wpsf__( 'Plugin "%s" was deactivated.' ), $sPlugin )
|
82 |
+
);
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* @return ICWP_WPSF_AuditTrail_Entries
|
87 |
+
*/
|
88 |
+
protected function getAuditTrailEntries() {
|
89 |
+
return ICWP_WPSF_AuditTrail_Entries::GetInstance();
|
90 |
+
}
|
91 |
+
}
|
92 |
+
|
93 |
+
endif;
|
src/icwp-processor-audit_trail_posts.php
ADDED
@@ -0,0 +1,136 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
+
* All rights reserved.
|
5 |
+
*
|
6 |
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
7 |
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
8 |
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
9 |
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
10 |
+
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
11 |
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
12 |
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
13 |
+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
14 |
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
15 |
+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
+
*/
|
17 |
+
|
18 |
+
require_once( dirname(__FILE__).'/icwp-processor-base.php' );
|
19 |
+
|
20 |
+
if ( !class_exists('ICWP_WPSF_Processor_AuditTrail_Posts') ):
|
21 |
+
|
22 |
+
class ICWP_WPSF_Processor_AuditTrail_Posts extends ICWP_WPSF_Processor_Base {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var ICWP_WPSF_FeatureHandler_AuditTrail
|
26 |
+
*/
|
27 |
+
protected $oFeatureOptions;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @param ICWP_WPSF_FeatureHandler_AuditTrail $oFeatureOptions
|
31 |
+
*/
|
32 |
+
public function __construct( ICWP_WPSF_FeatureHandler_AuditTrail $oFeatureOptions ) {
|
33 |
+
parent::__construct( $oFeatureOptions );
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
*/
|
38 |
+
public function run() {
|
39 |
+
if ( $this->getIsOption( 'enable_audit_context_wordpress', 'Y' ) ) {
|
40 |
+
add_action( 'deleted_post', array( $this, 'auditDeletedPost' ) );
|
41 |
+
add_action( 'transition_post_status', array( $this, 'auditPostStatus' ), 30 , 3 );
|
42 |
+
}
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* @param string $nPostId
|
47 |
+
* @return bool
|
48 |
+
*/
|
49 |
+
public function auditDeletedPost( $nPostId ) {
|
50 |
+
|
51 |
+
$oPost = get_post( $nPostId );
|
52 |
+
if ( ! ( $oPost instanceof WP_Post ) || ( $this->getIsIgnoredPostType( $oPost ) ) ) {
|
53 |
+
return;
|
54 |
+
}
|
55 |
+
|
56 |
+
$oAuditTrail = $this->getAuditTrailEntries();
|
57 |
+
$oAuditTrail->add(
|
58 |
+
'posts',
|
59 |
+
'post_deleted',
|
60 |
+
2,
|
61 |
+
sprintf( _wpsf__( 'WordPress Post entitled "%s" was permanently deleted from trash.' ), $oPost->post_title )
|
62 |
+
);
|
63 |
+
|
64 |
+
}
|
65 |
+
|
66 |
+
|
67 |
+
/**
|
68 |
+
* @param string $sNewStatus
|
69 |
+
* @param string $sOldStatus
|
70 |
+
* @param WP_Post $oPost
|
71 |
+
* @return bool
|
72 |
+
*/
|
73 |
+
public function auditPostStatus( $sNewStatus, $sOldStatus, $oPost ) {
|
74 |
+
|
75 |
+
if ( ! ( $oPost instanceof WP_Post ) || ( $this->getIsIgnoredPostType( $oPost ) ) || in_array( $sNewStatus, array( 'auto-draft', 'inherit' ) ) ) {
|
76 |
+
return;
|
77 |
+
}
|
78 |
+
|
79 |
+
if ( $sNewStatus == 'trash' ) {
|
80 |
+
$sEvent = 'post_trashed';
|
81 |
+
$sHumanEvent = _wpsf__( 'moved to trash' );
|
82 |
+
}
|
83 |
+
else if ( $sOldStatus == 'trash' && $sNewStatus != 'trash' ) {
|
84 |
+
$sEvent = 'post_recovered';
|
85 |
+
$sHumanEvent = _wpsf__( 'recovered from trash' );
|
86 |
+
}
|
87 |
+
else if ( in_array( $sNewStatus, array( 'publish', 'private' ) ) ) {
|
88 |
+
$sEvent = 'post_published';
|
89 |
+
$sHumanEvent = _wpsf__( 'published' );
|
90 |
+
}
|
91 |
+
else if ( in_array( $sOldStatus, array( 'publish', 'private' ) ) && $sNewStatus == 'draft' ) {
|
92 |
+
$sEvent = 'post_unpublished';
|
93 |
+
$sHumanEvent = _wpsf__( 'unpublished' );
|
94 |
+
}
|
95 |
+
else {
|
96 |
+
$sEvent = 'post_updated';
|
97 |
+
$sHumanEvent = _wpsf__( 'updated' );
|
98 |
+
}
|
99 |
+
|
100 |
+
$oAuditTrail = $this->getAuditTrailEntries();
|
101 |
+
$oAuditTrail->add(
|
102 |
+
'posts',
|
103 |
+
$sEvent,
|
104 |
+
1,
|
105 |
+
sprintf( _wpsf__( 'Post entitled "%s" was %s.' ), $oPost->post_title, $sHumanEvent )
|
106 |
+
);
|
107 |
+
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* @param WP_Post $oPost
|
112 |
+
* @return bool
|
113 |
+
*/
|
114 |
+
protected function getIsIgnoredPostType( $oPost ) {
|
115 |
+
return
|
116 |
+
( $oPost->post_status == 'auto-draft' )
|
117 |
+
||
|
118 |
+
in_array(
|
119 |
+
$oPost->post_type,
|
120 |
+
array(
|
121 |
+
'revision',
|
122 |
+
'nav_menu_item',
|
123 |
+
'attachment'
|
124 |
+
)
|
125 |
+
);
|
126 |
+
}
|
127 |
+
|
128 |
+
/**
|
129 |
+
* @return ICWP_WPSF_AuditTrail_Entries
|
130 |
+
*/
|
131 |
+
protected function getAuditTrailEntries() {
|
132 |
+
return ICWP_WPSF_AuditTrail_Entries::GetInstance();
|
133 |
+
}
|
134 |
+
}
|
135 |
+
|
136 |
+
endif;
|
src/icwp-processor-audit_trail_themes.php
ADDED
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
+
* All rights reserved.
|
5 |
+
*
|
6 |
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
7 |
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
8 |
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
9 |
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
10 |
+
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
11 |
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
12 |
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
13 |
+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
14 |
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
15 |
+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
+
*/
|
17 |
+
|
18 |
+
require_once( dirname(__FILE__).'/icwp-processor-base.php' );
|
19 |
+
|
20 |
+
if ( !class_exists('ICWP_WPSF_Processor_AuditTrail_Themes') ):
|
21 |
+
|
22 |
+
class ICWP_WPSF_Processor_AuditTrail_Themes extends ICWP_WPSF_Processor_Base {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var ICWP_WPSF_FeatureHandler_AuditTrail
|
26 |
+
*/
|
27 |
+
protected $oFeatureOptions;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @param ICWP_WPSF_FeatureHandler_AuditTrail $oFeatureOptions
|
31 |
+
*/
|
32 |
+
public function __construct( ICWP_WPSF_FeatureHandler_AuditTrail $oFeatureOptions ) {
|
33 |
+
parent::__construct( $oFeatureOptions );
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
*/
|
38 |
+
public function run() {
|
39 |
+
|
40 |
+
if ( $this->getIsOption( 'enable_audit_context_themes', 'Y' ) ) {
|
41 |
+
add_action( 'switch_theme', array( $this, 'auditSwitchTheme' ) );
|
42 |
+
// add_action( 'upgrader_process_complete', array( $this, 'auditInstalledTheme' ) );
|
43 |
+
}
|
44 |
+
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* @param string $sThemeName
|
49 |
+
* @return bool
|
50 |
+
*/
|
51 |
+
public function auditSwitchTheme( $sThemeName ) {
|
52 |
+
|
53 |
+
if ( empty( $sThemeName ) ) {
|
54 |
+
return false;
|
55 |
+
}
|
56 |
+
|
57 |
+
$oAuditTrail = $this->getAuditTrailEntries();
|
58 |
+
$oAuditTrail->add(
|
59 |
+
'themes',
|
60 |
+
'theme_activated',
|
61 |
+
1,
|
62 |
+
sprintf( _wpsf__( 'Theme "%s" was activated.' ), $sThemeName )
|
63 |
+
);
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* @return ICWP_WPSF_AuditTrail_Entries
|
68 |
+
*/
|
69 |
+
protected function getAuditTrailEntries() {
|
70 |
+
return ICWP_WPSF_AuditTrail_Entries::GetInstance();
|
71 |
+
}
|
72 |
+
}
|
73 |
+
|
74 |
+
endif;
|
src/icwp-processor-audit_trail_users.php
ADDED
@@ -0,0 +1,160 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
+
* All rights reserved.
|
5 |
+
*
|
6 |
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
7 |
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
8 |
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
9 |
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
10 |
+
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
11 |
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
12 |
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
13 |
+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
14 |
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
15 |
+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
+
*/
|
17 |
+
|
18 |
+
require_once( dirname(__FILE__).'/icwp-processor-base.php' );
|
19 |
+
|
20 |
+
if ( !class_exists('ICWP_WPSF_Processor_AuditTrail_Users') ):
|
21 |
+
|
22 |
+
class ICWP_WPSF_Processor_AuditTrail_Users extends ICWP_WPSF_Processor_Base {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var ICWP_WPSF_FeatureHandler_AuditTrail
|
26 |
+
*/
|
27 |
+
protected $oFeatureOptions;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @param ICWP_WPSF_FeatureHandler_AuditTrail $oFeatureOptions
|
31 |
+
*/
|
32 |
+
public function __construct( ICWP_WPSF_FeatureHandler_AuditTrail $oFeatureOptions ) {
|
33 |
+
parent::__construct( $oFeatureOptions );
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
*/
|
38 |
+
public function run() {
|
39 |
+
|
40 |
+
if ( $this->getIsOption( 'enable_audit_context_users', 'Y' ) ) {
|
41 |
+
add_action( 'wp_login_failed', array( $this, 'auditUserLoginFail' ) );
|
42 |
+
add_action( 'wp_login', array( $this, 'auditUserLoginSuccess' ) );
|
43 |
+
add_action( 'user_register', array( $this, 'auditNewUserRegistered' ) );
|
44 |
+
add_action( 'delete_user', array( $this, 'auditDeleteUser' ), 30, 2 );
|
45 |
+
}
|
46 |
+
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* @param string $sUsername
|
51 |
+
* @return bool
|
52 |
+
*/
|
53 |
+
public function auditUserLoginSuccess( $sUsername ) {
|
54 |
+
|
55 |
+
if ( empty( $sUsername ) ) {
|
56 |
+
return false;
|
57 |
+
}
|
58 |
+
|
59 |
+
$oAuditTrail = $this->getAuditTrailEntries();
|
60 |
+
$oAuditTrail->add(
|
61 |
+
'users',
|
62 |
+
'login_success',
|
63 |
+
1,
|
64 |
+
sprintf( _wpsf__( 'Attempted user login by "%s" was successful.' ), $sUsername )
|
65 |
+
);
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* @param string $sUsername
|
70 |
+
* @return bool
|
71 |
+
*/
|
72 |
+
public function auditUserLoginFail( $sUsername ) {
|
73 |
+
|
74 |
+
if ( empty( $sUsername ) ) {
|
75 |
+
return false;
|
76 |
+
}
|
77 |
+
|
78 |
+
$oAuditTrail = $this->getAuditTrailEntries();
|
79 |
+
$oAuditTrail->add(
|
80 |
+
'users',
|
81 |
+
'login_failure',
|
82 |
+
2,
|
83 |
+
sprintf( _wpsf__( 'Attempted user login by "%s" was failed.' ), $sUsername )
|
84 |
+
);
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* @param int $nUserId
|
89 |
+
* @return bool
|
90 |
+
*/
|
91 |
+
public function auditNewUserRegistered( $nUserId ) {
|
92 |
+
if ( empty( $nUserId ) ) {
|
93 |
+
return false;
|
94 |
+
}
|
95 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
96 |
+
$oNewUser = $oWp->getUserById( $nUserId );
|
97 |
+
|
98 |
+
$oAuditTrail = $this->getAuditTrailEntries();
|
99 |
+
$oAuditTrail->add(
|
100 |
+
'users',
|
101 |
+
'user_registered',
|
102 |
+
1,
|
103 |
+
_wpsf__( 'New WordPress user registered.').' '
|
104 |
+
.sprintf(
|
105 |
+
_wpsf__( 'New username is "%s" with email address "%s".' ),
|
106 |
+
empty( $oNewUser ) ? 'unknown' : $oNewUser->get( 'user_login' ),
|
107 |
+
empty( $oNewUser ) ? 'unknown' : $oNewUser->get( 'user_email' )
|
108 |
+
)
|
109 |
+
);
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* @param int $nUserId
|
114 |
+
* @param int $nReassigned
|
115 |
+
* @return bool
|
116 |
+
*/
|
117 |
+
public function auditDeleteUser( $nUserId, $nReassigned ) {
|
118 |
+
if ( empty( $nUserId ) ) {
|
119 |
+
return false;
|
120 |
+
}
|
121 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
122 |
+
$oDeletedUser = $oWp->getUserById( $nUserId );
|
123 |
+
$oReassignedUser = empty( $nReassigned ) ? null : $oWp->getUserById( $nReassigned );
|
124 |
+
|
125 |
+
// Build the audit message
|
126 |
+
$sAuditMessage =
|
127 |
+
_wpsf__( 'WordPress user deleted.')
|
128 |
+
.' '.sprintf(
|
129 |
+
_wpsf__( 'Username was "%s" with email address "%s".' ),
|
130 |
+
empty( $oDeletedUser ) ? 'unknown' : $oDeletedUser->get( 'user_login' ),
|
131 |
+
empty( $oDeletedUser ) ? 'unknown' : $oDeletedUser->get( 'user_email' )
|
132 |
+
).' ';
|
133 |
+
if ( empty( $oReassignedUser ) ) {
|
134 |
+
$sAuditMessage .= _wpsf__( 'Their posts were not reassigned to another user.' );
|
135 |
+
}
|
136 |
+
else {
|
137 |
+
$sAuditMessage .= sprintf(
|
138 |
+
_wpsf__( 'Their posts were reassigned to user "%s".' ),
|
139 |
+
$oReassignedUser->get( 'user_login' )
|
140 |
+
);
|
141 |
+
}
|
142 |
+
|
143 |
+
$oAuditTrail = $this->getAuditTrailEntries();
|
144 |
+
$oAuditTrail->add(
|
145 |
+
'users',
|
146 |
+
'user_deleted',
|
147 |
+
2,
|
148 |
+
$sAuditMessage
|
149 |
+
);
|
150 |
+
}
|
151 |
+
|
152 |
+
/**
|
153 |
+
* @return ICWP_WPSF_AuditTrail_Entries
|
154 |
+
*/
|
155 |
+
protected function getAuditTrailEntries() {
|
156 |
+
return ICWP_WPSF_AuditTrail_Entries::GetInstance();
|
157 |
+
}
|
158 |
+
}
|
159 |
+
|
160 |
+
endif;
|
src/icwp-processor-audit_trail_wordpress.php
ADDED
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
+
* All rights reserved.
|
5 |
+
*
|
6 |
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
7 |
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
8 |
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
9 |
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
10 |
+
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
11 |
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
12 |
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
13 |
+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
14 |
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
15 |
+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
+
*/
|
17 |
+
|
18 |
+
require_once( dirname(__FILE__).'/icwp-processor-base.php' );
|
19 |
+
|
20 |
+
if ( !class_exists('ICWP_WPSF_Processor_AuditTrail_Wordpress') ):
|
21 |
+
|
22 |
+
class ICWP_WPSF_Processor_AuditTrail_Wordpress extends ICWP_WPSF_Processor_Base {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var ICWP_WPSF_FeatureHandler_AuditTrail
|
26 |
+
*/
|
27 |
+
protected $oFeatureOptions;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @param ICWP_WPSF_FeatureHandler_AuditTrail $oFeatureOptions
|
31 |
+
*/
|
32 |
+
public function __construct( ICWP_WPSF_FeatureHandler_AuditTrail $oFeatureOptions ) {
|
33 |
+
parent::__construct( $oFeatureOptions );
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
*/
|
38 |
+
public function run() {
|
39 |
+
if ( $this->getIsOption( 'enable_audit_context_wordpress', 'Y' ) ) {
|
40 |
+
add_action( '_core_updated_successfully', array( $this, 'auditCoreUpdated' ) );
|
41 |
+
add_action( 'update_option_permalink_structure', array( $this, 'auditPermalinkStructure' ), 10, 2 );
|
42 |
+
}
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* @param string $sNewCoreVersion
|
47 |
+
* @return bool
|
48 |
+
*/
|
49 |
+
public function auditCoreUpdated( $sNewCoreVersion ) {
|
50 |
+
global $wp_version;
|
51 |
+
|
52 |
+
$oAuditTrail = $this->getAuditTrailEntries();
|
53 |
+
$oAuditTrail->add(
|
54 |
+
'wordpress',
|
55 |
+
'core_updated',
|
56 |
+
1,
|
57 |
+
sprintf( _wpsf__( 'WordPress Core was updated from "v%s" to "v%s".' ), $wp_version, $sNewCoreVersion )
|
58 |
+
);
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* @param string $sOld
|
63 |
+
* @param string $sNew
|
64 |
+
* @return bool
|
65 |
+
*/
|
66 |
+
public function auditPermalinkStructure( $sOld, $sNew ) {
|
67 |
+
$oAuditTrail = $this->getAuditTrailEntries();
|
68 |
+
$oAuditTrail->add(
|
69 |
+
'wordpress',
|
70 |
+
'permalinks_structure',
|
71 |
+
1,
|
72 |
+
sprintf( _wpsf__( 'WordPress Permalinks Structure was updated from "%s" to "%s".' ), $sOld, $sNew )
|
73 |
+
);
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* @return ICWP_WPSF_AuditTrail_Entries
|
78 |
+
*/
|
79 |
+
protected function getAuditTrailEntries() {
|
80 |
+
return ICWP_WPSF_AuditTrail_Entries::GetInstance();
|
81 |
+
}
|
82 |
+
}
|
83 |
+
|
84 |
+
endif;
|
src/icwp-processor-autoupdates.php
CHANGED
@@ -15,46 +15,49 @@
|
|
15 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
*/
|
17 |
|
18 |
-
require_once( dirname(__FILE__).'/icwp-base
|
19 |
|
20 |
if ( !class_exists('ICWP_AutoupdatesProcessor_V5') ):
|
21 |
|
22 |
-
class ICWP_AutoupdatesProcessor_V5 extends
|
23 |
|
24 |
const FilterPriority = 1001;
|
25 |
|
26 |
-
protected $sPluginFile;
|
27 |
-
|
28 |
/**
|
29 |
* @var boolean
|
30 |
*/
|
31 |
-
protected $
|
32 |
|
33 |
/**
|
34 |
* @param ICWP_WPSF_FeatureHandler_Autoupdates $oFeatureOptions
|
35 |
*/
|
36 |
public function __construct( ICWP_WPSF_FeatureHandler_Autoupdates $oFeatureOptions ) {
|
37 |
parent::__construct( $oFeatureOptions );
|
38 |
-
$this->sPluginFile = $this->oFeatureOptions->getPluginBaseFile();
|
39 |
}
|
40 |
|
41 |
/**
|
42 |
* @param boolean $infDoForceRun
|
43 |
*/
|
44 |
public function setForceRunAutoupdates( $infDoForceRun ) {
|
45 |
-
$this->
|
46 |
}
|
47 |
-
|
48 |
/**
|
|
|
49 |
*/
|
50 |
public function getForceRunAutoupdates() {
|
51 |
-
return apply_filters( '
|
52 |
}
|
53 |
|
54 |
/**
|
55 |
*/
|
56 |
public function run() {
|
57 |
|
|
|
|
|
|
|
|
|
|
|
58 |
// When we force run we only want our filters.
|
59 |
if ( $this->getForceRunAutoupdates() ) {
|
60 |
$aFilters = array(
|
@@ -195,7 +198,7 @@ class ICWP_AutoupdatesProcessor_V5 extends ICWP_BaseProcessor_V3 {
|
|
195 |
return $infUpdate;
|
196 |
}
|
197 |
|
198 |
-
if ( $sItemFile === $this->
|
199 |
if ( $this->getIsOption('autoupdate_plugin_self', 'Y') ) {
|
200 |
$this->doStatIncrement( 'autoupdates.plugins.self' );
|
201 |
return true;
|
@@ -214,7 +217,7 @@ class ICWP_AutoupdatesProcessor_V5 extends ICWP_BaseProcessor_V3 {
|
|
214 |
|
215 |
return $infUpdate;
|
216 |
}
|
217 |
-
|
218 |
/**
|
219 |
* This is a filter method designed to say whether WordPress theme upgrades should be permitted,
|
220 |
* based on the plugin settings.
|
@@ -243,35 +246,36 @@ class ICWP_AutoupdatesProcessor_V5 extends ICWP_BaseProcessor_V3 {
|
|
243 |
}
|
244 |
|
245 |
$aAutoupdateThemeFiles = apply_filters( 'icwp_wpsf_autoupdate_themes', array() );
|
246 |
-
|
247 |
if ( !empty( $aAutoupdateThemeFiles )
|
248 |
&& is_array($aAutoupdateThemeFiles)
|
249 |
&& in_array( $sItemFile, $aAutoupdateThemeFiles ) ) {
|
250 |
|
251 |
return true;
|
252 |
}
|
253 |
-
|
254 |
return $infUpdate;
|
255 |
}
|
256 |
-
|
257 |
/**
|
258 |
* This is a filter method designed to say whether WordPress automatic upgrades should be permitted
|
259 |
* if a version control system is detected.
|
260 |
-
*
|
261 |
-
* @param
|
|
|
262 |
* @return boolean
|
263 |
*/
|
264 |
public function disable_for_vcs( $checkout, $context ) {
|
265 |
return false;
|
266 |
}
|
267 |
-
|
268 |
/**
|
269 |
* A filter on whether or not a notification email is send after core upgrades are attempted.
|
270 |
*
|
271 |
-
* @param boolean $
|
272 |
* @return boolean
|
273 |
*/
|
274 |
-
public function autoupdate_send_email( $
|
275 |
return $this->getIsOption( 'enable_upgrade_notification_email', 'Y' );
|
276 |
}
|
277 |
|
@@ -292,6 +296,6 @@ class ICWP_AutoupdatesProcessor_V5 extends ICWP_BaseProcessor_V3 {
|
|
292 |
|
293 |
endif;
|
294 |
|
295 |
-
if ( !class_exists('
|
296 |
-
class
|
297 |
endif;
|
15 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
*/
|
17 |
|
18 |
+
require_once( dirname(__FILE__).'/icwp-processor-base.php' );
|
19 |
|
20 |
if ( !class_exists('ICWP_AutoupdatesProcessor_V5') ):
|
21 |
|
22 |
+
class ICWP_AutoupdatesProcessor_V5 extends ICWP_WPSF_Processor_Base {
|
23 |
|
24 |
const FilterPriority = 1001;
|
25 |
|
|
|
|
|
26 |
/**
|
27 |
* @var boolean
|
28 |
*/
|
29 |
+
protected $fDoForceRunAutoupdates = false;
|
30 |
|
31 |
/**
|
32 |
* @param ICWP_WPSF_FeatureHandler_Autoupdates $oFeatureOptions
|
33 |
*/
|
34 |
public function __construct( ICWP_WPSF_FeatureHandler_Autoupdates $oFeatureOptions ) {
|
35 |
parent::__construct( $oFeatureOptions );
|
|
|
36 |
}
|
37 |
|
38 |
/**
|
39 |
* @param boolean $infDoForceRun
|
40 |
*/
|
41 |
public function setForceRunAutoupdates( $infDoForceRun ) {
|
42 |
+
$this->fDoForceRunAutoupdates = $infDoForceRun;
|
43 |
}
|
44 |
+
|
45 |
/**
|
46 |
+
* @return boolean
|
47 |
*/
|
48 |
public function getForceRunAutoupdates() {
|
49 |
+
return apply_filters( $this->getFeatureOptions()->doPluginPrefix( 'force_autoupdate' ), $this->fDoForceRunAutoupdates );
|
50 |
}
|
51 |
|
52 |
/**
|
53 |
*/
|
54 |
public function run() {
|
55 |
|
56 |
+
$oDp = $this->loadDataProcessor();
|
57 |
+
if ( $oDp->FetchGet( 'forcerun' ) == 1 ) {
|
58 |
+
$this->setForceRunAutoupdates( true );
|
59 |
+
}
|
60 |
+
|
61 |
// When we force run we only want our filters.
|
62 |
if ( $this->getForceRunAutoupdates() ) {
|
63 |
$aFilters = array(
|
198 |
return $infUpdate;
|
199 |
}
|
200 |
|
201 |
+
if ( $sItemFile === $this->getFeatureOptions()->getPluginBaseFile() ) {
|
202 |
if ( $this->getIsOption('autoupdate_plugin_self', 'Y') ) {
|
203 |
$this->doStatIncrement( 'autoupdates.plugins.self' );
|
204 |
return true;
|
217 |
|
218 |
return $infUpdate;
|
219 |
}
|
220 |
+
|
221 |
/**
|
222 |
* This is a filter method designed to say whether WordPress theme upgrades should be permitted,
|
223 |
* based on the plugin settings.
|
246 |
}
|
247 |
|
248 |
$aAutoupdateThemeFiles = apply_filters( 'icwp_wpsf_autoupdate_themes', array() );
|
249 |
+
|
250 |
if ( !empty( $aAutoupdateThemeFiles )
|
251 |
&& is_array($aAutoupdateThemeFiles)
|
252 |
&& in_array( $sItemFile, $aAutoupdateThemeFiles ) ) {
|
253 |
|
254 |
return true;
|
255 |
}
|
256 |
+
|
257 |
return $infUpdate;
|
258 |
}
|
259 |
+
|
260 |
/**
|
261 |
* This is a filter method designed to say whether WordPress automatic upgrades should be permitted
|
262 |
* if a version control system is detected.
|
263 |
+
*
|
264 |
+
* @param $checkout
|
265 |
+
* @param $context
|
266 |
* @return boolean
|
267 |
*/
|
268 |
public function disable_for_vcs( $checkout, $context ) {
|
269 |
return false;
|
270 |
}
|
271 |
+
|
272 |
/**
|
273 |
* A filter on whether or not a notification email is send after core upgrades are attempted.
|
274 |
*
|
275 |
+
* @param boolean $fSendEmail
|
276 |
* @return boolean
|
277 |
*/
|
278 |
+
public function autoupdate_send_email( $fSendEmail ) {
|
279 |
return $this->getIsOption( 'enable_upgrade_notification_email', 'Y' );
|
280 |
}
|
281 |
|
296 |
|
297 |
endif;
|
298 |
|
299 |
+
if ( !class_exists('ICWP_WPSF_Processor_Autoupdates') ):
|
300 |
+
class ICWP_WPSF_Processor_Autoupdates extends ICWP_AutoupdatesProcessor_V5 { }
|
301 |
endif;
|
src/icwp-processor-base.php
ADDED
@@ -0,0 +1,333 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
+
* All rights reserved.
|
5 |
+
*
|
6 |
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
7 |
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
8 |
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
9 |
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
10 |
+
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
11 |
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
12 |
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
13 |
+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
14 |
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
15 |
+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
+
*
|
17 |
+
*/
|
18 |
+
|
19 |
+
if ( !class_exists('ICWP_BaseProcessor_V3') ):
|
20 |
+
|
21 |
+
class ICWP_BaseProcessor_V3 extends ICWP_WPSF_Foundation {
|
22 |
+
|
23 |
+
const PcreDelimiter = '/';
|
24 |
+
const LOG_MESSAGE_LEVEL_INFO = 0;
|
25 |
+
const LOG_MESSAGE_LEVEL_WARNING = 1;
|
26 |
+
const LOG_MESSAGE_LEVEL_CRITICAL = 2;
|
27 |
+
|
28 |
+
const LOG_CATEGORY_DEFAULT = 0;
|
29 |
+
const LOG_CATEGORY_FIREWALL = 1;
|
30 |
+
const LOG_CATEGORY_LOGINPROTECT = 2;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* @var array
|
34 |
+
*/
|
35 |
+
protected $m_aLog;
|
36 |
+
/**
|
37 |
+
* @var array
|
38 |
+
*/
|
39 |
+
protected $m_aLogMessages;
|
40 |
+
|
41 |
+
/**
|
42 |
+
* @var long
|
43 |
+
*/
|
44 |
+
protected static $nRequestIp;
|
45 |
+
/**
|
46 |
+
* @var long
|
47 |
+
*/
|
48 |
+
protected static $nRequestPostId;
|
49 |
+
/**
|
50 |
+
* @var integer
|
51 |
+
*/
|
52 |
+
protected static $nRequestTimestamp;
|
53 |
+
|
54 |
+
/**
|
55 |
+
* @var ICWP_WPSF_FeatureHandler_Base
|
56 |
+
*/
|
57 |
+
protected $oFeatureOptions;
|
58 |
+
|
59 |
+
public function __construct( ICWP_WPSF_FeatureHandler_Base $oFeatureOptions ) {
|
60 |
+
$this->oFeatureOptions = $oFeatureOptions;
|
61 |
+
$this->reset();
|
62 |
+
}
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Resets the object values to be re-used anew
|
66 |
+
*/
|
67 |
+
public function reset() {
|
68 |
+
$oDp = $this->loadDataProcessor();
|
69 |
+
if ( !isset( self::$nRequestIp ) ) {
|
70 |
+
self::$nRequestIp = $oDp->GetVisitorIpAddress();
|
71 |
+
}
|
72 |
+
if ( !isset( self::$nRequestTimestamp ) ) {
|
73 |
+
self::$nRequestTimestamp = $oDp->GetRequestTime();
|
74 |
+
}
|
75 |
+
$this->resetLog();
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Override to set what this processor does when it's "run"
|
80 |
+
*/
|
81 |
+
public function run() { }
|
82 |
+
|
83 |
+
/**
|
84 |
+
* @param $sOptionKey
|
85 |
+
* @param bool $mDefault
|
86 |
+
* @return bool
|
87 |
+
*/
|
88 |
+
public function getOption( $sOptionKey, $mDefault = false ) {
|
89 |
+
return $this->getFeatureOptions()->getOpt( $sOptionKey, $mDefault );
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* @param $sKey
|
94 |
+
* @param mixed $mValueToTest
|
95 |
+
* @param boolean $fStrict
|
96 |
+
* @return bool
|
97 |
+
*/
|
98 |
+
public function getIsOption( $sKey, $mValueToTest, $fStrict = false ) {
|
99 |
+
$mOptionValue = $this->getOption( $sKey );
|
100 |
+
return $fStrict? $mOptionValue === $mValueToTest : $mOptionValue == $mValueToTest;
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* @return bool|long
|
105 |
+
*/
|
106 |
+
public function getRequestPostId() {
|
107 |
+
if ( !isset( self::$nRequestPostId ) ) {
|
108 |
+
global $post;
|
109 |
+
if ( empty( $post ) ) {
|
110 |
+
return false;
|
111 |
+
}
|
112 |
+
self::$nRequestPostId = $post->ID;
|
113 |
+
}
|
114 |
+
return self::$nRequestPostId;
|
115 |
+
}
|
116 |
+
|
117 |
+
/**
|
118 |
+
* Resets the log
|
119 |
+
*/
|
120 |
+
public function resetLog() {
|
121 |
+
$this->m_aLogMessages = array();
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* @return bool
|
126 |
+
*/
|
127 |
+
public function getIsLogging() {
|
128 |
+
return false;
|
129 |
+
}
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Should return false when logging is disabled.
|
133 |
+
*
|
134 |
+
* @return false|array - false when logging is disabled, array with log data otherwise
|
135 |
+
* @see ICWP_WPSF_Processor_Base::getLogData()
|
136 |
+
*/
|
137 |
+
public function flushLogData() {
|
138 |
+
if ( !$this->getIsLogging() ) {
|
139 |
+
return false;
|
140 |
+
}
|
141 |
+
return false;
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Builds and returns the full log.
|
146 |
+
*
|
147 |
+
* @return array (associative)
|
148 |
+
*/
|
149 |
+
public function getLogData() {
|
150 |
+
|
151 |
+
if ( $this->getIsLogging() ) {
|
152 |
+
$this->m_aLog = array( 'messages' => serialize( $this->m_aLogMessages ) );
|
153 |
+
}
|
154 |
+
else {
|
155 |
+
$this->m_aLog = false;
|
156 |
+
}
|
157 |
+
|
158 |
+
return $this->m_aLog;
|
159 |
+
}
|
160 |
+
|
161 |
+
/**
|
162 |
+
* @return array
|
163 |
+
*/
|
164 |
+
public function getLogMessages() {
|
165 |
+
if ( !is_array( $this->m_aLogMessages ) ) {
|
166 |
+
$this->m_aLogMessages = array();
|
167 |
+
}
|
168 |
+
return $this->m_aLogMessages;
|
169 |
+
}
|
170 |
+
|
171 |
+
/**
|
172 |
+
* @param string $sLogMessage
|
173 |
+
* @param integer $sMessageType
|
174 |
+
*/
|
175 |
+
public function writeLog( $sLogMessage = '', $sMessageType = self::LOG_MESSAGE_LEVEL_INFO ) {
|
176 |
+
if ( !is_array( $this->m_aLogMessages ) ) {
|
177 |
+
$this->resetLog();
|
178 |
+
}
|
179 |
+
$this->m_aLogMessages[] = array( $sMessageType, $sLogMessage );
|
180 |
+
}
|
181 |
+
/**
|
182 |
+
* @param string $insLogMessage
|
183 |
+
*/
|
184 |
+
public function logInfo( $insLogMessage ) {
|
185 |
+
$this->writeLog( $insLogMessage, self::LOG_MESSAGE_LEVEL_INFO );
|
186 |
+
}
|
187 |
+
/**
|
188 |
+
* @param string $insLogMessage
|
189 |
+
*/
|
190 |
+
public function logWarning( $insLogMessage ) {
|
191 |
+
$this->writeLog( $insLogMessage, self::LOG_MESSAGE_LEVEL_WARNING );
|
192 |
+
}
|
193 |
+
/**
|
194 |
+
* @param string $insLogMessage
|
195 |
+
*/
|
196 |
+
public function logCritical( $insLogMessage ) {
|
197 |
+
$this->writeLog( $insLogMessage, self::LOG_MESSAGE_LEVEL_CRITICAL );
|
198 |
+
}
|
199 |
+
|
200 |
+
/**
|
201 |
+
* @param array $inaIpList
|
202 |
+
* @param integer $innIpAddress
|
203 |
+
* @param string $outsLabel
|
204 |
+
* @return boolean
|
205 |
+
*/
|
206 |
+
public function isIpOnlist( $inaIpList, $innIpAddress = 0, &$outsLabel = '' ) {
|
207 |
+
|
208 |
+
if ( empty( $innIpAddress ) || !isset( $inaIpList['ips'] ) ) {
|
209 |
+
return false;
|
210 |
+
}
|
211 |
+
|
212 |
+
$outsLabel = '';
|
213 |
+
foreach( $inaIpList['ips'] as $mWhitelistAddress ) {
|
214 |
+
|
215 |
+
$aIps = $this->parseIpAddress( $mWhitelistAddress );
|
216 |
+
if ( count( $aIps ) === 1 ) { //not a range
|
217 |
+
if ( $innIpAddress == $aIps[0] ) {
|
218 |
+
$outsLabel = $inaIpList['meta'][ md5( $mWhitelistAddress ) ];
|
219 |
+
return true;
|
220 |
+
}
|
221 |
+
}
|
222 |
+
else if ( count( $aIps ) == 2 ) {
|
223 |
+
if ( $aIps[0] <= $innIpAddress && $innIpAddress <= $aIps[1] ) {
|
224 |
+
$outsLabel = $inaIpList['meta'][ md5( $mWhitelistAddress ) ];
|
225 |
+
return true;
|
226 |
+
}
|
227 |
+
}
|
228 |
+
}
|
229 |
+
return false;
|
230 |
+
}
|
231 |
+
|
232 |
+
/**
|
233 |
+
* @param string $sIpAddress - an IP or IP address range in LONG format.
|
234 |
+
* @return array - with 1 ip address, or 2 addresses if it is a range.
|
235 |
+
*/
|
236 |
+
protected function parseIpAddress( $sIpAddress ) {
|
237 |
+
|
238 |
+
$aIps = array();
|
239 |
+
|
240 |
+
if ( empty($sIpAddress) ) {
|
241 |
+
return $aIps;
|
242 |
+
}
|
243 |
+
|
244 |
+
// offset=1 in the case that it's a range and the first number is negative on 32-bit systems
|
245 |
+
$mPos = strpos( $sIpAddress, '-', 1 );
|
246 |
+
|
247 |
+
if ( $mPos === false ) { //plain IP address
|
248 |
+
$aIps[] = $sIpAddress;
|
249 |
+
}
|
250 |
+
else {
|
251 |
+
//we remove the first character in case this is '-'
|
252 |
+
$aParts = array( substr( $sIpAddress, 0, 1 ), substr( $sIpAddress, 1 ) );
|
253 |
+
list( $sStart, $sEnd ) = explode( '-', $aParts[1], 2 );
|
254 |
+
$aIps[] = $aParts[0].$sStart;
|
255 |
+
$aIps[] = $sEnd;
|
256 |
+
}
|
257 |
+
return $aIps;
|
258 |
+
}
|
259 |
+
|
260 |
+
/**
|
261 |
+
* @return ICWP_WPSF_Processor_Email
|
262 |
+
*/
|
263 |
+
public function getEmailProcessor() {
|
264 |
+
return $this->getFeatureOptions()->getEmailProcessor();
|
265 |
+
}
|
266 |
+
|
267 |
+
/**
|
268 |
+
* @return ICWP_WPSF_Processor_Logging
|
269 |
+
*/
|
270 |
+
public function getLoggingProcessor() {
|
271 |
+
return $this->getFeatureOptions()->getLoggingProcessor();
|
272 |
+
}
|
273 |
+
|
274 |
+
/**
|
275 |
+
* Checks the $aData contains valid key values as laid out in $inaChecks
|
276 |
+
*
|
277 |
+
* @param array $aData
|
278 |
+
* @param array $inaChecks
|
279 |
+
* @return boolean
|
280 |
+
*/
|
281 |
+
protected function validateParameters( $aData, $inaChecks ) {
|
282 |
+
|
283 |
+
if ( !is_array( $aData ) ) {
|
284 |
+
return false;
|
285 |
+
}
|
286 |
+
|
287 |
+
foreach( $inaChecks as $sCheck ) {
|
288 |
+
if ( !array_key_exists( $sCheck, $aData ) || empty( $aData[ $sCheck ] ) ) {
|
289 |
+
return false;
|
290 |
+
}
|
291 |
+
}
|
292 |
+
return true;
|
293 |
+
}
|
294 |
+
|
295 |
+
/**
|
296 |
+
* @param $sStatKey
|
297 |
+
*/
|
298 |
+
protected function doStatIncrement( $sStatKey ) {
|
299 |
+
$this->getFeatureOptions()->doStatIncrement( $sStatKey );
|
300 |
+
}
|
301 |
+
|
302 |
+
/**
|
303 |
+
* @return ICWP_WPSF_FeatureHandler_Base
|
304 |
+
*/
|
305 |
+
protected function getFeatureOptions() {
|
306 |
+
return $this->oFeatureOptions;
|
307 |
+
}
|
308 |
+
|
309 |
+
/**
|
310 |
+
* Provides the basic HTML template for printing a WordPress Admin Notices
|
311 |
+
*
|
312 |
+
* @param $sNotice - The message to be displayed.
|
313 |
+
* @param $sMessageClass - either error or updated
|
314 |
+
* @param $infPrint - if true, will echo. false will return the string
|
315 |
+
* @return boolean|string
|
316 |
+
*/
|
317 |
+
protected function getAdminNoticeHtml( $sNotice = '', $sMessageClass = 'updated', $infPrint = false ) {
|
318 |
+
$sWrapper = '<div class="%s icwp-admin-notice">%s</div>';
|
319 |
+
$sFullNotice = sprintf( $sWrapper, $sMessageClass, $sNotice );
|
320 |
+
if ( $infPrint ) {
|
321 |
+
echo $sFullNotice;
|
322 |
+
return true;
|
323 |
+
} else {
|
324 |
+
return $sFullNotice;
|
325 |
+
}
|
326 |
+
}
|
327 |
+
}
|
328 |
+
|
329 |
+
endif;
|
330 |
+
|
331 |
+
if ( !class_exists('ICWP_WPSF_Processor_Base') ):
|
332 |
+
class ICWP_WPSF_Processor_Base extends ICWP_BaseProcessor_V3 { }
|
333 |
+
endif;
|
src/{icwp-basedb-processor.php → icwp-processor-basedb.php}
RENAMED
@@ -16,16 +16,12 @@
|
|
16 |
*
|
17 |
*/
|
18 |
|
19 |
-
require_once( dirname(__FILE__).'/icwp-base
|
20 |
|
21 |
-
if ( !class_exists('
|
22 |
|
23 |
-
class
|
24 |
|
25 |
-
const DB_TABLE_PREFIX = 'icwp_';
|
26 |
-
|
27 |
-
/**
|
28 |
-
*/
|
29 |
const CleanupCronActionHook = 'icwp_wpsf_cron_cleanupactionhook';
|
30 |
|
31 |
/**
|
@@ -43,33 +39,74 @@ class ICWP_BaseDbProcessor_WPSF extends ICWP_WPSF_BaseProcessor {
|
|
43 |
* @var array
|
44 |
*/
|
45 |
protected $m_aDataToWrite;
|
|
|
|
|
|
|
|
|
|
|
46 |
|
47 |
public function __construct( ICWP_WPSF_FeatureHandler_Base $oFeatureOptions, $sTableName = null ) {
|
48 |
parent::__construct( $oFeatureOptions );
|
49 |
$this->setTableName( $sTableName );
|
50 |
$this->createCleanupCron();
|
|
|
51 |
}
|
52 |
|
53 |
/**
|
54 |
* Override to set what this processor does when it's "run"
|
55 |
*/
|
56 |
-
public function run() {
|
57 |
-
|
58 |
-
|
59 |
-
|
|
|
|
|
|
|
60 |
}
|
61 |
}
|
62 |
|
63 |
/**
|
64 |
* Loads our WPDB object if required.
|
|
|
|
|
65 |
*/
|
66 |
protected function loadWpdb() {
|
67 |
if ( is_null( $this->oWpdb ) ) {
|
68 |
-
|
69 |
-
$this->
|
70 |
}
|
71 |
return $this->oWpdb;
|
72 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
|
74 |
/**
|
75 |
* @param array $inaLogData
|
@@ -104,7 +141,7 @@ class ICWP_BaseDbProcessor_WPSF extends ICWP_WPSF_BaseProcessor {
|
|
104 |
* @return boolean - whether the write to the DB was successful.
|
105 |
*/
|
106 |
public function commitData() {
|
107 |
-
if ( empty( $this->m_aDataToWrite ) ) {
|
108 |
return;
|
109 |
}
|
110 |
$fSuccess = true;
|
@@ -121,7 +158,6 @@ class ICWP_BaseDbProcessor_WPSF extends ICWP_WPSF_BaseProcessor {
|
|
121 |
}
|
122 |
|
123 |
/**
|
124 |
-
*
|
125 |
*/
|
126 |
protected function flushData() {
|
127 |
$this->m_aDataToWrite = null;
|
@@ -135,33 +171,60 @@ class ICWP_BaseDbProcessor_WPSF extends ICWP_WPSF_BaseProcessor {
|
|
135 |
$oDb = $this->loadWpdb();
|
136 |
return $oDb->insert( $this->getTableName(), $aData );
|
137 |
}
|
138 |
-
|
139 |
-
|
|
|
|
|
|
|
|
|
140 |
$oDb = $this->loadWpdb();
|
141 |
$sQuery = sprintf( "SELECT * FROM `%s` WHERE `deleted_at` = '0'", $this->getTableName() );
|
142 |
-
return $oDb->get_results( $sQuery, $
|
143 |
}
|
144 |
-
|
145 |
-
|
|
|
|
|
|
|
|
|
|
|
146 |
$oDb = $this->loadWpdb();
|
147 |
-
return $oDb->get_results( $sQuery,
|
148 |
}
|
149 |
-
|
150 |
-
|
|
|
|
|
|
|
|
|
|
|
151 |
$oDb = $this->loadWpdb();
|
152 |
-
return $oDb->get_row( $sQuery,
|
153 |
}
|
154 |
-
|
|
|
|
|
|
|
|
|
|
|
155 |
public function updateRowsFromTable( $aData, $aWhere ) {
|
156 |
$oDb = $this->loadWpdb();
|
157 |
return $oDb->update( $this->getTableName(), $aData, $aWhere );
|
158 |
}
|
159 |
-
|
|
|
|
|
|
|
|
|
160 |
public function deleteRowsFromTable( $aWhere ) {
|
161 |
$oDb = $this->loadWpdb();
|
162 |
return $oDb->delete( $this->getTableName(), $aWhere );
|
163 |
}
|
164 |
-
|
|
|
|
|
|
|
|
|
165 |
protected function deleteAllRowsOlderThan( $nTime ) {
|
166 |
$sQuery = "
|
167 |
DELETE from `%s`
|
@@ -173,12 +236,13 @@ class ICWP_BaseDbProcessor_WPSF extends ICWP_WPSF_BaseProcessor {
|
|
173 |
$this->getTableName(),
|
174 |
$nTime
|
175 |
);
|
176 |
-
$this->doSql( $sQuery );
|
177 |
}
|
178 |
|
179 |
-
|
180 |
-
|
181 |
-
|
|
|
182 |
|
183 |
/**
|
184 |
* Will remove all data from this table (to delete the table see dropTable)
|
@@ -207,24 +271,18 @@ class ICWP_BaseDbProcessor_WPSF extends ICWP_WPSF_BaseProcessor {
|
|
207 |
/**
|
208 |
* Given any SQL query, will perform it using the WordPress database object.
|
209 |
*
|
210 |
-
* @param string $
|
|
|
211 |
*/
|
212 |
-
public function doSql( $
|
213 |
$oDb = $this->loadWpdb();
|
214 |
-
$
|
215 |
-
return $
|
216 |
-
}
|
217 |
-
|
218 |
-
private function setTableName( $sTableName = null ) {
|
219 |
-
$oDb = $this->loadWpdb();
|
220 |
-
$sTableString =
|
221 |
-
$oDb->prefix
|
222 |
-
. self::DB_TABLE_PREFIX
|
223 |
-
. ( is_null( $sTableName ) ? $this->oFeatureOptions->getFeatureSlug() : $sTableName );
|
224 |
-
$this->sFullTableName = esc_sql( $sTableString );
|
225 |
-
return $this->sFullTableName;
|
226 |
}
|
227 |
|
|
|
|
|
|
|
228 |
protected function getTableName() {
|
229 |
if ( empty( $this->sFullTableName ) ) {
|
230 |
return $this->setTableName();
|
@@ -233,18 +291,27 @@ class ICWP_BaseDbProcessor_WPSF extends ICWP_WPSF_BaseProcessor {
|
|
233 |
}
|
234 |
|
235 |
/**
|
236 |
-
*
|
|
|
|
|
237 |
*/
|
238 |
-
|
239 |
-
|
240 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
241 |
}
|
242 |
|
243 |
/**
|
244 |
* Will setup the cleanup cron to clean out old entries. This should be overridden per implementation.
|
245 |
*/
|
246 |
protected function createCleanupCron() {
|
247 |
-
$sFullHookName = $this->
|
248 |
if ( ! wp_next_scheduled( $sFullHookName ) && ! defined( 'WP_INSTALLING' ) ) {
|
249 |
$nNextRun = strtotime( 'tomorrow 6am' ) - get_option( 'gmt_offset' ) * HOUR_IN_SECONDS;
|
250 |
wp_schedule_event( $nNextRun, 'daily', $sFullHookName );
|
@@ -258,13 +325,21 @@ class ICWP_BaseDbProcessor_WPSF extends ICWP_WPSF_BaseProcessor {
|
|
258 |
* @return bool
|
259 |
*/
|
260 |
public function getTableExists() {
|
|
|
|
|
|
|
|
|
|
|
|
|
261 |
$oDb = $this->loadWpdb();
|
262 |
$sQuery = "
|
263 |
SHOW TABLES LIKE '%s'
|
264 |
";
|
265 |
$sQuery = sprintf( $sQuery, $this->getTableName() );
|
266 |
$mResult = $oDb->get_var( $sQuery );
|
267 |
-
|
|
|
|
|
268 |
}
|
269 |
}
|
270 |
|
16 |
*
|
17 |
*/
|
18 |
|
19 |
+
require_once( dirname(__FILE__).'/icwp-processor-base.php' );
|
20 |
|
21 |
+
if ( !class_exists('ICWP_WPSF_BaseDbProcessor') ):
|
22 |
|
23 |
+
abstract class ICWP_WPSF_BaseDbProcessor extends ICWP_WPSF_Processor_Base {
|
24 |
|
|
|
|
|
|
|
|
|
25 |
const CleanupCronActionHook = 'icwp_wpsf_cron_cleanupactionhook';
|
26 |
|
27 |
/**
|
39 |
* @var array
|
40 |
*/
|
41 |
protected $m_aDataToWrite;
|
42 |
+
|
43 |
+
/**
|
44 |
+
* @var boolean
|
45 |
+
*/
|
46 |
+
protected $fTableExists;
|
47 |
|
48 |
public function __construct( ICWP_WPSF_FeatureHandler_Base $oFeatureOptions, $sTableName = null ) {
|
49 |
parent::__construct( $oFeatureOptions );
|
50 |
$this->setTableName( $sTableName );
|
51 |
$this->createCleanupCron();
|
52 |
+
add_action( $this->getFeatureOptions()->doPluginPrefix( 'delete_plugin' ), array( $this, 'deleteDatabase' ) );
|
53 |
}
|
54 |
|
55 |
/**
|
56 |
* Override to set what this processor does when it's "run"
|
57 |
*/
|
58 |
+
public function run() { }
|
59 |
+
|
60 |
+
/**
|
61 |
+
*/
|
62 |
+
public function deleteDatabase() {
|
63 |
+
if ( apply_filters( $this->getFeatureOptions()->doPluginPrefix( 'has_permission_to_submit' ), true ) && $this->getTableExists() ) {
|
64 |
+
$this->dropTable();
|
65 |
}
|
66 |
}
|
67 |
|
68 |
/**
|
69 |
* Loads our WPDB object if required.
|
70 |
+
*
|
71 |
+
* @return wpdb
|
72 |
*/
|
73 |
protected function loadWpdb() {
|
74 |
if ( is_null( $this->oWpdb ) ) {
|
75 |
+
$this->oWpdb = $this->getWpdb();
|
76 |
+
$this->initializeTable();
|
77 |
}
|
78 |
return $this->oWpdb;
|
79 |
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
*/
|
83 |
+
private function getWpdb() {
|
84 |
+
global $wpdb;
|
85 |
+
return $wpdb;
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* @return bool|int
|
90 |
+
*/
|
91 |
+
protected function createTable() {
|
92 |
+
$sSql = $this->getCreateTableSql();
|
93 |
+
if ( !empty( $sSql ) ) {
|
94 |
+
return $this->doSql( $sSql );
|
95 |
+
}
|
96 |
+
return true;
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
*/
|
101 |
+
protected function initializeTable() {
|
102 |
+
if ( $this->getTableExists() ) {
|
103 |
+
$sFullHookName = $this->getFeatureOptions()->doPluginPrefix( self::CleanupCronActionHook, '_' );
|
104 |
+
add_action( $sFullHookName, array( $this, 'cleanupDatabase' ) );
|
105 |
+
}
|
106 |
+
else {
|
107 |
+
$this->createTable();
|
108 |
+
}
|
109 |
+
}
|
110 |
|
111 |
/**
|
112 |
* @param array $inaLogData
|
141 |
* @return boolean - whether the write to the DB was successful.
|
142 |
*/
|
143 |
public function commitData() {
|
144 |
+
if ( empty( $this->m_aDataToWrite ) || !$this->getTableExists() ) {
|
145 |
return;
|
146 |
}
|
147 |
$fSuccess = true;
|
158 |
}
|
159 |
|
160 |
/**
|
|
|
161 |
*/
|
162 |
protected function flushData() {
|
163 |
$this->m_aDataToWrite = null;
|
171 |
$oDb = $this->loadWpdb();
|
172 |
return $oDb->insert( $this->getTableName(), $aData );
|
173 |
}
|
174 |
+
|
175 |
+
/**
|
176 |
+
* @param $nFormat
|
177 |
+
* @return array|boolean
|
178 |
+
*/
|
179 |
+
public function selectAllFromTable( $nFormat = ARRAY_A ) {
|
180 |
$oDb = $this->loadWpdb();
|
181 |
$sQuery = sprintf( "SELECT * FROM `%s` WHERE `deleted_at` = '0'", $this->getTableName() );
|
182 |
+
return $oDb->get_results( $sQuery, $nFormat );
|
183 |
}
|
184 |
+
|
185 |
+
/**
|
186 |
+
* @param string $sQuery
|
187 |
+
* @param $nFormat
|
188 |
+
* @return array|boolean
|
189 |
+
*/
|
190 |
+
public function selectCustomFromTable( $sQuery, $nFormat = ARRAY_A ) {
|
191 |
$oDb = $this->loadWpdb();
|
192 |
+
return $oDb->get_results( $sQuery, $nFormat );
|
193 |
}
|
194 |
+
|
195 |
+
/**
|
196 |
+
* @param string $sQuery
|
197 |
+
* @param $nFormat
|
198 |
+
* @return array|boolean
|
199 |
+
*/
|
200 |
+
public function selectRowFromTable( $sQuery, $nFormat = ARRAY_A ) {
|
201 |
$oDb = $this->loadWpdb();
|
202 |
+
return $oDb->get_row( $sQuery, $nFormat );
|
203 |
}
|
204 |
+
|
205 |
+
/**
|
206 |
+
* @param array $aData - new insert data (associative array, column=>data)
|
207 |
+
* @param array $aWhere - insert where (associative array)
|
208 |
+
* @return integer|boolean (number of rows affected)
|
209 |
+
*/
|
210 |
public function updateRowsFromTable( $aData, $aWhere ) {
|
211 |
$oDb = $this->loadWpdb();
|
212 |
return $oDb->update( $this->getTableName(), $aData, $aWhere );
|
213 |
}
|
214 |
+
|
215 |
+
/**
|
216 |
+
* @param array $aWhere - delete where (associative array)
|
217 |
+
* @return integer|boolean (number of rows affected)
|
218 |
+
*/
|
219 |
public function deleteRowsFromTable( $aWhere ) {
|
220 |
$oDb = $this->loadWpdb();
|
221 |
return $oDb->delete( $this->getTableName(), $aWhere );
|
222 |
}
|
223 |
+
|
224 |
+
/**
|
225 |
+
* @param integer $nTime
|
226 |
+
* @return bool|int
|
227 |
+
*/
|
228 |
protected function deleteAllRowsOlderThan( $nTime ) {
|
229 |
$sQuery = "
|
230 |
DELETE from `%s`
|
236 |
$this->getTableName(),
|
237 |
$nTime
|
238 |
);
|
239 |
+
return $this->doSql( $sQuery );
|
240 |
}
|
241 |
|
242 |
+
/**
|
243 |
+
* @return string
|
244 |
+
*/
|
245 |
+
abstract protected function getCreateTableSql();
|
246 |
|
247 |
/**
|
248 |
* Will remove all data from this table (to delete the table see dropTable)
|
271 |
/**
|
272 |
* Given any SQL query, will perform it using the WordPress database object.
|
273 |
*
|
274 |
+
* @param string $sSqlQuery
|
275 |
+
* @return integer|boolean (number of rows affected or just true/false)
|
276 |
*/
|
277 |
+
public function doSql( $sSqlQuery ) {
|
278 |
$oDb = $this->loadWpdb();
|
279 |
+
$mResult = $oDb->query( $sSqlQuery );
|
280 |
+
return $mResult;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
281 |
}
|
282 |
|
283 |
+
/**
|
284 |
+
* @return string
|
285 |
+
*/
|
286 |
protected function getTableName() {
|
287 |
if ( empty( $this->sFullTableName ) ) {
|
288 |
return $this->setTableName();
|
291 |
}
|
292 |
|
293 |
/**
|
294 |
+
* @param string $sTableName
|
295 |
+
* @return string
|
296 |
+
* @throws Exception
|
297 |
*/
|
298 |
+
private function setTableName( $sTableName = '' ) {
|
299 |
+
if ( empty( $sTableName ) ) {
|
300 |
+
throw new Exception( 'Database Table Name is EMPTY' );
|
301 |
+
}
|
302 |
+
$oDb = $this->getWpdb();
|
303 |
+
$sTableString =
|
304 |
+
$oDb->prefix
|
305 |
+
. $sTableName;
|
306 |
+
$this->sFullTableName = esc_sql( $sTableString );
|
307 |
+
return $this->sFullTableName;
|
308 |
}
|
309 |
|
310 |
/**
|
311 |
* Will setup the cleanup cron to clean out old entries. This should be overridden per implementation.
|
312 |
*/
|
313 |
protected function createCleanupCron() {
|
314 |
+
$sFullHookName = $this->getFeatureOptions()->doPluginPrefix( self::CleanupCronActionHook, '_' );
|
315 |
if ( ! wp_next_scheduled( $sFullHookName ) && ! defined( 'WP_INSTALLING' ) ) {
|
316 |
$nNextRun = strtotime( 'tomorrow 6am' ) - get_option( 'gmt_offset' ) * HOUR_IN_SECONDS;
|
317 |
wp_schedule_event( $nNextRun, 'daily', $sFullHookName );
|
325 |
* @return bool
|
326 |
*/
|
327 |
public function getTableExists() {
|
328 |
+
|
329 |
+
// only return true if this is true.
|
330 |
+
if ( $this->fTableExists === true ) {
|
331 |
+
return true;
|
332 |
+
}
|
333 |
+
|
334 |
$oDb = $this->loadWpdb();
|
335 |
$sQuery = "
|
336 |
SHOW TABLES LIKE '%s'
|
337 |
";
|
338 |
$sQuery = sprintf( $sQuery, $this->getTableName() );
|
339 |
$mResult = $oDb->get_var( $sQuery );
|
340 |
+
|
341 |
+
$this->fTableExists = !is_null( $mResult );
|
342 |
+
return $this->fTableExists;
|
343 |
}
|
344 |
}
|
345 |
|
src/icwp-processor-comments_filter.php
ADDED
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
+
* All rights reserved.
|
5 |
+
*
|
6 |
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
7 |
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
8 |
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
9 |
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
10 |
+
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
11 |
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
12 |
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
13 |
+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
14 |
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
15 |
+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
+
*/
|
17 |
+
|
18 |
+
require_once( dirname(__FILE__).'/icwp-processor-basedb.php' );
|
19 |
+
|
20 |
+
if ( !class_exists('ICWP_WPSF_Processor_CommentsFilter_V2') ):
|
21 |
+
|
22 |
+
class ICWP_WPSF_Processor_CommentsFilter_V2 extends ICWP_WPSF_Processor_Base {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @param ICWP_WPSF_FeatureHandler_CommentsFilter $oFeatureOptions
|
26 |
+
*/
|
27 |
+
public function __construct( ICWP_WPSF_FeatureHandler_CommentsFilter $oFeatureOptions ) {
|
28 |
+
parent::__construct( $oFeatureOptions );
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
*/
|
33 |
+
public function run() {
|
34 |
+
parent::run();
|
35 |
+
|
36 |
+
if ( $this->getIsOption( 'enable_comments_gasp_protection', 'Y' ) ) {
|
37 |
+
require_once('icwp-processor-commentsfilter_antibotspam.php');
|
38 |
+
$oBotSpamProcessor = new ICWP_WPSF_Processor_CommentsFilter_AntiBotSpam( $this->getFeatureOptions() );
|
39 |
+
$oBotSpamProcessor->run();
|
40 |
+
}
|
41 |
+
|
42 |
+
if ( $this->getIsOption( 'enable_comments_human_spam_filter', 'Y' ) ) {
|
43 |
+
require_once( 'icwp-processor-commentsfilter_humanspam.php' );
|
44 |
+
$oHumanSpamProcessor = new ICWP_WPSF_Processor_CommentsFilter_HumanSpam( $this->getFeatureOptions() );
|
45 |
+
$oHumanSpamProcessor->run();
|
46 |
+
}
|
47 |
+
|
48 |
+
add_filter( 'pre_comment_approved', array( $this, 'doSetCommentStatus' ), 1 );
|
49 |
+
add_filter( 'pre_comment_content', array( $this, 'doInsertCommentStatusExplanation' ), 1, 1 );
|
50 |
+
add_filter( 'comment_notification_recipients', array( $this, 'doClearCommentNotificationEmail_Filter' ), 100, 1 );
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* We set the final approval status of the comments if we've set it in our scans, and empties the notification email
|
55 |
+
* in case we "trash" it (since WP sends out a notification email if it's anything but SPAM)
|
56 |
+
*
|
57 |
+
* @param $sApprovalStatus
|
58 |
+
* @return string
|
59 |
+
*/
|
60 |
+
public function doSetCommentStatus( $sApprovalStatus ) {
|
61 |
+
$sStatus = apply_filters( $this->getFeatureOptions()->doPluginPrefix( 'comments_filter_status' ), '' );
|
62 |
+
return empty( $sStatus ) ? $sApprovalStatus : $sStatus;
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* @param string $sCommentContent
|
67 |
+
* @return string
|
68 |
+
*/
|
69 |
+
public function doInsertCommentStatusExplanation( $sCommentContent ) {
|
70 |
+
|
71 |
+
$sExplanation = apply_filters( $this->getFeatureOptions()->doPluginPrefix( 'comments_filter_status_explanation' ), '' );
|
72 |
+
|
73 |
+
// If either spam filtering process left an explanation, we add it here
|
74 |
+
if ( !empty( $sExplanation ) ) {
|
75 |
+
$sCommentContent = $sExplanation.$sCommentContent;
|
76 |
+
}
|
77 |
+
return $sCommentContent;
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* When you set a new comment as anything but 'spam' a notification email is sent to the post author.
|
82 |
+
* We suppress this for when we mark as trash by emptying the email notifications list.
|
83 |
+
*
|
84 |
+
* @param array $aEmails
|
85 |
+
* @return array
|
86 |
+
*/
|
87 |
+
public function doClearCommentNotificationEmail_Filter( $aEmails ) {
|
88 |
+
$sStatus = apply_filters( $this->getFeatureOptions()->doPluginPrefix( 'comments_filter_status' ), '' );
|
89 |
+
if ( $sStatus == 'trash' ) {
|
90 |
+
$aEmails = array();
|
91 |
+
}
|
92 |
+
return $aEmails;
|
93 |
+
}
|
94 |
+
|
95 |
+
}
|
96 |
+
endif;
|
97 |
+
|
98 |
+
if ( !class_exists('ICWP_WPSF_Processor_CommentsFilter') ):
|
99 |
+
class ICWP_WPSF_Processor_CommentsFilter extends ICWP_WPSF_Processor_CommentsFilter_V2 { }
|
100 |
+
endif;
|
src/{icwp-processor-commentsfilter.php → icwp-processor-commentsfilter_antibotspam.php}
RENAMED
@@ -15,26 +15,11 @@
|
|
15 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
*/
|
17 |
|
18 |
-
require_once( dirname(__FILE__).'/icwp-basedb
|
19 |
|
20 |
-
if ( !class_exists('
|
21 |
|
22 |
-
class
|
23 |
-
|
24 |
-
const TableName = 'comments_filter';
|
25 |
-
const Spam_Blacklist_Source = 'https://raw.githubusercontent.com/splorp/wordpress-comment-blacklist/master/blacklist.txt';
|
26 |
-
|
27 |
-
const TWODAYS = 172800;
|
28 |
-
|
29 |
-
/**
|
30 |
-
* @var string
|
31 |
-
*/
|
32 |
-
static protected $sSpamBlacklistFile;
|
33 |
-
|
34 |
-
/**
|
35 |
-
* @var string
|
36 |
-
*/
|
37 |
-
static protected $sModeFile_LoginThrottled;
|
38 |
|
39 |
/**
|
40 |
* The unique comment token assigned to this page
|
@@ -43,9 +28,9 @@ class ICWP_CommentsFilterProcessor_V2 extends ICWP_BaseDbProcessor_WPSF {
|
|
43 |
protected $sUniqueCommentToken;
|
44 |
/**
|
45 |
* The unique comment token assigned to this page
|
46 |
-
* @var
|
47 |
*/
|
48 |
-
protected $
|
49 |
/**
|
50 |
* @var string
|
51 |
*/
|
@@ -55,20 +40,11 @@ class ICWP_CommentsFilterProcessor_V2 extends ICWP_BaseDbProcessor_WPSF {
|
|
55 |
*/
|
56 |
protected $sCommentStatusExplanation;
|
57 |
|
58 |
-
/**
|
59 |
-
* Flag as to whether Two Factor Authentication will be by-passed when sending the verification
|
60 |
-
* email fails.
|
61 |
-
*
|
62 |
-
* @var boolean
|
63 |
-
*/
|
64 |
-
protected $m_fAllowTwoFactorByPass;
|
65 |
-
|
66 |
/**
|
67 |
* @param ICWP_WPSF_FeatureHandler_CommentsFilter $oFeatureOptions
|
68 |
*/
|
69 |
public function __construct( ICWP_WPSF_FeatureHandler_CommentsFilter $oFeatureOptions ) {
|
70 |
-
parent::__construct( $oFeatureOptions,
|
71 |
-
$this->createTable();
|
72 |
$this->reset();
|
73 |
}
|
74 |
|
@@ -80,7 +56,6 @@ class ICWP_CommentsFilterProcessor_V2 extends ICWP_BaseDbProcessor_WPSF {
|
|
80 |
$this->sUniqueCommentToken = '';
|
81 |
$this->sCommentStatus = '';
|
82 |
$this->sCommentStatusExplanation = '';
|
83 |
-
self::$sSpamBlacklistFile = $this->oFeatureOptions->getResourcesDir().'spamblacklist.txt';
|
84 |
}
|
85 |
|
86 |
/**
|
@@ -89,28 +64,45 @@ class ICWP_CommentsFilterProcessor_V2 extends ICWP_BaseDbProcessor_WPSF {
|
|
89 |
parent::run();
|
90 |
|
91 |
// Add GASP checking to the comment form.
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
|
|
|
|
|
|
96 |
|
97 |
-
|
98 |
-
|
99 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
100 |
}
|
101 |
|
102 |
/**
|
103 |
* @param array $aCommentData
|
104 |
* @return array
|
105 |
*/
|
106 |
-
public function
|
107 |
|
108 |
if ( !$this->getIfDoCommentsCheck() ) {
|
109 |
return $aCommentData;
|
110 |
}
|
111 |
|
112 |
$this->doGaspCommentCheck( $aCommentData['comment_post_ID'] );
|
113 |
-
$this->doBlacklistSpamCheck( $aCommentData );
|
114 |
|
115 |
// Now we check whether comment status is to completely reject and then we simply redirect to "home"
|
116 |
if ( $this->sCommentStatus == 'reject' ) {
|
@@ -121,18 +113,6 @@ class ICWP_CommentsFilterProcessor_V2 extends ICWP_BaseDbProcessor_WPSF {
|
|
121 |
return $aCommentData;
|
122 |
}
|
123 |
|
124 |
-
/**
|
125 |
-
* @param string $sCommentContent
|
126 |
-
* @return string
|
127 |
-
*/
|
128 |
-
public function doCommentContentPreProcess_Filter( $sCommentContent ) {
|
129 |
-
// If either spam filtering process left an explanation, we add it here
|
130 |
-
if ( !empty( $this->sCommentStatusExplanation ) ) {
|
131 |
-
$sCommentContent = $this->sCommentStatusExplanation.$sCommentContent;
|
132 |
-
}
|
133 |
-
return $sCommentContent;
|
134 |
-
}
|
135 |
-
|
136 |
/**
|
137 |
* Performs the actual GASP comment checking
|
138 |
*
|
@@ -152,14 +132,13 @@ class ICWP_CommentsFilterProcessor_V2 extends ICWP_BaseDbProcessor_WPSF {
|
|
152 |
$fIsSpam = true;
|
153 |
$sExplanation = '';
|
154 |
|
155 |
-
$this->loadDataProcessor();
|
156 |
-
|
157 |
-
$
|
158 |
-
$
|
159 |
-
$sFieldCommentToken = ICWP_WPSF_DataProcessor::FetchPost( 'comment_token' );
|
160 |
|
161 |
// we have the cb name, is it set?
|
162 |
-
if( !$sFieldCheckboxName ||
|
163 |
$sExplanation = sprintf( _wpsf__('Failed GASP Bot Filter Test (%s)' ), _wpsf__('checkbox') );
|
164 |
$sStatKey = 'checkbox';
|
165 |
}
|
@@ -184,148 +163,6 @@ class ICWP_CommentsFilterProcessor_V2 extends ICWP_BaseDbProcessor_WPSF {
|
|
184 |
}
|
185 |
}
|
186 |
|
187 |
-
/**
|
188 |
-
* @param $aCommentData
|
189 |
-
*/
|
190 |
-
protected function doBlacklistSpamCheck( $aCommentData ) {
|
191 |
-
$this->loadDataProcessor();
|
192 |
-
$this->doBlacklistSpamCheck_Action(
|
193 |
-
$aCommentData['comment_author'],
|
194 |
-
$aCommentData['comment_author_email'],
|
195 |
-
$aCommentData['comment_author_url'],
|
196 |
-
$aCommentData['comment_content'],
|
197 |
-
long2ip( self::$nRequestIp ),
|
198 |
-
isset( $_SERVER['HTTP_USER_AGENT'] ) ? substr( $_SERVER['HTTP_USER_AGENT'], 0, 254 ) : ''
|
199 |
-
);
|
200 |
-
}
|
201 |
-
|
202 |
-
/**
|
203 |
-
* Does the same as the WordPress blacklist filter, but more intelligently and with a nod towards much higher performance.
|
204 |
-
*
|
205 |
-
* It also uses defined options for which fields are checked for SPAM instead of just checking EVERYTHING!
|
206 |
-
*
|
207 |
-
* @param string $sAuthor
|
208 |
-
* @param string $sEmail
|
209 |
-
* @param string $sUrl
|
210 |
-
* @param string $sComment
|
211 |
-
* @param string $sUserIp
|
212 |
-
* @param string $sUserAgent
|
213 |
-
*/
|
214 |
-
public function doBlacklistSpamCheck_Action( $sAuthor, $sEmail, $sUrl, $sComment, $sUserIp, $sUserAgent ) {
|
215 |
-
|
216 |
-
// Check that we haven't already marked the comment through another scan, say GASP
|
217 |
-
if ( !empty( $this->sCommentStatus ) || !$this->getIsOption('enable_comments_human_spam_filter', 'Y') ) {
|
218 |
-
return;
|
219 |
-
}
|
220 |
-
|
221 |
-
// read the file of spam words
|
222 |
-
$sSpamWords = $this->getSpamBlacklist();
|
223 |
-
if ( empty($sSpamWords) ) {
|
224 |
-
return;
|
225 |
-
}
|
226 |
-
$aWords = explode( "\n", $sSpamWords );
|
227 |
-
|
228 |
-
$aItemsMap = array(
|
229 |
-
'comment_content' => $sComment,
|
230 |
-
'url' => $sUrl,
|
231 |
-
'author_name' => $sAuthor,
|
232 |
-
'author_email' => $sEmail,
|
233 |
-
'ip_address' => $sUserIp,
|
234 |
-
'user_agent' => $sUserAgent
|
235 |
-
);
|
236 |
-
$aDesiredItemsToCheck = $this->getOption('enable_comments_human_spam_filter_items');
|
237 |
-
$aItemsToCheck = array();
|
238 |
-
foreach( $aDesiredItemsToCheck as $sKey ) {
|
239 |
-
$aItemsToCheck[$sKey] = $aItemsMap[$sKey];
|
240 |
-
}
|
241 |
-
|
242 |
-
foreach( $aItemsToCheck as $sKey => $sItem ) {
|
243 |
-
foreach ( $aWords as $sWord ) {
|
244 |
-
if ( stripos( $sItem, $sWord ) !== false ) {
|
245 |
-
//mark as spam and exit;
|
246 |
-
$this->doStatIncrement( sprintf( 'spam.human.%s', $sKey ) );
|
247 |
-
$this->doStatHumanSpamWords( $sWord );
|
248 |
-
$this->sCommentStatus = $this->getOption('comments_default_action_human_spam');
|
249 |
-
$this->setCommentStatusExplanation( sprintf( _wpsf__('Human SPAM filter found "%s" in "%s"' ), $sWord, $sKey ) );
|
250 |
-
break 2;
|
251 |
-
}
|
252 |
-
}
|
253 |
-
}
|
254 |
-
}
|
255 |
-
|
256 |
-
/**
|
257 |
-
* @param $sStatWord
|
258 |
-
*/
|
259 |
-
protected function doStatHumanSpamWords( $sStatWord = '' ) {
|
260 |
-
$this->loadWpsfStatsProcessor();
|
261 |
-
if ( !empty( $sStatWord ) ) {
|
262 |
-
ICWP_Stats_WPSF::DoStatIncrementKeyValue( 'spam.human.words', base64_encode( $sStatWord ) );
|
263 |
-
}
|
264 |
-
}
|
265 |
-
|
266 |
-
/**
|
267 |
-
* @return null|string
|
268 |
-
*/
|
269 |
-
protected function getSpamBlacklist() {
|
270 |
-
$oFs = $this->loadFileSystemProcessor();
|
271 |
-
|
272 |
-
// first, does the file exist? If not import
|
273 |
-
if ( !$oFs->exists( self::$sSpamBlacklistFile ) ) {
|
274 |
-
$this->doSpamBlacklistImport();
|
275 |
-
}
|
276 |
-
// second, if it exists and it's older than 48hrs, update
|
277 |
-
else if ( self::$nRequestTimestamp - $oFs->getModifiedTime( self::$sSpamBlacklistFile ) > self::TWODAYS ) {
|
278 |
-
$this->doSpamBlacklistUpdate();
|
279 |
-
}
|
280 |
-
|
281 |
-
$sList = $oFs->getFileContent( self::$sSpamBlacklistFile );
|
282 |
-
return empty($sList)? '' : $sList;
|
283 |
-
}
|
284 |
-
|
285 |
-
/**
|
286 |
-
*/
|
287 |
-
protected function doSpamBlacklistUpdate() {
|
288 |
-
$oFs = $this->loadFileSystemProcessor();
|
289 |
-
$oFs->deleteFile( self::$sSpamBlacklistFile );
|
290 |
-
$this->doSpamBlacklistImport();
|
291 |
-
}
|
292 |
-
|
293 |
-
/**
|
294 |
-
*/
|
295 |
-
protected function doSpamBlacklistImport() {
|
296 |
-
$oFs = $this->loadFileSystemProcessor();
|
297 |
-
if ( !$oFs->exists( self::$sSpamBlacklistFile ) ) {
|
298 |
-
|
299 |
-
$sRawList = $this->doSpamBlacklistDownload();
|
300 |
-
|
301 |
-
if ( empty($sRawList) ) {
|
302 |
-
$sList = '';
|
303 |
-
}
|
304 |
-
else {
|
305 |
-
// filter out empty lines
|
306 |
-
$aWords = explode( "\n", $sRawList );
|
307 |
-
foreach ( $aWords as $nIndex => $sWord ) {
|
308 |
-
$sWord = trim($sWord);
|
309 |
-
if ( empty($sWord) ) {
|
310 |
-
unset( $aWords[$nIndex] );
|
311 |
-
}
|
312 |
-
}
|
313 |
-
$sList = implode( "\n", $aWords );
|
314 |
-
}
|
315 |
-
|
316 |
-
// save the list to disk for the future.
|
317 |
-
$oFs->putFileContent( self::$sSpamBlacklistFile, $sList );
|
318 |
-
}
|
319 |
-
}
|
320 |
-
|
321 |
-
/**
|
322 |
-
* @return string
|
323 |
-
*/
|
324 |
-
protected function doSpamBlacklistDownload() {
|
325 |
-
$oFs = $this->loadFileSystemProcessor();
|
326 |
-
return $oFs->getUrlContent( self::Spam_Blacklist_Source );
|
327 |
-
}
|
328 |
-
|
329 |
/**
|
330 |
* @return void
|
331 |
*/
|
@@ -337,10 +174,6 @@ class ICWP_CommentsFilterProcessor_V2 extends ICWP_BaseDbProcessor_WPSF {
|
|
337 |
|
338 |
$this->deleteOldPostCommentTokens();
|
339 |
$this->insertUniquePostCommentToken();
|
340 |
-
|
341 |
-
$this->loadDataProcessor();
|
342 |
-
$this->m_sUniqueFormId = ICWP_WPSF_DataProcessor::GenerateRandomString( rand(7, 23), true );
|
343 |
-
|
344 |
echo $this->getGaspCommentsHookHtml();
|
345 |
}
|
346 |
|
@@ -353,11 +186,8 @@ class ICWP_CommentsFilterProcessor_V2 extends ICWP_BaseDbProcessor_WPSF {
|
|
353 |
|
354 |
// Compatibility with shoutbox WP Wall Plugin
|
355 |
// http://wordpress.org/plugins/wp-wall/
|
356 |
-
if (
|
357 |
-
|
358 |
-
if ( !is_null( ICWP_WPSF_DataProcessor::FetchPost('submit_wall_post') ) ) {
|
359 |
-
return false;
|
360 |
-
}
|
361 |
}
|
362 |
|
363 |
//First, are comments allowed on this post?
|
@@ -385,14 +215,24 @@ class ICWP_CommentsFilterProcessor_V2 extends ICWP_BaseDbProcessor_WPSF {
|
|
385 |
// Compatibility with shoutbox WP Wall Plugin
|
386 |
// http://wordpress.org/plugins/wp-wall/
|
387 |
if ( function_exists( 'WPWall_Init' ) ) {
|
388 |
-
$this->loadDataProcessor();
|
389 |
-
if ( !is_null(
|
390 |
return false;
|
391 |
}
|
392 |
}
|
393 |
return true;
|
394 |
}
|
395 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
396 |
/**
|
397 |
* @return void
|
398 |
*/
|
@@ -406,34 +246,28 @@ class ICWP_CommentsFilterProcessor_V2 extends ICWP_BaseDbProcessor_WPSF {
|
|
406 |
* @return string
|
407 |
*/
|
408 |
protected function getGaspCommentsHookHtml() {
|
409 |
-
$
|
410 |
-
$sReturn = '<p id="'.$sId.'"></p>'; // we use this unique <p> to hook onto using javascript
|
411 |
$sReturn .= '<input type="hidden" id="_sugar_sweet_email" name="sugar_sweet_email" value="" />';
|
412 |
-
$sReturn .= '<input type="hidden" id="_comment_token" name="comment_token" value="'.$this->
|
413 |
return $sReturn;
|
414 |
}
|
415 |
|
416 |
protected function getGaspCommentsHtml() {
|
417 |
|
418 |
-
$sId = $this->
|
419 |
$sConfirm = stripslashes( $this->getOption('custom_message_checkbox') );
|
420 |
$sAlert = stripslashes( $this->getOption('custom_message_alert') );
|
421 |
$sCommentWait = stripslashes( $this->getOption('custom_message_comment_wait') );
|
422 |
$nCooldown = $this->getOption('comments_cooldown_interval');
|
423 |
$nExpire = $this->getOption('comments_token_expire_interval');
|
424 |
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
$sJsCommentWait = '"'.$sJsCommentWait.'"';
|
429 |
-
}
|
430 |
-
else {
|
431 |
-
$sJsCommentWait = '"'. $this->getOption('custom_message_comment_wait').'"';
|
432 |
-
}
|
433 |
$sCommentReload = $this->getOption('custom_message_comment_reload');
|
434 |
|
435 |
$sReturn = "
|
436 |
-
<script type
|
437 |
|
438 |
function cb_click$sId() {
|
439 |
cb_name$sId.value=cb$sId.name;
|
@@ -560,33 +394,7 @@ class ICWP_CommentsFilterProcessor_V2 extends ICWP_BaseDbProcessor_WPSF {
|
|
560 |
}
|
561 |
}
|
562 |
|
563 |
-
|
564 |
-
* We set the final approval status of the comments if we've set it in our scans, and empties the notification email
|
565 |
-
* in case we "trash" it (since WP sends out a notification email if it's anything but SPAM)
|
566 |
-
*
|
567 |
-
* @param $sApprovalStatus
|
568 |
-
* @return string
|
569 |
-
*/
|
570 |
-
public function doSetCommentStatus_Filter( $sApprovalStatus ) {
|
571 |
-
add_filter( 'comment_notification_recipients', array( $this, 'doClearCommentNotificationEmail_Filter' ), 100, 1 );
|
572 |
-
return empty( $this->sCommentStatus )? $sApprovalStatus : $this->sCommentStatus;
|
573 |
-
}
|
574 |
-
|
575 |
-
/**
|
576 |
-
* When you set a new comment as anything but 'spam' a notification email is sent to the post author.
|
577 |
-
* We suppress this for when we mark as trash by emptying the email notifications list.
|
578 |
-
*
|
579 |
-
* @param $aEmails
|
580 |
-
* @return array
|
581 |
-
*/
|
582 |
-
public function doClearCommentNotificationEmail_Filter( $aEmails ) {
|
583 |
-
if ( $this->sCommentStatus == 'trash' ) {
|
584 |
-
$aEmails = array();
|
585 |
-
}
|
586 |
-
return $aEmails;
|
587 |
-
}
|
588 |
-
|
589 |
-
public function createTable() {
|
590 |
// Set up comments ID table
|
591 |
$sSqlTables = "CREATE TABLE IF NOT EXISTS `%s` (
|
592 |
`id` int(11) NOT NULL AUTO_INCREMENT,
|
@@ -597,8 +405,7 @@ class ICWP_CommentsFilterProcessor_V2 extends ICWP_BaseDbProcessor_WPSF {
|
|
597 |
`deleted_at` int(15) NOT NULL DEFAULT '0',
|
598 |
PRIMARY KEY (`id`)
|
599 |
) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
|
600 |
-
|
601 |
-
return $this->doSql( $sSqlTables );
|
602 |
}
|
603 |
|
604 |
/**
|
@@ -690,7 +497,7 @@ class ICWP_CommentsFilterProcessor_V2 extends ICWP_BaseDbProcessor_WPSF {
|
|
690 |
* @return string
|
691 |
*/
|
692 |
protected function getUniqueCommentToken() {
|
693 |
-
if (
|
694 |
$this->sUniqueCommentToken = $this->generateUniqueToken();
|
695 |
}
|
696 |
return $this->sUniqueCommentToken;
|
@@ -721,7 +528,3 @@ class ICWP_CommentsFilterProcessor_V2 extends ICWP_BaseDbProcessor_WPSF {
|
|
721 |
}
|
722 |
}
|
723 |
endif;
|
724 |
-
|
725 |
-
if ( !class_exists('ICWP_WPSF_CommentsFilterProcessor') ):
|
726 |
-
class ICWP_WPSF_CommentsFilterProcessor extends ICWP_CommentsFilterProcessor_V2 { }
|
727 |
-
endif;
|
15 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
*/
|
17 |
|
18 |
+
require_once( dirname(__FILE__).'/icwp-processor-basedb.php' );
|
19 |
|
20 |
+
if ( !class_exists('ICWP_WPSF_Processor_CommentsFilter_AntiBotSpam') ):
|
21 |
|
22 |
+
class ICWP_WPSF_Processor_CommentsFilter_AntiBotSpam extends ICWP_WPSF_BaseDbProcessor {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
|
24 |
/**
|
25 |
* The unique comment token assigned to this page
|
28 |
protected $sUniqueCommentToken;
|
29 |
/**
|
30 |
* The unique comment token assigned to this page
|
31 |
+
* @var string
|
32 |
*/
|
33 |
+
protected $sUniqueFormId;
|
34 |
/**
|
35 |
* @var string
|
36 |
*/
|
40 |
*/
|
41 |
protected $sCommentStatusExplanation;
|
42 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
/**
|
44 |
* @param ICWP_WPSF_FeatureHandler_CommentsFilter $oFeatureOptions
|
45 |
*/
|
46 |
public function __construct( ICWP_WPSF_FeatureHandler_CommentsFilter $oFeatureOptions ) {
|
47 |
+
parent::__construct( $oFeatureOptions, $oFeatureOptions->getCommentsFilterTableName() );
|
|
|
48 |
$this->reset();
|
49 |
}
|
50 |
|
56 |
$this->sUniqueCommentToken = '';
|
57 |
$this->sCommentStatus = '';
|
58 |
$this->sCommentStatusExplanation = '';
|
|
|
59 |
}
|
60 |
|
61 |
/**
|
64 |
parent::run();
|
65 |
|
66 |
// Add GASP checking to the comment form.
|
67 |
+
add_action( 'comment_form', array( $this, 'printGaspFormHook_Action' ), 1 );
|
68 |
+
add_action( 'comment_form', array( $this, 'printGaspFormParts_Action' ), 2 );
|
69 |
+
add_filter( 'preprocess_comment', array( $this, 'doCommentChecking' ), 1, 1 );
|
70 |
+
|
71 |
+
add_filter( $this->getFeatureOptions()->doPluginPrefix( 'comments_filter_status' ), array( $this, 'getCommentStatus' ), 1 );
|
72 |
+
add_filter( $this->getFeatureOptions()->doPluginPrefix( 'comments_filter_status_explanation' ), array( $this, 'getCommentStatusExplanation' ), 1 );
|
73 |
+
}
|
74 |
|
75 |
+
/**
|
76 |
+
* A private plugin filter that lets us return up the newly set comment status.
|
77 |
+
*
|
78 |
+
* @param $sCurrentCommentStatus
|
79 |
+
* @return string
|
80 |
+
*/
|
81 |
+
public function getCommentStatus( $sCurrentCommentStatus ) {
|
82 |
+
return empty( $sCurrentCommentStatus )? $this->sCommentStatus : $sCurrentCommentStatus;
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* A private plugin filter that lets us return up the newly set comment status explanation
|
87 |
+
*
|
88 |
+
* @param $sCurrentCommentStatusExplanation
|
89 |
+
* @return string
|
90 |
+
*/
|
91 |
+
public function getCommentStatusExplanation( $sCurrentCommentStatusExplanation ) {
|
92 |
+
return empty( $sCurrentCommentStatusExplanation )? $this->sCommentStatusExplanation : $sCurrentCommentStatusExplanation;
|
93 |
}
|
94 |
|
95 |
/**
|
96 |
* @param array $aCommentData
|
97 |
* @return array
|
98 |
*/
|
99 |
+
public function doCommentChecking( $aCommentData ) {
|
100 |
|
101 |
if ( !$this->getIfDoCommentsCheck() ) {
|
102 |
return $aCommentData;
|
103 |
}
|
104 |
|
105 |
$this->doGaspCommentCheck( $aCommentData['comment_post_ID'] );
|
|
|
106 |
|
107 |
// Now we check whether comment status is to completely reject and then we simply redirect to "home"
|
108 |
if ( $this->sCommentStatus == 'reject' ) {
|
113 |
return $aCommentData;
|
114 |
}
|
115 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
116 |
/**
|
117 |
* Performs the actual GASP comment checking
|
118 |
*
|
132 |
$fIsSpam = true;
|
133 |
$sExplanation = '';
|
134 |
|
135 |
+
$oDp = $this->loadDataProcessor();
|
136 |
+
$sFieldCheckboxName = $oDp->FetchPost( 'cb_nombre' );
|
137 |
+
$sFieldHoney = $oDp->FetchPost( 'sugar_sweet_email' );
|
138 |
+
$sFieldCommentToken = $oDp->FetchPost( 'comment_token' );
|
|
|
139 |
|
140 |
// we have the cb name, is it set?
|
141 |
+
if( !$sFieldCheckboxName || !$oDp->FetchPost( $sFieldCheckboxName ) ) {
|
142 |
$sExplanation = sprintf( _wpsf__('Failed GASP Bot Filter Test (%s)' ), _wpsf__('checkbox') );
|
143 |
$sStatKey = 'checkbox';
|
144 |
}
|
163 |
}
|
164 |
}
|
165 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
166 |
/**
|
167 |
* @return void
|
168 |
*/
|
174 |
|
175 |
$this->deleteOldPostCommentTokens();
|
176 |
$this->insertUniquePostCommentToken();
|
|
|
|
|
|
|
|
|
177 |
echo $this->getGaspCommentsHookHtml();
|
178 |
}
|
179 |
|
186 |
|
187 |
// Compatibility with shoutbox WP Wall Plugin
|
188 |
// http://wordpress.org/plugins/wp-wall/
|
189 |
+
if ( !$this->getIfDoGaspCheck() ) {
|
190 |
+
return false;
|
|
|
|
|
|
|
191 |
}
|
192 |
|
193 |
//First, are comments allowed on this post?
|
215 |
// Compatibility with shoutbox WP Wall Plugin
|
216 |
// http://wordpress.org/plugins/wp-wall/
|
217 |
if ( function_exists( 'WPWall_Init' ) ) {
|
218 |
+
$oDp = $this->loadDataProcessor();
|
219 |
+
if ( !is_null( $oDp->FetchPost( 'submit_wall_post' ) ) ) {
|
220 |
return false;
|
221 |
}
|
222 |
}
|
223 |
return true;
|
224 |
}
|
225 |
|
226 |
+
/**
|
227 |
+
* @return string
|
228 |
+
*/
|
229 |
+
protected function getUniqueFormId() {
|
230 |
+
if ( !isset( $this->sUniqueFormId ) ) {
|
231 |
+
$this->sUniqueFormId = $this->loadDataProcessor()->GenerateRandomString( rand(7, 23), true );
|
232 |
+
}
|
233 |
+
return $this->sUniqueFormId;
|
234 |
+
}
|
235 |
+
|
236 |
/**
|
237 |
* @return void
|
238 |
*/
|
246 |
* @return string
|
247 |
*/
|
248 |
protected function getGaspCommentsHookHtml() {
|
249 |
+
$sReturn = '<p id="'.$this->getUniqueFormId().'"></p>'; // we use this unique <p> to hook onto using javascript
|
|
|
250 |
$sReturn .= '<input type="hidden" id="_sugar_sweet_email" name="sugar_sweet_email" value="" />';
|
251 |
+
$sReturn .= '<input type="hidden" id="_comment_token" name="comment_token" value="'.$this->getUniqueCommentToken().'" />';
|
252 |
return $sReturn;
|
253 |
}
|
254 |
|
255 |
protected function getGaspCommentsHtml() {
|
256 |
|
257 |
+
$sId = $this->getUniqueFormId();
|
258 |
$sConfirm = stripslashes( $this->getOption('custom_message_checkbox') );
|
259 |
$sAlert = stripslashes( $this->getOption('custom_message_alert') );
|
260 |
$sCommentWait = stripslashes( $this->getOption('custom_message_comment_wait') );
|
261 |
$nCooldown = $this->getOption('comments_cooldown_interval');
|
262 |
$nExpire = $this->getOption('comments_token_expire_interval');
|
263 |
|
264 |
+
$sJsCommentWait = '"'.str_replace( '%s', '"+nRemaining+"', $sCommentWait ).'"';
|
265 |
+
$sCommentWait = str_replace( '%s', $nCooldown, $sCommentWait );
|
266 |
+
|
|
|
|
|
|
|
|
|
|
|
267 |
$sCommentReload = $this->getOption('custom_message_comment_reload');
|
268 |
|
269 |
$sReturn = "
|
270 |
+
<script type=\"text/javascript\">
|
271 |
|
272 |
function cb_click$sId() {
|
273 |
cb_name$sId.value=cb$sId.name;
|
394 |
}
|
395 |
}
|
396 |
|
397 |
+
public function getCreateTableSql() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
398 |
// Set up comments ID table
|
399 |
$sSqlTables = "CREATE TABLE IF NOT EXISTS `%s` (
|
400 |
`id` int(11) NOT NULL AUTO_INCREMENT,
|
405 |
`deleted_at` int(15) NOT NULL DEFAULT '0',
|
406 |
PRIMARY KEY (`id`)
|
407 |
) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
|
408 |
+
return sprintf( $sSqlTables, $this->getTableName() );
|
|
|
409 |
}
|
410 |
|
411 |
/**
|
497 |
* @return string
|
498 |
*/
|
499 |
protected function getUniqueCommentToken() {
|
500 |
+
if ( empty( $this->sUniqueCommentToken ) ) {
|
501 |
$this->sUniqueCommentToken = $this->generateUniqueToken();
|
502 |
}
|
503 |
return $this->sUniqueCommentToken;
|
528 |
}
|
529 |
}
|
530 |
endif;
|
|
|
|
|
|
|
|
src/icwp-processor-commentsfilter_humanspam.php
ADDED
@@ -0,0 +1,309 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
+
* All rights reserved.
|
5 |
+
*
|
6 |
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
7 |
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
8 |
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
9 |
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
10 |
+
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
11 |
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
12 |
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
13 |
+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
14 |
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
15 |
+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
+
*/
|
17 |
+
|
18 |
+
require_once( dirname(__FILE__).'/icwp-processor-base.php' );
|
19 |
+
|
20 |
+
if ( !class_exists('ICWP_WPSF_Processor_CommentsFilter_HumanSpam') ):
|
21 |
+
|
22 |
+
class ICWP_WPSF_Processor_CommentsFilter_HumanSpam extends ICWP_WPSF_Processor_Base {
|
23 |
+
|
24 |
+
const Spam_Blacklist_Source = 'https://raw.githubusercontent.com/splorp/wordpress-comment-blacklist/master/blacklist.txt';
|
25 |
+
|
26 |
+
const TWODAYS = 172800;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @var string
|
30 |
+
*/
|
31 |
+
static protected $sSpamBlacklistFile;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* @var string
|
35 |
+
*/
|
36 |
+
protected $sCommentStatus = '';
|
37 |
+
/**
|
38 |
+
* @var string
|
39 |
+
*/
|
40 |
+
protected $sCommentStatusExplanation = '';
|
41 |
+
|
42 |
+
/**
|
43 |
+
* @param ICWP_WPSF_FeatureHandler_CommentsFilter $oFeatureOptions
|
44 |
+
*/
|
45 |
+
public function __construct( ICWP_WPSF_FeatureHandler_CommentsFilter $oFeatureOptions ) {
|
46 |
+
parent::__construct( $oFeatureOptions );
|
47 |
+
$this->reset();
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Resets the object values to be re-used anew
|
52 |
+
*/
|
53 |
+
public function reset() {
|
54 |
+
parent::reset();
|
55 |
+
$this->sCommentStatus = '';
|
56 |
+
$this->sCommentStatusExplanation = '';
|
57 |
+
self::$sSpamBlacklistFile = $this->getFeatureOptions()->getResourcesDir().'spamblacklist.txt';
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
*/
|
62 |
+
public function run() {
|
63 |
+
|
64 |
+
add_filter( $this->getFeatureOptions()->doPluginPrefix( 'admin_notices' ), array( $this, 'adminNoticeWarningAkismetRunning' ) );
|
65 |
+
|
66 |
+
$oDp = $this->loadDataProcessor();
|
67 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
68 |
+
|
69 |
+
if ( $oDp->GetIsRequestPost() && $oWp->getIsCurrentPage( 'wp-comments-post.php' ) ) {
|
70 |
+
add_filter( 'preprocess_comment', array( $this, 'doCommentChecking' ), 1, 1 );
|
71 |
+
add_filter( $this->getFeatureOptions()->doPluginPrefix( 'comments_filter_status' ), array( $this, 'getCommentStatus' ), 2 );
|
72 |
+
add_filter( $this->getFeatureOptions()->doPluginPrefix( 'comments_filter_status_explanation' ), array( $this, 'getCommentStatusExplanation' ), 2 );
|
73 |
+
}
|
74 |
+
}
|
75 |
+
|
76 |
+
public function adminNoticeWarningAkismetRunning( $aAdminNotices ) {
|
77 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
78 |
+
|
79 |
+
$sActivePluginFile = $oWp->getIsPluginActive( 'Akismet' );
|
80 |
+
if ( $sActivePluginFile ) {
|
81 |
+
$sMessage = _wpsf__( 'It appears you have Akismet Anti-SPAM running alongside the Simple Firewall Anti-SPAM.' )
|
82 |
+
.' <strong>'._wpsf__('This is not recommended and you should disable Akismet.').'</strong>';
|
83 |
+
$sMessage .= '<br />'.sprintf(
|
84 |
+
'<a href="%s" id="fromIcwp" class="button">%s</a>',
|
85 |
+
$oWp->getPluginDeactivateLink( $sActivePluginFile ),
|
86 |
+
_wpsf__( 'Click to deactivate Akismet now' )
|
87 |
+
);
|
88 |
+
$aAdminNotices[] = $this->getAdminNoticeHtml( $sMessage, 'error' );
|
89 |
+
}
|
90 |
+
return $aAdminNotices;
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* A private plugin filter that lets us return up the newly set comment status.
|
95 |
+
*
|
96 |
+
* @param $sCurrentCommentStatus
|
97 |
+
* @return string
|
98 |
+
*/
|
99 |
+
public function getCommentStatus( $sCurrentCommentStatus ) {
|
100 |
+
return empty( $sCurrentCommentStatus )? $this->sCommentStatus : $sCurrentCommentStatus;
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* A private plugin filter that lets us return up the newly set comment status explanation
|
105 |
+
*
|
106 |
+
* @param $sCurrentCommentStatusExplanation
|
107 |
+
* @return string
|
108 |
+
*/
|
109 |
+
public function getCommentStatusExplanation( $sCurrentCommentStatusExplanation ) {
|
110 |
+
return empty( $sCurrentCommentStatusExplanation )? $this->sCommentStatusExplanation : $sCurrentCommentStatusExplanation;
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Tells us whether, for this particular comment post, if we should do comments checking.
|
115 |
+
*
|
116 |
+
* @return boolean
|
117 |
+
*/
|
118 |
+
protected function getIfDoCommentsCheck() {
|
119 |
+
|
120 |
+
// First, are comments allowed on this post?
|
121 |
+
global $post;
|
122 |
+
if ( !isset( $post ) || $post->comment_status != 'open' ) {
|
123 |
+
return false;
|
124 |
+
}
|
125 |
+
|
126 |
+
if ( !is_user_logged_in() ) {
|
127 |
+
return true;
|
128 |
+
}
|
129 |
+
else if ( $this->getIsOption('enable_comments_gasp_protection_for_logged_in', 'Y') ) {
|
130 |
+
return true;
|
131 |
+
}
|
132 |
+
return false;
|
133 |
+
}
|
134 |
+
|
135 |
+
/**
|
136 |
+
* @param array $aCommentData
|
137 |
+
* @return array
|
138 |
+
*/
|
139 |
+
public function doCommentChecking( $aCommentData ) {
|
140 |
+
|
141 |
+
if ( !$this->getIfDoCommentsCheck() ) {
|
142 |
+
return $aCommentData;
|
143 |
+
}
|
144 |
+
|
145 |
+
$this->doBlacklistSpamCheck( $aCommentData );
|
146 |
+
|
147 |
+
// Now we check whether comment status is to completely reject and then we simply redirect to "home"
|
148 |
+
if ( $this->sCommentStatus == 'reject' ) {
|
149 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
150 |
+
$oWp->redirectToHome();
|
151 |
+
}
|
152 |
+
|
153 |
+
return $aCommentData;
|
154 |
+
}
|
155 |
+
|
156 |
+
/**
|
157 |
+
* @param $aCommentData
|
158 |
+
*/
|
159 |
+
protected function doBlacklistSpamCheck( $aCommentData ) {
|
160 |
+
$this->loadDataProcessor();
|
161 |
+
$this->doBlacklistSpamCheck_Action(
|
162 |
+
$aCommentData['comment_author'],
|
163 |
+
$aCommentData['comment_author_email'],
|
164 |
+
$aCommentData['comment_author_url'],
|
165 |
+
$aCommentData['comment_content'],
|
166 |
+
long2ip( self::$nRequestIp ),
|
167 |
+
isset( $_SERVER['HTTP_USER_AGENT'] ) ? substr( $_SERVER['HTTP_USER_AGENT'], 0, 254 ) : ''
|
168 |
+
);
|
169 |
+
}
|
170 |
+
|
171 |
+
/**
|
172 |
+
* Does the same as the WordPress blacklist filter, but more intelligently and with a nod towards much higher performance.
|
173 |
+
*
|
174 |
+
* It also uses defined options for which fields are checked for SPAM instead of just checking EVERYTHING!
|
175 |
+
*
|
176 |
+
* @param string $sAuthor
|
177 |
+
* @param string $sEmail
|
178 |
+
* @param string $sUrl
|
179 |
+
* @param string $sComment
|
180 |
+
* @param string $sUserIp
|
181 |
+
* @param string $sUserAgent
|
182 |
+
*/
|
183 |
+
public function doBlacklistSpamCheck_Action( $sAuthor, $sEmail, $sUrl, $sComment, $sUserIp, $sUserAgent ) {
|
184 |
+
|
185 |
+
// Check that we haven't already marked the comment through another scan, say GASP
|
186 |
+
if ( !empty( $this->sCommentStatus ) || !$this->getIsOption('enable_comments_human_spam_filter', 'Y') ) {
|
187 |
+
return;
|
188 |
+
}
|
189 |
+
|
190 |
+
// read the file of spam words
|
191 |
+
$sSpamWords = $this->getSpamBlacklist();
|
192 |
+
if ( empty($sSpamWords) ) {
|
193 |
+
return;
|
194 |
+
}
|
195 |
+
$aWords = explode( "\n", $sSpamWords );
|
196 |
+
|
197 |
+
$aItemsMap = array(
|
198 |
+
'comment_content' => $sComment,
|
199 |
+
'url' => $sUrl,
|
200 |
+
'author_name' => $sAuthor,
|
201 |
+
'author_email' => $sEmail,
|
202 |
+
'ip_address' => $sUserIp,
|
203 |
+
'user_agent' => $sUserAgent
|
204 |
+
);
|
205 |
+
$aDesiredItemsToCheck = $this->getOption('enable_comments_human_spam_filter_items');
|
206 |
+
$aItemsToCheck = array();
|
207 |
+
foreach( $aDesiredItemsToCheck as $sKey ) {
|
208 |
+
$aItemsToCheck[$sKey] = $aItemsMap[$sKey];
|
209 |
+
}
|
210 |
+
|
211 |
+
foreach( $aItemsToCheck as $sKey => $sItem ) {
|
212 |
+
foreach ( $aWords as $sWord ) {
|
213 |
+
if ( stripos( $sItem, $sWord ) !== false ) {
|
214 |
+
//mark as spam and exit;
|
215 |
+
$this->doStatIncrement( sprintf( 'spam.human.%s', $sKey ) );
|
216 |
+
$this->doStatHumanSpamWords( $sWord );
|
217 |
+
$this->sCommentStatus = $this->getOption( 'comments_default_action_human_spam' );
|
218 |
+
$this->setCommentStatusExplanation( sprintf( _wpsf__('Human SPAM filter found "%s" in "%s"' ), $sWord, $sKey ) );
|
219 |
+
break 2;
|
220 |
+
}
|
221 |
+
}
|
222 |
+
}
|
223 |
+
}
|
224 |
+
|
225 |
+
/**
|
226 |
+
* @param $sStatWord
|
227 |
+
*/
|
228 |
+
protected function doStatHumanSpamWords( $sStatWord = '' ) {
|
229 |
+
$this->loadStatsProcessor();
|
230 |
+
if ( !empty( $sStatWord ) ) {
|
231 |
+
ICWP_Stats_WPSF::DoStatIncrementKeyValue( 'spam.human.words', base64_encode( $sStatWord ) );
|
232 |
+
}
|
233 |
+
}
|
234 |
+
|
235 |
+
/**
|
236 |
+
* @return null|string
|
237 |
+
*/
|
238 |
+
protected function getSpamBlacklist() {
|
239 |
+
$oFs = $this->loadFileSystemProcessor();
|
240 |
+
|
241 |
+
// first, does the file exist? If not import
|
242 |
+
if ( !$oFs->exists( self::$sSpamBlacklistFile ) ) {
|
243 |
+
$this->doSpamBlacklistImport();
|
244 |
+
}
|
245 |
+
// second, if it exists and it's older than 48hrs, update
|
246 |
+
else if ( self::$nRequestTimestamp - $oFs->getModifiedTime( self::$sSpamBlacklistFile ) > self::TWODAYS ) {
|
247 |
+
$this->doSpamBlacklistUpdate();
|
248 |
+
}
|
249 |
+
|
250 |
+
$sList = $oFs->getFileContent( self::$sSpamBlacklistFile );
|
251 |
+
return empty($sList)? '' : $sList;
|
252 |
+
}
|
253 |
+
|
254 |
+
/**
|
255 |
+
*/
|
256 |
+
protected function doSpamBlacklistUpdate() {
|
257 |
+
$oFs = $this->loadFileSystemProcessor();
|
258 |
+
$oFs->deleteFile( self::$sSpamBlacklistFile );
|
259 |
+
$this->doSpamBlacklistImport();
|
260 |
+
}
|
261 |
+
|
262 |
+
/**
|
263 |
+
*/
|
264 |
+
protected function doSpamBlacklistImport() {
|
265 |
+
$oFs = $this->loadFileSystemProcessor();
|
266 |
+
if ( !$oFs->exists( self::$sSpamBlacklistFile ) ) {
|
267 |
+
|
268 |
+
$sRawList = $this->doSpamBlacklistDownload();
|
269 |
+
|
270 |
+
if ( empty($sRawList) ) {
|
271 |
+
$sList = '';
|
272 |
+
}
|
273 |
+
else {
|
274 |
+
// filter out empty lines
|
275 |
+
$aWords = explode( "\n", $sRawList );
|
276 |
+
foreach ( $aWords as $nIndex => $sWord ) {
|
277 |
+
$sWord = trim($sWord);
|
278 |
+
if ( empty($sWord) ) {
|
279 |
+
unset( $aWords[$nIndex] );
|
280 |
+
}
|
281 |
+
}
|
282 |
+
$sList = implode( "\n", $aWords );
|
283 |
+
}
|
284 |
+
|
285 |
+
// save the list to disk for the future.
|
286 |
+
$oFs->putFileContent( self::$sSpamBlacklistFile, $sList );
|
287 |
+
}
|
288 |
+
}
|
289 |
+
|
290 |
+
/**
|
291 |
+
* @return string
|
292 |
+
*/
|
293 |
+
protected function doSpamBlacklistDownload() {
|
294 |
+
$oFs = $this->loadFileSystemProcessor();
|
295 |
+
return $oFs->getUrlContent( self::Spam_Blacklist_Source );
|
296 |
+
}
|
297 |
+
|
298 |
+
/**
|
299 |
+
* @param $sExplanation
|
300 |
+
*/
|
301 |
+
protected function setCommentStatusExplanation( $sExplanation ) {
|
302 |
+
$this->sCommentStatusExplanation =
|
303 |
+
'[* '.sprintf( _wpsf__('WordPress Simple Firewall plugin marked this comment as "%s" because: %s.'),
|
304 |
+
$this->sCommentStatus,
|
305 |
+
$sExplanation
|
306 |
+
)." *]\n";
|
307 |
+
}
|
308 |
+
}
|
309 |
+
endif;
|
src/icwp-processor-email.php
CHANGED
@@ -15,11 +15,11 @@
|
|
15 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
*/
|
17 |
|
18 |
-
require_once( dirname(__FILE__).'/icwp-base
|
19 |
|
20 |
if ( !class_exists('ICWP_EmailProcessor_V1') ):
|
21 |
|
22 |
-
class ICWP_EmailProcessor_V1 extends
|
23 |
|
24 |
const Slug = 'email';
|
25 |
|
@@ -179,7 +179,7 @@ class ICWP_EmailProcessor_V1 extends ICWP_WPSF_BaseProcessor {
|
|
179 |
*/
|
180 |
public function getDefaultRecipientAddress() {
|
181 |
$oWpFunctions = $this->loadWpFunctionsProcessor();
|
182 |
-
return apply_filters( $this->
|
183 |
}
|
184 |
|
185 |
/**
|
@@ -200,6 +200,6 @@ class ICWP_EmailProcessor_V1 extends ICWP_WPSF_BaseProcessor {
|
|
200 |
|
201 |
endif;
|
202 |
|
203 |
-
if ( !class_exists('
|
204 |
-
class
|
205 |
endif;
|
15 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
*/
|
17 |
|
18 |
+
require_once( dirname(__FILE__).'/icwp-processor-base.php' );
|
19 |
|
20 |
if ( !class_exists('ICWP_EmailProcessor_V1') ):
|
21 |
|
22 |
+
class ICWP_EmailProcessor_V1 extends ICWP_WPSF_Processor_Base {
|
23 |
|
24 |
const Slug = 'email';
|
25 |
|
179 |
*/
|
180 |
public function getDefaultRecipientAddress() {
|
181 |
$oWpFunctions = $this->loadWpFunctionsProcessor();
|
182 |
+
return apply_filters( $this->getFeatureOptions()->doPluginPrefix( 'report_email_address' ), $oWpFunctions->getSiteAdminEmail() );
|
183 |
}
|
184 |
|
185 |
/**
|
200 |
|
201 |
endif;
|
202 |
|
203 |
+
if ( !class_exists('ICWP_WPSF_Processor_Email') ):
|
204 |
+
class ICWP_WPSF_Processor_Email extends ICWP_EmailProcessor_V1 { }
|
205 |
endif;
|
src/icwp-processor-firewall.php
CHANGED
@@ -15,11 +15,11 @@
|
|
15 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
*/
|
17 |
|
18 |
-
require_once( dirname(__FILE__).'/icwp-base
|
19 |
|
20 |
if ( !class_exists('ICWP_FirewallProcessor_V1') ):
|
21 |
|
22 |
-
class ICWP_FirewallProcessor_V1 extends
|
23 |
|
24 |
protected $m_aWhitelistPages;
|
25 |
protected $m_aWhitelistPagesPatterns;
|
@@ -73,25 +73,7 @@ class ICWP_FirewallProcessor_V1 extends ICWP_WPSF_BaseProcessor {
|
|
73 |
$sMessage = _wpsf__( "You were blocked by the %sWordPress Simple Firewall%s." );
|
74 |
$this->m_sFirewallMessage = sprintf( $sMessage, '<a href="http://wordpress.org/plugins/wp-simple-firewall/" target="_blank">', '</a>');
|
75 |
}
|
76 |
-
|
77 |
-
/**
|
78 |
-
* @see ICWP_WPSF_BaseProcessor::setOptions()
|
79 |
-
*/
|
80 |
-
public function setOptions( &$aOptions ) {
|
81 |
-
parent::setOptions( $aOptions );
|
82 |
-
$this->m_aCustomWhitelistPageParams = is_array( $this->getOption( 'page_params_whitelist' ) )? $this->getOption( 'page_params_whitelist' ) : array();
|
83 |
-
}
|
84 |
|
85 |
-
/**
|
86 |
-
* @return boolean
|
87 |
-
*/
|
88 |
-
public function getNeedsEmailHandler() {
|
89 |
-
if ( $this->getIsOption( 'block_send_email', 'Y' ) ) {
|
90 |
-
return true;
|
91 |
-
}
|
92 |
-
return false;
|
93 |
-
}
|
94 |
-
|
95 |
public function reset() {
|
96 |
parent::reset();
|
97 |
$this->m_nLoopProtect = 0;
|
@@ -109,7 +91,7 @@ class ICWP_FirewallProcessor_V1 extends ICWP_WPSF_BaseProcessor {
|
|
109 |
* Should return false when logging is disabled.
|
110 |
*
|
111 |
* @return false|array - false when logging is disabled, array with log data otherwise
|
112 |
-
* @see
|
113 |
*/
|
114 |
public function flushLogData() {
|
115 |
|
@@ -154,8 +136,8 @@ class ICWP_FirewallProcessor_V1 extends ICWP_WPSF_BaseProcessor {
|
|
154 |
return true;
|
155 |
}
|
156 |
|
157 |
-
$this->loadDataProcessor();
|
158 |
-
if ( $this->getOption('ignore_search_engines') == 'Y' &&
|
159 |
$this->logInfo( _wpsf__('Visitor detected as Search Engine Bot so by-passing Firewall Checking.') );
|
160 |
return true;
|
161 |
}
|
@@ -591,7 +573,7 @@ class ICWP_FirewallProcessor_V1 extends ICWP_WPSF_BaseProcessor {
|
|
591 |
)
|
592 |
);
|
593 |
|
594 |
-
$aCustomWhitelistPageParams = is_array( $this->getOption( 'page_params_whitelist' )
|
595 |
$this->m_aWhitelistPages = array_merge( $aDefaultWlPages, $aCustomWhitelistPageParams );
|
596 |
|
597 |
$this->m_aWhitelistPagesPatterns = array(
|
@@ -637,6 +619,6 @@ class ICWP_FirewallProcessor_V1 extends ICWP_WPSF_BaseProcessor {
|
|
637 |
|
638 |
endif;
|
639 |
|
640 |
-
if ( !class_exists('
|
641 |
-
class
|
642 |
endif;
|
15 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
*/
|
17 |
|
18 |
+
require_once( dirname(__FILE__).'/icwp-processor-base.php' );
|
19 |
|
20 |
if ( !class_exists('ICWP_FirewallProcessor_V1') ):
|
21 |
|
22 |
+
class ICWP_FirewallProcessor_V1 extends ICWP_WPSF_Processor_Base {
|
23 |
|
24 |
protected $m_aWhitelistPages;
|
25 |
protected $m_aWhitelistPagesPatterns;
|
73 |
$sMessage = _wpsf__( "You were blocked by the %sWordPress Simple Firewall%s." );
|
74 |
$this->m_sFirewallMessage = sprintf( $sMessage, '<a href="http://wordpress.org/plugins/wp-simple-firewall/" target="_blank">', '</a>');
|
75 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
76 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
public function reset() {
|
78 |
parent::reset();
|
79 |
$this->m_nLoopProtect = 0;
|
91 |
* Should return false when logging is disabled.
|
92 |
*
|
93 |
* @return false|array - false when logging is disabled, array with log data otherwise
|
94 |
+
* @see ICWP_WPSF_Processor_Base::getLogData()
|
95 |
*/
|
96 |
public function flushLogData() {
|
97 |
|
136 |
return true;
|
137 |
}
|
138 |
|
139 |
+
$oDp = $this->loadDataProcessor();
|
140 |
+
if ( $this->getOption('ignore_search_engines') == 'Y' && $oDp->IsSearchEngineBot() ) {
|
141 |
$this->logInfo( _wpsf__('Visitor detected as Search Engine Bot so by-passing Firewall Checking.') );
|
142 |
return true;
|
143 |
}
|
573 |
)
|
574 |
);
|
575 |
|
576 |
+
$aCustomWhitelistPageParams = is_array( $this->getOption( 'page_params_whitelist' ) )? $this->getOption( 'page_params_whitelist' ) : array();
|
577 |
$this->m_aWhitelistPages = array_merge( $aDefaultWlPages, $aCustomWhitelistPageParams );
|
578 |
|
579 |
$this->m_aWhitelistPagesPatterns = array(
|
619 |
|
620 |
endif;
|
621 |
|
622 |
+
if ( !class_exists('ICWP_WPSF_Processor_Firewall') ):
|
623 |
+
class ICWP_WPSF_Processor_Firewall extends ICWP_FirewallProcessor_V1 { }
|
624 |
endif;
|
src/icwp-processor-lockdown.php
CHANGED
@@ -15,136 +15,140 @@
|
|
15 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
*/
|
17 |
|
18 |
-
require_once( dirname(__FILE__).'/icwp-base
|
19 |
|
20 |
if ( !class_exists('ICWP_LockdownProcessor_V1') ):
|
21 |
|
22 |
-
class ICWP_LockdownProcessor_V1 extends
|
23 |
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
|
|
|
|
38 |
}
|
39 |
-
add_filter( 'user_has_cap', array( $this, 'disableFileEditing' ), 0, 3 );
|
40 |
-
}
|
41 |
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
// add_filter( 'bloginfo', array( $this, 'maskWordpressVersion' ), 1, 2 );
|
47 |
// add_filter( 'bloginfo_url', array( $this, 'maskWordpressVersion' ), 1, 2 );
|
48 |
-
|
49 |
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
|
54 |
-
|
55 |
-
|
56 |
-
|
|
|
|
|
57 |
}
|
58 |
-
force_ssl_login( true );
|
59 |
-
}
|
60 |
|
61 |
-
|
62 |
-
|
63 |
-
|
|
|
|
|
64 |
}
|
65 |
-
force_ssl_admin( true );
|
66 |
-
}
|
67 |
|
68 |
-
|
69 |
-
|
|
|
70 |
}
|
71 |
-
}
|
72 |
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
$
|
80 |
-
|
81 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
82 |
return $aAllCaps;
|
83 |
}
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
//
|
93 |
-
// $insOutput = $this->aOptions['mask_wordpress_version'];
|
94 |
// }
|
95 |
-
// return $
|
96 |
-
}
|
97 |
-
|
98 |
-
/**
|
99 |
-
*
|
100 |
-
*/
|
101 |
-
public function resetAuthKeysSalts() {
|
102 |
-
$oWpFs = $this->loadFileSystemProcessor();
|
103 |
-
|
104 |
-
// Get the new Salts
|
105 |
-
$sSaltsUrl = 'https://api.wordpress.org/secret-key/1.1/salt/';
|
106 |
-
$sSalts = $oWpFs->getUrlContent( $sSaltsUrl );
|
107 |
-
|
108 |
-
$sWpConfigContent = $oWpFs->getContent_WpConfig();
|
109 |
-
if ( is_null( $sWpConfigContent ) ) {
|
110 |
-
return;
|
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 |
-
$fKeyFound = true;
|
139 |
}
|
|
|
|
|
140 |
}
|
141 |
-
$aContent[$nStartLine] = $sSalts;
|
142 |
-
$oWpFs->putContent_WpConfig( implode( PHP_EOL, $aContent ) );
|
143 |
}
|
144 |
-
}
|
145 |
|
146 |
endif;
|
147 |
|
148 |
-
if ( !class_exists('
|
149 |
-
class
|
150 |
endif;
|
15 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
*/
|
17 |
|
18 |
+
require_once( dirname(__FILE__).'/icwp-processor-base.php' );
|
19 |
|
20 |
if ( !class_exists('ICWP_LockdownProcessor_V1') ):
|
21 |
|
22 |
+
class ICWP_LockdownProcessor_V1 extends ICWP_WPSF_Processor_Base {
|
23 |
|
24 |
+
/**
|
25 |
+
* @param ICWP_WPSF_FeatureHandler_Lockdown $oFeatureOptions
|
26 |
+
*/
|
27 |
+
public function __construct( ICWP_WPSF_FeatureHandler_Lockdown $oFeatureOptions ) {
|
28 |
+
parent::__construct( $oFeatureOptions );
|
29 |
+
}
|
30 |
|
31 |
+
/**
|
32 |
+
*/
|
33 |
+
public function run() {
|
34 |
+
|
35 |
+
if ( $this->getIsOption( 'disable_file_editing', 'Y' ) ) {
|
36 |
+
if ( !defined('DISALLOW_FILE_EDIT') ) {
|
37 |
+
define( 'DISALLOW_FILE_EDIT', true );
|
38 |
+
}
|
39 |
+
add_filter( 'user_has_cap', array( $this, 'disableFileEditing' ), 0, 3 );
|
40 |
}
|
|
|
|
|
41 |
|
42 |
+
$sWpVersionMask = $this->getOption('mask_wordpress_version');
|
43 |
+
if ( !empty( $sWpVersionMask ) ) {
|
44 |
+
global $wp_version;
|
45 |
+
$wp_version = $sWpVersionMask;
|
46 |
// add_filter( 'bloginfo', array( $this, 'maskWordpressVersion' ), 1, 2 );
|
47 |
// add_filter( 'bloginfo_url', array( $this, 'maskWordpressVersion' ), 1, 2 );
|
48 |
+
}
|
49 |
|
50 |
+
if ( false && $this->getOption('action_reset_auth_salts') == 'Y' ) {
|
51 |
+
add_action( 'init', array( $this, 'resetAuthKeysSalts' ), 1 );
|
52 |
+
}
|
53 |
|
54 |
+
if ( $this->getIsOption( 'force_ssl_login', 'Y' ) && function_exists('force_ssl_login') ) {
|
55 |
+
if ( !defined('FORCE_SSL_LOGIN') ) {
|
56 |
+
define( 'FORCE_SSL_LOGIN', true );
|
57 |
+
}
|
58 |
+
force_ssl_login( true );
|
59 |
}
|
|
|
|
|
60 |
|
61 |
+
if ( $this->getIsOption( 'force_ssl_admin', 'Y' ) && function_exists('force_ssl_admin') ) {
|
62 |
+
if ( !defined('FORCE_SSL_ADMIN') ) {
|
63 |
+
define( 'FORCE_SSL_ADMIN', true );
|
64 |
+
}
|
65 |
+
force_ssl_admin( true );
|
66 |
}
|
|
|
|
|
67 |
|
68 |
+
if ( $this->getIsOption( 'hide_wordpress_generator_tag', 'Y' ) ) {
|
69 |
+
remove_action( 'wp_head', 'wp_generator' );
|
70 |
+
}
|
71 |
}
|
|
|
72 |
|
73 |
+
/**
|
74 |
+
* @param array $aAllCaps
|
75 |
+
* @param $cap
|
76 |
+
* @param array $aArgs
|
77 |
+
* @return array
|
78 |
+
*/
|
79 |
+
public function disableFileEditing( $aAllCaps, $cap, $aArgs ) {
|
80 |
+
|
81 |
+
$aEditCapabilities = array( 'edit_themes', 'edit_plugins', 'edit_files' );
|
82 |
+
$sRequestedCapability = $aArgs[0];
|
83 |
+
|
84 |
+
if ( !in_array( $sRequestedCapability, $aEditCapabilities ) ) {
|
85 |
+
return $aAllCaps;
|
86 |
+
}
|
87 |
+
$aAllCaps[ $sRequestedCapability ] = false;
|
88 |
return $aAllCaps;
|
89 |
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* @param $sOutput
|
93 |
+
* @param $sShow
|
94 |
+
* @return string
|
95 |
+
*/
|
96 |
+
public function maskWordpressVersion( $sOutput, $sShow ) {
|
97 |
+
// if ( $sShow === 'version' ) {
|
98 |
+
// $sOutput = $this->aOptions['mask_wordpress_version'];
|
|
|
99 |
// }
|
100 |
+
// return $sOutput;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
101 |
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
*/
|
105 |
+
public function resetAuthKeysSalts() {
|
106 |
+
$oWpFs = $this->loadFileSystemProcessor();
|
107 |
+
|
108 |
+
// Get the new Salts
|
109 |
+
$sSaltsUrl = 'https://api.wordpress.org/secret-key/1.1/salt/';
|
110 |
+
$sSalts = $oWpFs->getUrlContent( $sSaltsUrl );
|
111 |
+
|
112 |
+
$sWpConfigContent = $oWpFs->getContent_WpConfig();
|
113 |
+
if ( is_null( $sWpConfigContent ) ) {
|
114 |
+
return;
|
115 |
+
}
|
116 |
+
|
117 |
+
$aKeys = array(
|
118 |
+
'AUTH_KEY',
|
119 |
+
'SECURE_AUTH_KEY',
|
120 |
+
'LOGGED_IN_KEY',
|
121 |
+
'NONCE_KEY',
|
122 |
+
'AUTH_SALT',
|
123 |
+
'SECURE_AUTH_SALT',
|
124 |
+
'LOGGED_IN_SALT',
|
125 |
+
'NONCE_SALT'
|
126 |
+
);
|
127 |
+
|
128 |
+
$aContent = explode( PHP_EOL, $sWpConfigContent );
|
129 |
+
$fKeyFound = false;
|
130 |
+
$nStartLine = 0;
|
131 |
+
foreach( $aContent as $nLineNumber => $sLine ) {
|
132 |
+
foreach( $aKeys as $nPosition => $sKey ) {
|
133 |
+
if ( strpos( $sLine, $sKey ) === false ) {
|
134 |
+
continue;
|
135 |
+
}
|
136 |
+
if ( $nStartLine == 0 ) {
|
137 |
+
$nStartLine = $nLineNumber;
|
138 |
+
}
|
139 |
+
else {
|
140 |
+
unset( $aContent[ $nLineNumber ] );
|
141 |
+
}
|
142 |
+
$fKeyFound = true;
|
143 |
}
|
|
|
144 |
}
|
145 |
+
$aContent[$nStartLine] = $sSalts;
|
146 |
+
$oWpFs->putContent_WpConfig( implode( PHP_EOL, $aContent ) );
|
147 |
}
|
|
|
|
|
148 |
}
|
|
|
149 |
|
150 |
endif;
|
151 |
|
152 |
+
if ( !class_exists('ICWP_WPSF_Processor_Lockdown') ):
|
153 |
+
class ICWP_WPSF_Processor_Lockdown extends ICWP_LockdownProcessor_V1 { }
|
154 |
endif;
|
src/icwp-processor-logging.php
CHANGED
@@ -15,13 +15,12 @@
|
|
15 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
*/
|
17 |
|
18 |
-
require_once( dirname(__FILE__).'/icwp-basedb
|
19 |
|
20 |
if ( !class_exists('ICWP_LoggingProcessor_V1') ):
|
21 |
|
22 |
-
class ICWP_LoggingProcessor_V1 extends
|
23 |
|
24 |
-
const TableName = 'wpsf_log';
|
25 |
const DaysToKeepLog = 7;
|
26 |
|
27 |
protected $sVisitorRequestId;
|
@@ -30,11 +29,9 @@ class ICWP_LoggingProcessor_V1 extends ICWP_BaseDbProcessor_WPSF {
|
|
30 |
* @param ICWP_WPSF_FeatureHandler_Logging $oFeatureOptions
|
31 |
*/
|
32 |
public function __construct( ICWP_WPSF_FeatureHandler_Logging $oFeatureOptions ) {
|
33 |
-
parent::__construct( $oFeatureOptions,
|
34 |
-
$this->createTable();
|
35 |
}
|
36 |
|
37 |
-
|
38 |
public function reset() {
|
39 |
parent::reset();
|
40 |
$this->m_sRequestId = uniqid();
|
@@ -77,8 +74,11 @@ class ICWP_LoggingProcessor_V1 extends ICWP_BaseDbProcessor_WPSF {
|
|
77 |
}
|
78 |
return $inaLogData;
|
79 |
}
|
80 |
-
|
81 |
-
|
|
|
|
|
|
|
82 |
// Set up log table
|
83 |
$sSqlTables = "CREATE TABLE IF NOT EXISTS `%s` (
|
84 |
`id` int(11) NOT NULL AUTO_INCREMENT,
|
@@ -91,8 +91,7 @@ class ICWP_LoggingProcessor_V1 extends ICWP_BaseDbProcessor_WPSF {
|
|
91 |
`deleted_at` int(15) NOT NULL DEFAULT '0',
|
92 |
PRIMARY KEY (`id`)
|
93 |
) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
|
94 |
-
|
95 |
-
return $this->doSql( $sSqlTables );
|
96 |
}
|
97 |
|
98 |
public function handleInstallUpgrade( $insCurrentVersion = '' ) {
|
@@ -118,6 +117,6 @@ class ICWP_LoggingProcessor_V1 extends ICWP_BaseDbProcessor_WPSF {
|
|
118 |
|
119 |
endif;
|
120 |
|
121 |
-
if ( !class_exists('
|
122 |
-
class
|
123 |
endif;
|
15 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
*/
|
17 |
|
18 |
+
require_once( dirname(__FILE__).'/icwp-processor-basedb.php' );
|
19 |
|
20 |
if ( !class_exists('ICWP_LoggingProcessor_V1') ):
|
21 |
|
22 |
+
class ICWP_LoggingProcessor_V1 extends ICWP_WPSF_BaseDbProcessor {
|
23 |
|
|
|
24 |
const DaysToKeepLog = 7;
|
25 |
|
26 |
protected $sVisitorRequestId;
|
29 |
* @param ICWP_WPSF_FeatureHandler_Logging $oFeatureOptions
|
30 |
*/
|
31 |
public function __construct( ICWP_WPSF_FeatureHandler_Logging $oFeatureOptions ) {
|
32 |
+
parent::__construct( $oFeatureOptions, $oFeatureOptions->getGeneralLoggingTableName() );
|
|
|
33 |
}
|
34 |
|
|
|
35 |
public function reset() {
|
36 |
parent::reset();
|
37 |
$this->m_sRequestId = uniqid();
|
74 |
}
|
75 |
return $inaLogData;
|
76 |
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* @return string
|
80 |
+
*/
|
81 |
+
public function getCreateTableSql() {
|
82 |
// Set up log table
|
83 |
$sSqlTables = "CREATE TABLE IF NOT EXISTS `%s` (
|
84 |
`id` int(11) NOT NULL AUTO_INCREMENT,
|
91 |
`deleted_at` int(15) NOT NULL DEFAULT '0',
|
92 |
PRIMARY KEY (`id`)
|
93 |
) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
|
94 |
+
return sprintf( $sSqlTables, $this->getTableName() );
|
|
|
95 |
}
|
96 |
|
97 |
public function handleInstallUpgrade( $insCurrentVersion = '' ) {
|
117 |
|
118 |
endif;
|
119 |
|
120 |
+
if ( !class_exists('ICWP_WPSF_Processor_Logging') ):
|
121 |
+
class ICWP_WPSF_Processor_Logging extends ICWP_LoggingProcessor_V1 { }
|
122 |
endif;
|
src/icwp-processor-login_protect.php
ADDED
@@ -0,0 +1,225 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
+
* All rights reserved.
|
5 |
+
*
|
6 |
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
7 |
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
8 |
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
9 |
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
10 |
+
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
11 |
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
12 |
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
13 |
+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
14 |
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
15 |
+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
+
*/
|
17 |
+
|
18 |
+
require_once( dirname(__FILE__).'/icwp-processor-base.php' );
|
19 |
+
|
20 |
+
if ( !class_exists('ICWP_WPSF_Processor_LoginProtect_V4') ):
|
21 |
+
|
22 |
+
class ICWP_WPSF_Processor_LoginProtect_V4 extends ICWP_WPSF_Processor_Base {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var ICWP_WPSF_FeatureHandler_LoginProtect
|
26 |
+
*/
|
27 |
+
protected $oFeatureOptions;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @var ICWP_WPSF_Processor_LoginProtect_Gasp
|
31 |
+
*/
|
32 |
+
protected $oProcessorGasp;
|
33 |
+
|
34 |
+
/**
|
35 |
+
* @var ICWP_WPSF_Processor_LoginProtect_Cooldown
|
36 |
+
*/
|
37 |
+
protected $oProcessorCooldown;
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @var ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth
|
41 |
+
*/
|
42 |
+
protected $oProcessorTwoFactor;
|
43 |
+
|
44 |
+
/**
|
45 |
+
* @var ICWP_WPSF_Processor_LoginProtect_Yubikey
|
46 |
+
*/
|
47 |
+
protected $oProcessorYubikey;
|
48 |
+
|
49 |
+
/**
|
50 |
+
* @param ICWP_WPSF_FeatureHandler_LoginProtect $oFeatureOptions
|
51 |
+
*/
|
52 |
+
public function __construct( ICWP_WPSF_FeatureHandler_LoginProtect $oFeatureOptions ) {
|
53 |
+
parent::__construct( $oFeatureOptions );
|
54 |
+
$this->reset();
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* @return bool|void
|
59 |
+
*/
|
60 |
+
public function getIsLogging() {
|
61 |
+
return $this->getIsOption( 'enable_login_protect_log', 'Y' );
|
62 |
+
}
|
63 |
+
|
64 |
+
/**
|
65 |
+
*/
|
66 |
+
public function run() {
|
67 |
+
parent::run();
|
68 |
+
$oDp = $this->loadDataProcessor();
|
69 |
+
$fIsPost = $oDp->GetIsRequestPost();
|
70 |
+
|
71 |
+
$aWhitelist = $this->getOption( 'ips_whitelist', array() );
|
72 |
+
if ( !empty( $aWhitelist ) && $this->isIpOnlist( $aWhitelist, self::$nRequestIp ) ) {
|
73 |
+
return true;
|
74 |
+
}
|
75 |
+
|
76 |
+
$oWp = $this->oFeatureOptions->loadWpFunctionsProcessor();
|
77 |
+
// XML-RPC Compatibility
|
78 |
+
if ( $oWp->getIsXmlrpc() && $this->getIsOption( 'enable_xmlrpc_compatibility', 'Y' ) ) {
|
79 |
+
return true;
|
80 |
+
}
|
81 |
+
|
82 |
+
// check for remote posting before anything else.
|
83 |
+
if ( $fIsPost && $this->getIsOption( 'enable_prevent_remote_post', 'Y' ) ) {
|
84 |
+
add_filter( 'authenticate', array( $this, 'checkRemotePostLogin_Filter' ), 9, 3);
|
85 |
+
}
|
86 |
+
|
87 |
+
// Add GASP checking to the login form.
|
88 |
+
if ( $this->getIsOption( 'enable_login_gasp_check', 'Y' ) ) {
|
89 |
+
$this->getProcessorGasp()->run();
|
90 |
+
}
|
91 |
+
|
92 |
+
if ( $fIsPost && $this->getOption( 'login_limit_interval' ) > 0 ) {
|
93 |
+
$this->getProcessorCooldown()->run();
|
94 |
+
}
|
95 |
+
|
96 |
+
// check for Yubikey auth after user is authenticated with WordPress.
|
97 |
+
if ( $this->getIsOption( 'enable_yubikey', 'Y' ) ) {
|
98 |
+
$this->getProcessorYubikey()->run();
|
99 |
+
}
|
100 |
+
|
101 |
+
if ( $this->oFeatureOptions->getIsTwoFactorAuthOn() ) {
|
102 |
+
$this->getProcessorTwoFactor()->run();
|
103 |
+
}
|
104 |
+
|
105 |
+
add_filter( 'wp_login_errors', array( $this, 'addLoginMessage' ) );
|
106 |
+
}
|
107 |
+
|
108 |
+
/**
|
109 |
+
* @param WP_Error $oError
|
110 |
+
* @return WP_Error
|
111 |
+
*/
|
112 |
+
public function addLoginMessage( $oError ) {
|
113 |
+
|
114 |
+
if ( ! $oError instanceof WP_Error ) {
|
115 |
+
$oError = new WP_Error();
|
116 |
+
}
|
117 |
+
|
118 |
+
$oDp = $this->loadDataProcessor();
|
119 |
+
$sForceLogout = $oDp->FetchGet( 'wpsf-forcelogout' );
|
120 |
+
if ( $sForceLogout == 6 ) {
|
121 |
+
$oError->add( 'wpsf-forcelogout', _wpsf__('Your Two-Factor Authentication Was Verified.').'<br />'._wpsf__('Please login again.') );
|
122 |
+
}
|
123 |
+
return $oError;
|
124 |
+
}
|
125 |
+
|
126 |
+
/**
|
127 |
+
* @param $oUser
|
128 |
+
* @param $sUsername
|
129 |
+
* @param $sPassword
|
130 |
+
* @return mixed
|
131 |
+
*/
|
132 |
+
public function checkRemotePostLogin_Filter( $oUser, $sUsername, $sPassword ) {
|
133 |
+
$oDp = $this->loadDataProcessor();
|
134 |
+
$sHttpRef = $oDp->FetchServer( 'HTTP_REFERER' );
|
135 |
+
|
136 |
+
if ( !empty( $sHttpRef ) ) {
|
137 |
+
$aHttpRefererParts = parse_url( $sHttpRef );
|
138 |
+
$aHomeUrlParts = parse_url( home_url() );
|
139 |
+
|
140 |
+
if ( !empty( $aHttpRefererParts['host'] ) && !empty( $aHomeUrlParts['host'] ) && ( $aHttpRefererParts['host'] === $aHomeUrlParts['host'] ) ) {
|
141 |
+
$this->doStatIncrement( 'login.remotepost.success' );
|
142 |
+
return $oUser;
|
143 |
+
}
|
144 |
+
}
|
145 |
+
|
146 |
+
$this->logWarning(
|
147 |
+
sprintf( _wpsf__('User "%s" attempted to login but the HTTP REFERER was either empty or it was a remote login attempt. Bot Perhaps? HTTP REFERER: "%s".'), $sUsername, $sHttpRef )
|
148 |
+
);
|
149 |
+
$this->doStatIncrement( 'login.remotepost.fail' );
|
150 |
+
wp_die(
|
151 |
+
_wpsf__( 'Sorry, you must login directly from within the site.' )
|
152 |
+
.' '._wpsf__( 'Remote login is not supported.' )
|
153 |
+
.'<br /><a href="http://icwp.io/4n" target="_blank">→'._wpsf__('More Info').'</a>'
|
154 |
+
);
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Should return false when logging is disabled.
|
159 |
+
*
|
160 |
+
* @return false|array - false when logging is disabled, array with log data otherwise
|
161 |
+
* @see ICWP_WPSF_Processor_Base::getLogData()
|
162 |
+
*/
|
163 |
+
public function flushLogData() {
|
164 |
+
|
165 |
+
if ( !$this->getIsLogging() || empty( $this->m_aLogMessages ) ) {
|
166 |
+
return false;
|
167 |
+
}
|
168 |
+
|
169 |
+
$this->m_aLog = array(
|
170 |
+
'category' => self::LOG_CATEGORY_LOGINPROTECT,
|
171 |
+
'messages' => serialize( $this->m_aLogMessages )
|
172 |
+
);
|
173 |
+
$this->resetLog();
|
174 |
+
return $this->m_aLog;
|
175 |
+
}
|
176 |
+
|
177 |
+
/**
|
178 |
+
* @return ICWP_WPSF_Processor_LoginProtect_Cooldown
|
179 |
+
*/
|
180 |
+
protected function getProcessorCooldown() {
|
181 |
+
if ( !isset( $this->oProcessorCooldown ) ) {
|
182 |
+
require_once('icwp-processor-loginprotect_cooldown.php');
|
183 |
+
$this->oProcessorCooldown = new ICWP_WPSF_Processor_LoginProtect_Cooldown( $this->oFeatureOptions );
|
184 |
+
}
|
185 |
+
return $this->oProcessorCooldown;
|
186 |
+
}
|
187 |
+
|
188 |
+
/**
|
189 |
+
* @return ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth
|
190 |
+
*/
|
191 |
+
protected function getProcessorTwoFactor() {
|
192 |
+
if ( !isset( $this->oProcessorTwoFactor ) ) {
|
193 |
+
require_once('icwp-processor-loginprotect_twofactorauth.php');
|
194 |
+
$this->oProcessorTwoFactor = new ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth( $this->oFeatureOptions );
|
195 |
+
}
|
196 |
+
return $this->oProcessorTwoFactor;
|
197 |
+
}
|
198 |
+
|
199 |
+
/**
|
200 |
+
* @return ICWP_WPSF_Processor_LoginProtect_Gasp
|
201 |
+
*/
|
202 |
+
protected function getProcessorGasp() {
|
203 |
+
if ( !isset( $this->oProcessorGasp ) ) {
|
204 |
+
require_once( 'icwp-processor-loginprotect_gasp.php' );
|
205 |
+
$this->oProcessorGasp = new ICWP_WPSF_Processor_LoginProtect_Gasp( $this->oFeatureOptions );
|
206 |
+
}
|
207 |
+
return $this->oProcessorGasp;
|
208 |
+
}
|
209 |
+
|
210 |
+
/**
|
211 |
+
* @return ICWP_WPSF_Processor_LoginProtect_Yubikey
|
212 |
+
*/
|
213 |
+
protected function getProcessorYubikey() {
|
214 |
+
if ( !isset( $this->oProcessorYubikey ) ) {
|
215 |
+
require_once('icwp-processor-loginprotect_yubikey.php');
|
216 |
+
$this->oProcessorYubikey = new ICWP_WPSF_Processor_LoginProtect_Yubikey( $this->oFeatureOptions );
|
217 |
+
}
|
218 |
+
return $this->oProcessorYubikey;
|
219 |
+
}
|
220 |
+
}
|
221 |
+
endif;
|
222 |
+
|
223 |
+
if ( !class_exists('ICWP_WPSF_Processor_LoginProtect') ):
|
224 |
+
class ICWP_WPSF_Processor_LoginProtect extends ICWP_WPSF_Processor_LoginProtect_V4 { }
|
225 |
+
endif;
|
src/icwp-processor-loginprotect.php
DELETED
@@ -1,1030 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
-
* All rights reserved.
|
5 |
-
*
|
6 |
-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
7 |
-
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
8 |
-
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
9 |
-
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
10 |
-
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
11 |
-
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
12 |
-
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
13 |
-
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
14 |
-
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
15 |
-
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
-
*/
|
17 |
-
|
18 |
-
require_once( dirname(__FILE__).'/icwp-basedb-processor.php' );
|
19 |
-
|
20 |
-
if ( !class_exists('ICWP_LoginProtectProcessor_V3') ):
|
21 |
-
|
22 |
-
class ICWP_LoginProtectProcessor_V3 extends ICWP_BaseDbProcessor_WPSF {
|
23 |
-
|
24 |
-
const TableName = 'login_auth';
|
25 |
-
const AuthActiveCookie = 'wpsf_auth';
|
26 |
-
const YubikeyVerifyApiUrl = 'https://api.yubico.com/wsapi/2.0/verify?id=%s&otp=%s&nonce=%s';
|
27 |
-
|
28 |
-
/**
|
29 |
-
* @var ICWP_WPSF_FeatureHandler_LoginProtect
|
30 |
-
*/
|
31 |
-
protected $oFeatureOptions;
|
32 |
-
|
33 |
-
/**
|
34 |
-
* @var string
|
35 |
-
*/
|
36 |
-
static protected $sModeFile_LoginThrottled;
|
37 |
-
|
38 |
-
/**
|
39 |
-
* The number of seconds between each authenticated login
|
40 |
-
* @var integer
|
41 |
-
*/
|
42 |
-
protected $m_nRequiredLoginInterval;
|
43 |
-
|
44 |
-
/**
|
45 |
-
* @var integer
|
46 |
-
*/
|
47 |
-
protected $m_nLastLoginTime;
|
48 |
-
/**
|
49 |
-
* @var string
|
50 |
-
*/
|
51 |
-
protected $nDaysToKeepLog = 1;
|
52 |
-
|
53 |
-
/**
|
54 |
-
* @param ICWP_WPSF_FeatureHandler_LoginProtect $oFeatureOptions
|
55 |
-
*/
|
56 |
-
public function __construct( ICWP_WPSF_FeatureHandler_LoginProtect $oFeatureOptions ) {
|
57 |
-
parent::__construct( $oFeatureOptions, self::TableName );
|
58 |
-
$this->createTable();
|
59 |
-
$this->reset();
|
60 |
-
}
|
61 |
-
|
62 |
-
/**
|
63 |
-
* Resets the object values to be re-used anew
|
64 |
-
*/
|
65 |
-
public function reset() {
|
66 |
-
parent::reset();
|
67 |
-
self::$sModeFile_LoginThrottled = dirname( __FILE__ ).'/../mode.login_throttled';
|
68 |
-
}
|
69 |
-
|
70 |
-
/**
|
71 |
-
*
|
72 |
-
* @param array $aOptions
|
73 |
-
*/
|
74 |
-
public function setOptions( &$aOptions ) {
|
75 |
-
parent::setOptions( $aOptions );
|
76 |
-
$this->setLoginCooldownInterval();
|
77 |
-
}
|
78 |
-
|
79 |
-
/**
|
80 |
-
* @return boolean
|
81 |
-
*/
|
82 |
-
public function getNeedsEmailHandler() {
|
83 |
-
return $this->getIsTwoFactorAuthOn();
|
84 |
-
}
|
85 |
-
|
86 |
-
/**
|
87 |
-
* @param string $sType can be either 'ip' or 'cookie'. If empty, both are checked looking for either.
|
88 |
-
* @return bool
|
89 |
-
*/
|
90 |
-
protected function getIsTwoFactorAuthOn( $sType = '' ) {
|
91 |
-
|
92 |
-
$fIp = $this->getIsOption( 'enable_two_factor_auth_by_ip', 'Y' );
|
93 |
-
$fCookie = $this->getIsOption( 'enable_two_factor_auth_by_cookie', 'Y' );
|
94 |
-
|
95 |
-
switch( $sType ) {
|
96 |
-
case 'ip':
|
97 |
-
return $fIp;
|
98 |
-
break;
|
99 |
-
case 'cookie':
|
100 |
-
return $fCookie;
|
101 |
-
break;
|
102 |
-
default:
|
103 |
-
return $fIp || $fCookie;
|
104 |
-
break;
|
105 |
-
}
|
106 |
-
}
|
107 |
-
|
108 |
-
/**
|
109 |
-
* @return bool|void
|
110 |
-
*/
|
111 |
-
public function getIsLogging() {
|
112 |
-
return $this->getIsOption( 'enable_login_protect_log', 'Y' );
|
113 |
-
}
|
114 |
-
|
115 |
-
/**
|
116 |
-
*/
|
117 |
-
public function run() {
|
118 |
-
parent::run();
|
119 |
-
$this->loadDataProcessor();
|
120 |
-
// $this->recreateTable();
|
121 |
-
|
122 |
-
$sRequestMethod = ICWP_WPSF_DataProcessor::ArrayFetch( $_SERVER, 'REQUEST_METHOD' );
|
123 |
-
$fIsPost = strtolower( empty($sRequestMethod)? '' : $sRequestMethod ) == 'post';
|
124 |
-
|
125 |
-
$aWhitelist = $this->getOption( 'ips_whitelist', array() );
|
126 |
-
if ( !empty( $aWhitelist ) && $this->isIpOnlist( $aWhitelist, self::GetVisitorIpAddress() ) ) {
|
127 |
-
return true;
|
128 |
-
}
|
129 |
-
|
130 |
-
// check for remote posting before anything else.
|
131 |
-
if ( $fIsPost && $this->getIsOption('enable_prevent_remote_post', 'Y') ) {
|
132 |
-
add_filter( 'authenticate', array( $this, 'checkRemotePostLogin_Filter' ), 9, 3);
|
133 |
-
}
|
134 |
-
|
135 |
-
// Add GASP checking to the login form.
|
136 |
-
if ( $this->getIsOption('enable_login_gasp_check', 'Y') ) {
|
137 |
-
add_action( 'login_form', array( $this, 'printGaspLoginCheck_Action' ) );
|
138 |
-
add_action( 'woocommerce_login_form', array( $this, 'printGaspLoginCheck_Action' ) );
|
139 |
-
add_filter( 'login_form_middle', array( $this, 'printGaspLoginCheck_Filter' ) );
|
140 |
-
add_filter( 'authenticate', array( $this, 'checkLoginForGasp_Filter' ), 22, 3);
|
141 |
-
}
|
142 |
-
|
143 |
-
// Do GASP checking if it's a form submit.
|
144 |
-
if ( $fIsPost && $this->getOption( 'login_limit_interval' ) > 0 ) {
|
145 |
-
// We give it a priority of 10 so that we can jump in before WordPress does its own validation.
|
146 |
-
add_filter( 'authenticate', array( $this, 'checkLoginInterval_Filter' ), 10, 3);
|
147 |
-
}
|
148 |
-
|
149 |
-
// check for Yubikey auth after user is authenticated with WordPress.
|
150 |
-
if ( $fIsPost && $this->getOption('enable_yubikey') && $this->getIsYubikeyConfigReady() ) {
|
151 |
-
add_filter( 'wp_authenticate_user', array( $this, 'checkYubikeyOtpAuth_Filter' ) );
|
152 |
-
add_action( 'login_form', array( $this, 'printYubikeyOtp_Action' ) );
|
153 |
-
}
|
154 |
-
|
155 |
-
if ( $this->getIsTwoFactorAuthOn() ) {
|
156 |
-
|
157 |
-
// If their click was successful we give them a lovely message
|
158 |
-
if ( ICWP_WPSF_DataProcessor::FetchGet( 'wpsfuserverified' ) ) {
|
159 |
-
add_filter( 'login_message', array( $this, 'displayVerifiedUserMessage_Filter' ) );
|
160 |
-
}
|
161 |
-
|
162 |
-
// Check the current logged-in user every page load.
|
163 |
-
add_action( 'init', array( $this, 'checkCurrentUserAuth_Action' ) );
|
164 |
-
|
165 |
-
// At this stage (30,3) WordPress has already (20) authenticated the user. So if the login
|
166 |
-
// is valid, the filter will have a valid WP_User object passed to it.
|
167 |
-
add_filter( 'authenticate', array( $this, 'checkUserAuthLogin_Filter' ), 30, 3);
|
168 |
-
}
|
169 |
-
}
|
170 |
-
|
171 |
-
/**
|
172 |
-
*/
|
173 |
-
public function printGaspLoginCheck_Action() {
|
174 |
-
echo $this->getGaspLoginHtml();
|
175 |
-
}
|
176 |
-
|
177 |
-
/**
|
178 |
-
* @return string
|
179 |
-
*/
|
180 |
-
public function printGaspLoginCheck_Filter() {
|
181 |
-
return $this->getGaspLoginHtml();
|
182 |
-
}
|
183 |
-
|
184 |
-
/**
|
185 |
-
* @param $inoUser
|
186 |
-
* @param $insUsername
|
187 |
-
* @param $insPassword
|
188 |
-
* @return mixed
|
189 |
-
*/
|
190 |
-
public function checkRemotePostLogin_Filter( $inoUser, $insUsername, $insPassword ) {
|
191 |
-
$this->loadDataProcessor();
|
192 |
-
$sHttpRef = ICWP_WPSF_DataProcessor::ArrayFetch( $_SERVER, 'HTTP_REFERER' );
|
193 |
-
$sHttpRef = is_null( $sHttpRef )? '' : $sHttpRef;
|
194 |
-
if ( empty($sHttpRef) || ( strpos($sHttpRef, home_url()) !== 0 ) ) {
|
195 |
-
$this->logWarning(
|
196 |
-
sprintf( _wpsf__('User "%s" attempted to login but the HTTP REFERER was either empty or it was a remote login attempt. Bot Perhaps? HTTP REFERER: "%s".'), $insUsername, $sHttpRef )
|
197 |
-
);
|
198 |
-
$this->doStatIncrement( 'login.remotepost.fail' );
|
199 |
-
wp_die(
|
200 |
-
_wpsf__( 'Sorry, you must login directly from within the site.' )
|
201 |
-
.'<br /><a href="http://icwp.io/4n" target="_blank">→'._wpsf__('More Info').'</a>'
|
202 |
-
);
|
203 |
-
}
|
204 |
-
else {
|
205 |
-
$this->doStatIncrement( 'login.remotepost.success' );
|
206 |
-
}
|
207 |
-
return $inoUser;
|
208 |
-
}
|
209 |
-
|
210 |
-
/**
|
211 |
-
* @param $inoUser
|
212 |
-
* @param $insUsername
|
213 |
-
* @param $insPassword
|
214 |
-
* @return WP_Error
|
215 |
-
*/
|
216 |
-
public function checkLoginForGasp_Filter( $inoUser, $insUsername, $insPassword ) {
|
217 |
-
|
218 |
-
if ( empty( $insUsername ) || is_wp_error( $inoUser ) ) {
|
219 |
-
return $inoUser;
|
220 |
-
}
|
221 |
-
if ( $this->doGaspChecks( $insUsername ) ) {
|
222 |
-
return $inoUser;
|
223 |
-
}
|
224 |
-
//This doesn't actually ever get returned because we die() within doGaspChecks()
|
225 |
-
return new WP_Error('wpsf_gaspfail', _wpsf__('G.A.S.P. Checking Failed.') );
|
226 |
-
}
|
227 |
-
|
228 |
-
/**
|
229 |
-
* Checks whether the current user that is logged-in is authenticated by IP address.
|
230 |
-
*
|
231 |
-
* If the user is not found to be valid, they're logged out.
|
232 |
-
*
|
233 |
-
* Should be hooked to 'init' so we have is_user_logged_in()
|
234 |
-
*/
|
235 |
-
public function checkCurrentUserAuth_Action() {
|
236 |
-
|
237 |
-
// User has clicked a link in their email to validate their IP address for login.
|
238 |
-
if ( ICWP_WPSF_DataProcessor::FetchGet( 'wpsf-action' ) == 'linkauth' ) {
|
239 |
-
$this->validateUserAuthLink();
|
240 |
-
}
|
241 |
-
|
242 |
-
if ( is_user_logged_in() ) {
|
243 |
-
$this->verifyCurrentUser();
|
244 |
-
}
|
245 |
-
}
|
246 |
-
|
247 |
-
public function displayVerifiedUserMessage_Filter( $insMessage ) {
|
248 |
-
$sStyles = 'background-color: #FAFFE8; border: 1px solid #DDDDDD; margin: 8px 0 10px 8px; padding: 16px;';
|
249 |
-
$insMessage .= '<h3 style="'.$sStyles.'">'._wpsf__('You have successfully verified your identity - you may now login').'</h3>';
|
250 |
-
return $insMessage;
|
251 |
-
}
|
252 |
-
|
253 |
-
/**
|
254 |
-
* Should return false when logging is disabled.
|
255 |
-
*
|
256 |
-
* @return false|array - false when logging is disabled, array with log data otherwise
|
257 |
-
* @see ICWP_WPSF_BaseProcessor::getLogData()
|
258 |
-
*/
|
259 |
-
public function flushLogData() {
|
260 |
-
|
261 |
-
if ( !$this->getIsLogging() || empty( $this->m_aLogMessages ) ) {
|
262 |
-
return false;
|
263 |
-
}
|
264 |
-
|
265 |
-
$this->m_aLog = array(
|
266 |
-
'category' => self::LOG_CATEGORY_LOGINPROTECT,
|
267 |
-
'messages' => serialize( $this->m_aLogMessages )
|
268 |
-
);
|
269 |
-
$this->resetLog();
|
270 |
-
return $this->m_aLog;
|
271 |
-
}
|
272 |
-
|
273 |
-
/**
|
274 |
-
* Checks the link details to ensure all is valid before authorizing the user.
|
275 |
-
*/
|
276 |
-
public function validateUserAuthLink() {
|
277 |
-
$this->loadDataProcessor();
|
278 |
-
// wpsfkey=%s&wpsf-action=%s&username=%s&uniqueid
|
279 |
-
|
280 |
-
if ( ICWP_WPSF_DataProcessor::FetchGet( 'wpsfkey' ) !== $this->oFeatureOptions->getTwoAuthSecretKey() ) {
|
281 |
-
return false;
|
282 |
-
}
|
283 |
-
|
284 |
-
$sUsername = ICWP_WPSF_DataProcessor::FetchGet( 'username' );
|
285 |
-
$sUniqueId = ICWP_WPSF_DataProcessor::FetchGet( 'uniqueid' );
|
286 |
-
if ( empty( $sUsername ) || empty( $sUniqueId ) ) {
|
287 |
-
return false;
|
288 |
-
}
|
289 |
-
|
290 |
-
$aWhere = array(
|
291 |
-
'unique_id' => $sUniqueId,
|
292 |
-
'wp_username' => $sUsername
|
293 |
-
);
|
294 |
-
|
295 |
-
$oWp = $this->loadWpFunctionsProcessor();
|
296 |
-
if ( $this->doMakePendingLoginAuthActive( $aWhere ) ) {
|
297 |
-
$this->logInfo(
|
298 |
-
sprintf( _wpsf__('User "%s" verified their identity using Two-Factor Authentication.'), $sUsername )
|
299 |
-
);
|
300 |
-
$this->setUserLoggedIn( $sUsername );
|
301 |
-
$this->doStatIncrement( 'login.twofactor.verified' );
|
302 |
-
$oWp->redirectToAdmin();
|
303 |
-
}
|
304 |
-
else {
|
305 |
-
$oWp->redirectToHome();
|
306 |
-
}
|
307 |
-
}
|
308 |
-
|
309 |
-
// WordPress Hooks and Filters:
|
310 |
-
|
311 |
-
/**
|
312 |
-
* Should be a filter added to WordPress's "authenticate" filter, but before WordPress performs
|
313 |
-
* it's own authentication (theirs is priority 30, so we could go in at around 20).
|
314 |
-
*
|
315 |
-
* @param null|WP_User|WP_Error $inoUser
|
316 |
-
* @param string $insUsername
|
317 |
-
* @param string $insPassword
|
318 |
-
* @return unknown|WP_Error
|
319 |
-
*/
|
320 |
-
public function checkLoginInterval_Filter( $inoUser, $insUsername, $insPassword ) {
|
321 |
-
// No login attempt was made.
|
322 |
-
if ( empty( $insUsername ) ) {
|
323 |
-
return $inoUser;
|
324 |
-
}
|
325 |
-
|
326 |
-
// Is there an interval set?
|
327 |
-
$this->setLoginCooldownInterval();
|
328 |
-
$nRequiredLoginInterval = $this->m_nRequiredLoginInterval;
|
329 |
-
if ( $nRequiredLoginInterval === false || $nRequiredLoginInterval == 0 ) {
|
330 |
-
return $inoUser;
|
331 |
-
}
|
332 |
-
|
333 |
-
// Get the last login time (and update it also for the next time)
|
334 |
-
$this->m_nLastLoginTime = $this->getLastLoginTime();
|
335 |
-
|
336 |
-
if ( empty( $this->m_nLastLoginTime ) || $this->m_nLastLoginTime < 0 ) {
|
337 |
-
$this->updateLastLoginThrottleTime( self::$nRequestTimestamp );
|
338 |
-
}
|
339 |
-
|
340 |
-
// If we're outside the interval, let the login process proceed as per normal and
|
341 |
-
// update our last login time.
|
342 |
-
$nLoginInterval = self::$nRequestTimestamp - $this->m_nLastLoginTime;
|
343 |
-
if ( $nLoginInterval > $nRequiredLoginInterval ) {
|
344 |
-
$this->updateLastLoginThrottleTime( self::$nRequestTimestamp );
|
345 |
-
$this->doStatIncrement( 'login.cooldown.success' );
|
346 |
-
return $inoUser;
|
347 |
-
}
|
348 |
-
|
349 |
-
// At this point someone has attempted to login within the previous login wait interval
|
350 |
-
// So we remove WordPress's authentication filter and our own user check authentication
|
351 |
-
// And finally return a WP_Error which will be reflected back to the user.
|
352 |
-
$this->doStatIncrement( 'login.cooldown.fail' );
|
353 |
-
remove_filter( 'authenticate', 'wp_authenticate_username_password', 20, 3 ); // wp-includes/user.php
|
354 |
-
remove_filter( 'authenticate', array( $this, 'checkUserAuthLogin_Filter' ), 30, 3);
|
355 |
-
|
356 |
-
$sErrorString = sprintf( _wpsf__( "Login Cooldown in effect. You must wait %s seconds before attempting to login again." ), ($nRequiredLoginInterval - $nLoginInterval ) );
|
357 |
-
$oError = new WP_Error( 'wpsf_logininterval', $sErrorString );
|
358 |
-
return $oError;
|
359 |
-
}
|
360 |
-
|
361 |
-
/**
|
362 |
-
* @return int
|
363 |
-
*/
|
364 |
-
protected function getLastLoginTime() {
|
365 |
-
$oWpFs = $this->loadFileSystemProcessor();
|
366 |
-
// Check that there is a login throttle file. If it exists and its modified time is greater than the
|
367 |
-
// current $this->m_nLastLoginTime it suggests another process has touched the file and updated it
|
368 |
-
// concurrently. So, we update our $this->m_nEmailThrottleTime accordingly.
|
369 |
-
if ( $oWpFs->fileAction( 'file_exists', self::$sModeFile_LoginThrottled ) ) {
|
370 |
-
$nModifiedTime = filemtime( self::$sModeFile_LoginThrottled );
|
371 |
-
if ( $nModifiedTime > $this->m_nLastLoginTime ) {
|
372 |
-
$this->m_nLastLoginTime = $nModifiedTime;
|
373 |
-
}
|
374 |
-
}
|
375 |
-
else { }
|
376 |
-
return $this->m_nLastLoginTime;
|
377 |
-
}
|
378 |
-
|
379 |
-
/**
|
380 |
-
* @param $innLastLoginTime
|
381 |
-
*/
|
382 |
-
public function updateLastLoginThrottleTime( $innLastLoginTime ) {
|
383 |
-
$oWpFs = $this->loadFileSystemProcessor();
|
384 |
-
$this->m_nLastLoginTime = $innLastLoginTime;
|
385 |
-
$oWpFs->fileAction( 'touch', array(self::$sModeFile_LoginThrottled, $innLastLoginTime) );
|
386 |
-
}
|
387 |
-
|
388 |
-
/**
|
389 |
-
*/
|
390 |
-
public function printYubikeyOtp_Action() {
|
391 |
-
$sHtml =
|
392 |
-
'<p class="yubikey-otp">
|
393 |
-
<label>%s<br />
|
394 |
-
<input type="text" name="yubiotp" class="input" value="" size="20" />
|
395 |
-
</label>
|
396 |
-
</p>
|
397 |
-
';
|
398 |
-
echo sprintf( $sHtml, '<a href="http://icwp.io/4i" target="_blank">'._wpsf__('Yubikey OTP').'</a>' );
|
399 |
-
}
|
400 |
-
|
401 |
-
/**
|
402 |
-
* @param WP_User $inoUser
|
403 |
-
* @return WP_User|WP_Error
|
404 |
-
*/
|
405 |
-
public function checkYubikeyOtpAuth_Filter( $inoUser ) {
|
406 |
-
$oError = new WP_Error();
|
407 |
-
|
408 |
-
// Before anything else we check that a Yubikey pair has been provided for this username (and that there are pairs in the first place!)
|
409 |
-
$aYubikeyUsernamePairs = $this->getOption('yubikey_unique_keys');
|
410 |
-
if ( !$this->getIsYubikeyConfigReady() ) { // configuration is clearly not completed yet.
|
411 |
-
return $inoUser;
|
412 |
-
}
|
413 |
-
|
414 |
-
$sOneTimePassword = empty( $_POST['yubiotp'] )? '' : trim( $_POST['yubiotp'] );
|
415 |
-
$sAppId = $this->getOption('yubikey_app_id');
|
416 |
-
$sApiKey = $this->getOption('yubikey_api_key');
|
417 |
-
|
418 |
-
// check that if we have a list of permitted keys, that the one used is on that list connected with the username.
|
419 |
-
$sYubikey12 = substr( $sOneTimePassword, 0 , 12 );
|
420 |
-
$fUsernameFound = false; // if username is never found, it means there's no yubikey specified which means we can bypass this authentication method.
|
421 |
-
$fFoundMatch = false;
|
422 |
-
foreach( $aYubikeyUsernamePairs as $aUsernameYubikeyPair ) {
|
423 |
-
if ( isset( $aUsernameYubikeyPair[$inoUser->user_login] ) ) {
|
424 |
-
$fUsernameFound = true;
|
425 |
-
if ( $aUsernameYubikeyPair[$inoUser->user_login] == $sYubikey12 ) {
|
426 |
-
$fFoundMatch = true;
|
427 |
-
break;
|
428 |
-
}
|
429 |
-
}
|
430 |
-
}
|
431 |
-
|
432 |
-
// If no yubikey-username pair found for given username, we by-pass Yubikey auth.
|
433 |
-
if ( !$fUsernameFound ) {
|
434 |
-
$this->logWarning(
|
435 |
-
sprintf( _wpsf__('User "%s" logged in without a Yubikey One Time Password because no username-yubikey pair was found for this user.'), $inoUser->user_login )
|
436 |
-
);
|
437 |
-
return $inoUser;
|
438 |
-
}
|
439 |
-
|
440 |
-
// Username was found in the list of key pairs, but the yubikey provided didn't match that username.
|
441 |
-
if ( !$fFoundMatch ) {
|
442 |
-
$oError->add(
|
443 |
-
'yubikey_not_allowed',
|
444 |
-
sprintf( _wpsf__( 'ERROR: %s' ), _wpsf__('The Yubikey provided is not on the list of permitted keys for this user.') )
|
445 |
-
);
|
446 |
-
$this->logWarning(
|
447 |
-
sprintf( _wpsf__('User "%s" attempted to login but Yubikey ID used was not in list of authorised keys: "%s".'), $inoUser->user_login, $sYubikey12 )
|
448 |
-
);
|
449 |
-
return $oError;
|
450 |
-
}
|
451 |
-
|
452 |
-
$oFs = $this->loadFileSystemProcessor();
|
453 |
-
|
454 |
-
$sNonce = md5( uniqid( rand() ) );
|
455 |
-
$sUrl = sprintf( self::YubikeyVerifyApiUrl, $sAppId, $sOneTimePassword, $sNonce );
|
456 |
-
$sRawYubiRequest = $oFs->getUrlContent( $sUrl );
|
457 |
-
|
458 |
-
// Validate response.
|
459 |
-
// 1. Check OTP and Nonce
|
460 |
-
if ( !preg_match( '/otp='.$sOneTimePassword.'/', $sRawYubiRequest, $aMatches )
|
461 |
-
|| !preg_match( '/nonce='.$sNonce.'/', $sRawYubiRequest, $aMatches )
|
462 |
-
) {
|
463 |
-
$oError->add(
|
464 |
-
'yubikey_validate_fail',
|
465 |
-
sprintf( _wpsf__( 'ERROR: %s' ), _wpsf__('The Yubikey authentication was not validated successfully.') )
|
466 |
-
);
|
467 |
-
$this->logWarning(
|
468 |
-
sprintf( _wpsf__('User "%s" attempted to login but Yubikey One Time Password failed to validate due to invalid Yubi API.'), $inoUser->user_login )
|
469 |
-
);
|
470 |
-
return $oError;
|
471 |
-
}
|
472 |
-
|
473 |
-
// Optionally we can check the hash, but since we're using HTTPS, this isn't necessary and adds more PHP requirements
|
474 |
-
|
475 |
-
// 2. Check status directly within response
|
476 |
-
preg_match( '/status=([a-zA-Z0-9_]+)/', $sRawYubiRequest, $aMatches );
|
477 |
-
$sStatus = $aMatches[1];
|
478 |
-
|
479 |
-
if ( $sStatus != 'OK' && $sStatus != 'REPLAYED_OTP' ) {
|
480 |
-
$oError->add(
|
481 |
-
'yubikey_validate_fail',
|
482 |
-
sprintf( _wpsf__( 'ERROR: %s' ), _wpsf__('The Yubikey authentication was not validated successfully.') )
|
483 |
-
);
|
484 |
-
$this->logWarning(
|
485 |
-
sprintf( _wpsf__('User "%s" attempted to login but Yubikey One Time Password failed to validate due to invalid Yubi API response status: %s.'), $inoUser->user_login, $sStatus )
|
486 |
-
);
|
487 |
-
return $oError;
|
488 |
-
}
|
489 |
-
|
490 |
-
$this->logInfo(
|
491 |
-
sprintf( _wpsf__('User "%s" successfully logged in using a validated Yubikey One Time Password.'), $inoUser->user_login )
|
492 |
-
);
|
493 |
-
return $inoUser;
|
494 |
-
}
|
495 |
-
|
496 |
-
/**
|
497 |
-
* @return bool
|
498 |
-
*/
|
499 |
-
protected function getIsYubikeyConfigReady() {
|
500 |
-
$sAppId = $this->getOption('yubikey_app_id');
|
501 |
-
$sApiKey = $this->getOption('yubikey_api_key');
|
502 |
-
$aYubikeyKeys = $this->getOption('yubikey_unique_keys');
|
503 |
-
return !empty($sAppId) && !empty($sApiKey) && !empty($aYubikeyKeys);
|
504 |
-
}
|
505 |
-
|
506 |
-
/**
|
507 |
-
* If $inoUser is a valid WP_User object, then the user logged in correctly.
|
508 |
-
*
|
509 |
-
* The flow is as follows:
|
510 |
-
* 0. If username is empty, there was no login attempt.
|
511 |
-
* 1. First we determine whether the user's login credentials were valid according to WordPress ($fUserLoginSuccess)
|
512 |
-
* 2. Then we ask our 2-factor processor whether the current IP address + username combination is authenticated.
|
513 |
-
* a) if yes, we return the WP_User object and login proceeds as per usual.
|
514 |
-
* b) if no, we return null, which will send the message back to the user that the login details were invalid.
|
515 |
-
* 3. If however the user's IP address + username combination is not authenticated, we react differently. We do not want
|
516 |
-
* to give away whether a login was successful, or even the login username details exist. So:
|
517 |
-
* a) if the login was a success we add a pending record to the authentication DB for this username+IP address combination and send the appropriate verification email
|
518 |
-
* b) then, we give back a message saying that if the login was successful, they would have received a verification email. In this way we give nothing away.
|
519 |
-
* c) note at this stage, if the username was empty, we give back nothing (this happens when wp-login.php is loaded as normal.
|
520 |
-
*
|
521 |
-
* @param WP_User|string $inoUser - the docs say the first parameter a string, WP actually gives a WP_User object (or null)
|
522 |
-
* @param string $insUsername
|
523 |
-
* @param string $insPassword
|
524 |
-
* @return WP_Error|WP_User|null - WP_User when the login success AND the IP is authenticated. null when login not successful but IP is valid. WP_Error otherwise.
|
525 |
-
*/
|
526 |
-
public function checkUserAuthLogin_Filter( $inoUser, $insUsername, $insPassword ) {
|
527 |
-
|
528 |
-
if ( empty( $insUsername ) ) {
|
529 |
-
return $inoUser;
|
530 |
-
}
|
531 |
-
|
532 |
-
$fUserLoginSuccess = is_object( $inoUser ) && ( $inoUser instanceof WP_User );
|
533 |
-
|
534 |
-
if ( is_wp_error( $inoUser ) ) {
|
535 |
-
$aCodes = $inoUser->get_error_codes();
|
536 |
-
if ( in_array( 'wpsf_logininterval', $aCodes ) ) {
|
537 |
-
return $inoUser;
|
538 |
-
}
|
539 |
-
}
|
540 |
-
else if ( $fUserLoginSuccess ) {
|
541 |
-
|
542 |
-
if ( !$this->getIsUserLevelSubjectToTwoFactorAuth( $inoUser->user_level ) ) {
|
543 |
-
return $inoUser;
|
544 |
-
}
|
545 |
-
|
546 |
-
if ( $this->isUserVerified( $insUsername ) ) {
|
547 |
-
return $inoUser;
|
548 |
-
}
|
549 |
-
else {
|
550 |
-
// Create a new 2-factor auth pending entry
|
551 |
-
$aNewAuthData = $this->addNewPendingLoginAuth( $inoUser->user_login );
|
552 |
-
|
553 |
-
// Now send email with authentication link for user.
|
554 |
-
if ( is_array( $aNewAuthData ) ) {
|
555 |
-
$this->doStatIncrement( 'login.twofactor.started' );
|
556 |
-
$fEmailSuccess = $this->sendEmailTwoFactorVerify( $inoUser, $aNewAuthData['ip'], $aNewAuthData['unique_id'] );
|
557 |
-
|
558 |
-
// Failure to send email - log them in.
|
559 |
-
if ( !$fEmailSuccess && $this->getIsOption( 'enable_two_factor_bypass_on_email_fail', 'Y' ) ) {
|
560 |
-
$this->doMakePendingLoginAuthActive( $aNewAuthData );
|
561 |
-
return $inoUser;
|
562 |
-
}
|
563 |
-
}
|
564 |
-
}
|
565 |
-
}
|
566 |
-
|
567 |
-
$sErrorString = "Login is protected by 2-factor authentication. If your login details were correct, you would have received an email to verify this IP address.";
|
568 |
-
return new WP_Error( 'wpsf_loginauth', $sErrorString );
|
569 |
-
}
|
570 |
-
|
571 |
-
/**
|
572 |
-
* TODO: http://stackoverflow.com/questions/3499104/how-to-know-the-role-of-current-user-in-wordpress
|
573 |
-
* @param integer $nUserLevel
|
574 |
-
* @return bool
|
575 |
-
*/
|
576 |
-
public function getIsUserLevelSubjectToTwoFactorAuth( $nUserLevel ) {
|
577 |
-
|
578 |
-
$aSubjectedUserLevels = $this->getOption( 'two_factor_auth_user_roles' );
|
579 |
-
if ( empty($aSubjectedUserLevels) || !is_array($aSubjectedUserLevels) ) {
|
580 |
-
$aSubjectedUserLevels = array( 1, 2, 3, 8 ); // by default all except subscribers!
|
581 |
-
}
|
582 |
-
|
583 |
-
// see: https://codex.wordpress.org/Roles_and_Capabilities#User_Level_to_Role_Conversion
|
584 |
-
|
585 |
-
// authors, contributors and subscribers
|
586 |
-
if ( $nUserLevel < 3 && in_array( $nUserLevel, $aSubjectedUserLevels ) ) {
|
587 |
-
return true;
|
588 |
-
}
|
589 |
-
// editors
|
590 |
-
if ( $nUserLevel >= 3 && $nUserLevel < 8 && in_array( 3, $aSubjectedUserLevels ) ) {
|
591 |
-
return true;
|
592 |
-
}
|
593 |
-
// administrators
|
594 |
-
if ( $nUserLevel >= 8 && $nUserLevel <= 10 && in_array( 8, $aSubjectedUserLevels ) ) {
|
595 |
-
return true;
|
596 |
-
}
|
597 |
-
return false;
|
598 |
-
}
|
599 |
-
|
600 |
-
public function getGaspLoginHtml() {
|
601 |
-
|
602 |
-
$sLabel = _wpsf__("I'm a human.");
|
603 |
-
$sAlert = _wpsf__("Please check the box to show us you're a human.");
|
604 |
-
|
605 |
-
$sUniqElem = 'icwp_wpsf_login_p'.uniqid();
|
606 |
-
|
607 |
-
$sStyles = '
|
608 |
-
<style>
|
609 |
-
#'.$sUniqElem.' {
|
610 |
-
clear:both;
|
611 |
-
border: 1px solid #888;
|
612 |
-
padding: 6px 8px 4px 10px;
|
613 |
-
margin: 0 0px 12px !important;
|
614 |
-
border-radius: 2px;
|
615 |
-
background-color: #f9f9f9;
|
616 |
-
}
|
617 |
-
#'.$sUniqElem.' input {
|
618 |
-
margin-right: 5px;
|
619 |
-
}
|
620 |
-
</style>
|
621 |
-
';
|
622 |
-
|
623 |
-
$sHtml =
|
624 |
-
$sStyles.
|
625 |
-
'<p id="'.$sUniqElem.'"></p>
|
626 |
-
<script type="text/javascript">
|
627 |
-
var icwp_wpsf_login_p = document.getElementById("'.$sUniqElem.'");
|
628 |
-
var icwp_wpsf_login_cb = document.createElement("input");
|
629 |
-
var icwp_wpsf_login_text = document.createTextNode(" '.$sLabel.'");
|
630 |
-
icwp_wpsf_login_cb.type = "checkbox";
|
631 |
-
icwp_wpsf_login_cb.id = "'.$this->getGaspCheckboxName().'";
|
632 |
-
icwp_wpsf_login_cb.name = "'.$this->getGaspCheckboxName().'";
|
633 |
-
icwp_wpsf_login_p.appendChild( icwp_wpsf_login_cb );
|
634 |
-
icwp_wpsf_login_p.appendChild( icwp_wpsf_login_text );
|
635 |
-
var frm = icwp_wpsf_login_cb.form;
|
636 |
-
frm.onsubmit = icwp_wpsf_login_it;
|
637 |
-
function icwp_wpsf_login_it(){
|
638 |
-
if(icwp_wpsf_login_cb.checked != true){
|
639 |
-
alert("'.$sAlert.'");
|
640 |
-
return false;
|
641 |
-
}
|
642 |
-
return true;
|
643 |
-
}
|
644 |
-
</script>
|
645 |
-
<noscript>'._wpsf__('You MUST enable Javascript to be able to login').'</noscript>
|
646 |
-
<input type="hidden" id="icwp_wpsf_login_email" name="icwp_wpsf_login_email" value="" />
|
647 |
-
';
|
648 |
-
|
649 |
-
return $sHtml;
|
650 |
-
}
|
651 |
-
|
652 |
-
/**
|
653 |
-
* @return string
|
654 |
-
*/
|
655 |
-
public function getGaspCheckboxName() {
|
656 |
-
return $this->oFeatureOptions->doPluginPrefix( $this->oFeatureOptions->getGaspKey(), '_' );
|
657 |
-
}
|
658 |
-
|
659 |
-
public function doGaspChecks( $insUsername ) {
|
660 |
-
if ( !isset( $_POST[ $this->getGaspCheckboxName() ] ) ) {
|
661 |
-
$this->logWarning(
|
662 |
-
sprintf( _wpsf__('User "%s" attempted to login but GASP checkbox was not present. Bot Perhaps? IP Address: "%s".'), $insUsername, long2ip(self::$nRequestIp) )
|
663 |
-
);
|
664 |
-
$this->doStatIncrement( 'login.gasp.checkbox.fail' );
|
665 |
-
wp_die( "You must check that box to say you're not a bot." );
|
666 |
-
return false;
|
667 |
-
}
|
668 |
-
else if ( isset( $_POST['icwp_wpsf_login_email'] ) && $_POST['icwp_wpsf_login_email'] !== '' ){
|
669 |
-
$this->logWarning(
|
670 |
-
sprintf( _wpsf__('User "%s" attempted to login but they were caught by the GASP honey pot. Bot Perhaps? IP Address: "%s".'), $insUsername, long2ip(self::$nRequestIp) )
|
671 |
-
);
|
672 |
-
$this->doStatIncrement( 'login.gasp.honeypot.fail' );
|
673 |
-
wp_die( _wpsf__('You appear to be a bot - terminating login attempt.') );
|
674 |
-
return false;
|
675 |
-
}
|
676 |
-
return true;
|
677 |
-
}
|
678 |
-
|
679 |
-
/**
|
680 |
-
*/
|
681 |
-
public function setLoginCooldownInterval() {
|
682 |
-
$nInterval = intval( $this->getOption('login_limit_interval', 0) );
|
683 |
-
$this->m_nRequiredLoginInterval = ( $nInterval < 0 )? 0 : $nInterval;
|
684 |
-
}
|
685 |
-
|
686 |
-
/**
|
687 |
-
* @param string $sUsername
|
688 |
-
* @return boolean
|
689 |
-
*/
|
690 |
-
public function addNewPendingLoginAuth( $sUsername ) {
|
691 |
-
|
692 |
-
if ( empty( $sUsername ) ) {
|
693 |
-
return false;
|
694 |
-
}
|
695 |
-
|
696 |
-
// First set any other pending entries for the given user to be deleted.
|
697 |
-
$aOldData = array(
|
698 |
-
'deleted_at' => self::$nRequestTimestamp,
|
699 |
-
'expired_at' => self::$nRequestTimestamp,
|
700 |
-
);
|
701 |
-
$aOldWhere = array(
|
702 |
-
'pending' => 1,
|
703 |
-
'deleted_at' => 0,
|
704 |
-
'wp_username' => $sUsername
|
705 |
-
);
|
706 |
-
$this->updateRowsFromTable( $aOldData, $aOldWhere );
|
707 |
-
|
708 |
-
// Now add new pending entry
|
709 |
-
$aNewData = array();
|
710 |
-
$aNewData[ 'unique_id' ] = uniqid();
|
711 |
-
$aNewData[ 'ip_long' ] = self::$nRequestIp;
|
712 |
-
$aNewData[ 'ip' ] = long2ip( self::$nRequestIp );
|
713 |
-
$aNewData[ 'wp_username' ] = $sUsername;
|
714 |
-
$aNewData[ 'pending' ] = 1;
|
715 |
-
$aNewData[ 'created_at' ] = self::$nRequestTimestamp;
|
716 |
-
|
717 |
-
$mResult = $this->insertIntoTable( $aNewData );
|
718 |
-
if ( $mResult ) {
|
719 |
-
$this->logInfo(
|
720 |
-
sprintf( _wpsf__('User "%s" created a pending Two-Factor Authentication for IP Address "%s".'), $sUsername, $aNewData[ 'ip' ] )
|
721 |
-
);
|
722 |
-
$mResult = $aNewData;
|
723 |
-
}
|
724 |
-
return $mResult;
|
725 |
-
}
|
726 |
-
|
727 |
-
/**
|
728 |
-
* Given a unique Id and a corresponding WordPress username, will update the authentication table so that it is active (pending=0).
|
729 |
-
*
|
730 |
-
* @param array $inaWhere - unique_id, wp_username
|
731 |
-
* @return boolean
|
732 |
-
*/
|
733 |
-
public function doMakePendingLoginAuthActive( $inaWhere ) {
|
734 |
-
|
735 |
-
$aChecks = array( 'unique_id', 'wp_username' );
|
736 |
-
if ( !$this->validateParameters( $inaWhere, $aChecks ) ) {
|
737 |
-
return false;
|
738 |
-
}
|
739 |
-
|
740 |
-
// First set any active, non-pending entries for the given user to be deleted
|
741 |
-
$this->terminateActiveLoginForUser( $inaWhere['wp_username'] );
|
742 |
-
|
743 |
-
// Now activate the new one.
|
744 |
-
|
745 |
-
// Updates the database
|
746 |
-
$inaWhere['pending'] = 1;
|
747 |
-
$inaWhere['deleted_at'] = 0;
|
748 |
-
$mResult = $this->updateRowsFromTable( array( 'pending' => 0 ), $inaWhere );
|
749 |
-
|
750 |
-
// Set the necessary cookie
|
751 |
-
$this->setAuthActiveCookie( $inaWhere['unique_id'] );
|
752 |
-
return $mResult;
|
753 |
-
}
|
754 |
-
|
755 |
-
/**
|
756 |
-
* Invalidates all currently active two-factor logins and redirects to admin (->login)
|
757 |
-
*/
|
758 |
-
public function doTerminateAllVerifiedLogins() {
|
759 |
-
$this->terminateAllVerifiedLogins();
|
760 |
-
$oWp = $this->loadWpFunctionsProcessor();
|
761 |
-
$oWp->redirectToAdmin();
|
762 |
-
}
|
763 |
-
|
764 |
-
/**
|
765 |
-
* @param $sUsername
|
766 |
-
*/
|
767 |
-
protected function setUserLoggedIn( $sUsername ) {
|
768 |
-
$oWp = $this->loadWpFunctionsProcessor();
|
769 |
-
$oUser = version_compare( $oWp->getWordpressVersion(), '3.2.2', '<=' )? get_userdatabylogin( $sUsername ) : get_user_by( 'login', $sUsername );
|
770 |
-
|
771 |
-
wp_clear_auth_cookie();
|
772 |
-
wp_set_current_user ( $oUser->ID, $oUser->user_login );
|
773 |
-
wp_set_auth_cookie ( $oUser->ID, true );
|
774 |
-
do_action( 'wp_login', $oUser->user_login );
|
775 |
-
}
|
776 |
-
|
777 |
-
/**
|
778 |
-
* Given a username will soft-delete any currently active two-factor authentication.
|
779 |
-
*
|
780 |
-
* @param $sUsername
|
781 |
-
*/
|
782 |
-
protected function terminateActiveLoginForUser( $sUsername ) {
|
783 |
-
$sQuery = "
|
784 |
-
UPDATE `%s`
|
785 |
-
SET `deleted_at` = '%s',
|
786 |
-
`expired_at` = '%s'
|
787 |
-
WHERE
|
788 |
-
`wp_username` = '%s'
|
789 |
-
AND `deleted_at` = '0'
|
790 |
-
AND `pending` = '0'
|
791 |
-
";
|
792 |
-
$sQuery = sprintf( $sQuery,
|
793 |
-
$this->getTableName(),
|
794 |
-
self::$nRequestTimestamp,
|
795 |
-
self::$nRequestTimestamp,
|
796 |
-
esc_sql( $sUsername )
|
797 |
-
);
|
798 |
-
$this->doSql( $sQuery );
|
799 |
-
}
|
800 |
-
|
801 |
-
/**
|
802 |
-
*
|
803 |
-
*/
|
804 |
-
protected function terminateAllVerifiedLogins() {
|
805 |
-
$sQuery = "
|
806 |
-
UPDATE `%s`
|
807 |
-
SET `deleted_at` = '%s',
|
808 |
-
`expired_at` = '%s'
|
809 |
-
WHERE
|
810 |
-
`deleted_at` = '0'
|
811 |
-
AND `pending` = '0'
|
812 |
-
";
|
813 |
-
$sQuery = sprintf( $sQuery,
|
814 |
-
$this->getTableName(),
|
815 |
-
self::$nRequestTimestamp,
|
816 |
-
self::$nRequestTimestamp
|
817 |
-
);
|
818 |
-
return $this->doSql( $sQuery );
|
819 |
-
}
|
820 |
-
|
821 |
-
/**
|
822 |
-
* @param $insUniqueId
|
823 |
-
*/
|
824 |
-
public function setAuthActiveCookie( $insUniqueId ) {
|
825 |
-
$nWeek = defined( 'WEEK_IN_SECONDS' )? WEEK_IN_SECONDS : 24*60*60;
|
826 |
-
setcookie( self::AuthActiveCookie, $insUniqueId, self::$nRequestTimestamp+$nWeek, COOKIEPATH, COOKIE_DOMAIN, false );
|
827 |
-
}
|
828 |
-
|
829 |
-
/**
|
830 |
-
* Checks whether a given user is authenticated.
|
831 |
-
*
|
832 |
-
* @param string $sUsername
|
833 |
-
* @return boolean
|
834 |
-
*/
|
835 |
-
public function isUserVerified( $sUsername ) {
|
836 |
-
|
837 |
-
$sQuery = "
|
838 |
-
SELECT *
|
839 |
-
FROM `%s`
|
840 |
-
WHERE
|
841 |
-
`wp_username` = '%s'
|
842 |
-
AND `pending` = '0'
|
843 |
-
AND `deleted_at` = '0'
|
844 |
-
AND `expired_at` = '0'
|
845 |
-
";
|
846 |
-
|
847 |
-
$sQuery = sprintf( $sQuery,
|
848 |
-
$this->getTableName(),
|
849 |
-
$sUsername
|
850 |
-
);
|
851 |
-
|
852 |
-
$mResult = $this->selectCustomFromTable( $sQuery );
|
853 |
-
|
854 |
-
if ( is_array( $mResult ) && count( $mResult ) == 1 ) {
|
855 |
-
// Now we test based on which types of 2-factor auth is enabled
|
856 |
-
$fVerified = true;
|
857 |
-
$aUserAuthData = $mResult[0];
|
858 |
-
if ( $this->getIsTwoFactorAuthOn('ip') && ( self::$nRequestIp != $aUserAuthData['ip_long'] ) ) {
|
859 |
-
$fVerified = false;
|
860 |
-
}
|
861 |
-
if ( $fVerified && $this->getIsTwoFactorAuthOn('cookie') && !$this->isAuthCookieValid($aUserAuthData['unique_id']) ) {
|
862 |
-
$fVerified = false;
|
863 |
-
}
|
864 |
-
return $fVerified;
|
865 |
-
}
|
866 |
-
else {
|
867 |
-
$this->logWarning(
|
868 |
-
sprintf( _wpsf__('User "%s" was found to be un-verified at the given IP Address "%s"'), $sUsername, long2ip( self::$nRequestIp ) )
|
869 |
-
);
|
870 |
-
return false;
|
871 |
-
}
|
872 |
-
}
|
873 |
-
|
874 |
-
/**
|
875 |
-
* @param $sUniqueId
|
876 |
-
* @return bool
|
877 |
-
*/
|
878 |
-
protected function isAuthCookieValid( $sUniqueId ) {
|
879 |
-
$this->loadDataProcessor();
|
880 |
-
return ICWP_WPSF_DataProcessor::FetchCookie( self::AuthActiveCookie ) == $sUniqueId;
|
881 |
-
}
|
882 |
-
|
883 |
-
/**
|
884 |
-
* If it cannot verify current user, will forcefully log them out and redirect to login
|
885 |
-
*/
|
886 |
-
public function verifyCurrentUser() {
|
887 |
-
$oUser = wp_get_current_user();
|
888 |
-
if ( is_object( $oUser ) && $oUser instanceof WP_User ) {
|
889 |
-
|
890 |
-
if ( $this->getIsUserLevelSubjectToTwoFactorAuth( $oUser->user_level ) && !$this->isUserVerified( $oUser->user_login ) ) {
|
891 |
-
$this->logWarning(
|
892 |
-
sprintf( _wpsf__('User "%s" was forcefully logged out as they are not verified by either cookie or IP address (or both).'), $oUser->user_login )
|
893 |
-
);
|
894 |
-
$this->doStatIncrement( 'login.userverify.fail' );
|
895 |
-
wp_logout();
|
896 |
-
$oWp = $this->loadWpFunctionsProcessor();
|
897 |
-
$oWp->redirectToLogin();
|
898 |
-
}
|
899 |
-
}
|
900 |
-
}
|
901 |
-
|
902 |
-
/**
|
903 |
-
* Given the necessary components, creates the 2-factor verification link for giving to the user.
|
904 |
-
*
|
905 |
-
* @param string $sUser
|
906 |
-
* @param string $sUniqueId
|
907 |
-
* @return string
|
908 |
-
*/
|
909 |
-
protected function generateTwoFactorVerifyLink( $sUser, $sUniqueId ) {
|
910 |
-
$sSiteUrl = home_url() . '?wpsfkey=%s&wpsf-action=%s&username=%s&uniqueid=%s';
|
911 |
-
$sAction = 'linkauth';
|
912 |
-
return sprintf( $sSiteUrl, $this->oFeatureOptions->getTwoAuthSecretKey(), $sAction, $sUser, $sUniqueId );
|
913 |
-
}
|
914 |
-
|
915 |
-
/**
|
916 |
-
* @param WP_User $inoUser
|
917 |
-
* @param string $insIpAddress
|
918 |
-
* @param string $insUniqueId
|
919 |
-
* @return boolean
|
920 |
-
*/
|
921 |
-
public function sendEmailTwoFactorVerify( WP_User $inoUser, $insIpAddress, $insUniqueId ) {
|
922 |
-
|
923 |
-
$sEmail = $inoUser->user_email;
|
924 |
-
$sAuthLink = $this->generateTwoFactorVerifyLink( $inoUser->user_login, $insUniqueId );
|
925 |
-
|
926 |
-
$aMessage = array(
|
927 |
-
_wpsf__('You, or someone pretending to be you, just attempted to login into your WordPress site.'),
|
928 |
-
_wpsf__('The IP Address / Cookie from which they tried to login is not currently verified.'),
|
929 |
-
_wpsf__('To validate this user, click the following link and then attempt to login again.'),
|
930 |
-
sprintf( _wpsf__('IP Address: %s'), $insIpAddress ),
|
931 |
-
sprintf( _wpsf__('Authentication Link: %s'), $sAuthLink ),
|
932 |
-
);
|
933 |
-
$sEmailSubject = sprintf( _wpsf__('Two-Factor Login Verification for: %s'), home_url() );
|
934 |
-
|
935 |
-
// add filters to email sending (for now only Mandrill)
|
936 |
-
add_filter( 'mandrill_payload', array($this, 'customiseMandrill') );
|
937 |
-
|
938 |
-
$fResult = $this->getEmailProcessor()->sendEmailTo( $sEmail, $sEmailSubject, $aMessage );
|
939 |
-
if ( $fResult ) {
|
940 |
-
$this->logInfo(
|
941 |
-
sprintf( _wpsf__('User "%s" was sent an email to verify their Identity using Two-Factor Login Auth for IP address "%s".'), $inoUser->user_login, $insIpAddress )
|
942 |
-
);
|
943 |
-
}
|
944 |
-
else {
|
945 |
-
$this->logCritical(
|
946 |
-
sprintf( _wpsf__('Tried to send User "%s" email to verify their Identity using Two-Factor Login Auth for IP Address "%s", but email sending failed.'), $inoUser->user_login, $insIpAddress )
|
947 |
-
);
|
948 |
-
}
|
949 |
-
return $fResult;
|
950 |
-
}
|
951 |
-
|
952 |
-
/**
|
953 |
-
* @param array $aMessage
|
954 |
-
* @return array
|
955 |
-
*/
|
956 |
-
public function customiseMandrill( $aMessage ) {
|
957 |
-
if ( empty( $aMessage['text'] ) ) {
|
958 |
-
$aMessage['text'] = $aMessage['html'];
|
959 |
-
}
|
960 |
-
return $aMessage;
|
961 |
-
}
|
962 |
-
|
963 |
-
public function createTable() {
|
964 |
-
|
965 |
-
// Set up login processor table
|
966 |
-
$sSqlTables = "CREATE TABLE IF NOT EXISTS `%s` (
|
967 |
-
`id` int(11) NOT NULL AUTO_INCREMENT,
|
968 |
-
`unique_id` varchar(20) NOT NULL DEFAULT '',
|
969 |
-
`wp_username` varchar(255) NOT NULL DEFAULT '',
|
970 |
-
`ip` varchar(20) NOT NULL DEFAULT '',
|
971 |
-
`ip_long` bigint(20) NOT NULL DEFAULT '0',
|
972 |
-
`pending` int(1) NOT NULL DEFAULT '0',
|
973 |
-
`created_at` int(15) NOT NULL DEFAULT '0',
|
974 |
-
`deleted_at` int(15) NOT NULL DEFAULT '0',
|
975 |
-
`expired_at` int(15) NOT NULL DEFAULT '0',
|
976 |
-
PRIMARY KEY (`id`)
|
977 |
-
) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
|
978 |
-
$sSqlTables = sprintf( $sSqlTables, $this->getTableName() );
|
979 |
-
$mResult = $this->doSql( $sSqlTables );
|
980 |
-
}
|
981 |
-
|
982 |
-
/**
|
983 |
-
* Assumes that unique_id AND wp_username have been set correctly in the data array (no checking done).
|
984 |
-
*
|
985 |
-
* @param array $inaData
|
986 |
-
* @return array
|
987 |
-
*/
|
988 |
-
protected function getLoginAuthData( $inaData ) {
|
989 |
-
|
990 |
-
$sQuery = "SELECT * FROM %s WHERE `unique_id` = `%s` AND `wp_username` = %s";
|
991 |
-
$sQuery = sprintf( $sQuery, $this->getTableName(), $inaData['unique_id'], $inaData['wp_username'] );
|
992 |
-
return $this->selectRowFromTable( $sQuery );
|
993 |
-
}
|
994 |
-
|
995 |
-
/**
|
996 |
-
* This is hooked into a cron in the base class and overrides the parent method.
|
997 |
-
*
|
998 |
-
* It'll delete everything older than 24hrs.
|
999 |
-
*/
|
1000 |
-
public function cleanupDatabase() {
|
1001 |
-
if ( !$this->getTableExists() ) {
|
1002 |
-
return;
|
1003 |
-
}
|
1004 |
-
$nTimeStamp = self::$nRequestTimestamp - (DAY_IN_SECONDS * $this->nDaysToKeepLog);
|
1005 |
-
$this->deleteAllRowsOlderThan( $nTimeStamp );
|
1006 |
-
}
|
1007 |
-
|
1008 |
-
/**
|
1009 |
-
* @param $nTimeStamp
|
1010 |
-
*/
|
1011 |
-
protected function deleteAllRowsOlderThan( $nTimeStamp ) {
|
1012 |
-
$sQuery = "
|
1013 |
-
DELETE from `%s`
|
1014 |
-
WHERE
|
1015 |
-
`created_at` < '%s'
|
1016 |
-
AND `pending` = '1'
|
1017 |
-
";
|
1018 |
-
$sQuery = sprintf( $sQuery,
|
1019 |
-
$this->getTableName(),
|
1020 |
-
esc_sql( $nTimeStamp )
|
1021 |
-
);
|
1022 |
-
$this->doSql( $sQuery );
|
1023 |
-
}
|
1024 |
-
|
1025 |
-
}
|
1026 |
-
endif;
|
1027 |
-
|
1028 |
-
if ( !class_exists('ICWP_WPSF_LoginProtectProcessor') ):
|
1029 |
-
class ICWP_WPSF_LoginProtectProcessor extends ICWP_LoginProtectProcessor_V3 { }
|
1030 |
-
endif;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/icwp-processor-loginprotect_cooldown.php
ADDED
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
+
* All rights reserved.
|
5 |
+
*
|
6 |
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
7 |
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
8 |
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
9 |
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
10 |
+
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
11 |
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
12 |
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
13 |
+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
14 |
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
15 |
+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
+
*/
|
17 |
+
|
18 |
+
require_once( dirname(__FILE__).'/icwp-processor-base.php' );
|
19 |
+
|
20 |
+
if ( !class_exists('ICWP_WPSF_Processor_LoginProtect_Cooldown') ):
|
21 |
+
|
22 |
+
class ICWP_WPSF_Processor_LoginProtect_Cooldown extends ICWP_WPSF_Processor_Base {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var ICWP_WPSF_FeatureHandler_LoginProtect
|
26 |
+
*/
|
27 |
+
protected $oFeatureOptions;
|
28 |
+
|
29 |
+
/**
|
30 |
+
*/
|
31 |
+
public function __construct( ICWP_WPSF_FeatureHandler_LoginProtect $oFeatureOptions ) {
|
32 |
+
parent::__construct( $oFeatureOptions );
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* @return int
|
37 |
+
*/
|
38 |
+
public function getLoginCooldownInterval() {
|
39 |
+
return $this->getOption( 'login_limit_interval' );
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* @return int
|
44 |
+
*/
|
45 |
+
public function getLastLoginTime() {
|
46 |
+
$sFilePath = $this->oFeatureOptions->getLastLoginTimeFilePath();
|
47 |
+
$oWpFs = $this->loadFileSystemProcessor();
|
48 |
+
$nModifiedFileTime = ( $oWpFs->exists( $sFilePath ) ) ? filemtime( $sFilePath ) : 0;
|
49 |
+
return max( $nModifiedFileTime, $this->getOption( 'last_login_time' ) );
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
*
|
54 |
+
*/
|
55 |
+
protected function updateLastLoginTime() {
|
56 |
+
$oDp = $this->loadDataProcessor();
|
57 |
+
$this->oFeatureOptions->setOpt( 'last_login_time', $oDp->GetRequestTime() );
|
58 |
+
$oWpFs = $this->loadFileSystemProcessor();
|
59 |
+
$oWpFs->touch( $this->oFeatureOptions->getLastLoginTimeFilePath(), $oDp->GetRequestTime() );
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
*/
|
64 |
+
public function run() {
|
65 |
+
// We give it a priority of 10 so that we can jump in before WordPress does its own validation.
|
66 |
+
add_filter( 'authenticate', array( $this, 'checkLoginInterval' ), 10, 3 );
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Should be a filter added to WordPress's "authenticate" filter, but before WordPress performs
|
71 |
+
* it's own authentication (theirs is priority 30, so we could go in at around 20).
|
72 |
+
*
|
73 |
+
* @param null|WP_User|WP_Error $oUser
|
74 |
+
* @param string $sUsername
|
75 |
+
* @param string $sPassword
|
76 |
+
* @return unknown|WP_Error
|
77 |
+
*/
|
78 |
+
public function checkLoginInterval( $oUser, $sUsername, $sPassword ) {
|
79 |
+
// No login attempt was made and we do nothing
|
80 |
+
if ( empty( $sUsername ) ) {
|
81 |
+
return $oUser;
|
82 |
+
}
|
83 |
+
|
84 |
+
// Is there an interval set?
|
85 |
+
$nRequiredLoginInterval = $this->getLoginCooldownInterval();
|
86 |
+
if ( empty( $nRequiredLoginInterval ) || $nRequiredLoginInterval < 0 ) {
|
87 |
+
return $oUser;
|
88 |
+
}
|
89 |
+
|
90 |
+
// If we're outside the interval, let the login process proceed as per normal and
|
91 |
+
// update our last login time.
|
92 |
+
$oDp = $this->loadDataProcessor();
|
93 |
+
$nCurrentLoginInterval = $oDp->GetRequestTime() - $this->getLastLoginTime();
|
94 |
+
if ( $nCurrentLoginInterval > $nRequiredLoginInterval ) {
|
95 |
+
$this->updateLastLoginTime();
|
96 |
+
$this->doStatIncrement( 'login.cooldown.success' );
|
97 |
+
return $oUser;
|
98 |
+
}
|
99 |
+
|
100 |
+
// At this point someone has attempted to login within the previous login wait interval
|
101 |
+
// So we remove WordPress's authentication filter and our own user check authentication
|
102 |
+
// And finally return a WP_Error which will be reflected back to the user.
|
103 |
+
$this->doStatIncrement( 'login.cooldown.fail' );
|
104 |
+
remove_filter( 'authenticate', 'wp_authenticate_username_password', 20, 3 ); // wp-includes/user.php
|
105 |
+
|
106 |
+
$sErrorString = sprintf( _wpsf__( "Login Cooldown in effect. You must wait %s seconds before attempting to login again." ), ($nRequiredLoginInterval - $nCurrentLoginInterval ) );
|
107 |
+
$oError = new WP_Error( 'wpsf_logininterval', $sErrorString );
|
108 |
+
return $oError;
|
109 |
+
}
|
110 |
+
}
|
111 |
+
endif;
|
src/icwp-processor-loginprotect_gasp.php
ADDED
@@ -0,0 +1,169 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
+
* All rights reserved.
|
5 |
+
*
|
6 |
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
7 |
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
8 |
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
9 |
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
10 |
+
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
11 |
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
12 |
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
13 |
+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
14 |
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
15 |
+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
+
*/
|
17 |
+
|
18 |
+
require_once( dirname(__FILE__).'/icwp-processor-base.php' );
|
19 |
+
|
20 |
+
if ( !class_exists('ICWP_WPSF_Processor_LoginProtect_Gasp') ):
|
21 |
+
|
22 |
+
class ICWP_WPSF_Processor_LoginProtect_Gasp extends ICWP_WPSF_Processor_Base {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var ICWP_WPSF_FeatureHandler_LoginProtect
|
26 |
+
*/
|
27 |
+
protected $oFeatureOptions;
|
28 |
+
|
29 |
+
/**
|
30 |
+
*/
|
31 |
+
public function __construct( ICWP_WPSF_FeatureHandler_LoginProtect $oFeatureOptions ) {
|
32 |
+
$this->oFeatureOptions = $oFeatureOptions;
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
*/
|
37 |
+
public function run() {
|
38 |
+
// Add GASP checking to the login form.
|
39 |
+
add_action( 'login_form', array( $this, 'printGaspLoginCheck_Action' ) );
|
40 |
+
add_action( 'woocommerce_login_form', array( $this, 'printGaspLoginCheck_Action' ) );
|
41 |
+
add_filter( 'login_form_middle', array( $this, 'printGaspLoginCheck_Filter' ) );
|
42 |
+
add_filter( 'authenticate', array( $this, 'checkLoginForGasp_Filter' ), 22, 3);
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
*/
|
47 |
+
public function printGaspLoginCheck_Action() {
|
48 |
+
echo $this->getGaspLoginHtml();
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* @return string
|
53 |
+
*/
|
54 |
+
public function printGaspLoginCheck_Filter() {
|
55 |
+
return $this->getGaspLoginHtml();
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* @param $oUser
|
60 |
+
* @param $sUsername
|
61 |
+
* @param $insPassword
|
62 |
+
* @return WP_Error
|
63 |
+
*/
|
64 |
+
public function checkLoginForGasp_Filter( $oUser, $sUsername, $insPassword ) {
|
65 |
+
|
66 |
+
if ( empty( $sUsername ) || is_wp_error( $oUser ) ) {
|
67 |
+
return $oUser;
|
68 |
+
}
|
69 |
+
if ( $this->doGaspChecks( $sUsername ) ) {
|
70 |
+
return $oUser;
|
71 |
+
}
|
72 |
+
//This doesn't actually ever get returned because we die() within doGaspChecks()
|
73 |
+
return new WP_Error('wpsf_gaspfail', _wpsf__('G.A.S.P. Checking Failed.') );
|
74 |
+
}
|
75 |
+
|
76 |
+
public function getGaspLoginHtml() {
|
77 |
+
|
78 |
+
$sLabel = _wpsf__("I'm a human.");
|
79 |
+
$sAlert = _wpsf__("Please check the box to show us you're a human.");
|
80 |
+
|
81 |
+
$sUniqElem = 'icwp_wpsf_login_p'.uniqid();
|
82 |
+
|
83 |
+
$sStyles = '
|
84 |
+
<style>
|
85 |
+
#'.$sUniqElem.' {
|
86 |
+
clear:both;
|
87 |
+
border: 1px solid #888;
|
88 |
+
padding: 6px 8px 4px 10px;
|
89 |
+
margin: 0 0px 12px !important;
|
90 |
+
border-radius: 2px;
|
91 |
+
background-color: #f9f9f9;
|
92 |
+
}
|
93 |
+
#'.$sUniqElem.' input {
|
94 |
+
margin-right: 5px;
|
95 |
+
}
|
96 |
+
</style>
|
97 |
+
';
|
98 |
+
|
99 |
+
$sHtml =
|
100 |
+
$sStyles.
|
101 |
+
'<p id="'.$sUniqElem.'"></p>
|
102 |
+
<script type="text/javascript">
|
103 |
+
var icwp_wpsf_login_p = document.getElementById("'.$sUniqElem.'");
|
104 |
+
var icwp_wpsf_login_cb = document.createElement("input");
|
105 |
+
var icwp_wpsf_login_text = document.createTextNode(" '.$sLabel.'");
|
106 |
+
icwp_wpsf_login_cb.type = "checkbox";
|
107 |
+
icwp_wpsf_login_cb.id = "'.$this->getGaspCheckboxName().'";
|
108 |
+
icwp_wpsf_login_cb.name = "'.$this->getGaspCheckboxName().'";
|
109 |
+
icwp_wpsf_login_p.appendChild( icwp_wpsf_login_cb );
|
110 |
+
icwp_wpsf_login_p.appendChild( icwp_wpsf_login_text );
|
111 |
+
var frm = icwp_wpsf_login_cb.form;
|
112 |
+
frm.onsubmit = icwp_wpsf_login_it;
|
113 |
+
function icwp_wpsf_login_it(){
|
114 |
+
if(icwp_wpsf_login_cb.checked != true){
|
115 |
+
alert("'.$sAlert.'");
|
116 |
+
return false;
|
117 |
+
}
|
118 |
+
return true;
|
119 |
+
}
|
120 |
+
</script>
|
121 |
+
<noscript>'._wpsf__('You MUST enable Javascript to be able to login').'</noscript>
|
122 |
+
<input type="hidden" id="icwp_wpsf_login_email" name="icwp_wpsf_login_email" value="" />
|
123 |
+
';
|
124 |
+
|
125 |
+
return $sHtml;
|
126 |
+
}
|
127 |
+
|
128 |
+
/**
|
129 |
+
* @return string
|
130 |
+
*/
|
131 |
+
public function getGaspCheckboxName() {
|
132 |
+
return $this->oFeatureOptions->doPluginPrefix( $this->oFeatureOptions->getGaspKey() );
|
133 |
+
}
|
134 |
+
|
135 |
+
/**
|
136 |
+
* @param $sUsername
|
137 |
+
* @return bool
|
138 |
+
*/
|
139 |
+
public function doGaspChecks( $sUsername ) {
|
140 |
+
$oDp = $this->loadDataProcessor();
|
141 |
+
$sGaspCheckBox = $oDp->FetchPost( $this->getGaspCheckboxName() );
|
142 |
+
$sHoney = $oDp->FetchPost( 'icwp_wpsf_login_email' );
|
143 |
+
|
144 |
+
if ( empty( $sGaspCheckBox ) ) {
|
145 |
+
$this->logWarning(
|
146 |
+
sprintf( _wpsf__('User "%s" attempted to login but GASP checkbox was not present. Bot Perhaps? IP Address: "%s".'),
|
147 |
+
$sUsername,
|
148 |
+
$oDp->FetchPost( false )
|
149 |
+
)
|
150 |
+
);
|
151 |
+
$this->doStatIncrement( 'login.gasp.checkbox.fail' );
|
152 |
+
wp_die( "You must check that box to say you're not a bot." );
|
153 |
+
return false;
|
154 |
+
}
|
155 |
+
else if ( !empty( $sHoney ) ) {
|
156 |
+
$this->logWarning(
|
157 |
+
sprintf( _wpsf__('User "%s" attempted to login but they were caught by the GASP honey pot. Bot Perhaps? IP Address: "%s".'),
|
158 |
+
$sUsername,
|
159 |
+
$oDp->FetchPost( false )
|
160 |
+
)
|
161 |
+
);
|
162 |
+
$this->doStatIncrement( 'login.gasp.honeypot.fail' );
|
163 |
+
wp_die( _wpsf__('You appear to be a bot - terminating login attempt.') );
|
164 |
+
return false;
|
165 |
+
}
|
166 |
+
return true;
|
167 |
+
}
|
168 |
+
}
|
169 |
+
endif;
|
src/icwp-processor-loginprotect_twofactorauth.php
ADDED
@@ -0,0 +1,548 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
+
* All rights reserved.
|
5 |
+
*
|
6 |
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
7 |
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
8 |
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
9 |
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
10 |
+
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
11 |
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
12 |
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
13 |
+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
14 |
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
15 |
+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
+
*/
|
17 |
+
|
18 |
+
require_once( dirname(__FILE__).'/icwp-processor-basedb.php' );
|
19 |
+
|
20 |
+
if ( !class_exists('ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth') ):
|
21 |
+
|
22 |
+
class ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth extends ICWP_WPSF_BaseDbProcessor {
|
23 |
+
|
24 |
+
const AuthActiveCookie = 'wpsf_auth';
|
25 |
+
|
26 |
+
/**
|
27 |
+
* @var ICWP_WPSF_FeatureHandler_LoginProtect
|
28 |
+
*/
|
29 |
+
protected $oFeatureOptions;
|
30 |
+
/**
|
31 |
+
* @var string
|
32 |
+
*/
|
33 |
+
protected $nDaysToKeepLog = 1;
|
34 |
+
|
35 |
+
/**
|
36 |
+
* @param ICWP_WPSF_FeatureHandler_LoginProtect $oFeatureOptions
|
37 |
+
*/
|
38 |
+
public function __construct( ICWP_WPSF_FeatureHandler_LoginProtect $oFeatureOptions ) {
|
39 |
+
parent::__construct( $oFeatureOptions, $oFeatureOptions->getTwoFactorAuthTableName() );
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
*/
|
44 |
+
public function run() {
|
45 |
+
parent::run();
|
46 |
+
$oDp = $this->loadDataProcessor();
|
47 |
+
|
48 |
+
// User has clicked a link in their email to validate their IP address for login.
|
49 |
+
if ( $oDp->FetchGet( 'wpsf-action' ) == 'linkauth' ) {
|
50 |
+
add_action( 'init', array( $this, 'validateUserAuthLink' ), 10 );
|
51 |
+
}
|
52 |
+
|
53 |
+
// Check the current logged-in user every page load.
|
54 |
+
add_action( 'init', array( $this, 'checkCurrentUserAuth' ), 11 );
|
55 |
+
|
56 |
+
// At this stage (30,3) WordPress has already (20) authenticated the user. So if the login
|
57 |
+
// is valid, the filter will have a valid WP_User object passed to it.
|
58 |
+
add_filter( 'authenticate', array( $this, 'doUserTwoFactorAuth' ), 30, 3);
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Checks whether the current user that is logged-in is authenticated by IP address.
|
63 |
+
*
|
64 |
+
* If the user is not found to be valid, they're logged out.
|
65 |
+
*
|
66 |
+
* Should be hooked to 'init' so we have is_user_logged_in()
|
67 |
+
*/
|
68 |
+
public function checkCurrentUserAuth() {
|
69 |
+
|
70 |
+
if ( is_user_logged_in() ) {
|
71 |
+
|
72 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
73 |
+
$oUser = $oWp->getCurrentWpUser();
|
74 |
+
if ( !is_null( $oUser ) ) {
|
75 |
+
|
76 |
+
if ( $this->getIsUserLevelSubjectToTwoFactorAuth( $oUser->user_level ) && !$this->getUserHasValidAuth( $oUser ) ) {
|
77 |
+
|
78 |
+
$this->logWarning(
|
79 |
+
sprintf( _wpsf__('User "%s" was forcefully logged out as they are not verified by either cookie or IP address (or both).'), $oUser->user_login )
|
80 |
+
);
|
81 |
+
|
82 |
+
$this->doStatIncrement( 'login.userverify.fail' );
|
83 |
+
$oWp->forceUserRelogin( array( 'wpsf-forcelogout' => 6 ) );
|
84 |
+
}
|
85 |
+
}
|
86 |
+
}
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Checks whether a given user is authenticated.
|
91 |
+
*
|
92 |
+
* @param WP_User $oUser
|
93 |
+
* @return boolean
|
94 |
+
*/
|
95 |
+
public function getUserHasValidAuth( $oUser ) {
|
96 |
+
|
97 |
+
$fVerified = false;
|
98 |
+
$aUserAuthData = $this->query_GetActiveAuthForUser( $oUser );
|
99 |
+
|
100 |
+
if ( !is_null( $aUserAuthData ) ) {
|
101 |
+
|
102 |
+
// Now we test based on which types of 2-factor auth is enabled
|
103 |
+
$fVerified = true;
|
104 |
+
if ( $this->oFeatureOptions->getIsTwoFactorAuthOn('ip') && ( self::$nRequestIp != $aUserAuthData['ip_long'] ) ) {
|
105 |
+
$fVerified = false;
|
106 |
+
}
|
107 |
+
|
108 |
+
if ( $fVerified && $this->oFeatureOptions->getIsTwoFactorAuthOn('cookie') && !$this->getIsAuthCookieValid( $aUserAuthData['unique_id'] ) ) {
|
109 |
+
$fVerified = false;
|
110 |
+
}
|
111 |
+
}
|
112 |
+
|
113 |
+
if ( !$fVerified ) {
|
114 |
+
$this->logWarning(
|
115 |
+
sprintf( _wpsf__('User "%s" was found to be un-verified at the given IP Address "%s"'), $oUser->user_login, long2ip( self::$nRequestIp ) )
|
116 |
+
);
|
117 |
+
}
|
118 |
+
|
119 |
+
return $fVerified;
|
120 |
+
}
|
121 |
+
|
122 |
+
/**
|
123 |
+
* Checks the link details to ensure all is valid before authorizing the user.
|
124 |
+
*/
|
125 |
+
public function validateUserAuthLink() {
|
126 |
+
$oDp = $this->loadDataProcessor();
|
127 |
+
// wpsfkey=%s&wpsf-action=%s&username=%s&uniqueid
|
128 |
+
|
129 |
+
if ( $oDp->FetchGet( 'wpsfkey' ) !== $this->oFeatureOptions->getTwoAuthSecretKey() ) {
|
130 |
+
return false;
|
131 |
+
}
|
132 |
+
|
133 |
+
$sUsername = $oDp->FetchGet( 'username' );
|
134 |
+
$sUniqueId = $oDp->FetchGet( 'uniqueid' );
|
135 |
+
|
136 |
+
if ( empty( $sUsername ) || empty( $sUniqueId ) ) {
|
137 |
+
return false;
|
138 |
+
}
|
139 |
+
|
140 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
141 |
+
if ( $this->setLoginAuthActive( $sUniqueId, $sUsername ) ) {
|
142 |
+
$this->logInfo(
|
143 |
+
sprintf( _wpsf__('User "%s" verified their identity using Two-Factor Authentication.'), $sUsername )
|
144 |
+
);
|
145 |
+
$this->doStatIncrement( 'login.twofactor.verified' );
|
146 |
+
$oWp->setUserLoggedIn( $sUsername );
|
147 |
+
$oWp->redirectToAdmin();
|
148 |
+
}
|
149 |
+
else {
|
150 |
+
$oWp->redirectToLogin();
|
151 |
+
}
|
152 |
+
}
|
153 |
+
|
154 |
+
/**
|
155 |
+
* If $inoUser is a valid WP_User object, then the user logged in correctly.
|
156 |
+
*
|
157 |
+
* The flow is as follows:
|
158 |
+
* 0. If username is empty, there was no login attempt.
|
159 |
+
* 1. First we determine whether the user's login credentials were valid according to WordPress ($fUserLoginSuccess)
|
160 |
+
* 2. Then we ask our 2-factor processor whether the current IP address + username combination is authenticated.
|
161 |
+
* a) if yes, we return the WP_User object and login proceeds as per usual.
|
162 |
+
* b) if no, we return null, which will send the message back to the user that the login details were invalid.
|
163 |
+
* 3. If however the user's IP address + username combination is not authenticated, we react differently. We do not want
|
164 |
+
* to give away whether a login was successful, or even the login username details exist. So:
|
165 |
+
* a) if the login was a success we add a pending record to the authentication DB for this username+IP address combination and send the appropriate verification email
|
166 |
+
* b) then, we give back a message saying that if the login was successful, they would have received a verification email. In this way we give nothing away.
|
167 |
+
* c) note at this stage, if the username was empty, we give back nothing (this happens when wp-login.php is loaded as normal.
|
168 |
+
*
|
169 |
+
* @param WP_User|string $oUser - the docs say the first parameter a string, WP actually gives a WP_User object (or null)
|
170 |
+
* @param string $sUsername
|
171 |
+
* @param string $sPassword
|
172 |
+
* @return WP_Error|WP_User|null - WP_User when the login success AND the IP is authenticated. null when login not successful but IP is valid. WP_Error otherwise.
|
173 |
+
*/
|
174 |
+
public function doUserTwoFactorAuth( $oUser, $sUsername, $sPassword ) {
|
175 |
+
|
176 |
+
if ( empty( $sUsername ) ) {
|
177 |
+
return $oUser;
|
178 |
+
}
|
179 |
+
|
180 |
+
$fUserLoginSuccess = is_object( $oUser ) && ( $oUser instanceof WP_User );
|
181 |
+
|
182 |
+
if ( $fUserLoginSuccess ) {
|
183 |
+
|
184 |
+
if ( !$this->getIsUserLevelSubjectToTwoFactorAuth( $oUser->user_level ) ) {
|
185 |
+
return $oUser;
|
186 |
+
}
|
187 |
+
if ( $this->getUserHasValidAuth( $oUser ) ) {
|
188 |
+
return $oUser;
|
189 |
+
}
|
190 |
+
|
191 |
+
// Create a new 2-factor auth pending entry
|
192 |
+
$aNewAuthData = $this->query_DoCreatePendingLoginAuth( $oUser->user_login );
|
193 |
+
|
194 |
+
// Now send email with authentication link for user.
|
195 |
+
if ( is_array( $aNewAuthData ) ) {
|
196 |
+
$this->doStatIncrement( 'login.twofactor.started' );
|
197 |
+
$fEmailSuccess = $this->sendEmailTwoFactorVerify( $oUser, $aNewAuthData['ip'], $aNewAuthData['unique_id'] );
|
198 |
+
|
199 |
+
// Failure to send email - log them in.
|
200 |
+
if ( !$fEmailSuccess && $this->getIsOption( 'enable_two_factor_bypass_on_email_fail', 'Y' ) ) {
|
201 |
+
$this->setLoginAuthActive( $aNewAuthData['unique_id'], $aNewAuthData['wp_username'] );
|
202 |
+
return $oUser;
|
203 |
+
}
|
204 |
+
}
|
205 |
+
}
|
206 |
+
|
207 |
+
// We default to returning a login cooldown error if that's in place.
|
208 |
+
if ( is_wp_error( $oUser ) ) {
|
209 |
+
$aCodes = $oUser->get_error_codes();
|
210 |
+
if ( in_array( 'wpsf_logininterval', $aCodes ) ) {
|
211 |
+
return $oUser;
|
212 |
+
}
|
213 |
+
}
|
214 |
+
|
215 |
+
$sErrorString = _wpsf__( "Login is protected by 2-factor authentication." )
|
216 |
+
.' '._wpsf__( "If your login details were correct, you will have received an email to complete the login process." ) ;
|
217 |
+
return new WP_Error( 'wpsf_loginauth', $sErrorString );
|
218 |
+
}
|
219 |
+
|
220 |
+
/**
|
221 |
+
* @param string $sUniqueId
|
222 |
+
* @param string $sUsername
|
223 |
+
* @return boolean
|
224 |
+
*/
|
225 |
+
public function setLoginAuthActive( $sUniqueId, $sUsername ) {
|
226 |
+
// 1. Terminate old entries
|
227 |
+
$this->query_DoTerminateActiveLoginForUser( $sUsername );
|
228 |
+
|
229 |
+
// 2. Authenticate new entry
|
230 |
+
$aWhere = array(
|
231 |
+
'unique_id' => $sUniqueId,
|
232 |
+
'wp_username' => $sUsername
|
233 |
+
);
|
234 |
+
$this->query_DoMakePendingLoginAuthActive( $aWhere );
|
235 |
+
|
236 |
+
// 3. Set Auth Cookie
|
237 |
+
$this->setAuthActiveCookie( $sUniqueId );
|
238 |
+
|
239 |
+
return true;
|
240 |
+
}
|
241 |
+
|
242 |
+
/**
|
243 |
+
* TODO: http://stackoverflow.com/questions/3499104/how-to-know-the-role-of-current-user-in-wordpress
|
244 |
+
* @param integer $nUserLevel
|
245 |
+
* @return bool
|
246 |
+
*/
|
247 |
+
protected function getIsUserLevelSubjectToTwoFactorAuth( $nUserLevel ) {
|
248 |
+
|
249 |
+
$aSubjectedUserLevels = $this->getOption( 'two_factor_auth_user_roles' );
|
250 |
+
if ( empty($aSubjectedUserLevels) || !is_array($aSubjectedUserLevels) ) {
|
251 |
+
$aSubjectedUserLevels = array( 1, 2, 3, 8 ); // by default all roles except subscribers!
|
252 |
+
}
|
253 |
+
|
254 |
+
// see: https://codex.wordpress.org/Roles_and_Capabilities#User_Level_to_Role_Conversion
|
255 |
+
|
256 |
+
// authors, contributors and subscribers
|
257 |
+
if ( $nUserLevel < 3 && in_array( $nUserLevel, $aSubjectedUserLevels ) ) {
|
258 |
+
return true;
|
259 |
+
}
|
260 |
+
// editors
|
261 |
+
if ( $nUserLevel >= 3 && $nUserLevel < 8 && in_array( 3, $aSubjectedUserLevels ) ) {
|
262 |
+
return true;
|
263 |
+
}
|
264 |
+
// administrators
|
265 |
+
if ( $nUserLevel >= 8 && $nUserLevel <= 10 && in_array( 8, $aSubjectedUserLevels ) ) {
|
266 |
+
return true;
|
267 |
+
}
|
268 |
+
return false;
|
269 |
+
}
|
270 |
+
|
271 |
+
/**
|
272 |
+
* @param string $sUsername
|
273 |
+
* @return boolean
|
274 |
+
*/
|
275 |
+
protected function query_DoCreatePendingLoginAuth( $sUsername ) {
|
276 |
+
|
277 |
+
if ( empty( $sUsername ) ) {
|
278 |
+
return false;
|
279 |
+
}
|
280 |
+
|
281 |
+
// First set any other pending entries for the given user to be deleted.
|
282 |
+
$aSetDeleted = array(
|
283 |
+
'deleted_at' => self::$nRequestTimestamp,
|
284 |
+
'expired_at' => self::$nRequestTimestamp,
|
285 |
+
);
|
286 |
+
$aOldPendingAuth = array(
|
287 |
+
'pending' => 1,
|
288 |
+
'deleted_at' => 0,
|
289 |
+
'wp_username' => $sUsername
|
290 |
+
);
|
291 |
+
$this->updateRowsFromTable( $aSetDeleted, $aOldPendingAuth );
|
292 |
+
|
293 |
+
// Now add new pending entry
|
294 |
+
$aNewData = array();
|
295 |
+
$aNewData[ 'unique_id' ] = uniqid();
|
296 |
+
$aNewData[ 'ip_long' ] = self::$nRequestIp;
|
297 |
+
$aNewData[ 'ip' ] = long2ip( self::$nRequestIp );
|
298 |
+
$aNewData[ 'wp_username' ] = $sUsername;
|
299 |
+
$aNewData[ 'pending' ] = 1;
|
300 |
+
$aNewData[ 'created_at' ] = self::$nRequestTimestamp;
|
301 |
+
|
302 |
+
$mResult = $this->insertIntoTable( $aNewData );
|
303 |
+
return $mResult ? $aNewData : $mResult;
|
304 |
+
}
|
305 |
+
|
306 |
+
/**
|
307 |
+
* Given a unique ID and a corresponding WordPress username, will update the authentication table so that it is active (pending=0).
|
308 |
+
*
|
309 |
+
* @param array $aWhere - unique_id, wp_username
|
310 |
+
* @return boolean
|
311 |
+
*/
|
312 |
+
public function query_DoMakePendingLoginAuthActive( $aWhere ) {
|
313 |
+
|
314 |
+
$aChecks = array( 'unique_id', 'wp_username' );
|
315 |
+
if ( !$this->validateParameters( $aWhere, $aChecks ) ) {
|
316 |
+
return false;
|
317 |
+
}
|
318 |
+
|
319 |
+
// Activate the new one.
|
320 |
+
$aWhere['pending'] = 1;
|
321 |
+
$aWhere['deleted_at'] = 0;
|
322 |
+
$mResult = $this->updateRowsFromTable( array( 'pending' => 0 ), $aWhere );
|
323 |
+
return $mResult;
|
324 |
+
}
|
325 |
+
|
326 |
+
/**
|
327 |
+
* Invalidates all currently active two-factor logins and redirects to admin (->login)
|
328 |
+
*/
|
329 |
+
public function doTerminateAllVerifiedLogins() {
|
330 |
+
$this->query_DoTerminateAllVerifiedLogins();
|
331 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
332 |
+
$oWp->redirectToAdmin();
|
333 |
+
}
|
334 |
+
|
335 |
+
/**
|
336 |
+
* Given a username will soft-delete any currently active two-factor authentication.
|
337 |
+
*
|
338 |
+
* @param $sUsername
|
339 |
+
*/
|
340 |
+
protected function query_DoTerminateActiveLoginForUser( $sUsername ) {
|
341 |
+
$sQuery = "
|
342 |
+
UPDATE `%s`
|
343 |
+
SET `deleted_at` = '%s',
|
344 |
+
`expired_at` = '%s'
|
345 |
+
WHERE
|
346 |
+
`wp_username` = '%s'
|
347 |
+
AND `deleted_at` = '0'
|
348 |
+
AND `pending` = '0'
|
349 |
+
";
|
350 |
+
$sQuery = sprintf( $sQuery,
|
351 |
+
$this->getTableName(),
|
352 |
+
self::$nRequestTimestamp,
|
353 |
+
self::$nRequestTimestamp,
|
354 |
+
esc_sql( $sUsername )
|
355 |
+
);
|
356 |
+
$this->doSql( $sQuery );
|
357 |
+
}
|
358 |
+
|
359 |
+
/**
|
360 |
+
*
|
361 |
+
*/
|
362 |
+
protected function query_DoTerminateAllVerifiedLogins() {
|
363 |
+
$sQuery = "
|
364 |
+
UPDATE `%s`
|
365 |
+
SET `deleted_at` = '%s',
|
366 |
+
`expired_at` = '%s'
|
367 |
+
WHERE
|
368 |
+
`deleted_at` = '0'
|
369 |
+
AND `pending` = '0'
|
370 |
+
";
|
371 |
+
$sQuery = sprintf( $sQuery,
|
372 |
+
$this->getTableName(),
|
373 |
+
self::$nRequestTimestamp,
|
374 |
+
self::$nRequestTimestamp
|
375 |
+
);
|
376 |
+
return $this->doSql( $sQuery );
|
377 |
+
}
|
378 |
+
|
379 |
+
/**
|
380 |
+
* @param $sUniqueId
|
381 |
+
*/
|
382 |
+
public function setAuthActiveCookie( $sUniqueId ) {
|
383 |
+
$nWeek = defined( 'WEEK_IN_SECONDS' )? WEEK_IN_SECONDS : 24*60*60;
|
384 |
+
setcookie( $this->oFeatureOptions->getTwoFactorAuthCookieName(), $sUniqueId, self::$nRequestTimestamp+$nWeek, COOKIEPATH, COOKIE_DOMAIN, false );
|
385 |
+
}
|
386 |
+
|
387 |
+
/**
|
388 |
+
* @param WP_User $oUser
|
389 |
+
* @return mixed
|
390 |
+
*/
|
391 |
+
protected function query_GetActiveAuthForUser( $oUser ) {
|
392 |
+
$sQuery = "
|
393 |
+
SELECT *
|
394 |
+
FROM `%s`
|
395 |
+
WHERE
|
396 |
+
`wp_username` = '%s'
|
397 |
+
AND `pending` = '0'
|
398 |
+
AND `deleted_at` = '0'
|
399 |
+
AND `expired_at` = '0'
|
400 |
+
";
|
401 |
+
|
402 |
+
$sQuery = sprintf( $sQuery,
|
403 |
+
$this->getTableName(),
|
404 |
+
$oUser->user_login
|
405 |
+
);
|
406 |
+
$mResult = $this->selectCustomFromTable( $sQuery );
|
407 |
+
return ( is_array( $mResult ) && count( $mResult ) == 1 ) ? $mResult[0] : null ;
|
408 |
+
}
|
409 |
+
|
410 |
+
/**
|
411 |
+
* @param $sUniqueId
|
412 |
+
* @return bool
|
413 |
+
*/
|
414 |
+
protected function getIsAuthCookieValid( $sUniqueId ) {
|
415 |
+
$oDp = $this->loadDataProcessor();
|
416 |
+
return $oDp->FetchCookie( $this->oFeatureOptions->getTwoFactorAuthCookieName() ) == $sUniqueId;
|
417 |
+
}
|
418 |
+
|
419 |
+
/**
|
420 |
+
* Given the necessary components, creates the 2-factor verification link for giving to the user.
|
421 |
+
*
|
422 |
+
* @param string $sUser
|
423 |
+
* @param string $sUniqueId
|
424 |
+
* @return string
|
425 |
+
*/
|
426 |
+
protected function generateTwoFactorVerifyLink( $sUser, $sUniqueId ) {
|
427 |
+
$aQueryArgs = array(
|
428 |
+
'wpsfkey' => $this->oFeatureOptions->getTwoAuthSecretKey(),
|
429 |
+
'wpsf-action' => 'linkauth',
|
430 |
+
'username' => $sUser,
|
431 |
+
'uniqueid' => $sUniqueId
|
432 |
+
);
|
433 |
+
return add_query_arg( $aQueryArgs, home_url() );
|
434 |
+
}
|
435 |
+
|
436 |
+
/**
|
437 |
+
* @param WP_User $oUser
|
438 |
+
* @param string $sIpAddress
|
439 |
+
* @param string $insUniqueId
|
440 |
+
* @return boolean
|
441 |
+
*/
|
442 |
+
public function sendEmailTwoFactorVerify( WP_User $oUser, $sIpAddress, $insUniqueId ) {
|
443 |
+
|
444 |
+
$sEmail = $oUser->user_email;
|
445 |
+
$sAuthLink = $this->generateTwoFactorVerifyLink( $oUser->user_login, $insUniqueId );
|
446 |
+
|
447 |
+
$aMessage = array(
|
448 |
+
_wpsf__('You, or someone pretending to be you, just attempted to login into your WordPress site.'),
|
449 |
+
_wpsf__('The IP Address / Cookie from which they tried to login is not currently verified.'),
|
450 |
+
_wpsf__('Click the following link to validate and complete the login process.') .' '._wpsf__('You will be logged in automatically upon successful authentication.'),
|
451 |
+
sprintf( _wpsf__('Username: %s'), $oUser->user_login ),
|
452 |
+
sprintf( _wpsf__('IP Address: %s'), $sIpAddress ),
|
453 |
+
sprintf( _wpsf__('Authentication Link: %s'), $sAuthLink ),
|
454 |
+
);
|
455 |
+
$sEmailSubject = sprintf( _wpsf__('Two-Factor Login Verification for: %s'), home_url() );
|
456 |
+
|
457 |
+
// add filters to email sending (for now only Mandrill)
|
458 |
+
add_filter( 'mandrill_payload', array ($this, 'customiseMandrill' ) );
|
459 |
+
|
460 |
+
$fResult = $this->getEmailProcessor()->sendEmailTo( $sEmail, $sEmailSubject, $aMessage );
|
461 |
+
if ( $fResult ) {
|
462 |
+
$this->logInfo(
|
463 |
+
sprintf( _wpsf__('User "%s" was sent an email to verify their Identity using Two-Factor Login Auth for IP address "%s".'), $oUser->user_login, $sIpAddress )
|
464 |
+
);
|
465 |
+
}
|
466 |
+
else {
|
467 |
+
$this->logCritical(
|
468 |
+
sprintf( _wpsf__('Tried to send User "%s" email to verify their Identity using Two-Factor Login Auth for IP Address "%s", but email sending failed.'), $oUser->user_login, $sIpAddress )
|
469 |
+
);
|
470 |
+
}
|
471 |
+
return $fResult;
|
472 |
+
}
|
473 |
+
|
474 |
+
/**
|
475 |
+
* @param array $aMessage
|
476 |
+
* @return array
|
477 |
+
*/
|
478 |
+
public function customiseMandrill( $aMessage ) {
|
479 |
+
if ( empty( $aMessage['text'] ) ) {
|
480 |
+
$aMessage['text'] = $aMessage['html'];
|
481 |
+
}
|
482 |
+
return $aMessage;
|
483 |
+
}
|
484 |
+
|
485 |
+
/**
|
486 |
+
* @return string
|
487 |
+
*/
|
488 |
+
public function getCreateTableSql() {
|
489 |
+
$sSqlTables = "CREATE TABLE IF NOT EXISTS `%s` (
|
490 |
+
`id` int(11) NOT NULL AUTO_INCREMENT,
|
491 |
+
`unique_id` varchar(20) NOT NULL DEFAULT '',
|
492 |
+
`wp_username` varchar(255) NOT NULL DEFAULT '',
|
493 |
+
`ip` varchar(20) NOT NULL DEFAULT '',
|
494 |
+
`ip_long` bigint(20) NOT NULL DEFAULT '0',
|
495 |
+
`pending` int(1) NOT NULL DEFAULT '0',
|
496 |
+
`created_at` int(15) NOT NULL DEFAULT '0',
|
497 |
+
`deleted_at` int(15) NOT NULL DEFAULT '0',
|
498 |
+
`expired_at` int(15) NOT NULL DEFAULT '0',
|
499 |
+
PRIMARY KEY (`id`)
|
500 |
+
) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
|
501 |
+
return sprintf( $sSqlTables, $this->getTableName() );
|
502 |
+
}
|
503 |
+
|
504 |
+
/**
|
505 |
+
* Assumes that unique_id AND wp_username have been set correctly in the data array (no checking done).
|
506 |
+
*
|
507 |
+
* @param array $inaData
|
508 |
+
* @return array
|
509 |
+
*/
|
510 |
+
protected function getLoginAuthData( $inaData ) {
|
511 |
+
|
512 |
+
$sQuery = "SELECT * FROM %s WHERE `unique_id` = `%s` AND `wp_username` = %s";
|
513 |
+
$sQuery = sprintf( $sQuery, $this->getTableName(), $inaData['unique_id'], $inaData['wp_username'] );
|
514 |
+
return $this->selectRowFromTable( $sQuery );
|
515 |
+
}
|
516 |
+
|
517 |
+
/**
|
518 |
+
* This is hooked into a cron in the base class and overrides the parent method.
|
519 |
+
*
|
520 |
+
* It'll delete everything older than 24hrs.
|
521 |
+
*/
|
522 |
+
public function cleanupDatabase() {
|
523 |
+
if ( !$this->getTableExists() ) {
|
524 |
+
return;
|
525 |
+
}
|
526 |
+
$nTimeStamp = self::$nRequestTimestamp - (DAY_IN_SECONDS * $this->nDaysToKeepLog);
|
527 |
+
$this->deleteAllRowsOlderThan( $nTimeStamp );
|
528 |
+
}
|
529 |
+
|
530 |
+
/**
|
531 |
+
* @param $nTimeStamp
|
532 |
+
*/
|
533 |
+
protected function deleteAllRowsOlderThan( $nTimeStamp ) {
|
534 |
+
$sQuery = "
|
535 |
+
DELETE from `%s`
|
536 |
+
WHERE
|
537 |
+
`created_at` < '%s'
|
538 |
+
AND `pending` = '1'
|
539 |
+
";
|
540 |
+
$sQuery = sprintf( $sQuery,
|
541 |
+
$this->getTableName(),
|
542 |
+
esc_sql( $nTimeStamp )
|
543 |
+
);
|
544 |
+
$this->doSql( $sQuery );
|
545 |
+
}
|
546 |
+
|
547 |
+
}
|
548 |
+
endif;
|
src/icwp-processor-loginprotect_yubikey.php
ADDED
@@ -0,0 +1,167 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
+
* All rights reserved.
|
5 |
+
*
|
6 |
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
7 |
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
8 |
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
9 |
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
10 |
+
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
11 |
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
12 |
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
13 |
+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
14 |
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
15 |
+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
+
*/
|
17 |
+
|
18 |
+
require_once( dirname(__FILE__).'/icwp-processor-base.php' );
|
19 |
+
|
20 |
+
if ( !class_exists('ICWP_WPSF_Processor_LoginProtect_Yubikey') ):
|
21 |
+
|
22 |
+
class ICWP_WPSF_Processor_LoginProtect_Yubikey extends ICWP_WPSF_Processor_Base {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @const string
|
26 |
+
*/
|
27 |
+
const YubikeyVerifyApiUrl = 'https://api.yubico.com/wsapi/2.0/verify?id=%s&otp=%s&nonce=%s';
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @var ICWP_WPSF_FeatureHandler_LoginProtect
|
31 |
+
*/
|
32 |
+
protected $oFeatureOptions;
|
33 |
+
|
34 |
+
/**
|
35 |
+
*/
|
36 |
+
public function __construct( ICWP_WPSF_FeatureHandler_LoginProtect $oFeatureOptions ) {
|
37 |
+
parent::__construct( $oFeatureOptions );
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
*/
|
42 |
+
public function run() {
|
43 |
+
if ( $this->getIsYubikeyConfigReady() ) {
|
44 |
+
add_filter( 'wp_authenticate_user', array( $this, 'checkYubikeyOtpAuth_Filter' ) );
|
45 |
+
add_action( 'login_form', array( $this, 'printYubikeyOtp_Action' ) );
|
46 |
+
}
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* @param WP_User $oUser
|
51 |
+
* @return WP_User|WP_Error
|
52 |
+
*/
|
53 |
+
public function checkYubikeyOtpAuth_Filter( $oUser ) {
|
54 |
+
$oError = new WP_Error();
|
55 |
+
|
56 |
+
// Before anything else we check that a Yubikey pair has been provided for this username (and that there are pairs in the first place!)
|
57 |
+
$aYubikeyUsernamePairs = $this->getOption('yubikey_unique_keys');
|
58 |
+
if ( !$this->getIsYubikeyConfigReady() ) { // configuration is clearly not completed yet.
|
59 |
+
return $oUser;
|
60 |
+
}
|
61 |
+
|
62 |
+
$sOneTimePassword = empty( $_POST['yubiotp'] )? '' : trim( $_POST['yubiotp'] );
|
63 |
+
$sAppId = $this->getOption('yubikey_app_id');
|
64 |
+
$sApiKey = $this->getOption('yubikey_api_key');
|
65 |
+
|
66 |
+
// check that if we have a list of permitted keys, that the one used is on that list connected with the username.
|
67 |
+
$sYubikey12 = substr( $sOneTimePassword, 0 , 12 );
|
68 |
+
$fUsernameFound = false; // if username is never found, it means there's no yubikey specified which means we can bypass this authentication method.
|
69 |
+
$fFoundMatch = false;
|
70 |
+
foreach( $aYubikeyUsernamePairs as $aUsernameYubikeyPair ) {
|
71 |
+
if ( isset( $aUsernameYubikeyPair[$oUser->user_login] ) ) {
|
72 |
+
$fUsernameFound = true;
|
73 |
+
if ( $aUsernameYubikeyPair[$oUser->user_login] == $sYubikey12 ) {
|
74 |
+
$fFoundMatch = true;
|
75 |
+
break;
|
76 |
+
}
|
77 |
+
}
|
78 |
+
}
|
79 |
+
|
80 |
+
// If no yubikey-username pair found for given username, we by-pass Yubikey auth.
|
81 |
+
if ( !$fUsernameFound ) {
|
82 |
+
$this->logWarning(
|
83 |
+
sprintf( _wpsf__('User "%s" logged in without a Yubikey One Time Password because no username-yubikey pair was found for this user.'), $oUser->user_login )
|
84 |
+
);
|
85 |
+
return $oUser;
|
86 |
+
}
|
87 |
+
|
88 |
+
// Username was found in the list of key pairs, but the yubikey provided didn't match that username.
|
89 |
+
if ( !$fFoundMatch ) {
|
90 |
+
$oError->add(
|
91 |
+
'yubikey_not_allowed',
|
92 |
+
sprintf( _wpsf__( 'ERROR: %s' ), _wpsf__('The Yubikey provided is not on the list of permitted keys for this user.') )
|
93 |
+
);
|
94 |
+
$this->logWarning(
|
95 |
+
sprintf( _wpsf__('User "%s" attempted to login but Yubikey ID used was not in list of authorised keys: "%s".'), $oUser->user_login, $sYubikey12 )
|
96 |
+
);
|
97 |
+
return $oError;
|
98 |
+
}
|
99 |
+
|
100 |
+
$oFs = $this->loadFileSystemProcessor();
|
101 |
+
|
102 |
+
$sNonce = md5( uniqid( rand() ) );
|
103 |
+
$sUrl = sprintf( self::YubikeyVerifyApiUrl, $sAppId, $sOneTimePassword, $sNonce );
|
104 |
+
$sRawYubiRequest = $oFs->getUrlContent( $sUrl );
|
105 |
+
|
106 |
+
// Validate response.
|
107 |
+
// 1. Check OTP and Nonce
|
108 |
+
if ( !preg_match( '/otp='.$sOneTimePassword.'/', $sRawYubiRequest, $aMatches )
|
109 |
+
|| !preg_match( '/nonce='.$sNonce.'/', $sRawYubiRequest, $aMatches )
|
110 |
+
) {
|
111 |
+
$oError->add(
|
112 |
+
'yubikey_validate_fail',
|
113 |
+
sprintf( _wpsf__( 'ERROR: %s' ), _wpsf__('The Yubikey authentication was not validated successfully.') )
|
114 |
+
);
|
115 |
+
$this->logWarning(
|
116 |
+
sprintf( _wpsf__('User "%s" attempted to login but Yubikey One Time Password failed to validate due to invalid Yubi API.'), $oUser->user_login )
|
117 |
+
);
|
118 |
+
return $oError;
|
119 |
+
}
|
120 |
+
|
121 |
+
// Optionally we can check the hash, but since we're using HTTPS, this isn't necessary and adds more PHP requirements
|
122 |
+
|
123 |
+
// 2. Check status directly within response
|
124 |
+
preg_match( '/status=([a-zA-Z0-9_]+)/', $sRawYubiRequest, $aMatches );
|
125 |
+
$sStatus = $aMatches[1];
|
126 |
+
|
127 |
+
if ( $sStatus != 'OK' && $sStatus != 'REPLAYED_OTP' ) {
|
128 |
+
$oError->add(
|
129 |
+
'yubikey_validate_fail',
|
130 |
+
sprintf( _wpsf__( 'ERROR: %s' ), _wpsf__('The Yubikey authentication was not validated successfully.') )
|
131 |
+
);
|
132 |
+
$this->logWarning(
|
133 |
+
sprintf( _wpsf__('User "%s" attempted to login but Yubikey One Time Password failed to validate due to invalid Yubi API response status: %s.'), $oUser->user_login, $sStatus )
|
134 |
+
);
|
135 |
+
return $oError;
|
136 |
+
}
|
137 |
+
|
138 |
+
$this->logInfo(
|
139 |
+
sprintf( _wpsf__('User "%s" successfully logged in using a validated Yubikey One Time Password.'), $oUser->user_login )
|
140 |
+
);
|
141 |
+
return $oUser;
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
*/
|
146 |
+
public function printYubikeyOtp_Action() {
|
147 |
+
$sHtml =
|
148 |
+
'<p class="yubikey-otp">
|
149 |
+
<label>%s<br />
|
150 |
+
<input type="text" name="yubiotp" class="input" value="" size="20" />
|
151 |
+
</label>
|
152 |
+
</p>
|
153 |
+
';
|
154 |
+
echo sprintf( $sHtml, '<a href="http://icwp.io/4i" target="_blank">'._wpsf__('Yubikey OTP').'</a>' );
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* @return bool
|
159 |
+
*/
|
160 |
+
protected function getIsYubikeyConfigReady() {
|
161 |
+
$sAppId = $this->getOption('yubikey_app_id');
|
162 |
+
$sApiKey = $this->getOption('yubikey_api_key');
|
163 |
+
$aYubikeyKeys = $this->getOption('yubikey_unique_keys');
|
164 |
+
return !empty($sAppId) && !empty($sApiKey) && !empty($aYubikeyKeys);
|
165 |
+
}
|
166 |
+
}
|
167 |
+
endif;
|
src/icwp-processor-plugin.php
CHANGED
@@ -15,11 +15,16 @@
|
|
15 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
*/
|
17 |
|
18 |
-
require_once( dirname(__FILE__).'/icwp-base
|
19 |
|
20 |
-
if ( !class_exists('
|
21 |
|
22 |
-
class
|
|
|
|
|
|
|
|
|
|
|
23 |
|
24 |
/**
|
25 |
* @param ICWP_WPSF_FeatureHandler_Plugin $oFeatureOptions
|
@@ -29,18 +34,196 @@ class ICWP_WPSF_PluginProcessor extends ICWP_WPSF_BaseProcessor {
|
|
29 |
}
|
30 |
|
31 |
/**
|
32 |
-
*
|
33 |
*/
|
34 |
public function run() {
|
|
|
35 |
$this->removePluginConflicts();
|
36 |
-
add_filter( $
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
}
|
38 |
|
|
|
|
|
|
|
|
|
39 |
public function getIsShowMarketing( $fShow ) {
|
40 |
if ( !$fShow ) {
|
41 |
return $fShow;
|
42 |
}
|
43 |
|
|
|
|
|
|
|
|
|
44 |
$oWpFunctions = $this->loadWpFunctionsProcessor();
|
45 |
if ( class_exists( 'Worpit_Plugin' ) ) {
|
46 |
if ( method_exists( 'Worpit_Plugin', 'IsLinked' ) ) {
|
@@ -53,10 +236,6 @@ class ICWP_WPSF_PluginProcessor extends ICWP_WPSF_BaseProcessor {
|
|
53 |
}
|
54 |
}
|
55 |
|
56 |
-
if ( $this->getInstallationDays() < 1 ) {
|
57 |
-
$fShow = false;
|
58 |
-
}
|
59 |
-
|
60 |
return $fShow;
|
61 |
}
|
62 |
|
@@ -64,8 +243,8 @@ class ICWP_WPSF_PluginProcessor extends ICWP_WPSF_BaseProcessor {
|
|
64 |
* @return int
|
65 |
*/
|
66 |
protected function getInstallationDays() {
|
67 |
-
$nTimeInstalled = $this->
|
68 |
-
if ( empty($nTimeInstalled) ) {
|
69 |
return 0;
|
70 |
}
|
71 |
return round( ( time() - $nTimeInstalled ) / DAY_IN_SECONDS );
|
@@ -81,6 +260,21 @@ class ICWP_WPSF_PluginProcessor extends ICWP_WPSF_BaseProcessor {
|
|
81 |
remove_action( 'init', array( $GLOBALS['aio_wp_security'], 'wp_security_plugin_init'), 0 );
|
82 |
}
|
83 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
84 |
}
|
85 |
|
86 |
endif;
|
15 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
*/
|
17 |
|
18 |
+
require_once( dirname(__FILE__).'/icwp-processor-base.php' );
|
19 |
|
20 |
+
if ( !class_exists('ICWP_WPSF_Processor_Plugin') ):
|
21 |
|
22 |
+
class ICWP_WPSF_Processor_Plugin extends ICWP_WPSF_Processor_Base {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var ICWP_WPSF_FeatureHandler_Plugin
|
26 |
+
*/
|
27 |
+
protected $oFeatureOptions;
|
28 |
|
29 |
/**
|
30 |
* @param ICWP_WPSF_FeatureHandler_Plugin $oFeatureOptions
|
34 |
}
|
35 |
|
36 |
/**
|
|
|
37 |
*/
|
38 |
public function run() {
|
39 |
+
$oFO = $this->getFeatureOptions();
|
40 |
$this->removePluginConflicts();
|
41 |
+
add_filter( $oFO->doPluginPrefix( 'show_marketing' ), array( $this, 'getIsShowMarketing' ) );
|
42 |
+
|
43 |
+
if ( $oFO->getController()->getIsValidAdminArea() ) {
|
44 |
+
|
45 |
+
// always show this notice
|
46 |
+
add_filter( $oFO->doPluginPrefix( 'admin_notices' ), array( $this, 'adminNoticeForceOffActive' ) );
|
47 |
+
add_filter( $oFO->doPluginPrefix( 'admin_notices' ), array( $this, 'adminNoticeFeedback' ) );
|
48 |
+
if ( $this->getIfShowAdminNotices() ) {
|
49 |
+
add_filter( $oFO->doPluginPrefix( 'admin_notices' ), array( $this, 'adminNoticeMailingListSignup' ) );
|
50 |
+
add_filter( $oFO->doPluginPrefix( 'admin_notices' ), array( $this, 'adminNoticeTranslations' ) );
|
51 |
+
add_filter( $oFO->doPluginPrefix( 'admin_notices' ), array( $this, 'adminNoticePluginUpgradeAvailable' ) );
|
52 |
+
add_filter( $oFO->doPluginPrefix( 'admin_notices' ), array( $this, 'adminNoticePostPluginUpgrade' ) );
|
53 |
+
}
|
54 |
+
|
55 |
+
}
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* @param array $aAdminNotices
|
60 |
+
* @return array
|
61 |
+
*/
|
62 |
+
public function adminNoticeForceOffActive( $aAdminNotices ) {
|
63 |
+
$fOverride = $this->getFeatureOptions()->getIfOverride();
|
64 |
+
if ( $fOverride ) {
|
65 |
+
ob_start();
|
66 |
+
include( $this->getFeatureOptions()->getViewSnippet( 'admin_notice_override' ) );
|
67 |
+
$sNoticeMessage = ob_get_contents();
|
68 |
+
ob_end_clean();
|
69 |
+
$aAdminNotices[] = $this->getAdminNoticeHtml( $sNoticeMessage, 'error', false );
|
70 |
+
}
|
71 |
+
return $aAdminNotices;
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* @param array $aAdminNotices
|
76 |
+
* @return array
|
77 |
+
*/
|
78 |
+
public function adminNoticeFeedback( $aAdminNotices ) {
|
79 |
+
$aAdminFeedbackNotice = $this->getOption( 'feedback_admin_notice' );
|
80 |
+
|
81 |
+
if ( !empty( $aAdminFeedbackNotice ) && is_array( $aAdminFeedbackNotice ) ) {
|
82 |
+
|
83 |
+
foreach ( $aAdminFeedbackNotice as $sNotice ) {
|
84 |
+
if ( empty( $sNotice ) || !is_string( $sNotice ) ) {
|
85 |
+
continue;
|
86 |
+
}
|
87 |
+
$aAdminNotices[] = $this->getAdminNoticeHtml( '<p>'.$sNotice.'</p>', 'updated', false );
|
88 |
+
}
|
89 |
+
$this->getFeatureOptions()->doClearAdminFeedback( 'feedback_admin_notice', array() );
|
90 |
+
}
|
91 |
+
|
92 |
+
return $aAdminNotices;
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* @param array $aAdminNotices
|
97 |
+
* @return array
|
98 |
+
*/
|
99 |
+
public function adminNoticeMailingListSignup( $aAdminNotices ) {
|
100 |
+
|
101 |
+
$nDays = $this->getInstallationDays();
|
102 |
+
if ( $nDays < 2 ) {
|
103 |
+
return $aAdminNotices;
|
104 |
+
}
|
105 |
+
|
106 |
+
$sCurrentMetaValue = $this->loadWpFunctionsProcessor()->getUserMeta( $this->getFeatureOptions()->prefixOptionKey( 'plugin_mailing_list_signup' ) );
|
107 |
+
if ( $sCurrentMetaValue == 'Y' ) {
|
108 |
+
return $aAdminNotices;
|
109 |
+
}
|
110 |
+
|
111 |
+
$sLink_HideNotice = $this->getUrl_PluginDashboard().'&'.$this->getFeatureOptions()->doPluginPrefix( 'hide_mailing_list_signup' ).'=1';
|
112 |
+
ob_start();
|
113 |
+
include( $this->getFeatureOptions()->getViewSnippet( 'admin_notice_mailchimp' ) );
|
114 |
+
$sNoticeMessage = ob_get_contents();
|
115 |
+
ob_end_clean();
|
116 |
+
|
117 |
+
$aAdminNotices[] = $this->getAdminNoticeHtml( $sNoticeMessage, 'updated', false );
|
118 |
+
return $aAdminNotices;
|
119 |
+
}
|
120 |
+
|
121 |
+
/**
|
122 |
+
* @param array $aAdminNotices
|
123 |
+
* @return array
|
124 |
+
*/
|
125 |
+
public function adminNoticePluginUpgradeAvailable( $aAdminNotices ) {
|
126 |
+
|
127 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
128 |
+
// Don't show on the update page
|
129 |
+
if ( $oWp->getIsPage_Updates() || !$oWp->getIsPluginUpdateAvailable( $this->getFeatureOptions()->getPluginBaseFile() ) ) {
|
130 |
+
return $aAdminNotices;
|
131 |
+
}
|
132 |
+
|
133 |
+
$sNoticeMessage = '<p>'.sprintf( _wpsf__( 'There is an update available for your WordPress Security plugin: %s.' ), '<strong>'.$this->getFeatureOptions()->getController()->getHumanName().'</strong>' ).'</p>';
|
134 |
+
$sNoticeMessage .= sprintf( '<a href="%s" class="button">'._wpsf__( 'Please click to update immediately' ).'</a>', $oWp->getPluginUpgradeLink( $this->getFeatureOptions()->getPluginBaseFile() ) );
|
135 |
+
|
136 |
+
$aAdminNotices[] = $this->getAdminNoticeHtml( $sNoticeMessage, 'updated', false );
|
137 |
+
return $aAdminNotices;
|
138 |
+
}
|
139 |
+
|
140 |
+
/**
|
141 |
+
* @param array $aAdminNotices
|
142 |
+
* @return array
|
143 |
+
*/
|
144 |
+
public function adminNoticePostPluginUpgrade( $aAdminNotices ) {
|
145 |
+
$oController = $this->getFeatureOptions()->getController();
|
146 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
147 |
+
|
148 |
+
$sCurrentMetaValue = $oWp->getUserMeta( $oController->doPluginOptionPrefix( 'current_version' ) );
|
149 |
+
if ( empty( $sCurrentMetaValue ) || $sCurrentMetaValue === $this->getFeatureOptions()->getVersion() ) {
|
150 |
+
return $aAdminNotices;
|
151 |
+
}
|
152 |
+
|
153 |
+
if ( $this->getInstallationDays() <= 1 ) {
|
154 |
+
$sMessage = sprintf(
|
155 |
+
_wpsf__( "Note: The %s plugin does not automatically turn on feature when you install." ),
|
156 |
+
$oController->getHumanName()
|
157 |
+
);
|
158 |
+
}
|
159 |
+
else {
|
160 |
+
$sMessage = sprintf(
|
161 |
+
_wpsf__( "Note: The %s plugin has been recently upgraded, but please remember that any new features are not automatically enabled." ),
|
162 |
+
$oController->getHumanName()
|
163 |
+
);
|
164 |
+
}
|
165 |
+
$sMessage .= '<br />'.sprintf(
|
166 |
+
'<a href="%s" id="fromIcwp" title="%s" target="_blank">%s</a>',
|
167 |
+
'http://icwp.io/27',
|
168 |
+
$oController->getHumanName(),
|
169 |
+
_wpsf__( 'Click to read about any important updates from the plugin home page.' )
|
170 |
+
);
|
171 |
+
$sButtonText = _wpsf__( 'Okay, hide this notice and go to the plugin dashboard.' );
|
172 |
+
|
173 |
+
$sMetaFlag = $oController->doPluginPrefix( 'hide_update_notice' );
|
174 |
+
$sAction = $oController->getPluginUrl_AdminPage().'&'.$sMetaFlag.'=1';
|
175 |
+
$sRedirectPage = $oWp->getUrl_CurrentAdminPage();
|
176 |
+
ob_start();
|
177 |
+
include( $this->getFeatureOptions()->getViewSnippet( 'admin_notice_plugin_upgraded' ) );
|
178 |
+
$sNoticeMessage = ob_get_contents();
|
179 |
+
ob_end_clean();
|
180 |
+
|
181 |
+
$aAdminNotices[] = $this->getAdminNoticeHtml( $sNoticeMessage, 'updated', false );
|
182 |
+
return $aAdminNotices;
|
183 |
+
}
|
184 |
+
|
185 |
+
/**
|
186 |
+
* @param array $aAdminNotices
|
187 |
+
* @return array
|
188 |
+
*/
|
189 |
+
public function adminNoticeTranslations( $aAdminNotices ) {
|
190 |
+
if ( $this->getInstallationDays() < 7 ) {
|
191 |
+
return $aAdminNotices;
|
192 |
+
}
|
193 |
+
|
194 |
+
$oController = $this->getFeatureOptions()->getController();
|
195 |
+
|
196 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
197 |
+
$sCurrentMetaValue = $oWp->getUserMeta( $oController->doPluginOptionPrefix( 'plugin_translation_notice' ) );
|
198 |
+
if ( empty( $sCurrentMetaValue ) || $sCurrentMetaValue === 'Y' ) {
|
199 |
+
return $aAdminNotices;
|
200 |
+
}
|
201 |
+
|
202 |
+
ob_start();
|
203 |
+
$sMetaFlag = $oController->doPluginPrefix( 'hide_translation_notice' );
|
204 |
+
$sAction = $oController->getPluginUrl_AdminPage().'&'.$sMetaFlag.'=1';
|
205 |
+
$sRedirectPage = $oWp->getUrl_CurrentAdminPage();
|
206 |
+
include( $this->getFeatureOptions()->getViewSnippet( 'admin_notice_translate_plugin' ) );
|
207 |
+
$sNoticeMessage = ob_get_contents();
|
208 |
+
ob_end_clean();
|
209 |
+
|
210 |
+
$aAdminNotices[] = $this->getAdminNoticeHtml( $sNoticeMessage, 'updated', false );
|
211 |
+
return $aAdminNotices;
|
212 |
}
|
213 |
|
214 |
+
/**
|
215 |
+
* @param $fShow
|
216 |
+
* @return bool
|
217 |
+
*/
|
218 |
public function getIsShowMarketing( $fShow ) {
|
219 |
if ( !$fShow ) {
|
220 |
return $fShow;
|
221 |
}
|
222 |
|
223 |
+
if ( $this->getInstallationDays() < 1 ) {
|
224 |
+
$fShow = false;
|
225 |
+
}
|
226 |
+
|
227 |
$oWpFunctions = $this->loadWpFunctionsProcessor();
|
228 |
if ( class_exists( 'Worpit_Plugin' ) ) {
|
229 |
if ( method_exists( 'Worpit_Plugin', 'IsLinked' ) ) {
|
236 |
}
|
237 |
}
|
238 |
|
|
|
|
|
|
|
|
|
239 |
return $fShow;
|
240 |
}
|
241 |
|
243 |
* @return int
|
244 |
*/
|
245 |
protected function getInstallationDays() {
|
246 |
+
$nTimeInstalled = $this->getFeatureOptions()->getOpt( 'installation_time' );
|
247 |
+
if ( empty( $nTimeInstalled ) ) {
|
248 |
return 0;
|
249 |
}
|
250 |
return round( ( time() - $nTimeInstalled ) / DAY_IN_SECONDS );
|
260 |
remove_action( 'init', array( $GLOBALS['aio_wp_security'], 'wp_security_plugin_init'), 0 );
|
261 |
}
|
262 |
}
|
263 |
+
|
264 |
+
/**
|
265 |
+
* @return bool
|
266 |
+
*/
|
267 |
+
protected function getIfShowAdminNotices() {
|
268 |
+
return $this->getFeatureOptions()->getOptIs( 'enable_upgrade_admin_notice', 'Y' );
|
269 |
+
}
|
270 |
+
|
271 |
+
/**
|
272 |
+
* @param string $sFeaturePage - leave empty to get the main dashboard
|
273 |
+
* @return mixed
|
274 |
+
*/
|
275 |
+
protected function getUrl_PluginDashboard( $sFeaturePage = '' ) {
|
276 |
+
return network_admin_url( sprintf( 'admin.php?page=%s', $this->getFeatureOptions()->doPluginPrefix( $sFeaturePage ) ) );
|
277 |
+
}
|
278 |
}
|
279 |
|
280 |
endif;
|
src/icwp-processor-privacyprotect.php
CHANGED
@@ -15,11 +15,11 @@
|
|
15 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
*/
|
17 |
|
18 |
-
require_once( dirname(__FILE__).'/icwp-basedb
|
19 |
|
20 |
if ( !class_exists('ICWP_PrivacyProtectProcessor_V1') ):
|
21 |
|
22 |
-
class ICWP_PrivacyProtectProcessor_V1 extends
|
23 |
|
24 |
const TableName = 'privacy_protect';
|
25 |
|
@@ -28,19 +28,9 @@ class ICWP_PrivacyProtectProcessor_V1 extends ICWP_BaseDbProcessor_WPSF {
|
|
28 |
*/
|
29 |
public function __construct( ICWP_WPSF_FeatureHandler_LoginProtect $oFeatureOptions ) {
|
30 |
parent::__construct( $oFeatureOptions, self::TableName );
|
31 |
-
$this->createTable();
|
32 |
$this->reset();
|
33 |
}
|
34 |
|
35 |
-
/**
|
36 |
-
* Resets the object values to be re-used anew
|
37 |
-
*/
|
38 |
-
public function reset() {
|
39 |
-
parent::reset();
|
40 |
-
$this->m_sUniqueToken = '';
|
41 |
-
$this->m_sCommentStatus = '';
|
42 |
-
}
|
43 |
-
|
44 |
/**
|
45 |
*/
|
46 |
public function run() {
|
@@ -150,7 +140,10 @@ class ICWP_PrivacyProtectProcessor_V1 extends ICWP_BaseDbProcessor_WPSF {
|
|
150 |
return $aLogData;
|
151 |
}
|
152 |
|
153 |
-
|
|
|
|
|
|
|
154 |
$sSqlTables = "CREATE TABLE IF NOT EXISTS `%s` (
|
155 |
`id` int(11) NOT NULL AUTO_INCREMENT,
|
156 |
`request_url` varchar(255) NOT NULL DEFAULT '',
|
@@ -163,13 +156,12 @@ class ICWP_PrivacyProtectProcessor_V1 extends ICWP_BaseDbProcessor_WPSF {
|
|
163 |
`deleted_at` int(15) NOT NULL DEFAULT 0,
|
164 |
PRIMARY KEY (`id`)
|
165 |
) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
|
166 |
-
|
167 |
-
$mResult = $this->doSql( $sSqlTables );
|
168 |
}
|
169 |
}
|
170 |
|
171 |
endif;
|
172 |
|
173 |
-
if ( !class_exists('
|
174 |
-
class
|
175 |
endif;
|
15 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
*/
|
17 |
|
18 |
+
require_once( dirname(__FILE__).'/icwp-processor-basedb.php' );
|
19 |
|
20 |
if ( !class_exists('ICWP_PrivacyProtectProcessor_V1') ):
|
21 |
|
22 |
+
class ICWP_PrivacyProtectProcessor_V1 extends ICWP_WPSF_BaseDbProcessor {
|
23 |
|
24 |
const TableName = 'privacy_protect';
|
25 |
|
28 |
*/
|
29 |
public function __construct( ICWP_WPSF_FeatureHandler_LoginProtect $oFeatureOptions ) {
|
30 |
parent::__construct( $oFeatureOptions, self::TableName );
|
|
|
31 |
$this->reset();
|
32 |
}
|
33 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
/**
|
35 |
*/
|
36 |
public function run() {
|
140 |
return $aLogData;
|
141 |
}
|
142 |
|
143 |
+
/**
|
144 |
+
* @return string
|
145 |
+
*/
|
146 |
+
public function getCreateTableSql() {
|
147 |
$sSqlTables = "CREATE TABLE IF NOT EXISTS `%s` (
|
148 |
`id` int(11) NOT NULL AUTO_INCREMENT,
|
149 |
`request_url` varchar(255) NOT NULL DEFAULT '',
|
156 |
`deleted_at` int(15) NOT NULL DEFAULT 0,
|
157 |
PRIMARY KEY (`id`)
|
158 |
) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
|
159 |
+
return sprintf( $sSqlTables, $this->getTableName() );
|
|
|
160 |
}
|
161 |
}
|
162 |
|
163 |
endif;
|
164 |
|
165 |
+
if ( !class_exists('ICWP_WPSF_Processor_PrivacyProtect') ):
|
166 |
+
class ICWP_WPSF_Processor_PrivacyProtect extends ICWP_PrivacyProtectProcessor_V1 { }
|
167 |
endif;
|
src/{icwp-processor-usermanagement.php → icwp-processor-user_management.php}
RENAMED
@@ -15,11 +15,11 @@
|
|
15 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
*/
|
17 |
|
18 |
-
require_once( dirname(__FILE__).'/icwp-basedb
|
19 |
|
20 |
if ( !class_exists('ICWP_WPSF_Processor_UserManagement_V1') ):
|
21 |
|
22 |
-
class ICWP_WPSF_Processor_UserManagement_V1 extends
|
23 |
|
24 |
const Session_Cookie = 'wpsf_sesh_id';
|
25 |
|
@@ -41,17 +41,28 @@ class ICWP_WPSF_Processor_UserManagement_V1 extends ICWP_BaseDbProcessor_WPSF {
|
|
41 |
* @param ICWP_WPSF_FeatureHandler_UserManagement $oFeatureOptions
|
42 |
*/
|
43 |
public function __construct( ICWP_WPSF_FeatureHandler_UserManagement $oFeatureOptions ) {
|
44 |
-
parent::__construct( $oFeatureOptions );
|
45 |
-
$this->createTable();
|
46 |
}
|
47 |
|
48 |
/**
|
49 |
*/
|
50 |
public function run() {
|
51 |
parent::run();
|
52 |
-
$this->loadDataProcessor();
|
53 |
|
54 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
$fIsPost = strtolower( empty($sRequestMethod)? '' : $sRequestMethod ) == 'post';
|
56 |
|
57 |
// Check the current logged-in user every page load.
|
@@ -68,13 +79,16 @@ class ICWP_WPSF_Processor_UserManagement_V1 extends ICWP_BaseDbProcessor_WPSF {
|
|
68 |
add_filter( 'authenticate', array( $this, 'createNewUserSession_Filter' ), 30, 3);
|
69 |
|
70 |
// When we know user has successfully authenticated and we activate the session entry in the database
|
71 |
-
add_action( 'wp_login', array( $this, '
|
|
|
|
|
72 |
|
73 |
add_action( 'wp_logout', array( $this, 'onWpLogout' ) );
|
74 |
|
75 |
add_filter( 'wp_login_errors', array( $this, 'addLoginMessage' ) );
|
76 |
}
|
77 |
|
|
|
78 |
/**
|
79 |
* @param WP_Error $oError
|
80 |
* @return WP_Error
|
@@ -85,8 +99,8 @@ class ICWP_WPSF_Processor_UserManagement_V1 extends ICWP_BaseDbProcessor_WPSF {
|
|
85 |
$oError = new WP_Error();
|
86 |
}
|
87 |
|
88 |
-
$this->loadDataProcessor();
|
89 |
-
$sForceLogout =
|
90 |
if ( $sForceLogout == 1 ) {
|
91 |
$oError->add( 'wpsf-forcelogout', _wpsf__('Your session has expired.').'<br />'._wpsf__('Please login again.') );
|
92 |
}
|
@@ -96,6 +110,12 @@ class ICWP_WPSF_Processor_UserManagement_V1 extends ICWP_BaseDbProcessor_WPSF {
|
|
96 |
else if ( $sForceLogout == 3 ) {
|
97 |
$oError->add( 'wpsf-forcelogout', _wpsf__('Your session was locked to another IP Address.').'<br />'._wpsf__('Please login again.') );
|
98 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
return $oError;
|
100 |
}
|
101 |
|
@@ -105,10 +125,28 @@ class ICWP_WPSF_Processor_UserManagement_V1 extends ICWP_BaseDbProcessor_WPSF {
|
|
105 |
public function checkCurrentUser_Action() {
|
106 |
$this->getSessionId();
|
107 |
if ( is_user_logged_in() ) {
|
108 |
-
$
|
109 |
-
$
|
110 |
-
|
111 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
112 |
}
|
113 |
}
|
114 |
|
@@ -120,44 +158,39 @@ class ICWP_WPSF_Processor_UserManagement_V1 extends ICWP_BaseDbProcessor_WPSF {
|
|
120 |
return false;
|
121 |
}
|
122 |
|
|
|
|
|
123 |
$aLoginSessionData = $this->getUserSessionRecord( $oUser->user_login );
|
124 |
if ( !$aLoginSessionData ) {
|
125 |
-
$
|
126 |
}
|
127 |
|
128 |
// check timeout interval
|
129 |
$nSessionTimeoutInterval = $this->getSessionTimeoutInterval();
|
130 |
if ( $nSessionTimeoutInterval > 0 && ( self::$nRequestTimestamp - $aLoginSessionData['logged_in_at'] > $nSessionTimeoutInterval ) ) {
|
131 |
-
$
|
132 |
}
|
133 |
|
134 |
// check idle timeout interval
|
135 |
$nSessionIdleTimeoutInterval = $this->getOption( 'session_idle_timeout_interval', 0 ) * HOUR_IN_SECONDS;
|
136 |
if ( intval($nSessionIdleTimeoutInterval) > 0 && ( (self::$nRequestTimestamp - $aLoginSessionData['last_activity_at']) > $nSessionIdleTimeoutInterval ) ) {
|
137 |
-
$
|
138 |
}
|
139 |
|
140 |
// check login ip address
|
141 |
$fLockToIp = $this->getIsOption( 'session_lock_location', 'Y' );
|
142 |
if ( $fLockToIp && self::$nRequestIp != $aLoginSessionData['ip_long'] ) {
|
143 |
-
$
|
144 |
}
|
|
|
|
|
145 |
}
|
146 |
|
147 |
/**
|
148 |
* @return integer
|
149 |
*/
|
150 |
protected function getSessionTimeoutInterval( ) {
|
151 |
-
return $this->getOption( 'session_timeout_interval'
|
152 |
-
}
|
153 |
-
|
154 |
-
/**
|
155 |
-
*
|
156 |
-
*/
|
157 |
-
protected function doLogout( $sParams = '' ) {
|
158 |
-
$oWp = $this->loadWpFunctionsProcessor();
|
159 |
-
$oWp->logoutUser();
|
160 |
-
$oWp->redirectToLogin( $sParams );
|
161 |
}
|
162 |
|
163 |
/**
|
@@ -173,7 +206,7 @@ class ICWP_WPSF_Processor_UserManagement_V1 extends ICWP_BaseDbProcessor_WPSF {
|
|
173 |
* Should return false when logging is disabled.
|
174 |
*
|
175 |
* @return false|array - false when logging is disabled, array with log data otherwise
|
176 |
-
* @see
|
177 |
*/
|
178 |
public function flushLogData() {
|
179 |
|
@@ -220,33 +253,41 @@ class ICWP_WPSF_Processor_UserManagement_V1 extends ICWP_BaseDbProcessor_WPSF {
|
|
220 |
*
|
221 |
*/
|
222 |
public function onWpLogout() {
|
223 |
-
$
|
224 |
-
$this->doTerminateUserSession( $oUser->user_login );
|
225 |
}
|
226 |
|
227 |
/**
|
228 |
-
* @param $sUsername
|
229 |
* @return boolean
|
230 |
*/
|
231 |
-
protected function
|
232 |
-
|
|
|
|
|
233 |
return false;
|
234 |
}
|
235 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
236 |
$aNewData = array(
|
237 |
'deleted_at' => self::$nRequestTimestamp
|
238 |
);
|
239 |
$aWhere = array(
|
240 |
-
'session_id' => $
|
241 |
'wp_username' => $sUsername,
|
242 |
'deleted_at' => 0
|
243 |
);
|
244 |
-
|
245 |
-
|
246 |
-
unset( $_COOKIE[ self::Session_Cookie ] );
|
247 |
-
setcookie( self::Session_Cookie, "", time()-3600, COOKIEPATH, COOKIE_DOMAIN, false );
|
248 |
-
|
249 |
-
return $mResult;
|
250 |
}
|
251 |
|
252 |
/**
|
@@ -258,7 +299,7 @@ class ICWP_WPSF_Processor_UserManagement_V1 extends ICWP_BaseDbProcessor_WPSF {
|
|
258 |
return false;
|
259 |
}
|
260 |
|
261 |
-
$this->loadDataProcessor();
|
262 |
// Add new session entry
|
263 |
// set attempts = 1 and then when we know it's a valid login, we zero it.
|
264 |
// First set any other entries for the given user to be deleted.
|
@@ -270,7 +311,7 @@ class ICWP_WPSF_Processor_UserManagement_V1 extends ICWP_BaseDbProcessor_WPSF {
|
|
270 |
$aNewData[ 'pending' ] = 1;
|
271 |
$aNewData[ 'logged_in_at' ] = self::$nRequestTimestamp;
|
272 |
$aNewData[ 'last_activity_at' ] = self::$nRequestTimestamp;
|
273 |
-
$aNewData[ 'last_activity_uri' ] =
|
274 |
$aNewData[ 'created_at' ] = self::$nRequestTimestamp;
|
275 |
$mResult = $this->insertIntoTable( $aNewData );
|
276 |
|
@@ -280,7 +321,17 @@ class ICWP_WPSF_Processor_UserManagement_V1 extends ICWP_BaseDbProcessor_WPSF {
|
|
280 |
/**
|
281 |
*/
|
282 |
protected function setSessionCookie() {
|
283 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
284 |
}
|
285 |
|
286 |
/**
|
@@ -297,19 +348,26 @@ class ICWP_WPSF_Processor_UserManagement_V1 extends ICWP_BaseDbProcessor_WPSF {
|
|
297 |
'login_attempts' => $aSessionData['login_attempts'] + 1
|
298 |
);
|
299 |
return $this->updateCurrentSession( $sUsername, $aNewData );
|
300 |
-
return $mResult;
|
301 |
}
|
302 |
|
303 |
/**
|
304 |
* @param string $sUsername
|
305 |
* @return boolean
|
306 |
*/
|
307 |
-
public function
|
308 |
if ( empty( $sUsername ) ) {
|
309 |
return false;
|
310 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
311 |
|
312 |
-
// First set any other entries for the given user to be deleted.
|
313 |
$aNewData = array(
|
314 |
'pending' => 0,
|
315 |
'logged_in_at' => self::$nRequestTimestamp,
|
@@ -328,6 +386,48 @@ class ICWP_WPSF_Processor_UserManagement_V1 extends ICWP_BaseDbProcessor_WPSF {
|
|
328 |
return $mResult;
|
329 |
}
|
330 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
331 |
/**
|
332 |
* @param WP_User $oUser
|
333 |
* @return boolean
|
@@ -337,7 +437,6 @@ class ICWP_WPSF_Processor_UserManagement_V1 extends ICWP_BaseDbProcessor_WPSF {
|
|
337 |
return false;
|
338 |
}
|
339 |
|
340 |
-
// First set any other entries for the given user to be deleted.
|
341 |
$aNewData = array(
|
342 |
'last_activity_at' => self::$nRequestTimestamp
|
343 |
);
|
@@ -353,10 +452,9 @@ class ICWP_WPSF_Processor_UserManagement_V1 extends ICWP_BaseDbProcessor_WPSF {
|
|
353 |
return false;
|
354 |
}
|
355 |
|
356 |
-
$this->loadDataProcessor();
|
357 |
-
// First set any other entries for the given user to be deleted.
|
358 |
$aNewData = array(
|
359 |
-
'last_activity_uri' =>
|
360 |
);
|
361 |
$mResult = $this->updateCurrentSession( $oUser->user_login, $aNewData );
|
362 |
return $mResult;
|
@@ -368,8 +466,18 @@ class ICWP_WPSF_Processor_UserManagement_V1 extends ICWP_BaseDbProcessor_WPSF {
|
|
368 |
* @return boolean
|
369 |
*/
|
370 |
protected function updateCurrentSession( $sUsername, $aUpdateData ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
371 |
$aWhere = array(
|
372 |
-
'session_id' => $
|
373 |
'deleted_at' => 0,
|
374 |
'wp_username' => $sUsername
|
375 |
);
|
@@ -399,6 +507,31 @@ class ICWP_WPSF_Processor_UserManagement_V1 extends ICWP_BaseDbProcessor_WPSF {
|
|
399 |
return $this->selectCustomFromTable( $sQuery );
|
400 |
}
|
401 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
402 |
/**
|
403 |
* Checks for and gets a user session.
|
404 |
*
|
@@ -426,6 +559,33 @@ class ICWP_WPSF_Processor_UserManagement_V1 extends ICWP_BaseDbProcessor_WPSF {
|
|
426 |
return $this->selectCustomFromTable( $sQuery );
|
427 |
}
|
428 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
429 |
/**
|
430 |
* Checks for and gets a user session.
|
431 |
*
|
@@ -452,12 +612,7 @@ class ICWP_WPSF_Processor_UserManagement_V1 extends ICWP_BaseDbProcessor_WPSF {
|
|
452 |
if ( is_array( $mResult ) && count( $mResult ) == 1 ) {
|
453 |
return $mResult[0];
|
454 |
}
|
455 |
-
|
456 |
-
$this->logWarning(
|
457 |
-
sprintf( _wpsf__('User "%s" was found to be un-verified at the given IP Address "%s"'), $sUsername, long2ip( self::$nRequestIp ) )
|
458 |
-
);
|
459 |
-
return false;
|
460 |
-
}
|
461 |
}
|
462 |
|
463 |
/**
|
@@ -465,9 +620,9 @@ class ICWP_WPSF_Processor_UserManagement_V1 extends ICWP_BaseDbProcessor_WPSF {
|
|
465 |
*/
|
466 |
protected function getSessionId() {
|
467 |
if ( empty( $this->sSessionId ) ) {
|
468 |
-
$this->loadDataProcessor();
|
469 |
-
$this->sSessionId =
|
470 |
-
if (
|
471 |
$this->sSessionId = md5( uniqid() );
|
472 |
$this->setSessionCookie();
|
473 |
}
|
@@ -475,9 +630,10 @@ class ICWP_WPSF_Processor_UserManagement_V1 extends ICWP_BaseDbProcessor_WPSF {
|
|
475 |
return $this->sSessionId;
|
476 |
}
|
477 |
|
478 |
-
|
479 |
-
|
480 |
-
|
|
|
481 |
$sSqlTables = "CREATE TABLE IF NOT EXISTS `%s` (
|
482 |
`id` int(11) NOT NULL AUTO_INCREMENT,
|
483 |
`session_id` varchar(32) NOT NULL DEFAULT '',
|
@@ -493,8 +649,7 @@ class ICWP_WPSF_Processor_UserManagement_V1 extends ICWP_BaseDbProcessor_WPSF {
|
|
493 |
`deleted_at` int(15) NOT NULL DEFAULT '0',
|
494 |
PRIMARY KEY (`id`)
|
495 |
) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
|
496 |
-
|
497 |
-
$mResult = $this->doSql( $sSqlTables );
|
498 |
}
|
499 |
|
500 |
/**
|
@@ -532,4 +687,4 @@ endif;
|
|
532 |
|
533 |
if ( !class_exists('ICWP_WPSF_Processor_UserManagement') ):
|
534 |
class ICWP_WPSF_Processor_UserManagement extends ICWP_WPSF_Processor_UserManagement_V1 { }
|
535 |
-
endif;
|
15 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
*/
|
17 |
|
18 |
+
require_once( dirname(__FILE__).'/icwp-processor-basedb.php' );
|
19 |
|
20 |
if ( !class_exists('ICWP_WPSF_Processor_UserManagement_V1') ):
|
21 |
|
22 |
+
class ICWP_WPSF_Processor_UserManagement_V1 extends ICWP_WPSF_BaseDbProcessor {
|
23 |
|
24 |
const Session_Cookie = 'wpsf_sesh_id';
|
25 |
|
41 |
* @param ICWP_WPSF_FeatureHandler_UserManagement $oFeatureOptions
|
42 |
*/
|
43 |
public function __construct( ICWP_WPSF_FeatureHandler_UserManagement $oFeatureOptions ) {
|
44 |
+
parent::__construct( $oFeatureOptions, $oFeatureOptions->getUserSessionsTableName() );
|
|
|
45 |
}
|
46 |
|
47 |
/**
|
48 |
*/
|
49 |
public function run() {
|
50 |
parent::run();
|
51 |
+
$oDp = $this->loadDataProcessor();
|
52 |
|
53 |
+
$oWp = $this->oFeatureOptions->loadWpFunctionsProcessor();
|
54 |
+
// XML-RPC Compatibility
|
55 |
+
if ( $oWp->getIsXmlrpc() && $this->getIsOption( 'enable_xmlrpc_compatibility', 'Y' ) ) {
|
56 |
+
return true;
|
57 |
+
}
|
58 |
+
|
59 |
+
if ( is_email( $this->getOption( 'enable_admin_login_email_notification' ) ) ) {
|
60 |
+
require_once('icwp-processor-usermanagement_adminloginnotification.php');
|
61 |
+
$oNotificationProcessor = new ICWP_WPSF_Processor_UserManagement_AdminLoginNotification( $this->oFeatureOptions );
|
62 |
+
$oNotificationProcessor->run();
|
63 |
+
}
|
64 |
+
|
65 |
+
$sRequestMethod = $oDp->FetchServer( 'REQUEST_METHOD' );
|
66 |
$fIsPost = strtolower( empty($sRequestMethod)? '' : $sRequestMethod ) == 'post';
|
67 |
|
68 |
// Check the current logged-in user every page load.
|
79 |
add_filter( 'authenticate', array( $this, 'createNewUserSession_Filter' ), 30, 3);
|
80 |
|
81 |
// When we know user has successfully authenticated and we activate the session entry in the database
|
82 |
+
add_action( 'wp_login', array( $this, 'handleUserSession' ) );
|
83 |
+
|
84 |
+
// add_action( 'wp_loaded', array( $this, 'autoForwardFromLogin' ) );
|
85 |
|
86 |
add_action( 'wp_logout', array( $this, 'onWpLogout' ) );
|
87 |
|
88 |
add_filter( 'wp_login_errors', array( $this, 'addLoginMessage' ) );
|
89 |
}
|
90 |
|
91 |
+
|
92 |
/**
|
93 |
* @param WP_Error $oError
|
94 |
* @return WP_Error
|
99 |
$oError = new WP_Error();
|
100 |
}
|
101 |
|
102 |
+
$oDp = $this->loadDataProcessor();
|
103 |
+
$sForceLogout = $oDp->FetchGet( 'wpsf-forcelogout' );
|
104 |
if ( $sForceLogout == 1 ) {
|
105 |
$oError->add( 'wpsf-forcelogout', _wpsf__('Your session has expired.').'<br />'._wpsf__('Please login again.') );
|
106 |
}
|
110 |
else if ( $sForceLogout == 3 ) {
|
111 |
$oError->add( 'wpsf-forcelogout', _wpsf__('Your session was locked to another IP Address.').'<br />'._wpsf__('Please login again.') );
|
112 |
}
|
113 |
+
else if ( $sForceLogout == 4 ) {
|
114 |
+
$oError->add( 'wpsf-forcelogout', _wpsf__('You do not currently have a Simple Firewall user session.').'<br />'._wpsf__('Please login again.') );
|
115 |
+
}
|
116 |
+
else if ( $sForceLogout == 5 ) {
|
117 |
+
$oError->add( 'wpsf-forcelogout', _wpsf__('An administrator has terminated this session.').'<br />'._wpsf__('Please login again.') );
|
118 |
+
}
|
119 |
return $oError;
|
120 |
}
|
121 |
|
125 |
public function checkCurrentUser_Action() {
|
126 |
$this->getSessionId();
|
127 |
if ( is_user_logged_in() ) {
|
128 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
129 |
+
$oUser = $oWp->getCurrentWpUser();
|
130 |
+
|
131 |
+
// only check the non-admin areas if specified to do so and it's not AJAX (we've removed the option to check admin only)
|
132 |
+
// if ( !$oWp->getIsAjax() && ( is_admin() || !$this->getIsOption( 'session_check_admin_area_only', 'Y' ) ) ) {
|
133 |
+
if ( is_admin() ) {
|
134 |
+
$this->doVerifyCurrentUser( $oUser );
|
135 |
+
}
|
136 |
+
|
137 |
+
// At this point session is validated
|
138 |
+
|
139 |
+
// This used to be an option, but to simplify, we've removed it and do it anyway.
|
140 |
+
if ( true || $this->getIsOption( 'session_auto_forward_to_admin_area', 'Y' ) ) {
|
141 |
+
$oDp = $this->loadDataProcessor();
|
142 |
+
$sWpLogin = 'wp-login.php';
|
143 |
+
if ( $oDp->FetchGet( 'action' ) != 'logout' && ( substr( $oWp->getCurrentPage(), -strlen( $sWpLogin ) ) === $sWpLogin ) ) {
|
144 |
+
$oWp->redirectToAdmin();
|
145 |
+
}
|
146 |
+
}
|
147 |
+
|
148 |
+
// always track activity
|
149 |
+
$this->updateSessionLastActivity( $oUser );
|
150 |
}
|
151 |
}
|
152 |
|
158 |
return false;
|
159 |
}
|
160 |
|
161 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
162 |
+
|
163 |
$aLoginSessionData = $this->getUserSessionRecord( $oUser->user_login );
|
164 |
if ( !$aLoginSessionData ) {
|
165 |
+
$oWp->forceUserRelogin( array( 'wpsf-forcelogout' => 4 ) );
|
166 |
}
|
167 |
|
168 |
// check timeout interval
|
169 |
$nSessionTimeoutInterval = $this->getSessionTimeoutInterval();
|
170 |
if ( $nSessionTimeoutInterval > 0 && ( self::$nRequestTimestamp - $aLoginSessionData['logged_in_at'] > $nSessionTimeoutInterval ) ) {
|
171 |
+
$oWp->forceUserRelogin( array( 'wpsf-forcelogout' => 1 ) );
|
172 |
}
|
173 |
|
174 |
// check idle timeout interval
|
175 |
$nSessionIdleTimeoutInterval = $this->getOption( 'session_idle_timeout_interval', 0 ) * HOUR_IN_SECONDS;
|
176 |
if ( intval($nSessionIdleTimeoutInterval) > 0 && ( (self::$nRequestTimestamp - $aLoginSessionData['last_activity_at']) > $nSessionIdleTimeoutInterval ) ) {
|
177 |
+
$oWp->forceUserRelogin( array( 'wpsf-forcelogout' => 2 ) );
|
178 |
}
|
179 |
|
180 |
// check login ip address
|
181 |
$fLockToIp = $this->getIsOption( 'session_lock_location', 'Y' );
|
182 |
if ( $fLockToIp && self::$nRequestIp != $aLoginSessionData['ip_long'] ) {
|
183 |
+
$oWp->forceUserRelogin( array( 'wpsf-forcelogout' => 3 ) );
|
184 |
}
|
185 |
+
|
186 |
+
return true;
|
187 |
}
|
188 |
|
189 |
/**
|
190 |
* @return integer
|
191 |
*/
|
192 |
protected function getSessionTimeoutInterval( ) {
|
193 |
+
return $this->getOption( 'session_timeout_interval' ) * DAY_IN_SECONDS;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
194 |
}
|
195 |
|
196 |
/**
|
206 |
* Should return false when logging is disabled.
|
207 |
*
|
208 |
* @return false|array - false when logging is disabled, array with log data otherwise
|
209 |
+
* @see ICWP_WPSF_Processor_Base::getLogData()
|
210 |
*/
|
211 |
public function flushLogData() {
|
212 |
|
253 |
*
|
254 |
*/
|
255 |
public function onWpLogout() {
|
256 |
+
$this->doTerminateCurrentUserSession();
|
|
|
257 |
}
|
258 |
|
259 |
/**
|
|
|
260 |
* @return boolean
|
261 |
*/
|
262 |
+
protected function doTerminateCurrentUserSession() {
|
263 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
264 |
+
$oUser = $oWp->getCurrentWpUser();
|
265 |
+
if ( empty( $oUser->user_login ) ) {
|
266 |
return false;
|
267 |
}
|
268 |
|
269 |
+
$mResult = $this->doTerminateUserSession( $oUser->user_login, $this->getSessionId() );
|
270 |
+
unset( $_COOKIE[ $this->oFeatureOptions->getUserSessionCookieName() ] );
|
271 |
+
setcookie( $this->oFeatureOptions->getUserSessionCookieName(), "", time()-3600, COOKIEPATH, COOKIE_DOMAIN, false );
|
272 |
+
return $mResult;
|
273 |
+
}
|
274 |
+
|
275 |
+
/**
|
276 |
+
* @param string $sUsername
|
277 |
+
* @param string $sSessionId
|
278 |
+
* @return boolean
|
279 |
+
*/
|
280 |
+
protected function doTerminateUserSession( $sUsername, $sSessionId ) {
|
281 |
+
|
282 |
$aNewData = array(
|
283 |
'deleted_at' => self::$nRequestTimestamp
|
284 |
);
|
285 |
$aWhere = array(
|
286 |
+
'session_id' => $sSessionId,
|
287 |
'wp_username' => $sUsername,
|
288 |
'deleted_at' => 0
|
289 |
);
|
290 |
+
return $this->updateRowsFromTable( $aNewData, $aWhere );
|
|
|
|
|
|
|
|
|
|
|
291 |
}
|
292 |
|
293 |
/**
|
299 |
return false;
|
300 |
}
|
301 |
|
302 |
+
$oDp = $this->loadDataProcessor();
|
303 |
// Add new session entry
|
304 |
// set attempts = 1 and then when we know it's a valid login, we zero it.
|
305 |
// First set any other entries for the given user to be deleted.
|
311 |
$aNewData[ 'pending' ] = 1;
|
312 |
$aNewData[ 'logged_in_at' ] = self::$nRequestTimestamp;
|
313 |
$aNewData[ 'last_activity_at' ] = self::$nRequestTimestamp;
|
314 |
+
$aNewData[ 'last_activity_uri' ] = $oDp->FetchServer( 'REQUEST_URI' );
|
315 |
$aNewData[ 'created_at' ] = self::$nRequestTimestamp;
|
316 |
$mResult = $this->insertIntoTable( $aNewData );
|
317 |
|
321 |
/**
|
322 |
*/
|
323 |
protected function setSessionCookie() {
|
324 |
+
if ( $this->getSessionTimeoutInterval() > 0 ) {
|
325 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
326 |
+
setcookie(
|
327 |
+
$this->oFeatureOptions->getUserSessionCookieName(),
|
328 |
+
$this->getSessionId(),
|
329 |
+
self::$nRequestTimestamp + $this->getSessionTimeoutInterval(),
|
330 |
+
$oWp->getCookiePath(),
|
331 |
+
$oWp->getCookieDomain(),
|
332 |
+
false
|
333 |
+
);
|
334 |
+
}
|
335 |
}
|
336 |
|
337 |
/**
|
348 |
'login_attempts' => $aSessionData['login_attempts'] + 1
|
349 |
);
|
350 |
return $this->updateCurrentSession( $sUsername, $aNewData );
|
|
|
351 |
}
|
352 |
|
353 |
/**
|
354 |
* @param string $sUsername
|
355 |
* @return boolean
|
356 |
*/
|
357 |
+
public function handleUserSession( $sUsername ) {
|
358 |
if ( empty( $sUsername ) ) {
|
359 |
return false;
|
360 |
}
|
361 |
+
$this->activateUserSession( $sUsername );
|
362 |
+
$this->doLimitUserSession( $sUsername );
|
363 |
+
}
|
364 |
+
|
365 |
+
/**
|
366 |
+
* @param string $sUsername
|
367 |
+
* @return boolean
|
368 |
+
*/
|
369 |
+
protected function activateUserSession( $sUsername ) {
|
370 |
|
|
|
371 |
$aNewData = array(
|
372 |
'pending' => 0,
|
373 |
'logged_in_at' => self::$nRequestTimestamp,
|
386 |
return $mResult;
|
387 |
}
|
388 |
|
389 |
+
/**
|
390 |
+
* @param string $sUsername
|
391 |
+
* @return boolean
|
392 |
+
*/
|
393 |
+
protected function doLimitUserSession( $sUsername ) {
|
394 |
+
|
395 |
+
$nSessionLimit = $this->getOption( 'session_username_concurrent_limit', 1 );
|
396 |
+
if ( $nSessionLimit <= 0 ) {
|
397 |
+
return true;
|
398 |
+
}
|
399 |
+
|
400 |
+
$aSessions = $this->getActiveSessionRecordsForUser( $sUsername );
|
401 |
+
$nSessionsToKill = count( $aSessions ) - $nSessionLimit;
|
402 |
+
if ( $nSessionsToKill < 1 ) {
|
403 |
+
return true;
|
404 |
+
}
|
405 |
+
|
406 |
+
for( $nCount = 0; $nCount < $nSessionsToKill; $nCount++ ) {
|
407 |
+
$mResult = $this->doTerminateUserSession( $aSessions[$nCount]['wp_username'], $aSessions[$nCount]['session_id'] );
|
408 |
+
}
|
409 |
+
return $mResult;
|
410 |
+
}
|
411 |
+
|
412 |
+
/**
|
413 |
+
* This is the same as both updateSessionLastActivityAt() and updateSessionLastActivityUri()
|
414 |
+
*
|
415 |
+
* @param WP_User $oUser
|
416 |
+
* @return boolean
|
417 |
+
*/
|
418 |
+
protected function updateSessionLastActivity( $oUser ) {
|
419 |
+
if ( !is_object( $oUser ) || ! ( $oUser instanceof WP_User ) ) {
|
420 |
+
return false;
|
421 |
+
}
|
422 |
+
|
423 |
+
$oDp = $this->loadDataProcessor();
|
424 |
+
$aNewData = array(
|
425 |
+
'last_activity_at' => self::$nRequestTimestamp,
|
426 |
+
'last_activity_uri' => $oDp->FetchServer( 'REQUEST_URI' )
|
427 |
+
);
|
428 |
+
return $this->updateCurrentSession( $oUser->user_login, $aNewData );
|
429 |
+
}
|
430 |
+
|
431 |
/**
|
432 |
* @param WP_User $oUser
|
433 |
* @return boolean
|
437 |
return false;
|
438 |
}
|
439 |
|
|
|
440 |
$aNewData = array(
|
441 |
'last_activity_at' => self::$nRequestTimestamp
|
442 |
);
|
452 |
return false;
|
453 |
}
|
454 |
|
455 |
+
$oDp = $this->loadDataProcessor();
|
|
|
456 |
$aNewData = array(
|
457 |
+
'last_activity_uri' => $oDp->FetchServer( 'REQUEST_URI' )
|
458 |
);
|
459 |
$mResult = $this->updateCurrentSession( $oUser->user_login, $aNewData );
|
460 |
return $mResult;
|
466 |
* @return boolean
|
467 |
*/
|
468 |
protected function updateCurrentSession( $sUsername, $aUpdateData ) {
|
469 |
+
return $this->updateSession( $this->getSessionId(), $sUsername, $aUpdateData );
|
470 |
+
}
|
471 |
+
|
472 |
+
/**
|
473 |
+
* @param string $sSessionId
|
474 |
+
* @param string $sUsername
|
475 |
+
* @param array $aUpdateData
|
476 |
+
* @return boolean
|
477 |
+
*/
|
478 |
+
protected function updateSession( $sSessionId, $sUsername, $aUpdateData ) {
|
479 |
$aWhere = array(
|
480 |
+
'session_id' => $sSessionId,
|
481 |
'deleted_at' => 0,
|
482 |
'wp_username' => $sUsername
|
483 |
);
|
507 |
return $this->selectCustomFromTable( $sQuery );
|
508 |
}
|
509 |
|
510 |
+
/**
|
511 |
+
* Checks for and gets a user session.
|
512 |
+
*
|
513 |
+
* @param string $sUsername
|
514 |
+
* @return array|boolean
|
515 |
+
*/
|
516 |
+
public function getActiveSessionRecordsForUser( $sUsername ) {
|
517 |
+
|
518 |
+
$sQuery = "
|
519 |
+
SELECT *
|
520 |
+
FROM `%s`
|
521 |
+
WHERE
|
522 |
+
`wp_username` = '%s'
|
523 |
+
AND `pending` = '0'
|
524 |
+
AND `deleted_at` = '0'
|
525 |
+
ORDER BY `last_activity_at` ASC
|
526 |
+
";
|
527 |
+
$sQuery = sprintf(
|
528 |
+
$sQuery,
|
529 |
+
$this->getTableName(),
|
530 |
+
$sUsername
|
531 |
+
);
|
532 |
+
return $this->selectCustomFromTable( $sQuery );
|
533 |
+
}
|
534 |
+
|
535 |
/**
|
536 |
* Checks for and gets a user session.
|
537 |
*
|
559 |
return $this->selectCustomFromTable( $sQuery );
|
560 |
}
|
561 |
|
562 |
+
/**
|
563 |
+
* Checks for and gets a user session.
|
564 |
+
*
|
565 |
+
* @param string $sSessionId
|
566 |
+
* @return array|boolean
|
567 |
+
*/
|
568 |
+
protected function getSessionRecord( $sSessionId = null ) {
|
569 |
+
|
570 |
+
$sQuery = "
|
571 |
+
SELECT *
|
572 |
+
FROM `%s`
|
573 |
+
WHERE
|
574 |
+
`session_id` = '%s'
|
575 |
+
AND `deleted_at` = '0'
|
576 |
+
";
|
577 |
+
$sQuery = sprintf( $sQuery,
|
578 |
+
$this->getTableName(),
|
579 |
+
empty( $sSessionId ) ? $this->getSessionId() : $sSessionId
|
580 |
+
);
|
581 |
+
|
582 |
+
$mResult = $this->selectCustomFromTable( $sQuery );
|
583 |
+
if ( is_array( $mResult ) && count( $mResult ) == 1 ) {
|
584 |
+
return $mResult[0];
|
585 |
+
}
|
586 |
+
return false;
|
587 |
+
}
|
588 |
+
|
589 |
/**
|
590 |
* Checks for and gets a user session.
|
591 |
*
|
612 |
if ( is_array( $mResult ) && count( $mResult ) == 1 ) {
|
613 |
return $mResult[0];
|
614 |
}
|
615 |
+
return false;
|
|
|
|
|
|
|
|
|
|
|
616 |
}
|
617 |
|
618 |
/**
|
620 |
*/
|
621 |
protected function getSessionId() {
|
622 |
if ( empty( $this->sSessionId ) ) {
|
623 |
+
$oDp = $this->loadDataProcessor();
|
624 |
+
$this->sSessionId = $oDp->FetchCookie( $this->oFeatureOptions->getUserSessionCookieName() );
|
625 |
+
if ( empty( $this->sSessionId ) ) {
|
626 |
$this->sSessionId = md5( uniqid() );
|
627 |
$this->setSessionCookie();
|
628 |
}
|
630 |
return $this->sSessionId;
|
631 |
}
|
632 |
|
633 |
+
/**
|
634 |
+
* @return string
|
635 |
+
*/
|
636 |
+
public function getCreateTableSql() {
|
637 |
$sSqlTables = "CREATE TABLE IF NOT EXISTS `%s` (
|
638 |
`id` int(11) NOT NULL AUTO_INCREMENT,
|
639 |
`session_id` varchar(32) NOT NULL DEFAULT '',
|
649 |
`deleted_at` int(15) NOT NULL DEFAULT '0',
|
650 |
PRIMARY KEY (`id`)
|
651 |
) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
|
652 |
+
return sprintf( $sSqlTables, $this->getTableName() );
|
|
|
653 |
}
|
654 |
|
655 |
/**
|
687 |
|
688 |
if ( !class_exists('ICWP_WPSF_Processor_UserManagement') ):
|
689 |
class ICWP_WPSF_Processor_UserManagement extends ICWP_WPSF_Processor_UserManagement_V1 { }
|
690 |
+
endif;
|
src/icwp-processor-usermanagement_adminloginnotification.php
ADDED
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
+
* All rights reserved.
|
5 |
+
*
|
6 |
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
7 |
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
8 |
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
9 |
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
10 |
+
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
11 |
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
12 |
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
13 |
+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
14 |
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
15 |
+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
+
*/
|
17 |
+
|
18 |
+
require_once( dirname(__FILE__).'/icwp-processor-base.php' );
|
19 |
+
|
20 |
+
if ( !class_exists('ICWP_WPSF_Processor_UserManagement_AdminLoginNotification') ):
|
21 |
+
|
22 |
+
class ICWP_WPSF_Processor_UserManagement_AdminLoginNotification extends ICWP_WPSF_Processor_Base {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @param ICWP_WPSF_FeatureHandler_UserManagement $oFeatureOptions
|
26 |
+
*/
|
27 |
+
public function __construct( ICWP_WPSF_FeatureHandler_UserManagement $oFeatureOptions ) {
|
28 |
+
parent::__construct( $oFeatureOptions );
|
29 |
+
}
|
30 |
+
|
31 |
+
public function run() {
|
32 |
+
if ( is_email( $this->getOption( 'enable_admin_login_email_notification' ) ) ) {
|
33 |
+
add_action( 'wp_login', array( $this, 'sendLoginEmailNotification' ) );
|
34 |
+
}
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* @param $sUsername
|
39 |
+
* @return mixed
|
40 |
+
*/
|
41 |
+
public function sendLoginEmailNotification( $sUsername ) {
|
42 |
+
|
43 |
+
if ( empty( $sUsername ) ) {
|
44 |
+
return false;
|
45 |
+
}
|
46 |
+
|
47 |
+
$oUser = get_user_by( 'login', $sUsername );
|
48 |
+
if ( !( $oUser instanceof WP_User ) ) {
|
49 |
+
return false;
|
50 |
+
}
|
51 |
+
|
52 |
+
$fIsAdministrator = isset( $oUser->caps['administrator'] ) && $oUser->caps['administrator'];
|
53 |
+
|
54 |
+
if ( !$fIsAdministrator ) {
|
55 |
+
return false;
|
56 |
+
}
|
57 |
+
|
58 |
+
$oDp = $this->loadDataProcessor();
|
59 |
+
$oEmailer = $this->getFeatureOptions()->getEmailProcessor();
|
60 |
+
|
61 |
+
$aMessage = array(
|
62 |
+
_wpsf__( 'As requested, the WordPress Simple Firewall is notifying you of an administrator login to a WordPress site that you manage.' ),
|
63 |
+
_wpsf__( 'Details for this user are below:' ),
|
64 |
+
'- '.sprintf( _wpsf__( 'Site URL: %s' ), home_url() ),
|
65 |
+
'- '.sprintf( _wpsf__( 'Username: %s' ), $sUsername ),
|
66 |
+
'- '.sprintf( _wpsf__( 'IP Address: %s' ), $oDp->GetVisitorIpAddress( false ) ),
|
67 |
+
_wpsf__( 'Thanks.' )
|
68 |
+
);
|
69 |
+
|
70 |
+
$fResult = $oEmailer->sendEmailTo(
|
71 |
+
$this->getOption( 'enable_admin_login_email_notification' ),
|
72 |
+
sprintf( 'Email Notice: An Administrator Just Logged Into %s', home_url() ),
|
73 |
+
$aMessage
|
74 |
+
);
|
75 |
+
return $fResult;
|
76 |
+
}
|
77 |
+
}
|
78 |
+
|
79 |
+
endif;
|
src/icwp-processor-yaml.php
ADDED
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
5 |
+
* All rights reserved.
|
6 |
+
*
|
7 |
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
8 |
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
9 |
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
10 |
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
11 |
+
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
12 |
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
13 |
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
14 |
+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
15 |
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
16 |
+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
17 |
+
*
|
18 |
+
*/
|
19 |
+
|
20 |
+
if ( !class_exists('ICWP_WPSF_YamlProcessor_V1') ):
|
21 |
+
|
22 |
+
class ICWP_WPSF_YamlProcessor_V1 {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @param string $sYamlString
|
26 |
+
* @return array
|
27 |
+
*/
|
28 |
+
public function parseYamlString( $sYamlString ) {
|
29 |
+
if ( ! $this->loadYamlParser() ) {
|
30 |
+
return null;
|
31 |
+
}
|
32 |
+
return Spyc::YAMLLoadString( $sYamlString );
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
*/
|
37 |
+
protected function loadYamlParser() {
|
38 |
+
if ( !class_exists( 'Spyc' ) ) {
|
39 |
+
require_once( 'lib/yaml/Spyc.php' );
|
40 |
+
}
|
41 |
+
return class_exists( 'Spyc' );
|
42 |
+
}
|
43 |
+
}
|
44 |
+
endif;
|
45 |
+
|
46 |
+
if ( !class_exists('ICWP_WPSF_YamlProcessor') ):
|
47 |
+
|
48 |
+
class ICWP_WPSF_YamlProcessor extends ICWP_WPSF_YamlProcessor_V1 {
|
49 |
+
|
50 |
+
/**
|
51 |
+
* @var ICWP_WPSF_YamlProcessor
|
52 |
+
*/
|
53 |
+
protected static $oInstance = NULL;
|
54 |
+
|
55 |
+
/**
|
56 |
+
* @return ICWP_WPSF_YamlProcessor
|
57 |
+
*/
|
58 |
+
public static function GetInstance() {
|
59 |
+
if ( is_null( self::$oInstance ) ) {
|
60 |
+
self::$oInstance = new self();
|
61 |
+
}
|
62 |
+
return self::$oInstance;
|
63 |
+
}
|
64 |
+
}
|
65 |
+
endif;
|
src/icwp-pure-base.php
CHANGED
@@ -1,949 +1,376 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
|
4 |
-
define( 'ICWP_DS', DIRECTORY_SEPARATOR );
|
5 |
-
}
|
6 |
-
|
7 |
-
require_once( dirname(__FILE__).'/icwp-once.php' );
|
8 |
-
require_once( dirname(__FILE__).'/icwp-wpfunctions.php' );
|
9 |
-
require_once( dirname(__FILE__).'/icwp-wpfilesystem.php' );
|
10 |
-
|
11 |
-
if ( !class_exists('ICWP_Pure_Base_V5') ):
|
12 |
-
|
13 |
-
class ICWP_Pure_Base_V5 extends ICWP_WPSF_Once {
|
14 |
-
|
15 |
-
const ViewExt = '.php';
|
16 |
-
const ViewDir = 'views';
|
17 |
-
|
18 |
-
/**
|
19 |
-
* @var ICWP_Wordpress_Simple_Firewall_Plugin
|
20 |
-
*/
|
21 |
-
protected $oPluginVo;
|
22 |
-
|
23 |
-
/**
|
24 |
-
* Set to true if it should never be shown in the dashboard
|
25 |
-
* @var string
|
26 |
-
*/
|
27 |
-
protected $fHeadless = false;
|
28 |
-
|
29 |
-
/**
|
30 |
-
* Set to true if this contains components from another plugin to stand alone
|
31 |
-
* @var string
|
32 |
-
*/
|
33 |
-
protected $m_sAutoUpdateUrl = '';
|
34 |
-
|
35 |
-
/**
|
36 |
-
* @var string
|
37 |
-
*/
|
38 |
-
protected $sPluginRootFile;
|
39 |
-
/**
|
40 |
-
* @var string
|
41 |
-
*/
|
42 |
-
protected $sPluginFileName;
|
43 |
-
/**
|
44 |
-
* @var string
|
45 |
-
*/
|
46 |
-
protected $sPluginRootDir;
|
47 |
-
/**
|
48 |
-
* @var string
|
49 |
-
*/
|
50 |
-
protected $sPluginBaseFile;
|
51 |
-
/**
|
52 |
-
* @var string
|
53 |
-
*/
|
54 |
-
protected $sPluginUrl;
|
55 |
-
/**
|
56 |
-
* @var string
|
57 |
-
*/
|
58 |
-
protected static $sOptionPrefix = '';
|
59 |
-
|
60 |
-
protected $aPluginMenu;
|
61 |
-
|
62 |
-
protected $sPluginSlug;
|
63 |
-
|
64 |
-
protected $fShowMarketing;
|
65 |
-
|
66 |
-
/**
|
67 |
-
* @var ICWP_WpFunctions_WPSF;
|
68 |
-
*/
|
69 |
-
protected $m_oWpFunctions;
|
70 |
-
|
71 |
-
/**
|
72 |
-
* @var ICWP_WpFilesystem_WPSF;
|
73 |
-
*/
|
74 |
-
protected $m_oWpFs;
|
75 |
-
|
76 |
-
public function __construct( ICWP_Wordpress_Simple_Firewall_Plugin $oPluginVo ) {
|
77 |
-
|
78 |
-
// All core values of the plugin are derived from the values stored in this value object.
|
79 |
-
$this->oPluginVo = $oPluginVo;
|
80 |
-
$this->sPluginRootFile = $this->oPluginVo->getRootFile();
|
81 |
-
$this->sPluginSlug = $this->oPluginVo->getPluginSlug();
|
82 |
-
self::$sOptionPrefix = $this->oPluginVo->getOptionStoragePrefix();
|
83 |
-
$this->setPaths();
|
84 |
-
|
85 |
-
add_action( 'plugins_loaded', array( $this, 'onWpPluginsLoaded' ) );
|
86 |
-
add_action( 'init', array( $this, 'onWpInit' ), 0 );
|
87 |
-
if ( $this->isValidAdminArea() ) {
|
88 |
-
add_action( 'admin_init', array( $this, 'onWpAdminInit' ) );
|
89 |
-
add_action( 'admin_notices', array( $this, 'onWpAdminNotices' ) );
|
90 |
-
add_action( 'network_admin_notices', array( $this, 'onWpAdminNotices' ) );
|
91 |
-
add_action( 'admin_menu', array( $this, 'onWpAdminMenu' ) );
|
92 |
-
add_action( 'network_admin_menu', array( $this, 'onWpAdminMenu' ) );
|
93 |
-
add_action( 'plugin_action_links', array( $this, 'onWpPluginActionLinks' ), 10, 4 );
|
94 |
-
// add_action( 'deactivate_plugin', array( $this, 'onWpHookDeactivatePlugin' ), 1, 1 );
|
95 |
-
add_action( 'wp_before_admin_bar_render', array( $this, 'onWpAdminBar' ), 1, 9999 );
|
96 |
-
}
|
97 |
-
add_action( 'in_plugin_update_message-'.$this->getPluginBaseFile(), array( $this, 'onWpPluginUpdateMessage' ) );
|
98 |
-
add_action( 'shutdown', array( $this, 'onWpShutdown' ) );
|
99 |
-
add_action( $this->doPluginPrefix( 'plugin_shutdown' ), array( $this, 'doPluginShutdown' ) );
|
100 |
|
101 |
-
|
102 |
-
}
|
103 |
|
104 |
-
|
105 |
-
* Returns this unique plugin prefix
|
106 |
-
*
|
107 |
-
* @param string $sGlue
|
108 |
-
* @return string
|
109 |
-
*/
|
110 |
-
public function getPluginPrefix( $sGlue = '-' ) {
|
111 |
-
return $this->oPluginVo->getFullPluginPrefix( $sGlue );
|
112 |
-
}
|
113 |
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
* @param string $sGlue
|
119 |
-
* @return string
|
120 |
-
*/
|
121 |
-
public function doPluginPrefix( $sSuffix = '', $sGlue = '-' ) {
|
122 |
-
$sPrefix = $this->oPluginVo->getFullPluginPrefix( $sGlue );
|
123 |
-
|
124 |
-
if ( $sSuffix == $sPrefix || strpos( $sSuffix, $sPrefix.$sGlue ) === 0 ) { //it already has the prefix
|
125 |
-
return $sSuffix;
|
126 |
-
}
|
127 |
|
128 |
-
|
129 |
-
}
|
130 |
-
|
131 |
-
protected function isValidAdminArea() {
|
132 |
-
$this->loadWpFunctions();
|
133 |
-
if ( !$this->m_oWpFunctions->isMultisite() && is_admin() ) {
|
134 |
-
return true;
|
135 |
-
}
|
136 |
-
else if ( $this->m_oWpFunctions->isMultisite() && $this->oPluginVo->getIsWpmsNetworkAdminOnly() && is_network_admin() ) {
|
137 |
-
return true;
|
138 |
-
}
|
139 |
-
return false;
|
140 |
-
}
|
141 |
-
|
142 |
-
/**
|
143 |
-
* Registers the plugins activation, deactivate and uninstall hooks.
|
144 |
-
*/
|
145 |
-
protected function registerActivationHooks() {
|
146 |
-
register_activation_hook( $this->sPluginRootFile, array( $this, 'onWpActivatePlugin' ) );
|
147 |
-
register_deactivation_hook( $this->sPluginRootFile, array( $this, 'onWpDeactivatePlugin' ) );
|
148 |
-
// register_uninstall_hook( $this->sPluginRootFile, array( $this, 'onWpUninstallPlugin' ) );
|
149 |
-
}
|
150 |
-
|
151 |
-
/**
|
152 |
-
* @since v3.0.0
|
153 |
-
*/
|
154 |
-
protected function setPaths() {
|
155 |
-
if ( empty( $this->sPluginRootFile ) ) {
|
156 |
-
$this->sPluginRootFile = __FILE__;
|
157 |
-
}
|
158 |
-
$this->sPluginFileName = basename( $this->sPluginRootFile );
|
159 |
-
$this->getPluginBaseFile();
|
160 |
-
$this->sPluginRootDir = dirname( $this->sPluginRootFile ).ICWP_DS;
|
161 |
-
$this->sPluginUrl = plugins_url( '/', $this->sPluginRootFile ) ; //this seems to use SSL more reliably than WP_PLUGIN_URL
|
162 |
-
}
|
163 |
-
|
164 |
-
/**
|
165 |
-
* This is the path to the main plugin file relative to the WordPress plugins directory.
|
166 |
-
*
|
167 |
-
* @return string
|
168 |
-
*/
|
169 |
-
public function getPluginBaseFile() {
|
170 |
-
if ( !isset( $this->sPluginBaseFile ) ) {
|
171 |
-
$this->sPluginBaseFile = plugin_basename( $this->sPluginRootFile );
|
172 |
-
}
|
173 |
-
return $this->sPluginBaseFile;
|
174 |
-
}
|
175 |
|
176 |
-
|
177 |
-
* @param boolean $fHasPermission
|
178 |
-
* @return boolean
|
179 |
-
*/
|
180 |
-
public function hasPermissionToView( $fHasPermission = true ) {
|
181 |
-
return $this->hasPermissionToSubmit( $fHasPermission );
|
182 |
-
}
|
183 |
|
184 |
-
|
185 |
-
|
186 |
-
* @return boolean
|
187 |
-
*/
|
188 |
-
public function hasPermissionToSubmit( $fHasPermission = true ) {
|
189 |
-
// first a basic admin check
|
190 |
-
return $fHasPermission && is_super_admin() && current_user_can( $this->oPluginVo->getBasePermissions() );
|
191 |
-
}
|
192 |
-
|
193 |
-
public function doPluginUpdateCheck() {
|
194 |
-
$oWp = $this->loadWpFunctions();
|
195 |
-
$oWp->getIsPluginUpdateAvailable( $this->getPluginBaseFile() );
|
196 |
-
}
|
197 |
-
|
198 |
-
protected function display( $insView, $inaData = array() ) {
|
199 |
-
$sFile = $this->sPluginRootDir.self::ViewDir.ICWP_DS.$insView.self::ViewExt;
|
200 |
-
|
201 |
-
if ( !is_file( $sFile ) ) {
|
202 |
-
echo "View not found: ".$sFile;
|
203 |
-
return false;
|
204 |
-
}
|
205 |
-
|
206 |
-
if ( count( $inaData ) > 0 ) {
|
207 |
-
extract( $inaData, EXTR_PREFIX_ALL, $this->oPluginVo->getParentSlug() ); //slug being 'icwp'
|
208 |
-
}
|
209 |
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
214 |
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
|
219 |
-
|
220 |
-
|
221 |
-
|
|
|
222 |
|
223 |
-
|
224 |
-
|
225 |
-
*/
|
226 |
-
public function onWpPluginsLoaded() {
|
227 |
-
if ( is_admin() ) {
|
228 |
-
//Handle plugin upgrades
|
229 |
-
$this->doPluginUpdateCheck();
|
230 |
-
$this->load_textdomain();
|
231 |
}
|
232 |
-
$this->handlePluginFormSubmit();
|
233 |
-
add_filter( 'all_plugins', array( $this, 'filter_hidePluginFromTableList' ) );
|
234 |
-
add_filter( 'site_transient_update_plugins', array( $this, 'filter_hidePluginUpdatesFromUI' ) );
|
235 |
-
}
|
236 |
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
*/
|
245 |
-
public function filter_hidePluginFromTableList( $aPlugins ) {
|
246 |
-
|
247 |
-
if ( !$this->fHeadless ) {
|
248 |
-
return $aPlugins;
|
249 |
}
|
250 |
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
273 |
}
|
274 |
|
275 |
-
|
276 |
-
|
|
|
|
|
|
|
|
|
277 |
}
|
278 |
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
*/
|
285 |
-
public function load_textdomain() {
|
286 |
-
//TODO: Can replace with $this->sPluginRootDir ?
|
287 |
-
load_plugin_textdomain( $this->oPluginVo->getTextDomain(), false, dirname( $this->getPluginBaseFile() ) . '/languages/' );
|
288 |
-
}
|
289 |
-
|
290 |
-
public function onWpInit() { }
|
291 |
-
|
292 |
-
public function onWpAdminInit() {
|
293 |
-
//Do Plugin-Specific Admin Work
|
294 |
-
if ( $this->getIsPage_PluginAdmin() ) {
|
295 |
-
add_action( 'admin_enqueue_scripts', array( $this, 'enqueueBootstrapLegacyAdminCss' ), 99 );
|
296 |
-
add_action( 'admin_enqueue_scripts', array( $this, 'enqueuePluginAdminCss' ), 99 );
|
297 |
-
}
|
298 |
-
}
|
299 |
-
|
300 |
-
public function onWpAdminMenu() {
|
301 |
-
if ( !$this->isValidAdminArea() ) {
|
302 |
-
return true;
|
303 |
-
}
|
304 |
-
$this->createMenu();
|
305 |
-
}
|
306 |
-
|
307 |
-
protected function createMenu() {
|
308 |
-
|
309 |
-
if ( $this->fHeadless ) {
|
310 |
-
return true;
|
311 |
-
}
|
312 |
-
|
313 |
-
$sFullParentMenuId = $this->getPluginPrefix();
|
314 |
-
add_menu_page( $this->oPluginVo->getHumanName(), $this->oPluginVo->getAdminMenuTitle(), $this->oPluginVo->getBasePermissions(), $sFullParentMenuId, array( $this, 'onDisplayAll' ), $this->getPluginLogoUrl16() );
|
315 |
-
//Create and Add the submenu items
|
316 |
-
// $this->createPluginSubMenuItems();
|
317 |
-
|
318 |
-
// allow for any plugin menu items that don't come from filters
|
319 |
-
add_filter( $this->doPluginPrefix( 'filter_plugin_submenu_items' ), array( $this, 'filter_addExtraAdminMenuItems' ) );
|
320 |
-
|
321 |
-
$aPluginMenuItems = apply_filters( $this->doPluginPrefix( 'filter_plugin_submenu_items' ), array() );
|
322 |
-
if ( !empty( $aPluginMenuItems ) ) {
|
323 |
-
foreach ( $aPluginMenuItems as $sMenuTitle => $aMenu ) {
|
324 |
-
list( $sMenuItemText, $sMenuItemId, $aMenuCallBack ) = $aMenu;
|
325 |
-
add_submenu_page(
|
326 |
-
$sFullParentMenuId,
|
327 |
-
$sMenuTitle,
|
328 |
-
$sMenuItemText,
|
329 |
-
$this->oPluginVo->getBasePermissions(),
|
330 |
-
$this->doPluginPrefix( $sMenuItemId ),
|
331 |
-
$aMenuCallBack
|
332 |
-
);
|
333 |
}
|
334 |
}
|
335 |
-
// if ( !empty($this->aPluginMenu) ) {
|
336 |
-
// foreach ( $this->aPluginMenu as $sMenuTitle => $aMenu ) {
|
337 |
-
// list( $sMenuItemText, $sMenuItemId, $sMenuCallBack ) = $aMenu;
|
338 |
-
// add_submenu_page( $sFullParentMenuId, $sMenuTitle, $sMenuItemText, $this->oPluginVo->getBasePermissions(), $sMenuItemId, array( $this, $sMenuCallBack ) );
|
339 |
-
// }
|
340 |
-
// }
|
341 |
-
$this->fixSubmenu();
|
342 |
-
}
|
343 |
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
return $aItems;
|
350 |
-
}
|
351 |
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
// $submenu[$sFullParentMenuId][0][0] = 'Dashboard';
|
363 |
}
|
364 |
-
}
|
365 |
-
|
366 |
-
/**
|
367 |
-
* Displaying all views now goes through this central function and we work out
|
368 |
-
* what to display based on the name of current hook/filter being processed.
|
369 |
-
*/
|
370 |
-
public function onDisplayAll() {
|
371 |
-
$this->onDisplayMainMenu();
|
372 |
-
}
|
373 |
-
|
374 |
-
/**
|
375 |
-
* The callback function for the main admin menu index page
|
376 |
-
*/
|
377 |
-
public function onDisplayMainMenu() {
|
378 |
-
$aData = array();
|
379 |
-
$this->display( $this->doPluginPrefix( 'index', '_' ), $aData );
|
380 |
-
}
|
381 |
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
'nonce_field' => $this->getPluginPrefix(),
|
389 |
-
'form_action' => 'admin.php?page='.$this->getCurrentWpAdminPage()
|
390 |
-
);
|
391 |
-
}
|
392 |
-
|
393 |
-
/**
|
394 |
-
*/
|
395 |
-
protected function getCurrentWpAdminPage() {
|
396 |
-
$sScript = isset( $_SERVER['SCRIPT_NAME'] )? $_SERVER['SCRIPT_NAME'] : $_SERVER['PHP_SELF'];
|
397 |
-
if ( is_admin() && !empty( $sScript ) && basename( $sScript ) == 'admin.php' ) {
|
398 |
-
$sCurrentPage = $this->fetchGet('page');
|
399 |
}
|
400 |
-
return empty($sCurrentPage)? '' : $sCurrentPage;
|
401 |
-
}
|
402 |
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
*/
|
411 |
-
protected function getIsPage_PluginAdmin() {
|
412 |
-
return ( strpos( $this->getCurrentWpAdminPage(), $this->getPluginPrefix() ) === 0 );
|
413 |
-
}
|
414 |
-
|
415 |
-
/**
|
416 |
-
* @param string $sFeaturePage - leave empty to get the main dashboard
|
417 |
-
* @return mixed
|
418 |
-
*/
|
419 |
-
protected function getUrl_PluginDashboard( $sFeaturePage = '' ) {
|
420 |
-
return network_admin_url( sprintf( 'admin.php?page=%s', $this->getSubmenuId( $sFeaturePage ) ) );
|
421 |
-
}
|
422 |
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
|
428 |
-
|
429 |
-
|
430 |
-
}
|
431 |
-
$this->fShowMarketing = true;
|
432 |
-
if ( class_exists( 'Worpit_Plugin' ) ) {
|
433 |
-
if ( method_exists( 'Worpit_Plugin', 'IsLinked' ) ) {
|
434 |
-
$this->fShowMarketing = !Worpit_Plugin::IsLinked();
|
435 |
}
|
436 |
-
|
|
|
|
|
|
|
|
|
|
|
437 |
&& get_option( Worpit_Plugin::$VariablePrefix.'assigned' ) == 'Y'
|
438 |
&& get_option( Worpit_Plugin::$VariablePrefix.'assigned_to' ) != '' ) {
|
439 |
-
|
440 |
-
|
441 |
-
}
|
442 |
-
}
|
443 |
-
return $this->fShowMarketing ;
|
444 |
-
}
|
445 |
-
|
446 |
-
/**
|
447 |
-
* On the plugins listing page, hides the edit and deactivate links
|
448 |
-
* for this plugin based on permissions
|
449 |
-
*
|
450 |
-
* @see ICWP_Pure_Base_V1::onWpPluginActionLinks()
|
451 |
-
*/
|
452 |
-
public function onWpPluginActionLinks( $aActionLinks, $sPluginFile ) {
|
453 |
-
|
454 |
-
if ( $sPluginFile == $this->getPluginBaseFile() ) {
|
455 |
-
if ( !$this->hasPermissionToSubmit() ) {
|
456 |
-
if ( array_key_exists( 'edit', $aActionLinks ) ) {
|
457 |
-
unset( $aActionLinks['edit'] );
|
458 |
-
}
|
459 |
-
if ( array_key_exists( 'deactivate', $aActionLinks ) ) {
|
460 |
-
unset( $aActionLinks['deactivate'] );
|
461 |
}
|
462 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
463 |
|
464 |
-
|
465 |
-
|
|
|
|
|
466 |
}
|
467 |
-
return $aActionLinks;
|
468 |
-
}
|
469 |
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
// Do we have admin priviledges?
|
475 |
-
if ( !$this->isValidAdminArea() || !current_user_can( $this->oPluginVo->getBasePermissions() ) ) {
|
476 |
return true;
|
477 |
}
|
478 |
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
}
|
489 |
-
if ( $this->hasPermissionToSubmit() ) {
|
490 |
-
$this->doAdminNoticePluginUpgradeAvailable();
|
491 |
-
}
|
492 |
}
|
493 |
-
}
|
494 |
-
|
495 |
-
protected function doAdminNoticePluginUpgradeAvailable() {
|
496 |
|
497 |
-
|
498 |
-
|
499 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
500 |
}
|
501 |
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
$
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
protected function doAdminNoticeOptionsUpdated(){
|
512 |
-
$sHtml = $this->getAdminNoticeHtml_OptionsUpdated();
|
513 |
-
if ( !empty($sHtml) ) {
|
514 |
-
$this->getAdminNoticeHtml( $sHtml, 'updated', true );
|
515 |
}
|
516 |
-
}
|
517 |
-
|
518 |
-
protected function doAdminNoticePostUpgrade() {
|
519 |
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
$sHtml = $this->getAdminNoticeHtml_VersionUpgrade();
|
525 |
-
if ( !empty($sHtml) ) {
|
526 |
-
$this->getAdminNoticeHtml( $sHtml, 'updated', true );
|
527 |
}
|
528 |
-
}
|
529 |
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
}
|
539 |
-
|
540 |
-
$sHtml = $this->getAdminNoticeHtml_Translations();
|
541 |
-
if ( !empty($sHtml) ) {
|
542 |
-
$this->getAdminNoticeHtml( $sHtml, 'updated', true );
|
543 |
}
|
544 |
-
}
|
545 |
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
$sCurrentMetaValue = $this->getUserMeta( 'plugin_mailing_list_signup' );
|
552 |
-
if ( $sCurrentMetaValue == 'Y' ) {
|
553 |
-
return;
|
554 |
}
|
555 |
|
556 |
-
|
557 |
-
|
558 |
-
|
|
|
559 |
}
|
560 |
-
}
|
561 |
|
562 |
-
|
563 |
-
* Override this to change the message for the particular plugin upgrade.
|
564 |
-
*/
|
565 |
-
protected function getAdminNoticeHtml_PluginUpgradeAvailable() {
|
566 |
-
$sUpgradeLink = $this->m_oWpFunctions->getPluginUpgradeLink( $this->getPluginBaseFile() );
|
567 |
-
$sNotice = '<p>There is an update available for the %s plugin. <a href="%s">Click to update immediately</a>.</p>';
|
568 |
-
$sNotice = sprintf( $sNotice, $this->oPluginVo->getHumanName(), $sUpgradeLink );
|
569 |
-
return $sNotice;
|
570 |
-
}
|
571 |
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
/**
|
578 |
-
* Provides the basic HTML template for printing a WordPress Admin Notices
|
579 |
-
*
|
580 |
-
* @param $insNotice - The message to be displayed.
|
581 |
-
* @param $insMessageClass - either error or updated
|
582 |
-
* @param $infPrint - if true, will echo. false will return the string
|
583 |
-
* @return boolean|string
|
584 |
-
*/
|
585 |
-
protected function getAdminNoticeHtml( $insNotice = '', $insMessageClass = 'updated', $infPrint = false ) {
|
586 |
-
|
587 |
-
$sFullNotice = '
|
588 |
-
<div id="message" class="'.$insMessageClass.'">
|
589 |
-
<style>#message form { margin: 0px; padding-bottom: 8px; }</style>
|
590 |
-
'.$insNotice.'
|
591 |
-
</div>
|
592 |
-
';
|
593 |
-
|
594 |
-
if ( $infPrint ) {
|
595 |
-
echo $sFullNotice;
|
596 |
-
return true;
|
597 |
-
} else {
|
598 |
-
return $sFullNotice;
|
599 |
}
|
600 |
-
}
|
601 |
-
|
602 |
-
/**
|
603 |
-
*
|
604 |
-
*/
|
605 |
-
protected function getShowAdminNotices() {
|
606 |
-
return true;
|
607 |
-
}
|
608 |
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
*/
|
615 |
-
protected function updateTranslationNoticeShownUserMeta( $nId = '', $sValue = 'Y' ) {
|
616 |
-
$this->updateUserMeta( 'plugin_translation_notice', $sValue, $nId );
|
617 |
-
}
|
618 |
-
|
619 |
-
/**
|
620 |
-
* Updates the current (or supplied user ID) user meta data with the version of the plugin
|
621 |
-
*
|
622 |
-
* @param $nId
|
623 |
-
* @param $sValue
|
624 |
-
*/
|
625 |
-
protected function updateMailingListSignupShownUserMeta( $nId = '', $sValue = 'Y' ) {
|
626 |
-
$this->updateUserMeta( 'plugin_mailing_list_signup', $sValue, $nId );
|
627 |
-
}
|
628 |
-
|
629 |
-
/**
|
630 |
-
* Updates the current (or supplied user ID) user meta data with the version of the plugin
|
631 |
-
*
|
632 |
-
* @param integer $nId
|
633 |
-
*/
|
634 |
-
protected function updateVersionUserMeta( $nId = null ) {
|
635 |
-
$this->updateUserMeta( 'current_version', $this->oPluginVo->getVersion(), $nId );
|
636 |
-
}
|
637 |
-
|
638 |
-
/**
|
639 |
-
* Updates the current (or supplied user ID) user meta data with the version of the plugin
|
640 |
-
*
|
641 |
-
* @param string $insKey
|
642 |
-
* @param mixed $mValue
|
643 |
-
* @param integer $innId -user ID
|
644 |
-
* @return boolean
|
645 |
-
*/
|
646 |
-
protected function updateUserMeta( $insKey, $mValue, $innId = null ) {
|
647 |
-
if ( empty( $innId ) ) {
|
648 |
-
$oCurrentUser = $this->getCurrentUser();
|
649 |
-
if ( !$oCurrentUser ) {
|
650 |
return;
|
651 |
}
|
652 |
-
$
|
653 |
-
|
654 |
-
else {
|
655 |
-
$nUserId = $innId;
|
656 |
-
}
|
657 |
-
return update_user_meta( $nUserId, self::$sOptionPrefix.$insKey, $mValue );
|
658 |
-
}
|
659 |
-
|
660 |
-
protected function getUserMeta( $sKey ) {
|
661 |
-
|
662 |
-
$oCurrentUser = $this->getCurrentUser();
|
663 |
-
if ( !$oCurrentUser ) {
|
664 |
-
return;
|
665 |
-
}
|
666 |
-
$nUserId = $oCurrentUser->ID;
|
667 |
-
|
668 |
-
$sCurrentMetaValue = get_user_meta( $nUserId, $this->doPluginPrefix( $sKey, '_' ), true );
|
669 |
-
// A guard whereby if we can't ever get a value for this meta, it means we can never set it.
|
670 |
-
if ( empty( $sCurrentMetaValue ) ) {
|
671 |
-
//the value has never been set, or it's been installed for the first time.
|
672 |
-
$this->updateUserMeta( $sKey, 'temp', $nUserId );
|
673 |
-
return ''; //meaning we don't show the update notice upon new installations and for those people who can't set the version in their meta.
|
674 |
-
}
|
675 |
-
return $sCurrentMetaValue;
|
676 |
-
}
|
677 |
-
|
678 |
-
/**
|
679 |
-
* @return mixed
|
680 |
-
*/
|
681 |
-
protected function getCurrentUser() {
|
682 |
-
if( !is_user_logged_in() ) {
|
683 |
-
return false;
|
684 |
-
}
|
685 |
-
global $current_user;
|
686 |
-
get_currentuserinfo();
|
687 |
-
return $current_user;
|
688 |
-
}
|
689 |
-
|
690 |
-
protected function handlePluginFormSubmit() {
|
691 |
-
if ( !$this->isIcwpPluginFormSubmit() ) {
|
692 |
-
return false;
|
693 |
-
}
|
694 |
-
// check_admin_referer( $this->getPluginPrefix() );
|
695 |
-
|
696 |
-
// do all the plugin feature/options saving
|
697 |
-
do_action( $this->doPluginPrefix( 'form_submit' ) );
|
698 |
-
|
699 |
-
if ( $this->getIsPage_PluginAdmin() ) {
|
700 |
-
wp_safe_redirect( $this->getUrl_PluginDashboard( $this->getCurrentWpAdminPage() ) );
|
701 |
-
return true;
|
702 |
-
}
|
703 |
-
}
|
704 |
-
|
705 |
-
/**
|
706 |
-
* @return bool
|
707 |
-
*/
|
708 |
-
protected function isIcwpPluginFormSubmit() {
|
709 |
-
if ( empty($_POST) && empty($_GET) ) {
|
710 |
-
return false;
|
711 |
-
}
|
712 |
-
|
713 |
-
$aFormSubmitOptions = array(
|
714 |
-
'icwp_plugin_form_submit',
|
715 |
-
'icwp_link_action',
|
716 |
-
'icwp_wpsf_admin_access_key_request'
|
717 |
-
);
|
718 |
-
foreach( $aFormSubmitOptions as $sOption ) {
|
719 |
-
if ( !is_null( $this->fetchRequest( $sOption, false ) ) ) {
|
720 |
-
return true;
|
721 |
}
|
722 |
}
|
723 |
-
return false;
|
724 |
-
}
|
725 |
-
|
726 |
-
public function enqueueBootstrapAdminCss() {
|
727 |
-
$sUnique = $this->doPluginPrefix( 'bootstrap_wpadmin_css' );
|
728 |
-
wp_register_style( $sUnique, $this->getCssUrl( 'bootstrap-wpadmin.css' ), false, $this->oPluginVo->getVersion() );
|
729 |
-
wp_enqueue_style( $sUnique );
|
730 |
-
}
|
731 |
-
|
732 |
-
public function enqueueBootstrapLegacyAdminCss() {
|
733 |
-
$sUnique = $this->doPluginPrefix( 'bootstrap_wpadmin_legacy_css' );
|
734 |
-
wp_register_style( $sUnique, $this->getCssUrl( 'bootstrap-wpadmin-legacy.css' ), false, $this->oPluginVo->getVersion() );
|
735 |
-
wp_enqueue_style( $sUnique );
|
736 |
-
|
737 |
-
$sUnique = $this->doPluginPrefix( 'bootstrap_wpadmin_css_fixes' );
|
738 |
-
wp_register_style( $sUnique, $this->getCssUrl('bootstrap-wpadmin-fixes.css'), array( $this->doPluginPrefix( 'bootstrap_wpadmin_legacy_css' ) ), $this->oPluginVo->getVersion() );
|
739 |
-
wp_enqueue_style( $sUnique );
|
740 |
-
}
|
741 |
-
|
742 |
-
public function enqueuePluginAdminCss() {
|
743 |
-
$sUnique = $this->doPluginPrefix( 'plugin_css', '_' );
|
744 |
-
wp_register_style( $sUnique, $this->getCssUrl('plugin.css'), array( $this->doPluginPrefix( 'bootstrap_wpadmin_css_fixes' ) ), $this->oPluginVo->getVersion() );
|
745 |
-
wp_enqueue_style( $sUnique );
|
746 |
-
}
|
747 |
-
protected function redirect( $insUrl, $innTimeout = 1 ) {
|
748 |
-
echo '
|
749 |
-
<script type="text/javascript">
|
750 |
-
function redirect() {
|
751 |
-
window.location = "'.$insUrl.'";
|
752 |
-
}
|
753 |
-
var oTimer = setTimeout( "redirect()", "'.($innTimeout * 1000).'" );
|
754 |
-
</script>';
|
755 |
-
}
|
756 |
-
|
757 |
-
/**
|
758 |
-
* Displays a message in the plugins listing when a plugin has an update available.
|
759 |
-
*/
|
760 |
-
public function onWpPluginUpdateMessage() {
|
761 |
-
echo '<div style="color: #dd3333;">'
|
762 |
-
.$this->getPluginsListUpdateMessage()
|
763 |
-
. '</div>';
|
764 |
-
}
|
765 |
-
|
766 |
-
protected function getPluginsListUpdateMessage() {
|
767 |
-
return '';
|
768 |
-
}
|
769 |
-
|
770 |
-
/**
|
771 |
-
* Hooked to 'deactivate_plugin' and can be used to interrupt the deactivation of this plugin.
|
772 |
-
* @param string $insPlugin
|
773 |
-
*/
|
774 |
-
public function onWpHookDeactivatePlugin( $insPlugin ) {
|
775 |
-
if ( strpos( $insPlugin, $this->sPluginFileName ) !== false ) {
|
776 |
-
$this->doPreventDeactivation( $insPlugin );
|
777 |
-
}
|
778 |
-
}
|
779 |
-
|
780 |
-
/**
|
781 |
-
* @param string $insPlugin - the path to the plugin file
|
782 |
-
*/
|
783 |
-
protected function doPreventDeactivation( $insPlugin ) {
|
784 |
-
if ( !$this->hasPermissionToSubmit() ) {
|
785 |
-
wp_die( 'Sorry, you do not have permission to disable this plugin. You need to authenticate first.' );
|
786 |
-
}
|
787 |
-
}
|
788 |
|
789 |
-
|
790 |
-
* Use this to wrap up the function when the PHP process is coming to an end. Call from onWpShudown()
|
791 |
-
*/
|
792 |
-
public function doPluginShutdown() { }
|
793 |
-
|
794 |
-
/**
|
795 |
-
* Hooked to 'shutdown'
|
796 |
-
*/
|
797 |
-
public function onWpShutdown() {
|
798 |
-
do_action( $this->doPluginPrefix( 'plugin_shutdown' ) );
|
799 |
-
}
|
800 |
-
|
801 |
-
public function onWpActivatePlugin() { }
|
802 |
-
public function onWpDeactivatePlugin() { }
|
803 |
-
public function onWpUninstallPlugin() { }
|
804 |
-
|
805 |
-
/**
|
806 |
-
* @return ICWP_WpFunctions_WPSF
|
807 |
-
*/
|
808 |
-
protected function loadWpFunctions() {
|
809 |
-
if ( !isset( $this->m_oWpFunctions ) ) {
|
810 |
-
$this->m_oWpFunctions = ICWP_WpFunctions_WPSF::GetInstance();
|
811 |
-
}
|
812 |
-
return $this->m_oWpFunctions;
|
813 |
-
}
|
814 |
|
815 |
-
|
816 |
-
|
817 |
-
*/
|
818 |
-
protected function loadWpFilesystem() {
|
819 |
-
return ICWP_WpFilesystem_WPSF::GetInstance();;
|
820 |
-
}
|
821 |
-
|
822 |
-
protected function flushCaches() {
|
823 |
-
if (function_exists('w3tc_pgcache_flush')) {
|
824 |
-
w3tc_pgcache_flush();
|
825 |
-
}
|
826 |
-
}
|
827 |
|
828 |
-
|
829 |
-
|
830 |
-
|
831 |
-
protected function getCssUrl( $insCss ) {
|
832 |
-
return $this->sPluginUrl.'resources/css/'.$insCss;
|
833 |
-
}
|
834 |
-
protected function getJsUrl( $insJs ) {
|
835 |
-
return $this->sPluginUrl.'resources/js/'.$insJs;
|
836 |
-
}
|
837 |
-
|
838 |
-
/**
|
839 |
-
* @param string $insKey
|
840 |
-
* @param boolean $infIncludeCookie
|
841 |
-
* @return mixed|null
|
842 |
-
*/
|
843 |
-
protected function fetchRequest( $insKey, $infIncludeCookie = true ) {
|
844 |
-
$mFetchVal = $this->fetchPost( $insKey );
|
845 |
-
if ( is_null( $mFetchVal ) ) {
|
846 |
-
$mFetchVal = $this->fetchGet( $insKey );
|
847 |
-
if ( is_null( $mFetchVal && $infIncludeCookie ) ) {
|
848 |
-
$mFetchVal = $this->fetchCookie( $insKey );
|
849 |
}
|
850 |
-
|
851 |
-
return $mFetchVal;
|
852 |
-
}
|
853 |
-
/**
|
854 |
-
* @param string $insKey
|
855 |
-
* @return mixed|null
|
856 |
-
*/
|
857 |
-
protected function fetchGet( $insKey ) {
|
858 |
-
if ( function_exists( 'filter_input' ) && defined( 'INPUT_GET' ) ) {
|
859 |
-
return filter_input( INPUT_GET, $insKey );
|
860 |
-
}
|
861 |
-
return $this->arrayFetch( $_GET, $insKey );
|
862 |
-
}
|
863 |
-
/**
|
864 |
-
* @param string $insKey The $_POST key
|
865 |
-
* @return mixed|null
|
866 |
-
*/
|
867 |
-
protected function fetchPost( $insKey ) {
|
868 |
-
if ( function_exists( 'filter_input' ) && defined( 'INPUT_POST' ) ) {
|
869 |
-
return filter_input( INPUT_POST, $insKey );
|
870 |
-
}
|
871 |
-
return $this->arrayFetch( $_POST, $insKey );
|
872 |
-
}
|
873 |
-
/**
|
874 |
-
* @param string $insKey The $_POST key
|
875 |
-
* @return mixed|null
|
876 |
-
*/
|
877 |
-
protected function fetchCookie( $insKey ) {
|
878 |
-
if ( function_exists( 'filter_input' ) && defined( 'INPUT_COOKIE' ) ) {
|
879 |
-
return filter_input( INPUT_COOKIE, $insKey );
|
880 |
-
}
|
881 |
-
return $this->arrayFetch( $_COOKIE, $insKey );
|
882 |
-
}
|
883 |
-
|
884 |
-
/**
|
885 |
-
* @param array $inaArray
|
886 |
-
* @param string $insKey The array key
|
887 |
-
* @return mixed|null
|
888 |
-
*/
|
889 |
-
protected function arrayFetch( &$inaArray, $insKey ) {
|
890 |
-
if ( empty( $inaArray ) ) {
|
891 |
-
return null;
|
892 |
-
}
|
893 |
-
if ( !isset( $inaArray[$insKey] ) ) {
|
894 |
-
return null;
|
895 |
-
}
|
896 |
-
return $inaArray[$insKey];
|
897 |
-
}
|
898 |
-
|
899 |
-
/**
|
900 |
-
* Performs a wp_die() but lets us do something first.
|
901 |
-
*/
|
902 |
-
protected function doWpDie( $insText = '' ) {
|
903 |
-
wp_die( $insText );
|
904 |
-
exit();
|
905 |
-
}
|
906 |
-
|
907 |
-
public function onWpAdminBar() {
|
908 |
-
$aNodes = $this->getAdminBarNodes();
|
909 |
-
foreach( $aNodes as $aNode ) {
|
910 |
-
$this->addAdminBarNode( $aNode );
|
911 |
-
}
|
912 |
-
}
|
913 |
-
|
914 |
-
protected function getAdminBarNodes() { }
|
915 |
|
916 |
-
|
917 |
-
|
918 |
-
|
919 |
-
|
920 |
-
|
921 |
-
unset( $aNode['children'] );
|
922 |
-
}
|
923 |
-
$wp_admin_bar->add_node( $aNode );
|
924 |
-
|
925 |
-
if ( !empty($aChildren) ) {
|
926 |
-
foreach( $aChildren as $aChild ) {
|
927 |
-
$aChild['parent'] = $aNode['id'];
|
928 |
-
$this->addAdminBarNode( $aChild );
|
929 |
}
|
930 |
}
|
931 |
}
|
932 |
|
933 |
-
protected function getPluginLogoUrl16() {
|
934 |
-
return $this->getImageUrl( 'pluginlogo_16x16.png' );
|
935 |
-
}
|
936 |
-
|
937 |
-
protected function getPluginLogoUrl32() {
|
938 |
-
return $this->getImageUrl( 'pluginlogo_32x32.png' );
|
939 |
-
}
|
940 |
-
|
941 |
-
/**
|
942 |
-
*/
|
943 |
-
protected function loadDataProcessor() {
|
944 |
-
require_once( dirname(__FILE__) . '/icwp-data-processor.php' );
|
945 |
-
}
|
946 |
-
|
947 |
-
}//CLASS
|
948 |
-
|
949 |
endif;
|
1 |
<?php
|
2 |
|
3 |
+
require_once( dirname(__FILE__).ICWP_DS.'icwp-foundation.php' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
+
if ( !class_exists('ICWP_Pure_Base_V6') ):
|
|
|
6 |
|
7 |
+
class ICWP_Pure_Base_V6 extends ICWP_WPSF_Foundation {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8 |
|
9 |
+
/**
|
10 |
+
* @var ICWP_WPSF_Plugin_Controller
|
11 |
+
*/
|
12 |
+
protected $oPluginController;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
|
14 |
+
protected $fShowMarketing;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
|
16 |
+
public function __construct( ICWP_WPSF_Plugin_Controller $oPluginController ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
|
18 |
+
// All core values of the plugin are derived from the values stored in this value object.
|
19 |
+
$this->oPluginController = $oPluginController;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
|
21 |
+
// add_action( 'plugins_loaded', array( $this, 'onWpPluginsLoaded' ) );
|
22 |
+
// add_action( 'init', array( $this, 'onWpInit' ), 0 );
|
23 |
+
if ( $this->getController()->getIsValidAdminArea( false ) ) {
|
24 |
+
add_action( 'admin_init', array( $this, 'onWpAdminInit' ) );
|
25 |
+
add_action( 'admin_menu', array( $this, 'onWpAdminMenu' ) );
|
26 |
+
add_action( 'network_admin_menu', array( $this, 'onWpAdminMenu' ) );
|
27 |
+
add_action( 'plugin_action_links', array( $this, 'onWpPluginActionLinks' ), 10, 4 );
|
28 |
+
// add_action( 'wp_before_admin_bar_render', array( $this, 'onWpAdminBar' ), 1, 9999 );
|
29 |
+
}
|
30 |
+
$this->registerActivationHooks();
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* @return ICWP_WPSF_Plugin_Controller
|
35 |
+
*/
|
36 |
+
public function getController() {
|
37 |
+
return $this->oPluginController;
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Returns this unique plugin prefix
|
42 |
+
*
|
43 |
+
* @param string $sGlue
|
44 |
+
* @return string
|
45 |
+
*/
|
46 |
+
public function getPluginPrefix( $sGlue = '-' ) {
|
47 |
+
return $this->getController()->getPluginPrefix( $sGlue );
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Will prefix and return any string with the unique plugin prefix.
|
52 |
+
*
|
53 |
+
* @param string $sSuffix
|
54 |
+
* @param string $sGlue
|
55 |
+
* @return string
|
56 |
+
*/
|
57 |
+
public function doPluginPrefix( $sSuffix = '', $sGlue = '-' ) {
|
58 |
+
return $this->getController()->doPluginPrefix( $sSuffix, $sGlue );
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Registers the plugins activation, deactivate and uninstall hooks.
|
63 |
+
*/
|
64 |
+
protected function registerActivationHooks() {
|
65 |
+
register_activation_hook( $this->getController()->getRootFile(), array( $this, 'onWpActivatePlugin' ) );
|
66 |
+
register_deactivation_hook( $this->getController()->getRootFile(), array( $this, 'onWpDeactivatePlugin' ) );
|
67 |
+
// register_uninstall_hook( $this->oPluginVo->getRootFile(), array( $this, 'onWpUninstallPlugin' ) );
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* This is the path to the main plugin file relative to the WordPress plugins directory.
|
72 |
+
*
|
73 |
+
* @return string
|
74 |
+
*/
|
75 |
+
public function getPluginBaseFile() {
|
76 |
+
return $this->getController()->getPluginBaseFile();
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* @param boolean $fHasPermission
|
81 |
+
* @return boolean
|
82 |
+
*/
|
83 |
+
public function hasPermissionToView( $fHasPermission = true ) {
|
84 |
+
return $this->hasPermissionToSubmit( $fHasPermission );
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* @param boolean $fHasPermission
|
89 |
+
* @return boolean
|
90 |
+
*/
|
91 |
+
public function hasPermissionToSubmit( $fHasPermission = true ) {
|
92 |
+
// first a basic admin check
|
93 |
+
return $fHasPermission && is_super_admin() && current_user_can( $this->getController()->getBasePermissions() );
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* @param string $sView
|
98 |
+
* @param array $aData
|
99 |
+
* @return bool
|
100 |
+
*/
|
101 |
+
protected function display( $sView, $aData = array() ) {
|
102 |
+
$sFile = $this->getController()->getViewPath( $sView );
|
103 |
+
|
104 |
+
if ( !is_file( $sFile ) ) {
|
105 |
+
echo "View not found: ".$sFile;
|
106 |
+
return false;
|
107 |
+
}
|
108 |
|
109 |
+
if ( count( $aData ) > 0 ) {
|
110 |
+
extract( $aData, EXTR_PREFIX_ALL, $this->getController()->getParentSlug() ); //slug being 'icwp'
|
111 |
+
}
|
112 |
|
113 |
+
ob_start();
|
114 |
+
include( $sFile );
|
115 |
+
$sContents = ob_get_contents();
|
116 |
+
ob_end_clean();
|
117 |
|
118 |
+
echo $sContents;
|
119 |
+
return true;
|
|
|
|
|
|
|
|
|
|
|
|
|
120 |
}
|
|
|
|
|
|
|
|
|
121 |
|
122 |
+
public function onWpAdminInit() {
|
123 |
+
//Do Plugin-Specific Admin Work
|
124 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'enqueuePluginGlobalAdminCss' ), 99 );
|
125 |
+
if ( $this->getIsPage_PluginAdmin() ) {
|
126 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'enqueueBootstrapLegacyAdminCss' ), 99 );
|
127 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'enqueuePluginAdminCss' ), 99 );
|
128 |
+
}
|
|
|
|
|
|
|
|
|
|
|
129 |
}
|
130 |
|
131 |
+
public function onWpAdminMenu() {
|
132 |
+
if ( !$this->getController()->getIsValidAdminArea() ) {
|
133 |
+
return true;
|
134 |
+
}
|
135 |
+
$this->createMenu();
|
136 |
+
}
|
137 |
+
|
138 |
+
protected function createMenu() {
|
139 |
+
$oPluginController = $this->getController();
|
140 |
+
|
141 |
+
$sFullParentMenuId = $this->getPluginPrefix();
|
142 |
+
add_menu_page(
|
143 |
+
$oPluginController->getHumanName(),
|
144 |
+
$oPluginController->getAdminMenuTitle(),
|
145 |
+
$oPluginController->getBasePermissions(),
|
146 |
+
$sFullParentMenuId,
|
147 |
+
array( $this, 'onDisplayAll' ),
|
148 |
+
$this->getController()->getPluginUrl_Image( 'pluginlogo_16x16.png' )
|
149 |
+
);
|
150 |
+
//Create and Add the submenu items
|
151 |
+
|
152 |
+
// allow for any plugin menu items that don't come from filters
|
153 |
+
add_filter( $this->doPluginPrefix( 'filter_plugin_submenu_items' ), array( $this, 'filter_addExtraAdminMenuItems' ) );
|
154 |
+
|
155 |
+
$aPluginMenuItems = apply_filters( $this->doPluginPrefix( 'filter_plugin_submenu_items' ), array() );
|
156 |
+
if ( !empty( $aPluginMenuItems ) ) {
|
157 |
+
foreach ( $aPluginMenuItems as $sMenuTitle => $aMenu ) {
|
158 |
+
list( $sMenuItemText, $sMenuItemId, $aMenuCallBack ) = $aMenu;
|
159 |
+
add_submenu_page(
|
160 |
+
$sFullParentMenuId,
|
161 |
+
$sMenuTitle,
|
162 |
+
$sMenuItemText,
|
163 |
+
$oPluginController->getBasePermissions(),
|
164 |
+
$sMenuItemId,
|
165 |
+
$aMenuCallBack
|
166 |
+
);
|
167 |
+
}
|
168 |
+
}
|
169 |
+
$this->fixSubmenu();
|
170 |
}
|
171 |
|
172 |
+
/**
|
173 |
+
* @param array $aItems
|
174 |
+
* @return array
|
175 |
+
*/
|
176 |
+
public function filter_addExtraAdminMenuItems( $aItems ) {
|
177 |
+
return $aItems;
|
178 |
}
|
179 |
|
180 |
+
protected function fixSubmenu() {
|
181 |
+
global $submenu;
|
182 |
+
$sFullParentMenuId = $this->getPluginPrefix();
|
183 |
+
if ( isset( $submenu[$sFullParentMenuId] ) ) {
|
184 |
+
unset( $submenu[$sFullParentMenuId][0] );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
185 |
}
|
186 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
187 |
|
188 |
+
/**
|
189 |
+
* Displaying all views now goes through this central function and we work out
|
190 |
+
* what to display based on the name of current hook/filter being processed.
|
191 |
+
*/
|
192 |
+
public function onDisplayAll() { }
|
|
|
|
|
193 |
|
194 |
+
protected function getBaseDisplayData() {
|
195 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
196 |
+
return array(
|
197 |
+
'plugin_url' => $this->getController()->getPluginUrl(),
|
198 |
+
'var_prefix' => $this->getController()->getOptionStoragePrefix(),
|
199 |
+
'sPluginName' => $this->getController()->getHumanName(),
|
200 |
+
'fShowAds' => $this->isShowMarketing(),
|
201 |
+
'nonce_field' => $this->getPluginPrefix(),
|
202 |
+
'form_action' => 'admin.php?page='.$oWp->getCurrentWpAdminPage()
|
203 |
+
);
|
|
|
204 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
205 |
|
206 |
+
/**
|
207 |
+
* @return bool
|
208 |
+
*/
|
209 |
+
protected function getIsPage_PluginMainDashboard() {
|
210 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
211 |
+
return ( $oWp->getCurrentWpAdminPage() == $this->getPluginPrefix() );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
212 |
}
|
|
|
|
|
213 |
|
214 |
+
/**
|
215 |
+
* @return bool
|
216 |
+
*/
|
217 |
+
protected function getIsPage_PluginAdmin() {
|
218 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
219 |
+
return ( strpos( $oWp->getCurrentWpAdminPage(), $this->getPluginPrefix() ) === 0 );
|
220 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
221 |
|
222 |
+
/**
|
223 |
+
* @return bool
|
224 |
+
*/
|
225 |
+
protected function isShowMarketing() {
|
226 |
|
227 |
+
if ( isset($this->fShowMarketing) ) {
|
228 |
+
return $this->fShowMarketing;
|
|
|
|
|
|
|
|
|
|
|
229 |
}
|
230 |
+
$this->fShowMarketing = true;
|
231 |
+
if ( class_exists( 'Worpit_Plugin' ) ) {
|
232 |
+
if ( method_exists( 'Worpit_Plugin', 'IsLinked' ) ) {
|
233 |
+
$this->fShowMarketing = !Worpit_Plugin::IsLinked();
|
234 |
+
}
|
235 |
+
else if ( function_exists( 'get_option' )
|
236 |
&& get_option( Worpit_Plugin::$VariablePrefix.'assigned' ) == 'Y'
|
237 |
&& get_option( Worpit_Plugin::$VariablePrefix.'assigned_to' ) != '' ) {
|
238 |
+
|
239 |
+
$this->fShowMarketing = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
240 |
}
|
241 |
}
|
242 |
+
return $this->fShowMarketing ;
|
243 |
+
}
|
244 |
+
|
245 |
+
/**
|
246 |
+
* On the plugins listing page, hides the edit and deactivate links
|
247 |
+
* for this plugin based on permissions
|
248 |
+
*
|
249 |
+
* @see ICWP_Pure_Base_V1::onWpPluginActionLinks()
|
250 |
+
*/
|
251 |
+
public function onWpPluginActionLinks( $aActionLinks, $sPluginFile ) {
|
252 |
+
|
253 |
+
if ( $sPluginFile == $this->getPluginBaseFile() ) {
|
254 |
+
if ( !$this->hasPermissionToSubmit() ) {
|
255 |
+
if ( array_key_exists( 'edit', $aActionLinks ) ) {
|
256 |
+
unset( $aActionLinks['edit'] );
|
257 |
+
}
|
258 |
+
if ( array_key_exists( 'deactivate', $aActionLinks ) ) {
|
259 |
+
unset( $aActionLinks['deactivate'] );
|
260 |
+
}
|
261 |
+
}
|
262 |
|
263 |
+
$sSettingsLink = sprintf( '<a href="%s">%s</a>', $this->getController()->getPluginUrl_AdminPage(), 'Dashboard' ); ;
|
264 |
+
array_unshift( $aActionLinks, $sSettingsLink );
|
265 |
+
}
|
266 |
+
return $aActionLinks;
|
267 |
}
|
|
|
|
|
268 |
|
269 |
+
/**
|
270 |
+
* @return bool
|
271 |
+
*/
|
272 |
+
protected function getShowAdminNotices() {
|
|
|
|
|
273 |
return true;
|
274 |
}
|
275 |
|
276 |
+
/**
|
277 |
+
* Updates the current (or supplied user ID) user meta data with the version of the plugin
|
278 |
+
*
|
279 |
+
* @param $nId
|
280 |
+
* @param $sValue
|
281 |
+
*/
|
282 |
+
protected function updateTranslationNoticeShownUserMeta( $nId = '', $sValue = 'Y' ) {
|
283 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
284 |
+
$oWp->updateUserMeta( $this->getController()->doPluginOptionPrefix( 'plugin_translation_notice' ), $sValue, $nId );
|
|
|
|
|
|
|
|
|
285 |
}
|
|
|
|
|
|
|
286 |
|
287 |
+
/**
|
288 |
+
* Updates the current (or supplied user ID) user meta data with the version of the plugin
|
289 |
+
*
|
290 |
+
* @param $nId
|
291 |
+
* @param $sValue
|
292 |
+
*/
|
293 |
+
protected function updateMailingListSignupShownUserMeta( $nId = '', $sValue = 'Y' ) {
|
294 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
295 |
+
$oWp->updateUserMeta( $this->getController()->doPluginOptionPrefix( 'plugin_mailing_list_signup' ), $sValue, $nId );
|
296 |
}
|
297 |
|
298 |
+
/**
|
299 |
+
* Updates the current (or supplied user ID) user meta data with the version of the plugin
|
300 |
+
*
|
301 |
+
* @param integer $nId
|
302 |
+
*/
|
303 |
+
protected function updateVersionUserMeta( $nId = null ) {
|
304 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
305 |
+
$oWp->updateUserMeta( $this->getController()->doPluginOptionPrefix( 'current_version' ), $this->getController()->getVersion(), $nId );
|
|
|
|
|
|
|
|
|
|
|
306 |
}
|
|
|
|
|
|
|
307 |
|
308 |
+
public function enqueueBootstrapAdminCss() {
|
309 |
+
$sUnique = $this->doPluginPrefix( 'bootstrap_wpadmin_css' );
|
310 |
+
wp_register_style( $sUnique, $this->getController()->getPluginUrl_Css( 'bootstrap-wpadmin.css' ), false, $this->getController()->getVersion() );
|
311 |
+
wp_enqueue_style( $sUnique );
|
|
|
|
|
|
|
312 |
}
|
|
|
313 |
|
314 |
+
public function enqueueBootstrapLegacyAdminCss() {
|
315 |
+
$sUnique = $this->doPluginPrefix( 'bootstrap_wpadmin_legacy_css' );
|
316 |
+
wp_register_style( $sUnique, $this->getController()->getPluginUrl_Css( 'bootstrap-wpadmin-legacy.css' ), false, $this->getController()->getVersion() );
|
317 |
+
wp_enqueue_style( $sUnique );
|
318 |
|
319 |
+
$sUnique = $this->doPluginPrefix( 'bootstrap_wpadmin_css_fixes' );
|
320 |
+
wp_register_style( $sUnique, $this->getController()->getPluginUrl_Css('bootstrap-wpadmin-fixes.css'), array( $this->doPluginPrefix( 'bootstrap_wpadmin_legacy_css' ) ), $this->getController()->getVersion() );
|
321 |
+
wp_enqueue_style( $sUnique );
|
|
|
|
|
|
|
|
|
|
|
322 |
}
|
|
|
323 |
|
324 |
+
public function enqueuePluginAdminCss() {
|
325 |
+
$sUnique = $this->doPluginPrefix( 'plugin_css' );
|
326 |
+
wp_register_style( $sUnique, $this->getController()->getPluginUrl_Css('plugin.css'), array( $this->doPluginPrefix( 'bootstrap_wpadmin_css_fixes' ) ), $this->getController()->getVersion().rand() );
|
327 |
+
wp_enqueue_style( $sUnique );
|
|
|
|
|
|
|
|
|
328 |
}
|
329 |
|
330 |
+
public function enqueuePluginGlobalAdminCss() {
|
331 |
+
$sUnique = $this->doPluginPrefix( 'global_plugin_css' );
|
332 |
+
wp_register_style( $sUnique, $this->getController()->getPluginUrl_Css('global-plugin.css'), false, $this->getController()->getVersion().rand() );
|
333 |
+
wp_enqueue_style( $sUnique );
|
334 |
}
|
|
|
335 |
|
336 |
+
public function onWpActivatePlugin() { }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
337 |
|
338 |
+
public function onWpDeactivatePlugin() {
|
339 |
+
if ( current_user_can( $this->getController()->getBasePermissions() ) ) {
|
340 |
+
do_action( $this->doPluginPrefix( 'delete_plugin' ) );
|
341 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
342 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
343 |
|
344 |
+
/**
|
345 |
+
*/
|
346 |
+
public function onWpAdminBar() {
|
347 |
+
$aNodes = $this->getAdminBarNodes();
|
348 |
+
if ( !is_array( $aNodes ) ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
349 |
return;
|
350 |
}
|
351 |
+
foreach( $aNodes as $aNode ) {
|
352 |
+
$this->addAdminBarNode( $aNode );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
353 |
}
|
354 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
355 |
|
356 |
+
protected function getAdminBarNodes() { }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
357 |
|
358 |
+
protected function addAdminBarNode( $aNode ) {
|
359 |
+
global $wp_admin_bar;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
360 |
|
361 |
+
if ( isset( $aNode['children'] ) ) {
|
362 |
+
$aChildren = $aNode['children'];
|
363 |
+
unset( $aNode['children'] );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
364 |
}
|
365 |
+
$wp_admin_bar->add_node( $aNode );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
366 |
|
367 |
+
if ( !empty($aChildren) ) {
|
368 |
+
foreach( $aChildren as $aChild ) {
|
369 |
+
$aChild['parent'] = $aNode['id'];
|
370 |
+
$this->addAdminBarNode( $aChild );
|
371 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
372 |
}
|
373 |
}
|
374 |
}
|
375 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
376 |
endif;
|
src/icwp-wpfilesystem.php
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
/**
|
3 |
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
* All rights reserved.
|
5 |
-
*
|
6 |
* Version: 2013-11-19
|
7 |
*
|
8 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
@@ -17,287 +17,335 @@
|
|
17 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
18 |
*/
|
19 |
|
20 |
-
if ( !class_exists('
|
21 |
-
|
22 |
-
class
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
|
|
|
|
45 |
}
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
if ( !$this->exists($this->m_sWpConfigPath) ) {
|
65 |
-
$this->m_sWpConfigPath = ABSPATH.'..'.ICWP_DS.'wp-config.php';
|
66 |
-
if ( !$this->exists($this->m_sWpConfigPath) ) {
|
67 |
-
$this->m_sWpConfigPath = false;
|
68 |
}
|
|
|
69 |
}
|
70 |
-
}
|
71 |
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
|
|
|
|
79 |
}
|
80 |
-
|
81 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
82 |
}
|
83 |
-
|
84 |
-
}
|
85 |
-
|
86 |
-
public function getContent_WpConfig() {
|
87 |
-
return $this->getFileContent( $this->m_sWpConfigPath );
|
88 |
-
}
|
89 |
-
|
90 |
-
public function putContent_WpConfig( $insContent ) {
|
91 |
-
return $this->putFileContent( $this->m_sWpConfigPath, $insContent );
|
92 |
-
}
|
93 |
-
|
94 |
-
|
95 |
-
/**
|
96 |
-
* @return string
|
97 |
-
*/
|
98 |
-
public function getWpConfigPath() {
|
99 |
-
return $this->m_sWpConfigPath;
|
100 |
-
}
|
101 |
-
|
102 |
-
public function getUrl( $insUrl ) {
|
103 |
-
$mResult = wp_remote_get( $insUrl );
|
104 |
-
if ( is_wp_error( $mResult ) ) {
|
105 |
return false;
|
106 |
}
|
107 |
-
|
108 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
109 |
}
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
public function getUrlContent( $insUrl ) {
|
114 |
-
|
115 |
-
$aResponse = $this->getUrl( $insUrl );
|
116 |
-
if ( !$aResponse ) {
|
117 |
-
return false;
|
118 |
}
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
131 |
}
|
|
|
132 |
}
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
$sFileContents = $this->getFileContent( $sFilePath );
|
143 |
-
if ( !is_null( $sFileContents ) && $sFileContents === $sContents ) {
|
144 |
-
return $this->deleteFile( $sFilePath );
|
145 |
}
|
|
|
146 |
}
|
147 |
-
return false;
|
148 |
-
}
|
149 |
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
157 |
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
*/
|
162 |
-
public function getAccessedTime( $sFilePath ) {
|
163 |
-
return $this->getTime($sFilePath, 'accessed');
|
164 |
-
}
|
165 |
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
|
|
|
|
|
|
172 |
|
173 |
-
|
174 |
-
|
|
|
|
|
|
|
|
|
175 |
}
|
176 |
|
177 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
178 |
|
179 |
-
|
|
|
|
|
|
|
|
|
|
|
180 |
|
181 |
-
|
182 |
-
return $fUseWp? $this->m_oWpFilesystem->mtime( $sFilePath ) : filemtime( $sFilePath );
|
183 |
-
break;
|
184 |
-
case 'accessed' :
|
185 |
-
return $fUseWp? $this->m_oWpFilesystem->atime( $sFilePath ) : fileatime( $sFilePath );
|
186 |
-
break;
|
187 |
-
default:
|
188 |
return null;
|
189 |
-
|
190 |
-
}
|
191 |
-
}
|
192 |
|
193 |
-
|
194 |
-
|
195 |
-
* @return NULL|boolean
|
196 |
-
*/
|
197 |
-
public function getCanReadWriteFile( $insFilePath ) {
|
198 |
-
if ( !file_exists( $insFilePath ) ) {
|
199 |
-
return null;
|
200 |
-
}
|
201 |
-
|
202 |
-
$nFileSize = filesize( $insFilePath );
|
203 |
-
if ( $nFileSize === 0 ) {
|
204 |
-
return null;
|
205 |
-
}
|
206 |
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
*/
|
218 |
-
public function getFileContent( $sFilePath ) {
|
219 |
-
if ( !$this->exists( $sFilePath ) ) {
|
220 |
-
return null;
|
221 |
-
}
|
222 |
-
if ( $this->m_oWpFilesystem ) {
|
223 |
-
return $this->m_oWpFilesystem->get_contents( $sFilePath );
|
224 |
-
}
|
225 |
-
else if ( function_exists('file_get_contents') ) {
|
226 |
-
return file_get_contents( $sFilePath );
|
227 |
}
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
239 |
}
|
240 |
-
|
241 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
242 |
}
|
243 |
-
return true;
|
244 |
-
}
|
245 |
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
252 |
return null;
|
253 |
}
|
254 |
-
if ( $this->m_oWpFilesystem ) {
|
255 |
-
return $this->m_oWpFilesystem->delete( $insFilePath );
|
256 |
-
}
|
257 |
-
else {
|
258 |
-
return unlink( $insFilePath );
|
259 |
-
}
|
260 |
-
}
|
261 |
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
)
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
}
|
271 |
-
|
272 |
-
if ( !$this->m_oWpFilesystem ) {
|
273 |
-
if ( function_exists( $insFunctionName ) ) {
|
274 |
-
call_user_func_array( $insFunctionName, $inaParams );
|
275 |
}
|
276 |
-
|
277 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
278 |
}
|
|
|
279 |
}
|
280 |
-
|
281 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
282 |
}
|
283 |
-
$sWpFunctionName = $aFunctionMap[$insFunctionName];
|
284 |
-
$sResult = call_user_func_array( array($this->m_oWpFilesystem, $sWpFunctionName), $inaParams );
|
285 |
-
return $sResult;
|
286 |
-
}
|
287 |
-
}
|
288 |
-
endif;
|
289 |
|
290 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
291 |
|
292 |
-
class ICWP_WpFilesystem_WPSF extends ICWP_WpFilesystem_V2 {
|
293 |
/**
|
294 |
-
* @return ICWP_WpFilesystem_WPSF
|
295 |
*/
|
296 |
-
|
297 |
-
if ( is_null(
|
298 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
299 |
}
|
300 |
-
return self::$oInstance;
|
301 |
}
|
302 |
}
|
303 |
-
endif;
|
2 |
/**
|
3 |
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
* All rights reserved.
|
5 |
+
*
|
6 |
* Version: 2013-11-19
|
7 |
*
|
8 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
17 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
18 |
*/
|
19 |
|
20 |
+
if ( !class_exists('ICWP_WPSF_WpFilesystem') ):
|
21 |
+
|
22 |
+
class ICWP_WPSF_WpFilesystem {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var ICWP_WPSF_WpFilesystem
|
26 |
+
*/
|
27 |
+
protected static $oInstance = NULL;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @var WP_Filesystem
|
31 |
+
*/
|
32 |
+
protected $oWpfs = null;
|
33 |
+
|
34 |
+
/**
|
35 |
+
* @var string
|
36 |
+
*/
|
37 |
+
protected $m_sWpConfigPath = null;
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @return ICWP_WPSF_WpFilesystem
|
41 |
+
*/
|
42 |
+
public static function GetInstance() {
|
43 |
+
if ( is_null( self::$oInstance ) ) {
|
44 |
+
self::$oInstance = new self();
|
45 |
+
}
|
46 |
+
return self::$oInstance;
|
47 |
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* @param string $sBase
|
51 |
+
* @param string $sPath
|
52 |
+
* @return string
|
53 |
+
*/
|
54 |
+
public function pathJoin( $sBase, $sPath ) {
|
55 |
+
return rtrim( $sBase, ICWP_DS ).ICWP_DS.ltrim( $sPath, ICWP_DS );
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* @param $sFilePath
|
60 |
+
* @return boolean|null true/false whether file/directory exists
|
61 |
+
*/
|
62 |
+
public function exists( $sFilePath ) {
|
63 |
+
$oFs = $this->getWpfs();
|
64 |
+
if ( $oFs ) {
|
65 |
+
return $oFs->exists( $sFilePath );
|
|
|
|
|
|
|
|
|
66 |
}
|
67 |
+
return function_exists( 'file_exists' ) ? file_exists( $sFilePath ) : null;
|
68 |
}
|
|
|
69 |
|
70 |
+
/**
|
71 |
+
* @param string $sNeedle
|
72 |
+
* @param string $sDir
|
73 |
+
* @param boolean $fCaseSensitive
|
74 |
+
* @return boolean
|
75 |
+
*/
|
76 |
+
public function fileExistsInDir( $sNeedle, $sDir, $fCaseSensitive = true ) {
|
77 |
+
if ( $fCaseSensitive ) {
|
78 |
+
return $this->exists( $this->pathJoin( $sDir, $sNeedle ) );
|
79 |
}
|
80 |
+
$sNeedle = strtolower( $sNeedle );
|
81 |
+
if ( $oHandle = opendir( $sDir ) ) {
|
82 |
+
|
83 |
+
while ( false !== ( $sFileEntry = readdir( $oHandle ) ) ) {
|
84 |
+
if ( !$this->isFile( $this->pathJoin( $sDir, $sFileEntry ) ) ) {
|
85 |
+
continue;
|
86 |
+
}
|
87 |
+
if ( $sNeedle == strtolower( $sFileEntry ) ) {
|
88 |
+
return true;
|
89 |
+
}
|
90 |
+
}
|
91 |
}
|
92 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
93 |
return false;
|
94 |
}
|
95 |
+
|
96 |
+
protected function setWpConfigPath() {
|
97 |
+
$this->m_sWpConfigPath = ABSPATH.'wp-config.php';
|
98 |
+
if ( !$this->exists($this->m_sWpConfigPath) ) {
|
99 |
+
$this->m_sWpConfigPath = ABSPATH.'..'.ICWP_DS.'wp-config.php';
|
100 |
+
if ( !$this->exists($this->m_sWpConfigPath) ) {
|
101 |
+
$this->m_sWpConfigPath = false;
|
102 |
+
}
|
103 |
+
}
|
104 |
}
|
105 |
+
|
106 |
+
public function getContent_WpConfig() {
|
107 |
+
return $this->getFileContent( $this->m_sWpConfigPath );
|
|
|
|
|
|
|
|
|
|
|
108 |
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* @param string $sContent
|
112 |
+
* @return bool
|
113 |
+
*/
|
114 |
+
public function putContent_WpConfig( $sContent ) {
|
115 |
+
return $this->putFileContent( $this->m_sWpConfigPath, $sContent );
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* @param string $sUrl
|
120 |
+
* @param boolean $fSecure
|
121 |
+
* @return boolean
|
122 |
+
*/
|
123 |
+
public function getIsUrlValid( $sUrl, $fSecure = false ) {
|
124 |
+
$sSchema = $fSecure? 'https://' : 'http://';
|
125 |
+
$sUrl = ( strpos( $sUrl, 'http' ) !== 0 )? $sSchema.$sUrl : $sUrl;
|
126 |
+
return ( $this->getUrl( $sUrl ) != false );
|
127 |
+
}
|
128 |
+
|
129 |
+
/**
|
130 |
+
* @return string
|
131 |
+
*/
|
132 |
+
public function getWpConfigPath() {
|
133 |
+
return $this->m_sWpConfigPath;
|
134 |
+
}
|
135 |
+
|
136 |
+
/**
|
137 |
+
* @param string $sUrl
|
138 |
+
* @return bool
|
139 |
+
*/
|
140 |
+
public function getUrl( $sUrl ) {
|
141 |
+
$mResult = wp_remote_get( $sUrl );
|
142 |
+
if ( is_wp_error( $mResult ) ) {
|
143 |
+
return false;
|
144 |
+
}
|
145 |
+
if ( !isset( $mResult['response']['code'] ) || $mResult['response']['code'] != 200 ) {
|
146 |
+
return false;
|
147 |
}
|
148 |
+
return $mResult;
|
149 |
}
|
150 |
+
|
151 |
+
/**
|
152 |
+
* @param string $sUrl
|
153 |
+
* @return bool|string
|
154 |
+
*/
|
155 |
+
public function getUrlContent( $sUrl ) {
|
156 |
+
$aResponse = $this->getUrl( $sUrl );
|
157 |
+
if ( !$aResponse || !isset( $aResponse['body'] ) ) {
|
158 |
+
return false;
|
|
|
|
|
|
|
159 |
}
|
160 |
+
return $aResponse['body'];
|
161 |
}
|
|
|
|
|
162 |
|
163 |
+
public function getCanWpRemoteGet() {
|
164 |
+
$aUrlsToTest = array(
|
165 |
+
'https://www.microsoft.com',
|
166 |
+
'https://www.google.com',
|
167 |
+
'https://www.facebook.com'
|
168 |
+
);
|
169 |
+
foreach( $aUrlsToTest as $sUrl ) {
|
170 |
+
if ( $this->getUrl( $sUrl ) !== false ) {
|
171 |
+
return true;
|
172 |
+
}
|
173 |
+
}
|
174 |
+
return false;
|
175 |
+
}
|
176 |
|
177 |
+
public function getCanDiskWrite() {
|
178 |
+
$sFilePath = dirname( __FILE__ ).'/testfile.'.rand().'txt';
|
179 |
+
$sContents = "Testing icwp file read and write.";
|
|
|
|
|
|
|
|
|
180 |
|
181 |
+
// Write, read, verify, delete.
|
182 |
+
if ( $this->putFileContent( $sFilePath, $sContents ) ) {
|
183 |
+
$sFileContents = $this->getFileContent( $sFilePath );
|
184 |
+
if ( !is_null( $sFileContents ) && $sFileContents === $sContents ) {
|
185 |
+
return $this->deleteFile( $sFilePath );
|
186 |
+
}
|
187 |
+
}
|
188 |
+
return false;
|
189 |
+
}
|
190 |
|
191 |
+
/**
|
192 |
+
* @param string $sFilePath
|
193 |
+
* @return int|null
|
194 |
+
*/
|
195 |
+
public function getModifiedTime( $sFilePath ) {
|
196 |
+
return $this->getTime( $sFilePath, 'modified' );
|
197 |
}
|
198 |
|
199 |
+
/**
|
200 |
+
* @param string $sFilePath
|
201 |
+
* @return int|null
|
202 |
+
*/
|
203 |
+
public function getAccessedTime( $sFilePath ) {
|
204 |
+
return $this->getTime( $sFilePath, 'accessed' );
|
205 |
+
}
|
206 |
|
207 |
+
/**
|
208 |
+
* @param string $sFilePath
|
209 |
+
* @param string $sProperty
|
210 |
+
* @return int|null
|
211 |
+
*/
|
212 |
+
public function getTime( $sFilePath, $sProperty = 'modified' ) {
|
213 |
|
214 |
+
if ( !$this->exists( $sFilePath ) ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
215 |
return null;
|
216 |
+
}
|
|
|
|
|
217 |
|
218 |
+
$oFs = $this->getWpfs();
|
219 |
+
switch ( $sProperty ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
220 |
|
221 |
+
case 'modified' :
|
222 |
+
return $oFs? $oFs->mtime( $sFilePath ) : filemtime( $sFilePath );
|
223 |
+
break;
|
224 |
+
case 'accessed' :
|
225 |
+
return $oFs? $oFs->atime( $sFilePath ) : fileatime( $sFilePath );
|
226 |
+
break;
|
227 |
+
default:
|
228 |
+
return null;
|
229 |
+
break;
|
230 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
231 |
}
|
232 |
+
|
233 |
+
/**
|
234 |
+
* @param string $sFilePath
|
235 |
+
* @return NULL|boolean
|
236 |
+
*/
|
237 |
+
public function getCanReadWriteFile( $sFilePath ) {
|
238 |
+
if ( !file_exists( $sFilePath ) ) {
|
239 |
+
return null;
|
240 |
+
}
|
241 |
+
|
242 |
+
$nFileSize = filesize( $sFilePath );
|
243 |
+
if ( $nFileSize === 0 ) {
|
244 |
+
return null;
|
245 |
+
}
|
246 |
+
|
247 |
+
$sFileContent = $this->getFileContent( $sFilePath );
|
248 |
+
if ( empty( $sFileContent ) ) {
|
249 |
+
return false; //can't even read the file!
|
250 |
+
}
|
251 |
+
return $this->putFileContent( $sFilePath, $sFileContent );
|
252 |
}
|
253 |
+
|
254 |
+
/**
|
255 |
+
* @param string $sFilePath
|
256 |
+
* @return string|null
|
257 |
+
*/
|
258 |
+
public function getFileContent( $sFilePath ) {
|
259 |
+
$sContents = null;
|
260 |
+
$oFs = $this->getWpfs();
|
261 |
+
if ( $oFs ) {
|
262 |
+
$sContents = $oFs->get_contents( $sFilePath );
|
263 |
+
}
|
264 |
+
|
265 |
+
if ( empty( $sContents ) && function_exists( 'file_get_contents' ) ) {
|
266 |
+
$sContents = file_get_contents( $sFilePath );
|
267 |
+
}
|
268 |
+
return $sContents;
|
269 |
}
|
|
|
|
|
270 |
|
271 |
+
/**
|
272 |
+
* @param string $sFilePath
|
273 |
+
* @param string $sContents
|
274 |
+
* @return boolean|null
|
275 |
+
*/
|
276 |
+
public function putFileContent( $sFilePath, $sContents ) {
|
277 |
+
$oFs = $this->getWpfs();
|
278 |
+
if ( $oFs ) {
|
279 |
+
return $oFs->put_contents( $sFilePath, $sContents, FS_CHMOD_FILE );
|
280 |
+
}
|
281 |
+
|
282 |
+
if ( function_exists( 'file_put_contents' ) ) {
|
283 |
+
return file_put_contents( $sFilePath, $sContents ) !== false;
|
284 |
+
}
|
285 |
return null;
|
286 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
287 |
|
288 |
+
/**
|
289 |
+
* @param $sFilePath
|
290 |
+
* @return boolean|null
|
291 |
+
*/
|
292 |
+
public function deleteFile( $sFilePath ) {
|
293 |
+
$oFs = $this->getWpfs();
|
294 |
+
if ( $oFs ) {
|
295 |
+
return $oFs->delete( $sFilePath );
|
|
|
|
|
|
|
|
|
|
|
296 |
}
|
297 |
+
|
298 |
+
return function_exists( 'unlink' ) ? unlink( $sFilePath ) : null;
|
299 |
+
}
|
300 |
+
|
301 |
+
/**
|
302 |
+
* @param $sFilePath
|
303 |
+
* @return bool|mixed
|
304 |
+
*/
|
305 |
+
public function isFile( $sFilePath ) {
|
306 |
+
$oFs = $this->getWpfs();
|
307 |
+
if ( $oFs ) {
|
308 |
+
return $oFs->is_file( $sFilePath );
|
309 |
}
|
310 |
+
return function_exists( 'is_file' ) ? is_file( $sFilePath ) : null;
|
311 |
}
|
312 |
+
|
313 |
+
/**
|
314 |
+
* @param string $sFilePath
|
315 |
+
* @param int $nTime
|
316 |
+
* @return bool|mixed
|
317 |
+
*/
|
318 |
+
public function touch( $sFilePath, $nTime ) {
|
319 |
+
$oFs = $this->getWpfs();
|
320 |
+
if ( $oFs ) {
|
321 |
+
return $oFs->touch( $sFilePath, $nTime );
|
322 |
+
}
|
323 |
+
return function_exists( 'touch' ) ? touch( $sFilePath, $nTime ) : null;
|
324 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
325 |
|
326 |
+
/**
|
327 |
+
*/
|
328 |
+
protected function getWpfs() {
|
329 |
+
if ( is_null( $this->oWpfs ) ) {
|
330 |
+
$this->initFileSystem();
|
331 |
+
}
|
332 |
+
return $this->oWpfs;
|
333 |
+
}
|
334 |
|
|
|
335 |
/**
|
|
|
336 |
*/
|
337 |
+
private function initFileSystem() {
|
338 |
+
if ( is_null( $this->oWpfs ) ) {
|
339 |
+
require_once( ABSPATH . 'wp-admin'.ICWP_DS.'includes'.ICWP_DS.'file.php' );
|
340 |
+
WP_Filesystem();
|
341 |
+
global $wp_filesystem;
|
342 |
+
if ( isset( $wp_filesystem ) && is_object( $wp_filesystem ) ) {
|
343 |
+
$this->oWpfs = $wp_filesystem;
|
344 |
+
}
|
345 |
+
else {
|
346 |
+
$this->oWpfs = false;
|
347 |
+
}
|
348 |
}
|
|
|
349 |
}
|
350 |
}
|
351 |
+
endif;
|
src/icwp-wpfunctions.php
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
/**
|
3 |
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
* All rights reserved.
|
5 |
-
*
|
6 |
* Version: 2013-08-14_A
|
7 |
*
|
8 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
@@ -17,230 +17,525 @@
|
|
17 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
18 |
*/
|
19 |
|
20 |
-
|
|
|
|
|
21 |
|
22 |
-
class
|
23 |
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
}
|
36 |
-
return self::$oInstance;
|
37 |
-
}
|
38 |
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
/**
|
52 |
-
* @param string $insPluginFile
|
53 |
-
* @return boolean|stdClass
|
54 |
-
*/
|
55 |
-
public function getIsPluginUpdateAvailable( $insPluginFile ) {
|
56 |
-
$aUpdates = $this->getWordpressUpdates();
|
57 |
-
if ( empty( $aUpdates ) ) {
|
58 |
return false;
|
59 |
}
|
60 |
-
|
61 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
}
|
63 |
-
return false;
|
64 |
-
}
|
65 |
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
return add_query_arg( $aQueryArgs, $sUrl );
|
74 |
-
}
|
75 |
-
|
76 |
-
public function getWordpressUpdates() {
|
77 |
-
$oCurrent = $this->getTransient( 'update_plugins' );
|
78 |
-
return $oCurrent->response;
|
79 |
-
}
|
80 |
-
|
81 |
-
/**
|
82 |
-
* The full plugin file to be upgraded.
|
83 |
-
*
|
84 |
-
* @param string $insPluginFile
|
85 |
-
* @return boolean
|
86 |
-
*/
|
87 |
-
public function doPluginUpgrade( $insPluginFile ) {
|
88 |
-
|
89 |
-
if ( !$this->getIsPluginUpdateAvailable($insPluginFile)
|
90 |
-
|| ( isset( $GLOBALS['pagenow'] ) && $GLOBALS['pagenow'] == 'update.php' ) ) {
|
91 |
-
return true;
|
92 |
-
}
|
93 |
-
$sUrl = $this->getPluginUpgradeLink( $insPluginFile );
|
94 |
-
wp_redirect( $sUrl );
|
95 |
-
exit();
|
96 |
-
}
|
97 |
-
/**
|
98 |
-
* @param string $insKey
|
99 |
-
* @return object
|
100 |
-
*/
|
101 |
-
protected function getTransient( $insKey ) {
|
102 |
-
|
103 |
-
// TODO: Handle multisite
|
104 |
-
|
105 |
-
if ( version_compare( $this->getWordpressVersion(), '2.7.9', '<=' ) ) {
|
106 |
-
return get_option( $insKey );
|
107 |
-
}
|
108 |
-
|
109 |
-
if ( function_exists( 'get_site_transient' ) ) {
|
110 |
-
return get_site_transient( $insKey );
|
111 |
-
}
|
112 |
-
|
113 |
-
if ( version_compare( $this->getWordpressVersion(), '2.9.9', '<=' ) ) {
|
114 |
-
return apply_filters( 'transient_'.$insKey, get_option( '_transient_'.$insKey ) );
|
115 |
-
}
|
116 |
-
|
117 |
-
return apply_filters( 'site_transient_'.$insKey, get_option( '_site_transient_'.$insKey ) );
|
118 |
-
}
|
119 |
-
|
120 |
-
/**
|
121 |
-
* @return string
|
122 |
-
*/
|
123 |
-
public function getWordpressVersion() {
|
124 |
-
global $wp_version;
|
125 |
-
|
126 |
-
if ( empty( $this->m_sWpVersion ) ) {
|
127 |
-
$sVersionFile = ABSPATH.WPINC.'/version.php';
|
128 |
-
$sVersionContents = file_get_contents( $sVersionFile );
|
129 |
-
|
130 |
-
if ( preg_match( '/wp_version\s=\s\'([^(\'|")]+)\'/i', $sVersionContents, $aMatches ) ) {
|
131 |
-
$this->m_sWpVersion = $aMatches[1];
|
132 |
-
}
|
133 |
-
}
|
134 |
-
return empty( $this->m_sWpVersion )? $wp_version : $this->m_sWpVersion;
|
135 |
-
}
|
136 |
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
public function redirectToLogin( $sParams = '' ) {
|
141 |
-
$sParams = empty( $sParams ) ? '' : '?'.$sParams;
|
142 |
-
header( "Location: ".site_url().'/wp-login.php'.$sParams );
|
143 |
-
exit();
|
144 |
-
}
|
145 |
-
/**
|
146 |
-
*/
|
147 |
-
public function redirectToAdmin() {
|
148 |
-
$this->doRedirect( is_multisite()? get_admin_url() : admin_url() );
|
149 |
-
}
|
150 |
-
/**
|
151 |
-
*/
|
152 |
-
public function redirectToHome() {
|
153 |
-
$this->doRedirect( home_url() );
|
154 |
-
}
|
155 |
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
|
|
|
|
|
|
160 |
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
|
|
173 |
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
180 |
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
187 |
}
|
188 |
-
return $this->fIsMultisite;
|
189 |
-
}
|
190 |
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
}
|
199 |
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
return $this->isMultisite() ? update_site_option( $sKey, $sValue ) : update_option( $sKey, $sValue );
|
207 |
-
}
|
208 |
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
public function getOption( $sKey, $mDefault = false ) {
|
215 |
-
return $this->isMultisite() ? get_site_option( $sKey, $mDefault ) : get_option( $sKey, $mDefault );
|
216 |
-
}
|
217 |
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
225 |
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
232 |
}
|
233 |
-
return empty($sCurrentPage)? '' : $sCurrentPage;
|
234 |
-
}
|
235 |
|
236 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
237 |
endif;
|
238 |
|
239 |
-
if ( !class_exists('
|
240 |
|
241 |
-
class
|
242 |
/**
|
243 |
-
* @return
|
244 |
*/
|
245 |
public static function GetInstance() {
|
246 |
if ( is_null( self::$oInstance ) ) {
|
2 |
/**
|
3 |
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
* All rights reserved.
|
5 |
+
*
|
6 |
* Version: 2013-08-14_A
|
7 |
*
|
8 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
17 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
18 |
*/
|
19 |
|
20 |
+
require_once( dirname(__FILE__).'/icwp-data-processor.php' );
|
21 |
+
|
22 |
+
if ( !class_exists('ICWP_WpFunctions_V5') ):
|
23 |
|
24 |
+
class ICWP_WpFunctions_V5 {
|
25 |
|
26 |
+
/**
|
27 |
+
* @var ICWP_WpFunctions_V5
|
28 |
+
*/
|
29 |
+
protected static $oInstance = NULL;
|
30 |
|
31 |
+
/**
|
32 |
+
* @return ICWP_WpFunctions_V5
|
33 |
+
*/
|
34 |
+
public static function GetInstance() {
|
35 |
+
if ( is_null( self::$oInstance ) ) {
|
36 |
+
self::$oInstance = new self();
|
37 |
+
}
|
38 |
+
return self::$oInstance;
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* @var string
|
43 |
+
*/
|
44 |
+
protected $sWpVersion;
|
45 |
+
|
46 |
+
/**
|
47 |
+
* @var boolean
|
48 |
+
*/
|
49 |
+
protected $fIsMultisite;
|
50 |
+
|
51 |
+
public function __construct() {}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* The full plugin file to be upgraded.
|
55 |
+
*
|
56 |
+
* @param string $sPluginFile
|
57 |
+
* @return boolean
|
58 |
+
*/
|
59 |
+
public function doPluginUpgrade( $sPluginFile ) {
|
60 |
+
|
61 |
+
if ( !$this->getIsPluginUpdateAvailable( $sPluginFile )
|
62 |
+
|| ( isset( $GLOBALS['pagenow'] ) && $GLOBALS['pagenow'] == 'update.php' ) ) {
|
63 |
+
return true;
|
64 |
+
}
|
65 |
+
$sUrl = $this->getPluginUpgradeLink( $sPluginFile );
|
66 |
+
wp_redirect( $sUrl );
|
67 |
+
exit();
|
68 |
}
|
|
|
|
|
69 |
|
70 |
+
/**
|
71 |
+
* @param string $sPluginFile
|
72 |
+
* @return boolean|stdClass
|
73 |
+
*/
|
74 |
+
public function getIsPluginUpdateAvailable( $sPluginFile ) {
|
75 |
+
$aUpdates = $this->getWordpressUpdates();
|
76 |
+
if ( empty( $aUpdates ) ) {
|
77 |
+
return false;
|
78 |
+
}
|
79 |
+
if ( isset( $aUpdates[ $sPluginFile ] ) ) {
|
80 |
+
return $aUpdates[ $sPluginFile ];
|
81 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
82 |
return false;
|
83 |
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* @param string $sCompareString
|
87 |
+
* @param string $sKey
|
88 |
+
* @return bool
|
89 |
+
*/
|
90 |
+
public function getIsPluginActive( $sCompareString, $sKey = 'Name' ) {
|
91 |
+
|
92 |
+
$sPluginFile = $this->getIsPluginInstalled( $sCompareString, $sKey );
|
93 |
+
if ( !$sPluginFile ) {
|
94 |
+
return false;
|
95 |
+
}
|
96 |
+
return is_plugin_active( $sPluginFile ) ? $sPluginFile : false;
|
97 |
}
|
|
|
|
|
98 |
|
99 |
+
/**
|
100 |
+
* @param string $sCompareString
|
101 |
+
* @param string $sKey
|
102 |
+
* @return bool|string
|
103 |
+
*/
|
104 |
+
public function getIsPluginInstalled( $sCompareString, $sKey = 'Name' ) {
|
105 |
+
$aPlugins = $this->getPlugins();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
106 |
|
107 |
+
if ( empty( $aPlugins ) || !is_array( $aPlugins ) ) {
|
108 |
+
return false;
|
109 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
110 |
|
111 |
+
foreach( $aPlugins as $sBaseFileName => $aPluginData ) {
|
112 |
+
if ( isset( $aPluginData[$sKey] ) && $sCompareString == $aPluginData[$sKey] ) {
|
113 |
+
return $sBaseFileName;
|
114 |
+
}
|
115 |
+
}
|
116 |
+
return false;
|
117 |
+
}
|
118 |
|
119 |
+
/**
|
120 |
+
* @param string $sPluginFile
|
121 |
+
* @return string
|
122 |
+
*/
|
123 |
+
public function getPluginActivateLink( $sPluginFile ) {
|
124 |
+
$sUrl = self_admin_url( 'plugins.php' ) ;
|
125 |
+
$aQueryArgs = array(
|
126 |
+
'action' => 'activate',
|
127 |
+
'plugin' => urlencode( $sPluginFile ),
|
128 |
+
'_wpnonce' => wp_create_nonce( 'activate-plugin_' . $sPluginFile )
|
129 |
+
);
|
130 |
+
return add_query_arg( $aQueryArgs, $sUrl );
|
131 |
+
}
|
132 |
|
133 |
+
/**
|
134 |
+
* @param string $sPluginFile
|
135 |
+
* @return string
|
136 |
+
*/
|
137 |
+
public function getPluginDeactivateLink( $sPluginFile ) {
|
138 |
+
$sUrl = self_admin_url( 'plugins.php' ) ;
|
139 |
+
$aQueryArgs = array(
|
140 |
+
'action' => 'deactivate',
|
141 |
+
'plugin' => urlencode( $sPluginFile ),
|
142 |
+
'_wpnonce' => wp_create_nonce( 'deactivate-plugin_' . $sPluginFile )
|
143 |
+
);
|
144 |
+
return add_query_arg( $aQueryArgs, $sUrl );
|
145 |
+
}
|
146 |
|
147 |
+
/**
|
148 |
+
* @param string $sPluginFile
|
149 |
+
* @return string
|
150 |
+
*/
|
151 |
+
public function getPluginUpgradeLink( $sPluginFile ) {
|
152 |
+
$sUrl = self_admin_url( 'update.php' ) ;
|
153 |
+
$aQueryArgs = array(
|
154 |
+
'action' => 'upgrade-plugin',
|
155 |
+
'plugin' => urlencode( $sPluginFile ),
|
156 |
+
'_wpnonce' => wp_create_nonce( 'upgrade-plugin_' . $sPluginFile )
|
157 |
+
);
|
158 |
+
return add_query_arg( $aQueryArgs, $sUrl );
|
159 |
}
|
|
|
|
|
160 |
|
161 |
+
/**
|
162 |
+
* @return array
|
163 |
+
*/
|
164 |
+
public function getWordpressUpdates() {
|
165 |
+
$oCurrent = $this->getTransient( 'update_plugins' );
|
166 |
+
return ( is_object( $oCurrent ) && isset( $oCurrent->response ) ) ? $oCurrent->response : array();
|
167 |
+
}
|
|
|
168 |
|
169 |
+
/**
|
170 |
+
* @return array
|
171 |
+
*/
|
172 |
+
public function getPlugins() {
|
173 |
+
return function_exists( 'get_plugins' ) ? get_plugins() : array();
|
174 |
+
}
|
|
|
|
|
175 |
|
176 |
+
/**
|
177 |
+
* @param string $sKey
|
178 |
+
* @return object
|
179 |
+
*/
|
180 |
+
protected function getTransient( $sKey ) {
|
|
|
|
|
|
|
181 |
|
182 |
+
// TODO: Handle multisite
|
183 |
+
|
184 |
+
if ( version_compare( $this->getWordpressVersion(), '2.7.9', '<=' ) ) {
|
185 |
+
return get_option( $sKey );
|
186 |
+
}
|
187 |
+
|
188 |
+
if ( function_exists( 'get_site_transient' ) ) {
|
189 |
+
$mResult = get_site_transient( $sKey );
|
190 |
+
if ( empty( $mResult ) ) {
|
191 |
+
remove_all_filters( 'pre_site_transient_'.$sKey );
|
192 |
+
$mResult = get_site_transient( $sKey );
|
193 |
+
}
|
194 |
+
return $mResult;
|
195 |
+
}
|
196 |
+
|
197 |
+
if ( version_compare( $this->getWordpressVersion(), '2.9.9', '<=' ) ) {
|
198 |
+
return apply_filters( 'transient_'.$sKey, get_option( '_transient_'.$sKey ) );
|
199 |
+
}
|
200 |
|
201 |
+
return apply_filters( 'site_transient_'.$sKey, get_option( '_site_transient_'.$sKey ) );
|
202 |
+
}
|
203 |
+
|
204 |
+
/**
|
205 |
+
* @return string
|
206 |
+
*/
|
207 |
+
public function getWordpressVersion() {
|
208 |
+
global $wp_version;
|
209 |
+
|
210 |
+
if ( empty( $this->sWpVersion ) ) {
|
211 |
+
$sVersionFile = ABSPATH.WPINC.'/version.php';
|
212 |
+
$sVersionContents = file_get_contents( $sVersionFile );
|
213 |
+
|
214 |
+
if ( preg_match( '/wp_version\s=\s\'([^(\'|")]+)\'/i', $sVersionContents, $aMatches ) ) {
|
215 |
+
$this->sWpVersion = $aMatches[1];
|
216 |
+
}
|
217 |
+
}
|
218 |
+
return empty( $this->sWpVersion )? $wp_version : $this->sWpVersion;
|
219 |
+
}
|
220 |
+
|
221 |
+
/**
|
222 |
+
* @param array $aQueryParams
|
223 |
+
*/
|
224 |
+
public function redirectToLogin( $aQueryParams = array() ) {
|
225 |
+
$sLoginUrl = $this->getWpLoginUrl();
|
226 |
+
$this->doRedirect( $sLoginUrl, $aQueryParams );
|
227 |
+
}
|
228 |
+
/**
|
229 |
+
* @param $aQueryParams
|
230 |
+
*/
|
231 |
+
public function redirectToAdmin( $aQueryParams = array() ) {
|
232 |
+
$this->doRedirect( is_multisite()? get_admin_url() : admin_url(), $aQueryParams );
|
233 |
+
}
|
234 |
+
/**
|
235 |
+
* @param $aQueryParams
|
236 |
+
*/
|
237 |
+
public function redirectToHome( $aQueryParams = array() ) {
|
238 |
+
$this->doRedirect( home_url(), $aQueryParams );
|
239 |
+
}
|
240 |
+
|
241 |
+
/**
|
242 |
+
* @param $sUrl
|
243 |
+
* @param $aQueryParams
|
244 |
+
* @uses exit()
|
245 |
+
*/
|
246 |
+
public function doRedirect( $sUrl, $aQueryParams = array() ) {
|
247 |
+
$sUrl = empty( $aQueryParams ) ? $sUrl : add_query_arg( $aQueryParams, $sUrl ) ;
|
248 |
+
wp_safe_redirect( $sUrl );
|
249 |
+
exit();
|
250 |
+
}
|
251 |
+
|
252 |
+
/**
|
253 |
+
* @return string
|
254 |
+
*/
|
255 |
+
public function getCurrentPage() {
|
256 |
+
global $pagenow;
|
257 |
+
return $pagenow;
|
258 |
+
}
|
259 |
+
|
260 |
+
/**
|
261 |
+
* @return string
|
262 |
+
*/
|
263 |
+
public function getUrl_CurrentAdminPage() {
|
264 |
+
|
265 |
+
$sPage = $this->getCurrentPage();
|
266 |
+
$sUrl = self_admin_url( $sPage );
|
267 |
+
|
268 |
+
//special case for plugin admin pages.
|
269 |
+
if ( $sPage == 'admin.php' ) {
|
270 |
+
$sSubPage = $this->loadDataProcessor()->FetchGet( 'page' );
|
271 |
+
if ( !empty( $sSubPage ) ) {
|
272 |
+
$aQueryArgs = array(
|
273 |
+
'page' => $sSubPage,
|
274 |
+
);
|
275 |
+
$sUrl = add_query_arg( $aQueryArgs, $sUrl );
|
276 |
+
}
|
277 |
+
}
|
278 |
+
return $sUrl;
|
279 |
+
}
|
280 |
+
|
281 |
+
/**
|
282 |
+
* @param string
|
283 |
+
* @return string
|
284 |
+
*/
|
285 |
+
public function getIsCurrentPage( $sPage ) {
|
286 |
+
return $sPage == $this->getCurrentPage();
|
287 |
+
}
|
288 |
+
|
289 |
+
/**
|
290 |
+
* @param string
|
291 |
+
* @return string
|
292 |
+
*/
|
293 |
+
public function getIsPage_Updates() {
|
294 |
+
return $this->getIsCurrentPage( 'update.php' );
|
295 |
+
}
|
296 |
+
|
297 |
+
/**
|
298 |
+
* @return bool
|
299 |
+
*/
|
300 |
+
public function getIsLoginRequest() {
|
301 |
+
$oDp = $this->loadDataProcessor();
|
302 |
+
return
|
303 |
+
$oDp->GetIsRequestPost()
|
304 |
+
&& $this->getIsCurrentPage( 'wp-login.php' )
|
305 |
+
&& !is_null( $oDp->FetchPost( 'log' ) )
|
306 |
+
&& !is_null( $oDp->FetchPost( 'pwd' ) );
|
307 |
+
}
|
308 |
+
|
309 |
+
/**
|
310 |
+
* @return bool
|
311 |
+
*/
|
312 |
+
public function getIsXmlrpc() {
|
313 |
+
// XML-RPC Compatibility
|
314 |
+
return ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST );
|
315 |
+
}
|
316 |
+
|
317 |
+
/**
|
318 |
+
* @return string
|
319 |
+
*/
|
320 |
+
public function getSiteName() {
|
321 |
+
return function_exists( 'get_bloginfo' )? get_bloginfo('name') : 'WordPress Site';
|
322 |
+
}
|
323 |
+
/**
|
324 |
+
* @return string
|
325 |
+
*/
|
326 |
+
public function getSiteAdminEmail() {
|
327 |
+
return function_exists( 'get_bloginfo' )? get_bloginfo('admin_email') : '';
|
328 |
+
}
|
329 |
+
|
330 |
+
/**
|
331 |
+
* @return string
|
332 |
+
*/
|
333 |
+
public function getCookieDomain() {
|
334 |
+
return defined( 'COOKIE_DOMAIN' ) ? COOKIE_DOMAIN : false;
|
335 |
+
}
|
336 |
+
|
337 |
+
/**
|
338 |
+
* @return string
|
339 |
+
*/
|
340 |
+
public function getCookiePath() {
|
341 |
+
return defined( 'COOKIEPATH' ) ? COOKIEPATH : '/';
|
342 |
+
}
|
343 |
+
|
344 |
+
/**
|
345 |
+
* @return boolean
|
346 |
+
*/
|
347 |
+
public function getIsAjax() {
|
348 |
+
return defined( 'DOING_AJAX' ) && DOING_AJAX;
|
349 |
+
}
|
350 |
+
|
351 |
+
/**
|
352 |
+
* @return boolean
|
353 |
+
*/
|
354 |
+
public function getIsCron() {
|
355 |
+
return defined( 'DOING_CRON' ) && DOING_CRON;
|
356 |
+
}
|
357 |
+
|
358 |
+
/**
|
359 |
+
* @param int $nId
|
360 |
+
* @return WP_User|null
|
361 |
+
*/
|
362 |
+
public function getUserById( $nId ) {
|
363 |
+
if ( version_compare( $this->getWordpressVersion(), '2.8.0', '<' ) || !function_exists( 'get_user_by' ) ) {
|
364 |
+
return null;
|
365 |
+
}
|
366 |
+
return get_user_by( 'id', $nId );
|
367 |
+
}
|
368 |
+
|
369 |
+
/**
|
370 |
+
* @param array $aLoginUrlParams
|
371 |
+
*/
|
372 |
+
public function forceUserRelogin( $aLoginUrlParams = array() ) {
|
373 |
+
$this->logoutUser();
|
374 |
+
$this->redirectToLogin( $aLoginUrlParams );
|
375 |
+
}
|
376 |
+
|
377 |
+
/**
|
378 |
+
* @param string $sRedirectUrl
|
379 |
+
*/
|
380 |
+
public function logoutUser( $sRedirectUrl = '' ) {
|
381 |
+
empty( $sRedirectUrl ) ? wp_logout() : wp_logout_url( $sRedirectUrl );
|
382 |
+
}
|
383 |
+
|
384 |
+
/**
|
385 |
+
* @return bool
|
386 |
+
*/
|
387 |
+
public function isMultisite() {
|
388 |
+
if ( !isset( $this->fIsMultisite ) ) {
|
389 |
+
$this->fIsMultisite = function_exists( 'is_multisite' ) && is_multisite();
|
390 |
+
}
|
391 |
+
return $this->fIsMultisite;
|
392 |
+
}
|
393 |
+
|
394 |
+
/**
|
395 |
+
* @param string $sKey
|
396 |
+
* @param string $sValue
|
397 |
+
* @return bool
|
398 |
+
*/
|
399 |
+
public function addOption( $sKey, $sValue ) {
|
400 |
+
return $this->isMultisite() ? add_site_option( $sKey, $sValue ) : add_option( $sKey, $sValue );
|
401 |
+
}
|
402 |
+
|
403 |
+
/**
|
404 |
+
* @param string $sKey
|
405 |
+
* @param $sValue
|
406 |
+
* @return boolean
|
407 |
+
*/
|
408 |
+
public function updateOption( $sKey, $sValue ) {
|
409 |
+
return $this->isMultisite() ? update_site_option( $sKey, $sValue ) : update_option( $sKey, $sValue );
|
410 |
+
}
|
411 |
+
|
412 |
+
/**
|
413 |
+
* @param string $sKey
|
414 |
+
* @param mixed $mDefault
|
415 |
+
* @return mixed
|
416 |
+
*/
|
417 |
+
public function getOption( $sKey, $mDefault = false ) {
|
418 |
+
return $this->isMultisite() ? get_site_option( $sKey, $mDefault ) : get_option( $sKey, $mDefault );
|
419 |
+
}
|
420 |
+
|
421 |
+
/**
|
422 |
+
* @param string $sKey
|
423 |
+
* @return mixed
|
424 |
+
*/
|
425 |
+
public function deleteOption( $sKey ) {
|
426 |
+
return $this->isMultisite() ? delete_site_option( $sKey ) : delete_option( $sKey );
|
427 |
+
}
|
428 |
+
|
429 |
+
/**
|
430 |
+
* @return string
|
431 |
+
*/
|
432 |
+
public function getCurrentWpAdminPage() {
|
433 |
+
|
434 |
+
$oDp = $this->loadDataProcessor();
|
435 |
+
$sScript = $oDp->FetchServer( 'SCRIPT_NAME' );
|
436 |
+
if ( empty( $sScript ) ) {
|
437 |
+
$sScript = $oDp->FetchServer( 'PHP_SELF' );
|
438 |
+
}
|
439 |
+
if ( is_admin() && !empty( $sScript ) && basename( $sScript ) == 'admin.php' ) {
|
440 |
+
$sCurrentPage = $oDp->FetchGet( 'page' );
|
441 |
+
}
|
442 |
+
return empty( $sCurrentPage ) ? '' : $sCurrentPage;
|
443 |
+
}
|
444 |
+
|
445 |
+
/**
|
446 |
+
* @return null|WP_User
|
447 |
+
*/
|
448 |
+
public function getCurrentWpUser() {
|
449 |
+
if ( is_user_logged_in() ) {
|
450 |
+
$oUser = wp_get_current_user();
|
451 |
+
if ( is_object( $oUser ) && $oUser instanceof WP_User ) {
|
452 |
+
return $oUser;
|
453 |
+
}
|
454 |
+
}
|
455 |
+
return null;
|
456 |
+
}
|
457 |
+
|
458 |
+
/**
|
459 |
+
* @param $sUsername
|
460 |
+
*/
|
461 |
+
public function setUserLoggedIn( $sUsername ) {
|
462 |
+
$oUser = version_compare( $this->getWordpressVersion(), '2.8.0', '<' )? get_userdatabylogin( $sUsername ) : get_user_by( 'login', $sUsername );
|
463 |
+
|
464 |
+
wp_clear_auth_cookie();
|
465 |
+
wp_set_current_user ( $oUser->ID, $oUser->user_login );
|
466 |
+
wp_set_auth_cookie ( $oUser->ID, true );
|
467 |
+
do_action( 'wp_login', $oUser->user_login, $oUser );
|
468 |
+
}
|
469 |
+
|
470 |
+
/**
|
471 |
+
* @return string
|
472 |
+
*/
|
473 |
+
protected function getWpLoginUrl() {
|
474 |
+
return site_url() . '/wp-login.php';
|
475 |
+
}
|
476 |
+
|
477 |
+
/**
|
478 |
+
* @param string $sKey should be already prefixed
|
479 |
+
* @param string $nId
|
480 |
+
* @return bool|string
|
481 |
+
*/
|
482 |
+
public function getUserMeta( $sKey, $nId = null ) {
|
483 |
+
$nUserId = $nId;
|
484 |
+
if ( empty( $nUserId ) ) {
|
485 |
+
$oCurrentUser = $this->getCurrentWpUser();
|
486 |
+
if ( is_null( $oCurrentUser ) ) {
|
487 |
+
return false;
|
488 |
+
}
|
489 |
+
$nUserId = $oCurrentUser->ID;
|
490 |
+
}
|
491 |
+
|
492 |
+
$sCurrentMetaValue = get_user_meta( $nUserId, $sKey, true );
|
493 |
+
// A guard whereby if we can't ever get a value for this meta, it means we can never set it.
|
494 |
+
if ( empty( $sCurrentMetaValue ) ) {
|
495 |
+
//the value has never been set, or it's been installed for the first time.
|
496 |
+
$this->updateUserMeta( $sKey, 'temp', $nUserId );
|
497 |
+
return '';
|
498 |
+
}
|
499 |
+
return $sCurrentMetaValue;
|
500 |
+
}
|
501 |
+
|
502 |
+
/**
|
503 |
+
* Updates the user meta data for the current (or supplied user ID)
|
504 |
+
*
|
505 |
+
* @param string $sKey
|
506 |
+
* @param mixed $mValue
|
507 |
+
* @param integer $nId -user ID
|
508 |
+
* @return boolean
|
509 |
+
*/
|
510 |
+
public function updateUserMeta( $sKey, $mValue, $nId = null ) {
|
511 |
+
$nUserId = $nId;
|
512 |
+
if ( empty( $nUserId ) ) {
|
513 |
+
$oCurrentUser = $this->getCurrentWpUser();
|
514 |
+
if ( is_null( $oCurrentUser ) ) {
|
515 |
+
return false;
|
516 |
+
}
|
517 |
+
$nUserId = $oCurrentUser->ID;
|
518 |
+
}
|
519 |
+
return update_user_meta( $nUserId, $sKey, $mValue );
|
520 |
}
|
|
|
|
|
521 |
|
522 |
+
/**
|
523 |
+
* @return ICWP_WPSF_DataProcessor
|
524 |
+
*/
|
525 |
+
public function loadDataProcessor() {
|
526 |
+
if ( !class_exists('ICWP_WPSF_DataProcessor') ) {
|
527 |
+
require_once( dirname(__FILE__).'/icwp-data-processor.php' );
|
528 |
+
}
|
529 |
+
return ICWP_WPSF_DataProcessor::GetInstance();
|
530 |
+
}
|
531 |
+
}
|
532 |
endif;
|
533 |
|
534 |
+
if ( !class_exists('ICWP_WPSF_WpFunctions') ):
|
535 |
|
536 |
+
class ICWP_WPSF_WpFunctions extends ICWP_WpFunctions_V5 {
|
537 |
/**
|
538 |
+
* @return ICWP_WPSF_WpFunctions
|
539 |
*/
|
540 |
public static function GetInstance() {
|
541 |
if ( is_null( self::$oInstance ) ) {
|
src/lib/yaml/Spyc.php
ADDED
@@ -0,0 +1,1147 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Spyc -- A Simple PHP YAML Class
|
4 |
+
* @version 0.5.1
|
5 |
+
* @author Vlad Andersen <vlad.andersen@gmail.com>
|
6 |
+
* @author Chris Wanstrath <chris@ozmm.org>
|
7 |
+
* @link https://github.com/mustangostang/spyc/
|
8 |
+
* @copyright Copyright 2005-2006 Chris Wanstrath, 2006-2011 Vlad Andersen
|
9 |
+
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
10 |
+
* @package Spyc
|
11 |
+
*/
|
12 |
+
|
13 |
+
if (!function_exists('spyc_load')) {
|
14 |
+
/**
|
15 |
+
* Parses YAML to array.
|
16 |
+
* @param string $string YAML string.
|
17 |
+
* @return array
|
18 |
+
*/
|
19 |
+
function spyc_load ($string) {
|
20 |
+
return Spyc::YAMLLoadString($string);
|
21 |
+
}
|
22 |
+
}
|
23 |
+
|
24 |
+
if (!function_exists('spyc_load_file')) {
|
25 |
+
/**
|
26 |
+
* Parses YAML to array.
|
27 |
+
* @param string $file Path to YAML file.
|
28 |
+
* @return array
|
29 |
+
*/
|
30 |
+
function spyc_load_file ($file) {
|
31 |
+
return Spyc::YAMLLoad($file);
|
32 |
+
}
|
33 |
+
}
|
34 |
+
|
35 |
+
if (!function_exists('spyc_dump')) {
|
36 |
+
/**
|
37 |
+
* Dumps array to YAML.
|
38 |
+
* @param array $data Array.
|
39 |
+
* @return string
|
40 |
+
*/
|
41 |
+
function spyc_dump ($data) {
|
42 |
+
return Spyc::YAMLDump($data, false, false, true);
|
43 |
+
}
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* The Simple PHP YAML Class.
|
48 |
+
*
|
49 |
+
* This class can be used to read a YAML file and convert its contents
|
50 |
+
* into a PHP array. It currently supports a very limited subsection of
|
51 |
+
* the YAML spec.
|
52 |
+
*
|
53 |
+
* Usage:
|
54 |
+
* <code>
|
55 |
+
* $Spyc = new Spyc;
|
56 |
+
* $array = $Spyc->load($file);
|
57 |
+
* </code>
|
58 |
+
* or:
|
59 |
+
* <code>
|
60 |
+
* $array = Spyc::YAMLLoad($file);
|
61 |
+
* </code>
|
62 |
+
* or:
|
63 |
+
* <code>
|
64 |
+
* $array = spyc_load_file($file);
|
65 |
+
* </code>
|
66 |
+
* @package Spyc
|
67 |
+
*/
|
68 |
+
class Spyc {
|
69 |
+
|
70 |
+
// SETTINGS
|
71 |
+
|
72 |
+
const REMPTY = "\0\0\0\0\0";
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Setting this to true will force YAMLDump to enclose any string value in
|
76 |
+
* quotes. False by default.
|
77 |
+
*
|
78 |
+
* @var bool
|
79 |
+
*/
|
80 |
+
public $setting_dump_force_quotes = false;
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Setting this to true will forse YAMLLoad to use syck_load function when
|
84 |
+
* possible. False by default.
|
85 |
+
* @var bool
|
86 |
+
*/
|
87 |
+
public $setting_use_syck_is_possible = false;
|
88 |
+
|
89 |
+
|
90 |
+
|
91 |
+
/**#@+
|
92 |
+
* @access private
|
93 |
+
* @var mixed
|
94 |
+
*/
|
95 |
+
private $_dumpIndent;
|
96 |
+
private $_dumpWordWrap;
|
97 |
+
private $_containsGroupAnchor = false;
|
98 |
+
private $_containsGroupAlias = false;
|
99 |
+
private $path;
|
100 |
+
private $result;
|
101 |
+
private $LiteralPlaceHolder = '___YAML_Literal_Block___';
|
102 |
+
private $SavedGroups = array();
|
103 |
+
private $indent;
|
104 |
+
/**
|
105 |
+
* Path modifier that should be applied after adding current element.
|
106 |
+
* @var array
|
107 |
+
*/
|
108 |
+
private $delayedPath = array();
|
109 |
+
|
110 |
+
/**#@+
|
111 |
+
* @access public
|
112 |
+
* @var mixed
|
113 |
+
*/
|
114 |
+
public $_nodeId;
|
115 |
+
|
116 |
+
/**
|
117 |
+
* Load a valid YAML string to Spyc.
|
118 |
+
* @param string $input
|
119 |
+
* @return array
|
120 |
+
*/
|
121 |
+
public function load ($input) {
|
122 |
+
return $this->__loadString($input);
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Load a valid YAML file to Spyc.
|
127 |
+
* @param string $file
|
128 |
+
* @return array
|
129 |
+
*/
|
130 |
+
public function loadFile ($file) {
|
131 |
+
return $this->__load($file);
|
132 |
+
}
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Load YAML into a PHP array statically
|
136 |
+
*
|
137 |
+
* The load method, when supplied with a YAML stream (string or file),
|
138 |
+
* will do its best to convert YAML in a file into a PHP array. Pretty
|
139 |
+
* simple.
|
140 |
+
* Usage:
|
141 |
+
* <code>
|
142 |
+
* $array = Spyc::YAMLLoad('lucky.yaml');
|
143 |
+
* print_r($array);
|
144 |
+
* </code>
|
145 |
+
* @access public
|
146 |
+
* @return array
|
147 |
+
* @param string $input Path of YAML file or string containing YAML
|
148 |
+
*/
|
149 |
+
public static function YAMLLoad($input) {
|
150 |
+
$Spyc = new Spyc;
|
151 |
+
return $Spyc->__load($input);
|
152 |
+
}
|
153 |
+
|
154 |
+
/**
|
155 |
+
* Load a string of YAML into a PHP array statically
|
156 |
+
*
|
157 |
+
* The load method, when supplied with a YAML string, will do its best
|
158 |
+
* to convert YAML in a string into a PHP array. Pretty simple.
|
159 |
+
*
|
160 |
+
* Note: use this function if you don't want files from the file system
|
161 |
+
* loaded and processed as YAML. This is of interest to people concerned
|
162 |
+
* about security whose input is from a string.
|
163 |
+
*
|
164 |
+
* Usage:
|
165 |
+
* <code>
|
166 |
+
* $array = Spyc::YAMLLoadString("---\n0: hello world\n");
|
167 |
+
* print_r($array);
|
168 |
+
* </code>
|
169 |
+
* @access public
|
170 |
+
* @return array
|
171 |
+
* @param string $input String containing YAML
|
172 |
+
*/
|
173 |
+
public static function YAMLLoadString($input) {
|
174 |
+
$Spyc = new Spyc;
|
175 |
+
return $Spyc->__loadString($input);
|
176 |
+
}
|
177 |
+
|
178 |
+
/**
|
179 |
+
* Dump YAML from PHP array statically
|
180 |
+
*
|
181 |
+
* The dump method, when supplied with an array, will do its best
|
182 |
+
* to convert the array into friendly YAML. Pretty simple. Feel free to
|
183 |
+
* save the returned string as nothing.yaml and pass it around.
|
184 |
+
*
|
185 |
+
* Oh, and you can decide how big the indent is and what the wordwrap
|
186 |
+
* for folding is. Pretty cool -- just pass in 'false' for either if
|
187 |
+
* you want to use the default.
|
188 |
+
*
|
189 |
+
* Indent's default is 2 spaces, wordwrap's default is 40 characters. And
|
190 |
+
* you can turn off wordwrap by passing in 0.
|
191 |
+
*
|
192 |
+
* @access public
|
193 |
+
* @return string
|
194 |
+
* @param array $array PHP array
|
195 |
+
* @param int $indent Pass in false to use the default, which is 2
|
196 |
+
* @param int $wordwrap Pass in 0 for no wordwrap, false for default (40)
|
197 |
+
* @param int $no_opening_dashes Do not start YAML file with "---\n"
|
198 |
+
*/
|
199 |
+
public static function YAMLDump($array, $indent = false, $wordwrap = false, $no_opening_dashes = false) {
|
200 |
+
$spyc = new Spyc;
|
201 |
+
return $spyc->dump($array, $indent, $wordwrap, $no_opening_dashes);
|
202 |
+
}
|
203 |
+
|
204 |
+
|
205 |
+
/**
|
206 |
+
* Dump PHP array to YAML
|
207 |
+
*
|
208 |
+
* The dump method, when supplied with an array, will do its best
|
209 |
+
* to convert the array into friendly YAML. Pretty simple. Feel free to
|
210 |
+
* save the returned string as tasteful.yaml and pass it around.
|
211 |
+
*
|
212 |
+
* Oh, and you can decide how big the indent is and what the wordwrap
|
213 |
+
* for folding is. Pretty cool -- just pass in 'false' for either if
|
214 |
+
* you want to use the default.
|
215 |
+
*
|
216 |
+
* Indent's default is 2 spaces, wordwrap's default is 40 characters. And
|
217 |
+
* you can turn off wordwrap by passing in 0.
|
218 |
+
*
|
219 |
+
* @access public
|
220 |
+
* @return string
|
221 |
+
* @param array $array PHP array
|
222 |
+
* @param int $indent Pass in false to use the default, which is 2
|
223 |
+
* @param int $wordwrap Pass in 0 for no wordwrap, false for default (40)
|
224 |
+
*/
|
225 |
+
public function dump($array,$indent = false,$wordwrap = false, $no_opening_dashes = false) {
|
226 |
+
// Dumps to some very clean YAML. We'll have to add some more features
|
227 |
+
// and options soon. And better support for folding.
|
228 |
+
|
229 |
+
// New features and options.
|
230 |
+
if ($indent === false or !is_numeric($indent)) {
|
231 |
+
$this->_dumpIndent = 2;
|
232 |
+
} else {
|
233 |
+
$this->_dumpIndent = $indent;
|
234 |
+
}
|
235 |
+
|
236 |
+
if ($wordwrap === false or !is_numeric($wordwrap)) {
|
237 |
+
$this->_dumpWordWrap = 40;
|
238 |
+
} else {
|
239 |
+
$this->_dumpWordWrap = $wordwrap;
|
240 |
+
}
|
241 |
+
|
242 |
+
// New YAML document
|
243 |
+
$string = "";
|
244 |
+
if (!$no_opening_dashes) $string = "---\n";
|
245 |
+
|
246 |
+
// Start at the base of the array and move through it.
|
247 |
+
if ($array) {
|
248 |
+
$array = (array)$array;
|
249 |
+
$previous_key = -1;
|
250 |
+
foreach ($array as $key => $value) {
|
251 |
+
if (!isset($first_key)) $first_key = $key;
|
252 |
+
$string .= $this->_yamlize($key,$value,0,$previous_key, $first_key, $array);
|
253 |
+
$previous_key = $key;
|
254 |
+
}
|
255 |
+
}
|
256 |
+
return $string;
|
257 |
+
}
|
258 |
+
|
259 |
+
/**
|
260 |
+
* Attempts to convert a key / value array item to YAML
|
261 |
+
* @access private
|
262 |
+
* @return string
|
263 |
+
* @param $key The name of the key
|
264 |
+
* @param $value The value of the item
|
265 |
+
* @param $indent The indent of the current node
|
266 |
+
*/
|
267 |
+
private function _yamlize($key,$value,$indent, $previous_key = -1, $first_key = 0, $source_array = null) {
|
268 |
+
if (is_array($value)) {
|
269 |
+
if (empty ($value))
|
270 |
+
return $this->_dumpNode($key, array(), $indent, $previous_key, $first_key, $source_array);
|
271 |
+
// It has children. What to do?
|
272 |
+
// Make it the right kind of item
|
273 |
+
$string = $this->_dumpNode($key, self::REMPTY, $indent, $previous_key, $first_key, $source_array);
|
274 |
+
// Add the indent
|
275 |
+
$indent += $this->_dumpIndent;
|
276 |
+
// Yamlize the array
|
277 |
+
$string .= $this->_yamlizeArray($value,$indent);
|
278 |
+
} elseif (!is_array($value)) {
|
279 |
+
// It doesn't have children. Yip.
|
280 |
+
$string = $this->_dumpNode($key, $value, $indent, $previous_key, $first_key, $source_array);
|
281 |
+
}
|
282 |
+
return $string;
|
283 |
+
}
|
284 |
+
|
285 |
+
/**
|
286 |
+
* Attempts to convert an array to YAML
|
287 |
+
* @access private
|
288 |
+
* @return string
|
289 |
+
* @param $array The array you want to convert
|
290 |
+
* @param $indent The indent of the current level
|
291 |
+
*/
|
292 |
+
private function _yamlizeArray($array,$indent) {
|
293 |
+
if (is_array($array)) {
|
294 |
+
$string = '';
|
295 |
+
$previous_key = -1;
|
296 |
+
foreach ($array as $key => $value) {
|
297 |
+
if (!isset($first_key)) $first_key = $key;
|
298 |
+
$string .= $this->_yamlize($key, $value, $indent, $previous_key, $first_key, $array);
|
299 |
+
$previous_key = $key;
|
300 |
+
}
|
301 |
+
return $string;
|
302 |
+
} else {
|
303 |
+
return false;
|
304 |
+
}
|
305 |
+
}
|
306 |
+
|
307 |
+
/**
|
308 |
+
* Returns YAML from a key and a value
|
309 |
+
* @access private
|
310 |
+
* @return string
|
311 |
+
* @param $key The name of the key
|
312 |
+
* @param $value The value of the item
|
313 |
+
* @param $indent The indent of the current node
|
314 |
+
*/
|
315 |
+
private function _dumpNode($key, $value, $indent, $previous_key = -1, $first_key = 0, $source_array = null) {
|
316 |
+
// do some folding here, for blocks
|
317 |
+
if (is_string ($value) && ((strpos($value,"\n") !== false || strpos($value,": ") !== false || strpos($value,"- ") !== false ||
|
318 |
+
strpos($value,"*") !== false || strpos($value,"#") !== false || strpos($value,"<") !== false || strpos($value,">") !== false || strpos ($value, ' ') !== false ||
|
319 |
+
strpos($value,"[") !== false || strpos($value,"]") !== false || strpos($value,"{") !== false || strpos($value,"}") !== false) || strpos($value,"&") !== false || strpos($value, "'") !== false || strpos($value, "!") === 0 ||
|
320 |
+
substr ($value, -1, 1) == ':')
|
321 |
+
) {
|
322 |
+
$value = $this->_doLiteralBlock($value,$indent);
|
323 |
+
} else {
|
324 |
+
$value = $this->_doFolding($value,$indent);
|
325 |
+
}
|
326 |
+
|
327 |
+
if ($value === array()) $value = '[ ]';
|
328 |
+
if ($value === "") $value = '""';
|
329 |
+
if (self::isTranslationWord($value)) {
|
330 |
+
$value = $this->_doLiteralBlock($value, $indent);
|
331 |
+
}
|
332 |
+
if (trim ($value) != $value)
|
333 |
+
$value = $this->_doLiteralBlock($value,$indent);
|
334 |
+
|
335 |
+
if (is_bool($value)) {
|
336 |
+
$value = $value ? "true" : "false";
|
337 |
+
}
|
338 |
+
|
339 |
+
if ($value === null) $value = 'null';
|
340 |
+
if ($value === "'" . self::REMPTY . "'") $value = null;
|
341 |
+
|
342 |
+
$spaces = str_repeat(' ',$indent);
|
343 |
+
|
344 |
+
//if (is_int($key) && $key - 1 == $previous_key && $first_key===0) {
|
345 |
+
if (is_array ($source_array) && array_keys($source_array) === range(0, count($source_array) - 1)) {
|
346 |
+
// It's a sequence
|
347 |
+
$string = $spaces.'- '.$value."\n";
|
348 |
+
} else {
|
349 |
+
// if ($first_key===0) throw new Exception('Keys are all screwy. The first one was zero, now it\'s "'. $key .'"');
|
350 |
+
// It's mapped
|
351 |
+
if (strpos($key, ":") !== false || strpos($key, "#") !== false) { $key = '"' . $key . '"'; }
|
352 |
+
$string = rtrim ($spaces.$key.': '.$value)."\n";
|
353 |
+
}
|
354 |
+
return $string;
|
355 |
+
}
|
356 |
+
|
357 |
+
/**
|
358 |
+
* Creates a literal block for dumping
|
359 |
+
* @access private
|
360 |
+
* @return string
|
361 |
+
* @param $value
|
362 |
+
* @param $indent int The value of the indent
|
363 |
+
*/
|
364 |
+
private function _doLiteralBlock($value,$indent) {
|
365 |
+
if ($value === "\n") return '\n';
|
366 |
+
if (strpos($value, "\n") === false && strpos($value, "'") === false) {
|
367 |
+
return sprintf ("'%s'", $value);
|
368 |
+
}
|
369 |
+
if (strpos($value, "\n") === false && strpos($value, '"') === false) {
|
370 |
+
return sprintf ('"%s"', $value);
|
371 |
+
}
|
372 |
+
$exploded = explode("\n",$value);
|
373 |
+
$newValue = '|';
|
374 |
+
$indent += $this->_dumpIndent;
|
375 |
+
$spaces = str_repeat(' ',$indent);
|
376 |
+
foreach ($exploded as $line) {
|
377 |
+
$newValue .= "\n" . $spaces . ($line);
|
378 |
+
}
|
379 |
+
return $newValue;
|
380 |
+
}
|
381 |
+
|
382 |
+
/**
|
383 |
+
* Folds a string of text, if necessary
|
384 |
+
* @access private
|
385 |
+
* @return string
|
386 |
+
* @param $value The string you wish to fold
|
387 |
+
*/
|
388 |
+
private function _doFolding($value,$indent) {
|
389 |
+
// Don't do anything if wordwrap is set to 0
|
390 |
+
|
391 |
+
if ($this->_dumpWordWrap !== 0 && is_string ($value) && strlen($value) > $this->_dumpWordWrap) {
|
392 |
+
$indent += $this->_dumpIndent;
|
393 |
+
$indent = str_repeat(' ',$indent);
|
394 |
+
$wrapped = wordwrap($value,$this->_dumpWordWrap,"\n$indent");
|
395 |
+
$value = ">\n".$indent.$wrapped;
|
396 |
+
} else {
|
397 |
+
if ($this->setting_dump_force_quotes && is_string ($value) && $value !== self::REMPTY)
|
398 |
+
$value = '"' . $value . '"';
|
399 |
+
if (is_numeric($value) && is_string($value))
|
400 |
+
$value = '"' . $value . '"';
|
401 |
+
}
|
402 |
+
|
403 |
+
|
404 |
+
return $value;
|
405 |
+
}
|
406 |
+
|
407 |
+
private function isTrueWord($value) {
|
408 |
+
$words = self::getTranslations(array('true', 'on', 'yes', 'y'));
|
409 |
+
return in_array($value, $words, true);
|
410 |
+
}
|
411 |
+
|
412 |
+
private function isFalseWord($value) {
|
413 |
+
$words = self::getTranslations(array('false', 'off', 'no', 'n'));
|
414 |
+
return in_array($value, $words, true);
|
415 |
+
}
|
416 |
+
|
417 |
+
private function isNullWord($value) {
|
418 |
+
$words = self::getTranslations(array('null', '~'));
|
419 |
+
return in_array($value, $words, true);
|
420 |
+
}
|
421 |
+
|
422 |
+
private function isTranslationWord($value) {
|
423 |
+
return (
|
424 |
+
self::isTrueWord($value) ||
|
425 |
+
self::isFalseWord($value) ||
|
426 |
+
self::isNullWord($value)
|
427 |
+
);
|
428 |
+
}
|
429 |
+
|
430 |
+
/**
|
431 |
+
* Coerce a string into a native type
|
432 |
+
* Reference: http://yaml.org/type/bool.html
|
433 |
+
* TODO: Use only words from the YAML spec.
|
434 |
+
* @access private
|
435 |
+
* @param $value The value to coerce
|
436 |
+
*/
|
437 |
+
private function coerceValue(&$value) {
|
438 |
+
if (self::isTrueWord($value)) {
|
439 |
+
$value = true;
|
440 |
+
} else if (self::isFalseWord($value)) {
|
441 |
+
$value = false;
|
442 |
+
} else if (self::isNullWord($value)) {
|
443 |
+
$value = null;
|
444 |
+
}
|
445 |
+
}
|
446 |
+
|
447 |
+
/**
|
448 |
+
* Given a set of words, perform the appropriate translations on them to
|
449 |
+
* match the YAML 1.1 specification for type coercing.
|
450 |
+
* @param $words The words to translate
|
451 |
+
* @access private
|
452 |
+
*/
|
453 |
+
private static function getTranslations(array $words) {
|
454 |
+
$result = array();
|
455 |
+
foreach ($words as $i) {
|
456 |
+
$result = array_merge($result, array(ucfirst($i), strtoupper($i), strtolower($i)));
|
457 |
+
}
|
458 |
+
return $result;
|
459 |
+
}
|
460 |
+
|
461 |
+
// LOADING FUNCTIONS
|
462 |
+
|
463 |
+
private function __load($input) {
|
464 |
+
$Source = $this->loadFromSource($input);
|
465 |
+
return $this->loadWithSource($Source);
|
466 |
+
}
|
467 |
+
|
468 |
+
private function __loadString($input) {
|
469 |
+
$Source = $this->loadFromString($input);
|
470 |
+
return $this->loadWithSource($Source);
|
471 |
+
}
|
472 |
+
|
473 |
+
private function loadWithSource($Source) {
|
474 |
+
if (empty ($Source)) return array();
|
475 |
+
if ($this->setting_use_syck_is_possible && function_exists ('syck_load')) {
|
476 |
+
$array = syck_load (implode ("\n", $Source));
|
477 |
+
return is_array($array) ? $array : array();
|
478 |
+
}
|
479 |
+
|
480 |
+
$this->path = array();
|
481 |
+
$this->result = array();
|
482 |
+
|
483 |
+
$cnt = count($Source);
|
484 |
+
for ($i = 0; $i < $cnt; $i++) {
|
485 |
+
$line = $Source[$i];
|
486 |
+
|
487 |
+
$this->indent = strlen($line) - strlen(ltrim($line));
|
488 |
+
$tempPath = $this->getParentPathByIndent($this->indent);
|
489 |
+
$line = self::stripIndent($line, $this->indent);
|
490 |
+
if (self::isComment($line)) continue;
|
491 |
+
if (self::isEmpty($line)) continue;
|
492 |
+
$this->path = $tempPath;
|
493 |
+
|
494 |
+
$literalBlockStyle = self::startsLiteralBlock($line);
|
495 |
+
if ($literalBlockStyle) {
|
496 |
+
$line = rtrim ($line, $literalBlockStyle . " \n");
|
497 |
+
$literalBlock = '';
|
498 |
+
$line .= ' '.$this->LiteralPlaceHolder;
|
499 |
+
$literal_block_indent = strlen($Source[$i+1]) - strlen(ltrim($Source[$i+1]));
|
500 |
+
while (++$i < $cnt && $this->literalBlockContinues($Source[$i], $this->indent)) {
|
501 |
+
$literalBlock = $this->addLiteralLine($literalBlock, $Source[$i], $literalBlockStyle, $literal_block_indent);
|
502 |
+
}
|
503 |
+
$i--;
|
504 |
+
}
|
505 |
+
|
506 |
+
// Strip out comments
|
507 |
+
if (strpos ($line, '#')) {
|
508 |
+
$line = preg_replace('/\s*#([^"\']+)$/','',$line);
|
509 |
+
}
|
510 |
+
|
511 |
+
while (++$i < $cnt && self::greedilyNeedNextLine($line)) {
|
512 |
+
$line = rtrim ($line, " \n\t\r") . ' ' . ltrim ($Source[$i], " \t");
|
513 |
+
}
|
514 |
+
$i--;
|
515 |
+
|
516 |
+
$lineArray = $this->_parseLine($line);
|
517 |
+
|
518 |
+
if ($literalBlockStyle)
|
519 |
+
$lineArray = $this->revertLiteralPlaceHolder ($lineArray, $literalBlock);
|
520 |
+
|
521 |
+
$this->addArray($lineArray, $this->indent);
|
522 |
+
|
523 |
+
foreach ($this->delayedPath as $indent => $delayedPath)
|
524 |
+
$this->path[$indent] = $delayedPath;
|
525 |
+
|
526 |
+
$this->delayedPath = array();
|
527 |
+
|
528 |
+
}
|
529 |
+
return $this->result;
|
530 |
+
}
|
531 |
+
|
532 |
+
private function loadFromSource ($input) {
|
533 |
+
if (!empty($input) && strpos($input, "\n") === false && file_exists($input))
|
534 |
+
$input = file_get_contents($input);
|
535 |
+
|
536 |
+
return $this->loadFromString($input);
|
537 |
+
}
|
538 |
+
|
539 |
+
private function loadFromString ($input) {
|
540 |
+
$lines = explode("\n",$input);
|
541 |
+
foreach ($lines as $k => $_) {
|
542 |
+
$lines[$k] = rtrim ($_, "\r");
|
543 |
+
}
|
544 |
+
return $lines;
|
545 |
+
}
|
546 |
+
|
547 |
+
/**
|
548 |
+
* Parses YAML code and returns an array for a node
|
549 |
+
* @access private
|
550 |
+
* @return array
|
551 |
+
* @param string $line A line from the YAML file
|
552 |
+
*/
|
553 |
+
private function _parseLine($line) {
|
554 |
+
if (!$line) return array();
|
555 |
+
$line = trim($line);
|
556 |
+
if (!$line) return array();
|
557 |
+
|
558 |
+
$array = array();
|
559 |
+
|
560 |
+
$group = $this->nodeContainsGroup($line);
|
561 |
+
if ($group) {
|
562 |
+
$this->addGroup($line, $group);
|
563 |
+
$line = $this->stripGroup ($line, $group);
|
564 |
+
}
|
565 |
+
|
566 |
+
if ($this->startsMappedSequence($line))
|
567 |
+
return $this->returnMappedSequence($line);
|
568 |
+
|
569 |
+
if ($this->startsMappedValue($line))
|
570 |
+
return $this->returnMappedValue($line);
|
571 |
+
|
572 |
+
if ($this->isArrayElement($line))
|
573 |
+
return $this->returnArrayElement($line);
|
574 |
+
|
575 |
+
if ($this->isPlainArray($line))
|
576 |
+
return $this->returnPlainArray($line);
|
577 |
+
|
578 |
+
|
579 |
+
return $this->returnKeyValuePair($line);
|
580 |
+
|
581 |
+
}
|
582 |
+
|
583 |
+
/**
|
584 |
+
* Finds the type of the passed value, returns the value as the new type.
|
585 |
+
* @access private
|
586 |
+
* @param string $value
|
587 |
+
* @return mixed
|
588 |
+
*/
|
589 |
+
private function _toType($value) {
|
590 |
+
if ($value === '') return "";
|
591 |
+
$first_character = $value[0];
|
592 |
+
$last_character = substr($value, -1, 1);
|
593 |
+
|
594 |
+
$is_quoted = false;
|
595 |
+
do {
|
596 |
+
if (!$value) break;
|
597 |
+
if ($first_character != '"' && $first_character != "'") break;
|
598 |
+
if ($last_character != '"' && $last_character != "'") break;
|
599 |
+
$is_quoted = true;
|
600 |
+
} while (0);
|
601 |
+
|
602 |
+
if ($is_quoted) {
|
603 |
+
$value = str_replace('\n', "\n", $value);
|
604 |
+
return strtr(substr ($value, 1, -1), array ('\\"' => '"', '\'\'' => '\'', '\\\'' => '\''));
|
605 |
+
}
|
606 |
+
|
607 |
+
if (strpos($value, ' #') !== false && !$is_quoted)
|
608 |
+
$value = preg_replace('/\s+#(.+)$/','',$value);
|
609 |
+
|
610 |
+
if ($first_character == '[' && $last_character == ']') {
|
611 |
+
// Take out strings sequences and mappings
|
612 |
+
$innerValue = trim(substr ($value, 1, -1));
|
613 |
+
if ($innerValue === '') return array();
|
614 |
+
$explode = $this->_inlineEscape($innerValue);
|
615 |
+
// Propagate value array
|
616 |
+
$value = array();
|
617 |
+
foreach ($explode as $v) {
|
618 |
+
$value[] = $this->_toType($v);
|
619 |
+
}
|
620 |
+
return $value;
|
621 |
+
}
|
622 |
+
|
623 |
+
if (strpos($value,': ')!==false && $first_character != '{') {
|
624 |
+
$array = explode(': ',$value);
|
625 |
+
$key = trim($array[0]);
|
626 |
+
array_shift($array);
|
627 |
+
$value = trim(implode(': ',$array));
|
628 |
+
$value = $this->_toType($value);
|
629 |
+
return array($key => $value);
|
630 |
+
}
|
631 |
+
|
632 |
+
if ($first_character == '{' && $last_character == '}') {
|
633 |
+
$innerValue = trim(substr ($value, 1, -1));
|
634 |
+
if ($innerValue === '') return array();
|
635 |
+
// Inline Mapping
|
636 |
+
// Take out strings sequences and mappings
|
637 |
+
$explode = $this->_inlineEscape($innerValue);
|
638 |
+
// Propagate value array
|
639 |
+
$array = array();
|
640 |
+
foreach ($explode as $v) {
|
641 |
+
$SubArr = $this->_toType($v);
|
642 |
+
if (empty($SubArr)) continue;
|
643 |
+
if (is_array ($SubArr)) {
|
644 |
+
$array[key($SubArr)] = $SubArr[key($SubArr)]; continue;
|
645 |
+
}
|
646 |
+
$array[] = $SubArr;
|
647 |
+
}
|
648 |
+
return $array;
|
649 |
+
}
|
650 |
+
|
651 |
+
if ($value == 'null' || $value == 'NULL' || $value == 'Null' || $value == '' || $value == '~') {
|
652 |
+
return null;
|
653 |
+
}
|
654 |
+
|
655 |
+
if ( is_numeric($value) && preg_match ('/^(-|)[1-9]+[0-9]*$/', $value) ){
|
656 |
+
$intvalue = (int)$value;
|
657 |
+
if ($intvalue != PHP_INT_MAX)
|
658 |
+
$value = $intvalue;
|
659 |
+
return $value;
|
660 |
+
}
|
661 |
+
|
662 |
+
if (is_numeric($value) && preg_match('/^0[xX][0-9a-fA-F]+$/', $value)) {
|
663 |
+
// Hexadecimal value.
|
664 |
+
return hexdec($value);
|
665 |
+
}
|
666 |
+
|
667 |
+
$this->coerceValue($value);
|
668 |
+
|
669 |
+
if (is_numeric($value)) {
|
670 |
+
if ($value === '0') return 0;
|
671 |
+
if (rtrim ($value, 0) === $value)
|
672 |
+
$value = (float)$value;
|
673 |
+
return $value;
|
674 |
+
}
|
675 |
+
|
676 |
+
return $value;
|
677 |
+
}
|
678 |
+
|
679 |
+
/**
|
680 |
+
* Used in inlines to check for more inlines or quoted strings
|
681 |
+
* @access private
|
682 |
+
* @return array
|
683 |
+
*/
|
684 |
+
private function _inlineEscape($inline) {
|
685 |
+
// There's gotta be a cleaner way to do this...
|
686 |
+
// While pure sequences seem to be nesting just fine,
|
687 |
+
// pure mappings and mappings with sequences inside can't go very
|
688 |
+
// deep. This needs to be fixed.
|
689 |
+
|
690 |
+
$seqs = array();
|
691 |
+
$maps = array();
|
692 |
+
$saved_strings = array();
|
693 |
+
$saved_empties = array();
|
694 |
+
|
695 |
+
// Check for empty strings
|
696 |
+
$regex = '/("")|(\'\')/';
|
697 |
+
if (preg_match_all($regex,$inline,$strings)) {
|
698 |
+
$saved_empties = $strings[0];
|
699 |
+
$inline = preg_replace($regex,'YAMLEmpty',$inline);
|
700 |
+
}
|
701 |
+
unset($regex);
|
702 |
+
|
703 |
+
// Check for strings
|
704 |
+
$regex = '/(?:(")|(?:\'))((?(1)[^"]+|[^\']+))(?(1)"|\')/';
|
705 |
+
if (preg_match_all($regex,$inline,$strings)) {
|
706 |
+
$saved_strings = $strings[0];
|
707 |
+
$inline = preg_replace($regex,'YAMLString',$inline);
|
708 |
+
}
|
709 |
+
unset($regex);
|
710 |
+
|
711 |
+
// echo $inline;
|
712 |
+
|
713 |
+
$i = 0;
|
714 |
+
do {
|
715 |
+
|
716 |
+
// Check for sequences
|
717 |
+
while (preg_match('/\[([^{}\[\]]+)\]/U',$inline,$matchseqs)) {
|
718 |
+
$seqs[] = $matchseqs[0];
|
719 |
+
$inline = preg_replace('/\[([^{}\[\]]+)\]/U', ('YAMLSeq' . (count($seqs) - 1) . 's'), $inline, 1);
|
720 |
+
}
|
721 |
+
|
722 |
+
// Check for mappings
|
723 |
+
while (preg_match('/{([^\[\]{}]+)}/U',$inline,$matchmaps)) {
|
724 |
+
$maps[] = $matchmaps[0];
|
725 |
+
$inline = preg_replace('/{([^\[\]{}]+)}/U', ('YAMLMap' . (count($maps) - 1) . 's'), $inline, 1);
|
726 |
+
}
|
727 |
+
|
728 |
+
if ($i++ >= 10) break;
|
729 |
+
|
730 |
+
} while (strpos ($inline, '[') !== false || strpos ($inline, '{') !== false);
|
731 |
+
|
732 |
+
$explode = explode(',',$inline);
|
733 |
+
$explode = array_map('trim', $explode);
|
734 |
+
$stringi = 0; $i = 0;
|
735 |
+
|
736 |
+
while (1) {
|
737 |
+
|
738 |
+
// Re-add the sequences
|
739 |
+
if (!empty($seqs)) {
|
740 |
+
foreach ($explode as $key => $value) {
|
741 |
+
if (strpos($value,'YAMLSeq') !== false) {
|
742 |
+
foreach ($seqs as $seqk => $seq) {
|
743 |
+
$explode[$key] = str_replace(('YAMLSeq'.$seqk.'s'),$seq,$value);
|
744 |
+
$value = $explode[$key];
|
745 |
+
}
|
746 |
+
}
|
747 |
+
}
|
748 |
+
}
|
749 |
+
|
750 |
+
// Re-add the mappings
|
751 |
+
if (!empty($maps)) {
|
752 |
+
foreach ($explode as $key => $value) {
|
753 |
+
if (strpos($value,'YAMLMap') !== false) {
|
754 |
+
foreach ($maps as $mapk => $map) {
|
755 |
+
$explode[$key] = str_replace(('YAMLMap'.$mapk.'s'), $map, $value);
|
756 |
+
$value = $explode[$key];
|
757 |
+
}
|
758 |
+
}
|
759 |
+
}
|
760 |
+
}
|
761 |
+
|
762 |
+
|
763 |
+
// Re-add the strings
|
764 |
+
if (!empty($saved_strings)) {
|
765 |
+
foreach ($explode as $key => $value) {
|
766 |
+
while (strpos($value,'YAMLString') !== false) {
|
767 |
+
$explode[$key] = preg_replace('/YAMLString/',$saved_strings[$stringi],$value, 1);
|
768 |
+
unset($saved_strings[$stringi]);
|
769 |
+
++$stringi;
|
770 |
+
$value = $explode[$key];
|
771 |
+
}
|
772 |
+
}
|
773 |
+
}
|
774 |
+
|
775 |
+
|
776 |
+
// Re-add the empties
|
777 |
+
if (!empty($saved_empties)) {
|
778 |
+
foreach ($explode as $key => $value) {
|
779 |
+
while (strpos($value,'YAMLEmpty') !== false) {
|
780 |
+
$explode[$key] = preg_replace('/YAMLEmpty/', '', $value, 1);
|
781 |
+
$value = $explode[$key];
|
782 |
+
}
|
783 |
+
}
|
784 |
+
}
|
785 |
+
|
786 |
+
$finished = true;
|
787 |
+
foreach ($explode as $key => $value) {
|
788 |
+
if (strpos($value,'YAMLSeq') !== false) {
|
789 |
+
$finished = false; break;
|
790 |
+
}
|
791 |
+
if (strpos($value,'YAMLMap') !== false) {
|
792 |
+
$finished = false; break;
|
793 |
+
}
|
794 |
+
if (strpos($value,'YAMLString') !== false) {
|
795 |
+
$finished = false; break;
|
796 |
+
}
|
797 |
+
if (strpos($value,'YAMLEmpty') !== false) {
|
798 |
+
$finished = false; break;
|
799 |
+
}
|
800 |
+
}
|
801 |
+
if ($finished) break;
|
802 |
+
|
803 |
+
$i++;
|
804 |
+
if ($i > 10)
|
805 |
+
break; // Prevent infinite loops.
|
806 |
+
}
|
807 |
+
|
808 |
+
|
809 |
+
return $explode;
|
810 |
+
}
|
811 |
+
|
812 |
+
private function literalBlockContinues ($line, $lineIndent) {
|
813 |
+
if (!trim($line)) return true;
|
814 |
+
if (strlen($line) - strlen(ltrim($line)) > $lineIndent) return true;
|
815 |
+
return false;
|
816 |
+
}
|
817 |
+
|
818 |
+
private function referenceContentsByAlias ($alias) {
|
819 |
+
do {
|
820 |
+
if (!isset($this->SavedGroups[$alias])) { echo "Bad group name: $alias."; break; }
|
821 |
+
$groupPath = $this->SavedGroups[$alias];
|
822 |
+
$value = $this->result;
|
823 |
+
foreach ($groupPath as $k) {
|
824 |
+
$value = $value[$k];
|
825 |
+
}
|
826 |
+
} while (false);
|
827 |
+
return $value;
|
828 |
+
}
|
829 |
+
|
830 |
+
private function addArrayInline ($array, $indent) {
|
831 |
+
$CommonGroupPath = $this->path;
|
832 |
+
if (empty ($array)) return false;
|
833 |
+
|
834 |
+
foreach ($array as $k => $_) {
|
835 |
+
$this->addArray(array($k => $_), $indent);
|
836 |
+
$this->path = $CommonGroupPath;
|
837 |
+
}
|
838 |
+
return true;
|
839 |
+
}
|
840 |
+
|
841 |
+
private function addArray ($incoming_data, $incoming_indent) {
|
842 |
+
|
843 |
+
// print_r ($incoming_data);
|
844 |
+
|
845 |
+
if (count ($incoming_data) > 1)
|
846 |
+
return $this->addArrayInline ($incoming_data, $incoming_indent);
|
847 |
+
|
848 |
+
$key = key ($incoming_data);
|
849 |
+
$value = isset($incoming_data[$key]) ? $incoming_data[$key] : null;
|
850 |
+
if ($key === '__!YAMLZero') $key = '0';
|
851 |
+
|
852 |
+
if ($incoming_indent == 0 && !$this->_containsGroupAlias && !$this->_containsGroupAnchor) { // Shortcut for root-level values.
|
853 |
+
if ($key || $key === '' || $key === '0') {
|
854 |
+
$this->result[$key] = $value;
|
855 |
+
} else {
|
856 |
+
$this->result[] = $value; end ($this->result); $key = key ($this->result);
|
857 |
+
}
|
858 |
+
$this->path[$incoming_indent] = $key;
|
859 |
+
return;
|
860 |
+
}
|
861 |
+
|
862 |
+
|
863 |
+
|
864 |
+
$history = array();
|
865 |
+
// Unfolding inner array tree.
|
866 |
+
$history[] = $_arr = $this->result;
|
867 |
+
foreach ($this->path as $k) {
|
868 |
+
$history[] = $_arr = $_arr[$k];
|
869 |
+
}
|
870 |
+
|
871 |
+
if ($this->_containsGroupAlias) {
|
872 |
+
$value = $this->referenceContentsByAlias($this->_containsGroupAlias);
|
873 |
+
$this->_containsGroupAlias = false;
|
874 |
+
}
|
875 |
+
|
876 |
+
|
877 |
+
// Adding string or numeric key to the innermost level or $this->arr.
|
878 |
+
if (is_string($key) && $key == '<<') {
|
879 |
+
if (!is_array ($_arr)) { $_arr = array (); }
|
880 |
+
|
881 |
+
$_arr = array_merge ($_arr, $value);
|
882 |
+
} else if ($key || $key === '' || $key === '0') {
|
883 |
+
if (!is_array ($_arr))
|
884 |
+
$_arr = array ($key=>$value);
|
885 |
+
else
|
886 |
+
$_arr[$key] = $value;
|
887 |
+
} else {
|
888 |
+
if (!is_array ($_arr)) { $_arr = array ($value); $key = 0; }
|
889 |
+
else { $_arr[] = $value; end ($_arr); $key = key ($_arr); }
|
890 |
+
}
|
891 |
+
|
892 |
+
$reverse_path = array_reverse($this->path);
|
893 |
+
$reverse_history = array_reverse ($history);
|
894 |
+
$reverse_history[0] = $_arr;
|
895 |
+
$cnt = count($reverse_history) - 1;
|
896 |
+
for ($i = 0; $i < $cnt; $i++) {
|
897 |
+
$reverse_history[$i+1][$reverse_path[$i]] = $reverse_history[$i];
|
898 |
+
}
|
899 |
+
$this->result = $reverse_history[$cnt];
|
900 |
+
|
901 |
+
$this->path[$incoming_indent] = $key;
|
902 |
+
|
903 |
+
if ($this->_containsGroupAnchor) {
|
904 |
+
$this->SavedGroups[$this->_containsGroupAnchor] = $this->path;
|
905 |
+
if (is_array ($value)) {
|
906 |
+
$k = key ($value);
|
907 |
+
if (!is_int ($k)) {
|
908 |
+
$this->SavedGroups[$this->_containsGroupAnchor][$incoming_indent + 2] = $k;
|
909 |
+
}
|
910 |
+
}
|
911 |
+
$this->_containsGroupAnchor = false;
|
912 |
+
}
|
913 |
+
|
914 |
+
}
|
915 |
+
|
916 |
+
private static function startsLiteralBlock ($line) {
|
917 |
+
$lastChar = substr (trim($line), -1);
|
918 |
+
if ($lastChar != '>' && $lastChar != '|') return false;
|
919 |
+
if ($lastChar == '|') return $lastChar;
|
920 |
+
// HTML tags should not be counted as literal blocks.
|
921 |
+
if (preg_match ('#<.*?>$#', $line)) return false;
|
922 |
+
return $lastChar;
|
923 |
+
}
|
924 |
+
|
925 |
+
private static function greedilyNeedNextLine($line) {
|
926 |
+
$line = trim ($line);
|
927 |
+
if (!strlen($line)) return false;
|
928 |
+
if (substr ($line, -1, 1) == ']') return false;
|
929 |
+
if ($line[0] == '[') return true;
|
930 |
+
if (preg_match ('#^[^:]+?:\s*\[#', $line)) return true;
|
931 |
+
return false;
|
932 |
+
}
|
933 |
+
|
934 |
+
private function addLiteralLine ($literalBlock, $line, $literalBlockStyle, $indent = -1) {
|
935 |
+
$line = self::stripIndent($line, $indent);
|
936 |
+
if ($literalBlockStyle !== '|') {
|
937 |
+
$line = self::stripIndent($line);
|
938 |
+
}
|
939 |
+
$line = rtrim ($line, "\r\n\t ") . "\n";
|
940 |
+
if ($literalBlockStyle == '|') {
|
941 |
+
return $literalBlock . $line;
|
942 |
+
}
|
943 |
+
if (strlen($line) == 0)
|
944 |
+
return rtrim($literalBlock, ' ') . "\n";
|
945 |
+
if ($line == "\n" && $literalBlockStyle == '>') {
|
946 |
+
return rtrim ($literalBlock, " \t") . "\n";
|
947 |
+
}
|
948 |
+
if ($line != "\n")
|
949 |
+
$line = trim ($line, "\r\n ") . " ";
|
950 |
+
return $literalBlock . $line;
|
951 |
+
}
|
952 |
+
|
953 |
+
function revertLiteralPlaceHolder ($lineArray, $literalBlock) {
|
954 |
+
foreach ($lineArray as $k => $_) {
|
955 |
+
if (is_array($_))
|
956 |
+
$lineArray[$k] = $this->revertLiteralPlaceHolder ($_, $literalBlock);
|
957 |
+
else if (substr($_, -1 * strlen ($this->LiteralPlaceHolder)) == $this->LiteralPlaceHolder)
|
958 |
+
$lineArray[$k] = rtrim ($literalBlock, " \r\n");
|
959 |
+
}
|
960 |
+
return $lineArray;
|
961 |
+
}
|
962 |
+
|
963 |
+
private static function stripIndent ($line, $indent = -1) {
|
964 |
+
if ($indent == -1) $indent = strlen($line) - strlen(ltrim($line));
|
965 |
+
return substr ($line, $indent);
|
966 |
+
}
|
967 |
+
|
968 |
+
private function getParentPathByIndent ($indent) {
|
969 |
+
if ($indent == 0) return array();
|
970 |
+
$linePath = $this->path;
|
971 |
+
do {
|
972 |
+
end($linePath); $lastIndentInParentPath = key($linePath);
|
973 |
+
if ($indent <= $lastIndentInParentPath) array_pop ($linePath);
|
974 |
+
} while ($indent <= $lastIndentInParentPath);
|
975 |
+
return $linePath;
|
976 |
+
}
|
977 |
+
|
978 |
+
|
979 |
+
private function clearBiggerPathValues ($indent) {
|
980 |
+
|
981 |
+
|
982 |
+
if ($indent == 0) $this->path = array();
|
983 |
+
if (empty ($this->path)) return true;
|
984 |
+
|
985 |
+
foreach ($this->path as $k => $_) {
|
986 |
+
if ($k > $indent) unset ($this->path[$k]);
|
987 |
+
}
|
988 |
+
|
989 |
+
return true;
|
990 |
+
}
|
991 |
+
|
992 |
+
|
993 |
+
private static function isComment ($line) {
|
994 |
+
if (!$line) return false;
|
995 |
+
if ($line[0] == '#') return true;
|
996 |
+
if (trim($line, " \r\n\t") == '---') return true;
|
997 |
+
return false;
|
998 |
+
}
|
999 |
+
|
1000 |
+
private static function isEmpty ($line) {
|
1001 |
+
return (trim ($line) === '');
|
1002 |
+
}
|
1003 |
+
|
1004 |
+
|
1005 |
+
private function isArrayElement ($line) {
|
1006 |
+
if (!$line || !is_scalar($line)) return false;
|
1007 |
+
if (substr($line, 0, 2) != '- ') return false;
|
1008 |
+
if (strlen ($line) > 3)
|
1009 |
+
if (substr($line,0,3) == '---') return false;
|
1010 |
+
|
1011 |
+
return true;
|
1012 |
+
}
|
1013 |
+
|
1014 |
+
private function isHashElement ($line) {
|
1015 |
+
return strpos($line, ':');
|
1016 |
+
}
|
1017 |
+
|
1018 |
+
private function isLiteral ($line) {
|
1019 |
+
if ($this->isArrayElement($line)) return false;
|
1020 |
+
if ($this->isHashElement($line)) return false;
|
1021 |
+
return true;
|
1022 |
+
}
|
1023 |
+
|
1024 |
+
|
1025 |
+
private static function unquote ($value) {
|
1026 |
+
if (!$value) return $value;
|
1027 |
+
if (!is_string($value)) return $value;
|
1028 |
+
if ($value[0] == '\'') return trim ($value, '\'');
|
1029 |
+
if ($value[0] == '"') return trim ($value, '"');
|
1030 |
+
return $value;
|
1031 |
+
}
|
1032 |
+
|
1033 |
+
private function startsMappedSequence ($line) {
|
1034 |
+
return (substr($line, 0, 2) == '- ' && substr ($line, -1, 1) == ':');
|
1035 |
+
}
|
1036 |
+
|
1037 |
+
private function returnMappedSequence ($line) {
|
1038 |
+
$array = array();
|
1039 |
+
$key = self::unquote(trim(substr($line,1,-1)));
|
1040 |
+
$array[$key] = array();
|
1041 |
+
$this->delayedPath = array(strpos ($line, $key) + $this->indent => $key);
|
1042 |
+
return array($array);
|
1043 |
+
}
|
1044 |
+
|
1045 |
+
private function checkKeysInValue($value) {
|
1046 |
+
if (strchr('[{"\'', $value[0]) === false) {
|
1047 |
+
if (strchr($value, ': ') !== false) {
|
1048 |
+
throw new Exception('Too many keys: '.$value);
|
1049 |
+
}
|
1050 |
+
}
|
1051 |
+
}
|
1052 |
+
|
1053 |
+
private function returnMappedValue ($line) {
|
1054 |
+
$this->checkKeysInValue($line);
|
1055 |
+
$array = array();
|
1056 |
+
$key = self::unquote (trim(substr($line,0,-1)));
|
1057 |
+
$array[$key] = '';
|
1058 |
+
return $array;
|
1059 |
+
}
|
1060 |
+
|
1061 |
+
private function startsMappedValue ($line) {
|
1062 |
+
return (substr ($line, -1, 1) == ':');
|
1063 |
+
}
|
1064 |
+
|
1065 |
+
private function isPlainArray ($line) {
|
1066 |
+
return ($line[0] == '[' && substr ($line, -1, 1) == ']');
|
1067 |
+
}
|
1068 |
+
|
1069 |
+
private function returnPlainArray ($line) {
|
1070 |
+
return $this->_toType($line);
|
1071 |
+
}
|
1072 |
+
|
1073 |
+
private function returnKeyValuePair ($line) {
|
1074 |
+
$array = array();
|
1075 |
+
$key = '';
|
1076 |
+
if (strpos ($line, ': ')) {
|
1077 |
+
// It's a key/value pair most likely
|
1078 |
+
// If the key is in double quotes pull it out
|
1079 |
+
if (($line[0] == '"' || $line[0] == "'") && preg_match('/^(["\'](.*)["\'](\s)*:)/',$line,$matches)) {
|
1080 |
+
$value = trim(str_replace($matches[1],'',$line));
|
1081 |
+
$key = $matches[2];
|
1082 |
+
} else {
|
1083 |
+
// Do some guesswork as to the key and the value
|
1084 |
+
$explode = explode(': ', $line);
|
1085 |
+
$key = trim(array_shift($explode));
|
1086 |
+
$value = trim(implode(': ', $explode));
|
1087 |
+
$this->checkKeysInValue($value);
|
1088 |
+
}
|
1089 |
+
// Set the type of the value. Int, string, etc
|
1090 |
+
$value = $this->_toType($value);
|
1091 |
+
if ($key === '0') $key = '__!YAMLZero';
|
1092 |
+
$array[$key] = $value;
|
1093 |
+
} else {
|
1094 |
+
$array = array ($line);
|
1095 |
+
}
|
1096 |
+
return $array;
|
1097 |
+
|
1098 |
+
}
|
1099 |
+
|
1100 |
+
|
1101 |
+
private function returnArrayElement ($line) {
|
1102 |
+
if (strlen($line) <= 1) return array(array()); // Weird %)
|
1103 |
+
$array = array();
|
1104 |
+
$value = trim(substr($line,1));
|
1105 |
+
$value = $this->_toType($value);
|
1106 |
+
if ($this->isArrayElement($value)) {
|
1107 |
+
$value = $this->returnArrayElement($value);
|
1108 |
+
}
|
1109 |
+
$array[] = $value;
|
1110 |
+
return $array;
|
1111 |
+
}
|
1112 |
+
|
1113 |
+
|
1114 |
+
private function nodeContainsGroup ($line) {
|
1115 |
+
$symbolsForReference = 'A-z0-9_\-';
|
1116 |
+
if (strpos($line, '&') === false && strpos($line, '*') === false) return false; // Please die fast ;-)
|
1117 |
+
if ($line[0] == '&' && preg_match('/^(&['.$symbolsForReference.']+)/', $line, $matches)) return $matches[1];
|
1118 |
+
if ($line[0] == '*' && preg_match('/^(\*['.$symbolsForReference.']+)/', $line, $matches)) return $matches[1];
|
1119 |
+
if (preg_match('/(&['.$symbolsForReference.']+)$/', $line, $matches)) return $matches[1];
|
1120 |
+
if (preg_match('/(\*['.$symbolsForReference.']+$)/', $line, $matches)) return $matches[1];
|
1121 |
+
if (preg_match ('#^\s*<<\s*:\s*(\*[^\s]+).*$#', $line, $matches)) return $matches[1];
|
1122 |
+
return false;
|
1123 |
+
|
1124 |
+
}
|
1125 |
+
|
1126 |
+
private function addGroup ($line, $group) {
|
1127 |
+
if ($group[0] == '&') $this->_containsGroupAnchor = substr ($group, 1);
|
1128 |
+
if ($group[0] == '*') $this->_containsGroupAlias = substr ($group, 1);
|
1129 |
+
//print_r ($this->path);
|
1130 |
+
}
|
1131 |
+
|
1132 |
+
private function stripGroup ($line, $group) {
|
1133 |
+
$line = trim(str_replace($group, '', $line));
|
1134 |
+
return $line;
|
1135 |
+
}
|
1136 |
+
}
|
1137 |
+
|
1138 |
+
// Enable use of Spyc from command line
|
1139 |
+
// The syntax is the following: php Spyc.php spyc.yaml
|
1140 |
+
|
1141 |
+
do {
|
1142 |
+
if (PHP_SAPI != 'cli') break;
|
1143 |
+
if (empty ($_SERVER['argc']) || $_SERVER['argc'] < 2) break;
|
1144 |
+
if (empty ($_SERVER['PHP_SELF']) || FALSE === strpos ($_SERVER['PHP_SELF'], 'Spyc.php') ) break;
|
1145 |
+
$file = $argv[1];
|
1146 |
+
echo json_encode (spyc_load_file ($file));
|
1147 |
+
} while (0);
|
views/icwp-wpsf-access_restricted_index.php
CHANGED
@@ -19,29 +19,28 @@ include_once( 'icwp-wpsf-config_header.php' );
|
|
19 |
}
|
20 |
else {
|
21 |
?>
|
22 |
-
<div class="well">
|
23 |
<h3><?php _wpsf_e( 'What should you enter here?');?></h3>
|
24 |
-
<p><?php _wpsf_e( 'At some point you supplied an Admin Access Key - to manage this plugin, you must supply it here first.')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
</div>
|
26 |
-
<form action="<?php echo $icwp_form_action; ?>" method="post" class="form-horizontal">
|
27 |
-
<input type="hidden" name="icwp_wpsf_requested_page" value="<?php echo $icwp_requested_page; ?>" />
|
28 |
-
<div class="control-group">
|
29 |
-
<label class="control-label" for="icwp_wpsf_admin_access_key_request"><?php _wpsf_e( 'Enter Access Key');?><br></label>
|
30 |
-
<div class="controls">
|
31 |
-
<div class="option_section selected_item active" id="option_section_icwp_wpsf_admin_access_key">
|
32 |
-
<label>
|
33 |
-
<input type="text" name="icwp_wpsf_admin_access_key_request" value="" autocomplete="off" />
|
34 |
-
</label>
|
35 |
-
<p class="help-block"><?php _wpsf_e( 'To manage this plugin you must enter the access key.');?></p>
|
36 |
-
</div>
|
37 |
-
</div><!-- controls -->
|
38 |
-
</div>
|
39 |
-
<div class="form-actions">
|
40 |
-
<?php wp_nonce_field( $icwp_nonce_field ); ?>
|
41 |
-
<input type="hidden" name="icwp_plugin_form_submit" value="Y" />
|
42 |
-
<button type="submit" class="btn btn-primary" name="submit"><?php _wpsf_e( 'Submit Key' ); ?></button>
|
43 |
-
</div>
|
44 |
-
</form>
|
45 |
<?php
|
46 |
}
|
47 |
?>
|
19 |
}
|
20 |
else {
|
21 |
?>
|
22 |
+
<div class="well admin_access_restriction_form">
|
23 |
<h3><?php _wpsf_e( 'What should you enter here?');?></h3>
|
24 |
+
<p><?php _wpsf_e( 'At some point you supplied an Admin Access Key - to manage this plugin, you must supply it here first.');?></p>
|
25 |
+
<form action="<?php echo $icwp_form_action; ?>" method="post" class="form-horizontal">
|
26 |
+
<div class="control-group">
|
27 |
+
<label class="control-label" for="<?php echo $icwp_var_prefix; ?>admin_access_key_request"><?php _wpsf_e( 'Enter Access Key');?><br></label>
|
28 |
+
<div class="controls">
|
29 |
+
<div class="option_section selected_item active" id="option_section_icwp_wpsf_admin_access_key">
|
30 |
+
<label>
|
31 |
+
<input type="text" name="<?php echo $icwp_var_prefix; ?>admin_access_key_request" value="" autocomplete="off" />
|
32 |
+
</label>
|
33 |
+
<p class="help-block"><?php _wpsf_e( 'To manage this plugin you must enter the access key.');?></p>
|
34 |
+
</div>
|
35 |
+
</div><!-- controls -->
|
36 |
+
</div>
|
37 |
+
<div class="form-actions">
|
38 |
+
<?php wp_nonce_field( $icwp_nonce_field ); ?>
|
39 |
+
<input type="hidden" name="<?php echo $icwp_var_prefix; ?>plugin_form_submit" value="Y" />
|
40 |
+
<button type="submit" class="btn btn-primary" name="submit"><?php _wpsf_e( 'Submit Access Key' ); ?></button>
|
41 |
+
</div>
|
42 |
+
</form>
|
43 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
<?php
|
45 |
}
|
46 |
?>
|
views/icwp-wpsf-audit_trail_viewer_index.php
ADDED
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
include_once( 'icwp-wpsf-config_header.php' );
|
3 |
+
|
4 |
+
$aLogTypes = array(
|
5 |
+
0 => _wpsf__('Info'),
|
6 |
+
1 => _wpsf__('Warning'),
|
7 |
+
2 => _wpsf__('Critical')
|
8 |
+
);
|
9 |
+
|
10 |
+
function printAuditTrailTable( $aAuditData ) {
|
11 |
+
if ( empty( $aAuditData ) ) {
|
12 |
+
return;
|
13 |
+
}
|
14 |
+
?>
|
15 |
+
<table class="table table-hover table-striped table-audit_trail">
|
16 |
+
<tr>
|
17 |
+
<th class="cell-time"><?php _wpsf_e('Time'); ?></th>
|
18 |
+
<th class="cell-event"><?php _wpsf_e('Event'); ?></th>
|
19 |
+
<th class="cell-message"><?php _wpsf_e('Message'); ?></th>
|
20 |
+
<th class="cell-username"><?php _wpsf_e('Username'); ?></th>
|
21 |
+
<th class="cell-category"><?php _wpsf_e('Category'); ?></th>
|
22 |
+
</tr>
|
23 |
+
<?php foreach( $aAuditData as $aAuditEntry ) : ?>
|
24 |
+
<tr>
|
25 |
+
<td><?php echo date( 'Y/m/d', $aAuditEntry['created_at'] ).'<br />'.date( 'H:i:s', $aAuditEntry['created_at'] ); ?></td>
|
26 |
+
<td><?php echo $aAuditEntry['event']; ?></td>
|
27 |
+
<td><?php echo $aAuditEntry['message']; ?></td>
|
28 |
+
<td><?php echo $aAuditEntry['wp_username']; ?></td>
|
29 |
+
<td><?php echo $aAuditEntry['category']; ?></td>
|
30 |
+
</tr>
|
31 |
+
<?php endforeach; ?>
|
32 |
+
</table>
|
33 |
+
<?php
|
34 |
+
}
|
35 |
+
?>
|
36 |
+
<div class="row">
|
37 |
+
<div class="<?php echo $icwp_fShowAds? 'span9' : 'span12'; ?>">
|
38 |
+
|
39 |
+
<h4 class="table-title"><?php _wpsf_e( 'Users' ); ?></h4>
|
40 |
+
<?php printAuditTrailTable( $icwp_aAuditDataUsers ); ?>
|
41 |
+
|
42 |
+
<h4 class="table-title"><?php _wpsf_e( 'Plugins' ); ?></h4>
|
43 |
+
<?php printAuditTrailTable( $icwp_aAuditDataPlugins ); ?>
|
44 |
+
|
45 |
+
<h4 class="table-title"><?php _wpsf_e( 'Themes' ); ?></h4>
|
46 |
+
<?php printAuditTrailTable( $icwp_aAuditDataThemes ); ?>
|
47 |
+
|
48 |
+
<h4 class="table-title"><?php _wpsf_e( 'WordPress' ); ?></h4>
|
49 |
+
<?php printAuditTrailTable( $icwp_aAuditDataWordpress ); ?>
|
50 |
+
|
51 |
+
<h4 class="table-title"><?php _wpsf_e( 'Posts' ); ?></h4>
|
52 |
+
<?php printAuditTrailTable( $icwp_aAuditDataPosts ); ?>
|
53 |
+
|
54 |
+
</div><!-- / span9 -->
|
55 |
+
|
56 |
+
<?php if ( $icwp_fShowAds ) : ?>
|
57 |
+
<div class="span3" id="side_widgets">
|
58 |
+
<?php echo getWidgetIframeHtml('side-widgets-wtb'); ?>
|
59 |
+
</div>
|
60 |
+
<?php endif; ?>
|
61 |
+
</div><!-- / row -->
|
62 |
+
|
63 |
+
<div class="row">
|
64 |
+
<div class="span6">
|
65 |
+
</div><!-- / span6 -->
|
66 |
+
<div class="span6">
|
67 |
+
<p></p>
|
68 |
+
</div><!-- / span6 -->
|
69 |
+
</div><!-- / row -->
|
70 |
+
<style>
|
71 |
+
|
72 |
+
h4.table-title {
|
73 |
+
font-size: 20px;
|
74 |
+
margin: 20px 0 10px 5px;
|
75 |
+
}
|
76 |
+
table.table.table-audit_trail {
|
77 |
+
border: 2px solid #777777;
|
78 |
+
margin-bottom: 40px;
|
79 |
+
}
|
80 |
+
th.cell-time {
|
81 |
+
width: 90px;
|
82 |
+
max-width: 90px;
|
83 |
+
}
|
84 |
+
th.cell-username {
|
85 |
+
width: 120px;
|
86 |
+
max-width: 120px;
|
87 |
+
}
|
88 |
+
th.cell-event {
|
89 |
+
width: 150px;
|
90 |
+
max-width: 150px;
|
91 |
+
}
|
92 |
+
th.cell-category {
|
93 |
+
width: 80px;
|
94 |
+
max-width: 80px;
|
95 |
+
}
|
96 |
+
th.cell-message {
|
97 |
+
}
|
98 |
+
th {
|
99 |
+
background-color: white;
|
100 |
+
}
|
101 |
+
|
102 |
+
tr.row-Warning td {
|
103 |
+
background-color: #F2D5AE;
|
104 |
+
}
|
105 |
+
tr.row-Critical td {
|
106 |
+
background-color: #DBAFB0;
|
107 |
+
}
|
108 |
+
tr.row-log-header td {
|
109 |
+
border-top: 2px solid #999 !important;
|
110 |
+
}
|
111 |
+
td.cell-log-type {
|
112 |
+
text-align: right !important;
|
113 |
+
}
|
114 |
+
td .cell-section {
|
115 |
+
display: inline-block;
|
116 |
+
}
|
117 |
+
td .section-ip {
|
118 |
+
width: 68%;
|
119 |
+
}
|
120 |
+
td .section-timestamp {
|
121 |
+
text-align: right;
|
122 |
+
width: 28%;
|
123 |
+
}
|
124 |
+
</style>
|
125 |
+
|
126 |
+
<?php include_once( 'icwp-wpsf-config_footer.php' );
|
views/icwp-wpsf-changlog_summary.php
ADDED
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<h2><?php _wpsf_e( 'Plugin Change Log Summary'); ?></h2>
|
2 |
+
<div class="span6" id="tbs_docs_examples">
|
3 |
+
<div class="well">
|
4 |
+
<h3><?php printf( _wpsf__('Release v%s'), $sLatestVersionBranch ) ; ?></h3>
|
5 |
+
<p><?php printf( _wpsf__('The following summarises the main changes to the plugin in the v%s release'), $sLatestVersionBranch ) ; ?></p>
|
6 |
+
<p><?php printf( _wpsf__('%snew%s refers to the absolute latest release.'), '<span class="label">', '</span>' ) ; ?></p>
|
7 |
+
<?php
|
8 |
+
$aNewLog = array(
|
9 |
+
'ADDED: Options to automatic updates to control where and whether email notifications are sent.',
|
10 |
+
'ADDED: Various fixes and verification of WordPress 3.8 compatibility.',
|
11 |
+
'ADDED: Integration with iControlWP and the automatic updates system.',
|
12 |
+
'ADDED: Better filesystem handling methods.',
|
13 |
+
'ADDED: Better firewall logic for whitelisting rules.',
|
14 |
+
'ADDED: Some new firewall white listing parameters to help with post editing.',
|
15 |
+
'ADDED: Option to run automatic updates upon demand according to your settings',
|
16 |
+
'ADDED: Localization capabilities. All we need now are translators.',
|
17 |
+
'ADDED: Option to mask the WordPress version so the real version is never publicly visible.'
|
18 |
+
);
|
19 |
+
?>
|
20 |
+
<ul>
|
21 |
+
<?php foreach( $aNewLog as $sItem ) : ?>
|
22 |
+
<li><span class="label"><?php _wpsf_e('new'); ?></span> <?php echo $sItem; ?></li>
|
23 |
+
<?php endforeach; ?>
|
24 |
+
</ul>
|
25 |
+
<?php
|
26 |
+
$aLog = array(
|
27 |
+
);
|
28 |
+
?>
|
29 |
+
<ul>
|
30 |
+
<?php foreach( $aLog as $sItem ) : ?>
|
31 |
+
<li><?php echo $sItem; ?></li>
|
32 |
+
<?php endforeach; ?>
|
33 |
+
</ul>
|
34 |
+
</div>
|
35 |
+
<div class="well">
|
36 |
+
<?php
|
37 |
+
$aLog = array(
|
38 |
+
|
39 |
+
'1.9.x' => array(
|
40 |
+
'ADDED: Block deactivation of plugin if admin access restriction is on.',
|
41 |
+
'ADDED: New feature to manage WordPress Automatic Updates.',
|
42 |
+
'FIXED: Several small bugs and streamlined codebase.',
|
43 |
+
),
|
44 |
+
'1.8.x' => array(
|
45 |
+
'ADDED: Admin Access Key Restriction feature.',
|
46 |
+
'ADDED: WordPress Lockdown feature.'
|
47 |
+
),
|
48 |
+
'1.7.x' => array(
|
49 |
+
'ADDED: Support for WPMU sites (only manageable as Super Admin).',
|
50 |
+
'CHANGE: Serious performance optimizations and a few bug fixes.',
|
51 |
+
),
|
52 |
+
'1.6.x' => array(
|
53 |
+
'ADDED: GASP-based, and further enhanced, SPAM comments filtering functionality.',
|
54 |
+
),
|
55 |
+
'1.5.x' => array(
|
56 |
+
'IMPROVED: Whitelisting/Blacklisting operations and options',
|
57 |
+
'NEW Option: Login Protect Dedicated IP Whitelist.',
|
58 |
+
'REMOVED Option: Firewall wp-login.php blocking'
|
59 |
+
),
|
60 |
+
'1.4.x' => array(
|
61 |
+
'NEW Option: Plugin will automatically upgrade itself when an update is detected - ensures plugin always remains current.',
|
62 |
+
'Now displays an admin notice when a plugin upgrade is available with a link to immediately update.',
|
63 |
+
'Plugin collision protection: removes collision with All In One WordPress Security.',
|
64 |
+
'Improved Login Cooldown Feature- works more like email throttling as it now uses an extra filesystem-based level of protection.',
|
65 |
+
"Fix - Login Cooldown Feature didn't take effect in certain circumstances.",
|
66 |
+
'Brand new plugin options system making them more efficient, easier to manage/update, using fewer WordPress database options',
|
67 |
+
'Huge improvements on database calls and efficiency in loading plugin options'
|
68 |
+
),
|
69 |
+
'1.3.x' => array(
|
70 |
+
"New Feature - Email Throttle. It will prevent you getting bombarded by 1000s of emails in case you're hit by a bot.",
|
71 |
+
"Another Firewall die() option. New option will print a message and uses the wp_die() function instead.",
|
72 |
+
"Option to separately log Login Protect features.",
|
73 |
+
"Refactored and improved the logging system.",
|
74 |
+
"Option to by-pass 2-factor authentication in the case sending the verification email fails.",
|
75 |
+
"Login Protect checking now better logs out users immediately with a redirect.",
|
76 |
+
"We now escape the log data being printed - just in case there's any HTML/JS etc in there we don't want.",
|
77 |
+
"Optimized and cleaned a lot of the option caching code to improve reliability and performance (more to come).",
|
78 |
+
),
|
79 |
+
|
80 |
+
'1.2.x' => array(
|
81 |
+
'New Feature - Ability to import settings from WordPress Firewall 2 Plugin.',
|
82 |
+
'New Feature - Login Form GASP-based Anti-Bot Protection.',
|
83 |
+
'New Feature - Login Cooldown Interval.',
|
84 |
+
'Performance optimizations.',
|
85 |
+
'UI Cleanup and code improvements.',
|
86 |
+
'Added new Login Protect feature where you can add 2-Factor Authentication to your WordPress user logins.',
|
87 |
+
'Improved method for processing the IP address lists to be more cross-platform reliable.',
|
88 |
+
'Improved .htaccess rules (thanks MickeyRoush).',
|
89 |
+
'Mailing method now uses WP_MAIL.'
|
90 |
+
),
|
91 |
+
|
92 |
+
'1.1.x' => array(
|
93 |
+
'Option to check Cookies values in firewall testing.',
|
94 |
+
'Ability to whitelist particular pages and their parameters.',
|
95 |
+
'Quite a few improvements made to the reliability of the firewall processing.',
|
96 |
+
'Option to completely ignore logged-in Administrators from the Firewall processing (they wont even trigger logging etc).',
|
97 |
+
'Ability to (un)blacklist and (un)whitelist IP addresses directly from within the log.',
|
98 |
+
'Helpful link to IP WHOIS from within the log.',
|
99 |
+
'Firewall logging now has its own dedicated database table.',
|
100 |
+
'Fix: Block email not showing the IPv4 friendly address.',
|
101 |
+
'You can now specify IP ranges in whitelists and blacklists.',
|
102 |
+
'You can now specify which email address to send the notification emails.',
|
103 |
+
"You can now add a comment to IP addresses in the whitelist/blacklist. To do this, write your IP address then type a SPACE and write whatever you want (don't take a new line').",
|
104 |
+
'You can now set to delete ALL firewall settings when you deactivate the plugin.',
|
105 |
+
'Improved formatting of the firewall log.'
|
106 |
+
)
|
107 |
+
);
|
108 |
+
?>
|
109 |
+
<?php foreach( $aLog as $sVersion => $aItems ) : ?>
|
110 |
+
<h3><?php printf( _wpsf__('Change log for the v%s release'), $sVersion ); ?></h3>
|
111 |
+
<ul>
|
112 |
+
<?php foreach( $aItems as $sItem ) : ?>
|
113 |
+
<li><?php echo $sItem; ?></li>
|
114 |
+
<?php endforeach; ?>
|
115 |
+
</ul>
|
116 |
+
<?php endforeach; ?>
|
117 |
+
</div>
|
118 |
+
</div><!-- / span6 -->
|
views/icwp-wpsf-config-options-table.php
CHANGED
@@ -8,7 +8,7 @@
|
|
8 |
?>
|
9 |
<div class="form-actions">
|
10 |
<input type="hidden" name="<?php echo $icwp_var_prefix; ?>all_options_input" value="<?php echo $icwp_all_options_input; ?>" />
|
11 |
-
<input type="hidden" name="
|
12 |
<button type="submit" class="btn btn-primary btn-large" name="submit"><?php _wpsf_e( 'Save All Settings' ); ?></button>
|
13 |
</div>
|
14 |
</form>
|
8 |
?>
|
9 |
<div class="form-actions">
|
10 |
<input type="hidden" name="<?php echo $icwp_var_prefix; ?>all_options_input" value="<?php echo $icwp_all_options_input; ?>" />
|
11 |
+
<input type="hidden" name="<?php echo $icwp_var_prefix; ?>plugin_form_submit" value="Y" />
|
12 |
<button type="submit" class="btn btn-primary btn-large" name="submit"><?php _wpsf_e( 'Save All Settings' ); ?></button>
|
13 |
</div>
|
14 |
</form>
|
views/icwp-wpsf-config_autoupdates_index.php
CHANGED
@@ -6,7 +6,7 @@ include_once( 'icwp-wpsf-config_header.php' );
|
|
6 |
|
7 |
<form action="<?php echo $icwp_form_action; ?>" method="post" class="form-horizontal">
|
8 |
|
9 |
-
<?php if ( $fAutoupdatesOn ) : ?>
|
10 |
<legend>Run Updates Now</legend>
|
11 |
<div class="control-group">
|
12 |
<label class="control-label">Run Automatic Updates
|
@@ -28,7 +28,7 @@ include_once( 'icwp-wpsf-config_header.php' );
|
|
28 |
?>
|
29 |
<div class="form-actions">
|
30 |
<input type="hidden" name="<?php echo $icwp_var_prefix; ?>all_options_input" value="<?php echo $icwp_all_options_input; ?>" />
|
31 |
-
<input type="hidden" name="
|
32 |
<button type="submit" class="btn btn-primary" name="submit"><?php _wpsf_e( 'Save All Settings' ); ?></button>
|
33 |
</div>
|
34 |
</form>
|
6 |
|
7 |
<form action="<?php echo $icwp_form_action; ?>" method="post" class="form-horizontal">
|
8 |
|
9 |
+
<?php if ( isset ( $fAutoupdatesOn ) && $fAutoupdatesOn ) : ?>
|
10 |
<legend>Run Updates Now</legend>
|
11 |
<div class="control-group">
|
12 |
<label class="control-label">Run Automatic Updates
|
28 |
?>
|
29 |
<div class="form-actions">
|
30 |
<input type="hidden" name="<?php echo $icwp_var_prefix; ?>all_options_input" value="<?php echo $icwp_all_options_input; ?>" />
|
31 |
+
<input type="hidden" name="<?php echo $icwp_var_prefix; ?>plugin_form_submit" value="Y" />
|
32 |
<button type="submit" class="btn btn-primary" name="submit"><?php _wpsf_e( 'Save All Settings' ); ?></button>
|
33 |
</div>
|
34 |
</form>
|
views/icwp-wpsf-config_header.php
CHANGED
@@ -2,13 +2,13 @@
|
|
2 |
include_once( dirname(__FILE__).ICWP_DS.'icwp_options_helper.php' );
|
3 |
include_once( dirname(__FILE__).ICWP_DS.'widgets'.ICWP_DS.'icwp_widgets.php' );
|
4 |
|
5 |
-
$sPluginName = 'WordPress Simple Firewall';
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
|
13 |
$sLatestVersionBranch = '2.x.x';
|
14 |
$sOn = _wpsf__( 'On' );
|
@@ -16,10 +16,10 @@ $sOff = _wpsf__( 'Off' );
|
|
16 |
?>
|
17 |
|
18 |
<div class="wrap">
|
19 |
-
<div class="bootstrap-wpadmin">
|
20 |
<div class="row">
|
21 |
<div class="span12">
|
22 |
-
<?php include_once(
|
23 |
</div>
|
24 |
</div>
|
25 |
<?php echo printOptionsPageHeader( $icwp_sFeatureName );
|
2 |
include_once( dirname(__FILE__).ICWP_DS.'icwp_options_helper.php' );
|
3 |
include_once( dirname(__FILE__).ICWP_DS.'widgets'.ICWP_DS.'icwp_widgets.php' );
|
4 |
|
5 |
+
$sPluginName = _wpsf__( 'WordPress Simple Firewall' );
|
6 |
+
//$fAdminAccessOn = $icwp_aMainOptions['enable_admin_access_restriction'] == 'Y';
|
7 |
+
//$fFirewallOn = $icwp_aMainOptions['enable_firewall'] == 'Y';
|
8 |
+
//$fLoginProtectOn = $icwp_aMainOptions['enable_login_protect'] == 'Y';
|
9 |
+
//$fCommentsFilteringOn = $icwp_aMainOptions['enable_comments_filter'] == 'Y';
|
10 |
+
//$fLockdownOn = $icwp_aMainOptions['enable_lockdown'] == 'Y';
|
11 |
+
//$fAutoupdatesOn = $icwp_aMainOptions['enable_autoupdates'] == 'Y';
|
12 |
|
13 |
$sLatestVersionBranch = '2.x.x';
|
14 |
$sOn = _wpsf__( 'On' );
|
16 |
?>
|
17 |
|
18 |
<div class="wrap">
|
19 |
+
<div class="bootstrap-wpadmin <?php echo isset($icwp_sFeatureSlug) ? $icwp_sFeatureSlug : ''; ?>">
|
20 |
<div class="row">
|
21 |
<div class="span12">
|
22 |
+
<?php include_once( 'icwp-wpsf-state_summary.php' ); ?>
|
23 |
</div>
|
24 |
</div>
|
25 |
<?php echo printOptionsPageHeader( $icwp_sFeatureName );
|
views/icwp-wpsf-config_plugin_index.php
CHANGED
@@ -19,7 +19,7 @@ include_once( 'icwp-wpsf-config_header.php' );
|
|
19 |
?>
|
20 |
<div class="form-actions">
|
21 |
<input type="hidden" name="<?php echo $icwp_var_prefix; ?>all_options_input" value="<?php echo $icwp_all_options_input; ?>" />
|
22 |
-
<input type="hidden" name="
|
23 |
<button type="submit" class="btn btn-primary" name="submit"><?php _wpsf_e( 'Save All Settings' ); ?></button>
|
24 |
</div>
|
25 |
</form>
|
@@ -42,253 +42,10 @@ include_once( 'icwp-wpsf-config_header.php' );
|
|
42 |
</div>
|
43 |
</div><!-- / row -->
|
44 |
<?php endif; ?>
|
45 |
-
|
46 |
-
<div class="row" id="tbs_docs">
|
47 |
-
<h2><?php _wpsf_e( 'Plugin Configuration Summary'); ?></h2>
|
48 |
-
<div class="span6" id="tbs_docs_shortcodes">
|
49 |
-
<div class="well">
|
50 |
-
<h4 style="margin-top:20px;">
|
51 |
-
<?php printf( _wpsf__('Firewall is %s'), $fFirewallOn ? $sOn : $sOff ); ?>
|
52 |
-
[ <a href="admin.php?page=icwp-wpsf-firewall"><?php _wpsf_e('Configure Now'); ?></a> ]</h4>
|
53 |
-
<?php if ( $fFirewallOn ) : ?>
|
54 |
-
<ul>
|
55 |
-
<li><?php printf( _wpsf__('Firewall logging is %s'), ($icwp_aFirewallOptions['enable_firewall_log'] == 'Y') ? $sOn : $sOff ); ?></li>
|
56 |
-
<li><?php _wpsf_e( 'When the firewall blocks a visit, it will:'); ?>
|
57 |
-
<?php
|
58 |
-
if( $icwp_aFirewallOptions['block_response'] == 'redirect_die' ) {
|
59 |
-
_wpsf_e( 'Die' );
|
60 |
-
}
|
61 |
-
else if ( $icwp_aFirewallOptions['block_response'] == 'redirect_die_message' ) {
|
62 |
-
_wpsf_e( 'Die with a message' );
|
63 |
-
}
|
64 |
-
else if ( $icwp_aFirewallOptions['block_response'] == 'redirect_home' ) {
|
65 |
-
_wpsf_e( 'Redirect to home page' );
|
66 |
-
}
|
67 |
-
else if ( $icwp_aFirewallOptions['block_response'] == 'redirect_404' ) {
|
68 |
-
_wpsf_e( 'Redirect to 404 page' );
|
69 |
-
}
|
70 |
-
else {
|
71 |
-
_wpsf_e( 'Unknown' );
|
72 |
-
}
|
73 |
-
?>
|
74 |
-
</li>
|
75 |
-
<?php if ( isset($icwp_aFirewallOptions['ips_whitelist']['ips']) ) : ?>
|
76 |
-
<li>
|
77 |
-
<?php printf( _wpsf__('You have %s whitelisted IP addresses'), count( $icwp_aFirewallOptions['ips_whitelist']['ips'] ) ); ?>
|
78 |
-
<?php foreach( $icwp_aFirewallOptions['ips_whitelist']['ips'] as $sIp ) : ?>
|
79 |
-
<br />
|
80 |
-
<?php printf( _wpsf__('%s labelled as %s'), long2ip($sIp), $icwp_aFirewallOptions['ips_whitelist']['meta'][md5( $sIp )] ); ?>
|
81 |
-
<?php endforeach; ?>
|
82 |
-
</li>
|
83 |
-
<?php endif; ?>
|
84 |
-
|
85 |
-
<?php if ( isset($icwp_aFirewallOptions['ips_blacklist']['ips']) ) : ?>
|
86 |
-
<li>
|
87 |
-
<?php printf( _wpsf__('You have %s blacklisted IP addresses'), count( $icwp_aFirewallOptions['ips_blacklist']['ips'] ) ); ?>
|
88 |
-
<?php foreach( $icwp_aFirewallOptions['ips_blacklist']['ips'] as $sIp ) : ?>
|
89 |
-
<br />
|
90 |
-
<?php printf( _wpsf__('%s labelled as %s'), long2ip($sIp), $icwp_aFirewallOptions['ips_blacklist']['meta'][md5( $sIp )] ); ?>
|
91 |
-
<?php endforeach; ?>
|
92 |
-
</li>
|
93 |
-
<?php endif; ?>
|
94 |
-
|
95 |
-
<li><?php printf( _wpsf__('Firewall blocks Directory Traversals: %s'), ($icwp_aFirewallOptions['block_dir_traversal'] == 'Y')? $sOn : $sOff ); ?></li>
|
96 |
-
<li><?php printf( _wpsf__('Firewall blocks SQL Queries: %s'), ($icwp_aFirewallOptions['block_sql_queries'] == 'Y')? $sOn : $sOff ); ?></li>
|
97 |
-
<li><?php printf( _wpsf__('Firewall blocks WordPress Specific Terms: %s'), ($icwp_aFirewallOptions['block_wordpress_terms'] == 'Y')? $sOn : $sOff ); ?></li>
|
98 |
-
<li><?php printf( _wpsf__('Firewall blocks Field Truncation Attacks: %s'), ($icwp_aFirewallOptions['block_field_truncation'] == 'Y')? $sOn : $sOff ); ?></li>
|
99 |
-
<li><?php printf( _wpsf__('Firewall blocks Directory Traversals: %s'), ($icwp_aFirewallOptions['block_dir_traversal'] == 'Y')? $sOn : $sOff ); ?></li>
|
100 |
-
<li><?php printf( _wpsf__('Firewall blocks Executable File Uploads: %s'), ($icwp_aFirewallOptions['block_exe_file_uploads'] == 'Y')? $sOn : $sOff ); ?></li>
|
101 |
-
<li><?php printf( _wpsf__('Firewall blocks Leading Schemas (HTTPS / HTTP): %s'), ($icwp_aFirewallOptions['block_leading_schema'] == 'Y')? $sOn : $sOff ); ?></li>
|
102 |
-
<li><?php printf( _wpsf__('Firewall Logging is %s'), ($icwp_aFirewallOptions['enable_firewall_log'] == 'Y')? $sOn : $sOff ); ?></li>
|
103 |
-
</ul>
|
104 |
-
<?php endif; ?>
|
105 |
-
<hr/>
|
106 |
-
<h4 style="margin-top:20px;">
|
107 |
-
<?php printf( _wpsf__('Login Protection is %s'), $fLoginProtectOn ? $sOn : $sOff ); ?>
|
108 |
-
[ <a href="admin.php?page=icwp-wpsf-login_protect"><?php _wpsf_e('Configure Now'); ?></a> ]</h4>
|
109 |
-
<?php if ( $fLoginProtectOn ) : ?>
|
110 |
-
<ul>
|
111 |
-
<?php if ( isset($icwp_aLoginProtectOptions['ips_whitelist']['ips']) ) : ?>
|
112 |
-
<li>
|
113 |
-
<?php printf( _wpsf__('You have %s whitelisted IP addresses'), count( $icwp_aLoginProtectOptions['ips_whitelist']['ips'] ) ); ?>
|
114 |
-
<?php foreach( $icwp_aLoginProtectOptions['ips_whitelist']['ips'] as $sIp ) : ?>
|
115 |
-
<br />
|
116 |
-
<?php printf( _wpsf__('%s labelled as %s'), long2ip($sIp), $icwp_aLoginProtectOptions['ips_whitelist']['meta'][md5( $sIp )] ); ?>
|
117 |
-
<?php endforeach; ?>
|
118 |
-
</li>
|
119 |
-
<?php endif; ?>
|
120 |
-
<li><?php printf( _wpsf__('Two Factor Login Authentication: %s'), ($icwp_aLoginProtectOptions['enable_two_factor_auth_by_ip'] == 'Y')? $sOn : $sOff ); ?></li>
|
121 |
-
<li><?php printf( _wpsf__('Two Factor Login By Pass: %s'), ($icwp_aLoginProtectOptions['enable_two_factor_bypass_on_email_fail'] == 'Y')? $sOn : $sOff ); ?></li>
|
122 |
-
<li><?php printf( _wpsf__('Login Cooldown Interval: %s'), ($icwp_aLoginProtectOptions['login_limit_interval'] == '0')? $sOff : sprintf( _wpsf__('%s seconds'), $icwp_aLoginProtectOptions['login_limit_interval'] ) ); ?></li>
|
123 |
-
<li><?php printf( _wpsf__('Login Form GASP Protection: %s'), ($icwp_aLoginProtectOptions['enable_login_gasp_check'] == 'Y')? $sOn : $sOff ); ?></li>
|
124 |
-
<li><?php printf( _wpsf__('Login Protect Logging: %s'), ($icwp_aLoginProtectOptions['enable_login_protect_log'] == 'Y')? $sOn : $sOff ); ?></li>
|
125 |
-
</ul>
|
126 |
-
<?php endif; ?>
|
127 |
-
<hr/>
|
128 |
-
<h4 style="margin-top:20px;">
|
129 |
-
<?php printf( _wpsf__('Comments Filtering is %s'), $fCommentsFilteringOn ? $sOn : $sOff ); ?>
|
130 |
-
[ <a href="admin.php?page=icwp-wpsf-comments_filter"><?php _wpsf_e('Configure Now'); ?></a> ]</h4>
|
131 |
-
<?php if ( $fCommentsFilteringOn ) : ?>
|
132 |
-
<ul>
|
133 |
-
<li><?php printf( _wpsf__('Enchanced GASP Protection: %s'), ($icwp_aCommentsFilterOptions['enable_comments_gasp_protection'] == 'Y')? $sOn : $sOff ); ?></li>
|
134 |
-
<li><?php printf( _wpsf__('Comments Cooldown Interval: %s'), ($icwp_aCommentsFilterOptions['comments_cooldown_interval'] == '0')? $sOff : sprintf( _wpsf__('%s seconds'), $icwp_aCommentsFilterOptions['comments_cooldown_interval'] ) ); ?></li>
|
135 |
-
<li><?php printf( _wpsf__('Comments Token Expire: %s'), ($icwp_aCommentsFilterOptions['comments_token_expire_interval'] == '0')? $sOff : sprintf( _wpsf__('%s seconds'), $icwp_aCommentsFilterOptions['comments_token_expire_interval'] ) ); ?></li>
|
136 |
-
</ul>
|
137 |
-
<?php endif; ?>
|
138 |
-
<hr/>
|
139 |
-
<h4 style="margin-top:20px;">
|
140 |
-
<?php printf( _wpsf__('WordPress Lockdown is %s'), $fLockdownOn ? $sOn : $sOff ); ?>
|
141 |
-
[ <a href="admin.php?page=icwp-wpsf-lockdown"><?php _wpsf_e('Configure Now'); ?></a> ]</h4>
|
142 |
-
<?php if ( $fLockdownOn ) : ?>
|
143 |
-
<ul>
|
144 |
-
<li><?php printf( _wpsf__('Disable File Editing: %s'), ($icwp_aLockdownOptions['disable_file_editing'] == 'Y')? $sOn : $sOff ); ?></li>
|
145 |
-
<li><?php printf( _wpsf__('Mask WordPress Version: %s'), empty($icwp_aLockdownOptions['mask_wordpress_version'])? $sOff : $icwp_aLockdownOptions['mask_wordpress_version'] ); ?></li>
|
146 |
-
</ul>
|
147 |
-
<?php endif; ?>
|
148 |
-
<hr/>
|
149 |
-
<h4 style="margin-top:20px;">
|
150 |
-
<?php printf( _wpsf__('Auto Updates is %s'), $fAutoupdatesOn ? $sOn : $sOff ); ?>
|
151 |
-
[ <a href="admin.php?page=icwp-wpsf-autoupdates"><?php _wpsf_e('Configure Now'); ?></a> ]</h4>
|
152 |
-
<?php if ( $fAutoupdatesOn ) :
|
153 |
-
|
154 |
-
if ( $icwp_aAutoupdatesOptions['autoupdate_core'] == 'core_never' ) {
|
155 |
-
$sAutoCoreUpdateOption = $sOff;
|
156 |
-
}
|
157 |
-
else if ( $icwp_aAutoupdatesOptions['autoupdate_core'] == 'core_minor' ) {
|
158 |
-
$sAutoCoreUpdateOption = _wpsf__('Minor Versions Only');
|
159 |
-
}
|
160 |
-
else {
|
161 |
-
$sAutoCoreUpdateOption = _wpsf__('Major and Minor Versions');
|
162 |
-
}
|
163 |
-
?>
|
164 |
-
<ul>
|
165 |
-
<li><?php printf( _wpsf__('Automatically Update WordPress Simple Firewall Plugin: %s'), ($icwp_aAutoupdatesOptions['autoupdate_plugin_self'] == 'Y')? $sOn : $sOff ); ?></li>
|
166 |
-
<li><?php printf( _wpsf__('Automatically Update WordPress Core: %s'), $sAutoCoreUpdateOption ); ?></li>
|
167 |
-
<li><?php printf( _wpsf__('Automatically Update Plugins: %s'), ($icwp_aAutoupdatesOptions['enable_autoupdate_plugins'] == 'Y')? $sOn : $sOff ); ?></li>
|
168 |
-
<li><?php printf( _wpsf__('Automatically Update Themes: %s'), ($icwp_aAutoupdatesOptions['enable_autoupdate_themes'] == 'Y')? $sOn : $sOff ); ?></li>
|
169 |
-
<li><?php printf( _wpsf__('Automatically Update Translations: %s'), ($icwp_aAutoupdatesOptions['enable_autoupdate_translations'] == 'Y')? $sOn : $sOff ); ?></li>
|
170 |
-
<li><?php printf( _wpsf__('Ignore Version Control Systems: %s'), ($icwp_aAutoupdatesOptions['enable_autoupdate_ignore_vcs'] == 'Y')? $sOn : $sOff ); ?></li>
|
171 |
-
</ul>
|
172 |
-
<?php endif; ?>
|
173 |
-
</div>
|
174 |
-
</div><!-- / span6 -->
|
175 |
-
<div class="span6" id="tbs_docs_examples">
|
176 |
-
<div class="well">
|
177 |
-
<h3><?php printf( _wpsf__('Release v%s'), $sLatestVersionBranch ) ; ?></h3>
|
178 |
-
<p><?php printf( _wpsf__('The following summarises the main changes to the plugin in the v%s release'), $sLatestVersionBranch ) ; ?></p>
|
179 |
-
<p><?php printf( _wpsf__('%snew%s refers to the absolute latest release.'), '<span class="label">', '</span>' ) ; ?></p>
|
180 |
-
<?php
|
181 |
-
$aNewLog = array(
|
182 |
-
'ADDED: Options to automatic updates to control where and whether email notifications are sent.',
|
183 |
-
'ADDED: Various fixes and verification of WordPress 3.8 compatibility.',
|
184 |
-
'ADDED: Integration with iControlWP and the automatic updates system.',
|
185 |
-
'ADDED: Better filesystem handling methods.',
|
186 |
-
'ADDED: Better firewall logic for whitelisting rules.',
|
187 |
-
'ADDED: Some new firewall white listing parameters to help with post editing.',
|
188 |
-
'ADDED: Option to run automatic updates upon demand according to your settings',
|
189 |
-
'ADDED: Localization capabilities. All we need now are translators.',
|
190 |
-
'ADDED: Option to mask the WordPress version so the real version is never publicly visible.'
|
191 |
-
);
|
192 |
-
?>
|
193 |
-
<ul>
|
194 |
-
<?php foreach( $aNewLog as $sItem ) : ?>
|
195 |
-
<li><span class="label"><?php _wpsf_e('new'); ?></span> <?php echo $sItem; ?></li>
|
196 |
-
<?php endforeach; ?>
|
197 |
-
</ul>
|
198 |
-
<?php
|
199 |
-
$aLog = array(
|
200 |
-
);
|
201 |
-
?>
|
202 |
-
<ul>
|
203 |
-
<?php foreach( $aLog as $sItem ) : ?>
|
204 |
-
<li><?php echo $sItem; ?></li>
|
205 |
-
<?php endforeach; ?>
|
206 |
-
</ul>
|
207 |
-
</div>
|
208 |
-
<div class="well">
|
209 |
-
<?php
|
210 |
-
$aLog = array(
|
211 |
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
'FIXED: Several small bugs and streamlined codebase.',
|
216 |
-
),
|
217 |
-
'1.8.x' => array(
|
218 |
-
'ADDED: Admin Access Key Restriction feature.',
|
219 |
-
'ADDED: WordPress Lockdown feature.'
|
220 |
-
),
|
221 |
-
'1.7.x' => array(
|
222 |
-
'ADDED: Support for WPMU sites (only manageable as Super Admin).',
|
223 |
-
'CHANGE: Serious performance optimizations and a few bug fixes.',
|
224 |
-
),
|
225 |
-
'1.6.x' => array(
|
226 |
-
'ADDED: GASP-based, and further enhanced, SPAM comments filtering functionality.',
|
227 |
-
),
|
228 |
-
'1.5.x' => array(
|
229 |
-
'IMPROVED: Whitelisting/Blacklisting operations and options',
|
230 |
-
'NEW Option: Login Protect Dedicated IP Whitelist.',
|
231 |
-
'REMOVED Option: Firewall wp-login.php blocking'
|
232 |
-
),
|
233 |
-
'1.4.x' => array(
|
234 |
-
'NEW Option: Plugin will automatically upgrade itself when an update is detected - ensures plugin always remains current.',
|
235 |
-
'Now displays an admin notice when a plugin upgrade is available with a link to immediately update.',
|
236 |
-
'Plugin collision protection: removes collision with All In One WordPress Security.',
|
237 |
-
'Improved Login Cooldown Feature- works more like email throttling as it now uses an extra filesystem-based level of protection.',
|
238 |
-
"Fix - Login Cooldown Feature didn't take effect in certain circumstances.",
|
239 |
-
'Brand new plugin options system making them more efficient, easier to manage/update, using fewer WordPress database options',
|
240 |
-
'Huge improvements on database calls and efficiency in loading plugin options'
|
241 |
-
),
|
242 |
-
'1.3.x' => array(
|
243 |
-
"New Feature - Email Throttle. It will prevent you getting bombarded by 1000s of emails in case you're hit by a bot.",
|
244 |
-
"Another Firewall die() option. New option will print a message and uses the wp_die() function instead.",
|
245 |
-
"Option to separately log Login Protect features.",
|
246 |
-
"Refactored and improved the logging system.",
|
247 |
-
"Option to by-pass 2-factor authentication in the case sending the verification email fails.",
|
248 |
-
"Login Protect checking now better logs out users immediately with a redirect.",
|
249 |
-
"We now escape the log data being printed - just in case there's any HTML/JS etc in there we don't want.",
|
250 |
-
"Optimized and cleaned a lot of the option caching code to improve reliability and performance (more to come).",
|
251 |
-
),
|
252 |
-
|
253 |
-
'1.2.x' => array(
|
254 |
-
'New Feature - Ability to import settings from WordPress Firewall 2 Plugin.',
|
255 |
-
'New Feature - Login Form GASP-based Anti-Bot Protection.',
|
256 |
-
'New Feature - Login Cooldown Interval.',
|
257 |
-
'Performance optimizations.',
|
258 |
-
'UI Cleanup and code improvements.',
|
259 |
-
'Added new Login Protect feature where you can add 2-Factor Authentication to your WordPress user logins.',
|
260 |
-
'Improved method for processing the IP address lists to be more cross-platform reliable.',
|
261 |
-
'Improved .htaccess rules (thanks MickeyRoush).',
|
262 |
-
'Mailing method now uses WP_MAIL.'
|
263 |
-
),
|
264 |
-
|
265 |
-
'1.1.x' => array(
|
266 |
-
'Option to check Cookies values in firewall testing.',
|
267 |
-
'Ability to whitelist particular pages and their parameters.',
|
268 |
-
'Quite a few improvements made to the reliability of the firewall processing.',
|
269 |
-
'Option to completely ignore logged-in Administrators from the Firewall processing (they wont even trigger logging etc).',
|
270 |
-
'Ability to (un)blacklist and (un)whitelist IP addresses directly from within the log.',
|
271 |
-
'Helpful link to IP WHOIS from within the log.',
|
272 |
-
'Firewall logging now has its own dedicated database table.',
|
273 |
-
'Fix: Block email not showing the IPv4 friendly address.',
|
274 |
-
'You can now specify IP ranges in whitelists and blacklists.',
|
275 |
-
'You can now specify which email address to send the notification emails.',
|
276 |
-
"You can now add a comment to IP addresses in the whitelist/blacklist. To do this, write your IP address then type a SPACE and write whatever you want (don't take a new line').",
|
277 |
-
'You can now set to delete ALL firewall settings when you deactivate the plugin.',
|
278 |
-
'Improved formatting of the firewall log.'
|
279 |
-
)
|
280 |
-
);
|
281 |
-
?>
|
282 |
-
<?php foreach( $aLog as $sVersion => $aItems ) : ?>
|
283 |
-
<h3><?php printf( _wpsf__('Change log for the v%s release'), $sVersion ); ?></h3>
|
284 |
-
<ul>
|
285 |
-
<?php foreach( $aItems as $sItem ) : ?>
|
286 |
-
<li><?php echo $sItem; ?></li>
|
287 |
-
<?php endforeach; ?>
|
288 |
-
</ul>
|
289 |
-
<?php endforeach; ?>
|
290 |
-
</div>
|
291 |
-
</div><!-- / span6 -->
|
292 |
</div><!-- / row -->
|
293 |
|
294 |
<div class="row">
|
19 |
?>
|
20 |
<div class="form-actions">
|
21 |
<input type="hidden" name="<?php echo $icwp_var_prefix; ?>all_options_input" value="<?php echo $icwp_all_options_input; ?>" />
|
22 |
+
<input type="hidden" name="<?php echo $icwp_var_prefix; ?>plugin_form_submit" value="Y" />
|
23 |
<button type="submit" class="btn btn-primary" name="submit"><?php _wpsf_e( 'Save All Settings' ); ?></button>
|
24 |
</div>
|
25 |
</form>
|
42 |
</div>
|
43 |
</div><!-- / row -->
|
44 |
<?php endif; ?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
|
46 |
+
<div class="row" id="tbs_docs">
|
47 |
+
<?php // include_once( 'icwp-wpsf-config_summary.php' ); ?>
|
48 |
+
<?php // include_once( 'icwp-wpsf-changlog_summary.php' ); ?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
</div><!-- / row -->
|
50 |
|
51 |
<div class="row">
|
views/icwp-wpsf-config_summary.php
ADDED
@@ -0,0 +1,128 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<h2><?php _wpsf_e( 'Plugin Configuration Summary'); ?></h2>
|
2 |
+
<div class="span6" id="tbs_docs_shortcodes">
|
3 |
+
<div class="well">
|
4 |
+
<h4 style="margin-top:20px;">
|
5 |
+
<?php printf( _wpsf__('Firewall is %s'), $fFirewallOn ? $sOn : $sOff ); ?>
|
6 |
+
[ <a href="admin.php?page=icwp-wpsf-firewall"><?php _wpsf_e('Configure Now'); ?></a> ]</h4>
|
7 |
+
<?php if ( $fFirewallOn ) : ?>
|
8 |
+
<ul>
|
9 |
+
<li><?php printf( _wpsf__('Firewall logging is %s'), ($icwp_aFirewallOptions['enable_firewall_log'] == 'Y') ? $sOn : $sOff ); ?></li>
|
10 |
+
<li><?php _wpsf_e( 'When the firewall blocks a visit, it will:'); ?>
|
11 |
+
<?php
|
12 |
+
if( $icwp_aFirewallOptions['block_response'] == 'redirect_die' ) {
|
13 |
+
_wpsf_e( 'Die' );
|
14 |
+
}
|
15 |
+
else if ( $icwp_aFirewallOptions['block_response'] == 'redirect_die_message' ) {
|
16 |
+
_wpsf_e( 'Die with a message' );
|
17 |
+
}
|
18 |
+
else if ( $icwp_aFirewallOptions['block_response'] == 'redirect_home' ) {
|
19 |
+
_wpsf_e( 'Redirect to home page' );
|
20 |
+
}
|
21 |
+
else if ( $icwp_aFirewallOptions['block_response'] == 'redirect_404' ) {
|
22 |
+
_wpsf_e( 'Redirect to 404 page' );
|
23 |
+
}
|
24 |
+
else {
|
25 |
+
_wpsf_e( 'Unknown' );
|
26 |
+
}
|
27 |
+
?>
|
28 |
+
</li>
|
29 |
+
<?php if ( isset($icwp_aFirewallOptions['ips_whitelist']['ips']) ) : ?>
|
30 |
+
<li>
|
31 |
+
<?php printf( _wpsf__('You have %s whitelisted IP addresses'), count( $icwp_aFirewallOptions['ips_whitelist']['ips'] ) ); ?>
|
32 |
+
<?php foreach( $icwp_aFirewallOptions['ips_whitelist']['ips'] as $sIp ) : ?>
|
33 |
+
<br />
|
34 |
+
<?php printf( _wpsf__('%s labelled as %s'), long2ip($sIp), $icwp_aFirewallOptions['ips_whitelist']['meta'][md5( $sIp )] ); ?>
|
35 |
+
<?php endforeach; ?>
|
36 |
+
</li>
|
37 |
+
<?php endif; ?>
|
38 |
+
|
39 |
+
<?php if ( isset($icwp_aFirewallOptions['ips_blacklist']['ips']) ) : ?>
|
40 |
+
<li>
|
41 |
+
<?php printf( _wpsf__('You have %s blacklisted IP addresses'), count( $icwp_aFirewallOptions['ips_blacklist']['ips'] ) ); ?>
|
42 |
+
<?php foreach( $icwp_aFirewallOptions['ips_blacklist']['ips'] as $sIp ) : ?>
|
43 |
+
<br />
|
44 |
+
<?php printf( _wpsf__('%s labelled as %s'), long2ip($sIp), $icwp_aFirewallOptions['ips_blacklist']['meta'][md5( $sIp )] ); ?>
|
45 |
+
<?php endforeach; ?>
|
46 |
+
</li>
|
47 |
+
<?php endif; ?>
|
48 |
+
|
49 |
+
<li><?php printf( _wpsf__('Firewall blocks Directory Traversals: %s'), ($icwp_aFirewallOptions['block_dir_traversal'] == 'Y')? $sOn : $sOff ); ?></li>
|
50 |
+
<li><?php printf( _wpsf__('Firewall blocks SQL Queries: %s'), ($icwp_aFirewallOptions['block_sql_queries'] == 'Y')? $sOn : $sOff ); ?></li>
|
51 |
+
<li><?php printf( _wpsf__('Firewall blocks WordPress Specific Terms: %s'), ($icwp_aFirewallOptions['block_wordpress_terms'] == 'Y')? $sOn : $sOff ); ?></li>
|
52 |
+
<li><?php printf( _wpsf__('Firewall blocks Field Truncation Attacks: %s'), ($icwp_aFirewallOptions['block_field_truncation'] == 'Y')? $sOn : $sOff ); ?></li>
|
53 |
+
<li><?php printf( _wpsf__('Firewall blocks Directory Traversals: %s'), ($icwp_aFirewallOptions['block_dir_traversal'] == 'Y')? $sOn : $sOff ); ?></li>
|
54 |
+
<li><?php printf( _wpsf__('Firewall blocks Executable File Uploads: %s'), ($icwp_aFirewallOptions['block_exe_file_uploads'] == 'Y')? $sOn : $sOff ); ?></li>
|
55 |
+
<li><?php printf( _wpsf__('Firewall blocks Leading Schemas (HTTPS / HTTP): %s'), ($icwp_aFirewallOptions['block_leading_schema'] == 'Y')? $sOn : $sOff ); ?></li>
|
56 |
+
<li><?php printf( _wpsf__('Firewall Logging is %s'), ($icwp_aFirewallOptions['enable_firewall_log'] == 'Y')? $sOn : $sOff ); ?></li>
|
57 |
+
</ul>
|
58 |
+
<?php endif; ?>
|
59 |
+
<hr/>
|
60 |
+
<h4 style="margin-top:20px;">
|
61 |
+
<?php printf( _wpsf__('Login Protection is %s'), $fLoginProtectOn ? $sOn : $sOff ); ?>
|
62 |
+
[ <a href="admin.php?page=icwp-wpsf-login_protect"><?php _wpsf_e('Configure Now'); ?></a> ]</h4>
|
63 |
+
<?php if ( $fLoginProtectOn ) : ?>
|
64 |
+
<ul>
|
65 |
+
<?php if ( isset($icwp_aLoginProtectOptions['ips_whitelist']['ips']) ) : ?>
|
66 |
+
<li>
|
67 |
+
<?php printf( _wpsf__('You have %s whitelisted IP addresses'), count( $icwp_aLoginProtectOptions['ips_whitelist']['ips'] ) ); ?>
|
68 |
+
<?php foreach( $icwp_aLoginProtectOptions['ips_whitelist']['ips'] as $sIp ) : ?>
|
69 |
+
<br />
|
70 |
+
<?php printf( _wpsf__('%s labelled as %s'), long2ip($sIp), $icwp_aLoginProtectOptions['ips_whitelist']['meta'][md5( $sIp )] ); ?>
|
71 |
+
<?php endforeach; ?>
|
72 |
+
</li>
|
73 |
+
<?php endif; ?>
|
74 |
+
<li><?php printf( _wpsf__('Two Factor Login Authentication: %s'), ($icwp_aLoginProtectOptions['enable_two_factor_auth_by_ip'] == 'Y')? $sOn : $sOff ); ?></li>
|
75 |
+
<li><?php printf( _wpsf__('Two Factor Login By Pass: %s'), ($icwp_aLoginProtectOptions['enable_two_factor_bypass_on_email_fail'] == 'Y')? $sOn : $sOff ); ?></li>
|
76 |
+
<li><?php printf( _wpsf__('Login Cooldown Interval: %s'), ($icwp_aLoginProtectOptions['login_limit_interval'] == '0')? $sOff : sprintf( _wpsf__('%s seconds'), $icwp_aLoginProtectOptions['login_limit_interval'] ) ); ?></li>
|
77 |
+
<li><?php printf( _wpsf__('Login Form GASP Protection: %s'), ($icwp_aLoginProtectOptions['enable_login_gasp_check'] == 'Y')? $sOn : $sOff ); ?></li>
|
78 |
+
<li><?php printf( _wpsf__('Login Protect Logging: %s'), ($icwp_aLoginProtectOptions['enable_login_protect_log'] == 'Y')? $sOn : $sOff ); ?></li>
|
79 |
+
</ul>
|
80 |
+
<?php endif; ?>
|
81 |
+
<hr/>
|
82 |
+
<h4 style="margin-top:20px;">
|
83 |
+
<?php printf( _wpsf__('Comments Filtering is %s'), $fCommentsFilteringOn ? $sOn : $sOff ); ?>
|
84 |
+
[ <a href="admin.php?page=icwp-wpsf-comments_filter"><?php _wpsf_e('Configure Now'); ?></a> ]</h4>
|
85 |
+
<?php if ( $fCommentsFilteringOn ) : ?>
|
86 |
+
<ul>
|
87 |
+
<li><?php printf( _wpsf__('Enchanced GASP Protection: %s'), ($icwp_aCommentsFilterOptions['enable_comments_gasp_protection'] == 'Y')? $sOn : $sOff ); ?></li>
|
88 |
+
<li><?php printf( _wpsf__('Comments Cooldown Interval: %s'), ($icwp_aCommentsFilterOptions['comments_cooldown_interval'] == '0')? $sOff : sprintf( _wpsf__('%s seconds'), $icwp_aCommentsFilterOptions['comments_cooldown_interval'] ) ); ?></li>
|
89 |
+
<li><?php printf( _wpsf__('Comments Token Expire: %s'), ($icwp_aCommentsFilterOptions['comments_token_expire_interval'] == '0')? $sOff : sprintf( _wpsf__('%s seconds'), $icwp_aCommentsFilterOptions['comments_token_expire_interval'] ) ); ?></li>
|
90 |
+
</ul>
|
91 |
+
<?php endif; ?>
|
92 |
+
<hr/>
|
93 |
+
<h4 style="margin-top:20px;">
|
94 |
+
<?php printf( _wpsf__('WordPress Lockdown is %s'), $fLockdownOn ? $sOn : $sOff ); ?>
|
95 |
+
[ <a href="admin.php?page=icwp-wpsf-lockdown"><?php _wpsf_e('Configure Now'); ?></a> ]</h4>
|
96 |
+
<?php if ( $fLockdownOn ) : ?>
|
97 |
+
<ul>
|
98 |
+
<li><?php printf( _wpsf__('Disable File Editing: %s'), ($icwp_aLockdownOptions['disable_file_editing'] == 'Y')? $sOn : $sOff ); ?></li>
|
99 |
+
<li><?php printf( _wpsf__('Mask WordPress Version: %s'), empty($icwp_aLockdownOptions['mask_wordpress_version'])? $sOff : $icwp_aLockdownOptions['mask_wordpress_version'] ); ?></li>
|
100 |
+
</ul>
|
101 |
+
<?php endif; ?>
|
102 |
+
<hr/>
|
103 |
+
<h4 style="margin-top:20px;">
|
104 |
+
<?php printf( _wpsf__('Auto Updates is %s'), $fAutoupdatesOn ? $sOn : $sOff ); ?>
|
105 |
+
[ <a href="admin.php?page=icwp-wpsf-autoupdates"><?php _wpsf_e('Configure Now'); ?></a> ]</h4>
|
106 |
+
<?php if ( $fAutoupdatesOn ) :
|
107 |
+
|
108 |
+
if ( $icwp_aAutoupdatesOptions['autoupdate_core'] == 'core_never' ) {
|
109 |
+
$sAutoCoreUpdateOption = $sOff;
|
110 |
+
}
|
111 |
+
else if ( $icwp_aAutoupdatesOptions['autoupdate_core'] == 'core_minor' ) {
|
112 |
+
$sAutoCoreUpdateOption = _wpsf__('Minor Versions Only');
|
113 |
+
}
|
114 |
+
else {
|
115 |
+
$sAutoCoreUpdateOption = _wpsf__('Major and Minor Versions');
|
116 |
+
}
|
117 |
+
?>
|
118 |
+
<ul>
|
119 |
+
<li><?php printf( _wpsf__('Automatically Update WordPress Simple Firewall Plugin: %s'), ($icwp_aAutoupdatesOptions['autoupdate_plugin_self'] == 'Y')? $sOn : $sOff ); ?></li>
|
120 |
+
<li><?php printf( _wpsf__('Automatically Update WordPress Core: %s'), $sAutoCoreUpdateOption ); ?></li>
|
121 |
+
<li><?php printf( _wpsf__('Automatically Update Plugins: %s'), ($icwp_aAutoupdatesOptions['enable_autoupdate_plugins'] == 'Y')? $sOn : $sOff ); ?></li>
|
122 |
+
<li><?php printf( _wpsf__('Automatically Update Themes: %s'), ($icwp_aAutoupdatesOptions['enable_autoupdate_themes'] == 'Y')? $sOn : $sOff ); ?></li>
|
123 |
+
<li><?php printf( _wpsf__('Automatically Update Translations: %s'), ($icwp_aAutoupdatesOptions['enable_autoupdate_translations'] == 'Y')? $sOn : $sOff ); ?></li>
|
124 |
+
<li><?php printf( _wpsf__('Ignore Version Control Systems: %s'), ($icwp_aAutoupdatesOptions['enable_autoupdate_ignore_vcs'] == 'Y')? $sOn : $sOff ); ?></li>
|
125 |
+
</ul>
|
126 |
+
<?php endif; ?>
|
127 |
+
</div>
|
128 |
+
</div><!-- / span6 -->
|
views/icwp-wpsf-config_user_management_index.php
CHANGED
@@ -34,7 +34,9 @@ function printSessionTable( $aSessionsData ) {
|
|
34 |
?>
|
35 |
<div class="row">
|
36 |
<div class="span12">
|
37 |
-
<h2><?php _wpsf_e('Current User Sessions')
|
|
|
|
|
38 |
<?php if ( !empty($icwp_aActiveSessions) ) : ?>
|
39 |
<?php printSessionTable($icwp_aActiveSessions); ?>
|
40 |
<?php else : ?>
|
34 |
?>
|
35 |
<div class="row">
|
36 |
<div class="span12">
|
37 |
+
<h2><?php _wpsf_e('Current User Sessions'); ?>
|
38 |
+
<small>(<?php echo sprintf( _wpsf__( 'now: %s' ), date( 'Y/m/d H:i:s', time() ) ) ?>)</small>
|
39 |
+
</h2>
|
40 |
<?php if ( !empty($icwp_aActiveSessions) ) : ?>
|
41 |
<?php printSessionTable($icwp_aActiveSessions); ?>
|
42 |
<?php else : ?>
|
views/{icwp_wpsf_firewall_log_index.php → icwp-wpsf-firewall_log_index.php}
RENAMED
@@ -14,7 +14,7 @@ $aLogTypes = array(
|
|
14 |
wp_nonce_field( $icwp_nonce_field );
|
15 |
?>
|
16 |
<div class="form-actions">
|
17 |
-
<input type="hidden" name="
|
18 |
<button type="submit" class="btn btn-primary" name="clear_log_submit" value="1"><?php _wpsf_e( 'Clear/Fix Log' ); ?></button>
|
19 |
</div>
|
20 |
</form>
|
14 |
wp_nonce_field( $icwp_nonce_field );
|
15 |
?>
|
16 |
<div class="form-actions">
|
17 |
+
<input type="hidden" name="<?php echo $icwp_var_prefix; ?>plugin_form_submit" value="Y" />
|
18 |
<button type="submit" class="btn btn-primary" name="clear_log_submit" value="1"><?php _wpsf_e( 'Clear/Fix Log' ); ?></button>
|
19 |
</div>
|
20 |
</form>
|
views/{icwp_wpsf_privacy_protect_log_index.php → icwp-wpsf-privacy_protect_log_index.php}
RENAMED
@@ -9,7 +9,7 @@ $icwp_fShowAds = false;
|
|
9 |
wp_nonce_field( $icwp_nonce_field );
|
10 |
?>
|
11 |
<div class="form-actions">
|
12 |
-
<input type="hidden" name="
|
13 |
<button type="submit" class="btn btn-primary" name="clear_log_submit"><?php _wpsf_e( 'Clear/Fix Log' ); ?></button>
|
14 |
</div>
|
15 |
</form>
|
9 |
wp_nonce_field( $icwp_nonce_field );
|
10 |
?>
|
11 |
<div class="form-actions">
|
12 |
+
<input type="hidden" name="<?php echo $icwp_var_prefix; ?>plugin_form_submit" value="Y" />
|
13 |
<button type="submit" class="btn btn-primary" name="clear_log_submit"><?php _wpsf_e( 'Clear/Fix Log' ); ?></button>
|
14 |
</div>
|
15 |
</form>
|
views/icwp_options_helper.php
CHANGED
@@ -25,12 +25,14 @@ function printAllPluginOptionsForm( $inaAllPluginOptions, $insVarPrefix = '', $i
|
|
25 |
|
26 |
//Take each Options Section in turn
|
27 |
foreach ( $inaAllPluginOptions as $sOptionSection ) {
|
28 |
-
|
|
|
|
|
29 |
$sRowId = str_replace( ' ', '', $sOptionSection['section_title'] );
|
30 |
//Print the Section Title
|
31 |
echo '
|
32 |
-
<div class="row" id="'.$sRowId.'">
|
33 |
-
<div class="
|
34 |
<fieldset>
|
35 |
<legend>'.$sOptionSection['section_title'].'</legend>
|
36 |
';
|
@@ -69,22 +71,44 @@ function printAllPluginOptionsForm( $inaAllPluginOptions, $insVarPrefix = '', $i
|
|
69 |
|
70 |
}
|
71 |
|
72 |
-
function getPluginOptionSpan( $
|
73 |
|
74 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
if ( $sOptionKey == 'spacer' ) {
|
76 |
$sHtml = '
|
77 |
-
<div class="span'.$
|
78 |
</div>
|
79 |
';
|
80 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
81 |
|
82 |
-
$sHelpLink = !empty($sHelpLink)? '<span>['.$sHelpLink.']</span>' : '';
|
83 |
$sSpanId = 'span_'.$insVarPrefix.$sOptionKey;
|
84 |
$sHtml = '
|
85 |
-
<div class="item_group span'.$
|
86 |
<div class="control-group">
|
87 |
-
<label class="control-label" for="'.$insVarPrefix.$sOptionKey.'">'.$sOptionHumanName
|
88 |
<div class="controls">
|
89 |
<div class="option_section'.( ($sOptionSaved == 'Y')? ' selected_item':'' ).'" id="option_section_'.$insVarPrefix.$sOptionKey.'">
|
90 |
<label>
|
@@ -92,7 +116,7 @@ function getPluginOptionSpan( $inaOption, $iSpanSize, $insVarPrefix = '' ) {
|
|
92 |
$sAdditionalClass = '';
|
93 |
$sHelpSection = '';
|
94 |
|
95 |
-
if ( $
|
96 |
|
97 |
$sChecked = ( $sOptionSaved == 'Y' )? 'checked="checked"' : '';
|
98 |
|
@@ -106,7 +130,7 @@ function getPluginOptionSpan( $inaOption, $iSpanSize, $insVarPrefix = '' ) {
|
|
106 |
'.$sOptionTitle;
|
107 |
|
108 |
}
|
109 |
-
else if ( $
|
110 |
$sTextInput = esc_attr( $sOptionSaved );
|
111 |
$sHtml .= '
|
112 |
<p>'.$sOptionTitle.'</p>
|
@@ -117,7 +141,7 @@ function getPluginOptionSpan( $inaOption, $iSpanSize, $insVarPrefix = '' ) {
|
|
117 |
id="'.$insVarPrefix.$sOptionKey.'"
|
118 |
class="span5" />';
|
119 |
}
|
120 |
-
else if ( $
|
121 |
$sTextInput = esc_attr( $sOptionSaved );
|
122 |
$sHtml .= '
|
123 |
<p>'.$sOptionTitle.'</p>
|
@@ -128,7 +152,7 @@ function getPluginOptionSpan( $inaOption, $iSpanSize, $insVarPrefix = '' ) {
|
|
128 |
id="'.$insVarPrefix.$sOptionKey.'"
|
129 |
class="span5" />';
|
130 |
}
|
131 |
-
else if ( $
|
132 |
$sTextInput = esc_attr( $sOptionSaved );
|
133 |
$sHtml .= '
|
134 |
<p>'.$sOptionTitle.'</p>
|
@@ -140,60 +164,44 @@ function getPluginOptionSpan( $inaOption, $iSpanSize, $insVarPrefix = '' ) {
|
|
140 |
class="span5" />';
|
141 |
|
142 |
}
|
143 |
-
else if (
|
144 |
|
145 |
-
|
146 |
-
$sInputType = $mOptionType['type'];
|
147 |
-
unset( $mOptionType['type'] );
|
148 |
-
}
|
149 |
-
else {
|
150 |
-
$sInputType = array_shift($mOptionType);
|
151 |
-
}
|
152 |
-
|
153 |
-
if ( $sInputType == 'select' ) {
|
154 |
-
|
155 |
-
$sFragment = '<p>'.$sOptionTitle.'</p>
|
156 |
<select
|
157 |
id="'.$insVarPrefix.$sOptionKey.'"
|
158 |
name="'.$insVarPrefix.$sOptionKey.'">';
|
159 |
|
160 |
-
|
161 |
-
|
162 |
-
list( $mOptionValue, $sOptionName ) = $aInput;
|
163 |
-
$fSelected = $sOptionSaved == $mOptionValue;
|
164 |
|
165 |
-
|
|
|
166 |
<option
|
167 |
value="'.$mOptionValue.'"
|
168 |
id="'.$insVarPrefix.$sOptionKey.'_'.$mOptionValue.'"'
|
169 |
-
|
170 |
-
}
|
171 |
-
$sFragment .= '</select>';
|
172 |
-
|
173 |
}
|
174 |
-
|
|
|
|
|
|
|
175 |
|
176 |
-
|
177 |
<select
|
178 |
id="'.$insVarPrefix.$sOptionKey.'"
|
179 |
-
name="'.$insVarPrefix.$sOptionKey.'[]" multiple multiple="multiple" size="'.count($
|
180 |
-
|
181 |
-
foreach( $mOptionType as $mOptionValue => $sOptionName ) {
|
182 |
|
183 |
-
|
184 |
|
185 |
-
|
186 |
-
|
187 |
value="'.$mOptionValue.'"
|
188 |
id="'.$insVarPrefix.$sOptionKey.'_'.$mOptionValue.'"'
|
189 |
-
|
190 |
-
}
|
191 |
-
$sFragment .= '</select>';
|
192 |
}
|
193 |
-
|
194 |
$sHtml .= $sFragment;
|
195 |
}
|
196 |
-
else if ( $
|
197 |
$sTextInput = esc_attr( $sOptionSaved );
|
198 |
$nRows = substr_count( $sTextInput, "\n" ) + 1;
|
199 |
$sHtml .= '
|
@@ -208,7 +216,7 @@ function getPluginOptionSpan( $inaOption, $iSpanSize, $insVarPrefix = '' ) {
|
|
208 |
$sOptionHelpText = '<p class="help-block">'.$sOptionHelpText.'</p>';
|
209 |
|
210 |
}
|
211 |
-
else if ( $
|
212 |
$sTextInput = esc_attr( $sOptionSaved );
|
213 |
$nRows = substr_count( $sTextInput, "\n" ) + 1;
|
214 |
$sHtml .= '
|
@@ -223,7 +231,7 @@ function getPluginOptionSpan( $inaOption, $iSpanSize, $insVarPrefix = '' ) {
|
|
223 |
$sOptionHelpText = '<p class="help-block">'.$sOptionHelpText.'</p>';
|
224 |
|
225 |
}
|
226 |
-
else if ( $
|
227 |
$sTextInput = esc_attr( $sOptionSaved );
|
228 |
$nRows = substr_count( $sTextInput, "\n" ) + 1;
|
229 |
$sHtml .= '
|
@@ -235,7 +243,7 @@ function getPluginOptionSpan( $inaOption, $iSpanSize, $insVarPrefix = '' ) {
|
|
235 |
rows="'.$nRows.'"
|
236 |
class="span5">'.$sTextInput.'</textarea>';
|
237 |
}
|
238 |
-
else if ( $
|
239 |
$sTextInput = esc_attr( $sOptionSaved );
|
240 |
$sHtml .= '
|
241 |
<p>'.$sOptionTitle.'</p>
|
25 |
|
26 |
//Take each Options Section in turn
|
27 |
foreach ( $inaAllPluginOptions as $sOptionSection ) {
|
28 |
+
|
29 |
+
$fIsPrimarySection = isset( $sOptionSection['section_primary'] ) && $sOptionSection['section_primary'];
|
30 |
+
|
31 |
$sRowId = str_replace( ' ', '', $sOptionSection['section_title'] );
|
32 |
//Print the Section Title
|
33 |
echo '
|
34 |
+
<div class="row option_section_row '.( $fIsPrimarySection? 'primary_section' : 'non_primary_section' ).'" id="'.$sRowId.'">
|
35 |
+
<div class="span'.( $fIsPrimarySection? '9' : '9' ).'">
|
36 |
<fieldset>
|
37 |
<legend>'.$sOptionSection['section_title'].'</legend>
|
38 |
';
|
71 |
|
72 |
}
|
73 |
|
74 |
+
function getPluginOptionSpan( $aOption, $nSpanSize, $insVarPrefix = '' ) {
|
75 |
|
76 |
+
$sOptionKey = $aOption['key'];
|
77 |
+
$sOptionSaved = $aOption['value'];
|
78 |
+
$sOptionDefault = $aOption['default'];
|
79 |
+
$sOptionType = $aOption['type'];
|
80 |
+
$aPossibleOptions = $aOption['value_options'];
|
81 |
+
$sHelpLink = $aOption['info_link'];
|
82 |
+
$sBlogLink = $aOption['blog_link'];
|
83 |
+
$sOptionHumanName = $aOption['name'];
|
84 |
+
$sOptionTitle = $aOption['summary'];
|
85 |
+
$sOptionHelpText = $aOption['description'];
|
86 |
+
|
87 |
if ( $sOptionKey == 'spacer' ) {
|
88 |
$sHtml = '
|
89 |
+
<div class="span'.$nSpanSize.'">
|
90 |
</div>
|
91 |
';
|
92 |
+
}
|
93 |
+
else {
|
94 |
+
|
95 |
+
$sLink = '';
|
96 |
+
$sLinkTemplate = '<br /><span>[%s]</span>';
|
97 |
+
if ( !empty($sHelpLink) ) {
|
98 |
+
$sLink = sprintf( $sLinkTemplate, '<a href="'.$sHelpLink.'" target="_blank">'._wpsf__('More Info').'</a>%s' );
|
99 |
+
if ( !empty( $sBlogLink ) ) {
|
100 |
+
$sLink = sprintf( $sLink, ' | <a href="'.$sBlogLink.'" target="_blank">'._wpsf__('Blog').'</a>' );
|
101 |
+
}
|
102 |
+
else {
|
103 |
+
$sLink = sprintf( $sLink, '' );
|
104 |
+
}
|
105 |
+
}
|
106 |
|
|
|
107 |
$sSpanId = 'span_'.$insVarPrefix.$sOptionKey;
|
108 |
$sHtml = '
|
109 |
+
<div class="item_group span'.$nSpanSize.' '.( ($sOptionSaved === 'Y' || $sOptionSaved != $sOptionDefault )? ' selected_item_group':'' ).'" id="'.$sSpanId.'">
|
110 |
<div class="control-group">
|
111 |
+
<label class="control-label" for="'.$insVarPrefix.$sOptionKey.'">'.$sOptionHumanName.$sLink.'</label>
|
112 |
<div class="controls">
|
113 |
<div class="option_section'.( ($sOptionSaved == 'Y')? ' selected_item':'' ).'" id="option_section_'.$insVarPrefix.$sOptionKey.'">
|
114 |
<label>
|
116 |
$sAdditionalClass = '';
|
117 |
$sHelpSection = '';
|
118 |
|
119 |
+
if ( $sOptionType === 'checkbox' ) {
|
120 |
|
121 |
$sChecked = ( $sOptionSaved == 'Y' )? 'checked="checked"' : '';
|
122 |
|
130 |
'.$sOptionTitle;
|
131 |
|
132 |
}
|
133 |
+
else if ( $sOptionType === 'text' ) {
|
134 |
$sTextInput = esc_attr( $sOptionSaved );
|
135 |
$sHtml .= '
|
136 |
<p>'.$sOptionTitle.'</p>
|
141 |
id="'.$insVarPrefix.$sOptionKey.'"
|
142 |
class="span5" />';
|
143 |
}
|
144 |
+
else if ( $sOptionType === 'password' ) {
|
145 |
$sTextInput = esc_attr( $sOptionSaved );
|
146 |
$sHtml .= '
|
147 |
<p>'.$sOptionTitle.'</p>
|
152 |
id="'.$insVarPrefix.$sOptionKey.'"
|
153 |
class="span5" />';
|
154 |
}
|
155 |
+
else if ( $sOptionType === 'email' ) {
|
156 |
$sTextInput = esc_attr( $sOptionSaved );
|
157 |
$sHtml .= '
|
158 |
<p>'.$sOptionTitle.'</p>
|
164 |
class="span5" />';
|
165 |
|
166 |
}
|
167 |
+
else if ( $sOptionType === 'select' ) {
|
168 |
|
169 |
+
$sFragment = '<p>'.$sOptionTitle.'</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
170 |
<select
|
171 |
id="'.$insVarPrefix.$sOptionKey.'"
|
172 |
name="'.$insVarPrefix.$sOptionKey.'">';
|
173 |
|
174 |
+
foreach( $aPossibleOptions as $mOptionValue => $sOptionName ) {
|
|
|
|
|
|
|
175 |
|
176 |
+
$fSelected = $sOptionSaved == $mOptionValue;
|
177 |
+
$sFragment .= '
|
178 |
<option
|
179 |
value="'.$mOptionValue.'"
|
180 |
id="'.$insVarPrefix.$sOptionKey.'_'.$mOptionValue.'"'
|
181 |
+
.( $fSelected? ' selected="selected"' : '') .'>'. $sOptionName.'</option>';
|
|
|
|
|
|
|
182 |
}
|
183 |
+
$sFragment .= '</select>';
|
184 |
+
$sHtml .= $sFragment;
|
185 |
+
}
|
186 |
+
else if ( $sOptionType === 'multiple_select' ) {
|
187 |
|
188 |
+
$sFragment = '<p>'.$sOptionTitle.'</p>
|
189 |
<select
|
190 |
id="'.$insVarPrefix.$sOptionKey.'"
|
191 |
+
name="'.$insVarPrefix.$sOptionKey.'[]" multiple multiple="multiple" size="'.count( $aPossibleOptions ).'">';
|
|
|
|
|
192 |
|
193 |
+
foreach( $aPossibleOptions as $mOptionValue => $sOptionName ) {
|
194 |
|
195 |
+
$fSelected = in_array( $mOptionValue, $sOptionSaved );
|
196 |
+
$sFragment .= '<option
|
197 |
value="'.$mOptionValue.'"
|
198 |
id="'.$insVarPrefix.$sOptionKey.'_'.$mOptionValue.'"'
|
199 |
+
.( $fSelected? ' selected="selected"' : '') .'>'. $sOptionName.'</option>';
|
|
|
|
|
200 |
}
|
201 |
+
$sFragment .= '</select>';
|
202 |
$sHtml .= $sFragment;
|
203 |
}
|
204 |
+
else if ( $sOptionType === 'ip_addresses' ) {
|
205 |
$sTextInput = esc_attr( $sOptionSaved );
|
206 |
$nRows = substr_count( $sTextInput, "\n" ) + 1;
|
207 |
$sHtml .= '
|
216 |
$sOptionHelpText = '<p class="help-block">'.$sOptionHelpText.'</p>';
|
217 |
|
218 |
}
|
219 |
+
else if ( $sOptionType === 'yubikey_unique_keys' ) {
|
220 |
$sTextInput = esc_attr( $sOptionSaved );
|
221 |
$nRows = substr_count( $sTextInput, "\n" ) + 1;
|
222 |
$sHtml .= '
|
231 |
$sOptionHelpText = '<p class="help-block">'.$sOptionHelpText.'</p>';
|
232 |
|
233 |
}
|
234 |
+
else if ( $sOptionType === 'comma_separated_lists' ) {
|
235 |
$sTextInput = esc_attr( $sOptionSaved );
|
236 |
$nRows = substr_count( $sTextInput, "\n" ) + 1;
|
237 |
$sHtml .= '
|
243 |
rows="'.$nRows.'"
|
244 |
class="span5">'.$sTextInput.'</textarea>';
|
245 |
}
|
246 |
+
else if ( $sOptionType === 'integer' ) {
|
247 |
$sTextInput = esc_attr( $sOptionSaved );
|
248 |
$sHtml .= '
|
249 |
<p>'.$sOptionTitle.'</p>
|
views/icwp_wpsf_index.php
CHANGED
@@ -23,7 +23,7 @@ include_once( 'icwp-wpsf-config_header.php' );
|
|
23 |
?>
|
24 |
<div class="form-actions">
|
25 |
<input type="hidden" name="<?php echo $icwp_var_prefix; ?>all_options_input" value="<?php echo $icwp_all_options_input; ?>" />
|
26 |
-
<input type="hidden" name="
|
27 |
<button type="submit" class="btn btn-primary" name="submit"><?php _wpsf_e( 'Save All Settings' ); ?></button>
|
28 |
</div>
|
29 |
</form>
|
23 |
?>
|
24 |
<div class="form-actions">
|
25 |
<input type="hidden" name="<?php echo $icwp_var_prefix; ?>all_options_input" value="<?php echo $icwp_all_options_input; ?>" />
|
26 |
+
<input type="hidden" name="<?php echo $icwp_var_prefix; ?>plugin_form_submit" value="Y" />
|
27 |
<button type="submit" class="btn btn-primary" name="submit"><?php _wpsf_e( 'Save All Settings' ); ?></button>
|
28 |
</div>
|
29 |
</form>
|
views/include_js.php
CHANGED
@@ -34,7 +34,7 @@
|
|
34 |
}
|
35 |
);
|
36 |
|
37 |
-
jQuery( 'select[name=<?php echo $
|
38 |
}
|
39 |
);
|
40 |
|
34 |
}
|
35 |
);
|
36 |
|
37 |
+
jQuery( 'select[name=<?php echo $icwp_var_prefix; ?>option]' ).trigger( 'change' );
|
38 |
}
|
39 |
);
|
40 |
|
views/snippets/admin_notice_mailchimp.php
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<!-- Begin MailChimp Signup Form -->
|
3 |
+
<div id="mc_embed_signup">
|
4 |
+
<form class="form form-inline" action="http://hostliketoast.us2.list-manage1.com/subscribe/post?u=e736870223389e44fb8915c9a&id=0e1d527259" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
|
5 |
+
<p>The WordPress Simple Firewall team has launched a education initiative to raise awareness of WordPress security and to provide further help with the WordPress Simple Firewall plugin. Get Involved here:</p>
|
6 |
+
<input type="text" value="" name="EMAIL" class="required email" id="mce-EMAIL" placeholder="Your Email" />
|
7 |
+
<input type="text" value="" name="FNAME" class="" id="mce-FNAME" placeholder="Your Name" />
|
8 |
+
<input type="hidden" value="<?php echo $nDays; ?>" name="DAYS" class="" id="mce-DAYS" />
|
9 |
+
<input type="submit" value="Get The News" name="subscribe" id="mc-embedded-subscribe" class="button" />
|
10 |
+
<a href="<?php echo $sLink_HideNotice;?>">Dismiss</a>
|
11 |
+
<div id="mce-responses" class="clear">
|
12 |
+
<div class="response" id="mce-error-response" style="display:none"></div>
|
13 |
+
<div class="response" id="mce-success-response" style="display:none"></div>
|
14 |
+
</div> <!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups-->
|
15 |
+
<div style="position: absolute; left: -5000px;"><input type="text" name="b_e736870223389e44fb8915c9a_0e1d527259" tabindex="-1" value=""></div>
|
16 |
+
<div class="clear"></div>
|
17 |
+
</form>
|
18 |
+
</div>
|
views/snippets/admin_notice_override.php
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<!-- Begin MailChimp Signup Form -->
|
3 |
+
<h3><?php echo sprintf( _wpsf__('Warning - %s.'), _wpsf__('The Simple Firewall is not currently running' ) ); ?></h3>
|
4 |
+
<p><?php echo sprintf( _wpsf__('Please delete the "%s" file to reactivate the Firewall processing' ), 'forceOff' );?></p>
|
views/snippets/admin_notice_plugin_upgraded.php
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<form method="post" action="<?php echo $sAction; ?>">
|
2 |
+
<input type="hidden" value="<?php echo $sRedirectPage; ?>" name="redirect_page" id="redirect_page">
|
3 |
+
<p><?php echo $sMessage; ?></p>
|
4 |
+
<input type="submit" value="<?php echo $sButtonText; ?>" name="submit" class="button" style="float:left; margin-bottom:10px;">
|
5 |
+
<div style="clear:both;"></div>
|
6 |
+
</form>
|
views/snippets/admin_notice_translate_plugin.php
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div id="IcwpTranslationsNotice">
|
2 |
+
<form method="post" action="<?php echo $sAction; ?>">
|
3 |
+
<input type="hidden" value="<?php echo $sRedirectPage; ?>" name="redirect_page" id="redirect_page">
|
4 |
+
<h4 style="margin:10px 0 3px;">
|
5 |
+
<?php _wpsf_e( 'Would you like to help translate the WordPress Simple Firewall into your language?' ); ?>
|
6 |
+
<?php printf( _wpsf__( 'Head over to: %s' ), '<a href="http://translate.icontrolwp.com" target="_blank">translate.icontrolwp.com</a>' ); ?>
|
7 |
+
</h4>
|
8 |
+
<input type="submit" value="<?php _wpsf_e( 'Dismiss this notice' ); ?>" name="submit" class="button" style="float:left; margin-bottom:10px;">
|
9 |
+
<div style="clear:both;"></div>
|
10 |
+
</form>
|
11 |
+
</div>
|