Version Description
- CHANGED: Simplified the automatic WordPress Plugin updates into 1 filter for consistency
Download this release
Release Info
Developer | paultgoodchild |
Plugin | Shield Security for WordPress |
Version | 1.9.2 |
Comparing to | |
See all releases |
Code changes from version 1.0 to 1.9.2
- .htaccess +4 -0
- icwp-wpsf.php +1072 -401
- mode.login_throttled +0 -0
- readme.txt +376 -36
- src/icwp-base-processor.php +353 -0
- src/icwp-basedb-processor.php +130 -0
- src/icwp-data-processor.php +193 -17
- src/icwp-firewall-processor.php +0 -502
- src/icwp-import-base-processor.php +84 -0
- src/icwp-import-wpf2-processor.php +147 -0
- src/icwp-optionshandler-autoupdates.php +148 -0
- src/icwp-optionshandler-base.php +569 -0
- src/icwp-optionshandler-commentsfilter.php +164 -0
- src/icwp-optionshandler-firewall.php +255 -0
- src/icwp-optionshandler-lockdown.php +123 -0
- src/icwp-optionshandler-loginprotect.php +150 -0
- src/icwp-optionshandler-wpsf.php +275 -0
- src/icwp-plugins-base.php +233 -59
- src/icwp-processor-autoupdates.php +81 -0
- src/icwp-processor-commentsfilter.php +431 -0
- src/icwp-processor-email.php +168 -0
- src/icwp-processor-firewall.php +620 -0
- src/icwp-processor-lockdown.php +109 -0
- src/icwp-processor-logging.php +108 -0
- src/icwp-processor-loginprotect.php +686 -0
- src/icwp-wpfilesystem.php +193 -0
- src/icwp-wpfunctions.php +118 -0
- views/icwp_options_helper.php +77 -4
- views/icwp_wpsf_access_key_request_index.php +64 -0
- views/{icwp_wpsf_firewall_config_index.php → icwp_wpsf_config_autoupdates_index.php} +3 -7
- views/icwp_wpsf_config_comments_filter_index.php +35 -0
- views/icwp_wpsf_config_firewall_index.php +38 -0
- views/icwp_wpsf_config_lockdown_index.php +35 -0
- views/icwp_wpsf_config_login_protect_index.php +35 -0
- views/icwp_wpsf_firewall_log_index.php +62 -30
- views/icwp_wpsf_index.php +208 -38
- views/widgets/icwp_common_widgets.php +5 -5
- views/widgets/icwp_widgets.php +3 -2
.htaccess
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
Order Allow,Deny
|
2 |
+
<FilesMatch "^.*\.(css|js|png)$">
|
3 |
+
Allow from all
|
4 |
+
</FilesMatch>
|
icwp-wpsf.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
2 |
/*
|
3 |
Plugin Name: WordPress Simple Firewall
|
4 |
-
Plugin URI: http://
|
5 |
Description: A Simple WordPress Firewall
|
6 |
-
Version: 1.
|
7 |
Author: iControlWP
|
8 |
-
Author URI: http://icwp.io/
|
9 |
*/
|
10 |
|
11 |
/**
|
@@ -27,342 +27,594 @@ Author URI: http://icwp.io/v
|
|
27 |
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
28 |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
29 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
30 |
-
*
|
31 |
*/
|
32 |
|
33 |
require_once( dirname(__FILE__).'/src/icwp-plugins-base.php' );
|
|
|
34 |
|
35 |
if ( !class_exists('ICWP_Wordpress_Simple_Firewall') ):
|
36 |
|
37 |
class ICWP_Wordpress_Simple_Firewall extends ICWP_WPSF_Base_Plugin {
|
38 |
|
39 |
-
const InputPrefix
|
40 |
-
const OptionPrefix
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
|
42 |
-
|
|
|
|
|
|
|
43 |
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
protected $
|
48 |
-
protected $m_aPluginOptions_WhitelistSection;
|
49 |
-
protected $m_aPluginOptions_BlacklistSection;
|
50 |
|
51 |
public function __construct() {
|
|
|
|
|
52 |
parent::__construct();
|
53 |
|
54 |
register_activation_hook( __FILE__, array( $this, 'onWpActivatePlugin' ) );
|
55 |
register_deactivation_hook( __FILE__, array( $this, 'onWpDeactivatePlugin' ) );
|
56 |
// register_uninstall_hook( __FILE__, array( &$this, 'onWpUninstallPlugin' ) );
|
57 |
-
|
|
|
58 |
self::$PLUGIN_NAME = basename(__FILE__);
|
59 |
self::$PLUGIN_PATH = plugin_basename( dirname(__FILE__) );
|
60 |
-
self::$
|
|
|
61 |
self::$PLUGIN_URL = plugins_url( '/', __FILE__ ) ;
|
62 |
self::$OPTION_PREFIX = self::OptionPrefix;
|
63 |
-
|
64 |
-
$this->m_sParentMenuIdSuffix = 'wpsf';
|
65 |
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
$this->override();
|
67 |
|
68 |
-
if (
|
69 |
-
|
70 |
-
$this->runFirewallProcess();
|
71 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
72 |
|
73 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
|
75 |
protected function override() {
|
76 |
if ( is_file( self::$PLUGIN_DIR . 'forceOff' ) ) {
|
77 |
-
|
|
|
|
|
|
|
|
|
78 |
}
|
79 |
else if ( is_file( self::$PLUGIN_DIR . 'forceOn' ) ) {
|
80 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
81 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
82 |
}
|
83 |
|
84 |
/**
|
85 |
-
*
|
86 |
-
*
|
87 |
-
* @param array $inaNewLogData
|
88 |
* @return boolean
|
89 |
*/
|
90 |
-
|
91 |
|
92 |
-
if (
|
|
|
|
|
|
|
93 |
return true;
|
94 |
}
|
95 |
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
100 |
}
|
101 |
-
return
|
102 |
}
|
103 |
|
104 |
/**
|
105 |
-
*
|
106 |
*
|
107 |
-
* @param
|
|
|
108 |
* @return boolean
|
109 |
*/
|
110 |
-
public function
|
|
|
|
|
111 |
|
112 |
-
$
|
113 |
-
if (
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
}
|
129 |
-
|
130 |
-
|
131 |
-
|
|
|
|
|
|
|
|
|
132 |
}
|
133 |
-
|
134 |
-
|
135 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
136 |
}
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
} else {
|
143 |
-
$oFP->reset();
|
144 |
}
|
|
|
|
|
|
|
|
|
145 |
|
146 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
147 |
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
|
|
|
|
|
|
167 |
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
172 |
}
|
173 |
}
|
174 |
-
$oFP->doFirewallBlock();
|
175 |
-
|
176 |
}
|
177 |
-
else {
|
178 |
-
$this->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
179 |
}
|
180 |
}
|
181 |
|
182 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
183 |
|
184 |
-
$this->
|
185 |
-
|
186 |
-
|
187 |
-
array( 'enable_firewall', '', 'N', 'checkbox', 'Enable Firewall', 'Completely turn on/off the firewall', 'Regardless of any settings anywhere else, this option will turn off the whole firewall, or enable your desired options below.' ),
|
188 |
-
array( 'enable_firewall_log', '', 'N', 'checkbox', 'Firewall Logging', 'Turn on a detailed Firewall Log', '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.' )
|
189 |
-
)
|
190 |
-
);
|
191 |
-
$this->m_aPluginOptions_BlockTypesSection = array(
|
192 |
-
'section_title' => 'Firewall Blocking Options',
|
193 |
-
'section_options' => array(
|
194 |
-
array(
|
195 |
-
'block_wplogin_access',
|
196 |
-
'',
|
197 |
-
'N',
|
198 |
-
'checkbox',
|
199 |
-
'Login Access',
|
200 |
-
'Block WP Login Access',
|
201 |
-
'This will block access to the WordPress Login (wp-login.php) except to IP Addresses on the whitelist. If the IP whitelist is empty, this setting is ignored (so you do not lock yourself out!)'
|
202 |
-
),
|
203 |
-
array(
|
204 |
-
'block_dir_traversal',
|
205 |
-
'',
|
206 |
-
'N',
|
207 |
-
'checkbox',
|
208 |
-
'Directory Traversals',
|
209 |
-
'Block Directory Traversals',
|
210 |
-
'This will block directory traversal paths in in application parameters (../, ../../etc/passwd, etc.)'
|
211 |
-
),
|
212 |
-
array(
|
213 |
-
'block_sql_queries',
|
214 |
-
'',
|
215 |
-
'N',
|
216 |
-
'checkbox',
|
217 |
-
'SQL Queries',
|
218 |
-
'Block SQL Queries',
|
219 |
-
'This will block in application parameters (union select, concat(, /**/, etc.).'
|
220 |
-
),
|
221 |
-
array(
|
222 |
-
'block_wordpress_terms',
|
223 |
-
'',
|
224 |
-
'N',
|
225 |
-
'checkbox',
|
226 |
-
'WordPress Terms',
|
227 |
-
'Block WordPress Specific Terms',
|
228 |
-
'This will block WordPress specific terms in application parameters (wp_, user_login, etc.).'
|
229 |
-
),
|
230 |
-
array(
|
231 |
-
'block_field_truncation',
|
232 |
-
'',
|
233 |
-
'N',
|
234 |
-
'checkbox',
|
235 |
-
'Field Truncation',
|
236 |
-
'Block Field Truncation Attacks',
|
237 |
-
'This will block field truncation attacks in application parameters.'
|
238 |
-
),
|
239 |
-
array(
|
240 |
-
'block_exe_file_uploads',
|
241 |
-
'',
|
242 |
-
'N',
|
243 |
-
'checkbox',
|
244 |
-
'Exe File Uploads',
|
245 |
-
'Block Executable File Uploads',
|
246 |
-
'This will block executable file uploads (.php, .exe, etc.).'
|
247 |
-
),
|
248 |
-
array(
|
249 |
-
'block_leading_schema',
|
250 |
-
'',
|
251 |
-
'N',
|
252 |
-
'checkbox',
|
253 |
-
'Leading Schemas',
|
254 |
-
'Block Leading Schemas (HTTPS / HTTP)',
|
255 |
-
'This will block leading schemas http:// and https:// in application parameters (off by default; may cause problems with many plugins).'
|
256 |
-
)
|
257 |
-
),
|
258 |
-
);
|
259 |
-
$this->m_aRedirectOptions = array( 'select',
|
260 |
-
array( 'redirect_die', 'Die' ),
|
261 |
-
array( 'redirect_home', 'Redirect To Home Page' ),
|
262 |
-
array( 'redirect_404', 'Return 404' ),
|
263 |
-
);
|
264 |
-
$this->m_aPluginOptions_BlockSection = array(
|
265 |
-
'section_title' => 'Choose Firewall Block Response',
|
266 |
-
'section_options' => array(
|
267 |
-
array( 'block_response', '', 'none', $this->m_aRedirectOptions, 'Block Response', 'Choose how the firewall responds when it blocks a request', '' ),
|
268 |
-
array( 'block_send_email', '', 'N', 'checkbox', 'Send Email Report', 'When a visitor is blocked it will send an email to the blog admin', '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.' ),
|
269 |
-
)
|
270 |
-
);
|
271 |
-
|
272 |
-
$this->m_aPluginOptions_WhitelistSection = array(
|
273 |
-
'section_title' => 'Choose IP Addresses To Whitelist',
|
274 |
-
'section_options' => array(
|
275 |
-
array(
|
276 |
-
'ips_whitelist',
|
277 |
-
'',
|
278 |
-
'none',
|
279 |
-
'ip_addresses',
|
280 |
-
'Whitelist IP Addresses',
|
281 |
-
'Choose IP Addresses that are never subjected to Firewall Rules',
|
282 |
-
'Take a new line per address. Each IP Address must be valid and will be checked.'
|
283 |
-
)
|
284 |
-
)
|
285 |
-
);
|
286 |
|
287 |
-
$this->
|
288 |
-
|
289 |
-
'section_options' => array(
|
290 |
-
array(
|
291 |
-
'ips_blacklist',
|
292 |
-
'',
|
293 |
-
'none',
|
294 |
-
'ip_addresses',
|
295 |
-
'Blacklist IP Addresses',
|
296 |
-
'Choose IP Addresses that are always blocked access to the site',
|
297 |
-
'Take a new line per address. Each IP Address must be valid and will be checked.'
|
298 |
-
)
|
299 |
-
)
|
300 |
-
);
|
301 |
|
302 |
-
$
|
303 |
-
&$this->m_aPluginOptions_Base,
|
304 |
-
&$this->m_aPluginOptions_BlockSection,
|
305 |
-
&$this->m_aPluginOptions_WhitelistSection,
|
306 |
-
&$this->m_aPluginOptions_BlacklistSection,
|
307 |
-
&$this->m_aPluginOptions_BlockTypesSection
|
308 |
-
);
|
309 |
|
310 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
311 |
|
312 |
-
|
|
|
313 |
|
314 |
-
|
315 |
-
|
316 |
-
|
|
|
|
|
|
|
317 |
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
323 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
324 |
public function onWpAdminInit() {
|
325 |
parent::onWpAdminInit();
|
326 |
-
|
327 |
// If it's a plugin admin page, we do certain things we don't do anywhere else.
|
328 |
if ( $this->isIcwpPluginAdminPage()) {
|
329 |
add_action( 'admin_enqueue_scripts', array( $this, 'enqueueBootstrapAdminCss' ), 99 );
|
330 |
}
|
331 |
|
332 |
-
// This is only done on WP Admin loads so as not to affect the front-end
|
333 |
-
$this->
|
|
|
|
|
334 |
|
335 |
//Multilingual support.
|
336 |
-
load_plugin_textdomain( '
|
337 |
}
|
338 |
|
339 |
-
protected function createPluginSubMenuItems(){
|
|
|
|
|
|
|
|
|
|
|
340 |
$this->m_aPluginMenu = array(
|
341 |
//Menu Page Title => Menu Item name, page ID (slug), callback function for this page - i.e. what to do/load.
|
342 |
-
$this->getSubmenuPageTitle( 'Firewall' ) => array( 'Firewall', $this->getSubmenuId('firewall
|
343 |
-
$this->getSubmenuPageTitle( '
|
|
|
|
|
|
|
|
|
344 |
);
|
345 |
-
}
|
346 |
-
|
347 |
-
/**
|
348 |
-
* Handles the upgrade from version 1 to version 2 of Twitter Bootstrap as well as any other plugin upgrade
|
349 |
-
*/
|
350 |
protected function handlePluginUpgrade() {
|
|
|
351 |
|
352 |
-
$sCurrentPluginVersion =
|
353 |
|
354 |
if ( $sCurrentPluginVersion !== self::$VERSION && current_user_can( 'manage_options' ) ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
355 |
|
356 |
-
//
|
|
|
357 |
|
358 |
-
//
|
359 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
360 |
}//if
|
361 |
|
362 |
//Someone clicked the button to acknowledge the update
|
363 |
if ( isset( $_POST[self::OptionPrefix.'hide_update_notice'] ) && isset( $_POST['user_id'] ) ) {
|
364 |
-
$
|
365 |
-
|
366 |
if ( $this->isShowMarketing() ) {
|
367 |
wp_redirect( admin_url( "admin.php?page=".$this->getFullParentMenuId() ) );
|
368 |
}
|
@@ -372,225 +624,552 @@ class ICWP_Wordpress_Simple_Firewall extends ICWP_WPSF_Base_Plugin {
|
|
372 |
}
|
373 |
}
|
374 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
375 |
public function onWpAdminNotices() {
|
376 |
-
|
377 |
-
//Do we have admin priviledges?
|
378 |
if ( !current_user_can( 'manage_options' ) ) {
|
379 |
return;
|
380 |
}
|
381 |
-
|
382 |
$this->adminNoticeOptionsUpdated();
|
|
|
|
|
|
|
|
|
383 |
}
|
384 |
|
385 |
/**
|
386 |
-
*
|
|
|
387 |
*/
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
return;
|
393 |
}
|
394 |
-
$nUserId = $oCurrentUser->ID;
|
395 |
-
$sCurrentVersion = get_user_meta( $nUserId, self::OptionPrefix.'current_version', true );
|
396 |
-
// A guard whereby if we can't ever get a value for this meta, it means we can never set it.
|
397 |
-
// If we can never set it, we shouldn't force the Ads on those users who can't get rid of it.
|
398 |
-
if ( $sCurrentVersion === false ) { //the value has never been set, or it's been installed for the first time.
|
399 |
-
$result = update_user_meta( $nUserId, self::OptionPrefix.'current_version', self::$VERSION );
|
400 |
-
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.
|
401 |
-
}
|
402 |
-
|
403 |
-
if ( $sCurrentVersion !== self::$VERSION ) {
|
404 |
-
|
405 |
-
$sRedirectPage = isset( $GLOBALS['pagenow'] ) ? $GLOBALS['pagenow'] : 'index.php';
|
406 |
-
ob_start();
|
407 |
-
?>
|
408 |
-
<style>
|
409 |
-
a#fromIcwp { padding: 0 5px; border-bottom: 1px dashed rgba(0,0,0,0.1); color: blue; font-weight: bold; }
|
410 |
-
</style>
|
411 |
-
<form id="IcwpUpdateNotice" method="post" action="admin.php?page=<?php echo $this->getSubmenuId('firewall-config'); ?>">
|
412 |
-
<input type="hidden" value="<?php echo $sRedirectPage; ?>" name="redirect_page" id="redirect_page">
|
413 |
-
<input type="hidden" value="1" name="<?php echo self::OptionPrefix; ?>hide_update_notice" id="<?php echo self::OptionPrefix; ?>hide_update_notice">
|
414 |
-
<input type="hidden" value="<?php echo $nUserId; ?>" name="user_id" id="user_id">
|
415 |
-
<h4 style="margin:10px 0 3px;">WordPress Firewall plugin has been updated- there may or may not be <a href="http://icwp.io/1v" id="fromIcwp" title="Twitter Bootstrap Plugin Shortcodes" target="_blank">updates to shortcodes</a> or the Bootstrap CSS may have changed quite a bit.</h4>
|
416 |
-
<input type="submit" value="Show me and hide this notice." name="submit" class="button" style="float:left; margin-bottom:10px;">
|
417 |
-
<div style="clear:both;"></div>
|
418 |
-
</form>
|
419 |
-
<?php
|
420 |
-
$sNotice = ob_get_contents();
|
421 |
-
ob_end_clean();
|
422 |
-
|
423 |
-
$this->getAdminNotice( $sNotice, 'updated', true );
|
424 |
-
}
|
425 |
|
426 |
-
|
427 |
-
|
428 |
-
private function adminNoticeOptionsUpdated() {
|
429 |
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
435 |
}
|
436 |
-
|
437 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
438 |
|
439 |
public function onDisplayMainMenu() {
|
440 |
|
441 |
-
//
|
442 |
-
|
|
|
|
|
|
|
|
|
|
|
443 |
|
444 |
$aData = array(
|
445 |
'plugin_url' => self::$PLUGIN_URL,
|
|
|
446 |
'aAllOptions' => $aAvailableOptions,
|
447 |
'fShowAds' => $this->isShowMarketing(),
|
448 |
-
|
449 |
-
'
|
450 |
-
'
|
451 |
-
'sBlockResponse' => self::getOption( 'block_response' ),
|
452 |
-
'fBlockSendEmail' => self::getOption( 'block_send_email' ) == 'Y',
|
453 |
-
'aIpWhitelist' => self::getOption( 'ips_whitelist' ),
|
454 |
-
'aIpBlacklist' => self::getOption( 'ips_blacklist' ),
|
455 |
-
'fBlockLogin' => self::getOption( 'block_wplogin_access' )== 'Y',
|
456 |
-
'fBlockDirTrav' => self::getOption( 'block_dir_traversal' )== 'Y',
|
457 |
-
'fBlockSql' => self::getOption( 'block_sql_queries' )== 'Y',
|
458 |
-
'fBlockWpTerms' => self::getOption( 'block_wordpress_terms' )== 'Y',
|
459 |
-
'fBlockFieldTrun' => self::getOption( 'block_field_truncation' )== 'Y',
|
460 |
-
'fBlockExeFile' => self::getOption( 'block_exe_file_uploads' )== 'Y',
|
461 |
-
'fBlockSchema' => self::getOption( 'block_leading_schema' )== 'Y'
|
462 |
);
|
463 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
464 |
$this->display( 'icwp_'.$this->m_sParentMenuIdSuffix.'_index', $aData );
|
465 |
}
|
466 |
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
$this->
|
|
|
471 |
|
472 |
-
|
473 |
-
$aAvailableOptions = array(
|
474 |
-
&$this->m_aPluginOptions_Base,
|
475 |
-
&$this->m_aPluginOptions_BlockSection,
|
476 |
-
&$this->m_aPluginOptions_WhitelistSection,
|
477 |
-
&$this->m_aPluginOptions_BlacklistSection,
|
478 |
-
&$this->m_aPluginOptions_BlockTypesSection
|
479 |
-
);
|
480 |
|
481 |
-
$sAllFormInputOptions = $this->collateAllFormInputsForAllOptions( $aAvailableOptions );
|
482 |
$aData = array(
|
483 |
'plugin_url' => self::$PLUGIN_URL,
|
484 |
'var_prefix' => self::OptionPrefix,
|
|
|
|
|
|
|
485 |
'fShowAds' => $this->isShowMarketing(),
|
486 |
-
'
|
487 |
-
'
|
488 |
-
'nonce_field' => $this->getSubmenuId('firewall').'_config',
|
489 |
-
'form_action' => 'admin.php?page='.$this->getSubmenuId('firewall-config'),
|
490 |
);
|
491 |
|
492 |
-
$this->display( '
|
493 |
}
|
494 |
|
495 |
-
|
|
|
|
|
|
|
|
|
|
|
496 |
|
497 |
-
$
|
|
|
|
|
498 |
$aData = array(
|
499 |
'plugin_url' => self::$PLUGIN_URL,
|
500 |
'var_prefix' => self::OptionPrefix,
|
501 |
-
'firewall_log' => self::getOption( 'firewall_log' ),
|
502 |
'fShowAds' => $this->isShowMarketing(),
|
503 |
-
'
|
504 |
-
'
|
|
|
|
|
505 |
);
|
506 |
-
|
507 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
508 |
}
|
509 |
|
510 |
protected function handlePluginFormSubmit() {
|
511 |
|
512 |
-
|
513 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
514 |
}
|
515 |
|
516 |
if ( isset( $_GET['page'] ) ) {
|
517 |
switch ( $_GET['page'] ) {
|
518 |
-
case $this->getSubmenuId(
|
519 |
-
$this->
|
520 |
break;
|
521 |
-
case $this->getSubmenuId( 'firewall
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
522 |
$this->handleSubmit_FirewallLog();
|
523 |
break;
|
|
|
|
|
|
|
524 |
}
|
525 |
}
|
|
|
|
|
|
|
|
|
|
|
526 |
|
527 |
-
if (
|
528 |
-
|
|
|
|
|
|
|
529 |
}
|
530 |
else {
|
531 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
532 |
}
|
533 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
534 |
}
|
535 |
|
536 |
-
protected function
|
537 |
//Ensures we're actually getting this request from WP.
|
538 |
-
check_admin_referer( $this->getSubmenuId('
|
|
|
|
|
|
|
|
|
539 |
|
540 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
541 |
|
542 |
if ( !isset($_POST[self::OptionPrefix.'all_options_input']) ) {
|
543 |
return;
|
544 |
}
|
545 |
-
$this->
|
|
|
|
|
|
|
546 |
}
|
547 |
|
548 |
-
protected function
|
549 |
//Ensures we're actually getting this request from WP.
|
550 |
-
check_admin_referer( $this->getSubmenuId('
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
551 |
|
552 |
// At the time of writing the page only has 1 form submission item - clear log
|
553 |
-
|
554 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
555 |
exit();
|
556 |
}
|
557 |
|
558 |
-
public function
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
559 |
}
|
560 |
|
561 |
-
|
|
|
|
|
|
|
|
|
562 |
}
|
563 |
|
564 |
-
public function onWpPluginActionLinks( $
|
|
|
565 |
if ( $insFile == plugin_basename( __FILE__ ) ) {
|
566 |
-
|
567 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
568 |
}
|
569 |
-
return $
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
570 |
}
|
571 |
|
572 |
protected function deleteAllPluginDbOptions() {
|
573 |
|
574 |
parent::deleteAllPluginDbOptions();
|
575 |
-
|
576 |
if ( !current_user_can( 'manage_options' ) ) {
|
577 |
return;
|
578 |
}
|
579 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
580 |
}
|
581 |
|
582 |
public function onWpDeactivatePlugin() {
|
583 |
-
|
584 |
-
if ( $this->getOption('delete_on_deactivate') == 'Y' ) {
|
585 |
$this->deleteAllPluginDbOptions();
|
586 |
}
|
587 |
-
|
588 |
-
$this->deleteOption( 'current_plugin_version' );
|
589 |
-
$this->deleteOption( 'feedback_admin_notice' );
|
590 |
-
|
591 |
-
}//onWpDeactivatePlugin
|
592 |
-
|
593 |
-
public function onWpActivatePlugin() { }
|
594 |
|
595 |
public function enqueueBootstrapAdminCss() {
|
596 |
wp_register_style( 'worpit_bootstrap_wpadmin_css', $this->getCssUrl( 'bootstrap-wpadmin.css' ), false, self::$VERSION );
|
@@ -599,52 +1178,144 @@ class ICWP_Wordpress_Simple_Firewall extends ICWP_WPSF_Base_Plugin {
|
|
599 |
wp_enqueue_style( 'worpit_bootstrap_wpadmin_css_fixes' );
|
600 |
}
|
601 |
|
602 |
-
|
603 |
-
*
|
604 |
-
*/
|
605 |
-
protected function filterIpsLists() {
|
606 |
|
607 |
-
$
|
608 |
-
|
609 |
-
|
610 |
-
|
|
|
611 |
}
|
612 |
-
$
|
613 |
-
|
614 |
-
|
615 |
-
self::updateOption( 'ips_whitelist', $this->verifyIpAddressList( $aWhitelistIpsFiltered ) );
|
616 |
}
|
|
|
|
|
|
|
|
|
|
|
617 |
|
618 |
-
$
|
619 |
-
|
620 |
-
|
621 |
-
|
|
|
622 |
}
|
623 |
-
$
|
624 |
-
$
|
625 |
-
|
626 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
627 |
}
|
628 |
}
|
629 |
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
634 |
}
|
635 |
-
|
636 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
637 |
}
|
638 |
-
|
639 |
-
|
640 |
-
|
|
|
|
|
|
|
|
|
641 |
}
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
646 |
}
|
647 |
-
return $inaIpList;
|
648 |
}
|
649 |
}
|
650 |
|
1 |
<?php
|
2 |
/*
|
3 |
Plugin Name: WordPress Simple Firewall
|
4 |
+
Plugin URI: http://icwp.io/2f
|
5 |
Description: A Simple WordPress Firewall
|
6 |
+
Version: 1.9.2
|
7 |
Author: iControlWP
|
8 |
+
Author URI: http://icwp.io/2e
|
9 |
*/
|
10 |
|
11 |
/**
|
27 |
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
28 |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
29 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
30 |
*/
|
31 |
|
32 |
require_once( dirname(__FILE__).'/src/icwp-plugins-base.php' );
|
33 |
+
require_once( dirname(__FILE__).'/src/icwp-data-processor.php' );
|
34 |
|
35 |
if ( !class_exists('ICWP_Wordpress_Simple_Firewall') ):
|
36 |
|
37 |
class ICWP_Wordpress_Simple_Firewall extends ICWP_WPSF_Base_Plugin {
|
38 |
|
39 |
+
const InputPrefix = 'icwp_wpsf_';
|
40 |
+
const OptionPrefix = 'icwp_wpsf_'; //ALL database options use this as the prefix.
|
41 |
+
const AdminAccessKeyCookieName = "icwp_wpsf_aakcook";
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Should be updated each new release.
|
45 |
+
* @var string
|
46 |
+
*/
|
47 |
+
static public $VERSION = '1.9.2';
|
48 |
+
|
49 |
+
/**
|
50 |
+
* @var ICWP_OptionsHandler_Wpsf
|
51 |
+
*/
|
52 |
+
protected $m_oWpsfOptions;
|
53 |
+
|
54 |
+
/**
|
55 |
+
* @var ICWP_OptionsHandler_Firewall
|
56 |
+
*/
|
57 |
+
protected $m_oFirewallOptions;
|
58 |
+
|
59 |
+
/**
|
60 |
+
* @var ICWP_OptionsHandler_LoginProtect
|
61 |
+
*/
|
62 |
+
protected $m_oLoginProtectOptions;
|
63 |
+
|
64 |
+
/**
|
65 |
+
* @var ICWP_OptionsHandler_CommentsFilter
|
66 |
+
*/
|
67 |
+
protected $m_oCommentsFilterOptions;
|
68 |
+
|
69 |
+
/**
|
70 |
+
* @var ICWP_OptionsHandler_Lockdown
|
71 |
+
*/
|
72 |
+
protected $m_oLockdownOptions;
|
73 |
+
|
74 |
+
/**
|
75 |
+
* @var ICWP_OptionsHandler_AutoUpdates
|
76 |
+
*/
|
77 |
+
protected $m_oAutoUpdatesOptions;
|
78 |
+
|
79 |
+
/**
|
80 |
+
* @var ICWP_FirewallProcessor
|
81 |
+
*/
|
82 |
+
protected $m_oFirewallProcessor;
|
83 |
+
|
84 |
+
/**
|
85 |
+
* @var ICWP_LoginProtectProcessor
|
86 |
+
*/
|
87 |
+
protected $m_oLoginProtectProcessor;
|
88 |
+
|
89 |
+
/**
|
90 |
+
* @var ICWP_CommentsFilterProcessor
|
91 |
+
*/
|
92 |
+
protected $m_oCommentsFilterProcessor;
|
93 |
+
|
94 |
+
/**
|
95 |
+
* @var ICWP_LockdownProcessor
|
96 |
+
*/
|
97 |
+
protected $m_oLockdownProcessor;
|
98 |
+
|
99 |
+
/**
|
100 |
+
* @var ICWP_AutoUpdatesProcessor
|
101 |
+
*/
|
102 |
+
protected $m_oAutoUpdatesProcessor;
|
103 |
|
104 |
+
/**
|
105 |
+
* @var ICWP_LoggingProcessor
|
106 |
+
*/
|
107 |
+
protected $m_oLoggingProcessor;
|
108 |
|
109 |
+
/**
|
110 |
+
* @var ICWP_EmailProcessor
|
111 |
+
*/
|
112 |
+
protected $m_oEmailProcessor;
|
|
|
|
|
113 |
|
114 |
public function __construct() {
|
115 |
+
|
116 |
+
$this->m_fNetworkAdminOnly = true;
|
117 |
parent::__construct();
|
118 |
|
119 |
register_activation_hook( __FILE__, array( $this, 'onWpActivatePlugin' ) );
|
120 |
register_deactivation_hook( __FILE__, array( $this, 'onWpDeactivatePlugin' ) );
|
121 |
// register_uninstall_hook( __FILE__, array( &$this, 'onWpUninstallPlugin' ) );
|
122 |
+
|
123 |
+
self::$PLUGIN_HUMAN_NAME = "WordPress Simple Firewall";
|
124 |
self::$PLUGIN_NAME = basename(__FILE__);
|
125 |
self::$PLUGIN_PATH = plugin_basename( dirname(__FILE__) );
|
126 |
+
self::$PLUGIN_FILE = plugin_basename(__FILE__);
|
127 |
+
self::$PLUGIN_DIR = WP_PLUGIN_DIR.ICWP_DS.self::$PLUGIN_PATH.ICWP_DS;
|
128 |
self::$PLUGIN_URL = plugins_url( '/', __FILE__ ) ;
|
129 |
self::$OPTION_PREFIX = self::OptionPrefix;
|
|
|
|
|
130 |
|
131 |
+
$this->m_sParentMenuIdSuffix = 'wpsf';
|
132 |
+
// loads the base plugin options from 1 db call
|
133 |
+
$this->loadOptionsHandler( 'Wpsf' );
|
134 |
+
$this->m_fAutoPluginUpgrade = false && $this->m_oWpsfOptions->getOpt( 'enable_auto_plugin_upgrade' ) == 'Y';
|
135 |
+
|
136 |
+
// checks for filesystem based firewall overrides
|
137 |
$this->override();
|
138 |
|
139 |
+
if ( $this->getIsMainFeatureEnabled( 'firewall' ) ) {
|
140 |
+
add_action( 'plugins_loaded', array( $this, 'runFirewallProcess' ), 1 );
|
|
|
141 |
}
|
142 |
+
|
143 |
+
if ( $this->getIsMainFeatureEnabled( 'login_protect' ) ) {
|
144 |
+
add_action( 'plugins_loaded', array( $this, 'runLoginProtect' ), 1 );
|
145 |
+
}
|
146 |
+
|
147 |
+
if ( $this->getIsMainFeatureEnabled( 'comments_filter' ) ) {
|
148 |
+
add_action( 'plugins_loaded', array( $this, 'runCommentsFilter' ), 1 );
|
149 |
+
}
|
150 |
+
|
151 |
+
if ( $this->getIsMainFeatureEnabled( 'lockdown' ) ) {
|
152 |
+
add_action( 'plugins_loaded', array( $this, 'runLockdown' ), 1 );
|
153 |
+
}
|
154 |
+
|
155 |
+
if ( $this->getIsMainFeatureEnabled( 'autoupdates' ) ) {
|
156 |
+
add_action( 'plugins_loaded', array( $this, 'runAutoUpdates' ), 1 );
|
157 |
+
}
|
158 |
+
|
159 |
+
add_action( 'in_plugin_update_message-'.self::$PLUGIN_FILE, array( $this, 'onWpPluginUpdateMessage' ) );
|
160 |
|
161 |
+
if ( isset( $_GET['turnoffperm'] ) ) {
|
162 |
+
$this->setPermissionToSubmit( false );
|
163 |
+
}
|
164 |
+
}
|
165 |
+
|
166 |
+
public function removePluginConflicts() {
|
167 |
+
if ( class_exists('AIO_WP_Security') && isset( $GLOBALS['aio_wp_security'] ) ) {
|
168 |
+
remove_action( 'init', array( $GLOBALS['aio_wp_security'], 'wp_security_plugin_init'), 0 );
|
169 |
+
}
|
170 |
+
}
|
171 |
+
|
172 |
+
/**
|
173 |
+
*/
|
174 |
+
public function onWpInit() {
|
175 |
+
parent::onWpInit();
|
176 |
+
add_action( 'plugin_action_links', array( $this, 'onWpPluginActionLinks' ), 10, 4 );
|
177 |
+
}
|
178 |
+
|
179 |
+
/**
|
180 |
+
* @param array $aPlugins
|
181 |
+
* @return unknown
|
182 |
+
*/
|
183 |
+
public function hide_plugin( $inaPlugins ) {
|
184 |
+
foreach ( $inaPlugins as $sSlug => $aData ) {
|
185 |
+
if ( strpos( $sSlug, 'icwp-wpsf.php' ) !== false ) {
|
186 |
+
unset( $inaPlugins[$sSlug] );
|
187 |
+
}
|
188 |
+
}
|
189 |
+
return $inaPlugins;
|
190 |
+
}
|
191 |
|
192 |
protected function override() {
|
193 |
if ( is_file( self::$PLUGIN_DIR . 'forceOff' ) ) {
|
194 |
+
$this->setSharedOption( 'enable_firewall', 'N' );
|
195 |
+
$this->setSharedOption( 'enable_login_protect', 'N' );
|
196 |
+
$this->setSharedOption( 'enable_comments_filter', 'N' );
|
197 |
+
$this->setSharedOption( 'enable_autoupdates', 'N' );
|
198 |
+
$this->setSharedOption( 'enable_admin_access_restriction', 'N' );
|
199 |
}
|
200 |
else if ( is_file( self::$PLUGIN_DIR . 'forceOn' ) ) {
|
201 |
+
$this->setSharedOption( 'enable_firewall', 'Y' );
|
202 |
+
$this->setSharedOption( 'enable_login_protect', 'Y' );
|
203 |
+
$this->setSharedOption( 'enable_comments_filter', 'Y' );
|
204 |
+
$this->setSharedOption( 'enable_autoupdates', 'Y' );
|
205 |
+
$this->setSharedOption( 'enable_admin_access_restriction', 'Y' );
|
206 |
+
}
|
207 |
+
else {
|
208 |
+
return true;
|
209 |
+
}
|
210 |
+
$this->resetFirewallProcessor();
|
211 |
+
$this->resetLoginProcessor();
|
212 |
+
}
|
213 |
+
|
214 |
+
protected function genSecretKey() {
|
215 |
+
$sKey = $this->m_oWpsfOptions->getOpt( 'secret_key' );
|
216 |
+
if ( empty( $sKey ) ) {
|
217 |
+
$sKey = md5( mt_rand() );
|
218 |
+
$this->m_oWpsfOptions->setOpt( 'secret_key', $sKey );
|
219 |
}
|
220 |
+
return $sKey;
|
221 |
+
}
|
222 |
+
|
223 |
+
protected function getFeaturesMap() {
|
224 |
+
return array(
|
225 |
+
'firewall' => 'Firewall',
|
226 |
+
'login_protect' => 'LoginProtect',
|
227 |
+
'comments_filter' => 'CommentsFilter',
|
228 |
+
'lockdown' => 'Lockdown',
|
229 |
+
'autoupdates' => 'AutoUpdates'
|
230 |
+
);
|
231 |
}
|
232 |
|
233 |
/**
|
234 |
+
* @param string $insFeature - firewall, login_protect, comments_filter, lockdown
|
|
|
|
|
235 |
* @return boolean
|
236 |
*/
|
237 |
+
public function getIsMainFeatureEnabled( $insFeature ) {
|
238 |
|
239 |
+
if ( is_file( self::$PLUGIN_DIR . 'forceOff' ) ) {
|
240 |
+
return false;
|
241 |
+
}
|
242 |
+
else if ( is_file( self::$PLUGIN_DIR . 'forceOn' ) ) {
|
243 |
return true;
|
244 |
}
|
245 |
|
246 |
+
$aFeatures = $this->getFeaturesMap();
|
247 |
+
|
248 |
+
switch ( $insFeature ) {
|
249 |
+
case 'admin_access':
|
250 |
+
$fEnabled = $this->m_oWpsfOptions->getOpt( 'enable_admin_access_restriction' ) == 'Y';
|
251 |
+
break;
|
252 |
+
default:
|
253 |
+
if ( array_key_exists( $insFeature, $aFeatures ) ) {
|
254 |
+
$fEnabled = $this->m_oWpsfOptions->getOpt( 'enable_'.$insFeature ) == 'Y';
|
255 |
+
}
|
256 |
+
else {
|
257 |
+
$fEnabled = false;
|
258 |
+
}
|
259 |
+
break;
|
260 |
}
|
261 |
+
return $fEnabled;
|
262 |
}
|
263 |
|
264 |
/**
|
265 |
+
* This is necessary because we store these values in several places and we need to always keep it in sync.
|
266 |
*
|
267 |
+
* @param string $sFeature
|
268 |
+
* @param boolean $infEnabled
|
269 |
* @return boolean
|
270 |
*/
|
271 |
+
public function setSharedOption( $insOption, $inmValue ) {
|
272 |
+
|
273 |
+
$aFeatures = $this->getFeaturesMap();
|
274 |
|
275 |
+
$sFeature = str_replace( 'enable_', '', $insOption );
|
276 |
+
if ( !array_key_exists( $sFeature, $aFeatures ) ) {
|
277 |
+
return;
|
278 |
+
}
|
279 |
+
|
280 |
+
$this->loadOptionsHandler( $aFeatures[$sFeature] );
|
281 |
+
$sOptions = 'm_o'.$aFeatures[$sFeature].'Options';// e.g. m_oFirewallOptions
|
282 |
+
$this->{$sOptions}->setOpt( $insOption, $inmValue );
|
283 |
+
$this->m_oWpsfOptions->setOpt( $insOption, $inmValue );
|
284 |
+
}
|
285 |
+
|
286 |
+
/**
|
287 |
+
* Updates the current log data with new data.
|
288 |
+
*
|
289 |
+
* @param array $inaNewLogData
|
290 |
+
* @return boolean
|
291 |
+
*/
|
292 |
+
protected function updateLogStore() {
|
293 |
+
|
294 |
+
if ( isset( $this->m_oFirewallProcessor ) && is_object( $this->m_oFirewallProcessor ) && $this->getIsMainFeatureEnabled( 'firewall' ) ) {
|
295 |
+
$aLogData = $this->m_oFirewallProcessor->flushLogData();
|
296 |
+
if ( !is_null( $aLogData ) && !empty( $aLogData ) ) {
|
297 |
+
$this->loadProcessor( 'Logging' );
|
298 |
+
$this->m_oLoggingProcessor->writeLog( $aLogData );
|
299 |
}
|
300 |
+
}
|
301 |
+
|
302 |
+
if ( isset( $this->m_oLoginProtectProcessor ) && is_object( $this->m_oLoginProtectProcessor ) && $this->getIsMainFeatureEnabled( 'login_protect' ) ) {
|
303 |
+
$aLogData = $this->m_oLoginProtectProcessor->flushLogData();
|
304 |
+
if ( !is_null( $aLogData ) && !empty( $aLogData ) ) {
|
305 |
+
$this->loadProcessor( 'Logging' );
|
306 |
+
$this->m_oLoggingProcessor->writeLog( $aLogData );
|
307 |
}
|
308 |
+
}
|
309 |
+
}
|
310 |
+
|
311 |
+
protected function loadOptionsHandler( $insOptionHandler, $infFullBuild = false ) {
|
312 |
+
|
313 |
+
$aAllHandlers = array_values( $this->getFeaturesMap() );
|
314 |
+
$aAllHandlers[] = 'Wpsf';
|
315 |
+
|
316 |
+
// special case
|
317 |
+
if ( $insOptionHandler == 'all' ) {
|
318 |
+
foreach( $aAllHandlers as $sHandler ) {
|
319 |
+
$this->loadOptionsHandler( $sHandler, $infFullBuild );
|
320 |
}
|
321 |
+
return;
|
322 |
+
}
|
323 |
+
|
324 |
+
if ( !in_array( $insOptionHandler, $aAllHandlers ) ) {
|
325 |
+
wp_die( 'Options handler is not permitted: '.$insOptionHandler );
|
|
|
|
|
326 |
}
|
327 |
+
|
328 |
+
$sOptionsVarName = 'm_o'.$insOptionHandler.'Options'; // e.g. m_oWpsfOptions
|
329 |
+
$sSourceFile = dirname(__FILE__).'/src/icwp-optionshandler-'.strtolower($insOptionHandler).'.php'; // e.g. icwp-optionshandler-wpsf.php
|
330 |
+
$sClassName = 'ICWP_OptionsHandler_'.$insOptionHandler; // e.g. ICWP_OptionsHandler_Wpsf
|
331 |
|
332 |
+
require_once( $sSourceFile );
|
333 |
+
if ( !isset( $this->{$sOptionsVarName} ) ) {
|
334 |
+
$this->{$sOptionsVarName} = new $sClassName( self::OptionPrefix, self::$VERSION, $infFullBuild );
|
335 |
+
}
|
336 |
+
if ( $infFullBuild ) {
|
337 |
+
$this->{$sOptionsVarName}->buildOptions();
|
338 |
+
}
|
339 |
+
}
|
340 |
+
|
341 |
+
protected function loadProcessor( $insProcessorName, $infReset = false ) {
|
342 |
|
343 |
+
$aAllProcessors = array(
|
344 |
+
'Firewall' => 'firewall',
|
345 |
+
'LoginProtect' => 'login',
|
346 |
+
'CommentsFilter' => 'comments',
|
347 |
+
'Lockdown' => 'lockdown',
|
348 |
+
'AutoUpdates' => 'autoupdates',
|
349 |
+
'Logging' => '',
|
350 |
+
'Email' => ''
|
351 |
+
);
|
352 |
+
|
353 |
+
if ( !array_key_exists( $insProcessorName, $aAllProcessors ) ) {
|
354 |
+
wp_die( 'Processor is not permitted here.' );
|
355 |
+
}
|
356 |
+
|
357 |
+
$sProcessorVarName = 'm_o'.$insProcessorName.'Processor'; // e.g. m_oFirewallProcessor
|
358 |
+
$sSourceFile = dirname(__FILE__).'/src/icwp-processor-'.strtolower($insProcessorName).'.php'; // e.g. icwp-optionshandler-wpsf.php
|
359 |
+
$sClassName = 'ICWP_'.$insProcessorName.'Processor'; // e.g. ICWP_FirewallProcessor
|
360 |
+
$sStoredOptionName = $aAllProcessors[$insProcessorName].'_processor'; // e.g. firewall_processor
|
361 |
+
$sOptionsHandlerVarName = 'm_o'.$insProcessorName.'Options'; // e.g. m_oFirewallOptions
|
362 |
+
|
363 |
+
require_once( $sSourceFile );
|
364 |
+
if ( empty( $this->{$sProcessorVarName} ) ) {
|
365 |
|
366 |
+
$this->{$sProcessorVarName} = self::getOption( $sStoredOptionName );
|
367 |
+
if ( is_object( $this->{$sProcessorVarName} ) && ( $this->{$sProcessorVarName} instanceof $sClassName ) ) {
|
368 |
+
$this->{$sProcessorVarName}->reset();
|
369 |
+
}
|
370 |
+
else {
|
371 |
+
$this->{$sProcessorVarName} = new $sClassName();
|
372 |
+
// Also loads the options handler where appropriate
|
373 |
+
if ( !empty( $aAllProcessors[ $insProcessorName ] ) ) {
|
374 |
+
$this->loadOptionsHandler( $insProcessorName );
|
375 |
+
// $this->{$sProcessorVarName}->setOptionsHandler( $this->{$sOptionsHandlerVarName} );
|
376 |
+
$this->{$sProcessorVarName}->setOptions( $this->{$sOptionsHandlerVarName}->getPluginOptionsValues() );
|
377 |
}
|
378 |
}
|
|
|
|
|
379 |
}
|
380 |
+
else if ( $infReset ) {
|
381 |
+
$this->{$sProcessorVarName}->reset();
|
382 |
+
}
|
383 |
+
// Now we handle any custom processor stuff
|
384 |
+
if ( $insProcessorName == 'LoginProtect' ) {
|
385 |
+
$this->m_oLoginProtectProcessor->setSecretKey( $this->genSecretKey() );
|
386 |
+
}
|
387 |
+
else if ( $insProcessorName == 'Email' ) {
|
388 |
+
$this->m_oEmailProcessor->setDefaultRecipientAddress( $this->m_oWpsfOptions->getOpt( 'block_send_email_address' ) );
|
389 |
+
$this->m_oEmailProcessor->setThrottleLimit( $this->m_oWpsfOptions->getOpt( 'send_email_throttle_limit' ) );
|
390 |
+
$sSiteName = function_exists( 'get_bloginfo' )? get_bloginfo('name') : '';
|
391 |
+
$this->m_oEmailProcessor->setSiteName( $sSiteName );
|
392 |
}
|
393 |
}
|
394 |
|
395 |
+
/**
|
396 |
+
* Should be called from the constructor so as to ensure it is called as early as possible.
|
397 |
+
*
|
398 |
+
* @param array $inaNewLogData
|
399 |
+
* @return boolean
|
400 |
+
*/
|
401 |
+
public function runFirewallProcess() {
|
402 |
|
403 |
+
if ( is_super_admin() && $this->getOption( 'whitelist_admins' ) == 'Y' ) {
|
404 |
+
return;
|
405 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
406 |
|
407 |
+
$this->loadProcessor( 'Firewall' );
|
408 |
+
$fFirewallBlockUser = !$this->m_oFirewallProcessor->doFirewallCheck();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
409 |
|
410 |
+
if ( $fFirewallBlockUser ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
411 |
|
412 |
+
if ( $this->m_oFirewallProcessor->getNeedsEmailHandler() ) {
|
413 |
+
$this->loadProcessor( 'Email' );
|
414 |
+
$this->m_oFirewallProcessor->setEmailHandler( $this->m_oEmailProcessor );
|
415 |
+
$this->m_oFirewallProcessor->doPreFirewallBlock();
|
416 |
+
$this->m_oEmailProcessor->store( self::getKey( 'email_processor' ) );
|
417 |
+
}
|
418 |
+
else {
|
419 |
+
$this->m_oFirewallProcessor->doPreFirewallBlock();
|
420 |
+
}
|
421 |
+
}
|
422 |
+
$this->updateLogStore();
|
423 |
+
$this->m_oFirewallProcessor->store( self::getKey( 'firewall_processor' ) );
|
424 |
+
|
425 |
+
if ( $fFirewallBlockUser ) {
|
426 |
+
$this->m_oFirewallProcessor->doFirewallBlock();
|
427 |
+
}
|
428 |
|
429 |
+
unset( $this->m_oFirewallProcessor );
|
430 |
+
}
|
431 |
|
432 |
+
/**
|
433 |
+
* Handles the running of all Login Protection processes.
|
434 |
+
*/
|
435 |
+
public function runLoginProtect() {
|
436 |
+
$this->loadProcessor( 'LoginProtect' );
|
437 |
+
$this->m_oLoginProtectProcessor->run();
|
438 |
|
439 |
+
// We don't want to load the email handler unless we really need it.
|
440 |
+
// 29 is just before we'll need it if we do
|
441 |
+
if ( $this->m_oLoginProtectProcessor->getNeedsEmailHandler() ) {
|
442 |
+
$this->loadProcessor( 'Email' );
|
443 |
+
$this->m_oLoginProtectProcessor->setEmailHandler( $this->m_oEmailProcessor );
|
444 |
+
}
|
445 |
+
}
|
446 |
+
|
447 |
+
/**
|
448 |
+
* Handles the running of all Comments Filter processes.
|
449 |
+
*/
|
450 |
+
public function runCommentsFilter() {
|
451 |
+
$this->loadProcessor( 'CommentsFilter' );
|
452 |
+
$this->m_oCommentsFilterProcessor->run();
|
453 |
+
}
|
454 |
+
|
455 |
+
/**
|
456 |
+
* Handles the running of all Lockdown processes.
|
457 |
+
*/
|
458 |
+
public function runLockdown() {
|
459 |
+
$this->loadProcessor( 'Lockdown' );
|
460 |
+
$this->m_oLockdownProcessor->run();
|
461 |
+
}
|
462 |
+
|
463 |
+
/**
|
464 |
+
* Handles the running of all Lockdown processes.
|
465 |
+
*/
|
466 |
+
public function runAutoUpdates() {
|
467 |
+
$this->loadProcessor( 'AutoUpdates' );
|
468 |
+
$this->m_oAutoUpdatesProcessor->run();
|
469 |
+
}
|
470 |
+
|
471 |
+
protected function getAllOptions() {
|
472 |
+
$aOptionNames = array(
|
473 |
+
'm_oWpsfOptions',
|
474 |
+
'm_oFirewallOptions',
|
475 |
+
'm_oLoginProtectOptions',
|
476 |
+
'm_oCommentsFilterOptions',
|
477 |
+
'm_oLockdownOptions',
|
478 |
+
'm_oAutoUpdatesOptions'
|
479 |
+
);
|
480 |
+
|
481 |
+
$this->loadOptionsHandler('all');
|
482 |
+
$aOptions = array();
|
483 |
+
foreach( $aOptionNames as $sName ) {
|
484 |
+
if ( isset( $this->{$sName} ) ) {
|
485 |
+
$aOptions[] = &$this->{$sName};
|
486 |
+
}
|
487 |
+
}
|
488 |
+
return $aOptions;
|
489 |
+
}
|
490 |
+
|
491 |
+
protected function getAllProcessors() {
|
492 |
+
$aProcessorNames = array(
|
493 |
+
'firewall_processor' => 'm_oFirewallProcessor',
|
494 |
+
'login_processor' => 'm_oLoginProtectProcessor',
|
495 |
+
'comments_processor' => 'm_oCommentsFilterProcessor',
|
496 |
+
'lockdown_processor' => 'm_oLockdownProcessor',
|
497 |
+
'autoupdates_processor' => 'm_oAutoUpdatesProcessor',
|
498 |
+
'logging_processor' => 'm_oLoggingProcessor',
|
499 |
+
'email_processor' => 'm_oEmailProcessor'
|
500 |
+
);
|
501 |
+
$aProcessors = array();
|
502 |
+
foreach( $aProcessorNames as $sKey => $sName ) {
|
503 |
+
if ( isset( $this->{$sName} ) ) {
|
504 |
+
$aProcessors[$sKey] = &$this->{$sName};
|
505 |
+
}
|
506 |
+
}
|
507 |
+
return $aProcessors;
|
508 |
+
}
|
509 |
|
510 |
+
/**
|
511 |
+
* Make sure and cache the processors after all is said and done.
|
512 |
+
*/
|
513 |
+
public function saveProcessors_Action() {
|
514 |
+
|
515 |
+
$this->updateLogStore();
|
516 |
+
|
517 |
+
$aOptions = $this->getAllOptions();
|
518 |
+
foreach( $aOptions as &$oOption ) {
|
519 |
+
if ( isset( $oOption ) ) {
|
520 |
+
$oOption->savePluginOptions();
|
521 |
+
}
|
522 |
+
}
|
523 |
+
$aProcessors = $this->getAllProcessors();
|
524 |
+
foreach( $aProcessors as $sKey => &$oProcessor ) {
|
525 |
+
$oProcessor->store( self::getKey( $sKey ) );
|
526 |
+
}
|
527 |
+
}
|
528 |
+
|
529 |
public function onWpAdminInit() {
|
530 |
parent::onWpAdminInit();
|
531 |
+
|
532 |
// If it's a plugin admin page, we do certain things we don't do anywhere else.
|
533 |
if ( $this->isIcwpPluginAdminPage()) {
|
534 |
add_action( 'admin_enqueue_scripts', array( $this, 'enqueueBootstrapAdminCss' ), 99 );
|
535 |
}
|
536 |
|
537 |
+
// This is only done on WP Admin loads so as not to affect the front-end and only if the firewall is enabled
|
538 |
+
if ( $this->getIsMainFeatureEnabled( 'firewall' ) ) {
|
539 |
+
$this->filterIpLists();
|
540 |
+
}
|
541 |
|
542 |
//Multilingual support.
|
543 |
+
// load_plugin_textdomain( 'icwp-wpsf', false, basename( dirname( __FILE__ ) ) . '/languages' );
|
544 |
}
|
545 |
|
546 |
+
protected function createPluginSubMenuItems() {
|
547 |
+
|
548 |
+
if ( !$this->hasPermissionToView() ) {
|
549 |
+
return;
|
550 |
+
}
|
551 |
+
|
552 |
$this->m_aPluginMenu = array(
|
553 |
//Menu Page Title => Menu Item name, page ID (slug), callback function for this page - i.e. what to do/load.
|
554 |
+
$this->getSubmenuPageTitle( 'Firewall' ) => array( 'Firewall', $this->getSubmenuId('firewall'), 'onDisplayAll' ),
|
555 |
+
$this->getSubmenuPageTitle( 'Login Protect' ) => array( 'Login Protect', $this->getSubmenuId('login_protect'), 'onDisplayAll' ),
|
556 |
+
$this->getSubmenuPageTitle( 'Comments Filter' ) => array( 'Comments Filter', $this->getSubmenuId('comments_filter'), 'onDisplayAll' ),
|
557 |
+
$this->getSubmenuPageTitle( 'Lockdown' ) => array( 'Lockdown', $this->getSubmenuId('lockdown'), 'onDisplayAll' ),
|
558 |
+
$this->getSubmenuPageTitle( 'Auto Updates' ) => array( 'Auto Updates', $this->getSubmenuId('autoupdates'), 'onDisplayAll' ),
|
559 |
+
$this->getSubmenuPageTitle( 'Log' ) => array( 'Log', $this->getSubmenuId('firewall_log'), 'onDisplayAll' )
|
560 |
);
|
561 |
+
}
|
562 |
+
|
|
|
|
|
|
|
563 |
protected function handlePluginUpgrade() {
|
564 |
+
parent::handlePluginUpgrade();
|
565 |
|
566 |
+
$sCurrentPluginVersion = $this->m_oWpsfOptions->getOpt( 'current_plugin_version' );
|
567 |
|
568 |
if ( $sCurrentPluginVersion !== self::$VERSION && current_user_can( 'manage_options' ) ) {
|
569 |
+
|
570 |
+
self::deleteOption( 'enable_firewall' );
|
571 |
+
self::deleteOption( 'enable_login_protect' );
|
572 |
+
self::deleteOption( 'enable_comments_filter' );
|
573 |
+
|
574 |
+
$this->loadProcessor( 'Logging' );
|
575 |
+
$this->m_oLoggingProcessor->handleInstallUpgrade( $sCurrentPluginVersion );
|
576 |
+
|
577 |
+
// handles migration to new dedicated options system
|
578 |
+
$this->loadOptionsHandler( 'all' );
|
579 |
|
580 |
+
// clears all the processor caches
|
581 |
+
$this->clearCaches();
|
582 |
|
583 |
+
// delete all the old stuff
|
584 |
+
$aOldOptionKeys = array (
|
585 |
+
'current_plugin_version',
|
586 |
+
'feedback_admin_notice',
|
587 |
+
'secret_key',
|
588 |
+
'block_send_email',
|
589 |
+
'block_send_email_address',
|
590 |
+
'send_email_throttle_limit',
|
591 |
+
'delete_on_deactivate',
|
592 |
+
'include_cookie_checks',
|
593 |
+
'block_dir_traversal',
|
594 |
+
'block_sql_queries',
|
595 |
+
'block_wordpress_terms',
|
596 |
+
'block_field_truncation',
|
597 |
+
'block_exe_file_uploads',
|
598 |
+
'block_leading_schema',
|
599 |
+
'ips_whitelist',
|
600 |
+
'ips_blacklist',
|
601 |
+
'page_params_whitelist',
|
602 |
+
'block_response',
|
603 |
+
'enable_firewall_log',
|
604 |
+
'enable_two_factor_auth_by_ip',
|
605 |
+
'enable_two_factor_bypass_on_email_fail',
|
606 |
+
'login_limit_interval',
|
607 |
+
'enable_login_gasp_check',
|
608 |
+
'enable_login_protect_log'
|
609 |
+
);
|
610 |
+
foreach( $aOldOptionKeys as $sOptionKey ) {
|
611 |
+
self::deleteOption( $sOptionKey );
|
612 |
+
}
|
613 |
}//if
|
614 |
|
615 |
//Someone clicked the button to acknowledge the update
|
616 |
if ( isset( $_POST[self::OptionPrefix.'hide_update_notice'] ) && isset( $_POST['user_id'] ) ) {
|
617 |
+
$this->updateVersionUserMeta( $_POST['user_id'] );
|
|
|
618 |
if ( $this->isShowMarketing() ) {
|
619 |
wp_redirect( admin_url( "admin.php?page=".$this->getFullParentMenuId() ) );
|
620 |
}
|
624 |
}
|
625 |
}
|
626 |
|
627 |
+
/**
|
628 |
+
* Updates the current (or supplied user ID) user meta data with the version of the plugin
|
629 |
+
*
|
630 |
+
* @param unknown_type $innId
|
631 |
+
*/
|
632 |
+
protected function updateVersionUserMeta( $innId = null ) {
|
633 |
+
if ( is_null( $innId ) ) {
|
634 |
+
$oCurrentUser = wp_get_current_user();
|
635 |
+
if ( !($oCurrentUser instanceof WP_User) ) {
|
636 |
+
return;
|
637 |
+
}
|
638 |
+
$nUserId = $oCurrentUser->ID;
|
639 |
+
}
|
640 |
+
else {
|
641 |
+
$nUserId = $innId;
|
642 |
+
}
|
643 |
+
update_user_meta( $nUserId, self::OptionPrefix.'current_version', self::$VERSION );
|
644 |
+
}
|
645 |
+
|
646 |
public function onWpAdminNotices() {
|
647 |
+
// Do we have admin priviledges?
|
|
|
648 |
if ( !current_user_can( 'manage_options' ) ) {
|
649 |
return;
|
650 |
}
|
651 |
+
parent::onWpAdminNotices();
|
652 |
$this->adminNoticeOptionsUpdated();
|
653 |
+
|
654 |
+
if ( $this->hasPermissionToView() ) {
|
655 |
+
$this->adminNoticeVersionUpgrade();
|
656 |
+
}
|
657 |
}
|
658 |
|
659 |
/**
|
660 |
+
* Displaying all views now goes through this central function and we work out
|
661 |
+
* what to display based on the name of current hook/filter being processed.
|
662 |
*/
|
663 |
+
public function onDisplayAll() {
|
664 |
+
|
665 |
+
if ( !$this->hasPermissionToView() ) {
|
666 |
+
$this->onDisplayAccessKeyRequest();
|
667 |
return;
|
668 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
669 |
|
670 |
+
$sPrefix = 'simple-firewall_page_icwp-wpsf-';
|
671 |
+
$sCurrent = str_replace( $sPrefix, '', current_filter() );
|
|
|
672 |
|
673 |
+
switch( $sCurrent ) {
|
674 |
+
case 'toplevel_page_'.self::ParentMenuId.'-wpsf' : //special case
|
675 |
+
$this->onDisplayMainMenu();
|
676 |
+
break;
|
677 |
+
case 'firewall_log' :
|
678 |
+
$this->onDisplayFirewallLog();
|
679 |
+
break;
|
680 |
+
default:
|
681 |
+
$aFeatures = $this->getFeaturesMap();
|
682 |
+
$this->loadOptionsHandler( $aFeatures[$sCurrent] );
|
683 |
+
$sOptionsName = 'm_o'.$aFeatures[$sCurrent].'Options';
|
684 |
+
$this->onDisplayConfig( $this->{$sOptionsName}, $sCurrent );
|
685 |
+
break;
|
686 |
}
|
687 |
+
}
|
688 |
+
|
689 |
+
public function onDisplayAccessKeyRequest() {
|
690 |
+
|
691 |
+
// Since this is always called until we have Permission, we have to handle the plugin
|
692 |
+
// form submission here too.
|
693 |
+
$aData = array(
|
694 |
+
'plugin_url' => self::$PLUGIN_URL,
|
695 |
+
'var_prefix' => self::OptionPrefix,
|
696 |
+
'nonce_field' => $this->getSubmenuId( 'wpsf-access-key' ),
|
697 |
+
'form_action' => 'admin.php?page='.$this->getSubmenuId()
|
698 |
+
);
|
699 |
+
$this->display( 'icwp_wpsf_access_key_request_index', $aData );
|
700 |
+
}
|
701 |
|
702 |
public function onDisplayMainMenu() {
|
703 |
|
704 |
+
// Just to ensure the nag bar disappears if/when they visit the dashboard
|
705 |
+
// regardless of clicking the button.
|
706 |
+
$this->updateVersionUserMeta();
|
707 |
+
|
708 |
+
$this->loadOptionsHandler( 'all' );
|
709 |
+
$aAvailableOptions = $this->m_oWpsfOptions->getOptions();
|
710 |
+
$sAllFormInputOptions = $this->m_oWpsfOptions->collateAllFormInputsForAllOptions();
|
711 |
|
712 |
$aData = array(
|
713 |
'plugin_url' => self::$PLUGIN_URL,
|
714 |
+
'var_prefix' => self::OptionPrefix,
|
715 |
'aAllOptions' => $aAvailableOptions,
|
716 |
'fShowAds' => $this->isShowMarketing(),
|
717 |
+
'all_options_input' => $sAllFormInputOptions,
|
718 |
+
'nonce_field' => $this->getSubmenuId('wpsf-dashboard'),
|
719 |
+
'form_action' => 'admin.php?page='.$this->getSubmenuId()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
720 |
);
|
721 |
|
722 |
+
$aData['aMainOptions'] = $this->m_oWpsfOptions->getPluginOptionsValues();
|
723 |
+
|
724 |
+
if ( $this->getIsMainFeatureEnabled('firewall') ) {
|
725 |
+
$this->loadOptionsHandler( 'Firewall' );
|
726 |
+
$aData['aFirewallOptions'] = $this->m_oFirewallOptions->getPluginOptionsValues();
|
727 |
+
}
|
728 |
+
if ( $this->getIsMainFeatureEnabled('login_protect') ) {
|
729 |
+
$this->loadOptionsHandler( 'LoginProtect' );
|
730 |
+
$aData['aLoginProtectOptions'] = $this->m_oLoginProtectOptions->getPluginOptionsValues();
|
731 |
+
}
|
732 |
+
if ( $this->getIsMainFeatureEnabled('comments_filter') ) {
|
733 |
+
$this->loadOptionsHandler( 'CommentsFilter' );
|
734 |
+
$aData['aCommentsFilterOptions'] = $this->m_oCommentsFilterOptions->getPluginOptionsValues();
|
735 |
+
}
|
736 |
+
if ( $this->getIsMainFeatureEnabled('lockdown') ) {
|
737 |
+
$this->loadOptionsHandler( 'Lockdown' );
|
738 |
+
$aData['aLockdownOptions'] = $this->m_oLockdownOptions->getPluginOptionsValues();
|
739 |
+
}
|
740 |
+
if ( $this->getIsMainFeatureEnabled('autoupdates') ) {
|
741 |
+
$this->loadOptionsHandler( 'AutoUpdates' );
|
742 |
+
$aData['aAutoUpdatesOptions'] = $this->m_oAutoUpdatesOptions->getPluginOptionsValues();
|
743 |
+
}
|
744 |
+
|
745 |
$this->display( 'icwp_'.$this->m_sParentMenuIdSuffix.'_index', $aData );
|
746 |
}
|
747 |
|
748 |
+
protected function onDisplayFirewallLog() {
|
749 |
+
|
750 |
+
$this->loadOptionsHandler( 'Firewall' );
|
751 |
+
$aIpWhitelist = $this->m_oFirewallOptions->getOpt( 'ips_whitelist' );
|
752 |
+
$aIpBlacklist = $this->m_oFirewallOptions->getOpt( 'ips_blacklist' );
|
753 |
|
754 |
+
$this->loadProcessor( 'Logging' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
755 |
|
|
|
756 |
$aData = array(
|
757 |
'plugin_url' => self::$PLUGIN_URL,
|
758 |
'var_prefix' => self::OptionPrefix,
|
759 |
+
'firewall_log' => $this->m_oLoggingProcessor->getLogs( true ),
|
760 |
+
'ip_whitelist' => isset( $aIpWhitelist['ips'] )? $aIpWhitelist['ips'] : array(),
|
761 |
+
'ip_blacklist' => isset( $aIpBlacklist['ips'] )? $aIpBlacklist['ips'] : array(),
|
762 |
'fShowAds' => $this->isShowMarketing(),
|
763 |
+
'nonce_field' => $this->getSubmenuId('firewall_log'),
|
764 |
+
'form_action' => 'admin.php?page='.$this->getSubmenuId('firewall_log'),
|
|
|
|
|
765 |
);
|
766 |
|
767 |
+
$this->display( 'icwp_wpsf_firewall_log_index', $aData );
|
768 |
}
|
769 |
|
770 |
+
/**
|
771 |
+
*
|
772 |
+
* @param ICWP_OptionsHandler_Base_WPSF $inoOptions
|
773 |
+
* @param string $insSlug
|
774 |
+
*/
|
775 |
+
protected function onDisplayConfig( $inoOptions, $insSlug ) {
|
776 |
|
777 |
+
$aAvailableOptions = $inoOptions->getOptions();
|
778 |
+
$sAllFormInputOptions = $inoOptions->collateAllFormInputsForAllOptions();
|
779 |
+
|
780 |
$aData = array(
|
781 |
'plugin_url' => self::$PLUGIN_URL,
|
782 |
'var_prefix' => self::OptionPrefix,
|
|
|
783 |
'fShowAds' => $this->isShowMarketing(),
|
784 |
+
'aAllOptions' => $aAvailableOptions,
|
785 |
+
'all_options_input' => $sAllFormInputOptions,
|
786 |
+
'nonce_field' => $this->getSubmenuId( $insSlug ),
|
787 |
+
'form_action' => 'admin.php?page='.$this->getSubmenuId( $insSlug ),
|
788 |
);
|
789 |
+
$this->display( 'icwp_wpsf_config_'.$insSlug.'_index', $aData );
|
790 |
+
}
|
791 |
+
|
792 |
+
protected function isPluginFormSubmit() {
|
793 |
+
|
794 |
+
$aPostSubmitOptions = array(
|
795 |
+
'icwp_plugin_form_submit',
|
796 |
+
'icwp_link_action',
|
797 |
+
'icwp_wpsf_admin_access_key_request'
|
798 |
+
);
|
799 |
+
|
800 |
+
foreach( $aPostSubmitOptions as $sOption ) {
|
801 |
+
if ( isset( $_POST[$sOption] ) || isset( $_GET[$sOption] ) ) {
|
802 |
+
return true;
|
803 |
+
}
|
804 |
+
}
|
805 |
+
return false;
|
806 |
}
|
807 |
|
808 |
protected function handlePluginFormSubmit() {
|
809 |
|
810 |
+
//should have already been checked, but just to make sure.
|
811 |
+
if ( !$this->isPluginFormSubmit() ) {
|
812 |
+
return false;
|
813 |
+
}
|
814 |
+
|
815 |
+
if ( isset( $_POST['icwp_wpsf_admin_access_key_request'] ) ) {
|
816 |
+
return $this->handleSubmit_AccessKeyRequest();
|
817 |
+
}
|
818 |
+
|
819 |
+
if ( !$this->hasPermissionToSubmit() ) {
|
820 |
+
return false;
|
821 |
}
|
822 |
|
823 |
if ( isset( $_GET['page'] ) ) {
|
824 |
switch ( $_GET['page'] ) {
|
825 |
+
case $this->getSubmenuId():
|
826 |
+
$this->handleSubmit_Dashboard();
|
827 |
break;
|
828 |
+
case $this->getSubmenuId( 'firewall' ):
|
829 |
+
$this->handleSubmit_FirewallConfig();
|
830 |
+
break;
|
831 |
+
case $this->getSubmenuId( 'login_protect' ):
|
832 |
+
$this->handleSubmit_LoginProtect();
|
833 |
+
break;
|
834 |
+
case $this->getSubmenuId( 'comments_filter' ):
|
835 |
+
$this->handleSubmit_CommentsFilter();
|
836 |
+
break;
|
837 |
+
case $this->getSubmenuId( 'lockdown' ):
|
838 |
+
$this->handleSubmit_Lockdown();
|
839 |
+
break;
|
840 |
+
case $this->getSubmenuId( 'autoupdates' ):
|
841 |
+
$this->handleSubmit_AutoUpdates();
|
842 |
+
break;
|
843 |
+
case $this->getSubmenuId( 'firewall_log' ):
|
844 |
$this->handleSubmit_FirewallLog();
|
845 |
break;
|
846 |
+
default:
|
847 |
+
return false;
|
848 |
+
break;
|
849 |
}
|
850 |
}
|
851 |
+
$this->resetLoggingProcessor();
|
852 |
+
return true;
|
853 |
+
}
|
854 |
+
|
855 |
+
protected function setPermissionToSubmit( $infPermission = false ) {
|
856 |
|
857 |
+
if ( $infPermission ) {
|
858 |
+
$sValue = $this->m_oWpsfOptions->getOpt( 'admin_access_key' );
|
859 |
+
$sTimeout = $this->m_oWpsfOptions->getOpt( 'admin_access_timeout' ) * 60;
|
860 |
+
$_COOKIE[ self::AdminAccessKeyCookieName ] = 1;
|
861 |
+
setcookie( self::AdminAccessKeyCookieName, $sValue, time()+$sTimeout, COOKIEPATH, COOKIE_DOMAIN, false );
|
862 |
}
|
863 |
else {
|
864 |
+
unset( $_COOKIE[ self::AdminAccessKeyCookieName ] );
|
865 |
+
setcookie( self::AdminAccessKeyCookieName, "", time()-3600, COOKIEPATH, COOKIE_DOMAIN, false );
|
866 |
+
}
|
867 |
+
}
|
868 |
+
|
869 |
+
/**
|
870 |
+
* @return boolean
|
871 |
+
*/
|
872 |
+
protected function hasPermissionToView() {
|
873 |
+
// For now we just use the submit permissions and we can adapt it later
|
874 |
+
return $this->hasPermissionToSubmit();
|
875 |
+
}
|
876 |
+
|
877 |
+
/**
|
878 |
+
* @return boolean
|
879 |
+
*/
|
880 |
+
protected function hasPermissionToSubmit() {
|
881 |
+
|
882 |
+
// first a basic admin check
|
883 |
+
if ( !is_super_admin() ) {
|
884 |
+
return false;
|
885 |
}
|
886 |
|
887 |
+
if ( $this->m_oWpsfOptions->getOpt( 'enable_admin_access_restriction' ) == 'Y' ) {
|
888 |
+
$sAccessKey = $this->m_oWpsfOptions->getOpt( 'admin_access_key' );
|
889 |
+
if ( !empty( $sAccessKey ) ) {
|
890 |
+
if ( isset( $_COOKIE[ self::AdminAccessKeyCookieName ] )
|
891 |
+
// && $_COOKIE[ self::AdminAccessKeyCookieName ] == $sAccessKey
|
892 |
+
) {
|
893 |
+
return true;
|
894 |
+
}
|
895 |
+
else {
|
896 |
+
return false;
|
897 |
+
}
|
898 |
+
}
|
899 |
+
}
|
900 |
+
return true;
|
901 |
}
|
902 |
|
903 |
+
protected function handleSubmit_AccessKeyRequest() {
|
904 |
//Ensures we're actually getting this request from WP.
|
905 |
+
check_admin_referer( $this->getSubmenuId('wpsf-access-key') );
|
906 |
+
|
907 |
+
$this->loadOptionsHandler( 'Wpsf' );
|
908 |
+
$sAccessKey = md5( trim( $_POST['icwp_wpsf_admin_access_key_request'] ) );
|
909 |
+
$sStoredAccessKey = $this->m_oWpsfOptions->getOpt( 'admin_access_key' );
|
910 |
|
911 |
+
if ( $sAccessKey === $sStoredAccessKey ) {
|
912 |
+
$this->setPermissionToSubmit( true );
|
913 |
+
header( 'Location: '.admin_url('admin.php?page=icwp-wpsf') );
|
914 |
+
exit();
|
915 |
+
}
|
916 |
+
return false;
|
917 |
+
}
|
918 |
+
|
919 |
+
protected function handleSubmit_Dashboard() {
|
920 |
+
//Ensures we're actually getting this request from WP.
|
921 |
+
check_admin_referer( $this->getSubmenuId('wpsf-dashboard') );
|
922 |
+
|
923 |
+
if ( !isset($_POST[self::OptionPrefix.'all_options_input']) ) {
|
924 |
+
return false;
|
925 |
+
}
|
926 |
+
|
927 |
+
$this->loadOptionsHandler( 'Wpsf' );
|
928 |
+
$this->m_oWpsfOptions->updatePluginOptionsFromSubmit( $_POST[self::OptionPrefix.'all_options_input'] );
|
929 |
+
|
930 |
+
$this->setSharedOption( 'enable_firewall', $this->m_oWpsfOptions->getOpt( 'enable_firewall' ) );
|
931 |
+
$this->setSharedOption( 'enable_login_protect', $this->m_oWpsfOptions->getOpt( 'enable_login_protect' ) );
|
932 |
+
$this->setSharedOption( 'enable_comments_filter', $this->m_oWpsfOptions->getOpt( 'enable_comments_filter' ) );
|
933 |
+
$this->setSharedOption( 'enable_lockdown', $this->m_oWpsfOptions->getOpt( 'enable_lockdown' ) );
|
934 |
+
$this->setSharedOption( 'enable_autoupdates', $this->m_oWpsfOptions->getOpt( 'enable_autoupdates' ) );
|
935 |
+
|
936 |
+
$this->clearCaches();
|
937 |
+
}
|
938 |
+
|
939 |
+
protected function handleSubmit_FirewallConfig() {
|
940 |
+
//Ensures we're actually getting this request from WP.
|
941 |
+
check_admin_referer( $this->getSubmenuId( 'firewall' ) );
|
942 |
+
|
943 |
+
if ( isset($_POST[ 'import-wpf2-submit' ] ) ) {
|
944 |
+
$this->importFromFirewall2Plugin();
|
945 |
+
}
|
946 |
+
else if ( !isset($_POST[self::OptionPrefix.'all_options_input']) ) {
|
947 |
+
return;
|
948 |
+
}
|
949 |
+
else {
|
950 |
+
$this->loadOptionsHandler( 'Firewall' );
|
951 |
+
$this->m_oFirewallOptions->updatePluginOptionsFromSubmit( $_POST[self::OptionPrefix.'all_options_input'] );
|
952 |
+
}
|
953 |
+
$this->setSharedOption( 'enable_firewall', $this->m_oFirewallOptions->getOpt( 'enable_firewall' ) );
|
954 |
+
$this->resetFirewallProcessor();
|
955 |
+
}
|
956 |
+
|
957 |
+
protected function handleSubmit_LoginProtect() {
|
958 |
+
//Ensures we're actually getting this request from WP.
|
959 |
+
check_admin_referer( $this->getSubmenuId('login_protect' ) );
|
960 |
|
961 |
if ( !isset($_POST[self::OptionPrefix.'all_options_input']) ) {
|
962 |
return;
|
963 |
}
|
964 |
+
$this->loadOptionsHandler( 'LoginProtect' );
|
965 |
+
$this->m_oLoginProtectOptions->updatePluginOptionsFromSubmit( $_POST[self::OptionPrefix.'all_options_input'] );
|
966 |
+
$this->setSharedOption( 'enable_login_protect', $this->m_oLoginProtectOptions->getOpt( 'enable_login_protect' ) );
|
967 |
+
$this->resetLoginProcessor();
|
968 |
}
|
969 |
|
970 |
+
protected function handleSubmit_CommentsFilter() {
|
971 |
//Ensures we're actually getting this request from WP.
|
972 |
+
check_admin_referer( $this->getSubmenuId('comments_filter' ) );
|
973 |
+
|
974 |
+
if ( !isset($_POST[self::OptionPrefix.'all_options_input']) ) {
|
975 |
+
return;
|
976 |
+
}
|
977 |
+
$this->loadOptionsHandler( 'CommentsFilter' );
|
978 |
+
$this->m_oCommentsFilterOptions->updatePluginOptionsFromSubmit( $_POST[self::OptionPrefix.'all_options_input'] );
|
979 |
+
$this->setSharedOption( 'enable_comments_filter', $this->m_oCommentsFilterOptions->getOpt( 'enable_comments_filter' ) );
|
980 |
+
$this->resetCommentsProcessor();
|
981 |
+
}
|
982 |
+
|
983 |
+
protected function handleSubmit_Lockdown() {
|
984 |
+
//Ensures we're actually getting this request from WP.
|
985 |
+
check_admin_referer( $this->getSubmenuId('lockdown' ) );
|
986 |
+
|
987 |
+
if ( !isset($_POST[self::OptionPrefix.'all_options_input']) ) {
|
988 |
+
return;
|
989 |
+
}
|
990 |
+
$this->loadOptionsHandler( 'Lockdown' );
|
991 |
+
$this->m_oLockdownOptions->updatePluginOptionsFromSubmit( $_POST[self::OptionPrefix.'all_options_input'] );
|
992 |
+
$this->setSharedOption( 'enable_lockdown', $this->m_oLockdownOptions->getOpt( 'enable_lockdown' ) );
|
993 |
+
$this->resetLockdownProcessor();
|
994 |
+
}
|
995 |
+
|
996 |
+
protected function handleSubmit_AutoUpdates() {
|
997 |
+
//Ensures we're actually getting this request from WP.
|
998 |
+
check_admin_referer( $this->getSubmenuId( 'autoupdates' ) );
|
999 |
+
|
1000 |
+
if ( !isset($_POST[self::OptionPrefix.'all_options_input']) ) {
|
1001 |
+
return;
|
1002 |
+
}
|
1003 |
+
$this->loadOptionsHandler( 'AutoUpdates' );
|
1004 |
+
$this->m_oAutoUpdatesOptions->updatePluginOptionsFromSubmit( $_POST[self::OptionPrefix.'all_options_input'] );
|
1005 |
+
$this->setSharedOption( 'enable_autoupdates', $this->m_oAutoUpdatesOptions->getOpt( 'enable_autoupdates' ) );
|
1006 |
+
$this->resetAutoUpdatesProcessor();
|
1007 |
+
}
|
1008 |
+
|
1009 |
+
protected function handleSubmit_FirewallLog() {
|
1010 |
+
|
1011 |
+
// Ensures we're actually getting this request from a valid WP submission.
|
1012 |
+
if ( !isset( $_REQUEST['_wpnonce'] ) || !wp_verify_nonce( $_REQUEST['_wpnonce'], $this->getSubmenuId( 'firewall_log' ) ) ) {
|
1013 |
+
wp_die();
|
1014 |
+
}
|
1015 |
|
1016 |
// At the time of writing the page only has 1 form submission item - clear log
|
1017 |
+
if ( isset( $_POST['clear_log_submit'] ) ) {
|
1018 |
+
$this->loadProcessor( 'Logging' );
|
1019 |
+
$this->m_oLoggingProcessor->recreateTable();
|
1020 |
+
}
|
1021 |
+
else if ( isset( $_GET['blackip'] ) ) {
|
1022 |
+
$this->addRawIpsToFirewallList( 'ips_blacklist', array( $_GET['blackip'] ) );
|
1023 |
+
}
|
1024 |
+
else if ( isset( $_GET['unblackip'] ) ) {
|
1025 |
+
$this->removeRawIpsFromFirewallList( 'ips_blacklist', array( $_GET['unblackip'] ) );
|
1026 |
+
}
|
1027 |
+
else if ( isset( $_GET['whiteip'] ) ) {
|
1028 |
+
$this->addRawIpsToFirewallList( 'ips_whitelist', array( $_GET['whiteip'] ) );
|
1029 |
+
}
|
1030 |
+
else if ( isset( $_GET['unwhiteip'] ) ) {
|
1031 |
+
$this->removeRawIpsFromFirewallList( 'ips_whitelist', array( $_GET['unwhiteip'] ) );
|
1032 |
+
}
|
1033 |
+
wp_safe_redirect( admin_url( "admin.php?page=".$this->getSubmenuId('firewall_log') ) ); //means no admin message is displayed
|
1034 |
exit();
|
1035 |
}
|
1036 |
|
1037 |
+
public function clearCaches() {
|
1038 |
+
$this->resetFirewallProcessor();
|
1039 |
+
$this->resetLoginProcessor();
|
1040 |
+
$this->resetLoggingProcessor();
|
1041 |
+
$this->resetCommentsProcessor();
|
1042 |
+
}
|
1043 |
+
|
1044 |
+
protected function resetEmailProcessor() {
|
1045 |
+
$this->m_oEmailProcessor = false;
|
1046 |
+
self::deleteOption( 'email_processor' );
|
1047 |
+
$this->loadProcessor( 'Email' );
|
1048 |
+
}
|
1049 |
+
|
1050 |
+
protected function resetFirewallProcessor() {
|
1051 |
+
$this->resetEmailProcessor();
|
1052 |
+
$this->m_oFirewallProcessor = false;
|
1053 |
+
self::deleteOption( 'firewall_processor' );
|
1054 |
+
$this->loadProcessor( 'Firewall' );
|
1055 |
+
}
|
1056 |
+
|
1057 |
+
protected function resetLoginProcessor() {
|
1058 |
+
$this->m_oLoginProtectProcessor = false;
|
1059 |
+
self::deleteOption( 'login_processor' );
|
1060 |
+
$this->loadProcessor( 'LoginProtect' );
|
1061 |
+
}
|
1062 |
+
|
1063 |
+
protected function resetCommentsProcessor() {
|
1064 |
+
$this->m_oCommentsFilterProcessor = false;
|
1065 |
+
self::deleteOption( 'comments_processor' );
|
1066 |
+
$this->loadProcessor( 'CommentsFilter' );
|
1067 |
+
}
|
1068 |
+
|
1069 |
+
protected function resetLockdownProcessor() {
|
1070 |
+
$this->m_oLockdownProcessor = false;
|
1071 |
+
self::deleteOption( 'lockdown_processor' );
|
1072 |
+
$this->loadProcessor( 'Lockdown' );
|
1073 |
+
}
|
1074 |
+
|
1075 |
+
protected function resetAutoUpdatesProcessor() {
|
1076 |
+
$this->m_oLockdownProcessor = false;
|
1077 |
+
self::deleteOption( 'autoupdates_processor' );
|
1078 |
+
$this->loadProcessor( 'AutoUpdates' );
|
1079 |
+
}
|
1080 |
+
|
1081 |
+
protected function resetLoggingProcessor() {
|
1082 |
+
$this->m_oLoggingProcessor = false;
|
1083 |
+
self::deleteOption( 'logging_processor' );
|
1084 |
+
$this->loadProcessor( 'Logging' );
|
1085 |
}
|
1086 |
|
1087 |
+
protected function importFromFirewall2Plugin() {
|
1088 |
+
$this->loadOptionsHandler( 'all' );
|
1089 |
+
require_once( dirname(__FILE__).'/src/icwp-import-wpf2-processor.php' );
|
1090 |
+
$oImportProcessor = new ICWP_ImportWpf2Processor( $this->m_oWpsfOptions, $this->m_oFirewallOptions );
|
1091 |
+
$oImportProcessor->runImport();
|
1092 |
}
|
1093 |
|
1094 |
+
public function onWpPluginActionLinks( $inaActionLinks, $insFile ) {
|
1095 |
+
|
1096 |
if ( $insFile == plugin_basename( __FILE__ ) ) {
|
1097 |
+
if ( !$this->hasPermissionToSubmit() ) {
|
1098 |
+
if ( array_key_exists( 'edit', $inaActionLinks ) ) {
|
1099 |
+
unset( $inaActionLinks['edit'] );
|
1100 |
+
}
|
1101 |
+
if ( array_key_exists( 'deactivate', $inaActionLinks ) ) {
|
1102 |
+
unset( $inaActionLinks['deactivate'] );
|
1103 |
+
}
|
1104 |
+
}
|
1105 |
+
$sSettingsLink = '<a href="'.admin_url( "admin.php" ).'?page='.$this->getSubmenuId().'">' . 'Dashboard' . '</a>';
|
1106 |
+
array_unshift( $inaActionLinks, $sSettingsLink );
|
1107 |
}
|
1108 |
+
return $inaActionLinks;
|
1109 |
+
}
|
1110 |
+
|
1111 |
+
public function onWpPluginsLoaded() {
|
1112 |
+
parent::onWpPluginsLoaded();
|
1113 |
+
|
1114 |
+
if ( $this->isValidAdminArea()
|
1115 |
+
&& $this->m_oWpsfOptions->getOpt('enable_upgrade_admin_notice') == 'Y'
|
1116 |
+
&& $this->hasPermissionToSubmit()
|
1117 |
+
) {
|
1118 |
+
$this->m_fDoAutoUpdateCheck = true;
|
1119 |
+
}
|
1120 |
+
|
1121 |
+
add_action( 'deactivate_plugin', array( $this, 'preventDeactivation' ), 1, 1 );
|
1122 |
+
$this->removePluginConflicts(); // removes conflicts with other plugins
|
1123 |
+
}
|
1124 |
+
|
1125 |
+
/**
|
1126 |
+
* @param string $insPlugin - the path to the plugin file
|
1127 |
+
*/
|
1128 |
+
public function preventDeactivation( $insPlugin ) {
|
1129 |
+
if ( strpos( $insPlugin, basename(__FILE__) ) !== false && !$this->hasPermissionToSubmit() ) {
|
1130 |
+
wp_die( 'Sorry, you do not have permission to disable this plugin. You need to authenticate first.' );
|
1131 |
+
}
|
1132 |
+
}
|
1133 |
+
|
1134 |
+
public function onWpShutdown() {
|
1135 |
+
parent::onWpShutdown();
|
1136 |
+
$this->saveProcessors_Action();
|
1137 |
}
|
1138 |
|
1139 |
protected function deleteAllPluginDbOptions() {
|
1140 |
|
1141 |
parent::deleteAllPluginDbOptions();
|
|
|
1142 |
if ( !current_user_can( 'manage_options' ) ) {
|
1143 |
return;
|
1144 |
}
|
1145 |
|
1146 |
+
$this->loadProcessor( 'Logging' );
|
1147 |
+
$this->m_oLoggingProcessor->dropTable();
|
1148 |
+
|
1149 |
+
$this->loadProcessor( 'LoginProtect' );
|
1150 |
+
$this->m_oLoginProtectProcessor->dropTable();
|
1151 |
+
|
1152 |
+
$this->loadProcessor( 'CommentsFilter' );
|
1153 |
+
$this->m_oCommentsFilterProcessor->dropTable();
|
1154 |
+
|
1155 |
+
$aOptions = $this->getAllOptions();
|
1156 |
+
foreach( $aOptions as &$oOption ) {
|
1157 |
+
$oOption->deletePluginOptions();
|
1158 |
+
}
|
1159 |
+
remove_action( 'shutdown', array( $this, 'onWpShutdown' ) );
|
1160 |
+
}
|
1161 |
+
|
1162 |
+
public function onWpPluginUpdateMessage() {
|
1163 |
+
echo '<div style="color: #dd3333;">'
|
1164 |
+
."Upgrade Now To Keep Your Firewall Up-To-Date With The Latest Features."
|
1165 |
+
. '</div>';
|
1166 |
}
|
1167 |
|
1168 |
public function onWpDeactivatePlugin() {
|
1169 |
+
if ( $this->m_oWpsfOptions->getOpt( 'delete_on_deactivate' ) == 'Y' ) {
|
|
|
1170 |
$this->deleteAllPluginDbOptions();
|
1171 |
}
|
1172 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1173 |
|
1174 |
public function enqueueBootstrapAdminCss() {
|
1175 |
wp_register_style( 'worpit_bootstrap_wpadmin_css', $this->getCssUrl( 'bootstrap-wpadmin.css' ), false, self::$VERSION );
|
1178 |
wp_enqueue_style( 'worpit_bootstrap_wpadmin_css_fixes' );
|
1179 |
}
|
1180 |
|
1181 |
+
public function addRawIpsToFirewallList( $insListName, $inaNewIps ) {
|
|
|
|
|
|
|
1182 |
|
1183 |
+
$this->loadOptionsHandler( 'Firewall' );
|
1184 |
+
|
1185 |
+
$aIplist = $this->m_oFirewallOptions->getOpt( $insListName );
|
1186 |
+
if ( empty( $aIplist ) ) {
|
1187 |
+
$aIplist = array();
|
1188 |
}
|
1189 |
+
$aNewList = array();
|
1190 |
+
foreach( $inaNewIps as $sAddress ) {
|
1191 |
+
$aNewList[ $sAddress ] = '';
|
|
|
1192 |
}
|
1193 |
+
$aIplist = $this->m_oFirewallOptions->setOpt( $insListName, ICWP_DataProcessor::Add_New_Raw_Ips( $aIplist, $aNewList ) );
|
1194 |
+
$this->resetFirewallProcessor();
|
1195 |
+
}
|
1196 |
+
|
1197 |
+
public function removeRawIpsFromFirewallList( $insListName, $inaRemoveIps ) {
|
1198 |
|
1199 |
+
$this->loadOptionsHandler( 'Firewall' );
|
1200 |
+
|
1201 |
+
$aIplist = $this->m_oFirewallOptions->getOpt( $insListName );
|
1202 |
+
if ( empty( $aIplist ) || empty( $inaRemoveIps ) ) {
|
1203 |
+
return;
|
1204 |
}
|
1205 |
+
$aIplist = $this->m_oFirewallOptions->setOpt( $insListName, ICWP_DataProcessor::Remove_Raw_Ips( $aIplist, $inaRemoveIps ) );
|
1206 |
+
$this->resetFirewallProcessor();
|
1207 |
+
}
|
1208 |
+
|
1209 |
+
/**
|
1210 |
+
*/
|
1211 |
+
protected function filterIpLists() {
|
1212 |
+
|
1213 |
+
$nNewAddedCount = 0;
|
1214 |
+
$mResult = $this->processIpFilter( 'ips_whitelist', 'icwp_simple_firewall_whitelist_ips', $nNewAddedCount );
|
1215 |
+
if ( $mResult !== false && $nNewAddedCount > 0 ) {
|
1216 |
+
$this->m_oFirewallOptions->setOpt( 'ips_whitelist', $mResult );
|
1217 |
+
$this->resetFirewallProcessor();
|
1218 |
+
}
|
1219 |
+
|
1220 |
+
$nNewAddedCount = 0;
|
1221 |
+
$mResult = $this->processIpFilter( 'ips_blacklist', 'icwp_simple_firewall_blacklist_ips', $nNewAddedCount );
|
1222 |
+
if ( $mResult !== false && $nNewAddedCount > 0 ) {
|
1223 |
+
$this->m_oFirewallOptions->setOpt( 'ips_blacklist', $mResult );
|
1224 |
+
$this->resetFirewallProcessor();
|
1225 |
}
|
1226 |
}
|
1227 |
|
1228 |
+
/**
|
1229 |
+
* @param string $insExistingListKey
|
1230 |
+
* @param string $insFilterName
|
1231 |
+
* @param integer $outnNewAdded
|
1232 |
+
* @return array|false
|
1233 |
+
*/
|
1234 |
+
protected function processIpFilter( $insExistingListKey, $insFilterName, &$outnNewAdded = 0 ) {
|
1235 |
+
|
1236 |
+
$aFilterIps = array();
|
1237 |
+
$aFilterIps = apply_filters( $insFilterName, $aFilterIps );
|
1238 |
+
|
1239 |
+
if ( !empty( $aFilterIps ) ) {
|
1240 |
+
|
1241 |
+
$aNewIps = array();
|
1242 |
+
foreach( $aFilterIps as $mKey => $sValue ) {
|
1243 |
+
|
1244 |
+
if ( is_string( $mKey ) ) { //it's the IP
|
1245 |
+
$sIP = $mKey;
|
1246 |
+
$sLabel = $sValue;
|
1247 |
+
}
|
1248 |
+
else { //it's not an associative array, so the value is the IP
|
1249 |
+
$sIP = $sValue;
|
1250 |
+
$sLabel = '';
|
1251 |
+
}
|
1252 |
+
$aNewIps[ $sIP ] = $sLabel;
|
1253 |
+
}
|
1254 |
+
|
1255 |
+
// Get the existing list
|
1256 |
+
$this->loadOptionsHandler( 'Firewall' );
|
1257 |
+
$aExistingIpList = $this->m_oFirewallOptions->getOpt( $insExistingListKey );
|
1258 |
+
if ( !is_array( $aExistingIpList ) ) {
|
1259 |
+
$aExistingIpList = array();
|
1260 |
+
}
|
1261 |
+
return ICWP_DataProcessor::Add_New_Raw_Ips( $aExistingIpList, $aNewIps, $outnNewAdded );
|
1262 |
}
|
1263 |
+
return false;
|
1264 |
+
}
|
1265 |
+
|
1266 |
+
/**
|
1267 |
+
* Shows the update notification - will bail out if the current user is not an admin
|
1268 |
+
*/
|
1269 |
+
private function adminNoticeVersionUpgrade() {
|
1270 |
+
|
1271 |
+
$oCurrentUser = wp_get_current_user();
|
1272 |
+
if ( !($oCurrentUser instanceof WP_User) ) {
|
1273 |
+
return;
|
1274 |
}
|
1275 |
+
$nUserId = $oCurrentUser->ID;
|
1276 |
+
$sCurrentVersion = get_user_meta( $nUserId, self::OptionPrefix.'current_version', true );
|
1277 |
+
// A guard whereby if we can't ever get a value for this meta, it means we can never set it.
|
1278 |
+
// If we can never set it, we shouldn't force the Ads on those users who can't get rid of it.
|
1279 |
+
if ( empty( $sCurrentVersion ) ) { //the value has never been set, or it's been installed for the first time.
|
1280 |
+
$result = update_user_meta( $nUserId, self::OptionPrefix.'current_version', self::$VERSION );
|
1281 |
+
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.
|
1282 |
}
|
1283 |
+
|
1284 |
+
if ( $sCurrentVersion !== self::$VERSION ) {
|
1285 |
+
|
1286 |
+
$sRedirectPage = isset( $GLOBALS['pagenow'] ) ? $GLOBALS['pagenow'] : 'index.php';
|
1287 |
+
$sRedirectPage = 'admin.php?page=icwp-wpsf';
|
1288 |
+
ob_start();
|
1289 |
+
?>
|
1290 |
+
<style>
|
1291 |
+
a#fromIcwp { padding: 0 5px; border-bottom: 1px dashed rgba(0,0,0,0.1); color: blue; font-weight: bold; }
|
1292 |
+
</style>
|
1293 |
+
<form id="IcwpUpdateNotice" method="post" action="admin.php?page=<?php echo $this->getSubmenuId('firewall'); ?>">
|
1294 |
+
<input type="hidden" value="<?php echo $sRedirectPage; ?>" name="redirect_page" id="redirect_page">
|
1295 |
+
<input type="hidden" value="1" name="<?php echo self::OptionPrefix; ?>hide_update_notice" id="<?php echo self::OptionPrefix; ?>hide_update_notice">
|
1296 |
+
<input type="hidden" value="<?php echo $nUserId; ?>" name="user_id" id="user_id">
|
1297 |
+
<h4 style="margin:10px 0 3px;">
|
1298 |
+
Note: WordPress Simple Firewall plugin <u>does not automatically turn on</u> when you install/update. There may also be
|
1299 |
+
<a href="http://icwp.io/27" id="fromIcwp" title="WordPress Simple Firewall Plugin" target="_blank">important updates to read about</a>.
|
1300 |
+
</h4>
|
1301 |
+
<input type="submit" value="Okay, show me the dashboard." name="submit" class="button" style="float:left; margin-bottom:10px;">
|
1302 |
+
<div style="clear:both;"></div>
|
1303 |
+
</form>
|
1304 |
+
<?php
|
1305 |
+
$sNotice = ob_get_contents();
|
1306 |
+
ob_end_clean();
|
1307 |
+
$this->getAdminNotice( $sNotice, 'updated', true );
|
1308 |
+
}
|
1309 |
+
}
|
1310 |
+
|
1311 |
+
private function adminNoticeOptionsUpdated() {
|
1312 |
+
|
1313 |
+
$sAdminFeedbackNotice = $this->m_oWpsfOptions->getOpt( 'feedback_admin_notice' );
|
1314 |
+
if ( !empty( $sAdminFeedbackNotice ) ) {
|
1315 |
+
$sNotice = '<p>'.$sAdminFeedbackNotice.'</p>';
|
1316 |
+
$this->getAdminNotice( $sNotice, 'updated', true );
|
1317 |
+
$this->m_oWpsfOptions->setOpt( 'feedback_admin_notice', '' );
|
1318 |
}
|
|
|
1319 |
}
|
1320 |
}
|
1321 |
|
mode.login_throttled
ADDED
File without changes
|
readme.txt
CHANGED
@@ -1,46 +1,131 @@
|
|
1 |
=== Plugin Name ===
|
2 |
-
Contributors:
|
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
|
7 |
Requires at least: 3.2.0
|
8 |
-
Tested up to: 3.
|
9 |
-
Stable tag: 1.
|
10 |
|
11 |
-
|
12 |
|
13 |
== Description ==
|
14 |
|
15 |
-
|
|
|
16 |
|
17 |
-
|
18 |
-
that hasn't been updated for more than 2 years.
|
19 |
|
20 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
|
22 |
It adds extra features over WordPress Firewall 2, including:
|
23 |
|
24 |
-
*
|
25 |
-
*
|
26 |
-
* Option
|
27 |
-
|
28 |
-
|
|
|
|
|
|
|
29 |
turn back on the firewall using the same method.
|
30 |
-
*
|
31 |
-
|
32 |
-
*
|
33 |
-
*
|
34 |
-
*
|
35 |
-
useful for 3rd party services that connect to the site using other plugins.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
|
37 |
== Installation ==
|
38 |
|
39 |
See FAQs.
|
40 |
|
41 |
-
==
|
42 |
|
43 |
-
|
|
|
|
|
|
|
|
|
44 |
|
45 |
This plugin should install as any other WordPress.org respository plugin.
|
46 |
|
@@ -58,25 +143,32 @@ Alternatively using FTP:
|
|
58 |
|
59 |
A new menu item will appear on the left-hand side called 'Simple Firewall'.
|
60 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
61 |
= How does the IP Whitelist work? =
|
62 |
|
63 |
Any IP address that is on the whitelist will not be subject to any of the firewall scanning/processing. This setting takes priority over all other settings.
|
64 |
|
65 |
-
=
|
66 |
|
67 |
-
|
68 |
|
69 |
-
|
70 |
-
who's IP address is not on the whitelist.
|
71 |
|
72 |
-
|
73 |
|
74 |
-
|
75 |
-
* you
|
76 |
-
* you have at least 1 IP address in the IP Whitelist, and
|
77 |
-
* your current IP address is not on the IP Whitelist.
|
78 |
|
79 |
-
|
80 |
|
81 |
Here's how:
|
82 |
|
@@ -87,20 +179,268 @@ Here's how:
|
|
87 |
|
88 |
If you want to turn the firewall on in the same way, create a file called "forceOn".
|
89 |
|
90 |
-
Remember: If you leave one of these files on the server, it will override your on/off settings, so you should delete it when you
|
91 |
|
92 |
= Which takes precedence... whitelist or blacklist? =
|
93 |
|
94 |
Whitelist. So if you have the same address in both lists, it'll be whitelisted and allowed to pass before the blacklist comes into effect.
|
95 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
== Screenshots ==
|
97 |
|
98 |
== Changelog ==
|
99 |
|
100 |
-
=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
101 |
* First Release
|
102 |
|
103 |
== Upgrade Notice ==
|
104 |
|
105 |
-
= 1.
|
106 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
=== Plugin Name ===
|
2 |
+
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
|
7 |
Requires at least: 3.2.0
|
8 |
+
Tested up to: 3.7
|
9 |
+
Stable tag: 1.9.2
|
10 |
|
11 |
+
Complete and Simple WordPress Security. Unrestricted, with no premium features.
|
12 |
|
13 |
== Description ==
|
14 |
|
15 |
+
The WordPress Simple Firewall is the only WordPress security plugin that *protects itself* - this plugin
|
16 |
+
will prevent access to itself so that unauthorized users can't deactivate or screw with your security settings.
|
17 |
|
18 |
+
A basic intro to all the features:
|
|
|
19 |
|
20 |
+
[youtube http://www.youtube.com/watch?v=r307fu3Eqbo]
|
21 |
+
|
22 |
+
Protects your WordPress site in 5 main ways:
|
23 |
+
|
24 |
+
= Plugin Self-Protection =
|
25 |
+
|
26 |
+
This plugins locks itself down - you can add access restriction to the plugin itself!
|
27 |
+
|
28 |
+
= A Simple, Effective Firewall =
|
29 |
+
|
30 |
+
Builds upon the simplicity and effectiveness of the WordPress Firewall 2 plugin.
|
31 |
+
|
32 |
+
= WordPress Login Protection =
|
33 |
+
|
34 |
+
Adds several layers of protection to the WordPress login screen through identity verification and Brute Force Login hacking prevention.
|
35 |
+
|
36 |
+
= Comments and SPAM Protection =
|
37 |
+
|
38 |
+
Uses and builds upon tried and tested SPAM prevention and filtering techniques with some unique approaches found only in this plugin.
|
39 |
+
|
40 |
+
= WordPress Lockdown =
|
41 |
+
|
42 |
+
Provides options for locking down your WordPress site from both legitimate users and people who may have gained unauthorized access.
|
43 |
+
|
44 |
+
Read more on each section below...
|
45 |
+
|
46 |
+
= A Simple Firewall =
|
47 |
+
|
48 |
+
The WordPress Simple Firewall is built to be reliable, and easy to use by **anyone**. Seriously, the interface is simple! :)
|
49 |
|
50 |
It adds extra features over WordPress Firewall 2, including:
|
51 |
|
52 |
+
* 7 Simple, clear, Firewall blocking options - pick and choose for ultimate protection and compatibility.
|
53 |
+
* Option: Ignore already logged-in Administrators so you don't firewall yourself as you work on the site.
|
54 |
+
* Option: IP Address Whitelist. So you can vet your own IP addresses and 3rd Party Services.
|
55 |
+
* Option: Developer option for 3rd Party Services to dynamically add IP Addresses to whitelist
|
56 |
+
(our plugin is built to work with others!) E.g. [iControlWP](http://www.icontrolwp.com/).
|
57 |
+
* Option: IP Address Blacklist so you can completely block sites/services based on their IP address.
|
58 |
+
* Option: to easily turn on / off the whole firewall without disabling the whole plugin! (so simple, but important)
|
59 |
+
* Recovery Option: You can use FTP to manually turn ON/OFF the Firewall. This means if you accidentally lock yourself out, you can forcefully turn off the firewall using FTP. You can also
|
60 |
turn back on the firewall using the same method.
|
61 |
+
* Performance: When the firewall is running it is processing EVERY page load. So your firewall checking needs to be fast.
|
62 |
+
This plugin is written to cache settings and minimize database access: 1-3 database calls per page load.
|
63 |
+
* Logging: Full logging of Firewall (and other options) to analyse and debug your traffic and settings.
|
64 |
+
* Option: Email when firewall blocks a page access - with option to specify recipient.
|
65 |
+
* Option: Email throttling. If you get hit by a bot you wont get 1000s of email... you can throttle how many emails are sent.
|
66 |
+
useful for 3rd party services that connect to the site using other plugins.
|
67 |
+
|
68 |
+
Basic functionality is based on the principles employed by the [WordPress Firewall 2 plugin](http://wordpress.org/plugins/wordpress-firewall-2/).
|
69 |
+
|
70 |
+
= Login and Identity Protection - Stops Brute Force Attacks =
|
71 |
+
|
72 |
+
Note: Login Protection is a completely independent feature to the Firewall. IP Address whitelists are not shared.
|
73 |
+
|
74 |
+
With our Login Protection features this plugin will single-handling prevent brute force login attack on all your WordPress sites.
|
75 |
+
|
76 |
+
It doesn't need IP Address Ban Lists (which are actually useless anyway), and instead puts hard limits on your WordPress site,
|
77 |
+
and force users to verify themselves when they login.
|
78 |
+
|
79 |
+
As of version 1.2.0+ you now have several ways to add simple protection to your WordPress Login system.
|
80 |
+
|
81 |
+
1. [Email-based 2-Factor Login Authentication](http://icwp.io/2v) based on IP address! (prevents brute force login attacks)
|
82 |
+
1. [Login Cooldown Interval](http://icwp.io/2t) - WordPress will only process 1 login per interval in seconds (prevents brute force login attacks)
|
83 |
+
1. [GASP Anti-Bot Login Form Protection](http://icwp.io/2u) - Adds 2 protection checks for all WordPress login attempts (prevents brute force login attacks using Bots)
|
84 |
+
|
85 |
+
These options alone will protect your WordPress sites from nearly all forms of Brute Force
|
86 |
+
login attacks.
|
87 |
+
|
88 |
+
And you hardly need to configure anything! Simply check the options to turn them on, set a cooldown interval and you're instantly protected.
|
89 |
+
|
90 |
+
= SPAM and Comments Filtering =
|
91 |
+
|
92 |
+
As of version 1.6, this plugin integrates [GASP Spambot Protection](http://wordpress.org/plugins/growmap-anti-spambot-plugin/).
|
93 |
+
|
94 |
+
We have taken this functionality a level further and added the concept of unique, per-page visit, Comment Tokens.
|
95 |
+
|
96 |
+
**Comment Tokens** are unique keys that are created every time a page loads and they are uniquely generated based on 3 factors:
|
97 |
+
|
98 |
+
1. The visitors IP address.
|
99 |
+
1. The Page they are viewing
|
100 |
+
1. A unique, random number, generated at the time the page is loaded.
|
101 |
+
|
102 |
+
This is all handle automatically and your users will not be affected - they'll still just have a checkbox like the original GASP plugin.
|
103 |
+
|
104 |
+
These comment tokens are then embedded in the comment form and must be presented to your WordPress site when a comment is posted. The plugin
|
105 |
+
will then examine the token, the IP address from which the comment is coming, and page upon which the comment is being posted. They must
|
106 |
+
all match before the comment is accepted.
|
107 |
+
|
108 |
+
Furthermore, we place a cooldown (i.e. you must wait X seconds before you can post using that token) and an expiration on these comment tokens.
|
109 |
+
The reasons for this are:
|
110 |
+
|
111 |
+
1. Cooldown means that a spambot cannot load a page, read the unique comment token and immediately re-post a comment to that page. It must wait
|
112 |
+
a while. This has the effect of slowing down the spambots, and, if the spambots get it wrong, they've wasted that token - as tokens can only
|
113 |
+
be used once.
|
114 |
+
1. Expirations mean that a spambot cannot get the token and use it whenever it likes, it must use it within the specfied time.
|
115 |
+
|
116 |
+
This all combines to make it much more difficult for spambots (and also human spammers as they have to now wait) to work their dirty magic :)
|
117 |
|
118 |
== Installation ==
|
119 |
|
120 |
See FAQs.
|
121 |
|
122 |
+
== Installation ==
|
123 |
|
124 |
+
Note: When you enable the plugin, the firewall is not automatically turned on. This plugin contains various different sections of
|
125 |
+
protection for your site and you should choose which you need based on your own requirements.
|
126 |
+
|
127 |
+
Why do we do this? Simple, performance and optimization - there is no reason to automatically turn on features for people that don't
|
128 |
+
need it as each site and set of requirements is different.
|
129 |
|
130 |
This plugin should install as any other WordPress.org respository plugin.
|
131 |
|
143 |
|
144 |
A new menu item will appear on the left-hand side called 'Simple Firewall'.
|
145 |
|
146 |
+
== Frequently Asked Questions ==
|
147 |
+
|
148 |
+
= My server has a firewall, why do I need this plugin? =
|
149 |
+
|
150 |
+
This plugin is more of an application firewall, rather than a server/network firewall. It is designed to interpret web calls to your site to
|
151 |
+
look for and find attempts to circumvent it and gain unauthorized access or cause damage.
|
152 |
+
|
153 |
+
Your network firewall is designed to restrict access to your server based on certain types of network traffic. The WordPress Simple Firewall
|
154 |
+
is designed to restrict access to your site, based on certain type of web calls.
|
155 |
+
|
156 |
= How does the IP Whitelist work? =
|
157 |
|
158 |
Any IP address that is on the whitelist will not be subject to any of the firewall scanning/processing. This setting takes priority over all other settings.
|
159 |
|
160 |
+
= Does the IP Whitelist/Blacklist support IP ranges? =
|
161 |
|
162 |
+
Yes. To specify a range you do something like: 192.168.1.10-192.168.1.20
|
163 |
|
164 |
+
= I've locked myself out from my own site! =
|
|
|
165 |
|
166 |
+
This happens when any the following 3 conditions are met:
|
167 |
|
168 |
+
* you have added your IP address to the firewall blacklist,
|
169 |
+
* you have enabled 2 factor authentication and email doesn't work on your site (and you haven't chosen the override option)
|
|
|
|
|
170 |
|
171 |
+
You can completely turn OFF (and ON) the WordPress Simple Firewall by creating a special file in the plugin folder.
|
172 |
|
173 |
Here's how:
|
174 |
|
179 |
|
180 |
If you want to turn the firewall on in the same way, create a file called "forceOn".
|
181 |
|
182 |
+
Remember: If you leave one of these files on the server, it will override your on/off settings, so you should delete it when you no longer need it.
|
183 |
|
184 |
= Which takes precedence... whitelist or blacklist? =
|
185 |
|
186 |
Whitelist. So if you have the same address in both lists, it'll be whitelisted and allowed to pass before the blacklist comes into effect.
|
187 |
|
188 |
+
= How does the pages/parameters whitelist work? =
|
189 |
+
|
190 |
+
It is a comma-separated list of pages and parameters. A NEW LINE should be taken for each new page name and its associated parameters.
|
191 |
+
|
192 |
+
The first entry on each line (before the first comma) is the page name. The rest of the items on the line are the parameters.
|
193 |
+
|
194 |
+
The following are some simple examples to illustrate:
|
195 |
+
|
196 |
+
**edit.php, featured**
|
197 |
+
|
198 |
+
On the edit.php page, the parameter with the name 'featured' will be ignored.
|
199 |
+
|
200 |
+
**admin.php, url, param01, password**
|
201 |
+
|
202 |
+
Any parameters that are passed to the page ending in 'admin.php' with the names 'url', 'param01' and 'password' will
|
203 |
+
be excluded from the firewall processing.
|
204 |
+
|
205 |
+
*, url, param, password
|
206 |
+
|
207 |
+
Putting a star first means that these exclusions apply to all pages. So for every page that is accessed, all the parameters
|
208 |
+
that are url, param and password will be ignored by the firewall.
|
209 |
+
|
210 |
+
= How does the login cooldown work? =
|
211 |
+
|
212 |
+
When enabled the plugin will prevent more than 1 login attempt to your site every "so-many" seconds. So if you enable a login cooldown
|
213 |
+
of 60 seconds, only 1 login attempt will be processed every 60 seconds. If you login incorrectly, you wont be able to attempt another
|
214 |
+
login for a further 60 seconds.
|
215 |
+
|
216 |
+
More Info: http://icwp.io/2t
|
217 |
+
|
218 |
+
= How does the GASP login protection work? =
|
219 |
+
|
220 |
+
This is best described on the blog: http://icwp.io/2u
|
221 |
+
|
222 |
+
= How does the 2-factor authentication work? =
|
223 |
+
|
224 |
+
Best described here: http://icwp.io/2v
|
225 |
+
|
226 |
== Screenshots ==
|
227 |
|
228 |
== Changelog ==
|
229 |
|
230 |
+
= TODO =
|
231 |
+
|
232 |
+
* ADD: Add various WordPress security features dynamically that would otherwise require wp-config.php editing.
|
233 |
+
* CHANGE: Interface to give a better "At-A-Glance" Dashboard summary view, that also allows you to turn on/off core features.
|
234 |
+
|
235 |
+
= 1.9.2 =
|
236 |
+
|
237 |
+
* CHANGED: Simplified the automatic WordPress Plugin updates into 1 filter for consistency
|
238 |
+
|
239 |
+
= 1.9.1 =
|
240 |
+
|
241 |
+
* ADDED: Increased admin access security features - blocks the deactivation of itself if you're not authenticated fully with the plugin.
|
242 |
+
* ADDED: If you're not authenticated with the plugin, the plugin listing view wont have 'Deactivate' or 'Edit' links.
|
243 |
+
|
244 |
+
= 1.9.0 =
|
245 |
+
|
246 |
+
* ADDED: New WordPress Automatic Updates Configuration settings
|
247 |
+
|
248 |
+
= 1.8.2 =
|
249 |
+
|
250 |
+
* ADDED: Notification of available plugin upgrade is now an option under the 'Dashboard'
|
251 |
+
* CHANGED: Certain admin and upgrade notices now only appear when you're authenticated with the plugin (if this is enabled)
|
252 |
+
* FIXED: PHP Notice with undefined index.
|
253 |
+
|
254 |
+
= 1.8.1 =
|
255 |
+
|
256 |
+
* ADDED: Feature- Access Key Restriction [more info](http://icwp.io/2s).
|
257 |
+
* ADDED: Feature- WordPress Lockdown. Currently only provides 1 option, but more to come.
|
258 |
+
|
259 |
+
= 1.7.3 =
|
260 |
+
|
261 |
+
* CHANGED: Reworked a lot of the plugin to optimize for further performance.
|
262 |
+
* FIX: Potential infinite loop in processing firewall.
|
263 |
+
|
264 |
+
= 1.7.1 =
|
265 |
+
|
266 |
+
* ADDED: Much more efficiency yet again in the loading/saving of the plugin options.
|
267 |
+
|
268 |
+
= 1.7.0 =
|
269 |
+
|
270 |
+
* ADDED: Preliminary WordPress Multisite (WPMS/WPMU) Support.
|
271 |
+
* CHANGED: The Firewall now kicks in on the 'plugins_loaded' hook instead of as the actual firewall plugin is initialized (as a result
|
272 |
+
of WP Multisite support).
|
273 |
+
|
274 |
+
= 1.6.2 =
|
275 |
+
|
276 |
+
* REMOVED: Automatic upgrade option until I can ascertain what caused the plugin to auto-disable.
|
277 |
+
|
278 |
+
= 1.6.1 =
|
279 |
+
|
280 |
+
* ADDED: Options to fully customize the text displayed by the GASP comments section.
|
281 |
+
* ADDED: Option to include logged-in users in the GASP Comments Filter.
|
282 |
+
|
283 |
+
= 1.6.0 =
|
284 |
+
|
285 |
+
* ADDED: A new section - 'Comments Filtering' that will form the basis for filtering comments with SPAM etc.
|
286 |
+
* ADDED: Option to add enhanced GASP based comments filtering to prevent SPAM bots posting comments to your site.
|
287 |
+
|
288 |
+
= 1.5.6 =
|
289 |
+
|
290 |
+
* IMPROVED: Whitelist/Blacklist IP range processing to better cater for ranges when saving, with more thorough checking.
|
291 |
+
* IMPROVED: Whitelist/Blacklist IP range processing for 32-bit systems.
|
292 |
+
* FIXED: A bug with Whitelist/Blacklist IP checking.
|
293 |
+
|
294 |
+
= 1.5.5 =
|
295 |
+
|
296 |
+
* FIXED: Quite a few bugs fixed.
|
297 |
+
|
298 |
+
= 1.5.4 =
|
299 |
+
|
300 |
+
* FIXED: Typo error.
|
301 |
+
|
302 |
+
= 1.5.3 =
|
303 |
+
|
304 |
+
* FIXED: Some of the firewall processors were saving unnecessary data.
|
305 |
+
|
306 |
+
= 1.5.2 =
|
307 |
+
|
308 |
+
* CHANGED: The method for finding the client IP address is more thorough, in a bid to work with Proxy servers etc.
|
309 |
+
* FIXED: PHP notice reported here: http://wordpress.org/support/topic/getting-errors-when-logged-in
|
310 |
+
|
311 |
+
= 1.5.1 =
|
312 |
+
|
313 |
+
* FIXED: Bug fix where IP address didn't show in email.
|
314 |
+
* FIXED: Attempt to fix problem where update message never hides.
|
315 |
+
|
316 |
+
= 1.5.0 =
|
317 |
+
|
318 |
+
* ADDED: A new IP whitelist on the Login Protect that lets you by-pass login protect rules for given IP addresses.
|
319 |
+
* REMOVED: Firewall rule for wp-login.php and whitelisted IPs.
|
320 |
+
|
321 |
+
= 1.4.2 =
|
322 |
+
|
323 |
+
* ADDED: The plugin now has an option to automatically upgrade itself when an update is detected - enabled by default.
|
324 |
+
|
325 |
+
= 1.4.1 =
|
326 |
+
|
327 |
+
* ADDED: The plugin will now displays an admin notice when a plugin upgrade is available with a link to immediately update.
|
328 |
+
* ADDED: Plugin collision: removes the main hook by 'All In One WordPress Security'. No need to have both plugins running.
|
329 |
+
* ADDED: Improved Login Cooldown Feature- works more like email throttling as it now uses an extra filesystem-based level of protection.
|
330 |
+
* FIXED: Login Cooldown Feature didn't take effect in certain circumstances.
|
331 |
+
|
332 |
+
= 1.4.0 =
|
333 |
+
|
334 |
+
* ADDED: All-new plugin options handling making them more efficient, easier to manage/update, using far fewer WordPress database options.
|
335 |
+
* CHANGED: Huge improvements on database calls and efficiency in loading plugin options.
|
336 |
+
* FIXED: Nonce implementation.
|
337 |
+
|
338 |
+
= 1.3.2 =
|
339 |
+
|
340 |
+
* FIXED: Small compatibility issue with Quick Cache menu not showing.
|
341 |
+
|
342 |
+
= 1.3.0 =
|
343 |
+
|
344 |
+
* ADDED: Email Throttle Feature - this will prevent you getting bombarded by 1000s of emails in case you're hit by a bot.
|
345 |
+
* ADDED: Another Firewall die() option. New option will print a message and uses the wp_die() function instead.
|
346 |
+
* ADDED: Refactored and improved the logging system (upgrading will delete your current logs!).
|
347 |
+
* ADDED: Option to separately log Login Protect features.
|
348 |
+
* ADDED: Option to by-pass 2-factor authentication in the case sending the verification email fails
|
349 |
+
(so you don't get locked out if your hosting doesn't support email!).
|
350 |
+
* CHANGED: Login Protect checking now better logs out users immediately with a redirect.
|
351 |
+
* CHANGED: We now escape the log data being printed - just in case there's any HTML/JS etc in there we don't want.
|
352 |
+
* CHANGED: Optimized and cleaned a lot of the option caching code to improve reliability and performance (more to come).
|
353 |
+
|
354 |
+
= 1.2.7 =
|
355 |
+
|
356 |
+
* FIX: Bug where the GASP Login protection was only working when you had 2-factor authentication enabled.
|
357 |
+
|
358 |
+
= 1.2.6 =
|
359 |
+
|
360 |
+
* ADDED: Ability to import settings from WordPress Firewall 2 plugin options - note, doesn't import page and variables whitelisting.
|
361 |
+
* FIX: A reported bug - parameter values could also be arrays.
|
362 |
+
|
363 |
+
= 1.2.5 =
|
364 |
+
|
365 |
+
* ADDED: New Feature - Option to add a checkbox that blocks automated SPAM Bots trying to log into your site.
|
366 |
+
* ADDED: Added a clear user message when they verify their 2-factor authentication.
|
367 |
+
* FIX: A few bugfixes and logic corrections.
|
368 |
+
|
369 |
+
= 1.2.4 =
|
370 |
+
|
371 |
+
* CHANGED: Documentation on the dashboard, and the message after installing the firewall have been updated to be clearer and more informative.
|
372 |
+
* FIX: A few bugfixes and logic corrections.
|
373 |
+
|
374 |
+
= 1.2.3 =
|
375 |
+
|
376 |
+
* FIX: bugfix.
|
377 |
+
|
378 |
+
= 1.2.2 =
|
379 |
+
|
380 |
+
* FIX: Some warnings and display bugs.
|
381 |
+
|
382 |
+
= 1.2.1 =
|
383 |
+
|
384 |
+
* ADDED: New Feature - Login Wait Interval. To reduce the effectiveness of brute force login attacks, you can add an interval by
|
385 |
+
which WordPress will wait before processing any more login attempts on a site.
|
386 |
+
* CHANGED: Optimized some settings for performance.
|
387 |
+
* CHANGED: Cleaned up the UI when the Firewall / Login Protect features are disabled (more to come).
|
388 |
+
* CHANGED: Further code improvements (more to come).
|
389 |
+
|
390 |
+
= 1.2.0 =
|
391 |
+
|
392 |
+
* ADDED: New Feature - **Login Protect**. Added 2-Factor Login Authentication for all users and their associated IP addresses.
|
393 |
+
* CHANGED: The method for processing the IP address lists is improved.
|
394 |
+
* CHANGED: Improved .htaccess rules (thanks MickeyRoush)
|
395 |
+
* CHANGED: Mailing method now uses WP_MAIL
|
396 |
+
* CHANGED: Lot's of code improvements.
|
397 |
+
|
398 |
+
= 1.1.6 =
|
399 |
+
|
400 |
+
* ADDED: Option to include Cookies in the firewall checking.
|
401 |
+
|
402 |
+
= 1.1.5 =
|
403 |
+
|
404 |
+
* ADDED: Ability to whitelist particular pages and their parameters (see FAQ)
|
405 |
+
* CHANGED: Quite a few improvements made to the reliability of the firewall processing.
|
406 |
+
|
407 |
+
= 1.1.4 =
|
408 |
+
|
409 |
+
* FIX: Left test path in plugin.
|
410 |
+
|
411 |
+
= 1.1.3 =
|
412 |
+
|
413 |
+
* ADDED: Option to completely ignore logged-in Administrators from the Firewall processing (they wont even trigger logging etc).
|
414 |
+
* ADDED: Ability to (un)blacklist and (un)whitelist IP addresses directly from within the log.
|
415 |
+
* ADDED: helpful link to IP WHOIS from within the log.
|
416 |
+
|
417 |
+
= 1.1.2 =
|
418 |
+
|
419 |
+
* CHANGED: Logging now has its own dedicated database table.
|
420 |
+
|
421 |
+
= 1.1.1 =
|
422 |
+
|
423 |
+
* Fix: Block notification emails weren't showing the user-friendly IP Address format.
|
424 |
+
|
425 |
+
= 1.1.0 =
|
426 |
+
|
427 |
+
* You can now specify IP ranges in whitelists and blacklists. To do this separate the start and end address with a hypen (-) E.g. For everything between 1.2.3.4 and 1.2.3.10, you would do: 1.2.3.4-1.2.3.10
|
428 |
+
* You can now specify which email address to send the notification emails.
|
429 |
+
* 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).
|
430 |
+
* You can now set to delete ALL firewall settings when you deactivate the plugin.
|
431 |
+
* Improved formatting of the firewall log.
|
432 |
+
|
433 |
+
= 1.0.2 =
|
434 |
* First Release
|
435 |
|
436 |
== Upgrade Notice ==
|
437 |
|
438 |
+
= 1.1.2 =
|
439 |
+
|
440 |
+
* CHANGED: Logging now has its own dedicated database table.
|
441 |
+
* Fix: Block notification emails weren't showing the user-friendly IP Address format.
|
442 |
+
* You can now specify IP ranges in whitelists and blacklists. To do this separate the start and end address with a hypen (-) E.g. For everything between 1.2.3.4 and 1.2.3.10, you would do: 1.2.3.4-1.2.3.10
|
443 |
+
* You can now specify which email address to send the notification emails.
|
444 |
+
* 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).
|
445 |
+
* You can now set to delete ALL firewall settings when you deactivate the plugin.
|
446 |
+
* Improved formatting of the firewall log.
|
src/icwp-base-processor.php
ADDED
@@ -0,0 +1,353 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2013 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_WPSF') ):
|
22 |
+
|
23 |
+
class ICWP_BaseProcessor_WPSF {
|
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 boolean
|
36 |
+
*/
|
37 |
+
protected $m_fNeedSave;
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @var array
|
41 |
+
*/
|
42 |
+
protected $m_aLog;
|
43 |
+
/**
|
44 |
+
* @var array
|
45 |
+
*/
|
46 |
+
protected $m_aLogMessages;
|
47 |
+
|
48 |
+
/**
|
49 |
+
* @var long
|
50 |
+
*/
|
51 |
+
protected $m_nRequestIp;
|
52 |
+
|
53 |
+
/**
|
54 |
+
* @var boolean
|
55 |
+
*/
|
56 |
+
protected $m_fLoggingEnabled;
|
57 |
+
|
58 |
+
/**
|
59 |
+
* @var ICWP_EmailProcessor
|
60 |
+
*/
|
61 |
+
protected $m_oEmailHandler;
|
62 |
+
|
63 |
+
/**
|
64 |
+
* @var array
|
65 |
+
*/
|
66 |
+
protected $m_aOptions;
|
67 |
+
|
68 |
+
/**
|
69 |
+
* @var ICWP_OptionsHandler_Base_WPSF
|
70 |
+
*/
|
71 |
+
protected $m_oOptionsHandler;
|
72 |
+
|
73 |
+
public function __construct() {
|
74 |
+
$this->m_fNeedSave = true;
|
75 |
+
$this->reset();
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Resets the object values to be re-used anew
|
80 |
+
*/
|
81 |
+
public function reset() {
|
82 |
+
$this->m_nRequestIp = self::GetVisitorIpAddress();
|
83 |
+
$this->resetLog();
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Ensure that when we save the object later, it doesn't save unnecessary data.
|
88 |
+
*/
|
89 |
+
public function doPreStore() {
|
90 |
+
unset( $this->m_oEmailHandler );
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* @param string $infKey
|
95 |
+
*/
|
96 |
+
public function store( $infKey ) {
|
97 |
+
if ( $this->getNeedSave() ) {
|
98 |
+
$this->doPreStore();
|
99 |
+
$this->setNeedSave( false );
|
100 |
+
update_option( $infKey, $this );
|
101 |
+
}
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* @return boolean
|
106 |
+
*/
|
107 |
+
public function getNeedSave() {
|
108 |
+
return $this->m_fNeedSave;
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* @param boolean $infNeedSave
|
113 |
+
*/
|
114 |
+
public function setNeedSave( $infNeedSave = true ) {
|
115 |
+
$this->m_fNeedSave = $infNeedSave;
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
*
|
120 |
+
* @param array $inoOptions
|
121 |
+
*/
|
122 |
+
public function setOptions( &$inaOptions ) {
|
123 |
+
$this->m_aOptions = $inaOptions;
|
124 |
+
}
|
125 |
+
/**
|
126 |
+
*
|
127 |
+
* @param array $inoOptionsHandler
|
128 |
+
*/
|
129 |
+
public function setOptionsHandler( ICWP_OptionsHandler_Base_WPSF &$inoOptionsHandler ) {
|
130 |
+
$this->m_oOptionsHandler = $inoOptionsHandler;
|
131 |
+
$this->m_aOptions = $this->m_oOptionsHandler->getPluginOptionsValues();
|
132 |
+
}
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Resets the log
|
136 |
+
*/
|
137 |
+
public function resetLog() {
|
138 |
+
$this->m_aLogMessages = array();
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* @param boolean $infEnableLogging
|
143 |
+
*/
|
144 |
+
public function setLogging( $infEnableLogging = true ) {
|
145 |
+
$this->m_fLoggingEnabled = $infEnableLogging;
|
146 |
+
}
|
147 |
+
|
148 |
+
/**
|
149 |
+
* Builds and returns the full log.
|
150 |
+
*
|
151 |
+
* @return array (associative)
|
152 |
+
*/
|
153 |
+
public function getLogData() {
|
154 |
+
|
155 |
+
if ( $this->m_fLoggingEnabled ) {
|
156 |
+
$this->m_aLog = array(
|
157 |
+
'messages' => serialize( $this->m_aLogMessages ),
|
158 |
+
);
|
159 |
+
}
|
160 |
+
else {
|
161 |
+
$this->m_aLog = false;
|
162 |
+
}
|
163 |
+
|
164 |
+
return $this->m_aLog;
|
165 |
+
}
|
166 |
+
|
167 |
+
/**
|
168 |
+
* @param string $insLogMessage
|
169 |
+
* @param string $insMessageType
|
170 |
+
*/
|
171 |
+
public function writeLog( $insLogMessage = '', $insMessageType = self::LOG_MESSAGE_LEVEL_INFO ) {
|
172 |
+
if ( !is_array( $this->m_aLogMessages ) ) {
|
173 |
+
$this->resetLog();
|
174 |
+
}
|
175 |
+
$this->m_aLogMessages[] = array( $insMessageType, $insLogMessage );
|
176 |
+
}
|
177 |
+
/**
|
178 |
+
* @param string $insLogMessage
|
179 |
+
*/
|
180 |
+
public function logInfo( $insLogMessage ) {
|
181 |
+
$this->writeLog( $insLogMessage, self::LOG_MESSAGE_LEVEL_INFO );
|
182 |
+
}
|
183 |
+
/**
|
184 |
+
* @param string $insLogMessage
|
185 |
+
*/
|
186 |
+
public function logWarning( $insLogMessage ) {
|
187 |
+
$this->writeLog( $insLogMessage, self::LOG_MESSAGE_LEVEL_WARNING );
|
188 |
+
}
|
189 |
+
/**
|
190 |
+
* @param string $insLogMessage
|
191 |
+
*/
|
192 |
+
public function logCritical( $insLogMessage ) {
|
193 |
+
$this->writeLog( $insLogMessage, self::LOG_MESSAGE_LEVEL_CRITICAL );
|
194 |
+
}
|
195 |
+
|
196 |
+
/**
|
197 |
+
* Cloudflare compatible.
|
198 |
+
*
|
199 |
+
* @return number - visitor IP Address as IP2Long
|
200 |
+
*/
|
201 |
+
public static function GetVisitorIpAddress( $infAsLong = true ) {
|
202 |
+
|
203 |
+
$aAddressSourceOptions = array(
|
204 |
+
'HTTP_CLIENT_IP',
|
205 |
+
'HTTP_X_FORWARDED_FOR',
|
206 |
+
'HTTP_X_FORWARDED',
|
207 |
+
'HTTP_FORWARDED',
|
208 |
+
'REMOTE_ADDR'
|
209 |
+
);
|
210 |
+
|
211 |
+
$fCanUseFilter = function_exists( 'filter_var' ) && defined( 'FILTER_FLAG_NO_PRIV_RANGE' ) && defined( 'FILTER_FLAG_IPV4' );
|
212 |
+
|
213 |
+
$aIpAddresses = array();
|
214 |
+
foreach( $aAddressSourceOptions as $sOption ) {
|
215 |
+
if ( empty( $_SERVER[ $sOption ] ) ) {
|
216 |
+
continue;
|
217 |
+
}
|
218 |
+
$sIpAddressToTest = $_SERVER[ $sOption ];
|
219 |
+
|
220 |
+
$aIpAddresses = explode( ',', $sIpAddressToTest ); //sometimes a comma-separated list is returned
|
221 |
+
foreach( $aIpAddresses as $sIpAddress ) {
|
222 |
+
|
223 |
+
if ( $fCanUseFilter && !self::IsAddressInPublicIpRange( $sIpAddress ) ) {
|
224 |
+
continue;
|
225 |
+
}
|
226 |
+
else {
|
227 |
+
return $infAsLong? ip2long( $sIpAddress ) : $sIpAddress;
|
228 |
+
}
|
229 |
+
}
|
230 |
+
}
|
231 |
+
return false;
|
232 |
+
}
|
233 |
+
|
234 |
+
/**
|
235 |
+
* Assumes a valid IPv4 address is provided as we're only testing for a whether the IP is public or not.
|
236 |
+
*
|
237 |
+
* @param string $insIpAddress
|
238 |
+
* @uses filter_var
|
239 |
+
*/
|
240 |
+
public static function IsAddressInPublicIpRange( $insIpAddress ) {
|
241 |
+
return filter_var( $insIpAddress, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE );
|
242 |
+
}
|
243 |
+
|
244 |
+
/**
|
245 |
+
* @param array $inaIpList
|
246 |
+
* @param integer $innIpAddress
|
247 |
+
* @return boolean
|
248 |
+
*/
|
249 |
+
public function isIpOnlist( $inaIpList, $innIpAddress = '', &$outsLabel = '' ) {
|
250 |
+
|
251 |
+
if ( empty( $innIpAddress ) || !isset( $inaIpList['ips'] ) ) {
|
252 |
+
return false;
|
253 |
+
}
|
254 |
+
|
255 |
+
$outsLabel = '';
|
256 |
+
foreach( $inaIpList['ips'] as $mWhitelistAddress ) {
|
257 |
+
|
258 |
+
$aIps = $this->parseIpAddress( $mWhitelistAddress );
|
259 |
+
if ( count( $aIps ) === 1 ) { //not a range
|
260 |
+
if ( $innIpAddress == $aIps[0] ) {
|
261 |
+
$outsLabel = $inaIpList['meta'][ md5( $mWhitelistAddress ) ];
|
262 |
+
return true;
|
263 |
+
}
|
264 |
+
}
|
265 |
+
else if ( count( $aIps ) == 2 ) {
|
266 |
+
if ( $aIps[0] <= $innIpAddress && $innIpAddress <= $aIps[1] ) {
|
267 |
+
$outsLabel = $inaIpList['meta'][ md5( $mWhitelistAddress ) ];
|
268 |
+
return true;
|
269 |
+
}
|
270 |
+
}
|
271 |
+
}
|
272 |
+
return false;
|
273 |
+
}
|
274 |
+
|
275 |
+
/**
|
276 |
+
* @param string $insIpAddress - an IP or IP address range in LONG format.
|
277 |
+
* @return array - with 1 ip address, or 2 addresses if it is a range.
|
278 |
+
*/
|
279 |
+
protected function parseIpAddress( $insIpAddress ) {
|
280 |
+
|
281 |
+
$aIps = array();
|
282 |
+
|
283 |
+
if ( empty($insIpAddress) ) {
|
284 |
+
return $aIps;
|
285 |
+
}
|
286 |
+
|
287 |
+
// offset=1 in the case that it's a range and the first number is negative on 32-bit systems
|
288 |
+
$mPos = strpos( $insIpAddress, '-', 1 );
|
289 |
+
|
290 |
+
if ( $mPos === false ) { //plain IP address
|
291 |
+
$aIps[] = $insIpAddress;
|
292 |
+
}
|
293 |
+
else {
|
294 |
+
//we remove the first character in case this is '-'
|
295 |
+
$aParts = array( substr( $insIpAddress, 0, 1 ), substr( $insIpAddress, 1 ) );
|
296 |
+
list( $sStart, $sEnd ) = explode( '-', $aParts[1], 2 );
|
297 |
+
$aIps[] = $aParts[0].$sStart;
|
298 |
+
$aIps[] = $sEnd;
|
299 |
+
}
|
300 |
+
return $aIps;
|
301 |
+
}
|
302 |
+
|
303 |
+
/**
|
304 |
+
* We force PHP to pass by reference in case of older versions of PHP (?)
|
305 |
+
*
|
306 |
+
* @param ICWP_EmailProcessor $inoEmailHandler
|
307 |
+
*/
|
308 |
+
public function setEmailHandler( ICWP_EmailProcessor &$inoEmailHandler ) {
|
309 |
+
$this->m_oEmailHandler = $inoEmailHandler;
|
310 |
+
}
|
311 |
+
|
312 |
+
/**
|
313 |
+
* @param string $insEmailSubject - message subject
|
314 |
+
* @param array $inaMessage - message content
|
315 |
+
* @return boolean - message sending success (remember that if throttled, returns true)
|
316 |
+
*/
|
317 |
+
public function sendEmail( $insEmailSubject, $inaMessage ) {
|
318 |
+
return $this->m_oEmailHandler->sendEmail( $insEmailSubject, $inaMessage );
|
319 |
+
}
|
320 |
+
|
321 |
+
/**
|
322 |
+
* @param string $insEmailAddress - message recipient
|
323 |
+
* @param string $insEmailSubject - message subject
|
324 |
+
* @param array $inaMessage - message content
|
325 |
+
* @return boolean - message sending success (remember that if throttled, returns true)
|
326 |
+
*/
|
327 |
+
public function sendEmailTo( $insEmailAddress, $insEmailSubject, $inaMessage ) {
|
328 |
+
return $this->m_oEmailHandler->sendEmailTo( $insEmailAddress, $insEmailSubject, $inaMessage );
|
329 |
+
}
|
330 |
+
|
331 |
+
/**
|
332 |
+
* Checks the $inaData contains valid key values as laid out in $inaChecks
|
333 |
+
*
|
334 |
+
* @param array $inaData
|
335 |
+
* @param array $inaChecks
|
336 |
+
* @return boolean
|
337 |
+
*/
|
338 |
+
protected function validateParameters( $inaData, $inaChecks ) {
|
339 |
+
|
340 |
+
if ( !is_array( $inaData ) ) {
|
341 |
+
return false;
|
342 |
+
}
|
343 |
+
|
344 |
+
foreach( $inaChecks as $sCheck ) {
|
345 |
+
if ( !array_key_exists( $sCheck, $inaData ) || empty( $inaData[ $sCheck ] ) ) {
|
346 |
+
return false;
|
347 |
+
}
|
348 |
+
}
|
349 |
+
return true;
|
350 |
+
}
|
351 |
+
}
|
352 |
+
|
353 |
+
endif;
|
src/icwp-basedb-processor.php
ADDED
@@ -0,0 +1,130 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2013 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 |
+
|
21 |
+
if ( !class_exists('ICWP_BaseDbProcessor_WPSF') ):
|
22 |
+
|
23 |
+
class ICWP_BaseDbProcessor_WPSF extends ICWP_BaseProcessor_WPSF {
|
24 |
+
|
25 |
+
const DB_TABLE_PREFIX = 'icwp_';
|
26 |
+
|
27 |
+
/**
|
28 |
+
* A link to the WordPress Database object so we don't have to "global" that every time.
|
29 |
+
* @var wpdb
|
30 |
+
*/
|
31 |
+
protected $m_oWpdb;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* The full database table name.
|
35 |
+
* @var string
|
36 |
+
*/
|
37 |
+
protected $m_sTableName;
|
38 |
+
|
39 |
+
public function __construct( $insTableName ) {
|
40 |
+
parent::__construct();
|
41 |
+
$this->reset();
|
42 |
+
$this->setTableName( $insTableName );
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Ensure that when we save the object later, it doesn't save unnecessary data.
|
47 |
+
*/
|
48 |
+
public function doPreStore() {
|
49 |
+
parent::doPreStore();
|
50 |
+
unset( $this->m_oWpdb );
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Resets the object values to be re-used anew
|
55 |
+
*/
|
56 |
+
public function reset() {
|
57 |
+
parent::reset();
|
58 |
+
global $wpdb;
|
59 |
+
$this->m_oWpdb = $wpdb;
|
60 |
+
}
|
61 |
+
|
62 |
+
public function insertIntoTable( $inaData ) {
|
63 |
+
return $this->m_oWpdb->insert( $this->m_sTableName, $inaData );
|
64 |
+
}
|
65 |
+
|
66 |
+
public function selectAllFromTable( $innFormat = ARRAY_A ) {
|
67 |
+
$sQuery = sprintf( "SELECT * FROM `%s` WHERE `deleted_at` = '0'", $this->m_sTableName );
|
68 |
+
return $this->m_oWpdb->get_results( $sQuery, $innFormat );
|
69 |
+
}
|
70 |
+
|
71 |
+
public function selectCustomFromTable( $insQuery ) {
|
72 |
+
return $this->m_oWpdb->get_results( $insQuery, ARRAY_A );
|
73 |
+
}
|
74 |
+
|
75 |
+
public function selectRowFromTable( $insQuery ) {
|
76 |
+
return $this->m_oWpdb->get_row( $insQuery, ARRAY_A );
|
77 |
+
}
|
78 |
+
|
79 |
+
public function updateRowsFromTable( $inaData, $inaWhere ) {
|
80 |
+
return $this->m_oWpdb->update( $this->m_sTableName, $inaData, $inaWhere );
|
81 |
+
}
|
82 |
+
|
83 |
+
public function deleteRowsFromTable( $inaWhere ) {
|
84 |
+
return $this->m_oWpdb->delete( $this->m_sTableName, $inaWhere );
|
85 |
+
}
|
86 |
+
|
87 |
+
public function createTable() {
|
88 |
+
//Override this function to create the Table you want.
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Will remove all data from this table (to delete the table see dropTable)
|
93 |
+
*/
|
94 |
+
public function emptyTable() {
|
95 |
+
$sQuery = sprintf( "TRUNCATE TABLE `%s`", $this->m_sTableName );
|
96 |
+
return $this->doSql( $sQuery );
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Will recreate the whole table
|
101 |
+
*/
|
102 |
+
public function recreateTable() {
|
103 |
+
$this->dropTable();
|
104 |
+
$this->createTable();
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Will completely remove this table from the database
|
109 |
+
*/
|
110 |
+
public function dropTable() {
|
111 |
+
$sQuery = sprintf( 'DROP TABLE IF EXISTS `%s`', $this->m_sTableName ) ;
|
112 |
+
return $this->doSql( $sQuery );
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Given any SQL query, will perform it using the WordPress database object.
|
117 |
+
*
|
118 |
+
* @param string $insSql
|
119 |
+
*/
|
120 |
+
public function doSql( $insSql ) {
|
121 |
+
return $this->m_oWpdb->query( $insSql );
|
122 |
+
}
|
123 |
+
|
124 |
+
private function setTableName( $insTableName ) {
|
125 |
+
return $this->m_sTableName = $this->m_oWpdb->base_prefix . self::DB_TABLE_PREFIX . $insTableName;
|
126 |
+
}
|
127 |
+
|
128 |
+
}
|
129 |
+
|
130 |
+
endif;
|
src/icwp-data-processor.php
CHANGED
@@ -3,6 +3,8 @@
|
|
3 |
/**
|
4 |
* Copyright (c) 2013 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
|
@@ -21,47 +23,167 @@ if ( !class_exists('ICWP_DataProcessor') ):
|
|
21 |
|
22 |
class ICWP_DataProcessor {
|
23 |
|
|
|
|
|
24 |
static public function ExtractIpAddresses( $insAddresses = '' ) {
|
25 |
|
26 |
-
$
|
27 |
|
28 |
if ( empty( $insAddresses ) ) {
|
29 |
-
return $
|
30 |
}
|
31 |
$aRawList = array_map( 'trim', explode( "\n", $insAddresses ) );
|
32 |
-
|
33 |
-
|
34 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
}
|
|
|
|
|
|
|
|
|
36 |
|
37 |
-
|
38 |
-
|
|
|
39 |
}
|
40 |
-
|
41 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
42 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
|
44 |
-
|
45 |
-
|
46 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
}
|
48 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
|
50 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
}
|
52 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
53 |
public static function Clean_Ip( $insRawAddress ) {
|
54 |
$insRawAddress = preg_replace( '/[a-z\s]/i', '', $insRawAddress );
|
55 |
$insRawAddress = str_replace( '.', 'PERIOD', $insRawAddress );
|
|
|
56 |
$insRawAddress = preg_replace( '/[^a-z0-9]/i', '', $insRawAddress );
|
57 |
$insRawAddress = str_replace( 'PERIOD', '.', $insRawAddress );
|
|
|
58 |
return $insRawAddress;
|
59 |
}
|
60 |
|
61 |
-
public static function
|
62 |
-
if (
|
63 |
if ( filter_var( $insIpAddress, FILTER_VALIDATE_IP ) ) {
|
64 |
-
return
|
65 |
}
|
66 |
}
|
67 |
else {
|
@@ -73,11 +195,65 @@ class ICWP_DataProcessor {
|
|
73 |
return false;
|
74 |
}
|
75 |
}
|
76 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
}
|
|
|
78 |
}
|
|
|
79 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
80 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
81 |
}
|
82 |
|
83 |
endif;
|
3 |
/**
|
4 |
* Copyright (c) 2013 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
|
23 |
|
24 |
class ICWP_DataProcessor {
|
25 |
|
26 |
+
public static $fUseFilter = false;
|
27 |
+
|
28 |
static public function ExtractIpAddresses( $insAddresses = '' ) {
|
29 |
|
30 |
+
$aRawAddresses = array();
|
31 |
|
32 |
if ( empty( $insAddresses ) ) {
|
33 |
+
return $aRawAddresses;
|
34 |
}
|
35 |
$aRawList = array_map( 'trim', explode( "\n", $insAddresses ) );
|
36 |
+
|
37 |
+
self::$fUseFilter = function_exists('filter_var') && defined( FILTER_VALIDATE_IP );
|
38 |
+
|
39 |
+
foreach( $aRawList as $sKey => $sRawAddressLine ) {
|
40 |
+
|
41 |
+
if ( empty( $sRawAddressLine ) ) {
|
42 |
+
continue;
|
43 |
+
}
|
44 |
+
|
45 |
+
// Each line can have a Label which is the IP separated with a space.
|
46 |
+
$aParts = explode( ' ', $sRawAddressLine, 2 );
|
47 |
+
if ( count( $aParts ) == 1 ) {
|
48 |
+
$aParts[] = '';
|
49 |
+
}
|
50 |
+
$aRawAddresses[ $aParts[0] ] = trim( $aParts[1] );
|
51 |
}
|
52 |
+
return self::Add_New_Raw_Ips( array(), $aRawAddresses );
|
53 |
+
}
|
54 |
+
|
55 |
+
static public function ExtractCommaSeparatedList( $insRawList = '' ) {
|
56 |
|
57 |
+
$aRawList = array();
|
58 |
+
if ( empty( $insRawList ) ) {
|
59 |
+
return $aRawList;
|
60 |
}
|
61 |
+
// $aRawList = array_map( 'trim', explode( "\n", $insRawList ) );
|
62 |
+
$aRawList = array_map( 'trim', preg_split( '/\r\n|\r|\n/', $insRawList ) );
|
63 |
+
$aNewList = array();
|
64 |
+
$fHadStar = false;
|
65 |
+
foreach( $aRawList as $sKey => $sRawLine ) {
|
66 |
+
|
67 |
+
if ( empty( $sRawLine ) ) {
|
68 |
+
continue;
|
69 |
+
}
|
70 |
+
$sRawLine = str_replace( ' ', '', $sRawLine );
|
71 |
+
$aParts = explode( ',', $sRawLine, 2 );
|
72 |
+
// we only permit 1x line beginning with *
|
73 |
+
if ( $aParts[0] == '*' ) {
|
74 |
+
if ( $fHadStar ) {
|
75 |
+
continue;
|
76 |
+
}
|
77 |
+
$fHadStar = true;
|
78 |
+
}
|
79 |
+
else {
|
80 |
+
//If there's only 1 item on the line, we assume it to be a global
|
81 |
+
// parameter rule
|
82 |
+
if ( count( $aParts ) == 1 || empty( $aParts[1] ) ) { // there was no comma in this line in the first place
|
83 |
+
array_unshift( $aParts, '*' );
|
84 |
+
}
|
85 |
+
}
|
86 |
+
|
87 |
+
$aParams = empty( $aParts[1] )? array() : explode( ',', $aParts[1] );
|
88 |
+
$aNewList[ $aParts[0] ] = $aParams;
|
89 |
}
|
90 |
+
return $aNewList;
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Given a list of new IPv4 address ($inaNewRawAddresses) it'll add them to the existing list
|
95 |
+
* ($inaCurrent) where they're not already found
|
96 |
+
*
|
97 |
+
* @param array $inaCurrent - the list to which to add the new addresses
|
98 |
+
* @param array $inaNewRawAddresses - the new IPv4 addresses
|
99 |
+
* @param int $outnNewAdded - the count of newly added IPs
|
100 |
+
* @return unknown|Ambigous <multitype:multitype: , string>
|
101 |
+
*/
|
102 |
+
public static function Add_New_Raw_Ips( $inaCurrent, $inaNewRawAddresses, &$outnNewAdded = 0 ) {
|
103 |
|
104 |
+
if ( empty( $inaNewRawAddresses ) ) {
|
105 |
+
return $inaCurrent;
|
106 |
+
}
|
107 |
+
|
108 |
+
if ( !array_key_exists( 'ips', $inaCurrent ) ) {
|
109 |
+
$inaCurrent['ips'] = array();
|
110 |
+
}
|
111 |
+
if ( !array_key_exists( 'meta', $inaCurrent ) ) {
|
112 |
+
$inaCurrent['meta'] = array();
|
113 |
+
}
|
114 |
+
|
115 |
+
foreach( $inaNewRawAddresses as $sRawIpAddress => $sLabel ) {
|
116 |
+
$mVerifiedIp = self::Verify_Ip( $sRawIpAddress );
|
117 |
+
if ( $mVerifiedIp !== false && !in_array( $mVerifiedIp, $inaCurrent['ips'] ) ) {
|
118 |
+
$inaCurrent['ips'][] = $mVerifiedIp;
|
119 |
+
if ( empty($sLabel) ) {
|
120 |
+
$sLabel = 'no label';
|
121 |
+
}
|
122 |
+
$inaCurrent['meta'][ md5( $mVerifiedIp ) ] = $sLabel;
|
123 |
+
$outnNewAdded++;
|
124 |
}
|
125 |
}
|
126 |
+
return $inaCurrent;
|
127 |
+
}
|
128 |
+
|
129 |
+
/**
|
130 |
+
* @param array $inaCurrent
|
131 |
+
* @param array $inaRawAddresses - should be a plain numerical array of IPv4 addresses
|
132 |
+
* @return array:
|
133 |
+
*/
|
134 |
+
public static function Remove_Raw_Ips( $inaCurrent, $inaRawAddresses ) {
|
135 |
+
if ( empty( $inaRawAddresses ) ) {
|
136 |
+
return $inaCurrent;
|
137 |
+
}
|
138 |
+
|
139 |
+
if ( !array_key_exists( 'ips', $inaCurrent ) ) {
|
140 |
+
$inaCurrent['ips'] = array();
|
141 |
+
}
|
142 |
+
if ( !array_key_exists( 'meta', $inaCurrent ) ) {
|
143 |
+
$inaCurrent['meta'] = array();
|
144 |
+
}
|
145 |
|
146 |
+
foreach( $inaRawAddresses as $sRawIpAddress ) {
|
147 |
+
$mVerifiedIp = self::Verify_Ip( $sRawIpAddress );
|
148 |
+
if ( $mVerifiedIp === false ) {
|
149 |
+
continue;
|
150 |
+
}
|
151 |
+
$mKey = array_search( $mVerifiedIp, $inaCurrent['ips'] );
|
152 |
+
if ( $mKey !== false ) {
|
153 |
+
unset( $inaCurrent['ips'][$mKey] );
|
154 |
+
unset( $inaCurrent['meta'][ md5( $mVerifiedIp ) ] );
|
155 |
+
}
|
156 |
+
}
|
157 |
+
return $inaCurrent;
|
158 |
}
|
159 |
|
160 |
+
public static function Verify_Ip( $insIpAddress ) {
|
161 |
+
|
162 |
+
$sAddress = self::Clean_Ip( $insIpAddress );
|
163 |
+
|
164 |
+
// Now, determine if this is an IP range, or just a plain IP address.
|
165 |
+
if ( strpos( $sAddress, '-' ) === false ) { //plain IP address
|
166 |
+
return self::Verify_Ip_Address( $sAddress );
|
167 |
+
}
|
168 |
+
else {
|
169 |
+
return self::Verify_Ip_Range( $sAddress );
|
170 |
+
}
|
171 |
+
}
|
172 |
+
|
173 |
public static function Clean_Ip( $insRawAddress ) {
|
174 |
$insRawAddress = preg_replace( '/[a-z\s]/i', '', $insRawAddress );
|
175 |
$insRawAddress = str_replace( '.', 'PERIOD', $insRawAddress );
|
176 |
+
$insRawAddress = str_replace( '-', 'HYPEN', $insRawAddress );
|
177 |
$insRawAddress = preg_replace( '/[^a-z0-9]/i', '', $insRawAddress );
|
178 |
$insRawAddress = str_replace( 'PERIOD', '.', $insRawAddress );
|
179 |
+
$insRawAddress = str_replace( 'HYPEN', '-', $insRawAddress );
|
180 |
return $insRawAddress;
|
181 |
}
|
182 |
|
183 |
+
public static function Verify_Ip_Address( $insIpAddress ) {
|
184 |
+
if ( self::$fUseFilter ) {
|
185 |
if ( filter_var( $insIpAddress, FILTER_VALIDATE_IP ) ) {
|
186 |
+
return ip2long( $insIpAddress );
|
187 |
}
|
188 |
}
|
189 |
else {
|
195 |
return false;
|
196 |
}
|
197 |
}
|
198 |
+
return ip2long( $insIpAddress );
|
199 |
+
}
|
200 |
+
}
|
201 |
+
return false;
|
202 |
+
}
|
203 |
+
|
204 |
+
/**
|
205 |
+
* The only ranges currently accepted are a.b.c.d-f.g.h.j
|
206 |
+
* @param string $insIpAddressRange
|
207 |
+
* @return string|boolean
|
208 |
+
*/
|
209 |
+
public static function Verify_Ip_Range( $insIpAddressRange ) {
|
210 |
+
|
211 |
+
list( $sIpRangeStart, $sIpRangeEnd ) = explode( '-', $insIpAddressRange, 2 );
|
212 |
+
|
213 |
+
if ( $sIpRangeStart == $sIpRangeEnd ) {
|
214 |
+
return self::Verify_Ip_Address( $sIpRangeStart );
|
215 |
+
}
|
216 |
+
else if ( self::Verify_Ip_Address( $sIpRangeStart ) && self::Verify_Ip_Address( $sIpRangeEnd ) ) {
|
217 |
+
$nStart = ip2long( $sIpRangeStart );
|
218 |
+
$nEnd = ip2long( $sIpRangeEnd );
|
219 |
+
|
220 |
+
// do our best to order it
|
221 |
+
if (
|
222 |
+
( $nStart > 0 && $nEnd > 0 && $nStart > $nEnd )
|
223 |
+
|| ( $nStart < 0 && $nEnd < 0 && $nStart > $nEnd )
|
224 |
+
) {
|
225 |
+
$nTemp = $nStart;
|
226 |
+
$nStart = $nEnd;
|
227 |
+
$nEnd = $nTemp;
|
228 |
}
|
229 |
+
return $nStart.'-'.$nEnd;
|
230 |
}
|
231 |
+
return false;
|
232 |
}
|
233 |
+
|
234 |
+
/**
|
235 |
+
* @param integer $innLength
|
236 |
+
* @param boolean $infBeginLetter
|
237 |
+
* @return string
|
238 |
+
*/
|
239 |
+
static public function GenerateRandomString( $innLength = 10, $infBeginLetter = false ) {
|
240 |
+
$aChars = array( 'abcdefghijkmnopqrstuvwxyz' );
|
241 |
+
$aChars[] = 'ABCDEFGHJKLMNPQRSTUVWXYZ';
|
242 |
|
243 |
+
$sCharset = implode( '', $aChars );
|
244 |
+
if ( $infBeginLetter ) {
|
245 |
+
$sPassword = $sCharset[ ( rand() % strlen( $sCharset ) ) ];
|
246 |
+
}
|
247 |
+
else {
|
248 |
+
$sPassword = '';
|
249 |
+
}
|
250 |
+
$sCharset .= '023456789';
|
251 |
+
|
252 |
+
for ( $i = $infBeginLetter? 1 : 0; $i < $innLength; $i++ ) {
|
253 |
+
$sPassword .= $sCharset[ ( rand() % strlen( $sCharset ) ) ];
|
254 |
+
}
|
255 |
+
return $sPassword;
|
256 |
+
}
|
257 |
}
|
258 |
|
259 |
endif;
|
src/icwp-firewall-processor.php
DELETED
@@ -1,502 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Copyright (c) 2013 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_DataProcessor') ):
|
20 |
-
|
21 |
-
class ICWP_FirewallProcessor {
|
22 |
-
|
23 |
-
const PcreDelimiter = '/';
|
24 |
-
const LOG_MESSAGE_TYPE_INFO = 0;
|
25 |
-
const LOG_MESSAGE_TYPE_WARNING = 1;
|
26 |
-
const LOG_MESSAGE_TYPE_CRITICAL = 2;
|
27 |
-
|
28 |
-
protected $m_sRequestId;
|
29 |
-
protected $m_sRequestIp;
|
30 |
-
|
31 |
-
protected $m_aBlockSettings;
|
32 |
-
protected $m_sBlockResponse;
|
33 |
-
protected $m_aWhitelistIps;
|
34 |
-
protected $m_aBlacklistIps;
|
35 |
-
|
36 |
-
protected $m_aWhitelistPages;
|
37 |
-
protected $m_aWhitelistPagesPatterns;
|
38 |
-
|
39 |
-
protected $m_aRequestUriParts;
|
40 |
-
|
41 |
-
protected $m_aLog;
|
42 |
-
|
43 |
-
/**
|
44 |
-
* A combination of the current request $_GET and $_POST
|
45 |
-
* @var array
|
46 |
-
*/
|
47 |
-
protected $m_aPageParams;
|
48 |
-
|
49 |
-
/**
|
50 |
-
* All the remaining values of the page parameters after they've been filtered
|
51 |
-
* @var array
|
52 |
-
*/
|
53 |
-
protected $m_aPageParamValues;
|
54 |
-
|
55 |
-
public function __construct( $inaBlockSettings, $inaIpWhitelist, $inaIpBlacklist, $insBlockResponse ) {
|
56 |
-
|
57 |
-
$this->reset();
|
58 |
-
$this->m_aBlockSettings = $inaBlockSettings;
|
59 |
-
$this->m_sBlockResponse = $insBlockResponse;
|
60 |
-
$this->m_aWhitelistIps = $inaIpWhitelist;
|
61 |
-
$this->m_aBlacklistIps = $inaIpBlacklist;
|
62 |
-
}
|
63 |
-
|
64 |
-
public function reset() {
|
65 |
-
$this->m_sRequestIp = self::GetVisitorIpAddress();
|
66 |
-
$this->m_sRequestId = $this->m_sRequestIp.'_'.uniqid();
|
67 |
-
$this->m_aRequestUriParts = array();
|
68 |
-
$this->m_aPageParams = array();
|
69 |
-
$this->m_aPageParamValues = array();
|
70 |
-
$this->resetLog();
|
71 |
-
}
|
72 |
-
|
73 |
-
public function resetLog() {
|
74 |
-
if ( !is_array($this->m_aLog) ) {
|
75 |
-
$this->m_aLog = array();
|
76 |
-
}
|
77 |
-
$this->m_aLog[ $this->m_sRequestId ] = array();
|
78 |
-
}
|
79 |
-
|
80 |
-
public function getLog() {
|
81 |
-
return $this->m_aLog;
|
82 |
-
}
|
83 |
-
|
84 |
-
/**
|
85 |
-
*
|
86 |
-
* @param string $insLogMessage
|
87 |
-
* @param string $insMessageType
|
88 |
-
*/
|
89 |
-
public function writeLog( $insLogMessage = '', $insMessageType = self::LOG_MESSAGE_TYPE_INFO ) {
|
90 |
-
if ( !isset( $this->m_aLog[ $this->m_sRequestId ] ) ) {
|
91 |
-
$this->resetLog();
|
92 |
-
}
|
93 |
-
$this->m_aLog[ $this->m_sRequestId ][] = array( time(), $insMessageType, $insLogMessage );
|
94 |
-
}
|
95 |
-
|
96 |
-
public function doFirewallCheck() {
|
97 |
-
|
98 |
-
//Check if the visitor is excluded from the firewall from the outset.
|
99 |
-
if ( $this->isVisitorOnWhitelist() ) {
|
100 |
-
$this->logInfo( 'Visitor is whitelisted by IP Address' );
|
101 |
-
return true;
|
102 |
-
}
|
103 |
-
else {
|
104 |
-
$this->logInfo( 'Visitor is NOT whitelisted by IP Address' );
|
105 |
-
}
|
106 |
-
|
107 |
-
//Check if the visitor is excluded from the firewall from the outset.
|
108 |
-
if ( $this->isVisitorOnBlacklist() ) {
|
109 |
-
$this->logWarning( 'Visitor is blacklisted by IP Address' );
|
110 |
-
return false;
|
111 |
-
}
|
112 |
-
else {
|
113 |
-
$this->logInfo( 'Visitor is NOT blacklisted by IP Address' );
|
114 |
-
}
|
115 |
-
|
116 |
-
// if we can't process the REQUEST_URI parts, we can't firewall so we effectively whitelist without erroring.
|
117 |
-
if ( !$this->setRequestUriPageParts() ) {
|
118 |
-
return true;
|
119 |
-
}
|
120 |
-
|
121 |
-
$fIsPermittedVisitor = true;
|
122 |
-
|
123 |
-
//Checking this comes before all else but after the IP whitelist check.
|
124 |
-
if ( $this->m_aBlockSettings[ 'block_wplogin_access' ] ) {
|
125 |
-
$fIsPermittedVisitor = $this->doPassCheckBlockWpLogin();
|
126 |
-
}
|
127 |
-
|
128 |
-
// Set up the page parameters ($_GET and $_POST). If there are none, quit since there's nothing for the firewall to check.
|
129 |
-
$this->setPageParams();
|
130 |
-
if ( $fIsPermittedVisitor && empty( $this->m_aPageParams ) ) {
|
131 |
-
$this->logInfo( 'There were no page parameters to check on this visit.' );
|
132 |
-
return true;
|
133 |
-
}
|
134 |
-
|
135 |
-
// Check if the page and its parameters are whitelisted.
|
136 |
-
if ( $fIsPermittedVisitor && $this->isPageWhitelisted() ) {
|
137 |
-
return true;
|
138 |
-
}
|
139 |
-
|
140 |
-
// ensures we have a simple array with all the values that need to be checked.
|
141 |
-
$this->m_aPageParamValues = array_values( $this->m_aPageParams );
|
142 |
-
|
143 |
-
if ( $fIsPermittedVisitor && $this->m_aBlockSettings[ 'block_dir_traversal' ] ) {
|
144 |
-
$fIsPermittedVisitor = $this->doPassCheckBlockDirTraversal();
|
145 |
-
}
|
146 |
-
if ( $fIsPermittedVisitor && $this->m_aBlockSettings[ 'block_sql_queries' ] ) {
|
147 |
-
$fIsPermittedVisitor = $this->doPassCheckBlockSqlQueries();
|
148 |
-
}
|
149 |
-
if ( $fIsPermittedVisitor && $this->m_aBlockSettings[ 'block_wordpress_terms' ] ) {
|
150 |
-
$fIsPermittedVisitor = $this->doPassCheckBlockWordpressTerms();
|
151 |
-
}
|
152 |
-
if ( $fIsPermittedVisitor && $this->m_aBlockSettings[ 'block_field_truncation' ] ) {
|
153 |
-
$fIsPermittedVisitor = $this->doPassCheckBlockFieldTruncation();
|
154 |
-
}
|
155 |
-
if ( $fIsPermittedVisitor && $this->m_aBlockSettings[ 'block_exe_file_uploads' ] ) {
|
156 |
-
$fIsPermittedVisitor = $this->doPassCheckBlockExeFileUploads();
|
157 |
-
}
|
158 |
-
if ( $fIsPermittedVisitor && $this->m_aBlockSettings[ 'block_leading_schema' ] ) {
|
159 |
-
$fIsPermittedVisitor = $this->doPassCheckBlockLoadingSchema();
|
160 |
-
}
|
161 |
-
|
162 |
-
return $fIsPermittedVisitor || isset($_GET['testfirewall']); //testing
|
163 |
-
}
|
164 |
-
|
165 |
-
/**
|
166 |
-
* This function assumes that isVisitorOnWhitelist() check has been run previously. Meaning the
|
167 |
-
* current visitor is NOT on the whitelist and so if the page they're accessing is wp-login then
|
168 |
-
* they do not pass this check.
|
169 |
-
*
|
170 |
-
* If whitelisted IPs is empty, we never block access.
|
171 |
-
*
|
172 |
-
* @return boolean
|
173 |
-
*/
|
174 |
-
protected function doPassCheckBlockWpLogin() {
|
175 |
-
|
176 |
-
list( $sRequestPage, $sRequestQuery ) = $this->m_aRequestUriParts;
|
177 |
-
|
178 |
-
if ( substr_count( $sRequestPage, '/wp-login.php' ) > 0 ) {
|
179 |
-
|
180 |
-
// We don't block wp-login.php if there are no whitelisted IPs.
|
181 |
-
if ( count( $this->m_aWhitelistIps ) < 1 ) {
|
182 |
-
$this->logInfo( 'Requested: Block access to wp-login.php, but this was skipped because whitelisted IPs list was empty.' );
|
183 |
-
return true;
|
184 |
-
}
|
185 |
-
|
186 |
-
$this->logWarning( 'Requested: Block access to wp-login.php. Visitor not on IP whitelist and blocked by firewall.' );
|
187 |
-
return false;
|
188 |
-
}
|
189 |
-
return true;
|
190 |
-
}
|
191 |
-
|
192 |
-
protected function doPassCheckBlockDirTraversal() {
|
193 |
-
$aTerms = array(
|
194 |
-
'etc/passwd',
|
195 |
-
'proc/self/environ',
|
196 |
-
'../'
|
197 |
-
);
|
198 |
-
$fPass = $this->doPassCheck( $this->m_aPageParamValues, $aTerms );
|
199 |
-
if ( !$fPass ) {
|
200 |
-
$this->logWarning( 'Requested: Block Directory Traversal. This visitor.' );
|
201 |
-
}
|
202 |
-
return $fPass;
|
203 |
-
}
|
204 |
-
|
205 |
-
protected function doPassCheckBlockSqlQueries() {
|
206 |
-
$aTerms = array(
|
207 |
-
'/concat\s*\(/i',
|
208 |
-
'/group_concat/i',
|
209 |
-
'/union.*select/i'
|
210 |
-
);
|
211 |
-
$fPass = $this->doPassCheck( $this->m_aPageParamValues, $aTerms, true );
|
212 |
-
if ( !$fPass ) {
|
213 |
-
$this->logWarning( 'Requested: Block access to wp-login.php, but this was skipped because whitelisted IPs list was empty.' );
|
214 |
-
}
|
215 |
-
return $fPass;
|
216 |
-
}
|
217 |
-
|
218 |
-
protected function doPassCheckBlockWordpressTerms() {
|
219 |
-
$aTerms = array(
|
220 |
-
'/wp_/i',
|
221 |
-
'/user_login/i',
|
222 |
-
'/user_pass/i',
|
223 |
-
'/0x[0-9a-f][0-9a-f]/i',
|
224 |
-
'/\/\*\*\//'
|
225 |
-
);
|
226 |
-
return $this->doPassCheck( $this->m_aPageParamValues, $aTerms, true );
|
227 |
-
}
|
228 |
-
|
229 |
-
protected function doPassCheckBlockFieldTruncation() {
|
230 |
-
$aTerms = array(
|
231 |
-
'/\s{49,}/i',
|
232 |
-
'/\x00/'
|
233 |
-
);
|
234 |
-
return $this->doPassCheck( $this->m_aPageParamValues, $aTerms, true );
|
235 |
-
}
|
236 |
-
|
237 |
-
protected function doPassCheckBlockExeFileUploads() {
|
238 |
-
$aTerms = array(
|
239 |
-
'/\.dll$/i', '/\.rb$/i', '/\.py$/i', '/\.exe$/i', '/\.php[3-6]?$/i', '/\.pl$/i',
|
240 |
-
'/\.perl$/i', '/\.ph[34]$/i', '/\.phl$/i', '/\.phtml$/i', '/\.phtm$/i'
|
241 |
-
);
|
242 |
-
|
243 |
-
if ( isset( $_FILES ) && !empty( $_FILES ) ) {
|
244 |
-
$aFileNames = array();
|
245 |
-
foreach( $_FILES as $aFile ) {
|
246 |
-
if ( !empty( $aFile['name'] ) ) {
|
247 |
-
$aFileNames[] = $aFile['name'];
|
248 |
-
}
|
249 |
-
}
|
250 |
-
return $this->doPassCheck( $aFileNames, $aTerms, true );
|
251 |
-
}
|
252 |
-
|
253 |
-
return true;
|
254 |
-
}
|
255 |
-
|
256 |
-
protected function doPassCheckBlockLoadingSchema() {
|
257 |
-
$aTerms = array(
|
258 |
-
'/^http/i', '/\.shtml$/i'
|
259 |
-
);
|
260 |
-
return $this->doPassCheck( $this->m_aPageParamValues, $aTerms, true );
|
261 |
-
}
|
262 |
-
|
263 |
-
/**
|
264 |
-
* Returns false when check fails - that is to say, it should be blocked by the firewall.
|
265 |
-
*
|
266 |
-
* @param array $inaValues
|
267 |
-
* @param array $inaTerms
|
268 |
-
* @param boolean $infRegex
|
269 |
-
* @return boolean
|
270 |
-
*/
|
271 |
-
private function doPassCheck( $inaValues, $inaTerms, $infRegex = false ) {
|
272 |
-
|
273 |
-
foreach ( $inaValues as $sValue ) {
|
274 |
-
foreach ( $inaTerms as $sTerm ) {
|
275 |
-
|
276 |
-
if ( $infRegex && preg_match( $sTerm, $sValue ) ) { //dodgy term pattern found in a parameter value
|
277 |
-
$this->logWarning(
|
278 |
-
sprintf( 'Page parameter failed firewall check. The value was %s and the term is matched was %s', $sValue, $sTerm )
|
279 |
-
);
|
280 |
-
return false;
|
281 |
-
}
|
282 |
-
else {
|
283 |
-
if ( strpos( $sValue, $sTerm ) !== false ) { //dodgy term found in a parameter value
|
284 |
-
$this->logWarning(
|
285 |
-
sprintf( 'Page parameter failed firewall check. The value was %s and the search term it matched was %s', $sValue, $sTerm )
|
286 |
-
);
|
287 |
-
return false;
|
288 |
-
}
|
289 |
-
}
|
290 |
-
}
|
291 |
-
}
|
292 |
-
return true;
|
293 |
-
}
|
294 |
-
|
295 |
-
public function doFirewallBlock() {
|
296 |
-
|
297 |
-
switch( $this->m_sBlockResponse ) {
|
298 |
-
|
299 |
-
case 'redirect_home':
|
300 |
-
header( "Location: ".home_url().'?testfirewall' );
|
301 |
-
exit();
|
302 |
-
break;
|
303 |
-
case 'redirect_404':
|
304 |
-
header( "Location: ".home_url().'/404?testfirewall' );
|
305 |
-
exit();
|
306 |
-
break;
|
307 |
-
case 'redirect_die':
|
308 |
-
die();
|
309 |
-
}
|
310 |
-
}
|
311 |
-
|
312 |
-
public function isPageWhitelisted() {
|
313 |
-
|
314 |
-
if ( empty( $this->m_aWhitelistPages ) ) {
|
315 |
-
$this->setWhitelistPages();
|
316 |
-
}
|
317 |
-
if ( empty( $this->m_aWhitelistPages ) ) {
|
318 |
-
return false;
|
319 |
-
}
|
320 |
-
|
321 |
-
// Check normal whitelisting pages without patterns.
|
322 |
-
if ( $this->checkPagesForWhiteListing( $this->m_aWhitelistPages ) ) {
|
323 |
-
return true;
|
324 |
-
}
|
325 |
-
// Check pattern-based whitelisting pages.
|
326 |
-
if ( $this->checkPagesForWhiteListing( $this->m_aWhitelistPagesPatterns ) ) {
|
327 |
-
return true;
|
328 |
-
}
|
329 |
-
|
330 |
-
return false;
|
331 |
-
}
|
332 |
-
|
333 |
-
/**
|
334 |
-
*
|
335 |
-
* @param array $inaWhitelistPagesParams
|
336 |
-
* @param boolean $infUseRegex
|
337 |
-
* @return boolean
|
338 |
-
*/
|
339 |
-
protected function checkPagesForWhiteListing( $inaWhitelistPagesParams = array(), $infUseRegex = false ) {
|
340 |
-
|
341 |
-
list( $sRequestPage, $sRequestQuery ) = $this->m_aRequestUriParts;
|
342 |
-
|
343 |
-
// Now we compare pages in the whitelist with the parts of the request uri. If we get a match, that page is whitelisted
|
344 |
-
$aWhitelistPages = array_keys( $inaWhitelistPagesParams );
|
345 |
-
|
346 |
-
// 1. Is the page in the list of white pages?
|
347 |
-
$fPageWhitelisted = false;
|
348 |
-
if ( $infUseRegex ) {
|
349 |
-
foreach ( $aWhitelistPages as $sPagePattern ) {
|
350 |
-
if ( preg_match( $sPagePattern, $sRequestPage ) ) {
|
351 |
-
$fPageWhitelisted = true;
|
352 |
-
break;
|
353 |
-
}
|
354 |
-
}
|
355 |
-
}
|
356 |
-
else if ( in_array( $sRequestPage, $aWhitelistPages ) ) {
|
357 |
-
$fPageWhitelisted = true;
|
358 |
-
}
|
359 |
-
|
360 |
-
if ( $fPageWhitelisted ) {
|
361 |
-
// the current page is whitelisted - now check if it has request parameters.
|
362 |
-
if ( empty( $inaWhitelistPagesParams[$sRequestPage] ) ) {
|
363 |
-
return true; //because it's just plain whitelisted
|
364 |
-
}
|
365 |
-
foreach ( $inaWhitelistPagesParams[$sRequestPage] as $sWhitelistParam ) {
|
366 |
-
if ( array_key_exists( $sWhitelistParam, $this->m_aPageParams ) ) {
|
367 |
-
unset( $this->m_aPageParams[ $sWhitelistParam ] );
|
368 |
-
}
|
369 |
-
}
|
370 |
-
// After removing all the whitelisted params, we now check if there are any params left that'll
|
371 |
-
// need matched later in the firewall checking. If there are no parameters left, we return true.
|
372 |
-
if ( empty( $this->m_aPageParams ) ) {
|
373 |
-
return true;
|
374 |
-
}
|
375 |
-
}
|
376 |
-
return false;
|
377 |
-
}
|
378 |
-
|
379 |
-
protected function setRequestUriPageParts() {
|
380 |
-
|
381 |
-
if ( !isset( $_SERVER['REQUEST_URI'] ) || empty( $_SERVER['REQUEST_URI'] ) ) {
|
382 |
-
$this->m_aRequestUriParts = false;
|
383 |
-
$this->logWarning( 'Could not parse the details of this page call as $_SERVER[REQUEST_URI] was empty or not defined.' );
|
384 |
-
return false;
|
385 |
-
}
|
386 |
-
$this->m_aRequestUriParts = explode( '?', $_SERVER['REQUEST_URI'] );
|
387 |
-
$this->logInfo( sprintf( 'Page Request URI: %s', $_SERVER['REQUEST_URI'] ) );
|
388 |
-
return true;
|
389 |
-
}
|
390 |
-
|
391 |
-
protected function setPageParams() {
|
392 |
-
$this->m_aPageParams = array_merge( $_GET, $_POST );
|
393 |
-
return true;
|
394 |
-
}
|
395 |
-
|
396 |
-
private function setWhitelistPages() {
|
397 |
-
|
398 |
-
$aDefaultWlPages = array(
|
399 |
-
'/wp-admin/options-general.php' => array(),
|
400 |
-
'/wp-admin/post-new.php' => array(),
|
401 |
-
'/wp-admin/page-new.php' => array(),
|
402 |
-
'/wp-admin/link-add.php' => array(),
|
403 |
-
'/wp-admin/media-upload.php' => array(),
|
404 |
-
'/wp-admin/post.php' => array(),
|
405 |
-
'/wp-admin/page.php' => array(),
|
406 |
-
'/wp-admin/admin-ajax.php' => array(),
|
407 |
-
'/wp-comments-post.php' => array(
|
408 |
-
'url',
|
409 |
-
'comment'
|
410 |
-
),
|
411 |
-
'/wp-login.php' => array(
|
412 |
-
'redirect_to'
|
413 |
-
)
|
414 |
-
);
|
415 |
-
|
416 |
-
// add in custom whitelisted pages later
|
417 |
-
|
418 |
-
$this->m_aWhitelistPages = $aDefaultWlPages;
|
419 |
-
$this->m_aWhitelistPagesPatterns = array(
|
420 |
-
'/wp-admin/\*' => array(
|
421 |
-
'_wp_original_http_referer',
|
422 |
-
'_wp_http_referer'
|
423 |
-
),
|
424 |
-
);
|
425 |
-
}
|
426 |
-
|
427 |
-
public function isVisitorOnWhitelist() {
|
428 |
-
return $this->isIpOnlist( $this->m_aWhitelistIps, $this->m_sRequestIp );
|
429 |
-
}
|
430 |
-
|
431 |
-
public function isVisitorOnBlacklist() {
|
432 |
-
return $this->isIpOnlist( $this->m_aBlacklistIps, $this->m_sRequestIp );
|
433 |
-
}
|
434 |
-
|
435 |
-
public function isIpOnlist( $inaList, $insIpAddress = '' ) {
|
436 |
-
|
437 |
-
if ( empty( $insIpAddress ) ) {
|
438 |
-
return true;
|
439 |
-
}
|
440 |
-
return in_array( $insIpAddress, $inaList );
|
441 |
-
}
|
442 |
-
|
443 |
-
public static function GetVisitorIpAddress() {
|
444 |
-
|
445 |
-
$sIpAddress = empty($_SERVER["HTTP_X_FORWARDED_FOR"]) ? $_SERVER["REMOTE_ADDR"] : $_SERVER["HTTP_X_FORWARDED_FOR"];
|
446 |
-
|
447 |
-
if( strpos($sIpAddress, ',') !== false ) {
|
448 |
-
$sIpAddress = explode(',', $sIpAddress);
|
449 |
-
$sIpAddress = $sIpAddress[0];
|
450 |
-
}
|
451 |
-
|
452 |
-
return $sIpAddress;
|
453 |
-
|
454 |
-
}//GetVisitorIpAddress
|
455 |
-
|
456 |
-
/**
|
457 |
-
* @param string $insLogMessage
|
458 |
-
*/
|
459 |
-
public function logInfo( $insLogMessage ) {
|
460 |
-
$this->writeLog( $insLogMessage, self::LOG_MESSAGE_TYPE_INFO );
|
461 |
-
}
|
462 |
-
/**
|
463 |
-
* @param string $insLogMessage
|
464 |
-
*/
|
465 |
-
public function logWarning( $insLogMessage ) {
|
466 |
-
$this->writeLog( $insLogMessage, self::LOG_MESSAGE_TYPE_WARNING );
|
467 |
-
}
|
468 |
-
/**
|
469 |
-
* @param string $insLogMessage
|
470 |
-
*/
|
471 |
-
public function logCritical( $insLogMessage ) {
|
472 |
-
$this->writeLog( $insLogMessage, self::LOG_MESSAGE_TYPE_CRITICAL );
|
473 |
-
}
|
474 |
-
|
475 |
-
public function sendBlockEmail( $insEmailAddress ) {
|
476 |
-
|
477 |
-
$aMessage = array(
|
478 |
-
'WordPress Simple Firewall has blocked a visitor to your site.',
|
479 |
-
'Log details for this visitor are below:',
|
480 |
-
'- IP Address: '.$this->m_sRequestIp
|
481 |
-
);
|
482 |
-
foreach( $this->m_aLog[ $this->m_sRequestId ] as $aLogItem ) {
|
483 |
-
list( $sTime, $sLogType, $sLogMessage ) = $aLogItem;
|
484 |
-
$aMessage[] = '- '.$aLogItem[2];
|
485 |
-
}
|
486 |
-
|
487 |
-
$aMessage[] = 'You could look up the offending IP Address here: http://ip-lookup.net/?ip='. $this->m_sRequestIp;
|
488 |
-
$sEmailSubject = 'Firewall Block Alert: ' . home_url();
|
489 |
-
$sSiteName = get_bloginfo('name');
|
490 |
-
$aHeaders = array(
|
491 |
-
'MIME-Version: 1.0',
|
492 |
-
'Content-type: text/plain; charset=iso-8859-1',
|
493 |
-
"From: Simple Firewall Plugin - $sSiteName <$insEmailAddress>",
|
494 |
-
'Reply-To: Site Admin <receiver@domain3.com>',
|
495 |
-
'Subject: '.$sEmailSubject,
|
496 |
-
'X-Mailer: PHP/'.phpversion()
|
497 |
-
);
|
498 |
-
mail( $insEmailAddress, $sEmailSubject, implode( "\r\n", $aMessage ), implode( "\r\n", $aHeaders ) );
|
499 |
-
}
|
500 |
-
}
|
501 |
-
|
502 |
-
endif;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/icwp-import-base-processor.php
ADDED
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2013 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_BaseProcessor_WPSF {
|
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
ADDED
@@ -0,0 +1,147 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2013 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_OptionsHandler_Wpsf
|
26 |
+
*/
|
27 |
+
protected $m_oWpsfOptions;
|
28 |
+
/**
|
29 |
+
* @var ICWP_OptionsHandler_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_DataProcessor::Add_New_Raw_Ips( $aTargetIpWhitelist, $aNewList ) );
|
140 |
+
// $this->updateTargetOption( $this->m_aOptionsMap['WP_firewall_whitelisted_ip'], ICWP_DataProcessor::Add_New_Raw_Ips( $aTargetIpWhitelist, $aNewList ) );
|
141 |
+
|
142 |
+
// Whitelisted Pages and Vars... maybe later :|
|
143 |
+
}
|
144 |
+
|
145 |
+
}
|
146 |
+
|
147 |
+
endif;
|
src/icwp-optionshandler-autoupdates.php
ADDED
@@ -0,0 +1,148 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2013 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_OptionsHandler_AutoUpdates') ):
|
21 |
+
|
22 |
+
class ICWP_OptionsHandler_AutoUpdates extends ICWP_OptionsHandler_Base_WPSF {
|
23 |
+
|
24 |
+
const StoreName = 'autoupdates_options';
|
25 |
+
|
26 |
+
public function __construct( $insPrefix, $insVersion ) {
|
27 |
+
parent::__construct( $insPrefix, self::StoreName, $insVersion );
|
28 |
+
}
|
29 |
+
|
30 |
+
public function doPrePluginOptionsSave() {}
|
31 |
+
|
32 |
+
public function defineOptions() {
|
33 |
+
|
34 |
+
$aAutoUpdatesBase = array(
|
35 |
+
'section_title' => 'Enable Automatic Updates Section',
|
36 |
+
'section_options' => array(
|
37 |
+
array(
|
38 |
+
'enable_autoupdates',
|
39 |
+
'',
|
40 |
+
'N',
|
41 |
+
'checkbox',
|
42 |
+
'Enable Auto Updates',
|
43 |
+
'Enable (or Disable) The WordPress Automatic Updates Feature',
|
44 |
+
'Regardless of any other settings, this option will turn Off the Auto Updates feature, or enable your selected Auto Updates options.'
|
45 |
+
)
|
46 |
+
)
|
47 |
+
);
|
48 |
+
$aAutoUpdateOptions = array( 'select',
|
49 |
+
array( 'core_never', 'Never' ),
|
50 |
+
array( 'core_minor', 'Minor Versions Only' ),
|
51 |
+
array( 'core_major', 'Major and Minor Versions' ),
|
52 |
+
);
|
53 |
+
$aAutoUpdateCore = array(
|
54 |
+
'section_title' => 'Automatic Plugin Self-Update',
|
55 |
+
'section_options' => array(
|
56 |
+
array(
|
57 |
+
'autoupdate_plugin_wpsf',
|
58 |
+
'',
|
59 |
+
'Y',
|
60 |
+
'checkbox',
|
61 |
+
'Auto Update Plugin',
|
62 |
+
'Always Automatically Update This Plugin',
|
63 |
+
'Regardless of any component settings below, automatically update the WordPress Simple Firewall plugin.'
|
64 |
+
)
|
65 |
+
)
|
66 |
+
);
|
67 |
+
$aAutoUpdateComponents = array(
|
68 |
+
'section_title' => 'Choose Which WordPress Components To Allow Automatic Updates',
|
69 |
+
'section_options' => array(
|
70 |
+
array(
|
71 |
+
'autoupdate_core',
|
72 |
+
'',
|
73 |
+
'core_minor',
|
74 |
+
$aAutoUpdateOptions,
|
75 |
+
'WordPress Core Updates',
|
76 |
+
'Decide how the WordPress Core will automatically update, if at all.',
|
77 |
+
'At least automatically upgrading minor versions is recommended (and is the WordPress default).'
|
78 |
+
),
|
79 |
+
array(
|
80 |
+
'enable_autoupdate_translations',
|
81 |
+
'',
|
82 |
+
'Y',
|
83 |
+
'checkbox',
|
84 |
+
'Translations',
|
85 |
+
'Automatically Update Translations',
|
86 |
+
'Note: Automatic updates for translations are enabled on WordPress by default.'
|
87 |
+
),
|
88 |
+
array(
|
89 |
+
'enable_autoupdate_plugins',
|
90 |
+
'',
|
91 |
+
'N',
|
92 |
+
'checkbox',
|
93 |
+
'Plugins',
|
94 |
+
'Automatically Update Plugins',
|
95 |
+
'Note: Automatic updates for plugins are disabled on WordPress by default.'
|
96 |
+
),
|
97 |
+
array(
|
98 |
+
'enable_autoupdate_themes',
|
99 |
+
'',
|
100 |
+
'N',
|
101 |
+
'checkbox',
|
102 |
+
'Themes',
|
103 |
+
'Automatically Update Themes',
|
104 |
+
'Note: Automatic updates for themes are disabled on WordPress by default.'
|
105 |
+
),
|
106 |
+
array(
|
107 |
+
'enable_autoupdate_ignore_vcs',
|
108 |
+
'',
|
109 |
+
'N',
|
110 |
+
'checkbox',
|
111 |
+
'Ignore Version Control',
|
112 |
+
'Ignore Version Control Systems Such As GIT and SVN',
|
113 |
+
'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'
|
114 |
+
)
|
115 |
+
)
|
116 |
+
);
|
117 |
+
$aAutoUpdateAll = array(
|
118 |
+
'section_title' => 'Disable ALL Automatic Updates',
|
119 |
+
'section_options' => array(
|
120 |
+
array(
|
121 |
+
'enable_autoupdate_disable_all',
|
122 |
+
'',
|
123 |
+
'N',
|
124 |
+
'checkbox',
|
125 |
+
'Disable All',
|
126 |
+
'Completely Disable Automatic Updates',
|
127 |
+
'When selected, regardless of any setting above, all automatic updates on this site will be completely disabled'
|
128 |
+
)
|
129 |
+
)
|
130 |
+
);
|
131 |
+
|
132 |
+
$this->m_aOptions = array(
|
133 |
+
$aAutoUpdatesBase,
|
134 |
+
$aAutoUpdateCore,
|
135 |
+
$aAutoUpdateComponents,
|
136 |
+
$aAutoUpdateAll
|
137 |
+
);
|
138 |
+
}
|
139 |
+
|
140 |
+
public function updateHandler() {
|
141 |
+
|
142 |
+
$sCurrentVersion = empty( $this->m_aOptionsValues[ 'current_plugin_version' ] )? '0.0' : $this->m_aOptionsValues[ 'current_plugin_version' ];
|
143 |
+
if ( version_compare( $sCurrentVersion, '1.9.0', '<' ) ) {
|
144 |
+
}//v1.9.0
|
145 |
+
}
|
146 |
+
}
|
147 |
+
|
148 |
+
endif;
|
src/icwp-optionshandler-base.php
ADDED
@@ -0,0 +1,569 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2013 iControlWP <support@icontrolwp.com>
|
4 |
+
* All rights reserved.
|
5 |
+
*
|
6 |
+
* Version: 2013-08-27-A
|
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 |
+
if ( !class_exists('ICWP_OptionsHandler_Base_WPSF') ):
|
21 |
+
|
22 |
+
class ICWP_OptionsHandler_Base_WPSF {
|
23 |
+
|
24 |
+
const CollateSeparator = '--SEP--';
|
25 |
+
|
26 |
+
/**
|
27 |
+
* @var boolean
|
28 |
+
*/
|
29 |
+
protected $m_fNeedSave;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* @var boolean
|
33 |
+
*/
|
34 |
+
protected $m_fFullInit;
|
35 |
+
|
36 |
+
/**
|
37 |
+
* @var string
|
38 |
+
*/
|
39 |
+
protected $m_sOptionPrefix;
|
40 |
+
|
41 |
+
/**
|
42 |
+
* @var string
|
43 |
+
*/
|
44 |
+
protected $m_sVersion;
|
45 |
+
|
46 |
+
/**
|
47 |
+
* @var array
|
48 |
+
*/
|
49 |
+
protected $m_aOptions;
|
50 |
+
|
51 |
+
/**
|
52 |
+
* @var array
|
53 |
+
*/
|
54 |
+
protected $m_aDirectSaveOptions;
|
55 |
+
|
56 |
+
/**
|
57 |
+
* @var boolean
|
58 |
+
*/
|
59 |
+
protected $m_fIsMultisite;
|
60 |
+
|
61 |
+
/**
|
62 |
+
* This is used primarily for the options deletion/cleanup. We store the names
|
63 |
+
* of options here that are not modified directly by the user/UI so that we can
|
64 |
+
* cleanup later on.
|
65 |
+
*
|
66 |
+
* @var array
|
67 |
+
*/
|
68 |
+
protected $m_aIndependentOptions;
|
69 |
+
|
70 |
+
/**
|
71 |
+
* These are options that need to be stored, but are never set by the UI.
|
72 |
+
*
|
73 |
+
* @var array
|
74 |
+
*/
|
75 |
+
protected $m_aNonUiOptions;
|
76 |
+
|
77 |
+
/**
|
78 |
+
* @var array
|
79 |
+
*/
|
80 |
+
protected $m_aOptionsValues;
|
81 |
+
|
82 |
+
/**
|
83 |
+
* @var array
|
84 |
+
*/
|
85 |
+
protected $m_aOptionsStoreName;
|
86 |
+
|
87 |
+
public function __construct( $insPrefix, $insStoreName, $insVersion ) {
|
88 |
+
$this->m_sOptionPrefix = $insPrefix;
|
89 |
+
$this->m_aOptionsStoreName = $insStoreName;
|
90 |
+
$this->m_sVersion = $insVersion;
|
91 |
+
|
92 |
+
$this->m_fIsMultisite = function_exists( 'is_multisite' ) && is_multisite();
|
93 |
+
|
94 |
+
// Handle any upgrades as necessary (only go near this if it's the admin area)
|
95 |
+
add_action( 'plugins_loaded', array( $this, 'doUpdates' ) );
|
96 |
+
}
|
97 |
+
|
98 |
+
public function doUpdates() {
|
99 |
+
if ( $this->hasPluginManageRights() ) {
|
100 |
+
$this->buildOptions();
|
101 |
+
$this->updateHandler();
|
102 |
+
}
|
103 |
+
}
|
104 |
+
|
105 |
+
public function hasPluginManageRights() {
|
106 |
+
if ( !current_user_can( 'manage_options' ) ) {
|
107 |
+
return false;
|
108 |
+
}
|
109 |
+
if ( $this->m_fIsMultisite && is_network_admin() ) {
|
110 |
+
return true;
|
111 |
+
}
|
112 |
+
else if ( !$this->m_fIsMultisite && is_admin() ) {
|
113 |
+
return true;
|
114 |
+
}
|
115 |
+
return false;
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* @return string
|
120 |
+
*/
|
121 |
+
public function getVersion() {
|
122 |
+
return $this->m_sVersion;
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* @return string
|
127 |
+
*/
|
128 |
+
public function setVersion( $insVersion ) {
|
129 |
+
return $this->m_sVersion = $insVersion;
|
130 |
+
}
|
131 |
+
|
132 |
+
/**
|
133 |
+
* Sets the value for the given option key
|
134 |
+
*
|
135 |
+
* @param string $insKey
|
136 |
+
* @param mixed $inmValue
|
137 |
+
* @return boolean
|
138 |
+
*/
|
139 |
+
public function setOpt( $insKey, $inmValue ) {
|
140 |
+
|
141 |
+
if ( !isset( $this->m_aOptionsValues ) ) {
|
142 |
+
$this->loadStoredOptionsValues();
|
143 |
+
}
|
144 |
+
|
145 |
+
if ( $this->getOpt( $insKey ) === $inmValue ) {
|
146 |
+
return true;
|
147 |
+
}
|
148 |
+
|
149 |
+
$this->m_aOptionsValues[ $insKey ] = $inmValue;
|
150 |
+
|
151 |
+
if ( !$this->m_fNeedSave ) {
|
152 |
+
$this->m_fNeedSave = true;
|
153 |
+
}
|
154 |
+
return true;
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* @param string $insKey
|
159 |
+
* @return Ambigous <boolean, multitype:>
|
160 |
+
*/
|
161 |
+
public function getOpt( $insKey ) {
|
162 |
+
if ( !isset( $this->m_aOptionsValues ) ) {
|
163 |
+
$this->loadStoredOptionsValues();
|
164 |
+
}
|
165 |
+
return ( isset( $this->m_aOptionsValues[ $insKey ] )? $this->m_aOptionsValues[ $insKey ] : false );
|
166 |
+
}
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Retrieves the full array of options->values
|
170 |
+
*
|
171 |
+
* @return array
|
172 |
+
*/
|
173 |
+
public function getOptions() {
|
174 |
+
if ( !isset( $this->m_aOptions ) ) {
|
175 |
+
$this->buildOptions();
|
176 |
+
}
|
177 |
+
return $this->m_aOptions;
|
178 |
+
}
|
179 |
+
|
180 |
+
/**
|
181 |
+
* Loads the options and their stored values from the WordPress Options store.
|
182 |
+
*
|
183 |
+
* @return array
|
184 |
+
*/
|
185 |
+
public function getPluginOptionsValues() {
|
186 |
+
$this->generateOptionsValues();
|
187 |
+
return $this->m_aOptionsValues;
|
188 |
+
}
|
189 |
+
|
190 |
+
/**
|
191 |
+
* Saves the options to the WordPress Options store.
|
192 |
+
*
|
193 |
+
* It will also update the stored plugin options version.
|
194 |
+
*/
|
195 |
+
public function savePluginOptions() {
|
196 |
+
|
197 |
+
$this->doPrePluginOptionsSave();
|
198 |
+
$this->updateOptionsVersion();
|
199 |
+
|
200 |
+
if ( !$this->m_fNeedSave ) {
|
201 |
+
return true;
|
202 |
+
}
|
203 |
+
|
204 |
+
$this->updateOption( $this->m_aOptionsStoreName, $this->m_aOptionsValues );
|
205 |
+
|
206 |
+
// Direct save options allow us to get fast access to certain values without loading the whole thing
|
207 |
+
if ( isset( $this->m_aDirectSaveOptions ) && is_array( $this->m_aDirectSaveOptions ) ) {
|
208 |
+
foreach( $this->m_aDirectSaveOptions as $sOptionKey ) {
|
209 |
+
$this->updateOption( $sOptionKey, $this->getOpt( $sOptionKey ) );
|
210 |
+
}
|
211 |
+
}
|
212 |
+
|
213 |
+
$this->m_fNeedSave = false;
|
214 |
+
}
|
215 |
+
|
216 |
+
public function collateAllFormInputsForAllOptions() {
|
217 |
+
|
218 |
+
if ( !isset( $this->m_aOptions ) ) {
|
219 |
+
$this->buildOptions();
|
220 |
+
}
|
221 |
+
|
222 |
+
$aToJoin = array();
|
223 |
+
foreach ( $this->m_aOptions as $aOptionsSection ) {
|
224 |
+
|
225 |
+
if ( empty( $aOptionsSection ) ) {
|
226 |
+
continue;
|
227 |
+
}
|
228 |
+
foreach ( $aOptionsSection['section_options'] as $aOption ) {
|
229 |
+
list($sKey, $fill1, $fill2, $sType) = $aOption;
|
230 |
+
$aToJoin[] = $sType.':'.$sKey;
|
231 |
+
}
|
232 |
+
}
|
233 |
+
return implode( self::CollateSeparator, $aToJoin );
|
234 |
+
}
|
235 |
+
|
236 |
+
/**
|
237 |
+
* @return array
|
238 |
+
*/
|
239 |
+
protected function generateOptionsValues() {
|
240 |
+
if ( !isset( $this->m_aOptionsValues ) ) {
|
241 |
+
$this->loadStoredOptionsValues();
|
242 |
+
}
|
243 |
+
if ( empty( $this->m_aOptionsValues ) ) {
|
244 |
+
$this->buildOptions(); // set the defaults
|
245 |
+
}
|
246 |
+
}
|
247 |
+
|
248 |
+
/**
|
249 |
+
* Loads the options and their stored values from the WordPress Options store.
|
250 |
+
*/
|
251 |
+
protected function loadStoredOptionsValues() {
|
252 |
+
if ( empty( $this->m_aOptionsValues ) ) {
|
253 |
+
$this->m_aOptionsValues = $this->getOption( $this->m_aOptionsStoreName );
|
254 |
+
if ( empty( $this->m_aOptionsValues ) ) {
|
255 |
+
$this->m_aOptionsValues = array();
|
256 |
+
$this->m_fNeedSave = true;
|
257 |
+
}
|
258 |
+
}
|
259 |
+
}
|
260 |
+
|
261 |
+
protected function defineOptions() {
|
262 |
+
|
263 |
+
if ( !empty( $this->m_aOptions ) ) {
|
264 |
+
return true;
|
265 |
+
}
|
266 |
+
|
267 |
+
$aMisc = array(
|
268 |
+
'section_title' => 'Miscellaneous Plugin Options',
|
269 |
+
'section_options' => array(
|
270 |
+
array(
|
271 |
+
'delete_on_deactivate',
|
272 |
+
'',
|
273 |
+
'N',
|
274 |
+
'checkbox',
|
275 |
+
'Delete Plugin Settings',
|
276 |
+
'Delete All Plugin Settings Upon Plugin Deactivation',
|
277 |
+
'Careful: Removes all plugin options when you deactivite the plugin.'
|
278 |
+
),
|
279 |
+
),
|
280 |
+
);
|
281 |
+
$this->m_aOptions = array( $aMisc );
|
282 |
+
}
|
283 |
+
|
284 |
+
/**
|
285 |
+
* Will initiate the plugin options structure for use by the UI builder.
|
286 |
+
*
|
287 |
+
* It will also fill in $this->m_aOptionsValues with defaults where appropriate.
|
288 |
+
*
|
289 |
+
* It doesn't set any values, just populates the array created in buildOptions()
|
290 |
+
* with values stored.
|
291 |
+
*
|
292 |
+
* It has to handle the conversion of stored values to data to be displayed to the user.
|
293 |
+
*
|
294 |
+
* @param string $insUpdateKey - if only want to update a single key, supply it here.
|
295 |
+
*/
|
296 |
+
protected function buildOptions() {
|
297 |
+
|
298 |
+
$this->defineOptions();
|
299 |
+
$this->loadStoredOptionsValues();
|
300 |
+
|
301 |
+
foreach ( $this->m_aOptions as &$aOptionsSection ) {
|
302 |
+
|
303 |
+
if ( empty( $aOptionsSection ) || !isset( $aOptionsSection['section_options'] ) ) {
|
304 |
+
continue;
|
305 |
+
}
|
306 |
+
|
307 |
+
foreach ( $aOptionsSection['section_options'] as &$aOptionParams ) {
|
308 |
+
|
309 |
+
list( $sOptionKey, $sOptionValue, $sOptionDefault, $sOptionType ) = $aOptionParams;
|
310 |
+
|
311 |
+
if ( $this->getOpt( $sOptionKey ) === false ) {
|
312 |
+
$this->setOpt( $sOptionKey, $sOptionDefault );
|
313 |
+
}
|
314 |
+
$mCurrentOptionVal = $this->getOpt( $sOptionKey );
|
315 |
+
|
316 |
+
if ( $sOptionType == 'password' && !empty( $mCurrentOptionVal ) ) {
|
317 |
+
$mCurrentOptionVal = '';
|
318 |
+
}
|
319 |
+
else if ( $sOptionType == 'ip_addresses' ) {
|
320 |
+
|
321 |
+
if ( empty( $mCurrentOptionVal ) ) {
|
322 |
+
$mCurrentOptionVal = '';
|
323 |
+
}
|
324 |
+
else {
|
325 |
+
$mCurrentOptionVal = implode( "\n", $this->convertIpListForDisplay( $mCurrentOptionVal ) );
|
326 |
+
}
|
327 |
+
}
|
328 |
+
else if ( $sOptionType == 'comma_separated_lists' ) {
|
329 |
+
|
330 |
+
if ( empty( $mCurrentOptionVal ) ) {
|
331 |
+
$mCurrentOptionVal = '';
|
332 |
+
}
|
333 |
+
else {
|
334 |
+
$aNewValues = array();
|
335 |
+
foreach( $mCurrentOptionVal as $sPage => $aParams ) {
|
336 |
+
$aNewValues[] = $sPage.', '. implode( ", ", $aParams );
|
337 |
+
}
|
338 |
+
$mCurrentOptionVal = implode( "\n", $aNewValues );
|
339 |
+
}
|
340 |
+
}
|
341 |
+
$aOptionParams[1] = $mCurrentOptionVal;
|
342 |
+
}
|
343 |
+
}
|
344 |
+
|
345 |
+
// Cater for Non-UI options that don't necessarily go through the UI
|
346 |
+
if ( isset($this->m_aNonUiOptions) && is_array($this->m_aNonUiOptions) ) {
|
347 |
+
foreach( $this->m_aNonUiOptions as $sOption ) {
|
348 |
+
if ( !$this->getOpt( $sOption ) ) {
|
349 |
+
$this->setOpt( $sOption, '' );
|
350 |
+
}
|
351 |
+
}
|
352 |
+
}
|
353 |
+
}
|
354 |
+
|
355 |
+
/**
|
356 |
+
* This is the point where you would want to do any options verification
|
357 |
+
*/
|
358 |
+
protected function doPrePluginOptionsSave() { }
|
359 |
+
|
360 |
+
/**
|
361 |
+
* Will return the 'current_plugin_version' if it is set, 0.0 otherwise.
|
362 |
+
*
|
363 |
+
* @return string
|
364 |
+
*/
|
365 |
+
public function getPluginOptionsVersion() {
|
366 |
+
$sVersion = $this->getOpt( 'current_plugin_version' );
|
367 |
+
return empty( $sVersion )? '0.0' :$sVersion;
|
368 |
+
}
|
369 |
+
|
370 |
+
/**
|
371 |
+
* Updates the 'current_plugin_version' to the offical plugin version.
|
372 |
+
*/
|
373 |
+
protected function updateOptionsVersion() {
|
374 |
+
$this->setOpt( 'current_plugin_version', $this->m_sVersion );
|
375 |
+
}
|
376 |
+
|
377 |
+
/**
|
378 |
+
* Deletes all the options including direct save.
|
379 |
+
*/
|
380 |
+
public function deletePluginOptions() {
|
381 |
+
|
382 |
+
$this->deleteOption( $this->m_aOptionsStoreName );
|
383 |
+
|
384 |
+
// Direct save options allow us to get fast access to certain values without loading the whole thing
|
385 |
+
if ( isset($this->m_aDirectSaveOptions) && is_array( $this->m_aDirectSaveOptions ) ) {
|
386 |
+
foreach( $this->m_aDirectSaveOptions as $sOptionKey ) {
|
387 |
+
$this->deleteOption( $sOptionKey );
|
388 |
+
}
|
389 |
+
}
|
390 |
+
// Independent options are those untouched by the User/UI that are saved elsewhere and directly to the WP Options table. They are "meta" options
|
391 |
+
if ( isset($this->m_aIndependentOptions) && is_array( $this->m_aIndependentOptions ) ) {
|
392 |
+
foreach( $this->m_aIndependentOptions as $sOptionKey ) {
|
393 |
+
$this->deleteOption( $sOptionKey );
|
394 |
+
}
|
395 |
+
}
|
396 |
+
}
|
397 |
+
|
398 |
+
protected function convertIpListForDisplay( $inaIpList = array() ) {
|
399 |
+
|
400 |
+
$aDisplay = array();
|
401 |
+
if ( empty( $inaIpList ) || empty( $inaIpList['ips'] ) ) {
|
402 |
+
return $aDisplay;
|
403 |
+
}
|
404 |
+
foreach( $inaIpList['ips'] as $sAddress ) {
|
405 |
+
// offset=1 in the case that it's a range and the first number is negative on 32-bit systems
|
406 |
+
$mPos = strpos( $sAddress, '-', 1 );
|
407 |
+
|
408 |
+
if ( $mPos === false ) { //plain IP address
|
409 |
+
$sDisplayText = long2ip( $sAddress );
|
410 |
+
}
|
411 |
+
else {
|
412 |
+
//we remove the first character in case this is '-'
|
413 |
+
$aParts = array( substr( $sAddress, 0, 1 ), substr( $sAddress, 1 ) );
|
414 |
+
list( $nStart, $nEnd ) = explode( '-', $aParts[1], 2 );
|
415 |
+
$sDisplayText = long2ip( $aParts[0].$nStart ) .'-'. long2ip( $nEnd );
|
416 |
+
}
|
417 |
+
$sLabel = $inaIpList['meta'][ md5($sAddress) ];
|
418 |
+
$sLabel = trim( $sLabel, '()' );
|
419 |
+
$aDisplay[] = $sDisplayText . ' ('.$sLabel.')';
|
420 |
+
}
|
421 |
+
return $aDisplay;
|
422 |
+
}
|
423 |
+
|
424 |
+
/**
|
425 |
+
* @param string $sAllOptionsInput - comma separated list of all the input keys to be processed from the $_POST
|
426 |
+
* @return void|boolean
|
427 |
+
*/
|
428 |
+
public function updatePluginOptionsFromSubmit( $sAllOptionsInput ) {
|
429 |
+
|
430 |
+
if ( empty( $sAllOptionsInput ) ) {
|
431 |
+
return;
|
432 |
+
}
|
433 |
+
|
434 |
+
$this->loadStoredOptionsValues();
|
435 |
+
|
436 |
+
$aAllInputOptions = explode( self::CollateSeparator, $sAllOptionsInput );
|
437 |
+
foreach ( $aAllInputOptions as $sInputKey ) {
|
438 |
+
$aInput = explode( ':', $sInputKey );
|
439 |
+
list( $sOptionType, $sOptionKey ) = $aInput;
|
440 |
+
|
441 |
+
$sOptionValue = $this->getFromPost( $sOptionKey );
|
442 |
+
if ( is_null($sOptionValue) ) {
|
443 |
+
|
444 |
+
if ( $sOptionType == 'text' || $sOptionType == 'email' ) { //if it was a text box, and it's null, don't update anything
|
445 |
+
continue;
|
446 |
+
}
|
447 |
+
else if ( $sOptionType == 'checkbox' ) { //if it was a checkbox, and it's null, it means 'N'
|
448 |
+
$sOptionValue = 'N';
|
449 |
+
}
|
450 |
+
else if ( $sOptionType == 'integer' ) { //if it was a integer, and it's null, it means '0'
|
451 |
+
$sOptionValue = 0;
|
452 |
+
}
|
453 |
+
}
|
454 |
+
else { //handle any pre-processing we need to.
|
455 |
+
|
456 |
+
if ( $sOptionType == 'integer' ) {
|
457 |
+
$sOptionValue = intval( $sOptionValue );
|
458 |
+
}
|
459 |
+
else if ( $sOptionType == 'password' && $this->hasEncryptOption() ) { //md5 any password fields
|
460 |
+
$sTempValue = trim( $sOptionValue );
|
461 |
+
if ( empty( $sTempValue ) ) {
|
462 |
+
continue;
|
463 |
+
}
|
464 |
+
$sOptionValue = md5( $sTempValue );
|
465 |
+
}
|
466 |
+
else if ( $sOptionType == 'ip_addresses' ) { //ip addresses are textareas, where each is separated by newline
|
467 |
+
|
468 |
+
if ( !class_exists('ICWP_DataProcessor') ) {
|
469 |
+
require_once ( dirname(__FILE__).'/icwp-data-processor.php' );
|
470 |
+
}
|
471 |
+
$oProcessor = new ICWP_DataProcessor();
|
472 |
+
$sOptionValue = $oProcessor->ExtractIpAddresses( $sOptionValue );
|
473 |
+
}
|
474 |
+
else if ( $sOptionType == 'email' && function_exists( 'is_email' ) && !is_email( $sOptionValue ) ) {
|
475 |
+
$sOptionValue = '';
|
476 |
+
}
|
477 |
+
else if ( $sOptionType == 'comma_separated_lists' ) {
|
478 |
+
if ( !class_exists('ICWP_DataProcessor') ) {
|
479 |
+
require_once ( dirname(__FILE__).'/icwp-data-processor.php' );
|
480 |
+
}
|
481 |
+
$oProcessor = new ICWP_DataProcessor();
|
482 |
+
$sOptionValue = $oProcessor->ExtractCommaSeparatedList( $sOptionValue );
|
483 |
+
}
|
484 |
+
}
|
485 |
+
$this->setOpt( $sOptionKey, $sOptionValue );
|
486 |
+
}
|
487 |
+
return $this->savePluginOptions( true );
|
488 |
+
}
|
489 |
+
|
490 |
+
/**
|
491 |
+
* Should be over-ridden by each new class to handle upgrades.
|
492 |
+
*
|
493 |
+
* Called upon construction and after plugin options are initialized.
|
494 |
+
*/
|
495 |
+
protected function updateHandler() { }
|
496 |
+
|
497 |
+
/**
|
498 |
+
* @param array $inaNewOptions
|
499 |
+
*/
|
500 |
+
protected function mergeNonUiOptions( $inaNewOptions = array() ) {
|
501 |
+
|
502 |
+
if ( !empty( $this->m_aNonUiOptions ) ) {
|
503 |
+
$this->m_aNonUiOptions = array_merge( $this->m_aNonUiOptions, $inaNewOptions );
|
504 |
+
}
|
505 |
+
else {
|
506 |
+
$this->m_aNonUiOptions = $inaNewOptions;
|
507 |
+
}
|
508 |
+
}
|
509 |
+
|
510 |
+
/**
|
511 |
+
* Copies WordPress Options to the options array and optionally deletes the original.
|
512 |
+
*
|
513 |
+
* @param array $inaOptions
|
514 |
+
* @param boolean $fDeleteOld
|
515 |
+
*/
|
516 |
+
protected function migrateOptions( $inaOptions, $fDeleteOld = false ) {
|
517 |
+
foreach( $inaOptions as $sOptionKey ) {
|
518 |
+
$mCurrentValue = $this->getOption( $sOptionKey );
|
519 |
+
if ( $mCurrentValue === false ) {
|
520 |
+
continue;
|
521 |
+
}
|
522 |
+
$this->setOpt( $sOptionKey, $mCurrentValue );
|
523 |
+
if ( $fDeleteOld ) {
|
524 |
+
$this->deleteOption( $sOptionKey );
|
525 |
+
}
|
526 |
+
}
|
527 |
+
}
|
528 |
+
|
529 |
+
/**
|
530 |
+
* @return boolean
|
531 |
+
*/
|
532 |
+
public function hasEncryptOption() {
|
533 |
+
return function_exists( 'md5' );
|
534 |
+
// return extension_loaded( 'mcrypt' );
|
535 |
+
}
|
536 |
+
|
537 |
+
protected function getVisitorIpAddress( $infAsLong = true ) {
|
538 |
+
require_once( dirname(__FILE__).'/icwp-base-processor.php' );
|
539 |
+
return ICWP_BaseProcessor_WPSF::GetVisitorIpAddress( $infAsLong );
|
540 |
+
}
|
541 |
+
|
542 |
+
/**
|
543 |
+
* @param string $insKey - the POST key
|
544 |
+
* @param string $insPrefix
|
545 |
+
* @return Ambigous <null, string>
|
546 |
+
*/
|
547 |
+
protected function getFromPost( $insKey, $insPrefix = null ) {
|
548 |
+
$sKey = ( is_null( $insPrefix )? $this->m_sOptionPrefix : $insPrefix ) . $insKey;
|
549 |
+
return ( isset( $_POST[ $sKey ] )? $_POST[ $sKey ]: null );
|
550 |
+
}
|
551 |
+
public function getOption( $insKey ) {
|
552 |
+
$sKey = $this->m_sOptionPrefix.$insKey;
|
553 |
+
return $this->m_fIsMultisite? get_site_option($sKey) : get_option($sKey);
|
554 |
+
}
|
555 |
+
public function addOption( $insKey, $insValue ) {
|
556 |
+
$sKey = $this->m_sOptionPrefix.$insKey;
|
557 |
+
return $this->m_fIsMultisite? add_site_option($sKey, $insValue) : add_option($sKey, $insValue);
|
558 |
+
}
|
559 |
+
public function updateOption( $insKey, $insValue ) {
|
560 |
+
$sKey = $this->m_sOptionPrefix.$insKey;
|
561 |
+
return $this->m_fIsMultisite? update_site_option($sKey, $insValue) : update_option($sKey, $insValue);
|
562 |
+
}
|
563 |
+
public function deleteOption( $insKey ) {
|
564 |
+
$sKey = $this->m_sOptionPrefix.$insKey;
|
565 |
+
return $this->m_fIsMultisite? delete_site_option($sKey) : delete_option($sKey);
|
566 |
+
}
|
567 |
+
}
|
568 |
+
|
569 |
+
endif;
|
src/icwp-optionshandler-commentsfilter.php
ADDED
@@ -0,0 +1,164 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2013 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_OptionsHandler_CommentsFilter') ):
|
21 |
+
|
22 |
+
class ICWP_OptionsHandler_CommentsFilter extends ICWP_OptionsHandler_Base_WPSF {
|
23 |
+
|
24 |
+
const StoreName = 'commentsfilter_options';
|
25 |
+
|
26 |
+
const DefaultCommentCooldown = 30; //seconds.
|
27 |
+
const DefaultCommentExpire = 600; //seconds.
|
28 |
+
|
29 |
+
public function __construct( $insPrefix, $insVersion ) {
|
30 |
+
parent::__construct( $insPrefix, self::StoreName, $insVersion );
|
31 |
+
}
|
32 |
+
|
33 |
+
public function defineOptions() {
|
34 |
+
|
35 |
+
$this->m_aDirectSaveOptions = array();
|
36 |
+
|
37 |
+
$aBase = array(
|
38 |
+
'section_title' => 'Enable Comments Filter',
|
39 |
+
'section_options' => array(
|
40 |
+
array(
|
41 |
+
'enable_comments_filter',
|
42 |
+
'',
|
43 |
+
'Y',
|
44 |
+
'checkbox',
|
45 |
+
'Enable Comments Filter',
|
46 |
+
'Enable (or Disable) The Comments Filter Feature',
|
47 |
+
'Regardless of any other settings, this option will turn Off the Comments Filter feature, or enable your chosen Comments Filter options.'
|
48 |
+
)
|
49 |
+
),
|
50 |
+
);
|
51 |
+
$aGasp = array(
|
52 |
+
'section_title' => 'G.A.S.P. Comment SPAM Protection',
|
53 |
+
'section_options' => array(
|
54 |
+
array(
|
55 |
+
'enable_comments_gasp_protection',
|
56 |
+
'',
|
57 |
+
'Y',
|
58 |
+
'checkbox',
|
59 |
+
'GASP Protection',
|
60 |
+
'Add Growmap Anti Spambot Protection to your comments',
|
61 |
+
'Taking the lead from the original GASP plugin for WordPress, we have extended it to include further protection. '.sprintf( '[%smore info%s]', '<a href="http://icwp.io/2n" target="_blank">', '</a>' )
|
62 |
+
),
|
63 |
+
array(
|
64 |
+
'enable_comments_gasp_protection_for_logged_in',
|
65 |
+
'',
|
66 |
+
'N',
|
67 |
+
'checkbox',
|
68 |
+
'Include Logged-In Users',
|
69 |
+
'You may also enable GASP for logged in users',
|
70 |
+
'Since logged-in users would be expected to be vetted, this is off by default.'
|
71 |
+
),
|
72 |
+
array(
|
73 |
+
'comments_cooldown_interval',
|
74 |
+
'',
|
75 |
+
'30',
|
76 |
+
'integer',
|
77 |
+
'Comments Cooldown',
|
78 |
+
'Limit posting a comment to X seconds after the page has loaded',
|
79 |
+
"By forcing a comments cooldown period, you restrict a Spambot's ability to post mutliple times to your posts."
|
80 |
+
),
|
81 |
+
array(
|
82 |
+
'comments_token_expire_interval',
|
83 |
+
'',
|
84 |
+
'600',
|
85 |
+
'integer',
|
86 |
+
'Comment Token Expire',
|
87 |
+
'A visitor has X seconds within which to post a comment',
|
88 |
+
"Default: 10 minutes (600 seconds). 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."
|
89 |
+
),
|
90 |
+
array(
|
91 |
+
'custom_message_checkbox',
|
92 |
+
'',
|
93 |
+
"I'm not a spammer.",
|
94 |
+
'text',
|
95 |
+
'Custom Checkbox Message',
|
96 |
+
"If you want a custom checkbox message, please specify this here.",
|
97 |
+
"You can customise the message beside the checkbox. Default: I'm not a spammer"
|
98 |
+
),
|
99 |
+
array(
|
100 |
+
'custom_message_alert',
|
101 |
+
'',
|
102 |
+
"Please check the box to confirm you're not a spammer",
|
103 |
+
'text',
|
104 |
+
'Custom Alert Message',
|
105 |
+
"If you want a custom alert message, please specify this here.",
|
106 |
+
"Default: Please check the box to confirm you're not a spammer"
|
107 |
+
),
|
108 |
+
array(
|
109 |
+
'custom_message_comment_wait',
|
110 |
+
'',
|
111 |
+
"Please wait %s seconds before posting your comment",
|
112 |
+
'text',
|
113 |
+
'Custom Alert Message',
|
114 |
+
"If you want a custom submit-button message please specify this here.",
|
115 |
+
"Where you see the '%s' this will be the number of seconds. You must ensure you include 1, and only 1, of these.
|
116 |
+
<br />Default: Please wait %s seconds before posting your comment"
|
117 |
+
),
|
118 |
+
array(
|
119 |
+
'custom_message_comment_reload',
|
120 |
+
'',
|
121 |
+
"Please reload this page to post a comment",
|
122 |
+
'text',
|
123 |
+
'Custom Alert Message',
|
124 |
+
"This message is displayed on the submit-button when the comment token is expired.",
|
125 |
+
"Default: Please reload this page to post a comment"
|
126 |
+
)
|
127 |
+
)
|
128 |
+
);
|
129 |
+
|
130 |
+
$this->m_aOptions = array(
|
131 |
+
$aBase,
|
132 |
+
$aGasp
|
133 |
+
);
|
134 |
+
}
|
135 |
+
|
136 |
+
/**
|
137 |
+
* This is the point where you would want to do any options verification
|
138 |
+
*/
|
139 |
+
protected function doPrePluginOptionsSave() {
|
140 |
+
|
141 |
+
$nCommentCooldown = $this->getOpt( 'comments_cooldown_interval' );
|
142 |
+
if ( $nCommentCooldown < 0 ) {
|
143 |
+
$nCommentCooldown = 0;
|
144 |
+
}
|
145 |
+
|
146 |
+
$nCommentTokenExpire = $this->getOpt( 'comments_token_expire_interval' );
|
147 |
+
if ( $nCommentTokenExpire < 0 ) {
|
148 |
+
$nCommentTokenExpire = 0;
|
149 |
+
}
|
150 |
+
|
151 |
+
if ( $nCommentTokenExpire != 0 && $nCommentCooldown > $nCommentTokenExpire ) {
|
152 |
+
$nCommentCooldown = self::DefaultCommentCooldown;
|
153 |
+
$nCommentTokenExpire = self::DefaultCommentExpire;
|
154 |
+
}
|
155 |
+
$this->setOpt( 'comments_cooldown_interval', $nCommentCooldown );
|
156 |
+
$this->setOpt( 'comments_token_expire_interval', $nCommentTokenExpire );
|
157 |
+
}
|
158 |
+
|
159 |
+
public function updateHandler() {
|
160 |
+
$sCurrentVersion = empty( $this->m_aOptionsValues[ 'current_plugin_version' ] )? '0.0' : $this->m_aOptionsValues[ 'current_plugin_version' ];
|
161 |
+
}
|
162 |
+
}
|
163 |
+
|
164 |
+
endif;
|
src/icwp-optionshandler-firewall.php
ADDED
@@ -0,0 +1,255 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2013 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_OptionsHandler_Firewall') ):
|
21 |
+
|
22 |
+
class ICWP_OptionsHandler_Firewall extends ICWP_OptionsHandler_Base_WPSF {
|
23 |
+
|
24 |
+
const StoreName = 'firewall_options';
|
25 |
+
|
26 |
+
public function __construct( $insPrefix, $insVersion ) {
|
27 |
+
parent::__construct( $insPrefix, self::StoreName, $insVersion );
|
28 |
+
}
|
29 |
+
|
30 |
+
public function doPrePluginOptionsSave() {
|
31 |
+
|
32 |
+
$aIpWhitelist = $this->getOpt( 'ips_blacklist' );
|
33 |
+
if ( $aIpWhitelist === false ) {
|
34 |
+
$aIpWhitelist = '';
|
35 |
+
$this->setOpt( 'ips_whitelist', $aIpWhitelist );
|
36 |
+
}
|
37 |
+
|
38 |
+
$aIpBlacklist = $this->getOpt( 'ips_blacklist' );
|
39 |
+
if ( $aIpBlacklist === false ) {
|
40 |
+
$aIpBlacklist = '';
|
41 |
+
$this->setOpt( 'ips_blacklist', $aIpBlacklist );
|
42 |
+
}
|
43 |
+
|
44 |
+
$aPageWhitelist = $this->getOpt( 'page_params_whitelist' );
|
45 |
+
if ( $aPageWhitelist === false ) {
|
46 |
+
$aPageWhitelist = '';
|
47 |
+
$this->setOpt( 'page_params_whitelist', $aPageWhitelist );
|
48 |
+
}
|
49 |
+
|
50 |
+
$sBlockResponse = $this->getOpt( 'block_response' );
|
51 |
+
if ( empty( $sBlockResponse ) ) {
|
52 |
+
$sBlockResponse = 'redirect_die_message';
|
53 |
+
$aIpWhitelist = $this->setOpt( 'block_response', $sBlockResponse );
|
54 |
+
}
|
55 |
+
}
|
56 |
+
|
57 |
+
public function defineOptions() {
|
58 |
+
|
59 |
+
$this->m_aDirectSaveOptions = array( 'whitelist_admins' );
|
60 |
+
|
61 |
+
$this->m_aFirewallBase = array(
|
62 |
+
'section_title' => 'Enable WordPress Firewall',
|
63 |
+
'section_options' => array(
|
64 |
+
array(
|
65 |
+
'enable_firewall',
|
66 |
+
'', 'N',
|
67 |
+
'checkbox',
|
68 |
+
'Enable Firewall',
|
69 |
+
'Enable (or Disable) The WordPress Firewall Feature',
|
70 |
+
'Regardless of any other settings, this option will turn Off the Firewall feature, or enable your selected Firewall options.'
|
71 |
+
)
|
72 |
+
)
|
73 |
+
);
|
74 |
+
$this->m_aBlockTypesSection = array(
|
75 |
+
'section_title' => 'Firewall Blocking Options',
|
76 |
+
'section_options' => array(
|
77 |
+
array(
|
78 |
+
'include_cookie_checks',
|
79 |
+
'',
|
80 |
+
'N',
|
81 |
+
'checkbox',
|
82 |
+
'Include Cookies',
|
83 |
+
'Also Test Cookie Values In Firewall Tests',
|
84 |
+
'The firewall will test GET and POST, but with this option checked, it will also COOKIE values for the same.'
|
85 |
+
),
|
86 |
+
array(
|
87 |
+
'block_dir_traversal',
|
88 |
+
'',
|
89 |
+
'N',
|
90 |
+
'checkbox',
|
91 |
+
'Directory Traversals',
|
92 |
+
'Block Directory Traversals',
|
93 |
+
'This will block directory traversal paths in in application parameters (../, ../../etc/passwd, etc.)'
|
94 |
+
),
|
95 |
+
array(
|
96 |
+
'block_sql_queries',
|
97 |
+
'',
|
98 |
+
'N',
|
99 |
+
'checkbox',
|
100 |
+
'SQL Queries',
|
101 |
+
'Block SQL Queries',
|
102 |
+
'This will block in application parameters (union select, concat(, /**/, etc.).'
|
103 |
+
),
|
104 |
+
array(
|
105 |
+
'block_wordpress_terms',
|
106 |
+
'',
|
107 |
+
'N',
|
108 |
+
'checkbox',
|
109 |
+
'WordPress Terms',
|
110 |
+
'Block WordPress Specific Terms',
|
111 |
+
'This will block WordPress specific terms in application parameters (wp_, user_login, etc.).'
|
112 |
+
),
|
113 |
+
array(
|
114 |
+
'block_field_truncation',
|
115 |
+
'',
|
116 |
+
'N',
|
117 |
+
'checkbox',
|
118 |
+
'Field Truncation',
|
119 |
+
'Block Field Truncation Attacks',
|
120 |
+
'This will block field truncation attacks in application parameters.'
|
121 |
+
),
|
122 |
+
array(
|
123 |
+
'block_exe_file_uploads',
|
124 |
+
'',
|
125 |
+
'N',
|
126 |
+
'checkbox',
|
127 |
+
'Exe File Uploads',
|
128 |
+
'Block Executable File Uploads',
|
129 |
+
'This will block executable file uploads (.php, .exe, etc.).'
|
130 |
+
),
|
131 |
+
array(
|
132 |
+
'block_leading_schema',
|
133 |
+
'',
|
134 |
+
'N',
|
135 |
+
'checkbox',
|
136 |
+
'Leading Schemas',
|
137 |
+
'Block Leading Schemas (HTTPS / HTTP)',
|
138 |
+
'This will block leading schemas http:// and https:// in application parameters (off by default; may cause problems with many plugins).'
|
139 |
+
)
|
140 |
+
),
|
141 |
+
);
|
142 |
+
$aRedirectOptions = array( 'select',
|
143 |
+
array( 'redirect_die_message', 'Die With Message' ),
|
144 |
+
array( 'redirect_die', 'Die' ),
|
145 |
+
array( 'redirect_home', 'Redirect To Home Page' ),
|
146 |
+
array( 'redirect_404', 'Return 404' ),
|
147 |
+
);
|
148 |
+
$this->m_aBlockSection = array(
|
149 |
+
'section_title' => 'Choose Firewall Block Response',
|
150 |
+
'section_options' => array(
|
151 |
+
array( 'block_response', '', 'none', $aRedirectOptions, 'Block Response', 'Choose how the firewall responds when it blocks a request', '' ),
|
152 |
+
array( 'block_send_email', '', 'N', 'checkbox', 'Send Email Report', 'When a visitor is blocked it will send an email to the blog admin', '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.' )
|
153 |
+
)
|
154 |
+
);
|
155 |
+
|
156 |
+
$this->m_aWhitelistSection = array(
|
157 |
+
'section_title' => 'Whitelist - IPs, Pages, Parameters, and Users that by-pass the Firewall',
|
158 |
+
'section_options' => array(
|
159 |
+
array(
|
160 |
+
'ips_whitelist',
|
161 |
+
'',
|
162 |
+
'',
|
163 |
+
'ip_addresses',
|
164 |
+
'Whitelist IP Addresses',
|
165 |
+
'Choose IP Addresses that are never subjected to Firewall Rules',
|
166 |
+
sprintf( 'Take a new line per address. Your IP address is: %s', '<span class="code">'.$this->getVisitorIpAddress( false ).'</span>' )
|
167 |
+
),
|
168 |
+
array(
|
169 |
+
'page_params_whitelist',
|
170 |
+
'',
|
171 |
+
'',
|
172 |
+
'comma_separated_lists',
|
173 |
+
'Whitelist Parameters',
|
174 |
+
'Detail pages and parameters that are whitelisted (ignored)',
|
175 |
+
'This should be used with caution and you should only provide parameter names that you need to have excluded.'
|
176 |
+
.' [<a href="http://icwp.io/2a" target="_blank">Help</a>]'
|
177 |
+
),
|
178 |
+
array(
|
179 |
+
'whitelist_admins',
|
180 |
+
'',
|
181 |
+
'N',
|
182 |
+
'checkbox',
|
183 |
+
'Ignore Administrators',
|
184 |
+
'Ignore users logged in as Administrator',
|
185 |
+
'Authenticated administrator users will not be processed by the firewall.'
|
186 |
+
)
|
187 |
+
)
|
188 |
+
);
|
189 |
+
|
190 |
+
$this->m_aBlacklistSection = array(
|
191 |
+
'section_title' => 'Choose IP Addresses To Blacklist',
|
192 |
+
'section_options' => array(
|
193 |
+
array(
|
194 |
+
'ips_blacklist',
|
195 |
+
'',
|
196 |
+
'',
|
197 |
+
'ip_addresses',
|
198 |
+
'Blacklist IP Addresses',
|
199 |
+
'Choose IP Addresses that are always blocked access to the site',
|
200 |
+
'Take a new line per address. Each IP Address must be valid and will be checked.'
|
201 |
+
)
|
202 |
+
)
|
203 |
+
);
|
204 |
+
$this->m_aFirewallMiscSection = array(
|
205 |
+
'section_title' => 'Miscellaneous Plugin Options',
|
206 |
+
'section_options' => array(
|
207 |
+
array(
|
208 |
+
'enable_firewall_log',
|
209 |
+
'', 'N',
|
210 |
+
'checkbox',
|
211 |
+
'Firewall Logging',
|
212 |
+
'Turn on a detailed Firewall Log',
|
213 |
+
'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.'
|
214 |
+
)
|
215 |
+
)
|
216 |
+
);
|
217 |
+
|
218 |
+
$this->m_aOptions = array(
|
219 |
+
$this->m_aFirewallBase,
|
220 |
+
$this->m_aBlockSection,
|
221 |
+
$this->m_aWhitelistSection,
|
222 |
+
$this->m_aBlacklistSection,
|
223 |
+
$this->m_aBlockTypesSection,
|
224 |
+
$this->m_aFirewallMiscSection
|
225 |
+
);
|
226 |
+
}
|
227 |
+
|
228 |
+
public function updateHandler() {
|
229 |
+
|
230 |
+
$sCurrentVersion = empty( $this->m_aOptionsValues[ 'current_plugin_version' ] )? '0.0' : $this->m_aOptionsValues[ 'current_plugin_version' ];
|
231 |
+
if ( version_compare( $sCurrentVersion, '1.4.0', '<' ) ) {
|
232 |
+
$aSettingsKey = array(
|
233 |
+
'current_plugin_version',
|
234 |
+
'enable_firewall',
|
235 |
+
'include_cookie_checks',
|
236 |
+
'block_dir_traversal',
|
237 |
+
'block_sql_queries',
|
238 |
+
'block_wordpress_terms',
|
239 |
+
'block_field_truncation',
|
240 |
+
'block_exe_file_uploads',
|
241 |
+
'block_leading_schema',
|
242 |
+
'block_send_email',
|
243 |
+
'ips_whitelist',
|
244 |
+
'ips_blacklist',
|
245 |
+
'page_params_whitelist',
|
246 |
+
'block_response',
|
247 |
+
'enable_firewall_log',
|
248 |
+
'whitelist_admins'
|
249 |
+
);
|
250 |
+
$this->migrateOptions( $aSettingsKey );
|
251 |
+
}//v1.4.0
|
252 |
+
}
|
253 |
+
}
|
254 |
+
|
255 |
+
endif;
|
src/icwp-optionshandler-lockdown.php
ADDED
@@ -0,0 +1,123 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2013 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 |
+
require_once( dirname(__FILE__).'/icwp-optionshandler-lockdown.php' );
|
20 |
+
|
21 |
+
if ( !class_exists('ICWP_OptionsHandler_Lockdown') ):
|
22 |
+
|
23 |
+
class ICWP_OptionsHandler_Lockdown extends ICWP_OptionsHandler_Base_WPSF {
|
24 |
+
|
25 |
+
const StoreName = 'lockdown_options';
|
26 |
+
|
27 |
+
public function __construct( $insPrefix, $insVersion ) {
|
28 |
+
parent::__construct( $insPrefix, self::StoreName, $insVersion );
|
29 |
+
}
|
30 |
+
|
31 |
+
public function doPrePluginOptionsSave() {
|
32 |
+
|
33 |
+
if ( $this->getOpt( 'action_reset_auth_salts' ) == 'Y' ) {
|
34 |
+
$this->setOpt( 'action_reset_auth_salts', 'P' );
|
35 |
+
}
|
36 |
+
else if ( $this->getOpt( 'action_reset_auth_salts' ) == 'P' ) {
|
37 |
+
$this->setOpt( 'action_reset_auth_salts', 'N' );
|
38 |
+
}
|
39 |
+
}
|
40 |
+
|
41 |
+
public function defineOptions() {
|
42 |
+
|
43 |
+
$aBase = array(
|
44 |
+
'section_title' => 'Enable Lockdown Feature',
|
45 |
+
'section_options' => array(
|
46 |
+
array(
|
47 |
+
'enable_lockdown',
|
48 |
+
'',
|
49 |
+
'N',
|
50 |
+
'checkbox',
|
51 |
+
'Enable Lockdown',
|
52 |
+
'Enable (or Disable) The Lockdown Feature',
|
53 |
+
'Regardless of any other settings, this option will turn Off the Lockdown feature, or enable your selected Lockdown options.'
|
54 |
+
)
|
55 |
+
)
|
56 |
+
);
|
57 |
+
$aAccess = array(
|
58 |
+
'section_title' => 'Access Options',
|
59 |
+
'section_options' => array(
|
60 |
+
array(
|
61 |
+
'disable_file_editing',
|
62 |
+
'',
|
63 |
+
'N',
|
64 |
+
'checkbox',
|
65 |
+
'Disable File Editing',
|
66 |
+
'Disable Ability To Edit Files',
|
67 |
+
'Removes the option to directly edit any files from within the WordPress admin area.
|
68 |
+
<br />Equivalent to setting DISALLOW_FILE_EDIT to TRUE.'
|
69 |
+
)
|
70 |
+
)
|
71 |
+
);
|
72 |
+
|
73 |
+
$this->m_aOptions = array(
|
74 |
+
$aBase,
|
75 |
+
$aAccess
|
76 |
+
);
|
77 |
+
|
78 |
+
if ( false && $this->getCanDoAuthSalts() ) {
|
79 |
+
$this->m_aOptions[] = array(
|
80 |
+
'section_title' => 'Security Actions',
|
81 |
+
'section_options' => array(
|
82 |
+
array(
|
83 |
+
'action_reset_auth_salts',
|
84 |
+
'',
|
85 |
+
'N',
|
86 |
+
'checkbox',
|
87 |
+
'Reset Auth Keys/Salts',
|
88 |
+
'Reset WordPress Authentication Keys and Salts',
|
89 |
+
'Selecting this and saving will reset the WordPress Authentication Keys and Salts in your wp-config.php file.
|
90 |
+
<br /><strong>Note: This will log you and all other users out of their current session.</strong>'
|
91 |
+
)
|
92 |
+
)
|
93 |
+
);
|
94 |
+
}
|
95 |
+
}
|
96 |
+
|
97 |
+
protected function getCanDoAuthSalts() {
|
98 |
+
require_once( dirname(__FILE__).'/icwp-wpfilesystem.php' );
|
99 |
+
$oWpFilesystem = new ICWP_WpFilesystem_WPSF();
|
100 |
+
|
101 |
+
if ( !$oWpFilesystem->getCanWpRemoteGet() ) {
|
102 |
+
return false;
|
103 |
+
}
|
104 |
+
|
105 |
+
if ( !$oWpFilesystem->getCanDiskWrite() ) {
|
106 |
+
return false;
|
107 |
+
}
|
108 |
+
|
109 |
+
$sWpConfigPath = is_file( ABSPATH.'wp-config.php' )? ABSPATH.'wp-config.php' : ABSPATH.'..'.ICWP_DS.'wp-config.php';
|
110 |
+
|
111 |
+
if ( !is_file( $sWpConfigPath ) ) {
|
112 |
+
var_dump('no wpconfig');
|
113 |
+
return false;
|
114 |
+
}
|
115 |
+
$mResult = $oWpFilesystem->getCanReadWriteFile( $sWpConfigPath );
|
116 |
+
return !empty( $mResult );
|
117 |
+
}
|
118 |
+
|
119 |
+
public function updateHandler() {
|
120 |
+
}
|
121 |
+
}
|
122 |
+
|
123 |
+
endif;
|
src/icwp-optionshandler-loginprotect.php
ADDED
@@ -0,0 +1,150 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2013 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_OptionsHandler_LoginProtect') ):
|
21 |
+
|
22 |
+
class ICWP_OptionsHandler_LoginProtect extends ICWP_OptionsHandler_Base_WPSF {
|
23 |
+
|
24 |
+
const StoreName = 'loginprotect_options';
|
25 |
+
|
26 |
+
public function __construct( $insPrefix, $insVersion ) {
|
27 |
+
parent::__construct( $insPrefix, self::StoreName, $insVersion );
|
28 |
+
}
|
29 |
+
|
30 |
+
public function defineOptions() {
|
31 |
+
|
32 |
+
$this->m_aDirectSaveOptions = array();
|
33 |
+
|
34 |
+
$this->m_aOptionsBase = array(
|
35 |
+
'section_title' => 'Enable Login Protection',
|
36 |
+
'section_options' => array(
|
37 |
+
array(
|
38 |
+
'enable_login_protect',
|
39 |
+
'',
|
40 |
+
'Y',
|
41 |
+
'checkbox',
|
42 |
+
'Enable Login Protect',
|
43 |
+
'Enable (or Disable) The Login Protection Feature',
|
44 |
+
'Regardless of any other settings, this option will turn Off the Login Protect feature, or enable your selected Login Protect options.'
|
45 |
+
)
|
46 |
+
),
|
47 |
+
);
|
48 |
+
$this->m_aWhitelist = array(
|
49 |
+
'section_title' => 'Whitelist IPs that by-pass Login Protect',
|
50 |
+
'section_options' => array(
|
51 |
+
array(
|
52 |
+
'ips_whitelist',
|
53 |
+
'',
|
54 |
+
'',
|
55 |
+
'ip_addresses',
|
56 |
+
'Whitelist IP Addresses',
|
57 |
+
'Specify IP Addresses that by-pass all Login Protect rules',
|
58 |
+
sprintf( 'Take a new line per address. Your IP address is: %s', '<span class="code">'.$this->getVisitorIpAddress( false ).'</span>' )
|
59 |
+
)
|
60 |
+
)
|
61 |
+
);
|
62 |
+
$this->m_aTwoFactorAuth = array(
|
63 |
+
'section_title' => 'Two-Factor Authentication Protection Options',
|
64 |
+
'section_options' => array(
|
65 |
+
array(
|
66 |
+
'enable_two_factor_auth_by_ip',
|
67 |
+
'',
|
68 |
+
'N',
|
69 |
+
'checkbox',
|
70 |
+
'Two-Factor Authentication',
|
71 |
+
'Two-Factor Login Authentication By IP Address',
|
72 |
+
'All users will be required to authenticate their logins by email-based two-factor authentication when logging in from a new IP address.'
|
73 |
+
),
|
74 |
+
array(
|
75 |
+
'enable_two_factor_bypass_on_email_fail',
|
76 |
+
'',
|
77 |
+
'N',
|
78 |
+
'checkbox',
|
79 |
+
'By-Pass On Failure',
|
80 |
+
'If Sending Verification Email Sending Fails, Two-Factor Login Authentication Is Ignored',
|
81 |
+
'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.'
|
82 |
+
)
|
83 |
+
)
|
84 |
+
);
|
85 |
+
$this->m_aLoginProtect = array(
|
86 |
+
'section_title' => 'Login Protection Options',
|
87 |
+
'section_options' => array(
|
88 |
+
array(
|
89 |
+
'login_limit_interval',
|
90 |
+
'',
|
91 |
+
'5',
|
92 |
+
'integer',
|
93 |
+
'Login Cooldown Interval',
|
94 |
+
'Limit login attempts to every X seconds',
|
95 |
+
'WordPress will process only ONE login attempt for every number of seconds specified. Zero (0) turns this off. Suggested: 5'
|
96 |
+
),
|
97 |
+
array(
|
98 |
+
'enable_login_gasp_check',
|
99 |
+
'',
|
100 |
+
'Y',
|
101 |
+
'checkbox',
|
102 |
+
'G.A.S.P Protection',
|
103 |
+
'Prevent Login By Bots using G.A.S.P. Protection',
|
104 |
+
'Adds a dynamically (Javascript) generated checkbox to the login form that prevents bots using automated login techniques. Recommended: ON'
|
105 |
+
)
|
106 |
+
)
|
107 |
+
);
|
108 |
+
|
109 |
+
$this->m_aLoggingSection = array(
|
110 |
+
'section_title' => 'Logging Options',
|
111 |
+
'section_options' => array(
|
112 |
+
array(
|
113 |
+
'enable_login_protect_log',
|
114 |
+
'', 'N',
|
115 |
+
'checkbox',
|
116 |
+
'Login Protect Logging',
|
117 |
+
'Turn on a detailed Login Protect Log',
|
118 |
+
'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.'
|
119 |
+
)
|
120 |
+
)
|
121 |
+
);
|
122 |
+
|
123 |
+
$this->m_aOptions = array(
|
124 |
+
$this->m_aOptionsBase,
|
125 |
+
$this->m_aWhitelist,
|
126 |
+
$this->m_aTwoFactorAuth,
|
127 |
+
$this->m_aLoginProtect,
|
128 |
+
$this->m_aLoggingSection
|
129 |
+
);
|
130 |
+
}
|
131 |
+
|
132 |
+
public function updateHandler() {
|
133 |
+
|
134 |
+
$sCurrentVersion = empty( $this->m_aOptionsValues[ 'current_plugin_version' ] )? '0.0' : $this->m_aOptionsValues[ 'current_plugin_version' ];
|
135 |
+
if ( version_compare( $sCurrentVersion, '1.4.0', '<' ) ) {
|
136 |
+
$aSettingsKey = array(
|
137 |
+
'current_plugin_version',
|
138 |
+
'enable_login_protect',
|
139 |
+
'enable_two_factor_auth_by_ip',
|
140 |
+
'enable_two_factor_bypass_on_email_fail',
|
141 |
+
'login_limit_interval',
|
142 |
+
'enable_login_gasp_check',
|
143 |
+
'enable_login_protect_log',
|
144 |
+
);
|
145 |
+
$this->migrateOptions( $aSettingsKey );
|
146 |
+
}//'1.4.0', '<'
|
147 |
+
}
|
148 |
+
}
|
149 |
+
|
150 |
+
endif;
|
src/icwp-optionshandler-wpsf.php
ADDED
@@ -0,0 +1,275 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2013 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_OptionsHandler_Wpsf') ):
|
21 |
+
|
22 |
+
class ICWP_OptionsHandler_Wpsf extends ICWP_OptionsHandler_Base_WPSF {
|
23 |
+
|
24 |
+
const StoreName = 'plugin_options';
|
25 |
+
const Default_AccessKeyTimeout = 30;
|
26 |
+
|
27 |
+
public function __construct( $insPrefix, $insVersion ) {
|
28 |
+
parent::__construct( $insPrefix, self::StoreName, $insVersion );
|
29 |
+
}
|
30 |
+
|
31 |
+
public function defineOptions() {
|
32 |
+
|
33 |
+
$this->m_aIndependentOptions = array(
|
34 |
+
'firewall_processor',
|
35 |
+
'login_processor',
|
36 |
+
'comments_processor',
|
37 |
+
'lockdown_processor',
|
38 |
+
'autoupdates_processor',
|
39 |
+
'logging_processor',
|
40 |
+
'email_processor'
|
41 |
+
);
|
42 |
+
|
43 |
+
$aNonUiOptions = array(
|
44 |
+
'secret_key',
|
45 |
+
'feedback_admin_notice',
|
46 |
+
'update_success_tracker',
|
47 |
+
'capability_can_disk_write',
|
48 |
+
'capability_can_remote_get'
|
49 |
+
);
|
50 |
+
$this->mergeNonUiOptions( $aNonUiOptions );
|
51 |
+
|
52 |
+
if ( $this->hasEncryptOption() ) {
|
53 |
+
|
54 |
+
$aAccessKey = array(
|
55 |
+
'section_title' => 'Admin Access Restriction',
|
56 |
+
'section_options' => array(
|
57 |
+
array(
|
58 |
+
'enable_admin_access_restriction',
|
59 |
+
'',
|
60 |
+
'N',
|
61 |
+
'checkbox',
|
62 |
+
'Enable Access Key',
|
63 |
+
'Enforce Admin Access Restriction',
|
64 |
+
sprintf(
|
65 |
+
'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. [%smore info%s]',
|
66 |
+
'<a href="http://icwp.io/2r" target="_blank">',
|
67 |
+
'</a>'
|
68 |
+
)
|
69 |
+
),
|
70 |
+
array(
|
71 |
+
'admin_access_timeout',
|
72 |
+
'',
|
73 |
+
self::Default_AccessKeyTimeout,
|
74 |
+
'integer',
|
75 |
+
'Access Key Timeout',
|
76 |
+
'Specify A Timeout For Plugin Admin Access',
|
77 |
+
'This will automatically expire your WordPress Simple Firewall session. Does not apply until you enter the access key again. Default: 30 minutes.'
|
78 |
+
),
|
79 |
+
array(
|
80 |
+
'admin_access_key',
|
81 |
+
'',
|
82 |
+
'',
|
83 |
+
'password',
|
84 |
+
'Admin Access Key',
|
85 |
+
'Specify Your Plugin Access Key',
|
86 |
+
'If you forget this, you could potentially lock yourself out from using this plugin. <strong>Leave it blank to <u>not</u> update it</strong>.'
|
87 |
+
)
|
88 |
+
)
|
89 |
+
);
|
90 |
+
}
|
91 |
+
|
92 |
+
$aGeneral = array(
|
93 |
+
'section_title' => 'General Plugin Options',
|
94 |
+
'section_options' => array(
|
95 |
+
array(
|
96 |
+
'enable_firewall',
|
97 |
+
'', 'N',
|
98 |
+
'checkbox',
|
99 |
+
'Enable Firewall',
|
100 |
+
'Enable (or Disable) The WordPress Firewall Feature',
|
101 |
+
'Regardless of any other settings, this option will turn Off the Firewall feature, or enable your selected Firewall options.'
|
102 |
+
),
|
103 |
+
array(
|
104 |
+
'enable_login_protect',
|
105 |
+
'',
|
106 |
+
'Y',
|
107 |
+
'checkbox',
|
108 |
+
'Enable Login Protect',
|
109 |
+
'Enable (or Disable) The Login Protection Feature',
|
110 |
+
'Regardless of any other settings, this option will turn Off the Login Protect feature, or enable your selected Login Protect options.'
|
111 |
+
),
|
112 |
+
array(
|
113 |
+
'enable_comments_filter',
|
114 |
+
'',
|
115 |
+
'Y',
|
116 |
+
'checkbox',
|
117 |
+
'Enable Comments Filter',
|
118 |
+
'Enable (or Disable) The Comments Filter Feature',
|
119 |
+
'Regardless of any other settings, this option will turn Off the Comments Filter feature, or enable your selected Comments Filter options.'
|
120 |
+
),
|
121 |
+
array(
|
122 |
+
'enable_lockdown',
|
123 |
+
'',
|
124 |
+
'N',
|
125 |
+
'checkbox',
|
126 |
+
'Enable Lockdown',
|
127 |
+
'Enable (or Disable) The Lockdown Feature',
|
128 |
+
'Regardless of any other settings, this option will turn Off the Lockdown feature, or enable your selected Lockdown options.'
|
129 |
+
),
|
130 |
+
array(
|
131 |
+
'enable_autoupdates',
|
132 |
+
'',
|
133 |
+
'N',
|
134 |
+
'checkbox',
|
135 |
+
'Enable Auto Updates',
|
136 |
+
'Enable (or Disable) The WordPress Automatic Updates Feature',
|
137 |
+
'Regardless of any other settings, this option will turn Off the Auto Updates feature, or enable your selected Auto Updates options.'
|
138 |
+
),
|
139 |
+
/*
|
140 |
+
array(
|
141 |
+
'enable_auto_plugin_upgrade',
|
142 |
+
'',
|
143 |
+
'N',
|
144 |
+
'checkbox',
|
145 |
+
'Auto-Upgrade',
|
146 |
+
'When an upgrade is detected, the plugin will automatically initiate the upgrade.',
|
147 |
+
'If you prefer to manage plugin upgrades, deselect this option. Otherwise, this plugin will auto-upgrade once any available update is detected.'
|
148 |
+
),
|
149 |
+
*/
|
150 |
+
array(
|
151 |
+
'enable_upgrade_admin_notice',
|
152 |
+
'',
|
153 |
+
'Y',
|
154 |
+
'checkbox',
|
155 |
+
'Upgrade Notice',
|
156 |
+
'Display A Notice When An Upgrade Is Available',
|
157 |
+
'Will display a notice at the top of your WordPress admin section when a plugin upgrade is available.'
|
158 |
+
),
|
159 |
+
array(
|
160 |
+
'delete_on_deactivate',
|
161 |
+
'',
|
162 |
+
'N',
|
163 |
+
'checkbox',
|
164 |
+
'Delete Plugin Settings',
|
165 |
+
'Delete All Plugin Settings Upon Plugin Deactivation',
|
166 |
+
'Careful: Removes all plugin options when you deactivite the plugin.'
|
167 |
+
)
|
168 |
+
)
|
169 |
+
);
|
170 |
+
|
171 |
+
$aEmail = array(
|
172 |
+
'section_title' => 'Email Options',
|
173 |
+
'section_options' => array(
|
174 |
+
array(
|
175 |
+
'block_send_email_address',
|
176 |
+
'',
|
177 |
+
'',
|
178 |
+
'email',
|
179 |
+
'Report Email',
|
180 |
+
'Where to send email reports',
|
181 |
+
'If this is empty, it will default to the blog admin email address.'
|
182 |
+
),
|
183 |
+
array(
|
184 |
+
'send_email_throttle_limit',
|
185 |
+
'',
|
186 |
+
'10',
|
187 |
+
'integer',
|
188 |
+
'Email Throttle Limit',
|
189 |
+
'Limit Emails Per Second',
|
190 |
+
'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'
|
191 |
+
)
|
192 |
+
)
|
193 |
+
);
|
194 |
+
|
195 |
+
$this->m_aOptions = array(
|
196 |
+
$aGeneral,
|
197 |
+
$aEmail
|
198 |
+
);
|
199 |
+
if ( isset( $aAccessKey ) ) {
|
200 |
+
array_unshift( $this->m_aOptions, $aAccessKey );
|
201 |
+
}
|
202 |
+
}
|
203 |
+
|
204 |
+
/**
|
205 |
+
* This is the point where you would want to do any options verification
|
206 |
+
*/
|
207 |
+
protected function doPrePluginOptionsSave() {
|
208 |
+
|
209 |
+
$nTimeout = $this->getOpt( 'admin_access_key_timeout');
|
210 |
+
if ( $nTimeout <= 0 ) {
|
211 |
+
$nTimeout = self::Default_AccessKeyTimeout;
|
212 |
+
}
|
213 |
+
$this->setOpt( 'admin_access_key_timeout', $nTimeout );
|
214 |
+
|
215 |
+
$sAccessKey = $this->getOpt( 'admin_access_key');
|
216 |
+
if ( empty( $sAccessKey ) ) {
|
217 |
+
$this->setOpt( 'enable_admin_access_restriction', 'N' );
|
218 |
+
}
|
219 |
+
|
220 |
+
$sEmail = $this->getOpt( 'block_send_email_address');
|
221 |
+
if ( empty( $sEmail ) || !is_email( $sEmail ) ) {
|
222 |
+
$sEmail = get_option('admin_email');
|
223 |
+
}
|
224 |
+
if ( is_email( $sEmail ) ) {
|
225 |
+
$this->setOpt( 'block_send_email_address', $sEmail );
|
226 |
+
}
|
227 |
+
|
228 |
+
$sLimit = $this->getOpt( 'send_email_throttle_limit' );
|
229 |
+
if ( !is_numeric( $sLimit ) || $sLimit < 0 ) {
|
230 |
+
$sLimit = 0;
|
231 |
+
}
|
232 |
+
$this->setOpt( 'send_email_throttle_limit', $sLimit );
|
233 |
+
}
|
234 |
+
|
235 |
+
protected function updateHandler() {
|
236 |
+
|
237 |
+
// the 'current_plugin_version' value moved from a direct save option to be
|
238 |
+
// included in the plugin options object, so we have to account for it being
|
239 |
+
// empty.
|
240 |
+
$sCurrentVersion = empty( $this->m_aOptionsValues[ 'current_plugin_version' ] )? '0.0' : $this->m_aOptionsValues[ 'current_plugin_version' ];
|
241 |
+
if ( version_compare( $sCurrentVersion, '1.4.0', '<' ) ) {
|
242 |
+
$aSettingsKey = array(
|
243 |
+
'current_plugin_version',
|
244 |
+
'enable_firewall',
|
245 |
+
'enable_login_protect',
|
246 |
+
'feedback_admin_notice',
|
247 |
+
'secret_key',
|
248 |
+
'block_send_email_address',
|
249 |
+
'send_email_throttle_limit',
|
250 |
+
'delete_on_deactivate'
|
251 |
+
);
|
252 |
+
$this->migrateOptions( $aSettingsKey );
|
253 |
+
}// '1.4.0', '<'
|
254 |
+
|
255 |
+
if ( version_compare( $sCurrentVersion, '1.8.2', '<=' ) ) {
|
256 |
+
|
257 |
+
$fCanRemoteGet = $this->getOpt( 'capability_can_remote_get' );
|
258 |
+
$fCanDiskWrite = $this->getOpt( 'capability_can_disk_write' );
|
259 |
+
|
260 |
+
if ( $fCanDiskWrite === false || $fCanRemoteGet === false ) {
|
261 |
+
require_once( dirname(__FILE__).'/icwp-wpfunctions.php' );
|
262 |
+
$oWpFilesystem = new ICWP_WpFilesystem_WPSF();
|
263 |
+
|
264 |
+
$fCanRemoteGet = $oWpFilesystem->getCanWpRemoteGet();
|
265 |
+
$this->setOpt( 'capability_can_remote_get', $fCanRemoteGet? 'Y' : 'N' );
|
266 |
+
|
267 |
+
$fCanDiskWrite = $oWpFilesystem->getCanDiskWrite();
|
268 |
+
$this->setOpt( 'capability_can_disk_write', $fCanDiskWrite? 'Y' : 'N' );
|
269 |
+
}
|
270 |
+
}// '1.8.2', '<='
|
271 |
+
}
|
272 |
+
|
273 |
+
}
|
274 |
+
|
275 |
+
endif;
|
src/icwp-plugins-base.php
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
if ( !defined('
|
4 |
-
define( '
|
5 |
}
|
6 |
|
7 |
if ( !function_exists( '_hlt_e' ) ) {
|
@@ -15,14 +15,18 @@ if ( !function_exists( '_hlt__' ) ) {
|
|
15 |
}
|
16 |
}
|
17 |
|
|
|
|
|
18 |
if ( !class_exists('ICWP_WPSF_Base_Plugin') ):
|
19 |
|
20 |
class ICWP_WPSF_Base_Plugin {
|
21 |
|
22 |
static public $VERSION;
|
23 |
|
|
|
24 |
static public $PLUGIN_NAME;
|
25 |
static public $PLUGIN_PATH;
|
|
|
26 |
static public $PLUGIN_DIR;
|
27 |
static public $PLUGIN_URL;
|
28 |
static public $PLUGIN_BASENAME;
|
@@ -38,6 +42,15 @@ class ICWP_WPSF_Base_Plugin {
|
|
38 |
const ViewExt = '.php';
|
39 |
const ViewDir = 'views';
|
40 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
protected $m_aPluginMenu;
|
42 |
|
43 |
protected $m_aAllPluginOptions;
|
@@ -46,35 +59,64 @@ class ICWP_WPSF_Base_Plugin {
|
|
46 |
|
47 |
protected $m_fShowMarketing = '';
|
48 |
|
49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
static protected $m_aFailedUpdateOptions;
|
51 |
|
52 |
public function __construct() {
|
53 |
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
add_action( '
|
60 |
-
add_action( '
|
61 |
-
|
|
|
|
|
|
|
|
|
|
|
62 |
/**
|
63 |
* We make the assumption that all settings updates are successful until told otherwise
|
64 |
* by an actual failing update_option call.
|
65 |
*/
|
66 |
-
self::$m_fUpdateSuccessTracker = true;
|
67 |
self::$m_aFailedUpdateOptions = array();
|
68 |
-
|
69 |
$this->m_sParentMenuIdSuffix = 'base';
|
70 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
71 |
|
72 |
protected function getFullParentMenuId() {
|
73 |
return self::ParentMenuId .'-'. $this->m_sParentMenuIdSuffix;
|
74 |
}//getFullParentMenuId
|
75 |
|
76 |
protected function display( $insView, $inaData = array() ) {
|
77 |
-
$sFile = dirname(__FILE__).
|
78 |
|
79 |
if ( !is_file( $sFile ) ) {
|
80 |
echo "View not found: ".$sFile;
|
@@ -107,8 +149,9 @@ class ICWP_WPSF_Base_Plugin {
|
|
107 |
protected function getSubmenuPageTitle( $insTitle ) {
|
108 |
return self::ParentTitle.' - '.$insTitle;
|
109 |
}
|
110 |
-
protected function getSubmenuId( $insId ) {
|
111 |
-
|
|
|
112 |
}
|
113 |
|
114 |
public function onWpPluginsLoaded() {
|
@@ -120,9 +163,11 @@ class ICWP_WPSF_Base_Plugin {
|
|
120 |
|
121 |
if ( $this->isIcwpPluginAdminPage() ) {
|
122 |
//Handle form submit
|
123 |
-
$this->handlePluginFormSubmit()
|
|
|
|
|
124 |
}
|
125 |
-
}
|
126 |
|
127 |
public function onWpInit() { }
|
128 |
|
@@ -130,10 +175,8 @@ class ICWP_WPSF_Base_Plugin {
|
|
130 |
|
131 |
//Do Plugin-Specific Admin Work
|
132 |
if ( $this->isIcwpPluginAdminPage() ) {
|
133 |
-
|
134 |
//Links up CSS styles for the plugin itself (set the admin bootstrap CSS as a dependency also)
|
135 |
$this->enqueuePluginAdminCss();
|
136 |
-
|
137 |
}
|
138 |
|
139 |
// Determine whether to show ads and marketing messages
|
@@ -141,25 +184,44 @@ class ICWP_WPSF_Base_Plugin {
|
|
141 |
$this->isShowMarketing();
|
142 |
|
143 |
}//onWpAdminInit
|
144 |
-
|
145 |
public function onWpAdminMenu() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
146 |
|
147 |
$sFullParentMenuId = $this->getFullParentMenuId();
|
148 |
-
|
149 |
-
add_menu_page( self::ParentTitle, self::ParentName, self::ParentPermissions, $sFullParentMenuId, array( $this, 'onDisplayMainMenu' ), $this->getImageUrl( 'icontrolwp_16x16.png' ) );
|
150 |
|
151 |
//Create and Add the submenu items
|
152 |
$this->createPluginSubMenuItems();
|
153 |
if ( !empty($this->m_aPluginMenu) ) {
|
154 |
foreach ( $this->m_aPluginMenu as $sMenuTitle => $aMenu ) {
|
155 |
list( $sMenuItemText, $sMenuItemId, $sMenuCallBack ) = $aMenu;
|
156 |
-
add_submenu_page( $sFullParentMenuId, $sMenuTitle, $sMenuItemText, self::ParentPermissions, $sMenuItemId, array(
|
157 |
}
|
158 |
}
|
159 |
|
160 |
$this->fixSubmenu();
|
161 |
-
|
162 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
163 |
|
164 |
protected function createPluginSubMenuItems(){
|
165 |
/* Override to create array of sub-menu items
|
@@ -231,14 +293,69 @@ class ICWP_WPSF_Base_Plugin {
|
|
231 |
/**
|
232 |
* Override this method to handle all the admin notices
|
233 |
*/
|
234 |
-
public function onWpAdminNotices() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
235 |
|
236 |
/**
|
237 |
* This is called from within onWpAdminInit. Use this solely to manage upgrades of the plugin
|
238 |
*/
|
239 |
-
protected function handlePluginUpgrade() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
240 |
|
241 |
protected function handlePluginFormSubmit() { }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
242 |
|
243 |
protected function enqueuePluginAdminCss() {
|
244 |
$iRand = rand();
|
@@ -271,7 +388,7 @@ class ICWP_WPSF_Base_Plugin {
|
|
271 |
} else {
|
272 |
return $sFullNotice;
|
273 |
}
|
274 |
-
}
|
275 |
|
276 |
protected function redirect( $insUrl, $innTimeout = 1 ) {
|
277 |
echo '
|
@@ -287,17 +404,7 @@ class ICWP_WPSF_Base_Plugin {
|
|
287 |
* A little helper function that populates all the plugin options arrays with DB values
|
288 |
*/
|
289 |
protected function readyAllPluginOptions() {
|
290 |
-
|
291 |
-
$this->populateAllPluginOptions();
|
292 |
-
}
|
293 |
-
|
294 |
-
/**
|
295 |
-
* Override to create the plugin options array.
|
296 |
-
*
|
297 |
-
* Returns false if nothing happens - i.e. not over-rided.
|
298 |
-
*/
|
299 |
-
protected function initPluginOptions() {
|
300 |
-
return false;
|
301 |
}
|
302 |
|
303 |
/**
|
@@ -309,7 +416,7 @@ class ICWP_WPSF_Base_Plugin {
|
|
309 |
*/
|
310 |
protected function populateAllPluginOptions() {
|
311 |
|
312 |
-
if ( empty($this->m_aAllPluginOptions)
|
313 |
return false;
|
314 |
}
|
315 |
self::PopulatePluginOptions( $this->m_aAllPluginOptions );
|
@@ -334,18 +441,55 @@ class ICWP_WPSF_Base_Plugin {
|
|
334 |
foreach ( $inaOptionsSection['section_options'] as &$aOptionParams ) {
|
335 |
|
336 |
list( $sOptionKey, $sOptionCurrent, $sOptionDefault, $sOptionType ) = $aOptionParams;
|
337 |
-
$
|
338 |
if ( $sOptionType == 'ip_addresses' ) {
|
339 |
-
if ( !empty( $
|
340 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
341 |
}
|
342 |
else {
|
343 |
-
$
|
344 |
}
|
345 |
}
|
346 |
-
$aOptionParams[1] = ($
|
347 |
}
|
348 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
349 |
|
350 |
/**
|
351 |
* $sAllOptionsInput is a comma separated list of all the input keys to be processed from the $_POST
|
@@ -364,15 +508,20 @@ class ICWP_WPSF_Base_Plugin {
|
|
364 |
$sOptionValue = $this->getAnswerFromPost( $sOptionKey );
|
365 |
if ( is_null($sOptionValue) ) {
|
366 |
|
367 |
-
if ( $sOptionType == 'text' ) { //if it was a text box, and it's null, don't update anything
|
368 |
continue;
|
369 |
} else if ( $sOptionType == 'checkbox' ) { //if it was a checkbox, and it's null, it means 'N'
|
370 |
$sOptionValue = 'N';
|
|
|
|
|
371 |
}
|
372 |
}
|
373 |
else { //handle any pre-processing we need to.
|
374 |
|
375 |
-
if ( $sOptionType == '
|
|
|
|
|
|
|
376 |
|
377 |
if ( !class_exists('ICWP_DataProcessor') ) {
|
378 |
require_once ( dirname(__FILE__).'/icwp-data-processor.php' );
|
@@ -380,6 +529,16 @@ class ICWP_WPSF_Base_Plugin {
|
|
380 |
$oProcessor = new ICWP_DataProcessor();
|
381 |
$sOptionValue = $oProcessor->ExtractIpAddresses( $sOptionValue );
|
382 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
383 |
}
|
384 |
$this->updateOption( $sOptionKey, $sOptionValue );
|
385 |
}
|
@@ -429,7 +588,7 @@ class ICWP_WPSF_Base_Plugin {
|
|
429 |
$iCount++;
|
430 |
}
|
431 |
return $sCollated;
|
432 |
-
}
|
433 |
|
434 |
protected function isIcwpPluginAdminPage() {
|
435 |
|
@@ -447,7 +606,7 @@ class ICWP_WPSF_Base_Plugin {
|
|
447 |
return;
|
448 |
}
|
449 |
|
450 |
-
if ( empty($this->m_aAllPluginOptions)
|
451 |
return;
|
452 |
}
|
453 |
|
@@ -463,34 +622,37 @@ class ICWP_WPSF_Base_Plugin {
|
|
463 |
|
464 |
protected function getAnswerFromPost( $insKey, $insPrefix = null ) {
|
465 |
if ( is_null( $insPrefix ) ) {
|
466 |
-
$insKey = self
|
467 |
}
|
468 |
return ( isset( $_POST[$insKey] )? $_POST[$insKey]: null );
|
469 |
}
|
470 |
|
471 |
static public function getOption( $insKey, $insAddPrefix = '' ) {
|
472 |
-
return get_option( self
|
473 |
}
|
474 |
|
475 |
static public function addOption( $insKey, $insValue ) {
|
476 |
-
return add_option( self
|
477 |
}
|
478 |
|
479 |
static public function updateOption( $insKey, $insValue ) {
|
480 |
-
if ( self::getOption( $insKey ) == $insValue ) {
|
481 |
return true;
|
482 |
}
|
483 |
-
$fResult = update_option( self
|
484 |
if ( !$fResult ) {
|
485 |
-
self::$
|
486 |
-
self::$m_aFailedUpdateOptions[] = self::$OPTION_PREFIX.$insKey;
|
487 |
}
|
488 |
}
|
489 |
|
490 |
static public function deleteOption( $insKey ) {
|
491 |
-
return delete_option( self
|
492 |
}
|
493 |
|
|
|
|
|
|
|
|
|
494 |
public function onWpActivatePlugin() { }
|
495 |
public function onWpDeactivatePlugin() { }
|
496 |
|
@@ -502,6 +664,12 @@ class ICWP_WPSF_Base_Plugin {
|
|
502 |
}
|
503 |
}
|
504 |
|
|
|
|
|
|
|
|
|
|
|
|
|
505 |
/**
|
506 |
* Takes an array, an array key, and a default value. If key isn't set, sets it to default.
|
507 |
*/
|
@@ -523,7 +691,13 @@ class ICWP_WPSF_Base_Plugin {
|
|
523 |
$inaArgs[$insAttrKey] = ( empty($sAttrValue) ) ? '' : ' '.$insElement.'="'.$sAttrValue.'"';
|
524 |
}
|
525 |
|
526 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
527 |
|
528 |
endif;
|
529 |
|
1 |
<?php
|
2 |
|
3 |
+
if ( !defined('ICWP_DS') ) {
|
4 |
+
define( 'ICWP_DS', DIRECTORY_SEPARATOR );
|
5 |
}
|
6 |
|
7 |
if ( !function_exists( '_hlt_e' ) ) {
|
15 |
}
|
16 |
}
|
17 |
|
18 |
+
require_once( dirname(__FILE__).'/icwp-wpfunctions.php' );
|
19 |
+
|
20 |
if ( !class_exists('ICWP_WPSF_Base_Plugin') ):
|
21 |
|
22 |
class ICWP_WPSF_Base_Plugin {
|
23 |
|
24 |
static public $VERSION;
|
25 |
|
26 |
+
static public $PLUGIN_HUMAN_NAME;
|
27 |
static public $PLUGIN_NAME;
|
28 |
static public $PLUGIN_PATH;
|
29 |
+
static public $PLUGIN_FILE;
|
30 |
static public $PLUGIN_DIR;
|
31 |
static public $PLUGIN_URL;
|
32 |
static public $PLUGIN_BASENAME;
|
42 |
const ViewExt = '.php';
|
43 |
const ViewDir = 'views';
|
44 |
|
45 |
+
/**
|
46 |
+
* @var boolean
|
47 |
+
*/
|
48 |
+
protected $m_fNetworkAdminOnly = false;
|
49 |
+
/**
|
50 |
+
* @var boolean
|
51 |
+
*/
|
52 |
+
protected $m_fIsMultisite;
|
53 |
+
|
54 |
protected $m_aPluginMenu;
|
55 |
|
56 |
protected $m_aAllPluginOptions;
|
59 |
|
60 |
protected $m_fShowMarketing = '';
|
61 |
|
62 |
+
protected $m_fDoAutoUpdateCheck = false;
|
63 |
+
|
64 |
+
protected $m_fAutoPluginUpgrade = false;
|
65 |
+
|
66 |
+
/**
|
67 |
+
* @var ICWP_WpFunctions_WPSF
|
68 |
+
*/
|
69 |
+
protected $m_oWpFunctions;
|
70 |
+
|
71 |
static protected $m_aFailedUpdateOptions;
|
72 |
|
73 |
public function __construct() {
|
74 |
|
75 |
+
$this->m_fIsMultisite = function_exists( 'is_multisite' ) && is_multisite();
|
76 |
+
|
77 |
+
add_action( 'plugins_loaded', array( $this, 'onWpPluginsLoaded' ) );
|
78 |
+
add_action( 'init', array( $this, 'onWpInit' ), 0 );
|
79 |
+
if ( $this->isValidAdminArea() ) {
|
80 |
+
add_action( 'admin_init', array( $this, 'onWpAdminInit' ) );
|
81 |
+
add_action( 'admin_notices', array( $this, 'onWpAdminNotices' ) );
|
82 |
+
add_action( 'admin_menu', array( $this, 'onWpAdminMenu' ) );
|
83 |
+
add_action( 'network_admin_menu', array( $this, 'onWpNetworkAdminMenu' ) );
|
84 |
+
// add_action( 'plugin_action_links', array( $this, 'onWpPluginActionLinks' ), 10, 4 );
|
85 |
+
}
|
86 |
+
add_action( 'shutdown', array( $this, 'onWpShutdown' ) );
|
87 |
+
|
88 |
/**
|
89 |
* We make the assumption that all settings updates are successful until told otherwise
|
90 |
* by an actual failing update_option call.
|
91 |
*/
|
|
|
92 |
self::$m_aFailedUpdateOptions = array();
|
|
|
93 |
$this->m_sParentMenuIdSuffix = 'base';
|
94 |
}
|
95 |
+
|
96 |
+
protected function isValidAdminArea() {
|
97 |
+
if ( !$this->m_fIsMultisite && is_admin() ) {
|
98 |
+
return true;
|
99 |
+
}
|
100 |
+
else if ( $this->m_fNetworkAdminOnly && $this->m_fIsMultisite && is_network_admin() ) {
|
101 |
+
return true;
|
102 |
+
}
|
103 |
+
return false;
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* @return boolean - true if plugin update is available
|
108 |
+
*/
|
109 |
+
public function doPluginUpdateCheck() {
|
110 |
+
$this->loadWpFunctions();
|
111 |
+
return $this->m_oWpFunctions->getIsPluginUpdateAvailable( self::$PLUGIN_FILE );
|
112 |
+
}
|
113 |
|
114 |
protected function getFullParentMenuId() {
|
115 |
return self::ParentMenuId .'-'. $this->m_sParentMenuIdSuffix;
|
116 |
}//getFullParentMenuId
|
117 |
|
118 |
protected function display( $insView, $inaData = array() ) {
|
119 |
+
$sFile = dirname(__FILE__).ICWP_DS.'..'.ICWP_DS.self::ViewDir.ICWP_DS.$insView.self::ViewExt;
|
120 |
|
121 |
if ( !is_file( $sFile ) ) {
|
122 |
echo "View not found: ".$sFile;
|
149 |
protected function getSubmenuPageTitle( $insTitle ) {
|
150 |
return self::ParentTitle.' - '.$insTitle;
|
151 |
}
|
152 |
+
protected function getSubmenuId( $insId = '' ) {
|
153 |
+
$sExtension = empty($insId)? '' : '-'.$insId;
|
154 |
+
return $this->getFullParentMenuId().$sExtension;
|
155 |
}
|
156 |
|
157 |
public function onWpPluginsLoaded() {
|
163 |
|
164 |
if ( $this->isIcwpPluginAdminPage() ) {
|
165 |
//Handle form submit
|
166 |
+
if ( $this->isPluginFormSubmit() && $this->handlePluginFormSubmit() ) {
|
167 |
+
$this->m_oWpsfOptions->setOpt( 'feedback_admin_notice', 'Updating Settings <strong>Succeeded</strong>.' );
|
168 |
+
}
|
169 |
}
|
170 |
+
}
|
171 |
|
172 |
public function onWpInit() { }
|
173 |
|
175 |
|
176 |
//Do Plugin-Specific Admin Work
|
177 |
if ( $this->isIcwpPluginAdminPage() ) {
|
|
|
178 |
//Links up CSS styles for the plugin itself (set the admin bootstrap CSS as a dependency also)
|
179 |
$this->enqueuePluginAdminCss();
|
|
|
180 |
}
|
181 |
|
182 |
// Determine whether to show ads and marketing messages
|
184 |
$this->isShowMarketing();
|
185 |
|
186 |
}//onWpAdminInit
|
187 |
+
|
188 |
public function onWpAdminMenu() {
|
189 |
+
if ( !$this->isValidAdminArea() ) {
|
190 |
+
return true;
|
191 |
+
}
|
192 |
+
$this->createMenu();
|
193 |
+
}
|
194 |
+
|
195 |
+
public function onWpNetworkAdminMenu() {
|
196 |
+
if ( !$this->isValidAdminArea() ) {
|
197 |
+
return true;
|
198 |
+
}
|
199 |
+
$this->createMenu();
|
200 |
+
}
|
201 |
+
|
202 |
+
protected function createMenu() {
|
203 |
|
204 |
$sFullParentMenuId = $this->getFullParentMenuId();
|
205 |
+
add_menu_page( self::ParentTitle, self::ParentName, self::ParentPermissions, $sFullParentMenuId, array( $this, 'onDisplayAll' ), $this->getImageUrl( 'icontrolwp_16x16.png' ) );
|
|
|
206 |
|
207 |
//Create and Add the submenu items
|
208 |
$this->createPluginSubMenuItems();
|
209 |
if ( !empty($this->m_aPluginMenu) ) {
|
210 |
foreach ( $this->m_aPluginMenu as $sMenuTitle => $aMenu ) {
|
211 |
list( $sMenuItemText, $sMenuItemId, $sMenuCallBack ) = $aMenu;
|
212 |
+
add_submenu_page( $sFullParentMenuId, $sMenuTitle, $sMenuItemText, self::ParentPermissions, $sMenuItemId, array( $this, $sMenuCallBack ) );
|
213 |
}
|
214 |
}
|
215 |
|
216 |
$this->fixSubmenu();
|
217 |
+
}
|
218 |
+
/**
|
219 |
+
* Displaying all views now goes through this central function and we work out
|
220 |
+
* what to display based on the name of current hook/filter being processed.
|
221 |
+
*/
|
222 |
+
public function onDisplayAll() {
|
223 |
+
$this->onDisplayMainMenu();
|
224 |
+
}
|
225 |
|
226 |
protected function createPluginSubMenuItems(){
|
227 |
/* Override to create array of sub-menu items
|
293 |
/**
|
294 |
* Override this method to handle all the admin notices
|
295 |
*/
|
296 |
+
public function onWpAdminNotices() {
|
297 |
+
// Do we have admin priviledges?
|
298 |
+
if ( !current_user_can( 'manage_options' ) ) {
|
299 |
+
return;
|
300 |
+
}
|
301 |
+
|
302 |
+
if ( $this->m_fDoAutoUpdateCheck ) {
|
303 |
+
$this->adminNoticePluginUpgradeAvailable();
|
304 |
+
}
|
305 |
+
}
|
306 |
+
|
307 |
+
/**
|
308 |
+
* Hooked to 'shutdown'
|
309 |
+
*/
|
310 |
+
public function onWpShutdown() { }
|
311 |
|
312 |
/**
|
313 |
* This is called from within onWpAdminInit. Use this solely to manage upgrades of the plugin
|
314 |
*/
|
315 |
+
protected function handlePluginUpgrade() {
|
316 |
+
|
317 |
+
if ( !is_admin() || !current_user_can( 'manage_options' ) ) {
|
318 |
+
return;
|
319 |
+
}
|
320 |
+
|
321 |
+
$this->flushCaches();
|
322 |
+
|
323 |
+
if ( $this->m_fAutoPluginUpgrade ) {
|
324 |
+
$this->loadWpFunctions();
|
325 |
+
$this->m_oWpFunctions->doPluginUpgrade( self::$PLUGIN_FILE );
|
326 |
+
}
|
327 |
+
}
|
328 |
+
|
329 |
+
protected function isPluginFormSubmit() { }
|
330 |
|
331 |
protected function handlePluginFormSubmit() { }
|
332 |
+
|
333 |
+
protected function adminNoticePluginUpgradeAvailable() {
|
334 |
+
|
335 |
+
// Don't show on the update page.
|
336 |
+
if ( isset( $GLOBALS['pagenow'] ) && $GLOBALS['pagenow'] == 'update.php' ) {
|
337 |
+
return;
|
338 |
+
}
|
339 |
+
|
340 |
+
if ( !isset( self::$PLUGIN_FILE ) ) {
|
341 |
+
self::$PLUGIN_FILE = plugin_basename(__FILE__);
|
342 |
+
}
|
343 |
+
if ( !$this->doPluginUpdateCheck() ) {
|
344 |
+
return;
|
345 |
+
}
|
346 |
+
$sNotice = $this->getAdminNoticePluginUpgradeAvailable();
|
347 |
+
$this->getAdminNotice( $sNotice, 'updated', true );
|
348 |
+
}
|
349 |
+
|
350 |
+
/**
|
351 |
+
* Override this to change the message for the particular plugin upgrade.
|
352 |
+
*/
|
353 |
+
protected function getAdminNoticePluginUpgradeAvailable() {
|
354 |
+
$sUpgradeLink = $this->m_oWpFunctions->getPluginUpgradeLink( self::$PLUGIN_FILE );
|
355 |
+
$sNotice = '<p>There is an update available for the %s plugin. <a href="%s">Click to update immediately</a>.</p>';
|
356 |
+
$sNotice = sprintf( $sNotice, self::$PLUGIN_HUMAN_NAME, $sUpgradeLink );
|
357 |
+
return $sNotice;
|
358 |
+
}
|
359 |
|
360 |
protected function enqueuePluginAdminCss() {
|
361 |
$iRand = rand();
|
388 |
} else {
|
389 |
return $sFullNotice;
|
390 |
}
|
391 |
+
}
|
392 |
|
393 |
protected function redirect( $insUrl, $innTimeout = 1 ) {
|
394 |
echo '
|
404 |
* A little helper function that populates all the plugin options arrays with DB values
|
405 |
*/
|
406 |
protected function readyAllPluginOptions() {
|
407 |
+
// $this->populateAllPluginOptions();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
408 |
}
|
409 |
|
410 |
/**
|
416 |
*/
|
417 |
protected function populateAllPluginOptions() {
|
418 |
|
419 |
+
if ( empty($this->m_aAllPluginOptions) ) {
|
420 |
return false;
|
421 |
}
|
422 |
self::PopulatePluginOptions( $this->m_aAllPluginOptions );
|
441 |
foreach ( $inaOptionsSection['section_options'] as &$aOptionParams ) {
|
442 |
|
443 |
list( $sOptionKey, $sOptionCurrent, $sOptionDefault, $sOptionType ) = $aOptionParams;
|
444 |
+
$mCurrentOptionVal = self::getOption( $sOptionKey );
|
445 |
if ( $sOptionType == 'ip_addresses' ) {
|
446 |
+
if ( !empty( $mCurrentOptionVal ) ) {
|
447 |
+
$mCurrentOptionVal = implode( "\n", self::ConvertIpListForDisplay( $mCurrentOptionVal ) );
|
448 |
+
}
|
449 |
+
else {
|
450 |
+
$mCurrentOptionVal = '';
|
451 |
+
}
|
452 |
+
}
|
453 |
+
else if ( $sOptionType == 'comma_separated_lists' ) {
|
454 |
+
if ( !empty( $mCurrentOptionVal ) ) {
|
455 |
+
$aNewValues = array();
|
456 |
+
foreach( $mCurrentOptionVal as $sPage => $aParams ) {
|
457 |
+
$aNewValues[] = $sPage.', '. implode( ", ", $aParams );
|
458 |
+
}
|
459 |
+
$mCurrentOptionVal = implode( "\n", $aNewValues );
|
460 |
}
|
461 |
else {
|
462 |
+
$mCurrentOptionVal = '';
|
463 |
}
|
464 |
}
|
465 |
+
$aOptionParams[1] = ($mCurrentOptionVal == '' )? $sOptionDefault : $mCurrentOptionVal;
|
466 |
}
|
467 |
}
|
468 |
+
|
469 |
+
public static function ConvertIpListForDisplay( $inaIpList = array() ) {
|
470 |
+
|
471 |
+
$aDisplay = array();
|
472 |
+
if ( empty( $inaIpList ) || empty( $inaIpList['ips'] ) ) {
|
473 |
+
return $aDisplay;
|
474 |
+
}
|
475 |
+
|
476 |
+
foreach( $inaIpList['ips'] as $sAddress ) {
|
477 |
+
|
478 |
+
$mPos = strpos( $sAddress, '-' );
|
479 |
+
|
480 |
+
if ( $mPos === false || $mPos === 0 ) { //plain IP address
|
481 |
+
$sDisplayText = long2ip( $sAddress );
|
482 |
+
}
|
483 |
+
else {
|
484 |
+
list($nStart, $nEnd) = explode( '-', $sAddress );
|
485 |
+
$sDisplayText = long2ip( $nStart ) .'-'. long2ip( $nEnd );
|
486 |
+
}
|
487 |
+
$sLabel = $inaIpList['meta'][ md5($sAddress) ];
|
488 |
+
$sLabel = trim( $sLabel, '()' );
|
489 |
+
$aDisplay[] = $sDisplayText . ' ('.$sLabel.')';
|
490 |
+
}
|
491 |
+
return $aDisplay;
|
492 |
+
}
|
493 |
|
494 |
/**
|
495 |
* $sAllOptionsInput is a comma separated list of all the input keys to be processed from the $_POST
|
508 |
$sOptionValue = $this->getAnswerFromPost( $sOptionKey );
|
509 |
if ( is_null($sOptionValue) ) {
|
510 |
|
511 |
+
if ( $sOptionType == 'text' || $sOptionType == 'email' ) { //if it was a text box, and it's null, don't update anything
|
512 |
continue;
|
513 |
} else if ( $sOptionType == 'checkbox' ) { //if it was a checkbox, and it's null, it means 'N'
|
514 |
$sOptionValue = 'N';
|
515 |
+
} else if ( $sOptionType == 'integer' ) { //if it was a integer, and it's null, it means '0'
|
516 |
+
$sOptionValue = 0;
|
517 |
}
|
518 |
}
|
519 |
else { //handle any pre-processing we need to.
|
520 |
|
521 |
+
if ( $sOptionType == 'integer' ) {
|
522 |
+
$sOptionValue = intval( $sOptionValue );
|
523 |
+
}
|
524 |
+
else if ( $sOptionType == 'ip_addresses' ) { //ip addresses are textareas, where each is separated by newline
|
525 |
|
526 |
if ( !class_exists('ICWP_DataProcessor') ) {
|
527 |
require_once ( dirname(__FILE__).'/icwp-data-processor.php' );
|
529 |
$oProcessor = new ICWP_DataProcessor();
|
530 |
$sOptionValue = $oProcessor->ExtractIpAddresses( $sOptionValue );
|
531 |
}
|
532 |
+
else if ( $sOptionType == 'email' && function_exists( 'is_email' ) && !is_email( $sOptionValue ) ) {
|
533 |
+
$sOptionValue = '';
|
534 |
+
}
|
535 |
+
else if ( $sOptionType == 'comma_separated_lists' ) {
|
536 |
+
if ( !class_exists('ICWP_DataProcessor') ) {
|
537 |
+
require_once ( dirname(__FILE__).'/icwp-data-processor.php' );
|
538 |
+
}
|
539 |
+
$oProcessor = new ICWP_DataProcessor();
|
540 |
+
$sOptionValue = $oProcessor->ExtractCommaSeparatedList( $sOptionValue );
|
541 |
+
}
|
542 |
}
|
543 |
$this->updateOption( $sOptionKey, $sOptionValue );
|
544 |
}
|
588 |
$iCount++;
|
589 |
}
|
590 |
return $sCollated;
|
591 |
+
}
|
592 |
|
593 |
protected function isIcwpPluginAdminPage() {
|
594 |
|
606 |
return;
|
607 |
}
|
608 |
|
609 |
+
if ( empty($this->m_aAllPluginOptions) ) {
|
610 |
return;
|
611 |
}
|
612 |
|
622 |
|
623 |
protected function getAnswerFromPost( $insKey, $insPrefix = null ) {
|
624 |
if ( is_null( $insPrefix ) ) {
|
625 |
+
$insKey = self::getKey($insKey);
|
626 |
}
|
627 |
return ( isset( $_POST[$insKey] )? $_POST[$insKey]: null );
|
628 |
}
|
629 |
|
630 |
static public function getOption( $insKey, $insAddPrefix = '' ) {
|
631 |
+
return get_option( self::getKey($insKey) );
|
632 |
}
|
633 |
|
634 |
static public function addOption( $insKey, $insValue ) {
|
635 |
+
return add_option( self::getKey($insKey), $insValue );
|
636 |
}
|
637 |
|
638 |
static public function updateOption( $insKey, $insValue ) {
|
639 |
+
if ( !is_object( $insValue ) && self::getOption( $insKey ) == $insValue ) {
|
640 |
return true;
|
641 |
}
|
642 |
+
$fResult = update_option( self::getKey($insKey), $insValue );
|
643 |
if ( !$fResult ) {
|
644 |
+
self::$m_aFailedUpdateOptions[] = self::getKey($insKey);
|
|
|
645 |
}
|
646 |
}
|
647 |
|
648 |
static public function deleteOption( $insKey ) {
|
649 |
+
return delete_option( self::getKey($insKey) );
|
650 |
}
|
651 |
|
652 |
+
static public function getKey( $insKey ) {
|
653 |
+
return self::$OPTION_PREFIX.$insKey;
|
654 |
+
}
|
655 |
+
|
656 |
public function onWpActivatePlugin() { }
|
657 |
public function onWpDeactivatePlugin() { }
|
658 |
|
664 |
}
|
665 |
}
|
666 |
|
667 |
+
protected function loadWpFunctions() {
|
668 |
+
if ( !isset( $this->m_oWpFunctions ) ) {
|
669 |
+
$this->m_oWpFunctions = new ICWP_WpFunctions_WPSF();
|
670 |
+
}
|
671 |
+
}
|
672 |
+
|
673 |
/**
|
674 |
* Takes an array, an array key, and a default value. If key isn't set, sets it to default.
|
675 |
*/
|
691 |
$inaArgs[$insAttrKey] = ( empty($sAttrValue) ) ? '' : ' '.$insElement.'="'.$sAttrValue.'"';
|
692 |
}
|
693 |
|
694 |
+
protected function flushCaches() {
|
695 |
+
if (function_exists('w3tc_pgcache_flush')) {
|
696 |
+
w3tc_pgcache_flush();
|
697 |
+
}
|
698 |
+
}
|
699 |
+
|
700 |
+
}
|
701 |
|
702 |
endif;
|
703 |
|
src/icwp-processor-autoupdates.php
ADDED
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2013 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-base-processor.php' );
|
19 |
+
|
20 |
+
if ( !class_exists('ICWP_AutoUpdatesProcessor') ):
|
21 |
+
|
22 |
+
class ICWP_AutoUpdatesProcessor extends ICWP_BaseProcessor_WPSF {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Resets the object values to be re-used anew
|
26 |
+
*/
|
27 |
+
public function reset() {
|
28 |
+
parent::reset();
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
*/
|
33 |
+
public function run() {
|
34 |
+
|
35 |
+
if ( $this->m_aOptions['autoupdate_core'] == 'core_never' ) {
|
36 |
+
add_filter( 'allow_minor_auto_core_updates', '__return_false' );
|
37 |
+
add_filter( 'allow_major_auto_core_updates', '__return_false' );
|
38 |
+
}
|
39 |
+
else if ( $this->m_aOptions['autoupdate_core'] == 'core_minor' ) {
|
40 |
+
add_filter( 'allow_minor_auto_core_updates', '__return_true' );
|
41 |
+
add_filter( 'allow_major_auto_core_updates', '__return_false' );
|
42 |
+
}
|
43 |
+
else if ( $this->m_aOptions['autoupdate_core'] == 'core_major' ) {
|
44 |
+
add_filter( 'allow_minor_auto_core_updates', '__return_true' );
|
45 |
+
add_filter( 'allow_major_auto_core_updates', '__return_true' );
|
46 |
+
}
|
47 |
+
|
48 |
+
$sFunction = ( $this->m_aOptions['enable_autoupdate_translations'] == 'Y' )? '__return_true' : '__return_false';
|
49 |
+
add_filter( 'auto_update_translation', $sFunction );
|
50 |
+
|
51 |
+
add_filter( 'auto_update_plugin', array( $this, 'autoupdate_plugins' ), 1, 2 );
|
52 |
+
|
53 |
+
$sFunction = ( $this->m_aOptions['enable_autoupdate_themes'] == 'Y' )? '__return_true' : '__return_false';
|
54 |
+
add_filter( 'auto_update_themes', $sFunction );
|
55 |
+
|
56 |
+
if ( $this->m_aOptions['enable_autoupdate_ignore_vcs'] == 'Y' ) {
|
57 |
+
add_filter( 'automatic_updates_is_vcs_checkout', array( $this, 'disable_for_vcs'), 10, 2 );
|
58 |
+
}
|
59 |
+
|
60 |
+
if ( $this->m_aOptions['enable_autoupdate_disable_all'] == 'Y' ) {
|
61 |
+
add_filter( 'automatic_updater_disabled', '__return_true' );
|
62 |
+
}
|
63 |
+
}
|
64 |
+
|
65 |
+
public function autoupdate_plugins( $infUpdate, $insPluginSlug ) {
|
66 |
+
|
67 |
+
if ( strpos( $insPluginSlug, 'icwp-wpsf.php') !== false ) {
|
68 |
+
return $this->m_aOptions['autoupdate_plugin_wpsf'] == 'Y';
|
69 |
+
}
|
70 |
+
if ( $this->m_aOptions['enable_autoupdate_plugins'] == 'Y' ) {
|
71 |
+
return true;
|
72 |
+
}
|
73 |
+
return $infUpdate;
|
74 |
+
}
|
75 |
+
|
76 |
+
public function disable_for_vcs( $checkout, $context ) {
|
77 |
+
return false;
|
78 |
+
}
|
79 |
+
}
|
80 |
+
|
81 |
+
endif;
|
src/icwp-processor-commentsfilter.php
ADDED
@@ -0,0 +1,431 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2013 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_CommentsFilterProcessor') ):
|
21 |
+
|
22 |
+
class ICWP_CommentsFilterProcessor extends ICWP_BaseDbProcessor_WPSF {
|
23 |
+
|
24 |
+
const TableName = 'comments_filter';
|
25 |
+
|
26 |
+
/**
|
27 |
+
* @var string
|
28 |
+
*/
|
29 |
+
static protected $sModeFile_LoginThrottled;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* The unique comment token assigned to this page
|
33 |
+
* @var integer
|
34 |
+
*/
|
35 |
+
protected $m_sUniqueToken;
|
36 |
+
|
37 |
+
/**
|
38 |
+
* The unique comment token assigned to this page
|
39 |
+
* @var integer
|
40 |
+
*/
|
41 |
+
protected $m_sUniqueFormId;
|
42 |
+
|
43 |
+
/**
|
44 |
+
* The length of time that must pass between a page being loaded and comment being posted.
|
45 |
+
* @var integer
|
46 |
+
*/
|
47 |
+
protected $m_nCommentCooldown;
|
48 |
+
|
49 |
+
/**
|
50 |
+
* The maxium length of time that comment token may last and be used.
|
51 |
+
* @var integer
|
52 |
+
*/
|
53 |
+
protected $m_nCommentTokenExpire;
|
54 |
+
|
55 |
+
protected $m_nLastLoginTime;
|
56 |
+
protected $m_sSecretKey;
|
57 |
+
|
58 |
+
protected $m_sGaspKey;
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Flag as to whether Two Factor Authentication will be by-pass when sending the verification
|
62 |
+
* email fails.
|
63 |
+
*
|
64 |
+
* @var boolean
|
65 |
+
*/
|
66 |
+
protected $m_fAllowTwoFactorByPass;
|
67 |
+
|
68 |
+
public function __construct() {
|
69 |
+
parent::__construct( self::TableName );
|
70 |
+
$this->createTable();
|
71 |
+
$this->reset();
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Resets the object values to be re-used anew
|
76 |
+
*/
|
77 |
+
public function reset() {
|
78 |
+
parent::reset();
|
79 |
+
$this->m_sUniqueToken = '';
|
80 |
+
$this->m_sCommentStatus = '';
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
*/
|
85 |
+
public function run() {
|
86 |
+
// Add GASP checking to the comment form.
|
87 |
+
if ( $this->m_aOptions[ 'enable_comments_gasp_protection' ] == 'Y' ) {
|
88 |
+
add_action( 'comment_form', array( $this, 'printGaspFormHook_Action' ), 1 );
|
89 |
+
add_action( 'comment_form', array( $this, 'printGaspFormParts_Action' ), 2 );
|
90 |
+
add_filter( 'preprocess_comment', array( $this, 'doGaspCommentCheck_Filter' ), 1, 1 );
|
91 |
+
add_filter( 'pre_comment_approved', array( $this, 'doGaspStatusSet_Filter' ), 1, 1 );
|
92 |
+
}
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* @return void
|
97 |
+
*/
|
98 |
+
public function printGaspFormHook_Action() {
|
99 |
+
|
100 |
+
if ( !$this->getDoCommentsCheck() ) {
|
101 |
+
return;
|
102 |
+
}
|
103 |
+
global $post;
|
104 |
+
if ( !isset( $post ) || $post->comment_status != 'open' ) {
|
105 |
+
return;
|
106 |
+
}
|
107 |
+
$this->deleteOldPostCommentTokens( $post->ID );
|
108 |
+
$this->createUniquePostCommentToken( $post->ID, $this->m_sUniqueToken );
|
109 |
+
|
110 |
+
require_once( dirname(__FILE__).'/icwp-data-processor.php' );
|
111 |
+
$this->m_sUniqueFormId = ICWP_DataProcessor::GenerateRandomString( rand(7, 23), true );
|
112 |
+
|
113 |
+
echo $this->getGaspCommentsHookHtml();
|
114 |
+
}
|
115 |
+
|
116 |
+
/**
|
117 |
+
* Tells us whether, for this particular comment post, if we should do comments checking.
|
118 |
+
*
|
119 |
+
* @return boolean
|
120 |
+
*/
|
121 |
+
protected function getDoCommentsCheck() {
|
122 |
+
if ( !is_user_logged_in() ) {
|
123 |
+
return true;
|
124 |
+
}
|
125 |
+
else if ( $this->m_aOptions[ 'enable_comments_gasp_protection_for_logged_in' ] == 'Y' ) {
|
126 |
+
return true;
|
127 |
+
}
|
128 |
+
return false;
|
129 |
+
}
|
130 |
+
|
131 |
+
/**
|
132 |
+
* @return void
|
133 |
+
*/
|
134 |
+
public function printGaspFormParts_Action() {
|
135 |
+
if ( $this->getDoCommentsCheck() ) {
|
136 |
+
echo $this->getGaspCommentsHtml();
|
137 |
+
}
|
138 |
+
}
|
139 |
+
|
140 |
+
/**
|
141 |
+
* @return string
|
142 |
+
*/
|
143 |
+
public function getGaspCommentsHookHtml() {
|
144 |
+
$sId = $this->m_sUniqueFormId;
|
145 |
+
$sReturn = '<p id="'.$sId.'"></p>'; // we use this unique <p> to hook onto using javascript
|
146 |
+
$sReturn .= '<input type="hidden" id="_sugar_sweet_email" name="sugar_sweet_email" value="" />';
|
147 |
+
$sReturn .= '<input type="hidden" id="_comment_token" name="comment_token" value="'.$this->m_sUniqueToken.'" />';
|
148 |
+
return $sReturn;
|
149 |
+
}
|
150 |
+
|
151 |
+
public function getGaspCommentsHtml() {
|
152 |
+
|
153 |
+
$sId = $this->m_sUniqueFormId;
|
154 |
+
$sConfirm = stripslashes( $this->m_aOptions[ 'custom_message_checkbox' ] );
|
155 |
+
$sAlert = stripslashes( $this->m_aOptions[ 'custom_message_alert' ] );
|
156 |
+
$sCommentWait = stripslashes( $this->m_aOptions[ 'custom_message_comment_wait' ] );
|
157 |
+
$nCooldown = $this->m_aOptions[ 'comments_cooldown_interval' ];
|
158 |
+
$nExpire = $this->m_aOptions[ 'comments_token_expire_interval' ];
|
159 |
+
|
160 |
+
if ( strpos( $sCommentWait, '%s' ) !== false ) {
|
161 |
+
$sCommentWait = sprintf( $sCommentWait, $nCooldown );
|
162 |
+
$sJsCommentWait = str_replace( '%s', '"+nRemaining+"', $this->m_aOptions[ 'custom_message_comment_wait' ] );
|
163 |
+
$sJsCommentWait = '"'.$sJsCommentWait.'"';
|
164 |
+
}
|
165 |
+
else {
|
166 |
+
$sJsCommentWait = '"'. $this->m_aOptions[ 'custom_message_comment_wait' ].'"';
|
167 |
+
}
|
168 |
+
$sCommentReload = $this->m_aOptions[ 'custom_message_comment_reload' ];
|
169 |
+
|
170 |
+
$sReturn = "
|
171 |
+
<script type='text/javascript'>
|
172 |
+
|
173 |
+
function cb_click$sId() {
|
174 |
+
cb_name$sId.value=cb$sId.name;
|
175 |
+
}
|
176 |
+
function check$sId() {
|
177 |
+
if( cb$sId.checked != true ) {
|
178 |
+
alert( \"$sAlert\" ); return false;
|
179 |
+
}
|
180 |
+
return true;
|
181 |
+
}
|
182 |
+
function reenableButton$sId() {
|
183 |
+
nTimerCounter{$sId}++;
|
184 |
+
nRemaining = $nCooldown - nTimerCounter$sId;
|
185 |
+
subbutton$sId.value = $sJsCommentWait;
|
186 |
+
if ( nTimerCounter$sId >= $nCooldown ) {
|
187 |
+
subbutton$sId.value = origButtonValue$sId;
|
188 |
+
subbutton$sId.disabled = false;
|
189 |
+
clearInterval( sCountdownTimer$sId );
|
190 |
+
}
|
191 |
+
}
|
192 |
+
function redisableButton$sId() {
|
193 |
+
subbutton$sId.value = \"$sCommentReload\";
|
194 |
+
subbutton$sId.disabled = true;
|
195 |
+
}
|
196 |
+
|
197 |
+
var $sId = document.getElementById('$sId');
|
198 |
+
|
199 |
+
var cb$sId = document.createElement('input');
|
200 |
+
cb$sId.type = 'checkbox';
|
201 |
+
cb$sId.id = 'checkbox$sId';
|
202 |
+
cb$sId.name = 'checkbox$sId';
|
203 |
+
cb$sId.style.width = '25px';
|
204 |
+
cb$sId.onclick = cb_click$sId;
|
205 |
+
|
206 |
+
var label$sId = document.createElement( 'label' );
|
207 |
+
label$sId.htmlFor = 'checkbox$sId';
|
208 |
+
label$sId.innerHTML = \"$sConfirm\";
|
209 |
+
|
210 |
+
var cb_name$sId = document.createElement('input');
|
211 |
+
cb_name$sId.type = 'hidden';
|
212 |
+
cb_name$sId.name = 'cb_nombre';
|
213 |
+
|
214 |
+
$sId.appendChild( cb$sId );
|
215 |
+
$sId.appendChild( label$sId );
|
216 |
+
$sId.appendChild( cb_name$sId );
|
217 |
+
|
218 |
+
var frm$sId = cb$sId.form;
|
219 |
+
frm$sId.onsubmit = check$sId;
|
220 |
+
|
221 |
+
".(
|
222 |
+
( $nCooldown > 0 || $nExpire > 0 ) ?
|
223 |
+
"
|
224 |
+
var subbuttonList$sId = frm$sId.querySelectorAll( 'input[type=\"submit\"]' );
|
225 |
+
|
226 |
+
if ( typeof( subbuttonList$sId ) != \"undefined\" ) {
|
227 |
+
subbutton$sId = subbuttonList{$sId}[0];
|
228 |
+
if ( typeof( subbutton$sId ) != \"undefined\" ) {
|
229 |
+
|
230 |
+
".(
|
231 |
+
( $nCooldown > 0 )?
|
232 |
+
"
|
233 |
+
subbutton$sId.disabled = true;
|
234 |
+
origButtonValue$sId = subbutton$sId.value;
|
235 |
+
subbutton$sId.value = \"$sCommentWait\";
|
236 |
+
nTimerCounter$sId = 0;
|
237 |
+
sCountdownTimer$sId = setInterval( reenableButton$sId, 1000 );
|
238 |
+
"
|
239 |
+
:''
|
240 |
+
).(
|
241 |
+
( $nExpire > 0 )? "sTimeoutTimer$sId = setTimeout( redisableButton$sId, ".(1000 * $nExpire - 1000)." );" : ''
|
242 |
+
)."
|
243 |
+
}
|
244 |
+
}
|
245 |
+
":''
|
246 |
+
)."
|
247 |
+
</script>
|
248 |
+
";
|
249 |
+
return $sReturn;
|
250 |
+
}
|
251 |
+
|
252 |
+
/**
|
253 |
+
* @param array $inaCommentData
|
254 |
+
* @return unknown|string
|
255 |
+
*/
|
256 |
+
public function doGaspCommentCheck_Filter( $inaCommentData ) {
|
257 |
+
|
258 |
+
if ( !$this->getDoCommentsCheck() ) {
|
259 |
+
return $inaCommentData;
|
260 |
+
}
|
261 |
+
if( !isset( $_POST['cb_nombre'] ) ) {
|
262 |
+
$this->m_sCommentStatus = 'spam';
|
263 |
+
}
|
264 |
+
// we have the cb name, is it set?
|
265 |
+
else if ( !isset( $_POST[ $_POST['cb_nombre'] ] ) ) {
|
266 |
+
$this->m_sCommentStatus = 'spam';
|
267 |
+
}
|
268 |
+
// honeypot check
|
269 |
+
else if ( isset( $_POST['sugar_sweet_email'] ) && $_POST['sugar_sweet_email'] !== '' ) {
|
270 |
+
$this->m_sCommentStatus = 'spam';
|
271 |
+
}
|
272 |
+
// check the unique comment token is present
|
273 |
+
else if ( !isset( $_POST['comment_token'] ) || !$this->checkCommentToken( $_POST['comment_token'], $inaCommentData['comment_post_ID'] ) ) {
|
274 |
+
$this->m_sCommentStatus = 'spam';
|
275 |
+
}
|
276 |
+
if ( false && $this->m_sCommentStatus = 'spam' ) { //add option to die later
|
277 |
+
wp_die( "Ding! Dong! The witch is dead." );
|
278 |
+
}
|
279 |
+
return $inaCommentData;
|
280 |
+
}
|
281 |
+
|
282 |
+
protected function checkCommentToken( $insCommentToken, $insPostId ) {
|
283 |
+
|
284 |
+
$sToken = esc_sql( $insCommentToken ); //just incase someone try to get funky.
|
285 |
+
|
286 |
+
// Try to get the database entry that corresponds to this set of data. If we get nothing, fail.
|
287 |
+
$sQuery = "
|
288 |
+
SELECT *
|
289 |
+
FROM `%s`
|
290 |
+
WHERE
|
291 |
+
`unique_token` = '%s'
|
292 |
+
AND `post_id` = '%s'
|
293 |
+
AND `ip_long` = '%s'
|
294 |
+
AND `deleted_at` = '0'
|
295 |
+
";
|
296 |
+
$sQuery = sprintf( $sQuery,
|
297 |
+
$this->m_sTableName,
|
298 |
+
$sToken,
|
299 |
+
$insPostId,
|
300 |
+
$this->m_nRequestIp
|
301 |
+
);
|
302 |
+
$mResult = $this->selectCustomFromTable( $sQuery );
|
303 |
+
|
304 |
+
if ( empty( $mResult ) || !is_array($mResult) || count($mResult) != 1 ) {
|
305 |
+
return false;
|
306 |
+
}
|
307 |
+
else {
|
308 |
+
// Only 1 chance is given per token, so we delete it
|
309 |
+
$this->deleteUniquePostCommentToken( $sToken, $insPostId );
|
310 |
+
|
311 |
+
// Did suficient time pass, or has it expired?
|
312 |
+
$nNow = time();
|
313 |
+
$aRecord = $mResult[0];
|
314 |
+
$nInterval = $nNow - $aRecord['created_at'];
|
315 |
+
if ( $nInterval < $this->m_aOptions[ 'comments_cooldown_interval' ]
|
316 |
+
|| ( $this->m_aOptions[ 'comments_token_expire_interval' ] > 0 && $nInterval > $this->m_aOptions[ 'comments_token_expire_interval' ] )
|
317 |
+
) {
|
318 |
+
return false;
|
319 |
+
}
|
320 |
+
return true;
|
321 |
+
}
|
322 |
+
}
|
323 |
+
|
324 |
+
public function doGaspStatusSet_Filter( $sApprovalStatus ) {
|
325 |
+
if( !empty( $this->m_sCommentStatus ) ){
|
326 |
+
$sApprovalStatus = $this->m_sCommentStatus;
|
327 |
+
}
|
328 |
+
return $sApprovalStatus;
|
329 |
+
}
|
330 |
+
|
331 |
+
public function createTable() {
|
332 |
+
|
333 |
+
// Set up comments ID table
|
334 |
+
$sSqlTables = "CREATE TABLE IF NOT EXISTS `%s` (
|
335 |
+
`id` int(11) NOT NULL AUTO_INCREMENT,
|
336 |
+
`post_id` int(11) NOT NULL DEFAULT '0',
|
337 |
+
`unique_token` varchar(32) NOT NULL DEFAULT '',
|
338 |
+
`ip_long` bigint(20) NOT NULL DEFAULT '0',
|
339 |
+
`created_at` int(15) NOT NULL DEFAULT '0',
|
340 |
+
`deleted_at` int(15) NOT NULL DEFAULT '0',
|
341 |
+
PRIMARY KEY (`id`)
|
342 |
+
) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
|
343 |
+
$sSqlTables = sprintf( $sSqlTables, $this->m_sTableName );
|
344 |
+
$mResult = $this->doSql( $sSqlTables );
|
345 |
+
}
|
346 |
+
|
347 |
+
/**
|
348 |
+
*
|
349 |
+
* @param string $insUniqueToken
|
350 |
+
* @param string $insPostId
|
351 |
+
*/
|
352 |
+
protected function deleteUniquePostCommentToken( $insUniqueToken, $insPostId, $infSoftDelete = false ) {
|
353 |
+
|
354 |
+
if ( $infSoftDelete ) {
|
355 |
+
$nNow = time();
|
356 |
+
$sQuery = "
|
357 |
+
UPDATE `%s`
|
358 |
+
SET `deleted_at` = '%s'
|
359 |
+
WHERE
|
360 |
+
`unique_token` = '%s'
|
361 |
+
AND `post_id` = '%s'
|
362 |
+
";
|
363 |
+
$sQuery = sprintf( $sQuery,
|
364 |
+
$this->m_sTableName,
|
365 |
+
$nNow,
|
366 |
+
$sToken,
|
367 |
+
$insPostId
|
368 |
+
);
|
369 |
+
$this->doSql( $sQuery );
|
370 |
+
}
|
371 |
+
else {
|
372 |
+
$aWhere['unique_token'] = $insUniqueToken;
|
373 |
+
$aWhere['post_id'] = $insPostId;
|
374 |
+
$this->deleteRowsFromTable( $aWhere );
|
375 |
+
}
|
376 |
+
}
|
377 |
+
|
378 |
+
/**
|
379 |
+
*
|
380 |
+
* @param string $insUniqueToken
|
381 |
+
* @param string $insPostId
|
382 |
+
*/
|
383 |
+
protected function deleteOldPostCommentTokens( $insPostId, $infSoftDelete = false ) {
|
384 |
+
|
385 |
+
if ( $infSoftDelete ) {
|
386 |
+
$nNow = time();
|
387 |
+
$sQuery = "
|
388 |
+
UPDATE `%s`
|
389 |
+
SET `deleted_at` = '%s'
|
390 |
+
WHERE
|
391 |
+
`ip_long` = '%s'
|
392 |
+
AND `post_id` = '%s'
|
393 |
+
";
|
394 |
+
$sQuery = sprintf( $sQuery,
|
395 |
+
$this->m_sTableName,
|
396 |
+
$nNow,
|
397 |
+
$this->m_nRequestIp,
|
398 |
+
$insPostId
|
399 |
+
);
|
400 |
+
$this->doSql( $sQuery );
|
401 |
+
}
|
402 |
+
else {
|
403 |
+
$aWhere['ip_long'] = $this->m_nRequestIp;
|
404 |
+
$aWhere['post_id'] = $insPostId;
|
405 |
+
$this->deleteRowsFromTable( $aWhere );
|
406 |
+
}
|
407 |
+
}
|
408 |
+
|
409 |
+
protected function createUniquePostCommentToken( $insPostId, &$outsUniqueToken = '' ) {
|
410 |
+
|
411 |
+
// Now add new pending entry
|
412 |
+
$nNow = time();
|
413 |
+
$outsUniqueToken = $this->getUniqueToken( $insPostId );
|
414 |
+
$aData = array();
|
415 |
+
$aData[ 'post_id' ] = $insPostId;
|
416 |
+
$aData[ 'unique_token' ] = $outsUniqueToken;
|
417 |
+
$aData[ 'ip_long' ] = $this->m_nRequestIp;
|
418 |
+
$aData[ 'created_at' ] = $nNow;
|
419 |
+
|
420 |
+
$mResult = $this->insertIntoTable( $aData );
|
421 |
+
return $mResult;
|
422 |
+
}
|
423 |
+
|
424 |
+
protected function getUniqueToken( $insPostId ) {
|
425 |
+
$sToken = uniqid( $this->m_nRequestIp.$insPostId );
|
426 |
+
return md5( $sToken );
|
427 |
+
}
|
428 |
+
|
429 |
+
}
|
430 |
+
|
431 |
+
endif;
|
src/icwp-processor-email.php
ADDED
@@ -0,0 +1,168 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2013 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-base-processor.php' );
|
19 |
+
|
20 |
+
if ( !class_exists('ICWP_EmailProcessor') ):
|
21 |
+
|
22 |
+
class ICWP_EmailProcessor extends ICWP_BaseProcessor_WPSF {
|
23 |
+
|
24 |
+
protected $m_sRecipientAddress;
|
25 |
+
protected $m_sSiteName;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @var string
|
29 |
+
*/
|
30 |
+
static protected $sModeFile_EmailThrottled;
|
31 |
+
/**
|
32 |
+
* @var int
|
33 |
+
*/
|
34 |
+
static protected $nThrottleInterval = 20;
|
35 |
+
/**
|
36 |
+
* @var int
|
37 |
+
*/
|
38 |
+
protected $m_nEmailThrottleLimit;
|
39 |
+
/**
|
40 |
+
* @var int
|
41 |
+
*/
|
42 |
+
protected $m_nEmailThrottleTime;
|
43 |
+
/**
|
44 |
+
* @var int
|
45 |
+
*/
|
46 |
+
protected $m_nEmailThrottleCount;
|
47 |
+
/**
|
48 |
+
* @var boolean
|
49 |
+
*/
|
50 |
+
protected $m_fEmailIsThrottled;
|
51 |
+
|
52 |
+
public function reset() {
|
53 |
+
parent::reset();
|
54 |
+
self::$sModeFile_EmailThrottled = dirname( __FILE__ ).'/../mode.email_throttled';
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* @param string $insEmailAddress
|
59 |
+
* @param string $insEmailSubject
|
60 |
+
* @param array $inaMessage
|
61 |
+
* @uses wp_mail
|
62 |
+
*/
|
63 |
+
public function sendEmailTo( $insEmailAddress, $insEmailSubject, $inaMessage ) {
|
64 |
+
|
65 |
+
$aHeaders = array(
|
66 |
+
'MIME-Version: 1.0',
|
67 |
+
'Content-type: text/plain;',
|
68 |
+
sprintf( 'From: %s, Simple Firewall Plugin <%s>', $this->m_sSiteName, $insEmailAddress ),
|
69 |
+
sprintf( "Subject: %s", $insEmailSubject ),
|
70 |
+
'X-Mailer: PHP/'.phpversion()
|
71 |
+
);
|
72 |
+
|
73 |
+
$this->updateEmailThrottle();
|
74 |
+
// We appear to have "succeeded" if the throttle is applied.
|
75 |
+
if ( $this->m_fEmailIsThrottled ) {
|
76 |
+
return true;
|
77 |
+
}
|
78 |
+
return wp_mail( $insEmailAddress, $insEmailSubject, implode( "\r\n", $inaMessage ), implode( "\r\n", $aHeaders ) );
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Will send email to the default recipient setup in the object.
|
83 |
+
*
|
84 |
+
* @param string $insEmailSubject
|
85 |
+
* @param array $inaMessage
|
86 |
+
*/
|
87 |
+
public function sendEmail( $insEmailSubject, $inaMessage ) {
|
88 |
+
if ( !isset( $this->m_sRecipientAddress ) ) {
|
89 |
+
return false;
|
90 |
+
}
|
91 |
+
return $this->sendEmailTo( $this->m_sRecipientAddress, $insEmailSubject, $inaMessage );
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Whether we're throttled is dependent on 2 signals. The time interval has changed, or the there's a file
|
96 |
+
* system object telling us we're throttled.
|
97 |
+
*
|
98 |
+
* The file system object takes precedence.
|
99 |
+
*
|
100 |
+
* @return boolean
|
101 |
+
*/
|
102 |
+
protected function updateEmailThrottle() {
|
103 |
+
|
104 |
+
// Throttling Is Effectively Off
|
105 |
+
if ( $this->m_nEmailThrottleLimit <= 0 ) {
|
106 |
+
$this->setThrottledFile( false );
|
107 |
+
return $this->m_fEmailIsThrottled;
|
108 |
+
}
|
109 |
+
|
110 |
+
// Check that there is an email throttle file. If it exists and its modified time is greater than the
|
111 |
+
// current $this->m_nEmailThrottleTime it suggests another process has touched the file and updated it
|
112 |
+
// concurrently. So, we update our $this->m_nEmailThrottleTime accordingly.
|
113 |
+
if ( is_file( self::$sModeFile_EmailThrottled ) ) {
|
114 |
+
$nModifiedTime = filemtime( self::$sModeFile_EmailThrottled );
|
115 |
+
if ( $nModifiedTime > $this->m_nEmailThrottleTime ) {
|
116 |
+
$this->m_nEmailThrottleTime = $nModifiedTime;
|
117 |
+
}
|
118 |
+
}
|
119 |
+
|
120 |
+
$nNow = time();
|
121 |
+
if ( !isset($this->m_nEmailThrottleTime) || $this->m_nEmailThrottleTime > $nNow ) {
|
122 |
+
$this->m_nEmailThrottleTime = $nNow;
|
123 |
+
}
|
124 |
+
if ( !isset($this->m_nEmailThrottleCount) ) {
|
125 |
+
$this->m_nEmailThrottleCount = 0;
|
126 |
+
}
|
127 |
+
|
128 |
+
// If $nNow is greater than throttle interval (1s) we turn off the file throttle and reset the count
|
129 |
+
$nDiff = $nNow - $this->m_nEmailThrottleTime;
|
130 |
+
if ( $nDiff > self::$nThrottleInterval ) {
|
131 |
+
$this->m_nEmailThrottleTime = $nNow;
|
132 |
+
$this->m_nEmailThrottleCount = 1; //we set to 1 assuming that this was called because we're about to send, or have just sent, an email.
|
133 |
+
$this->setThrottledFile( false );
|
134 |
+
}
|
135 |
+
else if ( is_file( self::$sModeFile_EmailThrottled ) || ( $this->m_nEmailThrottleCount >= $this->m_nEmailThrottleLimit ) ) {
|
136 |
+
$this->setThrottledFile( true );
|
137 |
+
}
|
138 |
+
else {
|
139 |
+
$this->m_nEmailThrottleCount++;
|
140 |
+
}
|
141 |
+
}
|
142 |
+
|
143 |
+
public function setThrottledFile( $infOn = false ) {
|
144 |
+
|
145 |
+
$this->m_fEmailIsThrottled = $infOn;
|
146 |
+
|
147 |
+
if ( $infOn && !is_file( self::$sModeFile_EmailThrottled ) && function_exists('touch') ) {
|
148 |
+
@touch( self::$sModeFile_EmailThrottled );
|
149 |
+
}
|
150 |
+
else if ( is_file(self::$sModeFile_EmailThrottled) ) {
|
151 |
+
@unlink( self::$sModeFile_EmailThrottled );
|
152 |
+
}
|
153 |
+
}
|
154 |
+
|
155 |
+
public function setDefaultRecipientAddress( $insEmailAddress ) {
|
156 |
+
$this->m_sRecipientAddress = $insEmailAddress;
|
157 |
+
}
|
158 |
+
|
159 |
+
public function setSiteName( $insName ) {
|
160 |
+
$this->m_sSiteName = $insName;
|
161 |
+
}
|
162 |
+
|
163 |
+
public function setThrottleLimit( $innLimit ) {
|
164 |
+
$this->m_nEmailThrottleLimit = $innLimit;
|
165 |
+
}
|
166 |
+
}
|
167 |
+
|
168 |
+
endif;
|
src/icwp-processor-firewall.php
ADDED
@@ -0,0 +1,620 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2013 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-base-processor.php' );
|
19 |
+
|
20 |
+
if ( !class_exists('ICWP_FirewallProcessor') ):
|
21 |
+
|
22 |
+
class ICWP_FirewallProcessor extends ICWP_BaseProcessor_WPSF {
|
23 |
+
|
24 |
+
protected $m_nRequestTimestamp;
|
25 |
+
|
26 |
+
protected $m_aBlockSettings;
|
27 |
+
|
28 |
+
protected $m_aWhitelistPages;
|
29 |
+
protected $m_aWhitelistPagesPatterns;
|
30 |
+
protected $m_aCustomWhitelistPageParams;
|
31 |
+
|
32 |
+
protected $m_aRequestUriParts;
|
33 |
+
|
34 |
+
private $m_nLoopProtect;
|
35 |
+
private $m_sFirewallMessage;
|
36 |
+
|
37 |
+
/**
|
38 |
+
* @var string
|
39 |
+
*/
|
40 |
+
protected $m_sListItemLabel;
|
41 |
+
|
42 |
+
/**
|
43 |
+
* A combination of all current request $_GET and $_POST (and optionally $_COOKIE)
|
44 |
+
* @var array
|
45 |
+
*/
|
46 |
+
protected $m_aOrigPageParams;
|
47 |
+
|
48 |
+
/**
|
49 |
+
* This is $m_aOrigPageParams after any parameter whitelisting has taken place
|
50 |
+
* @var array
|
51 |
+
*/
|
52 |
+
protected $m_aPageParams;
|
53 |
+
|
54 |
+
/**
|
55 |
+
* All the array values of $m_aPageParams
|
56 |
+
* @var array
|
57 |
+
*/
|
58 |
+
protected $m_aPageParamValuesToCheck;
|
59 |
+
|
60 |
+
/**
|
61 |
+
* All the remaining values of the page parameters after they've been filtered
|
62 |
+
* @var array
|
63 |
+
*/
|
64 |
+
protected $m_aPageParamValues;
|
65 |
+
|
66 |
+
public function __construct() {
|
67 |
+
parent::__construct();
|
68 |
+
|
69 |
+
$sMessage = "You were blocked by the %sWordPress Simple Firewall%s.";
|
70 |
+
$this->m_sFirewallMessage = sprintf( $sMessage, '<a href="http://wordpress.org/plugins/wp-simple-firewall/" target="_blank">', '</a>');
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* @see ICWP_BaseProcessor_WPSF::setOptions()
|
75 |
+
*/
|
76 |
+
public function setOptions( &$inaOptions ) {
|
77 |
+
parent::setOptions( $inaOptions );
|
78 |
+
|
79 |
+
// collect up all the settings to pass to the processor
|
80 |
+
$aSettingSlugs = array(
|
81 |
+
'include_cookie_checks',
|
82 |
+
'block_dir_traversal',
|
83 |
+
'block_sql_queries',
|
84 |
+
'block_wordpress_terms',
|
85 |
+
'block_field_truncation',
|
86 |
+
'block_exe_file_uploads',
|
87 |
+
'block_leading_schema'
|
88 |
+
);
|
89 |
+
$this->m_aBlockSettings = array();
|
90 |
+
foreach( $aSettingSlugs as $sSettingKey ) {
|
91 |
+
$this->m_aBlockSettings[ $sSettingKey ] = $this->m_aOptions[$sSettingKey] == 'Y';
|
92 |
+
}
|
93 |
+
|
94 |
+
$this->m_aCustomWhitelistPageParams = is_array( $this->m_aOptions[ 'page_params_whitelist' ] )? $this->m_aOptions[ 'page_params_whitelist' ] : array();
|
95 |
+
$this->setLogging( $this->m_aOptions[ 'enable_firewall_log' ] == 'Y' );
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* @return boolean
|
100 |
+
*/
|
101 |
+
public function getNeedsEmailHandler() {
|
102 |
+
if ( $this->m_aOptions['block_send_email'] == 'Y' ) {
|
103 |
+
return true;
|
104 |
+
}
|
105 |
+
return false;
|
106 |
+
}
|
107 |
+
|
108 |
+
public function reset() {
|
109 |
+
parent::reset();
|
110 |
+
$this->m_nRequestTimestamp = time();
|
111 |
+
$this->m_nLoopProtect = 0;
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Should return false when logging is disabled.
|
116 |
+
*
|
117 |
+
* @return false|array - false when logging is disabled, array with log data otherwise
|
118 |
+
* @see ICWP_BaseProcessor_WPSF::getLogData()
|
119 |
+
*/
|
120 |
+
public function flushLogData() {
|
121 |
+
|
122 |
+
if ( !$this->m_fLoggingEnabled ) {
|
123 |
+
return false;
|
124 |
+
}
|
125 |
+
|
126 |
+
$this->m_aLog = array(
|
127 |
+
'category' => self::LOG_CATEGORY_FIREWALL,
|
128 |
+
'messages' => serialize( $this->m_aLogMessages ),
|
129 |
+
'created_at' => $this->m_nRequestTimestamp,
|
130 |
+
'ip' => long2ip( $this->m_nRequestIp ),
|
131 |
+
'ip_long' => $this->m_nRequestIp,
|
132 |
+
);
|
133 |
+
$this->resetLog();
|
134 |
+
return $this->m_aLog;
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
* @return boolean - true if visitor is permitted, false if it should be blocked.
|
139 |
+
*/
|
140 |
+
public function doFirewallCheck() {
|
141 |
+
|
142 |
+
// if we couldn't process the REQUEST_URI parts, we can't firewall so we effectively whitelist without erroring.
|
143 |
+
$this->setRequestUriPageParts();
|
144 |
+
if ( empty( $this->m_aRequestUriParts ) ) {
|
145 |
+
$this->logInfo( 'Could not parse the URI so cannot effectively firewall.' );
|
146 |
+
return true;
|
147 |
+
}
|
148 |
+
|
149 |
+
// Set up the page parameters ($_GET and $_POST and optionally $_COOKIE). If there are none, quit since there's nothing for the firewall to check.
|
150 |
+
$this->setPageParams();
|
151 |
+
if ( empty( $this->m_aPageParams ) ) {
|
152 |
+
$this->logInfo( 'After any whitelist options were applied, there were no page parameters to check on this visit.' );
|
153 |
+
return true;
|
154 |
+
}
|
155 |
+
$this->m_aPageParamValuesToCheck = array_values( $this->m_aPageParams );
|
156 |
+
|
157 |
+
if ( $this->m_nRequestIp === false ) {
|
158 |
+
$this->logCritical(
|
159 |
+
"Visitor IP address could not be determined so we're by-passing the firewall. Label: %s"
|
160 |
+
);
|
161 |
+
return true;
|
162 |
+
}
|
163 |
+
|
164 |
+
// Check if the visitor is excluded from the firewall from the outset.
|
165 |
+
if ( $this->isVisitorOnWhitelist() ) {
|
166 |
+
$this->logInfo(
|
167 |
+
sprintf( 'Visitor is whitelisted by IP Address. Label: %s',
|
168 |
+
empty( $this->m_sListItemLabel )? 'No label.' : $this->m_sListItemLabel
|
169 |
+
)
|
170 |
+
);
|
171 |
+
return true;
|
172 |
+
}
|
173 |
+
|
174 |
+
//Check if the visitor is excluded from the firewall from the outset.
|
175 |
+
if ( $this->isVisitorOnBlacklist() ) {
|
176 |
+
$this->m_sFirewallMessage .= ' Your IP is Blacklisted.';
|
177 |
+
$this->logWarning(
|
178 |
+
sprintf( 'Visitor was blacklisted by IP Address. Label: %s',
|
179 |
+
empty( $this->m_sListItemLabel )? 'No label.' : $this->m_sListItemLabel
|
180 |
+
)
|
181 |
+
);
|
182 |
+
return false;
|
183 |
+
}
|
184 |
+
|
185 |
+
/* Removed as of version 1.5.0
|
186 |
+
// Checking this comes before all else but after the IP whitelist/blacklist check.
|
187 |
+
if ( $this->m_aBlockSettings[ 'block_wplogin_access' ] ) {
|
188 |
+
$fIsPermittedVisitor = $this->doPassCheckBlockWpLogin();
|
189 |
+
}
|
190 |
+
*/
|
191 |
+
|
192 |
+
$this->logInfo( 'Visitor IP was neither whitelisted nor blacklisted. Firewall checking started.' );
|
193 |
+
|
194 |
+
$fIsPermittedVisitor = true;
|
195 |
+
|
196 |
+
// Check if the page and its parameters are whitelisted.
|
197 |
+
if ( $fIsPermittedVisitor && $this->isPageWhitelisted() ) {
|
198 |
+
return true;
|
199 |
+
}
|
200 |
+
|
201 |
+
if ( $fIsPermittedVisitor && $this->m_aBlockSettings[ 'block_dir_traversal' ] ) {
|
202 |
+
$fIsPermittedVisitor = $this->doPassCheckBlockDirTraversal();
|
203 |
+
}
|
204 |
+
if ( $fIsPermittedVisitor && $this->m_aBlockSettings[ 'block_sql_queries' ] ) {
|
205 |
+
$fIsPermittedVisitor = $this->doPassCheckBlockSqlQueries();
|
206 |
+
}
|
207 |
+
if ( $fIsPermittedVisitor && $this->m_aBlockSettings[ 'block_wordpress_terms' ] ) {
|
208 |
+
$fIsPermittedVisitor = $this->doPassCheckBlockWordpressTerms();
|
209 |
+
}
|
210 |
+
if ( $fIsPermittedVisitor && $this->m_aBlockSettings[ 'block_field_truncation' ] ) {
|
211 |
+
$fIsPermittedVisitor = $this->doPassCheckBlockFieldTruncation();
|
212 |
+
}
|
213 |
+
if ( $fIsPermittedVisitor && $this->m_aBlockSettings[ 'block_exe_file_uploads' ] ) {
|
214 |
+
$fIsPermittedVisitor = $this->doPassCheckBlockExeFileUploads();
|
215 |
+
}
|
216 |
+
if ( $fIsPermittedVisitor && $this->m_aBlockSettings[ 'block_leading_schema' ] ) {
|
217 |
+
$fIsPermittedVisitor = $this->doPassCheckBlockLeadingSchema();
|
218 |
+
}
|
219 |
+
|
220 |
+
return $fIsPermittedVisitor;
|
221 |
+
}
|
222 |
+
|
223 |
+
/**
|
224 |
+
* This function assumes that isVisitorOnWhitelist() check has been run previously. Meaning the
|
225 |
+
* current visitor is NOT on the whitelist and so if the page they're accessing is wp-login then
|
226 |
+
* they do not pass this check.
|
227 |
+
*
|
228 |
+
* If whitelisted IPs is empty, we never block access.
|
229 |
+
*
|
230 |
+
* @return boolean
|
231 |
+
*/
|
232 |
+
protected function doPassCheckBlockWpLogin() {
|
233 |
+
|
234 |
+
list( $sRequestPage, $sRequestQuery ) = $this->m_aRequestUriParts;
|
235 |
+
|
236 |
+
if ( substr_count( $sRequestPage, '/wp-login.php' ) > 0 ) {
|
237 |
+
|
238 |
+
// We don't block wp-login.php if there are no whitelisted IPs.
|
239 |
+
if ( count( $this->m_aOptions[ 'ips_whitelist' ] ) < 1 ) {
|
240 |
+
$this->logInfo( 'Requested: Block access to wp-login.php, but this was skipped because whitelisted IPs list was empty.' );
|
241 |
+
return true;
|
242 |
+
}
|
243 |
+
|
244 |
+
$this->logWarning( 'Requested: Block access to wp-login.php. Visitor not on IP whitelist and blocked by firewall.' );
|
245 |
+
return false;
|
246 |
+
}
|
247 |
+
return true;
|
248 |
+
}
|
249 |
+
|
250 |
+
protected function doPassCheckBlockDirTraversal() {
|
251 |
+
$aTerms = array(
|
252 |
+
'etc/passwd',
|
253 |
+
'proc/self/environ',
|
254 |
+
'../'
|
255 |
+
);
|
256 |
+
$fPass = $this->doPassCheck( $this->m_aPageParamValuesToCheck, $aTerms );
|
257 |
+
if ( !$fPass ) {
|
258 |
+
$this->logWarning( 'Blocked Directory Traversal.' );
|
259 |
+
}
|
260 |
+
return $fPass;
|
261 |
+
}
|
262 |
+
|
263 |
+
protected function doPassCheckBlockSqlQueries() {
|
264 |
+
$aTerms = array(
|
265 |
+
'/concat\s*\(/i',
|
266 |
+
'/group_concat/i',
|
267 |
+
'/union.*select/i'
|
268 |
+
);
|
269 |
+
$fPass = $this->doPassCheck( $this->m_aPageParamValuesToCheck, $aTerms, true );
|
270 |
+
if ( !$fPass ) {
|
271 |
+
$this->logWarning( 'Requested: Block access to wp-login.php, but this was skipped because whitelisted IPs list was empty.' );
|
272 |
+
}
|
273 |
+
return $fPass;
|
274 |
+
}
|
275 |
+
|
276 |
+
protected function doPassCheckBlockWordpressTerms() {
|
277 |
+
$aTerms = array(
|
278 |
+
'/wp_/i',
|
279 |
+
'/user_login/i',
|
280 |
+
'/user_pass/i',
|
281 |
+
'/0x[0-9a-f][0-9a-f]/i',
|
282 |
+
'/\/\*\*\//'
|
283 |
+
);
|
284 |
+
$fPass = $this->doPassCheck( $this->m_aPageParamValuesToCheck, $aTerms, true );
|
285 |
+
if ( !$fPass ) {
|
286 |
+
$this->logWarning( 'Blocked WordPress Terms.' );
|
287 |
+
}
|
288 |
+
return $fPass;
|
289 |
+
}
|
290 |
+
|
291 |
+
protected function doPassCheckBlockFieldTruncation() {
|
292 |
+
$aTerms = array(
|
293 |
+
'/\s{49,}/i',
|
294 |
+
'/\x00/'
|
295 |
+
);
|
296 |
+
$fPass = $this->doPassCheck( $this->m_aPageParamValuesToCheck, $aTerms, true );
|
297 |
+
if ( !$fPass ) {
|
298 |
+
$this->logWarning( 'Blocked Field Truncation.' );
|
299 |
+
}
|
300 |
+
return $fPass;
|
301 |
+
}
|
302 |
+
|
303 |
+
protected function doPassCheckBlockExeFileUploads() {
|
304 |
+
$aTerms = array(
|
305 |
+
'/\.dll$/i', '/\.rb$/i', '/\.py$/i', '/\.exe$/i', '/\.php[3-6]?$/i', '/\.pl$/i',
|
306 |
+
'/\.perl$/i', '/\.ph[34]$/i', '/\.phl$/i', '/\.phtml$/i', '/\.phtm$/i'
|
307 |
+
);
|
308 |
+
|
309 |
+
if ( isset( $_FILES ) && !empty( $_FILES ) ) {
|
310 |
+
$aFileNames = array();
|
311 |
+
foreach( $_FILES as $aFile ) {
|
312 |
+
if ( !empty( $aFile['name'] ) ) {
|
313 |
+
$aFileNames[] = $aFile['name'];
|
314 |
+
}
|
315 |
+
}
|
316 |
+
$fPass = $this->doPassCheck( $aFileNames, $aTerms, true );
|
317 |
+
if ( !$fPass ) {
|
318 |
+
$this->logWarning( 'Blocked EXE File Uploads.' );
|
319 |
+
}
|
320 |
+
return $fPass;
|
321 |
+
}
|
322 |
+
return true;
|
323 |
+
}
|
324 |
+
|
325 |
+
protected function doPassCheckBlockLeadingSchema() {
|
326 |
+
$aTerms = array(
|
327 |
+
'/^http/i', '/\.shtml$/i'
|
328 |
+
);
|
329 |
+
$fPass = $this->doPassCheck( $this->m_aPageParamValuesToCheck, $aTerms, true );
|
330 |
+
if ( !$fPass ) {
|
331 |
+
$this->logWarning( 'Blocked Leading Schema.' );
|
332 |
+
}
|
333 |
+
return $fPass;
|
334 |
+
}
|
335 |
+
|
336 |
+
/**
|
337 |
+
* Returns false when check fails - that is to say, it should be blocked by the firewall.
|
338 |
+
*
|
339 |
+
* @param array $inaParamValues
|
340 |
+
* @param array $inaMatchTerms
|
341 |
+
* @param boolean $infRegex
|
342 |
+
* @return boolean
|
343 |
+
*/
|
344 |
+
private function doPassCheck( $inaParamValues, $inaMatchTerms, $infRegex = false ) {
|
345 |
+
|
346 |
+
$fFAIL = false;
|
347 |
+
foreach ( $inaParamValues as $mValue ) {
|
348 |
+
if ( is_array( $mValue ) ) {
|
349 |
+
|
350 |
+
// Protection against an infinite loop and we limit depth to 3.
|
351 |
+
if ( $this->m_nLoopProtect > 2 ) {
|
352 |
+
return true;
|
353 |
+
}
|
354 |
+
else {
|
355 |
+
$this->m_nLoopProtect++;
|
356 |
+
}
|
357 |
+
|
358 |
+
if ( !$this->doPassCheck( $mValue, $inaMatchTerms, $infRegex ) ) {
|
359 |
+
return false;
|
360 |
+
}
|
361 |
+
|
362 |
+
$this->m_nLoopProtect--;
|
363 |
+
}
|
364 |
+
else {
|
365 |
+
$mValue = (string) $mValue;
|
366 |
+
foreach ( $inaMatchTerms as $sTerm ) {
|
367 |
+
|
368 |
+
if ( $infRegex && preg_match( $sTerm, $mValue ) ) { //dodgy term pattern found in a parameter value
|
369 |
+
$fFAIL = true;
|
370 |
+
}
|
371 |
+
else if ( strpos( $mValue, $sTerm ) !== false ) { //dodgy term found in a parameter value
|
372 |
+
$fFAIL = true;
|
373 |
+
}
|
374 |
+
|
375 |
+
if ( $fFAIL ) {
|
376 |
+
$this->m_sFirewallMessage .= " Something in the URL, Form or Cookie data wasn't appropriate.";
|
377 |
+
$this->logWarning(
|
378 |
+
sprintf( 'Page parameter failed firewall check. The value was %s and the term matched was %s', $mValue, $sTerm )
|
379 |
+
);
|
380 |
+
return false;
|
381 |
+
}
|
382 |
+
|
383 |
+
}//foreach
|
384 |
+
}
|
385 |
+
}//foreach
|
386 |
+
|
387 |
+
return true;
|
388 |
+
}
|
389 |
+
|
390 |
+
public function doPreFirewallBlock() {
|
391 |
+
|
392 |
+
switch( $this->m_aOptions['block_response'] ) {
|
393 |
+
case 'redirect_die':
|
394 |
+
$this->logWarning(
|
395 |
+
sprintf( 'Firewall Block: Visitor connection was killed with %s', 'die()' )
|
396 |
+
);
|
397 |
+
break;
|
398 |
+
case 'redirect_die_message':
|
399 |
+
$this->logWarning(
|
400 |
+
sprintf( 'Firewall Block: Visitor connection was killed with %s and message', 'wp_die()' )
|
401 |
+
);
|
402 |
+
break;
|
403 |
+
case 'redirect_home':
|
404 |
+
$this->logWarning(
|
405 |
+
sprintf( 'Firewall Block: Visitor was sent HOME: %s', home_url() )
|
406 |
+
);
|
407 |
+
break;
|
408 |
+
case 'redirect_404':
|
409 |
+
$this->logWarning(
|
410 |
+
sprintf( 'Firewall Block: Visitor was sent 404: %s', home_url().'/404' )
|
411 |
+
);
|
412 |
+
break;
|
413 |
+
}
|
414 |
+
|
415 |
+
if ( $this->m_aOptions['block_send_email'] == 'Y' ) {
|
416 |
+
$this->sendBlockEmail();
|
417 |
+
}
|
418 |
+
}
|
419 |
+
|
420 |
+
public function doFirewallBlock() {
|
421 |
+
|
422 |
+
switch( $this->m_aOptions['block_response'] ) {
|
423 |
+
case 'redirect_die':
|
424 |
+
die();
|
425 |
+
case 'redirect_die_message':
|
426 |
+
wp_die( $this->m_sFirewallMessage );
|
427 |
+
exit();
|
428 |
+
break;
|
429 |
+
case 'redirect_home':
|
430 |
+
header( "Location: ".home_url() );
|
431 |
+
exit();
|
432 |
+
break;
|
433 |
+
case 'redirect_404':
|
434 |
+
header( "Location: ".home_url().'/404' );
|
435 |
+
exit();
|
436 |
+
break;
|
437 |
+
}
|
438 |
+
}
|
439 |
+
|
440 |
+
/**
|
441 |
+
*
|
442 |
+
* @return boolean
|
443 |
+
*/
|
444 |
+
public function isPageWhitelisted() {
|
445 |
+
return empty( $this->m_aPageParams );
|
446 |
+
}
|
447 |
+
|
448 |
+
public function filterWhitelistedPagesAndParams() {
|
449 |
+
|
450 |
+
if ( empty( $this->m_aWhitelistPages ) ) {
|
451 |
+
$this->setWhitelistPages();
|
452 |
+
if ( empty( $this->m_aWhitelistPages ) ) {
|
453 |
+
return false;
|
454 |
+
}
|
455 |
+
}
|
456 |
+
// Check normal whitelisting pages without patterns.
|
457 |
+
if ( $this->checkPagesForWhiteListing( $this->m_aWhitelistPages ) ) {
|
458 |
+
return true;
|
459 |
+
}
|
460 |
+
// Check pattern-based whitelisting pages.
|
461 |
+
if ( $this->checkPagesForWhiteListing( $this->m_aWhitelistPagesPatterns, true ) ) {
|
462 |
+
return true;
|
463 |
+
}
|
464 |
+
}
|
465 |
+
|
466 |
+
/**
|
467 |
+
* @param array $inaWhitelistPagesParams
|
468 |
+
* @param boolean $infUseRegex
|
469 |
+
* @return boolean
|
470 |
+
*/
|
471 |
+
protected function checkPagesForWhiteListing( $inaWhitelistPagesParams = array(), $infUseRegex = false ) {
|
472 |
+
|
473 |
+
if ( !is_array( $this->m_aRequestUriParts ) || count( $this->m_aRequestUriParts ) < 1 ) {
|
474 |
+
return true;
|
475 |
+
}
|
476 |
+
$sRequestPage = $this->m_aRequestUriParts[0];
|
477 |
+
|
478 |
+
// Now we compare pages in the whitelist with the parts of the request uri. If we get a match, that page is whitelisted
|
479 |
+
$aWhitelistPages = array_keys( $inaWhitelistPagesParams );
|
480 |
+
|
481 |
+
// 1. Is the page in the list of white pages?
|
482 |
+
$fPageWhitelisted = false;
|
483 |
+
foreach ( $inaWhitelistPagesParams as $sPageName => $aWhitlistedParams ) {
|
484 |
+
|
485 |
+
if ( $infUseRegex ) {
|
486 |
+
if ( preg_match( $sPageName, $sRequestPage ) ) {
|
487 |
+
$fPageWhitelisted = true;
|
488 |
+
break;
|
489 |
+
}
|
490 |
+
}
|
491 |
+
else {
|
492 |
+
if ( preg_match( self::PcreDelimiter. preg_quote( $sPageName, self::PcreDelimiter ).'$'.self::PcreDelimiter, $sRequestPage ) ) {
|
493 |
+
$fPageWhitelisted = true;
|
494 |
+
break;
|
495 |
+
}
|
496 |
+
}
|
497 |
+
}
|
498 |
+
|
499 |
+
// There's a list of globally whitelisted parameters (i.e. parameter ignored for all pages)
|
500 |
+
if ( array_key_exists( '*', $inaWhitelistPagesParams ) ) {
|
501 |
+
foreach ( $inaWhitelistPagesParams['*'] as $sWhitelistParam ) {
|
502 |
+
if ( array_key_exists( $sWhitelistParam, $this->m_aPageParams ) ) {
|
503 |
+
unset( $this->m_aPageParams[ $sWhitelistParam ] );
|
504 |
+
}
|
505 |
+
}
|
506 |
+
}
|
507 |
+
|
508 |
+
// There's a list of globally whitelisted parameters (i.e. parameter ignored for all pages)
|
509 |
+
if ( $fPageWhitelisted ) {
|
510 |
+
// the current page is whitelisted - now check if it has request parameters.
|
511 |
+
if ( empty( $aWhitlistedParams ) ) {
|
512 |
+
return true; //because it's just plain whitelisted as represented by an empty or unset array
|
513 |
+
}
|
514 |
+
foreach ( $aWhitlistedParams as $sWhitelistParam ) {
|
515 |
+
if ( array_key_exists( $sWhitelistParam, $this->m_aPageParams ) ) {
|
516 |
+
unset( $this->m_aPageParams[ $sWhitelistParam ] );
|
517 |
+
}
|
518 |
+
}
|
519 |
+
|
520 |
+
// After removing all the whitelisted params, we now check if there are any params left that'll
|
521 |
+
// need matched later in the firewall checking. If there are no parameters left, we return true.
|
522 |
+
if ( empty( $this->m_aPageParams ) ) {
|
523 |
+
return true;
|
524 |
+
}
|
525 |
+
}
|
526 |
+
return false;
|
527 |
+
}
|
528 |
+
|
529 |
+
protected function setRequestUriPageParts() {
|
530 |
+
|
531 |
+
if ( !isset( $_SERVER['REQUEST_URI'] ) || empty( $_SERVER['REQUEST_URI'] ) ) {
|
532 |
+
$this->m_aRequestUriParts = false;
|
533 |
+
$this->logWarning( 'Could not parse the details of this page call as $_SERVER[REQUEST_URI] was empty or not defined.' );
|
534 |
+
return false;
|
535 |
+
}
|
536 |
+
$this->m_aRequestUriParts = explode( '?', $_SERVER['REQUEST_URI'] );
|
537 |
+
$this->logInfo( sprintf( 'Page Request URI: %s', $_SERVER['REQUEST_URI'] ) );
|
538 |
+
return true;
|
539 |
+
}
|
540 |
+
|
541 |
+
protected function setPageParams() {
|
542 |
+
$this->m_aPageParams = array_merge( $_GET, $_POST );
|
543 |
+
if ( $this->m_aBlockSettings[ 'include_cookie_checks' ] ) {
|
544 |
+
$this->m_aPageParams = array_merge( $this->m_aPageParams, $_COOKIE );
|
545 |
+
}
|
546 |
+
|
547 |
+
if ( !empty( $this->m_aPageParams ) ) {
|
548 |
+
$this->filterWhitelistedPagesAndParams();
|
549 |
+
}
|
550 |
+
return true;
|
551 |
+
}
|
552 |
+
|
553 |
+
private function setWhitelistPages() {
|
554 |
+
|
555 |
+
$aDefaultWlPages = array(
|
556 |
+
'/wp-admin/options-general.php' => array(),
|
557 |
+
'/wp-admin/post-new.php' => array(),
|
558 |
+
'/wp-admin/page-new.php' => array(),
|
559 |
+
'/wp-admin/link-add.php' => array(),
|
560 |
+
'/wp-admin/media-upload.php' => array(),
|
561 |
+
'/wp-admin/post.php' => array(),
|
562 |
+
'/wp-admin/page.php' => array(),
|
563 |
+
'/wp-admin/admin-ajax.php' => array(),
|
564 |
+
'/wp-comments-post.php' => array(
|
565 |
+
'url',
|
566 |
+
'comment'
|
567 |
+
),
|
568 |
+
'/wp-login.php' => array(
|
569 |
+
'redirect_to'
|
570 |
+
)
|
571 |
+
);
|
572 |
+
|
573 |
+
if ( !is_null($this->m_aCustomWhitelistPageParams) && is_array($this->m_aCustomWhitelistPageParams) ) {
|
574 |
+
$this->m_aWhitelistPages = array_merge( $aDefaultWlPages, $this->m_aCustomWhitelistPageParams );
|
575 |
+
}
|
576 |
+
else {
|
577 |
+
$this->m_aWhitelistPages = $aDefaultWlPages;
|
578 |
+
}
|
579 |
+
|
580 |
+
$this->m_aWhitelistPagesPatterns = array(
|
581 |
+
self::PcreDelimiter.'\/wp-admin\/\*'.self::PcreDelimiter => array(
|
582 |
+
'_wp_original_http_referer',
|
583 |
+
'_wp_http_referer'
|
584 |
+
),
|
585 |
+
);
|
586 |
+
}
|
587 |
+
|
588 |
+
public function isVisitorOnWhitelist() {
|
589 |
+
return $this->isIpOnlist( $this->m_aOptions[ 'ips_whitelist' ], $this->m_nRequestIp, $this->m_sListItemLabel );
|
590 |
+
}
|
591 |
+
|
592 |
+
public function isVisitorOnBlacklist() {
|
593 |
+
return $this->isIpOnlist( $this->m_aOptions[ 'ips_blacklist' ], $this->m_nRequestIp, $this->m_sListItemLabel );
|
594 |
+
}
|
595 |
+
|
596 |
+
/**
|
597 |
+
* @return boolean
|
598 |
+
*/
|
599 |
+
public function sendBlockEmail() {
|
600 |
+
|
601 |
+
$sIp = long2ip( $this->m_nRequestIp );
|
602 |
+
$aMessage = array(
|
603 |
+
'WordPress Simple Firewall has blocked a visitor to your site.',
|
604 |
+
'Log details for this visitor are below:',
|
605 |
+
'- IP Address: '.$sIp,
|
606 |
+
);
|
607 |
+
foreach( $this->m_aLogMessages as $aLogItem ) {
|
608 |
+
list( $sLogType, $sLogMessage ) = $aLogItem;
|
609 |
+
$aMessage[] = '- '.$sLogMessage;
|
610 |
+
}
|
611 |
+
|
612 |
+
$sEmailSubject = 'Firewall Block Alert: ' . home_url();
|
613 |
+
$aMessage[] = 'You could look up the offending IP Address here: http://ip-lookup.net/?ip='.$sIp;
|
614 |
+
|
615 |
+
$this->logInfo( 'Firewall block email.' );
|
616 |
+
$this->sendEmail( $sEmailSubject, $aMessage );
|
617 |
+
}
|
618 |
+
}
|
619 |
+
|
620 |
+
endif;
|
src/icwp-processor-lockdown.php
ADDED
@@ -0,0 +1,109 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2013 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-base-processor.php' );
|
19 |
+
|
20 |
+
if ( !class_exists('ICWP_LockdownProcessor') ):
|
21 |
+
|
22 |
+
class ICWP_LockdownProcessor extends ICWP_BaseProcessor_WPSF {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Resets the object values to be re-used anew
|
26 |
+
*/
|
27 |
+
public function reset() {
|
28 |
+
parent::reset();
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
*/
|
33 |
+
public function run() {
|
34 |
+
|
35 |
+
if ( $this->m_aOptions['disable_file_editing'] == 'Y' ) {
|
36 |
+
add_filter( 'user_has_cap', array( $this, 'disableFileEditing' ), 0, 3 );
|
37 |
+
}
|
38 |
+
|
39 |
+
if ( false && $this->m_aOptions['action_reset_auth_salts'] == 'Y' ) {
|
40 |
+
add_action( 'init', array( $this, 'resetAuthKeysSalts' ), 1 );
|
41 |
+
}
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* @return array
|
46 |
+
*/
|
47 |
+
public function disableFileEditing( $inaAllCaps, $cap, $inaArgs ) {
|
48 |
+
|
49 |
+
$aEditCapabilities = array( 'edit_themes', 'edit_plugins', 'edit_files' );
|
50 |
+
$sRequestedCapability = $inaArgs[0];
|
51 |
+
|
52 |
+
if ( !in_array( $sRequestedCapability, $aEditCapabilities ) ) {
|
53 |
+
return $inaAllCaps;
|
54 |
+
}
|
55 |
+
$inaAllCaps[ $sRequestedCapability ] = false;
|
56 |
+
return $inaAllCaps;
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
*
|
61 |
+
*/
|
62 |
+
public function resetAuthKeysSalts() {
|
63 |
+
|
64 |
+
require_once( dirname(__FILE__).'/icwp-wpfilesystem.php' );
|
65 |
+
$oWpFilesystem = new ICWP_WpFilesystem_WPSF();
|
66 |
+
|
67 |
+
// Get the new Salts
|
68 |
+
$sSaltsUrl = 'https://api.wordpress.org/secret-key/1.1/salt/';
|
69 |
+
$sSalts = $oWpFilesystem->getUrlContent( $sSaltsUrl );
|
70 |
+
|
71 |
+
$sWpConfigContent = $oWpFilesystem->getContent_WpConfig();
|
72 |
+
if ( is_null( $sWpConfigContent ) ) {
|
73 |
+
return;
|
74 |
+
}
|
75 |
+
|
76 |
+
$aKeys = array(
|
77 |
+
'AUTH_KEY',
|
78 |
+
'SECURE_AUTH_KEY',
|
79 |
+
'LOGGED_IN_KEY',
|
80 |
+
'NONCE_KEY',
|
81 |
+
'AUTH_SALT',
|
82 |
+
'SECURE_AUTH_SALT',
|
83 |
+
'LOGGED_IN_SALT',
|
84 |
+
'NONCE_SALT'
|
85 |
+
);
|
86 |
+
|
87 |
+
$aContent = explode( PHP_EOL, $sWpConfigContent );
|
88 |
+
$fKeyFound = false;
|
89 |
+
$nStartLine = 0;
|
90 |
+
foreach( $aContent as $nLineNumber => $sLine ) {
|
91 |
+
foreach( $aKeys as $nPosition => $sKey ) {
|
92 |
+
if ( strpos( $sLine, $sKey ) === false ) {
|
93 |
+
continue;
|
94 |
+
}
|
95 |
+
if ( $nStartLine == 0 ) {
|
96 |
+
$nStartLine = $nLineNumber;
|
97 |
+
}
|
98 |
+
else {
|
99 |
+
unset( $aContent[ $nLineNumber ] );
|
100 |
+
}
|
101 |
+
$fKeyFound = true;
|
102 |
+
}
|
103 |
+
}
|
104 |
+
$aContent[$nStartLine] = $sSalts;
|
105 |
+
$oWpFilesystem->putContent_WpConfig( implode( PHP_EOL, $aContent ) );
|
106 |
+
}
|
107 |
+
}
|
108 |
+
|
109 |
+
endif;
|
src/icwp-processor-logging.php
ADDED
@@ -0,0 +1,108 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2013 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_LoggingProcessor') ):
|
21 |
+
|
22 |
+
class ICWP_LoggingProcessor extends ICWP_BaseDbProcessor_WPSF {
|
23 |
+
|
24 |
+
const TableName = 'wpsf_log';
|
25 |
+
protected $m_sRequestId;
|
26 |
+
|
27 |
+
public function __construct() {
|
28 |
+
parent::__construct( self::TableName );
|
29 |
+
$this->createTable();
|
30 |
+
}
|
31 |
+
|
32 |
+
public function reset() {
|
33 |
+
parent::reset();
|
34 |
+
$this->m_sRequestId = uniqid();
|
35 |
+
$this->m_nRequestIp = self::GetVisitorIpAddress();
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* @return array - numerical array of all log data entries.
|
40 |
+
*/
|
41 |
+
public function getLogs( $infReverseOrder = false ) {
|
42 |
+
$aLogData = $this->selectAllFromTable();
|
43 |
+
if ( $infReverseOrder && $aLogData && is_array( $aLogData ) ) {
|
44 |
+
$aLogData = array_reverse( $aLogData );
|
45 |
+
}
|
46 |
+
return $aLogData;
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* @return array - numerical array of all log data entries.
|
51 |
+
*/
|
52 |
+
public function writeLog( $inaLogData ) {
|
53 |
+
|
54 |
+
if ( empty( $inaLogData ) || empty( $inaLogData['messages'] ) ) {
|
55 |
+
return;
|
56 |
+
}
|
57 |
+
$aData = $this->completeLogData( $inaLogData );
|
58 |
+
$fSuccess = $this->insertIntoTable( $aData );
|
59 |
+
return $fSuccess;
|
60 |
+
}
|
61 |
+
|
62 |
+
protected function completeLogData( $inaLogData ) {
|
63 |
+
|
64 |
+
if ( !isset( $inaLogData['category'] ) ) {
|
65 |
+
$inaLogData['category'] = self::LOG_CATEGORY_DEFAULT;
|
66 |
+
}
|
67 |
+
if ( !isset( $inaLogData['request_id'] ) ) {
|
68 |
+
$inaLogData['request_id'] = $this->m_sRequestId;
|
69 |
+
}
|
70 |
+
if ( !isset( $inaLogData['ip'] ) ) {
|
71 |
+
$inaLogData['ip'] = self::GetVisitorIpAddress( false );
|
72 |
+
}
|
73 |
+
if ( !isset( $inaLogData['ip_long'] ) ) {
|
74 |
+
$inaLogData['ip_long'] = ip2long( $inaLogData['ip'] );
|
75 |
+
}
|
76 |
+
if ( !isset( $inaLogData['created_at'] ) ) {
|
77 |
+
$inaLogData['created_at'] = time();
|
78 |
+
}
|
79 |
+
return $inaLogData;
|
80 |
+
}
|
81 |
+
|
82 |
+
public function createTable() {
|
83 |
+
|
84 |
+
// Set up log table
|
85 |
+
$sSqlTables = "CREATE TABLE IF NOT EXISTS `%s` (
|
86 |
+
`id` int(11) NOT NULL AUTO_INCREMENT,
|
87 |
+
`request_id` varchar(255) NOT NULL DEFAULT '',
|
88 |
+
`category` int(5) NOT NULL DEFAULT '0',
|
89 |
+
`messages` text NOT NULL,
|
90 |
+
`ip` varchar(20) NOT NULL DEFAULT '',
|
91 |
+
`ip_long` bigint(20) NOT NULL DEFAULT '0',
|
92 |
+
`created_at` int(15) NOT NULL DEFAULT '0',
|
93 |
+
`deleted_at` int(15) NOT NULL DEFAULT '0',
|
94 |
+
PRIMARY KEY (`id`)
|
95 |
+
) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
|
96 |
+
$sSqlTables = sprintf( $sSqlTables, $this->m_sTableName );
|
97 |
+
return $this->doSql( $sSqlTables );
|
98 |
+
}
|
99 |
+
|
100 |
+
public function handleInstallUpgrade( $insCurrentVersion = '' ) {
|
101 |
+
if ( version_compare( $insCurrentVersion, '1.3.0', '<' ) ) {
|
102 |
+
// full delete of the log and recreate
|
103 |
+
$this->recreateTable();
|
104 |
+
}
|
105 |
+
}
|
106 |
+
}
|
107 |
+
|
108 |
+
endif;
|
src/icwp-processor-loginprotect.php
ADDED
@@ -0,0 +1,686 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2013 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') ):
|
21 |
+
|
22 |
+
class ICWP_LoginProtectProcessor extends ICWP_BaseDbProcessor_WPSF {
|
23 |
+
|
24 |
+
const TableName = 'login_auth';
|
25 |
+
|
26 |
+
/**
|
27 |
+
* @var string
|
28 |
+
*/
|
29 |
+
static protected $sModeFile_LoginThrottled;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* The number of seconds between each authenticated login
|
33 |
+
* @var integer
|
34 |
+
*/
|
35 |
+
protected $m_nRequiredLoginInterval;
|
36 |
+
|
37 |
+
protected $m_nLastLoginTime;
|
38 |
+
protected $m_sSecretKey;
|
39 |
+
|
40 |
+
protected $m_sGaspKey;
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Flag as to whether Two Factor Authentication will be by-pass when sending the verification
|
44 |
+
* email fails.
|
45 |
+
*
|
46 |
+
* @var boolean
|
47 |
+
*/
|
48 |
+
protected $m_fAllowTwoFactorByPass;
|
49 |
+
|
50 |
+
public function __construct() {
|
51 |
+
parent::__construct( self::TableName );
|
52 |
+
|
53 |
+
$this->m_sGaspKey = uniqid();
|
54 |
+
self::$sModeFile_LoginThrottled = dirname( __FILE__ ).'/../mode.login_throttled';
|
55 |
+
$this->updateLastLoginThrottleTime( time() );
|
56 |
+
|
57 |
+
$this->createTable();
|
58 |
+
$this->reset();
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Resets the object values to be re-used anew
|
63 |
+
*/
|
64 |
+
public function reset() {
|
65 |
+
parent::reset();
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Set the secret key by which authentication is validated.
|
70 |
+
*
|
71 |
+
* @param string $insSecretKey
|
72 |
+
*/
|
73 |
+
public function setSecretKey( $insSecretKey = '' ) {
|
74 |
+
if ( !empty( $insSecretKey ) ) {
|
75 |
+
$this->m_sSecretKey = $insSecretKey;
|
76 |
+
}
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
*
|
81 |
+
* @param array $inoOptions
|
82 |
+
*/
|
83 |
+
public function setOptions( &$inaOptions ) {
|
84 |
+
parent::setOptions( $inaOptions );
|
85 |
+
$this->setLogging();
|
86 |
+
$this->setLoginCooldownInterval();
|
87 |
+
$this->setTwoFactorByPassOnFail();
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* @return boolean
|
92 |
+
*/
|
93 |
+
public function getNeedsEmailHandler() {
|
94 |
+
if ( isset( $this->m_aOptions['enable_two_factor_auth_by_ip'] ) && $this->m_aOptions['enable_two_factor_auth_by_ip'] == 'Y' ) {
|
95 |
+
return true;
|
96 |
+
}
|
97 |
+
return false;
|
98 |
+
}
|
99 |
+
|
100 |
+
public function setLogging() {
|
101 |
+
parent::setLogging( $this->m_aOptions[ 'enable_login_protect_log' ] == 'Y' );
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* @param ICWP_OptionsHandler_LoginProtect $inoOptions
|
106 |
+
*/
|
107 |
+
public function run() {
|
108 |
+
$aWhitelist = $this->m_aOptions['ips_whitelist'];
|
109 |
+
if ( !empty( $aWhitelist ) && $this->isIpOnlist( $aWhitelist, self::GetVisitorIpAddress() ) ) {
|
110 |
+
return true;
|
111 |
+
}
|
112 |
+
|
113 |
+
// Add GASP checking to the login form.
|
114 |
+
if ( $this->m_aOptions['enable_login_gasp_check'] == 'Y' ) {
|
115 |
+
add_action( 'login_form', array( $this, 'printGaspLoginCheck_Action' ) );
|
116 |
+
add_filter( 'login_form_middle', array( $this, 'printGaspLoginCheck_Filter' ) );
|
117 |
+
add_filter( 'authenticate', array( $this, 'checkLoginForGasp_Filter' ), 9, 3);
|
118 |
+
}
|
119 |
+
|
120 |
+
if ( $this->m_aOptions['login_limit_interval'] > 0 ) {
|
121 |
+
// We give it a priority of 10 so that we can jump in before WordPress does its own validation.
|
122 |
+
add_filter( 'authenticate', array( $this, 'checkLoginInterval_Filter' ), 10, 3);
|
123 |
+
}
|
124 |
+
|
125 |
+
if ( $this->m_aOptions['enable_two_factor_auth_by_ip'] == 'Y' ) {
|
126 |
+
// User has clicked a link in their email to validate their IP address for login.
|
127 |
+
if ( isset( $_GET['wpsf-action'] ) && $_GET['wpsf-action'] == 'linkauth' ) {
|
128 |
+
$this->validateUserAuthLink();
|
129 |
+
}
|
130 |
+
|
131 |
+
// If their click was successful we give them a lovely message
|
132 |
+
if ( isset( $_GET['wpsfipverified']) ) {
|
133 |
+
add_filter( 'login_message', array( $this, 'displayVerifiedUserMessage_Filter' ) );
|
134 |
+
}
|
135 |
+
|
136 |
+
// Check the current logged-in user every page load.
|
137 |
+
add_action( 'init', array( $this, 'checkCurrentUserAuth_Action' ) );
|
138 |
+
|
139 |
+
// At this stage (30,3) WordPress has already authenticated the user. So if the login
|
140 |
+
// is valid, the filter will have a valid WP_User object passed to it.
|
141 |
+
add_filter( 'authenticate', array( $this, 'checkUserAuthLogin_Filter' ), 30, 3);
|
142 |
+
}
|
143 |
+
}
|
144 |
+
|
145 |
+
public function printGaspLoginCheck_Action() {
|
146 |
+
echo $this->getGaspLoginHtml();
|
147 |
+
}
|
148 |
+
|
149 |
+
public function printGaspLoginCheck_Filter() {
|
150 |
+
return $this->getGaspLoginHtml();
|
151 |
+
}
|
152 |
+
|
153 |
+
public function checkLoginForGasp_Filter( $inoUser, $insUsername, $insPassword ) {
|
154 |
+
|
155 |
+
if ( empty( $insUsername ) || is_wp_error( $inoUser ) ) {
|
156 |
+
return $inoUser;
|
157 |
+
}
|
158 |
+
if ( $this->doGaspChecks( $insUsername ) ) {
|
159 |
+
return $inoUser;
|
160 |
+
}
|
161 |
+
return null;
|
162 |
+
}
|
163 |
+
|
164 |
+
/**
|
165 |
+
* Checks whether the current user that is logged-in is authenticated by IP address.
|
166 |
+
*
|
167 |
+
* If the user is not found to be valid, they're logged out.
|
168 |
+
*
|
169 |
+
* Should be hooked to 'init' so we have is_user_logged_in()
|
170 |
+
*/
|
171 |
+
public function checkCurrentUserAuth_Action() {
|
172 |
+
if ( is_user_logged_in() ) {
|
173 |
+
$this->verifyCurrentUser();
|
174 |
+
}
|
175 |
+
}
|
176 |
+
|
177 |
+
public function displayVerifiedUserMessage_Filter( $insMessage ) {
|
178 |
+
$sStyles .= 'background-color: #FAFFE8; border: 1px solid #DDDDDD; margin: 8px 0 10px 8px; padding: 16px;';
|
179 |
+
$insMessage .= '<h3 style="'.$sStyles.'">You successfully verified your IP address - you may now login.</h3>';
|
180 |
+
return $insMessage;
|
181 |
+
}
|
182 |
+
|
183 |
+
/**
|
184 |
+
* Should return false when logging is disabled.
|
185 |
+
*
|
186 |
+
* @return false|array - false when logging is disabled, array with log data otherwise
|
187 |
+
* @see ICWP_BaseProcessor_WPSF::getLogData()
|
188 |
+
*/
|
189 |
+
public function flushLogData() {
|
190 |
+
|
191 |
+
if ( !$this->m_fLoggingEnabled || empty( $this->m_aLogMessages ) ) {
|
192 |
+
return false;
|
193 |
+
}
|
194 |
+
|
195 |
+
$this->m_aLog = array(
|
196 |
+
'category' => self::LOG_CATEGORY_LOGINPROTECT,
|
197 |
+
'messages' => serialize( $this->m_aLogMessages )
|
198 |
+
);
|
199 |
+
$this->resetLog();
|
200 |
+
return $this->m_aLog;
|
201 |
+
}
|
202 |
+
|
203 |
+
/**
|
204 |
+
* Checks the link details to ensure all is valid before authorizing the user.
|
205 |
+
*
|
206 |
+
* @return boolean
|
207 |
+
*/
|
208 |
+
public function validateUserAuthLink() {
|
209 |
+
// wpsfkey=%s&wpsf-action=%s&username=%s&uniqueid
|
210 |
+
|
211 |
+
if ( !isset( $_GET['wpsfkey'] ) || $_GET['wpsfkey'] !== $this->m_sSecretKey ) {
|
212 |
+
return false;
|
213 |
+
}
|
214 |
+
if ( empty( $_GET['username'] ) || empty( $_GET['uniqueid'] ) ) {
|
215 |
+
return false;
|
216 |
+
}
|
217 |
+
|
218 |
+
$aWhere = array(
|
219 |
+
'unique_id' => $_GET['uniqueid'],
|
220 |
+
'wp_username' => $_GET['username']
|
221 |
+
);
|
222 |
+
|
223 |
+
if ( $this->loginAuthMakeActive( $aWhere ) ) {
|
224 |
+
$this->redirectToLogin( '?wpsfipverified=1' );
|
225 |
+
}
|
226 |
+
else {
|
227 |
+
header( "Location: ".home_url() );
|
228 |
+
}
|
229 |
+
}
|
230 |
+
|
231 |
+
public function redirectToLogin( $sParams = '' ) {
|
232 |
+
header( "Location: ".site_url().'/wp-login.php'.$sParams );
|
233 |
+
}
|
234 |
+
|
235 |
+
// WordPress Hooks and Filters:
|
236 |
+
|
237 |
+
/**
|
238 |
+
* Should be a filter added to WordPress's "authenticate" filter, but before WordPress performs
|
239 |
+
* it's own authentication (theirs is priority 30, so we could go in at around 20).
|
240 |
+
*
|
241 |
+
* @param null|WP_User|WP_Error $inoUser
|
242 |
+
* @param string $insUsername
|
243 |
+
* @param string $insPassword
|
244 |
+
* @return unknown|WP_Error
|
245 |
+
*/
|
246 |
+
public function checkLoginInterval_Filter( $inoUser, $insUsername, $insPassword ) {
|
247 |
+
|
248 |
+
// No login attempt was made.
|
249 |
+
if ( empty( $insUsername ) ) {
|
250 |
+
return $inoUser;
|
251 |
+
}
|
252 |
+
|
253 |
+
// Is there an interval set?
|
254 |
+
$nRequiredLoginInterval = $this->m_nRequiredLoginInterval;
|
255 |
+
if ( $nRequiredLoginInterval === false || $nRequiredLoginInterval == 0 ) {
|
256 |
+
return $inoUser;
|
257 |
+
}
|
258 |
+
|
259 |
+
// Get the last login time (and update it also for the next time)
|
260 |
+
$sNow = time();
|
261 |
+
$this->m_nLastLoginTime = $this->getLastLoginTime();
|
262 |
+
|
263 |
+
if ( empty( $this->m_nLastLoginTime ) || $this->m_nLastLoginTime < 0 ) {
|
264 |
+
$this->updateLastLoginThrottleTime( $sNow );
|
265 |
+
}
|
266 |
+
|
267 |
+
// If we're outside the interval, let the login process proceed as per normal and
|
268 |
+
// update our last login time.
|
269 |
+
$nLoginInterval = $sNow - $this->m_nLastLoginTime;
|
270 |
+
if ( $nLoginInterval > $nRequiredLoginInterval ) {
|
271 |
+
$this->updateLastLoginThrottleTime( $sNow );
|
272 |
+
return $inoUser;
|
273 |
+
}
|
274 |
+
|
275 |
+
// At this point someone has attempted to login within the previous login wait interval
|
276 |
+
// So we remove WordPress's authentication filter and our own user check authentication
|
277 |
+
// And finally return a WP_Error which will be reflected back to the user.
|
278 |
+
remove_filter( 'authenticate', 'wp_authenticate_username_password', 20, 3 ); // wp-includes/user.php
|
279 |
+
remove_filter( 'authenticate', array( $this, 'checkUserAuthLogin_Filter' ), 30, 3);
|
280 |
+
|
281 |
+
$sErrorString = sprintf( "Sorry, you must wait %s seconds before attempting to login again.", ($nRequiredLoginInterval - $nLoginInterval ) );
|
282 |
+
$oError = new WP_Error( 'wpsf_logininterval', $sErrorString );
|
283 |
+
return $oError;
|
284 |
+
}
|
285 |
+
|
286 |
+
protected function getLastLoginTime() {
|
287 |
+
|
288 |
+
// Check that there is a login throttle file. If it exists and its modified time is greater than the
|
289 |
+
// current $this->m_nLastLoginTime it suggests another process has touched the file and updated it
|
290 |
+
// concurrently. So, we update our $this->m_nEmailThrottleTime accordingly.
|
291 |
+
if ( is_file( self::$sModeFile_LoginThrottled ) ) {
|
292 |
+
$nModifiedTime = filemtime( self::$sModeFile_LoginThrottled );
|
293 |
+
if ( $nModifiedTime > $this->m_nLastLoginTime ) {
|
294 |
+
$this->m_nLastLoginTime = $nModifiedTime;
|
295 |
+
}
|
296 |
+
}
|
297 |
+
return $this->m_nLastLoginTime;
|
298 |
+
}
|
299 |
+
|
300 |
+
public function updateLastLoginThrottleTime( $innLastLoginTime ) {
|
301 |
+
$this->m_nLastLoginTime = $innLastLoginTime;
|
302 |
+
if ( function_exists('touch') ) {
|
303 |
+
@touch( self::$sModeFile_LoginThrottled, $innLastLoginTime );
|
304 |
+
}
|
305 |
+
$this->setNeedSave();
|
306 |
+
}
|
307 |
+
|
308 |
+
/**
|
309 |
+
* If $inoUser is a valid WP_User object, then the user logged in correctly.
|
310 |
+
*
|
311 |
+
* The flow is as follows:
|
312 |
+
* 0. If username is empty, there was no login attempt.
|
313 |
+
* 1. First we determine whether the user's login credentials were valid according to WordPress ($fUserLoginSuccess)
|
314 |
+
* 2. Then we ask our 2-factor processor whether the current IP address + username combination is authenticated.
|
315 |
+
* a) if yes, we return the WP_User object and login proceeds as per usual.
|
316 |
+
* b) if no, we return null, which will send the message back to the user that the login details were invalid.
|
317 |
+
* 3. If however the user's IP address + username combination is not authenticated, we react differently. We do not want
|
318 |
+
* to give away whether a login was successful, or even the login username details exist. So:
|
319 |
+
* 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
|
320 |
+
* 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.
|
321 |
+
* c) note at this stage, if the username was empty, we give back nothing (this happens when wp-login.php is loaded as normal.
|
322 |
+
*
|
323 |
+
* @param WP_User|string $inmUser - the docs say the first parameter a string, WP actually gives a WP_User object (or null)
|
324 |
+
* @param string $insUsername
|
325 |
+
* @param string $insPassword
|
326 |
+
* @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.
|
327 |
+
*/
|
328 |
+
public function checkUserAuthLogin_Filter( $inoUser, $insUsername, $insPassword ) {
|
329 |
+
|
330 |
+
if ( empty( $insUsername ) ) {
|
331 |
+
return $inoUser;
|
332 |
+
}
|
333 |
+
|
334 |
+
$fUserLoginSuccess = is_object( $inoUser ) && ( $inoUser instanceof WP_User );
|
335 |
+
|
336 |
+
if ( is_wp_error( $inoUser ) ) {
|
337 |
+
$aCodes = $inoUser->get_error_codes();
|
338 |
+
if ( in_array( 'wpsf_logininterval', $aCodes ) ) {
|
339 |
+
return $inoUser;
|
340 |
+
}
|
341 |
+
}
|
342 |
+
else if ( $fUserLoginSuccess ) {
|
343 |
+
|
344 |
+
$aData = array( 'wp_username' => $insUsername );
|
345 |
+
if ( $this->isUserVerified( $aData ) ) {
|
346 |
+
return $inoUser;
|
347 |
+
}
|
348 |
+
else {
|
349 |
+
// Create a new 2-factor auth pending entry
|
350 |
+
$aNewAuthData = $this->loginAuthAddPending( array( 'wp_username' => $inoUser->user_login ) );
|
351 |
+
|
352 |
+
// Now send email with authentication link for user.
|
353 |
+
if ( is_array( $aNewAuthData ) ) {
|
354 |
+
$fEmailSuccess = $this->sendEmailTwoFactorVerify( $inoUser, $aNewAuthData['ip'], $aNewAuthData['unique_id'] );
|
355 |
+
|
356 |
+
// Failure to send email - log them in.
|
357 |
+
if ( !$fEmailSuccess && $this->getTwoFactorByPassOnFail() ) {
|
358 |
+
$this->loginAuthMakeActive( $aNewAuthData );
|
359 |
+
return $inoUser;
|
360 |
+
}
|
361 |
+
}
|
362 |
+
}
|
363 |
+
}
|
364 |
+
|
365 |
+
$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.";
|
366 |
+
return new WP_Error( 'wpsf_loginauth', $sErrorString );
|
367 |
+
}
|
368 |
+
|
369 |
+
public function getGaspLoginHtml() {
|
370 |
+
|
371 |
+
$sLabel = "I'm a human.";
|
372 |
+
$sAlert = "Please check the box to show us you're a human.";
|
373 |
+
|
374 |
+
$sUniqElem = 'icwp_wpsf_login_p'.uniqid();
|
375 |
+
|
376 |
+
$sStyles = '
|
377 |
+
<style>
|
378 |
+
#'.$sUniqElem.' {
|
379 |
+
clear:both;
|
380 |
+
border: 1px solid #888;
|
381 |
+
padding: 6px 8px 4px 10px;
|
382 |
+
margin: 0 0px 12px !important;
|
383 |
+
border-radius: 2px;
|
384 |
+
background-color: #f9f9f9;
|
385 |
+
}
|
386 |
+
#'.$sUniqElem.' input {
|
387 |
+
margin-right: 5px;
|
388 |
+
}
|
389 |
+
</style>
|
390 |
+
';
|
391 |
+
|
392 |
+
$sHtml =
|
393 |
+
$sStyles.
|
394 |
+
'<p id="'.$sUniqElem.'"></p>
|
395 |
+
<script type="text/javascript">
|
396 |
+
var icwp_wpsf_login_p = document.getElementById("'.$sUniqElem.'");
|
397 |
+
var icwp_wpsf_login_cb = document.createElement("input");
|
398 |
+
var icwp_wpsf_login_text = document.createTextNode(" '.$sLabel.'");
|
399 |
+
icwp_wpsf_login_cb.type = "checkbox";
|
400 |
+
icwp_wpsf_login_cb.id = "'.$this->getGaspCheckboxName().'";
|
401 |
+
icwp_wpsf_login_cb.name = "'.$this->getGaspCheckboxName().'";
|
402 |
+
icwp_wpsf_login_p.appendChild( icwp_wpsf_login_cb );
|
403 |
+
icwp_wpsf_login_p.appendChild( icwp_wpsf_login_text );
|
404 |
+
var frm = icwp_wpsf_login_cb.form;
|
405 |
+
frm.onsubmit = icwp_wpsf_login_it;
|
406 |
+
function icwp_wpsf_login_it(){
|
407 |
+
if(icwp_wpsf_login_cb.checked != true){
|
408 |
+
alert("'.$sAlert.'");
|
409 |
+
return false;
|
410 |
+
}
|
411 |
+
return true;
|
412 |
+
}
|
413 |
+
</script>
|
414 |
+
<noscript>You MUST enable Javascript to be able to login</noscript>
|
415 |
+
<input type="hidden" id="icwp_wpsf_login_email" name="icwp_wpsf_login_email" value="" />
|
416 |
+
';
|
417 |
+
|
418 |
+
return $sHtml;
|
419 |
+
}
|
420 |
+
|
421 |
+
public function getGaspCheckboxName() {
|
422 |
+
if ( empty( $this->m_sGaspKey ) ) {
|
423 |
+
$this->m_sGaspKey = uniqid();
|
424 |
+
}
|
425 |
+
return "icwp_wpsf_$this->m_sGaspKey";
|
426 |
+
}
|
427 |
+
|
428 |
+
public function doGaspChecks( $insUsername ) {
|
429 |
+
if ( !isset( $_POST[ $this->getGaspCheckboxName() ] ) ) {
|
430 |
+
$this->logWarning(
|
431 |
+
sprintf( 'User "%s" attempted to login but GASP checkbox was not present. Bot Perhaps? IP Address: "%s".', $insUsername, long2ip($this->m_nRequestIp) )
|
432 |
+
);
|
433 |
+
wp_die( "You must check that box to say you're not a bot." );
|
434 |
+
return false;
|
435 |
+
}
|
436 |
+
else if ( isset( $_POST['icwp_wpsf_login_email'] ) && $_POST['icwp_wpsf_login_email'] !== '' ){
|
437 |
+
$this->logWarning(
|
438 |
+
sprintf( 'User "%s" attempted to login but they were caught by the GASP honey pot. Bot Perhaps? IP Address: "%s".', $insUsername, long2ip($this->m_nRequestIp) )
|
439 |
+
);
|
440 |
+
wp_die( 'You smell like a bot.' );
|
441 |
+
return false;
|
442 |
+
}
|
443 |
+
return true;
|
444 |
+
}
|
445 |
+
|
446 |
+
public function setTwoFactorByPassOnFail() {
|
447 |
+
$this->m_fAllowTwoFactorByPass = $this->m_aOptions[ 'enable_two_factor_bypass_on_email_fail' ] == 'Y';
|
448 |
+
}
|
449 |
+
|
450 |
+
public function getTwoFactorByPassOnFail() {
|
451 |
+
if ( !isset( $this->m_fAllowTwoFactorByPass ) ) {
|
452 |
+
$this->m_fAllowTwoFactorByPass = false;
|
453 |
+
}
|
454 |
+
return $this->m_fAllowTwoFactorByPass;
|
455 |
+
}
|
456 |
+
|
457 |
+
public function setLoginCooldownInterval() {
|
458 |
+
$nInterval = intval( $this->m_aOptions[ 'login_limit_interval' ] );
|
459 |
+
$this->m_nRequiredLoginInterval = ( $nInterval < 0 )? 0 : $nInterval;
|
460 |
+
}
|
461 |
+
|
462 |
+
/**
|
463 |
+
* @param array $inaData
|
464 |
+
* @return boolean
|
465 |
+
*/
|
466 |
+
public function loginAuthAddPending( $inaData ) {
|
467 |
+
|
468 |
+
$aChecks = array( 'wp_username' );
|
469 |
+
if ( !$this->validateParameters( $inaData, $aChecks) ) {
|
470 |
+
return false;
|
471 |
+
}
|
472 |
+
|
473 |
+
$sNow = time();
|
474 |
+
|
475 |
+
// First set any other pending entries for the given user to be deleted.
|
476 |
+
$aOldData = array(
|
477 |
+
'deleted_at' => $sNow,
|
478 |
+
'expired_at' => $sNow,
|
479 |
+
);
|
480 |
+
$aOldWhere = array(
|
481 |
+
'pending' => 1,
|
482 |
+
'deleted_at' => 0,
|
483 |
+
'wp_username' => $inaData[ 'wp_username' ]
|
484 |
+
);
|
485 |
+
$this->updateRowsFromTable( $aOldData, $aOldWhere );
|
486 |
+
|
487 |
+
// Now add new pending entry
|
488 |
+
$inaData[ 'unique_id' ] = uniqid();
|
489 |
+
$inaData[ 'ip_long' ] = $this->m_nRequestIp;
|
490 |
+
$inaData[ 'ip' ] = long2ip( $this->m_nRequestIp );
|
491 |
+
$inaData[ 'pending' ] = 1;
|
492 |
+
$inaData[ 'created_at' ] = time();
|
493 |
+
|
494 |
+
$mResult = $this->insertIntoTable( $inaData );
|
495 |
+
if ( $mResult ) {
|
496 |
+
$this->logInfo(
|
497 |
+
sprintf( 'User "%s" created a pending Two-Factor Authentication for IP Address "%s".', $inaData[ 'wp_username' ], $inaData[ 'ip' ] )
|
498 |
+
);
|
499 |
+
$mResult = $inaData;
|
500 |
+
}
|
501 |
+
return $mResult;
|
502 |
+
}
|
503 |
+
|
504 |
+
/**
|
505 |
+
* Given a unique Id and a corresponding WordPress username, will update the authentication table so that it is active (pending=0).
|
506 |
+
*
|
507 |
+
* @param array $inaWhere - unique_id, wp_username
|
508 |
+
* @return boolean
|
509 |
+
*/
|
510 |
+
public function loginAuthMakeActive( $inaWhere ) {
|
511 |
+
|
512 |
+
$aChecks = array( 'unique_id', 'wp_username' );
|
513 |
+
if ( !$this->validateParameters( $inaWhere, $aChecks ) ) {
|
514 |
+
return false;
|
515 |
+
}
|
516 |
+
|
517 |
+
$sNow = time();
|
518 |
+
|
519 |
+
// First set any active, non-pending entries for the given user to be deleted.
|
520 |
+
$sQuery = "
|
521 |
+
UPDATE `%s`
|
522 |
+
SET `deleted_at` = '%s',
|
523 |
+
`expired_at` = '%s'
|
524 |
+
WHERE
|
525 |
+
`wp_username` = '%s'
|
526 |
+
AND `deleted_at` = '0'
|
527 |
+
AND `pending` = '0'
|
528 |
+
";
|
529 |
+
$sQuery = sprintf( $sQuery,
|
530 |
+
$this->m_sTableName,
|
531 |
+
$sNow,
|
532 |
+
$sNow,
|
533 |
+
$inaWhere['wp_username']
|
534 |
+
);
|
535 |
+
$this->doSql( $sQuery );
|
536 |
+
|
537 |
+
$inaWhere['pending'] = 1;
|
538 |
+
$inaWhere['deleted_at'] = 0;
|
539 |
+
|
540 |
+
// Now activate the new one.
|
541 |
+
$mResult = $this->updateRowsFromTable( array( 'pending' => 0 ), $inaWhere );
|
542 |
+
if ( $mResult ) {
|
543 |
+
$this->logInfo(
|
544 |
+
sprintf( 'User "%s" has verified their IP Address using Two-Factor Authentication.', $inaWhere[ 'wp_username' ] )
|
545 |
+
);
|
546 |
+
}
|
547 |
+
return $mResult;
|
548 |
+
}
|
549 |
+
|
550 |
+
/**
|
551 |
+
* Checks whether a given user is authenticated.
|
552 |
+
*
|
553 |
+
* @param array $inaWhere
|
554 |
+
* @return boolean
|
555 |
+
*/
|
556 |
+
public function isUserVerified( $inaWhere ) {
|
557 |
+
|
558 |
+
$aChecks = array( 'wp_username' );
|
559 |
+
if ( !$this->validateParameters( $inaWhere, $aChecks ) ) {
|
560 |
+
return false;
|
561 |
+
}
|
562 |
+
|
563 |
+
$sQuery = "
|
564 |
+
SELECT *
|
565 |
+
FROM `%s`
|
566 |
+
WHERE
|
567 |
+
`wp_username` = '%s'
|
568 |
+
AND `ip_long` = '%s'
|
569 |
+
AND `pending` = '0'
|
570 |
+
AND `deleted_at` = '0'
|
571 |
+
AND `expired_at` = '0'
|
572 |
+
";
|
573 |
+
$sQuery = sprintf( $sQuery,
|
574 |
+
$this->m_sTableName,
|
575 |
+
$inaWhere['wp_username'],
|
576 |
+
$this->m_nRequestIp
|
577 |
+
);
|
578 |
+
|
579 |
+
$mResult = $this->selectCustomFromTable( $sQuery );
|
580 |
+
if ( is_array( $mResult ) && count( $mResult ) == 1 ) {
|
581 |
+
return true;
|
582 |
+
}
|
583 |
+
else {
|
584 |
+
$this->logWarning(
|
585 |
+
sprintf( 'User "%s" was found to be un-verified at this given IP Address "%s".', $inaWhere[ 'wp_username' ], long2ip( $this->m_nRequestIp ) )
|
586 |
+
);
|
587 |
+
return false;
|
588 |
+
}
|
589 |
+
}
|
590 |
+
|
591 |
+
public function verifyCurrentUser() {
|
592 |
+
$oUser = wp_get_current_user();
|
593 |
+
if ( is_object( $oUser ) && $oUser instanceof WP_User ) {
|
594 |
+
|
595 |
+
$aData = array( 'wp_username' => $oUser->user_login );
|
596 |
+
if ( !$this->isUserVerified( $aData ) ) {
|
597 |
+
$this->logWarning(
|
598 |
+
sprintf( 'User "%s" was logged out.', $oUser->user_login )
|
599 |
+
);
|
600 |
+
wp_logout();
|
601 |
+
$this->redirectToLogin();
|
602 |
+
}
|
603 |
+
}
|
604 |
+
}
|
605 |
+
|
606 |
+
/**
|
607 |
+
* Given the necessary components, creates the 2-factor verification link for giving to the user.
|
608 |
+
*
|
609 |
+
* @param string $insKey
|
610 |
+
* @param string $insUser
|
611 |
+
* @param string $insUniqueId
|
612 |
+
* @return string
|
613 |
+
*/
|
614 |
+
public function getTwoFactorVerifyLink( $insKey, $insUser, $insUniqueId ) {
|
615 |
+
$sSiteUrl = home_url() . '?wpsfkey=%s&wpsf-action=%s&username=%s&uniqueid=%s';
|
616 |
+
$sAction = 'linkauth';
|
617 |
+
return sprintf( $sSiteUrl, $insKey, $sAction, $insUser, $insUniqueId );
|
618 |
+
}
|
619 |
+
|
620 |
+
/**
|
621 |
+
* @param string $sEmail
|
622 |
+
* @param string $insIpAddress
|
623 |
+
* @param string $insAuthLink
|
624 |
+
*/
|
625 |
+
public function sendEmailTwoFactorVerify( WP_User $inoUser, $insIpAddress, $insUniqueId ) {
|
626 |
+
|
627 |
+
$sEmail = $inoUser->user_email;
|
628 |
+
$sAuthLink = $this->getTwoFactorVerifyLink( $this->m_sSecretKey, $inoUser->user_login, $insUniqueId );
|
629 |
+
|
630 |
+
$aMessage = array(
|
631 |
+
'You, or someone pretending to be you, just attempted to login into your WordPress site.',
|
632 |
+
'The IP Address from which they tried to login is not currently valid.',
|
633 |
+
'To validate this address, click the following link, and then login again.',
|
634 |
+
'IP Address: '. $insIpAddress,
|
635 |
+
'Authentication Link: '. $sAuthLink
|
636 |
+
);
|
637 |
+
$sEmailSubject = 'Two-Factor Login Verification: ' . home_url();
|
638 |
+
|
639 |
+
$fResult = $this->sendEmailTo( $sEmail, $sEmailSubject, $aMessage );
|
640 |
+
if ( $fResult ) {
|
641 |
+
$this->logInfo(
|
642 |
+
sprintf( 'User "%s" was sent an email to verify their Two-Factor Login for IP Address "%s".', $inoUser->user_login, $insIpAddress )
|
643 |
+
);
|
644 |
+
}
|
645 |
+
else {
|
646 |
+
$this->logCritical(
|
647 |
+
sprintf( 'Tried to send User "%s" email to verify their Two-Factor Login for IP Address "%s", but email sending failed.', $inoUser->user_login, $insIpAddress )
|
648 |
+
);
|
649 |
+
}
|
650 |
+
return $fResult;
|
651 |
+
}
|
652 |
+
|
653 |
+
public function createTable() {
|
654 |
+
|
655 |
+
// Set up login processor table
|
656 |
+
$sSqlTables = "CREATE TABLE IF NOT EXISTS `%s` (
|
657 |
+
`id` int(11) NOT NULL AUTO_INCREMENT,
|
658 |
+
`unique_id` varchar(20) NOT NULL DEFAULT '',
|
659 |
+
`wp_username` varchar(255) NOT NULL DEFAULT '',
|
660 |
+
`ip` varchar(20) NOT NULL DEFAULT '',
|
661 |
+
`ip_long` bigint(20) NOT NULL DEFAULT '0',
|
662 |
+
`pending` int(1) NOT NULL DEFAULT '0',
|
663 |
+
`created_at` int(15) NOT NULL DEFAULT '0',
|
664 |
+
`deleted_at` int(15) NOT NULL DEFAULT '0',
|
665 |
+
`expired_at` int(15) NOT NULL DEFAULT '0',
|
666 |
+
PRIMARY KEY (`id`)
|
667 |
+
) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
|
668 |
+
$sSqlTables = sprintf( $sSqlTables, $this->m_sTableName );
|
669 |
+
$mResult = $this->doSql( $sSqlTables );
|
670 |
+
}
|
671 |
+
|
672 |
+
/**
|
673 |
+
* Assumes that unique_id AND wp_username have been set correctly in the data array (no checking done).
|
674 |
+
*
|
675 |
+
* @param array $inaData
|
676 |
+
* @return array
|
677 |
+
*/
|
678 |
+
protected function getLoginAuthData( $inaData ) {
|
679 |
+
|
680 |
+
$sQuery = "SELECT * FROM %s WHERE `unique_id` = `%s` AND `wp_username` = %s";
|
681 |
+
$sQuery = sprintf( $sQuery, $this->m_sTableName, $inaData['unique_id'], $inaData['wp_username'] );
|
682 |
+
return $this->selectRowFromTable( $sQuery );
|
683 |
+
}
|
684 |
+
}
|
685 |
+
|
686 |
+
endif;
|
src/icwp-wpfilesystem.php
ADDED
@@ -0,0 +1,193 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2013 iControlWP <support@icontrolwp.com>
|
4 |
+
* All rights reserved.
|
5 |
+
*
|
6 |
+
* Version: 2013-09-13_A
|
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 |
+
if ( !class_exists('ICWP_WpFilesystem_WPSF') ):
|
21 |
+
|
22 |
+
class ICWP_WpFilesystem_WPSF {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var object
|
26 |
+
*/
|
27 |
+
protected $m_oWpFilesystem = null;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @var string
|
31 |
+
*/
|
32 |
+
protected $m_sWpConfigPath = null;
|
33 |
+
|
34 |
+
public function __construct() {
|
35 |
+
$this->initFileSystem();
|
36 |
+
$this->setWpConfigPath();
|
37 |
+
}
|
38 |
+
|
39 |
+
protected function setWpConfigPath() {
|
40 |
+
$this->m_sWpConfigPath = ABSPATH.'wp-config.php';
|
41 |
+
if ( !is_file($this->m_sWpConfigPath) ) {
|
42 |
+
$this->m_sWpConfigPath = ABSPATH.'..'.ICWP_DS.'wp-config.php';
|
43 |
+
if ( !is_file($this->m_sWpConfigPath) ) {
|
44 |
+
$this->m_sWpConfigPath = false;
|
45 |
+
}
|
46 |
+
}
|
47 |
+
}
|
48 |
+
|
49 |
+
protected function initFileSystem() {
|
50 |
+
if ( is_null( $this->m_oWpFilesystem ) ) {
|
51 |
+
require_once(ABSPATH . 'wp-admin/includes/file.php');
|
52 |
+
WP_Filesystem();
|
53 |
+
global $wp_filesystem;
|
54 |
+
if ( isset( $wp_filesystem ) && is_object( $wp_filesystem ) ) {
|
55 |
+
$this->m_oWpFilesystem = &$wp_filesystem;
|
56 |
+
}
|
57 |
+
else {
|
58 |
+
$this->m_oWpFilesystem = false;
|
59 |
+
}
|
60 |
+
}
|
61 |
+
}
|
62 |
+
|
63 |
+
public function getContent_WpConfig() {
|
64 |
+
return $this->getFileContent( $this->m_sWpConfigPath );
|
65 |
+
}
|
66 |
+
|
67 |
+
public function putContent_WpConfig( $insContent ) {
|
68 |
+
return $this->putFileContent( $this->m_sWpConfigPath, $insContent );
|
69 |
+
}
|
70 |
+
|
71 |
+
|
72 |
+
/**
|
73 |
+
* @return string
|
74 |
+
*/
|
75 |
+
public function getWpConfigPath() {
|
76 |
+
return $this->m_sWpConfigPath;
|
77 |
+
}
|
78 |
+
|
79 |
+
public function getUrl( $insUrl ) {
|
80 |
+
$mResult = wp_remote_get( $insUrl );
|
81 |
+
if ( is_wp_error( $mResult ) ) {
|
82 |
+
return false;
|
83 |
+
}
|
84 |
+
if ( !isset( $mResult['response']['code'] ) || $mResult['response']['code'] != 200 ) {
|
85 |
+
return false;
|
86 |
+
}
|
87 |
+
return $mResult;
|
88 |
+
}
|
89 |
+
|
90 |
+
public function getUrlContent( $insUrl ) {
|
91 |
+
|
92 |
+
$aResponse = $this->getUrl( $insUrl );
|
93 |
+
if ( !$aResponse ) {
|
94 |
+
return false;
|
95 |
+
}
|
96 |
+
return $aResponse['body'];
|
97 |
+
}
|
98 |
+
|
99 |
+
public function getCanWpRemoteGet() {
|
100 |
+
$aUrlsToTest = array(
|
101 |
+
'https://www.microsoft.com',
|
102 |
+
'https://www.google.com',
|
103 |
+
'https://www.facebook.com'
|
104 |
+
);
|
105 |
+
foreach( $aUrlsToTest as $sUrl ) {
|
106 |
+
if ( $this->getUrl( $sUrl ) !== false ) {
|
107 |
+
return true;
|
108 |
+
}
|
109 |
+
}
|
110 |
+
return false;
|
111 |
+
}
|
112 |
+
|
113 |
+
public function getCanDiskWrite() {
|
114 |
+
$sFilePath = dirname( __FILE__ ).'/testfile.'.rand().'txt';
|
115 |
+
$sContents = "Testing icwp file read and write.";
|
116 |
+
|
117 |
+
// Write, read, verify, delete.
|
118 |
+
if ( $this->putFileContent( $sFilePath, $sContents ) ) {
|
119 |
+
$sFileContents = $this->getFileContent( $sFilePath );
|
120 |
+
if ( !is_null( $sFileContents ) && $sFileContents === $sContents ) {
|
121 |
+
return $this->deleteFile( $sFilePath );
|
122 |
+
}
|
123 |
+
}
|
124 |
+
return false;
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* @param string $insFilePath
|
129 |
+
* @return NULL|boolean
|
130 |
+
*/
|
131 |
+
public function getCanReadWriteFile( $insFilePath ) {
|
132 |
+
if ( !file_exists( $insFilePath ) ) {
|
133 |
+
return null;
|
134 |
+
}
|
135 |
+
|
136 |
+
$nFileSize = filesize( $insFilePath );
|
137 |
+
if ( $nFileSize === 0 ) {
|
138 |
+
return null;
|
139 |
+
}
|
140 |
+
|
141 |
+
$sFileContent = $this->getFileContent( $insFilePath );
|
142 |
+
if ( empty( $sFileContent ) ) {
|
143 |
+
return false; //can't even read the file!
|
144 |
+
}
|
145 |
+
return $this->putFileContent( $insFilePath, $sFileContent );
|
146 |
+
}
|
147 |
+
|
148 |
+
/**
|
149 |
+
* @return string|null
|
150 |
+
*/
|
151 |
+
public function getFileContent( $insFilePath ) {
|
152 |
+
if ( !file_exists( $insFilePath ) ) {
|
153 |
+
return null;
|
154 |
+
}
|
155 |
+
if ( $this->m_oWpFilesystem ) {
|
156 |
+
return $this->m_oWpFilesystem->get_contents( $insFilePath );
|
157 |
+
}
|
158 |
+
else if ( function_exists('file_get_contents') ) {
|
159 |
+
return file_get_contents( $insFilePath );
|
160 |
+
}
|
161 |
+
return null;
|
162 |
+
}
|
163 |
+
|
164 |
+
/**
|
165 |
+
* @return boolean
|
166 |
+
*/
|
167 |
+
public function putFileContent( $insFilePath, $insContents ) {
|
168 |
+
if ( $this->m_oWpFilesystem ) {
|
169 |
+
return $this->m_oWpFilesystem->put_contents( $insFilePath, $insContents, FS_CHMOD_FILE );
|
170 |
+
}
|
171 |
+
else if ( file_put_contents( $insFilePath, $insContents ) === false ) {
|
172 |
+
return false;
|
173 |
+
}
|
174 |
+
return true;
|
175 |
+
}
|
176 |
+
|
177 |
+
/**
|
178 |
+
* @return boolean
|
179 |
+
*/
|
180 |
+
public function deleteFile( $insFilePath ) {
|
181 |
+
if ( !file_exists( $insFilePath ) ) {
|
182 |
+
return null;
|
183 |
+
}
|
184 |
+
if ( $this->m_oWpFilesystem ) {
|
185 |
+
return $this->m_oWpFilesystem->delete( $insFilePath );
|
186 |
+
}
|
187 |
+
else {
|
188 |
+
return unlink( $insFilePath );
|
189 |
+
}
|
190 |
+
}
|
191 |
+
}
|
192 |
+
|
193 |
+
endif;
|
src/icwp-wpfunctions.php
ADDED
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2013 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
|
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 |
+
if ( !class_exists('ICWP_WpFunctions_WPSF') ):
|
21 |
+
|
22 |
+
class ICWP_WpFunctions_WPSF {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var string
|
26 |
+
*/
|
27 |
+
protected $m_sWpVersion;
|
28 |
+
|
29 |
+
public function __construct() {}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* @param string $insPluginFile
|
33 |
+
* @return boolean|stdClass
|
34 |
+
*/
|
35 |
+
public function getIsPluginUpdateAvailable( $insPluginFile ) {
|
36 |
+
$aUpdates = $this->getWordpressUpdates();
|
37 |
+
if ( empty( $aUpdates ) ) {
|
38 |
+
return false;
|
39 |
+
}
|
40 |
+
if ( isset( $aUpdates[ $insPluginFile ] ) ) {
|
41 |
+
return $aUpdates[ $insPluginFile ];
|
42 |
+
}
|
43 |
+
return false;
|
44 |
+
}
|
45 |
+
|
46 |
+
public function getPluginUpgradeLink( $insPluginFile ) {
|
47 |
+
$sUrl = self_admin_url( 'update.php' ) ;
|
48 |
+
$aQueryArgs = array(
|
49 |
+
'action' => 'upgrade-plugin',
|
50 |
+
'plugin' => urlencode( $insPluginFile ),
|
51 |
+
'_wpnonce' => wp_create_nonce( 'upgrade-plugin_' . $insPluginFile )
|
52 |
+
);
|
53 |
+
return add_query_arg( $aQueryArgs, $sUrl );
|
54 |
+
}
|
55 |
+
|
56 |
+
public function getWordpressUpdates() {
|
57 |
+
$oCurrent = $this->getTransient( 'update_plugins' );
|
58 |
+
return $oCurrent->response;
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* The full plugin file to be upgraded.
|
63 |
+
*
|
64 |
+
* @param string $insPluginFile
|
65 |
+
* @return boolean
|
66 |
+
*/
|
67 |
+
public function doPluginUpgrade( $insPluginFile ) {
|
68 |
+
|
69 |
+
if ( !$this->getIsPluginUpdateAvailable($insPluginFile)
|
70 |
+
|| ( isset( $GLOBALS['pagenow'] ) && $GLOBALS['pagenow'] == 'update.php' ) ) {
|
71 |
+
return true;
|
72 |
+
}
|
73 |
+
$sUrl = $this->getPluginUpgradeLink( $insPluginFile );
|
74 |
+
wp_redirect( $sUrl );
|
75 |
+
exit();
|
76 |
+
}
|
77 |
+
/**
|
78 |
+
* @param string $insKey
|
79 |
+
* @return object
|
80 |
+
*/
|
81 |
+
protected function getTransient( $insKey ) {
|
82 |
+
|
83 |
+
// TODO: Handle multisite
|
84 |
+
|
85 |
+
if ( version_compare( $this->getWordPressVersion(), '2.7.9', '<=' ) ) {
|
86 |
+
return get_option( $insKey );
|
87 |
+
}
|
88 |
+
|
89 |
+
if ( function_exists( 'get_site_transient' ) ) {
|
90 |
+
return get_site_transient( $insKey );
|
91 |
+
}
|
92 |
+
|
93 |
+
if ( version_compare( $this->getWordPressVersion(), '2.9.9', '<=' ) ) {
|
94 |
+
return apply_filters( 'transient_'.$insKey, get_option( '_transient_'.$insKey ) );
|
95 |
+
}
|
96 |
+
|
97 |
+
return apply_filters( 'site_transient_'.$insKey, get_option( '_site_transient_'.$insKey ) );
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* @return string
|
102 |
+
*/
|
103 |
+
public function getWordPressVersion() {
|
104 |
+
global $wp_version;
|
105 |
+
|
106 |
+
if ( empty( $this->m_sWpVersion ) ) {
|
107 |
+
$sVersionFile = ABSPATH.WPINC.'/version.php';
|
108 |
+
$sVersionContents = file_get_contents( $sVersionFile );
|
109 |
+
|
110 |
+
if ( preg_match( '/wp_version\s=\s\'([^(\'|")]+)\'/i', $sVersionContents, $aMatches ) ) {
|
111 |
+
$this->m_sWpVersion = $aMatches[1];
|
112 |
+
}
|
113 |
+
}
|
114 |
+
return $this->m_sWpVersion;
|
115 |
+
}
|
116 |
+
}
|
117 |
+
|
118 |
+
endif;
|
views/icwp_options_helper.php
CHANGED
@@ -1,5 +1,19 @@
|
|
1 |
<?php
|
2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
function printAllPluginOptionsForm( $inaAllPluginOptions, $insVarPrefix = '', $iOptionsPerRow = 1 ) {
|
4 |
|
5 |
if ( empty($inaAllPluginOptions) ) {
|
@@ -96,7 +110,8 @@ function getPluginOptionSpan( $inaOption, $iSpanSize, $insVarPrefix = '' ) {
|
|
96 |
|
97 |
$sOptionHelpText = '<p class="help-block">'.$sOptionHelpText.'</p>';
|
98 |
|
99 |
-
}
|
|
|
100 |
$sTextInput = esc_attr( $sOptionSaved );
|
101 |
$sHtml .= '
|
102 |
<p>'.$sOptionTitle.'</p>
|
@@ -109,7 +124,35 @@ function getPluginOptionSpan( $inaOption, $iSpanSize, $insVarPrefix = '' ) {
|
|
109 |
|
110 |
$sOptionHelpText = '<p class="help-block">'.$sOptionHelpText.'</p>';
|
111 |
|
112 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
113 |
|
114 |
$sInputType = array_shift($mOptionType);
|
115 |
|
@@ -131,7 +174,23 @@ function getPluginOptionSpan( $inaOption, $iSpanSize, $insVarPrefix = '' ) {
|
|
131 |
|
132 |
$sOptionHelpText = '<p class="help-block">'.$sOptionHelpText.'</p>';
|
133 |
|
134 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
135 |
$sTextInput = esc_attr( $sOptionSaved );
|
136 |
$nRows = substr_count( $sTextInput, "\n" ) + 1;
|
137 |
$sHtml .= '
|
@@ -144,7 +203,21 @@ function getPluginOptionSpan( $inaOption, $iSpanSize, $insVarPrefix = '' ) {
|
|
144 |
class="span5">'.$sTextInput.'</textarea>';
|
145 |
|
146 |
$sOptionHelpText = '<p class="help-block">'.$sOptionHelpText.'</p>';
|
147 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
148 |
$sHtml .= 'we should never reach this point';
|
149 |
}
|
150 |
|
1 |
<?php
|
2 |
|
3 |
+
function printOptionsPageHeader( $insSection = '' ) {
|
4 |
+
$sLinkedIcwp = '<a href="http://icwp.io/3a" target="_blank">iControlWP</a>';
|
5 |
+
echo '<div class="page-header">';
|
6 |
+
echo '<a href="http://icwp.io/2k" target="_blank"><div class="icon32" id="icontrolwp-icon"><br /></div></a>';
|
7 |
+
echo '<h2>';
|
8 |
+
if ( !empty($insSection) ) {
|
9 |
+
echo sprintf( _hlt__( '%s :: WordPress Simple Firewall (from %s)'), $insSection, $sLinkedIcwp );
|
10 |
+
}
|
11 |
+
else {
|
12 |
+
echo sprintf( _hlt__( 'WordPress Simple Firewall (from %s)'), $sLinkedIcwp );
|
13 |
+
}
|
14 |
+
echo '</h2></div>';
|
15 |
+
}
|
16 |
+
|
17 |
function printAllPluginOptionsForm( $inaAllPluginOptions, $insVarPrefix = '', $iOptionsPerRow = 1 ) {
|
18 |
|
19 |
if ( empty($inaAllPluginOptions) ) {
|
110 |
|
111 |
$sOptionHelpText = '<p class="help-block">'.$sOptionHelpText.'</p>';
|
112 |
|
113 |
+
}
|
114 |
+
else if ( $mOptionType === 'text' ) {
|
115 |
$sTextInput = esc_attr( $sOptionSaved );
|
116 |
$sHtml .= '
|
117 |
<p>'.$sOptionTitle.'</p>
|
124 |
|
125 |
$sOptionHelpText = '<p class="help-block">'.$sOptionHelpText.'</p>';
|
126 |
|
127 |
+
}
|
128 |
+
else if ( $mOptionType === 'password' ) {
|
129 |
+
$sTextInput = esc_attr( $sOptionSaved );
|
130 |
+
$sHtml .= '
|
131 |
+
<p>'.$sOptionTitle.'</p>
|
132 |
+
<input type="password"
|
133 |
+
name="'.$insVarPrefix.$sOptionKey.'"
|
134 |
+
value="'.$sTextInput.'"
|
135 |
+
placeholder="'.$sTextInput.'"
|
136 |
+
id="'.$insVarPrefix.$sOptionKey.'"
|
137 |
+
class="span5" />';
|
138 |
+
|
139 |
+
$sOptionHelpText = '<p class="help-block">'.$sOptionHelpText.'</p>';
|
140 |
+
}
|
141 |
+
else if ( $mOptionType === 'email' ) {
|
142 |
+
$sTextInput = esc_attr( $sOptionSaved );
|
143 |
+
$sHtml .= '
|
144 |
+
<p>'.$sOptionTitle.'</p>
|
145 |
+
<input type="text"
|
146 |
+
name="'.$insVarPrefix.$sOptionKey.'"
|
147 |
+
value="'.$sTextInput.'"
|
148 |
+
placeholder="'.$sTextInput.'"
|
149 |
+
id="'.$insVarPrefix.$sOptionKey.'"
|
150 |
+
class="span5" />';
|
151 |
+
|
152 |
+
$sOptionHelpText = '<p class="help-block">'.$sOptionHelpText.'</p>';
|
153 |
+
|
154 |
+
}
|
155 |
+
else if ( is_array($mOptionType) ) { //it's a select, or radio
|
156 |
|
157 |
$sInputType = array_shift($mOptionType);
|
158 |
|
174 |
|
175 |
$sOptionHelpText = '<p class="help-block">'.$sOptionHelpText.'</p>';
|
176 |
|
177 |
+
}
|
178 |
+
else if ( $mOptionType === 'ip_addresses' ) {
|
179 |
+
$sTextInput = esc_attr( $sOptionSaved );
|
180 |
+
$nRows = substr_count( $sTextInput, "\n" ) + 1;
|
181 |
+
$sHtml .= '
|
182 |
+
<p>'.$sOptionTitle.'</p>
|
183 |
+
<textarea type="text"
|
184 |
+
name="'.$insVarPrefix.$sOptionKey.'"
|
185 |
+
placeholder="'.$sTextInput.'"
|
186 |
+
id="'.$insVarPrefix.$sOptionKey.'"
|
187 |
+
rows="'.$nRows.'"
|
188 |
+
class="span5">'.$sTextInput.'</textarea>';
|
189 |
+
|
190 |
+
$sOptionHelpText = '<p class="help-block">'.$sOptionHelpText.'</p>';
|
191 |
+
|
192 |
+
}
|
193 |
+
else if ( $mOptionType === 'comma_separated_lists' ) {
|
194 |
$sTextInput = esc_attr( $sOptionSaved );
|
195 |
$nRows = substr_count( $sTextInput, "\n" ) + 1;
|
196 |
$sHtml .= '
|
203 |
class="span5">'.$sTextInput.'</textarea>';
|
204 |
|
205 |
$sOptionHelpText = '<p class="help-block">'.$sOptionHelpText.'</p>';
|
206 |
+
}
|
207 |
+
else if ( $mOptionType === 'integer' ) {
|
208 |
+
$sTextInput = esc_attr( $sOptionSaved );
|
209 |
+
$sHtml .= '
|
210 |
+
<p>'.$sOptionTitle.'</p>
|
211 |
+
<input type="text"
|
212 |
+
name="'.$insVarPrefix.$sOptionKey.'"
|
213 |
+
value="'.$sTextInput.'"
|
214 |
+
placeholder="'.$sTextInput.'"
|
215 |
+
id="'.$insVarPrefix.$sOptionKey.'"
|
216 |
+
class="span5" />';
|
217 |
+
|
218 |
+
$sOptionHelpText = '<p class="help-block">'.$sOptionHelpText.'</p>';
|
219 |
+
}
|
220 |
+
else {
|
221 |
$sHtml .= 'we should never reach this point';
|
222 |
}
|
223 |
|
views/icwp_wpsf_access_key_request_index.php
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
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 |
+
$sPluginName = 'WordPress Simple Firewall';
|
5 |
+
$fFirewallOn = $icwp_aMainOptions['enable_firewall'] == 'Y';
|
6 |
+
$fLoginProtectOn = $icwp_aMainOptions['enable_login_protect'] == 'Y';
|
7 |
+
$fCommentsFilteringOn = $icwp_aMainOptions['enable_comments_filter'] == 'Y';
|
8 |
+
?>
|
9 |
+
|
10 |
+
<div class="wrap">
|
11 |
+
<div class="bootstrap-wpadmin">
|
12 |
+
<?php echo printOptionsPageHeader( 'Admin Access Restriction' ); ?>
|
13 |
+
<div class="row">
|
14 |
+
<div class="span9">
|
15 |
+
<?php
|
16 |
+
if ( isset( $_COOKIE[ 'TODOcookie-name' ] ) ) { //the user hasn't created an encryption salt
|
17 |
+
?>
|
18 |
+
<div class="alert alert-info">
|
19 |
+
<p>You are currently authorized to access your cPanel Manager functions with this plugin.</p>
|
20 |
+
<p>You will be returned here once your session times out.</p>
|
21 |
+
<form method="post" action="<?php echo $worpit_form_action; ?>" class="form-horizontal">
|
22 |
+
<?php wp_nonce_field( $worpit_nonce_field ); ?>
|
23 |
+
<input type="hidden" name="cpm_form_submit" value="1" />
|
24 |
+
<button type="submit" class="btn btn-primary" name="submit_remove_access">End cPanel Manager Session Now</button>
|
25 |
+
</form>
|
26 |
+
</div>
|
27 |
+
<?php
|
28 |
+
}
|
29 |
+
else {
|
30 |
+
?>
|
31 |
+
<div class="well">
|
32 |
+
<h3>What should you enter here?</h3>
|
33 |
+
<p>At some point you supplied an <strong>Admin Access Key</strong> - to manage this plugin, you must supply it here first.</p>
|
34 |
+
</div>
|
35 |
+
<form action="<?php echo $icwp_form_action; ?>" method="post" class="form-horizontal">
|
36 |
+
<div class="control-group">
|
37 |
+
<label class="control-label" for="icwp_wpsf_admin_access_key_request">Enter Access Key<br></label>
|
38 |
+
<div class="controls">
|
39 |
+
<div class="option_section selected_item active" id="option_section_icwp_wpsf_admin_access_key">
|
40 |
+
<label>
|
41 |
+
<input type="text" name="icwp_wpsf_admin_access_key_request" value="" />
|
42 |
+
</label>
|
43 |
+
<p class="help-block">To manage this plugin you must enter the access key.</p>
|
44 |
+
</div>
|
45 |
+
</div><!-- controls -->
|
46 |
+
</div>
|
47 |
+
<div class="form-actions">
|
48 |
+
<?php wp_nonce_field( $icwp_nonce_field ); ?>
|
49 |
+
<input type="hidden" name="icwp_plugin_form_submit" value="Y" />
|
50 |
+
<button type="submit" class="btn btn-primary" name="submit"><?php _hlt_e( 'Submit Key'); ?></button>
|
51 |
+
</div>
|
52 |
+
</form>
|
53 |
+
<?php
|
54 |
+
}
|
55 |
+
?>
|
56 |
+
</div><!-- / span9 -->
|
57 |
+
<div class="span3" id="side_widgets">
|
58 |
+
<?php // echo getWidgetIframeHtml( 'cpm-side-widgets' ); ?>
|
59 |
+
</div>
|
60 |
+
</div>
|
61 |
+
|
62 |
+
</div><!-- / bootstrap-wpadmin -->
|
63 |
+
<?php include_once( dirname(__FILE__).'/include_js.php' ); ?>
|
64 |
+
</div><!-- / wrap -->
|
views/{icwp_wpsf_firewall_config_index.php → icwp_wpsf_config_autoupdates_index.php}
RENAMED
@@ -1,14 +1,10 @@
|
|
1 |
<?php
|
2 |
-
include_once( dirname(__FILE__).
|
3 |
-
include_once( dirname(__FILE__).
|
4 |
?>
|
5 |
<div class="wrap">
|
6 |
<div class="bootstrap-wpadmin">
|
7 |
-
|
8 |
-
<div class="page-header">
|
9 |
-
<a href="http://wwwicontrolwp.com/"><div class="icon32" id="icontrolwp-icon"><br /></div></a>
|
10 |
-
<h2><?php _hlt_e( 'Simple WordPress Firewall (from iControlWP)' ); ?></h2>
|
11 |
-
</div>
|
12 |
|
13 |
<div class="row">
|
14 |
<div class="<?php echo $icwp_fShowAds? 'span9' : 'span12'; ?>">
|
1 |
<?php
|
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 |
<div class="wrap">
|
6 |
<div class="bootstrap-wpadmin">
|
7 |
+
<?php echo printOptionsPageHeader( 'Auto WordPress Updates' ); ?>
|
|
|
|
|
|
|
|
|
8 |
|
9 |
<div class="row">
|
10 |
<div class="<?php echo $icwp_fShowAds? 'span9' : 'span12'; ?>">
|
views/icwp_wpsf_config_comments_filter_index.php
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
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 |
+
<div class="wrap">
|
6 |
+
<div class="bootstrap-wpadmin">
|
7 |
+
<?php echo printOptionsPageHeader( 'Comments (SPAM) Filter' ); ?>
|
8 |
+
|
9 |
+
<div class="row">
|
10 |
+
<div class="<?php echo $icwp_fShowAds? 'span9' : 'span12'; ?>">
|
11 |
+
|
12 |
+
<form action="<?php echo $icwp_form_action; ?>" method="post" class="form-horizontal">
|
13 |
+
<?php
|
14 |
+
wp_nonce_field( $icwp_nonce_field );
|
15 |
+
printAllPluginOptionsForm( $icwp_aAllOptions, $icwp_var_prefix, 1 );
|
16 |
+
?>
|
17 |
+
<div class="form-actions">
|
18 |
+
<input type="hidden" name="<?php echo $icwp_var_prefix; ?>all_options_input" value="<?php echo $icwp_all_options_input; ?>" />
|
19 |
+
<input type="hidden" name="icwp_plugin_form_submit" value="Y" />
|
20 |
+
<button type="submit" class="btn btn-primary" name="submit"><?php _hlt_e( 'Save All Settings'); ?></button>
|
21 |
+
</div>
|
22 |
+
</form>
|
23 |
+
|
24 |
+
</div><!-- / span9 -->
|
25 |
+
|
26 |
+
<?php if ( $icwp_fShowAds ) : ?>
|
27 |
+
<div class="span3" id="side_widgets">
|
28 |
+
<?php echo getWidgetIframeHtml('side-widgets-wtb'); ?>
|
29 |
+
</div>
|
30 |
+
<?php endif; ?>
|
31 |
+
</div><!-- / row -->
|
32 |
+
|
33 |
+
</div><!-- / bootstrap-wpadmin -->
|
34 |
+
<?php include_once( dirname(__FILE__).'/include_js.php' ); ?>
|
35 |
+
</div>
|
views/icwp_wpsf_config_firewall_index.php
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
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 |
+
<div class="wrap">
|
6 |
+
<div class="bootstrap-wpadmin">
|
7 |
+
<?php echo printOptionsPageHeader( 'Firewall' ); ?>
|
8 |
+
|
9 |
+
<div class="row">
|
10 |
+
<div class="<?php echo $icwp_fShowAds? 'span9' : 'span12'; ?>">
|
11 |
+
|
12 |
+
<form action="<?php echo $icwp_form_action; ?>" method="post" class="form-horizontal">
|
13 |
+
<?php
|
14 |
+
wp_nonce_field( $icwp_nonce_field );
|
15 |
+
printAllPluginOptionsForm( $icwp_aAllOptions, $icwp_var_prefix, 1 );
|
16 |
+
?>
|
17 |
+
<div class="form-actions">
|
18 |
+
<input type="hidden" name="<?php echo $icwp_var_prefix; ?>all_options_input" value="<?php echo $icwp_all_options_input; ?>" />
|
19 |
+
<input type="hidden" name="icwp_plugin_form_submit" value="Y" />
|
20 |
+
<button type="submit" class="btn btn-primary" name="submit"><?php _hlt_e( 'Save All Settings'); ?></button>
|
21 |
+
<?php if ( get_option ('WP_firewall_redirect_page') ) :?>
|
22 |
+
<button type="submit" class="btn btn-warning" name="import-wpf2-submit"><?php _hlt_e( 'Import From WordPress Firewall 2'); ?></button>
|
23 |
+
<?php endif; ?>
|
24 |
+
</div>
|
25 |
+
</form>
|
26 |
+
|
27 |
+
</div><!-- / span9 -->
|
28 |
+
|
29 |
+
<?php if ( $icwp_fShowAds ) : ?>
|
30 |
+
<div class="span3" id="side_widgets">
|
31 |
+
<?php echo getWidgetIframeHtml('side-widgets-wtb'); ?>
|
32 |
+
</div>
|
33 |
+
<?php endif; ?>
|
34 |
+
</div><!-- / row -->
|
35 |
+
|
36 |
+
</div><!-- / bootstrap-wpadmin -->
|
37 |
+
<?php include_once( dirname(__FILE__).'/include_js.php' ); ?>
|
38 |
+
</div>
|
views/icwp_wpsf_config_lockdown_index.php
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
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 |
+
<div class="wrap">
|
6 |
+
<div class="bootstrap-wpadmin">
|
7 |
+
<?php echo printOptionsPageHeader( 'Lockdown' ); ?>
|
8 |
+
|
9 |
+
<div class="row">
|
10 |
+
<div class="<?php echo $icwp_fShowAds? 'span9' : 'span12'; ?>">
|
11 |
+
|
12 |
+
<form action="<?php echo $icwp_form_action; ?>" method="post" class="form-horizontal">
|
13 |
+
<?php
|
14 |
+
wp_nonce_field( $icwp_nonce_field );
|
15 |
+
printAllPluginOptionsForm( $icwp_aAllOptions, $icwp_var_prefix, 1 );
|
16 |
+
?>
|
17 |
+
<div class="form-actions">
|
18 |
+
<input type="hidden" name="<?php echo $icwp_var_prefix; ?>all_options_input" value="<?php echo $icwp_all_options_input; ?>" />
|
19 |
+
<input type="hidden" name="icwp_plugin_form_submit" value="Y" />
|
20 |
+
<button type="submit" class="btn btn-primary" name="submit"><?php _hlt_e( 'Save All Settings'); ?></button>
|
21 |
+
</div>
|
22 |
+
</form>
|
23 |
+
|
24 |
+
</div><!-- / span9 -->
|
25 |
+
|
26 |
+
<?php if ( $icwp_fShowAds ) : ?>
|
27 |
+
<div class="span3" id="side_widgets">
|
28 |
+
<?php echo getWidgetIframeHtml('side-widgets-wtb'); ?>
|
29 |
+
</div>
|
30 |
+
<?php endif; ?>
|
31 |
+
</div><!-- / row -->
|
32 |
+
|
33 |
+
</div><!-- / bootstrap-wpadmin -->
|
34 |
+
<?php include_once( dirname(__FILE__).'/include_js.php' ); ?>
|
35 |
+
</div>
|
views/icwp_wpsf_config_login_protect_index.php
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
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 |
+
<div class="wrap">
|
6 |
+
<div class="bootstrap-wpadmin">
|
7 |
+
<?php echo printOptionsPageHeader( 'Login Protection' ); ?>
|
8 |
+
|
9 |
+
<div class="row">
|
10 |
+
<div class="<?php echo $icwp_fShowAds? 'span9' : 'span12'; ?>">
|
11 |
+
|
12 |
+
<form action="<?php echo $icwp_form_action; ?>" method="post" class="form-horizontal">
|
13 |
+
<?php
|
14 |
+
wp_nonce_field( $icwp_nonce_field );
|
15 |
+
printAllPluginOptionsForm( $icwp_aAllOptions, $icwp_var_prefix, 1 );
|
16 |
+
?>
|
17 |
+
<div class="form-actions">
|
18 |
+
<input type="hidden" name="<?php echo $icwp_var_prefix; ?>all_options_input" value="<?php echo $icwp_all_options_input; ?>" />
|
19 |
+
<input type="hidden" name="icwp_plugin_form_submit" value="Y" />
|
20 |
+
<button type="submit" class="btn btn-primary" name="submit"><?php _hlt_e( 'Save All Settings'); ?></button>
|
21 |
+
</div>
|
22 |
+
</form>
|
23 |
+
|
24 |
+
</div><!-- / span9 -->
|
25 |
+
|
26 |
+
<?php if ( $icwp_fShowAds ) : ?>
|
27 |
+
<div class="span3" id="side_widgets">
|
28 |
+
<?php echo getWidgetIframeHtml('side-widgets-wtb'); ?>
|
29 |
+
</div>
|
30 |
+
<?php endif; ?>
|
31 |
+
</div><!-- / row -->
|
32 |
+
|
33 |
+
</div><!-- / bootstrap-wpadmin -->
|
34 |
+
<?php include_once( dirname(__FILE__).'/include_js.php' ); ?>
|
35 |
+
</div>
|
views/icwp_wpsf_firewall_log_index.php
CHANGED
@@ -1,5 +1,6 @@
|
|
1 |
-
<?php
|
2 |
-
include_once( dirname(__FILE__).'
|
|
|
3 |
$sPluginName = 'WordPress Simple Firewall';
|
4 |
|
5 |
$aLogTypes = array(
|
@@ -7,7 +8,6 @@ $aLogTypes = array(
|
|
7 |
1 => 'Warning',
|
8 |
2 => 'Critical'
|
9 |
);
|
10 |
-
|
11 |
?>
|
12 |
<style>
|
13 |
tr.row-Info td {
|
@@ -18,55 +18,87 @@ $aLogTypes = array(
|
|
18 |
tr.row-Critical td {
|
19 |
background-color: #DBAFB0;
|
20 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
</style>
|
22 |
|
23 |
<div class="wrap">
|
24 |
<div class="bootstrap-wpadmin">
|
|
|
25 |
|
26 |
-
<div class="page-header">
|
27 |
-
<a href="http://icwp.io/t" target="_blank"><div class="icon32" id="icontrolwp-icon"><br /></div></a>
|
28 |
-
<h2>Firewall Log :: <?php echo $sPluginName; ?> Plugin (from iControlWP)</h2>
|
29 |
-
</div>
|
30 |
-
|
31 |
<div class="row">
|
32 |
<div class="<?php echo $icwp_fShowAds? 'span9' : 'span12'; ?>">
|
33 |
-
|
34 |
-
<?php if ( !$icwp_firewall_log ) : ?>
|
35 |
-
<?php echo 'There are currently no logs to display.'; ?>
|
36 |
-
<?php else : ?>
|
37 |
-
|
38 |
<form action="<?php echo $icwp_form_action; ?>" method="post" class="form-horizontal">
|
39 |
<?php
|
40 |
wp_nonce_field( $icwp_nonce_field );
|
41 |
?>
|
42 |
<div class="form-actions">
|
43 |
<input type="hidden" name="icwp_plugin_form_submit" value="Y" />
|
44 |
-
<button type="submit" class="btn btn-primary" name="
|
45 |
</div>
|
46 |
</form>
|
|
|
|
|
|
|
|
|
47 |
|
48 |
<table class="table table-bordered table-hover table-condensed">
|
49 |
<tr>
|
50 |
-
<th>Time</th>
|
51 |
<th>Message Type</th>
|
52 |
<th>Message</th>
|
53 |
</tr>
|
54 |
-
<?php foreach( $icwp_firewall_log as $sId => $aLogData ) :
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
</tr>
|
60 |
-
<?php
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
<
|
67 |
-
|
68 |
-
|
69 |
-
|
|
|
|
|
|
|
|
|
70 |
</table>
|
71 |
|
72 |
<?php endif; ?>
|
1 |
+
<?php
|
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 |
$sPluginName = 'WordPress Simple Firewall';
|
5 |
|
6 |
$aLogTypes = array(
|
8 |
1 => 'Warning',
|
9 |
2 => 'Critical'
|
10 |
);
|
|
|
11 |
?>
|
12 |
<style>
|
13 |
tr.row-Info td {
|
18 |
tr.row-Critical td {
|
19 |
background-color: #DBAFB0;
|
20 |
}
|
21 |
+
tr.row-log-header td {
|
22 |
+
border-top: 2px solid #999 !important;
|
23 |
+
}
|
24 |
+
td.cell-log-type {
|
25 |
+
text-align: right !important;
|
26 |
+
}
|
27 |
+
td .cell-section {
|
28 |
+
display: inline-block;
|
29 |
+
}
|
30 |
+
td .section-ip {
|
31 |
+
width: 68%;
|
32 |
+
}
|
33 |
+
td .section-timestamp {
|
34 |
+
text-align: right;
|
35 |
+
width: 28%;
|
36 |
+
}
|
37 |
</style>
|
38 |
|
39 |
<div class="wrap">
|
40 |
<div class="bootstrap-wpadmin">
|
41 |
+
<?php echo printOptionsPageHeader( 'Firewall Log' ); ?>
|
42 |
|
|
|
|
|
|
|
|
|
|
|
43 |
<div class="row">
|
44 |
<div class="<?php echo $icwp_fShowAds? 'span9' : 'span12'; ?>">
|
|
|
|
|
|
|
|
|
|
|
45 |
<form action="<?php echo $icwp_form_action; ?>" method="post" class="form-horizontal">
|
46 |
<?php
|
47 |
wp_nonce_field( $icwp_nonce_field );
|
48 |
?>
|
49 |
<div class="form-actions">
|
50 |
<input type="hidden" name="icwp_plugin_form_submit" value="Y" />
|
51 |
+
<button type="submit" class="btn btn-primary" name="clear_log_submit"><?php _hlt_e( 'Clear/Fix Log'); ?></button>
|
52 |
</div>
|
53 |
</form>
|
54 |
+
|
55 |
+
<?php if ( !$icwp_firewall_log ) : ?>
|
56 |
+
<?php echo 'There are currently no logs to display. If you expect there to be some, use the button above to Clean/Fix them.'; ?>
|
57 |
+
<?php else : ?>
|
58 |
|
59 |
<table class="table table-bordered table-hover table-condensed">
|
60 |
<tr>
|
|
|
61 |
<th>Message Type</th>
|
62 |
<th>Message</th>
|
63 |
</tr>
|
64 |
+
<?php foreach( $icwp_firewall_log as $sId => $aLogData ) : ?>
|
65 |
+
<tr class="row-log-header">
|
66 |
+
<td>IP: <strong><?php echo $aLogData['ip']; ?></strong></td>
|
67 |
+
<td colspan="2">
|
68 |
+
<span class="cell-section section-ip">
|
69 |
+
[ <a href="http://whois.domaintools.com/<?php echo $aLogData['ip']; ?>" target="_blank">IPWHOIS Lookup</a> ]
|
70 |
+
[
|
71 |
+
<?php if ( in_array( $aLogData['ip_long'], $icwp_ip_blacklist ) ) : ?>
|
72 |
+
<a href="<?php echo $icwp_form_action; ?>&unblackip=<?php echo $aLogData['ip']; ?>&_wpnonce=<?php echo wp_create_nonce($icwp_nonce_field); ?>&icwp_link_action=1">Remove From Firewall Blacklist</a>
|
73 |
+
<?php else: ?>
|
74 |
+
<a href="<?php echo $icwp_form_action; ?>&blackip=<?php echo $aLogData['ip']; ?>&_wpnonce=<?php echo wp_create_nonce($icwp_nonce_field); ?>&icwp_link_action=1">Add To Firewall Blacklist</a>
|
75 |
+
<?php endif; ?>
|
76 |
+
]
|
77 |
+
[
|
78 |
+
<?php if ( in_array( $aLogData['ip_long'], $icwp_ip_whitelist ) ) : ?>
|
79 |
+
<a href="<?php echo $icwp_form_action; ?>&unwhiteip=<?php echo $aLogData['ip']; ?>&_wpnonce=<?php echo wp_create_nonce($icwp_nonce_field); ?>&icwp_link_action=1">Remove From Firewall Whitelist</a>
|
80 |
+
<?php else: ?>
|
81 |
+
<a href="<?php echo $icwp_form_action; ?>&whiteip=<?php echo $aLogData['ip']; ?>&_wpnonce=<?php echo wp_create_nonce($icwp_nonce_field); ?>&icwp_link_action=1">Add To Firewall Whitelist</a>
|
82 |
+
<?php endif; ?>
|
83 |
+
]
|
84 |
+
</span>
|
85 |
+
<span class="cell-section section-timestamp"><?php echo date( 'Y/m/d H:i:s', $aLogData['created_at'] ); ?></span>
|
86 |
+
</td>
|
87 |
</tr>
|
88 |
+
<?php
|
89 |
+
$aMessages = unserialize( $aLogData['messages'] );
|
90 |
+
if ( is_array( $aMessages ) ) {
|
91 |
+
foreach( $aMessages as $aLogItem ) :
|
92 |
+
list( $sLogType, $sLogMessage ) = $aLogItem;
|
93 |
+
?>
|
94 |
+
<tr class="row-<?php echo $aLogTypes[$sLogType]; ?>">
|
95 |
+
<td class="cell-log-type"><?php echo $aLogTypes[$sLogType] ?></td>
|
96 |
+
<td><?php echo esc_attr($sLogMessage); ?></td>
|
97 |
+
</tr>
|
98 |
+
<?php
|
99 |
+
endforeach;
|
100 |
+
}
|
101 |
+
endforeach; ?>
|
102 |
</table>
|
103 |
|
104 |
<?php endif; ?>
|
views/icwp_wpsf_index.php
CHANGED
@@ -1,17 +1,42 @@
|
|
1 |
<?php
|
2 |
-
include_once( dirname(__FILE__).'
|
|
|
3 |
$sPluginName = 'WordPress Simple Firewall';
|
|
|
|
|
|
|
|
|
4 |
?>
|
5 |
|
6 |
<div class="wrap">
|
7 |
<div class="bootstrap-wpadmin">
|
8 |
-
|
9 |
-
<div class="page-header">
|
10 |
-
<a href="http://icwp.io/t" target="_blank"><div class="icon32" id="icontrolwp-icon"><br /></div></a>
|
11 |
-
<h2>Dashboard :: <?php echo $sPluginName; ?> Plugin (from iControlWP)</h2>
|
12 |
-
</div>
|
13 |
|
14 |
<?php include_once( dirname(__FILE__).'/widgets/icwp_common_widgets.php' ); ?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
|
16 |
<?php if ( $icwp_fShowAds ) : ?>
|
17 |
<div class="row" id="worpit_promo">
|
@@ -29,27 +54,28 @@ $sPluginName = 'WordPress Simple Firewall';
|
|
29 |
<?php endif; ?>
|
30 |
|
31 |
<div class="row" id="tbs_docs">
|
32 |
-
|
|
|
33 |
<div class="well">
|
34 |
-
<h3>
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
<?php else: ?>
|
40 |
-
|
41 |
<ul>
|
42 |
-
<li>Firewall is: <?php echo $
|
43 |
-
<li>
|
44 |
-
<li>When the firewall blocks a visit, it <?php echo $icwp_fBlockSendEmail? 'will': 'will not'; ?> send an email and then :
|
45 |
<?php
|
46 |
-
if( $
|
47 |
-
echo '
|
48 |
}
|
49 |
-
else if ( $
|
|
|
|
|
|
|
50 |
echo 'Redirect to home.';
|
51 |
}
|
52 |
-
else if ( $
|
53 |
echo 'Redirect to 404 page.';
|
54 |
}
|
55 |
else {
|
@@ -57,28 +83,172 @@ $sPluginName = 'WordPress Simple Firewall';
|
|
57 |
}
|
58 |
?>
|
59 |
</li>
|
60 |
-
|
61 |
-
<?php
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
<li>Firewall blocks
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
76 |
</ul>
|
77 |
<?php endif; ?>
|
78 |
</div>
|
79 |
</div><!-- / span6 -->
|
80 |
<div class="span6" id="tbs_docs_examples">
|
81 |
<div class="well">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
82 |
</div>
|
83 |
</div><!-- / span6 -->
|
84 |
</div><!-- / row -->
|
@@ -92,5 +262,5 @@ $sPluginName = 'WordPress Simple Firewall';
|
|
92 |
</div><!-- / row -->
|
93 |
|
94 |
</div><!-- / bootstrap-wpadmin -->
|
95 |
-
|
96 |
</div><!-- / wrap -->
|
1 |
<?php
|
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 |
$sPluginName = 'WordPress Simple Firewall';
|
5 |
+
$fFirewallOn = $icwp_aMainOptions['enable_firewall'] == 'Y';
|
6 |
+
$fLoginProtectOn = $icwp_aMainOptions['enable_login_protect'] == 'Y';
|
7 |
+
$fCommentsFilteringOn = $icwp_aMainOptions['enable_comments_filter'] == 'Y';
|
8 |
+
$fLockdownOn = $icwp_aMainOptions['enable_lockdown'] == 'Y';
|
9 |
?>
|
10 |
|
11 |
<div class="wrap">
|
12 |
<div class="bootstrap-wpadmin">
|
13 |
+
<?php echo printOptionsPageHeader( 'Dashboard' ); ?>
|
|
|
|
|
|
|
|
|
14 |
|
15 |
<?php include_once( dirname(__FILE__).'/widgets/icwp_common_widgets.php' ); ?>
|
16 |
+
|
17 |
+
<div class="row">
|
18 |
+
<div class="<?php echo $icwp_fShowAds? 'span9' : 'span12'; ?>">
|
19 |
+
|
20 |
+
<form action="<?php echo $icwp_form_action; ?>" method="post" class="form-horizontal">
|
21 |
+
<?php
|
22 |
+
wp_nonce_field( $icwp_nonce_field );
|
23 |
+
printAllPluginOptionsForm( $icwp_aAllOptions, $icwp_var_prefix, 1 );
|
24 |
+
?>
|
25 |
+
<div class="form-actions">
|
26 |
+
<input type="hidden" name="<?php echo $icwp_var_prefix; ?>all_options_input" value="<?php echo $icwp_all_options_input; ?>" />
|
27 |
+
<input type="hidden" name="icwp_plugin_form_submit" value="Y" />
|
28 |
+
<button type="submit" class="btn btn-primary" name="submit"><?php _hlt_e( 'Save All Settings'); ?></button>
|
29 |
+
</div>
|
30 |
+
</form>
|
31 |
+
|
32 |
+
</div><!-- / span9 -->
|
33 |
+
|
34 |
+
<?php if ( $icwp_fShowAds ) : ?>
|
35 |
+
<div class="span3" id="side_widgets">
|
36 |
+
<?php echo getWidgetIframeHtml('side-widgets-wtb'); ?>
|
37 |
+
</div>
|
38 |
+
<?php endif; ?>
|
39 |
+
</div><!-- / row -->
|
40 |
|
41 |
<?php if ( $icwp_fShowAds ) : ?>
|
42 |
<div class="row" id="worpit_promo">
|
54 |
<?php endif; ?>
|
55 |
|
56 |
<div class="row" id="tbs_docs">
|
57 |
+
<h2>Plugin Configuration Summary</h2>
|
58 |
+
<div class="span6" id="tbs_docs_shortcodes">
|
59 |
<div class="well">
|
60 |
+
<h3>Firewall Configuration</h3>
|
61 |
+
|
62 |
+
<h4 style="margin-top:20px;">Firewall is currently <?php echo $fFirewallOn ? 'ON' : 'OFF'; ?>.
|
63 |
+
[ <a href="admin.php?page=icwp-wpsf-firewall">Configure Now</a> ]</h4>
|
64 |
+
<?php if ( $fFirewallOn ) : ?>
|
|
|
|
|
65 |
<ul>
|
66 |
+
<li>Firewall logging is: <?php echo $icwp_aFirewallOptions['enable_firewall'] == 'Y'? 'ON' : 'OFF'; ?></li>
|
67 |
+
<li>When the firewall blocks a visit, it will:
|
|
|
68 |
<?php
|
69 |
+
if( $icwp_aFirewallOptions['block_response'] == 'redirect_die' ) {
|
70 |
+
echo 'Die.';
|
71 |
}
|
72 |
+
else if ( $icwp_aFirewallOptions['block_response'] == 'redirect_die_message' ) {
|
73 |
+
echo 'Die with a message.';
|
74 |
+
}
|
75 |
+
else if ( $icwp_aFirewallOptions['block_response'] == 'redirect_home' ) {
|
76 |
echo 'Redirect to home.';
|
77 |
}
|
78 |
+
else if ( $icwp_aFirewallOptions['block_response'] == 'redirect_404' ) {
|
79 |
echo 'Redirect to 404 page.';
|
80 |
}
|
81 |
else {
|
83 |
}
|
84 |
?>
|
85 |
</li>
|
86 |
+
<?php if ( isset($icwp_aFirewallOptions['ips_whitelist']['ips']) ) : ?>
|
87 |
+
<li>You have <?php echo count( $icwp_aFirewallOptions['ips_whitelist']['ips'] );?> whitelisted IP addresses:
|
88 |
+
<?php foreach( $icwp_aFirewallOptions['ips_whitelist']['ips'] as $sIp ) : ?>
|
89 |
+
<br /><?php echo long2ip($sIp); ?> labelled as <?php echo $icwp_aFirewallOptions['ips_whitelist']['meta'][md5( $sIp )]?>
|
90 |
+
<?php endforeach; ?>
|
91 |
+
</li>
|
92 |
+
<?php endif; ?>
|
93 |
+
|
94 |
+
<?php if ( isset($icwp_aFirewallOptions['ips_blacklist']['ips']) ) : ?>
|
95 |
+
<li>You have <?php echo count( $icwp_aFirewallOptions['ips_blacklist']['ips'] );?> blacklisted IP addresses:
|
96 |
+
<?php foreach( $icwp_aFirewallOptions['ips_blacklist']['ips'] as $sIp ) : ?>
|
97 |
+
<br /><?php echo long2ip($sIp); ?> labelled as <?php echo $icwp_aFirewallOptions['ips_whitelist']['meta'][md5( $sIp )]?>
|
98 |
+
<?php endforeach; ?>
|
99 |
+
</li>
|
100 |
+
<?php endif; ?>
|
101 |
+
<li>Firewall blocks Directory Traversals: <?php echo $icwp_aFirewallOptions['block_dir_traversal'] == 'Y'? 'ON' : 'OFF'; ?></li>
|
102 |
+
<li>Firewall blocks SQL Queries: <?php echo $icwp_aFirewallOptions['block_sql_queries'] == 'Y'? 'ON' : 'OFF'; ?></li>
|
103 |
+
<li>Firewall blocks WordPress Specific Terms: <?php echo $icwp_aFirewallOptions['block_wordpress_terms'] == 'Y'? 'ON' : 'OFF'; ?></li>
|
104 |
+
<li>Firewall blocks Field Truncation Attacks: <?php echo $icwp_aFirewallOptions['block_field_truncation'] == 'Y'? 'ON' : 'OFF'; ?></li>
|
105 |
+
<li>Firewall blocks Executable File Uploads:<?php echo $icwp_aFirewallOptions['block_exe_file_uploads'] == 'Y'? 'ON' : 'OFF'; ?> </li>
|
106 |
+
<li>Firewall blocks Leading Schemas (HTTPS / HTTP): <?php echo $icwp_aFirewallOptions['block_leading_schema'] == 'Y'? 'ON' : 'OFF'; ?></li>
|
107 |
+
<li>Firewall Logging: <?php echo ($icwp_aFirewallOptions['enable_firewall_log'] == 'Y')? 'ON' : 'OFF';?></li>
|
108 |
+
</ul>
|
109 |
+
<?php endif; ?>
|
110 |
+
|
111 |
+
<h4 style="margin-top:20px;">Login Protection is currently <?php echo $fLoginProtectOn? 'ON' : 'OFF'; ?>.
|
112 |
+
[ <a href="admin.php?page=icwp-wpsf-login_protect">Configure Now</a> ]</h4>
|
113 |
+
<?php if ( $fLoginProtectOn ) : ?>
|
114 |
+
<ul>
|
115 |
+
<?php if ( isset($icwp_aLoginProtectOptions['ips_whitelist']['ips']) ) : ?>
|
116 |
+
<li>You have <?php echo count( $icwp_aLoginProtectOptions['ips_whitelist']['ips'] );?> whitelisted IP addresses:
|
117 |
+
<?php foreach( $icwp_aLoginProtectOptions['ips_whitelist']['ips'] as $sIp ) : ?>
|
118 |
+
<br /><?php echo long2ip($sIp); ?> labelled as <?php echo $icwp_aLoginProtectOptions['ips_whitelist']['meta'][md5( $sIp )]?>
|
119 |
+
<?php endforeach; ?>
|
120 |
+
</li>
|
121 |
+
<?php endif; ?>
|
122 |
+
<li>Two Factor Login Authentication is: <?php echo $icwp_aLoginProtectOptions['enable_two_factor_auth_by_ip'] == 'Y'? 'ON' : 'OFF'; ?></li>
|
123 |
+
<li>Two Factor Login By Pass is: <?php echo $icwp_aLoginProtectOptions['enable_two_factor_bypass_on_email_fail'] == 'Y'? 'ON' : 'OFF'; ?></li>
|
124 |
+
<li>Login Cooldown Interval is: <?php echo ($icwp_aLoginProtectOptions['login_limit_interval'] == 0)? 'OFF' : $icwp_aLoginProtectOptions['login_limit_interval'].' seconds'; ?></li>
|
125 |
+
<li>Login Form GASP Protection: <?php echo ($icwp_aLoginProtectOptions['enable_login_gasp_check'] == 'Y')? 'ON' : 'OFF';?></li>
|
126 |
+
<li>Login Protect Logging: <?php echo ($icwp_aLoginProtectOptions['enable_login_protect_log'] == 'Y')? 'ON' : 'OFF';?></li>
|
127 |
+
</ul>
|
128 |
+
<?php endif; ?>
|
129 |
+
|
130 |
+
<h4 style="margin-top:20px;">Comments Filter is currently <?php echo $fCommentsFilteringOn? 'ON' : 'OFF'; ?>.
|
131 |
+
[ <a href="admin.php?page=icwp-wpsf-comments_filter">Configure Now</a> ]</h4>
|
132 |
+
<?php if ( $fCommentsFilteringOn ) : ?>
|
133 |
+
<ul>
|
134 |
+
<li>Enchanced GASP Protection is: <?php echo $icwp_aCommentsFilterOptions['enable_comments_gasp_protection'] == 'Y'? 'ON' : 'OFF'; ?></li>
|
135 |
+
<li>Comments Cooldown Interval is: <?php echo ($icwp_aCommentsFilterOptions['comments_cooldown_interval'] == 0)? 'OFF' : $icwp_aCommentsFilterOptions['comments_cooldown_interval'].' seconds'; ?></li>
|
136 |
+
<li>Comments Token Expire is: <?php echo ($icwp_aCommentsFilterOptions['comments_token_expire_interval'] == 0)? 'OFF' : $icwp_aCommentsFilterOptions['comments_token_expire_interval'].' seconds'; ?></li>
|
137 |
+
</ul>
|
138 |
+
<?php endif; ?>
|
139 |
+
|
140 |
+
<h4 style="margin-top:20px;">WordPress Lockdown is currently <?php echo $fLockdownOn? 'ON' : 'OFF'; ?>.
|
141 |
+
[ <a href="admin.php?page=icwp-wpsf-comments_filter">Configure Now</a> ]</h4>
|
142 |
+
<?php if ( $fLockdownOn ) : ?>
|
143 |
+
<ul>
|
144 |
+
<li>Disable File Editing is: <?php echo $icwp_aLockdownOptions['disable_file_editing'] == 'Y'? 'ON' : 'OFF'; ?></li>
|
145 |
</ul>
|
146 |
<?php endif; ?>
|
147 |
</div>
|
148 |
</div><!-- / span6 -->
|
149 |
<div class="span6" id="tbs_docs_examples">
|
150 |
<div class="well">
|
151 |
+
<h3>v1.9.x Release:</h3>
|
152 |
+
<p>The following summarises the main changes to the plugin in the 1.8.x release</p>
|
153 |
+
<p><span class="label ">new</span> means for the absolute latest release.</p>
|
154 |
+
<?php
|
155 |
+
$aNewLog = array(
|
156 |
+
'ADDED: Block deactivation of plugin if admin access restriction is on.',
|
157 |
+
'ADDED: New feature to manage WordPress Automatic Updates.',
|
158 |
+
'FIXED: Several small bugs and streamlined codebase.',
|
159 |
+
);
|
160 |
+
?>
|
161 |
+
<ul>
|
162 |
+
<?php foreach( $aNewLog as $sItem ) : ?>
|
163 |
+
<li><span class="label">new</span> <?php echo $sItem; ?></li>
|
164 |
+
<?php endforeach; ?>
|
165 |
+
</ul>
|
166 |
+
<?php
|
167 |
+
$aLog = array(
|
168 |
+
);
|
169 |
+
?>
|
170 |
+
<ul>
|
171 |
+
<?php foreach( $aLog as $sItem ) : ?>
|
172 |
+
<li><?php echo $sItem; ?></li>
|
173 |
+
<?php endforeach; ?>
|
174 |
+
</ul>
|
175 |
+
|
176 |
+
<?php
|
177 |
+
$aLog = array(
|
178 |
+
|
179 |
+
'1.8.x' => array(
|
180 |
+
'ADDED: Admin Access Key Restriction feature.',
|
181 |
+
'ADDED: WordPress Lockdown feature.'
|
182 |
+
),
|
183 |
+
'1.7.x' => array(
|
184 |
+
'ADDED: Support for WPMU sites (only manageable as Super Admin).',
|
185 |
+
'CHANGE: Serious performance optimizations and a few bug fixes.',
|
186 |
+
),
|
187 |
+
'1.6.x' => array(
|
188 |
+
'ADDED: GASP-based, and further enhanced, SPAM comments filtering functionality.',
|
189 |
+
),
|
190 |
+
'1.5.x' => array(
|
191 |
+
'IMPROVED: Whitelisting/Blacklisting operations and options',
|
192 |
+
'NEW Option: Login Protect Dedicated IP Whitelist.',
|
193 |
+
'REMOVED Option: Firewall wp-login.php blocking'
|
194 |
+
),
|
195 |
+
'1.4.x' => array(
|
196 |
+
'NEW Option: Plugin will automatically upgrade itself when an update is detected - ensures plugin always remains current.',
|
197 |
+
'Now displays an admin notice when a plugin upgrade is available with a link to immediately update.',
|
198 |
+
'Plugin collision protection: removes collision with All In One WordPress Security.',
|
199 |
+
'Improved Login Cooldown Feature- works more like email throttling as it now uses an extra filesystem-based level of protection.',
|
200 |
+
"Fix - Login Cooldown Feature didn't take effect in certain circumstances.",
|
201 |
+
'Brand new plugin options system making them more efficient, easier to manage/update, using fewer WordPress database options',
|
202 |
+
'Huge improvements on database calls and efficiency in loading plugin options'
|
203 |
+
),
|
204 |
+
'1.3.x' => array(
|
205 |
+
"New Feature - Email Throttle. It will prevent you getting bombarded by 1000s of emails in case you're hit by a bot.",
|
206 |
+
"Another Firewall die() option. New option will print a message and uses the wp_die() function instead.",
|
207 |
+
"Option to separately log Login Protect features.",
|
208 |
+
"Refactored and improved the logging system.",
|
209 |
+
"Option to by-pass 2-factor authentication in the case sending the verification email fails.",
|
210 |
+
"Login Protect checking now better logs out users immediately with a redirect.",
|
211 |
+
"We now escape the log data being printed - just in case there's any HTML/JS etc in there we don't want.",
|
212 |
+
"Optimized and cleaned a lot of the option caching code to improve reliability and performance (more to come).",
|
213 |
+
),
|
214 |
+
|
215 |
+
'1.2.x' => array(
|
216 |
+
'New Feature - Ability to import settings from WordPress Firewall 2 Plugin.',
|
217 |
+
'New Feature - Login Form GASP-based Anti-Bot Protection.',
|
218 |
+
'New Feature - Login Cooldown Interval.',
|
219 |
+
'Performance optimizations.',
|
220 |
+
'UI Cleanup and code improvements.',
|
221 |
+
'Added new Login Protect feature where you can add 2-Factor Authentication to your WordPress user logins.',
|
222 |
+
'Improved method for processing the IP address lists to be more cross-platform reliable.',
|
223 |
+
'Improved .htaccess rules (thanks MickeyRoush).',
|
224 |
+
'Mailing method now uses WP_MAIL.'
|
225 |
+
),
|
226 |
+
|
227 |
+
'1.1.x' => array(
|
228 |
+
'Option to check Cookies values in firewall testing.',
|
229 |
+
'Ability to whitelist particular pages and their parameters.',
|
230 |
+
'Quite a few improvements made to the reliability of the firewall processing.',
|
231 |
+
'Option to completely ignore logged-in Administrators from the Firewall processing (they wont even trigger logging etc).',
|
232 |
+
'Ability to (un)blacklist and (un)whitelist IP addresses directly from within the log.',
|
233 |
+
'Helpful link to IP WHOIS from within the log.',
|
234 |
+
'Firewall logging now has its own dedicated database table.',
|
235 |
+
'Fix: Block email not showing the IPv4 friendly address.',
|
236 |
+
'You can now specify IP ranges in whitelists and blacklists.',
|
237 |
+
'You can now specify which email address to send the notification emails.',
|
238 |
+
"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').",
|
239 |
+
'You can now set to delete ALL firewall settings when you deactivate the plugin.',
|
240 |
+
'Improved formatting of the firewall log.'
|
241 |
+
)
|
242 |
+
);
|
243 |
+
?>
|
244 |
+
<?php foreach( $aLog as $sVersion => $aItems ) : ?>
|
245 |
+
<h3>Change log for the v<?php echo $sVersion; ?> release:</h3>
|
246 |
+
<ul>
|
247 |
+
<?php foreach( $aItems as $sItem ) : ?>
|
248 |
+
<li><?php echo $sItem; ?></li>
|
249 |
+
<?php endforeach; ?>
|
250 |
+
</ul>
|
251 |
+
<?php endforeach; ?>
|
252 |
</div>
|
253 |
</div><!-- / span6 -->
|
254 |
</div><!-- / row -->
|
262 |
</div><!-- / row -->
|
263 |
|
264 |
</div><!-- / bootstrap-wpadmin -->
|
265 |
+
<?php include_once( dirname(__FILE__).'/include_js.php' ); ?>
|
266 |
</div><!-- / wrap -->
|
views/widgets/icwp_common_widgets.php
CHANGED
@@ -10,20 +10,20 @@ $sPluginName = 'WordPress Simple Firewall';
|
|
10 |
<p>Please help <u>spread the word</u> or check out what else we do ...</p>
|
11 |
</div>
|
12 |
<div class="span4">
|
13 |
-
<a href="https://twitter.com/share" class="twitter-share-button" data-url="http://
|
14 |
</div>
|
15 |
</div>
|
16 |
<div class="row">
|
17 |
<div class="span6">
|
18 |
<ul>
|
19 |
-
<li><a href="http://icwp.io/
|
20 |
-
<li><a href="http://icwp.io/
|
21 |
</ul>
|
22 |
</div>
|
23 |
<div class="span5">
|
24 |
<ul>
|
25 |
-
<li><a href="http://icwp.io/
|
26 |
-
<li><a href="http://wordpress.org/extend/plugins/
|
27 |
</ul>
|
28 |
</div>
|
29 |
</div>
|
10 |
<p>Please help <u>spread the word</u> or check out what else we do ...</p>
|
11 |
</div>
|
12 |
<div class="span4">
|
13 |
+
<a href="https://twitter.com/share" class="twitter-share-button" data-url="http://www.icontrolwp.com/our-wordpress-plugins/wordpress-simple-firewall-plugin/" data-text="I use the <?php echo $sPluginName; ?> plugin to protect my #WordPress sites!" data-via="iControlWP" data-size="large">Tweet</a><script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
|
14 |
</div>
|
15 |
</div>
|
16 |
<div class="row">
|
17 |
<div class="span6">
|
18 |
<ul>
|
19 |
+
<li><a href="http://icwp.io/2b" target="_blank"><strong>Manage <u>All</u> Your WordPress Sites In 1 Place!</strong></a></li>
|
20 |
+
<li><a href="http://icwp.io/2c" target="_blank">Check out all our other WordPress Plugins</a></li>
|
21 |
</ul>
|
22 |
</div>
|
23 |
<div class="span5">
|
24 |
<ul>
|
25 |
+
<li><a href="http://icwp.io/2d" target="_blank"><strong>Visit the plugin Help & Support page</strong></a>.</li>
|
26 |
+
<li><a href="http://wordpress.org/extend/plugins/wp-simple-firewall/" target="_blank">Show some love, and give this a 5 star rating on WordPress.org.</a></li>
|
27 |
</ul>
|
28 |
</div>
|
29 |
</div>
|
views/widgets/icwp_widgets.php
CHANGED
@@ -1,4 +1,5 @@
|
|
1 |
-
<?php
|
|
|
2 |
function getWidgetIframeHtml( $insSnippet ) {
|
3 |
|
4 |
$sSubPageNow = isset( $_GET['page'] )? 'page='.$_GET['page'].'&': '';
|
@@ -8,7 +9,7 @@ function getWidgetIframeHtml( $insSnippet ) {
|
|
8 |
$sIframeName = 'iframe-hlt-bootstrapcss-'.$insSnippet;
|
9 |
|
10 |
if ( strpos( $insSnippet, 'side-widgets') !== false ) {
|
11 |
-
$sHeight = '
|
12 |
}
|
13 |
elseif ( strpos( $insSnippet, 'dashboard-widget-developerchannel') !== false ) {
|
14 |
$sHeight = '312px';
|
1 |
+
<?php
|
2 |
+
|
3 |
function getWidgetIframeHtml( $insSnippet ) {
|
4 |
|
5 |
$sSubPageNow = isset( $_GET['page'] )? 'page='.$_GET['page'].'&': '';
|
9 |
$sIframeName = 'iframe-hlt-bootstrapcss-'.$insSnippet;
|
10 |
|
11 |
if ( strpos( $insSnippet, 'side-widgets') !== false ) {
|
12 |
+
$sHeight = '800px';
|
13 |
}
|
14 |
elseif ( strpos( $insSnippet, 'dashboard-widget-developerchannel') !== false ) {
|
15 |
$sHeight = '312px';
|