Version Description
- FIX: Improved compatibility with bbPress.
Download this release
Release Info
Developer | paultgoodchild |
Plugin | Shield Security for WordPress |
Version | 2.6.6 |
Comparing to | |
See all releases |
Code changes from version 2.0.0 to 2.6.6
- icwp-wpsf.php +561 -932
- languages/wp-simple-firewall-ca_ES.mo +0 -0
- languages/wp-simple-firewall-es_ES.mo +0 -0
- languages/wp-simple-firewall-fa_IR.mo +0 -0
- languages/wp-simple-firewall-he_IL.mo +0 -0
- languages/wp-simple-firewall-it_IT.mo +0 -0
- languages/wp-simple-firewall-pt_BR.mo +0 -0
- languages/wp-simple-firewall-tr_TR.mo +0 -0
- readme.txt +207 -30
- resources/css/{bootstrap-wpadmin.css → bootstrap-wpadmin-legacy.css} +0 -0
- resources/css/{icontrolwp-plugin.css → plugin.css} +20 -5
- resources/css/worpit-plugin.css +0 -119
- resources/images/icontrolwp_16x16.png +0 -0
- resources/images/icontrolwp_24x24.png +0 -0
- resources/images/icontrolwp_32x32.png +0 -0
- resources/images/pluginlogo_16x16.png +0 -0
- resources/images/pluginlogo_24x24.png +0 -0
- resources/images/pluginlogo_32x32.png +0 -0
- resources/images/pluginlogo_64x64.png +0 -0
- resources/spamblacklist.txt +10549 -0
- src/icwp-base-processor.php +111 -59
- src/icwp-basedb-processor.php +136 -6
- src/icwp-data-processor.php +198 -4
- src/icwp-feature-master.php +337 -0
- src/icwp-import-base-processor.php +2 -2
- src/icwp-import-wpf2-processor.php +3 -3
- src/icwp-once.php +49 -0
- src/icwp-optionshandler-autoupdates.php +51 -20
- src/icwp-optionshandler-base.php +156 -60
- src/icwp-optionshandler-commentsfilter.php +122 -21
- src/icwp-optionshandler-email.php +90 -0
- src/icwp-optionshandler-firewall.php +87 -51
- src/icwp-optionshandler-lockdown.php +44 -20
- src/icwp-optionshandler-logging.php +59 -0
- src/icwp-optionshandler-loginprotect.php +163 -26
- src/icwp-optionshandler-privacyprotect.php +99 -0
- src/icwp-optionshandler-wpsf.php +65 -90
- src/icwp-plugins-base.php +0 -692
- src/icwp-processor-autoupdates.php +248 -33
- src/icwp-processor-commentsfilter.php +355 -90
- src/icwp-processor-email.php +42 -16
- src/icwp-processor-firewall.php +114 -85
- src/icwp-processor-lockdown.php +47 -28
- src/icwp-processor-logging.php +33 -21
- src/icwp-processor-loginprotect.php +544 -146
- src/icwp-processor-privacyprotect.php +173 -0
- src/icwp-pure-base.php +966 -0
- src/icwp-wpfilesystem.php +126 -16
- src/icwp-wpfunctions.php +59 -7
- src/icwp-wpsf-stats.php +77 -0
- views/icwp_options_helper.php +81 -44
- views/icwp_wpsf_config_autoupdates_index.php +15 -1
- views/icwp_wpsf_config_login_protect_index.php +1 -0
- views/icwp_wpsf_config_privacy_protect_index.php +35 -0
- views/icwp_wpsf_firewall_log_index.php +0 -1
- views/icwp_wpsf_index.php +30 -18
- views/icwp_wpsf_privacy_protect_log_index.php +93 -0
- views/icwp_wpsf_state_summary.php +115 -0
- views/widgets/icwp_widgets.php +10 -12
icwp-wpsf.php
CHANGED
@@ -3,14 +3,14 @@
|
|
3 |
* Plugin Name: WordPress Simple Firewall
|
4 |
* Plugin URI: http://icwp.io/2f
|
5 |
* Description: A Simple WordPress Firewall
|
6 |
-
* Version: 2.
|
7 |
* Text Domain: wp-simple-firewall
|
8 |
* Author: iControlWP
|
9 |
* Author URI: http://icwp.io/2e
|
10 |
*/
|
11 |
|
12 |
/**
|
13 |
-
* Copyright (c)
|
14 |
* All rights reserved.
|
15 |
*
|
16 |
* "WordPress Simple Firewall" is
|
@@ -30,7 +30,7 @@
|
|
30 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
31 |
*/
|
32 |
|
33 |
-
require_once( dirname(__FILE__).'/src/icwp-
|
34 |
require_once( dirname(__FILE__).'/src/icwp-data-processor.php' );
|
35 |
|
36 |
if ( !function_exists( '_wpsf_e' ) ) {
|
@@ -46,22 +46,27 @@ if ( !function_exists( '_wpsf__' ) ) {
|
|
46 |
|
47 |
if ( !class_exists('ICWP_Wordpress_Simple_Firewall') ):
|
48 |
|
49 |
-
class ICWP_Wordpress_Simple_Firewall extends
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
|
|
|
|
54 |
|
|
|
|
|
|
|
|
|
55 |
/**
|
56 |
* Should be updated each new release.
|
57 |
* @var string
|
58 |
*/
|
59 |
-
|
60 |
-
|
61 |
/**
|
62 |
-
* @var
|
63 |
*/
|
64 |
-
|
65 |
|
66 |
/**
|
67 |
* @var ICWP_OptionsHandler_Firewall
|
@@ -72,6 +77,10 @@ class ICWP_Wordpress_Simple_Firewall extends ICWP_WPSF_Base_Plugin {
|
|
72 |
* @var ICWP_OptionsHandler_LoginProtect
|
73 |
*/
|
74 |
protected $m_oLoginProtectOptions;
|
|
|
|
|
|
|
|
|
75 |
|
76 |
/**
|
77 |
* @var ICWP_OptionsHandler_CommentsFilter
|
@@ -87,6 +96,11 @@ class ICWP_Wordpress_Simple_Firewall extends ICWP_WPSF_Base_Plugin {
|
|
87 |
* @var ICWP_OptionsHandler_AutoUpdates
|
88 |
*/
|
89 |
protected $m_oAutoUpdatesOptions;
|
|
|
|
|
|
|
|
|
|
|
90 |
|
91 |
/**
|
92 |
* @var ICWP_FirewallProcessor
|
@@ -102,19 +116,23 @@ class ICWP_Wordpress_Simple_Firewall extends ICWP_WPSF_Base_Plugin {
|
|
102 |
* @var ICWP_CommentsFilterProcessor
|
103 |
*/
|
104 |
protected $m_oCommentsFilterProcessor;
|
105 |
-
|
106 |
/**
|
107 |
* @var ICWP_LockdownProcessor
|
108 |
*/
|
109 |
protected $m_oLockdownProcessor;
|
|
|
|
|
|
|
|
|
110 |
|
111 |
/**
|
112 |
-
* @var
|
113 |
*/
|
114 |
protected $m_oAutoUpdatesProcessor;
|
115 |
|
116 |
/**
|
117 |
-
* @var
|
118 |
*/
|
119 |
protected $m_oLoggingProcessor;
|
120 |
|
@@ -122,330 +140,99 @@ class ICWP_Wordpress_Simple_Firewall extends ICWP_WPSF_Base_Plugin {
|
|
122 |
* @var ICWP_EmailProcessor
|
123 |
*/
|
124 |
protected $m_oEmailProcessor;
|
125 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
public function __construct() {
|
127 |
|
128 |
$this->m_fNetworkAdminOnly = true;
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
144 |
// loads the base plugin options from 1 db call
|
145 |
-
$this->loadOptionsHandler( '
|
146 |
-
$this->m_fAutoPluginUpgrade = false && $this->
|
147 |
|
148 |
// checks for filesystem based firewall overrides
|
149 |
$this->override();
|
150 |
-
|
151 |
-
if ( $this->getIsMainFeatureEnabled( 'firewall' ) ) {
|
152 |
-
add_action( 'plugins_loaded', array( $this, 'runFirewallProcess' ), 1 );
|
153 |
-
}
|
154 |
-
|
155 |
-
if ( $this->getIsMainFeatureEnabled( 'login_protect' ) ) {
|
156 |
-
add_action( 'plugins_loaded', array( $this, 'runLoginProtect' ), 1 );
|
157 |
-
}
|
158 |
-
|
159 |
-
if ( $this->getIsMainFeatureEnabled( 'comments_filter' ) ) {
|
160 |
-
add_action( 'plugins_loaded', array( $this, 'runCommentsFilter' ), 1 );
|
161 |
-
}
|
162 |
-
|
163 |
-
if ( $this->getIsMainFeatureEnabled( 'lockdown' ) ) {
|
164 |
-
add_action( 'plugins_loaded', array( $this, 'runLockdown' ), 1 );
|
165 |
-
}
|
166 |
-
|
167 |
-
if ( $this->getIsMainFeatureEnabled( 'autoupdates' ) ) {
|
168 |
-
add_action( 'plugins_loaded', array( $this, 'runAutoUpdates' ), 1 );
|
169 |
-
}
|
170 |
-
|
171 |
-
add_action( 'in_plugin_update_message-'.self::$PLUGIN_FILE, array( $this, 'onWpPluginUpdateMessage' ) );
|
172 |
|
173 |
if ( isset( $_GET['turnoffperm'] ) ) {
|
174 |
$this->setPermissionToSubmit( false );
|
175 |
}
|
176 |
-
}
|
177 |
-
|
178 |
-
/**
|
179 |
-
* Load the multilingual aspect of the plugin
|
180 |
-
*/
|
181 |
-
public function load_textdomain() {
|
182 |
-
load_plugin_textdomain( 'wp-simple-firewall', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
|
183 |
-
}
|
184 |
-
|
185 |
-
public function removePluginConflicts() {
|
186 |
-
if ( class_exists('AIO_WP_Security') && isset( $GLOBALS['aio_wp_security'] ) ) {
|
187 |
-
remove_action( 'init', array( $GLOBALS['aio_wp_security'], 'wp_security_plugin_init'), 0 );
|
188 |
-
}
|
189 |
-
}
|
190 |
-
|
191 |
-
/**
|
192 |
-
*/
|
193 |
-
public function onWpInit() {
|
194 |
-
parent::onWpInit();
|
195 |
-
add_action( 'plugin_action_links', array( $this, 'onWpPluginActionLinks' ), 10, 4 );
|
196 |
-
}
|
197 |
-
|
198 |
-
/**
|
199 |
-
* @param array $aPlugins
|
200 |
-
* @return unknown
|
201 |
-
*/
|
202 |
-
public function hide_plugin( $inaPlugins ) {
|
203 |
-
foreach ( $inaPlugins as $sSlug => $aData ) {
|
204 |
-
if ( strpos( $sSlug, 'icwp-wpsf.php' ) !== false ) {
|
205 |
-
unset( $inaPlugins[$sSlug] );
|
206 |
-
}
|
207 |
-
}
|
208 |
-
return $inaPlugins;
|
209 |
-
}
|
210 |
-
|
211 |
-
protected function override() {
|
212 |
-
if ( is_file( self::$PLUGIN_DIR . 'forceOff' ) ) {
|
213 |
-
$this->setSharedOption( 'enable_firewall', 'N' );
|
214 |
-
$this->setSharedOption( 'enable_login_protect', 'N' );
|
215 |
-
$this->setSharedOption( 'enable_comments_filter', 'N' );
|
216 |
-
$this->setSharedOption( 'enable_autoupdates', 'N' );
|
217 |
-
$this->setSharedOption( 'enable_admin_access_restriction', 'N' );
|
218 |
-
}
|
219 |
-
else if ( is_file( self::$PLUGIN_DIR . 'forceOn' ) ) {
|
220 |
-
$this->setSharedOption( 'enable_firewall', 'Y' );
|
221 |
-
$this->setSharedOption( 'enable_login_protect', 'Y' );
|
222 |
-
$this->setSharedOption( 'enable_comments_filter', 'Y' );
|
223 |
-
$this->setSharedOption( 'enable_autoupdates', 'Y' );
|
224 |
-
$this->setSharedOption( 'enable_admin_access_restriction', 'Y' );
|
225 |
-
}
|
226 |
-
else {
|
227 |
-
return true;
|
228 |
-
}
|
229 |
-
$this->resetFirewallProcessor();
|
230 |
-
$this->resetLoginProcessor();
|
231 |
-
}
|
232 |
-
|
233 |
-
protected function genSecretKey() {
|
234 |
-
$sKey = $this->m_oWpsfOptions->getOpt( 'secret_key' );
|
235 |
-
if ( empty( $sKey ) ) {
|
236 |
-
$sKey = md5( mt_rand() );
|
237 |
-
$this->m_oWpsfOptions->setOpt( 'secret_key', $sKey );
|
238 |
-
}
|
239 |
-
return $sKey;
|
240 |
-
}
|
241 |
-
|
242 |
-
protected function getFeaturesMap() {
|
243 |
-
return array(
|
244 |
-
'firewall' => 'Firewall',
|
245 |
-
'login_protect' => 'LoginProtect',
|
246 |
-
'comments_filter' => 'CommentsFilter',
|
247 |
-
'lockdown' => 'Lockdown',
|
248 |
-
'autoupdates' => 'AutoUpdates'
|
249 |
-
);
|
250 |
-
}
|
251 |
-
|
252 |
-
/**
|
253 |
-
* @param string $insFeature - firewall, login_protect, comments_filter, lockdown
|
254 |
-
* @return boolean
|
255 |
-
*/
|
256 |
-
public function getIsMainFeatureEnabled( $insFeature ) {
|
257 |
-
|
258 |
-
if ( is_file( self::$PLUGIN_DIR . 'forceOff' ) ) {
|
259 |
-
return false;
|
260 |
-
}
|
261 |
-
else if ( is_file( self::$PLUGIN_DIR . 'forceOn' ) ) {
|
262 |
-
return true;
|
263 |
-
}
|
264 |
-
|
265 |
-
$aFeatures = $this->getFeaturesMap();
|
266 |
-
|
267 |
-
switch ( $insFeature ) {
|
268 |
-
case 'admin_access':
|
269 |
-
$fEnabled = $this->m_oWpsfOptions->getOpt( 'enable_admin_access_restriction' ) == 'Y';
|
270 |
-
break;
|
271 |
-
default:
|
272 |
-
if ( array_key_exists( $insFeature, $aFeatures ) ) {
|
273 |
-
$fEnabled = $this->m_oWpsfOptions->getOpt( 'enable_'.$insFeature ) == 'Y';
|
274 |
-
}
|
275 |
-
else {
|
276 |
-
$fEnabled = false;
|
277 |
-
}
|
278 |
-
break;
|
279 |
-
}
|
280 |
-
return $fEnabled;
|
281 |
-
}
|
282 |
-
|
283 |
-
/**
|
284 |
-
* This is necessary because we store these values in several places and we need to always keep it in sync.
|
285 |
-
*
|
286 |
-
* @param string $sFeature
|
287 |
-
* @param boolean $infEnabled
|
288 |
-
* @return boolean
|
289 |
-
*/
|
290 |
-
public function setSharedOption( $insOption, $inmValue ) {
|
291 |
|
292 |
-
|
293 |
-
|
294 |
-
$sFeature = str_replace( 'enable_', '', $insOption );
|
295 |
-
if ( !array_key_exists( $sFeature, $aFeatures ) ) {
|
296 |
-
return;
|
297 |
-
}
|
298 |
-
|
299 |
-
$this->loadOptionsHandler( $aFeatures[$sFeature] );
|
300 |
-
$sOptions = 'm_o'.$aFeatures[$sFeature].'Options';// e.g. m_oFirewallOptions
|
301 |
-
$this->{$sOptions}->setOpt( $insOption, $inmValue );
|
302 |
-
$this->m_oWpsfOptions->setOpt( $insOption, $inmValue );
|
303 |
}
|
304 |
-
|
305 |
/**
|
306 |
-
*
|
307 |
-
*
|
308 |
-
* @param array $inaNewLogData
|
309 |
-
* @return boolean
|
310 |
*/
|
311 |
-
protected function
|
312 |
-
|
313 |
-
if (
|
314 |
-
|
315 |
-
if ( !is_null( $aLogData ) && !empty( $aLogData ) ) {
|
316 |
-
$this->loadProcessor( 'Logging' );
|
317 |
-
$this->m_oLoggingProcessor->writeLog( $aLogData );
|
318 |
-
}
|
319 |
-
}
|
320 |
-
|
321 |
-
if ( isset( $this->m_oLoginProtectProcessor ) && is_object( $this->m_oLoginProtectProcessor ) && $this->getIsMainFeatureEnabled( 'login_protect' ) ) {
|
322 |
-
$aLogData = $this->m_oLoginProtectProcessor->flushLogData();
|
323 |
-
if ( !is_null( $aLogData ) && !empty( $aLogData ) ) {
|
324 |
-
$this->loadProcessor( 'Logging' );
|
325 |
-
$this->m_oLoggingProcessor->writeLog( $aLogData );
|
326 |
-
}
|
327 |
-
}
|
328 |
-
}
|
329 |
-
|
330 |
-
protected function loadOptionsHandler( $insOptionHandler, $infFullBuild = false ) {
|
331 |
-
|
332 |
-
$aAllHandlers = array_values( $this->getFeaturesMap() );
|
333 |
-
$aAllHandlers[] = 'Wpsf';
|
334 |
-
|
335 |
-
// special case
|
336 |
-
if ( $insOptionHandler == 'all' ) {
|
337 |
-
foreach( $aAllHandlers as $sHandler ) {
|
338 |
-
$this->loadOptionsHandler( $sHandler, $infFullBuild );
|
339 |
-
}
|
340 |
-
return;
|
341 |
-
}
|
342 |
-
|
343 |
-
if ( !in_array( $insOptionHandler, $aAllHandlers ) ) {
|
344 |
-
wp_die( 'Options handler is not permitted: '.$insOptionHandler );
|
345 |
-
}
|
346 |
-
|
347 |
-
$sOptionsVarName = 'm_o'.$insOptionHandler.'Options'; // e.g. m_oWpsfOptions
|
348 |
-
$sSourceFile = dirname(__FILE__).'/src/icwp-optionshandler-'.strtolower($insOptionHandler).'.php'; // e.g. icwp-optionshandler-wpsf.php
|
349 |
-
$sClassName = 'ICWP_OptionsHandler_'.$insOptionHandler; // e.g. ICWP_OptionsHandler_Wpsf
|
350 |
-
|
351 |
-
require_once( $sSourceFile );
|
352 |
-
if ( !isset( $this->{$sOptionsVarName} ) ) {
|
353 |
-
$this->{$sOptionsVarName} = new $sClassName( self::OptionPrefix, self::$VERSION, $infFullBuild );
|
354 |
-
}
|
355 |
-
if ( $infFullBuild ) {
|
356 |
-
$this->{$sOptionsVarName}->buildOptions();
|
357 |
-
}
|
358 |
-
}
|
359 |
-
|
360 |
-
protected function loadProcessor( $insProcessorName, $infReset = false ) {
|
361 |
-
|
362 |
-
$aAllProcessors = array(
|
363 |
-
'Firewall' => 'firewall',
|
364 |
-
'LoginProtect' => 'login',
|
365 |
-
'CommentsFilter' => 'comments',
|
366 |
-
'Lockdown' => 'lockdown',
|
367 |
-
'AutoUpdates' => 'autoupdates',
|
368 |
-
'Logging' => '',
|
369 |
-
'Email' => ''
|
370 |
-
);
|
371 |
-
|
372 |
-
if ( !array_key_exists( $insProcessorName, $aAllProcessors ) ) {
|
373 |
-
wp_die( 'Processor is not permitted here.' );
|
374 |
-
}
|
375 |
-
|
376 |
-
$sProcessorVarName = 'm_o'.$insProcessorName.'Processor'; // e.g. m_oFirewallProcessor
|
377 |
-
$sSourceFile = dirname(__FILE__).'/src/icwp-processor-'.strtolower($insProcessorName).'.php'; // e.g. icwp-optionshandler-wpsf.php
|
378 |
-
$sClassName = 'ICWP_'.$insProcessorName.'Processor'; // e.g. ICWP_FirewallProcessor
|
379 |
-
$sStoredOptionName = $aAllProcessors[$insProcessorName].'_processor'; // e.g. firewall_processor
|
380 |
-
$sOptionsHandlerVarName = 'm_o'.$insProcessorName.'Options'; // e.g. m_oFirewallOptions
|
381 |
-
|
382 |
-
require_once( $sSourceFile );
|
383 |
-
if ( empty( $this->{$sProcessorVarName} ) ) {
|
384 |
-
|
385 |
-
$this->{$sProcessorVarName} = self::getOption( $sStoredOptionName );
|
386 |
-
if ( is_object( $this->{$sProcessorVarName} ) && ( $this->{$sProcessorVarName} instanceof $sClassName ) ) {
|
387 |
-
$this->{$sProcessorVarName}->reset();
|
388 |
-
}
|
389 |
-
else {
|
390 |
-
$this->{$sProcessorVarName} = new $sClassName();
|
391 |
-
// Also loads the options handler where appropriate
|
392 |
-
if ( !empty( $aAllProcessors[ $insProcessorName ] ) ) {
|
393 |
-
$this->loadOptionsHandler( $insProcessorName );
|
394 |
-
// $this->{$sProcessorVarName}->setOptionsHandler( $this->{$sOptionsHandlerVarName} );
|
395 |
-
$this->{$sProcessorVarName}->setOptions( $this->{$sOptionsHandlerVarName}->getPluginOptionsValues() );
|
396 |
-
}
|
397 |
-
}
|
398 |
-
}
|
399 |
-
else if ( $infReset ) {
|
400 |
-
$this->{$sProcessorVarName}->reset();
|
401 |
-
}
|
402 |
-
// Now we handle any custom processor stuff
|
403 |
-
if ( $insProcessorName == 'LoginProtect' ) {
|
404 |
-
$this->m_oLoginProtectProcessor->setSecretKey( $this->genSecretKey() );
|
405 |
-
}
|
406 |
-
else if ( $insProcessorName == 'Email' ) {
|
407 |
-
$this->m_oEmailProcessor->setDefaultRecipientAddress( $this->m_oWpsfOptions->getOpt( 'block_send_email_address' ) );
|
408 |
-
$this->m_oEmailProcessor->setThrottleLimit( $this->m_oWpsfOptions->getOpt( 'send_email_throttle_limit' ) );
|
409 |
-
$sSiteName = function_exists( 'get_bloginfo' )? get_bloginfo('name') : '';
|
410 |
-
$this->m_oEmailProcessor->setSiteName( $sSiteName );
|
411 |
}
|
|
|
|
|
|
|
412 |
}
|
413 |
|
414 |
/**
|
415 |
* Should be called from the constructor so as to ensure it is called as early as possible.
|
416 |
*
|
417 |
-
* @
|
418 |
-
* @return boolean
|
419 |
*/
|
420 |
public function runFirewallProcess() {
|
421 |
|
422 |
-
if ( is_super_admin() && $this->getOption( 'whitelist_admins' ) == 'Y' ) {
|
423 |
-
return;
|
424 |
-
}
|
425 |
-
|
426 |
$this->loadProcessor( 'Firewall' );
|
427 |
$fFirewallBlockUser = !$this->m_oFirewallProcessor->doFirewallCheck();
|
428 |
|
429 |
if ( $fFirewallBlockUser ) {
|
430 |
-
|
431 |
if ( $this->m_oFirewallProcessor->getNeedsEmailHandler() ) {
|
432 |
$this->loadProcessor( 'Email' );
|
433 |
$this->m_oFirewallProcessor->setEmailHandler( $this->m_oEmailProcessor );
|
434 |
-
$this->m_oFirewallProcessor->doPreFirewallBlock();
|
435 |
-
$this->m_oEmailProcessor->store( self::getKey( 'email_processor' ) );
|
436 |
-
}
|
437 |
-
else {
|
438 |
-
$this->m_oFirewallProcessor->doPreFirewallBlock();
|
439 |
}
|
|
|
440 |
}
|
441 |
-
$this->updateLogStore();
|
442 |
-
$this->m_oFirewallProcessor->store( self::getKey( 'firewall_processor' ) );
|
443 |
|
444 |
if ( $fFirewallBlockUser ) {
|
|
|
445 |
$this->m_oFirewallProcessor->doFirewallBlock();
|
446 |
}
|
447 |
-
|
448 |
-
unset( $this->m_oFirewallProcessor );
|
449 |
}
|
450 |
|
451 |
/**
|
@@ -453,251 +240,55 @@ class ICWP_Wordpress_Simple_Firewall extends ICWP_WPSF_Base_Plugin {
|
|
453 |
*/
|
454 |
public function runLoginProtect() {
|
455 |
$this->loadProcessor( 'LoginProtect' );
|
|
|
|
|
456 |
$this->m_oLoginProtectProcessor->run();
|
457 |
-
|
458 |
-
// We don't want to load the email handler unless we really need it.
|
459 |
-
// 29 is just before we'll need it if we do
|
460 |
-
if ( $this->m_oLoginProtectProcessor->getNeedsEmailHandler() ) {
|
461 |
-
$this->loadProcessor( 'Email' );
|
462 |
-
$this->m_oLoginProtectProcessor->setEmailHandler( $this->m_oEmailProcessor );
|
463 |
-
}
|
464 |
-
}
|
465 |
-
|
466 |
-
/**
|
467 |
-
* Handles the running of all Comments Filter processes.
|
468 |
-
*/
|
469 |
-
public function runCommentsFilter() {
|
470 |
-
$this->loadProcessor( 'CommentsFilter' );
|
471 |
-
$this->m_oCommentsFilterProcessor->run();
|
472 |
-
}
|
473 |
-
|
474 |
-
/**
|
475 |
-
* Handles the running of all Lockdown processes.
|
476 |
-
*/
|
477 |
-
public function runLockdown() {
|
478 |
-
$this->loadProcessor( 'Lockdown' );
|
479 |
-
$this->m_oLockdownProcessor->run();
|
480 |
}
|
481 |
|
482 |
/**
|
483 |
-
* Handles the running of all
|
484 |
*/
|
485 |
public function runAutoUpdates() {
|
486 |
$this->loadProcessor( 'AutoUpdates' );
|
487 |
-
$this->m_oAutoUpdatesProcessor->run();
|
488 |
-
}
|
489 |
-
|
490 |
-
protected function getAllOptions() {
|
491 |
-
$aOptionNames = array(
|
492 |
-
'm_oWpsfOptions',
|
493 |
-
'm_oFirewallOptions',
|
494 |
-
'm_oLoginProtectOptions',
|
495 |
-
'm_oCommentsFilterOptions',
|
496 |
-
'm_oLockdownOptions',
|
497 |
-
'm_oAutoUpdatesOptions'
|
498 |
-
);
|
499 |
-
|
500 |
-
$this->loadOptionsHandler('all');
|
501 |
-
$aOptions = array();
|
502 |
-
foreach( $aOptionNames as $sName ) {
|
503 |
-
if ( isset( $this->{$sName} ) ) {
|
504 |
-
$aOptions[] = &$this->{$sName};
|
505 |
-
}
|
506 |
-
}
|
507 |
-
return $aOptions;
|
508 |
-
}
|
509 |
-
|
510 |
-
protected function getAllProcessors() {
|
511 |
-
$aProcessorNames = array(
|
512 |
-
'firewall_processor' => 'm_oFirewallProcessor',
|
513 |
-
'login_processor' => 'm_oLoginProtectProcessor',
|
514 |
-
'comments_processor' => 'm_oCommentsFilterProcessor',
|
515 |
-
'lockdown_processor' => 'm_oLockdownProcessor',
|
516 |
-
'autoupdates_processor' => 'm_oAutoUpdatesProcessor',
|
517 |
-
'logging_processor' => 'm_oLoggingProcessor',
|
518 |
-
'email_processor' => 'm_oEmailProcessor'
|
519 |
-
);
|
520 |
-
$aProcessors = array();
|
521 |
-
foreach( $aProcessorNames as $sKey => $sName ) {
|
522 |
-
if ( isset( $this->{$sName} ) ) {
|
523 |
-
$aProcessors[$sKey] = &$this->{$sName};
|
524 |
-
}
|
525 |
-
}
|
526 |
-
return $aProcessors;
|
527 |
-
}
|
528 |
-
|
529 |
-
/**
|
530 |
-
* Make sure and cache the processors after all is said and done.
|
531 |
-
*/
|
532 |
-
public function saveProcessors_Action() {
|
533 |
-
|
534 |
-
$this->updateLogStore();
|
535 |
-
|
536 |
-
$aOptions = $this->getAllOptions();
|
537 |
-
foreach( $aOptions as &$oOption ) {
|
538 |
-
if ( isset( $oOption ) ) {
|
539 |
-
$oOption->savePluginOptions();
|
540 |
-
}
|
541 |
-
}
|
542 |
-
$aProcessors = $this->getAllProcessors();
|
543 |
-
foreach( $aProcessors as $sKey => &$oProcessor ) {
|
544 |
-
$oProcessor->store( self::getKey( $sKey ) );
|
545 |
-
}
|
546 |
-
}
|
547 |
-
|
548 |
-
public function onWpAdminInit() {
|
549 |
-
parent::onWpAdminInit();
|
550 |
-
|
551 |
-
// If it's a plugin admin page, we do certain things we don't do anywhere else.
|
552 |
-
if ( $this->isIcwpPluginAdminPage()) {
|
553 |
-
add_action( 'admin_enqueue_scripts', array( $this, 'enqueueBootstrapAdminCss' ), 99 );
|
554 |
-
}
|
555 |
-
|
556 |
-
// This is only done on WP Admin loads so as not to affect the front-end and only if the firewall is enabled
|
557 |
-
if ( $this->getIsMainFeatureEnabled( 'firewall' ) ) {
|
558 |
-
$this->filterIpLists();
|
559 |
-
}
|
560 |
-
|
561 |
-
//Multilingual support.
|
562 |
-
// load_plugin_textdomain( 'icwp-wpsf', false, basename( dirname( __FILE__ ) ) . '/languages' );
|
563 |
}
|
564 |
|
565 |
protected function createPluginSubMenuItems() {
|
566 |
-
|
567 |
-
if ( !$this->hasPermissionToView() ) {
|
568 |
-
return;
|
569 |
-
}
|
570 |
-
|
571 |
$this->m_aPluginMenu = array(
|
572 |
//Menu Page Title => Menu Item name, page ID (slug), callback function for this page - i.e. what to do/load.
|
573 |
-
$this->getSubmenuPageTitle( 'Firewall' )
|
574 |
-
$this->getSubmenuPageTitle( 'Login Protect' )
|
575 |
-
$this->getSubmenuPageTitle( 'Comments Filter' ) => array( 'Comments Filter', $this->getSubmenuId('comments_filter'), 'onDisplayAll' ),
|
576 |
-
$this->getSubmenuPageTitle( '
|
577 |
-
$this->getSubmenuPageTitle( '
|
578 |
-
$this->getSubmenuPageTitle( '
|
|
|
|
|
579 |
);
|
580 |
}
|
581 |
|
582 |
protected function handlePluginUpgrade() {
|
583 |
parent::handlePluginUpgrade();
|
584 |
|
585 |
-
$sCurrentPluginVersion = $this->
|
586 |
|
587 |
-
if ( $sCurrentPluginVersion !==
|
588 |
|
589 |
-
|
590 |
-
|
591 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
592 |
|
593 |
$this->loadProcessor( 'Logging' );
|
594 |
$this->m_oLoggingProcessor->handleInstallUpgrade( $sCurrentPluginVersion );
|
595 |
-
|
596 |
-
// handles migration to new dedicated options system
|
597 |
-
$this->loadOptionsHandler( 'all' );
|
598 |
|
599 |
// clears all the processor caches
|
600 |
$this->clearCaches();
|
601 |
-
|
602 |
-
// delete all the old stuff
|
603 |
-
$aOldOptionKeys = array (
|
604 |
-
'current_plugin_version',
|
605 |
-
'feedback_admin_notice',
|
606 |
-
'secret_key',
|
607 |
-
'block_send_email',
|
608 |
-
'block_send_email_address',
|
609 |
-
'send_email_throttle_limit',
|
610 |
-
'delete_on_deactivate',
|
611 |
-
'include_cookie_checks',
|
612 |
-
'block_dir_traversal',
|
613 |
-
'block_sql_queries',
|
614 |
-
'block_wordpress_terms',
|
615 |
-
'block_field_truncation',
|
616 |
-
'block_exe_file_uploads',
|
617 |
-
'block_leading_schema',
|
618 |
-
'ips_whitelist',
|
619 |
-
'ips_blacklist',
|
620 |
-
'page_params_whitelist',
|
621 |
-
'block_response',
|
622 |
-
'enable_firewall_log',
|
623 |
-
'enable_two_factor_auth_by_ip',
|
624 |
-
'enable_two_factor_bypass_on_email_fail',
|
625 |
-
'login_limit_interval',
|
626 |
-
'enable_login_gasp_check',
|
627 |
-
'enable_login_protect_log'
|
628 |
-
);
|
629 |
-
foreach( $aOldOptionKeys as $sOptionKey ) {
|
630 |
-
self::deleteOption( $sOptionKey );
|
631 |
-
}
|
632 |
-
}//if
|
633 |
-
|
634 |
-
//Someone clicked the button to acknowledge the update
|
635 |
-
if ( isset( $_POST[self::OptionPrefix.'hide_update_notice'] ) && isset( $_POST['user_id'] ) ) {
|
636 |
-
$this->updateVersionUserMeta( $_POST['user_id'] );
|
637 |
-
if ( $this->isShowMarketing() ) {
|
638 |
-
wp_redirect( admin_url( "admin.php?page=".$this->getFullParentMenuId() ) );
|
639 |
-
}
|
640 |
-
else {
|
641 |
-
wp_redirect( admin_url( $_POST['redirect_page'] ) );
|
642 |
-
}
|
643 |
-
}
|
644 |
-
if ( isset( $_POST[self::OptionPrefix.'hide_translation_notice'] ) && isset( $_POST['user_id'] ) ) {
|
645 |
-
$this->updateTranslationNoticeShownUserMeta( $_POST['user_id'] );
|
646 |
-
wp_redirect( admin_url( $_POST['redirect_page'] ) );
|
647 |
-
}
|
648 |
-
}
|
649 |
-
|
650 |
-
/**
|
651 |
-
* Updates the current (or supplied user ID) user meta data with the version of the plugin
|
652 |
-
*
|
653 |
-
* @param unknown_type $innId
|
654 |
-
*/
|
655 |
-
protected function updateVersionUserMeta( $innId = '' ) {
|
656 |
-
$this->updateUserMeta( 'current_version', self::$VERSION, $innId );
|
657 |
-
}
|
658 |
-
|
659 |
-
/**
|
660 |
-
* Updates the current (or supplied user ID) user meta data with the version of the plugin
|
661 |
-
*
|
662 |
-
* @param unknown_type $innId
|
663 |
-
*/
|
664 |
-
protected function updateTranslationNoticeShownUserMeta( $innId = '', $insValue = 'Y' ) {
|
665 |
-
$this->updateUserMeta( 'plugin_translation_notice', $insValue, $innId );
|
666 |
-
}
|
667 |
-
|
668 |
-
/**
|
669 |
-
* Updates the current (or supplied user ID) user meta data with the version of the plugin
|
670 |
-
*
|
671 |
-
* @param unknown_type $innId
|
672 |
-
*/
|
673 |
-
protected function updateUserMeta( $insKey, $inmValue, $innId = null ) {
|
674 |
-
if ( empty( $innId ) ) {
|
675 |
-
$oCurrentUser = wp_get_current_user();
|
676 |
-
if ( !($oCurrentUser instanceof WP_User) ) {
|
677 |
-
return;
|
678 |
-
}
|
679 |
-
$nUserId = $oCurrentUser->ID;
|
680 |
-
}
|
681 |
-
else {
|
682 |
-
$nUserId = $innId;
|
683 |
-
}
|
684 |
-
update_user_meta( $nUserId, self::OptionPrefix.$insKey, $inmValue );
|
685 |
-
}
|
686 |
-
|
687 |
-
public function onWpAdminNotices() {
|
688 |
-
// Do we have admin priviledges?
|
689 |
-
if ( !current_user_can( 'manage_options' ) ) {
|
690 |
-
return;
|
691 |
-
}
|
692 |
-
parent::onWpAdminNotices();
|
693 |
-
$this->adminNoticeOptionsUpdated();
|
694 |
-
|
695 |
-
if ( $this->hasPermissionToView() ) {
|
696 |
-
$this->adminNoticeVersionUpgrade();
|
697 |
-
}
|
698 |
-
|
699 |
-
if ( $this->hasPermissionToView() ) {
|
700 |
-
$this->adminNoticeTranslations();
|
701 |
}
|
702 |
}
|
703 |
|
@@ -711,14 +302,21 @@ class ICWP_Wordpress_Simple_Firewall extends ICWP_WPSF_Base_Plugin {
|
|
711 |
$this->onDisplayAccessKeyRequest();
|
712 |
return;
|
713 |
}
|
714 |
-
|
715 |
-
|
|
|
|
|
|
|
|
|
716 |
$sCurrent = str_replace( $sPrefix, '', current_filter() );
|
717 |
-
|
718 |
switch( $sCurrent ) {
|
719 |
-
case 'toplevel_page_'.self::
|
720 |
$this->onDisplayMainMenu();
|
721 |
break;
|
|
|
|
|
|
|
722 |
case 'firewall_log' :
|
723 |
$this->onDisplayFirewallLog();
|
724 |
break;
|
@@ -732,40 +330,30 @@ class ICWP_Wordpress_Simple_Firewall extends ICWP_WPSF_Base_Plugin {
|
|
732 |
}
|
733 |
|
734 |
public function onDisplayAccessKeyRequest() {
|
735 |
-
|
736 |
-
// Since this is always called until we have Permission, we have to handle the plugin
|
737 |
-
// form submission here too.
|
738 |
$aData = array(
|
739 |
-
'plugin_url' => self::$PLUGIN_URL,
|
740 |
-
'var_prefix' => self::OptionPrefix,
|
741 |
'nonce_field' => $this->getSubmenuId( 'wpsf-access-key' ),
|
742 |
-
'form_action' => 'admin.php?page='.$this->getSubmenuId()
|
743 |
);
|
|
|
744 |
$this->display( 'icwp_wpsf_access_key_request_index', $aData );
|
745 |
}
|
746 |
|
747 |
public function onDisplayMainMenu() {
|
748 |
|
749 |
-
|
750 |
-
|
751 |
-
$this->
|
752 |
-
|
753 |
-
$
|
754 |
-
$aAvailableOptions = $this->m_oWpsfOptions->getOptions();
|
755 |
-
$sAllFormInputOptions = $this->m_oWpsfOptions->collateAllFormInputsForAllOptions();
|
756 |
|
757 |
$aData = array(
|
758 |
-
'plugin_url' => self::$PLUGIN_URL,
|
759 |
-
'var_prefix' => self::OptionPrefix,
|
760 |
'aAllOptions' => $aAvailableOptions,
|
761 |
-
'fShowAds' => $this->isShowMarketing(),
|
762 |
'all_options_input' => $sAllFormInputOptions,
|
763 |
-
'nonce_field' => $this->getSubmenuId('wpsf-dashboard'),
|
764 |
-
'form_action' => 'admin.php?page='.$this->getSubmenuId()
|
765 |
);
|
|
|
|
|
|
|
|
|
766 |
|
767 |
-
$aData['aMainOptions'] = $this->m_oWpsfOptions->getPluginOptionsValues();
|
768 |
-
|
769 |
if ( $this->getIsMainFeatureEnabled('firewall') ) {
|
770 |
$this->loadOptionsHandler( 'Firewall' );
|
771 |
$aData['aFirewallOptions'] = $this->m_oFirewallOptions->getPluginOptionsValues();
|
@@ -786,87 +374,129 @@ class ICWP_Wordpress_Simple_Firewall extends ICWP_WPSF_Base_Plugin {
|
|
786 |
$this->loadOptionsHandler( 'AutoUpdates' );
|
787 |
$aData['aAutoUpdatesOptions'] = $this->m_oAutoUpdatesOptions->getPluginOptionsValues();
|
788 |
}
|
789 |
-
|
790 |
$this->display( 'icwp_'.$this->m_sParentMenuIdSuffix.'_index', $aData );
|
791 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
792 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
793 |
protected function onDisplayFirewallLog() {
|
794 |
|
795 |
$this->loadOptionsHandler( 'Firewall' );
|
796 |
$aIpWhitelist = $this->m_oFirewallOptions->getOpt( 'ips_whitelist' );
|
797 |
$aIpBlacklist = $this->m_oFirewallOptions->getOpt( 'ips_blacklist' );
|
798 |
-
|
799 |
$this->loadProcessor( 'Logging' );
|
800 |
|
|
|
801 |
$aData = array(
|
802 |
-
'
|
803 |
-
'var_prefix' => self::OptionPrefix,
|
804 |
-
'firewall_log' => $this->m_oLoggingProcessor->getLogs( true ),
|
805 |
'ip_whitelist' => isset( $aIpWhitelist['ips'] )? $aIpWhitelist['ips'] : array(),
|
806 |
'ip_blacklist' => isset( $aIpBlacklist['ips'] )? $aIpBlacklist['ips'] : array(),
|
807 |
-
'fShowAds' => $this->isShowMarketing(),
|
808 |
-
'nonce_field' => $this->getSubmenuId('firewall_log'),
|
809 |
-
'form_action' => 'admin.php?page='.$this->getSubmenuId('firewall_log'),
|
810 |
);
|
811 |
-
|
812 |
$this->display( 'icwp_wpsf_firewall_log_index', $aData );
|
813 |
}
|
814 |
-
|
815 |
/**
|
816 |
*
|
817 |
* @param ICWP_OptionsHandler_Base_WPSF $inoOptions
|
818 |
* @param string $insSlug
|
819 |
*/
|
820 |
protected function onDisplayConfig( $inoOptions, $insSlug ) {
|
821 |
-
|
822 |
$aAvailableOptions = $inoOptions->getOptions();
|
823 |
$sAllFormInputOptions = $inoOptions->collateAllFormInputsForAllOptions();
|
824 |
|
825 |
$aData = array(
|
826 |
-
'plugin_url' => self::$PLUGIN_URL,
|
827 |
-
'var_prefix' => self::OptionPrefix,
|
828 |
-
'fShowAds' => $this->isShowMarketing(),
|
829 |
'aAllOptions' => $aAvailableOptions,
|
830 |
'all_options_input' => $sAllFormInputOptions,
|
831 |
-
'nonce_field' => $this->getSubmenuId( $insSlug ),
|
832 |
-
'form_action' => 'admin.php?page='.$this->getSubmenuId( $insSlug ),
|
833 |
);
|
|
|
834 |
$this->display( 'icwp_wpsf_config_'.$insSlug.'_index', $aData );
|
835 |
}
|
836 |
-
|
837 |
-
|
|
|
|
|
|
|
838 |
|
839 |
-
$
|
|
|
|
|
|
|
|
|
840 |
'icwp_plugin_form_submit',
|
841 |
'icwp_link_action',
|
842 |
'icwp_wpsf_admin_access_key_request'
|
843 |
);
|
844 |
-
|
845 |
-
|
846 |
-
if ( isset( $_POST[$sOption] ) || isset( $_GET[$sOption] ) ) {
|
847 |
return true;
|
848 |
}
|
849 |
}
|
850 |
-
return false;
|
851 |
}
|
852 |
|
853 |
protected function handlePluginFormSubmit() {
|
854 |
-
|
855 |
-
//should have already been checked, but just to make sure.
|
856 |
-
if ( !$this->isPluginFormSubmit() ) {
|
857 |
-
return false;
|
858 |
-
}
|
859 |
-
|
860 |
-
if ( isset( $_POST['icwp_wpsf_admin_access_key_request'] ) ) {
|
861 |
return $this->handleSubmit_AccessKeyRequest();
|
862 |
}
|
863 |
|
864 |
-
if ( !$this->hasPermissionToSubmit() ) {
|
865 |
return false;
|
866 |
}
|
867 |
-
|
868 |
-
|
869 |
-
|
|
|
870 |
case $this->getSubmenuId():
|
871 |
$this->handleSubmit_Dashboard();
|
872 |
break;
|
@@ -888,21 +518,27 @@ class ICWP_Wordpress_Simple_Firewall extends ICWP_WPSF_Base_Plugin {
|
|
888 |
case $this->getSubmenuId( 'firewall_log' ):
|
889 |
$this->handleSubmit_FirewallLog();
|
890 |
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
891 |
default:
|
892 |
return false;
|
893 |
break;
|
894 |
}
|
895 |
}
|
896 |
-
$this->
|
897 |
return true;
|
898 |
}
|
899 |
|
900 |
protected function setPermissionToSubmit( $infPermission = false ) {
|
901 |
-
|
902 |
if ( $infPermission ) {
|
903 |
-
$
|
904 |
-
$
|
905 |
-
$
|
|
|
906 |
setcookie( self::AdminAccessKeyCookieName, $sValue, time()+$sTimeout, COOKIEPATH, COOKIE_DOMAIN, false );
|
907 |
}
|
908 |
else {
|
@@ -911,51 +547,57 @@ class ICWP_Wordpress_Simple_Firewall extends ICWP_WPSF_Base_Plugin {
|
|
911 |
}
|
912 |
}
|
913 |
|
914 |
-
/**
|
915 |
-
* @return boolean
|
916 |
-
*/
|
917 |
-
protected function hasPermissionToView() {
|
918 |
-
// For now we just use the submit permissions and we can adapt it later
|
919 |
-
return $this->hasPermissionToSubmit();
|
920 |
-
}
|
921 |
-
|
922 |
/**
|
923 |
* @return boolean
|
924 |
*/
|
925 |
protected function hasPermissionToSubmit() {
|
926 |
-
|
927 |
-
|
928 |
-
|
929 |
-
return false;
|
930 |
}
|
931 |
-
|
932 |
-
|
933 |
-
|
|
|
|
|
|
|
|
|
934 |
if ( !empty( $sAccessKey ) ) {
|
935 |
-
|
936 |
-
|
937 |
-
|
938 |
-
return true;
|
939 |
-
}
|
940 |
-
else {
|
941 |
-
return false;
|
942 |
-
}
|
943 |
}
|
944 |
}
|
945 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
946 |
}
|
947 |
|
948 |
protected function handleSubmit_AccessKeyRequest() {
|
949 |
//Ensures we're actually getting this request from WP.
|
950 |
check_admin_referer( $this->getSubmenuId('wpsf-access-key') );
|
951 |
|
952 |
-
$this->loadOptionsHandler( '
|
953 |
-
$sAccessKey = md5( trim( $
|
954 |
-
$sStoredAccessKey = $this->
|
955 |
|
956 |
if ( $sAccessKey === $sStoredAccessKey ) {
|
957 |
$this->setPermissionToSubmit( true );
|
958 |
-
header( 'Location: '.
|
959 |
exit();
|
960 |
}
|
961 |
return false;
|
@@ -963,22 +605,35 @@ class ICWP_Wordpress_Simple_Firewall extends ICWP_WPSF_Base_Plugin {
|
|
963 |
|
964 |
protected function handleSubmit_Dashboard() {
|
965 |
//Ensures we're actually getting this request from WP.
|
966 |
-
check_admin_referer( $this->getSubmenuId(
|
967 |
|
968 |
-
|
|
|
969 |
return false;
|
970 |
}
|
971 |
|
972 |
-
$this->loadOptionsHandler( '
|
973 |
-
$this->
|
974 |
-
|
975 |
-
$this->
|
976 |
-
$this->
|
977 |
-
|
978 |
-
$this->setSharedOption( '
|
979 |
-
$this->setSharedOption( '
|
980 |
-
|
|
|
|
|
|
|
|
|
|
|
981 |
$this->clearCaches();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
982 |
}
|
983 |
|
984 |
protected function handleSubmit_FirewallConfig() {
|
@@ -988,428 +643,402 @@ class ICWP_Wordpress_Simple_Firewall extends ICWP_WPSF_Base_Plugin {
|
|
988 |
if ( isset($_POST[ 'import-wpf2-submit' ] ) ) {
|
989 |
$this->importFromFirewall2Plugin();
|
990 |
}
|
991 |
-
else if ( !isset($_POST[self
|
992 |
return;
|
993 |
}
|
994 |
else {
|
995 |
$this->loadOptionsHandler( 'Firewall' );
|
996 |
-
$this->m_oFirewallOptions->updatePluginOptionsFromSubmit( $_POST[self
|
997 |
}
|
998 |
$this->setSharedOption( 'enable_firewall', $this->m_oFirewallOptions->getOpt( 'enable_firewall' ) );
|
999 |
-
$this->
|
1000 |
}
|
1001 |
-
|
1002 |
protected function handleSubmit_LoginProtect() {
|
1003 |
//Ensures we're actually getting this request from WP.
|
1004 |
check_admin_referer( $this->getSubmenuId('login_protect' ) );
|
1005 |
-
|
1006 |
-
if (
|
|
|
|
|
|
|
|
|
|
|
|
|
1007 |
return;
|
1008 |
}
|
1009 |
$this->loadOptionsHandler( 'LoginProtect' );
|
1010 |
-
$this->m_oLoginProtectOptions->updatePluginOptionsFromSubmit( $_POST[self
|
1011 |
$this->setSharedOption( 'enable_login_protect', $this->m_oLoginProtectOptions->getOpt( 'enable_login_protect' ) );
|
1012 |
-
$this->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1013 |
}
|
1014 |
|
1015 |
protected function handleSubmit_CommentsFilter() {
|
1016 |
//Ensures we're actually getting this request from WP.
|
1017 |
check_admin_referer( $this->getSubmenuId('comments_filter' ) );
|
1018 |
|
1019 |
-
if ( !isset($_POST[self
|
1020 |
return;
|
1021 |
}
|
1022 |
$this->loadOptionsHandler( 'CommentsFilter' );
|
1023 |
-
$this->m_oCommentsFilterOptions->updatePluginOptionsFromSubmit( $_POST[self
|
1024 |
$this->setSharedOption( 'enable_comments_filter', $this->m_oCommentsFilterOptions->getOpt( 'enable_comments_filter' ) );
|
1025 |
-
$this->
|
1026 |
}
|
1027 |
|
1028 |
protected function handleSubmit_Lockdown() {
|
1029 |
//Ensures we're actually getting this request from WP.
|
1030 |
check_admin_referer( $this->getSubmenuId('lockdown' ) );
|
1031 |
|
1032 |
-
if ( !isset($_POST[self
|
1033 |
return;
|
1034 |
}
|
1035 |
$this->loadOptionsHandler( 'Lockdown' );
|
1036 |
-
$this->m_oLockdownOptions->updatePluginOptionsFromSubmit( $_POST[self
|
1037 |
$this->setSharedOption( 'enable_lockdown', $this->m_oLockdownOptions->getOpt( 'enable_lockdown' ) );
|
1038 |
-
$this->
|
1039 |
}
|
1040 |
|
1041 |
protected function handleSubmit_AutoUpdates() {
|
1042 |
//Ensures we're actually getting this request from WP.
|
1043 |
check_admin_referer( $this->getSubmenuId( 'autoupdates' ) );
|
1044 |
|
1045 |
-
if (
|
|
|
|
|
|
|
|
|
|
|
|
|
1046 |
return;
|
1047 |
}
|
1048 |
$this->loadOptionsHandler( 'AutoUpdates' );
|
1049 |
-
$this->m_oAutoUpdatesOptions->updatePluginOptionsFromSubmit( $_POST[self
|
1050 |
$this->setSharedOption( 'enable_autoupdates', $this->m_oAutoUpdatesOptions->getOpt( 'enable_autoupdates' ) );
|
1051 |
-
$this->
|
1052 |
}
|
1053 |
|
1054 |
protected function handleSubmit_FirewallLog() {
|
1055 |
|
1056 |
// Ensures we're actually getting this request from a valid WP submission.
|
1057 |
-
|
|
|
1058 |
wp_die();
|
1059 |
}
|
|
|
|
|
1060 |
|
1061 |
// At the time of writing the page only has 1 form submission item - clear log
|
1062 |
-
if (
|
1063 |
$this->loadProcessor( 'Logging' );
|
1064 |
$this->m_oLoggingProcessor->recreateTable();
|
1065 |
}
|
1066 |
-
else
|
1067 |
-
$this->addRawIpsToFirewallList( '
|
|
|
|
|
|
|
|
|
1068 |
}
|
1069 |
-
|
1070 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1071 |
}
|
1072 |
-
|
1073 |
-
|
|
|
|
|
|
|
|
|
|
|
1074 |
}
|
1075 |
-
else
|
1076 |
-
$this->
|
|
|
|
|
|
|
|
|
1077 |
}
|
1078 |
-
wp_safe_redirect(
|
1079 |
exit();
|
1080 |
}
|
1081 |
-
|
1082 |
-
public function clearCaches() {
|
1083 |
-
$this->resetFirewallProcessor();
|
1084 |
-
$this->resetLoginProcessor();
|
1085 |
-
$this->resetLoggingProcessor();
|
1086 |
-
$this->resetCommentsProcessor();
|
1087 |
-
}
|
1088 |
-
|
1089 |
-
protected function resetEmailProcessor() {
|
1090 |
-
$this->m_oEmailProcessor = false;
|
1091 |
-
self::deleteOption( 'email_processor' );
|
1092 |
-
$this->loadProcessor( 'Email' );
|
1093 |
-
}
|
1094 |
-
|
1095 |
-
protected function resetFirewallProcessor() {
|
1096 |
-
$this->resetEmailProcessor();
|
1097 |
-
$this->m_oFirewallProcessor = false;
|
1098 |
-
self::deleteOption( 'firewall_processor' );
|
1099 |
-
$this->loadProcessor( 'Firewall' );
|
1100 |
-
}
|
1101 |
-
|
1102 |
-
protected function resetLoginProcessor() {
|
1103 |
-
$this->m_oLoginProtectProcessor = false;
|
1104 |
-
self::deleteOption( 'login_processor' );
|
1105 |
-
$this->loadProcessor( 'LoginProtect' );
|
1106 |
-
}
|
1107 |
-
|
1108 |
-
protected function resetCommentsProcessor() {
|
1109 |
-
$this->m_oCommentsFilterProcessor = false;
|
1110 |
-
self::deleteOption( 'comments_processor' );
|
1111 |
-
$this->loadProcessor( 'CommentsFilter' );
|
1112 |
-
}
|
1113 |
-
|
1114 |
-
protected function resetLockdownProcessor() {
|
1115 |
-
$this->m_oLockdownProcessor = false;
|
1116 |
-
self::deleteOption( 'lockdown_processor' );
|
1117 |
-
$this->loadProcessor( 'Lockdown' );
|
1118 |
-
}
|
1119 |
-
|
1120 |
-
protected function resetAutoUpdatesProcessor() {
|
1121 |
-
$this->m_oLockdownProcessor = false;
|
1122 |
-
self::deleteOption( 'autoupdates_processor' );
|
1123 |
-
$this->loadProcessor( 'AutoUpdates' );
|
1124 |
-
}
|
1125 |
-
|
1126 |
-
protected function resetLoggingProcessor() {
|
1127 |
-
$this->m_oLoggingProcessor = false;
|
1128 |
-
self::deleteOption( 'logging_processor' );
|
1129 |
-
$this->loadProcessor( 'Logging' );
|
1130 |
-
}
|
1131 |
-
|
1132 |
protected function importFromFirewall2Plugin() {
|
1133 |
$this->loadOptionsHandler( 'all' );
|
1134 |
require_once( dirname(__FILE__).'/src/icwp-import-wpf2-processor.php' );
|
1135 |
-
$oImportProcessor = new ICWP_ImportWpf2Processor( $this->
|
1136 |
$oImportProcessor->runImport();
|
1137 |
}
|
1138 |
|
1139 |
-
public function onWpPluginActionLinks( $inaActionLinks, $insFile ) {
|
1140 |
-
|
1141 |
-
if ( $insFile == plugin_basename( __FILE__ ) ) {
|
1142 |
-
if ( !$this->hasPermissionToSubmit() ) {
|
1143 |
-
if ( array_key_exists( 'edit', $inaActionLinks ) ) {
|
1144 |
-
unset( $inaActionLinks['edit'] );
|
1145 |
-
}
|
1146 |
-
if ( array_key_exists( 'deactivate', $inaActionLinks ) ) {
|
1147 |
-
unset( $inaActionLinks['deactivate'] );
|
1148 |
-
}
|
1149 |
-
}
|
1150 |
-
$sSettingsLink = '<a href="'.admin_url( "admin.php" ).'?page='.$this->getSubmenuId().'">' . 'Dashboard' . '</a>';
|
1151 |
-
array_unshift( $inaActionLinks, $sSettingsLink );
|
1152 |
-
}
|
1153 |
-
return $inaActionLinks;
|
1154 |
-
}
|
1155 |
-
|
1156 |
public function onWpPluginsLoaded() {
|
1157 |
parent::onWpPluginsLoaded();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1158 |
|
1159 |
if ( $this->isValidAdminArea()
|
1160 |
-
&& $this->
|
1161 |
&& $this->hasPermissionToSubmit()
|
1162 |
) {
|
1163 |
$this->m_fDoAutoUpdateCheck = true;
|
1164 |
}
|
1165 |
-
|
1166 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1167 |
|
1168 |
-
|
1169 |
-
|
|
|
|
|
|
|
1170 |
}
|
1171 |
-
|
1172 |
/**
|
1173 |
-
* @
|
1174 |
*/
|
1175 |
-
|
1176 |
-
|
1177 |
-
|
1178 |
-
|
1179 |
-
);
|
1180 |
}
|
|
|
1181 |
}
|
1182 |
-
|
1183 |
-
|
1184 |
-
|
1185 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
1186 |
}
|
1187 |
|
1188 |
-
|
1189 |
-
|
1190 |
-
|
1191 |
-
|
1192 |
-
|
1193 |
-
|
1194 |
-
|
1195 |
-
$this->loadProcessor( 'Logging' );
|
1196 |
-
$this->m_oLoggingProcessor->dropTable();
|
1197 |
-
|
1198 |
-
$this->loadProcessor( 'LoginProtect' );
|
1199 |
-
$this->m_oLoginProtectProcessor->dropTable();
|
1200 |
|
1201 |
-
$this->
|
1202 |
-
|
|
|
|
|
|
|
|
|
|
|
1203 |
|
1204 |
-
$
|
1205 |
-
|
1206 |
-
$
|
|
|
|
|
|
|
1207 |
}
|
1208 |
-
remove_action( 'shutdown', array( $this, 'onWpShutdown' ) );
|
1209 |
}
|
1210 |
|
1211 |
-
|
1212 |
-
|
1213 |
-
|
1214 |
-
. '</div>';
|
1215 |
}
|
1216 |
-
|
1217 |
-
|
1218 |
-
|
1219 |
-
$this->deleteAllPluginDbOptions();
|
1220 |
-
}
|
1221 |
}
|
1222 |
|
1223 |
-
|
1224 |
-
wp_register_style( 'worpit_bootstrap_wpadmin_css', $this->getCssUrl( 'bootstrap-wpadmin.css' ), false, self::$VERSION );
|
1225 |
-
wp_enqueue_style( 'worpit_bootstrap_wpadmin_css' );
|
1226 |
-
wp_register_style( 'worpit_bootstrap_wpadmin_css_fixes', $this->getCssUrl('bootstrap-wpadmin-fixes.css'), array('worpit_bootstrap_wpadmin_css'), self::$VERSION );
|
1227 |
-
wp_enqueue_style( 'worpit_bootstrap_wpadmin_css_fixes' );
|
1228 |
-
}
|
1229 |
-
|
1230 |
-
public function addRawIpsToFirewallList( $insListName, $inaNewIps ) {
|
1231 |
|
1232 |
-
$this->
|
1233 |
-
|
1234 |
-
$aIplist = $this->m_oFirewallOptions->getOpt( $insListName );
|
1235 |
-
if ( empty( $aIplist ) ) {
|
1236 |
-
$aIplist = array();
|
1237 |
}
|
1238 |
-
$aNewList = array();
|
1239 |
-
foreach( $inaNewIps as $sAddress ) {
|
1240 |
-
$aNewList[ $sAddress ] = '';
|
1241 |
-
}
|
1242 |
-
$aIplist = $this->m_oFirewallOptions->setOpt( $insListName, ICWP_DataProcessor::Add_New_Raw_Ips( $aIplist, $aNewList ) );
|
1243 |
-
$this->resetFirewallProcessor();
|
1244 |
-
}
|
1245 |
|
1246 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1247 |
|
1248 |
-
|
1249 |
-
|
1250 |
-
|
1251 |
-
if ( empty( $aIplist ) || empty( $inaRemoveIps ) ) {
|
1252 |
-
return;
|
1253 |
}
|
1254 |
-
|
1255 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1256 |
}
|
1257 |
-
|
1258 |
/**
|
|
|
1259 |
*/
|
1260 |
-
protected function
|
1261 |
-
|
1262 |
-
$
|
1263 |
-
|
1264 |
-
|
1265 |
-
$this->m_oFirewallOptions->setOpt( 'ips_whitelist', $mResult );
|
1266 |
-
$this->resetFirewallProcessor();
|
1267 |
-
}
|
1268 |
-
|
1269 |
-
$nNewAddedCount = 0;
|
1270 |
-
$mResult = $this->processIpFilter( 'ips_blacklist', 'icwp_simple_firewall_blacklist_ips', $nNewAddedCount );
|
1271 |
-
if ( $mResult !== false && $nNewAddedCount > 0 ) {
|
1272 |
-
$this->m_oFirewallOptions->setOpt( 'ips_blacklist', $mResult );
|
1273 |
-
$this->resetFirewallProcessor();
|
1274 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1275 |
}
|
1276 |
|
1277 |
-
|
1278 |
-
|
1279 |
-
|
1280 |
-
|
1281 |
-
|
1282 |
-
|
1283 |
-
protected function processIpFilter( $insExistingListKey, $insFilterName, &$outnNewAdded = 0 ) {
|
1284 |
-
|
1285 |
-
$aFilterIps = array();
|
1286 |
-
$aFilterIps = apply_filters( $insFilterName, $aFilterIps );
|
1287 |
-
|
1288 |
-
if ( !empty( $aFilterIps ) ) {
|
1289 |
-
|
1290 |
-
$aNewIps = array();
|
1291 |
-
foreach( $aFilterIps as $mKey => $sValue ) {
|
1292 |
-
|
1293 |
-
if ( is_string( $mKey ) ) { //it's the IP
|
1294 |
-
$sIP = $mKey;
|
1295 |
-
$sLabel = $sValue;
|
1296 |
-
}
|
1297 |
-
else { //it's not an associative array, so the value is the IP
|
1298 |
-
$sIP = $sValue;
|
1299 |
-
$sLabel = '';
|
1300 |
-
}
|
1301 |
-
$aNewIps[ $sIP ] = $sLabel;
|
1302 |
-
}
|
1303 |
-
|
1304 |
-
// Get the existing list
|
1305 |
-
$this->loadOptionsHandler( 'Firewall' );
|
1306 |
-
$aExistingIpList = $this->m_oFirewallOptions->getOpt( $insExistingListKey );
|
1307 |
-
if ( !is_array( $aExistingIpList ) ) {
|
1308 |
-
$aExistingIpList = array();
|
1309 |
-
}
|
1310 |
-
return ICWP_DataProcessor::Add_New_Raw_Ips( $aExistingIpList, $aNewIps, $outnNewAdded );
|
1311 |
}
|
1312 |
-
return false;
|
1313 |
}
|
1314 |
|
1315 |
-
|
1316 |
-
|
1317 |
-
|
1318 |
-
|
1319 |
-
|
1320 |
-
}
|
1321 |
-
$nUserId = $oCurrentUser->ID;
|
1322 |
-
|
1323 |
-
$sAlreadyShowTranslationNotice = get_user_meta( $nUserId, self::OptionPrefix.'plugin_translation_notice', true );
|
1324 |
-
// A guard whereby if we can't ever get a value for this meta, it means we can never set it.
|
1325 |
-
if ( empty( $sAlreadyShowTranslationNotice ) ) {
|
1326 |
-
//the value has never been set, or it's been installed for the first time.
|
1327 |
-
$this->updateTranslationNoticeShownUserMeta( $nUserId, 'M' );
|
1328 |
-
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.
|
1329 |
-
}
|
1330 |
-
|
1331 |
-
if ( $sAlreadyShowTranslationNotice !== 'Y' ) {
|
1332 |
-
|
1333 |
-
$sRedirectPage = isset( $GLOBALS['pagenow'] ) ? $GLOBALS['pagenow'] : 'index.php';
|
1334 |
-
ob_start();
|
1335 |
-
?>
|
1336 |
-
<style>
|
1337 |
-
a#fromIcwp { padding: 0 5px; border-bottom: 1px dashed rgba(0,0,0,0.1); color: blue; font-weight: bold; }
|
1338 |
-
</style>
|
1339 |
-
<form id="IcwpUpdateNotice" method="post" action="admin.php?page=<?php echo $this->getSubmenuId('firewall'); ?>">
|
1340 |
-
<input type="hidden" value="<?php echo $sRedirectPage; ?>" name="redirect_page" id="redirect_page">
|
1341 |
-
<input type="hidden" value="1" name="<?php echo self::OptionPrefix; ?>hide_translation_notice" id="<?php echo self::OptionPrefix; ?>hide_translation_notice">
|
1342 |
-
<input type="hidden" value="<?php echo $nUserId; ?>" name="user_id" id="user_id">
|
1343 |
-
<h4 style="margin:10px 0 3px;">
|
1344 |
-
<?php _wpsf_e( 'Would you like to help translate the WordPress Simple Firewall into your language?' ); ?>
|
1345 |
-
<?php printf( _wpsf__( 'Head over to: %s' ), '<a href="http://translate.icontrolwp.com" target="_blank">translate.icontrolwp.com</a>' ); ?>
|
1346 |
-
</h4>
|
1347 |
-
<input type="submit" value="<?php _wpsf_e( 'Dismiss this notice' ); ?>" name="submit" class="button" style="float:left; margin-bottom:10px;">
|
1348 |
-
<div style="clear:both;"></div>
|
1349 |
-
</form>
|
1350 |
-
<?php
|
1351 |
-
$sNotice = ob_get_contents();
|
1352 |
-
ob_end_clean();
|
1353 |
-
$this->getAdminNotice( $sNotice, 'updated', true );
|
1354 |
-
}
|
1355 |
}
|
1356 |
-
|
1357 |
/**
|
1358 |
-
*
|
1359 |
*/
|
1360 |
-
|
1361 |
-
|
1362 |
-
$
|
1363 |
-
if (
|
1364 |
-
return;
|
1365 |
-
}
|
1366 |
-
$nUserId = $oCurrentUser->ID;
|
1367 |
-
$sCurrentVersion = get_user_meta( $nUserId, self::OptionPrefix.'current_version', true );
|
1368 |
-
// A guard whereby if we can't ever get a value for this meta, it means we can never set it.
|
1369 |
-
// If we can never set it, we shouldn't force the Ads on those users who can't get rid of it.
|
1370 |
-
if ( empty( $sCurrentVersion ) ) { //the value has never been set, or it's been installed for the first time.
|
1371 |
-
$this->updateVersionUserMeta( $nUserId );
|
1372 |
-
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.
|
1373 |
-
}
|
1374 |
-
|
1375 |
-
if ( $sCurrentVersion !== self::$VERSION ) {
|
1376 |
-
|
1377 |
-
$sRedirectPage = isset( $GLOBALS['pagenow'] ) ? $GLOBALS['pagenow'] : 'index.php';
|
1378 |
-
$sRedirectPage = 'admin.php?page=icwp-wpsf';
|
1379 |
-
ob_start();
|
1380 |
-
?>
|
1381 |
-
<style>
|
1382 |
-
a#fromIcwp { padding: 0 5px; border-bottom: 1px dashed rgba(0,0,0,0.1); color: blue; font-weight: bold; }
|
1383 |
-
</style>
|
1384 |
-
<form id="IcwpUpdateNotice" method="post" action="admin.php?page=<?php echo $this->getSubmenuId('firewall'); ?>">
|
1385 |
-
<input type="hidden" value="<?php echo $sRedirectPage; ?>" name="redirect_page" id="redirect_page">
|
1386 |
-
<input type="hidden" value="1" name="<?php echo self::OptionPrefix; ?>hide_update_notice" id="<?php echo self::OptionPrefix; ?>hide_update_notice">
|
1387 |
-
<input type="hidden" value="<?php echo $nUserId; ?>" name="user_id" id="user_id">
|
1388 |
-
<h4 style="margin:10px 0 3px;">
|
1389 |
-
<?php _wpsf_e( 'Note: WordPress Simple Firewall plugin does not automatically turn on when you install/update.' ); ?>
|
1390 |
-
<?php printf( _wpsf__( 'There may also be %simportant updates to read about%s.' ), '<a href="http://icwp.io/27" id="fromIcwp" title="WordPress Simple Firewall" target="_blank">', '</a>' ); ?>
|
1391 |
-
</h4>
|
1392 |
-
<input type="submit" value="Okay, show me the dashboard." name="submit" class="button" style="float:left; margin-bottom:10px;">
|
1393 |
-
<div style="clear:both;"></div>
|
1394 |
-
</form>
|
1395 |
-
<?php
|
1396 |
-
$sNotice = ob_get_contents();
|
1397 |
-
ob_end_clean();
|
1398 |
-
$this->getAdminNotice( $sNotice, 'updated', true );
|
1399 |
}
|
|
|
1400 |
}
|
1401 |
-
|
1402 |
-
|
1403 |
-
|
1404 |
-
$
|
1405 |
-
|
1406 |
-
|
1407 |
-
|
1408 |
-
|
1409 |
-
|
1410 |
}
|
1411 |
}
|
1412 |
|
1413 |
endif;
|
1414 |
|
1415 |
-
$oICWP_Wpsf =
|
3 |
* Plugin Name: WordPress Simple Firewall
|
4 |
* Plugin URI: http://icwp.io/2f
|
5 |
* Description: A Simple WordPress Firewall
|
6 |
+
* Version: 2.6.6
|
7 |
* Text Domain: wp-simple-firewall
|
8 |
* Author: iControlWP
|
9 |
* Author URI: http://icwp.io/2e
|
10 |
*/
|
11 |
|
12 |
/**
|
13 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
14 |
* All rights reserved.
|
15 |
*
|
16 |
* "WordPress Simple Firewall" is
|
30 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
31 |
*/
|
32 |
|
33 |
+
require_once( dirname(__FILE__).'/src/icwp-feature-master.php' );
|
34 |
require_once( dirname(__FILE__).'/src/icwp-data-processor.php' );
|
35 |
|
36 |
if ( !function_exists( '_wpsf_e' ) ) {
|
46 |
|
47 |
if ( !class_exists('ICWP_Wordpress_Simple_Firewall') ):
|
48 |
|
49 |
+
class ICWP_Wordpress_Simple_Firewall extends ICWP_Feature_Master {
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Should be updated each new release.
|
53 |
+
* @var string
|
54 |
+
*/
|
55 |
+
const PluginVersion = '2.6.6';
|
56 |
|
57 |
+
/**
|
58 |
+
* @var string
|
59 |
+
*/
|
60 |
+
const PluginTextDomain = 'wp-simple-firewall';
|
61 |
/**
|
62 |
* Should be updated each new release.
|
63 |
* @var string
|
64 |
*/
|
65 |
+
const PluginSlug = 'wpsf'; //ALL database options use this as the prefix.
|
|
|
66 |
/**
|
67 |
+
* @var string
|
68 |
*/
|
69 |
+
const AdminAccessKeyCookieName = 'icwp_wpsf_aakcook';
|
70 |
|
71 |
/**
|
72 |
* @var ICWP_OptionsHandler_Firewall
|
77 |
* @var ICWP_OptionsHandler_LoginProtect
|
78 |
*/
|
79 |
protected $m_oLoginProtectOptions;
|
80 |
+
/**
|
81 |
+
* @var ICWP_OptionsHandler_PrivacyProtect
|
82 |
+
*/
|
83 |
+
protected $m_oPrivacyProtectOptions;
|
84 |
|
85 |
/**
|
86 |
* @var ICWP_OptionsHandler_CommentsFilter
|
96 |
* @var ICWP_OptionsHandler_AutoUpdates
|
97 |
*/
|
98 |
protected $m_oAutoUpdatesOptions;
|
99 |
+
|
100 |
+
/**
|
101 |
+
* @var ICWP_OptionsHandler_Email_Wpsf
|
102 |
+
*/
|
103 |
+
protected $m_oEmailOptions;
|
104 |
|
105 |
/**
|
106 |
* @var ICWP_FirewallProcessor
|
116 |
* @var ICWP_CommentsFilterProcessor
|
117 |
*/
|
118 |
protected $m_oCommentsFilterProcessor;
|
119 |
+
|
120 |
/**
|
121 |
* @var ICWP_LockdownProcessor
|
122 |
*/
|
123 |
protected $m_oLockdownProcessor;
|
124 |
+
/**
|
125 |
+
* @var ICWP_WPSF_PrivacyProtectProcessor
|
126 |
+
*/
|
127 |
+
protected $m_oPrivacyProtectProcessor;
|
128 |
|
129 |
/**
|
130 |
+
* @var ICWP_WPSF_AutoUpdatesProcessor
|
131 |
*/
|
132 |
protected $m_oAutoUpdatesProcessor;
|
133 |
|
134 |
/**
|
135 |
+
* @var ICWP_WPSF_LoggingProcessor
|
136 |
*/
|
137 |
protected $m_oLoggingProcessor;
|
138 |
|
140 |
* @var ICWP_EmailProcessor
|
141 |
*/
|
142 |
protected $m_oEmailProcessor;
|
143 |
+
|
144 |
+
/**
|
145 |
+
* @var bool
|
146 |
+
*/
|
147 |
+
private $fAdminAccessPermSubmit = null;
|
148 |
+
|
149 |
+
/**
|
150 |
+
*/
|
151 |
public function __construct() {
|
152 |
|
153 |
$this->m_fNetworkAdminOnly = true;
|
154 |
+
$this->m_sPluginRootFile = __FILE__; //ensure all relative paths etc. are setup.
|
155 |
+
|
156 |
+
self::$sOptionPrefix = sprintf( '%s_%s_', self::BaseSlug, self::PluginSlug );
|
157 |
+
$this->m_sVersion = self::PluginVersion;
|
158 |
+
$this->m_sPluginHumanName = "WordPress Simple Firewall";
|
159 |
+
$this->m_sPluginTextDomain = self::PluginTextDomain;
|
160 |
+
$this->m_sPluginMenuTitle = "Simple Firewall";
|
161 |
+
$this->m_sPluginSlug = self::PluginSlug;
|
162 |
+
$this->m_sParentMenuIdSuffix = self::PluginSlug;
|
163 |
+
|
164 |
+
parent::__construct(
|
165 |
+
array(
|
166 |
+
'logging' => 'Logging',
|
167 |
+
'email' => 'Email',
|
168 |
+
'firewall' => 'Firewall',
|
169 |
+
'login_protect' => 'LoginProtect',
|
170 |
+
'comments_filter' => 'CommentsFilter',
|
171 |
+
// 'privacy_protect' => 'PrivacyProtect',
|
172 |
+
'lockdown' => 'Lockdown',
|
173 |
+
'autoupdates' => 'AutoUpdates'
|
174 |
+
),
|
175 |
+
array(
|
176 |
+
'm_oPluginMainOptions',
|
177 |
+
'm_oEmailOptions',
|
178 |
+
'm_oFirewallOptions',
|
179 |
+
'm_oLoginProtectOptions',
|
180 |
+
'm_oCommentsFilterOptions',
|
181 |
+
'm_oPrivacyProtectOptions',
|
182 |
+
'm_oLockdownOptions',
|
183 |
+
'm_oAutoUpdatesOptions'
|
184 |
+
)
|
185 |
+
);
|
186 |
+
|
187 |
// loads the base plugin options from 1 db call
|
188 |
+
$this->loadOptionsHandler( 'PluginMain' );
|
189 |
+
$this->m_fAutoPluginUpgrade = false && $this->m_oPluginMainOptions->getOpt( 'enable_auto_plugin_upgrade' ) == 'Y';
|
190 |
|
191 |
// checks for filesystem based firewall overrides
|
192 |
$this->override();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
193 |
|
194 |
if ( isset( $_GET['turnoffperm'] ) ) {
|
195 |
$this->setPermissionToSubmit( false );
|
196 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
197 |
|
198 |
+
add_filter( 'pre_update_option', array($this, 'blockOptionsSaves'), 1, 3 );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
199 |
}
|
200 |
+
|
201 |
/**
|
202 |
+
* @return string
|
|
|
|
|
|
|
203 |
*/
|
204 |
+
protected function override() {
|
205 |
+
$sSetting = parent::override();
|
206 |
+
if ( empty( $sSetting ) ) {
|
207 |
+
return $sSetting;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
208 |
}
|
209 |
+
$this->m_oPluginMainOptions->setOpt( 'enable_admin_access_restriction', $sSetting );
|
210 |
+
$this->m_oPluginMainOptions->savePluginOptions();
|
211 |
+
return $sSetting;
|
212 |
}
|
213 |
|
214 |
/**
|
215 |
* Should be called from the constructor so as to ensure it is called as early as possible.
|
216 |
*
|
217 |
+
* @return void
|
|
|
218 |
*/
|
219 |
public function runFirewallProcess() {
|
220 |
|
|
|
|
|
|
|
|
|
221 |
$this->loadProcessor( 'Firewall' );
|
222 |
$fFirewallBlockUser = !$this->m_oFirewallProcessor->doFirewallCheck();
|
223 |
|
224 |
if ( $fFirewallBlockUser ) {
|
|
|
225 |
if ( $this->m_oFirewallProcessor->getNeedsEmailHandler() ) {
|
226 |
$this->loadProcessor( 'Email' );
|
227 |
$this->m_oFirewallProcessor->setEmailHandler( $this->m_oEmailProcessor );
|
|
|
|
|
|
|
|
|
|
|
228 |
}
|
229 |
+
$this->m_oFirewallProcessor->doPreFirewallBlock();
|
230 |
}
|
|
|
|
|
231 |
|
232 |
if ( $fFirewallBlockUser ) {
|
233 |
+
$this->shutdown();
|
234 |
$this->m_oFirewallProcessor->doFirewallBlock();
|
235 |
}
|
|
|
|
|
236 |
}
|
237 |
|
238 |
/**
|
240 |
*/
|
241 |
public function runLoginProtect() {
|
242 |
$this->loadProcessor( 'LoginProtect' );
|
243 |
+
$this->loadProcessor( 'Email' );
|
244 |
+
$this->m_oLoginProtectProcessor->setEmailHandler( $this->m_oEmailProcessor );
|
245 |
$this->m_oLoginProtectProcessor->run();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
246 |
}
|
247 |
|
248 |
/**
|
249 |
+
* Handles the running of all Auto Update processes.
|
250 |
*/
|
251 |
public function runAutoUpdates() {
|
252 |
$this->loadProcessor( 'AutoUpdates' );
|
253 |
+
$this->m_oAutoUpdatesProcessor->run( $this->getPluginFile() );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
254 |
}
|
255 |
|
256 |
protected function createPluginSubMenuItems() {
|
|
|
|
|
|
|
|
|
|
|
257 |
$this->m_aPluginMenu = array(
|
258 |
//Menu Page Title => Menu Item name, page ID (slug), callback function for this page - i.e. what to do/load.
|
259 |
+
$this->getSubmenuPageTitle( _wpsf__('Firewall') ) => array( 'Firewall', $this->getSubmenuId('firewall'), 'onDisplayAll' ),
|
260 |
+
$this->getSubmenuPageTitle( _wpsf__('Login Protect') ) => array( 'Login Protect', $this->getSubmenuId('login_protect'), 'onDisplayAll' ),
|
261 |
+
$this->getSubmenuPageTitle( _wpsf__('Comments Filter') ) => array( 'Comments Filter', $this->getSubmenuId('comments_filter'), 'onDisplayAll' ),
|
262 |
+
// $this->getSubmenuPageTitle( _wpsf__('Privacy Protect') ) => array( 'Privacy Protect', $this->getSubmenuId('privacy_protect'), 'onDisplayAll' ),
|
263 |
+
$this->getSubmenuPageTitle( _wpsf__('Automatic Updates') ) => array( 'Automatic Updates', $this->getSubmenuId('autoupdates'), 'onDisplayAll' ),
|
264 |
+
$this->getSubmenuPageTitle( _wpsf__('Lockdown') ) => array( 'Lockdown', $this->getSubmenuId('lockdown'), 'onDisplayAll' ),
|
265 |
+
$this->getSubmenuPageTitle( _wpsf__('Firewall Log' ) ) => array( 'Firewall Log', $this->getSubmenuId('firewall_log'), 'onDisplayAll' ),
|
266 |
+
// $this->getSubmenuPageTitle( _wpsf__('Privacy Log' ) ) => array( 'Privacy Log', $this->getSubmenuId('privacy_protect_log'), 'onDisplayAll' )
|
267 |
);
|
268 |
}
|
269 |
|
270 |
protected function handlePluginUpgrade() {
|
271 |
parent::handlePluginUpgrade();
|
272 |
|
273 |
+
$sCurrentPluginVersion = $this->m_oPluginMainOptions->getVersion();
|
274 |
|
275 |
+
if ( $sCurrentPluginVersion !== $this->m_sVersion && current_user_can( 'manage_options' ) ) {
|
276 |
|
277 |
+
$this->loadOptionsHandler( 'all' );
|
278 |
+
|
279 |
+
// refactoring so that email and logging options are more independent
|
280 |
+
if ( version_compare( $sCurrentPluginVersion, '2.3.0', '<' ) ) {
|
281 |
+
$this->deleteOption( 'whitelist_admins' );
|
282 |
+
|
283 |
+
$this->m_oEmailOptions->setOpt( 'block_send_email_address', $this->m_oPluginMainOptions->getOpt( 'block_send_email_address') );
|
284 |
+
$this->m_oEmailOptions->setOpt( 'send_email_throttle_limit', $this->m_oPluginMainOptions->getOpt( 'send_email_throttle_limit') );
|
285 |
+
}//v2.3.0
|
286 |
|
287 |
$this->loadProcessor( 'Logging' );
|
288 |
$this->m_oLoggingProcessor->handleInstallUpgrade( $sCurrentPluginVersion );
|
|
|
|
|
|
|
289 |
|
290 |
// clears all the processor caches
|
291 |
$this->clearCaches();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
292 |
}
|
293 |
}
|
294 |
|
302 |
$this->onDisplayAccessKeyRequest();
|
303 |
return;
|
304 |
}
|
305 |
+
|
306 |
+
// Just to ensure the nag bar disappears if/when they visit the dashboard
|
307 |
+
// regardless of clicking the button.
|
308 |
+
$this->updateVersionUserMeta();
|
309 |
+
|
310 |
+
$sPrefix = str_replace(' ', '-', strtolower($this->m_sPluginMenuTitle) ) .'_page_'.self::BaseSlug.'-'.self::PluginSlug.'-';
|
311 |
$sCurrent = str_replace( $sPrefix, '', current_filter() );
|
312 |
+
|
313 |
switch( $sCurrent ) {
|
314 |
+
case 'toplevel_page_'.self::BaseSlug.'-'.self::PluginSlug : //special case
|
315 |
$this->onDisplayMainMenu();
|
316 |
break;
|
317 |
+
case 'privacy_protect_log' :
|
318 |
+
$this->onDisplayPrivacyProtectLog();
|
319 |
+
break;
|
320 |
case 'firewall_log' :
|
321 |
$this->onDisplayFirewallLog();
|
322 |
break;
|
330 |
}
|
331 |
|
332 |
public function onDisplayAccessKeyRequest() {
|
|
|
|
|
|
|
333 |
$aData = array(
|
|
|
|
|
334 |
'nonce_field' => $this->getSubmenuId( 'wpsf-access-key' ),
|
|
|
335 |
);
|
336 |
+
$aData = array_merge( $this->getBaseDisplayData(), $aData );
|
337 |
$this->display( 'icwp_wpsf_access_key_request_index', $aData );
|
338 |
}
|
339 |
|
340 |
public function onDisplayMainMenu() {
|
341 |
|
342 |
+
$this->loadOptionsHandler( 'all', true );
|
343 |
+
$aAvailableOptions = array_merge( $this->m_oPluginMainOptions->getOptions(), $this->m_oEmailOptions->getOptions() );
|
344 |
+
$sMainOptions = $this->m_oPluginMainOptions->collateAllFormInputsForAllOptions();
|
345 |
+
$sEmailMainOptions = $this->m_oEmailOptions->collateAllFormInputsForAllOptions();
|
346 |
+
$sAllFormInputOptions = $sMainOptions.(ICWP_OptionsHandler_Base_Wpsf::CollateSeparator).$sEmailMainOptions;
|
|
|
|
|
347 |
|
348 |
$aData = array(
|
|
|
|
|
349 |
'aAllOptions' => $aAvailableOptions,
|
|
|
350 |
'all_options_input' => $sAllFormInputOptions,
|
|
|
|
|
351 |
);
|
352 |
+
$aData = array_merge( $this->getBaseDisplayData(), $aData );
|
353 |
+
|
354 |
+
$aData['aMainOptions'] = $this->m_oPluginMainOptions->getPluginOptionsValues();
|
355 |
+
$aData['aSummaryData'] = $this->getDashboardSummaryDisplayData();
|
356 |
|
|
|
|
|
357 |
if ( $this->getIsMainFeatureEnabled('firewall') ) {
|
358 |
$this->loadOptionsHandler( 'Firewall' );
|
359 |
$aData['aFirewallOptions'] = $this->m_oFirewallOptions->getPluginOptionsValues();
|
374 |
$this->loadOptionsHandler( 'AutoUpdates' );
|
375 |
$aData['aAutoUpdatesOptions'] = $this->m_oAutoUpdatesOptions->getPluginOptionsValues();
|
376 |
}
|
|
|
377 |
$this->display( 'icwp_'.$this->m_sParentMenuIdSuffix.'_index', $aData );
|
378 |
}
|
379 |
+
|
380 |
+
protected function getDashboardSummaryDisplayData() {
|
381 |
+
|
382 |
+
$aSummaryData = array();
|
383 |
+
$aSummaryData[] = array(
|
384 |
+
$this->m_oPluginMainOptions->getOpt( 'enable_admin_access_restriction' ) == 'Y',
|
385 |
+
_wpsf__('Admin Access Protection'),
|
386 |
+
$this->getSubmenuId()
|
387 |
+
);
|
388 |
+
|
389 |
+
$aSummaryData[] = array(
|
390 |
+
$this->getIsMainFeatureEnabled('firewall'),
|
391 |
+
_wpsf__('Firewall'),
|
392 |
+
$this->getSubmenuId( 'firewall' )
|
393 |
+
);
|
394 |
+
|
395 |
+
$aSummaryData[] = array(
|
396 |
+
$this->getIsMainFeatureEnabled('login_protect'),
|
397 |
+
_wpsf__('Login Protection'),
|
398 |
+
$this->getSubmenuId( 'login_protect' )
|
399 |
+
);
|
400 |
+
|
401 |
+
$aSummaryData[] = array(
|
402 |
+
$this->getIsMainFeatureEnabled('comments_filter'),
|
403 |
+
_wpsf__('Comments Filter'),
|
404 |
+
$this->getSubmenuId( 'comments_filter' )
|
405 |
+
);
|
406 |
+
|
407 |
+
$aSummaryData[] = array(
|
408 |
+
$this->getIsMainFeatureEnabled('autoupdates'),
|
409 |
+
_wpsf__('Auto Updates'),
|
410 |
+
$this->getSubmenuId( 'autoupdates' )
|
411 |
+
);
|
412 |
+
|
413 |
+
$aSummaryData[] = array(
|
414 |
+
$this->getIsMainFeatureEnabled('lockdown'),
|
415 |
+
_wpsf__('Lock Down'),
|
416 |
+
$this->getSubmenuId( 'lockdown' )
|
417 |
+
);
|
418 |
+
|
419 |
+
return $aSummaryData;
|
420 |
+
}
|
421 |
|
422 |
+
protected function onDisplayPrivacyProtectLog() {
|
423 |
+
|
424 |
+
$this->loadProcessor( 'PrivacyProtect' );
|
425 |
+
$aData = array(
|
426 |
+
'urlrequests_log' => $this->m_oPrivacyProtectProcessor->getLogs( true )
|
427 |
+
);
|
428 |
+
$aData = array_merge( $this->getBaseDisplayData('privacy_protect_log'), $aData );
|
429 |
+
$this->display( 'icwp_wpsf_privacy_protect_log_index', $aData );
|
430 |
+
}
|
431 |
+
|
432 |
protected function onDisplayFirewallLog() {
|
433 |
|
434 |
$this->loadOptionsHandler( 'Firewall' );
|
435 |
$aIpWhitelist = $this->m_oFirewallOptions->getOpt( 'ips_whitelist' );
|
436 |
$aIpBlacklist = $this->m_oFirewallOptions->getOpt( 'ips_blacklist' );
|
|
|
437 |
$this->loadProcessor( 'Logging' );
|
438 |
|
439 |
+
$aLogData = $this->m_oLoggingProcessor->getLogs( true );
|
440 |
$aData = array(
|
441 |
+
'firewall_log' => $aLogData,
|
|
|
|
|
442 |
'ip_whitelist' => isset( $aIpWhitelist['ips'] )? $aIpWhitelist['ips'] : array(),
|
443 |
'ip_blacklist' => isset( $aIpBlacklist['ips'] )? $aIpBlacklist['ips'] : array(),
|
|
|
|
|
|
|
444 |
);
|
445 |
+
$aData = array_merge( $this->getBaseDisplayData('firewall_log'), $aData );
|
446 |
$this->display( 'icwp_wpsf_firewall_log_index', $aData );
|
447 |
}
|
448 |
+
|
449 |
/**
|
450 |
*
|
451 |
* @param ICWP_OptionsHandler_Base_WPSF $inoOptions
|
452 |
* @param string $insSlug
|
453 |
*/
|
454 |
protected function onDisplayConfig( $inoOptions, $insSlug ) {
|
|
|
455 |
$aAvailableOptions = $inoOptions->getOptions();
|
456 |
$sAllFormInputOptions = $inoOptions->collateAllFormInputsForAllOptions();
|
457 |
|
458 |
$aData = array(
|
|
|
|
|
|
|
459 |
'aAllOptions' => $aAvailableOptions,
|
460 |
'all_options_input' => $sAllFormInputOptions,
|
|
|
|
|
461 |
);
|
462 |
+
$aData = array_merge( $this->getBaseDisplayData($insSlug), $aData );
|
463 |
$this->display( 'icwp_wpsf_config_'.$insSlug.'_index', $aData );
|
464 |
}
|
465 |
+
|
466 |
+
/**
|
467 |
+
* @return boolean
|
468 |
+
*/
|
469 |
+
protected function isIcwpPluginFormSubmit() {
|
470 |
|
471 |
+
if ( empty($_POST) && empty($_GET) ) {
|
472 |
+
return false;
|
473 |
+
}
|
474 |
+
|
475 |
+
$aFormSubmitOptions = array(
|
476 |
'icwp_plugin_form_submit',
|
477 |
'icwp_link_action',
|
478 |
'icwp_wpsf_admin_access_key_request'
|
479 |
);
|
480 |
+
foreach( $aFormSubmitOptions as $sOption ) {
|
481 |
+
if ( !is_null( $this->fetchRequest( $sOption, false ) ) ) {
|
|
|
482 |
return true;
|
483 |
}
|
484 |
}
|
485 |
+
return false;
|
486 |
}
|
487 |
|
488 |
protected function handlePluginFormSubmit() {
|
489 |
+
if ( !is_null( $this->fetchPost( 'icwp_wpsf_admin_access_key_request' ) ) ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
490 |
return $this->handleSubmit_AccessKeyRequest();
|
491 |
}
|
492 |
|
493 |
+
if ( !$this->hasPermissionToSubmit() || !$this->isIcwpPluginFormSubmit() ) {
|
494 |
return false;
|
495 |
}
|
496 |
+
|
497 |
+
$sCurrentPage = $this->fetchGet('page');
|
498 |
+
if ( !is_null($sCurrentPage) ) {
|
499 |
+
switch ( $sCurrentPage ) {
|
500 |
case $this->getSubmenuId():
|
501 |
$this->handleSubmit_Dashboard();
|
502 |
break;
|
518 |
case $this->getSubmenuId( 'firewall_log' ):
|
519 |
$this->handleSubmit_FirewallLog();
|
520 |
break;
|
521 |
+
case $this->getSubmenuId( 'privacy_protect' ):
|
522 |
+
$this->handleSubmit_PrivacyProtect();
|
523 |
+
break;
|
524 |
+
case $this->getSubmenuId( 'privacy_protect_log' ):
|
525 |
+
$this->handleSubmit_PrivacyProtectLog();
|
526 |
+
break;
|
527 |
default:
|
528 |
return false;
|
529 |
break;
|
530 |
}
|
531 |
}
|
532 |
+
$this->clearCaches();
|
533 |
return true;
|
534 |
}
|
535 |
|
536 |
protected function setPermissionToSubmit( $infPermission = false ) {
|
|
|
537 |
if ( $infPermission ) {
|
538 |
+
$this->loadDataProcessor();
|
539 |
+
$sValue = md5( $this->m_oPluginMainOptions->getOpt( 'admin_access_key' ).ICWP_WPSF_DataProcessor::GetVisitorIpAddress() );
|
540 |
+
$sTimeout = $this->m_oPluginMainOptions->getOpt( 'admin_access_timeout' ) * 60;
|
541 |
+
$_COOKIE[ self::AdminAccessKeyCookieName ] = $sValue;
|
542 |
setcookie( self::AdminAccessKeyCookieName, $sValue, time()+$sTimeout, COOKIEPATH, COOKIE_DOMAIN, false );
|
543 |
}
|
544 |
else {
|
547 |
}
|
548 |
}
|
549 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
550 |
/**
|
551 |
* @return boolean
|
552 |
*/
|
553 |
protected function hasPermissionToSubmit() {
|
554 |
+
|
555 |
+
if ( !is_null( $this->fAdminAccessPermSubmit ) ) {
|
556 |
+
return $this->fAdminAccessPermSubmit;
|
|
|
557 |
}
|
558 |
+
|
559 |
+
$this->fAdminAccessPermSubmit = true;
|
560 |
+
if ( !parent::hasPermissionToSubmit() ) {
|
561 |
+
$this->fAdminAccessPermSubmit = false;
|
562 |
+
}
|
563 |
+
if ( $this->fAdminAccessPermSubmit && $this->m_oPluginMainOptions->getOpt( 'enable_admin_access_restriction' ) == 'Y' ) {
|
564 |
+
$sAccessKey = $this->m_oPluginMainOptions->getOpt( 'admin_access_key' );
|
565 |
if ( !empty( $sAccessKey ) ) {
|
566 |
+
$this->loadDataProcessor();
|
567 |
+
$sHash = md5( $sAccessKey.ICWP_WPSF_DataProcessor::GetVisitorIpAddress() );
|
568 |
+
$this->fAdminAccessPermSubmit = isset( $_COOKIE[ self::AdminAccessKeyCookieName ] ) && ( $sHash == $_COOKIE[ self::AdminAccessKeyCookieName ] );
|
|
|
|
|
|
|
|
|
|
|
569 |
}
|
570 |
}
|
571 |
+
return $this->fAdminAccessPermSubmit;
|
572 |
+
}
|
573 |
+
|
574 |
+
/**
|
575 |
+
* Right before a plugin option is due to update it will check that we have permissions to do so and if not, will
|
576 |
+
* revert the option to save to the previous one.
|
577 |
+
*
|
578 |
+
* @param $mValue
|
579 |
+
* @param $sOption
|
580 |
+
* @param $mOldValue
|
581 |
+
* @return mixed
|
582 |
+
*/
|
583 |
+
public function blockOptionsSaves( $mValue, $sOption, $mOldValue ) {
|
584 |
+
if ( !preg_match( '/^'.self::$sOptionPrefix.'.*_options$/', $sOption ) || $this->fHasFtpOverride ) {
|
585 |
+
return $mValue;
|
586 |
+
}
|
587 |
+
return $this->hasPermissionToSubmit()? $mValue : $mOldValue;
|
588 |
}
|
589 |
|
590 |
protected function handleSubmit_AccessKeyRequest() {
|
591 |
//Ensures we're actually getting this request from WP.
|
592 |
check_admin_referer( $this->getSubmenuId('wpsf-access-key') );
|
593 |
|
594 |
+
$this->loadOptionsHandler( 'PluginMain' );
|
595 |
+
$sAccessKey = md5( trim( $this->fetchPost( 'icwp_wpsf_admin_access_key_request' ) ) );
|
596 |
+
$sStoredAccessKey = $this->m_oPluginMainOptions->getOpt( 'admin_access_key' );
|
597 |
|
598 |
if ( $sAccessKey === $sStoredAccessKey ) {
|
599 |
$this->setPermissionToSubmit( true );
|
600 |
+
header( 'Location: '.network_admin_url('admin.php?page=icwp-wpsf') );
|
601 |
exit();
|
602 |
}
|
603 |
return false;
|
605 |
|
606 |
protected function handleSubmit_Dashboard() {
|
607 |
//Ensures we're actually getting this request from WP.
|
608 |
+
check_admin_referer( $this->getSubmenuId() );
|
609 |
|
610 |
+
$aInputOptions = $this->fetchPost( self::$sOptionPrefix.'all_options_input' );
|
611 |
+
if ( is_null( $aInputOptions ) ) {
|
612 |
return false;
|
613 |
}
|
614 |
|
615 |
+
$this->loadOptionsHandler( 'PluginMain' );
|
616 |
+
$this->m_oPluginMainOptions->updatePluginOptionsFromSubmit( $aInputOptions );
|
617 |
+
|
618 |
+
$this->loadOptionsHandler( 'Email' );
|
619 |
+
$this->m_oEmailOptions->updatePluginOptionsFromSubmit( $aInputOptions );
|
620 |
+
|
621 |
+
$this->setSharedOption( 'enable_firewall', $this->m_oPluginMainOptions->getOpt( 'enable_firewall' ) );
|
622 |
+
$this->setSharedOption( 'enable_login_protect', $this->m_oPluginMainOptions->getOpt( 'enable_login_protect' ) );
|
623 |
+
$this->setSharedOption( 'enable_comments_filter', $this->m_oPluginMainOptions->getOpt( 'enable_comments_filter' ) );
|
624 |
+
$this->setSharedOption( 'enable_lockdown', $this->m_oPluginMainOptions->getOpt( 'enable_lockdown' ) );
|
625 |
+
$this->setSharedOption( 'enable_autoupdates', $this->m_oPluginMainOptions->getOpt( 'enable_autoupdates' ) );
|
626 |
+
$this->setSharedOption( 'enable_privacy_protect', $this->m_oPluginMainOptions->getOpt( 'enable_privacy_protect' ) );
|
627 |
+
|
628 |
+
$this->saveOptions();
|
629 |
$this->clearCaches();
|
630 |
+
|
631 |
+
if ( !$this->fetchPost( self::$sOptionPrefix.'enable_admin_access_restriction' ) ) {
|
632 |
+
$this->setPermissionToSubmit( false );
|
633 |
+
}
|
634 |
+
else {
|
635 |
+
wp_safe_redirect( network_admin_url('admin.php?page=icwp-wpsf') );
|
636 |
+
}
|
637 |
}
|
638 |
|
639 |
protected function handleSubmit_FirewallConfig() {
|
643 |
if ( isset($_POST[ 'import-wpf2-submit' ] ) ) {
|
644 |
$this->importFromFirewall2Plugin();
|
645 |
}
|
646 |
+
else if ( !isset($_POST[self::$sOptionPrefix.'all_options_input']) ) {
|
647 |
return;
|
648 |
}
|
649 |
else {
|
650 |
$this->loadOptionsHandler( 'Firewall' );
|
651 |
+
$this->m_oFirewallOptions->updatePluginOptionsFromSubmit( $_POST[self::$sOptionPrefix.'all_options_input'] );
|
652 |
}
|
653 |
$this->setSharedOption( 'enable_firewall', $this->m_oFirewallOptions->getOpt( 'enable_firewall' ) );
|
654 |
+
$this->resetProcessor( 'Firewall' );
|
655 |
}
|
656 |
+
|
657 |
protected function handleSubmit_LoginProtect() {
|
658 |
//Ensures we're actually getting this request from WP.
|
659 |
check_admin_referer( $this->getSubmenuId('login_protect' ) );
|
660 |
+
|
661 |
+
if ( $this->fetchPost( 'terminate-all-logins' ) ) {
|
662 |
+
$oProc = $this->getProcessorVar('LoginProtect');
|
663 |
+
$oProc->doTerminateAllVerifiedLogins();
|
664 |
+
return;
|
665 |
+
}
|
666 |
+
|
667 |
+
if ( !isset($_POST[self::$sOptionPrefix.'all_options_input']) ) {
|
668 |
return;
|
669 |
}
|
670 |
$this->loadOptionsHandler( 'LoginProtect' );
|
671 |
+
$this->m_oLoginProtectOptions->updatePluginOptionsFromSubmit( $_POST[self::$sOptionPrefix.'all_options_input'] );
|
672 |
$this->setSharedOption( 'enable_login_protect', $this->m_oLoginProtectOptions->getOpt( 'enable_login_protect' ) );
|
673 |
+
$this->resetProcessor( 'LoginProtect' );
|
674 |
+
}
|
675 |
+
|
676 |
+
protected function handleSubmit_PrivacyProtect() {
|
677 |
+
//Ensures we're actually getting this request from WP.
|
678 |
+
check_admin_referer( $this->getSubmenuId('privacy_protect' ) );
|
679 |
+
|
680 |
+
if ( !isset($_POST[self::$sOptionPrefix.'all_options_input']) ) {
|
681 |
+
return;
|
682 |
+
}
|
683 |
+
$this->loadOptionsHandler( 'PrivacyProtect' );
|
684 |
+
$this->m_oPrivacyProtectOptions->updatePluginOptionsFromSubmit( $_POST[self::$sOptionPrefix.'all_options_input'] );
|
685 |
+
$this->setSharedOption( 'enable_privacy_protect', $this->m_oPrivacyProtectOptions->getOpt( 'enable_privacy_protect' ) );
|
686 |
+
$this->resetProcessor( 'PrivacyProtect' );
|
687 |
}
|
688 |
|
689 |
protected function handleSubmit_CommentsFilter() {
|
690 |
//Ensures we're actually getting this request from WP.
|
691 |
check_admin_referer( $this->getSubmenuId('comments_filter' ) );
|
692 |
|
693 |
+
if ( !isset($_POST[self::$sOptionPrefix.'all_options_input']) ) {
|
694 |
return;
|
695 |
}
|
696 |
$this->loadOptionsHandler( 'CommentsFilter' );
|
697 |
+
$this->m_oCommentsFilterOptions->updatePluginOptionsFromSubmit( $_POST[self::$sOptionPrefix.'all_options_input'] );
|
698 |
$this->setSharedOption( 'enable_comments_filter', $this->m_oCommentsFilterOptions->getOpt( 'enable_comments_filter' ) );
|
699 |
+
$this->resetProcessor( 'CommentsFilter' );
|
700 |
}
|
701 |
|
702 |
protected function handleSubmit_Lockdown() {
|
703 |
//Ensures we're actually getting this request from WP.
|
704 |
check_admin_referer( $this->getSubmenuId('lockdown' ) );
|
705 |
|
706 |
+
if ( !isset($_POST[self::$sOptionPrefix.'all_options_input']) ) {
|
707 |
return;
|
708 |
}
|
709 |
$this->loadOptionsHandler( 'Lockdown' );
|
710 |
+
$this->m_oLockdownOptions->updatePluginOptionsFromSubmit( $_POST[self::$sOptionPrefix.'all_options_input'] );
|
711 |
$this->setSharedOption( 'enable_lockdown', $this->m_oLockdownOptions->getOpt( 'enable_lockdown' ) );
|
712 |
+
$this->resetProcessor( 'Lockdown' );
|
713 |
}
|
714 |
|
715 |
protected function handleSubmit_AutoUpdates() {
|
716 |
//Ensures we're actually getting this request from WP.
|
717 |
check_admin_referer( $this->getSubmenuId( 'autoupdates' ) );
|
718 |
|
719 |
+
if ( isset( $_GET['force_run_auto_updates'] ) && $_GET['force_run_auto_updates'] == 'now' ) {
|
720 |
+
$this->loadProcessor( 'AutoUpdates' );
|
721 |
+
$this->m_oAutoUpdatesProcessor->setForceRunAutoUpdates( true );
|
722 |
+
return;
|
723 |
+
}
|
724 |
+
|
725 |
+
if ( !isset($_POST[self::$sOptionPrefix.'all_options_input']) ) {
|
726 |
return;
|
727 |
}
|
728 |
$this->loadOptionsHandler( 'AutoUpdates' );
|
729 |
+
$this->m_oAutoUpdatesOptions->updatePluginOptionsFromSubmit( $_POST[self::$sOptionPrefix.'all_options_input'] );
|
730 |
$this->setSharedOption( 'enable_autoupdates', $this->m_oAutoUpdatesOptions->getOpt( 'enable_autoupdates' ) );
|
731 |
+
$this->resetProcessor( 'AutoUpdates' );
|
732 |
}
|
733 |
|
734 |
protected function handleSubmit_FirewallLog() {
|
735 |
|
736 |
// Ensures we're actually getting this request from a valid WP submission.
|
737 |
+
$sNonce = $this->fetchRequest( '_wpnonce', false );
|
738 |
+
if ( is_null( $sNonce ) || !wp_verify_nonce( $sNonce, $this->getSubmenuId( 'firewall_log' ) ) ) {
|
739 |
wp_die();
|
740 |
}
|
741 |
+
|
742 |
+
$this->loadOptionsHandler( 'Firewall' );
|
743 |
|
744 |
// At the time of writing the page only has 1 form submission item - clear log
|
745 |
+
if ( !is_null( $this->fetchPost( 'clear_log_submit' ) ) ) {
|
746 |
$this->loadProcessor( 'Logging' );
|
747 |
$this->m_oLoggingProcessor->recreateTable();
|
748 |
}
|
749 |
+
else {
|
750 |
+
$this->m_oFirewallOptions->addRawIpsToFirewallList( 'ips_whitelist', array( $this->fetchGet( 'whiteip' ) ) );
|
751 |
+
$this->m_oFirewallOptions->removeRawIpsFromFirewallList( 'ips_whitelist', array( $this->fetchGet( 'unwhiteip' ) ) );
|
752 |
+
$this->m_oFirewallOptions->addRawIpsToFirewallList( 'ips_blacklist', array( $this->fetchGet( 'blackip' ) ) );
|
753 |
+
$this->m_oFirewallOptions->removeRawIpsFromFirewallList( 'ips_blacklist', array( $this->fetchGet( 'unblackip' ) ) );
|
754 |
+
$this->resetProcessor( 'Firewall' );
|
755 |
}
|
756 |
+
wp_safe_redirect( network_admin_url( "admin.php?page=".$this->getSubmenuId('firewall_log') ) ); //means no admin message is displayed
|
757 |
+
exit();
|
758 |
+
}
|
759 |
+
|
760 |
+
protected function handleSubmit_PrivacyProtectLog() {
|
761 |
+
|
762 |
+
// Ensures we're actually getting this request from a valid WP submission.
|
763 |
+
$sNonce = $this->fetchRequest( '_wpnonce', false );
|
764 |
+
if ( is_null( $sNonce ) || !wp_verify_nonce( $sNonce, $this->getSubmenuId( 'privacy_protect_log' ) ) ) {
|
765 |
+
wp_die();
|
766 |
}
|
767 |
+
|
768 |
+
$this->loadOptionsHandler( 'PrivacyProtect' );
|
769 |
+
|
770 |
+
// At the time of writing the page only has 1 form submission item - clear log
|
771 |
+
if ( !is_null( $this->fetchPost( 'clear_log_submit' ) ) ) {
|
772 |
+
$this->loadProcessor( 'PrivacyProtect' );
|
773 |
+
$this->m_oPrivacyProtectProcessor->recreateTable();
|
774 |
}
|
775 |
+
else {
|
776 |
+
// $this->m_oFirewallOptions->addRawIpsToFirewallList( 'ips_whitelist', array( $this->fetchGet( 'whiteip' ) ) );
|
777 |
+
// $this->m_oFirewallOptions->removeRawIpsFromFirewallList( 'ips_whitelist', array( $this->fetchGet( 'unwhiteip' ) ) );
|
778 |
+
// $this->m_oFirewallOptions->addRawIpsToFirewallList( 'ips_blacklist', array( $this->fetchGet( 'blackip' ) ) );
|
779 |
+
// $this->m_oFirewallOptions->removeRawIpsFromFirewallList( 'ips_blacklist', array( $this->fetchGet( 'unblackip' ) ) );
|
780 |
+
// $this->resetProcessor( 'Firewall' );
|
781 |
}
|
782 |
+
wp_safe_redirect( network_admin_url( "admin.php?page=".$this->getSubmenuId('privacy_protect_log') ) ); //means no admin message is displayed
|
783 |
exit();
|
784 |
}
|
785 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
786 |
protected function importFromFirewall2Plugin() {
|
787 |
$this->loadOptionsHandler( 'all' );
|
788 |
require_once( dirname(__FILE__).'/src/icwp-import-wpf2-processor.php' );
|
789 |
+
$oImportProcessor = new ICWP_ImportWpf2Processor( $this->m_oPluginMainOptions, $this->m_oFirewallOptions );
|
790 |
$oImportProcessor->runImport();
|
791 |
}
|
792 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
793 |
public function onWpPluginsLoaded() {
|
794 |
parent::onWpPluginsLoaded();
|
795 |
+
|
796 |
+
$aFeatures = $this->getFeaturesMap();
|
797 |
+
foreach( $aFeatures as $sFeatureSlug => $sProcessor ) {
|
798 |
+
if ( !$this->getIsMainFeatureEnabled( $sFeatureSlug ) ) {
|
799 |
+
continue;
|
800 |
+
}
|
801 |
+
if ( $sFeatureSlug == 'firewall' ) {
|
802 |
+
$this->runFirewallProcess();
|
803 |
+
}
|
804 |
+
else if ( $sFeatureSlug == 'login_protect' ) {
|
805 |
+
$this->runLoginProtect();
|
806 |
+
}
|
807 |
+
else if ( $sFeatureSlug == 'autoupdates' ) {
|
808 |
+
$this->runAutoUpdates();
|
809 |
+
}
|
810 |
+
else {
|
811 |
+
$sProcessorVariable = $this->loadProcessor( $sProcessor );
|
812 |
+
$sProcessorVariable->run();
|
813 |
+
}
|
814 |
+
}
|
815 |
|
816 |
if ( $this->isValidAdminArea()
|
817 |
+
&& $this->m_oPluginMainOptions->getOpt('enable_upgrade_admin_notice') == 'Y'
|
818 |
&& $this->hasPermissionToSubmit()
|
819 |
) {
|
820 |
$this->m_fDoAutoUpdateCheck = true;
|
821 |
}
|
822 |
+
}
|
823 |
+
|
824 |
+
public function onWpAdminInit() {
|
825 |
+
parent::onWpAdminInit();
|
826 |
+
|
827 |
+
if ( $this->isValidAdminArea() ) {
|
828 |
+
//Someone clicked the button to acknowledge the update
|
829 |
+
$sMetaFlag = self::$sOptionPrefix.'hide_update_notice';
|
830 |
+
if ( $this->fetchRequest( $sMetaFlag ) == 1 ) {
|
831 |
+
$this->updateVersionUserMeta();
|
832 |
+
if ( $this->isShowMarketing() ) {
|
833 |
+
wp_redirect( network_admin_url( "admin.php?page=".$this->getFullParentMenuId() ) );
|
834 |
+
}
|
835 |
+
else {
|
836 |
+
wp_redirect( network_admin_url( $_POST['redirect_page'] ) );
|
837 |
+
}
|
838 |
+
}
|
839 |
+
|
840 |
+
$sMetaFlag = self::$sOptionPrefix.'hide_translation_notice';
|
841 |
+
if ( $this->fetchRequest( $sMetaFlag ) == 1 ) {
|
842 |
+
$this->updateTranslationNoticeShownUserMeta();
|
843 |
+
wp_redirect( network_admin_url( $_POST['redirect_page'] ) );
|
844 |
+
}
|
845 |
|
846 |
+
$sMetaFlag = self::$sOptionPrefix.'hide_mailing_list_signup';
|
847 |
+
if ( $this->fetchRequest( $sMetaFlag ) == 1 ) {
|
848 |
+
$this->updateMailingListSignupShownUserMeta();
|
849 |
+
}
|
850 |
+
}
|
851 |
}
|
852 |
+
|
853 |
/**
|
854 |
+
* @return bool
|
855 |
*/
|
856 |
+
protected function isShowMarketing() {
|
857 |
+
// don't show marketing on the first 24hrs.
|
858 |
+
if ( $this->getInstallationDays() < 1 ) {
|
859 |
+
return false;
|
|
|
860 |
}
|
861 |
+
return parent::isShowMarketing();
|
862 |
}
|
863 |
+
|
864 |
+
/**
|
865 |
+
* Lets you remove certain plugin conflicts that might interfere with this plugin
|
866 |
+
*
|
867 |
+
* @see ICWP_Pure_Base_V1::removePluginConflicts()
|
868 |
+
*/
|
869 |
+
protected function removePluginConflicts() {
|
870 |
+
if ( class_exists('AIO_WP_Security') && isset( $GLOBALS['aio_wp_security'] ) ) {
|
871 |
+
remove_action( 'init', array( $GLOBALS['aio_wp_security'], 'wp_security_plugin_init'), 0 );
|
872 |
+
}
|
873 |
}
|
874 |
|
875 |
+
/**
|
876 |
+
* Updates the current log data with new data.
|
877 |
+
*
|
878 |
+
* @return void
|
879 |
+
*/
|
880 |
+
protected function updateLogStore() {
|
|
|
|
|
|
|
|
|
|
|
|
|
881 |
|
882 |
+
if ( isset( $this->m_oFirewallProcessor ) && is_object( $this->m_oFirewallProcessor ) && $this->getIsMainFeatureEnabled( 'firewall' ) ) {
|
883 |
+
$aLogData = $this->m_oFirewallProcessor->flushLogData();
|
884 |
+
if ( !is_null( $aLogData ) && !empty( $aLogData ) ) {
|
885 |
+
$this->loadProcessor( 'Logging' );
|
886 |
+
$this->m_oLoggingProcessor->addDataToWrite( $aLogData );
|
887 |
+
}
|
888 |
+
}
|
889 |
|
890 |
+
if ( isset( $this->m_oLoginProtectProcessor ) && is_object( $this->m_oLoginProtectProcessor ) && $this->getIsMainFeatureEnabled( 'login_protect' ) ) {
|
891 |
+
$aLogData = $this->m_oLoginProtectProcessor->flushLogData();
|
892 |
+
if ( !is_null( $aLogData ) && !empty( $aLogData ) ) {
|
893 |
+
$this->loadProcessor( 'Logging' );
|
894 |
+
$this->m_oLoggingProcessor->addDataToWrite( $aLogData );
|
895 |
+
}
|
896 |
}
|
|
|
897 |
}
|
898 |
|
899 |
+
protected function shutdown() {
|
900 |
+
$this->updateLogStore();
|
901 |
+
parent::shutdown();
|
|
|
902 |
}
|
903 |
+
|
904 |
+
protected function getPluginsListUpdateMessage() {
|
905 |
+
return _wpsf__( 'Upgrade Now To Keep Your Firewall Up-To-Date With The Latest Features.' );
|
|
|
|
|
906 |
}
|
907 |
|
908 |
+
protected function getAdminNoticeHtml_Translations() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
909 |
|
910 |
+
if ( $this->getInstallationDays() < 7 ) {
|
911 |
+
return '';
|
|
|
|
|
|
|
912 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
913 |
|
914 |
+
$sMetaFlag = self::$sOptionPrefix.'hide_translation_notice';
|
915 |
+
|
916 |
+
$sRedirectPage = 'index.php';
|
917 |
+
ob_start(); ?>
|
918 |
+
<style>
|
919 |
+
a#fromIcwp { padding: 0 5px; border-bottom: 1px dashed rgba(0,0,0,0.1); color: blue; font-weight: bold; }
|
920 |
+
</style>
|
921 |
+
<form id="IcwpTranslationsNotice" method="post" action="admin.php?page=<?php echo $this->getSubmenuId('firewall'); ?>&<?php echo $sMetaFlag; ?>=1">
|
922 |
+
<input type="hidden" value="<?php echo $sRedirectPage; ?>" name="redirect_page" id="redirect_page">
|
923 |
+
<input type="hidden" value="1" name="<?php echo $sMetaFlag; ?>" id="<?php echo $sMetaFlag; ?>">
|
924 |
+
<h4 style="margin:10px 0 3px;">
|
925 |
+
<?php _wpsf_e( 'Would you like to help translate the WordPress Simple Firewall into your language?' ); ?>
|
926 |
+
<?php printf( _wpsf__( 'Head over to: %s' ), '<a href="http://translate.icontrolwp.com" target="_blank">translate.icontrolwp.com</a>' ); ?>
|
927 |
+
</h4>
|
928 |
+
<input type="submit" value="<?php _wpsf_e( 'Dismiss this notice' ); ?>" name="submit" class="button" style="float:left; margin-bottom:10px;">
|
929 |
+
<div style="clear:both;"></div>
|
930 |
+
</form>
|
931 |
+
<?php
|
932 |
+
$sNotice = ob_get_contents();
|
933 |
+
ob_end_clean();
|
934 |
+
return $sNotice;
|
935 |
+
}
|
936 |
+
|
937 |
+
protected function getAdminNoticeHtml_VersionUpgrade() {
|
938 |
|
939 |
+
// for now just showing this for the first 3 days of installation.
|
940 |
+
if ( $this->getInstallationDays() > 7 ) {
|
941 |
+
return '';
|
|
|
|
|
942 |
}
|
943 |
+
|
944 |
+
$sMetaFlag = self::$sOptionPrefix.'hide_update_notice';
|
945 |
+
|
946 |
+
$sRedirectPage = 'admin.php?page=icwp-wpsf';
|
947 |
+
ob_start(); ?>
|
948 |
+
<style>a#fromIcwp { padding: 0 5px; border-bottom: 1px dashed rgba(0,0,0,0.1); color: blue; font-weight: bold; }</style>
|
949 |
+
<form id="IcwpUpdateNotice" method="post" action="admin.php?page=<?php echo $this->getSubmenuId('firewall'); ?>&<?php echo $sMetaFlag; ?>=1">
|
950 |
+
<input type="hidden" value="<?php echo $sRedirectPage; ?>" name="redirect_page" id="redirect_page">
|
951 |
+
<input type="hidden" value="1" name="<?php echo $sMetaFlag; ?>" id="<?php echo $sMetaFlag; ?>">
|
952 |
+
<p>
|
953 |
+
<?php _wpsf_e( 'Note: WordPress Simple Firewall plugin does not automatically turn on when you install/update.' ); ?>
|
954 |
+
<?php printf( _wpsf__( 'There may also be %simportant updates to read about%s.' ), '<a href="http://icwp.io/27" id="fromIcwp" title="'._wpsf__( 'WordPress Simple Firewall' ).'" target="_blank">', '</a>' ); ?>
|
955 |
+
</p>
|
956 |
+
</h4>
|
957 |
+
<input type="submit" value="<?php _wpsf_e( 'Okay, show me the dashboard' ); ?>" name="submit" class="button" style="float:left; margin-bottom:10px;">
|
958 |
+
<div style="clear:both;"></div>
|
959 |
+
</form>
|
960 |
+
<?php
|
961 |
+
$sNotice = ob_get_contents();
|
962 |
+
ob_end_clean();
|
963 |
+
return $sNotice;
|
964 |
}
|
965 |
+
|
966 |
/**
|
967 |
+
* @return string|void
|
968 |
*/
|
969 |
+
protected function getAdminNoticeHtml_MailingListSignup() {
|
970 |
+
|
971 |
+
$nDays = $this->getInstallationDays();
|
972 |
+
if ( $nDays < 2 ) {
|
973 |
+
return '';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
974 |
}
|
975 |
+
$sMetaFlag = self::$sOptionPrefix.'hide_mailing_list_signup';
|
976 |
+
|
977 |
+
ob_start(); ?>
|
978 |
+
<!-- Begin MailChimp Signup Form -->
|
979 |
+
<div id="mc_embed_signup">
|
980 |
+
<form class="form form-inline" action="http://hostliketoast.us2.list-manage1.com/subscribe/post?u=e736870223389e44fb8915c9a&id=0e1d527259" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
|
981 |
+
<p>The WordPress Simple Firewall team has launched a education initiative to raise awareness of WordPress security and to provide further help with the WordPress Simple Firewall plugin. Get Involved here:</p>
|
982 |
+
<input type="text" value="" name="EMAIL" class="required email" id="mce-EMAIL" placeholder="Your Email" />
|
983 |
+
<input type="text" value="" name="FNAME" class="" id="mce-FNAME" placeholder="Your Name" />
|
984 |
+
<input type="hidden" value="<?php echo $nDays; ?>" name="DAYS" class="" id="mce-DAYS" />
|
985 |
+
<input type="submit" value="Get The News" name="subscribe" id="mc-embedded-subscribe" class="button" />
|
986 |
+
<a href="<?php echo network_admin_url('admin.php?page=icwp-wpsf').'&'.$sMetaFlag.'=1';?>">Dismiss</a>
|
987 |
+
<div id="mce-responses" class="clear">
|
988 |
+
<div class="response" id="mce-error-response" style="display:none"></div>
|
989 |
+
<div class="response" id="mce-success-response" style="display:none"></div>
|
990 |
+
</div> <!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups-->
|
991 |
+
<div style="position: absolute; left: -5000px;"><input type="text" name="b_e736870223389e44fb8915c9a_0e1d527259" tabindex="-1" value=""></div>
|
992 |
+
<div class="clear"></div>
|
993 |
+
</form>
|
994 |
+
</div>
|
995 |
+
|
996 |
+
<!--End mc_embed_signup-->
|
997 |
+
<?php
|
998 |
+
$sNotice = ob_get_contents();
|
999 |
+
ob_end_clean();
|
1000 |
+
return $sNotice;
|
1001 |
}
|
1002 |
|
1003 |
+
protected function getAdminNoticeHtml_OptionsUpdated() {
|
1004 |
+
$sAdminFeedbackNotice = $this->m_oPluginMainOptions->getOpt( 'feedback_admin_notice' );
|
1005 |
+
if ( !empty( $sAdminFeedbackNotice ) ) {
|
1006 |
+
$sNotice = '<p>'.$sAdminFeedbackNotice.'</p>';
|
1007 |
+
return $sNotice;
|
1008 |
+
$this->m_oPluginMainOptions->setOpt( 'feedback_admin_notice', '' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1009 |
}
|
|
|
1010 |
}
|
1011 |
|
1012 |
+
/**
|
1013 |
+
*
|
1014 |
+
*/
|
1015 |
+
protected function getShowAdminNotices() {
|
1016 |
+
return $this->m_oPluginMainOptions->getOpt('enable_upgrade_admin_notice') == 'Y';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1017 |
}
|
1018 |
+
|
1019 |
/**
|
1020 |
+
* @return int
|
1021 |
*/
|
1022 |
+
protected function getInstallationDays() {
|
1023 |
+
$this->loadOptionsHandler( 'PluginMain' );
|
1024 |
+
$nTimeInstalled = $this->m_oPluginMainOptions->getOpt( 'installation_time' );
|
1025 |
+
if ( empty($nTimeInstalled) ) {
|
1026 |
+
return 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1027 |
}
|
1028 |
+
return round( ( time() - $nTimeInstalled ) / DAY_IN_SECONDS );
|
1029 |
}
|
1030 |
+
|
1031 |
+
protected function getAdminBarNodes() {
|
1032 |
+
return array(); //disabled for now
|
1033 |
+
$aMenu = array(
|
1034 |
+
'id' => self::$sOptionPrefix.'admin_menu',
|
1035 |
+
'title' => '<span class="pluginlogo_16"> </span>'._wpsf__('Firewall').'',
|
1036 |
+
'href' => 'bob',
|
1037 |
+
);
|
1038 |
+
return array( $aMenu );
|
1039 |
}
|
1040 |
}
|
1041 |
|
1042 |
endif;
|
1043 |
|
1044 |
+
$oICWP_Wpsf = ICWP_Wordpress_Simple_Firewall::GetInstance( 'ICWP_Wordpress_Simple_Firewall' );
|
languages/wp-simple-firewall-ca_ES.mo
ADDED
Binary file
|
languages/wp-simple-firewall-es_ES.mo
ADDED
Binary file
|
languages/wp-simple-firewall-fa_IR.mo
ADDED
Binary file
|
languages/wp-simple-firewall-he_IL.mo
ADDED
Binary file
|
languages/wp-simple-firewall-it_IT.mo
ADDED
Binary file
|
languages/wp-simple-firewall-pt_BR.mo
ADDED
Binary file
|
languages/wp-simple-firewall-tr_TR.mo
ADDED
Binary file
|
readme.txt
CHANGED
@@ -3,47 +3,38 @@ 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.
|
9 |
-
Stable tag: 2.
|
10 |
|
11 |
-
Complete and Simple WordPress Security. Unrestricted,
|
12 |
|
13 |
== Description ==
|
14 |
|
15 |
-
The WordPress Simple Firewall is
|
16 |
-
will prevent access to itself so that unauthorized users can't deactivate or screw with your security settings.
|
17 |
|
18 |
-
|
|
|
19 |
|
20 |
-
|
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 |
-
=
|
|
|
33 |
|
34 |
-
|
|
|
35 |
|
36 |
-
=
|
|
|
37 |
|
38 |
-
|
|
|
39 |
|
40 |
-
|
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 |
|
@@ -145,6 +136,8 @@ 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
|
@@ -223,16 +216,200 @@ This is best described on the blog: http://icwp.io/2u
|
|
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 |
-
= 2.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
236 |
|
237 |
* ADDED: Localization capabilities. All we need now are translators! [Go here to get started](http://translate.icontrolwp.com/).
|
238 |
* ADDED: Option to mask the WordPress version so the real version is never publicly visible.
|
3 |
Donate link: http://icwp.io/q
|
4 |
License: GPLv3
|
5 |
License URI: http://www.gnu.org/licenses/gpl.html
|
6 |
+
Tags: WordPress Firewall, protection, whitelist, blacklist, two-factor authentication, GASP, comment spam, automatic updates, lockdown, login, hack, login
|
7 |
Requires at least: 3.2.0
|
8 |
+
Tested up to: 3.9
|
9 |
+
Stable tag: 2.6.6
|
10 |
|
11 |
+
Complete and Simple WordPress Security. Unrestricted, Easy, No Premium Features.
|
12 |
|
13 |
== Description ==
|
14 |
|
15 |
+
The WordPress Simple Firewall is [all you need to secure your WordPress](http://icwp.io/wpsf09) sites in 6 Key Areas:
|
|
|
16 |
|
17 |
+
= Plugin Admin Access Protection =
|
18 |
+
The **only** WordPress security plugin with a WordPress-independent security key to protects itself. [more info](http://icwp.io/wpsf05)
|
19 |
|
20 |
+
= Firewall Protection =
|
21 |
+
Blocks all web requests to the site that violate the firewall rules with easy setup! [more info](http://icwp.io/wpsf06)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
|
23 |
+
= Brute Force Login Protection and Two-Factor Authentication =
|
24 |
+
Provides highly effective Brute Force Hacking Protection and email based Two-Factor Authenticated login. [more info](http://icwp.io/wpsf07)
|
25 |
|
26 |
+
= Comment SPAM (Full replacement and upgrade from Akismet) =
|
27 |
+
Blocks **ALL** automatic Bot-SPAM, and catches Human Comments SPAM without sending data to 3rd parties or charging subscription fees. [more info](http://icwp.io/wpsf08)
|
28 |
|
29 |
+
= WordPress Lock Down =
|
30 |
+
Numerous mechanisms to lock down your WordPress admin area, such as blocking file edits and enforcing SSL.
|
31 |
|
32 |
+
= Automatic Updates =
|
33 |
+
Take back control of your WordPress Automatic Updates.
|
34 |
|
35 |
+
[youtube http://www.youtube.com/watch?v=r307fu3Eqbo]
|
|
|
|
|
|
|
|
|
36 |
|
37 |
+
= A Simple Firewall Explained =
|
38 |
|
39 |
The WordPress Simple Firewall is built to be reliable, and easy to use by **anyone**. Seriously, the interface is simple! :)
|
40 |
|
136 |
|
137 |
== Frequently Asked Questions ==
|
138 |
|
139 |
+
Please see the new [help centre](http://icwp.io/firewallhelp) for details on features and some FAQs.
|
140 |
+
|
141 |
= My server has a firewall, why do I need this plugin? =
|
142 |
|
143 |
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
|
216 |
|
217 |
Best described here: http://icwp.io/2v
|
218 |
|
219 |
+
= I'm getting an update message although I have auto update enabled? =
|
220 |
+
|
221 |
+
The Automatic (Background) WordPress updates happens on a WordPress schedule - it doesn't happen immediately when an update is detected.
|
222 |
+
You can either manually upgrade, or WordPress will handle it in due course.
|
223 |
+
|
224 |
== Screenshots ==
|
225 |
|
226 |
== Changelog ==
|
227 |
|
228 |
= TODO =
|
229 |
|
|
|
230 |
* CHANGE: Interface to give a better "At-A-Glance" Dashboard summary view, that also allows you to turn on/off core features.
|
231 |
|
232 |
+
= 2.6.6 =
|
233 |
+
|
234 |
+
* FIX: Improved compatibility with bbPress.
|
235 |
+
|
236 |
+
= 2.6.5 =
|
237 |
+
|
238 |
+
* FIX: Could not enable Admin Access Protection feature on new installs due to too aggressive testing on security.
|
239 |
+
|
240 |
+
= 2.6.4 =
|
241 |
+
|
242 |
+
* ENHANCED: Dashboard now shows a more visual summary of settings and removes duplicate options settings with links to sections.
|
243 |
+
* ENHANCED: WordPress Lock Down options now also set the corresponding WordPress defines if they're not already.
|
244 |
+
|
245 |
+
= 2.6.3 =
|
246 |
+
|
247 |
+
* ADDED: More in-line plugin links to help/blog resources
|
248 |
+
* ENHANCED: [Admin Access Protection](http://icwp.io/5b) is further enhanced in 3 ways:
|
249 |
+
|
250 |
+
1. More robust cookie values using MD5s
|
251 |
+
1. Blocks plugin options updating right at the point of WordPress options update so nothing can rewrite the actual plugin options.
|
252 |
+
1. Locks the current Admin Access session to your IP address - effectively only 1 Simple Firewall admin allowed at a time.
|
253 |
+
|
254 |
+
= 2.6.2 =
|
255 |
+
|
256 |
+
* ENHANCED: Added option to completely reject a SPAM comment and redirect to the home page (so it doesn't fill up your database with rubbish)
|
257 |
+
* ADDED: Plugin now has an internal stats counter for spam and other significant plugin events.
|
258 |
+
|
259 |
+
= 2.6.1 =
|
260 |
+
|
261 |
+
* ADDED: Plugin now installs with default SPAM blacklist.
|
262 |
+
* ADDED: Now automatically checks and updates the SPAM blacklist when it's older than 48hrs.
|
263 |
+
* ENHANCED: Comment messages indicate where the SPAM content was found when marking human-based spam messages.
|
264 |
+
|
265 |
+
= 2.6.0 =
|
266 |
+
|
267 |
+
**Major Features Release: Please review SPAM comments filtering options to determine where SPAM goes**
|
268 |
+
|
269 |
+
* FEATURE: Added Human SPAM comments filtering - replacement for Akismet that doesn't use or send any data to 3rd party services. Uses [Blacklist provided and maintained by Grant Hutchinson](https://github.com/splorp/wordpress-comment-blacklist)
|
270 |
+
* ENHANCED: Two-Factor Login now automatically logs in the user to the admin area without them having to re-login again.
|
271 |
+
* ENHANCED: Added ability to terminate all currently (two-factor) verified logins.
|
272 |
+
* ENHANCED: Spam filter/scanning adds an explanation to the SPAM content to show why a message was filtered.
|
273 |
+
* FIXES: For PHP warnings while in php strict mode.
|
274 |
+
* CLEAN: Much cleaning up of code.
|
275 |
+
|
276 |
+
= 2.5.9 =
|
277 |
+
|
278 |
+
* FEATURE: Added option to try and exclude search engine bots from firewall checking option - OFF by default.
|
279 |
+
|
280 |
+
= 2.5.8 =
|
281 |
+
|
282 |
+
* FEATURE: Added 'PHP Code' Firewall checking option.
|
283 |
+
|
284 |
+
= 2.5.7 =
|
285 |
+
|
286 |
+
* IMPROVED: Handling and logic of two-factor authentication and user roles/levels
|
287 |
+
|
288 |
+
= 2.5.6 =
|
289 |
+
|
290 |
+
* FEATURE: Added ability to specify the particular WordPress user roles that are subject to 2-factor authentication. (Default: Contributors, Authors, Editors and Administrators)
|
291 |
+
|
292 |
+
= 2.5.5 =
|
293 |
+
|
294 |
+
* FEATURE: Added 'Lockdown' feature to force login to WordPress over SSL.
|
295 |
+
* FEATURE: Added 'Lockdown' feature to force WordPress Admin dashboard to be delivered over SSL.
|
296 |
+
* FIX: Admin restricted access feature wasn't disabled with the "forceOff" option.
|
297 |
+
|
298 |
+
= 2.5.4 =
|
299 |
+
|
300 |
+
* FIX: How WordPress Automatic/Background Updates filters worked was changed with WordPress 3.8.2.
|
301 |
+
|
302 |
+
= 2.5.3 =
|
303 |
+
|
304 |
+
* UPDATED: Translations. And confirmed compatibility with WordPress 3.9
|
305 |
+
|
306 |
+
= 2.5.2 =
|
307 |
+
|
308 |
+
* FEATURE: Option to Prevent Remote Posting to the WordPress Login system. Will check that the login form was submitted from the same site.
|
309 |
+
|
310 |
+
= 2.5.1 =
|
311 |
+
|
312 |
+
* UPDATED: Translations and added some partials (Catalan, Persian)
|
313 |
+
* FIX: for cleanup cron running on non-existent tables.
|
314 |
+
|
315 |
+
= 2.5.0 =
|
316 |
+
|
317 |
+
* FEATURE: Two-Factor Authenticated Login using [Yubikey](http://icwp.io/4i) One Time Passwords (OTP).
|
318 |
+
|
319 |
+
= 2.4.3 =
|
320 |
+
|
321 |
+
* ADDED: Translations: Spanish, Italian, Turkish. (~15% complete)
|
322 |
+
* UPDATED: Hebrew Translations (100%)
|
323 |
+
|
324 |
+
= 2.4.2 =
|
325 |
+
|
326 |
+
* ADDED: Contextual help links for many options. More to come...
|
327 |
+
* ADDED: More Portuguese (Brazil) translations (~80%)
|
328 |
+
|
329 |
+
= 2.4.1 =
|
330 |
+
|
331 |
+
* ADDED: More strings to the translation set for better multilingual support
|
332 |
+
* ADDED: Portuguese (Brazil) translations (~40%)
|
333 |
+
* UPDATED: Hebrew Translations
|
334 |
+
* FIXED: Automatic cleaning of database logs wasn't actually working as expected. Should now be fixed.
|
335 |
+
|
336 |
+
= 2.4.0 =
|
337 |
+
|
338 |
+
* NEW: Option to enable Two-Factor Authentication based on Cookie. In this way you can tie a user session to a single browser.
|
339 |
+
* FIX: Better WordPress Multisite (WPMS) Support.
|
340 |
+
|
341 |
+
= 2.3.4 =
|
342 |
+
|
343 |
+
* FIX: Automatic updating of itself.
|
344 |
+
|
345 |
+
= 2.3.3 =
|
346 |
+
|
347 |
+
* ADDED: Hebrew Translations. Thanks [Ahrale](http://atar4u.com)!
|
348 |
+
* ADDED: Automatic trimming of the Firewall access log to 7 days - it just grows too large otherwise.
|
349 |
+
* FIX: The previously added automatic clean up of old comments and login protect database entries was wiping out the valid login protect
|
350 |
+
entries and was forcing users to re-login every 24hrs.
|
351 |
+
* FIX: Some small bugs, errors, and PHPDoc Comments.
|
352 |
+
|
353 |
+
= 2.3.2 =
|
354 |
+
|
355 |
+
* ADDED: Automatic cleaning of GASP Comments Filter and Login Protection database entries (older than 24hrs) using WordPress Cron (everyday @ 6am)
|
356 |
+
* CHANGED: Huge code refactoring to allow for more easily use with other WordPress plugins.
|
357 |
+
|
358 |
+
= 2.2.5 =
|
359 |
+
|
360 |
+
* ADDED: Email sending options for automatic update notifications - options to change the notification email address, or turn it off completely.
|
361 |
+
|
362 |
+
= 2.2.4 =
|
363 |
+
|
364 |
+
* FIX: Small bug fix.
|
365 |
+
* CHANGED: When running a force automatic updates process, tries to remove influence from other plugins and uses only this plugin's automatic updates settings.
|
366 |
+
* CHANGED: A bit of automatic updates code refactoring.
|
367 |
+
|
368 |
+
= 2.2.2 =
|
369 |
+
|
370 |
+
* CHANGED: Changed all options to be disabled by default.
|
371 |
+
* CHANGED: The option for admin notices will turn off all main admin notices except after you update options.
|
372 |
+
|
373 |
+
= 2.2.1 =
|
374 |
+
|
375 |
+
* ADDED: Verified compatibility with WordPress 3.8
|
376 |
+
|
377 |
+
= 2.2.0 =
|
378 |
+
|
379 |
+
* CHANGED: Certain filesystem calls are more compatible with restrictive hosting environments.
|
380 |
+
* CHANGED: Plugin is now ready to integate with [iControlWP automatic background updates system](http://www.icontrolwp.com/2013/11/manage-wordpress-automatic-background-updates-icontrolwp/).
|
381 |
+
* FIX: Login Protection Cooldown feature may not operate properly in certain scenarios.
|
382 |
+
|
383 |
+
= 2.1.5 =
|
384 |
+
|
385 |
+
* IMPROVED: Improved logic for Firewall whitelisting for pages and parameters to ensure whitelisting rules are followed.
|
386 |
+
* CHANGED: The whitelisting rule for posting pages/posts is only for the "content" and the firewall checking will apply to all other page parameters.
|
387 |
+
|
388 |
+
= 2.1.4 =
|
389 |
+
|
390 |
+
* FIX: When you run the Force Automatic Background Updates, it disables the plugins. This problem is now fixed.
|
391 |
+
|
392 |
+
= 2.1.2 =
|
393 |
+
|
394 |
+
* FIX: A bug that prevented auto-updates of this plugin.
|
395 |
+
* FIX: Not being able to hide translations and upgrade notices.
|
396 |
+
* ADDED: Tweaks to auto-update feature to allow interfacing with the iControlWP service to customize the auto update system.
|
397 |
+
|
398 |
+
= 2.1.0 =
|
399 |
+
|
400 |
+
* ADDED: A button that lets you run the WordPress Automatic Updates process on-demand (so you don't have to wait for WordPress cron).
|
401 |
+
* CHANGED: The plugin now sets more options to be turned on by default when the plugin is first activated.
|
402 |
+
* CHANGED: A lot of optimizations and code refactoring.
|
403 |
+
|
404 |
+
= 2.0.3 =
|
405 |
+
|
406 |
+
* FIX: Whoops, sorry, accidentally removed the option to toggle "disable file editing". It's back now.
|
407 |
+
|
408 |
+
= 2.0.2 =
|
409 |
+
|
410 |
+
* CHANGED: WordPress filters used to programmatically update whitelists now update the Login Protection IP whitelist
|
411 |
+
|
412 |
+
= 2.0.1 =
|
413 |
|
414 |
* ADDED: Localization capabilities. All we need now are translators! [Go here to get started](http://translate.icontrolwp.com/).
|
415 |
* ADDED: Option to mask the WordPress version so the real version is never publicly visible.
|
resources/css/{bootstrap-wpadmin.css → bootstrap-wpadmin-legacy.css}
RENAMED
File without changes
|
resources/css/{icontrolwp-plugin.css → plugin.css}
RENAMED
@@ -7,8 +7,18 @@
|
|
7 |
.bootstrap-wpadmin .row {
|
8 |
margin-left: 0;
|
9 |
}
|
10 |
-
#
|
11 |
-
background: url("../images/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
}
|
13 |
.wrap .icon32 {
|
14 |
width: 32px;
|
@@ -72,9 +82,10 @@ p.code-description {
|
|
72 |
font-style: italic;
|
73 |
}
|
74 |
.option_section {
|
75 |
-
|
76 |
-
border
|
77 |
-
|
|
|
78 |
padding: 8px 10px;
|
79 |
}
|
80 |
.option_section label {
|
@@ -124,4 +135,8 @@ table#tbl_tbs_options_javascript td {
|
|
124 |
/** OPTIONS PAGES **/
|
125 |
.bootstrap-wpadmin .row.row_number_1 {
|
126 |
padding-top: 18px;
|
|
|
|
|
|
|
|
|
127 |
}
|
7 |
.bootstrap-wpadmin .row {
|
8 |
margin-left: 0;
|
9 |
}
|
10 |
+
#pluginlogo_32 {
|
11 |
+
background: url("../images/pluginlogo_32x32.png") no-repeat 0px 3px transparent;
|
12 |
+
}
|
13 |
+
.pluginlogo_16 {
|
14 |
+
background: url("../images/pluginlogo_16x16.png") no-repeat 0px 3px transparent;
|
15 |
+
}
|
16 |
+
.page-header .header-icon32 {
|
17 |
+
display: inline-block;
|
18 |
+
float: left;
|
19 |
+
height: 40px;
|
20 |
+
vertical-align: middle;
|
21 |
+
width: 48px;
|
22 |
}
|
23 |
.wrap .icon32 {
|
24 |
width: 32px;
|
82 |
font-style: italic;
|
83 |
}
|
84 |
.option_section {
|
85 |
+
background-color: rgba(0, 0, 0, 0.008);
|
86 |
+
border: 1px solid #E6E6E6;
|
87 |
+
border-radius: 8px;
|
88 |
+
margin-bottom: 8px;
|
89 |
padding: 8px 10px;
|
90 |
}
|
91 |
.option_section label {
|
135 |
/** OPTIONS PAGES **/
|
136 |
.bootstrap-wpadmin .row.row_number_1 {
|
137 |
padding-top: 18px;
|
138 |
+
}
|
139 |
+
|
140 |
+
label input[type=checkbox] {
|
141 |
+
height: 16px !important;
|
142 |
}
|
resources/css/worpit-plugin.css
DELETED
@@ -1,119 +0,0 @@
|
|
1 |
-
@CHARSET "ISO-8859-1";
|
2 |
-
|
3 |
-
/* GENERAL STYLES */
|
4 |
-
|
5 |
-
.bootstrap-wpadmin {
|
6 |
-
}
|
7 |
-
.bootstrap-wpadmin .row {
|
8 |
-
margin-left: 0;
|
9 |
-
}
|
10 |
-
#worpit-icon {
|
11 |
-
background: url("../images/worpit_32x32.png") no-repeat 0px 3px transparent;
|
12 |
-
}
|
13 |
-
/* Form elements */
|
14 |
-
.bootstrap-wpadmin form fieldset {
|
15 |
-
}
|
16 |
-
.bootstrap-wpadmin .label {
|
17 |
-
vertical-align: baseline !important;
|
18 |
-
}
|
19 |
-
.shortcode-usage {
|
20 |
-
border-bottom: 1px solid #bbbbbb;
|
21 |
-
margin-bottom: 10px;
|
22 |
-
}
|
23 |
-
p.code-description {
|
24 |
-
font-style: italic;
|
25 |
-
}
|
26 |
-
/* Worpit promo */
|
27 |
-
#worpit_button {
|
28 |
-
background: url("../images/bright_squares.png") #EFEFEF;
|
29 |
-
}
|
30 |
-
#worpit_button {
|
31 |
-
border: 1px solid #cccccc;
|
32 |
-
border-radius: 4px;
|
33 |
-
height: 190px;
|
34 |
-
}
|
35 |
-
#worpit_button:hover {
|
36 |
-
box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.4);
|
37 |
-
border: 1px solid transparent;
|
38 |
-
}
|
39 |
-
.row#developer_channel_promo #developer_channel_description .well {
|
40 |
-
height: 275px;
|
41 |
-
}
|
42 |
-
.row#developer_channel_promo #developer_channel_form {
|
43 |
-
border: 1px solid #EEE;
|
44 |
-
border-radius: 6px;
|
45 |
-
height: 315px; /* 275px + 20px-padding-x2 */
|
46 |
-
}
|
47 |
-
.row#developer_channel_promo #developer_channel_form h3 {
|
48 |
-
padding: 10px 20px;
|
49 |
-
}
|
50 |
-
|
51 |
-
/** LESS PAGE **/
|
52 |
-
.enabled_section {
|
53 |
-
opacity: 1.0;
|
54 |
-
}
|
55 |
-
.disabled_section {
|
56 |
-
opacity: 0.5;
|
57 |
-
}
|
58 |
-
/* BOOSTRAP SETTINGS PAGE STYLES */
|
59 |
-
.wrap .icon32 {
|
60 |
-
width: 32px;
|
61 |
-
}
|
62 |
-
.submit span {
|
63 |
-
font-size: smaller;
|
64 |
-
font-style: italic;
|
65 |
-
}
|
66 |
-
.option_section {
|
67 |
-
border: 1px solid #f2f2f2;
|
68 |
-
border-radius: 8px 8px 8px 8px;
|
69 |
-
margin-bottom: 8px;
|
70 |
-
padding: 8px 10px;
|
71 |
-
}
|
72 |
-
.option_section label {
|
73 |
-
background-color: transparent;
|
74 |
-
}
|
75 |
-
.selected_item label {
|
76 |
-
font-weight: bold;
|
77 |
-
}
|
78 |
-
.nonselected_item {
|
79 |
-
background-color: transparent;
|
80 |
-
}
|
81 |
-
.nonselected_item label {
|
82 |
-
font-weight: normal;
|
83 |
-
}
|
84 |
-
.option_section:hover {
|
85 |
-
background-color: #ffffff;
|
86 |
-
border: 1px dashed #BBBBBB;
|
87 |
-
cursor: pointer;
|
88 |
-
}
|
89 |
-
|
90 |
-
.option_section.active {
|
91 |
-
background-color: #f6f6f6;
|
92 |
-
border-color: #dddddd;
|
93 |
-
}
|
94 |
-
table.tbl_tbs_options {
|
95 |
-
width: 100%;
|
96 |
-
border: 1px solid transparent;
|
97 |
-
}
|
98 |
-
table.tbl_tbs_options tr td {
|
99 |
-
width: 49%;
|
100 |
-
border: 1px solid transparent;
|
101 |
-
}
|
102 |
-
|
103 |
-
select#hlt_bootstrap_option {
|
104 |
-
padding: 5px;
|
105 |
-
border-radius:6px 6px 6px 6px;
|
106 |
-
line-height: auto;
|
107 |
-
height: 30px;
|
108 |
-
width: 200px;
|
109 |
-
}
|
110 |
-
|
111 |
-
table#tbl_tbs_options_javascript td {
|
112 |
-
vertical-align: top;
|
113 |
-
width: 50%;
|
114 |
-
}
|
115 |
-
|
116 |
-
/** OPTIONS PAGES **/
|
117 |
-
.bootstrap-wpadmin .row.row_number_1 {
|
118 |
-
padding-top: 18px;
|
119 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
resources/images/icontrolwp_16x16.png
DELETED
Binary file
|
resources/images/icontrolwp_24x24.png
DELETED
Binary file
|
resources/images/icontrolwp_32x32.png
DELETED
Binary file
|
resources/images/pluginlogo_16x16.png
ADDED
Binary file
|
resources/images/pluginlogo_24x24.png
ADDED
Binary file
|
resources/images/pluginlogo_32x32.png
ADDED
Binary file
|
resources/images/pluginlogo_64x64.png
ADDED
Binary file
|
resources/spamblacklist.txt
ADDED
@@ -0,0 +1,10549 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
_account
|
2 |
+
_article
|
3 |
+
_asics
|
4 |
+
_backup
|
5 |
+
_benefit
|
6 |
+
_blog
|
7 |
+
_bord
|
8 |
+
_build
|
9 |
+
_campaign
|
10 |
+
_coup
|
11 |
+
_data
|
12 |
+
_discount
|
13 |
+
_downtime
|
14 |
+
_e/
|
15 |
+
_emerg
|
16 |
+
_entr
|
17 |
+
_free
|
18 |
+
_help
|
19 |
+
_htm
|
20 |
+
_http
|
21 |
+
_index
|
22 |
+
_info
|
23 |
+
_java
|
24 |
+
_jersey
|
25 |
+
_key
|
26 |
+
_kino
|
27 |
+
_kit
|
28 |
+
_lacoste
|
29 |
+
_lauren
|
30 |
+
_link
|
31 |
+
_list
|
32 |
+
_load
|
33 |
+
_loan
|
34 |
+
_market
|
35 |
+
_misc
|
36 |
+
_news
|
37 |
+
_note
|
38 |
+
_occh
|
39 |
+
_online
|
40 |
+
_outlet
|
41 |
+
_porn
|
42 |
+
_post
|
43 |
+
_prof
|
44 |
+
_review
|
45 |
+
_sale
|
46 |
+
_scarpe
|
47 |
+
_select
|
48 |
+
_seo
|
49 |
+
_serv
|
50 |
+
_site
|
51 |
+
_spade
|
52 |
+
_store
|
53 |
+
_strat
|
54 |
+
_temp
|
55 |
+
_theme
|
56 |
+
_title
|
57 |
+
_track
|
58 |
+
_uptime
|
59 |
+
_url
|
60 |
+
_util
|
61 |
+
_vti
|
62 |
+
_weblog
|
63 |
+
---
|
64 |
+
--and
|
65 |
+
--bag
|
66 |
+
--jack
|
67 |
+
--serv
|
68 |
+
--shut
|
69 |
+
--stor
|
70 |
+
--that
|
71 |
+
-(
|
72 |
+
-24.
|
73 |
+
-abercrombie-
|
74 |
+
-abercrombie.
|
75 |
+
-abercrombie/
|
76 |
+
-abercrombiefitch-
|
77 |
+
-abercrombiefitch.
|
78 |
+
-abercrombiefitch/
|
79 |
+
-acne-
|
80 |
+
-acne.
|
81 |
+
-acne/
|
82 |
+
-adsense-
|
83 |
+
-adsense.
|
84 |
+
-adsense/
|
85 |
+
-amateur-
|
86 |
+
-amateur.
|
87 |
+
-amateur/
|
88 |
+
-anal-
|
89 |
+
-anal.
|
90 |
+
-anal/
|
91 |
+
-anonymous-
|
92 |
+
-anonymous.
|
93 |
+
-anonymous/
|
94 |
+
-argente-
|
95 |
+
-argente.
|
96 |
+
-argente/
|
97 |
+
-armani-
|
98 |
+
-armani.
|
99 |
+
-armani/
|
100 |
+
-asics-
|
101 |
+
-asics.
|
102 |
+
-asics/
|
103 |
+
-auction-
|
104 |
+
-auction.
|
105 |
+
-auction/
|
106 |
+
-authentic-
|
107 |
+
-authentic.
|
108 |
+
-authentic/
|
109 |
+
-b2b
|
110 |
+
-backpain-
|
111 |
+
-backpain.
|
112 |
+
-backpain/
|
113 |
+
-beneficial-
|
114 |
+
-beneficial.
|
115 |
+
-beneficial/
|
116 |
+
-bioactive-
|
117 |
+
-bioactive.
|
118 |
+
-bioactive/
|
119 |
+
-bioactives-
|
120 |
+
-bioactives.
|
121 |
+
-bioactives/
|
122 |
+
-bitcoin-
|
123 |
+
-bitcoin.
|
124 |
+
-bitcoin/
|
125 |
+
-blog.
|
126 |
+
-blog/
|
127 |
+
-blogs.
|
128 |
+
-blogs/
|
129 |
+
-bluray-
|
130 |
+
-bluray.
|
131 |
+
-bluray/
|
132 |
+
-bodybuilding.
|
133 |
+
-bodybuilding/
|
134 |
+
-breathalyzer-
|
135 |
+
-broker.
|
136 |
+
-broker/
|
137 |
+
-buy.
|
138 |
+
-buy/
|
139 |
+
-car.co
|
140 |
+
-car.in
|
141 |
+
-casas-en-
|
142 |
+
-cash.
|
143 |
+
-cash/
|
144 |
+
-casino-
|
145 |
+
-casino.
|
146 |
+
-casino/
|
147 |
+
-cell-phone-
|
148 |
+
-charms.
|
149 |
+
-charms/
|
150 |
+
-cheap-
|
151 |
+
-cheap.
|
152 |
+
-cheap/
|
153 |
+
-cheapest-
|
154 |
+
-cheapest.
|
155 |
+
-cheapest/
|
156 |
+
-cheat-
|
157 |
+
-cheat.
|
158 |
+
-cheat/
|
159 |
+
-cia.co
|
160 |
+
-cigar-
|
161 |
+
-cigar.
|
162 |
+
-cigar/
|
163 |
+
-cigarette-
|
164 |
+
-cigarette.
|
165 |
+
-cigarette/
|
166 |
+
-cigarettes-
|
167 |
+
-cigarettes.
|
168 |
+
-cigarettes/
|
169 |
+
-cigars-
|
170 |
+
-cigars.
|
171 |
+
-cigars/
|
172 |
+
-click-
|
173 |
+
-click.
|
174 |
+
-click/
|
175 |
+
-co.jp
|
176 |
+
-cock-
|
177 |
+
-cock.
|
178 |
+
-cock/
|
179 |
+
-coin.
|
180 |
+
-coin/
|
181 |
+
-coins.
|
182 |
+
-coins/
|
183 |
+
-comfort-
|
184 |
+
-cosmetics.
|
185 |
+
-costume.
|
186 |
+
-coupon-
|
187 |
+
-data-recovery-
|
188 |
+
-deluxe-
|
189 |
+
-demo1
|
190 |
+
-diagnostic-
|
191 |
+
-dieta-
|
192 |
+
-dieta.
|
193 |
+
-dieta/
|
194 |
+
-directory.
|
195 |
+
-discount
|
196 |
+
-doktora-
|
197 |
+
-doktora.
|
198 |
+
-doktora/
|
199 |
+
-domination-
|
200 |
+
-domination.
|
201 |
+
-domination/
|
202 |
+
-download.
|
203 |
+
-download/
|
204 |
+
-dre.
|
205 |
+
-dre/
|
206 |
+
-drmartens-
|
207 |
+
-drmartens.
|
208 |
+
-drmartens/
|
209 |
+
-e-guide-
|
210 |
+
-easily-
|
211 |
+
-ebay
|
212 |
+
-enlargement.
|
213 |
+
-enlargement/
|
214 |
+
-entries/
|
215 |
+
-escort.
|
216 |
+
-escort/
|
217 |
+
-essay.
|
218 |
+
-essay/
|
219 |
+
-executive.
|
220 |
+
-executive/
|
221 |
+
-fantasia-
|
222 |
+
-fantasia.
|
223 |
+
-fashion-
|
224 |
+
-fashion.
|
225 |
+
-fashion/
|
226 |
+
-filmy
|
227 |
+
-finance.
|
228 |
+
-finance/
|
229 |
+
-financing.
|
230 |
+
-financing/
|
231 |
+
-fitch.
|
232 |
+
-fitch/
|
233 |
+
-for-adult
|
234 |
+
-for-sale
|
235 |
+
-for-u-
|
236 |
+
-for-u.
|
237 |
+
-for-u/
|
238 |
+
-for-you
|
239 |
+
-foreclose-
|
240 |
+
-foreclose.
|
241 |
+
-foreclose/
|
242 |
+
-foreclosed-
|
243 |
+
-foreclosed.
|
244 |
+
-foreclosed/
|
245 |
+
-foreclosure-
|
246 |
+
-foreclosure.
|
247 |
+
-foreclosure/
|
248 |
+
-fotograf.
|
249 |
+
-fotograf/
|
250 |
+
-fotografia.
|
251 |
+
-fotografia/
|
252 |
+
-fuck-
|
253 |
+
-fuck.
|
254 |
+
-fuck/
|
255 |
+
-fucked-
|
256 |
+
-fucked.
|
257 |
+
-fucked/
|
258 |
+
-fucker-
|
259 |
+
-fucker.
|
260 |
+
-fucker/
|
261 |
+
-fucking-
|
262 |
+
-fucking.
|
263 |
+
-fucking/
|
264 |
+
-fucks-
|
265 |
+
-fucks.
|
266 |
+
-fucks/
|
267 |
+
-fund-
|
268 |
+
-fund.
|
269 |
+
-fund/
|
270 |
+
-gambling-
|
271 |
+
-gambling.
|
272 |
+
-gambling/
|
273 |
+
-gaming-
|
274 |
+
-gaming.
|
275 |
+
-gaming/
|
276 |
+
-get-free-
|
277 |
+
-gifts-
|
278 |
+
-handbag-
|
279 |
+
-handbag.
|
280 |
+
-handbag/
|
281 |
+
-handbags-
|
282 |
+
-handbags.
|
283 |
+
-handbags/
|
284 |
+
-harley-davidson-
|
285 |
+
-herbal-
|
286 |
+
-herbal.
|
287 |
+
-herbal/
|
288 |
+
-hermes-
|
289 |
+
-hermes.
|
290 |
+
-hermes/
|
291 |
+
-hgh.
|
292 |
+
-hgh/
|
293 |
+
-income-
|
294 |
+
-income.
|
295 |
+
-income/
|
296 |
+
-infotain
|
297 |
+
-insurance.
|
298 |
+
-insurance/
|
299 |
+
-iphone-4-
|
300 |
+
-iphone-5-
|
301 |
+
-jacket-
|
302 |
+
-jacket.
|
303 |
+
-jacket/
|
304 |
+
-jackets-
|
305 |
+
-jackets.
|
306 |
+
-jackets/
|
307 |
+
-jeremy-scott-
|
308 |
+
-jerking-
|
309 |
+
-jerking.
|
310 |
+
-jerking/
|
311 |
+
-jersey-
|
312 |
+
-jersey.
|
313 |
+
-jersey/
|
314 |
+
-jerseys.
|
315 |
+
-jerseys/
|
316 |
+
-kredyt
|
317 |
+
-lacoste-
|
318 |
+
-link.
|
319 |
+
-link/
|
320 |
+
-linkbuild
|
321 |
+
-loan-
|
322 |
+
-loans-
|
323 |
+
-longchamp-
|
324 |
+
-longchamp.
|
325 |
+
-longchamp/
|
326 |
+
-lottery-
|
327 |
+
-lottery.
|
328 |
+
-lottery/
|
329 |
+
-lotto-
|
330 |
+
-lotto.
|
331 |
+
-lotto/
|
332 |
+
-lover-
|
333 |
+
-lover.
|
334 |
+
-lover/
|
335 |
+
-magazin-
|
336 |
+
-magazini-
|
337 |
+
-malware-
|
338 |
+
-malware.
|
339 |
+
-malware/
|
340 |
+
-marant-
|
341 |
+
-marc-jacobs-
|
342 |
+
-marcjacobs-
|
343 |
+
-mastery.
|
344 |
+
-mastery/
|
345 |
+
-mbt.
|
346 |
+
-mbt/
|
347 |
+
-mbts.
|
348 |
+
-mbts/
|
349 |
+
-men-jersey
|
350 |
+
-mens-jersey
|
351 |
+
-mens.
|
352 |
+
-metods-
|
353 |
+
-mlm.
|
354 |
+
-mlm/
|
355 |
+
-mlsp.
|
356 |
+
-mlsp/
|
357 |
+
-model.co
|
358 |
+
-models.co
|
359 |
+
-mortgage-
|
360 |
+
-new-car-
|
361 |
+
-newports/
|
362 |
+
-npn.
|
363 |
+
-npn/
|
364 |
+
-nude-
|
365 |
+
-nudes-
|
366 |
+
-oakley.
|
367 |
+
-oakley/
|
368 |
+
-occhiali/
|
369 |
+
-odejda-
|
370 |
+
-off-your-
|
371 |
+
-offshore-
|
372 |
+
-onlayn-
|
373 |
+
-online.
|
374 |
+
-online/
|
375 |
+
-order-at-
|
376 |
+
-outlet.
|
377 |
+
-outlet/
|
378 |
+
-payday-
|
379 |
+
-pictures.
|
380 |
+
-poker-
|
381 |
+
-poker.
|
382 |
+
-poker/
|
383 |
+
-pokie-
|
384 |
+
-pokie.
|
385 |
+
-pokie/
|
386 |
+
-pokies-
|
387 |
+
-pokies.
|
388 |
+
-pokies/
|
389 |
+
-pozew-
|
390 |
+
-prada-
|
391 |
+
-prada.
|
392 |
+
-prada/
|
393 |
+
-premium-
|
394 |
+
-premium.
|
395 |
+
-premium/
|
396 |
+
-price.
|
397 |
+
-price/
|
398 |
+
-programy-
|
399 |
+
-programy.
|
400 |
+
-programy/
|
401 |
+
-promo-
|
402 |
+
-promo.
|
403 |
+
-promo/
|
404 |
+
-promotions-
|
405 |
+
-promotions.
|
406 |
+
-promotions/
|
407 |
+
-purse.
|
408 |
+
-purse/
|
409 |
+
-purses.
|
410 |
+
-purses/
|
411 |
+
-pussy-
|
412 |
+
-rayban.
|
413 |
+
-rdnk-
|
414 |
+
-real-estate-
|
415 |
+
-realestate-
|
416 |
+
-remote-access
|
417 |
+
-remote-desktop
|
418 |
+
-repair.co
|
419 |
+
-review.co
|
420 |
+
-review/
|
421 |
+
-rims-
|
422 |
+
-rozwod-
|
423 |
+
-ru.
|
424 |
+
-sale.co
|
425 |
+
-sale.org
|
426 |
+
-salvia-
|
427 |
+
-scarpe-
|
428 |
+
-search-engine
|
429 |
+
-searchengine
|
430 |
+
-secrets-
|
431 |
+
-select-your-
|
432 |
+
-selection.
|
433 |
+
-selection/
|
434 |
+
-seo
|
435 |
+
-service.
|
436 |
+
-sexy-
|
437 |
+
-shiatsu.
|
438 |
+
-shoes.
|
439 |
+
-shop.co
|
440 |
+
-sigareta-
|
441 |
+
-sigareta.
|
442 |
+
-sigareta/
|
443 |
+
-sigarety-
|
444 |
+
-sigarety.
|
445 |
+
-sigarety/
|
446 |
+
-sims-3.
|
447 |
+
-sims-3/
|
448 |
+
-soma.
|
449 |
+
-soma/
|
450 |
+
-speed-up-
|
451 |
+
-store.
|
452 |
+
-store/
|
453 |
+
-strona-
|
454 |
+
-strona.
|
455 |
+
-strona/
|
456 |
+
-strony-
|
457 |
+
-strony.
|
458 |
+
-strony/
|
459 |
+
-sunglasses-
|
460 |
+
-sunglasses.
|
461 |
+
-sunglasses/
|
462 |
+
-supplement-
|
463 |
+
-supplement.
|
464 |
+
-supplement/
|
465 |
+
-supplements-
|
466 |
+
-supplements.
|
467 |
+
-supplements/
|
468 |
+
-suppliment-
|
469 |
+
-suppliment.
|
470 |
+
-suppliment/
|
471 |
+
-suppliments-
|
472 |
+
-suppliments.
|
473 |
+
-suppliments/
|
474 |
+
-symptoms-
|
475 |
+
-tax-attorney
|
476 |
+
-tax-relief
|
477 |
+
-tax-settlement
|
478 |
+
-teen-in-
|
479 |
+
-the-best-
|
480 |
+
-the-easiest-
|
481 |
+
-the-greatest-
|
482 |
+
-thunderstick-
|
483 |
+
-tips/
|
484 |
+
-top-info
|
485 |
+
-tours.co
|
486 |
+
-traffic.
|
487 |
+
-trainings.
|
488 |
+
-trainings/
|
489 |
+
-transpiration-
|
490 |
+
-treatment-
|
491 |
+
-tw.in
|
492 |
+
-uggs-
|
493 |
+
-uk.net
|
494 |
+
-vaginal-
|
495 |
+
-vendita-
|
496 |
+
-vuitton-
|
497 |
+
-watches.
|
498 |
+
-watches/
|
499 |
+
-wayfarer.
|
500 |
+
-web-pag
|
501 |
+
-web-site
|
502 |
+
-webhost.
|
503 |
+
-website-
|
504 |
+
-wedding-dress
|
505 |
+
-wedding-photo
|
506 |
+
-wheels-
|
507 |
+
-wholesale.
|
508 |
+
-wizard.co
|
509 |
+
-women-jersey
|
510 |
+
-womens.
|
511 |
+
-xchange
|
512 |
+
・・
|
513 |
+
, ,
|
514 |
+
, .
|
515 |
+
,,
|
516 |
+
,.
|
517 |
+
,"
|
518 |
+
,ag
|
519 |
+
,an
|
520 |
+
,en
|
521 |
+
,he
|
522 |
+
,in
|
523 |
+
,kat,
|
524 |
+
,m,
|
525 |
+
,me
|
526 |
+
,no
|
527 |
+
,of
|
528 |
+
,on
|
529 |
+
,th
|
530 |
+
,title,
|
531 |
+
,we
|
532 |
+
、、
|
533 |
+
::
|
534 |
+
:)!
|
535 |
+
! .
|
536 |
+
!!!
|
537 |
+
!?’
|
538 |
+
!@#
|
539 |
+
????
|
540 |
+
?/pag
|
541 |
+
?add
|
542 |
+
?browse
|
543 |
+
?domain
|
544 |
+
?firma
|
545 |
+
?free
|
546 |
+
?kat
|
547 |
+
?key
|
548 |
+
?lang
|
549 |
+
?sexy
|
550 |
+
?store
|
551 |
+
?title
|
552 |
+
?twid
|
553 |
+
?user
|
554 |
+
?view
|
555 |
+
.%
|
556 |
+
.acgi
|
557 |
+
.adboard
|
558 |
+
.adsboard
|
559 |
+
.asp/
|
560 |
+
.azmya.
|
561 |
+
.baidu
|
562 |
+
.bioactive
|
563 |
+
.biz
|
564 |
+
.blogbox.be
|
565 |
+
.blogspace.
|
566 |
+
.bluray.
|
567 |
+
.causes-
|
568 |
+
.cfmx
|
569 |
+
.cgi
|
570 |
+
.com wild
|
571 |
+
.com/,
|
572 |
+
.com/%
|
573 |
+
.com/1.
|
574 |
+
.com/2.
|
575 |
+
.com/3.
|
576 |
+
.coupon
|
577 |
+
.credopa.in
|
578 |
+
.disposable-
|
579 |
+
.disposable/
|
580 |
+
.doorblog.jp
|
581 |
+
.executive-
|
582 |
+
.fake-
|
583 |
+
.fcgi
|
584 |
+
.filpan.ru
|
585 |
+
.filvce.in
|
586 |
+
.forum.
|
587 |
+
.frebvic.in
|
588 |
+
.freeforums.org
|
589 |
+
.games.pl
|
590 |
+
.hard-
|
591 |
+
.htm?
|
592 |
+
.htm/
|
593 |
+
.html?
|
594 |
+
.html/
|
595 |
+
.htn
|
596 |
+
.in/,
|
597 |
+
.in/1.
|
598 |
+
.in/2.
|
599 |
+
.in/3.
|
600 |
+
.info.
|
601 |
+
.info/,
|
602 |
+
.insanity-
|
603 |
+
.internet-
|
604 |
+
.jp/my/
|
605 |
+
.jp/shop
|
606 |
+
.longchamp-
|
607 |
+
.magix.net
|
608 |
+
.mobi/?
|
609 |
+
.moncler-
|
610 |
+
.net/online
|
611 |
+
.net/user
|
612 |
+
.nikeshox
|
613 |
+
.on-demand
|
614 |
+
.online.pl
|
615 |
+
.online.ws
|
616 |
+
.or.kr
|
617 |
+
.org/,
|
618 |
+
.org/user
|
619 |
+
.outlet.co
|
620 |
+
.php?
|
621 |
+
.php/?
|
622 |
+
.pl?
|
623 |
+
.pl/?
|
624 |
+
.pl/#
|
625 |
+
.pl/1.
|
626 |
+
.pl/2.
|
627 |
+
.pl/3.
|
628 |
+
.pl/content
|
629 |
+
.pl/member
|
630 |
+
.pl/profile
|
631 |
+
.pl/user
|
632 |
+
.pl#
|
633 |
+
.rar.
|
634 |
+
.redirects.
|
635 |
+
.rekla
|
636 |
+
.remote-desktop
|
637 |
+
.remotedesktop
|
638 |
+
.royal-
|
639 |
+
.rshacks.
|
640 |
+
.ru?
|
641 |
+
.ru/,
|
642 |
+
.ru/?
|
643 |
+
.ru/#
|
644 |
+
.ru/1.
|
645 |
+
.ru/2.
|
646 |
+
.ru/3.
|
647 |
+
.ru/content
|
648 |
+
.ru/forum
|
649 |
+
.ru/image
|
650 |
+
.ru/member
|
651 |
+
.ru/profile
|
652 |
+
.ru/service
|
653 |
+
.ru/user
|
654 |
+
.ru#
|
655 |
+
.sirenos.in
|
656 |
+
.smiley
|
657 |
+
.sunglasses-
|
658 |
+
.supreme-
|
659 |
+
.thearticle
|
660 |
+
.travel.pl
|
661 |
+
.twilight-
|
662 |
+
.univer.
|
663 |
+
.us/user
|
664 |
+
.webs.co
|
665 |
+
.worktop.
|
666 |
+
.worktops.
|
667 |
+
.za/image
|
668 |
+
''
|
669 |
+
)-
|
670 |
+
[...
|
671 |
+
[/color
|
672 |
+
[/move
|
673 |
+
[/url
|
674 |
+
[color
|
675 |
+
[move
|
676 |
+
[url
|
677 |
+
@123
|
678 |
+
@mail-
|
679 |
+
@toke.
|
680 |
+
*@
|
681 |
+
/-_
|
682 |
+
/?cat
|
683 |
+
/?doc
|
684 |
+
/?l1
|
685 |
+
/?l2
|
686 |
+
/?new
|
687 |
+
/?p=
|
688 |
+
/?pag
|
689 |
+
/?tag
|
690 |
+
/?uid
|
691 |
+
/.wd/
|
692 |
+
//123.
|
693 |
+
//aaa-
|
694 |
+
//aaa.
|
695 |
+
//act-
|
696 |
+
//act.
|
697 |
+
//affordable
|
698 |
+
//article
|
699 |
+
//best
|
700 |
+
//bitcoin
|
701 |
+
//businessdaily
|
702 |
+
//buy
|
703 |
+
//cheap
|
704 |
+
//compare
|
705 |
+
//contact
|
706 |
+
//eee
|
707 |
+
//escort
|
708 |
+
//forum
|
709 |
+
//free
|
710 |
+
//friend
|
711 |
+
//gay
|
712 |
+
//generic
|
713 |
+
//groups
|
714 |
+
//hgh
|
715 |
+
//images/
|
716 |
+
//income
|
717 |
+
//leverage
|
718 |
+
//official
|
719 |
+
//onsale
|
720 |
+
//pagina
|
721 |
+
//podcast-
|
722 |
+
//podcast.
|
723 |
+
//prosport
|
724 |
+
//reality
|
725 |
+
//royal-
|
726 |
+
//ru.
|
727 |
+
//shop
|
728 |
+
//test
|
729 |
+
//vpn-
|
730 |
+
//vpn.
|
731 |
+
//webpage
|
732 |
+
//website
|
733 |
+
//webstore
|
734 |
+
//wp-
|
735 |
+
/10.htm
|
736 |
+
/11.htm
|
737 |
+
/12.htm
|
738 |
+
/13.htm
|
739 |
+
/14.htm
|
740 |
+
/15.htm
|
741 |
+
/100mg
|
742 |
+
/a-
|
743 |
+
/a#
|
744 |
+
/abercrombie-
|
745 |
+
/abercrombie.
|
746 |
+
/about.
|
747 |
+
/acai
|
748 |
+
/acidreflux-
|
749 |
+
/acidreflux.
|
750 |
+
/add.
|
751 |
+
/addfeed/
|
752 |
+
/admin/
|
753 |
+
/administration/
|
754 |
+
/adorable-
|
755 |
+
/adorable.
|
756 |
+
/ads/
|
757 |
+
/affordable-
|
758 |
+
/affordable.
|
759 |
+
/airmax-
|
760 |
+
/airmax.
|
761 |
+
/alimenty/
|
762 |
+
/allimage/
|
763 |
+
/anonymous-
|
764 |
+
/anonymous.
|
765 |
+
/answer-
|
766 |
+
/answer.
|
767 |
+
/armani-
|
768 |
+
/armani.
|
769 |
+
/around.
|
770 |
+
/asics-
|
771 |
+
/asics.
|
772 |
+
/asp/
|
773 |
+
/asthma-
|
774 |
+
/asthma.
|
775 |
+
/attachments/
|
776 |
+
/authentic
|
777 |
+
/baby-
|
778 |
+
/baby.
|
779 |
+
/babydoll-
|
780 |
+
/babydoll.
|
781 |
+
/bag.sh/
|
782 |
+
/bags/
|
783 |
+
/banner-
|
784 |
+
/banner.
|
785 |
+
/banners-
|
786 |
+
/banners.
|
787 |
+
/bazar-
|
788 |
+
/bazar.
|
789 |
+
/bbs/
|
790 |
+
/best-
|
791 |
+
/best.
|
792 |
+
/better-
|
793 |
+
/better.
|
794 |
+
/birkenstock-
|
795 |
+
/birkenstock.
|
796 |
+
/birkenstocks-
|
797 |
+
/birkenstocks.
|
798 |
+
/birkin.
|
799 |
+
/bitcoin-
|
800 |
+
/black-friday
|
801 |
+
/blog:
|
802 |
+
/blog.
|
803 |
+
/blogid
|
804 |
+
/bloglist/
|
805 |
+
/blogs/
|
806 |
+
/board/
|
807 |
+
/bookmark-
|
808 |
+
/bookmark.
|
809 |
+
/bookmarks-
|
810 |
+
/bookmarks.
|
811 |
+
/brand1
|
812 |
+
/brand2
|
813 |
+
/brand3
|
814 |
+
/brand4
|
815 |
+
/brand5
|
816 |
+
/burberry-
|
817 |
+
/burberry1
|
818 |
+
/burberry2
|
819 |
+
/burberry3
|
820 |
+
/burberry4
|
821 |
+
/bustier-
|
822 |
+
/bustier.
|
823 |
+
/buy-
|
824 |
+
/buy.
|
825 |
+
/bvlgari-
|
826 |
+
/bvlgari.
|
827 |
+
/cache/
|
828 |
+
/campaign-
|
829 |
+
/campaign.
|
830 |
+
/campaign/
|
831 |
+
/campaigns-
|
832 |
+
/campaigns.
|
833 |
+
/campaigns/
|
834 |
+
/canadagoose-
|
835 |
+
/canadagoose.
|
836 |
+
/canadagoose/
|
837 |
+
/carinsur-
|
838 |
+
/carinsur.
|
839 |
+
/carinsurance-
|
840 |
+
/carinsurance.
|
841 |
+
/cartier-
|
842 |
+
/cartier.
|
843 |
+
/casino
|
844 |
+
/categories-
|
845 |
+
/category-
|
846 |
+
/chanel-
|
847 |
+
/chanel.
|
848 |
+
/chat/
|
849 |
+
/chaussure-
|
850 |
+
/chaussure.
|
851 |
+
/chaussures-
|
852 |
+
/chaussures.
|
853 |
+
/cheap-
|
854 |
+
/cheap.
|
855 |
+
/china.
|
856 |
+
/chrome/
|
857 |
+
/chrome=
|
858 |
+
/cigar-
|
859 |
+
/cigar.
|
860 |
+
/cigarette-
|
861 |
+
/cigarette.
|
862 |
+
/cigarettes-
|
863 |
+
/cigarettes.
|
864 |
+
/cigars-
|
865 |
+
/cigars.
|
866 |
+
/ck-
|
867 |
+
/ck.
|
868 |
+
/cl/
|
869 |
+
/cld-
|
870 |
+
/cld.
|
871 |
+
/clearance/
|
872 |
+
/clrb-
|
873 |
+
/clrb.
|
874 |
+
/coach-
|
875 |
+
/coach.
|
876 |
+
/coach/
|
877 |
+
/coachpurse-
|
878 |
+
/coachpurse.
|
879 |
+
/coachpurses-
|
880 |
+
/coachpurses.
|
881 |
+
/commodity-
|
882 |
+
/commodity.
|
883 |
+
/common/
|
884 |
+
/conf-
|
885 |
+
/conf.
|
886 |
+
/conf/
|
887 |
+
/config-
|
888 |
+
/config.
|
889 |
+
/config/
|
890 |
+
/configura-
|
891 |
+
/configura.
|
892 |
+
/configura/
|
893 |
+
/configuration-
|
894 |
+
/configuration.
|
895 |
+
/configuration/
|
896 |
+
/contact.
|
897 |
+
/content/
|
898 |
+
/coupon/
|
899 |
+
/coupons/
|
900 |
+
/crimea-
|
901 |
+
/css/
|
902 |
+
/customcontrol
|
903 |
+
/customer-care.
|
904 |
+
/customer-care/
|
905 |
+
/customercare-
|
906 |
+
/customercare.
|
907 |
+
/damen-moncler
|
908 |
+
/dat/
|
909 |
+
/data/
|
910 |
+
/datebase-
|
911 |
+
/datebase.
|
912 |
+
/db/
|
913 |
+
/dbase/
|
914 |
+
/dg-
|
915 |
+
/dg.
|
916 |
+
/diary-
|
917 |
+
/diary.
|
918 |
+
/diesel-
|
919 |
+
/diet.
|
920 |
+
/dieta.
|
921 |
+
/dior.
|
922 |
+
/div/
|
923 |
+
/dlia/
|
924 |
+
/dmg/
|
925 |
+
/dolce-gabbana
|
926 |
+
/doudoun.
|
927 |
+
/doudoune.
|
928 |
+
/download.
|
929 |
+
/drmartens-
|
930 |
+
/drug
|
931 |
+
/dsquared-
|
932 |
+
/dsquared.
|
933 |
+
/duvetica.
|
934 |
+
/economical-
|
935 |
+
/empower-
|
936 |
+
/en.
|
937 |
+
/eng/index
|
938 |
+
/engine/
|
939 |
+
/errorx/
|
940 |
+
/escort-
|
941 |
+
/escort.
|
942 |
+
/escorts-
|
943 |
+
/escorts.
|
944 |
+
/executive-
|
945 |
+
/extreme-
|
946 |
+
/fashion-
|
947 |
+
/features-
|
948 |
+
/feed/
|
949 |
+
/feeds/
|
950 |
+
/fendi-
|
951 |
+
/fendi.
|
952 |
+
/ferragamo-
|
953 |
+
/ferragamo.
|
954 |
+
/file/
|
955 |
+
/files/
|
956 |
+
/filmy
|
957 |
+
/finance.
|
958 |
+
/financing.
|
959 |
+
/flash/
|
960 |
+
/foot-care
|
961 |
+
/form.
|
962 |
+
/forum/
|
963 |
+
/forum1
|
964 |
+
/fotka.
|
965 |
+
/foto.
|
966 |
+
/fpdb/
|
967 |
+
/free/
|
968 |
+
/fuck-
|
969 |
+
/fuck.
|
970 |
+
/fucked-
|
971 |
+
/fucked.
|
972 |
+
/fucker-
|
973 |
+
/fucker.
|
974 |
+
/fucking-
|
975 |
+
/fucking.
|
976 |
+
/fucks-
|
977 |
+
/fucks.
|
978 |
+
/futbol-
|
979 |
+
/futbol/
|
980 |
+
/gagajapan-
|
981 |
+
/gagajapan.
|
982 |
+
/gagamilano-
|
983 |
+
/gagamilano.
|
984 |
+
/gekiyasu
|
985 |
+
/get-free
|
986 |
+
/get-widget
|
987 |
+
/getwidget
|
988 |
+
/gh0/
|
989 |
+
/gh1/
|
990 |
+
/glowna.
|
991 |
+
/gold.
|
992 |
+
/graphics/
|
993 |
+
/group1
|
994 |
+
/group2
|
995 |
+
/group3
|
996 |
+
/groups/
|
997 |
+
/grow-your
|
998 |
+
/gry-
|
999 |
+
/gry.
|
1000 |
+
/gucci-
|
1001 |
+
/gucci.
|
1002 |
+
/guest-book
|
1003 |
+
/guestbook
|
1004 |
+
/guide-
|
1005 |
+
/haglofs-
|
1006 |
+
/haglofs.
|
1007 |
+
/handle/
|
1008 |
+
/headlines/
|
1009 |
+
/hentai
|
1010 |
+
/hermes-
|
1011 |
+
/hermes.
|
1012 |
+
/herveleger
|
1013 |
+
/hgh-
|
1014 |
+
/hgh.
|
1015 |
+
/hiend
|
1016 |
+
/hire-
|
1017 |
+
/hollister-
|
1018 |
+
/hollister.
|
1019 |
+
/hollister/
|
1020 |
+
/home.
|
1021 |
+
/hot.
|
1022 |
+
/hotdeal
|
1023 |
+
/ii/
|
1024 |
+
/images-
|
1025 |
+
/images.
|
1026 |
+
/img/
|
1027 |
+
/img1/
|
1028 |
+
/img2/
|
1029 |
+
/inc-meta
|
1030 |
+
/inc/
|
1031 |
+
/include/
|
1032 |
+
/includes/
|
1033 |
+
/index-0
|
1034 |
+
/index-1
|
1035 |
+
/index-2
|
1036 |
+
/index-3
|
1037 |
+
/index-4
|
1038 |
+
/index-5
|
1039 |
+
/index.asp
|
1040 |
+
/index.php
|
1041 |
+
/index0
|
1042 |
+
/index1
|
1043 |
+
/index2
|
1044 |
+
/index3
|
1045 |
+
/index4
|
1046 |
+
/index5
|
1047 |
+
/indexdic
|
1048 |
+
/info-
|
1049 |
+
/info.
|
1050 |
+
/infopage/
|
1051 |
+
/infopages/
|
1052 |
+
/install/
|
1053 |
+
/insurance.
|
1054 |
+
/iphone-case
|
1055 |
+
/iss.php
|
1056 |
+
/jacket-
|
1057 |
+
/jacket.
|
1058 |
+
/jbs-
|
1059 |
+
/jbs.
|
1060 |
+
/jersey-
|
1061 |
+
/jersey.
|
1062 |
+
/jerseys-
|
1063 |
+
/jerseys.
|
1064 |
+
/job.
|
1065 |
+
/join.
|
1066 |
+
/jordan.
|
1067 |
+
/jordan1
|
1068 |
+
/jordan2
|
1069 |
+
/jordan3
|
1070 |
+
/jordan4
|
1071 |
+
/jordan5
|
1072 |
+
/js.
|
1073 |
+
/js/
|
1074 |
+
/just.
|
1075 |
+
/kat,
|
1076 |
+
/kd6
|
1077 |
+
/kinder-moncler
|
1078 |
+
/kitchenknife-
|
1079 |
+
/kitchenknife.
|
1080 |
+
/kitchenknives-
|
1081 |
+
/kitchenknives.
|
1082 |
+
/kommentar
|
1083 |
+
/konsultan
|
1084 |
+
/kredit
|
1085 |
+
/kredyt
|
1086 |
+
/lacoste-
|
1087 |
+
/lang-es/
|
1088 |
+
/latestmk-
|
1089 |
+
/latestmk.
|
1090 |
+
/legal/
|
1091 |
+
/libs/
|
1092 |
+
/lijst/
|
1093 |
+
/limewire
|
1094 |
+
/lingerie.
|
1095 |
+
/link-
|
1096 |
+
/link.
|
1097 |
+
/link/
|
1098 |
+
/linkdetail
|
1099 |
+
/linknum
|
1100 |
+
/links-
|
1101 |
+
/links.
|
1102 |
+
/list.
|
1103 |
+
/loans
|
1104 |
+
/locale/
|
1105 |
+
/logos/
|
1106 |
+
/longchamp-
|
1107 |
+
/louboutin-
|
1108 |
+
/love-fail
|
1109 |
+
/love-life
|
1110 |
+
/love-quote
|
1111 |
+
/lunette-
|
1112 |
+
/lunette.
|
1113 |
+
/lunettes-
|
1114 |
+
/lunettes.
|
1115 |
+
/lv.
|
1116 |
+
/lv/
|
1117 |
+
/mailer/
|
1118 |
+
/maillot-
|
1119 |
+
/maillot.
|
1120 |
+
/malware/
|
1121 |
+
/manolo-blahnik
|
1122 |
+
/manoloblahnik
|
1123 |
+
/massage
|
1124 |
+
/mbt-
|
1125 |
+
/mbt.
|
1126 |
+
/mcm.
|
1127 |
+
/med-
|
1128 |
+
/mediawiki/
|
1129 |
+
/medical
|
1130 |
+
/medication-
|
1131 |
+
/member/
|
1132 |
+
/members-
|
1133 |
+
/members.
|
1134 |
+
/members/
|
1135 |
+
/membership-
|
1136 |
+
/membership.
|
1137 |
+
/menu.
|
1138 |
+
/mk-us/
|
1139 |
+
/mkshop-
|
1140 |
+
/mkshop.
|
1141 |
+
/mlsp-
|
1142 |
+
/mlsp.
|
1143 |
+
/mlsp/
|
1144 |
+
/mobile/
|
1145 |
+
/module/
|
1146 |
+
/modules/
|
1147 |
+
/moncler-
|
1148 |
+
/moncler.
|
1149 |
+
/moncler/
|
1150 |
+
/montblanc.
|
1151 |
+
/mortgage
|
1152 |
+
/mulberry-
|
1153 |
+
/mulberry.
|
1154 |
+
/myspace/
|
1155 |
+
/n.php
|
1156 |
+
/nailart-
|
1157 |
+
/nailart.
|
1158 |
+
/nailart/
|
1159 |
+
/natverk/
|
1160 |
+
/netcat
|
1161 |
+
/netwerk/
|
1162 |
+
/network/
|
1163 |
+
/new.
|
1164 |
+
/newbalance
|
1165 |
+
/newports-
|
1166 |
+
/newports.
|
1167 |
+
/news.
|
1168 |
+
/newsletter/
|
1169 |
+
/newsletters/
|
1170 |
+
/nihon
|
1171 |
+
/nike-
|
1172 |
+
/nike.
|
1173 |
+
/nikefree
|
1174 |
+
/niketn
|
1175 |
+
/ninnki
|
1176 |
+
/no-excuse
|
1177 |
+
/node/
|
1178 |
+
/north-face
|
1179 |
+
/north-face-
|
1180 |
+
/northface-
|
1181 |
+
/northface.
|
1182 |
+
/novinki-
|
1183 |
+
/novinki.
|
1184 |
+
/npn-
|
1185 |
+
/npn.
|
1186 |
+
/oakley-
|
1187 |
+
/oakley.
|
1188 |
+
/oakley/
|
1189 |
+
/oakleycan
|
1190 |
+
/offering/
|
1191 |
+
/ok.php
|
1192 |
+
/online.
|
1193 |
+
/orderpage/
|
1194 |
+
/orgasm
|
1195 |
+
/other-
|
1196 |
+
/other.
|
1197 |
+
/outils/
|
1198 |
+
/page1.
|
1199 |
+
/page2.
|
1200 |
+
/page3.
|
1201 |
+
/page4.
|
1202 |
+
/page5.
|
1203 |
+
/pages-
|
1204 |
+
/pages.
|
1205 |
+
/pandorabead.
|
1206 |
+
/pantie-
|
1207 |
+
/panties-
|
1208 |
+
/panty-
|
1209 |
+
/php.
|
1210 |
+
/piece-
|
1211 |
+
/piece.
|
1212 |
+
/popup
|
1213 |
+
/porn
|
1214 |
+
/post:
|
1215 |
+
/postinfo-
|
1216 |
+
/postinfo.
|
1217 |
+
/pozew
|
1218 |
+
/prada-
|
1219 |
+
/prada.
|
1220 |
+
/premium-
|
1221 |
+
/premium.
|
1222 |
+
/pricing-
|
1223 |
+
/pricing.
|
1224 |
+
/privat-
|
1225 |
+
/private-
|
1226 |
+
/private.
|
1227 |
+
/private/
|
1228 |
+
/product/0/
|
1229 |
+
/produkter/
|
1230 |
+
/proficient-
|
1231 |
+
/profil-
|
1232 |
+
/profil.
|
1233 |
+
/profil/
|
1234 |
+
/profile-
|
1235 |
+
/profile.
|
1236 |
+
/profile/
|
1237 |
+
/prolist
|
1238 |
+
/property-
|
1239 |
+
/property.
|
1240 |
+
/prozac
|
1241 |
+
/pufy
|
1242 |
+
/pumps-
|
1243 |
+
/pumps.
|
1244 |
+
/q.
|
1245 |
+
/ra.php
|
1246 |
+
/ray-ban-
|
1247 |
+
/ray-ban.
|
1248 |
+
/ray-ban/
|
1249 |
+
/rayban-
|
1250 |
+
/rayban.
|
1251 |
+
/rayban/
|
1252 |
+
/read.php
|
1253 |
+
/readme.
|
1254 |
+
/readnews.
|
1255 |
+
/recap/
|
1256 |
+
/refreshers.
|
1257 |
+
/remote-desktop
|
1258 |
+
/remotedesktop
|
1259 |
+
/ri.ms
|
1260 |
+
/rozwod
|
1261 |
+
/rss.xml
|
1262 |
+
/ru/news/
|
1263 |
+
/sac-
|
1264 |
+
/sac.
|
1265 |
+
/sale-
|
1266 |
+
/sales-
|
1267 |
+
/salvia/
|
1268 |
+
/scarpe-
|
1269 |
+
/sconfig/
|
1270 |
+
/scripts-
|
1271 |
+
/scripts/
|
1272 |
+
/secure/
|
1273 |
+
/sendform/
|
1274 |
+
/seo
|
1275 |
+
/sex
|
1276 |
+
/show/
|
1277 |
+
/sigareta-
|
1278 |
+
/sigareta.
|
1279 |
+
/sigarety-
|
1280 |
+
/sigarety.
|
1281 |
+
/sims-3.
|
1282 |
+
/sinsaku
|
1283 |
+
/site/
|
1284 |
+
/site/ebay
|
1285 |
+
/sitemap.
|
1286 |
+
/siteold/
|
1287 |
+
/soft/
|
1288 |
+
/soma-
|
1289 |
+
/soma.
|
1290 |
+
/soma/
|
1291 |
+
/special-
|
1292 |
+
/special.
|
1293 |
+
/specialprojects-
|
1294 |
+
/specialprojects.
|
1295 |
+
/specials-
|
1296 |
+
/specials.
|
1297 |
+
/start.
|
1298 |
+
/strona-
|
1299 |
+
/strona/
|
1300 |
+
/strony-
|
1301 |
+
/strony/
|
1302 |
+
/stuff.
|
1303 |
+
/suggestions-
|
1304 |
+
/sunglasses-
|
1305 |
+
/sunglasses.
|
1306 |
+
/swf/
|
1307 |
+
/syaneru
|
1308 |
+
/systemdb.
|
1309 |
+
/sysuser/
|
1310 |
+
/tagged/
|
1311 |
+
/telecharger-
|
1312 |
+
/telecharger.
|
1313 |
+
/temp/
|
1314 |
+
/temp0
|
1315 |
+
/temp1
|
1316 |
+
/temp2
|
1317 |
+
/temp3
|
1318 |
+
/templates/
|
1319 |
+
/test.
|
1320 |
+
/the-first
|
1321 |
+
/the-sale
|
1322 |
+
/the-secret
|
1323 |
+
/the-shock
|
1324 |
+
/thebest
|
1325 |
+
/themes/
|
1326 |
+
/thesecret.
|
1327 |
+
/thread-
|
1328 |
+
/tiffany-
|
1329 |
+
/tiffany.
|
1330 |
+
/timberland-
|
1331 |
+
/timberland.
|
1332 |
+
/title,
|
1333 |
+
/tmp/
|
1334 |
+
/toms-
|
1335 |
+
/toms.
|
1336 |
+
/top100.
|
1337 |
+
/trac/ticket/
|
1338 |
+
/trackback
|
1339 |
+
/twilight-
|
1340 |
+
/ugg-
|
1341 |
+
/ugg/
|
1342 |
+
/uggs-
|
1343 |
+
/uggs.
|
1344 |
+
/uggsal/
|
1345 |
+
/update/
|
1346 |
+
/upload-
|
1347 |
+
/upload/
|
1348 |
+
/uploadfiles/
|
1349 |
+
/uploads/
|
1350 |
+
/url/
|
1351 |
+
/usa.
|
1352 |
+
/user-
|
1353 |
+
/user:
|
1354 |
+
/user.
|
1355 |
+
/usuario:
|
1356 |
+
/vb/
|
1357 |
+
/viewstory
|
1358 |
+
/visit.
|
1359 |
+
/visite.
|
1360 |
+
/vuitton-
|
1361 |
+
/vuitton.
|
1362 |
+
/vuittonpascher-
|
1363 |
+
/vuittonpascher.
|
1364 |
+
/wayfarer-
|
1365 |
+
/wayfarer.
|
1366 |
+
/web-design/
|
1367 |
+
/web0/
|
1368 |
+
/web1/
|
1369 |
+
/web2/
|
1370 |
+
/web3/
|
1371 |
+
/wedding.
|
1372 |
+
/wholesale-
|
1373 |
+
/wholesale.
|
1374 |
+
/wo.
|
1375 |
+
/woolrich-
|
1376 |
+
/woolrich.
|
1377 |
+
/wp-admin
|
1378 |
+
/wp-content
|
1379 |
+
/wp-image
|
1380 |
+
/wp-include
|
1381 |
+
/wp-list
|
1382 |
+
/wp-site
|
1383 |
+
/wpadmin
|
1384 |
+
/wpcontent
|
1385 |
+
/wpimage
|
1386 |
+
/wpinclude
|
1387 |
+
/wplist
|
1388 |
+
/wpsite
|
1389 |
+
/ww.
|
1390 |
+
/www/
|
1391 |
+
/x.co
|
1392 |
+
/xchange
|
1393 |
+
/xe/
|
1394 |
+
/xml/
|
1395 |
+
/ya.
|
1396 |
+
/yabb
|
1397 |
+
/yours.
|
1398 |
+
/z.
|
1399 |
+
/zumba-
|
1400 |
+
\xa9
|
1401 |
+
\xc3
|
1402 |
+
FENDI
|
1403 |
+
Hermes
|
1404 |
+
Paul Smith
|
1405 |
+
timberland
|
1406 |
+
ω
|
1407 |
+
а
|
1408 |
+
г
|
1409 |
+
エアマックス
|
1410 |
+
トゥミ
|
1411 |
+
トリーバーチ
|
1412 |
+
ナイキ
|
1413 |
+
ニューバランス
|
1414 |
+
プロモ
|
1415 |
+
ポールスミス
|
1416 |
+
ミュウ
|
1417 |
+
レプリカ
|
1418 |
+
ローン
|
1419 |
+
偽物
|
1420 |
+
利
|
1421 |
+
財布
|
1422 |
+
金
|
1423 |
+
&amp
|
1424 |
+
&article
|
1425 |
+
&eþh;
|
1426 |
+
κ
|
1427 |
+
ο
|
1428 |
+
&x6
|
1429 |
+
&x7
|
1430 |
+
#/a
|
1431 |
+
#file
|
1432 |
+
#random
|
1433 |
+
%7c
|
1434 |
+
%20-%20
|
1435 |
+
%20co
|
1436 |
+
%20on
|
1437 |
+
%20zappo
|
1438 |
+
%anchor%
|
1439 |
+
%d8%
|
1440 |
+
%e0%
|
1441 |
+
%titel%
|
1442 |
+
%title%
|
1443 |
+
%titlet%
|
1444 |
+
%u2019
|
1445 |
+
%url%
|
1446 |
+
+cheap
|
1447 |
+
+clearance
|
1448 |
+
+handbag
|
1449 |
+
+jersey
|
1450 |
+
+louboutin
|
1451 |
+
+outlet
|
1452 |
+
<a>
|
1453 |
+
=blog
|
1454 |
+
=captcha
|
1455 |
+
=node
|
1456 |
+
=profile
|
1457 |
+
=read
|
1458 |
+
=space
|
1459 |
+
=thread
|
1460 |
+
=utf8
|
1461 |
+
=view
|
1462 |
+
>.}
|
1463 |
+
>casino
|
1464 |
+
>cheap
|
1465 |
+
>enter
|
1466 |
+
>fuck
|
1467 |
+
>gluten
|
1468 |
+
>herpes
|
1469 |
+
>longchamp
|
1470 |
+
>pokie
|
1471 |
+
>sensual
|
1472 |
+
>shopping
|
1473 |
+
>ugg
|
1474 |
+
>woolr
|
1475 |
+
|chi
|
1476 |
+
|dal
|
1477 |
+
|det
|
1478 |
+
|for
|
1479 |
+
|per
|
1480 |
+
|porn
|
1481 |
+
|year
|
1482 |
+
|yr
|
1483 |
+
000mail
|
1484 |
+
1-1.
|
1485 |
+
1.cfm
|
1486 |
+
1.in
|
1487 |
+
1@1
|
1488 |
+
1@2
|
1489 |
+
1@3
|
1490 |
+
1big
|
1491 |
+
1bodog
|
1492 |
+
1c.in
|
1493 |
+
1minutesite
|
1494 |
+
1stop
|
1495 |
+
1test
|
1496 |
+
1to1
|
1497 |
+
2-global
|
1498 |
+
2.cfm
|
1499 |
+
2.in
|
1500 |
+
2@1
|
1501 |
+
2@2
|
1502 |
+
2@3
|
1503 |
+
2bj.ru
|
1504 |
+
2c.in
|
1505 |
+
2global
|
1506 |
+
2itb
|
1507 |
+
2sale
|
1508 |
+
2test
|
1509 |
+
2u.org
|
1510 |
+
3.cfm
|
1511 |
+
3.in
|
1512 |
+
3@1
|
1513 |
+
3@2
|
1514 |
+
3@3
|
1515 |
+
3j3j3
|
1516 |
+
3test
|
1517 |
+
3ww3
|
1518 |
+
4all
|
1519 |
+
4cheap
|
1520 |
+
4ever
|
1521 |
+
4firefall
|
1522 |
+
4less
|
1523 |
+
4sale
|
1524 |
+
4u.co
|
1525 |
+
4you.
|
1526 |
+
5health
|
1527 |
+
7handbag
|
1528 |
+
7purse
|
1529 |
+
8handbag
|
1530 |
+
8purse
|
1531 |
+
49ers jersey
|
1532 |
+
49ers online
|
1533 |
+
49ers-jersey
|
1534 |
+
49ers-online
|
1535 |
+
49ersjersey
|
1536 |
+
49ersonline
|
1537 |
+
100% legit
|
1538 |
+
100mg.
|
1539 |
+
111.
|
1540 |
+
111@
|
1541 |
+
123.co
|
1542 |
+
123.in
|
1543 |
+
123@
|
1544 |
+
222.co
|
1545 |
+
222.in
|
1546 |
+
365.co
|
1547 |
+
365.in
|
1548 |
+
404.php
|
1549 |
+
911.co
|
1550 |
+
911.in
|
1551 |
+
2007.co
|
1552 |
+
2008.co
|
1553 |
+
2009.co
|
1554 |
+
2010.co
|
1555 |
+
2011.co
|
1556 |
+
2012.co
|
1557 |
+
2013.co
|
1558 |
+
2013.de
|
1559 |
+
2013.in
|
1560 |
+
2013.or
|
1561 |
+
2013baby
|
1562 |
+
2013x.
|
1563 |
+
2014.co
|
1564 |
+
2014.de
|
1565 |
+
2014.in
|
1566 |
+
2014.or
|
1567 |
+
2014baby
|
1568 |
+
123456789
|
1569 |
+
¥·¥
|
1570 |
+
¥°¥
|
1571 |
+
a lots
|
1572 |
+
a-cell-phone
|
1573 |
+
a-lots
|
1574 |
+
a-powerful-way
|
1575 |
+
a.pri.l
|
1576 |
+
ã©
|
1577 |
+
a1.co
|
1578 |
+
â€
|
1579 |
+
aaa replica
|
1580 |
+
aaa-replica
|
1581 |
+
aaabbb
|
1582 |
+
abcwatch
|
1583 |
+
abdominaux
|
1584 |
+
abercrombie deutsch
|
1585 |
+
abercrombie kid
|
1586 |
+
abercrombie man
|
1587 |
+
abercrombie men
|
1588 |
+
abercrombie outlet
|
1589 |
+
abercrombie uomo
|
1590 |
+
abercrombie wom
|
1591 |
+
abercrombie-deutsch
|
1592 |
+
abercrombie-ital
|
1593 |
+
abercrombie-kid
|
1594 |
+
abercrombie-man
|
1595 |
+
abercrombie-men
|
1596 |
+
abercrombie-outlet
|
1597 |
+
abercrombie-uomo
|
1598 |
+
abercrombie-wom
|
1599 |
+
abercrombiee
|
1600 |
+
abercrombieital
|
1601 |
+
abercrombiekid
|
1602 |
+
abercrombieman
|
1603 |
+
abercrombiemen
|
1604 |
+
abercrombieoutlet
|
1605 |
+
abercrombieuomo
|
1606 |
+
abercrombiewom
|
1607 |
+
abilify
|
1608 |
+
about marijuana
|
1609 |
+
about_
|
1610 |
+
about-marijuana
|
1611 |
+
about/date
|
1612 |
+
abouther
|
1613 |
+
acai-
|
1614 |
+
acaiberry
|
1615 |
+
accouchement
|
1616 |
+
accounts receiv
|
1617 |
+
accounts-receiv
|
1618 |
+
accupril
|
1619 |
+
accutane
|
1620 |
+
acertemail.co
|
1621 |
+
acetazolamide
|
1622 |
+
acid-reflux
|
1623 |
+
acnecyst
|
1624 |
+
acnetreatment
|
1625 |
+
acomplia
|
1626 |
+
activation code
|
1627 |
+
activity/p/
|
1628 |
+
actonel
|
1629 |
+
actual effort
|
1630 |
+
actual thank
|
1631 |
+
actual-effort
|
1632 |
+
actual-thank
|
1633 |
+
actually thank
|
1634 |
+
actually-thank
|
1635 |
+
acutual
|
1636 |
+
acyclovir
|
1637 |
+
ad-wiki
|
1638 |
+
adbeat distrib
|
1639 |
+
adbeat expert
|
1640 |
+
adbeat trial
|
1641 |
+
adbeat-distrib
|
1642 |
+
adbeat-expert
|
1643 |
+
adbeat-trial
|
1644 |
+
adbeatdistrib
|
1645 |
+
adbeatexpert
|
1646 |
+
adbeattrial
|
1647 |
+
addarticle
|
1648 |
+
adderall
|
1649 |
+
adderoll
|
1650 |
+
addicted-to
|
1651 |
+
addidas
|
1652 |
+
additionay
|
1653 |
+
adenosyl
|
1654 |
+
adidas adizero
|
1655 |
+
adidas fotball
|
1656 |
+
adidas jeremy
|
1657 |
+
adidas js
|
1658 |
+
adidas origin
|
1659 |
+
adidas out
|
1660 |
+
adidas porsche
|
1661 |
+
adidas shop
|
1662 |
+
adidas slip
|
1663 |
+
adidas super
|
1664 |
+
adidas uomo
|
1665 |
+
adidas wing
|
1666 |
+
adidas-adizero
|
1667 |
+
adidas-corner
|
1668 |
+
adidas-fotball
|
1669 |
+
adidas-jeremy
|
1670 |
+
adidas-js
|
1671 |
+
adidas-orig
|
1672 |
+
adidas-out
|
1673 |
+
adidas-porsche
|
1674 |
+
adidas-shop
|
1675 |
+
adidas-slip
|
1676 |
+
adidas-super
|
1677 |
+
adidas-uomo
|
1678 |
+
adidas-wing
|
1679 |
+
adidashop
|
1680 |
+
adidasjeremy
|
1681 |
+
adidasjs
|
1682 |
+
adidasorig
|
1683 |
+
adidasoutlet
|
1684 |
+
adidasporsche
|
1685 |
+
adidasshop
|
1686 |
+
adidasslip
|
1687 |
+
adidassuper
|
1688 |
+
adidasuomo
|
1689 |
+
adidaswing
|
1690 |
+
adipex
|
1691 |
+
admin.cfm
|
1692 |
+
admin5
|
1693 |
+
ados populaire
|
1694 |
+
ados-populaire
|
1695 |
+
adospopulaire
|
1696 |
+
ads ad
|
1697 |
+
ads crack
|
1698 |
+
ads live
|
1699 |
+
ads-ad
|
1700 |
+
ads-crack
|
1701 |
+
ads-live
|
1702 |
+
adscrack
|
1703 |
+
adsjeremy
|
1704 |
+
adslive
|
1705 |
+
adsplus
|
1706 |
+
adsuse
|
1707 |
+
adswings
|
1708 |
+
adult baseball
|
1709 |
+
adult girl
|
1710 |
+
adult toy
|
1711 |
+
adult-baseball
|
1712 |
+
adult-girl
|
1713 |
+
adult-sex
|
1714 |
+
adult-story
|
1715 |
+
adult-toy
|
1716 |
+
adultdating
|
1717 |
+
adultgirl
|
1718 |
+
adultsex
|
1719 |
+
adulttoy
|
1720 |
+
advantages_of
|
1721 |
+
advantages-of
|
1722 |
+
advert-market
|
1723 |
+
advertise your
|
1724 |
+
advertise-your
|
1725 |
+
advertising-research
|
1726 |
+
advok
|
1727 |
+
adwings
|
1728 |
+
adwokacka
|
1729 |
+
adwokat
|
1730 |
+
adwords
|
1731 |
+
aff.php
|
1732 |
+
affiliate link
|
1733 |
+
affiliate-link
|
1734 |
+
affiliatelink
|
1735 |
+
affliction classic
|
1736 |
+
affliction jean
|
1737 |
+
affliction men
|
1738 |
+
affliction new
|
1739 |
+
affliction offer
|
1740 |
+
affliction-classic
|
1741 |
+
affliction-jean
|
1742 |
+
affliction-men
|
1743 |
+
affliction-new
|
1744 |
+
affliction-offer
|
1745 |
+
afflictionclassic
|
1746 |
+
afflictionjean
|
1747 |
+
afflictionmen
|
1748 |
+
afflictionnew
|
1749 |
+
afflictionoffer
|
1750 |
+
affordable handbag
|
1751 |
+
affordable-handbag
|
1752 |
+
african-canadian-model
|
1753 |
+
africancanadianmodel
|
1754 |
+
ãƒ
|
1755 |
+
age.webeden
|
1756 |
+
age|
|
1757 |
+
agedepot
|
1758 |
+
ageless female
|
1759 |
+
ageless male
|
1760 |
+
ageless men
|
1761 |
+
ageless women
|
1762 |
+
ageless-female
|
1763 |
+
ageless-male
|
1764 |
+
ageless-men
|
1765 |
+
ageless-women
|
1766 |
+
agencje-
|
1767 |
+
agent denim
|
1768 |
+
agent direct
|
1769 |
+
agent-denim
|
1770 |
+
agent-direct
|
1771 |
+
agentdenim
|
1772 |
+
ago|
|
1773 |
+
âgrâve
|
1774 |
+
aint goin
|
1775 |
+
aint-goin
|
1776 |
+
air max
|
1777 |
+
air-jorda
|
1778 |
+
air-max
|
1779 |
+
air-yeezy
|
1780 |
+
airjorda
|
1781 |
+
airmax
|
1782 |
+
airmax_
|
1783 |
+
airport--
|
1784 |
+
airport-transport
|
1785 |
+
airyeezy
|
1786 |
+
aitaiwan
|
1787 |
+
akkuschrauber
|
1788 |
+
aklotr
|
1789 |
+
aksudmias
|
1790 |
+
albuterol
|
1791 |
+
alendronate
|
1792 |
+
alkotla
|
1793 |
+
all-about-the
|
1794 |
+
allbestedmed
|
1795 |
+
allbestmed
|
1796 |
+
allianz/
|
1797 |
+
allright
|
1798 |
+
alluring escort
|
1799 |
+
alluring-escort
|
1800 |
+
allworkhome
|
1801 |
+
alprazolam
|
1802 |
+
amateur-homemade
|
1803 |
+
amateur.
|
1804 |
+
amateurhomemade
|
1805 |
+
amateurs.
|
1806 |
+
amazing post
|
1807 |
+
amazing-post
|
1808 |
+
amazn.co
|
1809 |
+
amazon.cm
|
1810 |
+
ambien
|
1811 |
+
ametuer
|
1812 |
+
aminocare
|
1813 |
+
amitriptyline
|
1814 |
+
amorti dynamique
|
1815 |
+
amorti-dynamique
|
1816 |
+
amour gratuite
|
1817 |
+
amour-gratuite
|
1818 |
+
amoxicil
|
1819 |
+
amoxil
|
1820 |
+
amzon.co
|
1821 |
+
an0n.me
|
1822 |
+
anabolic
|
1823 |
+
anal sex
|
1824 |
+
anal-sex
|
1825 |
+
analsex
|
1826 |
+
and-special
|
1827 |
+
andcloth
|
1828 |
+
andcoupon
|
1829 |
+
andjourney
|
1830 |
+
andmerciful
|
1831 |
+
androidclan
|
1832 |
+
androidmp3
|
1833 |
+
aneswr
|
1834 |
+
angebote
|
1835 |
+
animalbased
|
1836 |
+
ankle bootie
|
1837 |
+
ankle-bootie
|
1838 |
+
anklebootie
|
1839 |
+
ano.gd
|
1840 |
+
anonymous-download
|
1841 |
+
anonymousvpn
|
1842 |
+
answertraffic
|
1843 |
+
anti-aging
|
1844 |
+
antiage
|
1845 |
+
antiaging
|
1846 |
+
antispam
|
1847 |
+
antivirus/index
|
1848 |
+
antivirussen
|
1849 |
+
anuncios
|
1850 |
+
anү
|
1851 |
+
apartamentow
|
1852 |
+
apbd_sjs
|
1853 |
+
apex bionic
|
1854 |
+
apex-bionic
|
1855 |
+
apexbionic
|
1856 |
+
app.lk
|
1857 |
+
app.php
|
1858 |
+
apple-unlock
|
1859 |
+
appleunlock
|
1860 |
+
appro-chait
|
1861 |
+
appyourself
|
1862 |
+
apr.i.l
|
1863 |
+
aquarius-compat
|
1864 |
+
arcteryx-jp
|
1865 |
+
arcteryx-sale
|
1866 |
+
arcteryxjp
|
1867 |
+
arcteryxsale
|
1868 |
+
are added-
|
1869 |
+
areplica
|
1870 |
+
aricept
|
1871 |
+
aripiprex
|
1872 |
+
armagard.co
|
1873 |
+
armani costume
|
1874 |
+
armani-costume
|
1875 |
+
armanito
|
1876 |
+
aroma-paradise
|
1877 |
+
artemfrolov
|
1878 |
+
article content
|
1879 |
+
article dude
|
1880 |
+
article plus
|
1881 |
+
article-buzz
|
1882 |
+
article-content
|
1883 |
+
article-dude
|
1884 |
+
article-plus
|
1885 |
+
article,i
|
1886 |
+
article!
|
1887 |
+
article.co
|
1888 |
+
article.in
|
1889 |
+
article.net
|
1890 |
+
article.org
|
1891 |
+
article.php
|
1892 |
+
article/suggest
|
1893 |
+
articlebuzz
|
1894 |
+
articlepowa
|
1895 |
+
articles.co
|
1896 |
+
articles.in
|
1897 |
+
articles.net
|
1898 |
+
articles.org
|
1899 |
+
articlesub
|
1900 |
+
articulatio
|
1901 |
+
artikel
|
1902 |
+
artykul
|
1903 |
+
asd@
|
1904 |
+
asdasd
|
1905 |
+
asdf
|
1906 |
+
asicsshoe
|
1907 |
+
asikkusu
|
1908 |
+
aso expei
|
1909 |
+
asos coupon
|
1910 |
+
asos-coupon
|
1911 |
+
asoscoupon
|
1912 |
+
asp?folder
|
1913 |
+
asp?id
|
1914 |
+
asphalt8cheat
|
1915 |
+
asphalt8hack
|
1916 |
+
aspiring blog
|
1917 |
+
aspiring-blog
|
1918 |
+
assistance informatique
|
1919 |
+
assistance-inform
|
1920 |
+
assistance-informatique
|
1921 |
+
associate link
|
1922 |
+
associate-link
|
1923 |
+
assortiment
|
1924 |
+
astounding1
|
1925 |
+
astounding2
|
1926 |
+
astounding3
|
1927 |
+
astounding4
|
1928 |
+
astounding5
|
1929 |
+
astral-diamond
|
1930 |
+
aswenr
|
1931 |
+
at web,
|
1932 |
+
athletica lululemon
|
1933 |
+
athletica-lululemon
|
1934 |
+
ationincome
|
1935 |
+
ativan
|
1936 |
+
atomoxetine
|
1937 |
+
atorvastatin
|
1938 |
+
attraction marketing
|
1939 |
+
attraction-marketing
|
1940 |
+
australia boot
|
1941 |
+
australia out
|
1942 |
+
australia-boot
|
1943 |
+
australiaboot
|
1944 |
+
australian pokie
|
1945 |
+
australian-pokie
|
1946 |
+
auteur:nike
|
1947 |
+
authentic cheap
|
1948 |
+
authentic hermes
|
1949 |
+
authentic-cheap
|
1950 |
+
authentic-ugg
|
1951 |
+
authentichermes
|
1952 |
+
authenticugg
|
1953 |
+
authored subject
|
1954 |
+
authored-subject
|
1955 |
+
autoclinics.co.
|
1956 |
+
autocom
|
1957 |
+
automatic-pay
|
1958 |
+
automaticbackup.
|
1959 |
+
automaticpay
|
1960 |
+
autre artic
|
1961 |
+
autre-artic
|
1962 |
+
avatar-live
|
1963 |
+
avvessorie
|
1964 |
+
avvessory
|
1965 |
+
awokehim
|
1966 |
+
awordpress.
|
1967 |
+
azria outlet
|
1968 |
+
azria-outlet
|
1969 |
+
azur-lv
|
1970 |
+
ɑlivе
|
1971 |
+
b.u.y
|
1972 |
+
b54.in
|
1973 |
+
babycanread
|
1974 |
+
babyliss
|
1975 |
+
backlink
|
1976 |
+
baclofen
|
1977 |
+
bad credit
|
1978 |
+
bad-credit
|
1979 |
+
badcredit
|
1980 |
+
bag out
|
1981 |
+
bag-cheap
|
1982 |
+
bag-online
|
1983 |
+
bag-out
|
1984 |
+
bagcheap
|
1985 |
+
bagjap
|
1986 |
+
bagjp
|
1987 |
+
bagmirror
|
1988 |
+
bagonline
|
1989 |
+
bagonsale
|
1990 |
+
bagout
|
1991 |
+
bags afford
|
1992 |
+
bags online
|
1993 |
+
bags out
|
1994 |
+
bags sale
|
1995 |
+
bags uk
|
1996 |
+
bags-afford
|
1997 |
+
bags-cheap
|
1998 |
+
bags-online
|
1999 |
+
bags-out
|
2000 |
+
bagsale
|
2001 |
+
bagscheap
|
2002 |
+
bagsjap
|
2003 |
+
bagsjp
|
2004 |
+
bagsonline
|
2005 |
+
bagsout
|
2006 |
+
bagssale
|
2007 |
+
bagsstore
|
2008 |
+
bagstore
|
2009 |
+
bagsuk
|
2010 |
+
bailey ugg
|
2011 |
+
bailey-ugg
|
2012 |
+
baileyugg
|
2013 |
+
bajardepeso
|
2014 |
+
balance espana
|
2015 |
+
balance españa
|
2016 |
+
balenciagasingapore
|
2017 |
+
bally store
|
2018 |
+
bally-store
|
2019 |
+
ballystore
|
2020 |
+
ban baratas
|
2021 |
+
ban jacket
|
2022 |
+
ban occhiali
|
2023 |
+
ban online
|
2024 |
+
ban sunglass
|
2025 |
+
ban-baratas
|
2026 |
+
ban-jacket
|
2027 |
+
ban-occhiali
|
2028 |
+
ban-online
|
2029 |
+
ban-sunglass
|
2030 |
+
bancshare
|
2031 |
+
bangkok cosplay
|
2032 |
+
bangkok-cosplay
|
2033 |
+
bangkokcosplay
|
2034 |
+
banjacket
|
2035 |
+
bankbybank
|
2036 |
+
bankowoz
|
2037 |
+
bankrobber
|
2038 |
+
banonline
|
2039 |
+
bansunglass
|
2040 |
+
baratas-new
|
2041 |
+
baratasnewera
|
2042 |
+
baratos-new
|
2043 |
+
baratosnewera
|
2044 |
+
barbour cloth
|
2045 |
+
barbour jacket
|
2046 |
+
barbour outlet
|
2047 |
+
barbour-cloth
|
2048 |
+
barbour-jacket
|
2049 |
+
barbour-outlet
|
2050 |
+
barbourcloth
|
2051 |
+
barbourjacket
|
2052 |
+
barbouroutlet
|
2053 |
+
basket isabel
|
2054 |
+
basket-isabel
|
2055 |
+
basketisabel
|
2056 |
+
bat-pro
|
2057 |
+
bayswater bag
|
2058 |
+
bayswater-bag
|
2059 |
+
bazargorj
|
2060 |
+
bazookaapp
|
2061 |
+
bbombr
|
2062 |
+
bcbg dress
|
2063 |
+
bcbg-dress
|
2064 |
+
bddv
|
2065 |
+
be benefited
|
2066 |
+
beamten
|
2067 |
+
beanies1
|
2068 |
+
bears hat
|
2069 |
+
bears urlacher
|
2070 |
+
bears-hat
|
2071 |
+
bears-urlacher
|
2072 |
+
bearsurlacher
|
2073 |
+
beatbydre
|
2074 |
+
beats by
|
2075 |
+
beats monster
|
2076 |
+
beats pas
|
2077 |
+
beats studio
|
2078 |
+
beats-by
|
2079 |
+
beats-dr-dre
|
2080 |
+
beats-dre
|
2081 |
+
beats-monster
|
2082 |
+
beats-pas
|
2083 |
+
beats-studio
|
2084 |
+
beats+by
|
2085 |
+
beatsbydrdre
|
2086 |
+
beatsbydre
|
2087 |
+
beatscustom
|
2088 |
+
beatsdrdre
|
2089 |
+
beatsdre
|
2090 |
+
beatsmonster
|
2091 |
+
beatsstudio
|
2092 |
+
beaut beaut
|
2093 |
+
beaut bio
|
2094 |
+
beaut-beaut
|
2095 |
+
beaut-bio
|
2096 |
+
beautiful-wom
|
2097 |
+
beautifulwom
|
2098 |
+
bee-pollen.
|
2099 |
+
beeday
|
2100 |
+
beenpaid
|
2101 |
+
before-purchas
|
2102 |
+
behaviour-driven
|
2103 |
+
behind-knee
|
2104 |
+
behindknee
|
2105 |
+
beijing-escort
|
2106 |
+
beijing-massage
|
2107 |
+
beijingescort
|
2108 |
+
beijingmassage
|
2109 |
+
belize propert
|
2110 |
+
belize-propert
|
2111 |
+
belizepropert
|
2112 |
+
belly-fat
|
2113 |
+
belstaff bota
|
2114 |
+
belstaff chaqueta
|
2115 |
+
belstaff cuero
|
2116 |
+
belstaff espa
|
2117 |
+
belstaff españa
|
2118 |
+
belstaff handbag
|
2119 |
+
belstaff leder
|
2120 |
+
belstaff out
|
2121 |
+
belstaff-bota
|
2122 |
+
belstaff-chaqueta
|
2123 |
+
belstaff-cuero
|
2124 |
+
belstaff-espa
|
2125 |
+
belstaff-españa
|
2126 |
+
belstaff-handbag
|
2127 |
+
belstaff-leder
|
2128 |
+
belstaff-out
|
2129 |
+
belstaffbota
|
2130 |
+
belstaffchaqueta
|
2131 |
+
belstaffcuero
|
2132 |
+
belstaffespa
|
2133 |
+
belstaffespaña
|
2134 |
+
belstaffhandbag
|
2135 |
+
belstaffleder
|
2136 |
+
belstaffoutlet
|
2137 |
+
belt replica
|
2138 |
+
belt-replica
|
2139 |
+
beltreplica
|
2140 |
+
bengals merch
|
2141 |
+
bengals store
|
2142 |
+
bengals-merch
|
2143 |
+
bengals-store
|
2144 |
+
bengalsmerch
|
2145 |
+
bengalsstore
|
2146 |
+
benzoclin
|
2147 |
+
benzogenerator
|
2148 |
+
benzoylmethyl
|
2149 |
+
berlinmoncler
|
2150 |
+
berracom.ph
|
2151 |
+
best cyber
|
2152 |
+
best jersey
|
2153 |
+
best online
|
2154 |
+
best pant
|
2155 |
+
best tummy
|
2156 |
+
best website
|
2157 |
+
best-cyber
|
2158 |
+
best-diet
|
2159 |
+
best-direct
|
2160 |
+
best-discount
|
2161 |
+
best-fake
|
2162 |
+
best-home-cinema
|
2163 |
+
best-jersey
|
2164 |
+
best-pant
|
2165 |
+
best-phone
|
2166 |
+
best-software-for
|
2167 |
+
best-tummy
|
2168 |
+
best-way-to
|
2169 |
+
best-website
|
2170 |
+
bestad.
|
2171 |
+
bestads.
|
2172 |
+
bestcase
|
2173 |
+
bestcontractor
|
2174 |
+
bestdirect
|
2175 |
+
bestdiscount
|
2176 |
+
bestdrug
|
2177 |
+
bestfake
|
2178 |
+
bestfit
|
2179 |
+
bestjersey
|
2180 |
+
bestlaptop
|
2181 |
+
bestpant
|
2182 |
+
bestphone
|
2183 |
+
bestsuppl
|
2184 |
+
besttummy
|
2185 |
+
bestwebsite
|
2186 |
+
betlist
|
2187 |
+
betterjudg
|
2188 |
+
biaxin
|
2189 |
+
bieding laarzen
|
2190 |
+
bieding-laarzen
|
2191 |
+
biedinglaarzen
|
2192 |
+
bielizna
|
2193 |
+
big bling
|
2194 |
+
big-bling
|
2195 |
+
big-cock
|
2196 |
+
big-replica
|
2197 |
+
big-site
|
2198 |
+
big.site
|
2199 |
+
bigbling
|
2200 |
+
bigcock
|
2201 |
+
bigreplica
|
2202 |
+
billig
|
2203 |
+
binaires http
|
2204 |
+
bio bronz
|
2205 |
+
bio-bronz
|
2206 |
+
bird hack
|
2207 |
+
bird-hack
|
2208 |
+
birkenstock boston
|
2209 |
+
birkenstock online
|
2210 |
+
birkenstock-boston
|
2211 |
+
birkenstock-online
|
2212 |
+
birkenstockboston
|
2213 |
+
birkenstockonline
|
2214 |
+
birkenstockonsale
|
2215 |
+
birkenstocksandal
|
2216 |
+
birkenstockshop
|
2217 |
+
birkin bag
|
2218 |
+
birkin-bag
|
2219 |
+
birkinbag
|
2220 |
+
bisapp
|
2221 |
+
bit.ly
|
2222 |
+
bitartrate
|
2223 |
+
biuro-solido
|
2224 |
+
biz.pl
|
2225 |
+
biz.ru
|
2226 |
+
biznes
|
2227 |
+
bizstore
|
2228 |
+
biztalk
|
2229 |
+
biztout
|
2230 |
+
biżuteria
|
2231 |
+
black tight
|
2232 |
+
black ugg
|
2233 |
+
black-tight
|
2234 |
+
black-ugg
|
2235 |
+
black-www
|
2236 |
+
blackhat
|
2237 |
+
blackjack
|
2238 |
+
blacklabelj
|
2239 |
+
blacktight
|
2240 |
+
blackugg
|
2241 |
+
blanc pen
|
2242 |
+
blanc-pen
|
2243 |
+
blank http
|
2244 |
+
blazer-chaussure
|
2245 |
+
blazerchaussure
|
2246 |
+
blog beast
|
2247 |
+
blog here
|
2248 |
+
blog occasion
|
2249 |
+
blog platform
|
2250 |
+
blog soon
|
2251 |
+
blog video
|
2252 |
+
blog_
|
2253 |
+
blog-beast
|
2254 |
+
blog-here
|
2255 |
+
blog-occasion
|
2256 |
+
blog-platform
|
2257 |
+
blog-soon
|
2258 |
+
blog-trick
|
2259 |
+
blog-video
|
2260 |
+
blog-view
|
2261 |
+
blog/blog
|
2262 |
+
blog/comment
|
2263 |
+
blog/index
|
2264 |
+
blog/online
|
2265 |
+
blog/owner
|
2266 |
+
blog/post
|
2267 |
+
blog/view
|
2268 |
+
blog<
|
2269 |
+
blogbeast
|
2270 |
+
blogentry.
|
2271 |
+
bloghome
|
2272 |
+
blogid
|
2273 |
+
blogów
|
2274 |
+
blogplatform
|
2275 |
+
blogs-trick
|
2276 |
+
blogs.blog
|
2277 |
+
blogs/entry
|
2278 |
+
blogs/item
|
2279 |
+
blogs/post
|
2280 |
+
blogsoon
|
2281 |
+
blogtitle
|
2282 |
+
blowjob
|
2283 |
+
blue ugg
|
2284 |
+
blue-ugg
|
2285 |
+
bluehostreview
|
2286 |
+
bluetooth-jammer
|
2287 |
+
bluetoothheadset
|
2288 |
+
bluetoothjammer
|
2289 |
+
blueugg
|
2290 |
+
boaby
|
2291 |
+
bobet link
|
2292 |
+
bobet-link
|
2293 |
+
bodacious
|
2294 |
+
bodog8
|
2295 |
+
bonocasino
|
2296 |
+
bonus-code
|
2297 |
+
bonuscode
|
2298 |
+
book-ot-
|
2299 |
+
bookmark webpage
|
2300 |
+
bookmark-webpage
|
2301 |
+
bookmarked!
|
2302 |
+
boost-your
|
2303 |
+
boostyour
|
2304 |
+
boot online
|
2305 |
+
boot sale
|
2306 |
+
boot uk
|
2307 |
+
boot-get
|
2308 |
+
boot-online
|
2309 |
+
boot-queen
|
2310 |
+
boot-sale
|
2311 |
+
boot-uk
|
2312 |
+
bootcojp
|
2313 |
+
bootget
|
2314 |
+
bootonline
|
2315 |
+
bootqueen
|
2316 |
+
boots online
|
2317 |
+
boots sale
|
2318 |
+
boots ugg
|
2319 |
+
boots uk
|
2320 |
+
boots-get
|
2321 |
+
boots-online
|
2322 |
+
boots-queen
|
2323 |
+
boots-retail
|
2324 |
+
boots-sale
|
2325 |
+
boots-ugg
|
2326 |
+
boots-uk
|
2327 |
+
bootsale
|
2328 |
+
bootsget
|
2329 |
+
bootsonline
|
2330 |
+
bootsqueen
|
2331 |
+
bootsretail
|
2332 |
+
bootss
|
2333 |
+
bootssale
|
2334 |
+
bootsugg
|
2335 |
+
bootsuk
|
2336 |
+
boottenngoku
|
2337 |
+
bootugg
|
2338 |
+
bootuk
|
2339 |
+
borsa moncler
|
2340 |
+
borsa-moncler
|
2341 |
+
borsamoncler
|
2342 |
+
borse moncler
|
2343 |
+
borse-moncler
|
2344 |
+
borsemoncler
|
2345 |
+
boss.de
|
2346 |
+
botanical slim
|
2347 |
+
botanical-slim
|
2348 |
+
botasdefutbol
|
2349 |
+
bottes pas
|
2350 |
+
bottes ugg
|
2351 |
+
bottes-pas
|
2352 |
+
bottes-ugg
|
2353 |
+
bottespas
|
2354 |
+
bottesugg
|
2355 |
+
boutique balenciaga
|
2356 |
+
boutique chaussures
|
2357 |
+
boutique ugg
|
2358 |
+
boutique-balenciaga
|
2359 |
+
boutique-chaussures
|
2360 |
+
boutique-ugg
|
2361 |
+
boutiquechaussures
|
2362 |
+
boutiques ugg
|
2363 |
+
boutiques-ugg
|
2364 |
+
boutiquesugg
|
2365 |
+
boutiqueugg
|
2366 |
+
bow ugg
|
2367 |
+
bow-ugg
|
2368 |
+
bowugg
|
2369 |
+
boychik casino
|
2370 |
+
boychik-casino
|
2371 |
+
bracelet-sale
|
2372 |
+
braceletsale
|
2373 |
+
brain abundance
|
2374 |
+
brain-abundance
|
2375 |
+
brainabundance
|
2376 |
+
brand baseball
|
2377 |
+
brand bat
|
2378 |
+
brand engage
|
2379 |
+
brand mlb
|
2380 |
+
brand nba
|
2381 |
+
brand nhl
|
2382 |
+
brand-baseball
|
2383 |
+
brand-bat
|
2384 |
+
brand-corner
|
2385 |
+
brand-engage
|
2386 |
+
brand-jp
|
2387 |
+
brand-mlb
|
2388 |
+
brand-nba
|
2389 |
+
brand-nhl
|
2390 |
+
brandengage
|
2391 |
+
brandjp
|
2392 |
+
brandnames
|
2393 |
+
brandpurse
|
2394 |
+
bravemed
|
2395 |
+
braves jersey
|
2396 |
+
braves-jersey
|
2397 |
+
bravesjersey
|
2398 |
+
brazil bikini
|
2399 |
+
brazil-bikini
|
2400 |
+
brazilbikini
|
2401 |
+
brazzer
|
2402 |
+
breastactive
|
2403 |
+
bridal-gown
|
2404 |
+
bridalgown
|
2405 |
+
bridalshop
|
2406 |
+
brinkjewel
|
2407 |
+
britanniahotel
|
2408 |
+
brittany-battle
|
2409 |
+
brittanybattle
|
2410 |
+
brittny-battle
|
2411 |
+
brittnybattle
|
2412 |
+
broncos hat
|
2413 |
+
broncos-hat
|
2414 |
+
broncos-jersey
|
2415 |
+
broncos-official
|
2416 |
+
broncoshat
|
2417 |
+
broncosjersey
|
2418 |
+
broncosofficial
|
2419 |
+
brrip
|
2420 |
+
brugte mulberry
|
2421 |
+
brugte-mulberry
|
2422 |
+
bruiseviolet
|
2423 |
+
bruno cabas
|
2424 |
+
bruno-cabas
|
2425 |
+
brunocabas
|
2426 |
+
btn-phone
|
2427 |
+
btshoe
|
2428 |
+
buddie
|
2429 |
+
buddreview
|
2430 |
+
bukmacher
|
2431 |
+
bullion-account
|
2432 |
+
bumpant
|
2433 |
+
burberry bag
|
2434 |
+
burberry belt
|
2435 |
+
burberry borse
|
2436 |
+
burberry brit
|
2437 |
+
burberry clearance
|
2438 |
+
burberry coat
|
2439 |
+
burberry danmark
|
2440 |
+
burberry factory
|
2441 |
+
burberry lad
|
2442 |
+
burberry negozi
|
2443 |
+
burberry out
|
2444 |
+
burberry purse
|
2445 |
+
burberry sale
|
2446 |
+
burberry scarf
|
2447 |
+
burberry store
|
2448 |
+
burberry tasker
|
2449 |
+
burberry thai
|
2450 |
+
burberry uk
|
2451 |
+
burberry wallet
|
2452 |
+
burberry watch
|
2453 |
+
burberry-au
|
2454 |
+
burberry-belt
|
2455 |
+
burberry-borse
|
2456 |
+
burberry-brit
|
2457 |
+
burberry-clearance
|
2458 |
+
burberry-coat
|
2459 |
+
burberry-danmark
|
2460 |
+
burberry-hand
|
2461 |
+
burberry-lad
|
2462 |
+
burberry-negozi
|
2463 |
+
burberry-out
|
2464 |
+
burberry-purse
|
2465 |
+
burberry-sale
|
2466 |
+
burberry-scarf
|
2467 |
+
burberry-tasker
|
2468 |
+
burberry-wallet
|
2469 |
+
burberry-watch
|
2470 |
+
burberry.blog
|
2471 |
+
burberryau
|
2472 |
+
burberrybelt
|
2473 |
+
burberrybi
|
2474 |
+
burberryblack
|
2475 |
+
burberryborse
|
2476 |
+
burberrybrit
|
2477 |
+
burberryclearance
|
2478 |
+
burberrycoat
|
2479 |
+
burberrydanmark
|
2480 |
+
burberryhand
|
2481 |
+
burberrylad
|
2482 |
+
burberrynegozi
|
2483 |
+
burberryout
|
2484 |
+
burberrypurse
|
2485 |
+
burberrysale
|
2486 |
+
burberryscarf
|
2487 |
+
burberrysold
|
2488 |
+
burberrystore
|
2489 |
+
burberrysuto
|
2490 |
+
burberrytaschen
|
2491 |
+
burberrytasker
|
2492 |
+
burberrywallet
|
2493 |
+
burberrywatch
|
2494 |
+
burch-out
|
2495 |
+
burch-sale
|
2496 |
+
burchout
|
2497 |
+
burchsale
|
2498 |
+
business empire
|
2499 |
+
business-empire
|
2500 |
+
business-in
|
2501 |
+
business-loan
|
2502 |
+
business-market
|
2503 |
+
business-net
|
2504 |
+
businessboss
|
2505 |
+
businessfinder
|
2506 |
+
businessintel
|
2507 |
+
businessloan
|
2508 |
+
businessmarket
|
2509 |
+
businessnetwork
|
2510 |
+
buspirone
|
2511 |
+
busquemail
|
2512 |
+
busythumb
|
2513 |
+
butikk
|
2514 |
+
butnow
|
2515 |
+
butthe
|
2516 |
+
button ugg
|
2517 |
+
button-ugg
|
2518 |
+
buttonugg
|
2519 |
+
butwho
|
2520 |
+
buy acrylic
|
2521 |
+
buy ageless
|
2522 |
+
buy cheap
|
2523 |
+
buy fifa
|
2524 |
+
buy gig
|
2525 |
+
buy hermes
|
2526 |
+
buy insta
|
2527 |
+
buy jordan
|
2528 |
+
buy louis
|
2529 |
+
buy online
|
2530 |
+
buy private
|
2531 |
+
buy toms
|
2532 |
+
buy traffic
|
2533 |
+
buy women
|
2534 |
+
buy-acrylic
|
2535 |
+
buy-cheap
|
2536 |
+
buy-cig
|
2537 |
+
buy-fifa
|
2538 |
+
buy-gig
|
2539 |
+
buy-gucci
|
2540 |
+
buy-hair
|
2541 |
+
buy-insta
|
2542 |
+
buy-jordan
|
2543 |
+
buy-louis
|
2544 |
+
buy-movie
|
2545 |
+
buy-now
|
2546 |
+
buy-online
|
2547 |
+
buy-pill
|
2548 |
+
buy-plus
|
2549 |
+
buy-private
|
2550 |
+
buy-soma
|
2551 |
+
buy-toms
|
2552 |
+
buy-traffic
|
2553 |
+
buy-women
|
2554 |
+
buycanadagoose
|
2555 |
+
buycheap
|
2556 |
+
buycig
|
2557 |
+
buyhair
|
2558 |
+
buyhermes
|
2559 |
+
buying-facebook
|
2560 |
+
buyjap
|
2561 |
+
buyjordan
|
2562 |
+
buyjp
|
2563 |
+
buylouis
|
2564 |
+
buymovie
|
2565 |
+
buyonline
|
2566 |
+
buyplus
|
2567 |
+
buysoma
|
2568 |
+
buytoms
|
2569 |
+
buywomen
|
2570 |
+
bvlgari brand
|
2571 |
+
bvlgari store
|
2572 |
+
bvlgari-brand
|
2573 |
+
bvlgari-store
|
2574 |
+
bvlgaribrand
|
2575 |
+
bvlgarishop
|
2576 |
+
bvlgarisshop
|
2577 |
+
bvlgaristore
|
2578 |
+
by-dr-dre
|
2579 |
+
bydre-head
|
2580 |
+
bydrehead
|
2581 |
+
byo.co
|
2582 |
+
byt.es
|
2583 |
+
c.he.a.p
|
2584 |
+
c.he.ap
|
2585 |
+
c|pro
|
2586 |
+
cabas vanessa
|
2587 |
+
cabas-vanessa
|
2588 |
+
cabasvanessa
|
2589 |
+
cabin lithu
|
2590 |
+
cabin-lithu
|
2591 |
+
cabins it
|
2592 |
+
cabins lithu
|
2593 |
+
cabins-it
|
2594 |
+
cabins-lithu
|
2595 |
+
caellis
|
2596 |
+
cagoosejacket
|
2597 |
+
cagoosesale
|
2598 |
+
calabasas carpet
|
2599 |
+
calabasas rug
|
2600 |
+
calabasas-carpet
|
2601 |
+
calabasas-rug
|
2602 |
+
callgirl
|
2603 |
+
cambogia
|
2604 |
+
camgirl
|
2605 |
+
camicie abercrombie
|
2606 |
+
camicie negozi
|
2607 |
+
camicie-abercrombie
|
2608 |
+
camicie-negozi
|
2609 |
+
camicieabercrombie
|
2610 |
+
camicienegozi
|
2611 |
+
camisas ralph
|
2612 |
+
camisas-ralph
|
2613 |
+
camisasralph
|
2614 |
+
can-help-you
|
2615 |
+
canada loan
|
2616 |
+
canada-loan
|
2617 |
+
canadagoose-ca
|
2618 |
+
canadagoose-factory
|
2619 |
+
canadagoose-fr
|
2620 |
+
canadagoose-online
|
2621 |
+
canadagoose-out
|
2622 |
+
canadagooseannka
|
2623 |
+
canadagoosebanff
|
2624 |
+
canadagooseca
|
2625 |
+
canadagoosefactory
|
2626 |
+
canadagoosejack
|
2627 |
+
canadagoosemen
|
2628 |
+
canadagooseonline
|
2629 |
+
canadagooseoutlet
|
2630 |
+
canadagoosepark
|
2631 |
+
canadagooses
|
2632 |
+
canadagooses-factory
|
2633 |
+
canadagooses-out
|
2634 |
+
canadagoosesfactory
|
2635 |
+
canadagoosesoutlet
|
2636 |
+
canadaoutlet
|
2637 |
+
canadian hgh
|
2638 |
+
canadian loan
|
2639 |
+
canadian-hgh
|
2640 |
+
canadian-loan
|
2641 |
+
candycrush
|
2642 |
+
cannabis-seed
|
2643 |
+
cappelli boston
|
2644 |
+
cappelli new
|
2645 |
+
cappelli nfl
|
2646 |
+
cappelli-boston
|
2647 |
+
cappelli-new
|
2648 |
+
cappelli-nfl
|
2649 |
+
captchasnip
|
2650 |
+
card-debt
|
2651 |
+
cardy boot
|
2652 |
+
cardy-boot
|
2653 |
+
cardyboot
|
2654 |
+
care-cream
|
2655 |
+
carinsurance
|
2656 |
+
carisoprodol
|
2657 |
+
carrera bat
|
2658 |
+
carrera lunette
|
2659 |
+
carrera-bat
|
2660 |
+
carrera-lunette
|
2661 |
+
carreralunette
|
2662 |
+
carreramoinscher
|
2663 |
+
cars insurance
|
2664 |
+
cars-games
|
2665 |
+
cars-insurance
|
2666 |
+
cartuchos
|
2667 |
+
casaemail.co
|
2668 |
+
casebycase
|
2669 |
+
casesolution
|
2670 |
+
cash advance
|
2671 |
+
cash generator
|
2672 |
+
cash loan
|
2673 |
+
cash-advance
|
2674 |
+
cash-generator
|
2675 |
+
cash4gold
|
2676 |
+
cash4silver
|
2677 |
+
cashadvance
|
2678 |
+
cashforgold
|
2679 |
+
cashforsilver
|
2680 |
+
cashgenerator
|
2681 |
+
cashloan
|
2682 |
+
cashout
|
2683 |
+
casino enligne
|
2684 |
+
casino online
|
2685 |
+
casino only
|
2686 |
+
casino-enligne
|
2687 |
+
casino-game
|
2688 |
+
casino-online
|
2689 |
+
casino-only
|
2690 |
+
casino.co
|
2691 |
+
casinoenligne
|
2692 |
+
casinoer
|
2693 |
+
casinogame
|
2694 |
+
casinoonline
|
2695 |
+
casinos-
|
2696 |
+
casque beats
|
2697 |
+
casque-beats
|
2698 |
+
casquebeats
|
2699 |
+
casquette
|
2700 |
+
câsuâl
|
2701 |
+
casub.co
|
2702 |
+
catalog/preview
|
2703 |
+
catalogo/preview
|
2704 |
+
catalogs.cfm
|
2705 |
+
catalogues.cfm
|
2706 |
+
cavin-klein
|
2707 |
+
cavinklein
|
2708 |
+
ce billet
|
2709 |
+
ce-billet
|
2710 |
+
celebrex
|
2711 |
+
celebrities-nude
|
2712 |
+
celebritiesnude
|
2713 |
+
celebrity-nude
|
2714 |
+
celebritynude
|
2715 |
+
celexa
|
2716 |
+
celine bag
|
2717 |
+
celine hand
|
2718 |
+
celine luggage
|
2719 |
+
celine shop
|
2720 |
+
celine tote
|
2721 |
+
celine-bag
|
2722 |
+
celine-hand
|
2723 |
+
celine-luggage
|
2724 |
+
celine-shop
|
2725 |
+
celine-tote
|
2726 |
+
celine.gear
|
2727 |
+
celinebag
|
2728 |
+
celinehand
|
2729 |
+
celinehandbag
|
2730 |
+
celineluggage
|
2731 |
+
celineshop
|
2732 |
+
celinetote
|
2733 |
+
cellskin
|
2734 |
+
cellulitefree
|
2735 |
+
cellulitereview
|
2736 |
+
celtics color
|
2737 |
+
celtics-color
|
2738 |
+
celular
|
2739 |
+
cent|
|
2740 |
+
cgi-bin
|
2741 |
+
cgsaleca
|
2742 |
+
ch.e.ap
|
2743 |
+
ch.ea.p
|
2744 |
+
chandler baseball
|
2745 |
+
chandler-baseball
|
2746 |
+
chanel bag
|
2747 |
+
chanel handbag
|
2748 |
+
chanel out
|
2749 |
+
chanel purse
|
2750 |
+
chanel replica
|
2751 |
+
chanel sac
|
2752 |
+
chanel spring
|
2753 |
+
chanel_
|
2754 |
+
chanel--
|
2755 |
+
chanel-bag
|
2756 |
+
chanel-online
|
2757 |
+
chanel-out
|
2758 |
+
chanel-purse
|
2759 |
+
chanel-replica
|
2760 |
+
chanel-sac
|
2761 |
+
chanel-sale
|
2762 |
+
chanel-spring
|
2763 |
+
chanelbag
|
2764 |
+
chanelonline
|
2765 |
+
chaneloutlet
|
2766 |
+
chanelpurse
|
2767 |
+
chanelreplica
|
2768 |
+
chanelsac
|
2769 |
+
chanelsale
|
2770 |
+
chanelspring
|
2771 |
+
channel-operator
|
2772 |
+
chantix
|
2773 |
+
chapa shoe
|
2774 |
+
chapa-shoe
|
2775 |
+
chapashoe
|
2776 |
+
chaqueta cuero
|
2777 |
+
chaqueta oferta
|
2778 |
+
chaqueta-cuero
|
2779 |
+
chaqueta-oferta
|
2780 |
+
chaquetacuero
|
2781 |
+
chaquetaoferta
|
2782 |
+
chaquetas belstaff
|
2783 |
+
chaquetas-belstaff
|
2784 |
+
chaquetasbelstaff
|
2785 |
+
charlescave
|
2786 |
+
charms thomas
|
2787 |
+
charms-thomas
|
2788 |
+
charmsthomas
|
2789 |
+
chat-chat
|
2790 |
+
chatchat
|
2791 |
+
chaturbate
|
2792 |
+
chaussres boutique
|
2793 |
+
chaussres pascher
|
2794 |
+
chaussres-boutique
|
2795 |
+
chaussres-pascher
|
2796 |
+
chaussresboutique
|
2797 |
+
chaussrespascher
|
2798 |
+
chaussure louboutin
|
2799 |
+
chaussure paris
|
2800 |
+
chaussure_
|
2801 |
+
chaussure-asics
|
2802 |
+
chaussure-femme
|
2803 |
+
chaussure-homme
|
2804 |
+
chaussure-louboutin
|
2805 |
+
chaussure-paris
|
2806 |
+
chaussure-puma
|
2807 |
+
chaussureparis
|
2808 |
+
chaussures boutique
|
2809 |
+
chaussures christian
|
2810 |
+
chaussures femme
|
2811 |
+
chaussures louboutin
|
2812 |
+
chaussures paris
|
2813 |
+
chaussures pascher
|
2814 |
+
chaussures salomon
|
2815 |
+
chaussures ski
|
2816 |
+
chaussures sport
|
2817 |
+
chaussures ugg
|
2818 |
+
chaussures_
|
2819 |
+
chaussures- abil
|
2820 |
+
chaussures-asics
|
2821 |
+
chaussures-boutique
|
2822 |
+
chaussures-christian
|
2823 |
+
chaussures-femme
|
2824 |
+
chaussures-habil
|
2825 |
+
chaussures-homme
|
2826 |
+
chaussures-louboutin
|
2827 |
+
chaussures-paris
|
2828 |
+
chaussures-pascher
|
2829 |
+
chaussures-puma
|
2830 |
+
chaussures-salomon
|
2831 |
+
chaussures-ski
|
2832 |
+
chaussures-sport
|
2833 |
+
chaussures-ugg
|
2834 |
+
chaussuresboutique
|
2835 |
+
chaussureschristian
|
2836 |
+
chaussuresfemme
|
2837 |
+
chaussuresfr
|
2838 |
+
chaussureslouboutin
|
2839 |
+
chaussuresparis
|
2840 |
+
chaussurespascher
|
2841 |
+
chaussuressport
|
2842 |
+
chcoin.co
|
2843 |
+
cheap air
|
2844 |
+
cheap atlanta
|
2845 |
+
cheap authentic
|
2846 |
+
cheap bag
|
2847 |
+
cheap basket
|
2848 |
+
cheap beat
|
2849 |
+
cheap bike
|
2850 |
+
cheap carolina
|
2851 |
+
cheap carton
|
2852 |
+
cheap cheap
|
2853 |
+
cheap china
|
2854 |
+
cheap christian
|
2855 |
+
cheap denver
|
2856 |
+
cheap fifa
|
2857 |
+
cheap football
|
2858 |
+
cheap ga
|
2859 |
+
cheap galaxy
|
2860 |
+
cheap hockey
|
2861 |
+
cheap iphone
|
2862 |
+
cheap jersey
|
2863 |
+
cheap longchamp
|
2864 |
+
cheap louboutin
|
2865 |
+
cheap louis
|
2866 |
+
cheap mbt
|
2867 |
+
cheap michael
|
2868 |
+
cheap moncler
|
2869 |
+
cheap mont
|
2870 |
+
cheap nfl
|
2871 |
+
cheap nhl
|
2872 |
+
cheap nike
|
2873 |
+
cheap north
|
2874 |
+
cheap oakley
|
2875 |
+
cheap ray
|
2876 |
+
cheap red
|
2877 |
+
cheap sale
|
2878 |
+
cheap sherr
|
2879 |
+
cheap sunglass
|
2880 |
+
cheap supra
|
2881 |
+
cheap timberland
|
2882 |
+
cheap toms
|
2883 |
+
cheap travel
|
2884 |
+
cheap ugg
|
2885 |
+
cheap uk
|
2886 |
+
cheap wed
|
2887 |
+
cheap-adobe
|
2888 |
+
cheap-atlanta
|
2889 |
+
cheap-authentic
|
2890 |
+
cheap-bag
|
2891 |
+
cheap-basket
|
2892 |
+
cheap-beat
|
2893 |
+
cheap-bike
|
2894 |
+
cheap-carolina
|
2895 |
+
cheap-carton
|
2896 |
+
cheap-chanel
|
2897 |
+
cheap-cheap
|
2898 |
+
cheap-china
|
2899 |
+
cheap-christian
|
2900 |
+
cheap-converse
|
2901 |
+
cheap-denver
|
2902 |
+
cheap-fifa
|
2903 |
+
cheap-football
|
2904 |
+
cheap-ga
|
2905 |
+
cheap-gucci
|
2906 |
+
cheap-hat
|
2907 |
+
cheap-hermes
|
2908 |
+
cheap-hockey
|
2909 |
+
cheap-jacket
|
2910 |
+
cheap-jersey
|
2911 |
+
cheap-kobe
|
2912 |
+
cheap-louboutin
|
2913 |
+
cheap-mbt
|
2914 |
+
cheap-michael
|
2915 |
+
cheap-moncler
|
2916 |
+
cheap-mont
|
2917 |
+
cheap-nfl
|
2918 |
+
cheap-nhl
|
2919 |
+
cheap-nike
|
2920 |
+
cheap-north
|
2921 |
+
cheap-oakley
|
2922 |
+
cheap-pandora
|
2923 |
+
cheap-prada
|
2924 |
+
cheap-red
|
2925 |
+
cheap-sale
|
2926 |
+
cheap-sex
|
2927 |
+
cheap-sherr
|
2928 |
+
cheap-sunglass
|
2929 |
+
cheap-supra
|
2930 |
+
cheap-timberland
|
2931 |
+
cheap-tms
|
2932 |
+
cheap-toms
|
2933 |
+
cheap-travel
|
2934 |
+
cheap-ugg
|
2935 |
+
cheap-uk
|
2936 |
+
cheap-wed
|
2937 |
+
cheap+
|
2938 |
+
cheap<
|
2939 |
+
cheapadobe
|
2940 |
+
cheapatlanta
|
2941 |
+
cheapauthentic
|
2942 |
+
cheapbag
|
2943 |
+
cheapbasket
|
2944 |
+
cheapbeat
|
2945 |
+
cheapbeatsbydre
|
2946 |
+
cheapbike
|
2947 |
+
cheapchanel
|
2948 |
+
cheapchina
|
2949 |
+
cheapcoach
|
2950 |
+
cheapconverse
|
2951 |
+
cheapest hockey
|
2952 |
+
cheapest-hockey
|
2953 |
+
cheapest.co
|
2954 |
+
cheapesthockey
|
2955 |
+
cheapga
|
2956 |
+
cheapgucci
|
2957 |
+
cheaphat
|
2958 |
+
cheaphermes
|
2959 |
+
cheaphockey
|
2960 |
+
cheapiphone
|
2961 |
+
cheapjacket
|
2962 |
+
cheapjersey
|
2963 |
+
cheapjorda
|
2964 |
+
cheapkobe
|
2965 |
+
cheaplouboutin
|
2966 |
+
cheaplouis
|
2967 |
+
cheapmbt
|
2968 |
+
cheapmichael
|
2969 |
+
cheapmoncler
|
2970 |
+
cheapnfl
|
2971 |
+
cheapnike
|
2972 |
+
cheapnorth
|
2973 |
+
cheapoakley
|
2974 |
+
cheappandora
|
2975 |
+
cheapprada
|
2976 |
+
cheaprayban
|
2977 |
+
cheapred
|
2978 |
+
cheaps ugg
|
2979 |
+
cheaps-ugg
|
2980 |
+
cheapsale
|
2981 |
+
cheapsex
|
2982 |
+
cheapsugg
|
2983 |
+
cheapsunglass
|
2984 |
+
cheapsupra
|
2985 |
+
cheaptimberland
|
2986 |
+
cheaptms
|
2987 |
+
cheaptoms
|
2988 |
+
cheaptravel
|
2989 |
+
cheapugg
|
2990 |
+
cheapuk
|
2991 |
+
cheapweb
|
2992 |
+
cheat.co
|
2993 |
+
cheats for
|
2994 |
+
cheats-
|
2995 |
+
cheats-for
|
2996 |
+
cheats.co
|
2997 |
+
cheatsfor
|
2998 |
+
cheatss
|
2999 |
+
cheaρ
|
3000 |
+
check.asp
|
3001 |
+
check32attack
|
3002 |
+
cheesefruit
|
3003 |
+
chemise-ralph
|
3004 |
+
chemiseralph
|
3005 |
+
cher moncler
|
3006 |
+
cher prada
|
3007 |
+
cher-moncler
|
3008 |
+
cher-prada
|
3009 |
+
chermoncler
|
3010 |
+
cherprada
|
3011 |
+
chettelongchamp
|
3012 |
+
chf iraq
|
3013 |
+
chf-iraq
|
3014 |
+
chic mcm
|
3015 |
+
chic-mcm
|
3016 |
+
chicmcm
|
3017 |
+
china cheap
|
3018 |
+
china low
|
3019 |
+
china shop
|
3020 |
+
china wholesale
|
3021 |
+
china-cheap
|
3022 |
+
china-low
|
3023 |
+
china-shop
|
3024 |
+
china-wholesale
|
3025 |
+
chinacheap
|
3026 |
+
chinajorda
|
3027 |
+
chinalow
|
3028 |
+
chinawholesale
|
3029 |
+
chinska
|
3030 |
+
chlamydia
|
3031 |
+
chloe boot
|
3032 |
+
chloe sunglass
|
3033 |
+
chloe-boot
|
3034 |
+
chloe-sunglass
|
3035 |
+
chloeboot
|
3036 |
+
chloejp
|
3037 |
+
chloemoment
|
3038 |
+
chloeoutsale
|
3039 |
+
chloesunglass
|
3040 |
+
chloie
|
3041 |
+
choo sale
|
3042 |
+
choo-boots
|
3043 |
+
choo-sale
|
3044 |
+
chooboots
|
3045 |
+
chrismas.asp
|
3046 |
+
christian-louboutin
|
3047 |
+
christianlouboutin
|
3048 |
+
chrr-llc
|
3049 |
+
chung hightop
|
3050 |
+
chung-hightop
|
3051 |
+
cialis
|
3052 |
+
ciallis
|
3053 |
+
cig holder
|
3054 |
+
cig-holder
|
3055 |
+
cig-online
|
3056 |
+
cig-promo
|
3057 |
+
cig<
|
3058 |
+
cigar-cuba
|
3059 |
+
cigar-online
|
3060 |
+
cigar-store
|
3061 |
+
cigarcuba
|
3062 |
+
cigarette online
|
3063 |
+
cigarette-online
|
3064 |
+
cigarette<
|
3065 |
+
cigarettebuy
|
3066 |
+
cigarettes online
|
3067 |
+
cigarettes-online
|
3068 |
+
cigarettes<
|
3069 |
+
cigarettesbuy
|
3070 |
+
cigaronline
|
3071 |
+
cigarrette
|
3072 |
+
cigars-cuba
|
3073 |
+
cigars-online
|
3074 |
+
cigarscuba
|
3075 |
+
cigarsonline
|
3076 |
+
cigarstore
|
3077 |
+
cigbuy
|
3078 |
+
cigonline
|
3079 |
+
cigpromo
|
3080 |
+
cigs online
|
3081 |
+
cigs-online
|
3082 |
+
cigs-promo
|
3083 |
+
cigs<
|
3084 |
+
cigsbuy
|
3085 |
+
cigsonline
|
3086 |
+
cigspromo
|
3087 |
+
cinture gucci
|
3088 |
+
cinture outlet
|
3089 |
+
cinture-gucci
|
3090 |
+
cinture-outlet
|
3091 |
+
cinturegucci
|
3092 |
+
cintureoutlet
|
3093 |
+
ciproanti
|
3094 |
+
citʏ
|
3095 |
+
clans hack
|
3096 |
+
clans-hack
|
3097 |
+
clarisonic
|
3098 |
+
clash-of-clans
|
3099 |
+
clashofclans
|
3100 |
+
classic-ugg
|
3101 |
+
classicugg
|
3102 |
+
clavulanate
|
3103 |
+
clboot
|
3104 |
+
clck.ru
|
3105 |
+
cleaning calabasas
|
3106 |
+
cleaning http
|
3107 |
+
cleaning-calabasas
|
3108 |
+
clearance mbt
|
3109 |
+
clearance michael
|
3110 |
+
clearance out
|
3111 |
+
clearance sale
|
3112 |
+
clearance-mbt
|
3113 |
+
clearance-michael
|
3114 |
+
clearance-out
|
3115 |
+
clearance-sale
|
3116 |
+
clearancembt
|
3117 |
+
clearancemichael
|
3118 |
+
clearanceoutlet
|
3119 |
+
clearancesale
|
3120 |
+
clenbuterol
|
3121 |
+
clentching
|
3122 |
+
click here
|
3123 |
+
click_
|
3124 |
+
click-here
|
3125 |
+
click2
|
3126 |
+
click4
|
3127 |
+
clickbank
|
3128 |
+
clickforu
|
3129 |
+
clientarea
|
3130 |
+
climacool
|
3131 |
+
clomid
|
3132 |
+
clonazepam
|
3133 |
+
clone-key
|
3134 |
+
clonekey
|
3135 |
+
clothes online
|
3136 |
+
clothes-online
|
3137 |
+
clothesonline
|
3138 |
+
clothing abercrombie
|
3139 |
+
clothing online
|
3140 |
+
clothing-abercrombie
|
3141 |
+
clothing-online
|
3142 |
+
clothingabercrombie
|
3143 |
+
clothingonline
|
3144 |
+
clredheel
|
3145 |
+
clsale
|
3146 |
+
clshoe
|
3147 |
+
club-boy
|
3148 |
+
clubboy
|
3149 |
+
clusive vacation
|
3150 |
+
clusive-vacation
|
3151 |
+
clusivevacation
|
3152 |
+
clyel
|
3153 |
+
cms-temp
|
3154 |
+
cms-theme
|
3155 |
+
cnoesfs
|
3156 |
+
coach austr
|
3157 |
+
coach black
|
3158 |
+
coach factory
|
3159 |
+
coach flight
|
3160 |
+
coach handbag
|
3161 |
+
coach legacy
|
3162 |
+
coach out
|
3163 |
+
coach promo
|
3164 |
+
coach purse
|
3165 |
+
coach shoe
|
3166 |
+
coach sneaker
|
3167 |
+
coach thai
|
3168 |
+
coach wristlet
|
3169 |
+
coach-bag
|
3170 |
+
coach-black
|
3171 |
+
coach-factory
|
3172 |
+
coach-flight
|
3173 |
+
coach-legacy
|
3174 |
+
coach-men
|
3175 |
+
coach-new
|
3176 |
+
coach-out
|
3177 |
+
coach-promo
|
3178 |
+
coach-purse
|
3179 |
+
coach-shoe
|
3180 |
+
coach-sneaker
|
3181 |
+
coach-store
|
3182 |
+
coach-wristlet
|
3183 |
+
coach+promo
|
3184 |
+
coach+sneaker
|
3185 |
+
coach2you
|
3186 |
+
coachbag
|
3187 |
+
coachbags
|
3188 |
+
coachbay
|
3189 |
+
coachblack
|
3190 |
+
coachfactory
|
3191 |
+
coachflight
|
3192 |
+
coachhandbag
|
3193 |
+
coachja
|
3194 |
+
coachjap
|
3195 |
+
coachjp
|
3196 |
+
coachkan
|
3197 |
+
coachmise
|
3198 |
+
coachniho
|
3199 |
+
coachninnki
|
3200 |
+
coachoutlet
|
3201 |
+
coachpromo
|
3202 |
+
coachshoe
|
3203 |
+
coachsneaker
|
3204 |
+
coachstore
|
3205 |
+
coachsuto
|
3206 |
+
coachsyoppu
|
3207 |
+
coachtokyo
|
3208 |
+
coachwallet
|
3209 |
+
coachwristlet
|
3210 |
+
coachya
|
3211 |
+
code-generat
|
3212 |
+
colin-kaepernick
|
3213 |
+
collection effort
|
3214 |
+
college-loan
|
3215 |
+
collezione moncler
|
3216 |
+
collezione-moncler
|
3217 |
+
collezionemoncler
|
3218 |
+
colts hat
|
3219 |
+
colts-hat
|
3220 |
+
com http
|
3221 |
+
com.asp
|
3222 |
+
com.com
|
3223 |
+
com//
|
3224 |
+
com/author
|
3225 |
+
com/autocom
|
3226 |
+
com/bilder
|
3227 |
+
com/boards
|
3228 |
+
com/cheap
|
3229 |
+
com/css
|
3230 |
+
com/doc
|
3231 |
+
com/dress
|
3232 |
+
com/forum
|
3233 |
+
com/fr/
|
3234 |
+
com/ftp
|
3235 |
+
com/htm
|
3236 |
+
com/image
|
3237 |
+
com/include
|
3238 |
+
com/member
|
3239 |
+
com/moncler
|
3240 |
+
com/official
|
3241 |
+
com/online
|
3242 |
+
com/page1
|
3243 |
+
com/page2
|
3244 |
+
com/pharma
|
3245 |
+
com/profile
|
3246 |
+
com/public
|
3247 |
+
com/site
|
3248 |
+
com/tiffany
|
3249 |
+
com/ugg
|
3250 |
+
com/user
|
3251 |
+
com/vuitton
|
3252 |
+
com%2c
|
3253 |
+
com2.php
|
3254 |
+
comedyee
|
3255 |
+
comment-pag
|
3256 |
+
commentabout
|
3257 |
+
commented here
|
3258 |
+
commented-here
|
3259 |
+
commentsyou
|
3260 |
+
commerce retail
|
3261 |
+
commerce-retail
|
3262 |
+
community.atom
|
3263 |
+
commutee
|
3264 |
+
como ganhar
|
3265 |
+
como-ganhar
|
3266 |
+
compare price
|
3267 |
+
compare-price
|
3268 |
+
component/blog
|
3269 |
+
comprar
|
3270 |
+
computer-gaming
|
3271 |
+
computer-performance
|
3272 |
+
computerpressrelease
|
3273 |
+
computers.in
|
3274 |
+
comreview
|
3275 |
+
comunity
|
3276 |
+
conficker worm
|
3277 |
+
conficker-worm
|
3278 |
+
consalt-
|
3279 |
+
constructionn
|
3280 |
+
construtor
|
3281 |
+
contact/contact
|
3282 |
+
contactus/contact
|
3283 |
+
conversejapan
|
3284 |
+
conversejp
|
3285 |
+
conydot
|
3286 |
+
cooker-ninja
|
3287 |
+
cookerninja
|
3288 |
+
coordintaing
|
3289 |
+
copie ugg
|
3290 |
+
copie-ugg
|
3291 |
+
copieugg
|
3292 |
+
copy-wizard
|
3293 |
+
copywizard
|
3294 |
+
cordarone
|
3295 |
+
corporate-gift
|
3296 |
+
corporategift
|
3297 |
+
cort.as
|
3298 |
+
coskobo
|
3299 |
+
cosm tiques
|
3300 |
+
cosmetics-out
|
3301 |
+
cosmeticswholesale
|
3302 |
+
cosmtiques
|
3303 |
+
cost-effective
|
3304 |
+
costume ermen
|
3305 |
+
costume homme
|
3306 |
+
costume mariage
|
3307 |
+
costume marie
|
3308 |
+
costume marié
|
3309 |
+
costume tendance
|
3310 |
+
costume versace
|
3311 |
+
costume-ermen
|
3312 |
+
costume-homme
|
3313 |
+
costume-mariage
|
3314 |
+
costume-marie
|
3315 |
+
costume-marié
|
3316 |
+
costume-medieval
|
3317 |
+
costume-tendance
|
3318 |
+
costume-versace
|
3319 |
+
costumes homme
|
3320 |
+
costumes-homme
|
3321 |
+
couchey fr
|
3322 |
+
couchey-fr
|
3323 |
+
coucheyfr
|
3324 |
+
coumadin
|
3325 |
+
countrу
|
3326 |
+
couple gratuite
|
3327 |
+
couple-gratuite
|
3328 |
+
coupon_
|
3329 |
+
coupon-code
|
3330 |
+
coupon-pag
|
3331 |
+
coupon.blog
|
3332 |
+
couponcode
|
3333 |
+
coupons_
|
3334 |
+
coupons-pag
|
3335 |
+
couponsense
|
3336 |
+
courses casino
|
3337 |
+
courses-casino
|
3338 |
+
couture avec
|
3339 |
+
couture-avec
|
3340 |
+
coverages
|
3341 |
+
cozy-ugg
|
3342 |
+
cozyugg
|
3343 |
+
coսld
|
3344 |
+
cracked-pro
|
3345 |
+
crackedpro
|
3346 |
+
crane-hire
|
3347 |
+
cranehire
|
3348 |
+
create-product
|
3349 |
+
credit repair
|
3350 |
+
credit-card
|
3351 |
+
credit-report
|
3352 |
+
credit-score
|
3353 |
+
credit.eu
|
3354 |
+
creditcard.org
|
3355 |
+
creditreport
|
3356 |
+
cription.asp
|
3357 |
+
cristmas-
|
3358 |
+
crossof
|
3359 |
+
cruise vacation
|
3360 |
+
cruise-vacation
|
3361 |
+
cruisevacation
|
3362 |
+
crystalmall
|
3363 |
+
cuir vanessa
|
3364 |
+
cuir-vanessa
|
3365 |
+
cuirvanessa
|
3366 |
+
cup jersey
|
3367 |
+
cup-jersey
|
3368 |
+
cure herpes
|
3369 |
+
cure-herpes
|
3370 |
+
cure.co.
|
3371 |
+
curehelp
|
3372 |
+
cures.co.
|
3373 |
+
currency trad
|
3374 |
+
currency-trad
|
3375 |
+
custom-nike
|
3376 |
+
custom-rim
|
3377 |
+
custom-wheel
|
3378 |
+
custom+tire
|
3379 |
+
custom+wheel
|
3380 |
+
customrim
|
3381 |
+
customwheel
|
3382 |
+
cuurently
|
3383 |
+
cyber monday
|
3384 |
+
cyber-monday
|
3385 |
+
cybermonday
|
3386 |
+
cygara
|
3387 |
+
cymbalta
|
3388 |
+
cytotec
|
3389 |
+
cz/love
|
3390 |
+
cеrt
|
3391 |
+
dabloggs
|
3392 |
+
dafeult
|
3393 |
+
dailly
|
3394 |
+
daily.blog
|
3395 |
+
dailyreview.co
|
3396 |
+
dailystrength
|
3397 |
+
dakotasuki
|
3398 |
+
damen timberland
|
3399 |
+
damen-timberland
|
3400 |
+
damentimberland
|
3401 |
+
damier-azur
|
3402 |
+
damskie
|
3403 |
+
dannerjp
|
3404 |
+
dapoxetin
|
3405 |
+
dapoxetine
|
3406 |
+
darmowe ogloszenia
|
3407 |
+
darmowe ogłoszenia
|
3408 |
+
darmowe-ogloszenia
|
3409 |
+
darmowe-ogłoszenia
|
3410 |
+
darmowe-programy
|
3411 |
+
darmoweogloszenia
|
3412 |
+
darmoweogłoszenia
|
3413 |
+
darmoweprogramy
|
3414 |
+
darmowy
|
3415 |
+
darrellbox
|
3416 |
+
darrellwire
|
3417 |
+
darvocet
|
3418 |
+
data-tools
|
3419 |
+
database.co
|
3420 |
+
datarecovery.co
|
3421 |
+
datarecoveryhospital
|
3422 |
+
dataz
|
3423 |
+
dating-guide
|
3424 |
+
datingdirect
|
3425 |
+
datingguide
|
3426 |
+
datingsite
|
3427 |
+
day loan
|
3428 |
+
day-diet
|
3429 |
+
daytrade
|
3430 |
+
daytrading
|
3431 |
+
de site
|
3432 |
+
de-contacto
|
3433 |
+
de-site
|
3434 |
+
deal.blog
|
3435 |
+
dealonline
|
3436 |
+
dealsuk
|
3437 |
+
dealsus
|
3438 |
+
dealuk
|
3439 |
+
dealus
|
3440 |
+
dear-lover
|
3441 |
+
dearlover
|
3442 |
+
debt_
|
3443 |
+
debt-help
|
3444 |
+
debt-management
|
3445 |
+
debt-relief
|
3446 |
+
debt-solution
|
3447 |
+
debthelp
|
3448 |
+
debtrelief
|
3449 |
+
dedrease
|
3450 |
+
default/member
|
3451 |
+
default1
|
3452 |
+
default2
|
3453 |
+
definitelly
|
3454 |
+
delete_
|
3455 |
+
delpha_
|
3456 |
+
deltasone
|
3457 |
+
demo123
|
3458 |
+
demontag
|
3459 |
+
denschlaf
|
3460 |
+
dental-implant
|
3461 |
+
dental-quote
|
3462 |
+
depositbank
|
3463 |
+
depression-symptom
|
3464 |
+
depressionsymptom
|
3465 |
+
derm exclus
|
3466 |
+
derm-exclus
|
3467 |
+
dermexclus
|
3468 |
+
desconto
|
3469 |
+
designer bag
|
3470 |
+
designer-bag
|
3471 |
+
designer-brand
|
3472 |
+
designer-jewel
|
3473 |
+
designer-shoe
|
3474 |
+
designerbag
|
3475 |
+
designerbrand
|
3476 |
+
designerjewel
|
3477 |
+
designerlabel
|
3478 |
+
designershoe
|
3479 |
+
desktop-client
|
3480 |
+
desktopclient
|
3481 |
+
despaulsmith
|
3482 |
+
desyrel
|
3483 |
+
detail/www
|
3484 |
+
detektiv
|
3485 |
+
devenir trade
|
3486 |
+
devenir-trade
|
3487 |
+
devil1.
|
3488 |
+
devil2.
|
3489 |
+
devilspite
|
3490 |
+
dewelop
|
3491 |
+
dg-schoenen
|
3492 |
+
dg-shoe
|
3493 |
+
di droga
|
3494 |
+
di-droga
|
3495 |
+
diablo3
|
3496 |
+
diamox
|
3497 |
+
diary_
|
3498 |
+
diazepam
|
3499 |
+
diclofenac
|
3500 |
+
dienst.in
|
3501 |
+
diesel denim
|
3502 |
+
diesel hot
|
3503 |
+
diesel jean
|
3504 |
+
diesel uk
|
3505 |
+
diesel watch
|
3506 |
+
diesel-denim
|
3507 |
+
diesel-hot
|
3508 |
+
diesel-jean
|
3509 |
+
diesel-uk
|
3510 |
+
diesel-watch
|
3511 |
+
dieseldenim
|
3512 |
+
dieselhot
|
3513 |
+
dieselwatch
|
3514 |
+
diet-food
|
3515 |
+
diet-pill
|
3516 |
+
diet-plan
|
3517 |
+
diet-review
|
3518 |
+
diet-solution
|
3519 |
+
diet-suppl
|
3520 |
+
diet.co
|
3521 |
+
dietpill
|
3522 |
+
dietplan
|
3523 |
+
dietreview
|
3524 |
+
dietsolution
|
3525 |
+
dietsuppl
|
3526 |
+
differin
|
3527 |
+
diflucan
|
3528 |
+
diggs.us
|
3529 |
+
dincob
|
3530 |
+
dinner soup
|
3531 |
+
dinner-soup
|
3532 |
+
dior_
|
3533 |
+
diorkan
|
3534 |
+
direct-fund
|
3535 |
+
direct-health
|
3536 |
+
direct-lend
|
3537 |
+
direct-lone
|
3538 |
+
directhealth
|
3539 |
+
directlend
|
3540 |
+
directlone
|
3541 |
+
dirt-bike
|
3542 |
+
disclaim.asp
|
3543 |
+
discount bag
|
3544 |
+
discount jordan
|
3545 |
+
discount mbt
|
3546 |
+
discount mulberry
|
3547 |
+
discount nfl
|
3548 |
+
discount north
|
3549 |
+
discount ugg
|
3550 |
+
discount-
|
3551 |
+
discount-bag
|
3552 |
+
discount-cig
|
3553 |
+
discount-jordan
|
3554 |
+
discount-mbt
|
3555 |
+
discount-north
|
3556 |
+
discount-ugg
|
3557 |
+
discount-wheel
|
3558 |
+
discount.co
|
3559 |
+
discount.co.
|
3560 |
+
discount.org
|
3561 |
+
discountbag
|
3562 |
+
discountcig
|
3563 |
+
discounted north
|
3564 |
+
discounted-
|
3565 |
+
discounted-north
|
3566 |
+
discounted-wheel
|
3567 |
+
discountednorth
|
3568 |
+
discountedwheel
|
3569 |
+
discountmbt
|
3570 |
+
discountnorth
|
3571 |
+
discountt
|
3572 |
+
discountugg
|
3573 |
+
discountwheel
|
3574 |
+
diva-com
|
3575 |
+
divulgaemail
|
3576 |
+
djstool
|
3577 |
+
djtool
|
3578 |
+
dk http
|
3579 |
+
dlphone
|
3580 |
+
doable program
|
3581 |
+
doable-program
|
3582 |
+
doableprogram
|
3583 |
+
dobrucki.co
|
3584 |
+
dobrucki.pl
|
3585 |
+
doc/soap
|
3586 |
+
docid=
|
3587 |
+
doctermarten
|
3588 |
+
docteurdrebeat
|
3589 |
+
document_
|
3590 |
+
documents/celine
|
3591 |
+
documents/newbalance
|
3592 |
+
documents/nike
|
3593 |
+
documents/northface
|
3594 |
+
documents/rolex
|
3595 |
+
docxdrive
|
3596 |
+
does green
|
3597 |
+
does-green
|
3598 |
+
doesgreen
|
3599 |
+
doesn t
|
3600 |
+
dokumentov
|
3601 |
+
dokumentów
|
3602 |
+
dolce bag
|
3603 |
+
dolce-bag
|
3604 |
+
dolcebag
|
3605 |
+
dollar-service
|
3606 |
+
dollarservice
|
3607 |
+
dolphins jersey
|
3608 |
+
dolphins-jersey
|
3609 |
+
dolphinsjersey
|
3610 |
+
domainbie
|
3611 |
+
dominateseo
|
3612 |
+
domination-secret
|
3613 |
+
dominationsecret
|
3614 |
+
donna-donn
|
3615 |
+
donne-donn
|
3616 |
+
dos-seios
|
3617 |
+
dotcomsecret
|
3618 |
+
douchingteen
|
3619 |
+
doudoune
|
3620 |
+
downjacket
|
3621 |
+
download bracelet
|
3622 |
+
download-bracelet
|
3623 |
+
downloadbracelet
|
3624 |
+
doxycycline
|
3625 |
+
dragon avail
|
3626 |
+
dragon-avail
|
3627 |
+
dragons avail
|
3628 |
+
dragons-avail
|
3629 |
+
drayvera
|
3630 |
+
drdreheadphone
|
3631 |
+
dre beat
|
3632 |
+
dre cheap
|
3633 |
+
dre-beat
|
3634 |
+
dre-beats
|
3635 |
+
dre-cheap
|
3636 |
+
dre<
|
3637 |
+
drebeat
|
3638 |
+
drecheap
|
3639 |
+
dress link
|
3640 |
+
dress online
|
3641 |
+
dress shoe
|
3642 |
+
dress shop
|
3643 |
+
dress-link
|
3644 |
+
dress-online
|
3645 |
+
dress-shoe
|
3646 |
+
dress-shop
|
3647 |
+
dress.rent
|
3648 |
+
dresses.wed
|
3649 |
+
dresshop
|
3650 |
+
dresslink
|
3651 |
+
dressonline
|
3652 |
+
dresssale
|
3653 |
+
dressshop
|
3654 |
+
drivewayservice
|
3655 |
+
drmartensjapan
|
3656 |
+
drmartensjp
|
3657 |
+
drug-cheap
|
3658 |
+
drugcheap
|
3659 |
+
drugs-cheap
|
3660 |
+
drugscheap
|
3661 |
+
drupal-temp
|
3662 |
+
drupal-theme
|
3663 |
+
dsquared giubbotto
|
3664 |
+
dsquared jean
|
3665 |
+
dsquared online
|
3666 |
+
dsquared outlet
|
3667 |
+
dsquared shoe
|
3668 |
+
dsquared uomo
|
3669 |
+
dsquared-giubbotto
|
3670 |
+
dsquared-jean
|
3671 |
+
dsquared-online
|
3672 |
+
dsquared-outlet
|
3673 |
+
dsquared-shoe
|
3674 |
+
dsquared-uomo
|
3675 |
+
dsquaredonline
|
3676 |
+
dsquaredoutlet
|
3677 |
+
dsquaredshoe
|
3678 |
+
dubai-princess
|
3679 |
+
dubturbo
|
3680 |
+
dude.de
|
3681 |
+
dudes.de
|
3682 |
+
dummytest
|
3683 |
+
dunhill/dunhill
|
3684 |
+
dunjakke
|
3685 |
+
durant shoe
|
3686 |
+
durant-shoe
|
3687 |
+
duvetica outlet
|
3688 |
+
duvetica-outlet
|
3689 |
+
duveticaoutlet
|
3690 |
+
dvdrip
|
3691 |
+
dwi-attorney
|
3692 |
+
dwiattorney
|
3693 |
+
dylongfa
|
3694 |
+
dyubetika
|
3695 |
+
e-biz
|
3696 |
+
eâcute
|
3697 |
+
eairfix
|
3698 |
+
early-signs-of
|
3699 |
+
earthly lover
|
3700 |
+
earthly-lover
|
3701 |
+
ease.in
|
3702 |
+
easy.in
|
3703 |
+
easyloan
|
3704 |
+
easyrent
|
3705 |
+
eaudiovideo
|
3706 |
+
ebaypic
|
3707 |
+
ebook-reader-test
|
3708 |
+
ebook-test
|
3709 |
+
ebookreadertest
|
3710 |
+
ebooktest
|
3711 |
+
ecco out
|
3712 |
+
ecco-out
|
3713 |
+
eccooutlet
|
3714 |
+
ecent yeas
|
3715 |
+
ed-in-men
|
3716 |
+
eemail
|
3717 |
+
effexor
|
3718 |
+
egoodshop
|
3719 |
+
einkommen
|
3720 |
+
ejaculation-pharm
|
3721 |
+
ejaculationpharm
|
3722 |
+
el-gordo.c
|
3723 |
+
elamale
|
3724 |
+
elavil
|
3725 |
+
elite jersey
|
3726 |
+
elite model
|
3727 |
+
elite-jersey
|
3728 |
+
elite-men
|
3729 |
+
elite-model
|
3730 |
+
elitejersey
|
3731 |
+
elitemodel
|
3732 |
+
eloans
|
3733 |
+
elway-jersey
|
3734 |
+
elwayjersey
|
3735 |
+
email.htm
|
3736 |
+
email.tst
|
3737 |
+
emailsvip
|
3738 |
+
emailvip
|
3739 |
+
emarketing
|
3740 |
+
emiliopucci
|
3741 |
+
empire hack
|
3742 |
+
empire-hack
|
3743 |
+
empirehack
|
3744 |
+
empower network
|
3745 |
+
empower-network
|
3746 |
+
empowernetwork
|
3747 |
+
en/formula
|
3748 |
+
en/oakley
|
3749 |
+
endlaved
|
3750 |
+
eneugh
|
3751 |
+
eng/faq
|
3752 |
+
enhance-your
|
3753 |
+
enhancement-pill
|
3754 |
+
enhancementpill
|
3755 |
+
enjoy-more
|
3756 |
+
enourmous
|
3757 |
+
entry_
|
3758 |
+
entrykey
|
3759 |
+
entryview.asp
|
3760 |
+
envisionforce
|
3761 |
+
eomarketplace
|
3762 |
+
ephedra
|
3763 |
+
ephedrine
|
3764 |
+
epica watch
|
3765 |
+
epica-watch
|
3766 |
+
epo doping
|
3767 |
+
eqbandz
|
3768 |
+
equipment-manufactur
|
3769 |
+
era mlb
|
3770 |
+
era nba
|
3771 |
+
era nhl
|
3772 |
+
era uk
|
3773 |
+
era-mlb
|
3774 |
+
era-nba
|
3775 |
+
era-nfl
|
3776 |
+
era-nhl
|
3777 |
+
era-uk
|
3778 |
+
erectile
|
3779 |
+
erettile
|
3780 |
+
erjersey.co
|
3781 |
+
erjersey.net
|
3782 |
+
erolove
|
3783 |
+
erotic toy
|
3784 |
+
erotic-toy
|
3785 |
+
erotictoy
|
3786 |
+
erotik
|
3787 |
+
erotyczna
|
3788 |
+
errу
|
3789 |
+
es.iodress
|
3790 |
+
es/content
|
3791 |
+
escitalopram
|
3792 |
+
escort-zone
|
3793 |
+
escorts.
|
3794 |
+
escortss
|
3795 |
+
escortzone
|
3796 |
+
eshop.co
|
3797 |
+
essay-empire
|
3798 |
+
essay-service
|
3799 |
+
essayempire
|
3800 |
+
essays-empire
|
3801 |
+
essays-service
|
3802 |
+
essaysempire
|
3803 |
+
essayservice
|
3804 |
+
essaysservice
|
3805 |
+
estate pro
|
3806 |
+
estate whether
|
3807 |
+
estate-pro
|
3808 |
+
estate-whether
|
3809 |
+
estatepro
|
3810 |
+
estradiol
|
3811 |
+
etherdq
|
3812 |
+
euro-million
|
3813 |
+
euroditalog
|
3814 |
+
europe nfl
|
3815 |
+
eurovids
|
3816 |
+
evelyne bag
|
3817 |
+
evelyne-bag
|
3818 |
+
evelynebag
|
3819 |
+
event_
|
3820 |
+
eventid
|
3821 |
+
every advertise
|
3822 |
+
every1bet
|
3823 |
+
everythink
|
3824 |
+
evryday
|
3825 |
+
evеr
|
3826 |
+
exboyfriend
|
3827 |
+
excelent
|
3828 |
+
excellent blog
|
3829 |
+
excellent site
|
3830 |
+
excellent website
|
3831 |
+
excellent-blog
|
3832 |
+
excellent-site
|
3833 |
+
excellent-website
|
3834 |
+
excellentlunch
|
3835 |
+
exclusive rendez
|
3836 |
+
exclusive-rendez
|
3837 |
+
exclusive.ru
|
3838 |
+
executive search
|
3839 |
+
executive-search
|
3840 |
+
exelon
|
3841 |
+
exercice
|
3842 |
+
exgirlfriend
|
3843 |
+
exit.asp
|
3844 |
+
expensive vacation
|
3845 |
+
expensive-vacation
|
3846 |
+
expensivevacation
|
3847 |
+
expert suggestion
|
3848 |
+
expert-suggestion
|
3849 |
+
explosive growth
|
3850 |
+
explosive-growth
|
3851 |
+
express index
|
3852 |
+
express-index
|
3853 |
+
expressindex
|
3854 |
+
extra gry
|
3855 |
+
extreme-sport
|
3856 |
+
extremely}
|
3857 |
+
eyeglass sale
|
3858 |
+
eyeglass-sale
|
3859 |
+
eyeglasses sale
|
3860 |
+
eyeglasses-sale
|
3861 |
+
eyeglasssale
|
3862 |
+
eyеs
|
3863 |
+
eѕcort
|
3864 |
+
eхperienc
|
3865 |
+
fa‡on
|
3866 |
+
faar more
|
3867 |
+
faar-more
|
3868 |
+
fabulous drug
|
3869 |
+
fabulous-drug
|
3870 |
+
fabulousdrug
|
3871 |
+
face denali
|
3872 |
+
face jacket
|
3873 |
+
face out
|
3874 |
+
face sale
|
3875 |
+
face store
|
3876 |
+
face terra
|
3877 |
+
face vest
|
3878 |
+
face women
|
3879 |
+
face-denali
|
3880 |
+
face-jacket
|
3881 |
+
face-out
|
3882 |
+
face-sale
|
3883 |
+
face-store
|
3884 |
+
face-terra
|
3885 |
+
face-vest
|
3886 |
+
face-women
|
3887 |
+
facebok
|
3888 |
+
facebook advert
|
3889 |
+
facebook cash
|
3890 |
+
facebook class
|
3891 |
+
facebook-ads
|
3892 |
+
facebook-advert
|
3893 |
+
facebook-cash
|
3894 |
+
facebook-class
|
3895 |
+
facebook-fan
|
3896 |
+
facebook-traffic
|
3897 |
+
facebookads
|
3898 |
+
facebookadvert
|
3899 |
+
facebookcash
|
3900 |
+
facebookclass
|
3901 |
+
facebookfan
|
3902 |
+
facebooklike
|
3903 |
+
facebooku
|
3904 |
+
facejacket
|
3905 |
+
faceoutlet
|
3906 |
+
facesale
|
3907 |
+
facestore
|
3908 |
+
faceterra
|
3909 |
+
facevest
|
3910 |
+
facialhair
|
3911 |
+
factory outlet
|
3912 |
+
factory-out
|
3913 |
+
factory-outlet
|
3914 |
+
facts-about
|
3915 |
+
fagance
|
3916 |
+
fajki
|
3917 |
+
fajna strona
|
3918 |
+
fajna-fotka
|
3919 |
+
fajna-strona
|
3920 |
+
fajnafotka
|
3921 |
+
fajnastrona
|
3922 |
+
fajne
|
3923 |
+
fake mirror
|
3924 |
+
fake oakley
|
3925 |
+
fake rayban
|
3926 |
+
fake sunglass
|
3927 |
+
fake-converse
|
3928 |
+
fake-mirror
|
3929 |
+
fake-oakley
|
3930 |
+
fake-rayban
|
3931 |
+
fake-sunglass
|
3932 |
+
fakeconverse
|
3933 |
+
fakeoakley
|
3934 |
+
fakeok
|
3935 |
+
fakerayban
|
3936 |
+
fakesunglass
|
3937 |
+
falsedoc
|
3938 |
+
falsepassport
|
3939 |
+
fanshome
|
3940 |
+
fantastic blog
|
3941 |
+
fantastic-blog
|
3942 |
+
farmacias
|
3943 |
+
farming-secrets
|
3944 |
+
farmingsecrets
|
3945 |
+
fashion list
|
3946 |
+
fashion store
|
3947 |
+
fashion-boot
|
3948 |
+
fashion-bracelet
|
3949 |
+
fashion-class
|
3950 |
+
fashion-list
|
3951 |
+
fashion-store
|
3952 |
+
fashionboot
|
3953 |
+
fashionbracelet
|
3954 |
+
fashionistblog
|
3955 |
+
fast-loan
|
3956 |
+
fast|quick
|
3957 |
+
fastcash
|
3958 |
+
fastidious data
|
3959 |
+
fastidious thought
|
3960 |
+
fastidious urg
|
3961 |
+
fastidious-data
|
3962 |
+
fastidious-thought
|
3963 |
+
fastidious-urg
|
3964 |
+
fastloan
|
3965 |
+
fat loss
|
3966 |
+
fat men
|
3967 |
+
fat quite
|
3968 |
+
fat women
|
3969 |
+
fat-burn
|
3970 |
+
fat-loss
|
3971 |
+
fat-men
|
3972 |
+
fat-quite
|
3973 |
+
fat-women
|
3974 |
+
fatburn
|
3975 |
+
fatloss
|
3976 |
+
favorite website
|
3977 |
+
fb-ads
|
3978 |
+
fb-cash
|
3979 |
+
fb-traffic
|
3980 |
+
fbads
|
3981 |
+
fbcash
|
3982 |
+
fbfans
|
3983 |
+
fblike
|
3984 |
+
fckt
|
3985 |
+
fcukfcuk
|
3986 |
+
features.cfm
|
3987 |
+
federl
|
3988 |
+
feelng
|
3989 |
+
feichang0
|
3990 |
+
feihuang0
|
3991 |
+
felpe hollister
|
3992 |
+
felpe moncler
|
3993 |
+
felpe-hollister
|
3994 |
+
felpe-moncler
|
3995 |
+
felpemoncler
|
3996 |
+
female handbag
|
3997 |
+
female-handbag
|
3998 |
+
femalehandbag
|
3999 |
+
females handbag
|
4000 |
+
females-handbag
|
4001 |
+
femaleshandbag
|
4002 |
+
femme chaussure
|
4003 |
+
femme-chaussure
|
4004 |
+
femme-sac
|
4005 |
+
femmechaussure
|
4006 |
+
femmes-canada-goose
|
4007 |
+
femmesac
|
4008 |
+
femmescanadagoose
|
4009 |
+
fendi belt
|
4010 |
+
fendi-belt
|
4011 |
+
fendi1
|
4012 |
+
fendi2
|
4013 |
+
fendibelt
|
4014 |
+
fenoma
|
4015 |
+
fenteetum
|
4016 |
+
ferra-gamo
|
4017 |
+
ferragamo sale
|
4018 |
+
ferragamo tie
|
4019 |
+
ferragamo-sale
|
4020 |
+
ferragamo-tie
|
4021 |
+
ferragamolove
|
4022 |
+
ferragamosale
|
4023 |
+
ferragamoshop
|
4024 |
+
ferragamotie
|
4025 |
+
fg xpress
|
4026 |
+
fg-xpress
|
4027 |
+
fgxpress
|
4028 |
+
fibromyalgia
|
4029 |
+
fifa ultimate
|
4030 |
+
fifa-ultimate
|
4031 |
+
fifaultimate
|
4032 |
+
fightmark
|
4033 |
+
filenamedat
|
4034 |
+
filenamesdat
|
4035 |
+
filestube
|
4036 |
+
film porn
|
4037 |
+
film porno
|
4038 |
+
film x
|
4039 |
+
film-porn
|
4040 |
+
film-porno
|
4041 |
+
film-x
|
4042 |
+
filmizle
|
4043 |
+
films porn
|
4044 |
+
films x
|
4045 |
+
films-porn
|
4046 |
+
films-x
|
4047 |
+
finance-
|
4048 |
+
finance-blog
|
4049 |
+
financial debt
|
4050 |
+
financial_
|
4051 |
+
financial-debt
|
4052 |
+
financial-emergency
|
4053 |
+
financial-service
|
4054 |
+
financialservice
|
4055 |
+
finanse
|
4056 |
+
finansowanie
|
4057 |
+
finasteride
|
4058 |
+
find-the-answer
|
4059 |
+
findarticle
|
4060 |
+
findmewom
|
4061 |
+
fine wives
|
4062 |
+
fine-wives
|
4063 |
+
finewives
|
4064 |
+
fioricet
|
4065 |
+
firefox-setting
|
4066 |
+
firefoxik.ru
|
4067 |
+
firefoxsetting
|
4068 |
+
firm.ru
|
4069 |
+
firma.php
|
4070 |
+
fitch gilet
|
4071 |
+
fitch outlet
|
4072 |
+
fitch-gilet
|
4073 |
+
fitch-outlet
|
4074 |
+
fitchgilet
|
4075 |
+
fitchoutlet
|
4076 |
+
fitflop
|
4077 |
+
fivestardoll
|
4078 |
+
fix-credit
|
4079 |
+
fixcredit
|
4080 |
+
fixing-credit
|
4081 |
+
fixingcredit
|
4082 |
+
fjrm
|
4083 |
+
flagyl
|
4084 |
+
flappy-bird
|
4085 |
+
flappybird
|
4086 |
+
flats.webeden
|
4087 |
+
flexglobal
|
4088 |
+
flik.us
|
4089 |
+
flixya
|
4090 |
+
floridaflee
|
4091 |
+
floxacin
|
4092 |
+
fluccun
|
4093 |
+
fluconazole
|
4094 |
+
fluoxetine
|
4095 |
+
fluticasone
|
4096 |
+
fobur.in
|
4097 |
+
foodpyramid
|
4098 |
+
foolproof trick
|
4099 |
+
foolproof-trick
|
4100 |
+
foot nike
|
4101 |
+
foot-nike
|
4102 |
+
football shirt
|
4103 |
+
football-shirt
|
4104 |
+
footdiscount
|
4105 |
+
footwear jordan
|
4106 |
+
footwear mbt
|
4107 |
+
footwear-jordan
|
4108 |
+
footwear-mbt
|
4109 |
+
footwearmbt
|
4110 |
+
footwears
|
4111 |
+
for cheap
|
4112 |
+
for gucci
|
4113 |
+
for-cheap
|
4114 |
+
for-gucci
|
4115 |
+
for-interactive
|
4116 |
+
for-men
|
4117 |
+
for-money
|
4118 |
+
for-the-most
|
4119 |
+
for-windows-8
|
4120 |
+
for-your-need
|
4121 |
+
for+sale
|
4122 |
+
for|
|
4123 |
+
forboots
|
4124 |
+
forcheap
|
4125 |
+
forex
|
4126 |
+
forfree
|
4127 |
+
forgucci
|
4128 |
+
forhandlere
|
4129 |
+
forjp.co
|
4130 |
+
formaldress
|
4131 |
+
formula replica
|
4132 |
+
formula-replica
|
4133 |
+
forsale-japan
|
4134 |
+
forsalego
|
4135 |
+
forsalejapan
|
4136 |
+
forsales
|
4137 |
+
forthcoming post
|
4138 |
+
forthcoming-post
|
4139 |
+
forum coach
|
4140 |
+
forum-coach
|
4141 |
+
forum.asp
|
4142 |
+
forum.php
|
4143 |
+
forum/1/topic
|
4144 |
+
forum/ftopic
|
4145 |
+
forum/member
|
4146 |
+
forum/post
|
4147 |
+
forum/topic
|
4148 |
+
forum/user
|
4149 |
+
forums?func
|
4150 |
+
forums/1/topic
|
4151 |
+
forums/member
|
4152 |
+
forums/topic
|
4153 |
+
forums/user
|
4154 |
+
forwindows8
|
4155 |
+
foryou.co
|
4156 |
+
forzest
|
4157 |
+
fr canad
|
4158 |
+
fr-canad
|
4159 |
+
fr.fr/
|
4160 |
+
fr/acheter
|
4161 |
+
fr/botte
|
4162 |
+
fr/canad
|
4163 |
+
fr/costume
|
4164 |
+
fr/longchamp
|
4165 |
+
fr/pascher
|
4166 |
+
fradidas
|
4167 |
+
frames/index
|
4168 |
+
francemaillot
|
4169 |
+
fraudcenter
|
4170 |
+
frauen puma
|
4171 |
+
frauen-puma
|
4172 |
+
frauenpuma
|
4173 |
+
free class
|
4174 |
+
free gay
|
4175 |
+
free international
|
4176 |
+
free prescript
|
4177 |
+
free visitor
|
4178 |
+
free web
|
4179 |
+
free-bbs
|
4180 |
+
free-bid
|
4181 |
+
free-brows
|
4182 |
+
free-casino
|
4183 |
+
free-class
|
4184 |
+
free-gay
|
4185 |
+
free-international
|
4186 |
+
free-ipad
|
4187 |
+
free-iphone
|
4188 |
+
free-ipod
|
4189 |
+
free-mods
|
4190 |
+
free-movie
|
4191 |
+
free-offer
|
4192 |
+
free-online
|
4193 |
+
free-poker
|
4194 |
+
free-prescript
|
4195 |
+
free-program
|
4196 |
+
free-web
|
4197 |
+
free-website
|
4198 |
+
free.in
|
4199 |
+
freearticle
|
4200 |
+
freebbs
|
4201 |
+
freebid
|
4202 |
+
freebrows
|
4203 |
+
freecasino
|
4204 |
+
freeclass
|
4205 |
+
freedating
|
4206 |
+
freefor.co
|
4207 |
+
freegay
|
4208 |
+
freehub
|
4209 |
+
freeinternational
|
4210 |
+
freeipad
|
4211 |
+
freeiphone
|
4212 |
+
freeipod
|
4213 |
+
freembtrans
|
4214 |
+
freemovie
|
4215 |
+
freeoffer
|
4216 |
+
freeonline
|
4217 |
+
freepoker
|
4218 |
+
freesale
|
4219 |
+
freesalg
|
4220 |
+
freesimcard
|
4221 |
+
freeslotmachine
|
4222 |
+
freevideo
|
4223 |
+
freeweb
|
4224 |
+
freewebsite
|
4225 |
+
french escort
|
4226 |
+
french-escort
|
4227 |
+
frenchescort
|
4228 |
+
fresh review
|
4229 |
+
fresh-review
|
4230 |
+
freshreview
|
4231 |
+
freshwaterpearl
|
4232 |
+
friday moncler
|
4233 |
+
friday sale
|
4234 |
+
friday ugg
|
4235 |
+
friday-moncler
|
4236 |
+
friday-sale
|
4237 |
+
friday-ugg
|
4238 |
+
fridaymoncler
|
4239 |
+
fridaysale
|
4240 |
+
fridayugg
|
4241 |
+
frlongchamp
|
4242 |
+
frmoncler
|
4243 |
+
frontline commando
|
4244 |
+
frontline-commando
|
4245 |
+
fruitful design
|
4246 |
+
fruitful-design
|
4247 |
+
fruta planta
|
4248 |
+
frutaplanta
|
4249 |
+
fuckdown
|
4250 |
+
func.php
|
4251 |
+
fund http
|
4252 |
+
fund market
|
4253 |
+
fund trend
|
4254 |
+
fund-market
|
4255 |
+
fund-trend
|
4256 |
+
fundmarket
|
4257 |
+
funds.ru
|
4258 |
+
funsneak
|
4259 |
+
funwithwindows
|
4260 |
+
fur boot
|
4261 |
+
fur-boot
|
4262 |
+
furboot
|
4263 |
+
furiousguy
|
4264 |
+
furla bag
|
4265 |
+
furla candy
|
4266 |
+
furla handbag
|
4267 |
+
furla out
|
4268 |
+
furla-bag
|
4269 |
+
furla-candy
|
4270 |
+
furla-handbag
|
4271 |
+
furla-out
|
4272 |
+
furlahandbag
|
4273 |
+
furlasacs
|
4274 |
+
furnituresale
|
4275 |
+
furosemide
|
4276 |
+
furworld.ru
|
4277 |
+
futbol barcelona
|
4278 |
+
futbol-barcelona
|
4279 |
+
futbolbarcelona
|
4280 |
+
futuristic-market
|
4281 |
+
futuristicmarket
|
4282 |
+
f眉r
|
4283 |
+
g-string
|
4284 |
+
gaaab.co
|
4285 |
+
gabapentin
|
4286 |
+
gabbana store
|
4287 |
+
gabbana-cheap
|
4288 |
+
gabbana-shop
|
4289 |
+
gabbana-store
|
4290 |
+
gabbanacheap
|
4291 |
+
gabbanashop
|
4292 |
+
gabbanastore
|
4293 |
+
gafas ray
|
4294 |
+
gafas-ray
|
4295 |
+
gafasray
|
4296 |
+
gaga-japan
|
4297 |
+
gaga-jp
|
4298 |
+
gaga-milano
|
4299 |
+
gagner
|
4300 |
+
gain weight
|
4301 |
+
gain-weight
|
4302 |
+
gainweight
|
4303 |
+
galaxynail
|
4304 |
+
gallergrind
|
4305 |
+
gambling online
|
4306 |
+
gambling-online
|
4307 |
+
gamblingonline
|
4308 |
+
game wiki
|
4309 |
+
game-casino
|
4310 |
+
game-copy
|
4311 |
+
game-jersey
|
4312 |
+
game-wiki
|
4313 |
+
gamecopy
|
4314 |
+
gamedesigndegree
|
4315 |
+
gamegame
|
4316 |
+
games-casino
|
4317 |
+
gamewiki
|
4318 |
+
gamma blue
|
4319 |
+
gamma-blue
|
4320 |
+
gammablue
|
4321 |
+
gamyba
|
4322 |
+
gangprofil
|
4323 |
+
ganhar dinheiro
|
4324 |
+
ganhar-dinheiro
|
4325 |
+
gaogb
|
4326 |
+
gapscent
|
4327 |
+
garcinia
|
4328 |
+
gawab.com
|
4329 |
+
gay sex
|
4330 |
+
gay-sex
|
4331 |
+
gaysex
|
4332 |
+
gayusa
|
4333 |
+
gelatine free
|
4334 |
+
gelatine-free
|
4335 |
+
gemorroya
|
4336 |
+
genemy
|
4337 |
+
general/genera
|
4338 |
+
generate cash
|
4339 |
+
generate money
|
4340 |
+
generate-cash
|
4341 |
+
generate-money
|
4342 |
+
generatecash
|
4343 |
+
generatemoney
|
4344 |
+
generating cash
|
4345 |
+
generating money
|
4346 |
+
generating-cash
|
4347 |
+
generating-money
|
4348 |
+
generatingcash
|
4349 |
+
generatingmoney
|
4350 |
+
generation algorithm
|
4351 |
+
generation-algorithm
|
4352 |
+
generator-2014
|
4353 |
+
generator2014
|
4354 |
+
generatorpro
|
4355 |
+
genuine-pandora
|
4356 |
+
genuinely fast
|
4357 |
+
genuinely fruit
|
4358 |
+
genuinely-fast
|
4359 |
+
genuinely-fruit
|
4360 |
+
genuinepandora
|
4361 |
+
germany jersey
|
4362 |
+
germany-jersey
|
4363 |
+
germanylove
|
4364 |
+
gestione
|
4365 |
+
get_rid_of
|
4366 |
+
get-boot
|
4367 |
+
get-facebook
|
4368 |
+
get-hermes
|
4369 |
+
get-massive
|
4370 |
+
get-money-for
|
4371 |
+
get-rid-of
|
4372 |
+
get-the-answer
|
4373 |
+
getaloan
|
4374 |
+
getastyle
|
4375 |
+
gethermes
|
4376 |
+
getjoy
|
4377 |
+
getmassive
|
4378 |
+
getridof
|
4379 |
+
getting-men
|
4380 |
+
gettranslate
|
4381 |
+
getyou.asp
|
4382 |
+
gfband
|
4383 |
+
ghd gold
|
4384 |
+
ghd straight
|
4385 |
+
ghd-gold
|
4386 |
+
ghd-pascher
|
4387 |
+
ghd-straight
|
4388 |
+
ghdgold
|
4389 |
+
ghdpascher
|
4390 |
+
ghdstraight
|
4391 |
+
ghduk
|
4392 |
+
giants-shop
|
4393 |
+
giantsjersey
|
4394 |
+
giantsshop
|
4395 |
+
gifts-singapore
|
4396 |
+
giftsingapore
|
4397 |
+
giftssingapore
|
4398 |
+
gigantix.co
|
4399 |
+
gilet moncler
|
4400 |
+
gilet-moncler
|
4401 |
+
giletmoncler
|
4402 |
+
girl escort
|
4403 |
+
girl jordan
|
4404 |
+
girl-day-dress
|
4405 |
+
girl-escort
|
4406 |
+
girl-jordan
|
4407 |
+
girl-jp
|
4408 |
+
girldaydress
|
4409 |
+
girlescort
|
4410 |
+
girlie spouse
|
4411 |
+
girlie-spouse
|
4412 |
+
girliespouse
|
4413 |
+
girljordan
|
4414 |
+
girljp
|
4415 |
+
girls escort
|
4416 |
+
girls-day-dress
|
4417 |
+
girls-escort
|
4418 |
+
girlsdaydress
|
4419 |
+
girlsescort
|
4420 |
+
giubbotti woolrich
|
4421 |
+
giubbotti-woolrich
|
4422 |
+
giubbotto dsquared
|
4423 |
+
giubbotto-dsquared
|
4424 |
+
giuseppezanotti
|
4425 |
+
gkhk
|
4426 |
+
glamorousbag
|
4427 |
+
glasses-tokyo
|
4428 |
+
glassess
|
4429 |
+
glassestokyo
|
4430 |
+
gleevec
|
4431 |
+
glitter ugg
|
4432 |
+
glitter-ugg
|
4433 |
+
glitterugg
|
4434 |
+
global-agenda
|
4435 |
+
globalagenda
|
4436 |
+
globalist-agenda
|
4437 |
+
globalistagenda
|
4438 |
+
globalnpn
|
4439 |
+
glucophage
|
4440 |
+
glutamina
|
4441 |
+
glyburide
|
4442 |
+
gmaiil
|
4443 |
+
gneuienly
|
4444 |
+
gnlaser
|
4445 |
+
goedkoop
|
4446 |
+
gointeractive.co
|
4447 |
+
gojp.co
|
4448 |
+
gold-account
|
4449 |
+
gold-coin
|
4450 |
+
gold-earring
|
4451 |
+
gold-essay
|
4452 |
+
gold-ingot
|
4453 |
+
gold-jewelry
|
4454 |
+
gold-price
|
4455 |
+
gold-seiko
|
4456 |
+
gold.ru
|
4457 |
+
goldbarren
|
4458 |
+
goldcoin
|
4459 |
+
goldendoll
|
4460 |
+
goldessay
|
4461 |
+
goldgeek
|
4462 |
+
goldingot
|
4463 |
+
goldjewelry
|
4464 |
+
goldseiko
|
4465 |
+
goldsuppl
|
4466 |
+
goldtruth
|
4467 |
+
golf-promo
|
4468 |
+
golf-shop
|
4469 |
+
golfplaza
|
4470 |
+
golfpromo
|
4471 |
+
golfs
|
4472 |
+
gomaile.co
|
4473 |
+
goo.gl
|
4474 |
+
good article
|
4475 |
+
good blog
|
4476 |
+
good-article
|
4477 |
+
good-blog
|
4478 |
+
good-for-
|
4479 |
+
good-game
|
4480 |
+
good}
|
4481 |
+
goodbye.asp
|
4482 |
+
goodgame
|
4483 |
+
goodnessknows
|
4484 |
+
goodsblog
|
4485 |
+
google http
|
4486 |
+
google_
|
4487 |
+
google-java
|
4488 |
+
googlebind
|
4489 |
+
googleing
|
4490 |
+
googleusashop
|
4491 |
+
goose chill
|
4492 |
+
goose coat
|
4493 |
+
goose enfant
|
4494 |
+
goose expedition
|
4495 |
+
goose femme
|
4496 |
+
goose grise
|
4497 |
+
goose herre
|
4498 |
+
goose homme
|
4499 |
+
goose ital
|
4500 |
+
goose jacka
|
4501 |
+
goose jacke
|
4502 |
+
goose jakke
|
4503 |
+
goose jas
|
4504 |
+
goose norge
|
4505 |
+
goose online
|
4506 |
+
goose out
|
4507 |
+
goose paris
|
4508 |
+
goose parka
|
4509 |
+
goose pas
|
4510 |
+
goose retail
|
4511 |
+
goose sale
|
4512 |
+
goose v
|
4513 |
+
goose yorkville
|
4514 |
+
goose youth
|
4515 |
+
goose-canad
|
4516 |
+
goose-coat
|
4517 |
+
goose-enfant
|
4518 |
+
goose-expedition
|
4519 |
+
goose-femme
|
4520 |
+
goose-grise
|
4521 |
+
goose-herre
|
4522 |
+
goose-homme
|
4523 |
+
goose-ital
|
4524 |
+
goose-jacka
|
4525 |
+
goose-jacke
|
4526 |
+
goose-jakke
|
4527 |
+
goose-jas
|
4528 |
+
goose-norge
|
4529 |
+
goose-online
|
4530 |
+
goose-out
|
4531 |
+
goose-paris
|
4532 |
+
goose-parka
|
4533 |
+
goose-pas
|
4534 |
+
goose-retail
|
4535 |
+
goose-sale
|
4536 |
+
goose-v
|
4537 |
+
goose-vest
|
4538 |
+
goose-yorkville
|
4539 |
+
goose-youth
|
4540 |
+
goose<
|
4541 |
+
gooseca
|
4542 |
+
goosecanad
|
4543 |
+
goosecheap
|
4544 |
+
goosecoat
|
4545 |
+
goosedk
|
4546 |
+
gooseenfant
|
4547 |
+
gooseexpedition
|
4548 |
+
goosefemme
|
4549 |
+
goosegrise
|
4550 |
+
gooseherre
|
4551 |
+
goosehomme
|
4552 |
+
gooseital
|
4553 |
+
goosejacka
|
4554 |
+
goosejacke
|
4555 |
+
goosejakke
|
4556 |
+
goosejas
|
4557 |
+
goosenorge
|
4558 |
+
gooseonline
|
4559 |
+
gooseoutlet
|
4560 |
+
gooseparis
|
4561 |
+
gooseparka
|
4562 |
+
goosepas
|
4563 |
+
gooseretail
|
4564 |
+
goosesale
|
4565 |
+
goosescheap
|
4566 |
+
gooseshop
|
4567 |
+
goosevest
|
4568 |
+
gooseyorkville
|
4569 |
+
gooseyouth
|
4570 |
+
gorgeous escort
|
4571 |
+
gorgeous-escort
|
4572 |
+
gorgeousescort
|
4573 |
+
gosgov
|
4574 |
+
goshop.
|
4575 |
+
gotowkowa
|
4576 |
+
gotowkowe
|
4577 |
+
gown-love
|
4578 |
+
gownlove
|
4579 |
+
gowns-love
|
4580 |
+
gownslove
|
4581 |
+
goyard-bag
|
4582 |
+
goyard-online
|
4583 |
+
goyardbag
|
4584 |
+
goyardonline
|
4585 |
+
graduand
|
4586 |
+
gratuit http
|
4587 |
+
gratuit roulette
|
4588 |
+
gratuit-roulette
|
4589 |
+
gratuite http
|
4590 |
+
gratuitos
|
4591 |
+
graypanther
|
4592 |
+
grayson bag
|
4593 |
+
grayson-bag
|
4594 |
+
great article
|
4595 |
+
great blog
|
4596 |
+
great goods
|
4597 |
+
great written
|
4598 |
+
great-article
|
4599 |
+
great-blog
|
4600 |
+
great-essay
|
4601 |
+
great-goods
|
4602 |
+
great-things
|
4603 |
+
great-written
|
4604 |
+
great}
|
4605 |
+
greatbet
|
4606 |
+
greece-holid
|
4607 |
+
greeceholid
|
4608 |
+
green-smoker
|
4609 |
+
greensmoker
|
4610 |
+
greеce
|
4611 |
+
grise parka
|
4612 |
+
grise-parka
|
4613 |
+
griseofulvin
|
4614 |
+
griseparka
|
4615 |
+
grooming needs
|
4616 |
+
grooming-needs
|
4617 |
+
grossrx
|
4618 |
+
group_
|
4619 |
+
group-home
|
4620 |
+
group-review
|
4621 |
+
grow-cannabis
|
4622 |
+
growmens
|
4623 |
+
growth hormone
|
4624 |
+
growth-hormone
|
4625 |
+
growthhormone
|
4626 |
+
gruppmeddelanden
|
4627 |
+
gruzowe
|
4628 |
+
gruzu
|
4629 |
+
gry flesh
|
4630 |
+
gry online
|
4631 |
+
guarantee_
|
4632 |
+
guarantee-uptime
|
4633 |
+
guaranteed_
|
4634 |
+
guaranteed-uptime
|
4635 |
+
gucchi
|
4636 |
+
gucci bag
|
4637 |
+
gucci brief
|
4638 |
+
gucci discount
|
4639 |
+
gucci envy
|
4640 |
+
gucci factory
|
4641 |
+
gucci gucci
|
4642 |
+
gucci guilt
|
4643 |
+
gucci handbag
|
4644 |
+
gucci italia
|
4645 |
+
gucci online
|
4646 |
+
gucci out
|
4647 |
+
gucci sale
|
4648 |
+
gucci seller
|
4649 |
+
gucci time
|
4650 |
+
gucci vintage
|
4651 |
+
gucci_
|
4652 |
+
gucci--
|
4653 |
+
gucci-bag
|
4654 |
+
gucci-brief
|
4655 |
+
gucci-discount
|
4656 |
+
gucci-envy
|
4657 |
+
gucci-factory
|
4658 |
+
gucci-glass
|
4659 |
+
gucci-gucci
|
4660 |
+
gucci-guilt
|
4661 |
+
gucci-handbag
|
4662 |
+
gucci-italia
|
4663 |
+
gucci-online
|
4664 |
+
gucci-out
|
4665 |
+
gucci-purse
|
4666 |
+
gucci-replica
|
4667 |
+
gucci-sale
|
4668 |
+
gucci-seller
|
4669 |
+
gucci-time
|
4670 |
+
gucci-uk
|
4671 |
+
gucci-vintage
|
4672 |
+
gucci-you
|
4673 |
+
gucci2
|
4674 |
+
guccibag
|
4675 |
+
gucciden
|
4676 |
+
guccidiscount
|
4677 |
+
guccienvy
|
4678 |
+
guccifactory
|
4679 |
+
guccifr
|
4680 |
+
gucciglass
|
4681 |
+
guccigucci
|
4682 |
+
gucciguilt
|
4683 |
+
guccihandbag
|
4684 |
+
gucciinstock
|
4685 |
+
gucciitalia
|
4686 |
+
gucciiuk
|
4687 |
+
guccij
|
4688 |
+
guccikan
|
4689 |
+
guccinose
|
4690 |
+
guccionline
|
4691 |
+
guccioutlet
|
4692 |
+
gucciparis
|
4693 |
+
guccipurse
|
4694 |
+
guccireplica
|
4695 |
+
guccisale
|
4696 |
+
gucciseller
|
4697 |
+
guccisingapore
|
4698 |
+
gucciten
|
4699 |
+
guccitime
|
4700 |
+
gucciuk
|
4701 |
+
guccivintage
|
4702 |
+
gucciyu
|
4703 |
+
guerre gratuit
|
4704 |
+
guerre http
|
4705 |
+
guerre-gratuit
|
4706 |
+
guest-post
|
4707 |
+
guestpost
|
4708 |
+
guiltfree
|
4709 |
+
guru1
|
4710 |
+
gurus1
|
4711 |
+
gyslera
|
4712 |
+
g眉nstig
|
4713 |
+
habitof
|
4714 |
+
hack facebook
|
4715 |
+
hack fb
|
4716 |
+
hack-facebook
|
4717 |
+
hack-fb
|
4718 |
+
hack<
|
4719 |
+
hackasphalt
|
4720 |
+
hackfacebook
|
4721 |
+
hackfb
|
4722 |
+
hadheard
|
4723 |
+
hair-again
|
4724 |
+
hair-grow
|
4725 |
+
hair-remov
|
4726 |
+
hair-straight
|
4727 |
+
hairagain
|
4728 |
+
hairgrow
|
4729 |
+
hairmodel
|
4730 |
+
hairremov
|
4731 |
+
hairstraight
|
4732 |
+
hamilton norge
|
4733 |
+
hamilton-norge
|
4734 |
+
handbag distrib
|
4735 |
+
handbag louis
|
4736 |
+
handbag out
|
4737 |
+
handbag sale
|
4738 |
+
handbag store
|
4739 |
+
handbag uk
|
4740 |
+
handbag wholesale
|
4741 |
+
handbag wom
|
4742 |
+
handbag-distrib
|
4743 |
+
handbag-for
|
4744 |
+
handbag-louis
|
4745 |
+
handbag-out
|
4746 |
+
handbag-sale
|
4747 |
+
handbag-store
|
4748 |
+
handbag-wholesale
|
4749 |
+
handbag-wom
|
4750 |
+
handbag+
|
4751 |
+
handbagdistrib
|
4752 |
+
handbagfor
|
4753 |
+
handbaglouis
|
4754 |
+
handbagout
|
4755 |
+
handbags distrib
|
4756 |
+
handbags louis
|
4757 |
+
handbags out
|
4758 |
+
handbags store
|
4759 |
+
handbags uk
|
4760 |
+
handbags wholesale
|
4761 |
+
handbags wom
|
4762 |
+
handbags-distrib
|
4763 |
+
handbags-for
|
4764 |
+
handbags-louis
|
4765 |
+
handbags-out
|
4766 |
+
handbags-store
|
4767 |
+
handbags-wholesale
|
4768 |
+
handbags-wom
|
4769 |
+
handbagsale
|
4770 |
+
handbagsdistrib
|
4771 |
+
handbagsfor
|
4772 |
+
handbagslouis
|
4773 |
+
handbagsout
|
4774 |
+
handbagssale
|
4775 |
+
handbagsstore
|
4776 |
+
handbagstore
|
4777 |
+
handbagsu
|
4778 |
+
handbagswholesale
|
4779 |
+
handbagswom
|
4780 |
+
handbagu
|
4781 |
+
handbagwholesale
|
4782 |
+
handbagwom
|
4783 |
+
hanging-with-friends
|
4784 |
+
hangingwithfriends
|
4785 |
+
haohao
|
4786 |
+
hardtool
|
4787 |
+
harnessedthem
|
4788 |
+
has cuisine
|
4789 |
+
has-cuisine
|
4790 |
+
hats carolina
|
4791 |
+
hats chicago
|
4792 |
+
hats denver
|
4793 |
+
hats indiana
|
4794 |
+
hats oakland
|
4795 |
+
hats-carolina
|
4796 |
+
hats-chicago
|
4797 |
+
hats-cincin
|
4798 |
+
hats-denver
|
4799 |
+
hats-indiana
|
4800 |
+
hats-new
|
4801 |
+
hats-oakland
|
4802 |
+
hatschicago
|
4803 |
+
hatsdenver
|
4804 |
+
hatsindiana
|
4805 |
+
hatsnap
|
4806 |
+
hatsoakland
|
4807 |
+
hatssnap
|
4808 |
+
hautschez
|
4809 |
+
haveasite
|
4810 |
+
havegive
|
4811 |
+
havegone
|
4812 |
+
hawksjersey
|
4813 |
+
hcg-boost
|
4814 |
+
hcgboost
|
4815 |
+
headset2012
|
4816 |
+
headset2013
|
4817 |
+
headset2014
|
4818 |
+
healthhow
|
4819 |
+
hedge fund
|
4820 |
+
hedge-fund
|
4821 |
+
heel_pads
|
4822 |
+
heelped
|
4823 |
+
heil hitler
|
4824 |
+
heil-hitler
|
4825 |
+
heilhitler
|
4826 |
+
hellllo
|
4827 |
+
helllo
|
4828 |
+
hello-sex
|
4829 |
+
hellodress
|
4830 |
+
hellosex
|
4831 |
+
help_you
|
4832 |
+
help-tax
|
4833 |
+
helpcry
|
4834 |
+
helpful-information
|
4835 |
+
helpful-method
|
4836 |
+
helplink.asp
|
4837 |
+
hemorroide
|
4838 |
+
hence choose
|
4839 |
+
hentai
|
4840 |
+
herbal tincture
|
4841 |
+
herbal-medicin
|
4842 |
+
herbal-smoking
|
4843 |
+
herbal-tincture
|
4844 |
+
herbalmedicin
|
4845 |
+
herbalsmoking
|
4846 |
+
herbaltincture
|
4847 |
+
hermes austr
|
4848 |
+
hermes bag
|
4849 |
+
hermes belt
|
4850 |
+
hermes couch
|
4851 |
+
hermes evelyne
|
4852 |
+
hermes factory
|
4853 |
+
hermes handbag
|
4854 |
+
hermes official
|
4855 |
+
hermes out
|
4856 |
+
hermes scarve
|
4857 |
+
hermes store
|
4858 |
+
hermes uk
|
4859 |
+
hermes wallet
|
4860 |
+
hermes xl
|
4861 |
+
hermes-bag
|
4862 |
+
hermes-belt
|
4863 |
+
hermes-couch
|
4864 |
+
hermes-discount
|
4865 |
+
hermes-evelyne
|
4866 |
+
hermes-factory
|
4867 |
+
hermes-official
|
4868 |
+
hermes-out
|
4869 |
+
hermes-replica
|
4870 |
+
hermes-store
|
4871 |
+
hermes-uk
|
4872 |
+
hermes-wallet
|
4873 |
+
hermes-xl
|
4874 |
+
hermesbag
|
4875 |
+
hermesbelt
|
4876 |
+
hermescouch
|
4877 |
+
hermesdiscount
|
4878 |
+
hermesevelyne
|
4879 |
+
hermesfactory
|
4880 |
+
hermeshut
|
4881 |
+
hermesofficial
|
4882 |
+
hermesout
|
4883 |
+
hermesreplica
|
4884 |
+
hermesstore
|
4885 |
+
hermesuk
|
4886 |
+
hermeswallet
|
4887 |
+
hermesxl
|
4888 |
+
hernia support
|
4889 |
+
hernia surgery
|
4890 |
+
hernia-support
|
4891 |
+
hernia-surgery
|
4892 |
+
herpes infect
|
4893 |
+
herpes treatment
|
4894 |
+
herpes-infect
|
4895 |
+
herpes-treatment
|
4896 |
+
herpes<
|
4897 |
+
herren moncler
|
4898 |
+
herren timberland
|
4899 |
+
herren-moncler
|
4900 |
+
herren-timberland
|
4901 |
+
herrenmoncler
|
4902 |
+
herrentimberland
|
4903 |
+
heuer-new
|
4904 |
+
hfg.cc
|
4905 |
+
hfgfh
|
4906 |
+
hgfj
|
4907 |
+
hggh
|
4908 |
+
hgh
|
4909 |
+
hgh dopa
|
4910 |
+
hgh enhance
|
4911 |
+
hgh natural
|
4912 |
+
hgh purchase
|
4913 |
+
hgh-dopa
|
4914 |
+
hgh-enhance
|
4915 |
+
hgh-natural
|
4916 |
+
hgh-purchase
|
4917 |
+
hgh-sup
|
4918 |
+
hgher
|
4919 |
+
hghsup
|
4920 |
+
hid_
|
4921 |
+
hierbasmedicin
|
4922 |
+
high-heel
|
4923 |
+
high-profile
|
4924 |
+
high-protein
|
4925 |
+
high.cc
|
4926 |
+
highbloodpressure
|
4927 |
+
highprofile
|
4928 |
+
highprotein
|
4929 |
+
hingenieur
|
4930 |
+
hisslipper
|
4931 |
+
hitfit
|
4932 |
+
hjblog
|
4933 |
+
hleepd
|
4934 |
+
hndeds
|
4935 |
+
hogan online
|
4936 |
+
hogan out
|
4937 |
+
hogan scarpe
|
4938 |
+
hogan shoe
|
4939 |
+
hogan sito
|
4940 |
+
hogan-online
|
4941 |
+
hogan-out
|
4942 |
+
hogan-scarpe
|
4943 |
+
hogan-shoe
|
4944 |
+
hogan-sito
|
4945 |
+
hoganoutlet
|
4946 |
+
hoganshoe
|
4947 |
+
hogansito
|
4948 |
+
holdinga
|
4949 |
+
holdning
|
4950 |
+
hollister brasil
|
4951 |
+
hollister jean
|
4952 |
+
hollister lederjacke
|
4953 |
+
hollister nantes
|
4954 |
+
hollister online
|
4955 |
+
hollister pas
|
4956 |
+
hollister roma
|
4957 |
+
hollister shirt
|
4958 |
+
hollister short
|
4959 |
+
hollister sverige
|
4960 |
+
hollister swim
|
4961 |
+
hollister uk
|
4962 |
+
hollister-brasil
|
4963 |
+
hollister-deutsch
|
4964 |
+
hollister-jean
|
4965 |
+
hollister-lederjacke
|
4966 |
+
hollister-milano
|
4967 |
+
hollister-nantes
|
4968 |
+
hollister-online
|
4969 |
+
hollister-pas
|
4970 |
+
hollister-roma
|
4971 |
+
hollister-shirt
|
4972 |
+
hollister-short
|
4973 |
+
hollister-sverige
|
4974 |
+
hollister-swim
|
4975 |
+
hollister-uk
|
4976 |
+
hollisterbrasil
|
4977 |
+
hollisterdeutsch
|
4978 |
+
hollistermilano
|
4979 |
+
hollisternantes
|
4980 |
+
hollisteronline
|
4981 |
+
hollistershirt
|
4982 |
+
hollistersverige
|
4983 |
+
hollisterswim
|
4984 |
+
hollisteruk
|
4985 |
+
home-based
|
4986 |
+
home-loan
|
4987 |
+
home-remed
|
4988 |
+
homebased
|
4989 |
+
homeforsale
|
4990 |
+
homeloan
|
4991 |
+
homeremed
|
4992 |
+
homesforsale
|
4993 |
+
homme giorgio
|
4994 |
+
homme hugo
|
4995 |
+
homme solde
|
4996 |
+
homme-giorgio
|
4997 |
+
homme-hugo
|
4998 |
+
homme-solde
|
4999 |
+
hoodia
|
5000 |
+
hoodie-cheap
|
5001 |
+
hoodiecheap
|
5002 |
+
hoody-cheap
|
5003 |
+
hoodycheap
|
5004 |
+
hoolgain
|
5005 |
+
hoolz
|
5006 |
+
horoscopes
|
5007 |
+
horoskop
|
5008 |
+
horsesimul
|
5009 |
+
host.ro
|
5010 |
+
hosting community
|
5011 |
+
hosting-community
|
5012 |
+
hot tech
|
5013 |
+
hot_babe
|
5014 |
+
hot-babe
|
5015 |
+
hot-girl
|
5016 |
+
hot-love
|
5017 |
+
hot-pantie
|
5018 |
+
hot-panty
|
5019 |
+
hot-sale
|
5020 |
+
hot-tag
|
5021 |
+
hot-tags
|
5022 |
+
hot-tech
|
5023 |
+
hot.htm
|
5024 |
+
hotburberry
|
5025 |
+
hotel deal
|
5026 |
+
hotel hermes
|
5027 |
+
hotel-deal
|
5028 |
+
hotel-hermes
|
5029 |
+
hotelbritannia
|
5030 |
+
hoteldeal
|
5031 |
+
hotelhermes
|
5032 |
+
hoteli
|
5033 |
+
hotelmanchester
|
5034 |
+
hotgirl
|
5035 |
+
hotlove
|
5036 |
+
hotpantie
|
5037 |
+
hotpanty
|
5038 |
+
hotsale
|
5039 |
+
hotsunglass
|
5040 |
+
hottag
|
5041 |
+
hottest tech
|
5042 |
+
hottest update
|
5043 |
+
hottest-tech
|
5044 |
+
hottest-update
|
5045 |
+
hourpayday
|
5046 |
+
houseforsale
|
5047 |
+
housesforsale
|
5048 |
+
how_do_
|
5049 |
+
how-do-you
|
5050 |
+
how-to-buy
|
5051 |
+
how-to-clean
|
5052 |
+
how-to-creat
|
5053 |
+
how-to-get
|
5054 |
+
how-to-have
|
5055 |
+
how-to-lose
|
5056 |
+
how-to-make
|
5057 |
+
how-to-medi
|
5058 |
+
how-to-quick
|
5059 |
+
how-to-reduc
|
5060 |
+
how-to-restor
|
5061 |
+
how-to-sell
|
5062 |
+
how-to-speed
|
5063 |
+
how-to-take
|
5064 |
+
how-to-teach
|
5065 |
+
how-to-unlock
|
5066 |
+
how-to-win
|
5067 |
+
howtobuy
|
5068 |
+
howtocreat
|
5069 |
+
howtocure
|
5070 |
+
howtomake
|
5071 |
+
howtomedi
|
5072 |
+
howtoreg
|
5073 |
+
howtospeed
|
5074 |
+
howtounlock
|
5075 |
+
howtowin
|
5076 |
+
hppp
|
5077 |
+
hqsteroid
|
5078 |
+
htaccrss
|
5079 |
+
html-article
|
5080 |
+
htmllink
|
5081 |
+
htmlnew
|
5082 |
+
huay-today
|
5083 |
+
huaytoday
|
5084 |
+
hugescock
|
5085 |
+
hungurian
|
5086 |
+
huntingtexas
|
5087 |
+
huntingtx
|
5088 |
+
huperzine
|
5089 |
+
hyclate
|
5090 |
+
hydraulik-
|
5091 |
+
hydrocodone
|
5092 |
+
hydrotherapy
|
5093 |
+
hydroxatone
|
5094 |
+
hydroxy
|
5095 |
+
hyper-fb
|
5096 |
+
hyper-link
|
5097 |
+
hyperlink
|
5098 |
+
hypothyroidism
|
5099 |
+
hyzaar
|
5100 |
+
i aint
|
5101 |
+
i-aint
|
5102 |
+
i-will-be
|
5103 |
+
�
|
5104 |
+
i2g
|
5105 |
+
ia€?ll
|
5106 |
+
iamimports
|
5107 |
+
icon/set
|
5108 |
+
icons/set
|
5109 |
+
idanmark
|
5110 |
+
ideea
|
5111 |
+
ifyou
|
5112 |
+
im not
|
5113 |
+
im-not
|
5114 |
+
image-old
|
5115 |
+
image/cache
|
5116 |
+
image/image
|
5117 |
+
image/index
|
5118 |
+
image/old
|
5119 |
+
image/table
|
5120 |
+
image/ugg
|
5121 |
+
images-old
|
5122 |
+
images/cache
|
5123 |
+
images/celine
|
5124 |
+
images/image
|
5125 |
+
images/index
|
5126 |
+
images/newbalance
|
5127 |
+
images/nike
|
5128 |
+
images/northface
|
5129 |
+
images/old
|
5130 |
+
images/rolex
|
5131 |
+
images/smilies
|
5132 |
+
images/table
|
5133 |
+
images/ugg
|
5134 |
+
imalook
|
5135 |
+
imitation hermes
|
5136 |
+
imitaugg
|
5137 |
+
imitrex
|
5138 |
+
immediate income
|
5139 |
+
immediate-income
|
5140 |
+
immediateincome
|
5141 |
+
immediatey
|
5142 |
+
immobilier lux
|
5143 |
+
immobilier-lux
|
5144 |
+
immobilierlux
|
5145 |
+
implanty
|
5146 |
+
impregnacji
|
5147 |
+
impressive share
|
5148 |
+
impressive-share
|
5149 |
+
in-disguise
|
5150 |
+
inbeing
|
5151 |
+
inbto
|
5152 |
+
include priceless
|
5153 |
+
includes priceless
|
5154 |
+
income.in
|
5155 |
+
increase traffic
|
5156 |
+
increase-traffic
|
5157 |
+
increasetraffic
|
5158 |
+
incredible article
|
5159 |
+
incredible-article
|
5160 |
+
inderal
|
5161 |
+
indeutsch
|
5162 |
+
index/css
|
5163 |
+
indexold
|
5164 |
+
indicators.co
|
5165 |
+
inetry
|
5166 |
+
infected almost
|
5167 |
+
infected-almost
|
5168 |
+
infinity-2
|
5169 |
+
infinity2
|
5170 |
+
info/product
|
5171 |
+
info/tag
|
5172 |
+
info/user
|
5173 |
+
info/view
|
5174 |
+
infolist
|
5175 |
+
infonetcom
|
5176 |
+
informasjon.htm
|
5177 |
+
informatik
|
5178 |
+
informatique enligne
|
5179 |
+
informatique-enligne
|
5180 |
+
informative blog
|
5181 |
+
informative post
|
5182 |
+
informative web
|
5183 |
+
informative-blog
|
5184 |
+
informative-web
|
5185 |
+
infos-
|
5186 |
+
infos/
|
5187 |
+
infusionsoft
|
5188 |
+
infеcted crash
|
5189 |
+
infеcted-crash
|
5190 |
+
ington boot
|
5191 |
+
ington-boot
|
5192 |
+
ingtonboot
|
5193 |
+
ingugg
|
5194 |
+
inheritance cash
|
5195 |
+
inheritance-cash
|
5196 |
+
initiator_
|
5197 |
+
injectionfacts
|
5198 |
+
injury-lawyer
|
5199 |
+
injurylawyer
|
5200 |
+
insanejournal
|
5201 |
+
insanity workout
|
5202 |
+
insanity-workout
|
5203 |
+
insanity.php
|
5204 |
+
insanityworkout
|
5205 |
+
insdier
|
5206 |
+
insomnia tip
|
5207 |
+
insomnia-tip
|
5208 |
+
inspired-handbag
|
5209 |
+
inspiredhandbag
|
5210 |
+
instafab
|
5211 |
+
install-virtual
|
5212 |
+
installvirtual
|
5213 |
+
instant loan
|
5214 |
+
instant traffic
|
5215 |
+
instant web
|
5216 |
+
instant-blog
|
5217 |
+
instant-loan
|
5218 |
+
instantblog
|
5219 |
+
instantcash
|
5220 |
+
instantloan
|
5221 |
+
instantpay
|
5222 |
+
instantweekly
|
5223 |
+
instructor car
|
5224 |
+
instructor-car
|
5225 |
+
insurance car
|
5226 |
+
insurance-car
|
5227 |
+
insurance-compan
|
5228 |
+
insurance-quote
|
5229 |
+
insurances
|
5230 |
+
intagra
|
5231 |
+
intdrnation
|
5232 |
+
interesting blog
|
5233 |
+
interesting-blog
|
5234 |
+
interferende
|
5235 |
+
internet gambling
|
5236 |
+
internet lifestyle
|
5237 |
+
internet link
|
5238 |
+
internet pag
|
5239 |
+
internet poker
|
5240 |
+
internet site
|
5241 |
+
internet website
|
5242 |
+
internet-gambling
|
5243 |
+
internet-lifestyle
|
5244 |
+
internet-link
|
5245 |
+
internet-market
|
5246 |
+
internet-poker
|
5247 |
+
internet-site
|
5248 |
+
internet-website
|
5249 |
+
internet.in
|
5250 |
+
internetgambling
|
5251 |
+
internetowej
|
5252 |
+
internetpoker
|
5253 |
+
interracial
|
5254 |
+
intersting
|
5255 |
+
invest-money
|
5256 |
+
invest-off
|
5257 |
+
invest.net
|
5258 |
+
invest/stock
|
5259 |
+
investing/stock
|
5260 |
+
investing+
|
5261 |
+
investinwell
|
5262 |
+
investir
|
5263 |
+
investmoney
|
5264 |
+
investoff
|
5265 |
+
investor.ru
|
5266 |
+
inzest
|
5267 |
+
ip.idealhosting.net.tr
|
5268 |
+
ipad-2-case
|
5269 |
+
ipad-download
|
5270 |
+
ipad-repair
|
5271 |
+
ipad-suppl
|
5272 |
+
ipad2me
|
5273 |
+
ipad2you
|
5274 |
+
ipadrepair
|
5275 |
+
ipadsuppl
|
5276 |
+
iphone-crack
|
5277 |
+
iphone-repair
|
5278 |
+
iphone-suppl
|
5279 |
+
iphone/iphone
|
5280 |
+
iphone2me
|
5281 |
+
iphone2you
|
5282 |
+
iphone4case
|
5283 |
+
iphone4scase
|
5284 |
+
iphonecase
|
5285 |
+
iphonecrack
|
5286 |
+
iphonerepair
|
5287 |
+
iphonesuppl
|
5288 |
+
ipod-repair
|
5289 |
+
ipod-suppl
|
5290 |
+
ipodrepair
|
5291 |
+
ipodsuppl
|
5292 |
+
iprofit
|
5293 |
+
irc-chat
|
5294 |
+
is seo
|
5295 |
+
is-now-available
|
5296 |
+
is.gd
|
5297 |
+
isabel marant
|
5298 |
+
isabel-marant
|
5299 |
+
isabelmarant
|
5300 |
+
island jacket
|
5301 |
+
island-jacket
|
5302 |
+
islandjacket
|
5303 |
+
isotretinoine
|
5304 |
+
isseo
|
5305 |
+
istanbul escort
|
5306 |
+
istanbul-escort
|
5307 |
+
istanbulescort
|
5308 |
+
it rite
|
5309 |
+
it-rite
|
5310 |
+
italia scarpe
|
5311 |
+
italia-scarpe
|
5312 |
+
italiascarpe
|
5313 |
+
italy-shop
|
5314 |
+
italy-store
|
5315 |
+
italyshop
|
5316 |
+
italystore
|
5317 |
+
itemnotfound
|
5318 |
+
itstree
|
5319 |
+
iг
|
5320 |
+
jacken-online
|
5321 |
+
jackenonline
|
5322 |
+
jackenwest
|
5323 |
+
jacket canad
|
5324 |
+
jacket sale
|
5325 |
+
jacket-canad
|
5326 |
+
jacket-jp
|
5327 |
+
jacket-sale
|
5328 |
+
jacketcanad
|
5329 |
+
jackets sale
|
5330 |
+
jackets-for-kids
|
5331 |
+
jackets-for-men
|
5332 |
+
jackets-for-wom
|
5333 |
+
jackets-jp
|
5334 |
+
jackets-sale
|
5335 |
+
jackets2012
|
5336 |
+
jackets2013
|
5337 |
+
jackets2014
|
5338 |
+
jacketsale
|
5339 |
+
jacketsforkids
|
5340 |
+
jacketsformen
|
5341 |
+
jacketsforwom
|
5342 |
+
jacketssale
|
5343 |
+
jacketswom
|
5344 |
+
jagowho
|
5345 |
+
jam jordan
|
5346 |
+
jam-jordan
|
5347 |
+
japan-1
|
5348 |
+
japanconverse
|
5349 |
+
japandrmartens
|
5350 |
+
japaneseconverse
|
5351 |
+
japanesedrmartens
|
5352 |
+
japanesemarcjacobs
|
5353 |
+
japanesemontblanc
|
5354 |
+
japaneseswarovski
|
5355 |
+
japanmarcjacobs
|
5356 |
+
japanmonster
|
5357 |
+
japanmontblanc
|
5358 |
+
japannew
|
5359 |
+
japanonline
|
5360 |
+
japanswarovski
|
5361 |
+
jassen dames
|
5362 |
+
jassen outlet
|
5363 |
+
jassen-dames
|
5364 |
+
jassen-outlet
|
5365 |
+
jassendames
|
5366 |
+
jassenoutlet
|
5367 |
+
jcshoe
|
5368 |
+
jeacoma.co
|
5369 |
+
jean taste
|
5370 |
+
jean-taste
|
5371 |
+
jeans good
|
5372 |
+
jeans taste
|
5373 |
+
jeans-taste
|
5374 |
+
jeanstaste
|
5375 |
+
jeantaste
|
5376 |
+
jeremy scott
|
5377 |
+
jeremy-scott
|
5378 |
+
jeremyads
|
5379 |
+
jeremyscott
|
5380 |
+
jeremyscottwing
|
5381 |
+
jersetblack
|
5382 |
+
jersey cheap
|
5383 |
+
jersey from
|
5384 |
+
jersey wholesale
|
5385 |
+
jersey-2013
|
5386 |
+
jersey-2014
|
5387 |
+
jersey-cheap
|
5388 |
+
jersey-from
|
5389 |
+
jersey-pro
|
5390 |
+
jersey-wholesale
|
5391 |
+
jersey.htm
|
5392 |
+
jersey.us
|
5393 |
+
jersey+
|
5394 |
+
jersey2013
|
5395 |
+
jersey2014
|
5396 |
+
jerseycheap
|
5397 |
+
jerseyfrom
|
5398 |
+
jerseyonline
|
5399 |
+
jerseypro
|
5400 |
+
jerseyred
|
5401 |
+
jerseys cheap
|
5402 |
+
jerseys from
|
5403 |
+
jerseys wholesale
|
5404 |
+
jerseys-4-you
|
5405 |
+
jerseys-cheap
|
5406 |
+
jerseys-for-you
|
5407 |
+
jerseys-from
|
5408 |
+
jerseys-wholesale
|
5409 |
+
jerseys.us
|
5410 |
+
jerseys4you
|
5411 |
+
jerseyscheap
|
5412 |
+
jerseysforyou
|
5413 |
+
jerseysfrom
|
5414 |
+
jerseysusa
|
5415 |
+
jerseyswholesale
|
5416 |
+
jerseyusa
|
5417 |
+
jerseywhite
|
5418 |
+
jerseywholesale
|
5419 |
+
jewelery
|
5420 |
+
jeweline.
|
5421 |
+
jewellery.blog
|
5422 |
+
jewelry collect
|
5423 |
+
jewelry expens
|
5424 |
+
jewelry-collect
|
5425 |
+
jewelry-expens
|
5426 |
+
jewelry<
|
5427 |
+
jewelrybest
|
5428 |
+
jewelrycollect
|
5429 |
+
jewelryexpens
|
5430 |
+
jimmy-choo
|
5431 |
+
jimmychoo
|
5432 |
+
jjl
|
5433 |
+
joggingstroll
|
5434 |
+
jogos
|
5435 |
+
john-varvatos
|
5436 |
+
joint-pain
|
5437 |
+
jointpain
|
5438 |
+
jordan 1
|
5439 |
+
jordan 11
|
5440 |
+
jordan basket
|
5441 |
+
jordan brand
|
5442 |
+
jordan femme
|
5443 |
+
jordan gamma
|
5444 |
+
jordan out
|
5445 |
+
jordan pas
|
5446 |
+
jordan retro
|
5447 |
+
jordan shoe
|
5448 |
+
jordan store
|
5449 |
+
jordan-1
|
5450 |
+
jordan-11
|
5451 |
+
jordan-basket
|
5452 |
+
jordan-brand
|
5453 |
+
jordan-femme
|
5454 |
+
jordan-gamma
|
5455 |
+
jordan-pas
|
5456 |
+
jordan-retro
|
5457 |
+
jordan-sale
|
5458 |
+
jordan-shoe
|
5459 |
+
jordan-store
|
5460 |
+
jordan1
|
5461 |
+
jordanbrand
|
5462 |
+
jordangamma
|
5463 |
+
jordankicks
|
5464 |
+
jordanretro
|
5465 |
+
jordans cheap
|
5466 |
+
jordans-cheap
|
5467 |
+
jordansale
|
5468 |
+
jordanscheap
|
5469 |
+
jordanshoe
|
5470 |
+
jordansshoe
|
5471 |
+
jordanstore
|
5472 |
+
jordjev
|
5473 |
+
journal/item
|
5474 |
+
jp-bag
|
5475 |
+
jp-best
|
5476 |
+
jp-sale
|
5477 |
+
jp/blog
|
5478 |
+
jpbag
|
5479 |
+
jpbest
|
5480 |
+
jpcity.co
|
5481 |
+
jpconverse
|
5482 |
+
jpmarcjacob
|
5483 |
+
jpmonster
|
5484 |
+
jpsale
|
5485 |
+
jpsasics
|
5486 |
+
js wing
|
5487 |
+
js-wing
|
5488 |
+
jsadidas
|
5489 |
+
jswing
|
5490 |
+
juanjuan
|
5491 |
+
juicycouture
|
5492 |
+
jumpedup
|
5493 |
+
justcloud
|
5494 |
+
justness
|
5495 |
+
kaepernick jersey
|
5496 |
+
kaepernick wom
|
5497 |
+
kaepernick youth
|
5498 |
+
kaepernick-jersey
|
5499 |
+
kaepernick-wom
|
5500 |
+
kaepernick-youth
|
5501 |
+
kaepernickjersey
|
5502 |
+
kaepernickwom
|
5503 |
+
kaepernickyouth
|
5504 |
+
kaffee-maschine
|
5505 |
+
kaffeemaschine
|
5506 |
+
kamagra
|
5507 |
+
kameri
|
5508 |
+
kanalizacyjne
|
5509 |
+
kanyewestsun
|
5510 |
+
kardashian
|
5511 |
+
karenmillen-au
|
5512 |
+
karenmillenau
|
5513 |
+
karpaczwsieci
|
5514 |
+
karuteie
|
5515 |
+
kasino
|
5516 |
+
katalog
|
5517 |
+
katespadese
|
5518 |
+
kensington parka
|
5519 |
+
kensington-parka
|
5520 |
+
kensingtonparka
|
5521 |
+
key-programmer
|
5522 |
+
keygen
|
5523 |
+
keylessremote
|
5524 |
+
keyword.txt
|
5525 |
+
keywords1
|
5526 |
+
kfcnfl
|
5527 |
+
khumbu north
|
5528 |
+
khumbu-north
|
5529 |
+
kids nike
|
5530 |
+
kids out
|
5531 |
+
kids ugg
|
5532 |
+
kids-nike
|
5533 |
+
kids-ugg
|
5534 |
+
kidsnike
|
5535 |
+
kino-online
|
5536 |
+
kinoonline
|
5537 |
+
kitai
|
5538 |
+
kitchen-worktop
|
5539 |
+
kitchenworktop
|
5540 |
+
kleding winkel
|
5541 |
+
kleding-winkel
|
5542 |
+
kledingwinkel
|
5543 |
+
klonopin
|
5544 |
+
klub.ru
|
5545 |
+
knee-joint
|
5546 |
+
knee-pain
|
5547 |
+
kneejoint
|
5548 |
+
kneepain
|
5549 |
+
knicely
|
5550 |
+
knigki
|
5551 |
+
knigko
|
5552 |
+
knockoff eyewear
|
5553 |
+
knockoff-eyewear
|
5554 |
+
knockoff-handbag
|
5555 |
+
knockoffhandbag
|
5556 |
+
knolckoff
|
5557 |
+
knowledgeable individual
|
5558 |
+
knowledgeable-individual
|
5559 |
+
known blog
|
5560 |
+
known-blog
|
5561 |
+
kobe-shoe
|
5562 |
+
kobeshoe
|
5563 |
+
komputer
|
5564 |
+
komputery
|
5565 |
+
konkurs
|
5566 |
+
konsultan-
|
5567 |
+
kontakta-oss
|
5568 |
+
kontrahenta
|
5569 |
+
koop dsquared
|
5570 |
+
koop-dsquared
|
5571 |
+
koopdsquared
|
5572 |
+
koopsted
|
5573 |
+
kopfhoerer
|
5574 |
+
kopia-zapasowa
|
5575 |
+
kor outlet
|
5576 |
+
kor-outlet
|
5577 |
+
koroutlet
|
5578 |
+
kors austr
|
5579 |
+
kors bag
|
5580 |
+
kors brasil
|
5581 |
+
kors canad
|
5582 |
+
kors charlton
|
5583 |
+
kors cheap
|
5584 |
+
kors dillard
|
5585 |
+
kors factory
|
5586 |
+
kors france
|
5587 |
+
kors glass
|
5588 |
+
kors grayson
|
5589 |
+
kors hamilton
|
5590 |
+
kors handbag
|
5591 |
+
kors laptop
|
5592 |
+
kors milano
|
5593 |
+
kors out
|
5594 |
+
kors outlet
|
5595 |
+
kors puffer
|
5596 |
+
kors purse
|
5597 |
+
kors replica
|
5598 |
+
kors runway
|
5599 |
+
kors tonne
|
5600 |
+
kors uk
|
5601 |
+
kors vancouver
|
5602 |
+
kors wallet
|
5603 |
+
kors-bag
|
5604 |
+
kors-bags
|
5605 |
+
kors-canad
|
5606 |
+
kors-charlton
|
5607 |
+
kors-cheap
|
5608 |
+
kors-dillard
|
5609 |
+
kors-factory
|
5610 |
+
kors-glass
|
5611 |
+
kors-grayson
|
5612 |
+
kors-hamilton
|
5613 |
+
kors-handbag
|
5614 |
+
kors-laptop
|
5615 |
+
kors-milano
|
5616 |
+
kors-out
|
5617 |
+
kors-outlet
|
5618 |
+
kors-puffer
|
5619 |
+
kors-purse
|
5620 |
+
kors-tonne
|
5621 |
+
kors-vancouver
|
5622 |
+
kors-watch
|
5623 |
+
korsbag
|
5624 |
+
korscanad
|
5625 |
+
korsglass
|
5626 |
+
korshandbag
|
5627 |
+
korslaptop
|
5628 |
+
korsout
|
5629 |
+
korsoutlet
|
5630 |
+
korspurse
|
5631 |
+
korswatch
|
5632 |
+
kosmetyc
|
5633 |
+
kosmetyki
|
5634 |
+
kosze
|
5635 |
+
kreddyt
|
5636 |
+
kreddyyt
|
5637 |
+
kredit
|
5638 |
+
kredyt
|
5639 |
+
ku42.
|
5640 |
+
kvartiry
|
5641 |
+
k眉nst
|
5642 |
+
l.uk.e.w.a.rm
|
5643 |
+
l'argent
|
5644 |
+
l’argent
|
5645 |
+
laarzen kopen
|
5646 |
+
laarzen-kopen
|
5647 |
+
laarzenkopen
|
5648 |
+
labetalol
|
5649 |
+
lacoste-out
|
5650 |
+
lacosteout
|
5651 |
+
lamictal
|
5652 |
+
lamisil
|
5653 |
+
lancel pas
|
5654 |
+
lancel sac
|
5655 |
+
lancel-pas
|
5656 |
+
lancel-sac
|
5657 |
+
lancelad
|
5658 |
+
laplap
|
5659 |
+
large tote
|
5660 |
+
large-tote
|
5661 |
+
largetote
|
5662 |
+
lariam
|
5663 |
+
las|
|
5664 |
+
lasart.es
|
5665 |
+
laser-therapy
|
5666 |
+
lasercuttingmachine
|
5667 |
+
laseriv
|
5668 |
+
laserowe
|
5669 |
+
lasertherapy
|
5670 |
+
lasix
|
5671 |
+
latonya.
|
5672 |
+
lauren amsterdam
|
5673 |
+
lauren cheap
|
5674 |
+
lauren dame
|
5675 |
+
lauren factory
|
5676 |
+
lauren heren
|
5677 |
+
lauren home
|
5678 |
+
lauren homme
|
5679 |
+
lauren kleding
|
5680 |
+
lauren neder
|
5681 |
+
lauren norge
|
5682 |
+
lauren online
|
5683 |
+
lauren oslo
|
5684 |
+
lauren out
|
5685 |
+
lauren polo
|
5686 |
+
lauren ralph
|
5687 |
+
lauren sale
|
5688 |
+
lauren sverige
|
5689 |
+
lauren uk
|
5690 |
+
lauren-amsterdam
|
5691 |
+
lauren-austr
|
5692 |
+
lauren-cheap
|
5693 |
+
lauren-dame
|
5694 |
+
lauren-factory
|
5695 |
+
lauren-heren
|
5696 |
+
lauren-home
|
5697 |
+
lauren-homme
|
5698 |
+
lauren-kleding
|
5699 |
+
lauren-neder
|
5700 |
+
lauren-norge
|
5701 |
+
lauren-online
|
5702 |
+
lauren-oslo
|
5703 |
+
lauren-out
|
5704 |
+
lauren-polo
|
5705 |
+
lauren-ralph
|
5706 |
+
lauren-sale
|
5707 |
+
lauren-sverige
|
5708 |
+
lauren-uk
|
5709 |
+
laurenaustr
|
5710 |
+
laurencheap
|
5711 |
+
laurendame
|
5712 |
+
laurenhome
|
5713 |
+
laurenhomme
|
5714 |
+
laurennorge
|
5715 |
+
laurenonline
|
5716 |
+
laurenout
|
5717 |
+
laurenpolo
|
5718 |
+
laurenralph
|
5719 |
+
laurensale
|
5720 |
+
laurensverige
|
5721 |
+
laurent femme
|
5722 |
+
laurent sandal
|
5723 |
+
laurent-femme
|
5724 |
+
laurent-sandal
|
5725 |
+
laurentfemme
|
5726 |
+
laurenuk
|
5727 |
+
lawoffice.net
|
5728 |
+
lead-system
|
5729 |
+
leaked1
|
5730 |
+
learn facebook
|
5731 |
+
learn-facebook
|
5732 |
+
learn-helpful
|
5733 |
+
learnfacebook
|
5734 |
+
learningxchange
|
5735 |
+
learnpianohere
|
5736 |
+
leather-levi
|
5737 |
+
leatherlevi
|
5738 |
+
lebronshoe
|
5739 |
+
lebronxshoe
|
5740 |
+
led_display
|
5741 |
+
led_down
|
5742 |
+
led_flood
|
5743 |
+
led_indust
|
5744 |
+
led_street
|
5745 |
+
leder-jacken
|
5746 |
+
lederjacken
|
5747 |
+
leg-wear
|
5748 |
+
legal cash
|
5749 |
+
legal-cash
|
5750 |
+
legal-steroid
|
5751 |
+
legalbud
|
5752 |
+
legalsteroid
|
5753 |
+
legends hack
|
5754 |
+
legends-hack
|
5755 |
+
leger band
|
5756 |
+
leger-band
|
5757 |
+
legerband
|
5758 |
+
lend-direct
|
5759 |
+
lenddirect
|
5760 |
+
lendsomemoney
|
5761 |
+
lenjerie
|
5762 |
+
lesben-
|
5763 |
+
lesbos.
|
5764 |
+
lespaulsmith
|
5765 |
+
lesson1
|
5766 |
+
letrozole
|
5767 |
+
levaquin
|
5768 |
+
level 50
|
5769 |
+
level market
|
5770 |
+
level-50
|
5771 |
+
level-market
|
5772 |
+
levelmarket
|
5773 |
+
levitra
|
5774 |
+
levne
|
5775 |
+
liabaleles
|
5776 |
+
libraries.cfm
|
5777 |
+
library.cfm
|
5778 |
+
librarys.cfm
|
5779 |
+
librium
|
5780 |
+
lifeinsurance
|
5781 |
+
lifelock
|
5782 |
+
ligne http
|
5783 |
+
likе
|
5784 |
+
limited jersey
|
5785 |
+
limited-jersey
|
5786 |
+
limitedjersey
|
5787 |
+
limo-service
|
5788 |
+
linguim.co
|
5789 |
+
link http
|
5790 |
+
link issue
|
5791 |
+
link_
|
5792 |
+
link-bait
|
5793 |
+
link-build
|
5794 |
+
link-campaign
|
5795 |
+
link-issue
|
5796 |
+
link-juice
|
5797 |
+
link-market
|
5798 |
+
link-pyramid
|
5799 |
+
link-serv
|
5800 |
+
link-track
|
5801 |
+
link-vault
|
5802 |
+
linkbait
|
5803 |
+
linkbuild
|
5804 |
+
linkcampaign
|
5805 |
+
linking issue
|
5806 |
+
linking_
|
5807 |
+
linking-campaign
|
5808 |
+
linking-issue
|
5809 |
+
linking-market
|
5810 |
+
linking-serv
|
5811 |
+
linkingcampaign
|
5812 |
+
linkiseo
|
5813 |
+
linklegend
|
5814 |
+
linkman
|
5815 |
+
links http
|
5816 |
+
linktrack
|
5817 |
+
linkusup
|
5818 |
+
linkvault
|
5819 |
+
linkz
|
5820 |
+
lionsfan
|
5821 |
+
lionsjersey
|
5822 |
+
lipitor
|
5823 |
+
lisinopril
|
5824 |
+
lisseur-pascher
|
5825 |
+
lisseurpascher
|
5826 |
+
listajp
|
5827 |
+
listasegment
|
5828 |
+
litte more
|
5829 |
+
litte-more
|
5830 |
+
live-article
|
5831 |
+
livearticle
|
5832 |
+
livesex
|
5833 |
+
llifted
|
5834 |
+
loan canad
|
5835 |
+
loan compan
|
5836 |
+
loan fast
|
5837 |
+
loan http
|
5838 |
+
loan online
|
5839 |
+
loan-canad
|
5840 |
+
loan-compan
|
5841 |
+
loan-direct
|
5842 |
+
loan-fast
|
5843 |
+
loan-online
|
5844 |
+
loan.co
|
5845 |
+
loan.in
|
5846 |
+
loan.net
|
5847 |
+
loanalys
|
5848 |
+
loancompan
|
5849 |
+
loandirect
|
5850 |
+
loanfast
|
5851 |
+
loanonline
|
5852 |
+
loans canad
|
5853 |
+
loans compan
|
5854 |
+
loans fast
|
5855 |
+
loans http
|
5856 |
+
loans online
|
5857 |
+
loans-canad
|
5858 |
+
loans-compan
|
5859 |
+
loans-direct
|
5860 |
+
loans-fast
|
5861 |
+
loans-online
|
5862 |
+
loans.co
|
5863 |
+
loans.in
|
5864 |
+
loans.net
|
5865 |
+
loans1
|
5866 |
+
loans2
|
5867 |
+
loans3
|
5868 |
+
loans4
|
5869 |
+
loanscanad
|
5870 |
+
loanscompan
|
5871 |
+
loansdirect
|
5872 |
+
loansfast
|
5873 |
+
loansonline
|
5874 |
+
locate-cell-phone
|
5875 |
+
locateacellphone
|
5876 |
+
locatecellphone
|
5877 |
+
lodz
|
5878 |
+
łódź
|
5879 |
+
logcabins
|
5880 |
+
login.php
|
5881 |
+
loiusvuitton
|
5882 |
+
lol i
|
5883 |
+
london-genuine
|
5884 |
+
londongenuine
|
5885 |
+
long long
|
5886 |
+
longafter
|
5887 |
+
longchamp aus
|
5888 |
+
longchamp bag
|
5889 |
+
longchamp handbag
|
5890 |
+
longchamp pas
|
5891 |
+
longchamp pliage
|
5892 |
+
longchamp purse
|
5893 |
+
longchamp solde
|
5894 |
+
longchamp tasche
|
5895 |
+
longchamp tote
|
5896 |
+
longchamp uk
|
5897 |
+
longchamp-aus
|
5898 |
+
longchamp-handbag
|
5899 |
+
longchamp-pliage
|
5900 |
+
longchamp-purse
|
5901 |
+
longchamp-shop
|
5902 |
+
longchamp-solde
|
5903 |
+
longchamp-tasche
|
5904 |
+
longchamp-tote
|
5905 |
+
longchamp-uk
|
5906 |
+
longchamp.php
|
5907 |
+
longchampaus
|
5908 |
+
longchampbag
|
5909 |
+
longchamphandbag
|
5910 |
+
longchamplondon
|
5911 |
+
longchampoffici
|
5912 |
+
longchampout
|
5913 |
+
longchampp
|
5914 |
+
longchamppurse
|
5915 |
+
longchampsa
|
5916 |
+
longchampshop
|
5917 |
+
longchampsolde
|
5918 |
+
longchamptasche
|
5919 |
+
longchamptote
|
5920 |
+
longchampuk
|
5921 |
+
lookingfor
|
5922 |
+
loorg.de
|
5923 |
+
lorazepam
|
5924 |
+
lortab
|
5925 |
+
lose-weight
|
5926 |
+
loseweight
|
5927 |
+
loteprednol
|
5928 |
+
lotto-tip
|
5929 |
+
lottotip
|
5930 |
+
louboutin canad
|
5931 |
+
louboutin cheap
|
5932 |
+
louboutin discount
|
5933 |
+
louboutin out
|
5934 |
+
louboutin pas
|
5935 |
+
louboutin platform
|
5936 |
+
louboutin pump
|
5937 |
+
louboutin red
|
5938 |
+
louboutin sale
|
5939 |
+
louboutin shoe
|
5940 |
+
louboutin solde
|
5941 |
+
louboutin uk
|
5942 |
+
louboutin-chau
|
5943 |
+
louboutin-cheap
|
5944 |
+
louboutin-discount
|
5945 |
+
louboutin-out
|
5946 |
+
louboutin-pas
|
5947 |
+
louboutin-platform
|
5948 |
+
louboutin-pump
|
5949 |
+
louboutin-red
|
5950 |
+
louboutin-sale
|
5951 |
+
louboutin-shoe
|
5952 |
+
louboutin-solde
|
5953 |
+
louboutin8
|
5954 |
+
louboutindiscount
|
5955 |
+
louboutinfr
|
5956 |
+
loubouting
|
5957 |
+
louboutinout
|
5958 |
+
louboutinpas
|
5959 |
+
louboutinpascher
|
5960 |
+
louboutins pas
|
5961 |
+
louboutins-pas
|
5962 |
+
louboutinsale
|
5963 |
+
louboutinshoe
|
5964 |
+
louboutinsolde
|
5965 |
+
louboutinspas
|
5966 |
+
louboutinuk
|
5967 |
+
louis vitton
|
5968 |
+
louis vuittone
|
5969 |
+
louis_vuitton
|
5970 |
+
louis-vuitton
|
5971 |
+
louis-vuittone
|
5972 |
+
louis+vuitton
|
5973 |
+
louisvuit.
|
5974 |
+
louisvuitton
|
5975 |
+
louiswuitton
|
5976 |
+
love connector
|
5977 |
+
love-connector
|
5978 |
+
loved onein
|
5979 |
+
loved-onein
|
5980 |
+
lovelv
|
5981 |
+
lovely thong
|
5982 |
+
lovely-thong
|
5983 |
+
lovelyto
|
5984 |
+
lovemyhair
|
5985 |
+
lovingnatural
|
5986 |
+
low priced
|
5987 |
+
low-cost-
|
5988 |
+
low-priced
|
5989 |
+
lowpriced
|
5990 |
+
loyalty today
|
5991 |
+
loyalty-today
|
5992 |
+
loϲal
|
5993 |
+
lublin.
|
5994 |
+
lublina.
|
5995 |
+
luck jersey
|
5996 |
+
luck-jersey
|
5997 |
+
luckjersey
|
5998 |
+
luggagetote
|
5999 |
+
lululemon outlet
|
6000 |
+
lululemon-outlet
|
6001 |
+
lumigan
|
6002 |
+
luminor watch
|
6003 |
+
luminor-watch
|
6004 |
+
luminorwatch
|
6005 |
+
lunarglide
|
6006 |
+
lunarlon
|
6007 |
+
lunderground
|
6008 |
+
lunette oakley
|
6009 |
+
lunette solde
|
6010 |
+
lunette-oakley
|
6011 |
+
lunette-solde
|
6012 |
+
lunetteoakley
|
6013 |
+
lunettes oakley
|
6014 |
+
lunettes-de-soleil
|
6015 |
+
lunettes-oakley
|
6016 |
+
lunettesdesoleil
|
6017 |
+
lunettesoakley
|
6018 |
+
lunettesolde
|
6019 |
+
lunettespaschere
|
6020 |
+
lupusinfo
|
6021 |
+
lux-replica
|
6022 |
+
luxreplica
|
6023 |
+
luxury chanel
|
6024 |
+
luxury-brand
|
6025 |
+
luxury-chanel
|
6026 |
+
luxury-replica
|
6027 |
+
luxurybrand
|
6028 |
+
luxurychanel
|
6029 |
+
luxuryreplica
|
6030 |
+
lv austr
|
6031 |
+
lv bag
|
6032 |
+
lv brasil
|
6033 |
+
lv factory
|
6034 |
+
lv france
|
6035 |
+
lv-bag
|
6036 |
+
lv-discount
|
6037 |
+
lv-handbag
|
6038 |
+
lv-jp
|
6039 |
+
lv-out
|
6040 |
+
lv-replica
|
6041 |
+
lv-uk
|
6042 |
+
lvbag
|
6043 |
+
lvdiscount
|
6044 |
+
lvforsale
|
6045 |
+
lvhandbag
|
6046 |
+
lviv
|
6047 |
+
lvout
|
6048 |
+
lvreplica
|
6049 |
+
lvsale
|
6050 |
+
lvuk
|
6051 |
+
m88day
|
6052 |
+
mac-cosmetic
|
6053 |
+
mac-makeup
|
6054 |
+
macha-slim
|
6055 |
+
machaslim
|
6056 |
+
maclipgloss
|
6057 |
+
macmakeup
|
6058 |
+
madeknown
|
6059 |
+
madeye30
|
6060 |
+
magazine/page1
|
6061 |
+
magazine/page2
|
6062 |
+
magicmoncler
|
6063 |
+
magnificent article
|
6064 |
+
magnificent-article
|
6065 |
+
mail_
|
6066 |
+
mail.ru
|
6067 |
+
maillot man
|
6068 |
+
maillot ukraine
|
6069 |
+
maillot-enfant
|
6070 |
+
maillot-maillot
|
6071 |
+
maillot-man
|
6072 |
+
maillot-ukraine
|
6073 |
+
maillotman
|
6074 |
+
maillotukraine
|
6075 |
+
main longchamp
|
6076 |
+
main-longchamp
|
6077 |
+
main.htm
|
6078 |
+
main/main
|
6079 |
+
mainlongchamp
|
6080 |
+
majesticriver
|
6081 |
+
make money
|
6082 |
+
make-backup
|
6083 |
+
make-million
|
6084 |
+
make-money
|
6085 |
+
makebaby
|
6086 |
+
makeme
|
6087 |
+
makemoney
|
6088 |
+
makersnow
|
6089 |
+
makeup.blog
|
6090 |
+
making money
|
6091 |
+
making-money
|
6092 |
+
makingmoney
|
6093 |
+
maklare
|
6094 |
+
male enhance
|
6095 |
+
male-enhance
|
6096 |
+
maleenhance
|
6097 |
+
malepower
|
6098 |
+
malwareremov
|
6099 |
+
manage_
|
6100 |
+
manage/new
|
6101 |
+
management-software
|
6102 |
+
manchesterhotel
|
6103 |
+
manicshop
|
6104 |
+
manner puma
|
6105 |
+
månner puma
|
6106 |
+
manner-puma
|
6107 |
+
månner-puma
|
6108 |
+
mannerpuma
|
6109 |
+
månnerpuma
|
6110 |
+
manning jersey
|
6111 |
+
manning-jersey
|
6112 |
+
manningjersey
|
6113 |
+
manor escort
|
6114 |
+
manor-escort
|
6115 |
+
maran-train
|
6116 |
+
marant boot
|
6117 |
+
marant shoe
|
6118 |
+
marant sneak
|
6119 |
+
marant-boot
|
6120 |
+
marant-shoe
|
6121 |
+
marant-sneak
|
6122 |
+
marantboot
|
6123 |
+
marantrain
|
6124 |
+
marantshoe
|
6125 |
+
marantsneak
|
6126 |
+
marcjacobsjap
|
6127 |
+
marcjacobsjp
|
6128 |
+
margreet.
|
6129 |
+
mariage hugo
|
6130 |
+
mariage original
|
6131 |
+
mariage-hugo
|
6132 |
+
mariage-original
|
6133 |
+
marijuana fact
|
6134 |
+
marijuana-fact
|
6135 |
+
marker http
|
6136 |
+
markerboss
|
6137 |
+
markerdude
|
6138 |
+
markergaul
|
6139 |
+
market prices
|
6140 |
+
market samurai
|
6141 |
+
market-prices
|
6142 |
+
market-research.
|
6143 |
+
market-researching.
|
6144 |
+
market-samurai
|
6145 |
+
marketing online
|
6146 |
+
marketing samurai
|
6147 |
+
marketing-blog
|
6148 |
+
marketing-book
|
6149 |
+
marketing-market
|
6150 |
+
marketing-online
|
6151 |
+
marketing-samurai
|
6152 |
+
marketing-tip
|
6153 |
+
marketing.in
|
6154 |
+
marketingblog
|
6155 |
+
marketingbook
|
6156 |
+
marketinghero
|
6157 |
+
marketingsamurai
|
6158 |
+
marketingtip
|
6159 |
+
marketingxchange
|
6160 |
+
marketnn
|
6161 |
+
marketsamurai
|
6162 |
+
marlboro 100
|
6163 |
+
marlboro cig
|
6164 |
+
marlboro gold
|
6165 |
+
marlboro-100
|
6166 |
+
marlboro-cig
|
6167 |
+
marlboro-gold
|
6168 |
+
marlboro100
|
6169 |
+
marseille http
|
6170 |
+
marvelous post
|
6171 |
+
marvelous-post
|
6172 |
+
mass-facebook
|
6173 |
+
massarticle
|
6174 |
+
massive-web
|
6175 |
+
masszaz
|
6176 |
+
mastablasta
|
6177 |
+
master.ru
|
6178 |
+
mastermind-team
|
6179 |
+
mastermindteam
|
6180 |
+
matchcash
|
6181 |
+
matthewsjersey
|
6182 |
+
matural
|
6183 |
+
max griffey
|
6184 |
+
max sale
|
6185 |
+
max-griffey
|
6186 |
+
max-sale
|
6187 |
+
maxalt
|
6188 |
+
maxgriffey
|
6189 |
+
maxsale
|
6190 |
+
may-help-you
|
6191 |
+
mbt baridi
|
6192 |
+
mbt boot
|
6193 |
+
mbt chapa
|
6194 |
+
mbt clearance
|
6195 |
+
mbt exercise
|
6196 |
+
mbt footwear
|
6197 |
+
mbt fora
|
6198 |
+
mbt men
|
6199 |
+
mbt online
|
6200 |
+
mbt outlet
|
6201 |
+
mbt panda
|
6202 |
+
mbt sale
|
6203 |
+
mbt sandal
|
6204 |
+
mbt scarpe
|
6205 |
+
mbt schuhe
|
6206 |
+
mbt shoe
|
6207 |
+
mbt shop
|
6208 |
+
mbt special
|
6209 |
+
mbt tariki
|
6210 |
+
mbt tembea
|
6211 |
+
mbt train
|
6212 |
+
mbt tunisha
|
6213 |
+
mbt vanzari
|
6214 |
+
mbt women
|
6215 |
+
mbt_
|
6216 |
+
mbt-baridi
|
6217 |
+
mbt-boot
|
6218 |
+
mbt-carpe
|
6219 |
+
mbt-chapa
|
6220 |
+
mbt-clearance
|
6221 |
+
mbt-exercise
|
6222 |
+
mbt-footwear
|
6223 |
+
mbt-fora
|
6224 |
+
mbt-japan
|
6225 |
+
mbt-men
|
6226 |
+
mbt-online
|
6227 |
+
mbt-outlet
|
6228 |
+
mbt-panda
|
6229 |
+
mbt-sale
|
6230 |
+
mbt-sandal
|
6231 |
+
mbt-schuhe
|
6232 |
+
mbt-shoe
|
6233 |
+
mbt-shop
|
6234 |
+
mbt-special
|
6235 |
+
mbt-tariki
|
6236 |
+
mbt-tembea
|
6237 |
+
mbt-train
|
6238 |
+
mbt-tunisha
|
6239 |
+
mbt-vanzari
|
6240 |
+
mbt-women
|
6241 |
+
mbtbaridi
|
6242 |
+
mbtboot
|
6243 |
+
mbtchapa
|
6244 |
+
mbtclearance
|
6245 |
+
mbtexercise
|
6246 |
+
mbtfootwear
|
6247 |
+
mbtfora
|
6248 |
+
mbtgun
|
6249 |
+
mbtjapan
|
6250 |
+
mbtmen
|
6251 |
+
mbtonline
|
6252 |
+
mbtoutlet
|
6253 |
+
mbtpanda
|
6254 |
+
mbtsale
|
6255 |
+
mbtsandal
|
6256 |
+
mbtschuhe
|
6257 |
+
mbtshoe
|
6258 |
+
mbtshop
|
6259 |
+
mbtsko
|
6260 |
+
mbtspecial
|
6261 |
+
mbttariki
|
6262 |
+
mbttembea
|
6263 |
+
mbttrain
|
6264 |
+
mbttunisha
|
6265 |
+
mbtvanzari
|
6266 |
+
mbtwomen
|
6267 |
+
mckinqi
|
6268 |
+
mcm backpack
|
6269 |
+
mcm bag
|
6270 |
+
mcm handbag
|
6271 |
+
mcm-backpack
|
6272 |
+
mcm-bag
|
6273 |
+
mcm-handbag
|
6274 |
+
mcm.co
|
6275 |
+
mcmbackpack
|
6276 |
+
mcqueen club
|
6277 |
+
mcqueen dress
|
6278 |
+
mcqueen leopard
|
6279 |
+
mcqueen online
|
6280 |
+
mcqueen pashmin
|
6281 |
+
mcqueen shoe
|
6282 |
+
mcqueen silk
|
6283 |
+
mcqueen-club
|
6284 |
+
mcqueen-dress
|
6285 |
+
mcqueen-leopard
|
6286 |
+
mcqueen-online
|
6287 |
+
mcqueen-pashmin
|
6288 |
+
mcqueen-shoe
|
6289 |
+
mcqueen-silk
|
6290 |
+
mcqueenclub
|
6291 |
+
mcqueendress
|
6292 |
+
mcqueensilk
|
6293 |
+
me passionne
|
6294 |
+
me-passionne
|
6295 |
+
meandyou
|
6296 |
+
meble gabinetowe
|
6297 |
+
meble ogrodowe
|
6298 |
+
meble-gabinetowe
|
6299 |
+
meble-ogrodowe
|
6300 |
+
meblowy
|
6301 |
+
mechpromo.
|
6302 |
+
meclizine
|
6303 |
+
med-shop
|
6304 |
+
medbaz
|
6305 |
+
medecine
|
6306 |
+
medeniz
|
6307 |
+
media-palitra
|
6308 |
+
mediapalitra
|
6309 |
+
medicarefraud
|
6310 |
+
medieval-costume
|
6311 |
+
medigital
|
6312 |
+
medikal.co
|
6313 |
+
medizinische
|
6314 |
+
medphrase
|
6315 |
+
medshop
|
6316 |
+
meilleur casino
|
6317 |
+
meilleur-casino
|
6318 |
+
meilleurs casino
|
6319 |
+
meilleurs-casino
|
6320 |
+
melatonin
|
6321 |
+
meloxicam
|
6322 |
+
member_
|
6323 |
+
member.php
|
6324 |
+
memberlist.php
|
6325 |
+
members_
|
6326 |
+
membership hack
|
6327 |
+
membership-hack
|
6328 |
+
membership.php
|
6329 |
+
membershiphack
|
6330 |
+
men boost
|
6331 |
+
men handbag
|
6332 |
+
men-boost
|
6333 |
+
men-handbag
|
6334 |
+
men+shoe
|
6335 |
+
menboost
|
6336 |
+
mens coach
|
6337 |
+
mens-coach
|
6338 |
+
mens+coach
|
6339 |
+
menseekingwom
|
6340 |
+
mentalprocess
|
6341 |
+
menu/menu
|
6342 |
+
mequinol
|
6343 |
+
meratol
|
6344 |
+
mercantilism
|
6345 |
+
mercati di
|
6346 |
+
mercati-di
|
6347 |
+
mercenary.co
|
6348 |
+
meridia
|
6349 |
+
messengerstyle
|
6350 |
+
metacam
|
6351 |
+
metallo
|
6352 |
+
methadone
|
6353 |
+
methionine
|
6354 |
+
methode argent
|
6355 |
+
methode pour
|
6356 |
+
methode-argent
|
6357 |
+
methode-pour
|
6358 |
+
methodeargent
|
6359 |
+
methodepour
|
6360 |
+
metlifecare
|
6361 |
+
metronidazole
|
6362 |
+
mezzo louis
|
6363 |
+
mezzo-louis
|
6364 |
+
mezzolouis
|
6365 |
+
miami escort
|
6366 |
+
miami-escort
|
6367 |
+
michael-kors
|
6368 |
+
michael+kors
|
6369 |
+
michaelkors
|
6370 |
+
mieszkania
|
6371 |
+
mieszkanie
|
6372 |
+
milano scarpe
|
6373 |
+
milano-scarpe
|
6374 |
+
milanoscarpe
|
6375 |
+
milanosjapan
|
6376 |
+
mild activ
|
6377 |
+
mild-activ
|
6378 |
+
milendress
|
6379 |
+
millen au
|
6380 |
+
millen clearance
|
6381 |
+
millen color
|
6382 |
+
millen colour
|
6383 |
+
millen dress
|
6384 |
+
millen factory
|
6385 |
+
millen jacket
|
6386 |
+
millen out
|
6387 |
+
millen outlet
|
6388 |
+
millen shop
|
6389 |
+
millen uk
|
6390 |
+
millen-au
|
6391 |
+
millen-clearance
|
6392 |
+
millen-color
|
6393 |
+
millen-colour
|
6394 |
+
millen-dress
|
6395 |
+
millen-factory
|
6396 |
+
millen-jacket
|
6397 |
+
millen-out
|
6398 |
+
millen-outlet
|
6399 |
+
millen-shop
|
6400 |
+
millen-uk
|
6401 |
+
millenclearance
|
6402 |
+
millencolour
|
6403 |
+
millenjacket
|
6404 |
+
millenoutlet
|
6405 |
+
millenshop
|
6406 |
+
minecraftfree
|
6407 |
+
minicredit
|
6408 |
+
mintcoin
|
6409 |
+
minumum
|
6410 |
+
miracle-discount
|
6411 |
+
miraclediscount
|
6412 |
+
mirapex
|
6413 |
+
mister-design
|
6414 |
+
misterboy
|
6415 |
+
mittelx
|
6416 |
+
miu miu
|
6417 |
+
miu sunglass
|
6418 |
+
miu-miu
|
6419 |
+
miu-sunglass
|
6420 |
+
miumiu
|
6421 |
+
miusunglass
|
6422 |
+
mixed-race
|
6423 |
+
mixedrace
|
6424 |
+
mkhandbag
|
6425 |
+
mkout
|
6426 |
+
mlb cap
|
6427 |
+
mlb-cap
|
6428 |
+
mlbcap
|
6429 |
+
mlm business
|
6430 |
+
mlm lead
|
6431 |
+
mlm-business
|
6432 |
+
mlm-lead
|
6433 |
+
mlmlead
|
6434 |
+
mlskev
|
6435 |
+
mlsp suit
|
6436 |
+
mlsp-suit
|
6437 |
+
mlspweapon
|
6438 |
+
mmcenter.in
|
6439 |
+
mobi/news
|
6440 |
+
mobilabonnementer
|
6441 |
+
mobile sim
|
6442 |
+
mobile-phone
|
6443 |
+
mobistealth
|
6444 |
+
moczanowa
|
6445 |
+
modafinil
|
6446 |
+
models.in
|
6447 |
+
moderowany
|
6448 |
+
moduleinstance
|
6449 |
+
modules.php
|
6450 |
+
moldremov
|
6451 |
+
monclear
|
6452 |
+
moncler berriat
|
6453 |
+
moncler cap
|
6454 |
+
moncler cloth
|
6455 |
+
moncler coat
|
6456 |
+
moncler donn
|
6457 |
+
moncler femme
|
6458 |
+
moncler firenze
|
6459 |
+
moncler giub
|
6460 |
+
moncler handbag
|
6461 |
+
moncler homme
|
6462 |
+
moncler jack
|
6463 |
+
moncler jacke
|
6464 |
+
moncler jassen
|
6465 |
+
moncler jura
|
6466 |
+
moncler klassiker
|
6467 |
+
moncler man
|
6468 |
+
moncler men
|
6469 |
+
moncler online
|
6470 |
+
moncler out
|
6471 |
+
moncler padova
|
6472 |
+
moncler paris
|
6473 |
+
moncler parka
|
6474 |
+
moncler pas
|
6475 |
+
moncler pascher
|
6476 |
+
moncler piumini
|
6477 |
+
moncler polo
|
6478 |
+
moncler pour
|
6479 |
+
moncler prezzi
|
6480 |
+
moncler pullover
|
6481 |
+
moncler quincy
|
6482 |
+
moncler sito
|
6483 |
+
moncler ski
|
6484 |
+
moncler sold
|
6485 |
+
moncler store
|
6486 |
+
moncler strickjacke
|
6487 |
+
moncler sweater
|
6488 |
+
moncler tibet
|
6489 |
+
moncler uk
|
6490 |
+
moncler uomo
|
6491 |
+
moncler vast
|
6492 |
+
moncler väst
|
6493 |
+
moncler vente
|
6494 |
+
moncler vest
|
6495 |
+
moncler vos
|
6496 |
+
moncler weste
|
6497 |
+
moncler westen
|
6498 |
+
moncler--
|
6499 |
+
moncler-berriat
|
6500 |
+
moncler-cap
|
6501 |
+
moncler-cloth
|
6502 |
+
moncler-coat
|
6503 |
+
moncler-donn
|
6504 |
+
moncler-femme
|
6505 |
+
moncler-firenze
|
6506 |
+
moncler-giub
|
6507 |
+
moncler-handbag
|
6508 |
+
moncler-homme
|
6509 |
+
moncler-jack
|
6510 |
+
moncler-jacke
|
6511 |
+
moncler-jassen
|
6512 |
+
moncler-jura
|
6513 |
+
moncler-klassiker
|
6514 |
+
moncler-man
|
6515 |
+
moncler-men
|
6516 |
+
moncler-online
|
6517 |
+
moncler-out
|
6518 |
+
moncler-padova
|
6519 |
+
moncler-paris
|
6520 |
+
moncler-parka
|
6521 |
+
moncler-pas
|
6522 |
+
moncler-pascher
|
6523 |
+
moncler-piumini
|
6524 |
+
moncler-polo
|
6525 |
+
moncler-pour
|
6526 |
+
moncler-prezzi
|
6527 |
+
moncler-pullover
|
6528 |
+
moncler-quincy
|
6529 |
+
moncler-sito
|
6530 |
+
moncler-ski
|
6531 |
+
moncler-sold
|
6532 |
+
moncler-store
|
6533 |
+
moncler-strickjacke
|
6534 |
+
moncler-sweater
|
6535 |
+
moncler-tibet
|
6536 |
+
moncler-uk
|
6537 |
+
moncler-uomo
|
6538 |
+
moncler-vast
|
6539 |
+
moncler-väst
|
6540 |
+
moncler-vente
|
6541 |
+
moncler-vest
|
6542 |
+
moncler-vos
|
6543 |
+
moncler-weste
|
6544 |
+
moncler-westen
|
6545 |
+
moncler.arkis
|
6546 |
+
monclerberriat
|
6547 |
+
monclercap
|
6548 |
+
monclercloth
|
6549 |
+
monclercoat
|
6550 |
+
monclerdonn
|
6551 |
+
monclerfemme
|
6552 |
+
monclerfirenze
|
6553 |
+
monclergiub
|
6554 |
+
monclerhandbag
|
6555 |
+
monclerhomme
|
6556 |
+
monclerjack
|
6557 |
+
monclerjacke
|
6558 |
+
monclerjassen
|
6559 |
+
monclerjura
|
6560 |
+
monclerklassiker
|
6561 |
+
monclerman
|
6562 |
+
monclermen
|
6563 |
+
moncleronline
|
6564 |
+
monclerout
|
6565 |
+
monclerpadova
|
6566 |
+
monclerparis
|
6567 |
+
monclerparka
|
6568 |
+
monclerpas
|
6569 |
+
monclerpascher
|
6570 |
+
monclerpiumini
|
6571 |
+
monclerpolo
|
6572 |
+
monclerpour
|
6573 |
+
monclerprezzi
|
6574 |
+
monclerpullover
|
6575 |
+
monclerquincy
|
6576 |
+
monclersito
|
6577 |
+
monclerski
|
6578 |
+
monclersold
|
6579 |
+
monclerstore
|
6580 |
+
monclerstrickjacke
|
6581 |
+
monclersweater
|
6582 |
+
monclertibet
|
6583 |
+
moncleruk
|
6584 |
+
moncleruomo
|
6585 |
+
monclervast
|
6586 |
+
monclerväst
|
6587 |
+
monclervente
|
6588 |
+
monclervest
|
6589 |
+
monclervos
|
6590 |
+
monclerweste
|
6591 |
+
monclerwesten
|
6592 |
+
monday deal
|
6593 |
+
monday sale
|
6594 |
+
monday ugg
|
6595 |
+
monday-deal
|
6596 |
+
monday-sale
|
6597 |
+
monday-ugg
|
6598 |
+
mondaydeal
|
6599 |
+
mondaysale
|
6600 |
+
mondayugg
|
6601 |
+
money primar
|
6602 |
+
money-mak
|
6603 |
+
money-primar
|
6604 |
+
money-site
|
6605 |
+
money-with
|
6606 |
+
money.htm
|
6607 |
+
moneyfast
|
6608 |
+
moneymak
|
6609 |
+
moneyprimar
|
6610 |
+
monohydrate
|
6611 |
+
monroussillon
|
6612 |
+
monster beat
|
6613 |
+
monster_
|
6614 |
+
monster-beat
|
6615 |
+
monster-head
|
6616 |
+
monster/beat
|
6617 |
+
monsterbeat
|
6618 |
+
monsterhead
|
6619 |
+
monsterjapan
|
6620 |
+
monsterjp
|
6621 |
+
montblanc boutique
|
6622 |
+
montblanc franc
|
6623 |
+
montblanc japan
|
6624 |
+
montblanc jp
|
6625 |
+
montblanc kuge
|
6626 |
+
montblanc meister
|
6627 |
+
montblanc paris
|
6628 |
+
montblanc pen
|
6629 |
+
montblanc sold
|
6630 |
+
montblanc stylo
|
6631 |
+
montblanc-boutique
|
6632 |
+
montblanc-franc
|
6633 |
+
montblanc-japan
|
6634 |
+
montblanc-jp
|
6635 |
+
montblanc-kuge
|
6636 |
+
montblanc-meister
|
6637 |
+
montblanc-paris
|
6638 |
+
montblanc-pen
|
6639 |
+
montblanc-sold
|
6640 |
+
montblanc-stylo
|
6641 |
+
montblancboutique
|
6642 |
+
montblancfranc
|
6643 |
+
montblancjapan
|
6644 |
+
montblancjp
|
6645 |
+
montblanckuge
|
6646 |
+
montblancmeister
|
6647 |
+
montblancparis
|
6648 |
+
montblancpen
|
6649 |
+
montblancsold
|
6650 |
+
montblancstylo
|
6651 |
+
montrefemme
|
6652 |
+
more-deal
|
6653 |
+
morelvjp
|
6654 |
+
morpg
|
6655 |
+
mortgage.htm
|
6656 |
+
mortgagecalc
|
6657 |
+
moscow-model
|
6658 |
+
most-effective
|
6659 |
+
mostra video
|
6660 |
+
mostra-video
|
6661 |
+
mostravideo
|
6662 |
+
movie-online
|
6663 |
+
movie-zone
|
6664 |
+
movieonline
|
6665 |
+
movies-online
|
6666 |
+
movies-zone
|
6667 |
+
moviesandfilm
|
6668 |
+
moviesdl
|
6669 |
+
moviesonline
|
6670 |
+
movieszone
|
6671 |
+
moviezone
|
6672 |
+
moгe
|
6673 |
+
mp3-download
|
6674 |
+
mp3la.ru
|
6675 |
+
mp3player
|
6676 |
+
mpnth
|
6677 |
+
mrant sneak
|
6678 |
+
mrant-sneak
|
6679 |
+
mrantsneak
|
6680 |
+
msgnum
|
6681 |
+
much-boot
|
6682 |
+
much-gucci
|
6683 |
+
muchgucci
|
6684 |
+
mulberry bag
|
6685 |
+
mulberry handbag
|
6686 |
+
mulberry oak
|
6687 |
+
mulberry out
|
6688 |
+
mulberry purse
|
6689 |
+
mulberry tasker
|
6690 |
+
mulberry top
|
6691 |
+
mulberry uk
|
6692 |
+
mulberry-bag
|
6693 |
+
mulberry-fashion
|
6694 |
+
mulberry-handbag
|
6695 |
+
mulberry-oak
|
6696 |
+
mulberry-purse
|
6697 |
+
mulberry-tasker
|
6698 |
+
mulberry-top
|
6699 |
+
mulberry-uk
|
6700 |
+
mulberrybag
|
6701 |
+
mulberryfashion
|
6702 |
+
mulberryhandbag
|
6703 |
+
mulberrypurse
|
6704 |
+
mulberrytop
|
6705 |
+
muscle-suppl
|
6706 |
+
muscles exercis
|
6707 |
+
muscles-exercis
|
6708 |
+
musclesuppl
|
6709 |
+
muscular abdomen
|
6710 |
+
muscular-abdomen
|
6711 |
+
muscularwom
|
6712 |
+
mustangs http
|
6713 |
+
mutuelle sante
|
6714 |
+
mutuelle-sante
|
6715 |
+
mutuelles sante
|
6716 |
+
mutuelles-sante
|
6717 |
+
muzyczna
|
6718 |
+
muzyczny
|
6719 |
+
my bebo
|
6720 |
+
my blog
|
6721 |
+
my hermes
|
6722 |
+
my homepag
|
6723 |
+
my online
|
6724 |
+
my weblog
|
6725 |
+
my website
|
6726 |
+
my-bebo
|
6727 |
+
my-blog
|
6728 |
+
my-hermes
|
6729 |
+
my-homepag
|
6730 |
+
my-new-ip
|
6731 |
+
my-online
|
6732 |
+
my-virus
|
6733 |
+
my-weblog
|
6734 |
+
my-website
|
6735 |
+
mydead-
|
6736 |
+
mydomain
|
6737 |
+
myfitness
|
6738 |
+
mygiftcard
|
6739 |
+
myhermes
|
6740 |
+
myknee
|
6741 |
+
myleadsystem
|
6742 |
+
mylupus
|
6743 |
+
mynewsite
|
6744 |
+
mynfl
|
6745 |
+
myonline
|
6746 |
+
myqrop
|
6747 |
+
myreview.co
|
6748 |
+
mytest
|
6749 |
+
myvirus
|
6750 |
+
myweblog
|
6751 |
+
nail_art
|
6752 |
+
nail-art
|
6753 |
+
nail-fest
|
6754 |
+
nailart
|
6755 |
+
nailfest
|
6756 |
+
nailsjapan
|
6757 |
+
najlepsze
|
6758 |
+
nakedteen
|
6759 |
+
naltrexone
|
6760 |
+
name-brand
|
6761 |
+
nanogold
|
6762 |
+
naproxen
|
6763 |
+
natürlich
|
6764 |
+
natura.it
|
6765 |
+
natural cure
|
6766 |
+
natural-cure
|
6767 |
+
natural-way
|
6768 |
+
naturalcure
|
6769 |
+
naturalovarian
|
6770 |
+
naturalway
|
6771 |
+
natureto
|
6772 |
+
natürlich
|
6773 |
+
nba cappelli
|
6774 |
+
nba jersey
|
6775 |
+
nba_
|
6776 |
+
nba-cappelli
|
6777 |
+
nba-jersey
|
6778 |
+
nbajersey
|
6779 |
+
nbshoe
|
6780 |
+
need sex
|
6781 |
+
need-sex
|
6782 |
+
needmoney
|
6783 |
+
needsex
|
6784 |
+
negozi burberry
|
6785 |
+
negozi milano
|
6786 |
+
negozi online
|
6787 |
+
negozi-burberry
|
6788 |
+
negozi-milano
|
6789 |
+
negozi-online
|
6790 |
+
negoziburberry
|
6791 |
+
negozimilano
|
6792 |
+
negozio-hollister
|
6793 |
+
negoziohollister
|
6794 |
+
negozionline
|
6795 |
+
net/bilder
|
6796 |
+
net/fr/
|
6797 |
+
net/members/
|
6798 |
+
netload.in
|
6799 |
+
network scam
|
6800 |
+
network truth
|
6801 |
+
network-scam
|
6802 |
+
network-truth
|
6803 |
+
networkscam
|
6804 |
+
networktruth
|
6805 |
+
neurontin
|
6806 |
+
new gucci
|
6807 |
+
new jordan
|
6808 |
+
new weblog
|
6809 |
+
new-article
|
6810 |
+
new-balance
|
6811 |
+
new-gucci
|
6812 |
+
new-jordan
|
6813 |
+
new-oakley
|
6814 |
+
newarrival
|
6815 |
+
newarticle
|
6816 |
+
newbalance1
|
6817 |
+
newbalance2
|
6818 |
+
newblance-20
|
6819 |
+
newblance20
|
6820 |
+
newest news
|
6821 |
+
newest-news
|
6822 |
+
newgucci
|
6823 |
+
newhong
|
6824 |
+
newjordan
|
6825 |
+
newoakley
|
6826 |
+
newport 100s
|
6827 |
+
newport-100s
|
6828 |
+
newport100s
|
6829 |
+
news.in
|
6830 |
+
news/article
|
6831 |
+
newsarticle
|
6832 |
+
newss.
|
6833 |
+
newwebsite
|
6834 |
+
nexopia
|
6835 |
+
nfl austr
|
6836 |
+
nfl italia
|
6837 |
+
nfl jers
|
6838 |
+
nfl shop
|
6839 |
+
nfl-beanie
|
6840 |
+
nfl-italia
|
6841 |
+
nfl-jers
|
6842 |
+
nfl-official
|
6843 |
+
nfl-shop
|
6844 |
+
nfljers
|
6845 |
+
nflofficial
|
6846 |
+
nflshop
|
6847 |
+
nfr.cfm
|
6848 |
+
nhl jersey
|
6849 |
+
nhl replica
|
6850 |
+
nhl-jersey
|
6851 |
+
nhl-replica
|
6852 |
+
nhlreplica
|
6853 |
+
niaspan
|
6854 |
+
nice paragraph
|
6855 |
+
nice practice
|
6856 |
+
nice-paragraph
|
6857 |
+
nice-practice
|
6858 |
+
nicki-mariah
|
6859 |
+
nicoban
|
6860 |
+
nicolasbit
|
6861 |
+
nicе
|
6862 |
+
nieruchomosci
|
6863 |
+
nike 5.0
|
6864 |
+
nike free
|
6865 |
+
nike jersey
|
6866 |
+
nike jordan
|
6867 |
+
nike kd
|
6868 |
+
nike mercurial
|
6869 |
+
nike run
|
6870 |
+
nike shoe
|
6871 |
+
nike total
|
6872 |
+
nike_
|
6873 |
+
nike-and-shoe
|
6874 |
+
nike-blazer
|
6875 |
+
nike-dunk
|
6876 |
+
nike-free
|
6877 |
+
nike-freerun
|
6878 |
+
nike-jersey
|
6879 |
+
nike-jordan
|
6880 |
+
nike-kd
|
6881 |
+
nike-main
|
6882 |
+
nike-mercurial
|
6883 |
+
nike-run
|
6884 |
+
nike-shoe
|
6885 |
+
nike-total
|
6886 |
+
nike1
|
6887 |
+
nike2
|
6888 |
+
nikeairmax
|
6889 |
+
nikeairshop
|
6890 |
+
nikeandshoe
|
6891 |
+
nikeause
|
6892 |
+
nikeblazer
|
6893 |
+
nikedunk
|
6894 |
+
nikefree
|
6895 |
+
nikefreerun
|
6896 |
+
nikejersey
|
6897 |
+
nikejordan
|
6898 |
+
nikemain
|
6899 |
+
nikepasch
|
6900 |
+
nikerun
|
6901 |
+
nikeshoe
|
6902 |
+
nikeshop
|
6903 |
+
nikesportjap
|
6904 |
+
nikesportjp
|
6905 |
+
niketokyo
|
6906 |
+
niketotal
|
6907 |
+
ninja sword
|
6908 |
+
ninja-sword
|
6909 |
+
ninjasword
|
6910 |
+
niselv.co
|
6911 |
+
nitraazepam
|
6912 |
+
nitrazepam
|
6913 |
+
nizoral
|
6914 |
+
nm.ru
|
6915 |
+
no collateral
|
6916 |
+
no guarant
|
6917 |
+
no-cache
|
6918 |
+
no-collateral
|
6919 |
+
no-credit
|
6920 |
+
no-fuss
|
6921 |
+
no-guarant
|
6922 |
+
no-hassle
|
6923 |
+
no-prescript
|
6924 |
+
no1.co
|
6925 |
+
nocache
|
6926 |
+
nocredit
|
6927 |
+
nohassle
|
6928 |
+
nolvadex
|
6929 |
+
norge canad
|
6930 |
+
norge-canad
|
6931 |
+
norgecanad
|
6932 |
+
north_face
|
6933 |
+
north+face
|
6934 |
+
northface pascher
|
6935 |
+
northface-canad
|
6936 |
+
northface-jack
|
6937 |
+
northface-out
|
6938 |
+
northface-pascher
|
6939 |
+
northface-sale
|
6940 |
+
northface-uk
|
6941 |
+
northface-us
|
6942 |
+
northfacecanad
|
6943 |
+
northfacejack
|
6944 |
+
northfaceout
|
6945 |
+
northfacepascher
|
6946 |
+
northfacesale
|
6947 |
+
northfacetr
|
6948 |
+
northfaceuk
|
6949 |
+
northfaceus
|
6950 |
+
northfaceya
|
6951 |
+
northfce
|
6952 |
+
norvasc
|
6953 |
+
not-dienst
|
6954 |
+
not|
|
6955 |
+
notdienst
|
6956 |
+
notraty
|
6957 |
+
nouveau maillot
|
6958 |
+
nouveau-maillot
|
6959 |
+
nouveaumaillot
|
6960 |
+
nouvelles sneaker
|
6961 |
+
nouvelles-sneaker
|
6962 |
+
novinki_
|
6963 |
+
now.in
|
6964 |
+
nude-ass
|
6965 |
+
nude.htm
|
6966 |
+
nufactur
|
6967 |
+
nеar
|
6968 |
+
nօt
|
6969 |
+
oakeyspascher
|
6970 |
+
oakley canad
|
6971 |
+
oakley caveat
|
6972 |
+
oakley cross
|
6973 |
+
oakley five
|
6974 |
+
oakley frogskin
|
6975 |
+
oakley glass
|
6976 |
+
oakley juliet
|
6977 |
+
oakley out
|
6978 |
+
oakley polarized
|
6979 |
+
oakley sale
|
6980 |
+
oakley sunglass
|
6981 |
+
oakley_
|
6982 |
+
oakley-active
|
6983 |
+
oakley-canad
|
6984 |
+
oakley-caveat
|
6985 |
+
oakley-cheap
|
6986 |
+
oakley-cross
|
6987 |
+
oakley-five
|
6988 |
+
oakley-juliet
|
6989 |
+
oakley-out
|
6990 |
+
oakley-polarized
|
6991 |
+
oakley-store
|
6992 |
+
oakley-straight
|
6993 |
+
oakley-sunglass
|
6994 |
+
oakleyactive
|
6995 |
+
oakleycanad
|
6996 |
+
oakleycaveat
|
6997 |
+
oakleycheap
|
6998 |
+
oakleycross
|
6999 |
+
oakleyjuliet
|
7000 |
+
oakleymedusa
|
7001 |
+
oakleyout
|
7002 |
+
oakleypascher
|
7003 |
+
oakleyru
|
7004 |
+
oakleys sunglass
|
7005 |
+
oakleys-sunglass
|
7006 |
+
oakleys.net
|
7007 |
+
oakleysale
|
7008 |
+
oakleysj
|
7009 |
+
oakleyssunglass
|
7010 |
+
oakleystore
|
7011 |
+
oakleysuk
|
7012 |
+
oakleysunglass
|
7013 |
+
oakleytokyo
|
7014 |
+
oakleyuk
|
7015 |
+
öáøåâïïê
|
7016 |
+
obey posse
|
7017 |
+
obey-posse
|
7018 |
+
obtain consol
|
7019 |
+
obtain-consol
|
7020 |
+
obuwia
|
7021 |
+
obuwie
|
7022 |
+
oculosfeminino
|
7023 |
+
odszkodowania
|
7024 |
+
odziez
|
7025 |
+
oem-software
|
7026 |
+
oemsoftware
|
7027 |
+
of herpes
|
7028 |
+
of internet
|
7029 |
+
of-herpes
|
7030 |
+
of-internet
|
7031 |
+
offer outlet
|
7032 |
+
offer watch
|
7033 |
+
offer-outlet
|
7034 |
+
offer-watch
|
7035 |
+
offer.net
|
7036 |
+
offer.weebly
|
7037 |
+
offeroutlet
|
7038 |
+
offerwatch
|
7039 |
+
office autopilot
|
7040 |
+
office-autopilot
|
7041 |
+
officeautopilot
|
7042 |
+
official website
|
7043 |
+
official-sale
|
7044 |
+
official-steeler
|
7045 |
+
official-style
|
7046 |
+
official-ugg
|
7047 |
+
official-website
|
7048 |
+
officialmailsite
|
7049 |
+
officialsale
|
7050 |
+
officialsteeler
|
7051 |
+
officialstyle
|
7052 |
+
officialteamshop
|
7053 |
+
officialugg
|
7054 |
+
officialwebsite
|
7055 |
+
offight
|
7056 |
+
ofhuman
|
7057 |
+
oit|
|
7058 |
+
ojectx
|
7059 |
+
ok-cheap
|
7060 |
+
ok-sex
|
7061 |
+
okanyway
|
7062 |
+
okcanadagoose
|
7063 |
+
okcheap
|
7064 |
+
okpay
|
7065 |
+
oksex
|
7066 |
+
oksunglass
|
7067 |
+
old|
|
7068 |
+
once-in-a-lifetime
|
7069 |
+
one nike
|
7070 |
+
one-nike
|
7071 |
+
oneminutesite
|
7072 |
+
onenike
|
7073 |
+
onestrap
|
7074 |
+
online cash
|
7075 |
+
online casino
|
7076 |
+
online class
|
7077 |
+
online dating
|
7078 |
+
online espana
|
7079 |
+
online españa
|
7080 |
+
online gambling
|
7081 |
+
online gry
|
7082 |
+
online loan
|
7083 |
+
online out
|
7084 |
+
online pokie
|
7085 |
+
online shoe
|
7086 |
+
online shop
|
7087 |
+
online usa
|
7088 |
+
online-blog
|
7089 |
+
online-business
|
7090 |
+
online-cash
|
7091 |
+
online-casino
|
7092 |
+
online-cert
|
7093 |
+
online-class
|
7094 |
+
online-dating
|
7095 |
+
online-espana
|
7096 |
+
online-españa
|
7097 |
+
online-gambling
|
7098 |
+
online-gry
|
7099 |
+
online-invest
|
7100 |
+
online-kredit
|
7101 |
+
online-loan
|
7102 |
+
online-market
|
7103 |
+
online-med
|
7104 |
+
online-money
|
7105 |
+
online-out
|
7106 |
+
online-pokie
|
7107 |
+
online-sale
|
7108 |
+
online-shoe
|
7109 |
+
online-shop
|
7110 |
+
online-store
|
7111 |
+
online-usa
|
7112 |
+
online.de
|
7113 |
+
online.htm
|
7114 |
+
online.in
|
7115 |
+
online.web
|
7116 |
+
onlinebackup.
|
7117 |
+
onlineblog
|
7118 |
+
onlinebusiness
|
7119 |
+
onlinebuy
|
7120 |
+
onlinecash
|
7121 |
+
onlinecasino
|
7122 |
+
onlinecert
|
7123 |
+
onlinedating
|
7124 |
+
onlinede.
|
7125 |
+
onlinegambling
|
7126 |
+
onlineinvest
|
7127 |
+
onlinejp
|
7128 |
+
onlinekredit
|
7129 |
+
onlineloan
|
7130 |
+
onlinemed
|
7131 |
+
onlinemoney
|
7132 |
+
onlineout
|
7133 |
+
onlinepoker
|
7134 |
+
onlinepris
|
7135 |
+
onlines.co
|
7136 |
+
onlines.web
|
7137 |
+
onlinesale
|
7138 |
+
onlineshoe
|
7139 |
+
onlineshop
|
7140 |
+
onlinestore
|
7141 |
+
only pokie
|
7142 |
+
only-deal
|
7143 |
+
only-pokie
|
7144 |
+
onlyway
|
7145 |
+
onsale-
|
7146 |
+
onsale.asp
|
7147 |
+
onsale.co
|
7148 |
+
onsale.htm
|
7149 |
+
onsale.php
|
7150 |
+
onsales.co
|
7151 |
+
openair
|
7152 |
+
opinion.in
|
7153 |
+
opinions.in
|
7154 |
+
option binaire
|
7155 |
+
option-binaire
|
7156 |
+
options binaire
|
7157 |
+
options-binaire
|
7158 |
+
options-trad
|
7159 |
+
optionstrad
|
7160 |
+
oral-sex
|
7161 |
+
order_type
|
7162 |
+
ordersoma
|
7163 |
+
organogold
|
7164 |
+
orgazma
|
7165 |
+
oriflame
|
7166 |
+
original http
|
7167 |
+
orlistat
|
7168 |
+
osobistosci
|
7169 |
+
osobistości
|
7170 |
+
otonanocoach
|
7171 |
+
otoplasty
|
7172 |
+
otvety
|
7173 |
+
outelt
|
7174 |
+
outilclient
|
7175 |
+
outlet bag
|
7176 |
+
outlet canad
|
7177 |
+
outlet france
|
7178 |
+
outlet handbag
|
7179 |
+
outlet hermes
|
7180 |
+
outlet hogan
|
7181 |
+
outlet italia
|
7182 |
+
outlet louis
|
7183 |
+
outlet moncler
|
7184 |
+
outlet oakley
|
7185 |
+
outlet online
|
7186 |
+
outlet shoe
|
7187 |
+
outlet store
|
7188 |
+
outlet uk
|
7189 |
+
outlet usa
|
7190 |
+
outlet vancouver
|
7191 |
+
outlet woolrich
|
7192 |
+
outlet_
|
7193 |
+
outlet-austr
|
7194 |
+
outlet-canad
|
7195 |
+
outlet-france
|
7196 |
+
outlet-hermes
|
7197 |
+
outlet-hogan
|
7198 |
+
outlet-italia
|
7199 |
+
outlet-japan
|
7200 |
+
outlet-louis
|
7201 |
+
outlet-mart
|
7202 |
+
outlet-moncler
|
7203 |
+
outlet-online
|
7204 |
+
outlet-sale
|
7205 |
+
outlet-shoe
|
7206 |
+
outlet-shop
|
7207 |
+
outlet-store
|
7208 |
+
outlet-uk
|
7209 |
+
outlet-usa
|
7210 |
+
outlet-vancouver
|
7211 |
+
outlet-web
|
7212 |
+
outlet-woolrich
|
7213 |
+
outlet.co
|
7214 |
+
outlet.net
|
7215 |
+
outlet.org
|
7216 |
+
outlet.uk
|
7217 |
+
outlet.us
|
7218 |
+
outlet.weebly
|
7219 |
+
outlet4u
|
7220 |
+
outlet2012
|
7221 |
+
outlet2013
|
7222 |
+
outlet2014
|
7223 |
+
outletaustr
|
7224 |
+
outletbag
|
7225 |
+
outletcanad
|
7226 |
+
outletforsale
|
7227 |
+
outletfrance
|
7228 |
+
outlethermes
|
7229 |
+
outletitalia
|
7230 |
+
outletjapan
|
7231 |
+
outletlouis
|
7232 |
+
outletlove
|
7233 |
+
outletmart
|
7234 |
+
outletmoncler
|
7235 |
+
outletonline
|
7236 |
+
outlets-online
|
7237 |
+
outlets-sale
|
7238 |
+
outlets.co
|
7239 |
+
outlets.net
|
7240 |
+
outlets.org
|
7241 |
+
outlets.us
|
7242 |
+
outletsale
|
7243 |
+
outletshoe
|
7244 |
+
outletshop
|
7245 |
+
outletsonline
|
7246 |
+
outletssale
|
7247 |
+
outletstore
|
7248 |
+
outletuk
|
7249 |
+
outletusa
|
7250 |
+
outletweb
|
7251 |
+
outletwoolrich
|
7252 |
+
outplacement-compan
|
7253 |
+
outplacements
|
7254 |
+
outsourcing-compan
|
7255 |
+
ovariancyst
|
7256 |
+
own blogroll
|
7257 |
+
own-blogroll
|
7258 |
+
ownersinsur
|
7259 |
+
oxycodone
|
7260 |
+
oxycontin
|
7261 |
+
oympia
|
7262 |
+
oьtɑin
|
7263 |
+
p90x
|
7264 |
+
packersjersey
|
7265 |
+
page_
|
7266 |
+
page.tl
|
7267 |
+
page/pag
|
7268 |
+
pagss.htm
|
7269 |
+
pain-behind
|
7270 |
+
pain-relief.
|
7271 |
+
painbehind
|
7272 |
+
painrelief.
|
7273 |
+
paintedfor
|
7274 |
+
panda-shoe
|
7275 |
+
pandashoe
|
7276 |
+
pandora charm
|
7277 |
+
pandora online
|
7278 |
+
pandora sale
|
7279 |
+
pandora-bracelet
|
7280 |
+
pandora-charm
|
7281 |
+
pandora-jewelry
|
7282 |
+
pandora-online
|
7283 |
+
pandora-sale
|
7284 |
+
pandoraau
|
7285 |
+
pandorabracelet
|
7286 |
+
pandoracharm
|
7287 |
+
pandorajewelry
|
7288 |
+
pandorauk
|
7289 |
+
panerai clock
|
7290 |
+
panerai watch
|
7291 |
+
panerai-clock
|
7292 |
+
panerai-watch
|
7293 |
+
paneraiclock
|
7294 |
+
paneraiwatch
|
7295 |
+
panier site
|
7296 |
+
panier-site
|
7297 |
+
paniersite
|
7298 |
+
panthers jersey
|
7299 |
+
panthers merch
|
7300 |
+
panthers store
|
7301 |
+
panthers-jersey
|
7302 |
+
panthers-merch
|
7303 |
+
panthers-store
|
7304 |
+
panthersmerch
|
7305 |
+
panthersstore
|
7306 |
+
panty pic
|
7307 |
+
panty play
|
7308 |
+
panty sex
|
7309 |
+
panty-pic
|
7310 |
+
panty-play
|
7311 |
+
panty-sex
|
7312 |
+
pantymania
|
7313 |
+
pantypic
|
7314 |
+
pantyplay
|
7315 |
+
par/index
|
7316 |
+
paradisiaque
|
7317 |
+
paragraph writing
|
7318 |
+
paragraph-writing
|
7319 |
+
parajumpers
|
7320 |
+
parchet triplu
|
7321 |
+
parchet-triplu
|
7322 |
+
paretologic
|
7323 |
+
paris http
|
7324 |
+
paris model
|
7325 |
+
paris-for
|
7326 |
+
paris-model
|
7327 |
+
paris-royal
|
7328 |
+
parismodel
|
7329 |
+
parkiety
|
7330 |
+
part mariage
|
7331 |
+
part-mariage
|
7332 |
+
particular article
|
7333 |
+
particular-article
|
7334 |
+
party_feet
|
7335 |
+
party-poker
|
7336 |
+
partypoker
|
7337 |
+
pas cher
|
7338 |
+
pas-cher
|
7339 |
+
pascher
|
7340 |
+
pascherfr
|
7341 |
+
pascheroakley
|
7342 |
+
passprefix
|
7343 |
+
password generat
|
7344 |
+
password-generat
|
7345 |
+
passwort
|
7346 |
+
passwrot
|
7347 |
+
patagonia-zone
|
7348 |
+
patagoniazone
|
7349 |
+
patrao-online
|
7350 |
+
patraoonline
|
7351 |
+
patriots hat
|
7352 |
+
patriots-hat
|
7353 |
+
paulsmith-cheap
|
7354 |
+
paulsmith-shop
|
7355 |
+
paulsmith1
|
7356 |
+
paulsmith2
|
7357 |
+
paulsmith201
|
7358 |
+
paulsmithcheap
|
7359 |
+
paulsmithka
|
7360 |
+
paulsmithsa
|
7361 |
+
paulsmithshop
|
7362 |
+
paulsmithsu
|
7363 |
+
paxil
|
7364 |
+
pay_day
|
7365 |
+
pay-as-you-go
|
7366 |
+
payday loan
|
7367 |
+
payday-loan
|
7368 |
+
payday-on
|
7369 |
+
payday.co
|
7370 |
+
paydayloan
|
7371 |
+
paydaynote
|
7372 |
+
paydayon
|
7373 |
+
payed off
|
7374 |
+
payed-off
|
7375 |
+
paypal-cash
|
7376 |
+
paypalcash
|
7377 |
+
payroll-calc
|
7378 |
+
pbrolme
|
7379 |
+
pc health
|
7380 |
+
pc windows
|
7381 |
+
pc-access
|
7382 |
+
pc-health
|
7383 |
+
pc-windows
|
7384 |
+
pcaccess
|
7385 |
+
pchealthadvis
|
7386 |
+
pcstuff
|
7387 |
+
penis.co
|
7388 |
+
penisadv
|
7389 |
+
penisenlarg
|
7390 |
+
penny-auction
|
7391 |
+
penny-bid
|
7392 |
+
penny-stock
|
7393 |
+
pennyauction
|
7394 |
+
pennybid
|
7395 |
+
pennystock
|
7396 |
+
per-week
|
7397 |
+
percocet
|
7398 |
+
perday.co
|
7399 |
+
perfectvpn
|
7400 |
+
perfectwriting
|
7401 |
+
permission allow
|
7402 |
+
permission-allow
|
7403 |
+
permonth.co
|
7404 |
+
personal-experience
|
7405 |
+
personal-injury
|
7406 |
+
personalinjury
|
7407 |
+
personnalis
|
7408 |
+
perweek
|
7409 |
+
petencies
|
7410 |
+
pflegeversicherung
|
7411 |
+
pflegezusatzversicherung
|
7412 |
+
pg/blog
|
7413 |
+
pg/forum
|
7414 |
+
pg/profile
|
7415 |
+
pharmacies
|
7416 |
+
pharmacy
|
7417 |
+
pharmaun
|
7418 |
+
phentermine
|
7419 |
+
phlebotomy
|
7420 |
+
phon-store
|
7421 |
+
phone advert
|
7422 |
+
phone free
|
7423 |
+
phone-advert
|
7424 |
+
phone-free
|
7425 |
+
phone-jammer
|
7426 |
+
phone-lookup
|
7427 |
+
phone-number-lookup
|
7428 |
+
phone-store
|
7429 |
+
phoneadvert
|
7430 |
+
phoneforsale
|
7431 |
+
phonefree
|
7432 |
+
phonejammer
|
7433 |
+
phonelookup
|
7434 |
+
phonescanad
|
7435 |
+
phonesforsale
|
7436 |
+
phonestore
|
7437 |
+
phonstore
|
7438 |
+
photo/online
|
7439 |
+
photoeditingdeal
|
7440 |
+
php?article
|
7441 |
+
php?rowstart
|
7442 |
+
php?showuser
|
7443 |
+
php?title
|
7444 |
+
php5?title
|
7445 |
+
phpbb2
|
7446 |
+
phpinfo
|
7447 |
+
phync
|
7448 |
+
pidarashechk
|
7449 |
+
pignee
|
7450 |
+
pillonline
|
7451 |
+
pills.co
|
7452 |
+
pillsonline
|
7453 |
+
pink large
|
7454 |
+
pink-large
|
7455 |
+
pinklarge
|
7456 |
+
piscine
|
7457 |
+
piumini moncler
|
7458 |
+
piumini-moncler
|
7459 |
+
piuminimoncler
|
7460 |
+
piumino moncler
|
7461 |
+
piumino-moncler
|
7462 |
+
piuminomoncler
|
7463 |
+
plansare
|
7464 |
+
plavix
|
7465 |
+
play-free
|
7466 |
+
play-online
|
7467 |
+
playerblock
|
7468 |
+
playfree
|
7469 |
+
playonline
|
7470 |
+
plazajp
|
7471 |
+
pleasant designed
|
7472 |
+
pleasant good
|
7473 |
+
pleasant-designed
|
7474 |
+
pleasant-good
|
7475 |
+
pleassant
|
7476 |
+
pleease
|
7477 |
+
plombier http
|
7478 |
+
plombier paris
|
7479 |
+
plombier-paris
|
7480 |
+
plumbingservice
|
7481 |
+
plus-size
|
7482 |
+
plussize
|
7483 |
+
plytki
|
7484 |
+
plz respond
|
7485 |
+
plz-respond
|
7486 |
+
poco prezzo
|
7487 |
+
poco-prezzo
|
7488 |
+
point|
|
7489 |
+
points-generator
|
7490 |
+
pointsgenerator
|
7491 |
+
poished
|
7492 |
+
pojapan
|
7493 |
+
poker-chip
|
7494 |
+
poker-money
|
7495 |
+
poker-strateg
|
7496 |
+
pokera
|
7497 |
+
pokerchip
|
7498 |
+
pokermoney
|
7499 |
+
pokerstrateg
|
7500 |
+
pokie machine
|
7501 |
+
pokie online
|
7502 |
+
pokie-machine
|
7503 |
+
pokie-online
|
7504 |
+
pokiemachine
|
7505 |
+
pokieonline
|
7506 |
+
pokies online
|
7507 |
+
pokies-online
|
7508 |
+
pokiesonline
|
7509 |
+
pokornému
|
7510 |
+
polnocno
|
7511 |
+
pólnocno
|
7512 |
+
północno
|
7513 |
+
polo out
|
7514 |
+
polo ralph
|
7515 |
+
polo_
|
7516 |
+
polo-lacoste
|
7517 |
+
polo-ralph
|
7518 |
+
poloralph
|
7519 |
+
polos ralph
|
7520 |
+
polos-ralph
|
7521 |
+
polosralph
|
7522 |
+
popular brand
|
7523 |
+
popular-brand
|
7524 |
+
popularna
|
7525 |
+
popularną markę
|
7526 |
+
porn comic
|
7527 |
+
porn live
|
7528 |
+
porn sex
|
7529 |
+
porn vid
|
7530 |
+
porn-comic
|
7531 |
+
porn-live
|
7532 |
+
porn-sex
|
7533 |
+
porn-vid
|
7534 |
+
porn.
|
7535 |
+
pornlive
|
7536 |
+
porno gratuit
|
7537 |
+
porno http
|
7538 |
+
porno stream
|
7539 |
+
porno-
|
7540 |
+
porno-gratuit
|
7541 |
+
porno-stream
|
7542 |
+
porno.
|
7543 |
+
porno@
|
7544 |
+
pornolady
|
7545 |
+
pornsex
|
7546 |
+
possess
|
7547 |
+
post post
|
7548 |
+
post_
|
7549 |
+
post-post
|
7550 |
+
post-service
|
7551 |
+
post.much
|
7552 |
+
post.pw
|
7553 |
+
postcarf
|
7554 |
+
posting comment
|
7555 |
+
posting-comment
|
7556 |
+
posting!
|
7557 |
+
posts.asp
|
7558 |
+
posttestimonial
|
7559 |
+
powerball
|
7560 |
+
powerbank
|
7561 |
+
pozew.
|
7562 |
+
poznajseo
|
7563 |
+
poznan
|
7564 |
+
pozycjonowanie
|
7565 |
+
pozyczka
|
7566 |
+
pozyczki
|
7567 |
+
pp-class
|
7568 |
+
prada bag
|
7569 |
+
prada cheap
|
7570 |
+
prada dress
|
7571 |
+
prada handbag
|
7572 |
+
prada online
|
7573 |
+
prada out
|
7574 |
+
prada sac
|
7575 |
+
prada_
|
7576 |
+
prada-bag
|
7577 |
+
prada-cheap
|
7578 |
+
prada-new
|
7579 |
+
prada-online
|
7580 |
+
prada-out
|
7581 |
+
prada-sac
|
7582 |
+
pradabag
|
7583 |
+
pradacheap
|
7584 |
+
pradadesign
|
7585 |
+
pradagirl
|
7586 |
+
pradanew
|
7587 |
+
pradaonline
|
7588 |
+
pradaout
|
7589 |
+
pradasac
|
7590 |
+
prawnik
|
7591 |
+
prazosin
|
7592 |
+
prednisone
|
7593 |
+
pregnancysymptom
|
7594 |
+
premarin
|
7595 |
+
prematureejaculat
|
7596 |
+
premium key
|
7597 |
+
premium-account
|
7598 |
+
premium-cig
|
7599 |
+
premiumcig
|
7600 |
+
prentice capital
|
7601 |
+
prentice-capital
|
7602 |
+
prenticecapital
|
7603 |
+
prepaid-credit
|
7604 |
+
preparationwise
|
7605 |
+
prescription.htm
|
7606 |
+
presentation subsequent
|
7607 |
+
presentation-subsequent
|
7608 |
+
preserveness
|
7609 |
+
pressrelease.net
|
7610 |
+
pretty worth
|
7611 |
+
pretty-worth
|
7612 |
+
previcox
|
7613 |
+
price-of-gold
|
7614 |
+
pricetobook
|
7615 |
+
priligy
|
7616 |
+
primeessay
|
7617 |
+
private ftp
|
7618 |
+
private-ftp
|
7619 |
+
private-label
|
7620 |
+
privatelabel
|
7621 |
+
prix ugg
|
7622 |
+
prix-ugg
|
7623 |
+
prixugg
|
7624 |
+
pro key
|
7625 |
+
pro review
|
7626 |
+
pro-review
|
7627 |
+
proactol
|
7628 |
+
procedures-for
|
7629 |
+
proceesing
|
7630 |
+
produce article
|
7631 |
+
produce-article
|
7632 |
+
producer excellent
|
7633 |
+
producer-excellent
|
7634 |
+
product
|
7635 |
+
product-sale
|
7636 |
+
product/product
|
7637 |
+
produkcja
|
7638 |
+
profesjonal
|
7639 |
+
professional 2007
|
7640 |
+
professional 2008
|
7641 |
+
professional 2010
|
7642 |
+
professional-ugg
|
7643 |
+
professionals.co
|
7644 |
+
professionalugg
|
7645 |
+
profile_
|
7646 |
+
profile/?u
|
7647 |
+
profile/blog
|
7648 |
+
profile/profile
|
7649 |
+
profiles/blog
|
7650 |
+
profiles/profile
|
7651 |
+
profissionais
|
7652 |
+
profit-margin
|
7653 |
+
profit-seek
|
7654 |
+
profits-
|
7655 |
+
profitseek
|
7656 |
+
prohormone
|
7657 |
+
proisxozhdenie
|
7658 |
+
project-earn
|
7659 |
+
prokey
|
7660 |
+
prokeyshop
|
7661 |
+
prom-dress
|
7662 |
+
promo artist
|
7663 |
+
promo-artist
|
7664 |
+
promo-shop
|
7665 |
+
promo-store
|
7666 |
+
promo+code
|
7667 |
+
promoartist
|
7668 |
+
promocja
|
7669 |
+
promocode
|
7670 |
+
promoshop
|
7671 |
+
promostore
|
7672 |
+
promosystem
|
7673 |
+
promotional bag
|
7674 |
+
propecia
|
7675 |
+
proper-ugg
|
7676 |
+
property pro
|
7677 |
+
property-pro
|
7678 |
+
propertypro
|
7679 |
+
properugg
|
7680 |
+
propranolol
|
7681 |
+
prostitutki
|
7682 |
+
protein-diet
|
7683 |
+
proteindiet
|
7684 |
+
provewhether
|
7685 |
+
provigil
|
7686 |
+
proxénétisme
|
7687 |
+
prozac-
|
7688 |
+
prywatne
|
7689 |
+
przepisane
|
7690 |
+
przeprowadzki
|
7691 |
+
przysiegly
|
7692 |
+
psych-clinic
|
7693 |
+
psychclinic
|
7694 |
+
publica-foto
|
7695 |
+
publikacja
|
7696 |
+
pucci dress
|
7697 |
+
pucci-dress
|
7698 |
+
pucci-out
|
7699 |
+
puccidress
|
7700 |
+
pucciout
|
7701 |
+
pufy.
|
7702 |
+
puma deutsch
|
7703 |
+
puma ferrari
|
7704 |
+
puma outlet
|
7705 |
+
puma paidat
|
7706 |
+
puma schuhe
|
7707 |
+
puma sneak
|
7708 |
+
puma-deutsch
|
7709 |
+
puma-drifter
|
7710 |
+
puma-ferrari
|
7711 |
+
puma-lauf
|
7712 |
+
puma-nice
|
7713 |
+
puma-outlet
|
7714 |
+
puma-paidat
|
7715 |
+
puma-schuhe
|
7716 |
+
puma-sneak
|
7717 |
+
pumadeutsch
|
7718 |
+
pumadrifter
|
7719 |
+
pumaferrari
|
7720 |
+
pumalauf
|
7721 |
+
pumanice
|
7722 |
+
pumaoutlet
|
7723 |
+
pumapaidat
|
7724 |
+
pumaschuhe
|
7725 |
+
pumasneak
|
7726 |
+
pure-jobs
|
7727 |
+
purse forum
|
7728 |
+
purse online
|
7729 |
+
purse out
|
7730 |
+
purse-forum
|
7731 |
+
purse-out
|
7732 |
+
purse-sale
|
7733 |
+
purseout
|
7734 |
+
purses online
|
7735 |
+
purses out
|
7736 |
+
purses-out
|
7737 |
+
purses-sale
|
7738 |
+
pursesout
|
7739 |
+
puzzle maker
|
7740 |
+
puzzle-maker
|
7741 |
+
puzzlemaker
|
7742 |
+
pytanie
|
7743 |
+
qampuz
|
7744 |
+
qquality
|
7745 |
+
qry_
|
7746 |
+
qtrade
|
7747 |
+
quality article
|
7748 |
+
quality post
|
7749 |
+
quality-article
|
7750 |
+
quality-post
|
7751 |
+
quartz-seiko
|
7752 |
+
quartzseiko
|
7753 |
+
queen chiffon
|
7754 |
+
queen clutch
|
7755 |
+
queen out
|
7756 |
+
queen-chiffon
|
7757 |
+
queen-clutch
|
7758 |
+
queen-out
|
7759 |
+
queenchiffon
|
7760 |
+
queenclutch
|
7761 |
+
queenjp
|
7762 |
+
queenoutlet
|
7763 |
+
querireda
|
7764 |
+
quick loans
|
7765 |
+
quick_
|
7766 |
+
quick-loan
|
7767 |
+
quickloan
|
7768 |
+
quincy femme
|
7769 |
+
quincy-femme
|
7770 |
+
quincyfemme
|
7771 |
+
quit-smoking
|
7772 |
+
qvc
|
7773 |
+
r?f?rence
|
7774 |
+
radikal.ru
|
7775 |
+
radiocarpea
|
7776 |
+
raiders hat
|
7777 |
+
raiders-hat
|
7778 |
+
raidershat
|
7779 |
+
raloxifene
|
7780 |
+
ralph-lauren
|
7781 |
+
ramipril
|
7782 |
+
rank-build
|
7783 |
+
rankbuild
|
7784 |
+
ranking:
|
7785 |
+
rapid-pay
|
7786 |
+
rapidpay
|
7787 |
+
rasalinga
|
7788 |
+
rastreadores
|
7789 |
+
ravensfan
|
7790 |
+
ray-ban-aviator
|
7791 |
+
ray-ban-folding
|
7792 |
+
ray-bans
|
7793 |
+
rayban glass
|
7794 |
+
rayban_
|
7795 |
+
rayban-cheap
|
7796 |
+
rayban-glass
|
7797 |
+
raybaneye
|
7798 |
+
raybanglass
|
7799 |
+
raybanpascher
|
7800 |
+
raybanslunette
|
7801 |
+
raybansuk
|
7802 |
+
raybansun
|
7803 |
+
raybansunglass
|
7804 |
+
raybantokyo
|
7805 |
+
raybanuk
|
7806 |
+
razadyne
|
7807 |
+
readers-base
|
7808 |
+
readers' base
|
7809 |
+
readers’ base
|
7810 |
+
readyto
|
7811 |
+
real_estate
|
7812 |
+
real-estate-web
|
7813 |
+
real-estate.web
|
7814 |
+
realestate.co
|
7815 |
+
realestate.web
|
7816 |
+
realestate.wordpress
|
7817 |
+
reallywork.we
|
7818 |
+
realtor promo
|
7819 |
+
realtor-promo
|
7820 |
+
reasons-why
|
7821 |
+
reciclable
|
7822 |
+
recommended internet
|
7823 |
+
records.net
|
7824 |
+
recoverynow
|
7825 |
+
red christian
|
7826 |
+
red ugg
|
7827 |
+
red-ugg
|
7828 |
+
red+bottom+shoe
|
7829 |
+
redbottomshoe
|
7830 |
+
redirect_
|
7831 |
+
redirect.asp
|
7832 |
+
redskinsjersey
|
7833 |
+
redsoleshoe
|
7834 |
+
redugg
|
7835 |
+
redwingjp
|
7836 |
+
reebok baseball
|
7837 |
+
reebok scarpe
|
7838 |
+
reebok-baseball
|
7839 |
+
reebok-scarpe
|
7840 |
+
reebokscarpe
|
7841 |
+
reeview
|
7842 |
+
referencement
|
7843 |
+
référencement
|
7844 |
+
refluks
|
7845 |
+
reflux symptom
|
7846 |
+
reflux-symptom
|
7847 |
+
refluxsymptom
|
7848 |
+
reg_
|
7849 |
+
regarding blog
|
7850 |
+
regarfing
|
7851 |
+
registration strateg
|
7852 |
+
registration-strateg
|
7853 |
+
registrator
|
7854 |
+
registry-clean
|
7855 |
+
registry-fix
|
7856 |
+
registry-repair
|
7857 |
+
registry-tool
|
7858 |
+
registry+clean
|
7859 |
+
registry+fix
|
7860 |
+
registry+tool
|
7861 |
+
registryclean
|
7862 |
+
registryfix
|
7863 |
+
registryrepair
|
7864 |
+
registrytool
|
7865 |
+
reguliatory
|
7866 |
+
reirect
|
7867 |
+
rejersey.co
|
7868 |
+
rejersey.net
|
7869 |
+
rekla.
|
7870 |
+
reklamowe
|
7871 |
+
rekreacja
|
7872 |
+
relaxeԁ
|
7873 |
+
reliefsecret
|
7874 |
+
religion jeans
|
7875 |
+
religion-jeans
|
7876 |
+
religionjeans
|
7877 |
+
rellay
|
7878 |
+
remarkable post
|
7879 |
+
remarkable-post
|
7880 |
+
rent_in
|
7881 |
+
rent-car
|
7882 |
+
rentinsur
|
7883 |
+
replica bag
|
7884 |
+
replica birk
|
7885 |
+
replica china
|
7886 |
+
replica hand
|
7887 |
+
replica ip
|
7888 |
+
replica jersey
|
7889 |
+
replica louis
|
7890 |
+
replica nba
|
7891 |
+
replica oakley
|
7892 |
+
replica rayban
|
7893 |
+
replica service
|
7894 |
+
replica top
|
7895 |
+
replica ugg
|
7896 |
+
replica watch
|
7897 |
+
replica_
|
7898 |
+
replica-bag
|
7899 |
+
replica-brand
|
7900 |
+
replica-china
|
7901 |
+
replica-design
|
7902 |
+
replica-gucci
|
7903 |
+
replica-hand
|
7904 |
+
replica-handbag
|
7905 |
+
replica-ip
|
7906 |
+
replica-jersey
|
7907 |
+
replica-louis
|
7908 |
+
replica-nba
|
7909 |
+
replica-oakley
|
7910 |
+
replica-prada
|
7911 |
+
replica-rayban
|
7912 |
+
replica-rolex
|
7913 |
+
replica-service
|
7914 |
+
replica-store
|
7915 |
+
replica-top
|
7916 |
+
replica-ugg
|
7917 |
+
replica-world
|
7918 |
+
replica<
|
7919 |
+
replica7
|
7920 |
+
replica8
|
7921 |
+
replicabag
|
7922 |
+
replicabrand
|
7923 |
+
replicachanel
|
7924 |
+
replicachina
|
7925 |
+
replicadesign
|
7926 |
+
replicagucci
|
7927 |
+
replicahand
|
7928 |
+
replicahandbag
|
7929 |
+
replicaip
|
7930 |
+
replicajersey
|
7931 |
+
replicalouis
|
7932 |
+
replicanba
|
7933 |
+
replicaoakley
|
7934 |
+
replicaprad
|
7935 |
+
replicarayban
|
7936 |
+
replicarolex
|
7937 |
+
replicaservice
|
7938 |
+
replicastore
|
7939 |
+
replicatop
|
7940 |
+
replicaugg
|
7941 |
+
replicawatch
|
7942 |
+
replicaworld
|
7943 |
+
reports.php
|
7944 |
+
resist comment
|
7945 |
+
resist-comment
|
7946 |
+
resources/styles
|
7947 |
+
restoremen
|
7948 |
+
restoril
|
7949 |
+
results.htm
|
7950 |
+
retin-a
|
7951 |
+
reverse lookup
|
7952 |
+
reverse-lookup
|
7953 |
+
reverse-phone
|
7954 |
+
reverselookup
|
7955 |
+
reversephone
|
7956 |
+
review-source
|
7957 |
+
review.asp
|
7958 |
+
review.blog
|
7959 |
+
review.htm
|
7960 |
+
review.in
|
7961 |
+
reviews.asp
|
7962 |
+
reviews.blog
|
7963 |
+
reviews.htm
|
7964 |
+
reviews.in
|
7965 |
+
reviews.net
|
7966 |
+
reviews.org
|
7967 |
+
reviewsource
|
7968 |
+
reviewthe
|
7969 |
+
reviewx
|
7970 |
+
reviot
|
7971 |
+
revolutionjog
|
7972 |
+
revolutionstroll
|
7973 |
+
reԛuire
|
7974 |
+
rheumatoidarthritis
|
7975 |
+
rice-cooker
|
7976 |
+
ricecooker
|
7977 |
+
rich woolrich
|
7978 |
+
rich-woolrich
|
7979 |
+
richwoolrich
|
7980 |
+
right blog
|
7981 |
+
right-blog
|
7982 |
+
rightblog
|
7983 |
+
rilopkais.in
|
7984 |
+
rin.in
|
7985 |
+
riot points
|
7986 |
+
riot-points
|
7987 |
+
riotpoints
|
7988 |
+
ripoffreport
|
7989 |
+
rizatriptan
|
7990 |
+
robaxin
|
7991 |
+
robe-de-mariee
|
7992 |
+
robe-du-mariage
|
7993 |
+
robedemariee
|
7994 |
+
robedumariage
|
7995 |
+
robertby
|
7996 |
+
roger-vivier
|
7997 |
+
rok.ru
|
7998 |
+
rokettube
|
7999 |
+
roleplay
|
8000 |
+
rolex-watch
|
8001 |
+
rolexwatch
|
8002 |
+
roofingcontractor
|
8003 |
+
ropa belstaff
|
8004 |
+
ropa-belstaff
|
8005 |
+
ropabelstaff
|
8006 |
+
rose-shoe
|
8007 |
+
roseshoe
|
8008 |
+
rosettastoneeasy
|
8009 |
+
rosuvastatin
|
8010 |
+
rotating-hot-iron
|
8011 |
+
rotatinghotiron
|
8012 |
+
rouge moncler
|
8013 |
+
rouge-moncler
|
8014 |
+
rougemoncler
|
8015 |
+
roxy ugg
|
8016 |
+
roxy-ugg
|
8017 |
+
roxyugg
|
8018 |
+
royal-club
|
8019 |
+
royalclub
|
8020 |
+
róże
|
8021 |
+
rozszerzona
|
8022 |
+
rpg-online
|
8023 |
+
rpgonline
|
8024 |
+
rss.htm
|
8025 |
+
ru/pub
|
8026 |
+
runescape
|
8027 |
+
running sneak
|
8028 |
+
running-sneak
|
8029 |
+
runningsneak
|
8030 |
+
rusztowania
|
8031 |
+
rіght
|
8032 |
+
s.webeden
|
8033 |
+
sabo charm
|
8034 |
+
sabo out
|
8035 |
+
sabo ring
|
8036 |
+
sabo sale
|
8037 |
+
sabo shop
|
8038 |
+
sabo uk
|
8039 |
+
sabo-charm
|
8040 |
+
sabo-out
|
8041 |
+
sabocharm
|
8042 |
+
sac celine
|
8043 |
+
sac chloe
|
8044 |
+
sac hermes
|
8045 |
+
sac lancel
|
8046 |
+
sac longchamp
|
8047 |
+
sac louis
|
8048 |
+
sac vanessa
|
8049 |
+
sac vuitton
|
8050 |
+
sac_lancel
|
8051 |
+
sac-celine
|
8052 |
+
sac-chloe
|
8053 |
+
sac-hermes
|
8054 |
+
sac-lancel
|
8055 |
+
sac-longchamp
|
8056 |
+
sac-louis
|
8057 |
+
sac-vanessa
|
8058 |
+
sac-vuitton
|
8059 |
+
sacguess
|
8060 |
+
saclongchamp
|
8061 |
+
saclouis
|
8062 |
+
sacs longchamps
|
8063 |
+
sacs-fr
|
8064 |
+
sacs-longchamps
|
8065 |
+
sacsfr
|
8066 |
+
sacsguess
|
8067 |
+
sacslancel
|
8068 |
+
sacvanessa
|
8069 |
+
sacvuitton
|
8070 |
+
sadehap
|
8071 |
+
saints jersey
|
8072 |
+
saints-jersey
|
8073 |
+
saintsjersey
|
8074 |
+
saldi online
|
8075 |
+
saldi-footwear
|
8076 |
+
saldi-online
|
8077 |
+
saldifootwear
|
8078 |
+
saldionline
|
8079 |
+
sale louis
|
8080 |
+
sale lulu
|
8081 |
+
sale miami
|
8082 |
+
sale nederland
|
8083 |
+
sale oakley
|
8084 |
+
sale template
|
8085 |
+
sale-cheap
|
8086 |
+
sale-factory
|
8087 |
+
sale-jp
|
8088 |
+
sale-longchamp
|
8089 |
+
sale-louis
|
8090 |
+
sale-lulu
|
8091 |
+
sale-miami
|
8092 |
+
sale-nederland
|
8093 |
+
sale-oakley
|
8094 |
+
sale-template
|
8095 |
+
sale-tokyo
|
8096 |
+
sale-training
|
8097 |
+
sale.co.
|
8098 |
+
sale.weebly
|
8099 |
+
sale4u
|
8100 |
+
salecanad
|
8101 |
+
salecheap
|
8102 |
+
salefactory
|
8103 |
+
salejp
|
8104 |
+
salelouis
|
8105 |
+
salelulu
|
8106 |
+
salemiami
|
8107 |
+
saleoakley
|
8108 |
+
saleonline
|
8109 |
+
saleout
|
8110 |
+
sales-class
|
8111 |
+
sales-factory
|
8112 |
+
sales-inspir
|
8113 |
+
sales-train
|
8114 |
+
sales-training
|
8115 |
+
sales.co.
|
8116 |
+
sales+
|
8117 |
+
salesclass
|
8118 |
+
salesfactory
|
8119 |
+
saleshop
|
8120 |
+
salesshop
|
8121 |
+
salestrain
|
8122 |
+
salestraining
|
8123 |
+
saletemplate
|
8124 |
+
saletokyo
|
8125 |
+
saletraining
|
8126 |
+
saleu.co
|
8127 |
+
salomon athletic
|
8128 |
+
salomon canada
|
8129 |
+
salomon-athletic
|
8130 |
+
salomon-canada
|
8131 |
+
salomonathletic
|
8132 |
+
salomoncanada
|
8133 |
+
salvia.
|
8134 |
+
sameday-loan
|
8135 |
+
samedayloan
|
8136 |
+
sample@
|
8137 |
+
samurai siege
|
8138 |
+
samurai-siege
|
8139 |
+
sandaljp
|
8140 |
+
sandalsjp
|
8141 |
+
sanders jersey
|
8142 |
+
sanders-jersey
|
8143 |
+
sandersjersey
|
8144 |
+
sandypasch
|
8145 |
+
sante http
|
8146 |
+
satchelbag
|
8147 |
+
satcheldbag
|
8148 |
+
sauvegarde extern
|
8149 |
+
sauvegarde-extern
|
8150 |
+
sbobet
|
8151 |
+
scam.htm
|
8152 |
+
scam.in
|
8153 |
+
scam.net
|
8154 |
+
scam.org
|
8155 |
+
scar repair
|
8156 |
+
scar-repair
|
8157 |
+
scarpe air
|
8158 |
+
scarpe hogan
|
8159 |
+
scarpe italia
|
8160 |
+
scarpe mbt
|
8161 |
+
scarpe supra
|
8162 |
+
scarpe-air
|
8163 |
+
scarpe-basket
|
8164 |
+
scarpe-hogan
|
8165 |
+
scarpe-italia
|
8166 |
+
scarpe-mbt
|
8167 |
+
scarpe-supra
|
8168 |
+
scarpebasket
|
8169 |
+
scarpehogan
|
8170 |
+
scarpeitalia
|
8171 |
+
scarrepair
|
8172 |
+
schlgsseldienste
|
8173 |
+
schlüsseldienste
|
8174 |
+
schoenen dsquared
|
8175 |
+
schoenen-dsquared
|
8176 |
+
schoenendsquared
|
8177 |
+
school.a
|
8178 |
+
schuhe puma
|
8179 |
+
schuhe-puma
|
8180 |
+
schuhepuma
|
8181 |
+
sciatica pain
|
8182 |
+
scontati
|
8183 |
+
scoriescod
|
8184 |
+
scott wing
|
8185 |
+
scott-wing
|
8186 |
+
scottwing
|
8187 |
+
scrapebox
|
8188 |
+
seaddons
|
8189 |
+
seahawks jersey
|
8190 |
+
seahawks-jersey
|
8191 |
+
seahawksjersey
|
8192 |
+
search-engine-opt
|
8193 |
+
searchengine-opt
|
8194 |
+
searchengine.
|
8195 |
+
searchengineoptimiz
|
8196 |
+
seawaypab
|
8197 |
+
secondgrade
|
8198 |
+
secret advantage
|
8199 |
+
secret beautiful
|
8200 |
+
secret generous
|
8201 |
+
secret-advantage
|
8202 |
+
secret-beautiful
|
8203 |
+
secret-generous
|
8204 |
+
secret.co
|
8205 |
+
secretadvantage
|
8206 |
+
secretbeautiful
|
8207 |
+
secretgenerous
|
8208 |
+
security-for
|
8209 |
+
seek man
|
8210 |
+
seek men
|
8211 |
+
seek wom
|
8212 |
+
seek-man
|
8213 |
+
seek-men
|
8214 |
+
seek-wom
|
8215 |
+
seeking man
|
8216 |
+
seeking men
|
8217 |
+
seeking wom
|
8218 |
+
seeking-man
|
8219 |
+
seeking-men
|
8220 |
+
seeking-wom
|
8221 |
+
seekingman
|
8222 |
+
seekingmen
|
8223 |
+
seekingwom
|
8224 |
+
seekman
|
8225 |
+
seekmen
|
8226 |
+
seekwom
|
8227 |
+
seeming vexation
|
8228 |
+
seeming-vexation
|
8229 |
+
seikomise
|
8230 |
+
seks.ru
|
8231 |
+
sell-now
|
8232 |
+
sellnow
|
8233 |
+
send earning
|
8234 |
+
send-earning
|
8235 |
+
sendflowers
|
8236 |
+
sensual massage
|
8237 |
+
sensual-massage
|
8238 |
+
sentient-health
|
8239 |
+
sentienthealth
|
8240 |
+
senuke vps
|
8241 |
+
senuke-vps
|
8242 |
+
senukevps
|
8243 |
+
seo comp
|
8244 |
+
seo gig
|
8245 |
+
seo vps
|
8246 |
+
seo_
|
8247 |
+
seo-
|
8248 |
+
seo,
|
8249 |
+
seo.
|
8250 |
+
seoaddon
|
8251 |
+
seoagenc
|
8252 |
+
seohost
|
8253 |
+
seopick
|
8254 |
+
seoplugin
|
8255 |
+
seotool
|
8256 |
+
seovps
|
8257 |
+
seowith
|
8258 |
+
seriously entice
|
8259 |
+
seriously-entice
|
8260 |
+
serravalle outlet
|
8261 |
+
serravalle-outlet
|
8262 |
+
serravalleoutlet
|
8263 |
+
serrurier http
|
8264 |
+
serrurier marseille
|
8265 |
+
serrurier paris
|
8266 |
+
serrurier-marseille
|
8267 |
+
serrurier-paris
|
8268 |
+
sertraline
|
8269 |
+
server 2007
|
8270 |
+
server 2008
|
8271 |
+
services/services
|
8272 |
+
serwis
|
8273 |
+
settings1
|
8274 |
+
settings2
|
8275 |
+
settings3
|
8276 |
+
settlement cash
|
8277 |
+
settlement-cash
|
8278 |
+
sex advice
|
8279 |
+
sex-advice
|
8280 |
+
sex-blog
|
8281 |
+
sex-cam
|
8282 |
+
sex-game
|
8283 |
+
sex-shop
|
8284 |
+
sex-tape
|
8285 |
+
sex-toy
|
8286 |
+
sex-tube
|
8287 |
+
sex-web
|
8288 |
+
sex.htm
|
8289 |
+
sexadvice
|
8290 |
+
sexblog
|
8291 |
+
sexcam
|
8292 |
+
sexdate
|
8293 |
+
sexdating
|
8294 |
+
sexelist
|
8295 |
+
sexero
|
8296 |
+
sexgame
|
8297 |
+
sexo mon
|
8298 |
+
sexo-mon
|
8299 |
+
sexomon
|
8300 |
+
sexscandal
|
8301 |
+
sexshop
|
8302 |
+
sextape
|
8303 |
+
sextoy
|
8304 |
+
sextube
|
8305 |
+
sexual fantas
|
8306 |
+
sexual moment
|
8307 |
+
sexual-fantas
|
8308 |
+
sexual-moment
|
8309 |
+
sexualfantas
|
8310 |
+
sexweb
|
8311 |
+
sexy.co
|
8312 |
+
sgames.co
|
8313 |
+
shanghai-escort
|
8314 |
+
shanghai-massage
|
8315 |
+
shanghaiescort
|
8316 |
+
shanghaimassage
|
8317 |
+
shanrig
|
8318 |
+
shared site
|
8319 |
+
shed-fat
|
8320 |
+
shemale.
|
8321 |
+
shirt cease
|
8322 |
+
shirt-cease
|
8323 |
+
shoe dior
|
8324 |
+
shoe online
|
8325 |
+
shoe out
|
8326 |
+
shoe promo
|
8327 |
+
shoe-cloth
|
8328 |
+
shoe-dior
|
8329 |
+
shoe-japan
|
8330 |
+
shoe-online
|
8331 |
+
shoe-out
|
8332 |
+
shoe-promo
|
8333 |
+
shoe.asp
|
8334 |
+
shoecloth
|
8335 |
+
shoejapan
|
8336 |
+
shoejp.co
|
8337 |
+
shoeonline
|
8338 |
+
shoeout
|
8339 |
+
shoeoutlet
|
8340 |
+
shoes dior
|
8341 |
+
shoes mbt
|
8342 |
+
shoes online
|
8343 |
+
shoes out
|
8344 |
+
shoes-2014
|
8345 |
+
shoes-cheap
|
8346 |
+
shoes-cloth
|
8347 |
+
shoes-dior
|
8348 |
+
shoes-japan
|
8349 |
+
shoes-mbt
|
8350 |
+
shoes-on-sale
|
8351 |
+
shoes-online
|
8352 |
+
shoes-out
|
8353 |
+
shoes.asp
|
8354 |
+
shoes+for+men
|
8355 |
+
shoes+men
|
8356 |
+
shoes+women
|
8357 |
+
shoesale
|
8358 |
+
shoescloth
|
8359 |
+
shoesjapan
|
8360 |
+
shoeskan
|
8361 |
+
shoesmart
|
8362 |
+
shoesmbt
|
8363 |
+
shoesonline
|
8364 |
+
shoesonsale
|
8365 |
+
shoesout
|
8366 |
+
shoesoutlet
|
8367 |
+
shoessale
|
8368 |
+
shoestore
|
8369 |
+
shoesuk
|
8370 |
+
shoesus
|
8371 |
+
shoeuk
|
8372 |
+
shoot-tequila
|
8373 |
+
shop online
|
8374 |
+
shop-japan.co
|
8375 |
+
shop-nfl
|
8376 |
+
shop-now
|
8377 |
+
shop-online
|
8378 |
+
shop-pin
|
8379 |
+
shop.asia
|
8380 |
+
shopboots
|
8381 |
+
shopent.ru
|
8382 |
+
shopg2bags
|
8383 |
+
shopjapan.co
|
8384 |
+
shopjp
|
8385 |
+
shopnfl
|
8386 |
+
shopnow
|
8387 |
+
shopof
|
8388 |
+
shoponline
|
8389 |
+
shopping site
|
8390 |
+
shopping-ugg
|
8391 |
+
shopping+
|
8392 |
+
shopping24
|
8393 |
+
shoppingcenter.co
|
8394 |
+
shoppingugg
|
8395 |
+
shopuk
|
8396 |
+
shopus.co
|
8397 |
+
short ugg
|
8398 |
+
short-ugg
|
8399 |
+
shorttermloan
|
8400 |
+
shortugg
|
8401 |
+
should http
|
8402 |
+
shoulder tote
|
8403 |
+
shoulder-tote
|
8404 |
+
shouldertote
|
8405 |
+
show_
|
8406 |
+
shownews.
|
8407 |
+
showtopic
|
8408 |
+
si.lv.e.r.w.are
|
8409 |
+
sieg heil
|
8410 |
+
sieg-heil
|
8411 |
+
siege hack
|
8412 |
+
siege-hack
|
8413 |
+
siegheil
|
8414 |
+
sign-zodiac
|
8415 |
+
signed-jersey
|
8416 |
+
signifiant
|
8417 |
+
significant infos
|
8418 |
+
significant-infos
|
8419 |
+
signozodiac
|
8420 |
+
signzodiac
|
8421 |
+
silagra
|
8422 |
+
silberbarren
|
8423 |
+
sildenafil
|
8424 |
+
silver-and-gold
|
8425 |
+
silver-ingot
|
8426 |
+
silver-jewelry
|
8427 |
+
silveringot
|
8428 |
+
silverjewelry
|
8429 |
+
sim-only
|
8430 |
+
simply shared
|
8431 |
+
simply-shared
|
8432 |
+
sinequan
|
8433 |
+
singapore.htm
|
8434 |
+
site backup
|
8435 |
+
site link
|
8436 |
+
site official
|
8437 |
+
site position
|
8438 |
+
site traffic
|
8439 |
+
site-backup
|
8440 |
+
site-google
|
8441 |
+
site-link
|
8442 |
+
site-official
|
8443 |
+
site-position
|
8444 |
+
site-traffic
|
8445 |
+
site.co
|
8446 |
+
site.in
|
8447 |
+
site24
|
8448 |
+
sitecode
|
8449 |
+
sitelink
|
8450 |
+
sitemap
|
8451 |
+
sites24
|
8452 |
+
sito ufficiale
|
8453 |
+
sito-ufficiale
|
8454 |
+
siutpd
|
8455 |
+
sizegenetic
|
8456 |
+
skapa grupp
|
8457 |
+
skapa-grupp
|
8458 |
+
skapagrupp
|
8459 |
+
skelaxin
|
8460 |
+
skin pigment
|
8461 |
+
skin_pigment
|
8462 |
+
skin-pigment
|
8463 |
+
skincare-work
|
8464 |
+
skincarework
|
8465 |
+
skip-trace
|
8466 |
+
skip-tracing
|
8467 |
+
skjønnhetsprodukter
|
8468 |
+
sklep
|
8469 |
+
sklepy
|
8470 |
+
skor-rea
|
8471 |
+
skorrea
|
8472 |
+
skup-aut
|
8473 |
+
skup,aut
|
8474 |
+
sledge baseball
|
8475 |
+
sledge bat
|
8476 |
+
sledge-baseball
|
8477 |
+
sledge-bat
|
8478 |
+
slimpill
|
8479 |
+
slimup
|
8480 |
+
slongchamp
|
8481 |
+
slot machine
|
8482 |
+
slot-machine
|
8483 |
+
slotmachine
|
8484 |
+
smallbusinessplan
|
8485 |
+
smart-drug
|
8486 |
+
smartdrug
|
8487 |
+
smeoone
|
8488 |
+
smith soldes
|
8489 |
+
smith-soldes
|
8490 |
+
smithsoldes
|
8491 |
+
smokingnews
|
8492 |
+
sms grupp
|
8493 |
+
sms-grupp
|
8494 |
+
smsgrupp
|
8495 |
+
snapbacks
|
8496 |
+
sneaker.asp
|
8497 |
+
sneakerchef
|
8498 |
+
sneakerjapan
|
8499 |
+
sneakerjp
|
8500 |
+
sneakers retail
|
8501 |
+
sneakers-retail
|
8502 |
+
sneakers.asp
|
8503 |
+
sneakers24
|
8504 |
+
sneakersretail
|
8505 |
+
snipurl.com
|
8506 |
+
snism
|
8507 |
+
social-bookmark
|
8508 |
+
socialbookmark
|
8509 |
+
socialengine
|
8510 |
+
socialite.
|
8511 |
+
socialnetworkbuzz
|
8512 |
+
socialnetworksbuzz
|
8513 |
+
societys
|
8514 |
+
soeasy
|
8515 |
+
soft-secrets
|
8516 |
+
softsecrets
|
8517 |
+
software-secret
|
8518 |
+
software.in
|
8519 |
+
softwaresecret
|
8520 |
+
sohbet
|
8521 |
+
sold-out
|
8522 |
+
solde canad
|
8523 |
+
solde-canad
|
8524 |
+
soldecanad
|
8525 |
+
soldes louboutin
|
8526 |
+
soldes ralph
|
8527 |
+
soldes-louboutin
|
8528 |
+
soldes-ralph
|
8529 |
+
soldes.co
|
8530 |
+
soldes<
|
8531 |
+
soldeslouboutin
|
8532 |
+
soleil ray
|
8533 |
+
soleil-ray
|
8534 |
+
soleilray
|
8535 |
+
solução
|
8536 |
+
solutioninc
|
8537 |
+
solutionsinc
|
8538 |
+
sonicsearch
|
8539 |
+
sooemne
|
8540 |
+
soup.io/post
|
8541 |
+
sozedde.co
|
8542 |
+
sp1 key
|
8543 |
+
sp1-key
|
8544 |
+
spaccio gucci
|
8545 |
+
spaccio woolrich
|
8546 |
+
spaccio-gucci
|
8547 |
+
spaccio-woolrich
|
8548 |
+
spacciowoolrich
|
8549 |
+
spade diaper
|
8550 |
+
spade-diaper
|
8551 |
+
spam response
|
8552 |
+
spam-response
|
8553 |
+
spammer spam
|
8554 |
+
sparkle ugg
|
8555 |
+
sparkle-ugg
|
8556 |
+
sparkleugg
|
8557 |
+
special-offer
|
8558 |
+
specialty-transfer
|
8559 |
+
specialtytransfer
|
8560 |
+
specific gift
|
8561 |
+
specific-gift
|
8562 |
+
spedified
|
8563 |
+
speed-loan
|
8564 |
+
speedloan
|
8565 |
+
speedy-product
|
8566 |
+
spip.php
|
8567 |
+
splendid department
|
8568 |
+
splendid-department
|
8569 |
+
sponsoring secret
|
8570 |
+
sponsoring-secret
|
8571 |
+
sponsoringsecret
|
8572 |
+
sportbikepart
|
8573 |
+
sportbook
|
8574 |
+
sportsbet
|
8575 |
+
sportsbook
|
8576 |
+
sportsfanshop
|
8577 |
+
sportsfanstore
|
8578 |
+
sportsgear
|
8579 |
+
sportsjersey
|
8580 |
+
sprinkler tune
|
8581 |
+
sprinkler-tune
|
8582 |
+
sprzedaz
|
8583 |
+
spyder-jacket
|
8584 |
+
spyder-ski
|
8585 |
+
spyderjackets
|
8586 |
+
spyderski
|
8587 |
+
spyware
|
8588 |
+
squidoo.co
|
8589 |
+
ssory
|
8590 |
+
starsunglass
|
8591 |
+
state-of-the-art
|
8592 |
+
statuscode
|
8593 |
+
stazhirovka
|
8594 |
+
steelersfan
|
8595 |
+
stendra
|
8596 |
+
stevewynnloan
|
8597 |
+
stig hollister
|
8598 |
+
stig online
|
8599 |
+
stig-hollister
|
8600 |
+
stig-online
|
8601 |
+
stighollister
|
8602 |
+
stigonline
|
8603 |
+
stimulacion sex
|
8604 |
+
stimulacion-sex
|
8605 |
+
stivale timberland
|
8606 |
+
stivale-timberland
|
8607 |
+
stivaletimberland
|
8608 |
+
stivali timberland
|
8609 |
+
stivali-timberland
|
8610 |
+
stivalitimberland
|
8611 |
+
stodiobeat
|
8612 |
+
stodiosbeat
|
8613 |
+
stone japan
|
8614 |
+
stone-japan
|
8615 |
+
stonejapan
|
8616 |
+
stop-smoking
|
8617 |
+
store austr
|
8618 |
+
store gucci
|
8619 |
+
store out
|
8620 |
+
store-gucci
|
8621 |
+
store-out
|
8622 |
+
store-service
|
8623 |
+
store.htm
|
8624 |
+
store.org
|
8625 |
+
storegucci
|
8626 |
+
storejp
|
8627 |
+
storeoutlet
|
8628 |
+
stosunek
|
8629 |
+
stoxymom
|
8630 |
+
straightface
|
8631 |
+
strategies-for
|
8632 |
+
strategy-for
|
8633 |
+
stratificat.
|
8634 |
+
strattera
|
8635 |
+
stromectol
|
8636 |
+
studiobeat
|
8637 |
+
studiosbeat
|
8638 |
+
stumbledupon
|
8639 |
+
stumpmaster
|
8640 |
+
stunningq
|
8641 |
+
style mbt
|
8642 |
+
style-mbt
|
8643 |
+
styledkitchen
|
8644 |
+
stylembt
|
8645 |
+
styleshq
|
8646 |
+
stylevip
|
8647 |
+
stylomontblanc
|
8648 |
+
stylowe
|
8649 |
+
subject=
|
8650 |
+
succeed-online
|
8651 |
+
success you
|
8652 |
+
success-you
|
8653 |
+
successful blog
|
8654 |
+
successful-blog
|
8655 |
+
sucesso.co
|
8656 |
+
sucette
|
8657 |
+
suggested-website
|
8658 |
+
sumatriptan
|
8659 |
+
summer coach
|
8660 |
+
summer-coach
|
8661 |
+
sunchannel
|
8662 |
+
sunglass cheap
|
8663 |
+
sunglass out
|
8664 |
+
sunglassau
|
8665 |
+
sunglasses cheap
|
8666 |
+
sunglasses out
|
8667 |
+
sunglasses.us
|
8668 |
+
sunglassesau
|
8669 |
+
sunglassesok
|
8670 |
+
sunglassesuk
|
8671 |
+
sunglassok
|
8672 |
+
sunglassuk
|
8673 |
+
sunrize
|
8674 |
+
superarticle
|
8675 |
+
superheroz
|
8676 |
+
superstar class
|
8677 |
+
superstar-class
|
8678 |
+
superstarclass
|
8679 |
+
supply_
|
8680 |
+
supra shoe
|
8681 |
+
supra-shoe
|
8682 |
+
suprashoe
|
8683 |
+
suprax
|
8684 |
+
supreme-essay
|
8685 |
+
supremeessay
|
8686 |
+
surf online
|
8687 |
+
surf to
|
8688 |
+
surf-online
|
8689 |
+
surf-to
|
8690 |
+
surfing online
|
8691 |
+
surfing-online
|
8692 |
+
surprisezone
|
8693 |
+
suwa³ki
|
8694 |
+
svente enligne
|
8695 |
+
svente-enligne
|
8696 |
+
sventeenligne
|
8697 |
+
swarovski
|
8698 |
+
swarovskijapan
|
8699 |
+
swarovskijp
|
8700 |
+
swiss-replica
|
8701 |
+
sword trade
|
8702 |
+
sword-trade
|
8703 |
+
swords trade
|
8704 |
+
swords-trade
|
8705 |
+
swordstrade
|
8706 |
+
swordtrade
|
8707 |
+
syaneru
|
8708 |
+
symptom-med
|
8709 |
+
symptommed
|
8710 |
+
symptoms-med
|
8711 |
+
symptomsmed
|
8712 |
+
system-pro
|
8713 |
+
system-review
|
8714 |
+
tabaki
|
8715 |
+
tadalafil
|
8716 |
+
tadapox
|
8717 |
+
tag_heuer
|
8718 |
+
tag/event
|
8719 |
+
taille costume
|
8720 |
+
taille-costume
|
8721 |
+
taken gravely
|
8722 |
+
taken-gravely
|
8723 |
+
takenwith
|
8724 |
+
takje care
|
8725 |
+
takje-care
|
8726 |
+
tamiflu
|
8727 |
+
tamoxifen
|
8728 |
+
tamsulosin
|
8729 |
+
tanger outlet
|
8730 |
+
tanger-outlet
|
8731 |
+
tapicerowane
|
8732 |
+
targeted traffic
|
8733 |
+
targeted visit
|
8734 |
+
targeted visitor
|
8735 |
+
targeted-traffic
|
8736 |
+
targeted-visit
|
8737 |
+
targetedtraffic
|
8738 |
+
targetedvisit
|
8739 |
+
targetted traffic
|
8740 |
+
targetted visit
|
8741 |
+
targetted-traffic
|
8742 |
+
targetted-visit
|
8743 |
+
targettedtraffic
|
8744 |
+
targettedvisit
|
8745 |
+
tarif-malin
|
8746 |
+
tarifmalin
|
8747 |
+
tariki shoe
|
8748 |
+
tariki-shoe
|
8749 |
+
tarikishoe
|
8750 |
+
tarot divin
|
8751 |
+
tarot-divin
|
8752 |
+
tasche longchamp
|
8753 |
+
tasche-longchamp
|
8754 |
+
taschelongchamp
|
8755 |
+
taschen longchamp
|
8756 |
+
taschen-longchamp
|
8757 |
+
taschenlongchamp
|
8758 |
+
tastegood.co
|
8759 |
+
tattoo-tip
|
8760 |
+
tattootip
|
8761 |
+
tax-book
|
8762 |
+
tax-debt
|
8763 |
+
taxbook
|
8764 |
+
taxdebt
|
8765 |
+
teach-you-every
|
8766 |
+
teamproshop
|
8767 |
+
teen female
|
8768 |
+
teen porn
|
8769 |
+
teen sex
|
8770 |
+
teen-female
|
8771 |
+
teen-porn
|
8772 |
+
teen-sex
|
8773 |
+
teenage female
|
8774 |
+
teenage-female
|
8775 |
+
teenaged female
|
8776 |
+
teenaged-female
|
8777 |
+
teeniepant
|
8778 |
+
teenporn
|
8779 |
+
teensex
|
8780 |
+
teenwebcam
|
8781 |
+
tees hollister
|
8782 |
+
tees-hollister
|
8783 |
+
teeshollister
|
8784 |
+
tegs:
|
8785 |
+
telephone gratuit
|
8786 |
+
telephone-gratuit
|
8787 |
+
telepon-
|
8788 |
+
template.co
|
8789 |
+
templates.co
|
8790 |
+
templerun-
|
8791 |
+
templerun1
|
8792 |
+
tenormin
|
8793 |
+
term dinner
|
8794 |
+
term loan
|
8795 |
+
term-dinner
|
8796 |
+
termopane
|
8797 |
+
test.ca
|
8798 |
+
test.in
|
8799 |
+
test.tumblr
|
8800 |
+
test@
|
8801 |
+
test1.
|
8802 |
+
testosterone-boost
|
8803 |
+
testrun
|
8804 |
+
testuser
|
8805 |
+
tetracycline
|
8806 |
+
texans-jersey
|
8807 |
+
texansjersey
|
8808 |
+
tgf@
|
8809 |
+
thailove
|
8810 |
+
thanks.i
|
8811 |
+
that isnt
|
8812 |
+
that-isnt
|
8813 |
+
thatover
|
8814 |
+
thatprofit
|
8815 |
+
the -notify
|
8816 |
+
the pokie
|
8817 |
+
the the
|
8818 |
+
the threading
|
8819 |
+
the_best
|
8820 |
+
the-benefits-of
|
8821 |
+
the-best-treatment
|
8822 |
+
the-diet
|
8823 |
+
the-hypothyroid
|
8824 |
+
the-latest-
|
8825 |
+
the-most-common
|
8826 |
+
the-most-detail
|
8827 |
+
the-pokie
|
8828 |
+
the-right-way
|
8829 |
+
the-the
|
8830 |
+
the-threading
|
8831 |
+
theaverage
|
8832 |
+
thebestis
|
8833 |
+
thebestprice
|
8834 |
+
thedevelop
|
8835 |
+
theeasy
|
8836 |
+
theguest
|
8837 |
+
thehypothyroid
|
8838 |
+
theme sale
|
8839 |
+
theme-basic
|
8840 |
+
theme-generat
|
8841 |
+
theme-sale
|
8842 |
+
themebasic
|
8843 |
+
themegenerat
|
8844 |
+
themes sale
|
8845 |
+
themes-for-windows
|
8846 |
+
themes-sale
|
8847 |
+
themesforwindows
|
8848 |
+
therealest
|
8849 |
+
thes good
|
8850 |
+
thespacious
|
8851 |
+
thetopdog
|
8852 |
+
theyll
|
8853 |
+
thhis
|
8854 |
+
things-consume
|
8855 |
+
things-we-love
|
8856 |
+
this blog
|
8857 |
+
this review
|
8858 |
+
this weblog
|
8859 |
+
this website
|
8860 |
+
this-blog
|
8861 |
+
this-review
|
8862 |
+
this-weblog
|
8863 |
+
this-website
|
8864 |
+
thisjourney
|
8865 |
+
thm.htm
|
8866 |
+
thomas sabot
|
8867 |
+
thomas-sabot
|
8868 |
+
thomasfat
|
8869 |
+
thomassabo-sale
|
8870 |
+
thomassabo-uk
|
8871 |
+
thomassabosale
|
8872 |
+
thomassabouk
|
8873 |
+
thportfol
|
8874 |
+
thumb.jpeg
|
8875 |
+
thumb.jpg
|
8876 |
+
thumb.png
|
8877 |
+
thyromine
|
8878 |
+
tɦey
|
8879 |
+
ticket http
|
8880 |
+
tickets http
|
8881 |
+
tier business
|
8882 |
+
tier-business
|
8883 |
+
tiffany france
|
8884 |
+
tiffany jewel
|
8885 |
+
tiffany ring
|
8886 |
+
tiffany-france
|
8887 |
+
tiffany-jewel
|
8888 |
+
tiffany-out
|
8889 |
+
tiffany-ring
|
8890 |
+
tiffanyjewel
|
8891 |
+
tiffanyout
|
8892 |
+
tiffanyring
|
8893 |
+
tiffanysale
|
8894 |
+
tiffiny
|
8895 |
+
tihnikng
|
8896 |
+
tiki-index
|
8897 |
+
timberland cheap
|
8898 |
+
timberland out
|
8899 |
+
timberland pas
|
8900 |
+
timberland saldi
|
8901 |
+
timberland shoe
|
8902 |
+
timberland uom
|
8903 |
+
timberland-cheap
|
8904 |
+
timberland-out
|
8905 |
+
timberland-pas
|
8906 |
+
timberland-saldi
|
8907 |
+
timberland-uom
|
8908 |
+
timberland1
|
8909 |
+
timberland2
|
8910 |
+
timberlandboot
|
8911 |
+
timberlandcheap
|
8912 |
+
timberlandout
|
8913 |
+
timberlandpas
|
8914 |
+
timberlandsaldi
|
8915 |
+
timberlanduom
|
8916 |
+
time-synchronisation.co
|
8917 |
+
times(with
|
8918 |
+
timesamsonss
|
8919 |
+
timeshare
|
8920 |
+
tingenieur
|
8921 |
+
tiny.cc
|
8922 |
+
tinytowtimmy.co
|
8923 |
+
tinyurl.com
|
8924 |
+
tipblog
|
8925 |
+
tips-for-
|
8926 |
+
tips-to-start
|
8927 |
+
tips.info
|
8928 |
+
tipsblog
|
8929 |
+
tipsof
|
8930 |
+
tire-discount
|
8931 |
+
tire-wholesale
|
8932 |
+
tirediscount
|
8933 |
+
tires-discount
|
8934 |
+
tires-wholesale
|
8935 |
+
tiresdiscount
|
8936 |
+
tireswholesale
|
8937 |
+
tirewholesale
|
8938 |
+
tit-pad
|
8939 |
+
titans merch
|
8940 |
+
titans-merch
|
8941 |
+
titansmerch
|
8942 |
+
tizanidine
|
8943 |
+
tms-shoe
|
8944 |
+
tmsshoe
|
8945 |
+
tnf-sale
|
8946 |
+
tnfsale
|
8947 |
+
toasterovensnow
|
8948 |
+
today/article
|
8949 |
+
todsjapan
|
8950 |
+
todsjp
|
8951 |
+
toeshoe.co
|
8952 |
+
toeshoes.co
|
8953 |
+
tofranil
|
8954 |
+
toile vanessa
|
8955 |
+
toile-vanessa
|
8956 |
+
toilevanessa
|
8957 |
+
tojp.co
|
8958 |
+
token generat
|
8959 |
+
token hack
|
8960 |
+
token-generat
|
8961 |
+
token-hack
|
8962 |
+
tokyo-lv
|
8963 |
+
told u?
|
8964 |
+
toms price
|
8965 |
+
toms shoe
|
8966 |
+
toms women
|
8967 |
+
toms-cheap
|
8968 |
+
toms-price
|
8969 |
+
toms-shoe
|
8970 |
+
toms-women
|
8971 |
+
tomscheap
|
8972 |
+
tomsforsale
|
8973 |
+
tomsout
|
8974 |
+
tomsshoe
|
8975 |
+
tomsshoes
|
8976 |
+
tomswomen
|
8977 |
+
top tier
|
8978 |
+
top-forum
|
8979 |
+
top-list
|
8980 |
+
top-muscle
|
8981 |
+
top-rank
|
8982 |
+
top-search
|
8983 |
+
top-site
|
8984 |
+
top-tier
|
8985 |
+
topamax
|
8986 |
+
topcontractor
|
8987 |
+
topforum
|
8988 |
+
topiramate
|
8989 |
+
toplist
|
8990 |
+
topman123
|
8991 |
+
topmuscle
|
8992 |
+
toprank
|
8993 |
+
topsearch
|
8994 |
+
topseo
|
8995 |
+
topsite
|
8996 |
+
topvideocon
|
8997 |
+
torrent-movie
|
8998 |
+
torrentmovie
|
8999 |
+
torrents
|
9000 |
+
torsemide
|
9001 |
+
toryburch1
|
9002 |
+
toryburch2
|
9003 |
+
toryburchflat
|
9004 |
+
toryburchten
|
9005 |
+
totaldns.in
|
9006 |
+
totalizador
|
9007 |
+
tote handbag
|
9008 |
+
tote-handbag
|
9009 |
+
totehandbag
|
9010 |
+
town|
|
9011 |
+
tr.im
|
9012 |
+
trace-service
|
9013 |
+
tracing-service
|
9014 |
+
track-phone-location
|
9015 |
+
tracking-a-phone
|
9016 |
+
trade_your
|
9017 |
+
trading-method
|
9018 |
+
trafficz
|
9019 |
+
trailer sale
|
9020 |
+
trailer-sale
|
9021 |
+
trailersale
|
9022 |
+
training-online
|
9023 |
+
training-pro
|
9024 |
+
trainingonline
|
9025 |
+
trainingpro
|
9026 |
+
traitement-des
|
9027 |
+
tramadol
|
9028 |
+
transform-vhs
|
9029 |
+
travel.pl
|
9030 |
+
traveltrip
|
9031 |
+
trazodone
|
9032 |
+
treatment.in
|
9033 |
+
trempe sous
|
9034 |
+
trempe-sous
|
9035 |
+
trening
|
9036 |
+
tresore
|
9037 |
+
tretinoin
|
9038 |
+
trickphoto
|
9039 |
+
trimethoprim
|
9040 |
+
triviatrivia
|
9041 |
+
trollapp
|
9042 |
+
true search
|
9043 |
+
truly very
|
9044 |
+
truly-very
|
9045 |
+
truthabout
|
9046 |
+
try-these
|
9047 |
+
tubee.tv
|
9048 |
+
tucholskie
|
9049 |
+
tumi1
|
9050 |
+
tumi2
|
9051 |
+
tummy tuck
|
9052 |
+
tummy-tuck
|
9053 |
+
tummytuck
|
9054 |
+
turbo-vac
|
9055 |
+
turbosprezar
|
9056 |
+
turystyka
|
9057 |
+
tutorial.htm
|
9058 |
+
tutoringand
|
9059 |
+
tvturn
|
9060 |
+
tworzenie
|
9061 |
+
uauaua
|
9062 |
+
ubezpieczenia
|
9063 |
+
ubirkin
|
9064 |
+
ucoz.co
|
9065 |
+
ucoz.ru
|
9066 |
+
ufficiales
|
9067 |
+
ugboos
|
9068 |
+
ugbos
|
9069 |
+
ugg 3
|
9070 |
+
ugg ad
|
9071 |
+
ugg animal
|
9072 |
+
ugg austr
|
9073 |
+
ugg bailey
|
9074 |
+
ugg bamsestøvler
|
9075 |
+
ugg bebe
|
9076 |
+
ugg black
|
9077 |
+
ugg boot
|
9078 |
+
ugg botte
|
9079 |
+
ugg brown
|
9080 |
+
ugg brux
|
9081 |
+
ugg cheap
|
9082 |
+
ugg class
|
9083 |
+
ugg dakota
|
9084 |
+
ugg elsey
|
9085 |
+
ugg enfant
|
9086 |
+
ugg femme
|
9087 |
+
ugg fox
|
9088 |
+
ugg france
|
9089 |
+
ugg glove
|
9090 |
+
ugg hobo
|
9091 |
+
ugg hot
|
9092 |
+
ugg ken
|
9093 |
+
ugg mocha
|
9094 |
+
ugg noir
|
9095 |
+
ugg out
|
9096 |
+
ugg paris
|
9097 |
+
ugg pas
|
9098 |
+
ugg pascher
|
9099 |
+
ugg sale
|
9100 |
+
ugg shear
|
9101 |
+
ugg shoe
|
9102 |
+
ugg short
|
9103 |
+
ugg silver
|
9104 |
+
ugg sold
|
9105 |
+
ugg støvler
|
9106 |
+
ugg style
|
9107 |
+
ugg three
|
9108 |
+
ugg turn
|
9109 |
+
ugg wom
|
9110 |
+
ugg-3
|
9111 |
+
ugg-ad
|
9112 |
+
ugg-animal
|
9113 |
+
ugg-bailey
|
9114 |
+
ugg-bamsestøvler
|
9115 |
+
ugg-bebe
|
9116 |
+
ugg-best
|
9117 |
+
ugg-black
|
9118 |
+
ugg-boot
|
9119 |
+
ugg-botte
|
9120 |
+
ugg-brown
|
9121 |
+
ugg-brux
|
9122 |
+
ugg-cheap
|
9123 |
+
ugg-class
|
9124 |
+
ugg-comfort
|
9125 |
+
ugg-elsey
|
9126 |
+
ugg-enfant
|
9127 |
+
ugg-femme
|
9128 |
+
ugg-for
|
9129 |
+
ugg-fox
|
9130 |
+
ugg-france
|
9131 |
+
ugg-glove
|
9132 |
+
ugg-hobo
|
9133 |
+
ugg-hot
|
9134 |
+
ugg-ken
|
9135 |
+
ugg-mocha
|
9136 |
+
ugg-noir
|
9137 |
+
ugg-official
|
9138 |
+
ugg-on
|
9139 |
+
ugg-out
|
9140 |
+
ugg-paris
|
9141 |
+
ugg-pas
|
9142 |
+
ugg-pascher
|
9143 |
+
ugg-sale
|
9144 |
+
ugg-shear
|
9145 |
+
ugg-shoe
|
9146 |
+
ugg-short
|
9147 |
+
ugg-silver
|
9148 |
+
ugg-site
|
9149 |
+
ugg-sold
|
9150 |
+
ugg-støvler
|
9151 |
+
ugg-style
|
9152 |
+
ugg-three
|
9153 |
+
ugg-turn
|
9154 |
+
ugg-uk
|
9155 |
+
ugg-usa
|
9156 |
+
ugg-wom
|
9157 |
+
ugg.htm
|
9158 |
+
ugg+
|
9159 |
+
ugg=
|
9160 |
+
ugg3
|
9161 |
+
uggad
|
9162 |
+
ugganimal
|
9163 |
+
uggatcanad
|
9164 |
+
uggbailey
|
9165 |
+
uggbamsestøvler
|
9166 |
+
uggbebe
|
9167 |
+
uggbest
|
9168 |
+
uggblack
|
9169 |
+
uggboo
|
9170 |
+
uggboot
|
9171 |
+
uggbos
|
9172 |
+
uggbotte
|
9173 |
+
uggbrown
|
9174 |
+
uggbrux
|
9175 |
+
uggcheap
|
9176 |
+
uggclass
|
9177 |
+
uggclog
|
9178 |
+
uggcomfort
|
9179 |
+
uggdakota
|
9180 |
+
uggelsey
|
9181 |
+
uggenfant
|
9182 |
+
uggfemme
|
9183 |
+
uggfor
|
9184 |
+
uggfox
|
9185 |
+
uggfrance
|
9186 |
+
uggglove
|
9187 |
+
ugghobo
|
9188 |
+
ugghot
|
9189 |
+
uggken
|
9190 |
+
ugglove
|
9191 |
+
uggmocha
|
9192 |
+
uggnoir
|
9193 |
+
uggofficial
|
9194 |
+
uggonline
|
9195 |
+
uggout
|
9196 |
+
uggoutlet
|
9197 |
+
uggparis
|
9198 |
+
uggpas
|
9199 |
+
uggpascher
|
9200 |
+
uggs austr
|
9201 |
+
uggs bailey
|
9202 |
+
uggs bebe
|
9203 |
+
uggs black
|
9204 |
+
uggs boot
|
9205 |
+
uggs brux
|
9206 |
+
uggs class
|
9207 |
+
uggs elsey
|
9208 |
+
uggs femme
|
9209 |
+
uggs hot
|
9210 |
+
uggs http
|
9211 |
+
uggs kopen
|
9212 |
+
uggs mocha
|
9213 |
+
uggs neder
|
9214 |
+
uggs noir
|
9215 |
+
uggs out
|
9216 |
+
uggs paris
|
9217 |
+
uggs pas
|
9218 |
+
uggs pascher
|
9219 |
+
uggs sale
|
9220 |
+
uggs shoe
|
9221 |
+
uggs silver
|
9222 |
+
uggs sold
|
9223 |
+
uggs ugly
|
9224 |
+
uggs uitverkoop
|
9225 |
+
uggs wom
|
9226 |
+
uggs-austr
|
9227 |
+
uggs-bailey
|
9228 |
+
uggs-bebe
|
9229 |
+
uggs-black
|
9230 |
+
uggs-boot
|
9231 |
+
uggs-brux
|
9232 |
+
uggs-class
|
9233 |
+
uggs-elsey
|
9234 |
+
uggs-femme
|
9235 |
+
uggs-for
|
9236 |
+
uggs-hot
|
9237 |
+
uggs-kopen
|
9238 |
+
uggs-mocha
|
9239 |
+
uggs-neder
|
9240 |
+
uggs-noir
|
9241 |
+
uggs-on
|
9242 |
+
uggs-out
|
9243 |
+
uggs-paris
|
9244 |
+
uggs-pas
|
9245 |
+
uggs-pascher
|
9246 |
+
uggs-sale
|
9247 |
+
uggs-shoe
|
9248 |
+
uggs-silver
|
9249 |
+
uggs-site
|
9250 |
+
uggs-sold
|
9251 |
+
uggs-ugly
|
9252 |
+
uggs-uitverkoop
|
9253 |
+
uggs-uk
|
9254 |
+
uggs-usa
|
9255 |
+
uggs-wom
|
9256 |
+
uggs.co
|
9257 |
+
uggsale
|
9258 |
+
uggsaustr
|
9259 |
+
uggsbailey
|
9260 |
+
uggsbay
|
9261 |
+
uggsbebe
|
9262 |
+
uggsblack
|
9263 |
+
uggsboot
|
9264 |
+
uggsbrux
|
9265 |
+
uggscheap
|
9266 |
+
uggsclass
|
9267 |
+
uggselsey
|
9268 |
+
uggsfemme
|
9269 |
+
uggsfor
|
9270 |
+
uggshear
|
9271 |
+
uggshoe
|
9272 |
+
uggshort
|
9273 |
+
uggshot
|
9274 |
+
uggsilver
|
9275 |
+
uggsite
|
9276 |
+
uggskopen
|
9277 |
+
uggslove
|
9278 |
+
uggsmocha
|
9279 |
+
uggsneder
|
9280 |
+
uggsnoir
|
9281 |
+
uggsold
|
9282 |
+
uggsonline
|
9283 |
+
uggsout
|
9284 |
+
uggsoutlet
|
9285 |
+
uggsparis
|
9286 |
+
uggspas
|
9287 |
+
uggspascher
|
9288 |
+
uggss
|
9289 |
+
uggssilver
|
9290 |
+
uggstøvler
|
9291 |
+
uggstyle
|
9292 |
+
uggsugly
|
9293 |
+
uggsuitverkoop
|
9294 |
+
uggsusa
|
9295 |
+
uggsustra
|
9296 |
+
uggswom
|
9297 |
+
uggthree
|
9298 |
+
uggturn
|
9299 |
+
uggusa
|
9300 |
+
uggustra
|
9301 |
+
uggwom
|
9302 |
+
uhren out
|
9303 |
+
uk out
|
9304 |
+
uk sale
|
9305 |
+
uk-handbag
|
9306 |
+
uk-loan
|
9307 |
+
uk-mall
|
9308 |
+
uk-mart
|
9309 |
+
uk-out
|
9310 |
+
uk-sale
|
9311 |
+
uk.co.
|
9312 |
+
uk.webeden
|
9313 |
+
uk/mulberry
|
9314 |
+
uk/prada
|
9315 |
+
ukclsale
|
9316 |
+
ukgardenhouses
|
9317 |
+
ukhandbag
|
9318 |
+
ukloan
|
9319 |
+
ukmall
|
9320 |
+
ukmart
|
9321 |
+
ukonline
|
9322 |
+
ukoutlet
|
9323 |
+
uksale
|
9324 |
+
uksonline
|
9325 |
+
ukugg
|
9326 |
+
ukvip
|
9327 |
+
ulkotours
|
9328 |
+
ultimate microsoft
|
9329 |
+
ultimate sp1
|
9330 |
+
ultimate-microsoft
|
9331 |
+
ultimate-sp1
|
9332 |
+
ultimate-tab
|
9333 |
+
ultimatemicrosoft
|
9334 |
+
ultimatetab
|
9335 |
+
ultram
|
9336 |
+
umschuldung
|
9337 |
+
under pant
|
9338 |
+
under-pant
|
9339 |
+
underpant
|
9340 |
+
underthe
|
9341 |
+
une moncler
|
9342 |
+
une-moncler
|
9343 |
+
unemoncler
|
9344 |
+
unitedidesign
|
9345 |
+
universal-key
|
9346 |
+
unknown.ru
|
9347 |
+
unknown@
|
9348 |
+
unlock iphone
|
9349 |
+
unlock-iphone
|
9350 |
+
unlock-mobile
|
9351 |
+
unlock-phone
|
9352 |
+
unlockiphone
|
9353 |
+
unlockmobile
|
9354 |
+
unlockphone
|
9355 |
+
unwanted-hair
|
9356 |
+
unwantedhair
|
9357 |
+
uomo adidas
|
9358 |
+
uomo dsquared
|
9359 |
+
uomo man
|
9360 |
+
uomo moncler
|
9361 |
+
uomo timberland
|
9362 |
+
uomo-adidas
|
9363 |
+
uomo-dsquared
|
9364 |
+
uomo-man
|
9365 |
+
uomo-moncler
|
9366 |
+
uomo-short
|
9367 |
+
uomo-timberland
|
9368 |
+
uomoadidas
|
9369 |
+
uomoman
|
9370 |
+
uomomoncler
|
9371 |
+
uomotimberland
|
9372 |
+
up-to-date
|
9373 |
+
upgrade key
|
9374 |
+
upgrade-key
|
9375 |
+
upgradekey
|
9376 |
+
upload_
|
9377 |
+
upseseglype
|
9378 |
+
urlacher jersey
|
9379 |
+
urlacher-jersey
|
9380 |
+
urlacherjersey
|
9381 |
+
urls2
|
9382 |
+
urlstatusgo.htm
|
9383 |
+
uroda
|
9384 |
+
us/profile
|
9385 |
+
usa-best
|
9386 |
+
usabest
|
9387 |
+
user_
|
9388 |
+
user/profile
|
9389 |
+
user/view
|
9390 |
+
userinfo
|
9391 |
+
usualdiscuss
|
9392 |
+
usually relative
|
9393 |
+
usually-relative
|
9394 |
+
ut.ag/
|
9395 |
+
utilized use
|
9396 |
+
uustore
|
9397 |
+
uy/image
|
9398 |
+
valise louis
|
9399 |
+
valise-louis
|
9400 |
+
valiselouis
|
9401 |
+
valium
|
9402 |
+
valtrex
|
9403 |
+
valueble
|
9404 |
+
vanessa-bruno-sac
|
9405 |
+
vanessabrunosac
|
9406 |
+
vaporizer pen
|
9407 |
+
varabella
|
9408 |
+
vardenafil
|
9409 |
+
vegas hotel
|
9410 |
+
vegas show
|
9411 |
+
vegas social
|
9412 |
+
vegas-hotel
|
9413 |
+
vegas-show
|
9414 |
+
vegas-social
|
9415 |
+
vendita
|
9416 |
+
vendorlock
|
9417 |
+
venlafaxine
|
9418 |
+
ventolin inhale
|
9419 |
+
ventures impart
|
9420 |
+
ventures note
|
9421 |
+
ventures pleasant
|
9422 |
+
ventures profit
|
9423 |
+
ventures shape
|
9424 |
+
ventures-impart
|
9425 |
+
ventures-note
|
9426 |
+
ventures-pleasant
|
9427 |
+
ventures-profit
|
9428 |
+
ventures-shape
|
9429 |
+
versace-japan
|
9430 |
+
versacejapan
|
9431 |
+
versicherungsmakler
|
9432 |
+
very disconcertingly
|
9433 |
+
very-disconcertingly
|
9434 |
+
very}
|
9435 |
+
veste moncler
|
9436 |
+
veste-moncler
|
9437 |
+
vestemoncler
|
9438 |
+
vestidos
|
9439 |
+
veston class
|
9440 |
+
veston-class
|
9441 |
+
vestonclass
|
9442 |
+
vetement-femme
|
9443 |
+
vetement-homme
|
9444 |
+
veterinarnaya
|
9445 |
+
vhs-to-digital
|
9446 |
+
via-internet
|
9447 |
+
viagera
|
9448 |
+
viagra
|
9449 |
+
vicodin
|
9450 |
+
video sport
|
9451 |
+
video-magnif
|
9452 |
+
video-pokie
|
9453 |
+
video-sport
|
9454 |
+
video.htm
|
9455 |
+
videochat
|
9456 |
+
videogamedesign
|
9457 |
+
videomagnif
|
9458 |
+
videopokie
|
9459 |
+
videos.htm
|
9460 |
+
videosport
|
9461 |
+
vidios
|
9462 |
+
viencare
|
9463 |
+
view_
|
9464 |
+
view-article
|
9465 |
+
view-blog
|
9466 |
+
view-entry
|
9467 |
+
viewarticle
|
9468 |
+
viewblog
|
9469 |
+
viewentry
|
9470 |
+
viewlink
|
9471 |
+
viewpag
|
9472 |
+
viewtopic
|
9473 |
+
vigara
|
9474 |
+
vigrx
|
9475 |
+
vimax
|
9476 |
+
vinder burberry
|
9477 |
+
vinder-burberry
|
9478 |
+
vinderburberry
|
9479 |
+
vinhobrasil-
|
9480 |
+
vinhobrasil.
|
9481 |
+
vintage-erotic
|
9482 |
+
vinterjakker
|
9483 |
+
vipgirl
|
9484 |
+
viramune
|
9485 |
+
virtual sex
|
9486 |
+
virtual-sex
|
9487 |
+
virus answer
|
9488 |
+
virus hoax
|
9489 |
+
virus infеct
|
9490 |
+
virus remov
|
9491 |
+
virus secur
|
9492 |
+
virus-answer
|
9493 |
+
virus-hoax
|
9494 |
+
virus-infеct
|
9495 |
+
virus-remov
|
9496 |
+
virus-secur
|
9497 |
+
virusanswer
|
9498 |
+
virushoax
|
9499 |
+
virusinfеct
|
9500 |
+
virusremov
|
9501 |
+
virussecur
|
9502 |
+
visit homepage
|
9503 |
+
visit web
|
9504 |
+
visit-homepage
|
9505 |
+
visit-web
|
9506 |
+
visitant
|
9507 |
+
visitor/day
|
9508 |
+
visitors/day
|
9509 |
+
vitalikor
|
9510 |
+
vitamin-for
|
9511 |
+
vitaminfor
|
9512 |
+
vitamins-for
|
9513 |
+
vitaminsfor
|
9514 |
+
vitamix
|
9515 |
+
vitrine
|
9516 |
+
vivekkunwar
|
9517 |
+
vivier ballerine
|
9518 |
+
vivier-ballerine
|
9519 |
+
vivierballerine
|
9520 |
+
vivotab
|
9521 |
+
vogue toms
|
9522 |
+
vogue-toms
|
9523 |
+
voguetoms
|
9524 |
+
voyance amour
|
9525 |
+
voyance couple
|
9526 |
+
voyance gratuite
|
9527 |
+
voyance http
|
9528 |
+
voyance-amour
|
9529 |
+
voyance-couple
|
9530 |
+
voyance-gratuite
|
9531 |
+
voyance<
|
9532 |
+
vuitton austr
|
9533 |
+
vuitton bag
|
9534 |
+
vuitton belt
|
9535 |
+
vuitton black
|
9536 |
+
vuitton bracelet
|
9537 |
+
vuitton cig
|
9538 |
+
vuitton damier
|
9539 |
+
vuitton deutsch
|
9540 |
+
vuitton factory
|
9541 |
+
vuitton fanny
|
9542 |
+
vuitton fashion
|
9543 |
+
vuitton france
|
9544 |
+
vuitton fx
|
9545 |
+
vuitton glass
|
9546 |
+
vuitton hand
|
9547 |
+
vuitton hard
|
9548 |
+
vuitton men
|
9549 |
+
vuitton online
|
9550 |
+
vuitton out
|
9551 |
+
vuitton pas
|
9552 |
+
vuitton purse
|
9553 |
+
vuitton replica
|
9554 |
+
vuitton sac
|
9555 |
+
vuitton shoe
|
9556 |
+
vuitton sold
|
9557 |
+
vuitton speed
|
9558 |
+
vuitton taschen
|
9559 |
+
vuitton wallet
|
9560 |
+
vuitton wholesale
|
9561 |
+
vuitton women
|
9562 |
+
vuitton-bag
|
9563 |
+
vuitton-black
|
9564 |
+
vuitton-bracelet
|
9565 |
+
vuitton-cig
|
9566 |
+
vuitton-damier
|
9567 |
+
vuitton-fanny
|
9568 |
+
vuitton-fashion
|
9569 |
+
vuitton-glass
|
9570 |
+
vuitton-men
|
9571 |
+
vuitton-pas
|
9572 |
+
vuitton-purse
|
9573 |
+
vuitton-replica
|
9574 |
+
vuitton-shoe
|
9575 |
+
vuitton-sold
|
9576 |
+
vuitton-speed
|
9577 |
+
vuitton-uk
|
9578 |
+
vuitton-usa
|
9579 |
+
vuitton-wallet
|
9580 |
+
vuitton-wholesale
|
9581 |
+
vuitton-women
|
9582 |
+
vuitton<
|
9583 |
+
vuittonbag
|
9584 |
+
vuittoncig
|
9585 |
+
vuittondamier
|
9586 |
+
vuittonfanny
|
9587 |
+
vuittonfashion
|
9588 |
+
vuittonglass
|
9589 |
+
vuittononline
|
9590 |
+
vuittonpas
|
9591 |
+
vuittonpurse
|
9592 |
+
vuittonreplica
|
9593 |
+
vuittonsac
|
9594 |
+
vuittonsold
|
9595 |
+
vuittonspeed
|
9596 |
+
vuittonuk
|
9597 |
+
vuittonusa
|
9598 |
+
vuittonwallet
|
9599 |
+
vuittonwholesale
|
9600 |
+
wakka=
|
9601 |
+
wallet out
|
9602 |
+
wallet-out
|
9603 |
+
walletout
|
9604 |
+
wallinside
|
9605 |
+
walmartbuy
|
9606 |
+
walmartmail
|
9607 |
+
wang bag
|
9608 |
+
wang-bag
|
9609 |
+
wangbag
|
9610 |
+
wantsand
|
9611 |
+
warcraftguide
|
9612 |
+
ware-crack
|
9613 |
+
warecrack
|
9614 |
+
warehouse.net
|
9615 |
+
warehouse.org
|
9616 |
+
warehouse.pl
|
9617 |
+
warehouse.ru
|
9618 |
+
warehouse.us
|
9619 |
+
warepics
|
9620 |
+
warmjp
|
9621 |
+
warszawa
|
9622 |
+
wasbusiness
|
9623 |
+
watch video
|
9624 |
+
watch-quartz
|
9625 |
+
watch-replica
|
9626 |
+
watch-seiko
|
9627 |
+
watch-video
|
9628 |
+
watches-quartz
|
9629 |
+
watchesquartz
|
9630 |
+
watchhoshi
|
9631 |
+
watchquartz
|
9632 |
+
watchreplica
|
9633 |
+
watchseiko
|
9634 |
+
water-weight
|
9635 |
+
way-to-enjoy
|
9636 |
+
wayfarer baratas
|
9637 |
+
wayfarer glass
|
9638 |
+
wayfarer-baratas
|
9639 |
+
wayfarer-glass
|
9640 |
+
wayfarerglass
|
9641 |
+
wdmypass
|
9642 |
+
we-are-your
|
9643 |
+
weave-hair
|
9644 |
+
weavehair
|
9645 |
+
web anal
|
9646 |
+
web blog
|
9647 |
+
web owner
|
9648 |
+
web people
|
9649 |
+
web promo
|
9650 |
+
web_log
|
9651 |
+
web-anal
|
9652 |
+
web-blog
|
9653 |
+
web-hosting
|
9654 |
+
web-log
|
9655 |
+
web-owner
|
9656 |
+
web-people
|
9657 |
+
web-promo
|
9658 |
+
web-site
|
9659 |
+
web-solution
|
9660 |
+
web-traffic
|
9661 |
+
web-view
|
9662 |
+
web/icon
|
9663 |
+
web/index
|
9664 |
+
webanal
|
9665 |
+
webblog
|
9666 |
+
webcambabe
|
9667 |
+
webcamsex
|
9668 |
+
webdesign.co
|
9669 |
+
webfarma
|
9670 |
+
webhosting
|
9671 |
+
weblink
|
9672 |
+
weblog site
|
9673 |
+
weblog-site
|
9674 |
+
weblog}
|
9675 |
+
weblogto
|
9676 |
+
webmaster
|
9677 |
+
webnode.cn
|
9678 |
+
webnode.co
|
9679 |
+
webnode.cz
|
9680 |
+
webnode.fr
|
9681 |
+
webnode.hu
|
9682 |
+
webnode.it
|
9683 |
+
webnode.nl
|
9684 |
+
webpag
|
9685 |
+
webpharma
|
9686 |
+
webpromo
|
9687 |
+
webpromotion
|
9688 |
+
websex
|
9689 |
+
webshop/image
|
9690 |
+
website online
|
9691 |
+
website post
|
9692 |
+
website traffic
|
9693 |
+
website usa
|
9694 |
+
website visitor
|
9695 |
+
website-online
|
9696 |
+
website-post
|
9697 |
+
website-usa
|
9698 |
+
website-visitor
|
9699 |
+
website!!
|
9700 |
+
website}
|
9701 |
+
website1
|
9702 |
+
websiteonline
|
9703 |
+
websiterecord
|
9704 |
+
websites online
|
9705 |
+
websites-online
|
9706 |
+
websitesdesign
|
9707 |
+
websitesonline
|
9708 |
+
websiteusa
|
9709 |
+
websolution
|
9710 |
+
webviewconsult
|
9711 |
+
wedding jewelry
|
9712 |
+
wedding-jewelry
|
9713 |
+
weddingdress
|
9714 |
+
week.in
|
9715 |
+
weekly.in
|
9716 |
+
weeklyincome
|
9717 |
+
weeklyprofit
|
9718 |
+
weight gain
|
9719 |
+
weight loss
|
9720 |
+
weight-gain
|
9721 |
+
weight-loss
|
9722 |
+
weight-work
|
9723 |
+
weightgain
|
9724 |
+
weightloss
|
9725 |
+
weightnatural
|
9726 |
+
welcometonginx
|
9727 |
+
wellbutrin
|
9728 |
+
weptwith
|
9729 |
+
werbegeschenke
|
9730 |
+
westwood boot
|
9731 |
+
westwood-boot
|
9732 |
+
westwoodboot
|
9733 |
+
wet pant
|
9734 |
+
wet-pant
|
9735 |
+
wetpant
|
9736 |
+
wetting pant
|
9737 |
+
wetting-pant
|
9738 |
+
wettingpant
|
9739 |
+
weusecoin
|
9740 |
+
what-we-know
|
9741 |
+
what's up,
|
9742 |
+
what’s up,
|
9743 |
+
whatll
|
9744 |
+
whats up,
|
9745 |
+
whatsapp
|
9746 |
+
wheels.co
|
9747 |
+
wheels.net
|
9748 |
+
wheels.org
|
9749 |
+
whenshe
|
9750 |
+
where buy
|
9751 |
+
where-buy
|
9752 |
+
where-to-buy
|
9753 |
+
wherebuy
|
9754 |
+
wherecani
|
9755 |
+
wheretobuy
|
9756 |
+
whichpag
|
9757 |
+
white nfl
|
9758 |
+
white-nfl
|
9759 |
+
whitehat
|
9760 |
+
whois tool
|
9761 |
+
whois-tool
|
9762 |
+
wholesale acrylic
|
9763 |
+
wholesale bag
|
9764 |
+
wholesale cheap
|
9765 |
+
wholesale china
|
9766 |
+
wholesale coach
|
9767 |
+
wholesale free
|
9768 |
+
wholesale handbag
|
9769 |
+
wholesale jersey
|
9770 |
+
wholesale jordan
|
9771 |
+
wholesale led
|
9772 |
+
wholesale nba
|
9773 |
+
wholesale north
|
9774 |
+
wholesale polo
|
9775 |
+
wholesale-acrylic
|
9776 |
+
wholesale-bag
|
9777 |
+
wholesale-cheap
|
9778 |
+
wholesale-china
|
9779 |
+
wholesale-coach
|
9780 |
+
wholesale-free
|
9781 |
+
wholesale-handbag
|
9782 |
+
wholesale-jersey
|
9783 |
+
wholesale-jordan
|
9784 |
+
wholesale-led
|
9785 |
+
wholesale-mac
|
9786 |
+
wholesale-nba
|
9787 |
+
wholesale-north
|
9788 |
+
wholesale-polo
|
9789 |
+
wholesalebag
|
9790 |
+
wholesalecheap
|
9791 |
+
wholesalechina
|
9792 |
+
wholesalecoach
|
9793 |
+
wholesalefree
|
9794 |
+
wholesalehandbag
|
9795 |
+
wholesalejersey
|
9796 |
+
wholesalejordan
|
9797 |
+
wholesaleled
|
9798 |
+
wholesalemac
|
9799 |
+
wholesalenba
|
9800 |
+
wholesalenorth
|
9801 |
+
wholesalepolo
|
9802 |
+
wholesaler-mac
|
9803 |
+
wholesalermac
|
9804 |
+
why-would-you
|
9805 |
+
widyaw
|
9806 |
+
wifi-jammer
|
9807 |
+
wifijammer
|
9808 |
+
wiki/%
|
9809 |
+
wiki/index
|
9810 |
+
wiki/user
|
9811 |
+
wikka.php
|
9812 |
+
wille bijoux
|
9813 |
+
wille solde
|
9814 |
+
wille-bijoux
|
9815 |
+
wille-solde
|
9816 |
+
willebijoux
|
9817 |
+
willesolde
|
9818 |
+
wilson jersey
|
9819 |
+
wilson-jersey
|
9820 |
+
wilsonjersey
|
9821 |
+
win7.co
|
9822 |
+
win7pro
|
9823 |
+
win8.co
|
9824 |
+
win8pro
|
9825 |
+
windows anytime
|
9826 |
+
windows-8-theme
|
9827 |
+
windows-anytime
|
9828 |
+
windows-app
|
9829 |
+
windows7key
|
9830 |
+
windows8key
|
9831 |
+
windowsanytime
|
9832 |
+
windowsphone.co
|
9833 |
+
winesickle
|
9834 |
+
wingsshop
|
9835 |
+
winter jassen
|
9836 |
+
winter-jassen
|
9837 |
+
winterjassen
|
9838 |
+
with pics
|
9839 |
+
with-pics
|
9840 |
+
without prescript
|
9841 |
+
without-invest
|
9842 |
+
without-prescript
|
9843 |
+
women makeup
|
9844 |
+
women mbt
|
9845 |
+
women nike
|
9846 |
+
women-date
|
9847 |
+
women-makeup
|
9848 |
+
women-mbt
|
9849 |
+
women-nike
|
9850 |
+
womendate
|
9851 |
+
womenmbt
|
9852 |
+
womennike
|
9853 |
+
womens bcbg
|
9854 |
+
womens boot
|
9855 |
+
womens fashion
|
9856 |
+
womens hollister
|
9857 |
+
womens nike
|
9858 |
+
womens puma
|
9859 |
+
womens shoe
|
9860 |
+
womens watch
|
9861 |
+
womens-bag
|
9862 |
+
womens-bcbg
|
9863 |
+
womens-boot
|
9864 |
+
womens-fashion
|
9865 |
+
womens-hollister
|
9866 |
+
womens-nike
|
9867 |
+
womens-puma
|
9868 |
+
womens-shoe
|
9869 |
+
womens-train
|
9870 |
+
womens-watch
|
9871 |
+
womensbcbg
|
9872 |
+
womenseekingmen
|
9873 |
+
womensnike
|
9874 |
+
womenspuma
|
9875 |
+
won webpage
|
9876 |
+
won-webpage
|
9877 |
+
wonderful article
|
9878 |
+
wonderful post
|
9879 |
+
wonderful publish
|
9880 |
+
wonderful-article
|
9881 |
+
wonderful-post
|
9882 |
+
wonderful-publish
|
9883 |
+
woodgundy.us
|
9884 |
+
woolrich bliz
|
9885 |
+
woolrich cloth
|
9886 |
+
woolrich coat
|
9887 |
+
woolrich coupon
|
9888 |
+
woolrich donn
|
9889 |
+
woolrich europe
|
9890 |
+
woolrich field
|
9891 |
+
woolrich giub
|
9892 |
+
woolrich jacket
|
9893 |
+
woolrich john
|
9894 |
+
woolrich outlet
|
9895 |
+
woolrich parka
|
9896 |
+
woolrich piumini
|
9897 |
+
woolrich scarf
|
9898 |
+
woolrich store
|
9899 |
+
woolrich uomo
|
9900 |
+
woolrich vest
|
9901 |
+
woolrich wool
|
9902 |
+
woolrich-bliz
|
9903 |
+
woolrich-cloth
|
9904 |
+
woolrich-coat
|
9905 |
+
woolrich-coupon
|
9906 |
+
woolrich-donn
|
9907 |
+
woolrich-europe
|
9908 |
+
woolrich-field
|
9909 |
+
woolrich-giub
|
9910 |
+
woolrich-jacket
|
9911 |
+
woolrich-john
|
9912 |
+
woolrich-outlet
|
9913 |
+
woolrich-parka
|
9914 |
+
woolrich-piumini
|
9915 |
+
woolrich-scarf
|
9916 |
+
woolrich-store
|
9917 |
+
woolrich-uomo
|
9918 |
+
woolrich-vest
|
9919 |
+
woolrich-wool
|
9920 |
+
woolrich.arkis
|
9921 |
+
woolrichbliz
|
9922 |
+
woolrichcloth
|
9923 |
+
woolrichcoat
|
9924 |
+
woolrichcoupon
|
9925 |
+
woolrichdonn
|
9926 |
+
woolricheurope
|
9927 |
+
woolrichfield
|
9928 |
+
woolrichgiub
|
9929 |
+
woolrichjacket
|
9930 |
+
woolrichjohn
|
9931 |
+
woolrichoutlet
|
9932 |
+
woolrichparka
|
9933 |
+
woolrichpiumini
|
9934 |
+
woolrichscarf
|
9935 |
+
woolrichstore
|
9936 |
+
woolrichuomo
|
9937 |
+
woolrichvest
|
9938 |
+
woolrichwool
|
9939 |
+
woowoo-house
|
9940 |
+
woowoo-sex
|
9941 |
+
woowoo-site
|
9942 |
+
woowoohouse
|
9943 |
+
woowoosex
|
9944 |
+
woowoosite
|
9945 |
+
wordpress web
|
9946 |
+
wordpress-theme
|
9947 |
+
wordpress-web
|
9948 |
+
wordpresstheme
|
9949 |
+
wordpressweb
|
9950 |
+
work-review
|
9951 |
+
workout-sale
|
9952 |
+
workoutsale
|
9953 |
+
workreview
|
9954 |
+
world-venture
|
9955 |
+
worlds.blog
|
9956 |
+
worldugg
|
9957 |
+
worldventure
|
9958 |
+
worldwideugg
|
9959 |
+
wow-gold
|
9960 |
+
wowo-house
|
9961 |
+
wowo-sex
|
9962 |
+
wowo-site
|
9963 |
+
wowohouse
|
9964 |
+
wowosex
|
9965 |
+
wowosite
|
9966 |
+
wp robot
|
9967 |
+
wp-pad
|
9968 |
+
wp-phone
|
9969 |
+
wp-robot
|
9970 |
+
wprobot
|
9971 |
+
wpthemegen
|
9972 |
+
wristpain
|
9973 |
+
writing-service
|
9974 |
+
writingservice
|
9975 |
+
wwellness
|
9976 |
+
www.0day
|
9977 |
+
www.1
|
9978 |
+
www.2012
|
9979 |
+
www.2013
|
9980 |
+
www.2014
|
9981 |
+
www.adults
|
9982 |
+
www.anal
|
9983 |
+
www.angel
|
9984 |
+
www.article
|
9985 |
+
www.barata
|
9986 |
+
www.barato
|
9987 |
+
www.best-
|
9988 |
+
www.brand
|
9989 |
+
www.buy
|
9990 |
+
www.canadagoose
|
9991 |
+
www.cartier-
|
9992 |
+
www.casino
|
9993 |
+
www.cellphone
|
9994 |
+
www.chanel-
|
9995 |
+
www.cheap
|
9996 |
+
www.coach-
|
9997 |
+
www.deels
|
9998 |
+
www.drdrebeat
|
9999 |
+
www.easy
|
10000 |
+
www.efinancial
|
10001 |
+
www.erotic
|
10002 |
+
www.escort
|
10003 |
+
www.everyleg
|
10004 |
+
www.everylight
|
10005 |
+
www.everypant
|
10006 |
+
www.everysock
|
10007 |
+
www.everytight
|
10008 |
+
www.fake
|
10009 |
+
www.female
|
10010 |
+
www.filmy.
|
10011 |
+
www.financ
|
10012 |
+
www.forum
|
10013 |
+
www.fot-
|
10014 |
+
www.fot.
|
10015 |
+
www.fota-
|
10016 |
+
www.fota.
|
10017 |
+
www.foteczka
|
10018 |
+
www.fotka
|
10019 |
+
www.fotki
|
10020 |
+
www.foto-
|
10021 |
+
www.foto.
|
10022 |
+
www.fotoalbum
|
10023 |
+
www.fotograf
|
10024 |
+
www.fotomania
|
10025 |
+
www.freerun
|
10026 |
+
www.fullsize
|
10027 |
+
www.gambl
|
10028 |
+
www.game
|
10029 |
+
www.gift
|
10030 |
+
www.goosepa
|
10031 |
+
www.gucci
|
10032 |
+
www.handbag
|
10033 |
+
www.hermes
|
10034 |
+
www.herveleger
|
10035 |
+
www.hot
|
10036 |
+
www.howmuch
|
10037 |
+
www.information
|
10038 |
+
www.insta
|
10039 |
+
www.instyler
|
10040 |
+
www.isabelmarant
|
10041 |
+
www.kobe
|
10042 |
+
www.lastminute
|
10043 |
+
www.lebron
|
10044 |
+
www.link
|
10045 |
+
www.lolita
|
10046 |
+
www.louboutin
|
10047 |
+
www.love
|
10048 |
+
www.lv
|
10049 |
+
www.mcm
|
10050 |
+
www.moncler
|
10051 |
+
www.mulberry
|
10052 |
+
www.newbalance
|
10053 |
+
www.nike-
|
10054 |
+
www.numberone
|
10055 |
+
www.official
|
10056 |
+
www.online
|
10057 |
+
www.onsale
|
10058 |
+
www.out
|
10059 |
+
www.penis
|
10060 |
+
www.personal
|
10061 |
+
www.promo
|
10062 |
+
www.remote
|
10063 |
+
www.replica
|
10064 |
+
www.reviewon
|
10065 |
+
www.rims
|
10066 |
+
www.sadje
|
10067 |
+
www.sale
|
10068 |
+
www.scarpe
|
10069 |
+
www.seo
|
10070 |
+
www.sexy
|
10071 |
+
www.shoes
|
10072 |
+
www.streaming
|
10073 |
+
www.tea-
|
10074 |
+
www.top
|
10075 |
+
www.torrent
|
10076 |
+
www.ugg
|
10077 |
+
www.unlock
|
10078 |
+
www.videos
|
10079 |
+
www.wholesale
|
10080 |
+
www.win
|
10081 |
+
www.wtf
|
10082 |
+
www.ysl
|
10083 |
+
www.zapato
|
10084 |
+
www<
|
10085 |
+
wwwpctool
|
10086 |
+
wypoczynku
|
10087 |
+
wyposazenie
|
10088 |
+
wywóz
|
10089 |
+
wһen
|
10090 |
+
x streaming
|
10091 |
+
x-streaming
|
10092 |
+
x.ru
|
10093 |
+
xadidas
|
10094 |
+
xalatan
|
10095 |
+
xanax
|
10096 |
+
xelerated
|
10097 |
+
xenical
|
10098 |
+
xfire.com/blog
|
10099 |
+
xl paket
|
10100 |
+
xl-paket
|
10101 |
+
xlpaket
|
10102 |
+
xn--
|
10103 |
+
xopenex
|
10104 |
+
xrumer
|
10105 |
+
xwebsite
|
10106 |
+
xx.co
|
10107 |
+
xx.in
|
10108 |
+
xxx
|
10109 |
+
xyngular
|
10110 |
+
yanswer
|
10111 |
+
yearold
|
10112 |
+
ynimb
|
10113 |
+
yo-dick
|
10114 |
+
yoigucci
|
10115 |
+
you ssay
|
10116 |
+
you-ssay
|
10117 |
+
you-ugg
|
10118 |
+
you-want-it
|
10119 |
+
you,i
|
10120 |
+
youll
|
10121 |
+
young porn
|
10122 |
+
young-porn
|
10123 |
+
your blog
|
10124 |
+
your penis
|
10125 |
+
your success
|
10126 |
+
your traffic
|
10127 |
+
your weblog
|
10128 |
+
your website
|
10129 |
+
your_
|
10130 |
+
your-account
|
10131 |
+
your-blog
|
10132 |
+
your-budget
|
10133 |
+
your-credit
|
10134 |
+
your-ex
|
10135 |
+
your-family-member
|
10136 |
+
your-free
|
10137 |
+
your-loan
|
10138 |
+
your-penis
|
10139 |
+
your-personal
|
10140 |
+
your-profile
|
10141 |
+
your-site
|
10142 |
+
your-skin
|
10143 |
+
your-success
|
10144 |
+
your-weblog
|
10145 |
+
your-website
|
10146 |
+
your-windows
|
10147 |
+
your-your
|
10148 |
+
youraccount
|
10149 |
+
yourblog
|
10150 |
+
yourcredit
|
10151 |
+
yourdui
|
10152 |
+
yourex
|
10153 |
+
yourfree
|
10154 |
+
yourloan
|
10155 |
+
yourprofile
|
10156 |
+
yoursite
|
10157 |
+
yoursuccess
|
10158 |
+
yourwebsite
|
10159 |
+
youth jersey
|
10160 |
+
youth-jersey
|
10161 |
+
youthjersey
|
10162 |
+
youtube down
|
10163 |
+
youtube vi
|
10164 |
+
youtube-down
|
10165 |
+
youtube-vi
|
10166 |
+
youtubedown
|
10167 |
+
youtubevi
|
10168 |
+
youugg
|
10169 |
+
yoyo diet
|
10170 |
+
yoyo-diet
|
10171 |
+
yoyodiet
|
10172 |
+
ysl chaussure
|
10173 |
+
ysl femme
|
10174 |
+
ysl-chaussure
|
10175 |
+
ysl-femme
|
10176 |
+
yslchaussure
|
10177 |
+
yslfemme
|
10178 |
+
yumeeyum
|
10179 |
+
yuuguu
|
10180 |
+
yyou
|
10181 |
+
ÿþ
|
10182 |
+
yеar
|
10183 |
+
z.in
|
10184 |
+
zabaw
|
10185 |
+
zahnversicherung
|
10186 |
+
zahnzusatzversicherung
|
10187 |
+
zaidimai
|
10188 |
+
zaindeksowany
|
10189 |
+
zakazane
|
10190 |
+
zaklady
|
10191 |
+
zanaflex
|
10192 |
+
zanotti online
|
10193 |
+
zanotti sale
|
10194 |
+
zanotti shoe
|
10195 |
+
zanotti sneak
|
10196 |
+
zanotti-online
|
10197 |
+
zanotti-sale
|
10198 |
+
zanotti-shoe
|
10199 |
+
zanotti-sneak
|
10200 |
+
zanottionline
|
10201 |
+
zanottisale
|
10202 |
+
zanottishoe
|
10203 |
+
zanottisneak
|
10204 |
+
zantac
|
10205 |
+
zapatas asics
|
10206 |
+
zapatas_
|
10207 |
+
zapatas-asics
|
10208 |
+
zapatillas asics
|
10209 |
+
zapatillas_
|
10210 |
+
zapatillas-asics
|
10211 |
+
zapatodenewbalance
|
10212 |
+
zapraszam
|
10213 |
+
zawieszki
|
10214 |
+
zboard.php
|
10215 |
+
zcode
|
10216 |
+
zdrowie
|
10217 |
+
zealous of
|
10218 |
+
zealous-of
|
10219 |
+
zed-bull
|
10220 |
+
zedbull
|
10221 |
+
zenonia
|
10222 |
+
zero calorie
|
10223 |
+
zero-calorie
|
10224 |
+
zerocalorie
|
10225 |
+
zfymail
|
10226 |
+
zikinell
|
10227 |
+
zimmerman fund
|
10228 |
+
zimmerman hedge
|
10229 |
+
zimmerman-fund
|
10230 |
+
zimmerman-hedge
|
10231 |
+
zimovane
|
10232 |
+
zinger baseball
|
10233 |
+
zinger bat
|
10234 |
+
zinger-baseball
|
10235 |
+
zinger-bat
|
10236 |
+
zippo feuerzeuge
|
10237 |
+
zippo zubehor
|
10238 |
+
zippo zubehör
|
10239 |
+
zippo-feuerzeuge
|
10240 |
+
zippo-zubehor
|
10241 |
+
zippo-zubehör
|
10242 |
+
zippofeuerzeuge
|
10243 |
+
zippozubehor
|
10244 |
+
zippozubehör
|
10245 |
+
zithromax
|
10246 |
+
zlinks
|
10247 |
+
złote
|
10248 |
+
zmedicin
|
10249 |
+
zoe boot
|
10250 |
+
zoe-boot
|
10251 |
+
zoidstore
|
10252 |
+
zoloft
|
10253 |
+
zolpidem
|
10254 |
+
zonejp
|
10255 |
+
zopiclone
|
10256 |
+
zovirax
|
10257 |
+
zsurgical
|
10258 |
+
zumbah
|
10259 |
+
zvideo
|
10260 |
+
zxog
|
10261 |
+
zyban
|
10262 |
+
zyprexa
|
10263 |
+
zyrtec
|
10264 |
+
zyvox
|
10265 |
+
οn
|
10266 |
+
ύou
|
10267 |
+
ωhil
|
10268 |
+
ωіlly
|
10269 |
+
аl
|
10270 |
+
аr
|
10271 |
+
абонентская
|
10272 |
+
авиабилет
|
10273 |
+
агенств
|
10274 |
+
админу
|
10275 |
+
алкогольные
|
10276 |
+
альтернатива
|
10277 |
+
андроид
|
10278 |
+
банков
|
10279 |
+
без
|
10280 |
+
бензогенератор
|
10281 |
+
бесплатн
|
10282 |
+
блог
|
10283 |
+
вђ
|
10284 |
+
веб
|
10285 |
+
г©
|
10286 |
+
денег
|
10287 |
+
дешево
|
10288 |
+
доход
|
10289 |
+
доходы
|
10290 |
+
драйвера
|
10291 |
+
заболевани
|
10292 |
+
заработок
|
10293 |
+
зарегистрировать
|
10294 |
+
знакомства
|
10295 |
+
инете
|
10296 |
+
интересн
|
10297 |
+
интернет
|
10298 |
+
іt
|
10299 |
+
казино
|
10300 |
+
качест
|
10301 |
+
качественный
|
10302 |
+
квартир
|
10303 |
+
китай
|
10304 |
+
клубах
|
10305 |
+
комисси
|
10306 |
+
компьютер
|
10307 |
+
консультация
|
10308 |
+
кредит
|
10309 |
+
купить
|
10310 |
+
легальные
|
10311 |
+
магаз
|
10312 |
+
маркет
|
10313 |
+
массажистка
|
10314 |
+
материал
|
10315 |
+
мебель
|
10316 |
+
медиа палитра
|
10317 |
+
метал
|
10318 |
+
миллион
|
10319 |
+
молочной
|
10320 |
+
найти человека
|
10321 |
+
недорого
|
10322 |
+
новинки
|
10323 |
+
обучение
|
10324 |
+
объявлени
|
10325 |
+
одежда
|
10326 |
+
онлайн
|
10327 |
+
отзывы
|
10328 |
+
отличные
|
10329 |
+
официальных
|
10330 |
+
персональный
|
10331 |
+
плата
|
10332 |
+
подешевле
|
10333 |
+
пожаловать
|
10334 |
+
покер
|
10335 |
+
порно
|
10336 |
+
портал
|
10337 |
+
посетител
|
10338 |
+
похудению
|
10339 |
+
преобрести
|
10340 |
+
прибыль
|
10341 |
+
привлекательный
|
10342 |
+
приобрести
|
10343 |
+
продаже
|
10344 |
+
проститутки
|
10345 |
+
професси
|
10346 |
+
прошивка
|
10347 |
+
психоло
|
10348 |
+
путешествую
|
10349 |
+
рднк
|
10350 |
+
регистратор
|
10351 |
+
рекламное
|
10352 |
+
ресниц
|
10353 |
+
ресурс
|
10354 |
+
рублей
|
10355 |
+
сайтов
|
10356 |
+
секс
|
10357 |
+
селитра
|
10358 |
+
симпатичная
|
10359 |
+
симптом
|
10360 |
+
скачать
|
10361 |
+
спама
|
10362 |
+
спорт на
|
10363 |
+
спорт открытом
|
10364 |
+
спорт-на
|
10365 |
+
спорт-открытом
|
10366 |
+
справкой
|
10367 |
+
статей
|
10368 |
+
статья
|
10369 |
+
стоимость
|
10370 |
+
супер
|
10371 |
+
съемка
|
10372 |
+
такси
|
10373 |
+
трудоустройства
|
10374 |
+
уou
|
10375 |
+
удивительные
|
10376 |
+
услуг
|
10377 |
+
фабрика меха
|
10378 |
+
фильмов
|
10379 |
+
финансовую
|
10380 |
+
фирму
|
10381 |
+
форум
|
10382 |
+
фото
|
10383 |
+
футбол
|
10384 |
+
цена
|
10385 |
+
шапка-
|
10386 |
+
элитныеноутбуки
|
10387 |
+
юридической
|
10388 |
+
ԝill
|
10389 |
+
ոeutral
|
10390 |
+
ոotie
|
10391 |
+
ߋ
|
10392 |
+
คาสิโน
|
10393 |
+
ต่างหู
|
10394 |
+
루이비통
|
10395 |
+
アークテリクス
|
10396 |
+
アウトレット
|
10397 |
+
アディダス
|
10398 |
+
アメリカン エキスプレス
|
10399 |
+
アメリカン·エキスプレス
|
10400 |
+
アルマーニ
|
10401 |
+
いい
|
10402 |
+
いホスティング
|
10403 |
+
ヴィトン
|
10404 |
+
ヴェネタ
|
10405 |
+
ヴェルサーチ
|
10406 |
+
エアジョーダン
|
10407 |
+
エスパドリーユ
|
10408 |
+
エルメス
|
10409 |
+
オークリー
|
10410 |
+
おざ
|
10411 |
+
オロビアンコ
|
10412 |
+
お客
|
10413 |
+
お店を
|
10414 |
+
お金を
|
10415 |
+
ガガ
|
10416 |
+
カナダグース
|
10417 |
+
カルティエは
|
10418 |
+
ギフト
|
10419 |
+
グッチ
|
10420 |
+
クラシック
|
10421 |
+
クロエ
|
10422 |
+
クロムハーツ
|
10423 |
+
ケース
|
10424 |
+
ケイトスペード
|
10425 |
+
コピ
|
10426 |
+
ゴヤール
|
10427 |
+
ご了承
|
10428 |
+
ご返金
|
10429 |
+
サマンサタバサ
|
10430 |
+
ショッ
|
10431 |
+
ショルダーバッグ
|
10432 |
+
スニーカー
|
10433 |
+
スポード
|
10434 |
+
スワロフスキー
|
10435 |
+
セイコー
|
10436 |
+
セクシー
|
10437 |
+
セリーヌ
|
10438 |
+
ダウン
|
10439 |
+
ダコタ
|
10440 |
+
ダナー
|
10441 |
+
ダミエ
|
10442 |
+
チャンルー
|
10443 |
+
ティファニ
|
10444 |
+
ティンバ
|
10445 |
+
デュベティカ
|
10446 |
+
トゥミ
|
10447 |
+
トリーバーチ
|
10448 |
+
トレッキングシューズ
|
10449 |
+
ナイキ
|
10450 |
+
ニューバランス
|
10451 |
+
ネックレス
|
10452 |
+
ノースフェイス
|
10453 |
+
の値段
|
10454 |
+
バーバリー
|
10455 |
+
パタゴニア
|
10456 |
+
バッグ
|
10457 |
+
パネライ
|
10458 |
+
バンクオブアメリカ
|
10459 |
+
ビトン
|
10460 |
+
ブーツ
|
10461 |
+
フェラガモ
|
10462 |
+
フェンディ
|
10463 |
+
ブが広がります
|
10464 |
+
プライバシ
|
10465 |
+
ブランド
|
10466 |
+
ブルガリ
|
10467 |
+
ブレスレット
|
10468 |
+
ブログ
|
10469 |
+
プロダ
|
10470 |
+
プロモ
|
10471 |
+
ポーター
|
10472 |
+
ホグロフス
|
10473 |
+
ボッテガ
|
10474 |
+
ホット
|
10475 |
+
マークジェイコブス
|
10476 |
+
ミュウ
|
10477 |
+
ムービー用
|
10478 |
+
モンクレール
|
10479 |
+
モンブラン
|
10480 |
+
ユーチューブ
|
10481 |
+
ラウンジ
|
10482 |
+
ラゲージ
|
10483 |
+
ルイヴィトン
|
10484 |
+
ルブタン
|
10485 |
+
レシート
|
10486 |
+
レスポートサック
|
10487 |
+
レプリカ
|
10488 |
+
ロレックス
|
10489 |
+
ワンランク上の
|
10490 |
+
万年筆
|
10491 |
+
人気
|
10492 |
+
仕入れ
|
10493 |
+
他の製品
|
10494 |
+
保存
|
10495 |
+
保証
|
10496 |
+
割引
|
10497 |
+
化粧
|
10498 |
+
医師
|
10499 |
+
博彩
|
10500 |
+
危機
|
10501 |
+
取得
|
10502 |
+
受注
|
10503 |
+
吉田カバン
|
10504 |
+
商品
|
10505 |
+
外贸
|
10506 |
+
安い
|
10507 |
+
実店舗
|
10508 |
+
小銭入れ
|
10509 |
+
履
|
10510 |
+
巨大
|
10511 |
+
店の
|
10512 |
+
性愛的
|
10513 |
+
最安値
|
10514 |
+
札入れ
|
10515 |
+
毛刈
|
10516 |
+
漫画を
|
10517 |
+
激安
|
10518 |
+
無料に
|
10519 |
+
用品
|
10520 |
+
百家乐
|
10521 |
+
直営店
|
10522 |
+
真のメリット
|
10523 |
+
秋冬
|
10524 |
+
節約
|
10525 |
+
綺麗め
|
10526 |
+
脳症
|
10527 |
+
脿
|
10528 |
+
腕時計
|
10529 |
+
興奮
|
10530 |
+
芸能人
|
10531 |
+
茅
|
10532 |
+
血症
|
10533 |
+
行動電源
|
10534 |
+
評価
|
10535 |
+
財布
|
10536 |
+
貿易
|
10537 |
+
赌场
|
10538 |
+
輸入
|
10539 |
+
返品
|
10540 |
+
通信販売
|
10541 |
+
通販
|
10542 |
+
配送
|
10543 |
+
酒嗜
|
10544 |
+
金引換
|
10545 |
+
金融
|
10546 |
+
鈥?
|
10547 |
+
銉
|
10548 |
+
革の
|
10549 |
+
?>
|
src/icwp-base-processor.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* Copyright (c)
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* Version: 2013-08-27-B
|
@@ -18,9 +18,9 @@
|
|
18 |
*
|
19 |
*/
|
20 |
|
21 |
-
if ( !class_exists('
|
22 |
|
23 |
-
class
|
24 |
|
25 |
const PcreDelimiter = '/';
|
26 |
const LOG_MESSAGE_LEVEL_INFO = 0;
|
@@ -31,6 +31,11 @@ class ICWP_BaseProcessor_WPSF {
|
|
31 |
const LOG_CATEGORY_FIREWALL = 1;
|
32 |
const LOG_CATEGORY_LOGINPROTECT = 2;
|
33 |
|
|
|
|
|
|
|
|
|
|
|
34 |
/**
|
35 |
* @var boolean
|
36 |
*/
|
@@ -70,7 +75,8 @@ class ICWP_BaseProcessor_WPSF {
|
|
70 |
*/
|
71 |
protected $m_oOptionsHandler;
|
72 |
|
73 |
-
public function __construct() {
|
|
|
74 |
$this->m_fNeedSave = true;
|
75 |
$this->reset();
|
76 |
}
|
@@ -79,10 +85,15 @@ class ICWP_BaseProcessor_WPSF {
|
|
79 |
* Resets the object values to be re-used anew
|
80 |
*/
|
81 |
public function reset() {
|
82 |
-
$this->m_nRequestIp =
|
83 |
$this->resetLog();
|
84 |
}
|
85 |
|
|
|
|
|
|
|
|
|
|
|
86 |
/**
|
87 |
* Ensure that when we save the object later, it doesn't save unnecessary data.
|
88 |
*/
|
@@ -91,15 +102,20 @@ class ICWP_BaseProcessor_WPSF {
|
|
91 |
}
|
92 |
|
93 |
/**
|
94 |
-
* @param string $infKey
|
95 |
*/
|
96 |
-
public function store(
|
|
|
97 |
if ( $this->getNeedSave() ) {
|
98 |
-
$this->doPreStore();
|
99 |
$this->setNeedSave( false );
|
100 |
-
update_option( $
|
101 |
}
|
102 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
103 |
|
104 |
/**
|
105 |
* @return boolean
|
@@ -117,20 +133,40 @@ class ICWP_BaseProcessor_WPSF {
|
|
117 |
|
118 |
/**
|
119 |
*
|
120 |
-
* @param array $
|
121 |
*/
|
122 |
public function setOptions( &$inaOptions ) {
|
123 |
$this->m_aOptions = $inaOptions;
|
124 |
}
|
125 |
/**
|
126 |
*
|
127 |
-
* @param
|
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 |
*/
|
@@ -196,49 +232,12 @@ class ICWP_BaseProcessor_WPSF {
|
|
196 |
/**
|
197 |
* Cloudflare compatible.
|
198 |
*
|
199 |
-
* @
|
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
|
241 |
-
|
|
|
242 |
}
|
243 |
|
244 |
/**
|
@@ -305,7 +304,7 @@ class ICWP_BaseProcessor_WPSF {
|
|
305 |
*
|
306 |
* @param ICWP_EmailProcessor $inoEmailHandler
|
307 |
*/
|
308 |
-
public function setEmailHandler(
|
309 |
$this->m_oEmailHandler = $inoEmailHandler;
|
310 |
}
|
311 |
|
@@ -331,23 +330,76 @@ class ICWP_BaseProcessor_WPSF {
|
|
331 |
/**
|
332 |
* Checks the $inaData contains valid key values as laid out in $inaChecks
|
333 |
*
|
334 |
-
* @param array $
|
335 |
* @param array $inaChecks
|
336 |
* @return boolean
|
337 |
*/
|
338 |
-
protected function validateParameters( $
|
339 |
|
340 |
-
if ( !is_array( $
|
341 |
return false;
|
342 |
}
|
343 |
|
344 |
foreach( $inaChecks as $sCheck ) {
|
345 |
-
if ( !array_key_exists( $sCheck, $
|
346 |
return false;
|
347 |
}
|
348 |
}
|
349 |
return true;
|
350 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
351 |
}
|
352 |
|
|
|
|
|
|
|
|
|
353 |
endif;
|
1 |
<?php
|
2 |
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* Version: 2013-08-27-B
|
18 |
*
|
19 |
*/
|
20 |
|
21 |
+
if ( !class_exists('ICWP_BaseProcessor_V2') ):
|
22 |
|
23 |
+
class ICWP_BaseProcessor_V2 {
|
24 |
|
25 |
const PcreDelimiter = '/';
|
26 |
const LOG_MESSAGE_LEVEL_INFO = 0;
|
31 |
const LOG_CATEGORY_FIREWALL = 1;
|
32 |
const LOG_CATEGORY_LOGINPROTECT = 2;
|
33 |
|
34 |
+
/**
|
35 |
+
* @var string
|
36 |
+
*/
|
37 |
+
protected $m_sStorageKey;
|
38 |
+
|
39 |
/**
|
40 |
* @var boolean
|
41 |
*/
|
75 |
*/
|
76 |
protected $m_oOptionsHandler;
|
77 |
|
78 |
+
public function __construct( $insStorageKey ) {
|
79 |
+
$this->m_sStorageKey = $insStorageKey;
|
80 |
$this->m_fNeedSave = true;
|
81 |
$this->reset();
|
82 |
}
|
85 |
* Resets the object values to be re-used anew
|
86 |
*/
|
87 |
public function reset() {
|
88 |
+
$this->m_nRequestIp = $this->getVisitorIpAddress();
|
89 |
$this->resetLog();
|
90 |
}
|
91 |
|
92 |
+
/**
|
93 |
+
* Override to set what this processor does when it's "run"
|
94 |
+
*/
|
95 |
+
public function run() { }
|
96 |
+
|
97 |
/**
|
98 |
* Ensure that when we save the object later, it doesn't save unnecessary data.
|
99 |
*/
|
102 |
}
|
103 |
|
104 |
/**
|
|
|
105 |
*/
|
106 |
+
public function store() {
|
107 |
+
$this->doPreStore();
|
108 |
if ( $this->getNeedSave() ) {
|
|
|
109 |
$this->setNeedSave( false );
|
110 |
+
update_option( $this->m_sStorageKey, $this );
|
111 |
}
|
112 |
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
*/
|
116 |
+
public function deleteStore() {
|
117 |
+
delete_option( $this->m_sStorageKey );
|
118 |
+
}
|
119 |
|
120 |
/**
|
121 |
* @return boolean
|
133 |
|
134 |
/**
|
135 |
*
|
136 |
+
* @param array $inaOptions
|
137 |
*/
|
138 |
public function setOptions( &$inaOptions ) {
|
139 |
$this->m_aOptions = $inaOptions;
|
140 |
}
|
141 |
/**
|
142 |
*
|
143 |
+
* @param ICWP_OptionsHandler_Base_WPSF $inoOptionsHandler
|
144 |
*/
|
145 |
public function setOptionsHandler( ICWP_OptionsHandler_Base_WPSF &$inoOptionsHandler ) {
|
146 |
$this->m_oOptionsHandler = $inoOptionsHandler;
|
147 |
$this->m_aOptions = $this->m_oOptionsHandler->getPluginOptionsValues();
|
148 |
}
|
149 |
+
|
150 |
+
/**
|
151 |
+
* @param $insKey
|
152 |
+
* @param bool $inmDefault
|
153 |
+
* @return bool
|
154 |
+
*/
|
155 |
+
public function getOption( $insKey, $inmDefault = false ) {
|
156 |
+
return isset( $this->m_aOptions[$insKey] )? $this->m_aOptions[$insKey] : $inmDefault;
|
157 |
+
}
|
158 |
+
|
159 |
+
/**
|
160 |
+
* @param $sKey
|
161 |
+
* @param mixed $mValueToTest
|
162 |
+
* @param boolean $fStrict
|
163 |
+
* @return bool
|
164 |
+
*/
|
165 |
+
public function getIsOption( $sKey, $mValueToTest, $fStrict = false ) {
|
166 |
+
$mOptionValue = $this->getOption($sKey);
|
167 |
+
return $fStrict? $mOptionValue === $mValueToTest : $mOptionValue == $mValueToTest;
|
168 |
+
}
|
169 |
+
|
170 |
/**
|
171 |
* Resets the log
|
172 |
*/
|
232 |
/**
|
233 |
* Cloudflare compatible.
|
234 |
*
|
235 |
+
* @param boolean $infAsLong - visitor IP Address as IP2Long
|
236 |
+
* @return integer - visitor IP Address as IP2Long
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
237 |
*/
|
238 |
+
public function getVisitorIpAddress( $infAsLong = true ) {
|
239 |
+
require_once( dirname(__FILE__).'/icwp-data-processor.php' );
|
240 |
+
return ICWP_WPSF_DataProcessor::GetVisitorIpAddress( $infAsLong );
|
241 |
}
|
242 |
|
243 |
/**
|
304 |
*
|
305 |
* @param ICWP_EmailProcessor $inoEmailHandler
|
306 |
*/
|
307 |
+
public function setEmailHandler( &$inoEmailHandler ) {
|
308 |
$this->m_oEmailHandler = $inoEmailHandler;
|
309 |
}
|
310 |
|
330 |
/**
|
331 |
* Checks the $inaData contains valid key values as laid out in $inaChecks
|
332 |
*
|
333 |
+
* @param array $aData
|
334 |
* @param array $inaChecks
|
335 |
* @return boolean
|
336 |
*/
|
337 |
+
protected function validateParameters( $aData, $inaChecks ) {
|
338 |
|
339 |
+
if ( !is_array( $aData ) ) {
|
340 |
return false;
|
341 |
}
|
342 |
|
343 |
foreach( $inaChecks as $sCheck ) {
|
344 |
+
if ( !array_key_exists( $sCheck, $aData ) || empty( $aData[ $sCheck ] ) ) {
|
345 |
return false;
|
346 |
}
|
347 |
}
|
348 |
return true;
|
349 |
}
|
350 |
+
|
351 |
+
protected function constructStorageKey( $insPrefix = '', $insSlug = '' ) {
|
352 |
+
$sTemplate = '%s%s_processor';
|
353 |
+
return sprintf($sTemplate, $insPrefix, $insSlug );
|
354 |
+
}
|
355 |
+
|
356 |
+
/**
|
357 |
+
* Override this to provide custom cleanup.
|
358 |
+
*/
|
359 |
+
public function deleteAndCleanUp() {
|
360 |
+
$this->deleteStore();
|
361 |
+
}
|
362 |
+
|
363 |
+
/**
|
364 |
+
*/
|
365 |
+
protected function loadDataProcessor() {
|
366 |
+
require_once( dirname(__FILE__) . '/icwp-data-processor.php' );
|
367 |
+
}
|
368 |
+
|
369 |
+
/**
|
370 |
+
* @return ICWP_WpFilesystem_WPSF
|
371 |
+
*/
|
372 |
+
protected function loadFileSystemProcessor() {
|
373 |
+
require_once( dirname(__FILE__) . '/icwp-wpfilesystem.php' );
|
374 |
+
return ICWP_WpFilesystem_WPSF::GetInstance();
|
375 |
+
}
|
376 |
+
|
377 |
+
/**
|
378 |
+
* @return ICWP_WpFunctions_WPSF
|
379 |
+
*/
|
380 |
+
protected function loadWpFunctionsProcessor() {
|
381 |
+
require_once( dirname(__FILE__) . '/icwp-wpfunctions.php' );
|
382 |
+
return ICWP_WpFunctions_WPSF::GetInstance();
|
383 |
+
}
|
384 |
+
|
385 |
+
/**
|
386 |
+
* @return ICWP_WpFunctions_WPSF
|
387 |
+
*/
|
388 |
+
protected function loadWpsfStatsProcessor() {
|
389 |
+
require_once( dirname(__FILE__) . '/icwp-wpsf-stats.php' );
|
390 |
+
}
|
391 |
+
|
392 |
+
/**
|
393 |
+
* @param $sStatKey
|
394 |
+
*/
|
395 |
+
protected function doStatIncrement( $sStatKey ) {
|
396 |
+
$this->loadWpsfStatsProcessor();
|
397 |
+
ICWP_Stats_WPSF::DoStatIncrement( $sStatKey );
|
398 |
+
}
|
399 |
}
|
400 |
|
401 |
+
endif;
|
402 |
+
|
403 |
+
if ( !class_exists('ICWP_WPSF_BaseProcessor') ):
|
404 |
+
class ICWP_WPSF_BaseProcessor extends ICWP_BaseProcessor_V2 { }
|
405 |
endif;
|
src/icwp-basedb-processor.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* Copyright (c)
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
@@ -20,9 +20,13 @@ require_once( dirname(__FILE__).'/icwp-base-processor.php' );
|
|
20 |
|
21 |
if ( !class_exists('ICWP_BaseDbProcessor_WPSF') ):
|
22 |
|
23 |
-
class ICWP_BaseDbProcessor_WPSF extends
|
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.
|
@@ -35,11 +39,16 @@ class ICWP_BaseDbProcessor_WPSF extends ICWP_BaseProcessor_WPSF {
|
|
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 |
/**
|
@@ -47,6 +56,7 @@ class ICWP_BaseDbProcessor_WPSF extends ICWP_BaseProcessor_WPSF {
|
|
47 |
*/
|
48 |
public function doPreStore() {
|
49 |
parent::doPreStore();
|
|
|
50 |
unset( $this->m_oWpdb );
|
51 |
}
|
52 |
|
@@ -55,10 +65,82 @@ class ICWP_BaseDbProcessor_WPSF extends ICWP_BaseProcessor_WPSF {
|
|
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 |
}
|
@@ -83,6 +165,19 @@ class ICWP_BaseDbProcessor_WPSF extends ICWP_BaseProcessor_WPSF {
|
|
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.
|
@@ -118,13 +213,48 @@ class ICWP_BaseDbProcessor_WPSF extends ICWP_BaseProcessor_WPSF {
|
|
118 |
* @param string $insSql
|
119 |
*/
|
120 |
public function doSql( $insSql ) {
|
121 |
-
|
|
|
|
|
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;
|
1 |
<?php
|
2 |
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
20 |
|
21 |
if ( !class_exists('ICWP_BaseDbProcessor_WPSF') ):
|
22 |
|
23 |
+
class ICWP_BaseDbProcessor_WPSF extends ICWP_WPSF_BaseProcessor {
|
24 |
|
25 |
const DB_TABLE_PREFIX = 'icwp_';
|
26 |
+
|
27 |
+
/**
|
28 |
+
*/
|
29 |
+
const CleanupCronActionHook = 'icwp_wpsf_cron_cleanupactionhook';
|
30 |
|
31 |
/**
|
32 |
* A link to the WordPress Database object so we don't have to "global" that every time.
|
39 |
* @var string
|
40 |
*/
|
41 |
protected $m_sTableName;
|
42 |
+
/**
|
43 |
+
* @var array
|
44 |
+
*/
|
45 |
+
protected $m_aDataToWrite;
|
46 |
|
47 |
+
public function __construct( $insStorageKey, $insTableName ) {
|
48 |
+
parent::__construct( $insStorageKey );
|
49 |
$this->reset();
|
50 |
$this->setTableName( $insTableName );
|
51 |
+
$this->createCleanupCron();
|
52 |
}
|
53 |
|
54 |
/**
|
56 |
*/
|
57 |
public function doPreStore() {
|
58 |
parent::doPreStore();
|
59 |
+
$this->commitData();
|
60 |
unset( $this->m_oWpdb );
|
61 |
}
|
62 |
|
65 |
*/
|
66 |
public function reset() {
|
67 |
parent::reset();
|
68 |
+
$this->loadWpdb();
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Override to set what this processor does when it's "run"
|
73 |
+
*/
|
74 |
+
public function run() {
|
75 |
+
if ( $this->getTableExists() ) {
|
76 |
+
add_action( self::CleanupCronActionHook, array( $this, 'cleanupDatabase' ) );
|
77 |
+
}
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Loads our WPDB object if required.
|
82 |
+
*/
|
83 |
+
protected function loadWpdb() {
|
84 |
+
if ( !is_null( $this->m_oWpdb ) ) {
|
85 |
+
return;
|
86 |
+
}
|
87 |
global $wpdb;
|
88 |
$this->m_oWpdb = $wpdb;
|
89 |
}
|
90 |
|
91 |
+
/**
|
92 |
+
* @param array $inaLogData
|
93 |
+
* @return type
|
94 |
+
*/
|
95 |
+
public function addDataToWrite( $inaLogData ) {
|
96 |
+
if ( empty( $inaLogData ) || empty( $inaLogData['messages'] ) ) {
|
97 |
+
return;
|
98 |
+
}
|
99 |
+
if ( empty( $this->m_aDataToWrite ) ) {
|
100 |
+
$this->m_aDataToWrite = array();
|
101 |
+
}
|
102 |
+
$this->m_aDataToWrite[] = $this->completeDataForWrite( $inaLogData );
|
103 |
+
}
|
104 |
+
|
105 |
+
/**
|
106 |
+
* Ensures the data provided for writing to the db meets all the requirements.
|
107 |
+
*
|
108 |
+
* This should be overridden per implementation
|
109 |
+
*
|
110 |
+
* @return array
|
111 |
+
*/
|
112 |
+
protected function completeDataForWrite( $inaLogData ) {
|
113 |
+
if ( is_null( $inaLogData ) ) {
|
114 |
+
return array();
|
115 |
+
}
|
116 |
+
return $inaLogData;
|
117 |
+
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* @return boolean - whether the write to the DB was successful.
|
121 |
+
*/
|
122 |
+
public function commitData() {
|
123 |
+
if ( empty( $this->m_aDataToWrite ) ) {
|
124 |
+
return;
|
125 |
+
}
|
126 |
+
$this->loadWpdb();
|
127 |
+
$fSuccess = true;
|
128 |
+
foreach( $this->m_aDataToWrite as $aDataEntry ) {
|
129 |
+
$fSuccess = $fSuccess && $this->insertIntoTable( $aDataEntry );
|
130 |
+
}
|
131 |
+
if ( $fSuccess ) {
|
132 |
+
$this->flushData();
|
133 |
+
}
|
134 |
+
return $fSuccess;
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
*
|
139 |
+
*/
|
140 |
+
protected function flushData() {
|
141 |
+
$this->m_aDataToWrite = null;
|
142 |
+
}
|
143 |
+
|
144 |
public function insertIntoTable( $inaData ) {
|
145 |
return $this->m_oWpdb->insert( $this->m_sTableName, $inaData );
|
146 |
}
|
165 |
public function deleteRowsFromTable( $inaWhere ) {
|
166 |
return $this->m_oWpdb->delete( $this->m_sTableName, $inaWhere );
|
167 |
}
|
168 |
+
|
169 |
+
protected function deleteAllRowsOlderThan( $innTimeStamp ) {
|
170 |
+
$sQuery = "
|
171 |
+
DELETE from `%s`
|
172 |
+
WHERE
|
173 |
+
`created_at` < '%s'
|
174 |
+
";
|
175 |
+
$sQuery = sprintf( $sQuery,
|
176 |
+
$this->m_sTableName,
|
177 |
+
$innTimeStamp
|
178 |
+
);
|
179 |
+
$this->doSql( $sQuery );
|
180 |
+
}
|
181 |
|
182 |
public function createTable() {
|
183 |
//Override this function to create the Table you want.
|
213 |
* @param string $insSql
|
214 |
*/
|
215 |
public function doSql( $insSql ) {
|
216 |
+
$this->loadWpdb();
|
217 |
+
$fResult = $this->m_oWpdb->query( $insSql );
|
218 |
+
return $fResult;
|
219 |
}
|
220 |
|
221 |
private function setTableName( $insTableName ) {
|
222 |
+
return $this->m_sTableName = esc_sql( $this->m_oWpdb->base_prefix . self::DB_TABLE_PREFIX . $insTableName );
|
223 |
+
}
|
224 |
+
|
225 |
+
/**
|
226 |
+
* Override this to provide custom cleanup.
|
227 |
+
*/
|
228 |
+
public function deleteAndCleanUp() {
|
229 |
+
parent::deleteAndCleanUp();
|
230 |
+
$this->dropTable();
|
231 |
+
}
|
232 |
+
|
233 |
+
/**
|
234 |
+
* Will setup the cleanup cron to clean out old entries. This should be overridden per implementation.
|
235 |
+
*/
|
236 |
+
protected function createCleanupCron() {
|
237 |
+
if ( ! wp_next_scheduled( self::CleanupCronActionHook ) && ! defined( 'WP_INSTALLING' ) ) {
|
238 |
+
$nNextRun = strtotime( 'tomorrow 6am' ) - get_option( 'gmt_offset' ) * HOUR_IN_SECONDS;
|
239 |
+
wp_schedule_event( $nNextRun, 'daily', self::CleanupCronActionHook );
|
240 |
+
}
|
241 |
}
|
242 |
|
243 |
+
public function cleanupDatabase() {
|
244 |
+
//by default do nothing - oiverrde this method
|
245 |
+
}
|
246 |
+
|
247 |
+
/**
|
248 |
+
* @return bool
|
249 |
+
*/
|
250 |
+
public function getTableExists() {
|
251 |
+
$sQuery = "
|
252 |
+
SHOW TABLES LIKE '%s'
|
253 |
+
";
|
254 |
+
$sQuery = sprintf( $sQuery, $this->m_sTableName );
|
255 |
+
$mResult = $this->m_oWpdb->get_var( $sQuery );
|
256 |
+
return !is_null( $mResult );
|
257 |
+
}
|
258 |
}
|
259 |
|
260 |
endif;
|
src/icwp-data-processor.php
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<?php
|
2 |
|
3 |
/**
|
4 |
-
* Copyright (c)
|
5 |
* All rights reserved.
|
6 |
*
|
7 |
* Version: 2013-08-27-A
|
@@ -19,12 +19,62 @@
|
|
19 |
*
|
20 |
*/
|
21 |
|
22 |
-
if ( !class_exists('
|
23 |
|
24 |
-
class
|
25 |
|
26 |
public static $fUseFilter = false;
|
27 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
static public function ExtractIpAddresses( $insAddresses = '' ) {
|
29 |
|
30 |
$aRawAddresses = array();
|
@@ -96,11 +146,13 @@ class ICWP_DataProcessor {
|
|
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
|
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 |
}
|
@@ -200,6 +252,65 @@ class ICWP_DataProcessor {
|
|
200 |
}
|
201 |
return false;
|
202 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
203 |
|
204 |
/**
|
205 |
* The only ranges currently accepted are a.b.c.d-f.g.h.j
|
@@ -231,6 +342,24 @@ class ICWP_DataProcessor {
|
|
231 |
return false;
|
232 |
}
|
233 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
234 |
/**
|
235 |
* @param integer $innLength
|
236 |
* @param boolean $infBeginLetter
|
@@ -254,6 +383,71 @@ class ICWP_DataProcessor {
|
|
254 |
}
|
255 |
return $sPassword;
|
256 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
257 |
}
|
258 |
|
|
|
|
|
|
|
|
|
259 |
endif;
|
1 |
<?php
|
2 |
|
3 |
/**
|
4 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
5 |
* All rights reserved.
|
6 |
*
|
7 |
* Version: 2013-08-27-A
|
19 |
*
|
20 |
*/
|
21 |
|
22 |
+
if ( !class_exists('ICWP_DataProcessor_V1') ):
|
23 |
|
24 |
+
class ICWP_DataProcessor_V1 {
|
25 |
|
26 |
public static $fUseFilter = false;
|
27 |
|
28 |
+
/**
|
29 |
+
* Cloudflare compatible.
|
30 |
+
*
|
31 |
+
* @param boolean $infAsLong
|
32 |
+
* @return bool|integer - visitor IP Address as IP2Long
|
33 |
+
*/
|
34 |
+
public static function GetVisitorIpAddress( $infAsLong = true ) {
|
35 |
+
|
36 |
+
$aAddressSourceOptions = array(
|
37 |
+
'HTTP_CF_CONNECTING_IP',
|
38 |
+
'HTTP_CLIENT_IP',
|
39 |
+
'HTTP_X_FORWARDED_FOR',
|
40 |
+
'HTTP_X_FORWARDED',
|
41 |
+
'HTTP_FORWARDED',
|
42 |
+
'REMOTE_ADDR'
|
43 |
+
);
|
44 |
+
$fCanUseFilter = function_exists( 'filter_var' ) && defined( 'FILTER_FLAG_NO_PRIV_RANGE' ) && defined( 'FILTER_FLAG_IPV4' );
|
45 |
+
|
46 |
+
$aIpAddresses = array();
|
47 |
+
foreach( $aAddressSourceOptions as $sOption ) {
|
48 |
+
if ( empty( $_SERVER[ $sOption ] ) ) {
|
49 |
+
continue;
|
50 |
+
}
|
51 |
+
$sIpAddressToTest = $_SERVER[ $sOption ];
|
52 |
+
|
53 |
+
$aIpAddresses = explode( ',', $sIpAddressToTest ); //sometimes a comma-separated list is returned
|
54 |
+
foreach( $aIpAddresses as $sIpAddress ) {
|
55 |
+
|
56 |
+
if ( $fCanUseFilter && !self::IsAddressInPublicIpRange( $sIpAddress ) ) {
|
57 |
+
continue;
|
58 |
+
}
|
59 |
+
else {
|
60 |
+
return $infAsLong? ip2long( $sIpAddress ) : $sIpAddress;
|
61 |
+
}
|
62 |
+
}
|
63 |
+
}
|
64 |
+
return false;
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Assumes a valid IPv4 address is provided as we're only testing for a whether the IP is public or not.
|
69 |
+
*
|
70 |
+
* @param string $insIpAddress
|
71 |
+
* @uses filter_var
|
72 |
+
* @return boolean
|
73 |
+
*/
|
74 |
+
public static function IsAddressInPublicIpRange( $insIpAddress ) {
|
75 |
+
return filter_var( $insIpAddress, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE );
|
76 |
+
}
|
77 |
+
|
78 |
static public function ExtractIpAddresses( $insAddresses = '' ) {
|
79 |
|
80 |
$aRawAddresses = array();
|
146 |
*
|
147 |
* @param array $inaCurrent - the list to which to add the new addresses
|
148 |
* @param array $inaNewRawAddresses - the new IPv4 addresses
|
149 |
+
* @param int $outnNewAdded - the count of newly added IPs
|
150 |
* @return unknown|Ambigous <multitype:multitype: , string>
|
151 |
*/
|
152 |
public static function Add_New_Raw_Ips( $inaCurrent, $inaNewRawAddresses, &$outnNewAdded = 0 ) {
|
153 |
|
154 |
+
$outnNewAdded = 0;
|
155 |
+
|
156 |
if ( empty( $inaNewRawAddresses ) ) {
|
157 |
return $inaCurrent;
|
158 |
}
|
252 |
}
|
253 |
return false;
|
254 |
}
|
255 |
+
|
256 |
+
/**
|
257 |
+
* Taken from http://www.phacks.net/detecting-search-engine-bot-and-web-spiders/
|
258 |
+
*/
|
259 |
+
public static function IsSearchEngineBot() {
|
260 |
+
|
261 |
+
if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
|
262 |
+
return false;
|
263 |
+
}
|
264 |
+
$sUserAgent = $_SERVER['HTTP_USER_AGENT'];
|
265 |
+
$sBots = 'Googlebot|bingbot|Twitterbot|Baiduspider|ia_archiver|R6_FeedFetcher|NetcraftSurveyAgent'
|
266 |
+
.'|Sogou web spider|Yahoo! Slurp|facebookexternalhit|PrintfulBot|msnbot|UnwindFetchor|urlresolver|Butterfly|TweetmemeBot';
|
267 |
+
|
268 |
+
return ( preg_match( "/$sBots/", $sUserAgent ) > 0 );
|
269 |
+
//
|
270 |
+
// $aBots = array(
|
271 |
+
// 'Googlebot',
|
272 |
+
// 'bingbot',
|
273 |
+
// 'Twitterbot',
|
274 |
+
// 'Baiduspider',
|
275 |
+
// 'ia_archiver',
|
276 |
+
// 'R6_FeedFetcher',
|
277 |
+
// 'NetcraftSurveyAgent',
|
278 |
+
// 'Sogou web spider',
|
279 |
+
// 'Yahoo! Slurp',
|
280 |
+
// 'facebookexternalhit',
|
281 |
+
// 'PrintfulBot',
|
282 |
+
// 'msnbot',
|
283 |
+
// 'UnwindFetchor',
|
284 |
+
// 'urlresolver',
|
285 |
+
// 'Butterfly',
|
286 |
+
// 'TweetmemeBot'
|
287 |
+
// );
|
288 |
+
//
|
289 |
+
// $aCrawlers = array(
|
290 |
+
// 'Google' => 'Google',
|
291 |
+
// 'msnbot' => 'MSN',
|
292 |
+
// 'Rambler' => 'Rambler',
|
293 |
+
// 'Yahoo' => 'Yahoo',
|
294 |
+
// 'AbachoBOT' => 'AbachoBOT',
|
295 |
+
// 'accoona' => 'Accoona',
|
296 |
+
// 'AcoiRobot' => 'AcoiRobot',
|
297 |
+
// 'ASPSeek' => 'ASPSeek',
|
298 |
+
// 'CrocCrawler' => 'CrocCrawler',
|
299 |
+
// 'Dumbot' => 'Dumbot',
|
300 |
+
// 'FAST-WebCrawler' => 'FAST-WebCrawler',
|
301 |
+
// 'GeonaBot' => 'GeonaBot',
|
302 |
+
// 'Gigabot' => 'Gigabot',
|
303 |
+
// 'Lycos' => 'Lycos spider',
|
304 |
+
// 'MSRBOT' => 'MSRBOT',
|
305 |
+
// 'Scooter' => 'Altavista robot',
|
306 |
+
// 'AltaVista' => 'Altavista robot',
|
307 |
+
// 'IDBot' => 'ID-Search Bot',
|
308 |
+
// 'eStyle' => 'eStyle Bot',
|
309 |
+
// 'Scrubby' => 'Scrubby robot'
|
310 |
+
// );
|
311 |
+
|
312 |
+
return array_key_exists( $sUserAgent, $aCrawlers );
|
313 |
+
}
|
314 |
|
315 |
/**
|
316 |
* The only ranges currently accepted are a.b.c.d-f.g.h.j
|
342 |
return false;
|
343 |
}
|
344 |
|
345 |
+
public static function CleanYubikeyUniqueKeys( $insRawKeys ) {
|
346 |
+
$aKeys = explode( "\n", $insRawKeys );
|
347 |
+
foreach( $aKeys as $nIndex => $sUsernameKey ) {
|
348 |
+
if ( empty( $sUsernameKey ) ) {
|
349 |
+
unset( $aKeys[$nIndex] );
|
350 |
+
continue;
|
351 |
+
}
|
352 |
+
$aParts = array_map( 'trim', explode( ',', $sUsernameKey ) );
|
353 |
+
if ( empty( $aParts[0] ) || empty( $aParts[1] ) || strlen( $aParts[1] ) < 12 ) {
|
354 |
+
unset( $aKeys[$nIndex] );
|
355 |
+
continue;
|
356 |
+
}
|
357 |
+
$aParts[1] = substr( $aParts[1], 0, 12 );
|
358 |
+
$aKeys[$nIndex] = array( $aParts[0] => $aParts[1] );
|
359 |
+
}
|
360 |
+
return $aKeys;
|
361 |
+
}
|
362 |
+
|
363 |
/**
|
364 |
* @param integer $innLength
|
365 |
* @param boolean $infBeginLetter
|
383 |
}
|
384 |
return $sPassword;
|
385 |
}
|
386 |
+
|
387 |
+
/**
|
388 |
+
* @param string $insKey
|
389 |
+
* @param boolean $infIncludeCookie
|
390 |
+
* @return mixed|null
|
391 |
+
*/
|
392 |
+
public static function FetchRequest( $insKey, $infIncludeCookie = true ) {
|
393 |
+
$mFetchVal = self::FetchPost( $insKey );
|
394 |
+
if ( is_null( $mFetchVal ) ) {
|
395 |
+
$mFetchVal = self::FetchGet( $insKey );
|
396 |
+
if ( is_null( $mFetchVal && $infIncludeCookie ) ) {
|
397 |
+
$mFetchVal = self::FetchCookie( $insKey );
|
398 |
+
}
|
399 |
+
}
|
400 |
+
return $mFetchVal;
|
401 |
+
}
|
402 |
+
/**
|
403 |
+
* @param string $insKey
|
404 |
+
* @return mixed|null
|
405 |
+
*/
|
406 |
+
public static function FetchGet( $insKey ) {
|
407 |
+
if ( function_exists( 'filter_input' ) && defined( 'INPUT_GET' ) ) {
|
408 |
+
return filter_input( INPUT_GET, $insKey );
|
409 |
+
}
|
410 |
+
return self::ArrayFetch( $_GET, $insKey );
|
411 |
+
}
|
412 |
+
/**
|
413 |
+
* @param string $insKey The $_POST key
|
414 |
+
* @return mixed|null
|
415 |
+
*/
|
416 |
+
public static function FetchPost( $insKey ) {
|
417 |
+
if ( function_exists( 'filter_input' ) && defined( 'INPUT_POST' ) ) {
|
418 |
+
return filter_input( INPUT_POST, $insKey );
|
419 |
+
}
|
420 |
+
return self::ArrayFetch( $_POST, $insKey );
|
421 |
+
}
|
422 |
+
/**
|
423 |
+
* @param string $insKey The $_POST key
|
424 |
+
* @return mixed|null
|
425 |
+
*/
|
426 |
+
public static function FetchCookie( $insKey ) {
|
427 |
+
if ( function_exists( 'filter_input' ) && defined( 'INPUT_COOKIE' ) ) {
|
428 |
+
return filter_input( INPUT_COOKIE, $insKey );
|
429 |
+
}
|
430 |
+
return self::ArrayFetch( $_COOKIE, $insKey );
|
431 |
+
}
|
432 |
+
|
433 |
+
/**
|
434 |
+
* @param array $inaArray
|
435 |
+
* @param string $insKey The array key
|
436 |
+
* @return mixed|null
|
437 |
+
*/
|
438 |
+
public static function ArrayFetch( &$inaArray, $insKey ) {
|
439 |
+
if ( empty( $inaArray ) ) {
|
440 |
+
return null;
|
441 |
+
}
|
442 |
+
if ( !isset( $inaArray[$insKey] ) ) {
|
443 |
+
return null;
|
444 |
+
}
|
445 |
+
return $inaArray[$insKey];
|
446 |
+
}
|
447 |
}
|
448 |
|
449 |
+
endif;
|
450 |
+
|
451 |
+
if ( !class_exists('ICWP_WPSF_DataProcessor') ):
|
452 |
+
class ICWP_WPSF_DataProcessor extends ICWP_DataProcessor_V1 { }
|
453 |
endif;
|
src/icwp-feature-master.php
ADDED
@@ -0,0 +1,337 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
+
* All rights reserved.
|
5 |
+
*
|
6 |
+
* This is
|
7 |
+
* distributed under the GNU General Public License, Version 2,
|
8 |
+
* June 1991. Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin
|
9 |
+
* St, Fifth Floor, Boston, MA 02110, USA
|
10 |
+
*
|
11 |
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
12 |
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
13 |
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
14 |
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
15 |
+
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
16 |
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
17 |
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
18 |
+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
19 |
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
20 |
+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
21 |
+
*/
|
22 |
+
|
23 |
+
require_once( dirname(__FILE__).'/icwp-pure-base.php' );
|
24 |
+
|
25 |
+
if ( !class_exists('ICWP_Feature_Master') ):
|
26 |
+
|
27 |
+
class ICWP_Feature_Master extends ICWP_Pure_Base_V4 {
|
28 |
+
|
29 |
+
/**
|
30 |
+
*@var array
|
31 |
+
*/
|
32 |
+
protected $m_aFeatures;
|
33 |
+
|
34 |
+
/**
|
35 |
+
*@var array
|
36 |
+
*/
|
37 |
+
protected $m_aOptionsHandlers;
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @var ICWP_OptionsHandler_Wpsf
|
41 |
+
*/
|
42 |
+
protected $m_oPluginMainOptions;
|
43 |
+
|
44 |
+
protected $fHasFtpOverride = false;
|
45 |
+
|
46 |
+
public function __construct( $inaFeatures, $inaOptions ) {
|
47 |
+
parent::__construct();
|
48 |
+
$this->m_aFeatures = $inaFeatures;
|
49 |
+
$this->m_aOptionsHandlers = $inaOptions;
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Based on the existence of files placed within the plugin directory, will enable or disable
|
54 |
+
* all registered features and return the value of the override setting that was put in place.
|
55 |
+
*
|
56 |
+
* @return string - override settings (empty string if none).
|
57 |
+
*/
|
58 |
+
protected function override() {
|
59 |
+
|
60 |
+
if ( $this->m_oWpFs->exists( path_join($this->m_sPluginDir, 'forceOff') ) ) {
|
61 |
+
$fHasFtpOverride = true;
|
62 |
+
$sSetting = 'N';
|
63 |
+
}
|
64 |
+
else if ( $this->m_oWpFs->exists( path_join($this->m_sPluginDir, 'forceOn') ) ) {
|
65 |
+
$fHasFtpOverride = true;
|
66 |
+
$sSetting = 'Y';
|
67 |
+
}
|
68 |
+
else {
|
69 |
+
$sSetting = '';
|
70 |
+
}
|
71 |
+
|
72 |
+
if ( $sSetting == '' ) {
|
73 |
+
return $sSetting;
|
74 |
+
}
|
75 |
+
|
76 |
+
$aFeatures = $this->getFeaturesMap();
|
77 |
+
foreach( $aFeatures as $sFeature => $sName ) {
|
78 |
+
$this->setSharedOption( 'enable_'.$sFeature, $sSetting );
|
79 |
+
}
|
80 |
+
return $sSetting;
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* @return array
|
85 |
+
*/
|
86 |
+
protected function getFeaturesMap() {
|
87 |
+
return $this->m_aFeatures;
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Given a certain feature 'slug' will return true if this is a particular supported feature of this plugin.
|
92 |
+
*
|
93 |
+
* @param string $insFeature
|
94 |
+
* @return boolean
|
95 |
+
*/
|
96 |
+
public function getIsFeature( $insFeature ) {
|
97 |
+
return array_key_exists( $insFeature, $this->getFeaturesMap() ) || in_array( $insFeature, $this->getFeaturesMap() );
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* @param string $insFeature - firewall, login_protect, comments_filter, lockdown
|
102 |
+
* @return boolean
|
103 |
+
*/
|
104 |
+
public function getIsMainFeatureEnabled( $insFeature ) {
|
105 |
+
|
106 |
+
if ( $this->m_oWpFs->exists( $this->m_sPluginPath . 'forceOff' ) ) {
|
107 |
+
return false;
|
108 |
+
}
|
109 |
+
else if ( $this->m_oWpFs->exists( $this->m_sPluginPath . 'forceOn' ) ) {
|
110 |
+
return true;
|
111 |
+
}
|
112 |
+
|
113 |
+
$aFeatures = $this->getFeaturesMap();
|
114 |
+
if ( array_key_exists( $insFeature, $aFeatures ) ) {
|
115 |
+
$fEnabled = $this->m_oPluginMainOptions->getOpt( 'enable_'.$insFeature ) == 'Y';
|
116 |
+
}
|
117 |
+
else {
|
118 |
+
$fEnabled = false;
|
119 |
+
}
|
120 |
+
return $fEnabled;
|
121 |
+
}
|
122 |
+
|
123 |
+
/**
|
124 |
+
* This is necessary because we store these values in several places and we need to always keep it in sync.
|
125 |
+
*
|
126 |
+
* @param string $insOption
|
127 |
+
* @param mixed $inmValue
|
128 |
+
* @return boolean
|
129 |
+
*/
|
130 |
+
public function setSharedOption( $insOption, $inmValue ) {
|
131 |
+
|
132 |
+
$aFeatures = $this->getFeaturesMap();
|
133 |
+
|
134 |
+
$sFeature = str_replace( 'enable_', '', $insOption );
|
135 |
+
if ( !array_key_exists( $sFeature, $aFeatures ) ) {
|
136 |
+
return;
|
137 |
+
}
|
138 |
+
|
139 |
+
$this->loadOptionsHandler( $aFeatures[$sFeature] );
|
140 |
+
$sOptions = 'm_o'.$aFeatures[$sFeature].'Options';// e.g. m_oFirewallOptions
|
141 |
+
$this->{$sOptions}->setOpt( $insOption, $inmValue );
|
142 |
+
$this->m_oPluginMainOptions->setOpt( $insOption, $inmValue );
|
143 |
+
}
|
144 |
+
|
145 |
+
protected function loadOptionsHandler( $insOptionHandler = 'PluginMain', $infRecreate = false, $infFullBuild = false ) {
|
146 |
+
|
147 |
+
$aAllHandlers = array_values( $this->getFeaturesMap() );
|
148 |
+
$aAllHandlers[] = 'PluginMain';
|
149 |
+
|
150 |
+
// special case
|
151 |
+
if ( $insOptionHandler == 'all' ) {
|
152 |
+
foreach( $aAllHandlers as $sHandler ) {
|
153 |
+
$fSuccess = $this->loadOptionsHandler( $sHandler, $infRecreate, $infFullBuild );
|
154 |
+
}
|
155 |
+
return $fSuccess;
|
156 |
+
}
|
157 |
+
|
158 |
+
if ( !in_array( $insOptionHandler, $aAllHandlers ) ) {
|
159 |
+
return false;
|
160 |
+
}
|
161 |
+
|
162 |
+
$sOptionsVarName = 'm_o'.$insOptionHandler.'Options'; // e.g. m_oPluginMainOptions
|
163 |
+
if ( $insOptionHandler == 'PluginMain' ) {
|
164 |
+
$sSourceFile = dirname(__FILE__).'/icwp-optionshandler-'.$this->m_sPluginSlug.'.php'; // e.g. icwp-optionshandler-wpsf.php
|
165 |
+
$sClassName = 'ICWP_OptionsHandler_'.ucfirst( $this->m_sPluginSlug ); // e.g. ICWP_OptionsHandler_Wpsf
|
166 |
+
}
|
167 |
+
else {
|
168 |
+
$sSourceFile = dirname(__FILE__).'/icwp-optionshandler-'.strtolower($insOptionHandler).'.php'; // e.g. icwp-optionshandler-wpsf.php
|
169 |
+
$sClassName = 'ICWP_OptionsHandler_'.$insOptionHandler; // e.g. ICWP_OptionsHandler_Wpsf
|
170 |
+
}
|
171 |
+
|
172 |
+
require_once( $sSourceFile );
|
173 |
+
if ( $infRecreate || !isset( $this->{$sOptionsVarName} ) ) {
|
174 |
+
$this->{$sOptionsVarName} = new $sClassName( self::$sOptionPrefix, $this->m_sVersion, $infFullBuild );
|
175 |
+
}
|
176 |
+
if ( $infFullBuild ) {
|
177 |
+
$this->{$sOptionsVarName}->buildOptions();
|
178 |
+
}
|
179 |
+
return true;
|
180 |
+
}
|
181 |
+
|
182 |
+
/**
|
183 |
+
* Given a feature/processor name will load the variable for it, including the appropriate source file.
|
184 |
+
*
|
185 |
+
* @param string $insProcessorName
|
186 |
+
* @param boolean $infRebuild
|
187 |
+
* @return ICWP_OptionsHandler_Base_Wpsf
|
188 |
+
*/
|
189 |
+
protected function loadProcessor( $insProcessorName, $infRebuild = false ) {
|
190 |
+
$aAllProcessors = $this->getFeaturesMap();
|
191 |
+
|
192 |
+
if ( !in_array( $insProcessorName, array_values($aAllProcessors) ) ) {
|
193 |
+
$this->doWpDie( sprintf('Processor %s is not permitted here.', $insProcessorName) );
|
194 |
+
}
|
195 |
+
$sProcessorVarName = 'm_o'.$insProcessorName.'Processor'; // e.g. m_oFirewallProcessor
|
196 |
+
$sSourceFile = dirname(__FILE__).'/icwp-processor-'.strtolower($insProcessorName).'.php'; // e.g. icwp-optionshandler-wpsf.php
|
197 |
+
$sClassName = 'ICWP_'.strtoupper( $this->m_sPluginSlug ).'_'.$insProcessorName.'Processor'; // e.g. ICWP_WPSF_FirewallProcessor
|
198 |
+
$sStorageKey = array_search($insProcessorName, $aAllProcessors).'_processor'; // e.g. firewall_processor
|
199 |
+
$sOptionsHandlerVarName = 'm_o'.$insProcessorName.'Options'; // e.g. m_oFirewallOptions
|
200 |
+
|
201 |
+
require_once( $sSourceFile );
|
202 |
+
if ( $infRebuild || empty( $this->{$sProcessorVarName} ) ) {
|
203 |
+
$oTemp = $this->getOption( $sStorageKey );
|
204 |
+
if ( !$infRebuild && is_object( $oTemp ) && ( $oTemp instanceof $sClassName ) ) {
|
205 |
+
$oTemp->reset();
|
206 |
+
}
|
207 |
+
else {
|
208 |
+
$oTemp = new $sClassName( self::$sOptionPrefix );
|
209 |
+
}
|
210 |
+
$this->{$sProcessorVarName} = $oTemp;
|
211 |
+
}
|
212 |
+
if ( $this->loadOptionsHandler( $insProcessorName ) ) {
|
213 |
+
$aOptionsValues = $this->{$sOptionsHandlerVarName}->getPluginOptionsValues();
|
214 |
+
$this->{$sProcessorVarName}->setOptions( $aOptionsValues );
|
215 |
+
}
|
216 |
+
return $this->{$sProcessorVarName};
|
217 |
+
}
|
218 |
+
|
219 |
+
protected function resetProcessor( $insProcessorName ) {
|
220 |
+
if ( !$this->getIsFeature( $insProcessorName ) ) {
|
221 |
+
$this->doWpDie('Not a processor: '.$insProcessorName);
|
222 |
+
return;
|
223 |
+
}
|
224 |
+
$this->loadProcessor( $insProcessorName );
|
225 |
+
return;
|
226 |
+
}
|
227 |
+
|
228 |
+
protected function resetOptionHandler( $insOptionName ) {
|
229 |
+
if ( !$this->getIsFeature( $insOptionName ) ) {
|
230 |
+
$this->doWpDie('Not a feature: '.$insOptionName);
|
231 |
+
return;
|
232 |
+
}
|
233 |
+
$this->loadOptionsHandler( $insOptionName );
|
234 |
+
return;
|
235 |
+
}
|
236 |
+
|
237 |
+
public function clearCaches() {
|
238 |
+
$aFeatures = $this->getFeaturesMap();
|
239 |
+
foreach( $aFeatures as $sFeature ) {
|
240 |
+
$this->resetOptionHandler( $sFeature );
|
241 |
+
$this->resetProcessor( $sFeature );
|
242 |
+
}
|
243 |
+
}
|
244 |
+
|
245 |
+
protected function getAllOptionsHandlers() {
|
246 |
+
$this->loadOptionsHandler('all');
|
247 |
+
$aOptions = array();
|
248 |
+
foreach( $this->m_aOptionsHandlers as $sName ) {
|
249 |
+
if ( isset( $this->{$sName} ) ) {
|
250 |
+
$aOptions[] = &$this->{$sName};
|
251 |
+
}
|
252 |
+
}
|
253 |
+
return $aOptions;
|
254 |
+
}
|
255 |
+
|
256 |
+
/**
|
257 |
+
* Makes sure and cache the processors after all is said and done.
|
258 |
+
*/
|
259 |
+
public function saveProcessors() {
|
260 |
+
$aFeatures = $this->getFeaturesMap();
|
261 |
+
foreach( $aFeatures as $sSlug => $sProcessorName ) {
|
262 |
+
$oProcessor = $this->getProcessorVar( $sProcessorName );
|
263 |
+
if ( !is_null($oProcessor) && is_object($oProcessor) ) {
|
264 |
+
$oProcessor->store();
|
265 |
+
}
|
266 |
+
}
|
267 |
+
}
|
268 |
+
|
269 |
+
/**
|
270 |
+
* Makes sure and cache the processors after all is said and done.
|
271 |
+
*/
|
272 |
+
public function saveOptions() {
|
273 |
+
$aOptions = $this->getAllOptionsHandlers();
|
274 |
+
foreach( $aOptions as &$oOption ) {
|
275 |
+
if ( isset( $oOption ) ) {
|
276 |
+
$oOption->savePluginOptions();
|
277 |
+
}
|
278 |
+
}
|
279 |
+
}
|
280 |
+
|
281 |
+
/**
|
282 |
+
*
|
283 |
+
* @param string $insProcessorName
|
284 |
+
* @param bool $infLoad
|
285 |
+
* @return null|ICWP_WPSF_BaseProcessor
|
286 |
+
*/
|
287 |
+
protected function getProcessorVar( $insProcessorName, $infLoad = false ) {
|
288 |
+
if ( !$this->getIsFeature( $insProcessorName ) ) {
|
289 |
+
return null;
|
290 |
+
}
|
291 |
+
$sProcessorVariable = 'm_o'.$insProcessorName.'Processor';
|
292 |
+
if ( $infLoad || !isset( $this->{$sProcessorVariable} ) ) {
|
293 |
+
$this->loadProcessor( $insProcessorName );
|
294 |
+
}
|
295 |
+
$sProcessorVariable = 'm_o'.$insProcessorName.'Processor';
|
296 |
+
return $this->{$sProcessorVariable};
|
297 |
+
}
|
298 |
+
|
299 |
+
protected function shutdown() {
|
300 |
+
parent::shutdown();
|
301 |
+
$this->saveOptions();
|
302 |
+
$this->saveProcessors();
|
303 |
+
}
|
304 |
+
|
305 |
+
protected function deleteAllPluginDbOptions() {
|
306 |
+
if ( !current_user_can( 'manage_options' ) ) {
|
307 |
+
return;
|
308 |
+
}
|
309 |
+
|
310 |
+
$aOptions = $this->getAllOptionsHandlers();
|
311 |
+
foreach( $aOptions as &$oOption ) {
|
312 |
+
$oOption->deletePluginOptions();
|
313 |
+
}
|
314 |
+
|
315 |
+
$aFeatures = $this->getFeaturesMap();
|
316 |
+
foreach( $aFeatures as $sSlug => $sProcessorName ) {
|
317 |
+
$oProcessor = $this->getProcessorVar( $sProcessorName, true );
|
318 |
+
if ( !is_null($oProcessor) && is_object($oProcessor) ) {
|
319 |
+
$oProcessor->deleteAndCleanUp();
|
320 |
+
}
|
321 |
+
}
|
322 |
+
remove_action( 'shutdown', array( $this, 'onWpShutdown' ) );
|
323 |
+
}
|
324 |
+
|
325 |
+
public function onWpActivatePlugin() {
|
326 |
+
$this->loadOptionsHandler( 'all', true, true );
|
327 |
+
}
|
328 |
+
|
329 |
+
public function onWpDeactivatePlugin() {
|
330 |
+
if ( $this->m_oPluginMainOptions->getOpt( 'delete_on_deactivate' ) == 'Y' ) {
|
331 |
+
$this->deleteAllPluginDbOptions();
|
332 |
+
}
|
333 |
+
}
|
334 |
+
|
335 |
+
}
|
336 |
+
|
337 |
+
endif;
|
src/icwp-import-base-processor.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* Copyright (c)
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
@@ -21,7 +21,7 @@ require_once( dirname(__FILE__).'/icwp-data-processor.php' );
|
|
21 |
|
22 |
if ( !class_exists('ICWP_ImportBaseProcessor') ):
|
23 |
|
24 |
-
class ICWP_ImportBaseProcessor extends
|
25 |
|
26 |
/**
|
27 |
* The options prefix used by the target plugin
|
1 |
<?php
|
2 |
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
21 |
|
22 |
if ( !class_exists('ICWP_ImportBaseProcessor') ):
|
23 |
|
24 |
+
class ICWP_ImportBaseProcessor extends ICWP_WPSF_BaseProcessor {
|
25 |
|
26 |
/**
|
27 |
* The options prefix used by the target plugin
|
src/icwp-import-wpf2-processor.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* Copyright (c)
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
@@ -136,8 +136,8 @@ class ICWP_ImportWpf2Processor extends ICWP_ImportBaseProcessor {
|
|
136 |
if ( empty( $aTargetIpWhitelist ) ) {
|
137 |
$aTargetIpWhitelist = array();
|
138 |
}
|
139 |
-
$this->m_oFirewallOptions->setOpt( $this->m_aOptionsMap['WP_firewall_whitelisted_ip'],
|
140 |
-
// $this->updateTargetOption( $this->m_aOptionsMap['WP_firewall_whitelisted_ip'],
|
141 |
|
142 |
// Whitelisted Pages and Vars... maybe later :|
|
143 |
}
|
1 |
<?php
|
2 |
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
136 |
if ( empty( $aTargetIpWhitelist ) ) {
|
137 |
$aTargetIpWhitelist = array();
|
138 |
}
|
139 |
+
$this->m_oFirewallOptions->setOpt( $this->m_aOptionsMap['WP_firewall_whitelisted_ip'], ICWP_WPSF_DataProcessor::Add_New_Raw_Ips( $aTargetIpWhitelist, $aNewList ) );
|
140 |
+
// $this->updateTargetOption( $this->m_aOptionsMap['WP_firewall_whitelisted_ip'], ICWP_WPSF_DataProcessor::Add_New_Raw_Ips( $aTargetIpWhitelist, $aNewList ) );
|
141 |
|
142 |
// Whitelisted Pages and Vars... maybe later :|
|
143 |
}
|
src/icwp-once.php
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
+
* All rights reserved.
|
5 |
+
*
|
6 |
+
* Version: 2013-12-17-V1
|
7 |
+
*
|
8 |
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
9 |
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
10 |
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
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_Once_V1') ):
|
21 |
+
|
22 |
+
class ICWP_Once_V1 {
|
23 |
+
/**
|
24 |
+
* @var ICWP_WPSF_Once
|
25 |
+
*/
|
26 |
+
protected static $oInstance = NULL;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @return ICWP_Once_V1
|
30 |
+
*/
|
31 |
+
public static function & GetInstance( $insCalledClass = '' ) {
|
32 |
+
if ( is_null( self::$oInstance ) ) {
|
33 |
+
if ( function_exists( 'get_called_class' ) ) {
|
34 |
+
$sCalledClass = get_called_class();
|
35 |
+
self::$oInstance = new $sCalledClass();
|
36 |
+
}
|
37 |
+
else {
|
38 |
+
self::$oInstance = new $insCalledClass();
|
39 |
+
}
|
40 |
+
}
|
41 |
+
return self::$oInstance;
|
42 |
+
}
|
43 |
+
}
|
44 |
+
|
45 |
+
endif;
|
46 |
+
|
47 |
+
if ( !class_exists('ICWP_WPSF_Once') ):
|
48 |
+
class ICWP_WPSF_Once extends ICWP_Once_V1 { }
|
49 |
+
endif;
|
src/icwp-optionshandler-autoupdates.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* Copyright (c)
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
@@ -17,16 +17,16 @@
|
|
17 |
|
18 |
require_once( dirname(__FILE__).'/icwp-optionshandler-base.php' );
|
19 |
|
20 |
-
if ( !class_exists('
|
21 |
|
22 |
-
class
|
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() {
|
@@ -37,11 +37,27 @@ class ICWP_OptionsHandler_AutoUpdates extends ICWP_OptionsHandler_Base_WPSF {
|
|
37 |
array(
|
38 |
'enable_autoupdates',
|
39 |
'',
|
40 |
-
'
|
41 |
'checkbox',
|
42 |
_wpsf__( 'Enable Auto Updates' ),
|
43 |
_wpsf__( 'Enable (or Disable) The Simple Firewall Automatic Updates Feature' ),
|
44 |
-
_wpsf__( '
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
)
|
46 |
)
|
47 |
);
|
@@ -49,13 +65,14 @@ class ICWP_OptionsHandler_AutoUpdates extends ICWP_OptionsHandler_Base_WPSF {
|
|
49 |
'section_title' => _wpsf__('Automatic Plugin Self-Update'),
|
50 |
'section_options' => array(
|
51 |
array(
|
52 |
-
'
|
53 |
'',
|
54 |
'Y',
|
55 |
'checkbox',
|
56 |
_wpsf__( 'Auto Update Plugin' ),
|
57 |
_wpsf__( 'Always Automatically Update This Plugin' ),
|
58 |
-
_wpsf__( 'Regardless of any component settings below, automatically update the WordPress Simple Firewall plugin.' )
|
|
|
59 |
)
|
60 |
)
|
61 |
);
|
@@ -74,7 +91,8 @@ class ICWP_OptionsHandler_AutoUpdates extends ICWP_OptionsHandler_Base_WPSF {
|
|
74 |
$aAutoUpdateOptions,
|
75 |
_wpsf__( 'WordPress Core Updates' ),
|
76 |
_wpsf__( 'Decide how the WordPress Core will automatically update, if at all' ),
|
77 |
-
_wpsf__( 'At least automatically upgrading minor versions is recommended (and is the WordPress default).' )
|
|
|
78 |
),
|
79 |
array(
|
80 |
'enable_autoupdate_translations',
|
@@ -114,17 +132,27 @@ class ICWP_OptionsHandler_AutoUpdates extends ICWP_OptionsHandler_Base_WPSF {
|
|
114 |
)
|
115 |
)
|
116 |
);
|
117 |
-
|
118 |
-
|
|
|
119 |
'section_options' => array(
|
120 |
array(
|
121 |
-
'
|
122 |
'',
|
123 |
-
'
|
124 |
'checkbox',
|
125 |
-
_wpsf__( '
|
126 |
-
_wpsf__( '
|
127 |
-
_wpsf__( '
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
)
|
129 |
)
|
130 |
);
|
@@ -134,15 +162,18 @@ class ICWP_OptionsHandler_AutoUpdates extends ICWP_OptionsHandler_Base_WPSF {
|
|
134 |
$aAutoUpdateAll,
|
135 |
$aAutoUpdatePlugin,
|
136 |
$aAutoUpdateComponents,
|
|
|
137 |
);
|
138 |
}
|
139 |
|
140 |
public function updateHandler() {
|
141 |
|
142 |
-
$sCurrentVersion =
|
143 |
-
|
144 |
-
}//v1.9.0
|
145 |
}
|
146 |
}
|
147 |
|
148 |
-
endif;
|
|
|
|
1 |
<?php
|
2 |
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
17 |
|
18 |
require_once( dirname(__FILE__).'/icwp-optionshandler-base.php' );
|
19 |
|
20 |
+
if ( !class_exists('ICWP_OptionsHandler_AutoUpdates_V2') ):
|
21 |
|
22 |
+
class ICWP_OptionsHandler_AutoUpdates_V2 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() {
|
37 |
array(
|
38 |
'enable_autoupdates',
|
39 |
'',
|
40 |
+
'Y',
|
41 |
'checkbox',
|
42 |
_wpsf__( 'Enable Auto Updates' ),
|
43 |
_wpsf__( 'Enable (or Disable) The Simple Firewall Automatic Updates Feature' ),
|
44 |
+
sprintf( _wpsf__( 'Checking/Un-Checking this option will completely turn on/off the whole %s feature.' ), _wpsf__('Automatic Updates') ),
|
45 |
+
'<a href="http://icwp.io/3w" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
46 |
+
)
|
47 |
+
)
|
48 |
+
);
|
49 |
+
$aAutoUpdateAll = array(
|
50 |
+
'section_title' => _wpsf__('Disable ALL WordPress Automatic Updates'),
|
51 |
+
'section_options' => array(
|
52 |
+
array(
|
53 |
+
'enable_autoupdate_disable_all',
|
54 |
+
'',
|
55 |
+
'N',
|
56 |
+
'checkbox',
|
57 |
+
_wpsf__( 'Disable All' ),
|
58 |
+
_wpsf__( 'Completely Disable WordPress Automatic Updates' ),
|
59 |
+
_wpsf__( 'When selected, regardless of any other settings, all WordPress automatic updates on this site will be completely disabled!' ),
|
60 |
+
'<a href="http://icwp.io/3v" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
61 |
)
|
62 |
)
|
63 |
);
|
65 |
'section_title' => _wpsf__('Automatic Plugin Self-Update'),
|
66 |
'section_options' => array(
|
67 |
array(
|
68 |
+
'autoupdate_plugin_self',
|
69 |
'',
|
70 |
'Y',
|
71 |
'checkbox',
|
72 |
_wpsf__( 'Auto Update Plugin' ),
|
73 |
_wpsf__( 'Always Automatically Update This Plugin' ),
|
74 |
+
_wpsf__( 'Regardless of any component settings below, automatically update the WordPress Simple Firewall plugin.' ),
|
75 |
+
'<a href="http://icwp.io/3u" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
76 |
)
|
77 |
)
|
78 |
);
|
91 |
$aAutoUpdateOptions,
|
92 |
_wpsf__( 'WordPress Core Updates' ),
|
93 |
_wpsf__( 'Decide how the WordPress Core will automatically update, if at all' ),
|
94 |
+
_wpsf__( 'At least automatically upgrading minor versions is recommended (and is the WordPress default).' ),
|
95 |
+
'<a href="http://icwp.io/3x" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
96 |
),
|
97 |
array(
|
98 |
'enable_autoupdate_translations',
|
132 |
)
|
133 |
)
|
134 |
);
|
135 |
+
|
136 |
+
$aAutoUpdateEmail = array(
|
137 |
+
'section_title' => _wpsf__('Automatic Update Email Notifications'),
|
138 |
'section_options' => array(
|
139 |
array(
|
140 |
+
'enable_upgrade_notification_email',
|
141 |
'',
|
142 |
+
'Y',
|
143 |
'checkbox',
|
144 |
+
_wpsf__( 'Send Report Email' ),
|
145 |
+
_wpsf__( 'Send email notices after automatic updates' ),
|
146 |
+
_wpsf__( 'You can turn on/off email notices from automatic updates by un/checking this box.' )
|
147 |
+
),
|
148 |
+
array(
|
149 |
+
'override_email_address',
|
150 |
+
'',
|
151 |
+
'',
|
152 |
+
'email',
|
153 |
+
_wpsf__( 'Report Email Address' ),
|
154 |
+
_wpsf__( 'Where to send upgrade notification reports' ),
|
155 |
+
_wpsf__( 'If this is empty, it will default to the Site admin email address' )
|
156 |
)
|
157 |
)
|
158 |
);
|
162 |
$aAutoUpdateAll,
|
163 |
$aAutoUpdatePlugin,
|
164 |
$aAutoUpdateComponents,
|
165 |
+
$aAutoUpdateEmail
|
166 |
);
|
167 |
}
|
168 |
|
169 |
public function updateHandler() {
|
170 |
|
171 |
+
$sCurrentVersion = $this->getVersion();
|
172 |
+
$sCurrentVersion = empty( $sCurrentVersion )? '0.0' : $sCurrentVersion;
|
173 |
+
if ( version_compare( $sCurrentVersion, '1.9.0', '<' ) ) { }//v1.9.0
|
174 |
}
|
175 |
}
|
176 |
|
177 |
+
endif;
|
178 |
+
|
179 |
+
class ICWP_OptionsHandler_AutoUpdates extends ICWP_OptionsHandler_AutoUpdates_V2 { }
|
src/icwp-optionshandler-base.php
CHANGED
@@ -1,9 +1,9 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* Copyright (c)
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
-
* Version: 2013-
|
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
|
@@ -17,11 +17,18 @@
|
|
17 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
18 |
*/
|
19 |
|
20 |
-
if ( !class_exists('
|
21 |
|
22 |
-
class
|
23 |
|
|
|
|
|
|
|
24 |
const CollateSeparator = '--SEP--';
|
|
|
|
|
|
|
|
|
25 |
|
26 |
/**
|
27 |
* @var boolean
|
@@ -57,16 +64,7 @@ class ICWP_OptionsHandler_Base_WPSF {
|
|
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 |
*
|
@@ -84,6 +82,11 @@ class ICWP_OptionsHandler_Base_WPSF {
|
|
84 |
*/
|
85 |
protected $m_aOptionsStoreName;
|
86 |
|
|
|
|
|
|
|
|
|
|
|
87 |
public function __construct( $insPrefix, $insStoreName, $insVersion ) {
|
88 |
$this->m_sOptionPrefix = $insPrefix;
|
89 |
$this->m_aOptionsStoreName = $insStoreName;
|
@@ -92,10 +95,17 @@ class ICWP_OptionsHandler_Base_WPSF {
|
|
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( '
|
96 |
}
|
97 |
|
98 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
if ( $this->hasPluginManageRights() ) {
|
100 |
$this->buildOptions();
|
101 |
$this->updateHandler();
|
@@ -119,14 +129,49 @@ class ICWP_OptionsHandler_Base_WPSF {
|
|
119 |
* @return string
|
120 |
*/
|
121 |
public function getVersion() {
|
122 |
-
return $this->
|
123 |
}
|
124 |
|
125 |
/**
|
|
|
126 |
* @return string
|
127 |
*/
|
128 |
public function setVersion( $insVersion ) {
|
129 |
-
return $this->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
130 |
}
|
131 |
|
132 |
/**
|
@@ -138,6 +183,10 @@ class ICWP_OptionsHandler_Base_WPSF {
|
|
138 |
*/
|
139 |
public function setOpt( $insKey, $inmValue ) {
|
140 |
|
|
|
|
|
|
|
|
|
141 |
if ( !isset( $this->m_aOptionsValues ) ) {
|
142 |
$this->loadStoredOptionsValues();
|
143 |
}
|
@@ -171,9 +220,7 @@ class ICWP_OptionsHandler_Base_WPSF {
|
|
171 |
* @return array
|
172 |
*/
|
173 |
public function getOptions() {
|
174 |
-
|
175 |
-
$this->buildOptions();
|
176 |
-
}
|
177 |
return $this->m_aOptions;
|
178 |
}
|
179 |
|
@@ -196,20 +243,10 @@ class ICWP_OptionsHandler_Base_WPSF {
|
|
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 |
|
@@ -293,11 +330,12 @@ class ICWP_OptionsHandler_Base_WPSF {
|
|
293 |
*
|
294 |
* @param string $insUpdateKey - if only want to update a single key, supply it here.
|
295 |
*/
|
296 |
-
|
297 |
|
298 |
$this->defineOptions();
|
299 |
$this->loadStoredOptionsValues();
|
300 |
|
|
|
301 |
foreach ( $this->m_aOptions as &$aOptionsSection ) {
|
302 |
|
303 |
if ( empty( $aOptionsSection ) || !isset( $aOptionsSection['section_options'] ) ) {
|
@@ -307,7 +345,9 @@ class ICWP_OptionsHandler_Base_WPSF {
|
|
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 |
}
|
@@ -325,6 +365,19 @@ class ICWP_OptionsHandler_Base_WPSF {
|
|
325 |
$mCurrentOptionVal = implode( "\n", $this->convertIpListForDisplay( $mCurrentOptionVal ) );
|
326 |
}
|
327 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
328 |
else if ( $sOptionType == 'comma_separated_lists' ) {
|
329 |
|
330 |
if ( empty( $mCurrentOptionVal ) ) {
|
@@ -345,6 +398,7 @@ class ICWP_OptionsHandler_Base_WPSF {
|
|
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 |
}
|
@@ -378,23 +432,9 @@ class ICWP_OptionsHandler_Base_WPSF {
|
|
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();
|
@@ -426,6 +466,9 @@ class ICWP_OptionsHandler_Base_WPSF {
|
|
426 |
* @return void|boolean
|
427 |
*/
|
428 |
public function updatePluginOptionsFromSubmit( $sAllOptionsInput ) {
|
|
|
|
|
|
|
429 |
|
430 |
if ( empty( $sAllOptionsInput ) ) {
|
431 |
return;
|
@@ -437,6 +480,10 @@ class ICWP_OptionsHandler_Base_WPSF {
|
|
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) ) {
|
@@ -464,21 +511,15 @@ class ICWP_OptionsHandler_Base_WPSF {
|
|
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 |
}
|
@@ -535,8 +576,8 @@ class ICWP_OptionsHandler_Base_WPSF {
|
|
535 |
}
|
536 |
|
537 |
protected function getVisitorIpAddress( $infAsLong = true ) {
|
538 |
-
require_once( dirname(__FILE__).'/icwp-
|
539 |
-
return
|
540 |
}
|
541 |
|
542 |
/**
|
@@ -564,6 +605,61 @@ class ICWP_OptionsHandler_Base_WPSF {
|
|
564 |
$sKey = $this->m_sOptionPrefix.$insKey;
|
565 |
return $this->m_fIsMultisite? delete_site_option($sKey) : delete_option($sKey);
|
566 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
567 |
}
|
568 |
|
569 |
-
endif;
|
|
|
|
1 |
<?php
|
2 |
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
+
* Version: 2013-11-15-V1
|
7 |
*
|
8 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
9 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
17 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
18 |
*/
|
19 |
|
20 |
+
if ( !class_exists('ICWP_OptionsHandler_Base_V2') ):
|
21 |
|
22 |
+
class ICWP_OptionsHandler_Base_V2 {
|
23 |
|
24 |
+
/**
|
25 |
+
* @var string
|
26 |
+
*/
|
27 |
const CollateSeparator = '--SEP--';
|
28 |
+
/**
|
29 |
+
* @var string
|
30 |
+
*/
|
31 |
+
const PluginVersionKey = 'current_plugin_version';
|
32 |
|
33 |
/**
|
34 |
* @var boolean
|
64 |
* @var boolean
|
65 |
*/
|
66 |
protected $m_fIsMultisite;
|
67 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
/**
|
69 |
* These are options that need to be stored, but are never set by the UI.
|
70 |
*
|
82 |
*/
|
83 |
protected $m_aOptionsStoreName;
|
84 |
|
85 |
+
/**
|
86 |
+
* @var array
|
87 |
+
*/
|
88 |
+
protected $aOptionsKeys;
|
89 |
+
|
90 |
public function __construct( $insPrefix, $insStoreName, $insVersion ) {
|
91 |
$this->m_sOptionPrefix = $insPrefix;
|
92 |
$this->m_aOptionsStoreName = $insStoreName;
|
95 |
$this->m_fIsMultisite = function_exists( 'is_multisite' ) && is_multisite();
|
96 |
|
97 |
// Handle any upgrades as necessary (only go near this if it's the admin area)
|
98 |
+
add_action( 'init', array( $this, 'onWpPluginsLoaded' ), 1 );
|
99 |
}
|
100 |
|
101 |
+
/**
|
102 |
+
* A action added to WordPress 'plugins_loaded' hook
|
103 |
+
*/
|
104 |
+
public function onWpPluginsLoaded() {
|
105 |
+
$this->doUpdates();
|
106 |
+
}
|
107 |
+
|
108 |
+
protected function doUpdates() {
|
109 |
if ( $this->hasPluginManageRights() ) {
|
110 |
$this->buildOptions();
|
111 |
$this->updateHandler();
|
129 |
* @return string
|
130 |
*/
|
131 |
public function getVersion() {
|
132 |
+
return $this->getOpt( self::PluginVersionKey );
|
133 |
}
|
134 |
|
135 |
/**
|
136 |
+
* @param string
|
137 |
* @return string
|
138 |
*/
|
139 |
public function setVersion( $insVersion ) {
|
140 |
+
return $this->setOpt( self::PluginVersionKey, $insVersion );
|
141 |
+
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
* Gets the array of all possible options keys
|
145 |
+
*
|
146 |
+
* @return array
|
147 |
+
*/
|
148 |
+
public function getOptionsKeys() {
|
149 |
+
$this->setOptionsKeys();
|
150 |
+
return $this->aOptionsKeys;
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* @return void
|
155 |
+
*/
|
156 |
+
public function setOptionsKeys() {
|
157 |
+
if ( !empty( $this->aOptionsKeys ) ) {
|
158 |
+
return;
|
159 |
+
}
|
160 |
+
$this->buildOptions();
|
161 |
+
}
|
162 |
+
|
163 |
+
/**
|
164 |
+
* Determines whether the given option key is a valid options
|
165 |
+
*
|
166 |
+
* @param string
|
167 |
+
* @return boolean
|
168 |
+
*/
|
169 |
+
public function getIsOptionKey( $sOptionKey ) {
|
170 |
+
if ( $sOptionKey == self::PluginVersionKey ) {
|
171 |
+
return true;
|
172 |
+
}
|
173 |
+
$this->setOptionsKeys();
|
174 |
+
return ( in_array( $sOptionKey, $this->aOptionsKeys ) );
|
175 |
}
|
176 |
|
177 |
/**
|
183 |
*/
|
184 |
public function setOpt( $insKey, $inmValue ) {
|
185 |
|
186 |
+
if ( !$this->getIsOptionKey( $insKey ) ) {
|
187 |
+
return false;
|
188 |
+
}
|
189 |
+
|
190 |
if ( !isset( $this->m_aOptionsValues ) ) {
|
191 |
$this->loadStoredOptionsValues();
|
192 |
}
|
220 |
* @return array
|
221 |
*/
|
222 |
public function getOptions() {
|
223 |
+
$this->buildOptions();
|
|
|
|
|
224 |
return $this->m_aOptions;
|
225 |
}
|
226 |
|
243 |
|
244 |
$this->doPrePluginOptionsSave();
|
245 |
$this->updateOptionsVersion();
|
|
|
246 |
if ( !$this->m_fNeedSave ) {
|
247 |
return true;
|
248 |
}
|
|
|
249 |
$this->updateOption( $this->m_aOptionsStoreName, $this->m_aOptionsValues );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
250 |
$this->m_fNeedSave = false;
|
251 |
}
|
252 |
|
330 |
*
|
331 |
* @param string $insUpdateKey - if only want to update a single key, supply it here.
|
332 |
*/
|
333 |
+
public function buildOptions() {
|
334 |
|
335 |
$this->defineOptions();
|
336 |
$this->loadStoredOptionsValues();
|
337 |
|
338 |
+
$this->aOptionsKeys = array();
|
339 |
foreach ( $this->m_aOptions as &$aOptionsSection ) {
|
340 |
|
341 |
if ( empty( $aOptionsSection ) || !isset( $aOptionsSection['section_options'] ) ) {
|
345 |
foreach ( $aOptionsSection['section_options'] as &$aOptionParams ) {
|
346 |
|
347 |
list( $sOptionKey, $sOptionValue, $sOptionDefault, $sOptionType ) = $aOptionParams;
|
348 |
+
|
349 |
+
$this->aOptionsKeys[] = $sOptionKey;
|
350 |
+
|
351 |
if ( $this->getOpt( $sOptionKey ) === false ) {
|
352 |
$this->setOpt( $sOptionKey, $sOptionDefault );
|
353 |
}
|
365 |
$mCurrentOptionVal = implode( "\n", $this->convertIpListForDisplay( $mCurrentOptionVal ) );
|
366 |
}
|
367 |
}
|
368 |
+
else if ( $sOptionType == 'yubikey_unique_keys' ) {
|
369 |
+
|
370 |
+
if ( empty( $mCurrentOptionVal ) ) {
|
371 |
+
$mCurrentOptionVal = '';
|
372 |
+
}
|
373 |
+
else {
|
374 |
+
$aDisplay = array();
|
375 |
+
foreach( $mCurrentOptionVal as $aParts ) {
|
376 |
+
$aDisplay[] = key($aParts) .', '. reset($aParts);
|
377 |
+
}
|
378 |
+
$mCurrentOptionVal = implode( "\n", $aDisplay );
|
379 |
+
}
|
380 |
+
}
|
381 |
else if ( $sOptionType == 'comma_separated_lists' ) {
|
382 |
|
383 |
if ( empty( $mCurrentOptionVal ) ) {
|
398 |
// Cater for Non-UI options that don't necessarily go through the UI
|
399 |
if ( isset($this->m_aNonUiOptions) && is_array($this->m_aNonUiOptions) ) {
|
400 |
foreach( $this->m_aNonUiOptions as $sOption ) {
|
401 |
+
$this->aOptionsKeys[] = $sOption;
|
402 |
if ( !$this->getOpt( $sOption ) ) {
|
403 |
$this->setOpt( $sOption, '' );
|
404 |
}
|
432 |
* Deletes all the options including direct save.
|
433 |
*/
|
434 |
public function deletePluginOptions() {
|
|
|
435 |
$this->deleteOption( $this->m_aOptionsStoreName );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
436 |
}
|
437 |
+
|
438 |
protected function convertIpListForDisplay( $inaIpList = array() ) {
|
439 |
|
440 |
$aDisplay = array();
|
466 |
* @return void|boolean
|
467 |
*/
|
468 |
public function updatePluginOptionsFromSubmit( $sAllOptionsInput ) {
|
469 |
+
|
470 |
+
require_once ( dirname(__FILE__).'/icwp-data-processor.php' );
|
471 |
+
$oProcessor = new ICWP_WPSF_DataProcessor();
|
472 |
|
473 |
if ( empty( $sAllOptionsInput ) ) {
|
474 |
return;
|
480 |
foreach ( $aAllInputOptions as $sInputKey ) {
|
481 |
$aInput = explode( ':', $sInputKey );
|
482 |
list( $sOptionType, $sOptionKey ) = $aInput;
|
483 |
+
|
484 |
+
if ( !$this->getIsOptionKey( $sOptionKey ) ) {
|
485 |
+
continue;
|
486 |
+
}
|
487 |
|
488 |
$sOptionValue = $this->getFromPost( $sOptionKey );
|
489 |
if ( is_null($sOptionValue) ) {
|
511 |
$sOptionValue = md5( $sTempValue );
|
512 |
}
|
513 |
else if ( $sOptionType == 'ip_addresses' ) { //ip addresses are textareas, where each is separated by newline
|
|
|
|
|
|
|
|
|
|
|
514 |
$sOptionValue = $oProcessor->ExtractIpAddresses( $sOptionValue );
|
515 |
}
|
516 |
+
else if ( $sOptionType == 'yubikey_unique_keys' ) { //ip addresses are textareas, where each is separated by newline and are 12 chars long
|
517 |
+
$sOptionValue = $oProcessor->CleanYubikeyUniqueKeys( $sOptionValue );
|
518 |
+
}
|
519 |
else if ( $sOptionType == 'email' && function_exists( 'is_email' ) && !is_email( $sOptionValue ) ) {
|
520 |
$sOptionValue = '';
|
521 |
}
|
522 |
else if ( $sOptionType == 'comma_separated_lists' ) {
|
|
|
|
|
|
|
|
|
523 |
$sOptionValue = $oProcessor->ExtractCommaSeparatedList( $sOptionValue );
|
524 |
}
|
525 |
}
|
576 |
}
|
577 |
|
578 |
protected function getVisitorIpAddress( $infAsLong = true ) {
|
579 |
+
require_once( dirname(__FILE__).'/icwp-data-processor.php' );
|
580 |
+
return ICWP_WPSF_DataProcessor::GetVisitorIpAddress( $infAsLong );
|
581 |
}
|
582 |
|
583 |
/**
|
605 |
$sKey = $this->m_sOptionPrefix.$insKey;
|
606 |
return $this->m_fIsMultisite? delete_site_option($sKey) : delete_option($sKey);
|
607 |
}
|
608 |
+
|
609 |
+
|
610 |
+
/**
|
611 |
+
* @param string $insExistingListKey
|
612 |
+
* @param string $insFilterName
|
613 |
+
* @return array|false
|
614 |
+
*/
|
615 |
+
protected function processIpFilter( $insExistingListKey, $insFilterName ) {
|
616 |
+
$aFilterIps = apply_filters( $insFilterName, array() );
|
617 |
+
if ( empty( $aFilterIps ) ) {
|
618 |
+
return false;
|
619 |
+
}
|
620 |
+
|
621 |
+
$aNewIps = array();
|
622 |
+
foreach( $aFilterIps as $mKey => $sValue ) {
|
623 |
+
if ( is_string( $mKey ) ) { //it's the IP
|
624 |
+
$sIP = $mKey;
|
625 |
+
$sLabel = $sValue;
|
626 |
+
}
|
627 |
+
else { //it's not an associative array, so the value is the IP
|
628 |
+
$sIP = $sValue;
|
629 |
+
$sLabel = '';
|
630 |
+
}
|
631 |
+
$aNewIps[ $sIP ] = $sLabel;
|
632 |
+
}
|
633 |
+
|
634 |
+
// now add and store the new IPs
|
635 |
+
$aExistingIpList = $this->getOpt( $insExistingListKey );
|
636 |
+
if ( !is_array( $aExistingIpList ) ) {
|
637 |
+
$aExistingIpList = array();
|
638 |
+
}
|
639 |
+
|
640 |
+
$this->loadDataProcessor();
|
641 |
+
$nNewAddedCount = 0;
|
642 |
+
$aNewList = ICWP_WPSF_DataProcessor::Add_New_Raw_Ips( $aExistingIpList, $aNewIps, $nNewAddedCount );
|
643 |
+
if ( $nNewAddedCount > 0 ) {
|
644 |
+
$this->setOpt( $insExistingListKey, $aNewList );
|
645 |
+
}
|
646 |
+
}
|
647 |
+
|
648 |
+
protected function loadDataProcessor() {
|
649 |
+
if ( !class_exists('ICWP_WPSF_DataProcessor') ) {
|
650 |
+
require_once( dirname(__FILE__).'/icwp-data-processor.php' );
|
651 |
+
}
|
652 |
+
}
|
653 |
+
|
654 |
+
/**
|
655 |
+
* @return ICWP_WpFilesystem_WPSF
|
656 |
+
*/
|
657 |
+
protected function loadFileSystemProcessor() {
|
658 |
+
require_once( dirname(__FILE__) . '/icwp-wpfilesystem.php' );
|
659 |
+
return ICWP_WpFilesystem_WPSF::GetInstance();
|
660 |
+
}
|
661 |
}
|
662 |
|
663 |
+
endif;
|
664 |
+
|
665 |
+
class ICWP_OptionsHandler_Base_Wpsf extends ICWP_OptionsHandler_Base_V2 { }
|
src/icwp-optionshandler-commentsfilter.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* Copyright (c)
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
@@ -19,7 +19,7 @@ require_once( dirname(__FILE__).'/icwp-optionshandler-base.php' );
|
|
19 |
|
20 |
if ( !class_exists('ICWP_OptionsHandler_CommentsFilter') ):
|
21 |
|
22 |
-
class ICWP_OptionsHandler_CommentsFilter extends
|
23 |
|
24 |
const StoreName = 'commentsfilter_options';
|
25 |
|
@@ -29,27 +29,67 @@ class ICWP_OptionsHandler_CommentsFilter extends ICWP_OptionsHandler_Base_WPSF {
|
|
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' => _wpsf__( 'Enable Comments Filter' ),
|
39 |
'section_options' => array(
|
40 |
array(
|
41 |
'enable_comments_filter',
|
42 |
'',
|
43 |
-
'
|
44 |
'checkbox',
|
45 |
_wpsf__( 'Enable Comments Filter' ),
|
46 |
-
_wpsf__( 'Enable (or Disable) The SPAM Comments Filter Feature
|
47 |
-
_wpsf__( '
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
)
|
49 |
),
|
50 |
);
|
|
|
51 |
$aGasp = array(
|
52 |
-
'section_title' => _wpsf__( '
|
53 |
'section_options' => array(
|
54 |
array(
|
55 |
'enable_comments_gasp_protection',
|
@@ -58,8 +98,19 @@ class ICWP_OptionsHandler_CommentsFilter extends ICWP_OptionsHandler_Base_WPSF {
|
|
58 |
'checkbox',
|
59 |
_wpsf__( 'GASP Protection' ),
|
60 |
_wpsf__( 'Add Growmap Anti Spambot Protection to your comments' ),
|
61 |
-
_wpsf__( 'Taking the lead from the original GASP plugin for WordPress, we have extended it to include
|
62 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
),
|
64 |
array(
|
65 |
'enable_comments_gasp_protection_for_logged_in',
|
@@ -77,7 +128,8 @@ class ICWP_OptionsHandler_CommentsFilter extends ICWP_OptionsHandler_Base_WPSF {
|
|
77 |
'integer',
|
78 |
_wpsf__( 'Comments Cooldown' ),
|
79 |
_wpsf__( 'Limit posting comments to X seconds after the page has loaded' ),
|
80 |
-
_wpsf__( "By forcing a comments cooldown period, you restrict a Spambot's ability to post mutliple times to your posts." )
|
|
|
81 |
),
|
82 |
array(
|
83 |
'comments_token_expire_interval',
|
@@ -86,9 +138,16 @@ class ICWP_OptionsHandler_CommentsFilter extends ICWP_OptionsHandler_Base_WPSF {
|
|
86 |
'integer',
|
87 |
_wpsf__( 'Comment Token Expire' ),
|
88 |
_wpsf__( 'A visitor has X seconds within which to post a comment' ),
|
89 |
-
_wpsf__( "Default: 600 seconds (10 minutes). Each visitor is given a unique 'Token' so they can comment. This restricts spambots, but we need to force these tokens to expire and at the same time not bother the visitors." )
|
90 |
-
|
91 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
92 |
array(
|
93 |
'custom_message_checkbox',
|
94 |
'',
|
@@ -97,7 +156,8 @@ class ICWP_OptionsHandler_CommentsFilter extends ICWP_OptionsHandler_Base_WPSF {
|
|
97 |
_wpsf__( 'Custom Checkbox Message' ),
|
98 |
_wpsf__( 'If you want a custom checkbox message, please provide this here' ),
|
99 |
_wpsf__( "You can customise the message beside the checkbox." )
|
100 |
-
.'<br />'.sprintf( _wpsf__( 'Default Message: %s' ), _wpsf__("Please check the box to confirm you're not a spammer") )
|
|
|
101 |
),
|
102 |
array(
|
103 |
'custom_message_alert',
|
@@ -107,7 +167,8 @@ class ICWP_OptionsHandler_CommentsFilter extends ICWP_OptionsHandler_Base_WPSF {
|
|
107 |
_wpsf__( 'Custom Alert Message' ),
|
108 |
_wpsf__( 'If you want a custom alert message, please provide this here' ),
|
109 |
_wpsf__( "This alert message is displayed when a visitor attempts to submit a comment without checking the box." )
|
110 |
-
.'<br />'.sprintf( _wpsf__( 'Default Message: %s' ), _wpsf__("Please check the box to confirm you're not a spammer") )
|
|
|
111 |
),
|
112 |
array(
|
113 |
'custom_message_comment_wait',
|
@@ -117,7 +178,8 @@ class ICWP_OptionsHandler_CommentsFilter extends ICWP_OptionsHandler_Base_WPSF {
|
|
117 |
_wpsf__( 'Custom Wait Message' ),
|
118 |
_wpsf__( 'If you want a custom submit-button wait message, please provide this here.' ),
|
119 |
_wpsf__( "Where you see the '%s' this will be the number of seconds. You must ensure you include 1, and only 1, of these." )
|
120 |
-
.'<br />'.sprintf( _wpsf__( 'Default Message: %s' ), _wpsf__('Please wait %s seconds before posting your comment') )
|
|
|
121 |
),
|
122 |
array(
|
123 |
'custom_message_comment_reload',
|
@@ -127,14 +189,17 @@ class ICWP_OptionsHandler_CommentsFilter extends ICWP_OptionsHandler_Base_WPSF {
|
|
127 |
_wpsf__( 'Custom Reload Message' ),
|
128 |
_wpsf__( 'If you want a custom message when the comment token has expired, please provide this here.' ),
|
129 |
_wpsf__( 'This message is displayed on the submit-button when the comment token is expired' )
|
130 |
-
.'<br />'.sprintf( _wpsf__( 'Default Message: %s' ), _wpsf__("Please reload this page to post a comment") )
|
|
|
131 |
)
|
132 |
)
|
133 |
);
|
134 |
|
135 |
$this->m_aOptions = array(
|
136 |
$aBase,
|
137 |
-
$
|
|
|
|
|
138 |
);
|
139 |
}
|
140 |
|
@@ -159,6 +224,42 @@ class ICWP_OptionsHandler_CommentsFilter extends ICWP_OptionsHandler_Base_WPSF {
|
|
159 |
}
|
160 |
$this->setOpt( 'comments_cooldown_interval', $nCommentCooldown );
|
161 |
$this->setOpt( 'comments_token_expire_interval', $nCommentTokenExpire );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
162 |
}
|
163 |
|
164 |
public function updateHandler() {
|
1 |
<?php
|
2 |
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
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 |
|
29 |
public function __construct( $insPrefix, $insVersion ) {
|
30 |
parent::__construct( $insPrefix, self::StoreName, $insVersion );
|
31 |
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* @return bool|void
|
35 |
+
*/
|
36 |
public function defineOptions() {
|
37 |
|
|
|
|
|
38 |
$aBase = array(
|
39 |
+
'section_title' => sprintf( _wpsf__( 'Enable Plugin Feature: %s' ), _wpsf__('SPAM Comments Protection Filter') ),
|
40 |
'section_options' => array(
|
41 |
array(
|
42 |
'enable_comments_filter',
|
43 |
'',
|
44 |
+
'N',
|
45 |
'checkbox',
|
46 |
_wpsf__( 'Enable Comments Filter' ),
|
47 |
+
_wpsf__( 'Enable (or Disable) The SPAM Comments Protection Filter Feature' ),
|
48 |
+
sprintf( _wpsf__( 'Checking/Un-Checking this option will completely turn on/off the whole %s feature.' ), _wpsf__('SPAM Comments Protection Filter') ),
|
49 |
+
'<a href="http://icwp.io/3z" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
50 |
+
.' | <a href="http://icwp.io/wpsf04" target="_blank">'._wpsf__( 'blog' ).'</a>'
|
51 |
+
)
|
52 |
+
)
|
53 |
+
);
|
54 |
+
|
55 |
+
$aHumanSpam = array(
|
56 |
+
'section_title' => sprintf( _wpsf__( '%s Comment SPAM Protection Filter' ), _wpsf__('Human') ),
|
57 |
+
'section_options' => array(
|
58 |
+
array(
|
59 |
+
'enable_comments_human_spam_filter',
|
60 |
+
'',
|
61 |
+
'N',
|
62 |
+
'checkbox',
|
63 |
+
_wpsf__( 'Human SPAM Filter' ),
|
64 |
+
_wpsf__( 'Enable (or Disable) The Human SPAM Filter Feature.' ),
|
65 |
+
_wpsf__( 'Scans the content of WordPress comments for keywords that are indicative of SPAM and marks the comment according to your preferred setting below.' ),
|
66 |
+
'<a href="http://icwp.io/57" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
67 |
+
),
|
68 |
+
array(
|
69 |
+
'enable_comments_human_spam_filter_items',
|
70 |
+
'',
|
71 |
+
$this->getHumanSpamFilterItems( true ),
|
72 |
+
$this->getHumanSpamFilterItems(),
|
73 |
+
_wpsf__( 'Comment Filter Items' ),
|
74 |
+
_wpsf__( 'Select The Items To Scan For SPAM' ),
|
75 |
+
_wpsf__( 'When a user submits a comment, only the selected parts of the comment data will be scanned for SPAM content.' ).' '.sprintf( _wpsf__('Recommended: %s'), _wpsf__('All') ),
|
76 |
+
'<a href="http://icwp.io/58" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
77 |
+
),
|
78 |
+
array(
|
79 |
+
'comments_default_action_human_spam',
|
80 |
+
'',
|
81 |
+
'spam',
|
82 |
+
$this->getSpamHandlingResponses(),
|
83 |
+
_wpsf__( 'Default SPAM Action' ),
|
84 |
+
_wpsf__( 'How To Categorise Comments When Identified To Be SPAM' ),
|
85 |
+
sprintf( _wpsf__( 'When a comment is detected as being SPAM from %s, the comment will be categorised based on this setting.' ), '<span style"text-decoration:underline;">'._wpsf__('a human commenter').'</span>' ),
|
86 |
+
'<a href="http://icwp.io/59" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
87 |
)
|
88 |
),
|
89 |
);
|
90 |
+
|
91 |
$aGasp = array(
|
92 |
+
'section_title' => sprintf( _wpsf__( '%s Comment SPAM Protection Filter' ), _wpsf__('Automatic Bot') ),
|
93 |
'section_options' => array(
|
94 |
array(
|
95 |
'enable_comments_gasp_protection',
|
98 |
'checkbox',
|
99 |
_wpsf__( 'GASP Protection' ),
|
100 |
_wpsf__( 'Add Growmap Anti Spambot Protection to your comments' ),
|
101 |
+
_wpsf__( 'Taking the lead from the original GASP plugin for WordPress, we have extended it to include advanced spam-bot protection.' ),
|
102 |
+
'<a href="http://icwp.io/3n" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
103 |
+
.' | <a href="http://icwp.io/2n" target="_blank">'._wpsf__( 'blog' ).'</a>'
|
104 |
+
),
|
105 |
+
array(
|
106 |
+
'comments_default_action_spam_bot',
|
107 |
+
'',
|
108 |
+
'trash',
|
109 |
+
$this->getSpamHandlingResponses(),
|
110 |
+
_wpsf__( 'Default SPAM Action' ),
|
111 |
+
_wpsf__( 'How To Categorise Comments When Identified To Be SPAM' ),
|
112 |
+
sprintf( _wpsf__( 'When a comment is detected as being SPAM from %s, the comment will be categorised based on this setting.' ), '<span style"text-decoration:underline;">'._wpsf__('an automatic bot').'</span>' ),
|
113 |
+
'<a href="http://icwp.io/59" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
114 |
),
|
115 |
array(
|
116 |
'enable_comments_gasp_protection_for_logged_in',
|
128 |
'integer',
|
129 |
_wpsf__( 'Comments Cooldown' ),
|
130 |
_wpsf__( 'Limit posting comments to X seconds after the page has loaded' ),
|
131 |
+
_wpsf__( "By forcing a comments cooldown period, you restrict a Spambot's ability to post mutliple times to your posts." ),
|
132 |
+
'<a href="http://icwp.io/3o" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
133 |
),
|
134 |
array(
|
135 |
'comments_token_expire_interval',
|
138 |
'integer',
|
139 |
_wpsf__( 'Comment Token Expire' ),
|
140 |
_wpsf__( 'A visitor has X seconds within which to post a comment' ),
|
141 |
+
_wpsf__( "Default: 600 seconds (10 minutes). Each visitor is given a unique 'Token' so they can comment. This restricts spambots, but we need to force these tokens to expire and at the same time not bother the visitors." ),
|
142 |
+
'<a href="http://icwp.io/3o" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
143 |
+
|
144 |
+
)
|
145 |
+
)
|
146 |
+
);
|
147 |
+
|
148 |
+
$aCustomMessages = array(
|
149 |
+
'section_title' => sprintf( _wpsf__( 'Customize Messages Shown To User' ), _wpsf__('Automatic Bot') ),
|
150 |
+
'section_options' => array(
|
151 |
array(
|
152 |
'custom_message_checkbox',
|
153 |
'',
|
156 |
_wpsf__( 'Custom Checkbox Message' ),
|
157 |
_wpsf__( 'If you want a custom checkbox message, please provide this here' ),
|
158 |
_wpsf__( "You can customise the message beside the checkbox." )
|
159 |
+
.'<br />'.sprintf( _wpsf__( 'Default Message: %s' ), _wpsf__("Please check the box to confirm you're not a spammer") ),
|
160 |
+
'<a href="http://icwp.io/3p" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
161 |
),
|
162 |
array(
|
163 |
'custom_message_alert',
|
167 |
_wpsf__( 'Custom Alert Message' ),
|
168 |
_wpsf__( 'If you want a custom alert message, please provide this here' ),
|
169 |
_wpsf__( "This alert message is displayed when a visitor attempts to submit a comment without checking the box." )
|
170 |
+
.'<br />'.sprintf( _wpsf__( 'Default Message: %s' ), _wpsf__("Please check the box to confirm you're not a spammer") ),
|
171 |
+
'<a href="http://icwp.io/3p" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
172 |
),
|
173 |
array(
|
174 |
'custom_message_comment_wait',
|
178 |
_wpsf__( 'Custom Wait Message' ),
|
179 |
_wpsf__( 'If you want a custom submit-button wait message, please provide this here.' ),
|
180 |
_wpsf__( "Where you see the '%s' this will be the number of seconds. You must ensure you include 1, and only 1, of these." )
|
181 |
+
.'<br />'.sprintf( _wpsf__( 'Default Message: %s' ), _wpsf__('Please wait %s seconds before posting your comment') ),
|
182 |
+
'<a href="http://icwp.io/3p" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
183 |
),
|
184 |
array(
|
185 |
'custom_message_comment_reload',
|
189 |
_wpsf__( 'Custom Reload Message' ),
|
190 |
_wpsf__( 'If you want a custom message when the comment token has expired, please provide this here.' ),
|
191 |
_wpsf__( 'This message is displayed on the submit-button when the comment token is expired' )
|
192 |
+
.'<br />'.sprintf( _wpsf__( 'Default Message: %s' ), _wpsf__("Please reload this page to post a comment") ),
|
193 |
+
'<a href="http://icwp.io/3p" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
194 |
)
|
195 |
)
|
196 |
);
|
197 |
|
198 |
$this->m_aOptions = array(
|
199 |
$aBase,
|
200 |
+
$aHumanSpam,
|
201 |
+
$aGasp,
|
202 |
+
$aCustomMessages
|
203 |
);
|
204 |
}
|
205 |
|
224 |
}
|
225 |
$this->setOpt( 'comments_cooldown_interval', $nCommentCooldown );
|
226 |
$this->setOpt( 'comments_token_expire_interval', $nCommentTokenExpire );
|
227 |
+
|
228 |
+
$aCommentsFilters = $this->getOpt( 'enable_comments_human_spam_filter_items' );
|
229 |
+
if ( empty($aCommentsFilters) || !is_array( $aCommentsFilters ) ) {
|
230 |
+
$this->setOpt( 'enable_comments_human_spam_filter_items', $this->getHumanSpamFilterItems( true ) );
|
231 |
+
}
|
232 |
+
}
|
233 |
+
|
234 |
+
/**
|
235 |
+
* @return array
|
236 |
+
*/
|
237 |
+
protected function getSpamHandlingResponses() {
|
238 |
+
return array( 'select',
|
239 |
+
array( 0, _wpsf__( 'Mark As Pending Moderation' ) ),
|
240 |
+
array( 'spam', _wpsf__( 'Mark As SPAM' ) ),
|
241 |
+
array( 'trash', _wpsf__( 'Move To Trash' ) ),
|
242 |
+
array( 'reject', _wpsf__( 'Reject And Redirect' ) )
|
243 |
+
);
|
244 |
+
}
|
245 |
+
|
246 |
+
/**
|
247 |
+
*
|
248 |
+
*/
|
249 |
+
protected function getHumanSpamFilterItems( $fAsDefaults = false ) {
|
250 |
+
$aFilterItems = array( 'type' => 'multiple_select',
|
251 |
+
'author_name' => _wpsf__('Author Name'),
|
252 |
+
'author_email' => _wpsf__('Author Email'),
|
253 |
+
'comment_content' => _wpsf__('Comment Content'),
|
254 |
+
'url' => _wpsf__('URL'),
|
255 |
+
'ip_address' => _wpsf__('IP Address'),
|
256 |
+
'user_agent' => _wpsf__('Browser User Agent')
|
257 |
+
);
|
258 |
+
if ( $fAsDefaults ) {
|
259 |
+
unset($aFilterItems['type']);
|
260 |
+
return array_keys($aFilterItems);
|
261 |
+
}
|
262 |
+
return $aFilterItems;
|
263 |
}
|
264 |
|
265 |
public function updateHandler() {
|
src/icwp-optionshandler-email.php
ADDED
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
+
* All rights reserved.
|
5 |
+
*
|
6 |
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
7 |
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
8 |
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
9 |
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
10 |
+
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
11 |
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
12 |
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
13 |
+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
14 |
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
15 |
+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
+
*/
|
17 |
+
|
18 |
+
require_once( dirname(__FILE__).'/icwp-optionshandler-base.php' );
|
19 |
+
|
20 |
+
if ( !class_exists('ICWP_OptionsHandler_Email') ):
|
21 |
+
|
22 |
+
class ICWP_OptionsHandler_Email extends ICWP_OptionsHandler_Base_Wpsf {
|
23 |
+
|
24 |
+
const StoreName = 'email_options';
|
25 |
+
|
26 |
+
public function __construct( $insPrefix, $insVersion ) {
|
27 |
+
parent::__construct( $insPrefix, self::StoreName, $insVersion );
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* @return bool|void
|
32 |
+
*/
|
33 |
+
public function defineOptions() {
|
34 |
+
$aEmail = array(
|
35 |
+
'section_title' => _wpsf__( 'Email Options' ),
|
36 |
+
'section_options' => array(
|
37 |
+
array(
|
38 |
+
'block_send_email_address',
|
39 |
+
'',
|
40 |
+
'',
|
41 |
+
'email',
|
42 |
+
_wpsf__( 'Report Email' ),
|
43 |
+
_wpsf__( 'Where to send email reports' ),
|
44 |
+
_wpsf__( 'If this is empty, it will default to the blog admin email address' )
|
45 |
+
),
|
46 |
+
array(
|
47 |
+
'send_email_throttle_limit',
|
48 |
+
'',
|
49 |
+
'10',
|
50 |
+
'integer',
|
51 |
+
_wpsf__( 'Email Throttle Limit' ),
|
52 |
+
_wpsf__( 'Limit Emails Per Second' ),
|
53 |
+
_wpsf__( 'You throttle emails sent by this plugin by limiting the number of emails sent every second. This is useful in case you get hit by a bot attack. Zero (0) turns this off. Suggested: 10' )
|
54 |
+
)
|
55 |
+
)
|
56 |
+
);
|
57 |
+
|
58 |
+
$this->m_aOptions = array(
|
59 |
+
$aEmail
|
60 |
+
);
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* This is the point where you would want to do any options verification
|
65 |
+
*/
|
66 |
+
protected function doPrePluginOptionsSave() {
|
67 |
+
$sEmail = $this->getOpt( 'block_send_email_address');
|
68 |
+
if ( empty( $sEmail ) || !is_email( $sEmail ) ) {
|
69 |
+
$sEmail = get_option('admin_email');
|
70 |
+
}
|
71 |
+
if ( is_email( $sEmail ) ) {
|
72 |
+
$this->setOpt( 'block_send_email_address', $sEmail );
|
73 |
+
}
|
74 |
+
|
75 |
+
$sLimit = $this->getOpt( 'send_email_throttle_limit' );
|
76 |
+
if ( !is_numeric( $sLimit ) || $sLimit < 0 ) {
|
77 |
+
$sLimit = 0;
|
78 |
+
}
|
79 |
+
$this->setOpt( 'send_email_throttle_limit', $sLimit );
|
80 |
+
}
|
81 |
+
|
82 |
+
protected function updateHandler() {
|
83 |
+
$sCurrentVersion = empty( $this->m_aOptionsValues[ 'current_plugin_version' ] )? '0.0' : $this->m_aOptionsValues[ 'current_plugin_version' ];
|
84 |
+
if ( version_compare( $sCurrentVersion, '2.3.0', '<=' ) ) {
|
85 |
+
}
|
86 |
+
}
|
87 |
+
|
88 |
+
}
|
89 |
+
|
90 |
+
endif;
|
src/icwp-optionshandler-firewall.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* Copyright (c)
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
@@ -19,27 +19,31 @@ require_once( dirname(__FILE__).'/icwp-optionshandler-base.php' );
|
|
19 |
|
20 |
if ( !class_exists('ICWP_OptionsHandler_Firewall') ):
|
21 |
|
22 |
-
class ICWP_OptionsHandler_Firewall extends
|
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( '
|
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 ) {
|
@@ -53,25 +57,28 @@ class ICWP_OptionsHandler_Firewall extends ICWP_OptionsHandler_Base_WPSF {
|
|
53 |
$aIpWhitelist = $this->setOpt( 'block_response', $sBlockResponse );
|
54 |
}
|
55 |
}
|
56 |
-
|
57 |
-
public function defineOptions() {
|
58 |
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
|
|
|
|
63 |
'section_options' => array(
|
64 |
array(
|
65 |
'enable_firewall',
|
66 |
-
'',
|
|
|
67 |
'checkbox',
|
68 |
_wpsf__( 'Enable Firewall' ),
|
69 |
_wpsf__( 'Enable (or Disable) The WordPress Firewall Feature' ),
|
70 |
-
_wpsf__( '
|
|
|
|
|
71 |
)
|
72 |
)
|
73 |
);
|
74 |
-
$
|
75 |
'section_title' => _wpsf__( 'Firewall Blocking Options' ),
|
76 |
'section_options' => array(
|
77 |
array(
|
@@ -86,7 +93,7 @@ class ICWP_OptionsHandler_Firewall extends ICWP_OptionsHandler_Base_WPSF {
|
|
86 |
array(
|
87 |
'block_dir_traversal',
|
88 |
'',
|
89 |
-
'
|
90 |
'checkbox',
|
91 |
_wpsf__( 'Directory Traversals' ),
|
92 |
_wpsf__( 'Block Directory Traversals' ),
|
@@ -95,7 +102,7 @@ class ICWP_OptionsHandler_Firewall extends ICWP_OptionsHandler_Base_WPSF {
|
|
95 |
array(
|
96 |
'block_sql_queries',
|
97 |
'',
|
98 |
-
'
|
99 |
'checkbox',
|
100 |
_wpsf__( 'SQL Queries' ),
|
101 |
_wpsf__( 'Block SQL Queries' ),
|
@@ -113,12 +120,22 @@ class ICWP_OptionsHandler_Firewall extends ICWP_OptionsHandler_Base_WPSF {
|
|
113 |
array(
|
114 |
'block_field_truncation',
|
115 |
'',
|
116 |
-
'
|
117 |
'checkbox',
|
118 |
_wpsf__( 'Field Truncation' ),
|
119 |
_wpsf__( 'Block Field Truncation Attacks' ),
|
120 |
_wpsf__( 'This will block field truncation attacks in application parameters.' )
|
121 |
),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
122 |
array(
|
123 |
'block_exe_file_uploads',
|
124 |
'',
|
@@ -140,12 +157,12 @@ class ICWP_OptionsHandler_Firewall extends ICWP_OptionsHandler_Base_WPSF {
|
|
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 |
-
$
|
149 |
'section_title' => _wpsf__( 'Choose Firewall Block Response' ),
|
150 |
'section_options' => array(
|
151 |
array(
|
@@ -169,7 +186,7 @@ class ICWP_OptionsHandler_Firewall extends ICWP_OptionsHandler_Base_WPSF {
|
|
169 |
)
|
170 |
);
|
171 |
|
172 |
-
$
|
173 |
'section_title' => _wpsf__( 'Whitelists - IPs, Pages, Parameters, and Users that by-pass the Firewall' ),
|
174 |
'section_options' => array(
|
175 |
array(
|
@@ -194,16 +211,25 @@ class ICWP_OptionsHandler_Firewall extends ICWP_OptionsHandler_Base_WPSF {
|
|
194 |
array(
|
195 |
'whitelist_admins',
|
196 |
'',
|
197 |
-
'
|
198 |
'checkbox',
|
199 |
-
_wpsf__( 'Ignore Administrators' ),
|
200 |
_wpsf__( 'Ignore users logged in as Administrator' ),
|
201 |
_wpsf__( 'Authenticated administrator users will not be processed by the firewall' )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
202 |
)
|
203 |
)
|
204 |
);
|
205 |
|
206 |
-
$
|
207 |
'section_title' => _wpsf__( 'Choose IP Addresses To Blacklist' ),
|
208 |
'section_options' => array(
|
209 |
array(
|
@@ -217,7 +243,7 @@ class ICWP_OptionsHandler_Firewall extends ICWP_OptionsHandler_Base_WPSF {
|
|
217 |
)
|
218 |
)
|
219 |
);
|
220 |
-
$
|
221 |
'section_title' => _wpsf__( 'Miscellaneous Plugin Options' ),
|
222 |
'section_options' => array(
|
223 |
array(
|
@@ -233,12 +259,12 @@ class ICWP_OptionsHandler_Firewall extends ICWP_OptionsHandler_Base_WPSF {
|
|
233 |
);
|
234 |
|
235 |
$this->m_aOptions = array(
|
236 |
-
$
|
237 |
-
$
|
238 |
-
$
|
239 |
-
$
|
240 |
-
$
|
241 |
-
$
|
242 |
);
|
243 |
}
|
244 |
|
@@ -246,27 +272,37 @@ class ICWP_OptionsHandler_Firewall extends ICWP_OptionsHandler_Base_WPSF {
|
|
246 |
|
247 |
$sCurrentVersion = empty( $this->m_aOptionsValues[ 'current_plugin_version' ] )? '0.0' : $this->m_aOptionsValues[ 'current_plugin_version' ];
|
248 |
if ( version_compare( $sCurrentVersion, '1.4.0', '<' ) ) {
|
249 |
-
$aSettingsKey = array(
|
250 |
-
'current_plugin_version',
|
251 |
-
'enable_firewall',
|
252 |
-
'include_cookie_checks',
|
253 |
-
'block_dir_traversal',
|
254 |
-
'block_sql_queries',
|
255 |
-
'block_wordpress_terms',
|
256 |
-
'block_field_truncation',
|
257 |
-
'block_exe_file_uploads',
|
258 |
-
'block_leading_schema',
|
259 |
-
'block_send_email',
|
260 |
-
'ips_whitelist',
|
261 |
-
'ips_blacklist',
|
262 |
-
'page_params_whitelist',
|
263 |
-
'block_response',
|
264 |
-
'enable_firewall_log',
|
265 |
-
'whitelist_admins'
|
266 |
-
);
|
267 |
-
$this->migrateOptions( $aSettingsKey );
|
268 |
}//v1.4.0
|
269 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
270 |
}
|
271 |
|
272 |
endif;
|
1 |
<?php
|
2 |
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
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 |
+
/**
|
31 |
+
*/
|
32 |
public function doPrePluginOptionsSave() {
|
33 |
|
34 |
+
$aIpWhitelist = $this->getOpt( 'ips_whitelist' );
|
35 |
if ( $aIpWhitelist === false ) {
|
36 |
$aIpWhitelist = '';
|
37 |
$this->setOpt( 'ips_whitelist', $aIpWhitelist );
|
38 |
}
|
39 |
+
$this->processIpFilter( 'ips_whitelist', 'icwp_simple_firewall_whitelist_ips' );
|
40 |
|
41 |
$aIpBlacklist = $this->getOpt( 'ips_blacklist' );
|
42 |
if ( $aIpBlacklist === false ) {
|
43 |
$aIpBlacklist = '';
|
44 |
$this->setOpt( 'ips_blacklist', $aIpBlacklist );
|
45 |
}
|
46 |
+
$this->processIpFilter( 'ips_blacklist', 'icwp_simple_firewall_blacklist_ips' );
|
47 |
|
48 |
$aPageWhitelist = $this->getOpt( 'page_params_whitelist' );
|
49 |
if ( $aPageWhitelist === false ) {
|
57 |
$aIpWhitelist = $this->setOpt( 'block_response', $sBlockResponse );
|
58 |
}
|
59 |
}
|
|
|
|
|
60 |
|
61 |
+
/**
|
62 |
+
* @return bool|void
|
63 |
+
*/
|
64 |
+
public function defineOptions() {
|
65 |
+
$aFirewallBase = array(
|
66 |
+
'section_title' => sprintf( _wpsf__( 'Enable Plugin Feature: %s' ), _wpsf__('WordPress Firewall') ),
|
67 |
'section_options' => array(
|
68 |
array(
|
69 |
'enable_firewall',
|
70 |
+
'',
|
71 |
+
'N',
|
72 |
'checkbox',
|
73 |
_wpsf__( 'Enable Firewall' ),
|
74 |
_wpsf__( 'Enable (or Disable) The WordPress Firewall Feature' ),
|
75 |
+
sprintf( _wpsf__( 'Checking/Un-Checking this option will completely turn on/off the whole %s feature.' ), _wpsf__('WordPress Firewall') ),
|
76 |
+
'<a href="http://icwp.io/43" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
77 |
+
.' | <a href="http://icwp.io/wpsf01" target="_blank">'._wpsf__( 'blog' ).'</a>'
|
78 |
)
|
79 |
)
|
80 |
);
|
81 |
+
$aBlockTypesSection = array(
|
82 |
'section_title' => _wpsf__( 'Firewall Blocking Options' ),
|
83 |
'section_options' => array(
|
84 |
array(
|
93 |
array(
|
94 |
'block_dir_traversal',
|
95 |
'',
|
96 |
+
'Y',
|
97 |
'checkbox',
|
98 |
_wpsf__( 'Directory Traversals' ),
|
99 |
_wpsf__( 'Block Directory Traversals' ),
|
102 |
array(
|
103 |
'block_sql_queries',
|
104 |
'',
|
105 |
+
'Y',
|
106 |
'checkbox',
|
107 |
_wpsf__( 'SQL Queries' ),
|
108 |
_wpsf__( 'Block SQL Queries' ),
|
120 |
array(
|
121 |
'block_field_truncation',
|
122 |
'',
|
123 |
+
'Y',
|
124 |
'checkbox',
|
125 |
_wpsf__( 'Field Truncation' ),
|
126 |
_wpsf__( 'Block Field Truncation Attacks' ),
|
127 |
_wpsf__( 'This will block field truncation attacks in application parameters.' )
|
128 |
),
|
129 |
+
array(
|
130 |
+
'block_php_code',
|
131 |
+
'',
|
132 |
+
'N',
|
133 |
+
'checkbox',
|
134 |
+
_wpsf__( 'PHP Code' ),
|
135 |
+
sprintf( _wpsf__( 'Block %s' ), _wpsf__( 'PHP Code Includes' ) ),
|
136 |
+
_wpsf__( 'This will block any data that appears to try and include PHP files.' )
|
137 |
+
.'<br />'. _wpsf__( 'Will probably block saving within the Plugin/Theme file editors.' )
|
138 |
+
),
|
139 |
array(
|
140 |
'block_exe_file_uploads',
|
141 |
'',
|
157 |
),
|
158 |
);
|
159 |
$aRedirectOptions = array( 'select',
|
160 |
+
array( 'redirect_die_message', _wpsf__( 'Die With Message' ) ),
|
161 |
+
array( 'redirect_die', _wpsf__( 'Die' ) ),
|
162 |
+
array( 'redirect_home', _wpsf__( 'Redirect To Home Page' ) ),
|
163 |
+
array( 'redirect_404', _wpsf__( 'Return 404' ) ),
|
164 |
);
|
165 |
+
$aBlockSection = array(
|
166 |
'section_title' => _wpsf__( 'Choose Firewall Block Response' ),
|
167 |
'section_options' => array(
|
168 |
array(
|
186 |
)
|
187 |
);
|
188 |
|
189 |
+
$aWhitelistSection = array(
|
190 |
'section_title' => _wpsf__( 'Whitelists - IPs, Pages, Parameters, and Users that by-pass the Firewall' ),
|
191 |
'section_options' => array(
|
192 |
array(
|
211 |
array(
|
212 |
'whitelist_admins',
|
213 |
'',
|
214 |
+
'Y',
|
215 |
'checkbox',
|
216 |
+
sprintf( _wpsf__( 'Ignore %s' ), _wpsf__( 'Administrators' ) ),
|
217 |
_wpsf__( 'Ignore users logged in as Administrator' ),
|
218 |
_wpsf__( 'Authenticated administrator users will not be processed by the firewall' )
|
219 |
+
),
|
220 |
+
array(
|
221 |
+
'ignore_search_engines',
|
222 |
+
'',
|
223 |
+
'N',
|
224 |
+
'checkbox',
|
225 |
+
sprintf( _wpsf__( 'Ignore %s' ), _wpsf__( 'Search Engines' ) ),
|
226 |
+
_wpsf__( 'Ignore Search Engine Bots' ),
|
227 |
+
_wpsf__( 'When selected, the firewall will try to recognise search engine spiders/bots and not apply firewall rules to them' )
|
228 |
)
|
229 |
)
|
230 |
);
|
231 |
|
232 |
+
$aBlacklistSection = array(
|
233 |
'section_title' => _wpsf__( 'Choose IP Addresses To Blacklist' ),
|
234 |
'section_options' => array(
|
235 |
array(
|
243 |
)
|
244 |
)
|
245 |
);
|
246 |
+
$aMisc = array(
|
247 |
'section_title' => _wpsf__( 'Miscellaneous Plugin Options' ),
|
248 |
'section_options' => array(
|
249 |
array(
|
259 |
);
|
260 |
|
261 |
$this->m_aOptions = array(
|
262 |
+
$aFirewallBase,
|
263 |
+
$aBlockSection,
|
264 |
+
$aWhitelistSection,
|
265 |
+
$aBlacklistSection,
|
266 |
+
$aBlockTypesSection,
|
267 |
+
$aMisc
|
268 |
);
|
269 |
}
|
270 |
|
272 |
|
273 |
$sCurrentVersion = empty( $this->m_aOptionsValues[ 'current_plugin_version' ] )? '0.0' : $this->m_aOptionsValues[ 'current_plugin_version' ];
|
274 |
if ( version_compare( $sCurrentVersion, '1.4.0', '<' ) ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
275 |
}//v1.4.0
|
276 |
}
|
277 |
+
|
278 |
+
public function addRawIpsToFirewallList( $insListName, $inaNewIps ) {
|
279 |
+
if ( empty( $inaNewIps ) ) {
|
280 |
+
return;
|
281 |
+
}
|
282 |
+
|
283 |
+
$aIplist = $this->getOpt( $insListName );
|
284 |
+
if ( empty( $aIplist ) ) {
|
285 |
+
$aIplist = array();
|
286 |
+
}
|
287 |
+
$aNewList = array();
|
288 |
+
foreach( $inaNewIps as $sAddress ) {
|
289 |
+
$aNewList[ $sAddress ] = '';
|
290 |
+
}
|
291 |
+
$this->setOpt( $insListName, ICWP_WPSF_DataProcessor::Add_New_Raw_Ips( $aIplist, $aNewList ) );
|
292 |
+
}
|
293 |
+
|
294 |
+
public function removeRawIpsFromFirewallList( $insListName, $inaRemoveIps ) {
|
295 |
+
if ( empty( $inaRemoveIps ) ) {
|
296 |
+
return;
|
297 |
+
}
|
298 |
+
|
299 |
+
$aIplist = $this->getOpt( $insListName );
|
300 |
+
if ( empty( $aIplist ) || empty( $inaRemoveIps ) ) {
|
301 |
+
return;
|
302 |
+
}
|
303 |
+
$this->setOpt( $insListName, ICWP_WPSF_DataProcessor::Remove_Raw_Ips( $aIplist, $inaRemoveIps ) );
|
304 |
+
}
|
305 |
+
|
306 |
}
|
307 |
|
308 |
endif;
|
src/icwp-optionshandler-lockdown.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* Copyright (c)
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
@@ -16,11 +16,10 @@
|
|
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
|
24 |
|
25 |
const StoreName = 'lockdown_options';
|
26 |
|
@@ -42,11 +41,14 @@ class ICWP_OptionsHandler_Lockdown extends ICWP_OptionsHandler_Base_WPSF {
|
|
42 |
$this->setOpt( 'mask_wordpress_version', preg_replace( '/[^a-z0-9_.-]/i', '', $sCurrent ) );
|
43 |
}
|
44 |
}
|
45 |
-
|
|
|
|
|
|
|
46 |
public function defineOptions() {
|
47 |
|
48 |
$aBase = array(
|
49 |
-
'section_title' => _wpsf__( 'Enable
|
50 |
'section_options' => array(
|
51 |
array(
|
52 |
'enable_lockdown',
|
@@ -55,7 +57,8 @@ class ICWP_OptionsHandler_Lockdown extends ICWP_OptionsHandler_Base_WPSF {
|
|
55 |
'checkbox',
|
56 |
_wpsf__( 'Enable Lockdown' ),
|
57 |
_wpsf__( 'Enable (or Disable) The Lockdown Feature' ),
|
58 |
-
_wpsf__( '
|
|
|
59 |
)
|
60 |
)
|
61 |
);
|
@@ -70,11 +73,34 @@ class ICWP_OptionsHandler_Lockdown extends ICWP_OptionsHandler_Base_WPSF {
|
|
70 |
_wpsf__( 'Disable File Editing' ),
|
71 |
_wpsf__( 'Disable Ability To Edit Files' ),
|
72 |
_wpsf__( 'Removes the option to directly edit any files from within the WordPress admin area.' )
|
73 |
-
.'<br />'._wpsf__( 'Equivalent to setting DISALLOW_FILE_EDIT to TRUE.' )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
)
|
75 |
)
|
76 |
);
|
77 |
-
$
|
78 |
'section_title' => _wpsf__( 'WordPress Obscurity Options' ),
|
79 |
'section_options' => array(
|
80 |
array(
|
@@ -85,14 +111,16 @@ class ICWP_OptionsHandler_Lockdown extends ICWP_OptionsHandler_Base_WPSF {
|
|
85 |
_wpsf__( 'Mask WordPress Version' ),
|
86 |
_wpsf__( 'Prevents Public Display Of Your WordPress Version' ),
|
87 |
_wpsf__( 'Enter how you would like your WordPress version displayed publicly. Leave blank to disable this feature.' )
|
88 |
-
.'<br />'._wpsf__( 'Warning: This may interfere with WordPress plugins that rely on the $wp_version variable.' )
|
|
|
89 |
)
|
90 |
)
|
91 |
);
|
92 |
|
93 |
$this->m_aOptions = array(
|
94 |
$aBase,
|
95 |
-
$aAccess
|
|
|
96 |
);
|
97 |
|
98 |
if ( false && $this->getCanDoAuthSalts() ) {
|
@@ -115,29 +143,25 @@ class ICWP_OptionsHandler_Lockdown extends ICWP_OptionsHandler_Base_WPSF {
|
|
115 |
}
|
116 |
|
117 |
protected function getCanDoAuthSalts() {
|
118 |
-
|
119 |
-
$oWpFilesystem = new ICWP_WpFilesystem_WPSF();
|
120 |
|
121 |
-
if ( !$
|
122 |
return false;
|
123 |
}
|
124 |
|
125 |
-
if ( !$
|
126 |
return false;
|
127 |
}
|
128 |
|
129 |
-
$sWpConfigPath =
|
130 |
|
131 |
-
if (
|
132 |
-
var_dump('no wpconfig');
|
133 |
return false;
|
134 |
}
|
135 |
-
$mResult = $
|
136 |
return !empty( $mResult );
|
137 |
}
|
138 |
|
139 |
-
public function updateHandler() {
|
140 |
-
}
|
141 |
}
|
142 |
|
143 |
endif;
|
1 |
<?php
|
2 |
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
16 |
*/
|
17 |
|
18 |
require_once( dirname(__FILE__).'/icwp-optionshandler-base.php' );
|
|
|
19 |
|
20 |
if ( !class_exists('ICWP_OptionsHandler_Lockdown') ):
|
21 |
|
22 |
+
class ICWP_OptionsHandler_Lockdown extends ICWP_OptionsHandler_Base_Wpsf {
|
23 |
|
24 |
const StoreName = 'lockdown_options';
|
25 |
|
41 |
$this->setOpt( 'mask_wordpress_version', preg_replace( '/[^a-z0-9_.-]/i', '', $sCurrent ) );
|
42 |
}
|
43 |
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* @return bool|void
|
47 |
+
*/
|
48 |
public function defineOptions() {
|
49 |
|
50 |
$aBase = array(
|
51 |
+
'section_title' => sprintf( _wpsf__( 'Enable Plugin Feature: %s' ), _wpsf__('WordPress Lockdown') ),
|
52 |
'section_options' => array(
|
53 |
array(
|
54 |
'enable_lockdown',
|
57 |
'checkbox',
|
58 |
_wpsf__( 'Enable Lockdown' ),
|
59 |
_wpsf__( 'Enable (or Disable) The Lockdown Feature' ),
|
60 |
+
sprintf( _wpsf__( 'Checking/Un-Checking this option will completely turn on/off the whole %s feature.' ), _wpsf__('WordPress Lockdown') ),
|
61 |
+
'<a href="http://icwp.io/4r" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
62 |
)
|
63 |
)
|
64 |
);
|
73 |
_wpsf__( 'Disable File Editing' ),
|
74 |
_wpsf__( 'Disable Ability To Edit Files' ),
|
75 |
_wpsf__( 'Removes the option to directly edit any files from within the WordPress admin area.' )
|
76 |
+
.'<br />'._wpsf__( 'Equivalent to setting DISALLOW_FILE_EDIT to TRUE.' ),
|
77 |
+
'<a href="http://icwp.io/4q" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
78 |
+
),
|
79 |
+
array(
|
80 |
+
'force_ssl_login',
|
81 |
+
'',
|
82 |
+
'N',
|
83 |
+
'checkbox',
|
84 |
+
_wpsf__( 'Force SSL Login' ),
|
85 |
+
_wpsf__( 'Forces Login Form To Be Submitted Over SSL' ),
|
86 |
+
_wpsf__( 'Please only enable this option if you have a valid SSL certificate installed.' )
|
87 |
+
.'<br />'._wpsf__( 'Equivalent to setting FORCE_SSL_LOGIN to TRUE.' ),
|
88 |
+
'<a href="http://icwp.io/4s" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
89 |
+
),
|
90 |
+
array(
|
91 |
+
'force_ssl_admin',
|
92 |
+
'',
|
93 |
+
'N',
|
94 |
+
'checkbox',
|
95 |
+
_wpsf__( 'Force SSL Admin' ),
|
96 |
+
_wpsf__( 'Forces WordPress Admin Dashboard To Be Delivered Over SSL' ),
|
97 |
+
_wpsf__( 'Please only enable this option if you have a valid SSL certificate installed.' )
|
98 |
+
.'<br />'._wpsf__( 'Equivalent to setting FORCE_SSL_ADMIN to TRUE.' ),
|
99 |
+
'<a href="http://icwp.io/4t" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
100 |
)
|
101 |
)
|
102 |
);
|
103 |
+
$aObscurity = array(
|
104 |
'section_title' => _wpsf__( 'WordPress Obscurity Options' ),
|
105 |
'section_options' => array(
|
106 |
array(
|
111 |
_wpsf__( 'Mask WordPress Version' ),
|
112 |
_wpsf__( 'Prevents Public Display Of Your WordPress Version' ),
|
113 |
_wpsf__( 'Enter how you would like your WordPress version displayed publicly. Leave blank to disable this feature.' )
|
114 |
+
.'<br />'._wpsf__( 'Warning: This may interfere with WordPress plugins that rely on the $wp_version variable.' ),
|
115 |
+
'<a href="http://icwp.io/43" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
116 |
)
|
117 |
)
|
118 |
);
|
119 |
|
120 |
$this->m_aOptions = array(
|
121 |
$aBase,
|
122 |
+
$aAccess,
|
123 |
+
$aObscurity
|
124 |
);
|
125 |
|
126 |
if ( false && $this->getCanDoAuthSalts() ) {
|
143 |
}
|
144 |
|
145 |
protected function getCanDoAuthSalts() {
|
146 |
+
$oWpFs = $this->loadFileSystemProcessor();
|
|
|
147 |
|
148 |
+
if ( !$oWpFs->getCanWpRemoteGet() ) {
|
149 |
return false;
|
150 |
}
|
151 |
|
152 |
+
if ( !$oWpFs->getCanDiskWrite() ) {
|
153 |
return false;
|
154 |
}
|
155 |
|
156 |
+
$sWpConfigPath = $oWpFs->exists( ABSPATH.'wp-config.php' )? ABSPATH.'wp-config.php' : ABSPATH.'..'.ICWP_DS.'wp-config.php';
|
157 |
|
158 |
+
if ( !$oWpFs->exists( $sWpConfigPath ) ) {
|
|
|
159 |
return false;
|
160 |
}
|
161 |
+
$mResult = $oWpFs->getCanReadWriteFile( $sWpConfigPath );
|
162 |
return !empty( $mResult );
|
163 |
}
|
164 |
|
|
|
|
|
165 |
}
|
166 |
|
167 |
endif;
|
src/icwp-optionshandler-logging.php
ADDED
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
+
* All rights reserved.
|
5 |
+
*
|
6 |
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
7 |
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
8 |
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
9 |
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
10 |
+
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
11 |
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
12 |
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
13 |
+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
14 |
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
15 |
+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
+
*/
|
17 |
+
|
18 |
+
require_once( dirname(__FILE__).'/icwp-optionshandler-base.php' );
|
19 |
+
|
20 |
+
if ( !class_exists('ICWP_OptionsHandler_Logging') ):
|
21 |
+
|
22 |
+
class ICWP_OptionsHandler_Logging extends ICWP_OptionsHandler_Base_Wpsf {
|
23 |
+
|
24 |
+
const StoreName = 'logging_options';
|
25 |
+
|
26 |
+
public function __construct( $insPrefix, $insVersion ) {
|
27 |
+
parent::__construct( $insPrefix, self::StoreName, $insVersion );
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* @return bool|void
|
32 |
+
*/
|
33 |
+
public function defineOptions() {
|
34 |
+
$aBase = array(
|
35 |
+
'section_title' => _wpsf__( 'Enable Logging' ),
|
36 |
+
'section_options' => array(
|
37 |
+
array(
|
38 |
+
'enable_logging',
|
39 |
+
'',
|
40 |
+
'Y',
|
41 |
+
'checkbox',
|
42 |
+
_wpsf__( 'Enable Logging' ),
|
43 |
+
_wpsf__( 'Enable (or Disable) The Plugin Logging Feature.' ),
|
44 |
+
_wpsf__( 'Regardless of any other settings, this option will turn off the Logging system, or enable your chosen Logging options.' )
|
45 |
+
)
|
46 |
+
)
|
47 |
+
);
|
48 |
+
$this->m_aOptions = array(
|
49 |
+
$aBase
|
50 |
+
);
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* This is the point where you would want to do any options verification
|
55 |
+
*/
|
56 |
+
protected function doPrePluginOptionsSave() { }
|
57 |
+
}
|
58 |
+
|
59 |
+
endif;
|
src/icwp-optionshandler-loginprotect.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* Copyright (c)
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
@@ -19,7 +19,7 @@ require_once( dirname(__FILE__).'/icwp-optionshandler-base.php' );
|
|
19 |
|
20 |
if ( !class_exists('ICWP_OptionsHandler_LoginProtect') ):
|
21 |
|
22 |
-
class ICWP_OptionsHandler_LoginProtect extends
|
23 |
|
24 |
const StoreName = 'loginprotect_options';
|
25 |
|
@@ -27,25 +27,42 @@ class ICWP_OptionsHandler_LoginProtect extends ICWP_OptionsHandler_Base_WPSF {
|
|
27 |
parent::__construct( $insPrefix, self::StoreName, $insVersion );
|
28 |
}
|
29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
public function defineOptions() {
|
31 |
|
32 |
-
$
|
33 |
-
|
34 |
-
$this->m_aOptionsBase = array(
|
35 |
-
'section_title' => _wpsf__( 'Enable Login Protection' ),
|
36 |
'section_options' => array(
|
37 |
array(
|
38 |
'enable_login_protect',
|
39 |
'',
|
40 |
-
'
|
41 |
'checkbox',
|
42 |
_wpsf__( 'Enable Login Protect' ),
|
43 |
_wpsf__( 'Enable (or Disable) The Login Protection Feature' ),
|
44 |
-
_wpsf__( '
|
|
|
|
|
45 |
)
|
46 |
),
|
47 |
);
|
48 |
-
$
|
49 |
'section_title' => _wpsf__( 'Whitelist IPs that by-pass Login Protect' ),
|
50 |
'section_options' => array(
|
51 |
array(
|
@@ -55,21 +72,44 @@ class ICWP_OptionsHandler_LoginProtect extends ICWP_OptionsHandler_Base_WPSF {
|
|
55 |
'ip_addresses',
|
56 |
_wpsf__( 'Whitelist IP Addresses' ),
|
57 |
_wpsf__( 'Specify IP Addresses that by-pass all Login Protect rules' ),
|
58 |
-
sprintf( _wpsf__( 'Take a new line per address. Your IP address is: %s' ), '<span class="code">'.$this->getVisitorIpAddress( false ).'</span>' )
|
|
|
59 |
)
|
60 |
)
|
61 |
);
|
62 |
-
|
|
|
63 |
'section_title' => _wpsf__( 'Two-Factor Authentication Protection Options' ),
|
64 |
'section_options' => array(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
array(
|
66 |
'enable_two_factor_auth_by_ip',
|
67 |
'',
|
68 |
'N',
|
69 |
'checkbox',
|
70 |
-
_wpsf__( 'Two-Factor Authentication' ),
|
71 |
-
_wpsf__( 'Two-Factor Login Authentication By IP Address' ),
|
72 |
-
_wpsf__( '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',
|
@@ -82,17 +122,18 @@ class ICWP_OptionsHandler_LoginProtect extends ICWP_OptionsHandler_Base_WPSF {
|
|
82 |
)
|
83 |
)
|
84 |
);
|
85 |
-
$
|
86 |
'section_title' => _wpsf__( 'Login Protection Options' ),
|
87 |
'section_options' => array(
|
88 |
array(
|
89 |
'login_limit_interval',
|
90 |
'',
|
91 |
-
'
|
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',
|
@@ -101,12 +142,87 @@ class ICWP_OptionsHandler_LoginProtect extends ICWP_OptionsHandler_Base_WPSF {
|
|
101 |
'checkbox',
|
102 |
_wpsf__( 'G.A.S.P Protection' ),
|
103 |
_wpsf__( 'Use G.A.S.P. Protection To Prevent Login Attempts By Bots' ),
|
104 |
-
_wpsf__( 'Adds a dynamically (Javascript) generated checkbox to the login form that prevents bots using automated login techniques. Recommended: ON' )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
105 |
)
|
106 |
)
|
107 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
108 |
|
109 |
-
$
|
110 |
'section_title' => _wpsf__( 'Logging Options' ),
|
111 |
'section_options' => array(
|
112 |
array(
|
@@ -122,11 +238,12 @@ class ICWP_OptionsHandler_LoginProtect extends ICWP_OptionsHandler_Base_WPSF {
|
|
122 |
);
|
123 |
|
124 |
$this->m_aOptions = array(
|
125 |
-
$
|
126 |
-
$
|
127 |
-
$
|
128 |
-
$
|
129 |
-
$
|
|
|
130 |
);
|
131 |
}
|
132 |
|
@@ -146,6 +263,26 @@ class ICWP_OptionsHandler_LoginProtect extends ICWP_OptionsHandler_Base_WPSF {
|
|
146 |
$this->migrateOptions( $aSettingsKey );
|
147 |
}//'1.4.0', '<'
|
148 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
149 |
}
|
150 |
|
151 |
endif;
|
1 |
<?php
|
2 |
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
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 |
|
27 |
parent::__construct( $insPrefix, self::StoreName, $insVersion );
|
28 |
}
|
29 |
|
30 |
+
public function doPrePluginOptionsSave() {
|
31 |
+
$aIpWhitelist = $this->getOpt( 'ips_whitelist' );
|
32 |
+
if ( $aIpWhitelist === false ) {
|
33 |
+
$aIpWhitelist = '';
|
34 |
+
$this->setOpt( 'ips_whitelist', $aIpWhitelist );
|
35 |
+
}
|
36 |
+
$this->processIpFilter( 'ips_whitelist', 'icwp_simple_firewall_whitelist_ips' );
|
37 |
+
|
38 |
+
$aTwoFactorAuthRoles = $this->getOpt( 'two_factor_auth_user_roles' );
|
39 |
+
if ( empty($aTwoFactorAuthRoles) || !is_array( $aTwoFactorAuthRoles ) ) {
|
40 |
+
$this->setOpt( 'two_factor_auth_user_roles', $this->getTwoFactorUserAuthRoles( true ) );
|
41 |
+
}
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* @return bool|void
|
46 |
+
*/
|
47 |
public function defineOptions() {
|
48 |
|
49 |
+
$aOptionsBase = array(
|
50 |
+
'section_title' => sprintf( _wpsf__( 'Enable Plugin Feature: %s' ), _wpsf__('Login Protection') ),
|
|
|
|
|
51 |
'section_options' => array(
|
52 |
array(
|
53 |
'enable_login_protect',
|
54 |
'',
|
55 |
+
'N',
|
56 |
'checkbox',
|
57 |
_wpsf__( 'Enable Login Protect' ),
|
58 |
_wpsf__( 'Enable (or Disable) The Login Protection Feature' ),
|
59 |
+
sprintf( _wpsf__( 'Checking/Un-Checking this option will completely turn on/off the whole %s feature.' ), _wpsf__('Login Protection') ),
|
60 |
+
'<a href="http://icwp.io/51" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
61 |
+
.' | <a href="http://icwp.io/wpsf03" target="_blank">'._wpsf__( 'blog' ).'</a>'
|
62 |
)
|
63 |
),
|
64 |
);
|
65 |
+
$aWhitelist = array(
|
66 |
'section_title' => _wpsf__( 'Whitelist IPs that by-pass Login Protect' ),
|
67 |
'section_options' => array(
|
68 |
array(
|
72 |
'ip_addresses',
|
73 |
_wpsf__( 'Whitelist IP Addresses' ),
|
74 |
_wpsf__( 'Specify IP Addresses that by-pass all Login Protect rules' ),
|
75 |
+
sprintf( _wpsf__( 'Take a new line per address. Your IP address is: %s' ), '<span class="code">'.$this->getVisitorIpAddress( false ).'</span>' ),
|
76 |
+
'<a href="http://icwp.io/52" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
77 |
)
|
78 |
)
|
79 |
);
|
80 |
+
|
81 |
+
$aTwoFactorAuth = array(
|
82 |
'section_title' => _wpsf__( 'Two-Factor Authentication Protection Options' ),
|
83 |
'section_options' => array(
|
84 |
+
array(
|
85 |
+
'two_factor_auth_user_roles',
|
86 |
+
'',
|
87 |
+
$this->getTwoFactorUserAuthRoles( true ), // default is Contributors, Authors, Editors and Administrators
|
88 |
+
$this->getTwoFactorUserAuthRoles(),
|
89 |
+
_wpsf__( 'Two-Factor Auth User Roles' ),
|
90 |
+
_wpsf__( 'All User Roles Subject To Two-Factor Authentication' ),
|
91 |
+
_wpsf__( 'Select which types of users/roles will be subject to two-factor login authentication.' ),
|
92 |
+
'<a href="http://icwp.io/4v" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
93 |
+
),
|
94 |
array(
|
95 |
'enable_two_factor_auth_by_ip',
|
96 |
'',
|
97 |
'N',
|
98 |
'checkbox',
|
99 |
+
sprintf( _wpsf__( 'Two-Factor Authentication (%s)' ), _wpsf__('IP') ),
|
100 |
+
sprintf( _wpsf__( 'Two-Factor Login Authentication By %s' ), _wpsf__('IP Address') ),
|
101 |
+
_wpsf__( 'All users will be required to authenticate their logins by email-based two-factor authentication when logging in from a new IP address' ),
|
102 |
+
'<a href="http://icwp.io/3s" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
103 |
+
),
|
104 |
+
array(
|
105 |
+
'enable_two_factor_auth_by_cookie',
|
106 |
+
'',
|
107 |
+
'N',
|
108 |
+
'checkbox',
|
109 |
+
sprintf( _wpsf__( 'Two-Factor Authentication (%s)' ), _wpsf__('Cookie') ),
|
110 |
+
sprintf( _wpsf__( 'Two-Factor Login Authentication By %s' ), _wpsf__('Cookie') ),
|
111 |
+
_wpsf__( 'This will restrict all user login sessions to a single browser. Use this if your users have dynamic IP addresses.' ),
|
112 |
+
'<a href="http://icwp.io/3t" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
113 |
),
|
114 |
array(
|
115 |
'enable_two_factor_bypass_on_email_fail',
|
122 |
)
|
123 |
)
|
124 |
);
|
125 |
+
$aLoginProtect = array(
|
126 |
'section_title' => _wpsf__( 'Login Protection Options' ),
|
127 |
'section_options' => array(
|
128 |
array(
|
129 |
'login_limit_interval',
|
130 |
'',
|
131 |
+
'10',
|
132 |
'integer',
|
133 |
+
_wpsf__('Login Cooldown Interval'),
|
134 |
+
_wpsf__('Limit login attempts to every X seconds'),
|
135 |
+
_wpsf__('WordPress will process only ONE login attempt for every number of seconds specified. Zero (0) turns this off. Suggested: 5'),
|
136 |
+
'<a href="http://icwp.io/3q" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
137 |
),
|
138 |
array(
|
139 |
'enable_login_gasp_check',
|
142 |
'checkbox',
|
143 |
_wpsf__( 'G.A.S.P Protection' ),
|
144 |
_wpsf__( 'Use G.A.S.P. Protection To Prevent Login Attempts By Bots' ),
|
145 |
+
_wpsf__( 'Adds a dynamically (Javascript) generated checkbox to the login form that prevents bots using automated login techniques. Recommended: ON' ),
|
146 |
+
'<a href="http://icwp.io/3r" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
147 |
+
),
|
148 |
+
array(
|
149 |
+
'enable_prevent_remote_post',
|
150 |
+
'',
|
151 |
+
'Y',
|
152 |
+
'checkbox',
|
153 |
+
_wpsf__( 'Prevent Remote Login' ),
|
154 |
+
_wpsf__( 'Prevents Remote Login Attempts From Other Locations' ),
|
155 |
+
_wpsf__( 'Prevents any login attempts that do not originate from your website. This prevent bots from attempting to login remotely. Recommended: ON' ),
|
156 |
+
'<a href="http://icwp.io/4n" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
157 |
)
|
158 |
)
|
159 |
);
|
160 |
+
|
161 |
+
$aYubikeyProtect = array(
|
162 |
+
'section_title' => _wpsf__( 'Yubikey Authentication' ),
|
163 |
+
'section_options' => array(
|
164 |
+
array(
|
165 |
+
'enable_yubikey',
|
166 |
+
'',
|
167 |
+
'N',
|
168 |
+
'checkbox',
|
169 |
+
_wpsf__('Enable Yubikey Authentication'),
|
170 |
+
_wpsf__('Turn On / Off Yubikey Authentication On This Site'),
|
171 |
+
_wpsf__('Combined with your Yubikey API Key (below) this will form the basis of your Yubikey Authentication'),
|
172 |
+
'<a href="http://icwp.io/4f" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
173 |
+
),
|
174 |
+
array(
|
175 |
+
'yubikey_app_id',
|
176 |
+
'',
|
177 |
+
'',
|
178 |
+
'text',
|
179 |
+
_wpsf__('Yubikey App ID'),
|
180 |
+
_wpsf__('Your Unique Yubikey App ID'),
|
181 |
+
_wpsf__('Combined with your Yubikey API Key (below) this will form the basis of your Yubikey Authentication')
|
182 |
+
. _wpsf__( 'Please review the [more info] link on how to get your own Yubikey App ID and API Key.' ),
|
183 |
+
'<a href="http://icwp.io/4g" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
184 |
+
),
|
185 |
+
array(
|
186 |
+
'yubikey_api_key',
|
187 |
+
'',
|
188 |
+
'',
|
189 |
+
'text',
|
190 |
+
_wpsf__( 'Yubikey API Key' ),
|
191 |
+
_wpsf__( 'Your Unique Yubikey App API Key' ),
|
192 |
+
_wpsf__( 'Combined with your Yubikey App ID (above) this will form the basis of your Yubikey Authentication.' )
|
193 |
+
. _wpsf__( 'Please review the [more info] link on how to get your own Yubikey App ID and API Key.' ),
|
194 |
+
'<a href="http://icwp.io/4g" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
195 |
+
),
|
196 |
+
array(
|
197 |
+
'yubikey_unique_keys',
|
198 |
+
'',
|
199 |
+
'',
|
200 |
+
'yubikey_unique_keys',
|
201 |
+
_wpsf__( 'Yubikey Unique Keys' ),
|
202 |
+
_wpsf__( 'Permitted Username - Yubikey Pairs For This Site' ),
|
203 |
+
'<strong>'. sprintf( _wpsf__( 'Format: %s' ), 'Username,Yubikey').'</strong>'
|
204 |
+
.'<br />- '. _wpsf__( 'Provide Username<->Yubikey Pairs that are usable on this site.')
|
205 |
+
.'<br />- '. _wpsf__( 'If a Username if not assigned a Yubikey, Yubikey Authentication is OFF for that user.')
|
206 |
+
.'<br />- '. _wpsf__( 'Each [Username,Key] pair should be separated by a new line: you only need to provide the first 12 characters of the yubikey.' ),
|
207 |
+
'<a href="http://icwp.io/4h" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
208 |
+
),
|
209 |
+
/*
|
210 |
+
array(
|
211 |
+
'enable_yubikey_only',
|
212 |
+
'',
|
213 |
+
'N',
|
214 |
+
'checkbox',
|
215 |
+
_wpsf__('Enable Yubikey Only'),
|
216 |
+
_wpsf__('Turn On / Off Yubikey Only Authentication'),
|
217 |
+
_wpsf__('Yubikey Only Authentication is where you can login into your WordPress site with just a Yubikey OTP.')
|
218 |
+
.'<br />- '. _wpsf__("You don't need to enter a username or a password, just a valid Yubikey OTP.")
|
219 |
+
.'<br />- '. _wpsf__("Check your list of Yubikeys as only 1 WordPress username may be assigned to a given Yubikey ID (but you may have multiple Yubikeys for a given username)."),
|
220 |
+
sprintf( _wpsf__( '%smore info%s' ), '<a href="http://icwp.io/4f" target="_blank">', '</a>' )
|
221 |
+
),*/
|
222 |
+
)
|
223 |
+
);
|
224 |
|
225 |
+
$aLoggingSection = array(
|
226 |
'section_title' => _wpsf__( 'Logging Options' ),
|
227 |
'section_options' => array(
|
228 |
array(
|
238 |
);
|
239 |
|
240 |
$this->m_aOptions = array(
|
241 |
+
$aOptionsBase,
|
242 |
+
$aWhitelist,
|
243 |
+
$aLoginProtect,
|
244 |
+
$aTwoFactorAuth,
|
245 |
+
$aYubikeyProtect,
|
246 |
+
$aLoggingSection
|
247 |
);
|
248 |
}
|
249 |
|
263 |
$this->migrateOptions( $aSettingsKey );
|
264 |
}//'1.4.0', '<'
|
265 |
}
|
266 |
+
|
267 |
+
/**
|
268 |
+
* @param boolean $fAsDefaults
|
269 |
+
* @return array
|
270 |
+
*/
|
271 |
+
protected function getTwoFactorUserAuthRoles( $fAsDefaults = false ) {
|
272 |
+
$aTwoAuthRoles = array( 'type' => 'multiple_select',
|
273 |
+
0 => _wpsf__('Subscribers'),
|
274 |
+
1 => _wpsf__('Contributors'),
|
275 |
+
2 => _wpsf__('Authors'),
|
276 |
+
3 => _wpsf__('Editors'),
|
277 |
+
8 => _wpsf__('Administrators')
|
278 |
+
);
|
279 |
+
if ( $fAsDefaults ) {
|
280 |
+
unset($aTwoAuthRoles['type']);
|
281 |
+
unset($aTwoAuthRoles[0]);
|
282 |
+
return array_keys($aTwoAuthRoles);
|
283 |
+
}
|
284 |
+
return $aTwoAuthRoles;
|
285 |
+
}
|
286 |
}
|
287 |
|
288 |
endif;
|
src/icwp-optionshandler-privacyprotect.php
ADDED
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
+
* All rights reserved.
|
5 |
+
*
|
6 |
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
7 |
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
8 |
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
9 |
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
10 |
+
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
11 |
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
12 |
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
13 |
+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
14 |
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
15 |
+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
+
*/
|
17 |
+
|
18 |
+
require_once( dirname(__FILE__).'/icwp-optionshandler-base.php' );
|
19 |
+
|
20 |
+
if ( !class_exists('ICWP_OptionsHandler_PrivacyProtect') ):
|
21 |
+
|
22 |
+
class ICWP_OptionsHandler_PrivacyProtect extends ICWP_OptionsHandler_Base_Wpsf {
|
23 |
+
|
24 |
+
const StoreName = 'privacyprotect_options';
|
25 |
+
|
26 |
+
public function __construct( $insPrefix, $insVersion ) {
|
27 |
+
parent::__construct( $insPrefix, self::StoreName, $insVersion );
|
28 |
+
}
|
29 |
+
|
30 |
+
public function doPrePluginOptionsSave() { }
|
31 |
+
|
32 |
+
/**
|
33 |
+
* @return bool|void
|
34 |
+
*/
|
35 |
+
public function defineOptions() {
|
36 |
+
|
37 |
+
$aOptionsBase = array(
|
38 |
+
'section_title' => _wpsf__( 'Enable Privacy Protection' ),
|
39 |
+
'section_options' => array(
|
40 |
+
array(
|
41 |
+
'enable_privacy_protect',
|
42 |
+
'',
|
43 |
+
'N',
|
44 |
+
'checkbox',
|
45 |
+
sprintf( _wpsf__( 'Enable %s' ), _wpsf__('Privacy Protection') ),
|
46 |
+
sprintf( _wpsf__( 'Enable (or Disable) The %s Feature' ), _wpsf__('Privacy Protection') ),
|
47 |
+
_wpsf__( 'Regardless of any other settings, this option will turn off the Privacy Protection feature, or enable your selected Privacy Protection options' ),
|
48 |
+
'<a href="http://icwp.io/3y" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
49 |
+
)
|
50 |
+
),
|
51 |
+
);
|
52 |
+
$aFurtherOptions = array(
|
53 |
+
'section_title' => _wpsf__( 'Data Filtering and Logging Options' ),
|
54 |
+
'section_options' => array(
|
55 |
+
array(
|
56 |
+
'ignore_local_requests',
|
57 |
+
'',
|
58 |
+
'Y',
|
59 |
+
'checkbox',
|
60 |
+
_wpsf__( 'Ignore Local Requests' ),
|
61 |
+
_wpsf__( 'Ignore Requests This Site Makes To Itself' ),
|
62 |
+
_wpsf__( 'Does not log any requests this site makes to itself - for example the WP Cron' ),
|
63 |
+
'<a href="http://icwp.io/3y" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
64 |
+
),
|
65 |
+
array(
|
66 |
+
'filter_wordpressorg_update_data',
|
67 |
+
'',
|
68 |
+
'Y',
|
69 |
+
'checkbox',
|
70 |
+
sprintf( _wpsf__( 'Enable %s' ), _wpsf__('WordPress.org Privacy') ),
|
71 |
+
_wpsf__( 'Enable Filtering Of Identifiable Data Sent To WordPress.org' ),
|
72 |
+
_wpsf__( 'With this option enabled, any identifiable information about your site will be stripped from the web requests made to WordPress.org' ),
|
73 |
+
'<a href="http://icwp.io/3y" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
74 |
+
),
|
75 |
+
array(
|
76 |
+
'filter_site_url',
|
77 |
+
'',
|
78 |
+
'N',
|
79 |
+
'checkbox',
|
80 |
+
sprintf( _wpsf__( 'Enable %s' ), _wpsf__('Site URL Filter') ),
|
81 |
+
_wpsf__( 'Enable Filtering Of Your Site URL From All Web Calls' ),
|
82 |
+
_wpsf__( 'With this option enabled, all web calls made that contain your site URL will filter this URL and replace it with a random string' ),
|
83 |
+
'<a href="http://icwp.io/3y" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
84 |
+
)
|
85 |
+
)
|
86 |
+
);
|
87 |
+
|
88 |
+
$this->m_aOptions = array(
|
89 |
+
$aOptionsBase,
|
90 |
+
$aFurtherOptions
|
91 |
+
);
|
92 |
+
}
|
93 |
+
|
94 |
+
public function updateHandler() {
|
95 |
+
$sCurrentVersion = empty( $this->m_aOptionsValues[ 'current_plugin_version' ] )? '0.0' : $this->m_aOptionsValues[ 'current_plugin_version' ];
|
96 |
+
}
|
97 |
+
}
|
98 |
+
|
99 |
+
endif;
|
src/icwp-optionshandler-wpsf.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* Copyright (c)
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
@@ -19,7 +19,7 @@ require_once( dirname(__FILE__).'/icwp-optionshandler-base.php' );
|
|
19 |
|
20 |
if ( !class_exists('ICWP_OptionsHandler_Wpsf') ):
|
21 |
|
22 |
-
class ICWP_OptionsHandler_Wpsf extends
|
23 |
|
24 |
const StoreName = 'plugin_options';
|
25 |
const Default_AccessKeyTimeout = 30;
|
@@ -27,25 +27,24 @@ class ICWP_OptionsHandler_Wpsf extends ICWP_OptionsHandler_Base_WPSF {
|
|
27 |
public function __construct( $insPrefix, $insVersion ) {
|
28 |
parent::__construct( $insPrefix, self::StoreName, $insVersion );
|
29 |
}
|
30 |
-
|
31 |
-
public function defineOptions() {
|
32 |
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
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 |
|
@@ -61,8 +60,9 @@ class ICWP_OptionsHandler_Wpsf extends ICWP_OptionsHandler_Base_WPSF {
|
|
61 |
'checkbox',
|
62 |
_wpsf__( 'Enable Access Key' ),
|
63 |
_wpsf__( 'Enforce Admin Access Restriction' ),
|
64 |
-
_wpsf__( 'Enable this with great care and consideration. When this Access Key option is enabled, you must specify a key below and use it to gain access to this plugin.' )
|
65 |
-
|
|
|
66 |
),
|
67 |
array(
|
68 |
'admin_access_timeout',
|
@@ -72,6 +72,7 @@ class ICWP_OptionsHandler_Wpsf extends ICWP_OptionsHandler_Base_WPSF {
|
|
72 |
_wpsf__( 'Access Key Timeout' ),
|
73 |
_wpsf__( 'Specify A Timeout For Plugin Admin Access' ),
|
74 |
_wpsf__( 'This will automatically expire your WordPress Simple Firewall session. Does not apply until you enter the access key again. Default: 30 minutes.' ),
|
|
|
75 |
),
|
76 |
array(
|
77 |
'admin_access_key',
|
@@ -81,7 +82,8 @@ class ICWP_OptionsHandler_Wpsf extends ICWP_OptionsHandler_Base_WPSF {
|
|
81 |
_wpsf__( 'Admin Access Key' ),
|
82 |
_wpsf__( 'Specify Your Plugin Access Key' ),
|
83 |
_wpsf__( 'If you forget this, you could potentially lock yourself out from using this plugin.' )
|
84 |
-
.'<strong>'._wpsf__( 'Leave it blank to not update it' ).'</strong>',
|
|
|
85 |
)
|
86 |
)
|
87 |
);
|
@@ -89,6 +91,30 @@ class ICWP_OptionsHandler_Wpsf extends ICWP_OptionsHandler_Base_WPSF {
|
|
89 |
|
90 |
$aGeneral = array(
|
91 |
'section_title' => _wpsf__( 'General Plugin Options' ),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
92 |
'section_options' => array(
|
93 |
array(
|
94 |
'enable_firewall',
|
@@ -101,7 +127,7 @@ class ICWP_OptionsHandler_Wpsf extends ICWP_OptionsHandler_Base_WPSF {
|
|
101 |
array(
|
102 |
'enable_login_protect',
|
103 |
'',
|
104 |
-
'
|
105 |
'checkbox',
|
106 |
_wpsf__( 'Enable Login Protect' ),
|
107 |
_wpsf__( 'Enable (or Disable) The Login Protection Feature' ),
|
@@ -110,12 +136,22 @@ class ICWP_OptionsHandler_Wpsf extends ICWP_OptionsHandler_Base_WPSF {
|
|
110 |
array(
|
111 |
'enable_comments_filter',
|
112 |
'',
|
113 |
-
'
|
114 |
'checkbox',
|
115 |
_wpsf__( 'Enable Comments Filter' ),
|
116 |
_wpsf__( 'Enable (or Disable) The Comments Filter Feature' ),
|
117 |
_wpsf__( 'Regardless of any other settings, this option will turn off the Comments Filter feature, or enable your selected Comments Filter options' )
|
118 |
),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
119 |
array(
|
120 |
'enable_lockdown',
|
121 |
'',
|
@@ -128,71 +164,18 @@ class ICWP_OptionsHandler_Wpsf extends ICWP_OptionsHandler_Base_WPSF {
|
|
128 |
array(
|
129 |
'enable_autoupdates',
|
130 |
'',
|
131 |
-
'
|
132 |
'checkbox',
|
133 |
_wpsf__( 'Enable Auto Updates' ),
|
134 |
_wpsf__( 'Enable (or Disable) The Auto Updates Feature' ),
|
135 |
_wpsf__( 'Regardless of any other settings, this option will turn off the Auto Updates feature, or enable your selected Auto Updates options' )
|
136 |
-
),
|
137 |
-
/*
|
138 |
-
array(
|
139 |
-
'enable_auto_plugin_upgrade',
|
140 |
-
'',
|
141 |
-
'N',
|
142 |
-
'checkbox',
|
143 |
-
'Auto-Upgrade',
|
144 |
-
'When an upgrade is detected, the plugin will automatically initiate the upgrade.',
|
145 |
-
'If you prefer to manage plugin upgrades, deselect this option. Otherwise, this plugin will auto-upgrade once any available update is detected.'
|
146 |
-
),
|
147 |
-
*/
|
148 |
-
array(
|
149 |
-
'enable_upgrade_admin_notice',
|
150 |
-
'',
|
151 |
-
'Y',
|
152 |
-
'checkbox',
|
153 |
-
_wpsf__( 'Plugin Upgrade Notice' ),
|
154 |
-
_wpsf__( 'Display A Notice When An Upgrade Is Available' ),
|
155 |
-
_wpsf__( 'Displays a notice at the top of your WordPress admin section when a plugin upgrade is available' )
|
156 |
-
),
|
157 |
-
array(
|
158 |
-
'delete_on_deactivate',
|
159 |
-
'',
|
160 |
-
'N',
|
161 |
-
'checkbox',
|
162 |
-
_wpsf__( 'Delete Plugin Settings' ),
|
163 |
-
_wpsf__( 'Delete All Plugin Settings Upon Plugin Deactivation' ),
|
164 |
-
_wpsf__( 'Careful: Removes all plugin options when you deactivate the plugin' )
|
165 |
-
)
|
166 |
-
)
|
167 |
-
);
|
168 |
-
|
169 |
-
$aEmail = array(
|
170 |
-
'section_title' => _wpsf__( 'Email Options' ),
|
171 |
-
'section_options' => array(
|
172 |
-
array(
|
173 |
-
'block_send_email_address',
|
174 |
-
'',
|
175 |
-
'',
|
176 |
-
'email',
|
177 |
-
_wpsf__( 'Report Email' ),
|
178 |
-
_wpsf__( 'Where to send email reports' ),
|
179 |
-
_wpsf__( 'If this is empty, it will default to the blog admin email address' )
|
180 |
-
),
|
181 |
-
array(
|
182 |
-
'send_email_throttle_limit',
|
183 |
-
'',
|
184 |
-
'10',
|
185 |
-
'integer',
|
186 |
-
_wpsf__( 'Email Throttle Limit' ),
|
187 |
-
_wpsf__( 'Limit Emails Per Second' ),
|
188 |
-
_wpsf__( 'You throttle emails sent by this plugin by limiting the number of emails sent every second. This is useful in case you get hit by a bot attack. Zero (0) turns this off. Suggested: 10' )
|
189 |
)
|
190 |
)
|
191 |
);
|
192 |
|
193 |
$this->m_aOptions = array(
|
194 |
$aGeneral,
|
195 |
-
$
|
196 |
);
|
197 |
if ( isset( $aAccessKey ) ) {
|
198 |
array_unshift( $this->m_aOptions, $aAccessKey );
|
@@ -214,20 +197,13 @@ class ICWP_OptionsHandler_Wpsf extends ICWP_OptionsHandler_Base_WPSF {
|
|
214 |
if ( empty( $sAccessKey ) ) {
|
215 |
$this->setOpt( 'enable_admin_access_restriction', 'N' );
|
216 |
}
|
217 |
-
|
218 |
-
$sEmail = $this->getOpt( 'block_send_email_address');
|
219 |
-
if ( empty( $sEmail ) || !is_email( $sEmail ) ) {
|
220 |
-
$sEmail = get_option('admin_email');
|
221 |
-
}
|
222 |
-
if ( is_email( $sEmail ) ) {
|
223 |
-
$this->setOpt( 'block_send_email_address', $sEmail );
|
224 |
-
}
|
225 |
|
226 |
-
$
|
227 |
-
|
228 |
-
|
|
|
|
|
229 |
}
|
230 |
-
$this->setOpt( 'send_email_throttle_limit', $sLimit );
|
231 |
}
|
232 |
|
233 |
protected function updateHandler() {
|
@@ -256,13 +232,12 @@ class ICWP_OptionsHandler_Wpsf extends ICWP_OptionsHandler_Base_WPSF {
|
|
256 |
$fCanDiskWrite = $this->getOpt( 'capability_can_disk_write' );
|
257 |
|
258 |
if ( $fCanDiskWrite === false || $fCanRemoteGet === false ) {
|
259 |
-
|
260 |
-
$oWpFilesystem = new ICWP_WpFilesystem_WPSF();
|
261 |
|
262 |
-
$fCanRemoteGet = $
|
263 |
$this->setOpt( 'capability_can_remote_get', $fCanRemoteGet? 'Y' : 'N' );
|
264 |
|
265 |
-
$fCanDiskWrite = $
|
266 |
$this->setOpt( 'capability_can_disk_write', $fCanDiskWrite? 'Y' : 'N' );
|
267 |
}
|
268 |
}// '1.8.2', '<='
|
1 |
<?php
|
2 |
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
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;
|
27 |
public function __construct( $insPrefix, $insVersion ) {
|
28 |
parent::__construct( $insPrefix, self::StoreName, $insVersion );
|
29 |
}
|
|
|
|
|
30 |
|
31 |
+
/**
|
32 |
+
* @return bool|void
|
33 |
+
*/
|
34 |
+
public function defineOptions() {
|
|
|
|
|
|
|
|
|
|
|
35 |
|
36 |
$aNonUiOptions = array(
|
37 |
+
'installation_time',
|
38 |
'secret_key',
|
39 |
'feedback_admin_notice',
|
40 |
'update_success_tracker',
|
41 |
'capability_can_disk_write',
|
42 |
+
'capability_can_remote_get',
|
43 |
+
'enable_firewall',
|
44 |
+
'enable_login_protect',
|
45 |
+
'enable_comments_filter',
|
46 |
+
'enable_lockdown',
|
47 |
+
'enable_autoupdates'
|
48 |
);
|
49 |
$this->mergeNonUiOptions( $aNonUiOptions );
|
50 |
|
60 |
'checkbox',
|
61 |
_wpsf__( 'Enable Access Key' ),
|
62 |
_wpsf__( 'Enforce Admin Access Restriction' ),
|
63 |
+
_wpsf__( 'Enable this with great care and consideration. When this Access Key option is enabled, you must specify a key below and use it to gain access to this plugin.' ),
|
64 |
+
'<a href="http://icwp.io/40" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
65 |
+
.' | <a href="http://icwp.io/wpsf02" target="_blank">'._wpsf__( 'blog' ).'</a>'
|
66 |
),
|
67 |
array(
|
68 |
'admin_access_timeout',
|
72 |
_wpsf__( 'Access Key Timeout' ),
|
73 |
_wpsf__( 'Specify A Timeout For Plugin Admin Access' ),
|
74 |
_wpsf__( 'This will automatically expire your WordPress Simple Firewall session. Does not apply until you enter the access key again. Default: 30 minutes.' ),
|
75 |
+
'<a href="http://icwp.io/41" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
76 |
),
|
77 |
array(
|
78 |
'admin_access_key',
|
82 |
_wpsf__( 'Admin Access Key' ),
|
83 |
_wpsf__( 'Specify Your Plugin Access Key' ),
|
84 |
_wpsf__( 'If you forget this, you could potentially lock yourself out from using this plugin.' )
|
85 |
+
.' <strong>'._wpsf__( 'Leave it blank to not update it' ).'</strong>',
|
86 |
+
'<a href="http://icwp.io/42" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
87 |
)
|
88 |
)
|
89 |
);
|
91 |
|
92 |
$aGeneral = array(
|
93 |
'section_title' => _wpsf__( 'General Plugin Options' ),
|
94 |
+
'section_options' => array(
|
95 |
+
array(
|
96 |
+
'enable_upgrade_admin_notice',
|
97 |
+
'',
|
98 |
+
'Y',
|
99 |
+
'checkbox',
|
100 |
+
_wpsf__( 'Plugin Notices' ),
|
101 |
+
_wpsf__( 'Display Notices For Updates' ),
|
102 |
+
_wpsf__( 'Disable this option to hide certain plugin admin notices about available updates and post-update notices' )
|
103 |
+
),
|
104 |
+
array(
|
105 |
+
'delete_on_deactivate',
|
106 |
+
'',
|
107 |
+
'N',
|
108 |
+
'checkbox',
|
109 |
+
_wpsf__( 'Delete Plugin Settings' ),
|
110 |
+
_wpsf__( 'Delete All Plugin Settings Upon Plugin Deactivation' ),
|
111 |
+
_wpsf__( 'Careful: Removes all plugin options when you deactivate the plugin' )
|
112 |
+
)
|
113 |
+
)
|
114 |
+
);
|
115 |
+
|
116 |
+
$aGlobal = array(
|
117 |
+
'section_title' => _wpsf__( 'Global Plugin Features' ),
|
118 |
'section_options' => array(
|
119 |
array(
|
120 |
'enable_firewall',
|
127 |
array(
|
128 |
'enable_login_protect',
|
129 |
'',
|
130 |
+
'N',
|
131 |
'checkbox',
|
132 |
_wpsf__( 'Enable Login Protect' ),
|
133 |
_wpsf__( 'Enable (or Disable) The Login Protection Feature' ),
|
136 |
array(
|
137 |
'enable_comments_filter',
|
138 |
'',
|
139 |
+
'N',
|
140 |
'checkbox',
|
141 |
_wpsf__( 'Enable Comments Filter' ),
|
142 |
_wpsf__( 'Enable (or Disable) The Comments Filter Feature' ),
|
143 |
_wpsf__( 'Regardless of any other settings, this option will turn off the Comments Filter feature, or enable your selected Comments Filter options' )
|
144 |
),
|
145 |
+
// array(
|
146 |
+
// 'enable_privacy_protect',
|
147 |
+
// '',
|
148 |
+
// 'N',
|
149 |
+
// 'checkbox',
|
150 |
+
// sprintf( _wpsf__( 'Enable %s' ), _wpsf__('Privacy Protection') ),
|
151 |
+
// sprintf( _wpsf__( 'Enable (or Disable) The %s Feature' ), _wpsf__('Privacy Protection') ),
|
152 |
+
// _wpsf__( 'Regardless of any other settings, this option will turn off the Privacy Protection feature, or enable your selected Privacy Protection options' ),
|
153 |
+
// '<a href="http://icwp.io/3y" target="_blank">'._wpsf__( 'more info' ).'</a>'
|
154 |
+
// ),
|
155 |
array(
|
156 |
'enable_lockdown',
|
157 |
'',
|
164 |
array(
|
165 |
'enable_autoupdates',
|
166 |
'',
|
167 |
+
'Y',
|
168 |
'checkbox',
|
169 |
_wpsf__( 'Enable Auto Updates' ),
|
170 |
_wpsf__( 'Enable (or Disable) The Auto Updates Feature' ),
|
171 |
_wpsf__( 'Regardless of any other settings, this option will turn off the Auto Updates feature, or enable your selected Auto Updates options' )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
172 |
)
|
173 |
)
|
174 |
);
|
175 |
|
176 |
$this->m_aOptions = array(
|
177 |
$aGeneral,
|
178 |
+
// $aGlobal
|
179 |
);
|
180 |
if ( isset( $aAccessKey ) ) {
|
181 |
array_unshift( $this->m_aOptions, $aAccessKey );
|
197 |
if ( empty( $sAccessKey ) ) {
|
198 |
$this->setOpt( 'enable_admin_access_restriction', 'N' );
|
199 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
200 |
|
201 |
+
$this->setOpt( 'enable_logging', 'Y' );
|
202 |
+
|
203 |
+
$nInstalledAt = $this->getOpt( 'installation_time' );
|
204 |
+
if ( empty($nInstalledAt) || $nInstalledAt <= 0 ) {
|
205 |
+
$this->setOpt( 'installation_time', time() );
|
206 |
}
|
|
|
207 |
}
|
208 |
|
209 |
protected function updateHandler() {
|
232 |
$fCanDiskWrite = $this->getOpt( 'capability_can_disk_write' );
|
233 |
|
234 |
if ( $fCanDiskWrite === false || $fCanRemoteGet === false ) {
|
235 |
+
$oWpFs = $this->loadFileSystemProcessor();
|
|
|
236 |
|
237 |
+
$fCanRemoteGet = $oWpFs->getCanWpRemoteGet();
|
238 |
$this->setOpt( 'capability_can_remote_get', $fCanRemoteGet? 'Y' : 'N' );
|
239 |
|
240 |
+
$fCanDiskWrite = $oWpFs->getCanDiskWrite();
|
241 |
$this->setOpt( 'capability_can_disk_write', $fCanDiskWrite? 'Y' : 'N' );
|
242 |
}
|
243 |
}// '1.8.2', '<='
|
src/icwp-plugins-base.php
DELETED
@@ -1,692 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
if ( !defined('ICWP_DS') ) {
|
4 |
-
define( 'ICWP_DS', DIRECTORY_SEPARATOR );
|
5 |
-
}
|
6 |
-
|
7 |
-
require_once( dirname(__FILE__).'/icwp-wpfunctions.php' );
|
8 |
-
|
9 |
-
if ( !class_exists('ICWP_WPSF_Base_Plugin') ):
|
10 |
-
|
11 |
-
class ICWP_WPSF_Base_Plugin {
|
12 |
-
|
13 |
-
static public $VERSION;
|
14 |
-
|
15 |
-
static public $PLUGIN_HUMAN_NAME;
|
16 |
-
static public $PLUGIN_NAME;
|
17 |
-
static public $PLUGIN_PATH;
|
18 |
-
static public $PLUGIN_FILE;
|
19 |
-
static public $PLUGIN_DIR;
|
20 |
-
static public $PLUGIN_URL;
|
21 |
-
static public $PLUGIN_BASENAME;
|
22 |
-
static public $OPTION_PREFIX;
|
23 |
-
|
24 |
-
const ParentTitle = 'iControlWP Plugins';
|
25 |
-
const ParentName = 'Simple Firewall';
|
26 |
-
const ParentPermissions = 'manage_options';
|
27 |
-
const ParentMenuId = 'icwp';
|
28 |
-
const VariablePrefix = 'icwp';
|
29 |
-
const BaseOptionPrefix = 'icwp_';
|
30 |
-
|
31 |
-
const ViewExt = '.php';
|
32 |
-
const ViewDir = 'views';
|
33 |
-
|
34 |
-
/**
|
35 |
-
* @var boolean
|
36 |
-
*/
|
37 |
-
protected $m_fNetworkAdminOnly = false;
|
38 |
-
/**
|
39 |
-
* @var boolean
|
40 |
-
*/
|
41 |
-
protected $m_fIsMultisite;
|
42 |
-
|
43 |
-
protected $m_aPluginMenu;
|
44 |
-
|
45 |
-
protected $m_aAllPluginOptions;
|
46 |
-
|
47 |
-
protected $m_sParentMenuIdSuffix;
|
48 |
-
|
49 |
-
protected $m_fShowMarketing = '';
|
50 |
-
|
51 |
-
protected $m_fDoAutoUpdateCheck = false;
|
52 |
-
|
53 |
-
protected $m_fAutoPluginUpgrade = false;
|
54 |
-
|
55 |
-
/**
|
56 |
-
* @var ICWP_WpFunctions_WPSF
|
57 |
-
*/
|
58 |
-
protected $m_oWpFunctions;
|
59 |
-
|
60 |
-
static protected $m_aFailedUpdateOptions;
|
61 |
-
|
62 |
-
public function __construct() {
|
63 |
-
|
64 |
-
$this->m_fIsMultisite = function_exists( 'is_multisite' ) && is_multisite();
|
65 |
-
|
66 |
-
add_action( 'plugins_loaded', array( $this, 'onWpPluginsLoaded' ) );
|
67 |
-
add_action( 'init', array( $this, 'onWpInit' ), 0 );
|
68 |
-
if ( $this->isValidAdminArea() ) {
|
69 |
-
add_action( 'admin_init', array( $this, 'onWpAdminInit' ) );
|
70 |
-
add_action( 'admin_notices', array( $this, 'onWpAdminNotices' ) );
|
71 |
-
add_action( 'admin_menu', array( $this, 'onWpAdminMenu' ) );
|
72 |
-
add_action( 'network_admin_menu', array( $this, 'onWpNetworkAdminMenu' ) );
|
73 |
-
// add_action( 'plugin_action_links', array( $this, 'onWpPluginActionLinks' ), 10, 4 );
|
74 |
-
}
|
75 |
-
add_action( 'shutdown', array( $this, 'onWpShutdown' ) );
|
76 |
-
|
77 |
-
/**
|
78 |
-
* We make the assumption that all settings updates are successful until told otherwise
|
79 |
-
* by an actual failing update_option call.
|
80 |
-
*/
|
81 |
-
self::$m_aFailedUpdateOptions = array();
|
82 |
-
$this->m_sParentMenuIdSuffix = 'base';
|
83 |
-
}
|
84 |
-
|
85 |
-
protected function isValidAdminArea() {
|
86 |
-
if ( !$this->m_fIsMultisite && is_admin() ) {
|
87 |
-
return true;
|
88 |
-
}
|
89 |
-
else if ( $this->m_fNetworkAdminOnly && $this->m_fIsMultisite && is_network_admin() ) {
|
90 |
-
return true;
|
91 |
-
}
|
92 |
-
return false;
|
93 |
-
}
|
94 |
-
|
95 |
-
/**
|
96 |
-
* @return boolean - true if plugin update is available
|
97 |
-
*/
|
98 |
-
public function doPluginUpdateCheck() {
|
99 |
-
$this->loadWpFunctions();
|
100 |
-
return $this->m_oWpFunctions->getIsPluginUpdateAvailable( self::$PLUGIN_FILE );
|
101 |
-
}
|
102 |
-
|
103 |
-
protected function getFullParentMenuId() {
|
104 |
-
return self::ParentMenuId .'-'. $this->m_sParentMenuIdSuffix;
|
105 |
-
}//getFullParentMenuId
|
106 |
-
|
107 |
-
protected function display( $insView, $inaData = array() ) {
|
108 |
-
$sFile = dirname(__FILE__).ICWP_DS.'..'.ICWP_DS.self::ViewDir.ICWP_DS.$insView.self::ViewExt;
|
109 |
-
|
110 |
-
if ( !is_file( $sFile ) ) {
|
111 |
-
echo "View not found: ".$sFile;
|
112 |
-
return false;
|
113 |
-
}
|
114 |
-
|
115 |
-
if ( count( $inaData ) > 0 ) {
|
116 |
-
extract( $inaData, EXTR_PREFIX_ALL, self::VariablePrefix );
|
117 |
-
}
|
118 |
-
|
119 |
-
ob_start();
|
120 |
-
include( $sFile );
|
121 |
-
$sContents = ob_get_contents();
|
122 |
-
ob_end_clean();
|
123 |
-
|
124 |
-
echo $sContents;
|
125 |
-
return true;
|
126 |
-
}
|
127 |
-
|
128 |
-
protected function getImageUrl( $insImage ) {
|
129 |
-
return self::$PLUGIN_URL.'resources/images/'.$insImage;
|
130 |
-
}
|
131 |
-
protected function getCssUrl( $insCss ) {
|
132 |
-
return self::$PLUGIN_URL.'resources/css/'.$insCss;
|
133 |
-
}
|
134 |
-
protected function getJsUrl( $insJs ) {
|
135 |
-
return self::$PLUGIN_URL.'resources/js/'.$insJs;
|
136 |
-
}
|
137 |
-
|
138 |
-
protected function getSubmenuPageTitle( $insTitle ) {
|
139 |
-
return self::ParentTitle.' - '.$insTitle;
|
140 |
-
}
|
141 |
-
protected function getSubmenuId( $insId = '' ) {
|
142 |
-
$sExtension = empty($insId)? '' : '-'.$insId;
|
143 |
-
return $this->getFullParentMenuId().$sExtension;
|
144 |
-
}
|
145 |
-
|
146 |
-
public function onWpPluginsLoaded() {
|
147 |
-
|
148 |
-
if ( is_admin() ) {
|
149 |
-
//Handle plugin upgrades
|
150 |
-
$this->handlePluginUpgrade();
|
151 |
-
}
|
152 |
-
|
153 |
-
if ( $this->isIcwpPluginAdminPage() ) {
|
154 |
-
//Handle form submit
|
155 |
-
if ( $this->isPluginFormSubmit() && $this->handlePluginFormSubmit() ) {
|
156 |
-
$this->m_oWpsfOptions->setOpt( 'feedback_admin_notice', 'Updating Settings <strong>Succeeded</strong>.' );
|
157 |
-
}
|
158 |
-
}
|
159 |
-
}
|
160 |
-
|
161 |
-
public function onWpInit() { }
|
162 |
-
|
163 |
-
public function onWpAdminInit() {
|
164 |
-
|
165 |
-
//Do Plugin-Specific Admin Work
|
166 |
-
if ( $this->isIcwpPluginAdminPage() ) {
|
167 |
-
//Links up CSS styles for the plugin itself (set the admin bootstrap CSS as a dependency also)
|
168 |
-
$this->enqueuePluginAdminCss();
|
169 |
-
}
|
170 |
-
|
171 |
-
// Determine whether to show ads and marketing messages
|
172 |
-
// Currently this is when the site uses the iControlWP service and is linked
|
173 |
-
$this->isShowMarketing();
|
174 |
-
|
175 |
-
}//onWpAdminInit
|
176 |
-
|
177 |
-
public function onWpAdminMenu() {
|
178 |
-
if ( !$this->isValidAdminArea() ) {
|
179 |
-
return true;
|
180 |
-
}
|
181 |
-
$this->createMenu();
|
182 |
-
}
|
183 |
-
|
184 |
-
public function onWpNetworkAdminMenu() {
|
185 |
-
if ( !$this->isValidAdminArea() ) {
|
186 |
-
return true;
|
187 |
-
}
|
188 |
-
$this->createMenu();
|
189 |
-
}
|
190 |
-
|
191 |
-
protected function createMenu() {
|
192 |
-
|
193 |
-
$sFullParentMenuId = $this->getFullParentMenuId();
|
194 |
-
add_menu_page( self::ParentTitle, self::ParentName, self::ParentPermissions, $sFullParentMenuId, array( $this, 'onDisplayAll' ), $this->getImageUrl( 'icontrolwp_16x16.png' ) );
|
195 |
-
|
196 |
-
//Create and Add the submenu items
|
197 |
-
$this->createPluginSubMenuItems();
|
198 |
-
if ( !empty($this->m_aPluginMenu) ) {
|
199 |
-
foreach ( $this->m_aPluginMenu as $sMenuTitle => $aMenu ) {
|
200 |
-
list( $sMenuItemText, $sMenuItemId, $sMenuCallBack ) = $aMenu;
|
201 |
-
add_submenu_page( $sFullParentMenuId, $sMenuTitle, $sMenuItemText, self::ParentPermissions, $sMenuItemId, array( $this, $sMenuCallBack ) );
|
202 |
-
}
|
203 |
-
}
|
204 |
-
|
205 |
-
$this->fixSubmenu();
|
206 |
-
}
|
207 |
-
/**
|
208 |
-
* Displaying all views now goes through this central function and we work out
|
209 |
-
* what to display based on the name of current hook/filter being processed.
|
210 |
-
*/
|
211 |
-
public function onDisplayAll() {
|
212 |
-
$this->onDisplayMainMenu();
|
213 |
-
}
|
214 |
-
|
215 |
-
protected function createPluginSubMenuItems(){
|
216 |
-
/* Override to create array of sub-menu items
|
217 |
-
$this->m_aPluginMenu = array(
|
218 |
-
//Menu Page Title => Menu Item name, page ID (slug), callback function onLoad.
|
219 |
-
$this->getSubmenuPageTitle( 'Content by Country' ) => array( 'Content by Country', $this->getSubmenuId('main'), 'onDisplayCbcMain' ),
|
220 |
-
);
|
221 |
-
*/
|
222 |
-
}//createPluginSubMenuItems
|
223 |
-
|
224 |
-
protected function fixSubmenu() {
|
225 |
-
global $submenu;
|
226 |
-
$sFullParentMenuId = $this->getFullParentMenuId();
|
227 |
-
if ( isset( $submenu[$sFullParentMenuId] ) ) {
|
228 |
-
$submenu[$sFullParentMenuId][0][0] = 'Dashboard';
|
229 |
-
}
|
230 |
-
}
|
231 |
-
|
232 |
-
/**
|
233 |
-
* The callback function for the main admin menu index page
|
234 |
-
*/
|
235 |
-
public function onDisplayMainMenu() {
|
236 |
-
$aData = array(
|
237 |
-
'plugin_url' => self::$PLUGIN_URL,
|
238 |
-
'fShowAds' => $this->isShowMarketing()
|
239 |
-
);
|
240 |
-
$this->display( 'icwp_'.$this->m_sParentMenuIdSuffix.'_index', $aData );
|
241 |
-
}
|
242 |
-
|
243 |
-
protected function isShowMarketing() {
|
244 |
-
|
245 |
-
if ( $this->m_fShowMarketing == 'Y' ) {
|
246 |
-
return true;
|
247 |
-
}
|
248 |
-
elseif ( $this->m_fShowMarketing == 'N' ) {
|
249 |
-
return false;
|
250 |
-
}
|
251 |
-
|
252 |
-
$sServiceClassName = 'Worpit_Plugin';
|
253 |
-
$this->m_fShowMarketing = 'Y';
|
254 |
-
if ( class_exists( 'Worpit_Plugin' ) ) {
|
255 |
-
if ( method_exists( 'Worpit_Plugin', 'IsLinked' ) ) {
|
256 |
-
$this->m_fShowMarketing = Worpit_Plugin::IsLinked() ? 'N' : 'Y';
|
257 |
-
}
|
258 |
-
elseif ( function_exists( 'get_option' )
|
259 |
-
&& get_option( Worpit_Plugin::$VariablePrefix.'assigned' ) == 'Y'
|
260 |
-
&& get_option( Worpit_Plugin::$VariablePrefix.'assigned_to' ) != '' ) {
|
261 |
-
|
262 |
-
$this->m_fShowMarketing = 'N';
|
263 |
-
}
|
264 |
-
}
|
265 |
-
return $this->m_fShowMarketing === 'N' ? false : true;
|
266 |
-
}
|
267 |
-
|
268 |
-
/**
|
269 |
-
* The Action Links in the main plugins page. Defaults to link to the main Dashboard page
|
270 |
-
*
|
271 |
-
* @param $inaLinks
|
272 |
-
* @param $insFile
|
273 |
-
*/
|
274 |
-
public function onWpPluginActionLinks( $inaLinks, $insFile ) {
|
275 |
-
if ( $insFile == self::$PLUGIN_BASENAME ) {
|
276 |
-
$sSettingsLink = '<a href="'.admin_url( "admin.php" ).'?page='.$this->getFullParentMenuId().'">' . _wpsf__( 'Settings', 'worpit' ) . '</a>';
|
277 |
-
array_unshift( $inaLinks, $sSettingsLink );
|
278 |
-
}
|
279 |
-
return $inaLinks;
|
280 |
-
}
|
281 |
-
|
282 |
-
/**
|
283 |
-
* Override this method to handle all the admin notices
|
284 |
-
*/
|
285 |
-
public function onWpAdminNotices() {
|
286 |
-
// Do we have admin priviledges?
|
287 |
-
if ( !current_user_can( 'manage_options' ) ) {
|
288 |
-
return;
|
289 |
-
}
|
290 |
-
|
291 |
-
if ( $this->m_fDoAutoUpdateCheck ) {
|
292 |
-
$this->adminNoticePluginUpgradeAvailable();
|
293 |
-
}
|
294 |
-
}
|
295 |
-
|
296 |
-
/**
|
297 |
-
* Hooked to 'shutdown'
|
298 |
-
*/
|
299 |
-
public function onWpShutdown() { }
|
300 |
-
|
301 |
-
/**
|
302 |
-
* This is called from within onWpAdminInit. Use this solely to manage upgrades of the plugin
|
303 |
-
*/
|
304 |
-
protected function handlePluginUpgrade() {
|
305 |
-
|
306 |
-
if ( !is_admin() || !current_user_can( 'manage_options' ) ) {
|
307 |
-
return;
|
308 |
-
}
|
309 |
-
|
310 |
-
$this->flushCaches();
|
311 |
-
|
312 |
-
if ( $this->m_fAutoPluginUpgrade ) {
|
313 |
-
$this->loadWpFunctions();
|
314 |
-
$this->m_oWpFunctions->doPluginUpgrade( self::$PLUGIN_FILE );
|
315 |
-
}
|
316 |
-
}
|
317 |
-
|
318 |
-
protected function isPluginFormSubmit() { }
|
319 |
-
|
320 |
-
protected function handlePluginFormSubmit() { }
|
321 |
-
|
322 |
-
protected function adminNoticePluginUpgradeAvailable() {
|
323 |
-
|
324 |
-
// Don't show on the update page.
|
325 |
-
if ( isset( $GLOBALS['pagenow'] ) && $GLOBALS['pagenow'] == 'update.php' ) {
|
326 |
-
return;
|
327 |
-
}
|
328 |
-
|
329 |
-
if ( !isset( self::$PLUGIN_FILE ) ) {
|
330 |
-
self::$PLUGIN_FILE = plugin_basename(__FILE__);
|
331 |
-
}
|
332 |
-
if ( !$this->doPluginUpdateCheck() ) {
|
333 |
-
return;
|
334 |
-
}
|
335 |
-
$sNotice = $this->getAdminNoticePluginUpgradeAvailable();
|
336 |
-
$this->getAdminNotice( $sNotice, 'updated', true );
|
337 |
-
}
|
338 |
-
|
339 |
-
/**
|
340 |
-
* Override this to change the message for the particular plugin upgrade.
|
341 |
-
*/
|
342 |
-
protected function getAdminNoticePluginUpgradeAvailable() {
|
343 |
-
$sUpgradeLink = $this->m_oWpFunctions->getPluginUpgradeLink( self::$PLUGIN_FILE );
|
344 |
-
$sNotice = '<p>There is an update available for the %s plugin. <a href="%s">Click to update immediately</a>.</p>';
|
345 |
-
$sNotice = sprintf( $sNotice, self::$PLUGIN_HUMAN_NAME, $sUpgradeLink );
|
346 |
-
return $sNotice;
|
347 |
-
}
|
348 |
-
|
349 |
-
protected function enqueuePluginAdminCss() {
|
350 |
-
$iRand = rand();
|
351 |
-
wp_register_style( 'worpit_plugin_css'.$iRand, $this->getCssUrl('icontrolwp-plugin.css'), array('worpit_bootstrap_wpadmin_css_fixes'), self::$VERSION );
|
352 |
-
wp_enqueue_style( 'worpit_plugin_css'.$iRand );
|
353 |
-
}//enqueuePluginAdminCss
|
354 |
-
|
355 |
-
/**
|
356 |
-
* Provides the basic HTML template for printing a WordPress Admin Notices
|
357 |
-
*
|
358 |
-
* @param $insNotice - The message to be displayed.
|
359 |
-
* @param $insMessageClass - either error or updated
|
360 |
-
* @param $infPrint - if true, will echo. false will return the string
|
361 |
-
* @return boolean|string
|
362 |
-
*/
|
363 |
-
protected function getAdminNotice( $insNotice = '', $insMessageClass = 'updated', $infPrint = false ) {
|
364 |
-
|
365 |
-
$sFullNotice = '
|
366 |
-
<div id="message" class="'.$insMessageClass.'">
|
367 |
-
<style>
|
368 |
-
#message form { margin: 0px; }
|
369 |
-
</style>
|
370 |
-
'.$insNotice.'
|
371 |
-
</div>
|
372 |
-
';
|
373 |
-
|
374 |
-
if ( $infPrint ) {
|
375 |
-
echo $sFullNotice;
|
376 |
-
return true;
|
377 |
-
} else {
|
378 |
-
return $sFullNotice;
|
379 |
-
}
|
380 |
-
}
|
381 |
-
|
382 |
-
protected function redirect( $insUrl, $innTimeout = 1 ) {
|
383 |
-
echo '
|
384 |
-
<script type="text/javascript">
|
385 |
-
function redirect() {
|
386 |
-
window.location = "'.$insUrl.'";
|
387 |
-
}
|
388 |
-
var oTimer = setTimeout( "redirect()", "'.($innTimeout * 1000).'" );
|
389 |
-
</script>';
|
390 |
-
}
|
391 |
-
|
392 |
-
/**
|
393 |
-
* A little helper function that populates all the plugin options arrays with DB values
|
394 |
-
*/
|
395 |
-
protected function readyAllPluginOptions() {
|
396 |
-
// $this->populateAllPluginOptions();
|
397 |
-
}
|
398 |
-
|
399 |
-
/**
|
400 |
-
* Reads the current value for ALL plugin options from the WP options db.
|
401 |
-
*
|
402 |
-
* Assumes the standard plugin options array structure. Over-ride to change.
|
403 |
-
*
|
404 |
-
* NOT automatically executed on any hooks.
|
405 |
-
*/
|
406 |
-
protected function populateAllPluginOptions() {
|
407 |
-
|
408 |
-
if ( empty($this->m_aAllPluginOptions) ) {
|
409 |
-
return false;
|
410 |
-
}
|
411 |
-
self::PopulatePluginOptions( $this->m_aAllPluginOptions );
|
412 |
-
|
413 |
-
}//populateAllPluginOptions
|
414 |
-
|
415 |
-
public static function PopulatePluginOptions( &$inaAllOptions ) {
|
416 |
-
|
417 |
-
if ( empty($inaAllOptions) ) {
|
418 |
-
return false;
|
419 |
-
}
|
420 |
-
foreach ( $inaAllOptions as &$aOptionsSection ) {
|
421 |
-
self::PopulatePluginOptionsSection($aOptionsSection);
|
422 |
-
}
|
423 |
-
}
|
424 |
-
|
425 |
-
public static function PopulatePluginOptionsSection( &$inaOptionsSection ) {
|
426 |
-
|
427 |
-
if ( empty($inaOptionsSection) ) {
|
428 |
-
return false;
|
429 |
-
}
|
430 |
-
foreach ( $inaOptionsSection['section_options'] as &$aOptionParams ) {
|
431 |
-
|
432 |
-
list( $sOptionKey, $sOptionCurrent, $sOptionDefault, $sOptionType ) = $aOptionParams;
|
433 |
-
$mCurrentOptionVal = self::getOption( $sOptionKey );
|
434 |
-
if ( $sOptionType == 'ip_addresses' ) {
|
435 |
-
if ( !empty( $mCurrentOptionVal ) ) {
|
436 |
-
$mCurrentOptionVal = implode( "\n", self::ConvertIpListForDisplay( $mCurrentOptionVal ) );
|
437 |
-
}
|
438 |
-
else {
|
439 |
-
$mCurrentOptionVal = '';
|
440 |
-
}
|
441 |
-
}
|
442 |
-
else if ( $sOptionType == 'comma_separated_lists' ) {
|
443 |
-
if ( !empty( $mCurrentOptionVal ) ) {
|
444 |
-
$aNewValues = array();
|
445 |
-
foreach( $mCurrentOptionVal as $sPage => $aParams ) {
|
446 |
-
$aNewValues[] = $sPage.', '. implode( ", ", $aParams );
|
447 |
-
}
|
448 |
-
$mCurrentOptionVal = implode( "\n", $aNewValues );
|
449 |
-
}
|
450 |
-
else {
|
451 |
-
$mCurrentOptionVal = '';
|
452 |
-
}
|
453 |
-
}
|
454 |
-
$aOptionParams[1] = ($mCurrentOptionVal == '' )? $sOptionDefault : $mCurrentOptionVal;
|
455 |
-
}
|
456 |
-
}
|
457 |
-
|
458 |
-
public static function ConvertIpListForDisplay( $inaIpList = array() ) {
|
459 |
-
|
460 |
-
$aDisplay = array();
|
461 |
-
if ( empty( $inaIpList ) || empty( $inaIpList['ips'] ) ) {
|
462 |
-
return $aDisplay;
|
463 |
-
}
|
464 |
-
|
465 |
-
foreach( $inaIpList['ips'] as $sAddress ) {
|
466 |
-
|
467 |
-
$mPos = strpos( $sAddress, '-' );
|
468 |
-
|
469 |
-
if ( $mPos === false || $mPos === 0 ) { //plain IP address
|
470 |
-
$sDisplayText = long2ip( $sAddress );
|
471 |
-
}
|
472 |
-
else {
|
473 |
-
list($nStart, $nEnd) = explode( '-', $sAddress );
|
474 |
-
$sDisplayText = long2ip( $nStart ) .'-'. long2ip( $nEnd );
|
475 |
-
}
|
476 |
-
$sLabel = $inaIpList['meta'][ md5($sAddress) ];
|
477 |
-
$sLabel = trim( $sLabel, '()' );
|
478 |
-
$aDisplay[] = $sDisplayText . ' ('.$sLabel.')';
|
479 |
-
}
|
480 |
-
return $aDisplay;
|
481 |
-
}
|
482 |
-
|
483 |
-
/**
|
484 |
-
* $sAllOptionsInput is a comma separated list of all the input keys to be processed from the $_POST
|
485 |
-
*/
|
486 |
-
protected function updatePluginOptionsFromSubmit( $sAllOptionsInput ) {
|
487 |
-
|
488 |
-
if ( empty($sAllOptionsInput) ) {
|
489 |
-
return;
|
490 |
-
}
|
491 |
-
|
492 |
-
$aAllInputOptions = explode( ',', $sAllOptionsInput);
|
493 |
-
foreach ( $aAllInputOptions as $sInputKey ) {
|
494 |
-
$aInput = explode( ':', $sInputKey );
|
495 |
-
list( $sOptionType, $sOptionKey ) = $aInput;
|
496 |
-
|
497 |
-
$sOptionValue = $this->getAnswerFromPost( $sOptionKey );
|
498 |
-
if ( is_null($sOptionValue) ) {
|
499 |
-
|
500 |
-
if ( $sOptionType == 'text' || $sOptionType == 'email' ) { //if it was a text box, and it's null, don't update anything
|
501 |
-
continue;
|
502 |
-
} else if ( $sOptionType == 'checkbox' ) { //if it was a checkbox, and it's null, it means 'N'
|
503 |
-
$sOptionValue = 'N';
|
504 |
-
} else if ( $sOptionType == 'integer' ) { //if it was a integer, and it's null, it means '0'
|
505 |
-
$sOptionValue = 0;
|
506 |
-
}
|
507 |
-
}
|
508 |
-
else { //handle any pre-processing we need to.
|
509 |
-
|
510 |
-
if ( $sOptionType == 'integer' ) {
|
511 |
-
$sOptionValue = intval( $sOptionValue );
|
512 |
-
}
|
513 |
-
else if ( $sOptionType == 'ip_addresses' ) { //ip addresses are textareas, where each is separated by newline
|
514 |
-
|
515 |
-
if ( !class_exists('ICWP_DataProcessor') ) {
|
516 |
-
require_once ( dirname(__FILE__).'/icwp-data-processor.php' );
|
517 |
-
}
|
518 |
-
$oProcessor = new ICWP_DataProcessor();
|
519 |
-
$sOptionValue = $oProcessor->ExtractIpAddresses( $sOptionValue );
|
520 |
-
}
|
521 |
-
else if ( $sOptionType == 'email' && function_exists( 'is_email' ) && !is_email( $sOptionValue ) ) {
|
522 |
-
$sOptionValue = '';
|
523 |
-
}
|
524 |
-
else if ( $sOptionType == 'comma_separated_lists' ) {
|
525 |
-
if ( !class_exists('ICWP_DataProcessor') ) {
|
526 |
-
require_once ( dirname(__FILE__).'/icwp-data-processor.php' );
|
527 |
-
}
|
528 |
-
$oProcessor = new ICWP_DataProcessor();
|
529 |
-
$sOptionValue = $oProcessor->ExtractCommaSeparatedList( $sOptionValue );
|
530 |
-
}
|
531 |
-
}
|
532 |
-
$this->updateOption( $sOptionKey, $sOptionValue );
|
533 |
-
}
|
534 |
-
|
535 |
-
return true;
|
536 |
-
}//updatePluginOptionsFromSubmit
|
537 |
-
|
538 |
-
protected function collateAllFormInputsForAllOptions($aAllOptions, $sInputSeparator = ',') {
|
539 |
-
|
540 |
-
if ( empty($aAllOptions) ) {
|
541 |
-
return '';
|
542 |
-
}
|
543 |
-
$iCount = 0;
|
544 |
-
foreach ( $aAllOptions as $aOptionsSection ) {
|
545 |
-
|
546 |
-
if ( $iCount == 0 ) {
|
547 |
-
$sCollated = $this->collateAllFormInputsForOptionsSection($aOptionsSection, $sInputSeparator);
|
548 |
-
} else {
|
549 |
-
$sCollated .= $sInputSeparator.$this->collateAllFormInputsForOptionsSection($aOptionsSection, $sInputSeparator);
|
550 |
-
}
|
551 |
-
$iCount++;
|
552 |
-
}
|
553 |
-
return $sCollated;
|
554 |
-
|
555 |
-
}//collateAllFormInputsAllOptions
|
556 |
-
|
557 |
-
/**
|
558 |
-
* Returns a comma seperated list of all the options in a given options section.
|
559 |
-
*
|
560 |
-
* @param array $aOptionsSection
|
561 |
-
*/
|
562 |
-
protected function collateAllFormInputsForOptionsSection( $aOptionsSection, $sInputSeparator = ',' ) {
|
563 |
-
|
564 |
-
if ( empty($aOptionsSection) ) {
|
565 |
-
return '';
|
566 |
-
}
|
567 |
-
$iCount = 0;
|
568 |
-
foreach ( $aOptionsSection['section_options'] as $aOption ) {
|
569 |
-
|
570 |
-
list($sKey, $fill1, $fill2, $sType) = $aOption;
|
571 |
-
|
572 |
-
if ( $iCount == 0 ) {
|
573 |
-
$sCollated = $sType.':'.$sKey;
|
574 |
-
} else {
|
575 |
-
$sCollated .= $sInputSeparator.$sType.':'.$sKey;
|
576 |
-
}
|
577 |
-
$iCount++;
|
578 |
-
}
|
579 |
-
return $sCollated;
|
580 |
-
}
|
581 |
-
|
582 |
-
protected function isIcwpPluginAdminPage() {
|
583 |
-
|
584 |
-
$sSubPageNow = isset( $_GET['page'] )? $_GET['page']: '';
|
585 |
-
if ( is_admin() && !empty($sSubPageNow) && (strpos( $sSubPageNow, $this->getFullParentMenuId() ) === 0 )) { //admin area, and the 'page' begins with 'worpit'
|
586 |
-
return true;
|
587 |
-
}
|
588 |
-
|
589 |
-
return false;
|
590 |
-
}//isIcwpPluginAdminPage
|
591 |
-
|
592 |
-
protected function deleteAllPluginDbOptions() {
|
593 |
-
|
594 |
-
if ( !current_user_can( 'manage_options' ) ) {
|
595 |
-
return;
|
596 |
-
}
|
597 |
-
|
598 |
-
if ( empty($this->m_aAllPluginOptions) ) {
|
599 |
-
return;
|
600 |
-
}
|
601 |
-
|
602 |
-
foreach ( $this->m_aAllPluginOptions as $aOptionsSection ) {
|
603 |
-
foreach ( $aOptionsSection['section_options'] as $aOptionParams ) {
|
604 |
-
if ( isset( $aOptionParams[0] ) ) {
|
605 |
-
$this->deleteOption($aOptionParams[0]);
|
606 |
-
}
|
607 |
-
}
|
608 |
-
}
|
609 |
-
|
610 |
-
}//deleteAllPluginDbOptions
|
611 |
-
|
612 |
-
protected function getAnswerFromPost( $insKey, $insPrefix = null ) {
|
613 |
-
if ( is_null( $insPrefix ) ) {
|
614 |
-
$insKey = self::getKey($insKey);
|
615 |
-
}
|
616 |
-
return ( isset( $_POST[$insKey] )? $_POST[$insKey]: null );
|
617 |
-
}
|
618 |
-
|
619 |
-
static public function getOption( $insKey, $insAddPrefix = '' ) {
|
620 |
-
return get_option( self::getKey($insKey) );
|
621 |
-
}
|
622 |
-
|
623 |
-
static public function addOption( $insKey, $insValue ) {
|
624 |
-
return add_option( self::getKey($insKey), $insValue );
|
625 |
-
}
|
626 |
-
|
627 |
-
static public function updateOption( $insKey, $insValue ) {
|
628 |
-
if ( !is_object( $insValue ) && self::getOption( $insKey ) == $insValue ) {
|
629 |
-
return true;
|
630 |
-
}
|
631 |
-
$fResult = update_option( self::getKey($insKey), $insValue );
|
632 |
-
if ( !$fResult ) {
|
633 |
-
self::$m_aFailedUpdateOptions[] = self::getKey($insKey);
|
634 |
-
}
|
635 |
-
}
|
636 |
-
|
637 |
-
static public function deleteOption( $insKey ) {
|
638 |
-
return delete_option( self::getKey($insKey) );
|
639 |
-
}
|
640 |
-
|
641 |
-
static public function getKey( $insKey ) {
|
642 |
-
return self::$OPTION_PREFIX.$insKey;
|
643 |
-
}
|
644 |
-
|
645 |
-
public function onWpActivatePlugin() { }
|
646 |
-
public function onWpDeactivatePlugin() { }
|
647 |
-
|
648 |
-
public function onWpUninstallPlugin() {
|
649 |
-
|
650 |
-
//Do we have admin priviledges?
|
651 |
-
if ( current_user_can( 'manage_options' ) ) {
|
652 |
-
$this->deleteAllPluginDbOptions();
|
653 |
-
}
|
654 |
-
}
|
655 |
-
|
656 |
-
protected function loadWpFunctions() {
|
657 |
-
if ( !isset( $this->m_oWpFunctions ) ) {
|
658 |
-
$this->m_oWpFunctions = new ICWP_WpFunctions_WPSF();
|
659 |
-
}
|
660 |
-
}
|
661 |
-
|
662 |
-
/**
|
663 |
-
* Takes an array, an array key, and a default value. If key isn't set, sets it to default.
|
664 |
-
*/
|
665 |
-
protected function def( &$aSrc, $insKey, $insValue = '' ) {
|
666 |
-
if ( !isset( $aSrc[$insKey] ) ) {
|
667 |
-
$aSrc[$insKey] = $insValue;
|
668 |
-
}
|
669 |
-
}
|
670 |
-
/**
|
671 |
-
* Takes an array, an array key and an element type. If value is empty, sets the html element
|
672 |
-
* string to empty string, otherwise forms a complete html element parameter.
|
673 |
-
*
|
674 |
-
* E.g. noEmptyElement( aSomeArray, sSomeArrayKey, "style" )
|
675 |
-
* will return String: style="aSomeArray[sSomeArrayKey]" or empty string.
|
676 |
-
*/
|
677 |
-
protected function noEmptyElement( &$inaArgs, $insAttrKey, $insElement = '' ) {
|
678 |
-
$sAttrValue = $inaArgs[$insAttrKey];
|
679 |
-
$insElement = ( $insElement == '' )? $insAttrKey : $insElement;
|
680 |
-
$inaArgs[$insAttrKey] = ( empty($sAttrValue) ) ? '' : ' '.$insElement.'="'.$sAttrValue.'"';
|
681 |
-
}
|
682 |
-
|
683 |
-
protected function flushCaches() {
|
684 |
-
if (function_exists('w3tc_pgcache_flush')) {
|
685 |
-
w3tc_pgcache_flush();
|
686 |
-
}
|
687 |
-
}
|
688 |
-
|
689 |
-
}
|
690 |
-
|
691 |
-
endif;
|
692 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/icwp-processor-autoupdates.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* Copyright (c)
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
@@ -17,65 +17,280 @@
|
|
17 |
|
18 |
require_once( dirname(__FILE__).'/icwp-base-processor.php' );
|
19 |
|
20 |
-
if ( !class_exists('
|
21 |
|
22 |
-
class
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
|
24 |
/**
|
25 |
-
* Resets the object values to be re-used anew
|
26 |
*/
|
27 |
-
public function
|
28 |
-
|
29 |
}
|
30 |
|
31 |
/**
|
32 |
*/
|
33 |
-
public function run() {
|
34 |
|
35 |
-
|
36 |
-
|
37 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
}
|
39 |
-
|
40 |
-
|
41 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
42 |
}
|
43 |
-
|
44 |
-
|
45 |
-
add_filter( '
|
46 |
}
|
47 |
|
48 |
-
|
49 |
-
add_filter( '
|
50 |
-
|
51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
|
53 |
-
|
54 |
-
|
|
|
55 |
|
56 |
-
if ( $
|
57 |
-
|
|
|
58 |
}
|
59 |
-
|
60 |
-
|
61 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
}
|
|
|
63 |
}
|
64 |
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
69 |
}
|
70 |
-
if ( $this->
|
|
|
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;
|
|
|
|
|
|
|
|
1 |
<?php
|
2 |
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
17 |
|
18 |
require_once( dirname(__FILE__).'/icwp-base-processor.php' );
|
19 |
|
20 |
+
if ( !class_exists('ICWP_AutoUpdatesProcessor_V4') ):
|
21 |
|
22 |
+
class ICWP_AutoUpdatesProcessor_V4 extends ICWP_BaseProcessor_V2 {
|
23 |
+
|
24 |
+
const Slug = 'autoupdates';
|
25 |
+
|
26 |
+
const FilterPriority = 1001;
|
27 |
+
|
28 |
+
protected $m_sPluginFile;
|
29 |
+
|
30 |
+
/**
|
31 |
+
* @var boolean
|
32 |
+
*/
|
33 |
+
protected $m_fDoForceRunAutoUpdates = false;
|
34 |
+
|
35 |
+
public function __construct( $insOptionPrefix = '' ) {
|
36 |
+
parent::__construct( $this->constructStorageKey( $insOptionPrefix, self::Slug ) );
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @param boolean $infDoForceRun
|
41 |
+
*/
|
42 |
+
public function setForceRunAutoUpdates( $infDoForceRun ) {
|
43 |
+
$this->m_fDoForceRunAutoUpdates = $infDoForceRun;
|
44 |
+
}
|
45 |
|
46 |
/**
|
|
|
47 |
*/
|
48 |
+
public function getForceRunAutoUpdates() {
|
49 |
+
return apply_filters( 'icwp_force_autoupdate', $this->m_fDoForceRunAutoUpdates );
|
50 |
}
|
51 |
|
52 |
/**
|
53 |
*/
|
54 |
+
public function run( $insPluginFile = '' ) {
|
55 |
|
56 |
+
$this->m_sPluginFile = $insPluginFile;
|
57 |
+
|
58 |
+
// When we force run we only want our filters.
|
59 |
+
if ( $this->getForceRunAutoUpdates() ) {
|
60 |
+
$aFilters = array(
|
61 |
+
'allow_minor_auto_core_updates',
|
62 |
+
'allow_major_auto_core_updates',
|
63 |
+
'auto_update_translation',
|
64 |
+
'auto_update_plugin',
|
65 |
+
'auto_update_theme',
|
66 |
+
'automatic_updates_is_vcs_checkout',
|
67 |
+
'automatic_updater_disabled'
|
68 |
+
);
|
69 |
+
foreach( $aFilters as $sFilter ) {
|
70 |
+
remove_all_filters( $sFilter );
|
71 |
+
}
|
72 |
}
|
73 |
+
|
74 |
+
add_filter( 'allow_minor_auto_core_updates', array( $this, 'autoupdate_core_minor' ), self::FilterPriority );
|
75 |
+
add_filter( 'allow_major_auto_core_updates', array( $this, 'autoupdate_core_major' ), self::FilterPriority );
|
76 |
+
|
77 |
+
add_filter( 'auto_update_translation', array( $this, 'autoupdate_translations' ), self::FilterPriority, 2 );
|
78 |
+
add_filter( 'auto_update_plugin', array( $this, 'autoupdate_plugins' ), self::FilterPriority, 2 );
|
79 |
+
add_filter( 'auto_update_theme', array( $this, 'autoupdate_themes' ), self::FilterPriority, 2 );
|
80 |
+
|
81 |
+
if ( $this->getIsOption('enable_autoupdate_ignore_vcs', 'Y') ) {
|
82 |
+
add_filter( 'automatic_updates_is_vcs_checkout', array( $this, 'disable_for_vcs' ), 10, 2 );
|
83 |
}
|
84 |
+
|
85 |
+
if ( $this->getIsOption('enable_autoupdate_disable_all', 'Y') ) {
|
86 |
+
add_filter( 'automatic_updater_disabled', '__return_true', self::FilterPriority );
|
87 |
}
|
88 |
|
89 |
+
add_filter( 'auto_core_update_send_email', array( $this, 'autoupdate_send_email' ), self::FilterPriority, 1 ); //more parameter options here for later
|
90 |
+
add_filter( 'auto_core_update_email', array( $this, 'autoupdate_email_override' ), self::FilterPriority, 1 ); //more parameter options here for later
|
91 |
+
|
92 |
+
if ( $this->getForceRunAutoUpdates() ) {
|
93 |
+
$this->force_run_autoupdates( 'update-core.php' ); //we'll redirect to the updates page for to show
|
94 |
+
}
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Will force-run the WordPress automatic updates process and then redirect to the updates screen.
|
99 |
+
*/
|
100 |
+
public function force_run_autoupdates( $insRedirect = false ) {
|
101 |
+
$lock_name = 'auto_updater.lock'; //ref: /wp-admin/includes/class-wp-upgrader.php
|
102 |
+
delete_option( $lock_name );
|
103 |
+
if ( !defined('DOING_CRON') ) {
|
104 |
+
define( 'DOING_CRON', true ); // this prevents WP from disabling plugins pre-upgrade
|
105 |
+
}
|
106 |
|
107 |
+
// does the actual updating
|
108 |
+
$this->doStatIncrement( 'autoupdates.forcerun' );
|
109 |
+
wp_maybe_auto_update();
|
110 |
|
111 |
+
if ( !empty( $insRedirect ) ) {
|
112 |
+
wp_redirect( network_admin_url( $insRedirect ) );
|
113 |
+
exit();
|
114 |
}
|
115 |
+
return true;
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* This is a filter method designed to say whether a major core WordPress upgrade should be permitted,
|
120 |
+
* based on the plugin settings.
|
121 |
+
*
|
122 |
+
* @param boolean $infUpdate
|
123 |
+
* @return boolean
|
124 |
+
*/
|
125 |
+
public function autoupdate_core_major( $infUpdate ) {
|
126 |
+
if ( $this->getIsOption('autoupdate_core', 'core_never') ) {
|
127 |
+
$this->doStatIncrement( 'autoupdates.core.major.blocked' );
|
128 |
+
return false;
|
129 |
+
}
|
130 |
+
else if ( $this->getIsOption('autoupdate_core', 'core_major') ) {
|
131 |
+
$this->doStatIncrement( 'autoupdates.core.major.allowed' );
|
132 |
+
return true;
|
133 |
}
|
134 |
+
return $infUpdate;
|
135 |
}
|
136 |
|
137 |
+
/**
|
138 |
+
* This is a filter method designed to say whether a minor core WordPress upgrade should be permitted,
|
139 |
+
* based on the plugin settings.
|
140 |
+
*
|
141 |
+
* @param boolean $infUpdate
|
142 |
+
* @return boolean
|
143 |
+
*/
|
144 |
+
public function autoupdate_core_minor( $infUpdate ) {
|
145 |
+
if ( $this->getIsOption('autoupdate_core', 'core_never') ) {
|
146 |
+
$this->doStatIncrement( 'autoupdates.core.minor.blocked' );
|
147 |
+
return false;
|
148 |
}
|
149 |
+
else if ( $this->getIsOption('autoupdate_core', 'core_minor') ) {
|
150 |
+
$this->doStatIncrement( 'autoupdates.core.minor.allowed' );
|
151 |
return true;
|
152 |
}
|
153 |
return $infUpdate;
|
154 |
}
|
155 |
|
156 |
+
/**
|
157 |
+
* This is a filter method designed to say whether a WordPress translations upgrades should be permitted,
|
158 |
+
* based on the plugin settings.
|
159 |
+
*
|
160 |
+
* @param boolean $infUpdate
|
161 |
+
* @param string $insSlug
|
162 |
+
* @return boolean
|
163 |
+
*/
|
164 |
+
public function autoupdate_translations( $infUpdate, $insSlug ) {
|
165 |
+
if ( $this->getIsOption('enable_autoupdate_translations', 'Y') ) {
|
166 |
+
return true;
|
167 |
+
}
|
168 |
+
return $infUpdate;
|
169 |
+
}
|
170 |
+
|
171 |
+
/**
|
172 |
+
* This is a filter method designed to say whether WordPress plugin upgrades should be permitted,
|
173 |
+
* based on the plugin settings.
|
174 |
+
*
|
175 |
+
* @param boolean $infUpdate
|
176 |
+
* @param StdClass|string $mItem
|
177 |
+
* @return boolean
|
178 |
+
*/
|
179 |
+
public function autoupdate_plugins( $infUpdate, $mItem ) {
|
180 |
+
|
181 |
+
// first, is global auto updates for plugins set
|
182 |
+
if ( $this->getIsOption('enable_autoupdate_plugins', 'Y') ) {
|
183 |
+
$this->doStatIncrement( 'autoupdates.plugins.all' );
|
184 |
+
return true;
|
185 |
+
}
|
186 |
+
|
187 |
+
if ( is_object( $mItem ) && isset( $mItem->plugin ) ) { // WP 3.8.2+
|
188 |
+
$sItemFile = $mItem->plugin;
|
189 |
+
}
|
190 |
+
else if ( is_string( $mItem ) ) { // WP pre-3.8.2
|
191 |
+
$sItemFile = $mItem;
|
192 |
+
}
|
193 |
+
// at this point we don't have a slug to use so we just return the current update setting
|
194 |
+
else {
|
195 |
+
return $infUpdate;
|
196 |
+
}
|
197 |
+
|
198 |
+
if ( $sItemFile === $this->m_sPluginFile ) {
|
199 |
+
if ( $this->getIsOption('autoupdate_plugin_self', 'Y') ) {
|
200 |
+
$this->doStatIncrement( 'autoupdates.plugins.self' );
|
201 |
+
return true;
|
202 |
+
}
|
203 |
+
return false;
|
204 |
+
}
|
205 |
+
|
206 |
+
$aAutoUpdatePluginFiles = apply_filters( 'icwp_wpsf_autoupdate_plugins', array() );
|
207 |
+
|
208 |
+
if ( !empty( $aAutoUpdatePluginFiles )
|
209 |
+
&& is_array($aAutoUpdatePluginFiles)
|
210 |
+
&& in_array( $sItemFile, $aAutoUpdatePluginFiles ) ) {
|
211 |
+
|
212 |
+
return true;
|
213 |
+
}
|
214 |
+
|
215 |
+
return $infUpdate;
|
216 |
+
}
|
217 |
+
|
218 |
+
/**
|
219 |
+
* This is a filter method designed to say whether WordPress theme upgrades should be permitted,
|
220 |
+
* based on the plugin settings.
|
221 |
+
*
|
222 |
+
* @param boolean $infUpdate
|
223 |
+
* @param stdClass|string $mItem
|
224 |
+
* @return boolean
|
225 |
+
*/
|
226 |
+
public function autoupdate_themes( $infUpdate, $mItem ) {
|
227 |
+
|
228 |
+
// first, is global auto updates for themes set
|
229 |
+
if ( $this->getIsOption('enable_autoupdate_themes', 'Y') ) {
|
230 |
+
$this->doStatIncrement( 'autoupdates.themes.all' );
|
231 |
+
return true;
|
232 |
+
}
|
233 |
+
|
234 |
+
if ( is_object( $mItem ) && isset( $mItem->theme ) ) { // WP 3.8.2+
|
235 |
+
$sItemFile = $mItem->theme;
|
236 |
+
}
|
237 |
+
else if ( is_string( $mItem ) ) { // WP pre-3.8.2
|
238 |
+
$sItemFile = $mItem;
|
239 |
+
}
|
240 |
+
// at this point we don't have a slug to use so we just return the current update setting
|
241 |
+
else {
|
242 |
+
return $infUpdate;
|
243 |
+
}
|
244 |
+
|
245 |
+
$aAutoUpdateThemeFiles = apply_filters( 'icwp_wpsf_autoupdate_themes', array() );
|
246 |
+
|
247 |
+
if ( !empty( $aAutoUpdateThemeFiles )
|
248 |
+
&& is_array($aAutoUpdateThemeFiles)
|
249 |
+
&& in_array( $sItemFile, $aAutoUpdateThemeFiles ) ) {
|
250 |
+
|
251 |
+
return true;
|
252 |
+
}
|
253 |
+
|
254 |
+
return $infUpdate;
|
255 |
+
}
|
256 |
+
|
257 |
+
/**
|
258 |
+
* This is a filter method designed to say whether WordPress automatic upgrades should be permitted
|
259 |
+
* if a version control system is detected.
|
260 |
+
*
|
261 |
+
* @param boolean $infUpdate
|
262 |
+
* @return boolean
|
263 |
+
*/
|
264 |
public function disable_for_vcs( $checkout, $context ) {
|
265 |
return false;
|
266 |
}
|
267 |
+
|
268 |
+
/**
|
269 |
+
* A filter on whether or not a notification email is send after core upgrades are attempted.
|
270 |
+
*
|
271 |
+
* @param boolean $infSendEmail
|
272 |
+
* @return boolean
|
273 |
+
*/
|
274 |
+
public function autoupdate_send_email( $infSendEmail ) {
|
275 |
+
return $this->getIsOption('enable_upgrade_notification_email', 'Y');
|
276 |
+
}
|
277 |
+
|
278 |
+
/**
|
279 |
+
* A filter on the target email address to which to send upgrade notification emails.
|
280 |
+
*
|
281 |
+
* @param array $aEmailParams
|
282 |
+
* @return array
|
283 |
+
*/
|
284 |
+
public function autoupdate_email_override( $aEmailParams ) {
|
285 |
+
if ( !empty( $this->m_aOptions['override_email_address'] ) ) {
|
286 |
+
$aEmailParams['to'] = $this->m_aOptions['override_email_address'];
|
287 |
+
}
|
288 |
+
return $aEmailParams;
|
289 |
+
}
|
290 |
}
|
291 |
|
292 |
+
endif;
|
293 |
+
|
294 |
+
if ( !class_exists('ICWP_WPSF_AutoUpdatesProcessor') ):
|
295 |
+
class ICWP_WPSF_AutoUpdatesProcessor extends ICWP_AutoUpdatesProcessor_V4 { }
|
296 |
+
endif;
|
src/icwp-processor-commentsfilter.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* Copyright (c)
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
@@ -17,56 +17,75 @@
|
|
17 |
|
18 |
require_once( dirname(__FILE__).'/icwp-basedb-processor.php' );
|
19 |
|
20 |
-
if ( !class_exists('
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
* email fails.
|
63 |
*
|
64 |
* @var boolean
|
65 |
*/
|
66 |
protected $m_fAllowTwoFactorByPass;
|
67 |
|
68 |
-
public function __construct() {
|
69 |
-
parent::__construct( self::
|
70 |
$this->createTable();
|
71 |
$this->reset();
|
72 |
}
|
@@ -77,29 +96,255 @@ class ICWP_CommentsFilterProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
77 |
public function reset() {
|
78 |
parent::reset();
|
79 |
$this->m_sUniqueToken = '';
|
80 |
-
$this->
|
|
|
|
|
81 |
}
|
82 |
|
83 |
/**
|
84 |
*/
|
85 |
public function run() {
|
|
|
|
|
|
|
|
|
86 |
// Add GASP checking to the comment form.
|
87 |
-
if ( $this->
|
88 |
add_action( 'comment_form', array( $this, 'printGaspFormHook_Action' ), 1 );
|
89 |
add_action( 'comment_form', array( $this, 'printGaspFormParts_Action' ), 2 );
|
90 |
-
|
91 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
92 |
}
|
93 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
|
95 |
/**
|
96 |
* @return void
|
97 |
*/
|
98 |
public function printGaspFormHook_Action() {
|
99 |
|
100 |
-
if ( !$this->
|
101 |
return;
|
102 |
}
|
|
|
103 |
global $post;
|
104 |
if ( !isset( $post ) || $post->comment_status != 'open' ) {
|
105 |
return;
|
@@ -108,7 +353,7 @@ class ICWP_CommentsFilterProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
108 |
$this->createUniquePostCommentToken( $post->ID, $this->m_sUniqueToken );
|
109 |
|
110 |
require_once( dirname(__FILE__).'/icwp-data-processor.php' );
|
111 |
-
$this->m_sUniqueFormId =
|
112 |
|
113 |
echo $this->getGaspCommentsHookHtml();
|
114 |
}
|
@@ -118,11 +363,11 @@ class ICWP_CommentsFilterProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
118 |
*
|
119 |
* @return boolean
|
120 |
*/
|
121 |
-
protected function
|
122 |
if ( !is_user_logged_in() ) {
|
123 |
return true;
|
124 |
}
|
125 |
-
else if ( $this->
|
126 |
return true;
|
127 |
}
|
128 |
return false;
|
@@ -132,7 +377,7 @@ class ICWP_CommentsFilterProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
132 |
* @return void
|
133 |
*/
|
134 |
public function printGaspFormParts_Action() {
|
135 |
-
if ( $this->
|
136 |
echo $this->getGaspCommentsHtml();
|
137 |
}
|
138 |
}
|
@@ -140,7 +385,7 @@ class ICWP_CommentsFilterProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
140 |
/**
|
141 |
* @return string
|
142 |
*/
|
143 |
-
|
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="" />';
|
@@ -148,24 +393,24 @@ class ICWP_CommentsFilterProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
148 |
return $sReturn;
|
149 |
}
|
150 |
|
151 |
-
|
152 |
|
153 |
$sId = $this->m_sUniqueFormId;
|
154 |
-
$sConfirm = stripslashes( $this->
|
155 |
-
$sAlert = stripslashes( $this->
|
156 |
-
$sCommentWait = stripslashes( $this->
|
157 |
-
$nCooldown = $this->
|
158 |
-
$nExpire = $this->
|
159 |
-
|
160 |
if ( strpos( $sCommentWait, '%s' ) !== false ) {
|
161 |
$sCommentWait = sprintf( $sCommentWait, $nCooldown );
|
162 |
-
$sJsCommentWait = str_replace( '%s', '"+nRemaining+"', $this->
|
163 |
$sJsCommentWait = '"'.$sJsCommentWait.'"';
|
164 |
}
|
165 |
else {
|
166 |
-
$sJsCommentWait = '"'. $this->
|
167 |
}
|
168 |
-
$sCommentReload = $this->
|
169 |
|
170 |
$sReturn = "
|
171 |
<script type='text/javascript'>
|
@@ -248,40 +493,15 @@ class ICWP_CommentsFilterProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
248 |
";
|
249 |
return $sReturn;
|
250 |
}
|
251 |
-
|
252 |
/**
|
253 |
-
* @param
|
254 |
-
* @
|
|
|
255 |
*/
|
256 |
-
|
257 |
-
|
258 |
-
|
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 = "
|
@@ -296,7 +516,7 @@ class ICWP_CommentsFilterProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
296 |
$sQuery = sprintf( $sQuery,
|
297 |
$this->m_sTableName,
|
298 |
$sToken,
|
299 |
-
$
|
300 |
$this->m_nRequestIp
|
301 |
);
|
302 |
$mResult = $this->selectCustomFromTable( $sQuery );
|
@@ -306,30 +526,48 @@ class ICWP_CommentsFilterProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
306 |
}
|
307 |
else {
|
308 |
// Only 1 chance is given per token, so we delete it
|
309 |
-
$this->deleteUniquePostCommentToken( $sToken, $
|
310 |
|
311 |
-
// Did
|
312 |
$nNow = time();
|
313 |
$aRecord = $mResult[0];
|
314 |
$nInterval = $nNow - $aRecord['created_at'];
|
315 |
if ( $nInterval < $this->m_aOptions[ 'comments_cooldown_interval' ]
|
316 |
-
|| ( $this->
|
317 |
) {
|
318 |
return false;
|
319 |
}
|
320 |
return true;
|
321 |
}
|
322 |
}
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
327 |
}
|
328 |
-
return $
|
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,
|
@@ -341,16 +579,16 @@ class ICWP_CommentsFilterProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
341 |
PRIMARY KEY (`id`)
|
342 |
) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
|
343 |
$sSqlTables = sprintf( $sSqlTables, $this->m_sTableName );
|
344 |
-
|
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 = "
|
@@ -361,10 +599,10 @@ class ICWP_CommentsFilterProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
361 |
AND `post_id` = '%s'
|
362 |
";
|
363 |
$sQuery = sprintf( $sQuery,
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
);
|
369 |
$this->doSql( $sQuery );
|
370 |
}
|
@@ -374,14 +612,14 @@ class ICWP_CommentsFilterProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
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 = "
|
@@ -400,12 +638,13 @@ class ICWP_CommentsFilterProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
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
|
@@ -425,7 +664,33 @@ class ICWP_CommentsFilterProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
425 |
$sToken = uniqid( $this->m_nRequestIp.$insPostId );
|
426 |
return md5( $sToken );
|
427 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
428 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
429 |
}
|
|
|
430 |
|
|
|
|
|
431 |
endif;
|
1 |
<?php
|
2 |
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
17 |
|
18 |
require_once( dirname(__FILE__).'/icwp-basedb-processor.php' );
|
19 |
|
20 |
+
if ( !class_exists('ICWP_CommentsFilterProcessor_V2') ):
|
21 |
+
|
22 |
+
class ICWP_CommentsFilterProcessor_V2 extends ICWP_BaseDbProcessor_WPSF {
|
23 |
+
|
24 |
+
const Slug = 'comments_filter';
|
25 |
+
const Spam_Blacklist_Source = 'https://raw.githubusercontent.com/splorp/wordpress-comment-blacklist/master/blacklist.txt';
|
26 |
+
|
27 |
+
const TWODAYS = 172800;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @var string
|
31 |
+
*/
|
32 |
+
static protected $sSpamBlacklistFile;
|
33 |
|
|
|
|
|
|
|
|
|
34 |
/**
|
35 |
* @var string
|
36 |
*/
|
37 |
static protected $sModeFile_LoginThrottled;
|
|
|
38 |
/**
|
39 |
* The unique comment token assigned to this page
|
40 |
* @var integer
|
41 |
*/
|
42 |
protected $m_sUniqueToken;
|
|
|
43 |
/**
|
44 |
* The unique comment token assigned to this page
|
45 |
* @var integer
|
46 |
*/
|
47 |
protected $m_sUniqueFormId;
|
|
|
48 |
/**
|
49 |
* The length of time that must pass between a page being loaded and comment being posted.
|
50 |
* @var integer
|
51 |
*/
|
52 |
protected $m_nCommentCooldown;
|
|
|
53 |
/**
|
54 |
* The maxium length of time that comment token may last and be used.
|
55 |
* @var integer
|
56 |
*/
|
57 |
protected $m_nCommentTokenExpire;
|
58 |
+
/**
|
59 |
+
* @var integer
|
60 |
+
*/
|
61 |
protected $m_nLastLoginTime;
|
62 |
+
/**
|
63 |
+
* @var string
|
64 |
+
*/
|
65 |
protected $m_sSecretKey;
|
66 |
+
/**
|
67 |
+
* @var string
|
68 |
+
*/
|
69 |
protected $m_sGaspKey;
|
|
|
70 |
/**
|
71 |
+
* @var string
|
72 |
+
*/
|
73 |
+
protected $sCommentStatus;
|
74 |
+
/**
|
75 |
+
* @var string
|
76 |
+
*/
|
77 |
+
protected $sCommentStatusExplanation;
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Flag as to whether Two Factor Authentication will be by-passed when sending the verification
|
81 |
* email fails.
|
82 |
*
|
83 |
* @var boolean
|
84 |
*/
|
85 |
protected $m_fAllowTwoFactorByPass;
|
86 |
|
87 |
+
public function __construct( $insOptionPrefix = '' ) {
|
88 |
+
parent::__construct( $this->constructStorageKey( $insOptionPrefix, self::Slug ), self::Slug );
|
89 |
$this->createTable();
|
90 |
$this->reset();
|
91 |
}
|
96 |
public function reset() {
|
97 |
parent::reset();
|
98 |
$this->m_sUniqueToken = '';
|
99 |
+
$this->sCommentStatus = '';
|
100 |
+
$this->sCommentStatusExplanation = '';
|
101 |
+
self::$sSpamBlacklistFile = dirname(__FILE__).ICWP_DS.'..'.ICWP_DS.'resources'.ICWP_DS.'spamblacklist.txt';
|
102 |
}
|
103 |
|
104 |
/**
|
105 |
*/
|
106 |
public function run() {
|
107 |
+
parent::run();
|
108 |
+
|
109 |
+
$fDoSetCommentStatus = false;
|
110 |
+
|
111 |
// Add GASP checking to the comment form.
|
112 |
+
if ( $this->getIsOption('enable_comments_gasp_protection', 'Y') ) {
|
113 |
add_action( 'comment_form', array( $this, 'printGaspFormHook_Action' ), 1 );
|
114 |
add_action( 'comment_form', array( $this, 'printGaspFormParts_Action' ), 2 );
|
115 |
+
}
|
116 |
+
|
117 |
+
add_filter( 'preprocess_comment', array( $this, 'doCommentPreProcess_Filter' ), 1, 1 );
|
118 |
+
add_filter( 'pre_comment_content', array( $this, 'doCommentContentPreProcess_Filter' ), 1, 1 );
|
119 |
+
add_filter( 'pre_comment_approved', array( $this, 'doSetCommentStatus_Filter' ), 1 );
|
120 |
+
}
|
121 |
+
|
122 |
+
/**
|
123 |
+
* @param array $aCommentData
|
124 |
+
* @return array
|
125 |
+
*/
|
126 |
+
public function doCommentPreProcess_Filter( $aCommentData ) {
|
127 |
+
|
128 |
+
if ( !$this->getIfDoCommentsCheck() ) {
|
129 |
+
return $aCommentData;
|
130 |
+
}
|
131 |
+
|
132 |
+
$this->doGaspCommentCheck( $aCommentData['comment_post_ID'] );
|
133 |
+
$this->doBlacklistSpamCheck( $aCommentData );
|
134 |
+
|
135 |
+
// Now we check whether comment status is to completely reject and then we simply redirect to "home"
|
136 |
+
if ( $this->sCommentStatus == 'reject' ) {
|
137 |
+
$oWpFunctions = $this->loadWpFunctionsProcessor();
|
138 |
+
$oWpFunctions->redirectToHome();
|
139 |
+
}
|
140 |
+
|
141 |
+
return $aCommentData;
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* @param string $sCommentContent
|
146 |
+
* @return string
|
147 |
+
*/
|
148 |
+
public function doCommentContentPreProcess_Filter( $sCommentContent ) {
|
149 |
+
// If either spam filtering process left an explanation, we add it here
|
150 |
+
if ( !empty( $this->sCommentStatusExplanation ) ) {
|
151 |
+
$sCommentContent = $this->sCommentStatusExplanation.$sCommentContent;
|
152 |
+
}
|
153 |
+
return $sCommentContent;
|
154 |
+
}
|
155 |
+
|
156 |
+
/**
|
157 |
+
* Performs the actual GASP comment checking
|
158 |
+
*
|
159 |
+
* @param $nPostId
|
160 |
+
*/
|
161 |
+
protected function doGaspCommentCheck( $nPostId ) {
|
162 |
+
|
163 |
+
//Check that we haven't already marked the comment through another scan
|
164 |
+
if ( !empty( $this->sCommentStatus ) || !$this->getIsOption('enable_comments_gasp_protection', 'Y') ) {
|
165 |
+
return;
|
166 |
+
}
|
167 |
+
|
168 |
+
$fIsSpam = true;
|
169 |
+
$sExplanation = '';
|
170 |
+
|
171 |
+
// we have the cb name, is it set?
|
172 |
+
if( !isset( $_POST['cb_nombre'] ) || !isset( $_POST[ $_POST['cb_nombre'] ] ) ) {
|
173 |
+
$sExplanation = sprintf( _wpsf__('Failed GASP Bot Filter Test (%s)' ), _wpsf__('checkbox') );
|
174 |
+
$sStatKey = 'checkbox';
|
175 |
+
}
|
176 |
+
// honeypot check
|
177 |
+
else if ( isset( $_POST['sugar_sweet_email'] ) && $_POST['sugar_sweet_email'] !== '' ) {
|
178 |
+
$sExplanation = sprintf( _wpsf__('Failed GASP Bot Filter Test (%s)' ), _wpsf__('honeypot') );
|
179 |
+
$sStatKey = 'honeypot';
|
180 |
+
}
|
181 |
+
// check the unique comment token is present
|
182 |
+
else if ( !isset( $_POST['comment_token'] ) || !$this->checkCommentToken( $_POST['comment_token'], $nPostId ) ) {
|
183 |
+
$sExplanation = sprintf( _wpsf__('Failed GASP Bot Filter Test (%s)' ), _wpsf__('comment token failure') );
|
184 |
+
$sStatKey = 'token';
|
185 |
+
}
|
186 |
+
else {
|
187 |
+
$fIsSpam = false;
|
188 |
+
}
|
189 |
+
|
190 |
+
if ( $fIsSpam ) {
|
191 |
+
$this->doStatIncrement( sprintf( 'spam.gasp.%s', $sStatKey ) );
|
192 |
+
$this->sCommentStatus = $this->getOption('comments_default_action_spam_bot');
|
193 |
+
$this->setCommentStatusExplanation( $sExplanation );
|
194 |
+
}
|
195 |
+
}
|
196 |
+
|
197 |
+
/**
|
198 |
+
* @param $aCommentData
|
199 |
+
*/
|
200 |
+
protected function doBlacklistSpamCheck( $aCommentData ) {
|
201 |
+
$this->loadDataProcessor();
|
202 |
+
$this->doBlacklistSpamCheck_Action(
|
203 |
+
$aCommentData['comment_author'],
|
204 |
+
$aCommentData['comment_author_email'],
|
205 |
+
$aCommentData['comment_author_url'],
|
206 |
+
$aCommentData['comment_content'],
|
207 |
+
ICWP_WPSF_DataProcessor::GetVisitorIpAddress( false ),
|
208 |
+
isset( $_SERVER['HTTP_USER_AGENT'] ) ? substr( $_SERVER['HTTP_USER_AGENT'], 0, 254 ) : ''
|
209 |
+
);
|
210 |
+
}
|
211 |
+
|
212 |
+
/**
|
213 |
+
* Does the same as the WordPress blacklist filter, but more intelligently and with a nod towards much higher performance.
|
214 |
+
*
|
215 |
+
* It also uses defined options for which fields are checked for SPAM instead of just checking EVERYTHING!
|
216 |
+
*
|
217 |
+
* @param string $sAuthor
|
218 |
+
* @param string $sEmail
|
219 |
+
* @param string $sUrl
|
220 |
+
* @param string $sComment
|
221 |
+
* @param string $sUserIp
|
222 |
+
* @param string $sUserAgent
|
223 |
+
*/
|
224 |
+
public function doBlacklistSpamCheck_Action( $sAuthor, $sEmail, $sUrl, $sComment, $sUserIp, $sUserAgent ) {
|
225 |
+
|
226 |
+
// Check that we haven't already marked the comment through another scan, say GASP
|
227 |
+
if ( !empty( $this->sCommentStatus ) || !$this->getIsOption('enable_comments_human_spam_filter', 'Y') ) {
|
228 |
+
return;
|
229 |
+
}
|
230 |
+
|
231 |
+
// read the file of spam words
|
232 |
+
$sSpamWords = $this->getSpamBlacklist();
|
233 |
+
if ( empty($sSpamWords) ) {
|
234 |
+
return;
|
235 |
+
}
|
236 |
+
$aWords = explode( "\n", $sSpamWords );
|
237 |
+
|
238 |
+
$aItemsMap = array(
|
239 |
+
'comment_content' => $sComment,
|
240 |
+
'url' => $sUrl,
|
241 |
+
'author_name' => $sAuthor,
|
242 |
+
'author_email' => $sEmail,
|
243 |
+
'ip_address' => $sUserIp,
|
244 |
+
'user_agent' => $sUserAgent
|
245 |
+
);
|
246 |
+
$aDesiredItemsToCheck = $this->getOption('enable_comments_human_spam_filter_items');
|
247 |
+
$aItemsToCheck = array();
|
248 |
+
foreach( $aDesiredItemsToCheck as $sKey ) {
|
249 |
+
$aItemsToCheck[$sKey] = $aItemsMap[$sKey];
|
250 |
+
}
|
251 |
+
|
252 |
+
foreach( $aItemsToCheck as $sKey => $sItem ) {
|
253 |
+
foreach ( $aWords as $sWord ) {
|
254 |
+
if ( stripos( $sItem, $sWord ) !== false ) {
|
255 |
+
//mark as spam and exit;
|
256 |
+
$this->doStatIncrement( sprintf( 'spam.human.%s', $sKey ) );
|
257 |
+
$this->doStatHumanSpamWords( $sWord );
|
258 |
+
$this->sCommentStatus = $this->getOption('comments_default_action_human_spam');
|
259 |
+
$this->setCommentStatusExplanation( sprintf( _wpsf__('Human SPAM filter found "%s" in "%s"' ), $sWord, $sKey ) );
|
260 |
+
break 2;
|
261 |
+
}
|
262 |
+
}
|
263 |
+
}
|
264 |
+
}
|
265 |
+
|
266 |
+
/**
|
267 |
+
* @param $sStatWord
|
268 |
+
*/
|
269 |
+
protected function doStatHumanSpamWords( $sStatWord = '' ) {
|
270 |
+
$this->loadWpsfStatsProcessor();
|
271 |
+
if ( !empty($sStatWord) ) {
|
272 |
+
ICWP_Stats_WPSF::DoStatIncrementKeyValue( 'spam.human.words', base64_encode( $sStatWord ) );
|
273 |
+
}
|
274 |
+
}
|
275 |
+
|
276 |
+
/**
|
277 |
+
* @return null|string
|
278 |
+
*/
|
279 |
+
protected function getSpamBlacklist() {
|
280 |
+
$oFs = $this->loadFileSystemProcessor();
|
281 |
+
|
282 |
+
// first, does the file exist? If not import
|
283 |
+
if ( !$oFs->exists( self::$sSpamBlacklistFile ) ) {
|
284 |
+
$this->doSpamBlacklistImport();
|
285 |
+
}
|
286 |
+
// second, if it exists and it's older than 48hrs, update
|
287 |
+
else if ( time() - $oFs->getModifiedTime( self::$sSpamBlacklistFile ) > self::TWODAYS ) {
|
288 |
+
$this->doSpamBlacklistUpdate();
|
289 |
+
}
|
290 |
+
|
291 |
+
$sList = $oFs->getFileContent( self::$sSpamBlacklistFile );
|
292 |
+
return empty($sList)? '' : $sList;
|
293 |
+
}
|
294 |
+
|
295 |
+
/**
|
296 |
+
*/
|
297 |
+
protected function doSpamBlacklistUpdate() {
|
298 |
+
$oFs = $this->loadFileSystemProcessor();
|
299 |
+
$oFs->deleteFile( self::$sSpamBlacklistFile );
|
300 |
+
$this->doSpamBlacklistImport();
|
301 |
+
}
|
302 |
+
|
303 |
+
/**
|
304 |
+
*/
|
305 |
+
protected function doSpamBlacklistImport() {
|
306 |
+
$oFs = $this->loadFileSystemProcessor();
|
307 |
+
if ( !$oFs->exists( self::$sSpamBlacklistFile ) ) {
|
308 |
+
|
309 |
+
$sRawList = $this->doSpamBlacklistDownload();
|
310 |
+
|
311 |
+
if ( empty($sRawList) ) {
|
312 |
+
$sList = '';
|
313 |
+
}
|
314 |
+
else {
|
315 |
+
// filter out empty lines
|
316 |
+
$aWords = explode( "\n", $sRawList );
|
317 |
+
foreach ( $aWords as $nIndex => $sWord ) {
|
318 |
+
$sWord = trim($sWord);
|
319 |
+
if ( empty($sWord) ) {
|
320 |
+
unset( $aWords[$nIndex] );
|
321 |
+
}
|
322 |
+
}
|
323 |
+
$sList = implode( "\n", $aWords );
|
324 |
+
}
|
325 |
+
|
326 |
+
// save the list to disk for the future.
|
327 |
+
$oFs->putFileContent( self::$sSpamBlacklistFile, $sList );
|
328 |
}
|
329 |
}
|
330 |
+
|
331 |
+
/**
|
332 |
+
* @return string
|
333 |
+
*/
|
334 |
+
protected function doSpamBlacklistDownload() {
|
335 |
+
$oFs = $this->loadFileSystemProcessor();
|
336 |
+
return $oFs->getUrlContent( self::Spam_Blacklist_Source );
|
337 |
+
}
|
338 |
|
339 |
/**
|
340 |
* @return void
|
341 |
*/
|
342 |
public function printGaspFormHook_Action() {
|
343 |
|
344 |
+
if ( !$this->getIfDoCommentsCheck() ) {
|
345 |
return;
|
346 |
}
|
347 |
+
|
348 |
global $post;
|
349 |
if ( !isset( $post ) || $post->comment_status != 'open' ) {
|
350 |
return;
|
353 |
$this->createUniquePostCommentToken( $post->ID, $this->m_sUniqueToken );
|
354 |
|
355 |
require_once( dirname(__FILE__).'/icwp-data-processor.php' );
|
356 |
+
$this->m_sUniqueFormId = ICWP_WPSF_DataProcessor::GenerateRandomString( rand(7, 23), true );
|
357 |
|
358 |
echo $this->getGaspCommentsHookHtml();
|
359 |
}
|
363 |
*
|
364 |
* @return boolean
|
365 |
*/
|
366 |
+
protected function getIfDoCommentsCheck() {
|
367 |
if ( !is_user_logged_in() ) {
|
368 |
return true;
|
369 |
}
|
370 |
+
else if ( $this->getIsOption('enable_comments_gasp_protection_for_logged_in', 'Y') ) {
|
371 |
return true;
|
372 |
}
|
373 |
return false;
|
377 |
* @return void
|
378 |
*/
|
379 |
public function printGaspFormParts_Action() {
|
380 |
+
if ( $this->getIfDoCommentsCheck() ) {
|
381 |
echo $this->getGaspCommentsHtml();
|
382 |
}
|
383 |
}
|
385 |
/**
|
386 |
* @return string
|
387 |
*/
|
388 |
+
protected function getGaspCommentsHookHtml() {
|
389 |
$sId = $this->m_sUniqueFormId;
|
390 |
$sReturn = '<p id="'.$sId.'"></p>'; // we use this unique <p> to hook onto using javascript
|
391 |
$sReturn .= '<input type="hidden" id="_sugar_sweet_email" name="sugar_sweet_email" value="" />';
|
393 |
return $sReturn;
|
394 |
}
|
395 |
|
396 |
+
protected function getGaspCommentsHtml() {
|
397 |
|
398 |
$sId = $this->m_sUniqueFormId;
|
399 |
+
$sConfirm = stripslashes( $this->getOption('custom_message_checkbox') );
|
400 |
+
$sAlert = stripslashes( $this->getOption('custom_message_alert') );
|
401 |
+
$sCommentWait = stripslashes( $this->getOption('custom_message_comment_wait') );
|
402 |
+
$nCooldown = $this->getOption('comments_cooldown_interval');
|
403 |
+
$nExpire = $this->getOption('comments_token_expire_interval');
|
404 |
+
|
405 |
if ( strpos( $sCommentWait, '%s' ) !== false ) {
|
406 |
$sCommentWait = sprintf( $sCommentWait, $nCooldown );
|
407 |
+
$sJsCommentWait = str_replace( '%s', '"+nRemaining+"', $this->getOption('custom_message_comment_wait') );
|
408 |
$sJsCommentWait = '"'.$sJsCommentWait.'"';
|
409 |
}
|
410 |
else {
|
411 |
+
$sJsCommentWait = '"'. $this->getOption('custom_message_comment_wait').'"';
|
412 |
}
|
413 |
+
$sCommentReload = $this->getOption('custom_message_comment_reload');
|
414 |
|
415 |
$sReturn = "
|
416 |
<script type='text/javascript'>
|
493 |
";
|
494 |
return $sReturn;
|
495 |
}
|
496 |
+
|
497 |
/**
|
498 |
+
* @param $sCommentToken
|
499 |
+
* @param $sPostId
|
500 |
+
* @return bool
|
501 |
*/
|
502 |
+
protected function checkCommentToken( $sCommentToken, $sPostId ) {
|
503 |
+
|
504 |
+
$sToken = esc_sql( $sCommentToken ); //just in-case someones tries to get all funky up in it
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
505 |
|
506 |
// Try to get the database entry that corresponds to this set of data. If we get nothing, fail.
|
507 |
$sQuery = "
|
516 |
$sQuery = sprintf( $sQuery,
|
517 |
$this->m_sTableName,
|
518 |
$sToken,
|
519 |
+
$sPostId,
|
520 |
$this->m_nRequestIp
|
521 |
);
|
522 |
$mResult = $this->selectCustomFromTable( $sQuery );
|
526 |
}
|
527 |
else {
|
528 |
// Only 1 chance is given per token, so we delete it
|
529 |
+
$this->deleteUniquePostCommentToken( $sToken, $sPostId );
|
530 |
|
531 |
+
// Did sufficient time pass, or has it expired?
|
532 |
$nNow = time();
|
533 |
$aRecord = $mResult[0];
|
534 |
$nInterval = $nNow - $aRecord['created_at'];
|
535 |
if ( $nInterval < $this->m_aOptions[ 'comments_cooldown_interval' ]
|
536 |
+
|| ( $this->getOption( 'comments_token_expire_interval' ) > 0 && $nInterval > $this->getOption('comments_token_expire_interval') )
|
537 |
) {
|
538 |
return false;
|
539 |
}
|
540 |
return true;
|
541 |
}
|
542 |
}
|
543 |
+
|
544 |
+
/**
|
545 |
+
* We set the final approval status of the comments if we've set it in our scans, and empties the notification email
|
546 |
+
* in case we "trash" it (since WP sends out a notification email if it's anything but SPAM)
|
547 |
+
*
|
548 |
+
* @param $sApprovalStatus
|
549 |
+
* @return string
|
550 |
+
*/
|
551 |
+
public function doSetCommentStatus_Filter( $sApprovalStatus ) {
|
552 |
+
add_filter( 'comment_notification_recipients', array( $this, 'doClearCommentNotificationEmail_Filter' ), 100, 1 );
|
553 |
+
return empty( $this->sCommentStatus )? $sApprovalStatus : $this->sCommentStatus;
|
554 |
+
}
|
555 |
+
|
556 |
+
/**
|
557 |
+
* When you set a new comment as anything but 'spam' a notification email is sent to the post author.
|
558 |
+
* We suppress this for when we mark as trash by emptying the email notifications list.
|
559 |
+
*
|
560 |
+
* @param $aEmails
|
561 |
+
* @return array
|
562 |
+
*/
|
563 |
+
public function doClearCommentNotificationEmail_Filter( $aEmails ) {
|
564 |
+
if ( $this->sCommentStatus == 'trash' ) {
|
565 |
+
$aEmails = array();
|
566 |
}
|
567 |
+
return $aEmails;
|
568 |
}
|
569 |
|
570 |
public function createTable() {
|
|
|
571 |
// Set up comments ID table
|
572 |
$sSqlTables = "CREATE TABLE IF NOT EXISTS `%s` (
|
573 |
`id` int(11) NOT NULL AUTO_INCREMENT,
|
579 |
PRIMARY KEY (`id`)
|
580 |
) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
|
581 |
$sSqlTables = sprintf( $sSqlTables, $this->m_sTableName );
|
582 |
+
return $this->doSql( $sSqlTables );
|
583 |
}
|
584 |
+
|
585 |
/**
|
|
|
586 |
* @param string $insUniqueToken
|
587 |
* @param string $insPostId
|
588 |
+
* @param boolean $infSoftDelete
|
589 |
*/
|
590 |
protected function deleteUniquePostCommentToken( $insUniqueToken, $insPostId, $infSoftDelete = false ) {
|
591 |
+
|
592 |
if ( $infSoftDelete ) {
|
593 |
$nNow = time();
|
594 |
$sQuery = "
|
599 |
AND `post_id` = '%s'
|
600 |
";
|
601 |
$sQuery = sprintf( $sQuery,
|
602 |
+
$this->m_sTableName,
|
603 |
+
$nNow,
|
604 |
+
$insUniqueToken,
|
605 |
+
$insPostId
|
606 |
);
|
607 |
$this->doSql( $sQuery );
|
608 |
}
|
612 |
$this->deleteRowsFromTable( $aWhere );
|
613 |
}
|
614 |
}
|
615 |
+
|
616 |
/**
|
617 |
+
*
|
618 |
* @param string $insUniqueToken
|
619 |
* @param string $insPostId
|
620 |
*/
|
621 |
protected function deleteOldPostCommentTokens( $insPostId, $infSoftDelete = false ) {
|
622 |
+
|
623 |
if ( $infSoftDelete ) {
|
624 |
$nNow = time();
|
625 |
$sQuery = "
|
638 |
$this->doSql( $sQuery );
|
639 |
}
|
640 |
else {
|
641 |
+
$aWhere = array();
|
642 |
$aWhere['ip_long'] = $this->m_nRequestIp;
|
643 |
$aWhere['post_id'] = $insPostId;
|
644 |
$this->deleteRowsFromTable( $aWhere );
|
645 |
}
|
646 |
}
|
647 |
+
|
648 |
protected function createUniquePostCommentToken( $insPostId, &$outsUniqueToken = '' ) {
|
649 |
|
650 |
// Now add new pending entry
|
664 |
$sToken = uniqid( $this->m_nRequestIp.$insPostId );
|
665 |
return md5( $sToken );
|
666 |
}
|
667 |
+
|
668 |
+
/**
|
669 |
+
* @param $sExplanation
|
670 |
+
*/
|
671 |
+
protected function setCommentStatusExplanation( $sExplanation ) {
|
672 |
+
$this->sCommentStatusExplanation =
|
673 |
+
'[* '.sprintf( _wpsf__('WordPress Simple Firewall plugin marked this comment as "%s" because: %s.'),
|
674 |
+
$this->sCommentStatus,
|
675 |
+
$sExplanation
|
676 |
+
)." *]\n";
|
677 |
+
}
|
678 |
|
679 |
+
/**
|
680 |
+
* This is hooked into a cron in the base class and overrides the parent method.
|
681 |
+
*
|
682 |
+
* It'll delete everything older than 24hrs.
|
683 |
+
*/
|
684 |
+
public function cleanupDatabase() {
|
685 |
+
if ( !$this->getTableExists() ) {
|
686 |
+
return;
|
687 |
+
}
|
688 |
+
$nTimeStamp = time() - DAY_IN_SECONDS;
|
689 |
+
$this->deleteAllRowsOlderThan( $nTimeStamp );
|
690 |
+
}
|
691 |
}
|
692 |
+
endif;
|
693 |
|
694 |
+
if ( !class_exists('ICWP_WPSF_CommentsFilterProcessor') ):
|
695 |
+
class ICWP_WPSF_CommentsFilterProcessor extends ICWP_CommentsFilterProcessor_V2 { }
|
696 |
endif;
|
src/icwp-processor-email.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* Copyright (c)
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
@@ -17,9 +17,11 @@
|
|
17 |
|
18 |
require_once( dirname(__FILE__).'/icwp-base-processor.php' );
|
19 |
|
20 |
-
if ( !class_exists('
|
21 |
|
22 |
-
class
|
|
|
|
|
23 |
|
24 |
protected $m_sRecipientAddress;
|
25 |
protected $m_sSiteName;
|
@@ -31,7 +33,7 @@ class ICWP_EmailProcessor extends ICWP_BaseProcessor_WPSF {
|
|
31 |
/**
|
32 |
* @var int
|
33 |
*/
|
34 |
-
static protected $nThrottleInterval =
|
35 |
/**
|
36 |
* @var int
|
37 |
*/
|
@@ -48,6 +50,10 @@ class ICWP_EmailProcessor extends ICWP_BaseProcessor_WPSF {
|
|
48 |
* @var boolean
|
49 |
*/
|
50 |
protected $m_fEmailIsThrottled;
|
|
|
|
|
|
|
|
|
51 |
|
52 |
public function reset() {
|
53 |
parent::reset();
|
@@ -65,17 +71,19 @@ class ICWP_EmailProcessor extends ICWP_BaseProcessor_WPSF {
|
|
65 |
$aHeaders = array(
|
66 |
'MIME-Version: 1.0',
|
67 |
'Content-type: text/plain;',
|
68 |
-
sprintf( 'From: %s, Simple Firewall Plugin <%s>', $this->
|
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 |
-
|
|
|
|
|
79 |
}
|
80 |
|
81 |
/**
|
@@ -85,10 +93,7 @@ class ICWP_EmailProcessor extends ICWP_BaseProcessor_WPSF {
|
|
85 |
* @param array $inaMessage
|
86 |
*/
|
87 |
public function sendEmail( $insEmailSubject, $inaMessage ) {
|
88 |
-
|
89 |
-
return false;
|
90 |
-
}
|
91 |
-
return $this->sendEmailTo( $this->m_sRecipientAddress, $insEmailSubject, $inaMessage );
|
92 |
}
|
93 |
|
94 |
/**
|
@@ -102,7 +107,7 @@ class ICWP_EmailProcessor extends ICWP_BaseProcessor_WPSF {
|
|
102 |
protected function updateEmailThrottle() {
|
103 |
|
104 |
// Throttling Is Effectively Off
|
105 |
-
if ( $this->
|
106 |
$this->setThrottledFile( false );
|
107 |
return $this->m_fEmailIsThrottled;
|
108 |
}
|
@@ -132,7 +137,7 @@ class ICWP_EmailProcessor extends ICWP_BaseProcessor_WPSF {
|
|
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->
|
136 |
$this->setThrottledFile( true );
|
137 |
}
|
138 |
else {
|
@@ -147,7 +152,7 @@ class ICWP_EmailProcessor extends ICWP_BaseProcessor_WPSF {
|
|
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 |
}
|
@@ -156,13 +161,34 @@ class ICWP_EmailProcessor extends ICWP_BaseProcessor_WPSF {
|
|
156 |
$this->m_sRecipientAddress = $insEmailAddress;
|
157 |
}
|
158 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
159 |
public function setSiteName( $insName ) {
|
160 |
$this->m_sSiteName = $insName;
|
161 |
}
|
162 |
|
163 |
-
public function
|
164 |
-
$this->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
165 |
}
|
166 |
}
|
167 |
|
|
|
|
|
|
|
|
|
168 |
endif;
|
1 |
<?php
|
2 |
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
17 |
|
18 |
require_once( dirname(__FILE__).'/icwp-base-processor.php' );
|
19 |
|
20 |
+
if ( !class_exists('ICWP_EmailProcessor_V1') ):
|
21 |
|
22 |
+
class ICWP_EmailProcessor_V1 extends ICWP_WPSF_BaseProcessor {
|
23 |
+
|
24 |
+
const Slug = 'email';
|
25 |
|
26 |
protected $m_sRecipientAddress;
|
27 |
protected $m_sSiteName;
|
33 |
/**
|
34 |
* @var int
|
35 |
*/
|
36 |
+
static protected $nThrottleInterval = 1;
|
37 |
/**
|
38 |
* @var int
|
39 |
*/
|
50 |
* @var boolean
|
51 |
*/
|
52 |
protected $m_fEmailIsThrottled;
|
53 |
+
|
54 |
+
public function __construct( $insOptionPrefix = '' ) {
|
55 |
+
parent::__construct( $this->constructStorageKey( $insOptionPrefix, self::Slug ) );
|
56 |
+
}
|
57 |
|
58 |
public function reset() {
|
59 |
parent::reset();
|
71 |
$aHeaders = array(
|
72 |
'MIME-Version: 1.0',
|
73 |
'Content-type: text/plain;',
|
74 |
+
sprintf( 'From: %s, Simple Firewall Plugin <%s>', $this->getSiteName(), $insEmailAddress ),
|
75 |
sprintf( "Subject: %s", $insEmailSubject ),
|
76 |
'X-Mailer: PHP/'.phpversion()
|
77 |
);
|
78 |
|
79 |
$this->updateEmailThrottle();
|
80 |
+
// We make it appear to have "succeeded" if the throttle is applied.
|
81 |
if ( $this->m_fEmailIsThrottled ) {
|
82 |
return true;
|
83 |
}
|
84 |
+
$fSuccess = wp_mail( $insEmailAddress, $insEmailSubject, implode( "\r\n", $inaMessage ), implode( "\r\n", $aHeaders ) );
|
85 |
+
$this->store();
|
86 |
+
return $fSuccess;
|
87 |
}
|
88 |
|
89 |
/**
|
93 |
* @param array $inaMessage
|
94 |
*/
|
95 |
public function sendEmail( $insEmailSubject, $inaMessage ) {
|
96 |
+
return $this->sendEmailTo( $this->getDefaultRecipientAddress(), $insEmailSubject, $inaMessage );
|
|
|
|
|
|
|
97 |
}
|
98 |
|
99 |
/**
|
107 |
protected function updateEmailThrottle() {
|
108 |
|
109 |
// Throttling Is Effectively Off
|
110 |
+
if ( $this->getThrottleLimit() <= 0 ) {
|
111 |
$this->setThrottledFile( false );
|
112 |
return $this->m_fEmailIsThrottled;
|
113 |
}
|
137 |
$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.
|
138 |
$this->setThrottledFile( false );
|
139 |
}
|
140 |
+
else if ( is_file( self::$sModeFile_EmailThrottled ) || ( $this->m_nEmailThrottleCount >= $this->getThrottleLimit() ) ) {
|
141 |
$this->setThrottledFile( true );
|
142 |
}
|
143 |
else {
|
152 |
if ( $infOn && !is_file( self::$sModeFile_EmailThrottled ) && function_exists('touch') ) {
|
153 |
@touch( self::$sModeFile_EmailThrottled );
|
154 |
}
|
155 |
+
else if ( !$infOn && is_file(self::$sModeFile_EmailThrottled) ) {
|
156 |
@unlink( self::$sModeFile_EmailThrottled );
|
157 |
}
|
158 |
}
|
161 |
$this->m_sRecipientAddress = $insEmailAddress;
|
162 |
}
|
163 |
|
164 |
+
public function getDefaultRecipientAddress() {
|
165 |
+
if ( empty( $this->m_sRecipientAddress ) ) {
|
166 |
+
$this->m_sRecipientAddress = $this->m_aOptions[ 'block_send_email_address' ];
|
167 |
+
}
|
168 |
+
return $this->m_sRecipientAddress;
|
169 |
+
}
|
170 |
+
|
171 |
public function setSiteName( $insName ) {
|
172 |
$this->m_sSiteName = $insName;
|
173 |
}
|
174 |
|
175 |
+
public function getSiteName() {
|
176 |
+
if ( empty( $this->m_sSiteName ) ) {
|
177 |
+
$this->m_sSiteName = function_exists( 'get_bloginfo' )? get_bloginfo('name') : 'WordPress Site';
|
178 |
+
}
|
179 |
+
return $this->m_sSiteName;
|
180 |
+
}
|
181 |
+
|
182 |
+
public function getThrottleLimit() {
|
183 |
+
if ( empty( $this->m_nEmailThrottleLimit ) ) {
|
184 |
+
$this->m_nEmailThrottleLimit = $this->m_aOptions[ 'send_email_throttle_limit' ];
|
185 |
+
}
|
186 |
+
return $this->m_nEmailThrottleLimit;
|
187 |
}
|
188 |
}
|
189 |
|
190 |
+
endif;
|
191 |
+
|
192 |
+
if ( !class_exists('ICWP_WPSF_EmailProcessor') ):
|
193 |
+
class ICWP_WPSF_EmailProcessor extends ICWP_EmailProcessor_V1 { }
|
194 |
endif;
|
src/icwp-processor-firewall.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* Copyright (c)
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
@@ -17,9 +17,11 @@
|
|
17 |
|
18 |
require_once( dirname(__FILE__).'/icwp-base-processor.php' );
|
19 |
|
20 |
-
if ( !class_exists('
|
21 |
|
22 |
-
class
|
|
|
|
|
23 |
|
24 |
protected $m_nRequestTimestamp;
|
25 |
|
@@ -34,6 +36,11 @@ class ICWP_FirewallProcessor extends ICWP_BaseProcessor_WPSF {
|
|
34 |
private $m_nLoopProtect;
|
35 |
private $m_sFirewallMessage;
|
36 |
|
|
|
|
|
|
|
|
|
|
|
37 |
/**
|
38 |
* @var string
|
39 |
*/
|
@@ -63,15 +70,15 @@ class ICWP_FirewallProcessor extends ICWP_BaseProcessor_WPSF {
|
|
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
|
75 |
*/
|
76 |
public function setOptions( &$inaOptions ) {
|
77 |
parent::setOptions( $inaOptions );
|
@@ -83,16 +90,17 @@ class ICWP_FirewallProcessor extends ICWP_BaseProcessor_WPSF {
|
|
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->
|
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->
|
96 |
}
|
97 |
|
98 |
/**
|
@@ -109,13 +117,14 @@ class ICWP_FirewallProcessor extends ICWP_BaseProcessor_WPSF {
|
|
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
|
119 |
*/
|
120 |
public function flushLogData() {
|
121 |
|
@@ -138,25 +147,36 @@ class ICWP_FirewallProcessor extends ICWP_BaseProcessor_WPSF {
|
|
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( '
|
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
|
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
|
160 |
);
|
161 |
return true;
|
162 |
}
|
@@ -164,37 +184,36 @@ class ICWP_FirewallProcessor extends ICWP_BaseProcessor_WPSF {
|
|
164 |
// Check if the visitor is excluded from the firewall from the outset.
|
165 |
if ( $this->isVisitorOnWhitelist() ) {
|
166 |
$this->logInfo(
|
167 |
-
sprintf( 'Visitor is
|
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
|
179 |
-
empty( $this->m_sListItemLabel )? 'No label.' : $this->m_sListItemLabel
|
180 |
)
|
181 |
);
|
|
|
182 |
return false;
|
183 |
}
|
184 |
|
185 |
-
|
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 |
|
@@ -210,6 +229,9 @@ class ICWP_FirewallProcessor extends ICWP_BaseProcessor_WPSF {
|
|
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 |
}
|
@@ -220,33 +242,6 @@ class ICWP_FirewallProcessor extends ICWP_BaseProcessor_WPSF {
|
|
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',
|
@@ -255,7 +250,8 @@ class ICWP_FirewallProcessor extends ICWP_BaseProcessor_WPSF {
|
|
255 |
);
|
256 |
$fPass = $this->doPassCheck( $this->m_aPageParamValuesToCheck, $aTerms );
|
257 |
if ( !$fPass ) {
|
258 |
-
$this->logWarning( 'Blocked Directory Traversal
|
|
|
259 |
}
|
260 |
return $fPass;
|
261 |
}
|
@@ -268,7 +264,8 @@ class ICWP_FirewallProcessor extends ICWP_BaseProcessor_WPSF {
|
|
268 |
);
|
269 |
$fPass = $this->doPassCheck( $this->m_aPageParamValuesToCheck, $aTerms, true );
|
270 |
if ( !$fPass ) {
|
271 |
-
$this->logWarning( '
|
|
|
272 |
}
|
273 |
return $fPass;
|
274 |
}
|
@@ -281,9 +278,11 @@ class ICWP_FirewallProcessor extends ICWP_BaseProcessor_WPSF {
|
|
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 |
}
|
@@ -295,11 +294,24 @@ class ICWP_FirewallProcessor extends ICWP_BaseProcessor_WPSF {
|
|
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',
|
@@ -315,7 +327,8 @@ class ICWP_FirewallProcessor extends ICWP_BaseProcessor_WPSF {
|
|
315 |
}
|
316 |
$fPass = $this->doPassCheck( $aFileNames, $aTerms, true );
|
317 |
if ( !$fPass ) {
|
318 |
-
$this->logWarning( 'Blocked EXE File Uploads
|
|
|
319 |
}
|
320 |
return $fPass;
|
321 |
}
|
@@ -328,7 +341,8 @@ class ICWP_FirewallProcessor extends ICWP_BaseProcessor_WPSF {
|
|
328 |
);
|
329 |
$fPass = $this->doPassCheck( $this->m_aPageParamValuesToCheck, $aTerms, true );
|
330 |
if ( !$fPass ) {
|
331 |
-
$this->logWarning( 'Blocked Leading Schema
|
|
|
332 |
}
|
333 |
return $fPass;
|
334 |
}
|
@@ -375,7 +389,7 @@ class ICWP_FirewallProcessor extends ICWP_BaseProcessor_WPSF {
|
|
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
|
379 |
);
|
380 |
return false;
|
381 |
}
|
@@ -392,22 +406,22 @@ class ICWP_FirewallProcessor extends ICWP_BaseProcessor_WPSF {
|
|
392 |
switch( $this->m_aOptions['block_response'] ) {
|
393 |
case 'redirect_die':
|
394 |
$this->logWarning(
|
395 |
-
sprintf( 'Firewall Block: Visitor connection was killed with
|
396 |
);
|
397 |
break;
|
398 |
case 'redirect_die_message':
|
399 |
$this->logWarning(
|
400 |
-
sprintf( 'Firewall Block: Visitor connection was killed with
|
401 |
);
|
402 |
break;
|
403 |
case 'redirect_home':
|
404 |
$this->logWarning(
|
405 |
-
sprintf( 'Firewall Block: Visitor was sent HOME
|
406 |
);
|
407 |
break;
|
408 |
case 'redirect_404':
|
409 |
$this->logWarning(
|
410 |
-
sprintf( 'Firewall Block
|
411 |
);
|
412 |
break;
|
413 |
}
|
@@ -421,10 +435,9 @@ class ICWP_FirewallProcessor extends ICWP_BaseProcessor_WPSF {
|
|
421 |
|
422 |
switch( $this->m_aOptions['block_response'] ) {
|
423 |
case 'redirect_die':
|
424 |
-
|
425 |
case 'redirect_die_message':
|
426 |
wp_die( $this->m_sFirewallMessage );
|
427 |
-
exit();
|
428 |
break;
|
429 |
case 'redirect_home':
|
430 |
header( "Location: ".home_url() );
|
@@ -432,17 +445,18 @@ class ICWP_FirewallProcessor extends ICWP_BaseProcessor_WPSF {
|
|
432 |
break;
|
433 |
case 'redirect_404':
|
434 |
header( "Location: ".home_url().'/404' );
|
435 |
-
|
|
|
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() {
|
@@ -477,7 +491,7 @@ class ICWP_FirewallProcessor extends ICWP_BaseProcessor_WPSF {
|
|
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 ) {
|
@@ -489,7 +503,9 @@ class ICWP_FirewallProcessor extends ICWP_BaseProcessor_WPSF {
|
|
489 |
}
|
490 |
}
|
491 |
else {
|
492 |
-
|
|
|
|
|
493 |
$fPageWhitelisted = true;
|
494 |
break;
|
495 |
}
|
@@ -505,10 +521,11 @@ class ICWP_FirewallProcessor extends ICWP_BaseProcessor_WPSF {
|
|
505 |
}
|
506 |
}
|
507 |
|
508 |
-
//
|
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 ) {
|
@@ -520,6 +537,7 @@ class ICWP_FirewallProcessor extends ICWP_BaseProcessor_WPSF {
|
|
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 |
}
|
@@ -530,11 +548,15 @@ class ICWP_FirewallProcessor extends ICWP_BaseProcessor_WPSF {
|
|
530 |
|
531 |
if ( !isset( $_SERVER['REQUEST_URI'] ) || empty( $_SERVER['REQUEST_URI'] ) ) {
|
532 |
$this->m_aRequestUriParts = false;
|
533 |
-
$this->logWarning(
|
|
|
|
|
534 |
return false;
|
535 |
}
|
536 |
$this->m_aRequestUriParts = explode( '?', $_SERVER['REQUEST_URI'] );
|
537 |
-
$this->logInfo(
|
|
|
|
|
538 |
return true;
|
539 |
}
|
540 |
|
@@ -547,6 +569,9 @@ class ICWP_FirewallProcessor extends ICWP_BaseProcessor_WPSF {
|
|
547 |
if ( !empty( $this->m_aPageParams ) ) {
|
548 |
$this->filterWhitelistedPagesAndParams();
|
549 |
}
|
|
|
|
|
|
|
550 |
return true;
|
551 |
}
|
552 |
|
@@ -558,7 +583,8 @@ class ICWP_FirewallProcessor extends ICWP_BaseProcessor_WPSF {
|
|
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(
|
@@ -600,21 +626,24 @@ class ICWP_FirewallProcessor extends ICWP_BaseProcessor_WPSF {
|
|
600 |
|
601 |
$sIp = long2ip( $this->m_nRequestIp );
|
602 |
$aMessage = array(
|
603 |
-
'WordPress Simple Firewall has blocked a
|
604 |
-
'Log details for this visitor are below:',
|
605 |
-
'- IP Address: '
|
606 |
);
|
607 |
foreach( $this->m_aLogMessages as $aLogItem ) {
|
608 |
list( $sLogType, $sLogMessage ) = $aLogItem;
|
609 |
-
$aMessage[] = '-
|
610 |
}
|
611 |
-
|
612 |
-
|
613 |
-
$
|
614 |
-
|
615 |
-
$this->logInfo( 'Firewall block email.' );
|
616 |
$this->sendEmail( $sEmailSubject, $aMessage );
|
|
|
617 |
}
|
618 |
}
|
619 |
|
|
|
|
|
|
|
|
|
620 |
endif;
|
1 |
<?php
|
2 |
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
17 |
|
18 |
require_once( dirname(__FILE__).'/icwp-base-processor.php' );
|
19 |
|
20 |
+
if ( !class_exists('ICWP_FirewallProcessor_V1') ):
|
21 |
|
22 |
+
class ICWP_FirewallProcessor_V1 extends ICWP_WPSF_BaseProcessor {
|
23 |
+
|
24 |
+
const Slug = 'firewall';
|
25 |
|
26 |
protected $m_nRequestTimestamp;
|
27 |
|
36 |
private $m_nLoopProtect;
|
37 |
private $m_sFirewallMessage;
|
38 |
|
39 |
+
/**
|
40 |
+
* @var boolean
|
41 |
+
*/
|
42 |
+
protected $m_fRequestIsWhitelisted;
|
43 |
+
|
44 |
/**
|
45 |
* @var string
|
46 |
*/
|
70 |
*/
|
71 |
protected $m_aPageParamValues;
|
72 |
|
73 |
+
public function __construct( $insOptionPrefix = '' ) {
|
74 |
+
parent::__construct( $this->constructStorageKey( $insOptionPrefix, self::Slug ) );
|
75 |
|
76 |
$sMessage = "You were blocked by the %sWordPress Simple Firewall%s.";
|
77 |
$this->m_sFirewallMessage = sprintf( $sMessage, '<a href="http://wordpress.org/plugins/wp-simple-firewall/" target="_blank">', '</a>');
|
78 |
}
|
79 |
|
80 |
/**
|
81 |
+
* @see ICWP_WPSF_BaseProcessor::setOptions()
|
82 |
*/
|
83 |
public function setOptions( &$inaOptions ) {
|
84 |
parent::setOptions( $inaOptions );
|
90 |
'block_sql_queries',
|
91 |
'block_wordpress_terms',
|
92 |
'block_field_truncation',
|
93 |
+
'block_php_code',
|
94 |
'block_exe_file_uploads',
|
95 |
'block_leading_schema'
|
96 |
);
|
97 |
$this->m_aBlockSettings = array();
|
98 |
foreach( $aSettingSlugs as $sSettingKey ) {
|
99 |
+
$this->m_aBlockSettings[ $sSettingKey ] = $this->getOption( $sSettingKey ) == 'Y';
|
100 |
}
|
101 |
|
102 |
$this->m_aCustomWhitelistPageParams = is_array( $this->m_aOptions[ 'page_params_whitelist' ] )? $this->m_aOptions[ 'page_params_whitelist' ] : array();
|
103 |
+
$this->setLogging( $this->getOption('enable_firewall_log') == 'Y' );
|
104 |
}
|
105 |
|
106 |
/**
|
117 |
parent::reset();
|
118 |
$this->m_nRequestTimestamp = time();
|
119 |
$this->m_nLoopProtect = 0;
|
120 |
+
$this->m_fRequestIsWhitelisted = false;
|
121 |
}
|
122 |
|
123 |
/**
|
124 |
* Should return false when logging is disabled.
|
125 |
*
|
126 |
* @return false|array - false when logging is disabled, array with log data otherwise
|
127 |
+
* @see ICWP_WPSF_BaseProcessor::getLogData()
|
128 |
*/
|
129 |
public function flushLogData() {
|
130 |
|
147 |
* @return boolean - true if visitor is permitted, false if it should be blocked.
|
148 |
*/
|
149 |
public function doFirewallCheck() {
|
150 |
+
|
151 |
+
if ( $this->getOption('whitelist_admins') == 'Y' && is_super_admin() ) {
|
152 |
+
$this->logInfo( _wpsf__('Logged-in administrators currently by-pass all firewall checking.') );
|
153 |
+
return true;
|
154 |
+
}
|
155 |
|
156 |
// if we couldn't process the REQUEST_URI parts, we can't firewall so we effectively whitelist without erroring.
|
157 |
$this->setRequestUriPageParts();
|
158 |
if ( empty( $this->m_aRequestUriParts ) ) {
|
159 |
+
$this->logInfo( _wpsf__('Cannot Run Firewall checking because parsing the URI failed.') );
|
160 |
return true;
|
161 |
}
|
162 |
+
|
163 |
+
$this->loadDataProcessor();
|
164 |
+
if ( $this->getOption('ignore_search_engines') == 'Y' && ICWP_WPSF_DataProcessor::IsSearchEngineBot() ) {
|
165 |
+
$this->logInfo( _wpsf__('Visitor detected as Search Engine Bot so by-passing Firewall Checking.') );
|
166 |
+
return true;
|
167 |
+
}
|
168 |
+
|
169 |
// 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.
|
170 |
$this->setPageParams();
|
171 |
if ( empty( $this->m_aPageParams ) ) {
|
172 |
+
$this->logInfo( _wpsf__('After whitelist options were applied, there were no page parameters to check on this visit.') );
|
173 |
return true;
|
174 |
}
|
175 |
$this->m_aPageParamValuesToCheck = array_values( $this->m_aPageParams );
|
176 |
|
177 |
if ( $this->m_nRequestIp === false ) {
|
178 |
$this->logCritical(
|
179 |
+
_wpsf__("Visitor IP address could not be determined so by-passing the Firewall.")
|
180 |
);
|
181 |
return true;
|
182 |
}
|
184 |
// Check if the visitor is excluded from the firewall from the outset.
|
185 |
if ( $this->isVisitorOnWhitelist() ) {
|
186 |
$this->logInfo(
|
187 |
+
sprintf( _wpsf__('Visitor is white-listed by IP Address. Label: %s'),
|
188 |
+
empty( $this->m_sListItemLabel )? _wpsf__('No label.') : $this->m_sListItemLabel
|
189 |
)
|
190 |
);
|
191 |
+
$this->doStatIncrement( 'firewall.allowed.whitelist' );
|
192 |
return true;
|
193 |
}
|
194 |
|
195 |
+
// Check if the visitor is excluded from the firewall from the outset.
|
196 |
if ( $this->isVisitorOnBlacklist() ) {
|
197 |
$this->m_sFirewallMessage .= ' Your IP is Blacklisted.';
|
198 |
$this->logWarning(
|
199 |
+
sprintf( _wpsf__('Visitor was black-listed by IP Address. Label: %s'),
|
200 |
+
empty( $this->m_sListItemLabel )? _wpsf__('No label.') : $this->m_sListItemLabel
|
201 |
)
|
202 |
);
|
203 |
+
$this->doStatIncrement( 'firewall.blocked.blacklist' );
|
204 |
return false;
|
205 |
}
|
206 |
|
207 |
+
$this->logInfo( _wpsf__('Visitor IP was neither white-listed nor black-listed. Firewall checking started...') );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
208 |
|
209 |
$fIsPermittedVisitor = true;
|
210 |
|
211 |
// Check if the page and its parameters are whitelisted.
|
212 |
if ( $fIsPermittedVisitor && $this->isPageWhitelisted() ) {
|
213 |
+
$this->logWarning(
|
214 |
+
_wpsf__('All page request parameters were white-listed.' )
|
215 |
+
);
|
216 |
+
$this->doStatIncrement( 'firewall.allowed.pagewhitelist' );
|
217 |
return true;
|
218 |
}
|
219 |
|
229 |
if ( $fIsPermittedVisitor && $this->m_aBlockSettings[ 'block_field_truncation' ] ) {
|
230 |
$fIsPermittedVisitor = $this->doPassCheckBlockFieldTruncation();
|
231 |
}
|
232 |
+
if ( $fIsPermittedVisitor && $this->m_aBlockSettings[ 'block_php_code' ] ) {
|
233 |
+
$fIsPermittedVisitor = $this->doPassCheckPhpCode();
|
234 |
+
}
|
235 |
if ( $fIsPermittedVisitor && $this->m_aBlockSettings[ 'block_exe_file_uploads' ] ) {
|
236 |
$fIsPermittedVisitor = $this->doPassCheckBlockExeFileUploads();
|
237 |
}
|
242 |
return $fIsPermittedVisitor;
|
243 |
}
|
244 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
245 |
protected function doPassCheckBlockDirTraversal() {
|
246 |
$aTerms = array(
|
247 |
'etc/passwd',
|
250 |
);
|
251 |
$fPass = $this->doPassCheck( $this->m_aPageParamValuesToCheck, $aTerms );
|
252 |
if ( !$fPass ) {
|
253 |
+
$this->logWarning( sprintf( _wpsf__('Firewall Blocked: %s'), _wpsf__('Directory Traversal') ) );
|
254 |
+
$this->doStatIncrement( 'firewall.blocked.dirtraversal' );
|
255 |
}
|
256 |
return $fPass;
|
257 |
}
|
264 |
);
|
265 |
$fPass = $this->doPassCheck( $this->m_aPageParamValuesToCheck, $aTerms, true );
|
266 |
if ( !$fPass ) {
|
267 |
+
$this->logWarning( sprintf( _wpsf__('Firewall Blocked: %s'), _wpsf__('SQL Queries') ) );
|
268 |
+
$this->doStatIncrement( 'firewall.blocked.sqlqueries' );
|
269 |
}
|
270 |
return $fPass;
|
271 |
}
|
278 |
'/0x[0-9a-f][0-9a-f]/i',
|
279 |
'/\/\*\*\//'
|
280 |
);
|
281 |
+
|
282 |
$fPass = $this->doPassCheck( $this->m_aPageParamValuesToCheck, $aTerms, true );
|
283 |
if ( !$fPass ) {
|
284 |
+
$this->logWarning( sprintf( _wpsf__('Firewall Blocked: %s'), _wpsf__('WordPress Terms') ) );
|
285 |
+
$this->doStatIncrement( 'firewall.blocked.wpterms' );
|
286 |
}
|
287 |
return $fPass;
|
288 |
}
|
294 |
);
|
295 |
$fPass = $this->doPassCheck( $this->m_aPageParamValuesToCheck, $aTerms, true );
|
296 |
if ( !$fPass ) {
|
297 |
+
$this->logWarning( sprintf( _wpsf__('Firewall Blocked: %s'), _wpsf__('Field Truncation') ) );
|
298 |
+
$this->doStatIncrement( 'firewall.blocked.fieldtruncation' );
|
299 |
}
|
300 |
return $fPass;
|
301 |
}
|
302 |
+
|
303 |
+
protected function doPassCheckPhpCode() {
|
304 |
+
$aTerms = array(
|
305 |
+
'/(include|include_once|require|require_once)(\s*\(|\s*\'|\s*"|\s+\w+)/i'
|
306 |
+
);
|
307 |
+
$fPass = $this->doPassCheck( $this->m_aPageParamValuesToCheck, $aTerms, true );
|
308 |
+
if ( !$fPass ) {
|
309 |
+
$this->logWarning( sprintf( _wpsf__('Firewall Blocked: %s'), _wpsf__('PHP Code') ) );
|
310 |
+
$this->doStatIncrement( 'firewall.blocked.phpcode' );
|
311 |
+
}
|
312 |
+
return $fPass;
|
313 |
+
}
|
314 |
+
|
315 |
protected function doPassCheckBlockExeFileUploads() {
|
316 |
$aTerms = array(
|
317 |
'/\.dll$/i', '/\.rb$/i', '/\.py$/i', '/\.exe$/i', '/\.php[3-6]?$/i', '/\.pl$/i',
|
327 |
}
|
328 |
$fPass = $this->doPassCheck( $aFileNames, $aTerms, true );
|
329 |
if ( !$fPass ) {
|
330 |
+
$this->logWarning( sprintf( _wpsf__('Firewall Blocked: %s'), _wpsf__('EXE File Uploads') ) );
|
331 |
+
$this->doStatIncrement( 'firewall.blocked.exefile' );
|
332 |
}
|
333 |
return $fPass;
|
334 |
}
|
341 |
);
|
342 |
$fPass = $this->doPassCheck( $this->m_aPageParamValuesToCheck, $aTerms, true );
|
343 |
if ( !$fPass ) {
|
344 |
+
$this->logWarning( sprintf( _wpsf__('Firewall Blocked: %s'), _wpsf__('Leading Schema') ) );
|
345 |
+
$this->doStatIncrement( 'firewall.blocked.schema' );
|
346 |
}
|
347 |
return $fPass;
|
348 |
}
|
389 |
if ( $fFAIL ) {
|
390 |
$this->m_sFirewallMessage .= " Something in the URL, Form or Cookie data wasn't appropriate.";
|
391 |
$this->logWarning(
|
392 |
+
sprintf( 'Page parameter failed firewall check. The offending value was %s', $mValue )
|
393 |
);
|
394 |
return false;
|
395 |
}
|
406 |
switch( $this->m_aOptions['block_response'] ) {
|
407 |
case 'redirect_die':
|
408 |
$this->logWarning(
|
409 |
+
sprintf( _wpsf__('Firewall Block Response: %s'), _wpsf__('Visitor connection was killed with wp_die()') )
|
410 |
);
|
411 |
break;
|
412 |
case 'redirect_die_message':
|
413 |
$this->logWarning(
|
414 |
+
sprintf( _wpsf__('Firewall Block Response: %s'), _wpsf__('Visitor connection was killed with wp_die() and message') )
|
415 |
);
|
416 |
break;
|
417 |
case 'redirect_home':
|
418 |
$this->logWarning(
|
419 |
+
sprintf( _wpsf__('Firewall Block Response: %s'), _wpsf__('Visitor was sent HOME') )
|
420 |
);
|
421 |
break;
|
422 |
case 'redirect_404':
|
423 |
$this->logWarning(
|
424 |
+
sprintf( _wpsf__('Firewall Block Response: %s'), _wpsf__('Visitor was sent 404') )
|
425 |
);
|
426 |
break;
|
427 |
}
|
435 |
|
436 |
switch( $this->m_aOptions['block_response'] ) {
|
437 |
case 'redirect_die':
|
438 |
+
break;
|
439 |
case 'redirect_die_message':
|
440 |
wp_die( $this->m_sFirewallMessage );
|
|
|
441 |
break;
|
442 |
case 'redirect_home':
|
443 |
header( "Location: ".home_url() );
|
445 |
break;
|
446 |
case 'redirect_404':
|
447 |
header( "Location: ".home_url().'/404' );
|
448 |
+
break;
|
449 |
+
default:
|
450 |
break;
|
451 |
}
|
452 |
+
exit();
|
453 |
}
|
454 |
|
455 |
/**
|
|
|
456 |
* @return boolean
|
457 |
*/
|
458 |
public function isPageWhitelisted() {
|
459 |
+
return empty( $this->m_aPageParams ) || $this->m_fRequestIsWhitelisted;
|
460 |
}
|
461 |
|
462 |
public function filterWhitelistedPagesAndParams() {
|
491 |
|
492 |
// Now we compare pages in the whitelist with the parts of the request uri. If we get a match, that page is whitelisted
|
493 |
$aWhitelistPages = array_keys( $inaWhitelistPagesParams );
|
494 |
+
|
495 |
// 1. Is the page in the list of white pages?
|
496 |
$fPageWhitelisted = false;
|
497 |
foreach ( $inaWhitelistPagesParams as $sPageName => $aWhitlistedParams ) {
|
503 |
}
|
504 |
}
|
505 |
else {
|
506 |
+
$sWhitelistedPageAsPreg = preg_quote( $sPageName, self::PcreDelimiter );
|
507 |
+
$sWhitelistedPageAsPreg = sprintf( '%s%s$%s', self::PcreDelimiter, $sWhitelistedPageAsPreg, self::PcreDelimiter );
|
508 |
+
if ( preg_match( $sWhitelistedPageAsPreg, $sRequestPage ) ) {
|
509 |
$fPageWhitelisted = true;
|
510 |
break;
|
511 |
}
|
521 |
}
|
522 |
}
|
523 |
|
524 |
+
// Given the page is found to be on the whitelist, we want to check if it's the whole page, or certain parameters only
|
525 |
if ( $fPageWhitelisted ) {
|
526 |
// the current page is whitelisted - now check if it has request parameters.
|
527 |
if ( empty( $aWhitlistedParams ) ) {
|
528 |
+
$this->m_fRequestIsWhitelisted = true;
|
529 |
return true; //because it's just plain whitelisted as represented by an empty or unset array
|
530 |
}
|
531 |
foreach ( $aWhitlistedParams as $sWhitelistParam ) {
|
537 |
// After removing all the whitelisted params, we now check if there are any params left that'll
|
538 |
// need matched later in the firewall checking. If there are no parameters left, we return true.
|
539 |
if ( empty( $this->m_aPageParams ) ) {
|
540 |
+
$this->m_fRequestIsWhitelisted = true;
|
541 |
return true;
|
542 |
}
|
543 |
}
|
548 |
|
549 |
if ( !isset( $_SERVER['REQUEST_URI'] ) || empty( $_SERVER['REQUEST_URI'] ) ) {
|
550 |
$this->m_aRequestUriParts = false;
|
551 |
+
$this->logWarning(
|
552 |
+
sprintf( _wpsf__('Could not parse the details of this page call as "%s" was empty or not defined '), $_SERVER['REQUEST_URI'] )
|
553 |
+
);
|
554 |
return false;
|
555 |
}
|
556 |
$this->m_aRequestUriParts = explode( '?', $_SERVER['REQUEST_URI'] );
|
557 |
+
$this->logInfo(
|
558 |
+
sprintf( _wpsf__('Page Request URI: %s'), $_SERVER['REQUEST_URI'] )
|
559 |
+
);
|
560 |
return true;
|
561 |
}
|
562 |
|
569 |
if ( !empty( $this->m_aPageParams ) ) {
|
570 |
$this->filterWhitelistedPagesAndParams();
|
571 |
}
|
572 |
+
else {
|
573 |
+
$this->m_fRequestIsWhitelisted = true;
|
574 |
+
}
|
575 |
return true;
|
576 |
}
|
577 |
|
583 |
'/wp-admin/page-new.php' => array(),
|
584 |
'/wp-admin/link-add.php' => array(),
|
585 |
'/wp-admin/media-upload.php' => array(),
|
586 |
+
'/wp-admin/post.php' => array( 'content' ),
|
587 |
+
'/wp-admin/plugin-editor.php' => array( 'newcontent' ),
|
588 |
'/wp-admin/page.php' => array(),
|
589 |
'/wp-admin/admin-ajax.php' => array(),
|
590 |
'/wp-comments-post.php' => array(
|
626 |
|
627 |
$sIp = long2ip( $this->m_nRequestIp );
|
628 |
$aMessage = array(
|
629 |
+
_wpsf__('WordPress Simple Firewall has blocked a page visit to your site.'),
|
630 |
+
_wpsf__('Log details for this visitor are below:'),
|
631 |
+
'- '.sprintf( _wpsf__('IP Address: %s'), $sIp )
|
632 |
);
|
633 |
foreach( $this->m_aLogMessages as $aLogItem ) {
|
634 |
list( $sLogType, $sLogMessage ) = $aLogItem;
|
635 |
+
$aMessage[] = '- '.$sLogMessage;
|
636 |
}
|
637 |
+
$aMessage[] = sprintf( _wpsf__('You can look up the offending IP Address here: %s'), 'http://ip-lookup.net/?ip='.$sIp );
|
638 |
+
|
639 |
+
$sEmailSubject = sprintf( _wpsf__('Firewall Block Email Alert: %s'), home_url() );
|
|
|
|
|
640 |
$this->sendEmail( $sEmailSubject, $aMessage );
|
641 |
+
$this->logInfo( _wpsf__('Firewall block email alert sent.') );
|
642 |
}
|
643 |
}
|
644 |
|
645 |
+
endif;
|
646 |
+
|
647 |
+
if ( !class_exists('ICWP_WPSF_FirewallProcessor') ):
|
648 |
+
class ICWP_WPSF_FirewallProcessor extends ICWP_FirewallProcessor_V1 { }
|
649 |
endif;
|
src/icwp-processor-lockdown.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* Copyright (c)
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
@@ -17,50 +17,67 @@
|
|
17 |
|
18 |
require_once( dirname(__FILE__).'/icwp-base-processor.php' );
|
19 |
|
20 |
-
if ( !class_exists('
|
21 |
|
22 |
-
class
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
parent::reset();
|
29 |
}
|
30 |
-
|
31 |
/**
|
32 |
*/
|
33 |
public function run() {
|
34 |
|
35 |
-
if ( $this->
|
|
|
|
|
|
|
36 |
add_filter( 'user_has_cap', array( $this, 'disableFileEditing' ), 0, 3 );
|
37 |
}
|
38 |
-
|
39 |
-
|
|
|
40 |
global $wp_version;
|
41 |
-
$wp_version = $
|
42 |
// add_filter( 'bloginfo', array( $this, 'maskWordpressVersion' ), 1, 2 );
|
43 |
// add_filter( 'bloginfo_url', array( $this, 'maskWordpressVersion' ), 1, 2 );
|
44 |
-
}
|
45 |
|
46 |
-
if ( false && $this->
|
47 |
add_action( 'init', array( $this, 'resetAuthKeysSalts' ), 1 );
|
48 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
}
|
50 |
-
|
51 |
/**
|
52 |
* @return array
|
53 |
*/
|
54 |
-
public function disableFileEditing( $
|
55 |
|
56 |
$aEditCapabilities = array( 'edit_themes', 'edit_plugins', 'edit_files' );
|
57 |
-
$sRequestedCapability = $
|
58 |
|
59 |
if ( !in_array( $sRequestedCapability, $aEditCapabilities ) ) {
|
60 |
-
return $
|
61 |
}
|
62 |
-
$
|
63 |
-
return $
|
64 |
}
|
65 |
|
66 |
/**
|
@@ -77,15 +94,13 @@ class ICWP_LockdownProcessor extends ICWP_BaseProcessor_WPSF {
|
|
77 |
*
|
78 |
*/
|
79 |
public function resetAuthKeysSalts() {
|
80 |
-
|
81 |
-
require_once( dirname(__FILE__).'/icwp-wpfilesystem.php' );
|
82 |
-
$oWpFilesystem = new ICWP_WpFilesystem_WPSF();
|
83 |
|
84 |
// Get the new Salts
|
85 |
$sSaltsUrl = 'https://api.wordpress.org/secret-key/1.1/salt/';
|
86 |
-
$sSalts = $
|
87 |
|
88 |
-
$sWpConfigContent = $
|
89 |
if ( is_null( $sWpConfigContent ) ) {
|
90 |
return;
|
91 |
}
|
@@ -119,8 +134,12 @@ class ICWP_LockdownProcessor extends ICWP_BaseProcessor_WPSF {
|
|
119 |
}
|
120 |
}
|
121 |
$aContent[$nStartLine] = $sSalts;
|
122 |
-
$
|
123 |
}
|
124 |
}
|
125 |
|
|
|
|
|
|
|
|
|
126 |
endif;
|
1 |
<?php
|
2 |
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
17 |
|
18 |
require_once( dirname(__FILE__).'/icwp-base-processor.php' );
|
19 |
|
20 |
+
if ( !class_exists('ICWP_LockdownProcessor_V1') ):
|
21 |
|
22 |
+
class ICWP_LockdownProcessor_V1 extends ICWP_WPSF_BaseProcessor {
|
23 |
+
|
24 |
+
const Slug = 'lockdown';
|
25 |
+
|
26 |
+
public function __construct( $insOptionPrefix = '' ) {
|
27 |
+
parent::__construct( $this->constructStorageKey( $insOptionPrefix, self::Slug ) );
|
|
|
28 |
}
|
29 |
+
|
30 |
/**
|
31 |
*/
|
32 |
public function run() {
|
33 |
|
34 |
+
if ( $this->getIsOption( 'disable_file_editing', 'Y' ) ) {
|
35 |
+
if ( !defined('DISALLOW_FILE_EDIT') ) {
|
36 |
+
define( 'DISALLOW_FILE_EDIT', true );
|
37 |
+
}
|
38 |
add_filter( 'user_has_cap', array( $this, 'disableFileEditing' ), 0, 3 );
|
39 |
}
|
40 |
+
|
41 |
+
$sWpVersionMask = $this->getOption('mask_wordpress_version');
|
42 |
+
if ( !empty( $sWpVersionMask ) ) {
|
43 |
global $wp_version;
|
44 |
+
$wp_version = $sWpVersionMask;
|
45 |
// add_filter( 'bloginfo', array( $this, 'maskWordpressVersion' ), 1, 2 );
|
46 |
// add_filter( 'bloginfo_url', array( $this, 'maskWordpressVersion' ), 1, 2 );
|
47 |
+
}
|
48 |
|
49 |
+
if ( false && $this->getOption('action_reset_auth_salts') == 'Y' ) {
|
50 |
add_action( 'init', array( $this, 'resetAuthKeysSalts' ), 1 );
|
51 |
}
|
52 |
+
|
53 |
+
if ( $this->getIsOption( 'force_ssl_login', 'Y' ) && function_exists('force_ssl_login') ) {
|
54 |
+
if ( !defined('FORCE_SSL_LOGIN') ) {
|
55 |
+
define( 'FORCE_SSL_LOGIN', true );
|
56 |
+
}
|
57 |
+
force_ssl_login( true );
|
58 |
+
}
|
59 |
+
|
60 |
+
if ( $this->getIsOption( 'force_ssl_admin', 'Y' ) && function_exists('force_ssl_admin') ) {
|
61 |
+
if ( !defined('FORCE_SSL_ADMIN') ) {
|
62 |
+
define( 'FORCE_SSL_ADMIN', true );
|
63 |
+
}
|
64 |
+
force_ssl_admin( true );
|
65 |
+
}
|
66 |
}
|
67 |
+
|
68 |
/**
|
69 |
* @return array
|
70 |
*/
|
71 |
+
public function disableFileEditing( $aAllCaps, $cap, $aArgs ) {
|
72 |
|
73 |
$aEditCapabilities = array( 'edit_themes', 'edit_plugins', 'edit_files' );
|
74 |
+
$sRequestedCapability = $aArgs[0];
|
75 |
|
76 |
if ( !in_array( $sRequestedCapability, $aEditCapabilities ) ) {
|
77 |
+
return $aAllCaps;
|
78 |
}
|
79 |
+
$aAllCaps[ $sRequestedCapability ] = false;
|
80 |
+
return $aAllCaps;
|
81 |
}
|
82 |
|
83 |
/**
|
94 |
*
|
95 |
*/
|
96 |
public function resetAuthKeysSalts() {
|
97 |
+
$oWpFs = $this->loadFileSystemProcessor();
|
|
|
|
|
98 |
|
99 |
// Get the new Salts
|
100 |
$sSaltsUrl = 'https://api.wordpress.org/secret-key/1.1/salt/';
|
101 |
+
$sSalts = $oWpFs->getUrlContent( $sSaltsUrl );
|
102 |
|
103 |
+
$sWpConfigContent = $oWpFs->getContent_WpConfig();
|
104 |
if ( is_null( $sWpConfigContent ) ) {
|
105 |
return;
|
106 |
}
|
134 |
}
|
135 |
}
|
136 |
$aContent[$nStartLine] = $sSalts;
|
137 |
+
$oWpFs->putContent_WpConfig( implode( PHP_EOL, $aContent ) );
|
138 |
}
|
139 |
}
|
140 |
|
141 |
+
endif;
|
142 |
+
|
143 |
+
if ( !class_exists('ICWP_WPSF_LockdownProcessor') ):
|
144 |
+
class ICWP_WPSF_LockdownProcessor extends ICWP_LockdownProcessor_V1 { }
|
145 |
endif;
|
src/icwp-processor-logging.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* Copyright (c)
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
@@ -17,25 +17,28 @@
|
|
17 |
|
18 |
require_once( dirname(__FILE__).'/icwp-basedb-processor.php' );
|
19 |
|
20 |
-
if ( !class_exists('
|
21 |
|
22 |
-
class
|
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 ) {
|
@@ -47,19 +50,12 @@ class ICWP_LoggingProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
47 |
}
|
48 |
|
49 |
/**
|
50 |
-
*
|
|
|
|
|
|
|
51 |
*/
|
52 |
-
|
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;
|
@@ -80,7 +76,6 @@ class ICWP_LoggingProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
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,
|
@@ -103,6 +98,23 @@ class ICWP_LoggingProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
103 |
$this->recreateTable();
|
104 |
}
|
105 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
106 |
}
|
107 |
|
|
|
|
|
|
|
|
|
108 |
endif;
|
1 |
<?php
|
2 |
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
17 |
|
18 |
require_once( dirname(__FILE__).'/icwp-basedb-processor.php' );
|
19 |
|
20 |
+
if ( !class_exists('ICWP_LoggingProcessor_V1') ):
|
21 |
|
22 |
+
class ICWP_LoggingProcessor_V1 extends ICWP_BaseDbProcessor_WPSF {
|
23 |
|
24 |
+
const Slug = 'logging';
|
25 |
const TableName = 'wpsf_log';
|
26 |
+
const DaysToKeepLog = 7;
|
27 |
+
|
28 |
protected $m_sRequestId;
|
29 |
+
|
30 |
+
public function __construct( $insOptionPrefix = '' ) {
|
31 |
+
parent::__construct( $this->constructStorageKey( $insOptionPrefix, self::Slug ), self::TableName );
|
32 |
$this->createTable();
|
33 |
}
|
34 |
+
|
35 |
public function reset() {
|
36 |
parent::reset();
|
37 |
$this->m_sRequestId = uniqid();
|
|
|
38 |
}
|
39 |
|
40 |
/**
|
41 |
+
* @param boolean $infReverseOrder
|
42 |
* @return array - numerical array of all log data entries.
|
43 |
*/
|
44 |
public function getLogs( $infReverseOrder = false ) {
|
50 |
}
|
51 |
|
52 |
/**
|
53 |
+
* Ensures the log data provided has all the necessary data points to be written to the DB
|
54 |
+
*
|
55 |
+
* @param array $inaLogData
|
56 |
+
* @return array
|
57 |
*/
|
58 |
+
protected function completeDataForWrite( $inaLogData ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
|
60 |
if ( !isset( $inaLogData['category'] ) ) {
|
61 |
$inaLogData['category'] = self::LOG_CATEGORY_DEFAULT;
|
76 |
}
|
77 |
|
78 |
public function createTable() {
|
|
|
79 |
// Set up log table
|
80 |
$sSqlTables = "CREATE TABLE IF NOT EXISTS `%s` (
|
81 |
`id` int(11) NOT NULL AUTO_INCREMENT,
|
98 |
$this->recreateTable();
|
99 |
}
|
100 |
}
|
101 |
+
|
102 |
+
/**
|
103 |
+
* This is hooked into a cron in the base class and overrides the parent method.
|
104 |
+
*
|
105 |
+
* It'll delete everything older than 7 days.
|
106 |
+
*/
|
107 |
+
public function cleanupDatabase() {
|
108 |
+
if ( !$this->getTableExists() ) {
|
109 |
+
return;
|
110 |
+
}
|
111 |
+
$nTimeStamp = time() - DAY_IN_SECONDS * self::DaysToKeepLog;
|
112 |
+
$this->deleteAllRowsOlderThan( $nTimeStamp );
|
113 |
+
}
|
114 |
}
|
115 |
|
116 |
+
endif;
|
117 |
+
|
118 |
+
if ( !class_exists('ICWP_WPSF_LoggingProcessor') ):
|
119 |
+
class ICWP_WPSF_LoggingProcessor extends ICWP_LoggingProcessor_V1 { }
|
120 |
endif;
|
src/icwp-processor-loginprotect.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* Copyright (c)
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
@@ -17,12 +17,15 @@
|
|
17 |
|
18 |
require_once( dirname(__FILE__).'/icwp-basedb-processor.php' );
|
19 |
|
20 |
-
if ( !class_exists('
|
21 |
|
22 |
-
class
|
23 |
|
|
|
24 |
const TableName = 'login_auth';
|
25 |
-
|
|
|
|
|
26 |
/**
|
27 |
* @var string
|
28 |
*/
|
@@ -33,11 +36,23 @@ class ICWP_LoginProtectProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
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
|
@@ -46,14 +61,11 @@ class ICWP_LoginProtectProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
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 |
}
|
@@ -63,6 +75,21 @@ class ICWP_LoginProtectProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
63 |
*/
|
64 |
public function reset() {
|
65 |
parent::reset();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
}
|
67 |
|
68 |
/**
|
@@ -72,13 +99,16 @@ class ICWP_LoginProtectProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
72 |
*/
|
73 |
public function setSecretKey( $insSecretKey = '' ) {
|
74 |
if ( !empty( $insSecretKey ) ) {
|
|
|
|
|
|
|
75 |
$this->m_sSecretKey = $insSecretKey;
|
76 |
}
|
77 |
}
|
78 |
|
79 |
/**
|
80 |
*
|
81 |
-
* @param array $
|
82 |
*/
|
83 |
public function setOptions( &$inaOptions ) {
|
84 |
parent::setOptions( $inaOptions );
|
@@ -91,76 +121,148 @@ class ICWP_LoginProtectProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
91 |
* @return boolean
|
92 |
*/
|
93 |
public function getNeedsEmailHandler() {
|
94 |
-
|
95 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
}
|
97 |
-
return false;
|
98 |
}
|
99 |
|
100 |
-
public function setLogging() {
|
101 |
-
parent::setLogging( $this->
|
102 |
}
|
103 |
|
104 |
/**
|
105 |
-
* @param ICWP_OptionsHandler_LoginProtect $inoOptions
|
106 |
*/
|
107 |
public function run() {
|
108 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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->
|
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' ),
|
|
|
118 |
}
|
119 |
|
120 |
-
if
|
|
|
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 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
|
|
|
|
131 |
// If their click was successful we give them a lovely message
|
132 |
-
if (
|
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 |
-
|
|
|
162 |
}
|
163 |
-
|
164 |
/**
|
165 |
* Checks whether the current user that is logged-in is authenticated by IP address.
|
166 |
*
|
@@ -169,14 +271,20 @@ class ICWP_LoginProtectProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
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
|
179 |
-
$insMessage .= '<h3 style="'.$sStyles.'">You successfully verified your
|
180 |
return $insMessage;
|
181 |
}
|
182 |
|
@@ -184,7 +292,7 @@ class ICWP_LoginProtectProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
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
|
188 |
*/
|
189 |
public function flushLogData() {
|
190 |
|
@@ -202,36 +310,40 @@ class ICWP_LoginProtectProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
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 (
|
212 |
return false;
|
213 |
}
|
214 |
-
|
|
|
|
|
|
|
215 |
return false;
|
216 |
}
|
217 |
|
218 |
$aWhere = array(
|
219 |
-
'unique_id' => $
|
220 |
-
'wp_username' => $
|
221 |
);
|
222 |
-
|
223 |
-
|
224 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
225 |
}
|
226 |
else {
|
227 |
-
|
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 |
/**
|
@@ -244,13 +356,13 @@ class ICWP_LoginProtectProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
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;
|
@@ -269,42 +381,168 @@ class ICWP_LoginProtectProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
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( "
|
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 (
|
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 |
-
|
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 |
*
|
@@ -320,7 +558,7 @@ class ICWP_LoginProtectProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
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 $
|
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.
|
@@ -340,22 +578,26 @@ class ICWP_LoginProtectProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
340 |
}
|
341 |
}
|
342 |
else if ( $fUserLoginSuccess ) {
|
343 |
-
|
344 |
-
|
345 |
-
|
|
|
|
|
|
|
346 |
return $inoUser;
|
347 |
}
|
348 |
else {
|
349 |
// Create a new 2-factor auth pending entry
|
350 |
-
$aNewAuthData = $this->
|
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->
|
359 |
return $inoUser;
|
360 |
}
|
361 |
}
|
@@ -365,11 +607,40 @@ class ICWP_LoginProtectProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
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 |
|
@@ -411,7 +682,7 @@ class ICWP_LoginProtectProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
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 |
|
@@ -428,23 +699,25 @@ class ICWP_LoginProtectProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
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 |
-
|
|
|
441 |
return false;
|
442 |
}
|
443 |
return true;
|
444 |
}
|
445 |
|
446 |
public function setTwoFactorByPassOnFail() {
|
447 |
-
$this->m_fAllowTwoFactorByPass = $this->
|
448 |
}
|
449 |
|
450 |
public function getTwoFactorByPassOnFail() {
|
@@ -453,20 +726,21 @@ class ICWP_LoginProtectProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
453 |
}
|
454 |
return $this->m_fAllowTwoFactorByPass;
|
455 |
}
|
456 |
-
|
|
|
|
|
457 |
public function setLoginCooldownInterval() {
|
458 |
-
$nInterval = intval( $this->
|
459 |
$this->m_nRequiredLoginInterval = ( $nInterval < 0 )? 0 : $nInterval;
|
460 |
}
|
461 |
|
462 |
/**
|
463 |
-
* @param
|
464 |
* @return boolean
|
465 |
*/
|
466 |
-
public function
|
467 |
|
468 |
-
|
469 |
-
if ( !$this->validateParameters( $inaData, $aChecks) ) {
|
470 |
return false;
|
471 |
}
|
472 |
|
@@ -480,23 +754,25 @@ class ICWP_LoginProtectProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
480 |
$aOldWhere = array(
|
481 |
'pending' => 1,
|
482 |
'deleted_at' => 0,
|
483 |
-
'wp_username' => $
|
484 |
);
|
485 |
$this->updateRowsFromTable( $aOldData, $aOldWhere );
|
486 |
|
487 |
// Now add new pending entry
|
488 |
-
$
|
489 |
-
$
|
490 |
-
$
|
491 |
-
$
|
492 |
-
$
|
|
|
|
|
493 |
|
494 |
-
$mResult = $this->insertIntoTable( $
|
495 |
if ( $mResult ) {
|
496 |
$this->logInfo(
|
497 |
-
sprintf( 'User "%s" created a pending Two-Factor Authentication for IP Address "%s".', $
|
498 |
);
|
499 |
-
$mResult = $
|
500 |
}
|
501 |
return $mResult;
|
502 |
}
|
@@ -507,16 +783,57 @@ class ICWP_LoginProtectProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
507 |
* @param array $inaWhere - unique_id, wp_username
|
508 |
* @return boolean
|
509 |
*/
|
510 |
-
public function
|
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',
|
@@ -530,75 +847,109 @@ class ICWP_LoginProtectProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
530 |
$this->m_sTableName,
|
531 |
$sNow,
|
532 |
$sNow,
|
533 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
534 |
);
|
535 |
$this->doSql( $sQuery );
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
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
|
554 |
* @return boolean
|
555 |
*/
|
556 |
-
public function isUserVerified( $
|
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 |
-
$
|
576 |
-
$this->m_nRequestIp
|
577 |
);
|
578 |
|
579 |
$mResult = $this->selectCustomFromTable( $sQuery );
|
|
|
580 |
if ( is_array( $mResult ) && count( $mResult ) == 1 ) {
|
581 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
582 |
}
|
583 |
else {
|
584 |
$this->logWarning(
|
585 |
-
sprintf( 'User "%s" was found to be un-verified at
|
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 |
-
|
596 |
-
if ( !$this->isUserVerified( $aData ) ) {
|
597 |
$this->logWarning(
|
598 |
-
sprintf( 'User "%s" was logged out.', $oUser->user_login )
|
599 |
);
|
|
|
600 |
wp_logout();
|
601 |
-
$this->
|
|
|
602 |
}
|
603 |
}
|
604 |
}
|
@@ -606,49 +957,62 @@ class ICWP_LoginProtectProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
606 |
/**
|
607 |
* Given the necessary components, creates the 2-factor verification link for giving to the user.
|
608 |
*
|
609 |
-
* @param string $
|
610 |
-
* @param string $
|
611 |
-
* @param string $insUniqueId
|
612 |
* @return string
|
613 |
*/
|
614 |
-
|
615 |
$sSiteUrl = home_url() . '?wpsfkey=%s&wpsf-action=%s&username=%s&uniqueid=%s';
|
616 |
$sAction = 'linkauth';
|
617 |
-
return sprintf( $sSiteUrl, $
|
618 |
}
|
619 |
|
620 |
/**
|
621 |
-
* @param
|
622 |
* @param string $insIpAddress
|
623 |
-
* @param string $
|
|
|
624 |
*/
|
625 |
public function sendEmailTwoFactorVerify( WP_User $inoUser, $insIpAddress, $insUniqueId ) {
|
626 |
|
627 |
$sEmail = $inoUser->user_email;
|
628 |
-
$sAuthLink = $this->
|
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
|
633 |
-
'To validate this
|
634 |
-
'IP Address: '
|
635 |
-
'Authentication Link: '
|
636 |
);
|
637 |
-
$sEmailSubject = 'Two-Factor Login Verification: '
|
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
|
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 |
|
@@ -681,6 +1045,40 @@ class ICWP_LoginProtectProcessor extends ICWP_BaseDbProcessor_WPSF {
|
|
681 |
$sQuery = sprintf( $sQuery, $this->m_sTableName, $inaData['unique_id'], $inaData['wp_username'] );
|
682 |
return $this->selectRowFromTable( $sQuery );
|
683 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
684 |
}
|
|
|
685 |
|
|
|
|
|
686 |
endif;
|
1 |
<?php
|
2 |
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
17 |
|
18 |
require_once( dirname(__FILE__).'/icwp-basedb-processor.php' );
|
19 |
|
20 |
+
if ( !class_exists('ICWP_LoginProtectProcessor_V2') ):
|
21 |
|
22 |
+
class ICWP_LoginProtectProcessor_V2 extends ICWP_BaseDbProcessor_WPSF {
|
23 |
|
24 |
+
const Slug = 'login_protect';
|
25 |
const TableName = 'login_auth';
|
26 |
+
const AuthActiveCookie = 'wpsf_auth';
|
27 |
+
const YubikeyVerifyApiUrl = 'https://api.yubico.com/wsapi/2.0/verify?id=%s&otp=%s&nonce=%s';
|
28 |
+
|
29 |
/**
|
30 |
* @var string
|
31 |
*/
|
36 |
* @var integer
|
37 |
*/
|
38 |
protected $m_nRequiredLoginInterval;
|
39 |
+
|
40 |
+
/**
|
41 |
+
* @var integer
|
42 |
+
*/
|
43 |
protected $m_nLastLoginTime;
|
44 |
+
/**
|
45 |
+
* @var string
|
46 |
+
*/
|
47 |
protected $m_sSecretKey;
|
48 |
+
/**
|
49 |
+
* @var string
|
50 |
+
*/
|
51 |
protected $m_sGaspKey;
|
52 |
+
/**
|
53 |
+
* @var string
|
54 |
+
*/
|
55 |
+
protected $nDaysToKeepLog = 1;
|
56 |
|
57 |
/**
|
58 |
* Flag as to whether Two Factor Authentication will be by-pass when sending the verification
|
61 |
* @var boolean
|
62 |
*/
|
63 |
protected $m_fAllowTwoFactorByPass;
|
|
|
|
|
|
|
64 |
|
65 |
+
public function __construct( $insOptionPrefix = '' ) {
|
66 |
+
parent::__construct( $this->constructStorageKey( $insOptionPrefix, self::Slug ), self::TableName );
|
67 |
$this->m_sGaspKey = uniqid();
|
|
|
68 |
$this->updateLastLoginThrottleTime( time() );
|
|
|
69 |
$this->createTable();
|
70 |
$this->reset();
|
71 |
}
|
75 |
*/
|
76 |
public function reset() {
|
77 |
parent::reset();
|
78 |
+
self::$sModeFile_LoginThrottled = dirname( __FILE__ ).'/../mode.login_throttled';
|
79 |
+
$this->genSecretKey();
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Set the secret key by which authentication is validated.
|
84 |
+
*
|
85 |
+
* @param boolean $infForceUpdate
|
86 |
+
* @return string
|
87 |
+
*/
|
88 |
+
public function genSecretKey( $infForceUpdate = false ) {
|
89 |
+
if ( empty( $this->m_sSecretKey ) || $infForceUpdate ) {
|
90 |
+
$this->m_sSecretKey = md5( mt_rand() );
|
91 |
+
}
|
92 |
+
return $this->m_sSecretKey;
|
93 |
}
|
94 |
|
95 |
/**
|
99 |
*/
|
100 |
public function setSecretKey( $insSecretKey = '' ) {
|
101 |
if ( !empty( $insSecretKey ) ) {
|
102 |
+
$this->genSecretKey();
|
103 |
+
}
|
104 |
+
else {
|
105 |
$this->m_sSecretKey = $insSecretKey;
|
106 |
}
|
107 |
}
|
108 |
|
109 |
/**
|
110 |
*
|
111 |
+
* @param array $inaOptions
|
112 |
*/
|
113 |
public function setOptions( &$inaOptions ) {
|
114 |
parent::setOptions( $inaOptions );
|
121 |
* @return boolean
|
122 |
*/
|
123 |
public function getNeedsEmailHandler() {
|
124 |
+
return $this->getIsTwoFactorAuthOn();
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* @param string $sType can be either 'ip' or 'cookie'. If empty, both are checked looking for either.
|
129 |
+
* @return bool
|
130 |
+
*/
|
131 |
+
protected function getIsTwoFactorAuthOn( $sType = '' ) {
|
132 |
+
|
133 |
+
$fIp = $this->getOption( 'enable_two_factor_auth_by_ip', 'N' ) == 'Y';
|
134 |
+
$fCookie = $this->getOption( 'enable_two_factor_auth_by_cookie', 'N' ) == 'Y';
|
135 |
+
|
136 |
+
switch( $sType ) {
|
137 |
+
case 'ip':
|
138 |
+
return $fIp;
|
139 |
+
break;
|
140 |
+
case 'cookie':
|
141 |
+
return $fCookie;
|
142 |
+
break;
|
143 |
+
default:
|
144 |
+
return $fIp || $fCookie;
|
145 |
+
break;
|
146 |
}
|
|
|
147 |
}
|
148 |
|
149 |
+
public function setLogging( $infEnableLogging = true ) {
|
150 |
+
parent::setLogging( $this->getOption('enable_login_protect_log') == 'Y' );
|
151 |
}
|
152 |
|
153 |
/**
|
|
|
154 |
*/
|
155 |
public function run() {
|
156 |
+
parent::run();
|
157 |
+
$this->loadDataProcessor();
|
158 |
+
// $this->recreateTable();
|
159 |
+
|
160 |
+
$sRequestMethod = ICWP_WPSF_DataProcessor::ArrayFetch( $_SERVER, 'REQUEST_METHOD' );
|
161 |
+
$fIsPost = strtolower( empty($sRequestMethod)? '' : $sRequestMethod ) == 'post';
|
162 |
+
|
163 |
+
$aWhitelist = $this->getOption( 'ips_whitelist', array() );
|
164 |
if ( !empty( $aWhitelist ) && $this->isIpOnlist( $aWhitelist, self::GetVisitorIpAddress() ) ) {
|
165 |
return true;
|
166 |
}
|
167 |
+
|
168 |
+
// check for remote posting before anything else.
|
169 |
+
if ( $fIsPost && $this->getIsOption('enable_prevent_remote_post', 'Y') ) {
|
170 |
+
add_filter( 'authenticate', array( $this, 'checkRemotePostLogin_Filter' ), 9, 3);
|
171 |
+
}
|
172 |
+
|
173 |
// Add GASP checking to the login form.
|
174 |
+
if ( $this->getIsOption('enable_login_gasp_check', 'Y') ) {
|
175 |
add_action( 'login_form', array( $this, 'printGaspLoginCheck_Action' ) );
|
176 |
add_filter( 'login_form_middle', array( $this, 'printGaspLoginCheck_Filter' ) );
|
177 |
+
add_filter( 'authenticate', array( $this, 'checkLoginForGasp_Filter' ), 22, 3);
|
178 |
+
// add_action( 'woocommerce_login_form', array( $this, 'printGaspLoginCheck_Action' ) );
|
179 |
}
|
180 |
|
181 |
+
// Do GASP checking if it's a form submit.
|
182 |
+
if ( $fIsPost && $this->getOption( 'login_limit_interval' ) > 0 ) {
|
183 |
// We give it a priority of 10 so that we can jump in before WordPress does its own validation.
|
184 |
add_filter( 'authenticate', array( $this, 'checkLoginInterval_Filter' ), 10, 3);
|
185 |
}
|
186 |
+
|
187 |
+
// check for Yubikey auth after user is authenticated with WordPress.
|
188 |
+
if ( $fIsPost && $this->getOption('enable_yubikey') && $this->getIsYubikeyConfigReady() ) {
|
189 |
+
add_filter( 'wp_authenticate_user', array( $this, 'checkYubikeyOtpAuth_Filter' ) );
|
190 |
+
add_action( 'login_form', array( $this, 'printYubikeyOtp_Action' ) );
|
191 |
+
}
|
192 |
+
|
193 |
+
if ( $this->getIsTwoFactorAuthOn() ) {
|
194 |
+
|
195 |
// If their click was successful we give them a lovely message
|
196 |
+
if ( ICWP_WPSF_DataProcessor::FetchGet( 'wpsfuserverified' ) ) {
|
197 |
add_filter( 'login_message', array( $this, 'displayVerifiedUserMessage_Filter' ) );
|
198 |
}
|
199 |
+
|
200 |
// Check the current logged-in user every page load.
|
201 |
add_action( 'init', array( $this, 'checkCurrentUserAuth_Action' ) );
|
202 |
+
|
203 |
+
// At this stage (30,3) WordPress has already (20) authenticated the user. So if the login
|
204 |
// is valid, the filter will have a valid WP_User object passed to it.
|
205 |
add_filter( 'authenticate', array( $this, 'checkUserAuthLogin_Filter' ), 30, 3);
|
206 |
}
|
207 |
}
|
208 |
+
|
209 |
+
/**
|
210 |
+
*/
|
211 |
public function printGaspLoginCheck_Action() {
|
212 |
echo $this->getGaspLoginHtml();
|
213 |
}
|
214 |
+
|
215 |
+
/**
|
216 |
+
* @return string
|
217 |
+
*/
|
218 |
public function printGaspLoginCheck_Filter() {
|
219 |
return $this->getGaspLoginHtml();
|
220 |
}
|
221 |
|
222 |
+
/**
|
223 |
+
* @param $inoUser
|
224 |
+
* @param $insUsername
|
225 |
+
* @param $insPassword
|
226 |
+
* @return mixed
|
227 |
+
*/
|
228 |
+
public function checkRemotePostLogin_Filter( $inoUser, $insUsername, $insPassword ) {
|
229 |
+
$this->loadDataProcessor();
|
230 |
+
$sHttpRef = ICWP_WPSF_DataProcessor::ArrayFetch( $_SERVER, 'HTTP_REFERER' );
|
231 |
+
$sHttpRef = is_null( $sHttpRef )? '' : $sHttpRef;
|
232 |
+
if ( empty($sHttpRef) || ( strpos($sHttpRef, home_url()) !== 0 ) ) {
|
233 |
+
$this->logWarning(
|
234 |
+
sprintf( _wpsf__('User "%s" attempted to login but the HTTP REFERER was either empty or it was a remote login attempt. Bot Perhaps? HTTP REFERER: "%s".'), $insUsername, $sHttpRef )
|
235 |
+
);
|
236 |
+
$this->doStatIncrement( 'login.remotepost.fail' );
|
237 |
+
wp_die(
|
238 |
+
_wpsf__( 'Sorry, you must login directly from within the site.' )
|
239 |
+
.'<br /><a href="http://icwp.io/4n" target="_blank">→'._wpsf__('More Info').'</a>'
|
240 |
+
);
|
241 |
+
}
|
242 |
+
else {
|
243 |
+
$this->doStatIncrement( 'login.remotepost.success' );
|
244 |
+
}
|
245 |
+
return $inoUser;
|
246 |
+
}
|
247 |
+
|
248 |
+
/**
|
249 |
+
* @param $inoUser
|
250 |
+
* @param $insUsername
|
251 |
+
* @param $insPassword
|
252 |
+
* @return WP_Error
|
253 |
+
*/
|
254 |
public function checkLoginForGasp_Filter( $inoUser, $insUsername, $insPassword ) {
|
255 |
+
|
256 |
if ( empty( $insUsername ) || is_wp_error( $inoUser ) ) {
|
257 |
return $inoUser;
|
258 |
}
|
259 |
if ( $this->doGaspChecks( $insUsername ) ) {
|
260 |
return $inoUser;
|
261 |
}
|
262 |
+
//This doesn't actually ever get returned because we die() within doGaspChecks()
|
263 |
+
return new WP_Error('wpsf_gaspfail', _wpsf__('G.A.S.P. Checking Failed.') );
|
264 |
}
|
265 |
+
|
266 |
/**
|
267 |
* Checks whether the current user that is logged-in is authenticated by IP address.
|
268 |
*
|
271 |
* Should be hooked to 'init' so we have is_user_logged_in()
|
272 |
*/
|
273 |
public function checkCurrentUserAuth_Action() {
|
274 |
+
|
275 |
+
// User has clicked a link in their email to validate their IP address for login.
|
276 |
+
if ( ICWP_WPSF_DataProcessor::FetchGet( 'wpsf-action' ) == 'linkauth' ) {
|
277 |
+
$this->validateUserAuthLink();
|
278 |
+
}
|
279 |
+
|
280 |
if ( is_user_logged_in() ) {
|
281 |
$this->verifyCurrentUser();
|
282 |
}
|
283 |
}
|
284 |
|
285 |
public function displayVerifiedUserMessage_Filter( $insMessage ) {
|
286 |
+
$sStyles = 'background-color: #FAFFE8; border: 1px solid #DDDDDD; margin: 8px 0 10px 8px; padding: 16px;';
|
287 |
+
$insMessage .= '<h3 style="'.$sStyles.'">'._wpsf__('You have successfully verified your identity - you may now login').'</h3>';
|
288 |
return $insMessage;
|
289 |
}
|
290 |
|
292 |
* Should return false when logging is disabled.
|
293 |
*
|
294 |
* @return false|array - false when logging is disabled, array with log data otherwise
|
295 |
+
* @see ICWP_WPSF_BaseProcessor::getLogData()
|
296 |
*/
|
297 |
public function flushLogData() {
|
298 |
|
310 |
|
311 |
/**
|
312 |
* Checks the link details to ensure all is valid before authorizing the user.
|
|
|
|
|
313 |
*/
|
314 |
public function validateUserAuthLink() {
|
315 |
+
$this->loadDataProcessor();
|
316 |
// wpsfkey=%s&wpsf-action=%s&username=%s&uniqueid
|
317 |
+
|
318 |
+
if ( ICWP_WPSF_DataProcessor::FetchGet( 'wpsfkey' ) !== $this->m_sSecretKey ) {
|
319 |
return false;
|
320 |
}
|
321 |
+
|
322 |
+
$sUsername = ICWP_WPSF_DataProcessor::FetchGet( 'username' );
|
323 |
+
$sUniqueId = ICWP_WPSF_DataProcessor::FetchGet( 'uniqueid' );
|
324 |
+
if ( empty( $sUsername ) || empty( $sUniqueId ) ) {
|
325 |
return false;
|
326 |
}
|
327 |
|
328 |
$aWhere = array(
|
329 |
+
'unique_id' => $sUniqueId,
|
330 |
+
'wp_username' => $sUsername
|
331 |
);
|
332 |
+
|
333 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
334 |
+
if ( $this->doMakePendingLoginAuthActive( $aWhere ) ) {
|
335 |
+
$this->logInfo(
|
336 |
+
sprintf( _wpsf__('User "%s" verified their identity using Two-Factor Authentication.'), $sUsername )
|
337 |
+
);
|
338 |
+
$this->setUserLoggedIn( $sUsername );
|
339 |
+
$this->doStatIncrement( 'login.twofactor.verified' );
|
340 |
+
$oWp->redirectToAdmin();
|
341 |
}
|
342 |
else {
|
343 |
+
$oWp->redirectToHome();
|
344 |
}
|
345 |
}
|
346 |
+
|
|
|
|
|
|
|
|
|
347 |
// WordPress Hooks and Filters:
|
348 |
|
349 |
/**
|
356 |
* @return unknown|WP_Error
|
357 |
*/
|
358 |
public function checkLoginInterval_Filter( $inoUser, $insUsername, $insPassword ) {
|
|
|
359 |
// No login attempt was made.
|
360 |
if ( empty( $insUsername ) ) {
|
361 |
return $inoUser;
|
362 |
}
|
363 |
|
364 |
// Is there an interval set?
|
365 |
+
$this->setLoginCooldownInterval();
|
366 |
$nRequiredLoginInterval = $this->m_nRequiredLoginInterval;
|
367 |
if ( $nRequiredLoginInterval === false || $nRequiredLoginInterval == 0 ) {
|
368 |
return $inoUser;
|
381 |
$nLoginInterval = $sNow - $this->m_nLastLoginTime;
|
382 |
if ( $nLoginInterval > $nRequiredLoginInterval ) {
|
383 |
$this->updateLastLoginThrottleTime( $sNow );
|
384 |
+
$this->doStatIncrement( 'login.cooldown.success' );
|
385 |
return $inoUser;
|
386 |
}
|
387 |
|
388 |
// At this point someone has attempted to login within the previous login wait interval
|
389 |
// So we remove WordPress's authentication filter and our own user check authentication
|
390 |
// And finally return a WP_Error which will be reflected back to the user.
|
391 |
+
$this->doStatIncrement( 'login.cooldown.fail' );
|
392 |
remove_filter( 'authenticate', 'wp_authenticate_username_password', 20, 3 ); // wp-includes/user.php
|
393 |
remove_filter( 'authenticate', array( $this, 'checkUserAuthLogin_Filter' ), 30, 3);
|
394 |
|
395 |
+
$sErrorString = sprintf( _wpsf__( "Login Cooldown in effect. You must wait %s seconds before attempting to login again." ), ($nRequiredLoginInterval - $nLoginInterval ) );
|
396 |
$oError = new WP_Error( 'wpsf_logininterval', $sErrorString );
|
397 |
return $oError;
|
398 |
}
|
399 |
+
|
400 |
+
/**
|
401 |
+
* @return int
|
402 |
+
*/
|
403 |
protected function getLastLoginTime() {
|
404 |
+
$oWpFs = $this->loadFileSystemProcessor();
|
405 |
// Check that there is a login throttle file. If it exists and its modified time is greater than the
|
406 |
// current $this->m_nLastLoginTime it suggests another process has touched the file and updated it
|
407 |
// concurrently. So, we update our $this->m_nEmailThrottleTime accordingly.
|
408 |
+
if ( $oWpFs->fileAction( 'file_exists', self::$sModeFile_LoginThrottled ) ) {
|
409 |
$nModifiedTime = filemtime( self::$sModeFile_LoginThrottled );
|
410 |
if ( $nModifiedTime > $this->m_nLastLoginTime ) {
|
411 |
$this->m_nLastLoginTime = $nModifiedTime;
|
412 |
}
|
413 |
}
|
414 |
+
else { }
|
415 |
return $this->m_nLastLoginTime;
|
416 |
}
|
417 |
+
|
418 |
+
/**
|
419 |
+
* @param $innLastLoginTime
|
420 |
+
*/
|
421 |
public function updateLastLoginThrottleTime( $innLastLoginTime ) {
|
422 |
+
$oWpFs = $this->loadFileSystemProcessor();
|
423 |
$this->m_nLastLoginTime = $innLastLoginTime;
|
424 |
+
$oWpFs->fileAction( 'touch', array(self::$sModeFile_LoginThrottled, $innLastLoginTime) );
|
|
|
|
|
425 |
$this->setNeedSave();
|
426 |
}
|
427 |
|
428 |
+
/**
|
429 |
+
*/
|
430 |
+
public function printYubikeyOtp_Action() {
|
431 |
+
$sHtml =
|
432 |
+
'<p class="yubikey-otp">
|
433 |
+
<label>%s<br />
|
434 |
+
<input type="text" name="yubiotp" class="input" value="" size="20" />
|
435 |
+
</label>
|
436 |
+
</p>
|
437 |
+
';
|
438 |
+
echo sprintf( $sHtml, '<a href="http://icwp.io/4i" target="_blank">'._wpsf__('Yubikey OTP').'</a>' );
|
439 |
+
}
|
440 |
+
|
441 |
+
/**
|
442 |
+
* @param WP_User $inoUser
|
443 |
+
* @return WP_User|WP_Error
|
444 |
+
*/
|
445 |
+
public function checkYubikeyOtpAuth_Filter( $inoUser ) {
|
446 |
+
$oError = new WP_Error();
|
447 |
+
|
448 |
+
// Before anything else we check that a Yubikey pair has been provided for this username (and that there are pairs in the first place!)
|
449 |
+
$aYubikeyUsernamePairs = $this->getOption('yubikey_unique_keys');
|
450 |
+
if ( !$this->getIsYubikeyConfigReady() ) { // configuration is clearly not completed yet.
|
451 |
+
return $inoUser;
|
452 |
+
}
|
453 |
+
|
454 |
+
$sOneTimePassword = empty( $_POST['yubiotp'] )? '' : trim( $_POST['yubiotp'] );
|
455 |
+
$sAppId = $this->getOption('yubikey_app_id');
|
456 |
+
$sApiKey = $this->getOption('yubikey_api_key');
|
457 |
+
|
458 |
+
// check that if we have a list of permitted keys, that the one used is on that list connected with the username.
|
459 |
+
$sYubikey12 = substr( $sOneTimePassword, 0 , 12 );
|
460 |
+
$fUsernameFound = false; // if username is never found, it means there's no yubikey specified which means we can bypass this authentication method.
|
461 |
+
$fFoundMatch = false;
|
462 |
+
foreach( $aYubikeyUsernamePairs as $aUsernameYubikeyPair ) {
|
463 |
+
if ( isset( $aUsernameYubikeyPair[$inoUser->user_login] ) ) {
|
464 |
+
$fUsernameFound = true;
|
465 |
+
if ( $aUsernameYubikeyPair[$inoUser->user_login] == $sYubikey12 ) {
|
466 |
+
$fFoundMatch = true;
|
467 |
+
break;
|
468 |
+
}
|
469 |
+
}
|
470 |
+
}
|
471 |
+
|
472 |
+
// If no yubikey-username pair found for given username, we by-pass Yubikey auth.
|
473 |
+
if ( !$fUsernameFound ) {
|
474 |
+
$this->logWarning(
|
475 |
+
sprintf( _wpsf__('User "%s" logged in without a Yubikey One Time Password because no username-yubikey pair was found for this user.'), $inoUser->user_login )
|
476 |
+
);
|
477 |
+
return $inoUser;
|
478 |
+
}
|
479 |
+
|
480 |
+
// Username was found in the list of key pairs, but the yubikey provided didn't match that username.
|
481 |
+
if ( !$fFoundMatch ) {
|
482 |
+
$oError->add(
|
483 |
+
'yubikey_not_allowed',
|
484 |
+
sprintf( _wpsf__( 'ERROR: %s' ), _wpsf__('The Yubikey provided is not on the list of permitted keys for this user.') )
|
485 |
+
);
|
486 |
+
$this->logWarning(
|
487 |
+
sprintf( _wpsf__('User "%s" attempted to login but Yubikey ID used was not in list of authorised keys: "%s".'), $inoUser->user_login, $sYubikey12 )
|
488 |
+
);
|
489 |
+
return $oError;
|
490 |
+
}
|
491 |
+
|
492 |
+
$oFs = $this->loadFileSystemProcessor();
|
493 |
+
|
494 |
+
$sNonce = md5( uniqid( rand() ) );
|
495 |
+
$sUrl = sprintf( self::YubikeyVerifyApiUrl, $sAppId, $sOneTimePassword, $sNonce );
|
496 |
+
$sRawYubiRequest = $oFs->getUrlContent( $sUrl );
|
497 |
+
|
498 |
+
// Validate response.
|
499 |
+
// 1. Check OTP and Nonce
|
500 |
+
if ( !preg_match( '/otp='.$sOneTimePassword.'/', $sRawYubiRequest, $aMatches )
|
501 |
+
|| !preg_match( '/nonce='.$sNonce.'/', $sRawYubiRequest, $aMatches )
|
502 |
+
) {
|
503 |
+
$oError->add(
|
504 |
+
'yubikey_validate_fail',
|
505 |
+
sprintf( _wpsf__( 'ERROR: %s' ), _wpsf__('The Yubikey authentication was not validated successfully.') )
|
506 |
+
);
|
507 |
+
$this->logWarning(
|
508 |
+
sprintf( _wpsf__('User "%s" attempted to login but Yubikey One Time Password failed to validate due to invalid Yubi API.'), $inoUser->user_login )
|
509 |
+
);
|
510 |
+
return $oError;
|
511 |
+
}
|
512 |
+
|
513 |
+
// Optionally we can check the hash, but since we're using HTTPS, this isn't necessary and adds more PHP requirements
|
514 |
+
|
515 |
+
// 2. Check status directly within response
|
516 |
+
preg_match( '/status=([a-zA-Z0-9_]+)/', $sRawYubiRequest, $aMatches );
|
517 |
+
$sStatus = $aMatches[1];
|
518 |
+
|
519 |
+
if ( $sStatus != 'OK' && $sStatus != 'REPLAYED_OTP' ) {
|
520 |
+
$oError->add(
|
521 |
+
'yubikey_validate_fail',
|
522 |
+
sprintf( _wpsf__( 'ERROR: %s' ), _wpsf__('The Yubikey authentication was not validated successfully.') )
|
523 |
+
);
|
524 |
+
$this->logWarning(
|
525 |
+
sprintf( _wpsf__('User "%s" attempted to login but Yubikey One Time Password failed to validate due to invalid Yubi API response status: %s.'), $inoUser->user_login, $sStatus )
|
526 |
+
);
|
527 |
+
return $oError;
|
528 |
+
}
|
529 |
+
|
530 |
+
$this->logInfo(
|
531 |
+
sprintf( _wpsf__('User "%s" successfully logged in using a validated Yubikey One Time Password.'), $inoUser->user_login )
|
532 |
+
);
|
533 |
+
return $inoUser;
|
534 |
+
}
|
535 |
+
|
536 |
+
/**
|
537 |
+
* @return bool
|
538 |
+
*/
|
539 |
+
protected function getIsYubikeyConfigReady() {
|
540 |
+
$sAppId = $this->getOption('yubikey_app_id');
|
541 |
+
$sApiKey = $this->getOption('yubikey_api_key');
|
542 |
+
$aYubikeyKeys = $this->getOption('yubikey_unique_keys');
|
543 |
+
return !empty($sAppId) && !empty($sApiKey) && !empty($aYubikeyKeys);
|
544 |
+
}
|
545 |
+
|
546 |
/**
|
547 |
* If $inoUser is a valid WP_User object, then the user logged in correctly.
|
548 |
*
|
558 |
* 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.
|
559 |
* c) note at this stage, if the username was empty, we give back nothing (this happens when wp-login.php is loaded as normal.
|
560 |
*
|
561 |
+
* @param WP_User|string $inoUser - the docs say the first parameter a string, WP actually gives a WP_User object (or null)
|
562 |
* @param string $insUsername
|
563 |
* @param string $insPassword
|
564 |
* @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.
|
578 |
}
|
579 |
}
|
580 |
else if ( $fUserLoginSuccess ) {
|
581 |
+
|
582 |
+
if ( !$this->getIsUserLevelSubjectToTwoFactorAuth( $inoUser->user_level ) ) {
|
583 |
+
return $inoUser;
|
584 |
+
}
|
585 |
+
|
586 |
+
if ( $this->isUserVerified( $insUsername ) ) {
|
587 |
return $inoUser;
|
588 |
}
|
589 |
else {
|
590 |
// Create a new 2-factor auth pending entry
|
591 |
+
$aNewAuthData = $this->addNewPendingLoginAuth( $inoUser->user_login );
|
592 |
|
593 |
// Now send email with authentication link for user.
|
594 |
if ( is_array( $aNewAuthData ) ) {
|
595 |
+
$this->doStatIncrement( 'login.twofactor.started' );
|
596 |
$fEmailSuccess = $this->sendEmailTwoFactorVerify( $inoUser, $aNewAuthData['ip'], $aNewAuthData['unique_id'] );
|
597 |
|
598 |
// Failure to send email - log them in.
|
599 |
if ( !$fEmailSuccess && $this->getTwoFactorByPassOnFail() ) {
|
600 |
+
$this->doMakePendingLoginAuthActive( $aNewAuthData );
|
601 |
return $inoUser;
|
602 |
}
|
603 |
}
|
607 |
$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.";
|
608 |
return new WP_Error( 'wpsf_loginauth', $sErrorString );
|
609 |
}
|
610 |
+
|
611 |
+
/**
|
612 |
+
* TODO: http://stackoverflow.com/questions/3499104/how-to-know-the-role-of-current-user-in-wordpress
|
613 |
+
* @param integer $nUserLevel
|
614 |
+
* @return bool
|
615 |
+
*/
|
616 |
+
public function getIsUserLevelSubjectToTwoFactorAuth( $nUserLevel ) {
|
617 |
+
|
618 |
+
$aSubjectedUserLevels = $this->getOption( 'two_factor_auth_user_roles' );
|
619 |
+
if ( empty($aSubjectedUserLevels) || !is_array($aSubjectedUserLevels) ) {
|
620 |
+
$aSubjectedUserLevels = array( 1, 2, 3, 8 ); // by default all except subscribers!
|
621 |
+
}
|
622 |
+
|
623 |
+
// see: https://codex.wordpress.org/Roles_and_Capabilities#User_Level_to_Role_Conversion
|
624 |
+
|
625 |
+
// authors, contributors and subscribers
|
626 |
+
if ( $nUserLevel < 3 && in_array( $nUserLevel, $aSubjectedUserLevels ) ) {
|
627 |
+
return true;
|
628 |
+
}
|
629 |
+
// editors
|
630 |
+
if ( $nUserLevel >= 3 && $nUserLevel < 8 && in_array( 3, $aSubjectedUserLevels ) ) {
|
631 |
+
return true;
|
632 |
+
}
|
633 |
+
// administrators
|
634 |
+
if ( $nUserLevel >= 8 && $nUserLevel <= 10 && in_array( 8, $aSubjectedUserLevels ) ) {
|
635 |
+
return true;
|
636 |
+
}
|
637 |
+
return false;
|
638 |
+
}
|
639 |
|
640 |
public function getGaspLoginHtml() {
|
641 |
|
642 |
+
$sLabel = _wpsf__("I'm a human.");
|
643 |
+
$sAlert = _wpsf__("Please check the box to show us you're a human.");
|
644 |
|
645 |
$sUniqElem = 'icwp_wpsf_login_p'.uniqid();
|
646 |
|
682 |
return true;
|
683 |
}
|
684 |
</script>
|
685 |
+
<noscript>'._wpsf__('You MUST enable Javascript to be able to login').'</noscript>
|
686 |
<input type="hidden" id="icwp_wpsf_login_email" name="icwp_wpsf_login_email" value="" />
|
687 |
';
|
688 |
|
699 |
public function doGaspChecks( $insUsername ) {
|
700 |
if ( !isset( $_POST[ $this->getGaspCheckboxName() ] ) ) {
|
701 |
$this->logWarning(
|
702 |
+
sprintf( _wpsf__('User "%s" attempted to login but GASP checkbox was not present. Bot Perhaps? IP Address: "%s".'), $insUsername, long2ip($this->m_nRequestIp) )
|
703 |
);
|
704 |
+
$this->doStatIncrement( 'login.gasp.checkbox.fail' );
|
705 |
wp_die( "You must check that box to say you're not a bot." );
|
706 |
return false;
|
707 |
}
|
708 |
else if ( isset( $_POST['icwp_wpsf_login_email'] ) && $_POST['icwp_wpsf_login_email'] !== '' ){
|
709 |
$this->logWarning(
|
710 |
+
sprintf( _wpsf__('User "%s" attempted to login but they were caught by the GASP honey pot. Bot Perhaps? IP Address: "%s".'), $insUsername, long2ip($this->m_nRequestIp) )
|
711 |
);
|
712 |
+
$this->doStatIncrement( 'login.gasp.honeypot.fail' );
|
713 |
+
wp_die( _wpsf__('You appear to be a bot - terminating login attempt.') );
|
714 |
return false;
|
715 |
}
|
716 |
return true;
|
717 |
}
|
718 |
|
719 |
public function setTwoFactorByPassOnFail() {
|
720 |
+
$this->m_fAllowTwoFactorByPass = $this->getIsOption( 'enable_two_factor_bypass_on_email_fail', 'Y' );
|
721 |
}
|
722 |
|
723 |
public function getTwoFactorByPassOnFail() {
|
726 |
}
|
727 |
return $this->m_fAllowTwoFactorByPass;
|
728 |
}
|
729 |
+
|
730 |
+
/**
|
731 |
+
*/
|
732 |
public function setLoginCooldownInterval() {
|
733 |
+
$nInterval = intval( $this->getOption('login_limit_interval', 0) );
|
734 |
$this->m_nRequiredLoginInterval = ( $nInterval < 0 )? 0 : $nInterval;
|
735 |
}
|
736 |
|
737 |
/**
|
738 |
+
* @param string $sUsername
|
739 |
* @return boolean
|
740 |
*/
|
741 |
+
public function addNewPendingLoginAuth( $sUsername ) {
|
742 |
|
743 |
+
if ( empty( $sUsername ) ) {
|
|
|
744 |
return false;
|
745 |
}
|
746 |
|
754 |
$aOldWhere = array(
|
755 |
'pending' => 1,
|
756 |
'deleted_at' => 0,
|
757 |
+
'wp_username' => $sUsername
|
758 |
);
|
759 |
$this->updateRowsFromTable( $aOldData, $aOldWhere );
|
760 |
|
761 |
// Now add new pending entry
|
762 |
+
$aNewData = array();
|
763 |
+
$aNewData[ 'unique_id' ] = uniqid();
|
764 |
+
$aNewData[ 'ip_long' ] = $this->m_nRequestIp;
|
765 |
+
$aNewData[ 'ip' ] = long2ip( $this->m_nRequestIp );
|
766 |
+
$aNewData[ 'wp_username' ] = $sUsername;
|
767 |
+
$aNewData[ 'pending' ] = 1;
|
768 |
+
$aNewData[ 'created_at' ] = time();
|
769 |
|
770 |
+
$mResult = $this->insertIntoTable( $aNewData );
|
771 |
if ( $mResult ) {
|
772 |
$this->logInfo(
|
773 |
+
sprintf( _wpsf__('User "%s" created a pending Two-Factor Authentication for IP Address "%s".'), $sUsername, $aNewData[ 'ip' ] )
|
774 |
);
|
775 |
+
$mResult = $aNewData;
|
776 |
}
|
777 |
return $mResult;
|
778 |
}
|
783 |
* @param array $inaWhere - unique_id, wp_username
|
784 |
* @return boolean
|
785 |
*/
|
786 |
+
public function doMakePendingLoginAuthActive( $inaWhere ) {
|
787 |
|
788 |
$aChecks = array( 'unique_id', 'wp_username' );
|
789 |
if ( !$this->validateParameters( $inaWhere, $aChecks ) ) {
|
790 |
return false;
|
791 |
}
|
792 |
|
793 |
+
// First set any active, non-pending entries for the given user to be deleted
|
794 |
+
$this->terminateActiveLoginForUser( $inaWhere['wp_username'] );
|
795 |
+
|
796 |
+
// Now activate the new one.
|
797 |
+
|
798 |
+
// Updates the database
|
799 |
+
$inaWhere['pending'] = 1;
|
800 |
+
$inaWhere['deleted_at'] = 0;
|
801 |
+
$mResult = $this->updateRowsFromTable( array( 'pending' => 0 ), $inaWhere );
|
802 |
+
|
803 |
+
// Set the necessary cookie
|
804 |
+
$this->setAuthActiveCookie( $inaWhere['unique_id'] );
|
805 |
+
return $mResult;
|
806 |
+
}
|
807 |
+
|
808 |
+
/**
|
809 |
+
* Invalidates all currently active two-factor logins and redirects to admin (->login)
|
810 |
+
*/
|
811 |
+
public function doTerminateAllVerifiedLogins() {
|
812 |
+
$this->terminateAllVerifiedLogins();
|
813 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
814 |
+
$oWp->redirectToAdmin();
|
815 |
+
}
|
816 |
+
|
817 |
+
/**
|
818 |
+
* @param $sUsername
|
819 |
+
*/
|
820 |
+
protected function setUserLoggedIn( $sUsername ) {
|
821 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
822 |
+
$oUser = version_compare( $oWp->getWordpressVersion(), '3.2.2', '<=' )? get_userdatabylogin( $sUsername ) : get_user_by( 'login', $sUsername );
|
823 |
+
|
824 |
+
wp_clear_auth_cookie();
|
825 |
+
wp_set_current_user ( $oUser->ID, $oUser->user_login );
|
826 |
+
wp_set_auth_cookie ( $oUser->ID, true );
|
827 |
+
do_action( 'wp_login', $oUser->user_login );
|
828 |
+
}
|
829 |
+
|
830 |
+
/**
|
831 |
+
* Given a username will soft-delete any currently active two-factor authentication.
|
832 |
+
*
|
833 |
+
* @param $sUsername
|
834 |
+
*/
|
835 |
+
protected function terminateActiveLoginForUser( $sUsername ) {
|
836 |
$sNow = time();
|
|
|
|
|
837 |
$sQuery = "
|
838 |
UPDATE `%s`
|
839 |
SET `deleted_at` = '%s',
|
847 |
$this->m_sTableName,
|
848 |
$sNow,
|
849 |
$sNow,
|
850 |
+
esc_sql( $sUsername )
|
851 |
+
);
|
852 |
+
$this->doSql( $sQuery );
|
853 |
+
}
|
854 |
+
|
855 |
+
/**
|
856 |
+
*
|
857 |
+
*/
|
858 |
+
protected function terminateAllVerifiedLogins() {
|
859 |
+
$sNow = time();
|
860 |
+
$sQuery = "
|
861 |
+
UPDATE `%s`
|
862 |
+
SET `deleted_at` = '%s',
|
863 |
+
`expired_at` = '%s'
|
864 |
+
WHERE
|
865 |
+
`deleted_at` = '0'
|
866 |
+
AND `pending` = '0'
|
867 |
+
";
|
868 |
+
$sQuery = sprintf( $sQuery,
|
869 |
+
$this->m_sTableName,
|
870 |
+
$sNow,
|
871 |
+
$sNow
|
872 |
);
|
873 |
$this->doSql( $sQuery );
|
874 |
+
}
|
875 |
+
|
876 |
+
/**
|
877 |
+
* @param $insUniqueId
|
878 |
+
*/
|
879 |
+
public function setAuthActiveCookie( $insUniqueId ) {
|
880 |
+
$nWeek = defined( 'WEEK_IN_SECONDS' )? WEEK_IN_SECONDS : 24*60*60;
|
881 |
+
setcookie( self::AuthActiveCookie, $insUniqueId, time()+$nWeek, COOKIEPATH, COOKIE_DOMAIN, false );
|
|
|
|
|
|
|
|
|
882 |
}
|
883 |
|
884 |
/**
|
885 |
* Checks whether a given user is authenticated.
|
886 |
*
|
887 |
+
* @param string $sUsername
|
888 |
* @return boolean
|
889 |
*/
|
890 |
+
public function isUserVerified( $sUsername ) {
|
891 |
+
|
|
|
|
|
|
|
|
|
|
|
892 |
$sQuery = "
|
893 |
SELECT *
|
894 |
FROM `%s`
|
895 |
WHERE
|
896 |
`wp_username` = '%s'
|
|
|
897 |
AND `pending` = '0'
|
898 |
AND `deleted_at` = '0'
|
899 |
AND `expired_at` = '0'
|
900 |
";
|
901 |
+
|
902 |
$sQuery = sprintf( $sQuery,
|
903 |
$this->m_sTableName,
|
904 |
+
$sUsername
|
|
|
905 |
);
|
906 |
|
907 |
$mResult = $this->selectCustomFromTable( $sQuery );
|
908 |
+
|
909 |
if ( is_array( $mResult ) && count( $mResult ) == 1 ) {
|
910 |
+
// Now we test based on which types of 2-factor auth is enabled
|
911 |
+
$fVerified = true;
|
912 |
+
$aUserAuthData = $mResult[0];
|
913 |
+
if ( $this->getIsTwoFactorAuthOn('ip') && ( $this->m_nRequestIp != $aUserAuthData['ip_long'] ) ) {
|
914 |
+
$fVerified = false;
|
915 |
+
}
|
916 |
+
if ( $fVerified && $this->getIsTwoFactorAuthOn('cookie') && !$this->isAuthCookieValid($aUserAuthData['unique_id']) ) {
|
917 |
+
$fVerified = false;
|
918 |
+
}
|
919 |
+
return $fVerified;
|
920 |
}
|
921 |
else {
|
922 |
$this->logWarning(
|
923 |
+
sprintf( _wpsf__('User "%s" was found to be un-verified at the given IP Address "%s"'), $sUsername, long2ip( $this->m_nRequestIp ) )
|
924 |
);
|
925 |
return false;
|
926 |
}
|
927 |
}
|
928 |
+
|
929 |
+
/**
|
930 |
+
* @param $sUniqueId
|
931 |
+
* @return bool
|
932 |
+
*/
|
933 |
+
protected function isAuthCookieValid( $sUniqueId ) {
|
934 |
+
$this->loadDataProcessor();
|
935 |
+
return ICWP_WPSF_DataProcessor::FetchCookie( self::AuthActiveCookie ) == $sUniqueId;
|
936 |
+
}
|
937 |
+
|
938 |
+
/**
|
939 |
+
* If it cannot verify current user, will forcefully log them out and redirect to login
|
940 |
+
*/
|
941 |
public function verifyCurrentUser() {
|
942 |
$oUser = wp_get_current_user();
|
943 |
if ( is_object( $oUser ) && $oUser instanceof WP_User ) {
|
944 |
|
945 |
+
if ( $this->getIsUserLevelSubjectToTwoFactorAuth( $oUser->user_level ) && !$this->isUserVerified( $oUser->user_login ) ) {
|
|
|
946 |
$this->logWarning(
|
947 |
+
sprintf( _wpsf__('User "%s" was forcefully logged out as they are not verified.'), $oUser->user_login )
|
948 |
);
|
949 |
+
$this->doStatIncrement( 'login.userverify.fail' );
|
950 |
wp_logout();
|
951 |
+
$oWp = $this->loadWpFunctionsProcessor();
|
952 |
+
$oWp->redirectToLogin();
|
953 |
}
|
954 |
}
|
955 |
}
|
957 |
/**
|
958 |
* Given the necessary components, creates the 2-factor verification link for giving to the user.
|
959 |
*
|
960 |
+
* @param string $sUser
|
961 |
+
* @param string $sUniqueId
|
|
|
962 |
* @return string
|
963 |
*/
|
964 |
+
protected function generateTwoFactorVerifyLink( $sUser, $sUniqueId ) {
|
965 |
$sSiteUrl = home_url() . '?wpsfkey=%s&wpsf-action=%s&username=%s&uniqueid=%s';
|
966 |
$sAction = 'linkauth';
|
967 |
+
return sprintf( $sSiteUrl, $this->m_sSecretKey, $sAction, $sUser, $sUniqueId );
|
968 |
}
|
969 |
|
970 |
/**
|
971 |
+
* @param WP_User $inoUser
|
972 |
* @param string $insIpAddress
|
973 |
+
* @param string $insUniqueId
|
974 |
+
* @return boolean
|
975 |
*/
|
976 |
public function sendEmailTwoFactorVerify( WP_User $inoUser, $insIpAddress, $insUniqueId ) {
|
977 |
|
978 |
$sEmail = $inoUser->user_email;
|
979 |
+
$sAuthLink = $this->generateTwoFactorVerifyLink( $inoUser->user_login, $insUniqueId );
|
980 |
|
981 |
$aMessage = array(
|
982 |
+
_wpsf__('You, or someone pretending to be you, just attempted to login into your WordPress site.'),
|
983 |
+
_wpsf__('The IP Address / Cookie from which they tried to login is not currently verified.'),
|
984 |
+
_wpsf__('To validate this user, click the following link and then attempt to login again.'),
|
985 |
+
sprintf( _wpsf__('IP Address: %s'), $insIpAddress ),
|
986 |
+
sprintf( _wpsf__('Authentication Link: %s'), $sAuthLink ),
|
987 |
);
|
988 |
+
$sEmailSubject = sprintf( _wpsf__('Two-Factor Login Verification for: %s'), home_url() );
|
989 |
+
|
990 |
+
// add filters to email sending (for now only Mandrill)
|
991 |
+
add_filter( 'mandrill_payload', array($this, 'customiseMandrill') );
|
992 |
+
|
993 |
$fResult = $this->sendEmailTo( $sEmail, $sEmailSubject, $aMessage );
|
994 |
if ( $fResult ) {
|
995 |
$this->logInfo(
|
996 |
+
sprintf( _wpsf__('User "%s" was sent an email to verify their Identity using Two-Factor Login Auth for IP address "%s".'), $inoUser->user_login, $insIpAddress )
|
997 |
);
|
998 |
}
|
999 |
else {
|
1000 |
$this->logCritical(
|
1001 |
+
sprintf( _wpsf__('Tried to send User "%s" email to verify their Identity using Two-Factor Login Auth for IP Address "%s", but email sending failed.'), $inoUser->user_login, $insIpAddress )
|
1002 |
);
|
1003 |
}
|
1004 |
return $fResult;
|
1005 |
}
|
1006 |
+
|
1007 |
+
/**
|
1008 |
+
*
|
1009 |
+
*/
|
1010 |
+
public function customiseMandrill( $aMessage ) {
|
1011 |
+
if ( empty( $aMessage['text'] ) ) {
|
1012 |
+
$aMessage['text'] = $aMessage['html'];
|
1013 |
+
}
|
1014 |
+
return $aMessage;
|
1015 |
+
}
|
1016 |
|
1017 |
public function createTable() {
|
1018 |
|
1045 |
$sQuery = sprintf( $sQuery, $this->m_sTableName, $inaData['unique_id'], $inaData['wp_username'] );
|
1046 |
return $this->selectRowFromTable( $sQuery );
|
1047 |
}
|
1048 |
+
|
1049 |
+
/**
|
1050 |
+
* This is hooked into a cron in the base class and overrides the parent method.
|
1051 |
+
*
|
1052 |
+
* It'll delete everything older than 24hrs.
|
1053 |
+
*/
|
1054 |
+
public function cleanupDatabase() {
|
1055 |
+
if ( !$this->getTableExists() ) {
|
1056 |
+
return;
|
1057 |
+
}
|
1058 |
+
$nTimeStamp = time() - (DAY_IN_SECONDS * $this->nDaysToKeepLog);
|
1059 |
+
$this->deleteAllRowsOlderThan( $nTimeStamp );
|
1060 |
+
}
|
1061 |
+
|
1062 |
+
/**
|
1063 |
+
* @param $nTimeStamp
|
1064 |
+
*/
|
1065 |
+
protected function deleteAllRowsOlderThan( $nTimeStamp ) {
|
1066 |
+
$sQuery = "
|
1067 |
+
DELETE from `%s`
|
1068 |
+
WHERE
|
1069 |
+
`created_at` < '%s'
|
1070 |
+
AND `pending` = '1'
|
1071 |
+
";
|
1072 |
+
$sQuery = sprintf( $sQuery,
|
1073 |
+
$this->m_sTableName,
|
1074 |
+
esc_sql( $nTimeStamp )
|
1075 |
+
);
|
1076 |
+
$this->doSql( $sQuery );
|
1077 |
+
}
|
1078 |
+
|
1079 |
}
|
1080 |
+
endif;
|
1081 |
|
1082 |
+
if ( !class_exists('ICWP_WPSF_LoginProtectProcessor') ):
|
1083 |
+
class ICWP_WPSF_LoginProtectProcessor extends ICWP_LoginProtectProcessor_V2 { }
|
1084 |
endif;
|
src/icwp-processor-privacyprotect.php
ADDED
@@ -0,0 +1,173 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
+
* All rights reserved.
|
5 |
+
*
|
6 |
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
7 |
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
8 |
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
9 |
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
10 |
+
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
11 |
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
12 |
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
13 |
+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
14 |
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
15 |
+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
+
*/
|
17 |
+
|
18 |
+
require_once( dirname(__FILE__).'/icwp-basedb-processor.php' );
|
19 |
+
|
20 |
+
if ( !class_exists('ICWP_PrivacyProtectProcessor_V1') ):
|
21 |
+
|
22 |
+
class ICWP_PrivacyProtectProcessor_V1 extends ICWP_BaseDbProcessor_WPSF {
|
23 |
+
|
24 |
+
const Slug = 'privacy_protect';
|
25 |
+
|
26 |
+
public function __construct( $insOptionPrefix = '' ) {
|
27 |
+
parent::__construct( $this->constructStorageKey( $insOptionPrefix, self::Slug ), self::Slug );
|
28 |
+
$this->createTable();
|
29 |
+
$this->reset();
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Resets the object values to be re-used anew
|
34 |
+
*/
|
35 |
+
public function reset() {
|
36 |
+
parent::reset();
|
37 |
+
$this->m_sUniqueToken = '';
|
38 |
+
$this->m_sCommentStatus = '';
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
*/
|
43 |
+
public function run() {
|
44 |
+
parent::run();
|
45 |
+
if ( $this->getOption('enable_privacy_protect') == 'Y' ) {
|
46 |
+
add_action( 'http_api_debug', array( $this, 'logHttpRequest' ), 1000, 5 );
|
47 |
+
add_filter( 'http_request_args', array( $this, 'cleanHttpRequestData' ), 1000, 2 );
|
48 |
+
}
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* @param $oHttpResponse
|
53 |
+
* @param $sResponse
|
54 |
+
* @param $sCallingClass
|
55 |
+
* @param $aRequestArgs
|
56 |
+
* @param $sRequestUrl
|
57 |
+
* @return bool
|
58 |
+
*/
|
59 |
+
public function logHttpRequest( $oHttpResponse, $sResponse, $sCallingClass, $aRequestArgs, $sRequestUrl ) {
|
60 |
+
|
61 |
+
if ( $this->getOption('ignore_local_requests') == 'Y' && $this->getIsLocalRequest($aRequestArgs) ) {
|
62 |
+
return true;
|
63 |
+
}
|
64 |
+
|
65 |
+
// Now add new pending entry
|
66 |
+
$nNow = time();
|
67 |
+
$aData = array();
|
68 |
+
$aData[ 'request_url' ] = $sRequestUrl;
|
69 |
+
$aData[ 'request_method' ] = $aRequestArgs['method'];
|
70 |
+
$aData[ 'is_ssl' ] = strpos( $sRequestUrl, 'https' ) === 0? 1 : 0;
|
71 |
+
$aData[ 'is_error' ] = is_wp_error( $oHttpResponse )? 1 : 0;
|
72 |
+
$aData[ 'request_args' ] = serialize( $aRequestArgs );
|
73 |
+
$aData[ 'requested_at' ] = $nNow;
|
74 |
+
|
75 |
+
$mResult = $this->insertIntoTable( $aData );
|
76 |
+
return $mResult;
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* @param $aRequestArgs
|
81 |
+
* @param $sRequestUrl
|
82 |
+
* @return mixed
|
83 |
+
*/
|
84 |
+
public function cleanHttpRequestData( $aRequestArgs, $sRequestUrl ) {
|
85 |
+
|
86 |
+
$sSiteUrl = str_replace( array( 'http://', 'https://' ), '', network_home_url() );
|
87 |
+
$sRandomUrl = $this->generateRandomString().'.com';
|
88 |
+
|
89 |
+
if ( $this->getOption('filter_site_url') == 'Y'
|
90 |
+
|| ( $this->getOption('filter_wordpressorg_update_data') == 'Y' && ( strpos( $sRequestUrl, 'wordpress.org' ) !== false ) )
|
91 |
+
) {
|
92 |
+
$aRequestArgs['user-agent'] = str_replace( $sSiteUrl, $sRandomUrl, $aRequestArgs['user-agent'] );
|
93 |
+
|
94 |
+
$aHeaders = $aRequestArgs['headers'];
|
95 |
+
foreach( $aHeaders as $sKey => $sValue ) {
|
96 |
+
$aHeaders[$sKey] = str_replace( $sSiteUrl, $sRandomUrl, $aHeaders[$sKey] );
|
97 |
+
}
|
98 |
+
$aRequestArgs['headers'] = $aHeaders;
|
99 |
+
|
100 |
+
$aRequestArgs['icwp_wpsf'] = _wpsf__( 'Site URL filtered by the WordPress Simple Firewall plugin' );
|
101 |
+
|
102 |
+
// Now filter the URL only if it isn't LOCAL
|
103 |
+
if ( isset( $aRequestArgs['local'] ) && $aRequestArgs['local'] != 1 ) {
|
104 |
+
//unfortunately can't filter the URL.
|
105 |
+
//TODO: $pre = apply_filters( 'pre_http_request', false, $r, $url );
|
106 |
+
}
|
107 |
+
|
108 |
+
// if ( isset($aRequestArgs['headers']['wp_install']) ) {
|
109 |
+
// $aRequestArgs['headers']['wp_install'] = str_replace( $sSiteUrl, $sRandomUrl, $aRequestArgs['headers']['wp_install'] );
|
110 |
+
// }
|
111 |
+
// if ( isset($aRequestArgs['headers']['wp_blog']) ) {
|
112 |
+
// $aRequestArgs['headers']['wp_blog'] = str_replace( $sSiteUrl, $sRandomUrl, $aRequestArgs['headers']['wp_blog'] );
|
113 |
+
// }
|
114 |
+
}
|
115 |
+
return $aRequestArgs;
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* @param $aRequestArgs
|
120 |
+
* @return bool
|
121 |
+
*/
|
122 |
+
protected function getIsLocalRequest( &$aRequestArgs ) {
|
123 |
+
return isset( $aRequestArgs['local'] ) && $aRequestArgs['local'] == 1;
|
124 |
+
}
|
125 |
+
|
126 |
+
/**
|
127 |
+
* @param int $nLength
|
128 |
+
* @return string
|
129 |
+
*/
|
130 |
+
protected function generateRandomString( $nLength = 10 ) {
|
131 |
+
$sCharacters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
132 |
+
$sRandomString = '';
|
133 |
+
for ($i = 0; $i < $nLength; $i++) {
|
134 |
+
$sRandomString .= $sCharacters[rand(0, strlen($sCharacters) - 1)];
|
135 |
+
}
|
136 |
+
return $sRandomString;
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* @param boolean $infReverseOrder
|
141 |
+
* @return array - numerical array of all log data entries.
|
142 |
+
*/
|
143 |
+
public function getLogs( $infReverseOrder = false ) {
|
144 |
+
$aLogData = $this->selectAllFromTable();
|
145 |
+
if ( $infReverseOrder && $aLogData && is_array( $aLogData ) ) {
|
146 |
+
$aLogData = array_reverse( $aLogData );
|
147 |
+
}
|
148 |
+
return $aLogData;
|
149 |
+
}
|
150 |
+
|
151 |
+
public function createTable() {
|
152 |
+
$sSqlTables = "CREATE TABLE IF NOT EXISTS `%s` (
|
153 |
+
`id` int(11) NOT NULL AUTO_INCREMENT,
|
154 |
+
`request_url` varchar(255) NOT NULL DEFAULT '',
|
155 |
+
`request_port` mediumint(5) UNSIGNED NOT NULL DEFAULT 80,
|
156 |
+
`request_method` varchar(4) NOT NULL DEFAULT 'GET',
|
157 |
+
`request_args` text NOT NULL DEFAULT '',
|
158 |
+
`is_ssl` tinyint(1) NOT NULL DEFAULT 0,
|
159 |
+
`is_error` tinyint(1) NOT NULL DEFAULT 0,
|
160 |
+
`requested_at` int(15) NOT NULL DEFAULT 0,
|
161 |
+
`deleted_at` int(15) NOT NULL DEFAULT 0,
|
162 |
+
PRIMARY KEY (`id`)
|
163 |
+
) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
|
164 |
+
$sSqlTables = sprintf( $sSqlTables, $this->m_sTableName );
|
165 |
+
$mResult = $this->doSql( $sSqlTables );
|
166 |
+
}
|
167 |
+
}
|
168 |
+
|
169 |
+
endif;
|
170 |
+
|
171 |
+
if ( !class_exists('ICWP_WPSF_PrivacyProtectProcessor') ):
|
172 |
+
class ICWP_WPSF_PrivacyProtectProcessor extends ICWP_PrivacyProtectProcessor_V1 { }
|
173 |
+
endif;
|
src/icwp-pure-base.php
ADDED
@@ -0,0 +1,966 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if ( !defined('ICWP_DS') ) {
|
4 |
+
define( 'ICWP_DS', DIRECTORY_SEPARATOR );
|
5 |
+
}
|
6 |
+
|
7 |
+
require_once( dirname(__FILE__).'/icwp-once.php' );
|
8 |
+
require_once( dirname(__FILE__).'/icwp-wpfunctions.php' );
|
9 |
+
require_once( dirname(__FILE__).'/icwp-wpfilesystem.php' );
|
10 |
+
|
11 |
+
if ( !class_exists('ICWP_Pure_Base_V4') ):
|
12 |
+
|
13 |
+
class ICWP_Pure_Base_V4 extends ICWP_WPSF_Once {
|
14 |
+
|
15 |
+
const BaseTitle = 'iControlWP Plugins';
|
16 |
+
const BaseSlug = 'icwp';
|
17 |
+
const BasePermissions = 'manage_options';
|
18 |
+
|
19 |
+
const ViewExt = '.php';
|
20 |
+
const ViewDir = 'views';
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @var string
|
24 |
+
*/
|
25 |
+
protected $m_sVersion;
|
26 |
+
/**
|
27 |
+
* Set to true if it should never be shown in the dashboard
|
28 |
+
* @var string
|
29 |
+
*/
|
30 |
+
protected $m_fHeadless = false;
|
31 |
+
/**
|
32 |
+
* Set to true if this contains components from another plugin to stand alone
|
33 |
+
* @var string
|
34 |
+
*/
|
35 |
+
protected $m_fStandAlone = false;
|
36 |
+
/**
|
37 |
+
* Set to true if this contains components from another plugin to stand alone
|
38 |
+
* @var string
|
39 |
+
*/
|
40 |
+
protected $m_sAutoUpdateUrl = '';
|
41 |
+
/**
|
42 |
+
* @var boolean
|
43 |
+
*/
|
44 |
+
protected $m_fIsMultisite;
|
45 |
+
/**
|
46 |
+
* @var boolean
|
47 |
+
*/
|
48 |
+
protected $m_fNetworkAdminOnly = false;
|
49 |
+
|
50 |
+
/**
|
51 |
+
* @var string
|
52 |
+
*/
|
53 |
+
protected $m_sPluginHumanName;
|
54 |
+
/**
|
55 |
+
* @var string
|
56 |
+
*/
|
57 |
+
protected $m_sPluginTextDomain;
|
58 |
+
/**
|
59 |
+
* @var string
|
60 |
+
*/
|
61 |
+
protected $m_sPluginMenuTitle;
|
62 |
+
|
63 |
+
/**
|
64 |
+
* @var string
|
65 |
+
*/
|
66 |
+
protected $m_sPluginRootFile;
|
67 |
+
/**
|
68 |
+
* @var string
|
69 |
+
*/
|
70 |
+
protected $m_sPluginName;
|
71 |
+
/**
|
72 |
+
* @var string
|
73 |
+
*/
|
74 |
+
protected $m_sPluginDir;
|
75 |
+
/**
|
76 |
+
* @var string
|
77 |
+
*/
|
78 |
+
protected $m_sPluginPath;
|
79 |
+
/**
|
80 |
+
* @var string
|
81 |
+
*/
|
82 |
+
protected $m_sPluginFile;
|
83 |
+
/**
|
84 |
+
* @var string
|
85 |
+
*/
|
86 |
+
protected $m_sPluginUrl;
|
87 |
+
/**
|
88 |
+
* @var string
|
89 |
+
*/
|
90 |
+
protected static $sOptionPrefix = '';
|
91 |
+
|
92 |
+
protected $m_aPluginMenu;
|
93 |
+
|
94 |
+
protected $m_sParentMenuIdSuffix;
|
95 |
+
|
96 |
+
protected $m_sPluginSlug;
|
97 |
+
|
98 |
+
protected $fShowMarketing;
|
99 |
+
|
100 |
+
protected $m_fAutoPluginUpgrade = false;
|
101 |
+
|
102 |
+
/**
|
103 |
+
* @var ICWP_WpFunctions_WPSF;
|
104 |
+
*/
|
105 |
+
protected $m_oWpFunctions;
|
106 |
+
|
107 |
+
/**
|
108 |
+
* @var ICWP_WpFilesystem_WPSF;
|
109 |
+
*/
|
110 |
+
protected $m_oWpFs;
|
111 |
+
|
112 |
+
public function __construct() {
|
113 |
+
|
114 |
+
add_action( 'plugins_loaded', array( $this, 'onWpPluginsLoaded' ) );
|
115 |
+
add_action( 'init', array( $this, 'onWpInit' ), 0 );
|
116 |
+
if ( $this->isValidAdminArea() ) {
|
117 |
+
add_action( 'admin_init', array( $this, 'onWpAdminInit' ) );
|
118 |
+
add_action( 'admin_notices', array( $this, 'onWpAdminNotices' ) );
|
119 |
+
add_action( 'network_admin_notices', array( $this, 'onWpAdminNotices' ) );
|
120 |
+
add_action( 'admin_menu', array( $this, 'onWpAdminMenu' ) );
|
121 |
+
add_action( 'network_admin_menu', array( $this, 'onWpNetworkAdminMenu' ) );
|
122 |
+
add_action( 'plugin_action_links', array( $this, 'onWpPluginActionLinks' ), 10, 4 );
|
123 |
+
add_action( 'deactivate_plugin', array( $this, 'onWpHookDeactivatePlugin' ), 1, 1 );
|
124 |
+
add_action( 'wp_before_admin_bar_render', array( $this, 'onWpAdminBar' ), 1, 9999 );
|
125 |
+
}
|
126 |
+
add_action( 'in_plugin_update_message-'.$this->m_sPluginFile, array( $this, 'onWpPluginUpdateMessage' ) );
|
127 |
+
add_action( 'shutdown', array( $this, 'onWpShutdown' ) );
|
128 |
+
|
129 |
+
$this->m_fIsMultisite = function_exists( 'is_multisite' ) && is_multisite();
|
130 |
+
$this->m_oWpFs = ICWP_WpFilesystem_WPSF::GetInstance();
|
131 |
+
$this->setPaths();
|
132 |
+
$this->registerActivationHooks();
|
133 |
+
}
|
134 |
+
|
135 |
+
/**
|
136 |
+
* This is a generic plugin auto-update checker. Since the library is never included WordPress.org
|
137 |
+
* plugins, this may never actually run.
|
138 |
+
*
|
139 |
+
* @return void
|
140 |
+
*/
|
141 |
+
protected function setupAutoUpdates() {
|
142 |
+
$sLibSource = $this->m_sPluginDir.'/src/lib/plugin-update-checker.php';
|
143 |
+
if ( !is_file($sLibSource) || empty( $this->m_sAutoUpdateUrl ) ) {
|
144 |
+
return;
|
145 |
+
}
|
146 |
+
require_once( $sLibSource );
|
147 |
+
$oUpdateChecker = new PluginUpdateChecker(
|
148 |
+
$this->m_sAutoUpdateUrl,
|
149 |
+
$this->m_sPluginRootFile,
|
150 |
+
$this->m_sPluginTextDomain
|
151 |
+
);
|
152 |
+
}
|
153 |
+
|
154 |
+
protected function isValidAdminArea() {
|
155 |
+
if ( !$this->m_fIsMultisite && is_admin() ) {
|
156 |
+
return true;
|
157 |
+
}
|
158 |
+
else if ( $this->m_fNetworkAdminOnly && $this->m_fIsMultisite && is_network_admin() ) {
|
159 |
+
return true;
|
160 |
+
}
|
161 |
+
return false;
|
162 |
+
}
|
163 |
+
|
164 |
+
/**
|
165 |
+
* Registers the plugins activation, deactivate and uninstall hooks.
|
166 |
+
*/
|
167 |
+
protected function registerActivationHooks() {
|
168 |
+
register_activation_hook( $this->m_sPluginRootFile, array( $this, 'onWpActivatePlugin' ) );
|
169 |
+
register_deactivation_hook( $this->m_sPluginRootFile, array( $this, 'onWpDeactivatePlugin' ) );
|
170 |
+
// register_uninstall_hook( $this->m_sPluginRootFile, array( $this, 'onWpUninstallPlugin' ) );
|
171 |
+
}
|
172 |
+
|
173 |
+
/**
|
174 |
+
* @since v3.0.0
|
175 |
+
*/
|
176 |
+
protected function setPaths() {
|
177 |
+
|
178 |
+
if ( empty( $this->m_sPluginRootFile ) ) {
|
179 |
+
$this->m_sPluginRootFile = __FILE__;
|
180 |
+
}
|
181 |
+
$this->m_sPluginName = basename( $this->m_sPluginRootFile );
|
182 |
+
$this->m_sPluginPath = plugin_basename( dirname( $this->m_sPluginRootFile ) );
|
183 |
+
$this->m_sPluginFile = plugin_basename( $this->m_sPluginRootFile );
|
184 |
+
$this->m_sPluginDir = dirname( $this->m_sPluginRootFile ).ICWP_DS;
|
185 |
+
$this->m_sPluginUrl = plugins_url( '/', $this->m_sPluginRootFile ) ; //this seems to use SSL more reliably than WP_PLUGIN_URL
|
186 |
+
}
|
187 |
+
|
188 |
+
/**
|
189 |
+
* @return string
|
190 |
+
*/
|
191 |
+
public function getPluginFile() {
|
192 |
+
return $this->m_sPluginFile;
|
193 |
+
}
|
194 |
+
|
195 |
+
/**
|
196 |
+
* @return boolean
|
197 |
+
*/
|
198 |
+
protected function hasPermissionToView() {
|
199 |
+
return $this->hasPermissionToSubmit();
|
200 |
+
}
|
201 |
+
/**
|
202 |
+
* @return boolean
|
203 |
+
*/
|
204 |
+
protected function hasPermissionToSubmit() {
|
205 |
+
// first a basic admin check
|
206 |
+
return is_super_admin() && current_user_can( 'manage_options' );
|
207 |
+
}
|
208 |
+
|
209 |
+
public function doPluginUpdateCheck() {
|
210 |
+
$this->loadWpFunctions();
|
211 |
+
$this->m_oWpFunctions->getIsPluginUpdateAvailable( $this->m_sPluginPath );
|
212 |
+
}
|
213 |
+
|
214 |
+
protected function getFullParentMenuId() {
|
215 |
+
return self::BaseSlug .'-'. $this->m_sParentMenuIdSuffix;
|
216 |
+
}
|
217 |
+
|
218 |
+
protected function display( $insView, $inaData = array() ) {
|
219 |
+
$sFile = $this->m_sPluginDir.self::ViewDir.ICWP_DS.$insView.self::ViewExt;
|
220 |
+
|
221 |
+
if ( !is_file( $sFile ) ) {
|
222 |
+
echo "View not found: ".$sFile;
|
223 |
+
return false;
|
224 |
+
}
|
225 |
+
|
226 |
+
if ( count( $inaData ) > 0 ) {
|
227 |
+
extract( $inaData, EXTR_PREFIX_ALL, self::BaseSlug );
|
228 |
+
}
|
229 |
+
|
230 |
+
ob_start();
|
231 |
+
include( $sFile );
|
232 |
+
$sContents = ob_get_contents();
|
233 |
+
ob_end_clean();
|
234 |
+
|
235 |
+
echo $sContents;
|
236 |
+
return true;
|
237 |
+
}
|
238 |
+
|
239 |
+
protected function getSubmenuPageTitle( $insTitle ) {
|
240 |
+
return self::BaseTitle.' - '.$insTitle;
|
241 |
+
}
|
242 |
+
protected function getSubmenuId( $insId = '' ) {
|
243 |
+
$sExtension = empty($insId)? '' : '-'.$insId;
|
244 |
+
return $this->getFullParentMenuId().$sExtension;
|
245 |
+
}
|
246 |
+
|
247 |
+
/**
|
248 |
+
* Hooked to 'plugins_loaded'
|
249 |
+
*/
|
250 |
+
public function onWpPluginsLoaded() {
|
251 |
+
$this->setupAutoUpdates();
|
252 |
+
if ( is_admin() ) {
|
253 |
+
//Handle plugin upgrades
|
254 |
+
$this->handlePluginUpgrade();
|
255 |
+
$this->doPluginUpdateCheck();
|
256 |
+
$this->load_textdomain();
|
257 |
+
}
|
258 |
+
if ( $this->isIcwpPluginFormSubmit() ) {
|
259 |
+
$this->handlePluginFormSubmit();
|
260 |
+
}
|
261 |
+
add_filter( 'all_plugins', array( $this, 'hidePluginFromTableList' ) );
|
262 |
+
add_filter( 'site_transient_update_plugins', array( $this, 'hidePluginUpdatesFromUI' ) );
|
263 |
+
$this->removePluginConflicts(); // removes conflicts with other plugins
|
264 |
+
}
|
265 |
+
|
266 |
+
/**
|
267 |
+
* Override this to remove conflicts with other plugins that may have loaded
|
268 |
+
* that interfere with normal operations.
|
269 |
+
*/
|
270 |
+
protected function removePluginConflicts() {}
|
271 |
+
|
272 |
+
/**
|
273 |
+
* Added to a WordPress filter ('all_plugins') which will remove this particular plugin from the
|
274 |
+
* list of all plugins based on the "plugin file" name.
|
275 |
+
*
|
276 |
+
* @uses $this->m_fHeadless if the plugin is headless, it is hidden
|
277 |
+
* @return array
|
278 |
+
*/
|
279 |
+
public function hidePluginFromTableList( $inaPlugins ) {
|
280 |
+
|
281 |
+
if ( !$this->m_fHeadless ) {
|
282 |
+
return $inaPlugins;
|
283 |
+
}
|
284 |
+
|
285 |
+
foreach ( $inaPlugins as $sName => $aData ) {
|
286 |
+
if ( $this->m_sPluginFile === $sName ) {
|
287 |
+
unset( $inaPlugins[$sName] );
|
288 |
+
}
|
289 |
+
}
|
290 |
+
return $inaPlugins;
|
291 |
+
}
|
292 |
+
|
293 |
+
/**
|
294 |
+
* Added to the WordPress filter ('site_transient_update_plugins') in order to remove visibility of updates
|
295 |
+
* from the WordPress Admin UI.
|
296 |
+
*
|
297 |
+
* In order to ensure that WordPress still checks for plugin updates it will not remove this plugin from
|
298 |
+
* the list of plugins if DOING_CRON is set to true.
|
299 |
+
*
|
300 |
+
* @uses $this->m_fHeadless if the plugin is headless, it is hidden
|
301 |
+
* @return StdClass
|
302 |
+
*/
|
303 |
+
public function hidePluginUpdatesFromUI( $inoPlugins ) {
|
304 |
+
|
305 |
+
if ( ( defined( 'DOING_CRON' ) && DOING_CRON ) || !$this->m_fHeadless ) {
|
306 |
+
return $inoPlugins;
|
307 |
+
}
|
308 |
+
|
309 |
+
if ( !empty( $inoPlugins->response ) ) {
|
310 |
+
$aResponse = $inoPlugins->response;
|
311 |
+
foreach ( $aResponse as $sPluginFile => $oData ) {
|
312 |
+
if ( $sPluginFile == $this->m_sPluginFile ) {
|
313 |
+
unset( $inoPlugins->response[$sPluginFile] );
|
314 |
+
}
|
315 |
+
}
|
316 |
+
}
|
317 |
+
return $inoPlugins;
|
318 |
+
}
|
319 |
+
|
320 |
+
/**
|
321 |
+
* Load the multilingual aspect of the plugin
|
322 |
+
*/
|
323 |
+
public function load_textdomain() {
|
324 |
+
$stest = dirname( $this->m_sPluginRootFile );
|
325 |
+
// var_dump($stest);
|
326 |
+
// var_dump($this->m_sPluginTextDomain);
|
327 |
+
load_plugin_textdomain( $this->m_sPluginTextDomain, false, dirname($this->m_sPluginFile) . '/languages/' );
|
328 |
+
}
|
329 |
+
|
330 |
+
public function onWpInit() { }
|
331 |
+
|
332 |
+
public function onWpAdminInit() {
|
333 |
+
//Do Plugin-Specific Admin Work
|
334 |
+
if ( $this->isIcwpPluginAdminPage() ) {
|
335 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'enqueueBootstrapLegacyAdminCss' ), 99 );
|
336 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'enqueuePluginAdminCss' ), 99 );
|
337 |
+
}
|
338 |
+
}
|
339 |
+
|
340 |
+
public function onWpAdminMenu() {
|
341 |
+
if ( !$this->isValidAdminArea() ) {
|
342 |
+
return true;
|
343 |
+
}
|
344 |
+
$this->createMenu();
|
345 |
+
}
|
346 |
+
|
347 |
+
public function onWpNetworkAdminMenu() {
|
348 |
+
if ( !$this->isValidAdminArea() ) {
|
349 |
+
return true;
|
350 |
+
}
|
351 |
+
$this->createMenu();
|
352 |
+
}
|
353 |
+
|
354 |
+
protected function createMenu() {
|
355 |
+
|
356 |
+
if ( $this->m_fHeadless ) {
|
357 |
+
return true;
|
358 |
+
}
|
359 |
+
|
360 |
+
$sFullParentMenuId = $this->getFullParentMenuId();
|
361 |
+
add_menu_page( self::BaseTitle, $this->m_sPluginMenuTitle, self::BasePermissions, $sFullParentMenuId, array( $this, 'onDisplayAll' ), $this->getPluginLogoUrl16() );
|
362 |
+
//Create and Add the submenu items
|
363 |
+
$this->createPluginSubMenuItems();
|
364 |
+
if ( !empty($this->m_aPluginMenu) ) {
|
365 |
+
foreach ( $this->m_aPluginMenu as $sMenuTitle => $aMenu ) {
|
366 |
+
list( $sMenuItemText, $sMenuItemId, $sMenuCallBack ) = $aMenu;
|
367 |
+
add_submenu_page( $sFullParentMenuId, $sMenuTitle, $sMenuItemText, self::BasePermissions, $sMenuItemId, array( $this, $sMenuCallBack ) );
|
368 |
+
}
|
369 |
+
}
|
370 |
+
$this->fixSubmenu();
|
371 |
+
}
|
372 |
+
|
373 |
+
protected function createPluginSubMenuItems(){
|
374 |
+
/* Override to create array of sub-menu items
|
375 |
+
$this->m_aPluginMenu = array(
|
376 |
+
//Menu Page Title => Menu Item name, page ID (slug), callback function onLoad.
|
377 |
+
$this->getSubmenuPageTitle( 'Content by Country' ) => array( 'Content by Country', $this->getSubmenuId('main'), 'onDisplayCbcMain' ),
|
378 |
+
);
|
379 |
+
*/
|
380 |
+
}
|
381 |
+
|
382 |
+
protected function fixSubmenu() {
|
383 |
+
global $submenu;
|
384 |
+
$sFullParentMenuId = $this->getFullParentMenuId();
|
385 |
+
if ( isset( $submenu[$sFullParentMenuId] ) ) {
|
386 |
+
$submenu[$sFullParentMenuId][0][0] = 'Dashboard';
|
387 |
+
}
|
388 |
+
}
|
389 |
+
|
390 |
+
/**
|
391 |
+
* Displaying all views now goes through this central function and we work out
|
392 |
+
* what to display based on the name of current hook/filter being processed.
|
393 |
+
*/
|
394 |
+
public function onDisplayAll() {
|
395 |
+
$this->onDisplayMainMenu();
|
396 |
+
}
|
397 |
+
|
398 |
+
/**
|
399 |
+
* The callback function for the main admin menu index page
|
400 |
+
*/
|
401 |
+
public function onDisplayMainMenu() {
|
402 |
+
$aData = array(
|
403 |
+
'plugin_url' => $this->m_sPluginUrl,
|
404 |
+
'fShowAds' => $this->isShowMarketing()
|
405 |
+
);
|
406 |
+
$this->display( self::BaseSlug.'_'.$this->m_sParentMenuIdSuffix.'_index', $aData );
|
407 |
+
}
|
408 |
+
|
409 |
+
protected function getBaseDisplayData( $insSubmenuId = '' ) {
|
410 |
+
return array(
|
411 |
+
'plugin_url' => $this->m_sPluginUrl,
|
412 |
+
'var_prefix' => self::$sOptionPrefix,
|
413 |
+
'sPluginName' => $this->m_sPluginHumanName,
|
414 |
+
'fShowAds' => $this->isShowMarketing(),
|
415 |
+
'nonce_field' => $this->getSubmenuId( $insSubmenuId ),
|
416 |
+
'form_action' => 'admin.php?page='.$this->getSubmenuId( $insSubmenuId )
|
417 |
+
);
|
418 |
+
}
|
419 |
+
|
420 |
+
/**
|
421 |
+
* @return bool
|
422 |
+
*/
|
423 |
+
protected function isShowMarketing() {
|
424 |
+
|
425 |
+
if ( isset($this->fShowMarketing) ) {
|
426 |
+
return $this->fShowMarketing;
|
427 |
+
}
|
428 |
+
$this->fShowMarketing = true;
|
429 |
+
if ( class_exists( 'Worpit_Plugin' ) ) {
|
430 |
+
if ( method_exists( 'Worpit_Plugin', 'IsLinked' ) ) {
|
431 |
+
$this->fShowMarketing = !Worpit_Plugin::IsLinked();
|
432 |
+
}
|
433 |
+
else if ( function_exists( 'get_option' )
|
434 |
+
&& get_option( Worpit_Plugin::$VariablePrefix.'assigned' ) == 'Y'
|
435 |
+
&& get_option( Worpit_Plugin::$VariablePrefix.'assigned_to' ) != '' ) {
|
436 |
+
|
437 |
+
$this->fShowMarketing = false;
|
438 |
+
}
|
439 |
+
}
|
440 |
+
return $this->fShowMarketing ;
|
441 |
+
}
|
442 |
+
|
443 |
+
/**
|
444 |
+
* On the plugins listing page, hides the edit and deactivate links
|
445 |
+
* for this plugin based on permissions
|
446 |
+
*
|
447 |
+
* @see ICWP_Pure_Base_V1::onWpPluginActionLinks()
|
448 |
+
*/
|
449 |
+
public function onWpPluginActionLinks( $inaActionLinks, $insFile ) {
|
450 |
+
|
451 |
+
if ( $insFile == $this->m_sPluginFile ) {
|
452 |
+
if ( !$this->hasPermissionToSubmit() ) {
|
453 |
+
if ( array_key_exists( 'edit', $inaActionLinks ) ) {
|
454 |
+
unset( $inaActionLinks['edit'] );
|
455 |
+
}
|
456 |
+
if ( array_key_exists( 'deactivate', $inaActionLinks ) ) {
|
457 |
+
unset( $inaActionLinks['deactivate'] );
|
458 |
+
}
|
459 |
+
}
|
460 |
+
$sSettingsLink = '<a href="'.network_admin_url( "admin.php" ).'?page='.$this->getSubmenuId().'">' . 'Dashboard' . '</a>';
|
461 |
+
array_unshift( $inaActionLinks, $sSettingsLink );
|
462 |
+
}
|
463 |
+
return $inaActionLinks;
|
464 |
+
}
|
465 |
+
|
466 |
+
/**
|
467 |
+
* Override this method to handle all the admin notices
|
468 |
+
*/
|
469 |
+
public function onWpAdminNotices() {
|
470 |
+
// Do we have admin priviledges?
|
471 |
+
if ( !$this->isValidAdminArea() || !current_user_can( 'manage_options' ) ) {
|
472 |
+
return true;
|
473 |
+
}
|
474 |
+
|
475 |
+
$this->doAdminNoticeOptionsUpdated();
|
476 |
+
|
477 |
+
// If we've set to not show admin notices ever
|
478 |
+
if ( $this->getShowAdminNotices() ) {
|
479 |
+
|
480 |
+
if ( $this->hasPermissionToView() ) {
|
481 |
+
$this->doAdminNoticePostUpgrade();
|
482 |
+
$this->doAdminNoticeTranslations();
|
483 |
+
$this->doAdminNoticeMailingListSignup();
|
484 |
+
}
|
485 |
+
if ( $this->hasPermissionToSubmit() ) {
|
486 |
+
$this->doAdminNoticePluginUpgradeAvailable();
|
487 |
+
}
|
488 |
+
}
|
489 |
+
}
|
490 |
+
|
491 |
+
protected function doAdminNoticePluginUpgradeAvailable() {
|
492 |
+
|
493 |
+
// Don't show on the update page.
|
494 |
+
if ( isset( $GLOBALS['pagenow'] ) && $GLOBALS['pagenow'] == 'update.php' ) {
|
495 |
+
return;
|
496 |
+
}
|
497 |
+
// We need to have the correct plugin file set before proceeding.
|
498 |
+
if ( !isset( $this->m_sPluginFile ) ) {
|
499 |
+
return;
|
500 |
+
}
|
501 |
+
|
502 |
+
$this->loadWpFunctions();
|
503 |
+
$oUpdate = $this->m_oWpFunctions->getIsPluginUpdateAvailable( $this->m_sPluginFile );
|
504 |
+
if ( !$oUpdate ) {
|
505 |
+
return;
|
506 |
+
}
|
507 |
+
$sNotice = $this->getAdminNoticeHtml_PluginUpgradeAvailable();
|
508 |
+
$this->getAdminNoticeHtml( $sNotice, 'updated', true );
|
509 |
+
}
|
510 |
+
|
511 |
+
protected function doAdminNoticeOptionsUpdated(){
|
512 |
+
$sHtml = $this->getAdminNoticeHtml_OptionsUpdated();
|
513 |
+
if ( !empty($sHtml) ) {
|
514 |
+
$this->getAdminNoticeHtml( $sHtml, 'updated', true );
|
515 |
+
}
|
516 |
+
}
|
517 |
+
|
518 |
+
protected function doAdminNoticePostUpgrade() {
|
519 |
+
|
520 |
+
$sCurrentMetaValue = $this->getUserMeta( 'current_version' );
|
521 |
+
if ( $sCurrentMetaValue === $this->m_sVersion ) {
|
522 |
+
return;
|
523 |
+
}
|
524 |
+
$sHtml = $this->getAdminNoticeHtml_VersionUpgrade();
|
525 |
+
if ( !empty($sHtml) ) {
|
526 |
+
$this->getAdminNoticeHtml( $sHtml, 'updated', true );
|
527 |
+
}
|
528 |
+
}
|
529 |
+
|
530 |
+
/**
|
531 |
+
*
|
532 |
+
*/
|
533 |
+
protected function doAdminNoticeTranslations(){
|
534 |
+
|
535 |
+
$sCurrentMetaValue = $this->getUserMeta( 'plugin_translation_notice' );
|
536 |
+
if ( $sCurrentMetaValue === 'Y' ) {
|
537 |
+
return;
|
538 |
+
}
|
539 |
+
|
540 |
+
$sHtml = $this->getAdminNoticeHtml_Translations();
|
541 |
+
if ( !empty($sHtml) ) {
|
542 |
+
$this->getAdminNoticeHtml( $sHtml, 'updated', true );
|
543 |
+
}
|
544 |
+
}
|
545 |
+
|
546 |
+
/**
|
547 |
+
*
|
548 |
+
*/
|
549 |
+
protected function doAdminNoticeMailingListSignup(){
|
550 |
+
|
551 |
+
$sCurrentMetaValue = $this->getUserMeta( 'plugin_mailing_list_signup' );
|
552 |
+
if ( $sCurrentMetaValue == 'Y' ) {
|
553 |
+
return;
|
554 |
+
}
|
555 |
+
|
556 |
+
$sHtml = $this->getAdminNoticeHtml_MailingListSignup();
|
557 |
+
if ( !empty($sHtml) ) {
|
558 |
+
$this->getAdminNoticeHtml( $sHtml, 'updated', true );
|
559 |
+
}
|
560 |
+
}
|
561 |
+
|
562 |
+
/**
|
563 |
+
* Override this to change the message for the particular plugin upgrade.
|
564 |
+
*/
|
565 |
+
protected function getAdminNoticeHtml_PluginUpgradeAvailable() {
|
566 |
+
$sUpgradeLink = $this->m_oWpFunctions->getPluginUpgradeLink( $this->m_sPluginFile );
|
567 |
+
$sNotice = '<p>There is an update available for the %s plugin. <a href="%s">Click to update immediately</a>.</p>';
|
568 |
+
$sNotice = sprintf( $sNotice, $this->m_sPluginHumanName, $sUpgradeLink );
|
569 |
+
return $sNotice;
|
570 |
+
}
|
571 |
+
|
572 |
+
protected function getAdminNoticeHtml_OptionsUpdated() { }
|
573 |
+
protected function getAdminNoticeHtml_VersionUpgrade() { }
|
574 |
+
protected function getAdminNoticeHtml_Translations() { }
|
575 |
+
protected function getAdminNoticeHtml_MailingListSignup() { }
|
576 |
+
|
577 |
+
/**
|
578 |
+
* Provides the basic HTML template for printing a WordPress Admin Notices
|
579 |
+
*
|
580 |
+
* @param $insNotice - The message to be displayed.
|
581 |
+
* @param $insMessageClass - either error or updated
|
582 |
+
* @param $infPrint - if true, will echo. false will return the string
|
583 |
+
* @return boolean|string
|
584 |
+
*/
|
585 |
+
protected function getAdminNoticeHtml( $insNotice = '', $insMessageClass = 'updated', $infPrint = false ) {
|
586 |
+
|
587 |
+
$sFullNotice = '
|
588 |
+
<div id="message" class="'.$insMessageClass.'">
|
589 |
+
<style>#message form { margin: 0px; padding-bottom: 8px; }</style>
|
590 |
+
'.$insNotice.'
|
591 |
+
</div>
|
592 |
+
';
|
593 |
+
|
594 |
+
if ( $infPrint ) {
|
595 |
+
echo $sFullNotice;
|
596 |
+
return true;
|
597 |
+
} else {
|
598 |
+
return $sFullNotice;
|
599 |
+
}
|
600 |
+
}
|
601 |
+
|
602 |
+
/**
|
603 |
+
*
|
604 |
+
*/
|
605 |
+
protected function getShowAdminNotices() {
|
606 |
+
return true;
|
607 |
+
}
|
608 |
+
|
609 |
+
/**
|
610 |
+
* Updates the current (or supplied user ID) user meta data with the version of the plugin
|
611 |
+
*
|
612 |
+
* @param $nId
|
613 |
+
* @param $sValue
|
614 |
+
*/
|
615 |
+
protected function updateTranslationNoticeShownUserMeta( $nId = '', $sValue = 'Y' ) {
|
616 |
+
$this->updateUserMeta( 'plugin_translation_notice', $sValue, $nId );
|
617 |
+
}
|
618 |
+
/**
|
619 |
+
* Updates the current (or supplied user ID) user meta data with the version of the plugin
|
620 |
+
*
|
621 |
+
* @param $nId
|
622 |
+
* @param $sValue
|
623 |
+
*/
|
624 |
+
protected function updateMailingListSignupShownUserMeta( $nId = '', $sValue = 'Y' ) {
|
625 |
+
$this->updateUserMeta( 'plugin_mailing_list_signup', $sValue, $nId );
|
626 |
+
}
|
627 |
+
|
628 |
+
/**
|
629 |
+
* Updates the current (or supplied user ID) user meta data with the version of the plugin
|
630 |
+
*
|
631 |
+
* @param unknown_type $innId
|
632 |
+
*/
|
633 |
+
protected function updateVersionUserMeta( $innId = '' ) {
|
634 |
+
$this->updateUserMeta( 'current_version', $this->m_sVersion, $innId );
|
635 |
+
}
|
636 |
+
|
637 |
+
/**
|
638 |
+
* Updates the current (or supplied user ID) user meta data with the version of the plugin
|
639 |
+
*
|
640 |
+
* @param string $insKey
|
641 |
+
* @param mixed $mValue
|
642 |
+
* @param integer $innId -user ID
|
643 |
+
* @return boolean
|
644 |
+
*/
|
645 |
+
protected function updateUserMeta( $insKey, $mValue, $innId = null ) {
|
646 |
+
if ( empty( $innId ) ) {
|
647 |
+
$oCurrentUser = $this->getCurrentUser();
|
648 |
+
if ( !$oCurrentUser ) {
|
649 |
+
return;
|
650 |
+
}
|
651 |
+
$nUserId = $oCurrentUser->ID;
|
652 |
+
}
|
653 |
+
else {
|
654 |
+
$nUserId = $innId;
|
655 |
+
}
|
656 |
+
return update_user_meta( $nUserId, self::$sOptionPrefix.$insKey, $mValue );
|
657 |
+
}
|
658 |
+
|
659 |
+
protected function getUserMeta( $sKey ) {
|
660 |
+
|
661 |
+
$oCurrentUser = $this->getCurrentUser();
|
662 |
+
if ( !$oCurrentUser ) {
|
663 |
+
return;
|
664 |
+
}
|
665 |
+
$nUserId = $oCurrentUser->ID;
|
666 |
+
|
667 |
+
$sCurrentMetaValue = get_user_meta( $nUserId, self::$sOptionPrefix.$sKey, true );
|
668 |
+
// A guard whereby if we can't ever get a value for this meta, it means we can never set it.
|
669 |
+
if ( empty( $sCurrentMetaValue ) ) {
|
670 |
+
//the value has never been set, or it's been installed for the first time.
|
671 |
+
$this->updateUserMeta( $sKey, 'temp', $nUserId );
|
672 |
+
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.
|
673 |
+
}
|
674 |
+
return $sCurrentMetaValue;
|
675 |
+
}
|
676 |
+
|
677 |
+
/**
|
678 |
+
* @return mixed
|
679 |
+
*/
|
680 |
+
protected function getCurrentUser() {
|
681 |
+
if( !is_user_logged_in() ) {
|
682 |
+
return false;
|
683 |
+
}
|
684 |
+
global $current_user;
|
685 |
+
get_currentuserinfo();
|
686 |
+
return $current_user;
|
687 |
+
}
|
688 |
+
|
689 |
+
/**
|
690 |
+
* This is called from within onWpAdminInit. Use this solely to manage upgrades of the plugin
|
691 |
+
*/
|
692 |
+
protected function handlePluginUpgrade() {
|
693 |
+
if ( !is_admin() || !current_user_can( 'manage_options' ) ) {
|
694 |
+
return;
|
695 |
+
}
|
696 |
+
if ( $this->m_fAutoPluginUpgrade ) {
|
697 |
+
$this->loadWpFunctions();
|
698 |
+
$this->m_oWpFunctions->doPluginUpgrade( $this->m_sPluginFile );
|
699 |
+
}
|
700 |
+
}
|
701 |
+
|
702 |
+
protected function handlePluginFormSubmit() { }
|
703 |
+
|
704 |
+
protected function isIcwpPluginFormSubmit() {
|
705 |
+
return isset( $_POST['icwp_plugin_form_submit'] );
|
706 |
+
}
|
707 |
+
|
708 |
+
protected function isIcwpPluginAdminPage() {
|
709 |
+
$sSubPageNow = isset( $_GET['page'] )? $_GET['page']: '';
|
710 |
+
if ( is_admin() && !empty($sSubPageNow) && (strpos( $sSubPageNow, $this->getFullParentMenuId() ) === 0 )) { //admin area, and the 'page' begins with 'worpit'
|
711 |
+
return true;
|
712 |
+
}
|
713 |
+
return false;
|
714 |
+
}
|
715 |
+
|
716 |
+
public function enqueueBootstrapAdminCss() {
|
717 |
+
wp_register_style( self::$sOptionPrefix.'bootstrap_wpadmin_css', $this->getCssUrl( 'bootstrap-wpadmin.css' ), false, $this->m_sVersion );
|
718 |
+
wp_enqueue_style( self::$sOptionPrefix.'bootstrap_wpadmin_css' );
|
719 |
+
}
|
720 |
+
|
721 |
+
public function enqueueBootstrapLegacyAdminCss() {
|
722 |
+
wp_register_style( self::$sOptionPrefix.'bootstrap_wpadmin_legacy_css', $this->getCssUrl( 'bootstrap-wpadmin-legacy.css' ), false, $this->m_sVersion );
|
723 |
+
wp_enqueue_style( self::$sOptionPrefix.'bootstrap_wpadmin_legacy_css' );
|
724 |
+
wp_register_style( self::$sOptionPrefix.'bootstrap_wpadmin_css_fixes', $this->getCssUrl('bootstrap-wpadmin-fixes.css'), array( self::$sOptionPrefix.'bootstrap_wpadmin_legacy_css'), $this->m_sVersion );
|
725 |
+
wp_enqueue_style( self::$sOptionPrefix.'bootstrap_wpadmin_css_fixes' );
|
726 |
+
}
|
727 |
+
|
728 |
+
public function enqueuePluginAdminCss() {
|
729 |
+
wp_register_style( self::$sOptionPrefix.'plugin_css', $this->getCssUrl('plugin.css'), array(self::$sOptionPrefix.'bootstrap_wpadmin_css_fixes'), $this->m_sVersion );
|
730 |
+
wp_enqueue_style( self::$sOptionPrefix.'plugin_css' );
|
731 |
+
}
|
732 |
+
|
733 |
+
protected function redirect( $insUrl, $innTimeout = 1 ) {
|
734 |
+
echo '
|
735 |
+
<script type="text/javascript">
|
736 |
+
function redirect() {
|
737 |
+
window.location = "'.$insUrl.'";
|
738 |
+
}
|
739 |
+
var oTimer = setTimeout( "redirect()", "'.($innTimeout * 1000).'" );
|
740 |
+
</script>';
|
741 |
+
}
|
742 |
+
|
743 |
+
/**
|
744 |
+
* Displays a message in the plugins listing when a plugin has an update available.
|
745 |
+
* @param string $insPlugin
|
746 |
+
*/
|
747 |
+
public function onWpPluginUpdateMessage() {
|
748 |
+
echo '<div style="color: #dd3333;">'
|
749 |
+
.$this->getPluginsListUpdateMessage()
|
750 |
+
. '</div>';
|
751 |
+
}
|
752 |
+
|
753 |
+
protected function getPluginsListUpdateMessage() {
|
754 |
+
return '';
|
755 |
+
}
|
756 |
+
|
757 |
+
/**
|
758 |
+
* Hooked to 'deactivate_plugin' and can be used to interrupt the deactivation of this plugin.
|
759 |
+
* @param string $insPlugin
|
760 |
+
*/
|
761 |
+
public function onWpHookDeactivatePlugin( $insPlugin ) {
|
762 |
+
if ( strpos( $insPlugin, $this->m_sPluginName ) !== false ) {
|
763 |
+
$this->doPreventDeactivation( $insPlugin );
|
764 |
+
}
|
765 |
+
}
|
766 |
+
|
767 |
+
/**
|
768 |
+
* @param string $insPlugin - the path to the plugin file
|
769 |
+
*/
|
770 |
+
protected function doPreventDeactivation( $insPlugin ) {
|
771 |
+
if ( !$this->hasPermissionToSubmit() ) {
|
772 |
+
wp_die( 'Sorry, you do not have permission to disable this plugin. You need to authenticate first.' );
|
773 |
+
}
|
774 |
+
}
|
775 |
+
|
776 |
+
/**
|
777 |
+
* Gets the WordPress option based on this object's option prefix.
|
778 |
+
* @param string $insKey
|
779 |
+
* @return mixed
|
780 |
+
*/
|
781 |
+
public function getOption( $insKey ) {
|
782 |
+
return get_option( $this->getOptionKey($insKey) );
|
783 |
+
}
|
784 |
+
|
785 |
+
/**
|
786 |
+
* @param string $insKey
|
787 |
+
* @param mixed $insValue
|
788 |
+
* @return boolean
|
789 |
+
*/
|
790 |
+
public function addOption( $insKey, $inmValue ) {
|
791 |
+
return add_option( $this->getOptionKey($insKey), $inmValue );
|
792 |
+
}
|
793 |
+
|
794 |
+
/**
|
795 |
+
* @param string $insKey
|
796 |
+
* @param mixed $inmValue
|
797 |
+
* @return boolean
|
798 |
+
*/
|
799 |
+
public function updateOption( $insKey, $inmValue ) {
|
800 |
+
return update_option( $this->getOptionKey($insKey), $inmValue );
|
801 |
+
}
|
802 |
+
|
803 |
+
/**
|
804 |
+
* @param string $insKey
|
805 |
+
* @return boolean
|
806 |
+
*/
|
807 |
+
public function deleteOption( $insKey ) {
|
808 |
+
return delete_option( $this->getOptionKey($insKey) );
|
809 |
+
}
|
810 |
+
|
811 |
+
public function getOptionKey( $insKey ) {
|
812 |
+
return self::$sOptionPrefix.$insKey;
|
813 |
+
}
|
814 |
+
|
815 |
+
/**
|
816 |
+
* Use this to wrap up the function when the PHP process is coming to an end. Call from onWpShudown()
|
817 |
+
*/
|
818 |
+
protected function shutdown() {
|
819 |
+
|
820 |
+
}
|
821 |
+
|
822 |
+
/**
|
823 |
+
* Hooked to 'shutdown'
|
824 |
+
*/
|
825 |
+
public function onWpShutdown() {
|
826 |
+
$this->shutdown();
|
827 |
+
}
|
828 |
+
|
829 |
+
public function onWpActivatePlugin() { }
|
830 |
+
public function onWpDeactivatePlugin() { }
|
831 |
+
public function onWpUninstallPlugin() { }
|
832 |
+
|
833 |
+
protected function loadWpFunctions() {
|
834 |
+
if ( !isset( $this->m_oWpFunctions ) ) {
|
835 |
+
$this->m_oWpFunctions = ICWP_WpFunctions_WPSF::GetInstance();
|
836 |
+
}
|
837 |
+
}
|
838 |
+
|
839 |
+
protected function flushCaches() {
|
840 |
+
if (function_exists('w3tc_pgcache_flush')) {
|
841 |
+
w3tc_pgcache_flush();
|
842 |
+
}
|
843 |
+
}
|
844 |
+
|
845 |
+
protected function getImageUrl( $insImage ) {
|
846 |
+
return $this->m_sPluginUrl.'resources/images/'.$insImage;
|
847 |
+
}
|
848 |
+
protected function getCssUrl( $insCss ) {
|
849 |
+
return $this->m_sPluginUrl.'resources/css/'.$insCss;
|
850 |
+
}
|
851 |
+
protected function getJsUrl( $insJs ) {
|
852 |
+
return $this->m_sPluginUrl.'resources/js/'.$insJs;
|
853 |
+
}
|
854 |
+
|
855 |
+
/**
|
856 |
+
* @param string $insKey
|
857 |
+
* @param boolean $infIncludeCookie
|
858 |
+
* @return mixed|null
|
859 |
+
*/
|
860 |
+
protected function fetchRequest( $insKey, $infIncludeCookie = true ) {
|
861 |
+
$mFetchVal = $this->fetchPost( $insKey );
|
862 |
+
if ( is_null( $mFetchVal ) ) {
|
863 |
+
$mFetchVal = $this->fetchGet( $insKey );
|
864 |
+
if ( is_null( $mFetchVal && $infIncludeCookie ) ) {
|
865 |
+
$mFetchVal = $this->fetchCookie( $insKey );
|
866 |
+
}
|
867 |
+
}
|
868 |
+
return $mFetchVal;
|
869 |
+
}
|
870 |
+
/**
|
871 |
+
* @param string $insKey
|
872 |
+
* @return mixed|null
|
873 |
+
*/
|
874 |
+
protected function fetchGet( $insKey ) {
|
875 |
+
if ( function_exists( 'filter_input' ) && defined( 'INPUT_GET' ) ) {
|
876 |
+
return filter_input( INPUT_GET, $insKey );
|
877 |
+
}
|
878 |
+
return $this->arrayFetch( $_GET, $insKey );
|
879 |
+
}
|
880 |
+
/**
|
881 |
+
* @param string $insKey The $_POST key
|
882 |
+
* @return mixed|null
|
883 |
+
*/
|
884 |
+
protected function fetchPost( $insKey ) {
|
885 |
+
if ( function_exists( 'filter_input' ) && defined( 'INPUT_POST' ) ) {
|
886 |
+
return filter_input( INPUT_POST, $insKey );
|
887 |
+
}
|
888 |
+
return $this->arrayFetch( $_POST, $insKey );
|
889 |
+
}
|
890 |
+
/**
|
891 |
+
* @param string $insKey The $_POST key
|
892 |
+
* @return mixed|null
|
893 |
+
*/
|
894 |
+
protected function fetchCookie( $insKey ) {
|
895 |
+
if ( function_exists( 'filter_input' ) && defined( 'INPUT_COOKIE' ) ) {
|
896 |
+
return filter_input( INPUT_COOKIE, $insKey );
|
897 |
+
}
|
898 |
+
return $this->arrayFetch( $_COOKIE, $insKey );
|
899 |
+
}
|
900 |
+
|
901 |
+
/**
|
902 |
+
* @param array $inaArray
|
903 |
+
* @param string $insKey The array key
|
904 |
+
* @return mixed|null
|
905 |
+
*/
|
906 |
+
protected function arrayFetch( &$inaArray, $insKey ) {
|
907 |
+
if ( empty( $inaArray ) ) {
|
908 |
+
return null;
|
909 |
+
}
|
910 |
+
if ( !isset( $inaArray[$insKey] ) ) {
|
911 |
+
return null;
|
912 |
+
}
|
913 |
+
return $inaArray[$insKey];
|
914 |
+
}
|
915 |
+
|
916 |
+
/**
|
917 |
+
* Performs a wp_die() but lets us do something first.
|
918 |
+
*/
|
919 |
+
protected function doWpDie( $insText = '' ) {
|
920 |
+
wp_die( $insText );
|
921 |
+
exit();
|
922 |
+
}
|
923 |
+
|
924 |
+
public function onWpAdminBar() {
|
925 |
+
$aNodes = $this->getAdminBarNodes();
|
926 |
+
foreach( $aNodes as $aNode ) {
|
927 |
+
$this->addAdminBarNode( $aNode );
|
928 |
+
}
|
929 |
+
}
|
930 |
+
|
931 |
+
protected function getAdminBarNodes() { }
|
932 |
+
|
933 |
+
protected function addAdminBarNode( $aNode ) {
|
934 |
+
global $wp_admin_bar;
|
935 |
+
|
936 |
+
if ( isset( $aNode['children'] ) ) {
|
937 |
+
$aChildren = $aNode['children'];
|
938 |
+
unset( $aNode['children'] );
|
939 |
+
}
|
940 |
+
$wp_admin_bar->add_node( $aNode );
|
941 |
+
|
942 |
+
if ( !empty($aChildren) ) {
|
943 |
+
foreach( $aChildren as $aChild ) {
|
944 |
+
$aChild['parent'] = $aNode['id'];
|
945 |
+
$this->addAdminBarNode( $aChild );
|
946 |
+
}
|
947 |
+
}
|
948 |
+
}
|
949 |
+
|
950 |
+
protected function getPluginLogoUrl16() {
|
951 |
+
return $this->getImageUrl( 'pluginlogo_16x16.png' );
|
952 |
+
}
|
953 |
+
|
954 |
+
protected function getPluginLogoUrl32() {
|
955 |
+
return $this->getImageUrl( 'pluginlogo_32x32.png' );
|
956 |
+
}
|
957 |
+
|
958 |
+
/**
|
959 |
+
*/
|
960 |
+
protected function loadDataProcessor() {
|
961 |
+
require_once( dirname(__FILE__) . '/icwp-data-processor.php' );
|
962 |
+
}
|
963 |
+
|
964 |
+
}//CLASS
|
965 |
+
|
966 |
+
endif;
|
src/icwp-wpfilesystem.php
CHANGED
@@ -1,9 +1,9 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* Copyright (c)
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
-
* Version: 2013-
|
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
|
@@ -17,9 +17,14 @@
|
|
17 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
18 |
*/
|
19 |
|
20 |
-
if ( !class_exists('
|
|
|
|
|
21 |
|
22 |
-
|
|
|
|
|
|
|
23 |
|
24 |
/**
|
25 |
* @var object
|
@@ -31,16 +36,34 @@ class ICWP_WpFilesystem_WPSF {
|
|
31 |
*/
|
32 |
protected $m_sWpConfigPath = null;
|
33 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
public function __construct() {
|
35 |
$this->initFileSystem();
|
36 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
}
|
38 |
|
39 |
protected function setWpConfigPath() {
|
40 |
$this->m_sWpConfigPath = ABSPATH.'wp-config.php';
|
41 |
-
if (
|
42 |
$this->m_sWpConfigPath = ABSPATH.'..'.ICWP_DS.'wp-config.php';
|
43 |
-
if (
|
44 |
$this->m_sWpConfigPath = false;
|
45 |
}
|
46 |
}
|
@@ -123,7 +146,50 @@ class ICWP_WpFilesystem_WPSF {
|
|
123 |
}
|
124 |
return false;
|
125 |
}
|
126 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
127 |
/**
|
128 |
* @param string $insFilePath
|
129 |
* @return NULL|boolean
|
@@ -146,39 +212,43 @@ class ICWP_WpFilesystem_WPSF {
|
|
146 |
}
|
147 |
|
148 |
/**
|
|
|
149 |
* @return string|null
|
150 |
*/
|
151 |
-
public function getFileContent( $
|
152 |
-
if (
|
153 |
return null;
|
154 |
}
|
155 |
if ( $this->m_oWpFilesystem ) {
|
156 |
-
return $this->m_oWpFilesystem->get_contents( $
|
157 |
}
|
158 |
else if ( function_exists('file_get_contents') ) {
|
159 |
-
return file_get_contents( $
|
160 |
}
|
161 |
return null;
|
162 |
}
|
163 |
|
164 |
/**
|
|
|
|
|
165 |
* @return boolean
|
166 |
*/
|
167 |
-
public function putFileContent( $
|
168 |
if ( $this->m_oWpFilesystem ) {
|
169 |
-
return $this->m_oWpFilesystem->put_contents( $
|
170 |
}
|
171 |
-
else if ( file_put_contents( $
|
172 |
return false;
|
173 |
}
|
174 |
return true;
|
175 |
}
|
176 |
|
177 |
/**
|
|
|
178 |
* @return boolean
|
179 |
*/
|
180 |
public function deleteFile( $insFilePath ) {
|
181 |
-
if (
|
182 |
return null;
|
183 |
}
|
184 |
if ( $this->m_oWpFilesystem ) {
|
@@ -188,6 +258,46 @@ class ICWP_WpFilesystem_WPSF {
|
|
188 |
return unlink( $insFilePath );
|
189 |
}
|
190 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
191 |
}
|
|
|
|
|
|
|
192 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
193 |
endif;
|
1 |
<?php
|
2 |
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
+
* Version: 2013-11-19
|
7 |
*
|
8 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
9 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
17 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
18 |
*/
|
19 |
|
20 |
+
if ( !class_exists('ICWP_WpFilesystem_V2') ):
|
21 |
+
|
22 |
+
class ICWP_WpFilesystem_V2 {
|
23 |
|
24 |
+
/**
|
25 |
+
* @var ICWP_WpFilesystem_V2
|
26 |
+
*/
|
27 |
+
protected static $oInstance = NULL;
|
28 |
|
29 |
/**
|
30 |
* @var object
|
36 |
*/
|
37 |
protected $m_sWpConfigPath = null;
|
38 |
|
39 |
+
/**
|
40 |
+
* @return ICWP_WpFilesystem_V2
|
41 |
+
*/
|
42 |
+
public static function GetInstance() {
|
43 |
+
if ( is_null( self::$oInstance ) ) {
|
44 |
+
self::$oInstance = new self();
|
45 |
+
}
|
46 |
+
return self::$oInstance;
|
47 |
+
}
|
48 |
+
|
49 |
public function __construct() {
|
50 |
$this->initFileSystem();
|
51 |
+
// $this->setWpConfigPath();
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* @param $sPath
|
56 |
+
* @return boolean true/false whether file/directory exists
|
57 |
+
*/
|
58 |
+
public function exists( $sPath ) {
|
59 |
+
return $this->fileAction( 'file_exists', $sPath );
|
60 |
}
|
61 |
|
62 |
protected function setWpConfigPath() {
|
63 |
$this->m_sWpConfigPath = ABSPATH.'wp-config.php';
|
64 |
+
if ( !$this->exists($this->m_sWpConfigPath) ) {
|
65 |
$this->m_sWpConfigPath = ABSPATH.'..'.ICWP_DS.'wp-config.php';
|
66 |
+
if ( !$this->exists($this->m_sWpConfigPath) ) {
|
67 |
$this->m_sWpConfigPath = false;
|
68 |
}
|
69 |
}
|
146 |
}
|
147 |
return false;
|
148 |
}
|
149 |
+
|
150 |
+
/**
|
151 |
+
* @param $sFilePath
|
152 |
+
* @return int|null
|
153 |
+
*/
|
154 |
+
public function getModifiedTime( $sFilePath ) {
|
155 |
+
return $this->getTime($sFilePath, 'modified');
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* @param $sFilePath
|
160 |
+
* @return int|null
|
161 |
+
*/
|
162 |
+
public function getAccessedTime( $sFilePath ) {
|
163 |
+
return $this->getTime($sFilePath, 'accessed');
|
164 |
+
}
|
165 |
+
|
166 |
+
/**
|
167 |
+
* @param $sFilePath
|
168 |
+
* @param string $sProperty
|
169 |
+
* @return int|null
|
170 |
+
*/
|
171 |
+
public function getTime( $sFilePath, $sProperty = 'modified' ) {
|
172 |
+
|
173 |
+
if ( !$this->exists($sFilePath) ) {
|
174 |
+
return null;
|
175 |
+
}
|
176 |
+
|
177 |
+
$fUseWp = $this->m_oWpFilesystem ? true : false;
|
178 |
+
|
179 |
+
switch ( $sProperty ) {
|
180 |
+
|
181 |
+
case 'modified' :
|
182 |
+
return $fUseWp? $this->m_oWpFilesystem->mtime( $sFilePath ) : filemtime( $sFilePath );
|
183 |
+
break;
|
184 |
+
case 'accessed' :
|
185 |
+
return $fUseWp? $this->m_oWpFilesystem->atime( $sFilePath ) : fileatime( $sFilePath );
|
186 |
+
break;
|
187 |
+
default:
|
188 |
+
return null;
|
189 |
+
break;
|
190 |
+
}
|
191 |
+
}
|
192 |
+
|
193 |
/**
|
194 |
* @param string $insFilePath
|
195 |
* @return NULL|boolean
|
212 |
}
|
213 |
|
214 |
/**
|
215 |
+
* @param string $sFilePath
|
216 |
* @return string|null
|
217 |
*/
|
218 |
+
public function getFileContent( $sFilePath ) {
|
219 |
+
if ( !$this->exists( $sFilePath ) ) {
|
220 |
return null;
|
221 |
}
|
222 |
if ( $this->m_oWpFilesystem ) {
|
223 |
+
return $this->m_oWpFilesystem->get_contents( $sFilePath );
|
224 |
}
|
225 |
else if ( function_exists('file_get_contents') ) {
|
226 |
+
return file_get_contents( $sFilePath );
|
227 |
}
|
228 |
return null;
|
229 |
}
|
230 |
|
231 |
/**
|
232 |
+
* @param string $sFilePath
|
233 |
+
* @param string $sContents
|
234 |
* @return boolean
|
235 |
*/
|
236 |
+
public function putFileContent( $sFilePath, $sContents ) {
|
237 |
if ( $this->m_oWpFilesystem ) {
|
238 |
+
return $this->m_oWpFilesystem->put_contents( $sFilePath, $sContents, FS_CHMOD_FILE );
|
239 |
}
|
240 |
+
else if ( file_put_contents( $sFilePath, $sContents ) === false ) {
|
241 |
return false;
|
242 |
}
|
243 |
return true;
|
244 |
}
|
245 |
|
246 |
/**
|
247 |
+
* @param $insFilePath
|
248 |
* @return boolean
|
249 |
*/
|
250 |
public function deleteFile( $insFilePath ) {
|
251 |
+
if ( !$this->exists( $insFilePath ) ) {
|
252 |
return null;
|
253 |
}
|
254 |
if ( $this->m_oWpFilesystem ) {
|
258 |
return unlink( $insFilePath );
|
259 |
}
|
260 |
}
|
261 |
+
|
262 |
+
public function fileAction( $insFunctionName, $inaParams ) {
|
263 |
+
$aFunctionMap = array(
|
264 |
+
'file_exists' => 'exists',
|
265 |
+
'touch' => 'touch'
|
266 |
+
);
|
267 |
+
|
268 |
+
if ( !is_array($inaParams) ) {
|
269 |
+
$inaParams = array($inaParams);
|
270 |
+
}
|
271 |
+
|
272 |
+
if ( !$this->m_oWpFilesystem ) {
|
273 |
+
if ( function_exists( $insFunctionName ) ) {
|
274 |
+
call_user_func_array( $insFunctionName, $inaParams );
|
275 |
+
}
|
276 |
+
else {
|
277 |
+
return false;
|
278 |
+
}
|
279 |
+
}
|
280 |
+
if ( !array_key_exists($insFunctionName, $aFunctionMap) ) {
|
281 |
+
return false;
|
282 |
+
}
|
283 |
+
$sWpFunctionName = $aFunctionMap[$insFunctionName];
|
284 |
+
$sResult = call_user_func_array( array($this->m_oWpFilesystem, $sWpFunctionName), $inaParams );
|
285 |
+
return $sResult;
|
286 |
+
}
|
287 |
}
|
288 |
+
endif;
|
289 |
+
|
290 |
+
if ( !class_exists('ICWP_WpFilesystem_WPSF') ):
|
291 |
|
292 |
+
class ICWP_WpFilesystem_WPSF extends ICWP_WpFilesystem_V2 {
|
293 |
+
/**
|
294 |
+
* @return ICWP_WpFilesystem_WPSF
|
295 |
+
*/
|
296 |
+
public static function GetInstance() {
|
297 |
+
if ( is_null( self::$oInstance ) ) {
|
298 |
+
self::$oInstance = new self();
|
299 |
+
}
|
300 |
+
return self::$oInstance;
|
301 |
+
}
|
302 |
+
}
|
303 |
endif;
|
src/icwp-wpfunctions.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* Copyright (c)
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* Version: 2013-08-14_A
|
@@ -17,9 +17,24 @@
|
|
17 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
18 |
*/
|
19 |
|
20 |
-
if ( !class_exists('
|
|
|
|
|
21 |
|
22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
|
24 |
/**
|
25 |
* @var string
|
@@ -82,7 +97,7 @@ class ICWP_WpFunctions_WPSF {
|
|
82 |
|
83 |
// TODO: Handle multisite
|
84 |
|
85 |
-
if ( version_compare( $this->
|
86 |
return get_option( $insKey );
|
87 |
}
|
88 |
|
@@ -90,7 +105,7 @@ class ICWP_WpFunctions_WPSF {
|
|
90 |
return get_site_transient( $insKey );
|
91 |
}
|
92 |
|
93 |
-
if ( version_compare( $this->
|
94 |
return apply_filters( 'transient_'.$insKey, get_option( '_transient_'.$insKey ) );
|
95 |
}
|
96 |
|
@@ -100,7 +115,7 @@ class ICWP_WpFunctions_WPSF {
|
|
100 |
/**
|
101 |
* @return string
|
102 |
*/
|
103 |
-
public function
|
104 |
global $wp_version;
|
105 |
|
106 |
if ( empty( $this->m_sWpVersion ) ) {
|
@@ -111,8 +126,45 @@ class ICWP_WpFunctions_WPSF {
|
|
111 |
$this->m_sWpVersion = $aMatches[1];
|
112 |
}
|
113 |
}
|
114 |
-
return $this->m_sWpVersion;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
115 |
}
|
116 |
}
|
|
|
|
|
|
|
117 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
118 |
endif;
|
1 |
<?php
|
2 |
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
* All rights reserved.
|
5 |
*
|
6 |
* Version: 2013-08-14_A
|
17 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
18 |
*/
|
19 |
|
20 |
+
if ( !class_exists('ICWP_WpFunctions_V3') ):
|
21 |
+
|
22 |
+
class ICWP_WpFunctions_V3 {
|
23 |
|
24 |
+
/**
|
25 |
+
* @var ICWP_WpFunctions_V3
|
26 |
+
*/
|
27 |
+
protected static $oInstance = NULL;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @return ICWP_WpFunctions_V3
|
31 |
+
*/
|
32 |
+
public static function GetInstance() {
|
33 |
+
if ( is_null( self::$oInstance ) ) {
|
34 |
+
self::$oInstance = new self();
|
35 |
+
}
|
36 |
+
return self::$oInstance;
|
37 |
+
}
|
38 |
|
39 |
/**
|
40 |
* @var string
|
97 |
|
98 |
// TODO: Handle multisite
|
99 |
|
100 |
+
if ( version_compare( $this->getWordpressVersion(), '2.7.9', '<=' ) ) {
|
101 |
return get_option( $insKey );
|
102 |
}
|
103 |
|
105 |
return get_site_transient( $insKey );
|
106 |
}
|
107 |
|
108 |
+
if ( version_compare( $this->getWordpressVersion(), '2.9.9', '<=' ) ) {
|
109 |
return apply_filters( 'transient_'.$insKey, get_option( '_transient_'.$insKey ) );
|
110 |
}
|
111 |
|
115 |
/**
|
116 |
* @return string
|
117 |
*/
|
118 |
+
public function getWordpressVersion() {
|
119 |
global $wp_version;
|
120 |
|
121 |
if ( empty( $this->m_sWpVersion ) ) {
|
126 |
$this->m_sWpVersion = $aMatches[1];
|
127 |
}
|
128 |
}
|
129 |
+
return empty( $this->m_sWpVersion )? $wp_version : $this->m_sWpVersion;
|
130 |
+
}
|
131 |
+
|
132 |
+
/**
|
133 |
+
* @param string $sParams
|
134 |
+
*/
|
135 |
+
public function redirectToLogin( $sParams = '' ) {
|
136 |
+
header( "Location: ".site_url().'/wp-login.php'.$sParams );
|
137 |
+
exit();
|
138 |
+
}
|
139 |
+
/**
|
140 |
+
*/
|
141 |
+
public function redirectToAdmin() {
|
142 |
+
$this->doRedirect( is_multisite()? get_admin_url() : admin_url() );
|
143 |
+
}
|
144 |
+
/**
|
145 |
+
*/
|
146 |
+
public function redirectToHome() {
|
147 |
+
$this->doRedirect( home_url() );
|
148 |
+
}
|
149 |
+
|
150 |
+
public function doRedirect( $sUrl ) {
|
151 |
+
wp_safe_redirect( $sUrl );
|
152 |
+
exit();
|
153 |
}
|
154 |
}
|
155 |
+
endif;
|
156 |
+
|
157 |
+
if ( !class_exists('ICWP_WpFunctions_WPSF') ):
|
158 |
|
159 |
+
class ICWP_WpFunctions_WPSF extends ICWP_WpFunctions_V3 {
|
160 |
+
/**
|
161 |
+
* @return ICWP_WpFunctions_WPSF
|
162 |
+
*/
|
163 |
+
public static function GetInstance() {
|
164 |
+
if ( is_null( self::$oInstance ) ) {
|
165 |
+
self::$oInstance = new self();
|
166 |
+
}
|
167 |
+
return self::$oInstance;
|
168 |
+
}
|
169 |
+
}
|
170 |
endif;
|
src/icwp-wpsf-stats.php
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2014 iControlWP <support@icontrolwp.com>
|
4 |
+
* All rights reserved.
|
5 |
+
*
|
6 |
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
7 |
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
8 |
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
9 |
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
10 |
+
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
11 |
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
12 |
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
13 |
+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
14 |
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
15 |
+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
16 |
+
*/
|
17 |
+
|
18 |
+
if ( !class_exists('ICWP_Stats_WPSF') ):
|
19 |
+
|
20 |
+
class ICWP_Stats_WPSF {
|
21 |
+
|
22 |
+
const Stats_Key = 'icwp_wpsf_stats';
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var array
|
26 |
+
*/
|
27 |
+
private static $aStats;
|
28 |
+
|
29 |
+
public function __construct() { }
|
30 |
+
|
31 |
+
/**
|
32 |
+
* @param $sKey
|
33 |
+
*/
|
34 |
+
public static function DoStatIncrement( $sKey ) {
|
35 |
+
self::LoadStats();
|
36 |
+
self::$aStats[$sKey] = isset( self::$aStats[$sKey] )? self::$aStats[$sKey] + 1 : 1;
|
37 |
+
self::SaveStats();
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* The provided key is an array, and the value to count is the key of the array that should be incremented.
|
42 |
+
*
|
43 |
+
* @param $sKey
|
44 |
+
* @param $sValueToCount
|
45 |
+
*/
|
46 |
+
public static function DoStatIncrementKeyValue( $sKey, $sValueToCount ) {
|
47 |
+
self::LoadStats();
|
48 |
+
if ( !isset( self::$aStats[$sKey] ) || !is_array( self::$aStats[$sKey] ) ) {
|
49 |
+
self::$aStats[$sKey] = array();
|
50 |
+
}
|
51 |
+
self::$aStats[$sKey][$sValueToCount] = isset( self::$aStats[$sKey][$sValueToCount] )? self::$aStats[$sKey][$sValueToCount] + 1 : 1;
|
52 |
+
self::SaveStats();
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
*/
|
57 |
+
protected static function LoadStats() {
|
58 |
+
if ( isset( self::$aStats ) ) {
|
59 |
+
return;
|
60 |
+
}
|
61 |
+
self::$aStats = get_option( self::Stats_Key );
|
62 |
+
if ( !is_array( self::$aStats ) ) {
|
63 |
+
self::$aStats = array();
|
64 |
+
self::SaveStats();
|
65 |
+
}
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
*/
|
70 |
+
public static function SaveStats() {
|
71 |
+
if ( !empty(self::$aStats) ) {
|
72 |
+
update_option( self::Stats_Key, self::$aStats );
|
73 |
+
}
|
74 |
+
}
|
75 |
+
}
|
76 |
+
|
77 |
+
endif;
|
views/icwp_options_helper.php
CHANGED
@@ -3,8 +3,7 @@
|
|
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"
|
7 |
-
echo '<h2>';
|
8 |
$sBaseTitle = sprintf( _wpsf__( 'WordPress Simple Firewall (from %s)' ), $sLinkedIcwp );
|
9 |
if ( !empty($insSection) ) {
|
10 |
echo sprintf( '%s :: %s', $insSection, $sBaseTitle );
|
@@ -23,8 +22,7 @@ function printAllPluginOptionsForm( $inaAllPluginOptions, $insVarPrefix = '', $i
|
|
23 |
|
24 |
$iRowWidth = 8; //8 spans.
|
25 |
$iOptionWidth = $iRowWidth / $iOptionsPerRow;
|
26 |
-
|
27 |
-
|
28 |
//Take each Options Section in turn
|
29 |
foreach ( $inaAllPluginOptions as $sOptionSection ) {
|
30 |
|
@@ -67,13 +65,13 @@ function printAllPluginOptionsForm( $inaAllPluginOptions, $insVarPrefix = '', $i
|
|
67 |
</div>
|
68 |
';
|
69 |
|
70 |
-
}
|
71 |
|
72 |
}//printAllPluginOptionsForm
|
73 |
|
74 |
function getPluginOptionSpan( $inaOption, $iSpanSize, $insVarPrefix = '' ) {
|
75 |
|
76 |
-
list( $sOptionKey, $sOptionSaved, $sOptionDefault, $mOptionType, $sOptionHumanName, $sOptionTitle, $sOptionHelpText ) = $inaOption;
|
77 |
|
78 |
if ( $sOptionKey == 'spacer' ) {
|
79 |
$sHtml = '
|
@@ -81,19 +79,18 @@ function getPluginOptionSpan( $inaOption, $iSpanSize, $insVarPrefix = '' ) {
|
|
81 |
</div>
|
82 |
';
|
83 |
} else {
|
84 |
-
|
|
|
85 |
$sSpanId = 'span_'.$insVarPrefix.$sOptionKey;
|
86 |
$sHtml = '
|
87 |
<div class="span'.$iSpanSize.'" id="'.$sSpanId.'">
|
88 |
<div class="control-group">
|
89 |
-
<label class="control-label" for="'.$insVarPrefix.$sOptionKey.'">'.$sOptionHumanName.'<br
|
90 |
<div class="controls">
|
91 |
<div class="option_section'.( ($sOptionSaved == 'Y')? ' selected_item':'' ).'" id="option_section_'.$insVarPrefix.$sOptionKey.'">
|
92 |
<label>
|
93 |
';
|
94 |
$sAdditionalClass = '';
|
95 |
-
$sTextInput = '';
|
96 |
-
$sChecked = '';
|
97 |
$sHelpSection = '';
|
98 |
|
99 |
if ( $mOptionType === 'checkbox' ) {
|
@@ -108,8 +105,6 @@ function getPluginOptionSpan( $inaOption, $iSpanSize, $insVarPrefix = '' ) {
|
|
108 |
class="'.$sAdditionalClass.'"
|
109 |
id="'.$insVarPrefix.$sOptionKey.'" />
|
110 |
'.$sOptionTitle;
|
111 |
-
|
112 |
-
$sOptionHelpText = '<p class="help-block">'.$sOptionHelpText.'</p>';
|
113 |
|
114 |
}
|
115 |
else if ( $mOptionType === 'text' ) {
|
@@ -122,9 +117,6 @@ function getPluginOptionSpan( $inaOption, $iSpanSize, $insVarPrefix = '' ) {
|
|
122 |
placeholder="'.$sTextInput.'"
|
123 |
id="'.$insVarPrefix.$sOptionKey.'"
|
124 |
class="span5" />';
|
125 |
-
|
126 |
-
$sOptionHelpText = '<p class="help-block">'.$sOptionHelpText.'</p>';
|
127 |
-
|
128 |
}
|
129 |
else if ( $mOptionType === 'password' ) {
|
130 |
$sTextInput = esc_attr( $sOptionSaved );
|
@@ -136,8 +128,6 @@ function getPluginOptionSpan( $inaOption, $iSpanSize, $insVarPrefix = '' ) {
|
|
136 |
placeholder="'.$sTextInput.'"
|
137 |
id="'.$insVarPrefix.$sOptionKey.'"
|
138 |
class="span5" />';
|
139 |
-
|
140 |
-
$sOptionHelpText = '<p class="help-block">'.$sOptionHelpText.'</p>';
|
141 |
}
|
142 |
else if ( $mOptionType === 'email' ) {
|
143 |
$sTextInput = esc_attr( $sOptionSaved );
|
@@ -149,32 +139,60 @@ function getPluginOptionSpan( $inaOption, $iSpanSize, $insVarPrefix = '' ) {
|
|
149 |
placeholder="'.$sTextInput.'"
|
150 |
id="'.$insVarPrefix.$sOptionKey.'"
|
151 |
class="span5" />';
|
152 |
-
|
153 |
-
$sOptionHelpText = '<p class="help-block">'.$sOptionHelpText.'</p>';
|
154 |
-
|
155 |
}
|
156 |
else if ( is_array($mOptionType) ) { //it's a select, or radio
|
157 |
-
|
158 |
-
$sInputType = array_shift($mOptionType);
|
159 |
|
160 |
-
if ( $
|
161 |
-
$
|
162 |
-
|
163 |
}
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
$sHtml .= '
|
168 |
-
<option value="'.$aInput[0].'" id="'.$insVarPrefix.$sOptionKey.'_'.$aInput[0].'"' . (( $sOptionSaved == $aInput[0] )? ' selected="selected"' : '') .'>'. $aInput[1].'</option>';
|
169 |
}
|
170 |
-
|
171 |
-
if ($sInputType == 'select') {
|
172 |
-
|
173 |
-
</
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
174 |
}
|
175 |
-
|
176 |
-
|
177 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
178 |
}
|
179 |
else if ( $mOptionType === 'ip_addresses' ) {
|
180 |
$sTextInput = esc_attr( $sOptionSaved );
|
@@ -187,11 +205,11 @@ function getPluginOptionSpan( $inaOption, $iSpanSize, $insVarPrefix = '' ) {
|
|
187 |
id="'.$insVarPrefix.$sOptionKey.'"
|
188 |
rows="'.$nRows.'"
|
189 |
class="span5">'.$sTextInput.'</textarea>';
|
190 |
-
|
191 |
$sOptionHelpText = '<p class="help-block">'.$sOptionHelpText.'</p>';
|
192 |
-
|
193 |
}
|
194 |
-
else if ( $mOptionType === '
|
195 |
$sTextInput = esc_attr( $sOptionSaved );
|
196 |
$nRows = substr_count( $sTextInput, "\n" ) + 1;
|
197 |
$sHtml .= '
|
@@ -202,8 +220,21 @@ function getPluginOptionSpan( $inaOption, $iSpanSize, $insVarPrefix = '' ) {
|
|
202 |
id="'.$insVarPrefix.$sOptionKey.'"
|
203 |
rows="'.$nRows.'"
|
204 |
class="span5">'.$sTextInput.'</textarea>';
|
205 |
-
|
206 |
$sOptionHelpText = '<p class="help-block">'.$sOptionHelpText.'</p>';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
207 |
}
|
208 |
else if ( $mOptionType === 'integer' ) {
|
209 |
$sTextInput = esc_attr( $sOptionSaved );
|
@@ -215,16 +246,22 @@ function getPluginOptionSpan( $inaOption, $iSpanSize, $insVarPrefix = '' ) {
|
|
215 |
placeholder="'.$sTextInput.'"
|
216 |
id="'.$insVarPrefix.$sOptionKey.'"
|
217 |
class="span5" />';
|
218 |
-
|
219 |
-
$sOptionHelpText = '<p class="help-block">'.$sOptionHelpText.'</p>';
|
220 |
}
|
221 |
else {
|
222 |
$sHtml .= 'we should never reach this point';
|
223 |
}
|
|
|
|
|
|
|
|
|
|
|
224 |
|
|
|
|
|
225 |
$sHtml .= '
|
226 |
</label>
|
227 |
'.$sOptionHelpText.'
|
|
|
228 |
</div>
|
229 |
</div><!-- controls -->'
|
230 |
.$sHelpSection.'
|
@@ -234,4 +271,4 @@ function getPluginOptionSpan( $inaOption, $iSpanSize, $insVarPrefix = '' ) {
|
|
234 |
}
|
235 |
|
236 |
return $sHtml;
|
237 |
-
}
|
3 |
function printOptionsPageHeader( $insSection = '' ) {
|
4 |
$sLinkedIcwp = '<a href="http://icwp.io/3a" target="_blank">iControlWP</a>';
|
5 |
echo '<div class="page-header">';
|
6 |
+
echo '<h2><a id="pluginlogo_32" class="header-icon32" href="http://icwp.io/2k" target="_blank"></a>';
|
|
|
7 |
$sBaseTitle = sprintf( _wpsf__( 'WordPress Simple Firewall (from %s)' ), $sLinkedIcwp );
|
8 |
if ( !empty($insSection) ) {
|
9 |
echo sprintf( '%s :: %s', $insSection, $sBaseTitle );
|
22 |
|
23 |
$iRowWidth = 8; //8 spans.
|
24 |
$iOptionWidth = $iRowWidth / $iOptionsPerRow;
|
25 |
+
|
|
|
26 |
//Take each Options Section in turn
|
27 |
foreach ( $inaAllPluginOptions as $sOptionSection ) {
|
28 |
|
65 |
</div>
|
66 |
';
|
67 |
|
68 |
+
}
|
69 |
|
70 |
}//printAllPluginOptionsForm
|
71 |
|
72 |
function getPluginOptionSpan( $inaOption, $iSpanSize, $insVarPrefix = '' ) {
|
73 |
|
74 |
+
list( $sOptionKey, $sOptionSaved, $sOptionDefault, $mOptionType, $sOptionHumanName, $sOptionTitle, $sOptionHelpText, $sHelpLink ) = array_pad( $inaOption, 8, '' );
|
75 |
|
76 |
if ( $sOptionKey == 'spacer' ) {
|
77 |
$sHtml = '
|
79 |
</div>
|
80 |
';
|
81 |
} else {
|
82 |
+
|
83 |
+
$sHelpLink = !empty($sHelpLink)? '<span>['.$sHelpLink.']</span>' : '';
|
84 |
$sSpanId = 'span_'.$insVarPrefix.$sOptionKey;
|
85 |
$sHtml = '
|
86 |
<div class="span'.$iSpanSize.'" id="'.$sSpanId.'">
|
87 |
<div class="control-group">
|
88 |
+
<label class="control-label" for="'.$insVarPrefix.$sOptionKey.'">'.$sOptionHumanName.'<br />'.$sHelpLink.'</label>
|
89 |
<div class="controls">
|
90 |
<div class="option_section'.( ($sOptionSaved == 'Y')? ' selected_item':'' ).'" id="option_section_'.$insVarPrefix.$sOptionKey.'">
|
91 |
<label>
|
92 |
';
|
93 |
$sAdditionalClass = '';
|
|
|
|
|
94 |
$sHelpSection = '';
|
95 |
|
96 |
if ( $mOptionType === 'checkbox' ) {
|
105 |
class="'.$sAdditionalClass.'"
|
106 |
id="'.$insVarPrefix.$sOptionKey.'" />
|
107 |
'.$sOptionTitle;
|
|
|
|
|
108 |
|
109 |
}
|
110 |
else if ( $mOptionType === 'text' ) {
|
117 |
placeholder="'.$sTextInput.'"
|
118 |
id="'.$insVarPrefix.$sOptionKey.'"
|
119 |
class="span5" />';
|
|
|
|
|
|
|
120 |
}
|
121 |
else if ( $mOptionType === 'password' ) {
|
122 |
$sTextInput = esc_attr( $sOptionSaved );
|
128 |
placeholder="'.$sTextInput.'"
|
129 |
id="'.$insVarPrefix.$sOptionKey.'"
|
130 |
class="span5" />';
|
|
|
|
|
131 |
}
|
132 |
else if ( $mOptionType === 'email' ) {
|
133 |
$sTextInput = esc_attr( $sOptionSaved );
|
139 |
placeholder="'.$sTextInput.'"
|
140 |
id="'.$insVarPrefix.$sOptionKey.'"
|
141 |
class="span5" />';
|
142 |
+
|
|
|
|
|
143 |
}
|
144 |
else if ( is_array($mOptionType) ) { //it's a select, or radio
|
|
|
|
|
145 |
|
146 |
+
if ( isset( $mOptionType['type'] ) ) {
|
147 |
+
$sInputType = $mOptionType['type'];
|
148 |
+
unset( $mOptionType['type'] );
|
149 |
}
|
150 |
+
else {
|
151 |
+
$sInputType = array_shift($mOptionType);
|
|
|
|
|
|
|
152 |
}
|
153 |
+
|
154 |
+
if ( $sInputType == 'select' ) {
|
155 |
+
|
156 |
+
$sFragment = '<p>'.$sOptionTitle.'</p>
|
157 |
+
<select
|
158 |
+
id="'.$insVarPrefix.$sOptionKey.'"
|
159 |
+
name="'.$insVarPrefix.$sOptionKey.'">';
|
160 |
+
|
161 |
+
foreach( $mOptionType as $aInput ) {
|
162 |
+
|
163 |
+
list( $mOptionValue, $sOptionName ) = $aInput;
|
164 |
+
$fSelected = $sOptionSaved == $mOptionValue;
|
165 |
+
|
166 |
+
$sFragment .= '
|
167 |
+
<option
|
168 |
+
value="'.$mOptionValue.'"
|
169 |
+
id="'.$insVarPrefix.$sOptionKey.'_'.$mOptionValue.'"'
|
170 |
+
.( $fSelected? ' selected="selected"' : '') .'>'. $sOptionName.'</option>';
|
171 |
+
}
|
172 |
+
$sFragment .= '</select>';
|
173 |
+
|
174 |
}
|
175 |
+
if ( $sInputType == 'multiple_select' ) {
|
176 |
+
|
177 |
+
$sFragment = '<p>'.$sOptionTitle.'</p>
|
178 |
+
<select
|
179 |
+
id="'.$insVarPrefix.$sOptionKey.'"
|
180 |
+
name="'.$insVarPrefix.$sOptionKey.'[]" multiple multiple="multiple" size="'.count($mOptionType).'">';
|
181 |
+
|
182 |
+
foreach( $mOptionType as $mOptionValue => $sOptionName ) {
|
183 |
+
|
184 |
+
$fSelected = in_array( $mOptionValue, $sOptionSaved );
|
185 |
+
|
186 |
+
$sFragment .= '
|
187 |
+
<option
|
188 |
+
value="'.$mOptionValue.'"
|
189 |
+
id="'.$insVarPrefix.$sOptionKey.'_'.$mOptionValue.'"'
|
190 |
+
.( $fSelected? ' selected="selected"' : '') .'>'. $sOptionName.'</option>';
|
191 |
+
}
|
192 |
+
$sFragment .= '</select>';
|
193 |
+
}
|
194 |
+
|
195 |
+
$sHtml .= $sFragment;
|
196 |
}
|
197 |
else if ( $mOptionType === 'ip_addresses' ) {
|
198 |
$sTextInput = esc_attr( $sOptionSaved );
|
205 |
id="'.$insVarPrefix.$sOptionKey.'"
|
206 |
rows="'.$nRows.'"
|
207 |
class="span5">'.$sTextInput.'</textarea>';
|
208 |
+
|
209 |
$sOptionHelpText = '<p class="help-block">'.$sOptionHelpText.'</p>';
|
210 |
+
|
211 |
}
|
212 |
+
else if ( $mOptionType === 'yubikey_unique_keys' ) {
|
213 |
$sTextInput = esc_attr( $sOptionSaved );
|
214 |
$nRows = substr_count( $sTextInput, "\n" ) + 1;
|
215 |
$sHtml .= '
|
220 |
id="'.$insVarPrefix.$sOptionKey.'"
|
221 |
rows="'.$nRows.'"
|
222 |
class="span5">'.$sTextInput.'</textarea>';
|
223 |
+
|
224 |
$sOptionHelpText = '<p class="help-block">'.$sOptionHelpText.'</p>';
|
225 |
+
|
226 |
+
}
|
227 |
+
else if ( $mOptionType === 'comma_separated_lists' ) {
|
228 |
+
$sTextInput = esc_attr( $sOptionSaved );
|
229 |
+
$nRows = substr_count( $sTextInput, "\n" ) + 1;
|
230 |
+
$sHtml .= '
|
231 |
+
<p>'.$sOptionTitle.'</p>
|
232 |
+
<textarea type="text"
|
233 |
+
name="'.$insVarPrefix.$sOptionKey.'"
|
234 |
+
placeholder="'.$sTextInput.'"
|
235 |
+
id="'.$insVarPrefix.$sOptionKey.'"
|
236 |
+
rows="'.$nRows.'"
|
237 |
+
class="span5">'.$sTextInput.'</textarea>';
|
238 |
}
|
239 |
else if ( $mOptionType === 'integer' ) {
|
240 |
$sTextInput = esc_attr( $sOptionSaved );
|
246 |
placeholder="'.$sTextInput.'"
|
247 |
id="'.$insVarPrefix.$sOptionKey.'"
|
248 |
class="span5" />';
|
|
|
|
|
249 |
}
|
250 |
else {
|
251 |
$sHtml .= 'we should never reach this point';
|
252 |
}
|
253 |
+
|
254 |
+
// $sOptionHelpText = '<p class="help-block">'
|
255 |
+
// .$sOptionHelpText
|
256 |
+
// .( isset($sHelpLink)? '<br /><span class="help-link">['.$sHelpLink.']</span>':'' )
|
257 |
+
// .'</p>';
|
258 |
|
259 |
+
$sOptionHelpText = '<p class="help-block">'.$sOptionHelpText.'</p>';
|
260 |
+
|
261 |
$sHtml .= '
|
262 |
</label>
|
263 |
'.$sOptionHelpText.'
|
264 |
+
<div style="clear:both"></div>
|
265 |
</div>
|
266 |
</div><!-- controls -->'
|
267 |
.$sHelpSection.'
|
271 |
}
|
272 |
|
273 |
return $sHtml;
|
274 |
+
}
|
views/icwp_wpsf_config_autoupdates_index.php
CHANGED
@@ -5,11 +5,25 @@ include_once( dirname(__FILE__).ICWP_DS.'widgets'.ICWP_DS.'icwp_widgets.php' );
|
|
5 |
<div class="wrap">
|
6 |
<div class="bootstrap-wpadmin">
|
7 |
<?php echo printOptionsPageHeader( _wpsf__('Auto WordPress Updates') ); ?>
|
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 );
|
5 |
<div class="wrap">
|
6 |
<div class="bootstrap-wpadmin">
|
7 |
<?php echo printOptionsPageHeader( _wpsf__('Auto WordPress Updates') ); ?>
|
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 |
+
<legend>Run Updates Now</legend>
|
14 |
+
<div class="control-group">
|
15 |
+
<label class="control-label">Run Automatic Updates
|
16 |
+
<br /><span>[<a target="_blank" href="http://icwp.io/44">more info</a>]</span>
|
17 |
+
</label>
|
18 |
+
<div class="controls">
|
19 |
+
<div id="icwp_wpsf_force_run_autoupdates" class="option_section selected_item active">
|
20 |
+
<a class="btn btn-warning" href="<?php echo $icwp_form_action; ?>&force_run_auto_updates=now&_wpnonce=<?php echo wp_create_nonce($icwp_nonce_field); ?>&icwp_link_action=1">
|
21 |
+
<?php echo _wpsf__('Force Run Automatic Updates Now').' →';?>
|
22 |
+
</a>
|
23 |
+
<p class="help-block">WordPress Automatic Updates runs twice daily, but you can run it now on-demand.</p>
|
24 |
+
</div>
|
25 |
+
</div><!-- controls -->
|
26 |
+
</div>
|
27 |
<?php
|
28 |
wp_nonce_field( $icwp_nonce_field );
|
29 |
printAllPluginOptionsForm( $icwp_aAllOptions, $icwp_var_prefix, 1 );
|
views/icwp_wpsf_config_login_protect_index.php
CHANGED
@@ -18,6 +18,7 @@ include_once( dirname(__FILE__).ICWP_DS.'widgets'.ICWP_DS.'icwp_widgets.php' );
|
|
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 _wpsf_e( 'Save All Settings' ); ?></button>
|
|
|
21 |
</div>
|
22 |
</form>
|
23 |
|
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 _wpsf_e( 'Save All Settings' ); ?></button>
|
21 |
+
<button type="submit" class="btn btn-warning" name="terminate-all-logins" value="1" style="margin-left: 15px"><?php _wpsf_e( 'Clear All Verified Logins' ); ?></button>
|
22 |
</div>
|
23 |
</form>
|
24 |
|
views/icwp_wpsf_config_privacy_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( _wpsf__('Privacy Protect') ); ?>
|
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 _wpsf_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
@@ -2,7 +2,6 @@
|
|
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(
|
7 |
0 => _wpsf__('Info'),
|
8 |
1 => _wpsf__('Warning'),
|
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 |
$aLogTypes = array(
|
6 |
0 => _wpsf__('Info'),
|
7 |
1 => _wpsf__('Warning'),
|
views/icwp_wpsf_index.php
CHANGED
@@ -2,13 +2,14 @@
|
|
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 |
$fAutoUpdatesOn = $icwp_aMainOptions['enable_autoupdates'] == 'Y';
|
10 |
|
11 |
-
$sLatestVersionBranch = '2.
|
12 |
$sOn = _wpsf__( 'On' );
|
13 |
$sOff = _wpsf__( 'Off' );
|
14 |
?>
|
@@ -17,11 +18,20 @@ $sOff = _wpsf__( 'Off' );
|
|
17 |
<div class="bootstrap-wpadmin">
|
18 |
<?php echo printOptionsPageHeader( 'Dashboard' ); ?>
|
19 |
|
20 |
-
<?php
|
21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
<div class="row">
|
23 |
<div class="<?php echo $icwp_fShowAds? 'span9' : 'span12'; ?>">
|
24 |
-
|
|
|
|
|
25 |
<form action="<?php echo $icwp_form_action; ?>" method="post" class="form-horizontal">
|
26 |
<?php
|
27 |
wp_nonce_field( $icwp_nonce_field );
|
@@ -43,19 +53,14 @@ $sOff = _wpsf__( 'Off' );
|
|
43 |
<?php endif; ?>
|
44 |
</div><!-- / row -->
|
45 |
|
46 |
-
<?php
|
47 |
-
<div class="row" id="worpit_promo">
|
48 |
-
<div class="span12">
|
49 |
-
<?php echo getWidgetIframeHtml( 'dashboard-widget-worpit-wtb' ); ?>
|
50 |
-
</div>
|
51 |
-
</div><!-- / row -->
|
52 |
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
<?php endif; ?>
|
60 |
|
61 |
<div class="row" id="tbs_docs">
|
@@ -141,7 +146,7 @@ $sOff = _wpsf__( 'Off' );
|
|
141 |
<?php endif; ?>
|
142 |
<hr/>
|
143 |
<h4 style="margin-top:20px;">
|
144 |
-
<?php printf( _wpsf__('
|
145 |
[ <a href="admin.php?page=icwp-wpsf-comments_filter"><?php _wpsf_e('Configure Now'); ?></a> ]</h4>
|
146 |
<?php if ( $fCommentsFilteringOn ) : ?>
|
147 |
<ul>
|
@@ -177,7 +182,7 @@ $sOff = _wpsf__( 'Off' );
|
|
177 |
}
|
178 |
?>
|
179 |
<ul>
|
180 |
-
<li><?php printf( _wpsf__('Automatically Update WordPress Simple Firewall Plugin: %s'), ($icwp_aAutoUpdatesOptions['
|
181 |
<li><?php printf( _wpsf__('Automatically Update WordPress Core: %s'), $sAutoCoreUpdateOption ); ?></li>
|
182 |
<li><?php printf( _wpsf__('Automatically Update Plugins: %s'), ($icwp_aAutoUpdatesOptions['enable_autoupdate_plugins'] == 'Y')? $sOn : $sOff ); ?></li>
|
183 |
<li><?php printf( _wpsf__('Automatically Update Themes: %s'), ($icwp_aAutoUpdatesOptions['enable_autoupdate_themes'] == 'Y')? $sOn : $sOff ); ?></li>
|
@@ -194,6 +199,13 @@ $sOff = _wpsf__( 'Off' );
|
|
194 |
<p><?php printf( _wpsf__('%snew%s refers to the absolute latest release.'), '<span class="label">', '</span>' ) ; ?></p>
|
195 |
<?php
|
196 |
$aNewLog = array(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
197 |
'ADDED: Localization capabilities. All we need now are translators.',
|
198 |
'ADDED: Option to mask the WordPress version so the real version is never publicly visible.'
|
199 |
);
|
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 |
+
$fAdminAccessOn = $icwp_aMainOptions['enable_admin_access_restriction'] == 'Y';
|
6 |
$fFirewallOn = $icwp_aMainOptions['enable_firewall'] == 'Y';
|
7 |
$fLoginProtectOn = $icwp_aMainOptions['enable_login_protect'] == 'Y';
|
8 |
$fCommentsFilteringOn = $icwp_aMainOptions['enable_comments_filter'] == 'Y';
|
9 |
$fLockdownOn = $icwp_aMainOptions['enable_lockdown'] == 'Y';
|
10 |
$fAutoUpdatesOn = $icwp_aMainOptions['enable_autoupdates'] == 'Y';
|
11 |
|
12 |
+
$sLatestVersionBranch = '2.x.x';
|
13 |
$sOn = _wpsf__( 'On' );
|
14 |
$sOff = _wpsf__( 'Off' );
|
15 |
?>
|
18 |
<div class="bootstrap-wpadmin">
|
19 |
<?php echo printOptionsPageHeader( 'Dashboard' ); ?>
|
20 |
|
21 |
+
<?php if ( $icwp_fShowAds ) : ?>
|
22 |
+
<div class="row" id="worpit_promo">
|
23 |
+
<div class="span12">
|
24 |
+
<?php echo getWidgetIframeHtml( 'dashboard-widget-worpit-wtb' ); ?>
|
25 |
+
</div>
|
26 |
+
</div><!-- / row -->
|
27 |
+
|
28 |
+
<?php endif; ?>
|
29 |
+
|
30 |
<div class="row">
|
31 |
<div class="<?php echo $icwp_fShowAds? 'span9' : 'span12'; ?>">
|
32 |
+
|
33 |
+
<?php include_once( dirname(__FILE__).'/icwp_wpsf_state_summary.php' ); ?>
|
34 |
+
|
35 |
<form action="<?php echo $icwp_form_action; ?>" method="post" class="form-horizontal">
|
36 |
<?php
|
37 |
wp_nonce_field( $icwp_nonce_field );
|
53 |
<?php endif; ?>
|
54 |
</div><!-- / row -->
|
55 |
|
56 |
+
<?php include_once( dirname(__FILE__).'/widgets/icwp_common_widgets.php' ); ?>
|
|
|
|
|
|
|
|
|
|
|
57 |
|
58 |
+
<?php if ( $icwp_fShowAds ) : ?>
|
59 |
+
<div class="row" id="developer_channel_promo">
|
60 |
+
<div class="span12">
|
61 |
+
<?php echo getWidgetIframeHtml('dashboard-widget-developerchannel-wtb'); ?>
|
62 |
+
</div>
|
63 |
+
</div><!-- / row -->
|
64 |
<?php endif; ?>
|
65 |
|
66 |
<div class="row" id="tbs_docs">
|
146 |
<?php endif; ?>
|
147 |
<hr/>
|
148 |
<h4 style="margin-top:20px;">
|
149 |
+
<?php printf( _wpsf__('Comments Filtering is %s'), $fCommentsFilteringOn ? $sOn : $sOff ); ?>
|
150 |
[ <a href="admin.php?page=icwp-wpsf-comments_filter"><?php _wpsf_e('Configure Now'); ?></a> ]</h4>
|
151 |
<?php if ( $fCommentsFilteringOn ) : ?>
|
152 |
<ul>
|
182 |
}
|
183 |
?>
|
184 |
<ul>
|
185 |
+
<li><?php printf( _wpsf__('Automatically Update WordPress Simple Firewall Plugin: %s'), ($icwp_aAutoUpdatesOptions['autoupdate_plugin_self'] == 'Y')? $sOn : $sOff ); ?></li>
|
186 |
<li><?php printf( _wpsf__('Automatically Update WordPress Core: %s'), $sAutoCoreUpdateOption ); ?></li>
|
187 |
<li><?php printf( _wpsf__('Automatically Update Plugins: %s'), ($icwp_aAutoUpdatesOptions['enable_autoupdate_plugins'] == 'Y')? $sOn : $sOff ); ?></li>
|
188 |
<li><?php printf( _wpsf__('Automatically Update Themes: %s'), ($icwp_aAutoUpdatesOptions['enable_autoupdate_themes'] == 'Y')? $sOn : $sOff ); ?></li>
|
199 |
<p><?php printf( _wpsf__('%snew%s refers to the absolute latest release.'), '<span class="label">', '</span>' ) ; ?></p>
|
200 |
<?php
|
201 |
$aNewLog = array(
|
202 |
+
'ADDED: Options to automatic updates to control where and whether email notifications are sent.',
|
203 |
+
'ADDED: Various fixes and verification of WordPress 3.8 compatibility.',
|
204 |
+
'ADDED: Integration with iControlWP and the automatic updates system.',
|
205 |
+
'ADDED: Better filesystem handling methods.',
|
206 |
+
'ADDED: Better firewall logic for whitelisting rules.',
|
207 |
+
'ADDED: Some new firewall white listing parameters to help with post editing.',
|
208 |
+
'ADDED: Option to run automatic updates upon demand according to your settings',
|
209 |
'ADDED: Localization capabilities. All we need now are translators.',
|
210 |
'ADDED: Option to mask the WordPress version so the real version is never publicly visible.'
|
211 |
);
|
views/icwp_wpsf_privacy_protect_log_index.php
ADDED
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
$icwp_fShowAds = false;
|
6 |
+
?>
|
7 |
+
<style>
|
8 |
+
dt {
|
9 |
+
width: auto !important;
|
10 |
+
}
|
11 |
+
tr.row-log-header td {
|
12 |
+
border-top: 2px solid #999 !important;
|
13 |
+
}
|
14 |
+
td .cell-section {
|
15 |
+
display: inline-block;
|
16 |
+
}
|
17 |
+
td .section-timestamp {
|
18 |
+
text-align: right;
|
19 |
+
width: 28%;
|
20 |
+
}
|
21 |
+
</style>
|
22 |
+
|
23 |
+
<div class="wrap">
|
24 |
+
<div class="bootstrap-wpadmin">
|
25 |
+
<?php echo printOptionsPageHeader( _wpsf__('Privacy Log') ); ?>
|
26 |
+
|
27 |
+
<div class="row">
|
28 |
+
<div class="<?php echo $icwp_fShowAds? 'span9' : 'span12'; ?>">
|
29 |
+
<form action="<?php echo $icwp_form_action; ?>" method="post" class="form-horizontal">
|
30 |
+
<?php
|
31 |
+
wp_nonce_field( $icwp_nonce_field );
|
32 |
+
?>
|
33 |
+
<div class="form-actions">
|
34 |
+
<input type="hidden" name="icwp_plugin_form_submit" value="Y" />
|
35 |
+
<button type="submit" class="btn btn-primary" name="clear_log_submit"><?php _wpsf_e( 'Clear/Fix Log' ); ?></button>
|
36 |
+
</div>
|
37 |
+
</form>
|
38 |
+
|
39 |
+
<?php if ( !$icwp_urlrequests_log ) : ?>
|
40 |
+
<?php echo 'There are currently no logs to display. If you expect there to be some, use the button above to Clean/Fix them.'; ?>
|
41 |
+
<?php else : ?>
|
42 |
+
|
43 |
+
<table class="table table-bordered table-hover table-condensed">
|
44 |
+
<tr>
|
45 |
+
<th><?php _wpsf_e('Date'); ?></th>
|
46 |
+
<th><?php _wpsf_e('URL'); ?></th>
|
47 |
+
<th><?php _wpsf_e('Method'); ?></th>
|
48 |
+
<th><?php _wpsf_e('Data'); ?></th>
|
49 |
+
<th><?php _wpsf_e('Error?'); ?></th>
|
50 |
+
</tr>
|
51 |
+
<?php foreach( $icwp_urlrequests_log as $sId => $aLogData ) : ?>
|
52 |
+
<tr class="row-log-header">
|
53 |
+
<td>
|
54 |
+
<span class="cell-section section-timestamp"><?php echo date( 'Y/m/d H:i:s', $aLogData['requested_at'] ); ?></span>
|
55 |
+
</td>
|
56 |
+
<td><?php echo $aLogData['request_url']; ?></td>
|
57 |
+
<td><?php echo $aLogData['request_method']; ?></td>
|
58 |
+
<td>
|
59 |
+
<dl class="dl-horizontal">
|
60 |
+
<?php
|
61 |
+
$aArgs = unserialize( $aLogData['request_args'] );
|
62 |
+
foreach( $aArgs as $sKey => $mValue ) {
|
63 |
+
echo sprintf( '<dt>%s</dt><dd>%s </dd>', $sKey, is_scalar( $mValue )? esc_attr( urldecode($mValue) ) : print_r( $mValue, true ) );
|
64 |
+
}
|
65 |
+
?>
|
66 |
+
</dl>
|
67 |
+
</td>
|
68 |
+
<td><?php echo $aLogData['is_error']; ?></td>
|
69 |
+
</tr>
|
70 |
+
<?php endforeach; ?>
|
71 |
+
</table>
|
72 |
+
|
73 |
+
<?php endif; ?>
|
74 |
+
</div><!-- / span9 -->
|
75 |
+
|
76 |
+
<?php if ( $icwp_fShowAds ) : ?>
|
77 |
+
<div class="span3" id="side_widgets">
|
78 |
+
<?php echo getWidgetIframeHtml('side-widgets-wtb'); ?>
|
79 |
+
</div>
|
80 |
+
<?php endif; ?>
|
81 |
+
</div><!-- / row -->
|
82 |
+
|
83 |
+
<div class="row">
|
84 |
+
<div class="span6">
|
85 |
+
</div><!-- / span6 -->
|
86 |
+
<div class="span6">
|
87 |
+
<p></p>
|
88 |
+
</div><!-- / span6 -->
|
89 |
+
</div><!-- / row -->
|
90 |
+
|
91 |
+
</div><!-- / bootstrap-wpadmin -->
|
92 |
+
|
93 |
+
</div><!-- / wrap -->
|
views/icwp_wpsf_state_summary.php
ADDED
@@ -0,0 +1,115 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
if ( empty($icwp_aSummaryData) ) {
|
3 |
+
return;
|
4 |
+
}
|
5 |
+
$fAdminAccessOn = $icwp_aMainOptions['enable_admin_access_restriction'] == 'Y';
|
6 |
+
$fFirewallOn = $icwp_aMainOptions['enable_firewall'] == 'Y';
|
7 |
+
$fLoginProtectOn = $icwp_aMainOptions['enable_login_protect'] == 'Y';
|
8 |
+
$fCommentsFilteringOn = $icwp_aMainOptions['enable_comments_filter'] == 'Y';
|
9 |
+
$fLockdownOn = $icwp_aMainOptions['enable_lockdown'] == 'Y';
|
10 |
+
$fAutoUpdatesOn = $icwp_aMainOptions['enable_autoupdates'] == 'Y';
|
11 |
+
|
12 |
+
$sOn = _wpsf__( 'On' );
|
13 |
+
$sOff = _wpsf__( 'Off' );
|
14 |
+
|
15 |
+
$sInnerSpanSize = 'span4';
|
16 |
+
|
17 |
+
function printFeatureSummaryBlock( $fOn, $sName, $sSettingsHref= '', $sInnerSpanSize = 4 ) {
|
18 |
+
$sFeatureSummaryBlockNameTemplates = '%s : <span class="feature-enabled-text">%s</span>';
|
19 |
+
$sOn = _wpsf__( 'On' );
|
20 |
+
$sOff = _wpsf__( 'Off' );
|
21 |
+
?>
|
22 |
+
<div class="span<?php echo $sInnerSpanSize;?> feature-summary-block state-<?php echo strtolower( $fOn? $sOn : $sOff ); ?>"
|
23 |
+
id="feature-<?php echo str_replace( ' ', '', strtolower($sName) ); ?>"
|
24 |
+
>
|
25 |
+
<div class="row-fluid">
|
26 |
+
<div class="feature-icon span3">
|
27 |
+
</div>
|
28 |
+
<div class="span8 offset1">
|
29 |
+
<a class="btn btn-<?php echo $fOn?'success':'warning';?>"
|
30 |
+
<?php echo empty($sSettingsHref)? 'disabled="disabled"': sprintf('href="%s"',$sSettingsHref);?>>
|
31 |
+
<?php echo empty($sSettingsHref)? _wpsf_e('See Below') : _wpsf_e('Go To Settings');?>
|
32 |
+
</a>
|
33 |
+
</div>
|
34 |
+
</div>
|
35 |
+
<div class="feature-name">
|
36 |
+
<?php echo sprintf( $sFeatureSummaryBlockNameTemplates, $sName, $fOn? 'ON':'OFF' ); ?>
|
37 |
+
</div>
|
38 |
+
</div>
|
39 |
+
<?php
|
40 |
+
}
|
41 |
+
|
42 |
+
?>
|
43 |
+
<style>
|
44 |
+
.feature-summary-blocks {
|
45 |
+
}
|
46 |
+
.feature-summary-blocks .feature-summary-block {
|
47 |
+
background-color: #F6F6F6;
|
48 |
+
border: 1px solid rgba(0, 0, 0, 0.3);
|
49 |
+
border-radius: 3px;
|
50 |
+
margin-bottom: 20px;
|
51 |
+
padding: 0;
|
52 |
+
}
|
53 |
+
.feature-summary-blocks .feature-summary-block.state-on {
|
54 |
+
background-color: rgba( 102, 216, 45, 0.2 );
|
55 |
+
}
|
56 |
+
.feature-summary-blocks .feature-summary-block.state-off {
|
57 |
+
background-color: rgba( 239, 141, 49, 0.2 );
|
58 |
+
}
|
59 |
+
.feature-summary-blocks .feature-summary-block .row-fluid .feature-icon {
|
60 |
+
padding: 20px;
|
61 |
+
text-align: center;
|
62 |
+
}
|
63 |
+
.feature-summary-blocks .feature-summary-block .row-fluid div {
|
64 |
+
line-height: 46px;
|
65 |
+
padding: 20px;
|
66 |
+
text-align: center;
|
67 |
+
}
|
68 |
+
.feature-summary-blocks .feature-summary-block .feature-icon a {
|
69 |
+
margin-left: 53px;
|
70 |
+
}
|
71 |
+
.feature-summary-blocks .feature-summary-block .feature-name {
|
72 |
+
border-top: 1px dashed #999999;
|
73 |
+
padding: 5px 20px;
|
74 |
+
}
|
75 |
+
.feature-summary-blocks .feature-summary-block .feature-name .feature-enabled-text {
|
76 |
+
float: right;
|
77 |
+
}
|
78 |
+
.feature-summary-blocks .feature-summary-block .feature-icon:before {
|
79 |
+
-webkit-font-smoothing: antialiased;
|
80 |
+
display: inline-block;
|
81 |
+
font: 48px/1 'dashicons';
|
82 |
+
vertical-align: top;
|
83 |
+
}
|
84 |
+
#feature-adminaccessprotection .feature-icon:before {
|
85 |
+
content: "\f332";
|
86 |
+
}
|
87 |
+
#feature-firewall .feature-icon:before {
|
88 |
+
content: "\f479";
|
89 |
+
}
|
90 |
+
#feature-loginprotection .feature-icon:before {
|
91 |
+
content: "\f110";
|
92 |
+
}
|
93 |
+
#feature-commentsfilter .feature-icon:before {
|
94 |
+
content: "\f130";
|
95 |
+
}
|
96 |
+
#feature-autoupdates .feature-icon:before {
|
97 |
+
content: "\f463";
|
98 |
+
}
|
99 |
+
#feature-lockdown .feature-icon:before {
|
100 |
+
content: "\f160";
|
101 |
+
}
|
102 |
+
|
103 |
+
</style>
|
104 |
+
|
105 |
+
<div class="row-fluid feature-summary-blocks">
|
106 |
+
<?php
|
107 |
+
foreach( $icwp_aSummaryData as $nKey => $aSummary ) {
|
108 |
+
if ( $nKey > 0 && ($nKey % 3 == 0) ) {
|
109 |
+
echo '</div><div class="row-fluid feature-summary-blocks">';
|
110 |
+
}
|
111 |
+
$sPage = isset( $_GET['page'] )? $_GET['page'] : '';
|
112 |
+
printFeatureSummaryBlock( $aSummary[0], $aSummary[1], ( $sPage==$aSummary[2])? '' : network_admin_url( 'admin.php?page='.$aSummary[2] ) );
|
113 |
+
}
|
114 |
+
?>
|
115 |
+
</div>
|
views/widgets/icwp_widgets.php
CHANGED
@@ -1,28 +1,26 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
function getWidgetIframeHtml( $insSnippet ) {
|
4 |
-
|
5 |
$sSubPageNow = isset( $_GET['page'] )? 'page='.$_GET['page'].'&': '';
|
6 |
-
|
7 |
$sWidth = '100%';
|
8 |
-
$sBackgroundColor = "
|
9 |
$sIframeName = 'iframe-hlt-bootstrapcss-'.$insSnippet;
|
10 |
-
|
11 |
if ( strpos( $insSnippet, 'side-widgets') !== false ) {
|
12 |
-
$sHeight = '
|
13 |
}
|
14 |
elseif ( strpos( $insSnippet, 'dashboard-widget-developerchannel') !== false ) {
|
15 |
$sHeight = '312px';
|
16 |
}
|
17 |
elseif ( strpos( $insSnippet, 'dashboard-widget-worpit') !== false ) {
|
18 |
$sHeight = '230px';
|
19 |
-
|
20 |
}
|
21 |
-
|
22 |
return '<iframe name="'.$sIframeName.'"
|
23 |
-
src="http://www.
|
24 |
width="'.$sWidth.'" height="'.$sHeight.'" frameborder="0" scrolling="no" style="background-color:'.$sBackgroundColor.';" ></iframe>
|
25 |
';
|
26 |
-
|
27 |
-
}
|
28 |
-
?>
|
1 |
<?php
|
|
|
2 |
function getWidgetIframeHtml( $insSnippet ) {
|
3 |
+
|
4 |
$sSubPageNow = isset( $_GET['page'] )? 'page='.$_GET['page'].'&': '';
|
5 |
+
|
6 |
$sWidth = '100%';
|
7 |
+
$sBackgroundColor = "rgba(0, 0, 0, 0)";
|
8 |
$sIframeName = 'iframe-hlt-bootstrapcss-'.$insSnippet;
|
9 |
+
|
10 |
if ( strpos( $insSnippet, 'side-widgets') !== false ) {
|
11 |
+
$sHeight = '1200px';
|
12 |
}
|
13 |
elseif ( strpos( $insSnippet, 'dashboard-widget-developerchannel') !== false ) {
|
14 |
$sHeight = '312px';
|
15 |
}
|
16 |
elseif ( strpos( $insSnippet, 'dashboard-widget-worpit') !== false ) {
|
17 |
$sHeight = '230px';
|
18 |
+
$sBackgroundColor = 'whiteSmoke';
|
19 |
}
|
20 |
+
|
21 |
return '<iframe name="'.$sIframeName.'"
|
22 |
+
src="http://www.icontrolwp.com/custom/remote/plugins/hlt-bootstrapcss-plugin-widgets.php?'.$sSubPageNow.'snippet='.$insSnippet.'"
|
23 |
width="'.$sWidth.'" height="'.$sHeight.'" frameborder="0" scrolling="no" style="background-color:'.$sBackgroundColor.';" ></iframe>
|
24 |
';
|
25 |
+
|
26 |
+
}
|
|