Wordfence Security – Firewall & Malware Scan - Version 7.1.8

Version Description

  • Improvement: Better detection of removal status when uninstalling the WAF's auto-prepend file.
  • Improvement: Switched optional mailing list signup to go directly through our servers rather than a third party.
  • Fix: Fixed the dashboard erroneously showing the payment method as missing for some payment methods.
  • Fix: If a premium license is deleted from wordfence.com, the plugin will now automatically downgrade rather than get stuck in an intermediate state.
  • Fix: Changed some wording to consistently use "License" or "License Key".
Download this release

Release Info

Developer wfryan
Plugin Icon 128x128 Wordfence Security – Firewall & Malware Scan
Version 7.1.8
Comparing to
See all releases

Code changes from version 7.1.7 to 7.1.8

Files changed (47) hide show
  1. css/{activity-report-widget.1528224180.css → activity-report-widget.1530033614.css} +0 -0
  2. css/{diff.1528224180.css → diff.1530033614.css} +0 -0
  3. css/{dt_table.1528224180.css → dt_table.1530033614.css} +0 -0
  4. css/{fullLog.1528224180.css → fullLog.1530033614.css} +0 -0
  5. css/{iptraf.1528224180.css → iptraf.1530033614.css} +0 -0
  6. css/{jquery-ui-timepicker-addon.1528224180.css → jquery-ui-timepicker-addon.1530033614.css} +0 -0
  7. css/{jquery-ui.min.1528224180.css → jquery-ui.min.1530033614.css} +0 -0
  8. css/{jquery-ui.structure.min.1528224180.css → jquery-ui.structure.min.1530033614.css} +0 -0
  9. css/{jquery-ui.theme.min.1528224180.css → jquery-ui.theme.min.1530033614.css} +0 -0
  10. css/{main.1528224180.css → main.1530033614.css} +0 -0
  11. css/{phpinfo.1528224180.css → phpinfo.1530033614.css} +0 -0
  12. css/{wf-adminbar.1528224180.css → wf-adminbar.1530033614.css} +0 -0
  13. css/{wf-colorbox.1528224180.css → wf-colorbox.1530033614.css} +0 -0
  14. css/{wf-font-awesome.1528224180.css → wf-font-awesome.1530033614.css} +0 -0
  15. css/{wf-ionicons.1528224180.css → wf-ionicons.1530033614.css} +0 -0
  16. css/{wf-onboarding.1528224180.css → wf-onboarding.1530033614.css} +0 -0
  17. css/{wf-roboto-font.1528224180.css → wf-roboto-font.1530033614.css} +0 -0
  18. css/{wfselect2.min.1528224180.css → wfselect2.min.1530033614.css} +0 -0
  19. css/{wordfenceBox.1528224180.css → wordfenceBox.1530033614.css} +0 -0
  20. js/{Chart.bundle.min.1528224180.js → Chart.bundle.min.1530033614.js} +0 -0
  21. js/{admin.1528224180.js → admin.1530033614.js} +1 -1
  22. js/{admin.ajaxWatcher.1528224180.js → admin.ajaxWatcher.1530033614.js} +0 -0
  23. js/{admin.liveTraffic.1528224180.js → admin.liveTraffic.1530033614.js} +0 -0
  24. js/{date.1528224180.js → date.1530033614.js} +0 -0
  25. js/{jquery-ui-timepicker-addon.1528224180.js → jquery-ui-timepicker-addon.1530033614.js} +0 -0
  26. js/{jquery.colorbox-min.1528224180.js → jquery.colorbox-min.1530033614.js} +0 -0
  27. js/{jquery.colorbox.1528224180.js → jquery.colorbox.1530033614.js} +0 -0
  28. js/{jquery.dataTables.min.1528224180.js → jquery.dataTables.min.1530033614.js} +0 -0
  29. js/{jquery.qrcode.min.1528224180.js → jquery.qrcode.min.1530033614.js} +0 -0
  30. js/{jquery.tmpl.min.1528224180.js → jquery.tmpl.min.1530033614.js} +0 -0
  31. js/{jquery.tools.min.1528224180.js → jquery.tools.min.1530033614.js} +0 -0
  32. js/{knockout-3.3.0.1528224180.js → knockout-3.3.0.1530033614.js} +0 -0
  33. js/{perf.1528224180.js → perf.1530033614.js} +0 -0
  34. js/{wfdashboard.1528224180.js → wfdashboard.1530033614.js} +0 -0
  35. js/{wfdropdown.1528224180.js → wfdropdown.1530033614.js} +0 -0
  36. js/{wfglobal.1528224180.js → wfglobal.1530033614.js} +3 -23
  37. js/{wfpopover.1528224180.js → wfpopover.1530033614.js} +0 -0
  38. js/{wfselect2.min.1528224180.js → wfselect2.min.1530033614.js} +0 -0
  39. lib/conntest.php +1 -1
  40. lib/wfAPI.php +9 -1
  41. lib/wfConfig.php +3 -3
  42. lib/wordfenceClass.php +59 -23
  43. readme.txt +8 -1
  44. views/onboarding/fresh-install.php +0 -1
  45. views/onboarding/modal-final-attempt.php +0 -1
  46. views/waf/options-group-basic-firewall.php +18 -0
  47. wordfence.php +3 -3
css/{activity-report-widget.1528224180.css → activity-report-widget.1530033614.css} RENAMED
File without changes
css/{diff.1528224180.css → diff.1530033614.css} RENAMED
File without changes
css/{dt_table.1528224180.css → dt_table.1530033614.css} RENAMED
File without changes
css/{fullLog.1528224180.css → fullLog.1530033614.css} RENAMED
File without changes
css/{iptraf.1528224180.css → iptraf.1530033614.css} RENAMED
File without changes
css/{jquery-ui-timepicker-addon.1528224180.css → jquery-ui-timepicker-addon.1530033614.css} RENAMED
File without changes
css/{jquery-ui.min.1528224180.css → jquery-ui.min.1530033614.css} RENAMED
File without changes
css/{jquery-ui.structure.min.1528224180.css → jquery-ui.structure.min.1530033614.css} RENAMED
File without changes
css/{jquery-ui.theme.min.1528224180.css → jquery-ui.theme.min.1530033614.css} RENAMED
File without changes
css/{main.1528224180.css → main.1530033614.css} RENAMED
File without changes
css/{phpinfo.1528224180.css → phpinfo.1530033614.css} RENAMED
File without changes
css/{wf-adminbar.1528224180.css → wf-adminbar.1530033614.css} RENAMED
File without changes
css/{wf-colorbox.1528224180.css → wf-colorbox.1530033614.css} RENAMED
File without changes
css/{wf-font-awesome.1528224180.css → wf-font-awesome.1530033614.css} RENAMED
File without changes
css/{wf-ionicons.1528224180.css → wf-ionicons.1530033614.css} RENAMED
File without changes
css/{wf-onboarding.1528224180.css → wf-onboarding.1530033614.css} RENAMED
File without changes
css/{wf-roboto-font.1528224180.css → wf-roboto-font.1530033614.css} RENAMED
File without changes
css/{wfselect2.min.1528224180.css → wfselect2.min.1530033614.css} RENAMED
File without changes
css/{wordfenceBox.1528224180.css → wordfenceBox.1530033614.css} RENAMED
File without changes
js/{Chart.bundle.min.1528224180.js → Chart.bundle.min.1530033614.js} RENAMED
File without changes
js/{admin.1528224180.js → admin.1530033614.js} RENAMED
@@ -3256,7 +3256,7 @@
3256
  self.colorboxModalHTML((self.isSmallScreen ? '300px' : '400px'), 'Rules Updated', 'Your rules have been updated successfully. You are ' +
3257
  'currently using the free version of Wordfence. ' +
3258
  'Upgrade to Wordfence premium to have your rules updated automatically as new threats emerge. ' +
3259
- '<a href="https://www.wordfence.com/wafUpdateRules1/wordfence-signup/">Click here to purchase a premium API key</a>. ' +
3260
  '<em>Note: Your rules will still update every 30 days as a free user.</em>');
3261
  } else {
3262
  self.colorboxModal((self.isSmallScreen ? '300px' : '400px'), 'Rules Updated', 'Your rules have been updated successfully.');
3256
  self.colorboxModalHTML((self.isSmallScreen ? '300px' : '400px'), 'Rules Updated', 'Your rules have been updated successfully. You are ' +
3257
  'currently using the free version of Wordfence. ' +
3258
  'Upgrade to Wordfence premium to have your rules updated automatically as new threats emerge. ' +
3259
+ '<a href="https://www.wordfence.com/wafUpdateRules1/wordfence-signup/">Click here to purchase a premium license</a>. ' +
3260
  '<em>Note: Your rules will still update every 30 days as a free user.</em>');
3261
  } else {
3262
  self.colorboxModal((self.isSmallScreen ? '300px' : '400px'), 'Rules Updated', 'Your rules have been updated successfully.');
js/{admin.ajaxWatcher.1528224180.js → admin.ajaxWatcher.1530033614.js} RENAMED
File without changes
js/{admin.liveTraffic.1528224180.js → admin.liveTraffic.1530033614.js} RENAMED
File without changes
js/{date.1528224180.js → date.1530033614.js} RENAMED
File without changes
js/{jquery-ui-timepicker-addon.1528224180.js → jquery-ui-timepicker-addon.1530033614.js} RENAMED
File without changes
js/{jquery.colorbox-min.1528224180.js → jquery.colorbox-min.1530033614.js} RENAMED
File without changes
js/{jquery.colorbox.1528224180.js → jquery.colorbox.1530033614.js} RENAMED
File without changes
js/{jquery.dataTables.min.1528224180.js → jquery.dataTables.min.1530033614.js} RENAMED
File without changes
js/{jquery.qrcode.min.1528224180.js → jquery.qrcode.min.1530033614.js} RENAMED
File without changes
js/{jquery.tmpl.min.1528224180.js → jquery.tmpl.min.1530033614.js} RENAMED
File without changes
js/{jquery.tools.min.1528224180.js → jquery.tools.min.1530033614.js} RENAMED
File without changes
js/{knockout-3.3.0.1528224180.js → knockout-3.3.0.1530033614.js} RENAMED
File without changes
js/{perf.1528224180.js → perf.1530033614.js} RENAMED
File without changes
js/{wfdashboard.1528224180.js → wfdashboard.1530033614.js} RENAMED
File without changes
js/{wfdropdown.1528224180.js → wfdropdown.1530033614.js} RENAMED
File without changes
js/{wfglobal.1528224180.js → wfglobal.1530033614.js} RENAMED
@@ -118,29 +118,9 @@
118
  }
119
 
120
  if (subscribe) {
121
- for (var i = 0; i < emails.length; i++) {
122
- $.ajax({
123
- type: 'POST',
124
- url: 'https://www.aweber.com/scripts/addlead.pl',
125
- data: {
126
- meta_web_form_id: '1428034071',
127
- meta_split_id: '',
128
- listname: 'wordfence',
129
- redirect: 'https://www.aweber.com/thankyou-coi.htm?m=text',
130
- meta_adtracking: 'widgetForm',
131
- meta_message: '1',
132
- meta_required: 'email',
133
- meta_tooltip: '',
134
- email: emails[i]
135
- },
136
- success: function(res) {
137
- //Do nothing
138
- },
139
- error: function() {
140
- //Do nothing
141
- }
142
- });
143
- }
144
  }
145
  },
146
  onboardingInstallLicense: function(license, successCallback, errorCallback) {
118
  }
119
 
120
  if (subscribe) {
121
+ this.ajax('wordfence_mailingSignup', {emails: JSON.stringify(emails)}, function(res) {
122
+ //Do nothing
123
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  }
125
  },
126
  onboardingInstallLicense: function(license, successCallback, errorCallback) {
js/{wfpopover.1528224180.js → wfpopover.1530033614.js} RENAMED
File without changes
js/{wfselect2.min.1528224180.js → wfselect2.min.1530033614.js} RENAMED
File without changes
lib/conntest.php CHANGED
@@ -67,7 +67,7 @@ function doCurlTest($protocol){
67
  curl_setopt ($curl, CURLOPT_WRITEFUNCTION, 'curlWrite');
68
  curl_exec($curl);
69
  $httpStatus = curl_getinfo($curl, CURLINFO_HTTP_CODE);
70
- if(strpos($curlContent, 'Your site did not send an API key') !== false){
71
  echo "Curl connectivity test passed.<br /><br />\n";
72
  } else {
73
  $curlErrorNo = curl_errno($curl);
67
  curl_setopt ($curl, CURLOPT_WRITEFUNCTION, 'curlWrite');
68
  curl_exec($curl);
69
  $httpStatus = curl_getinfo($curl, CURLINFO_HTTP_CODE);
70
+ if(strpos($curlContent, 'Your site did not send a license key') !== false){
71
  echo "Curl connectivity test passed.<br /><br />\n";
72
  } else {
73
  $curlErrorNo = curl_errno($curl);
lib/wfAPI.php CHANGED
@@ -69,11 +69,19 @@ class wfAPI {
69
  if (isset($dat['_hasKeyConflict'])) {
70
  $hasKeyConflict = ($dat['_hasKeyConflict'] == 1);
71
  if ($hasKeyConflict) {
72
- new wfNotification(null, wfNotification::PRIORITY_HIGH_CRITICAL, '<a href="' . network_admin_url('admin.php?page=Wordfence&subpage=global_options') . '">The Wordfence API key you\'re using does not match this site\'s address. Premium features are disabled.</a>', 'wfplugin_keyconflict', null, array(array('link' => 'https://www.wordfence.com/manage-wordfence-api-keys/', 'label' => 'Manage Keys')));
73
  wfConfig::set('hasKeyConflict', 1);
74
  }
75
  }
76
 
 
 
 
 
 
 
 
 
77
  if (!$hasKeyConflict) {
78
  wfConfig::remove('hasKeyConflict');
79
  $n = wfNotification::getNotificationForCategory('wfplugin_keyconflict');
69
  if (isset($dat['_hasKeyConflict'])) {
70
  $hasKeyConflict = ($dat['_hasKeyConflict'] == 1);
71
  if ($hasKeyConflict) {
72
+ new wfNotification(null, wfNotification::PRIORITY_HIGH_CRITICAL, '<a href="' . network_admin_url('admin.php?page=Wordfence&subpage=global_options') . '">The Wordfence license you\'re using does not match this site\'s address. Premium features are disabled.</a>', 'wfplugin_keyconflict', null, array(array('link' => 'https://www.wordfence.com/manage-wordfence-api-keys/', 'label' => 'Manage Keys')));
73
  wfConfig::set('hasKeyConflict', 1);
74
  }
75
  }
76
 
77
+ $keyNoLongerValid = false;
78
+ if (isset($dat['_keyNoLongerValid'])) {
79
+ $keyNoLongerValid = ($dat['_keyNoLongerValid'] == 1);
80
+ if ($keyNoLongerValid) {
81
+ wordfence::ajax_downgradeLicense_callback();
82
+ }
83
+ }
84
+
85
  if (!$hasKeyConflict) {
86
  wfConfig::remove('hasKeyConflict');
87
  $n = wfNotification::getNotificationForCategory('wfplugin_keyconflict');
lib/wfConfig.php CHANGED
@@ -1569,7 +1569,7 @@ Options -ExecCGI
1569
  }
1570
  }
1571
  catch (Exception $e) {
1572
- throw new wfConfigException(__('Your options have been saved, but you left your API key blank, so we tried to get you a free API key from the Wordfence servers. There was a problem fetching the free key: ', 'wordfence') . wp_kses($e->getMessage(), array()));
1573
  }
1574
  }
1575
  else if ($existingAPIKey != $apiKey) { //Key changed, try activating
@@ -1590,7 +1590,7 @@ Options -ExecCGI
1590
  }
1591
  }
1592
  catch (Exception $e) {
1593
- throw new wfConfigException(__('Your options have been saved. However we noticed you changed your API key, and we tried to verify it with the Wordfence servers but received an error: ', 'wordfence') . wp_kses($e->getMessage(), array()));
1594
  }
1595
  }
1596
  else { //Key unchanged, just ping it
@@ -1619,7 +1619,7 @@ Options -ExecCGI
1619
  wfConfig::set('keyType', $keyType);
1620
  }
1621
  catch (Exception $e){
1622
- throw new wfConfigException(__('Your options have been saved. However we tried to verify your API key with the Wordfence servers and received an error: ', 'wordfence') . wp_kses($e->getMessage(), array()));
1623
  }
1624
  }
1625
  }
1569
  }
1570
  }
1571
  catch (Exception $e) {
1572
+ throw new wfConfigException(__('Your options have been saved, but you left your license key blank, so we tried to get you a free license key from the Wordfence servers. There was a problem fetching the free key: ', 'wordfence') . wp_kses($e->getMessage(), array()));
1573
  }
1574
  }
1575
  else if ($existingAPIKey != $apiKey) { //Key changed, try activating
1590
  }
1591
  }
1592
  catch (Exception $e) {
1593
+ throw new wfConfigException(__('Your options have been saved. However we noticed you changed your license key, and we tried to verify it with the Wordfence servers but received an error: ', 'wordfence') . wp_kses($e->getMessage(), array()));
1594
  }
1595
  }
1596
  else { //Key unchanged, just ping it
1619
  wfConfig::set('keyType', $keyType);
1620
  }
1621
  catch (Exception $e){
1622
+ throw new wfConfigException(__('Your options have been saved. However we tried to verify your license key with the Wordfence servers and received an error: ', 'wordfence') . wp_kses($e->getMessage(), array()));
1623
  }
1624
  }
1625
  }
lib/wordfenceClass.php CHANGED
@@ -179,7 +179,7 @@ class wordfence {
179
  wfVersionCheckController::shared()->checkVersionsAndWarn();
180
  }
181
  private static function keyAlert($msg){
182
- self::alert($msg, $msg . " To ensure uninterrupted Premium Wordfence protection on your site,\nplease renew your API key by visiting http://www.wordfence.com/ Sign in, go to your dashboard,\nselect the key about to expire and click the button to renew that API key.", false);
183
  }
184
  public static function dailyCron() {
185
  $lastDailyCron = (int) wfConfig::get('lastDailyCron', 0);
@@ -206,8 +206,8 @@ class wordfence {
206
  wfConfig::set('keyAutoRenew10Sent', '');
207
  } else if ($keyExpDays <= 12 && $keyExpDays > 0 && !wfConfig::get('keyAutoRenew10Sent')) {
208
  wfConfig::set('keyAutoRenew10Sent', 1);
209
- $email = "Your Premium Wordfence API Key is set to auto-renew in 10 days.";
210
- self::alert($email, "$email To update your API key settings please visit http://www.wordfence.com/zz9/dashboard", false);
211
  }
212
  } else {
213
  if($keyExpDays > 15){
@@ -219,20 +219,20 @@ class wordfence {
219
  } else if($keyExpDays <= 15 && $keyExpDays > 0){
220
  if($keyExpDays <= 15 && $keyExpDays >= 11 && (! wfConfig::get('keyExp15Sent'))){
221
  wfConfig::set('keyExp15Sent', 1);
222
- self::keyAlert("Your Premium Wordfence API Key expires in less than 2 weeks.");
223
  } else if($keyExpDays <= 7 && $keyExpDays >= 4 && (! wfConfig::get('keyExp7Sent'))){
224
  wfConfig::set('keyExp7Sent', 1);
225
- self::keyAlert("Your Premium Wordfence API Key expires in less than a week.");
226
  } else if($keyExpDays == 2 && (! wfConfig::get('keyExp2Sent'))){
227
  wfConfig::set('keyExp2Sent', 1);
228
- self::keyAlert("Your Premium Wordfence API Key expires in 2 days.");
229
  } else if($keyExpDays == 1 && (! wfConfig::get('keyExp1Sent'))){
230
  wfConfig::set('keyExp1Sent', 1);
231
- self::keyAlert("Your Premium Wordfence API Key expires in 1 day.");
232
  }
233
  } else if($keyIsExpired && (! wfConfig::get('keyExpFinalSent')) ){
234
  wfConfig::set('keyExpFinalSent', 1);
235
- self::keyAlert("Your Wordfence Premium API Key has Expired!");
236
  }
237
  }
238
  }
@@ -254,7 +254,7 @@ class wordfence {
254
  wfConfig::set('keyType', $keyType);
255
  }
256
  catch(Exception $e){
257
- wordfence::status(4, 'error', "Could not verify Wordfence API Key: " . $e->getMessage());
258
  wfConfig::set('useNoc3Secure', false);
259
  }
260
 
@@ -478,10 +478,10 @@ SQL
478
  wfConfig::set('keyType', wfAPI::KEY_TYPE_FREE);
479
  $freshAPIKey = true;
480
  } else {
481
- throw new Exception("Could not understand the response we received from the Wordfence servers when applying for a free API key.");
482
  }
483
  } catch(Exception $e){
484
- error_log("Could not fetch free API key from Wordfence: " . $e->getMessage());
485
  return;
486
  }
487
  }
@@ -3064,7 +3064,7 @@ SQL
3064
  return array('ok' => 1);
3065
  }
3066
  public static function ajax_sendActivityLog_callback(){
3067
- $content = "SITE: " . site_url() . "\nPLUGIN VERSION: " . WORDFENCE_VERSION . "\nWP VERSION: " . wfUtils::getWPVersion() . "\nAPI KEY: " . wfConfig::get('apiKey') . "\nADMIN EMAIL: " . get_option('admin_email') . "\nLOG:\n\n";
3068
  $wfdb = new wfDB();
3069
  $table_wfStatus = wfDB::networkTable('wfStatus');
3070
  $q = $wfdb->querySelect("select ctime, level, type, msg from {$table_wfStatus} order by ctime desc limit 10000");
@@ -3168,15 +3168,21 @@ SQL
3168
  wfConfig::set('keyType', wfAPI::KEY_TYPE_FREE);
3169
  //When downgrading we must disable all two factor authentication because it can lock an admin out if we don't.
3170
  wfConfig::set_ser('twoFactorUsers', array());
 
 
 
 
 
 
3171
  self::licenseStatusChanged();
3172
  if (method_exists(wfWAF::getInstance()->getStorageEngine(), 'purgeIPBlocks')) {
3173
  wfWAF::getInstance()->getStorageEngine()->purgeIPBlocks(wfWAFStorageInterface::IP_BLOCKS_BLACKLIST);
3174
  }
3175
  } else {
3176
- throw new Exception("Could not understand the response we received from the Wordfence servers when applying for a free API key.");
3177
  }
3178
  } catch(Exception $e){
3179
- return array('errorMsg' => "Could not fetch free API key from Wordfence: " . wp_kses($e->getMessage(), array()));
3180
  }
3181
  return array('ok' => 1);
3182
  }
@@ -3590,6 +3596,19 @@ SQL
3590
  'success' => 1,
3591
  );
3592
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
3593
  public static function ajax_enableAllOptionsPage_callback() {
3594
  wfConfig::set('displayTopLevelOptions', 1);
3595
  $n = wfNotification::getNotificationForCategory('wfplugin_devalloptions');
@@ -5024,7 +5043,7 @@ HTML;
5024
  'dismissNotification', 'utilityScanForBlacklisted', 'dashboardShowMore',
5025
  'saveOptions', 'restoreDefaults', 'enableAllOptionsPage', 'createBlock', 'deleteBlocks', 'makePermanentBlocks', 'getBlocks',
5026
  'installAutoPrepend', 'uninstallAutoPrepend',
5027
- 'installLicense', 'recordTOUPP',
5028
  ) as $func){
5029
  add_action('wp_ajax_wordfence_' . $func, 'wordfence::ajaxReceiver');
5030
  }
@@ -6692,13 +6711,16 @@ to your httpd.conf if using Apache, or find documentation on how to disable dire
6692
  }
6693
 
6694
  try {
6695
- if ($helper->usesUserIni() && (!isset($_POST['iniModified']) || (isset($_POST['iniModified']) && !$_POST['iniModified']))) { //Uses .user.ini but not yet modified
6696
  $hasPreviousAutoPrepend = $helper->performIniRemoval($wp_filesystem);
6697
 
6698
  $iniTTL = intval(ini_get('user_ini.cache_ttl'));
6699
  if ($iniTTL == 0) {
6700
  $iniTTL = 300; //The PHP default
6701
  }
 
 
 
6702
  $timeout = max(30, $iniTTL);
6703
  $timeoutString = wfUtils::makeDuration($timeout);
6704
 
@@ -6729,19 +6751,33 @@ to your httpd.conf if using Apache, or find documentation on how to disable dire
6729
  }
6730
  return $response;
6731
  }
6732
- else { //.user.ini modified if applicable and waiting period elapsed or otherwise ready to advance to next step
6733
- if ($helper->usesUserIni() && WFWAF_AUTO_PREPEND) { //.user.ini modified, but the WAF is still enabled
6734
- $userIniError = '<p class="wf-error">' . __('Extended Protection Mode has not been disabled. This may be because <code>auto_prepend_file</code> is configured somewhere else or the value is still cached by PHP.', 'wordfence') . '</p>';
 
 
 
 
 
 
 
6735
  $html = wfView::create('waf/waf-modal-wrapper', array(
6736
  'title' => __('Unable to Uninstall', 'wordfence'),
6737
  'html' => $userIniError,
6738
  'helpHTML' => sprintf(__('If you cannot complete the uninstall process, <a target="_blank" rel="noopener noreferrer" href="%s">click here for help</a>', 'wordfence'), wfSupportController::esc_supportURL(wfSupportController::ITEM_FIREWALL_WAF_REMOVE_MANUALLY)),
6739
  'footerButtonTitle' => __('Cancel', 'wordfence'),
6740
  ))->render();
6741
- return array('uninstallationFailed' => 1, 'html' => $html);
6742
- }
6743
- else if (!$helper->usesUserIni()) {
6744
- $helper->performIniRemoval($wp_filesystem); //Do .htaccess here
 
 
 
 
 
 
 
6745
  }
6746
 
6747
  $helper->performAutoPrependFileRemoval($wp_filesystem);
179
  wfVersionCheckController::shared()->checkVersionsAndWarn();
180
  }
181
  private static function keyAlert($msg){
182
+ self::alert($msg, $msg . " To ensure uninterrupted Premium Wordfence protection on your site,\nplease renew your license by visiting http://www.wordfence.com/ Sign in, go to your dashboard,\nselect the license about to expire and click the button to renew that license.", false);
183
  }
184
  public static function dailyCron() {
185
  $lastDailyCron = (int) wfConfig::get('lastDailyCron', 0);
206
  wfConfig::set('keyAutoRenew10Sent', '');
207
  } else if ($keyExpDays <= 12 && $keyExpDays > 0 && !wfConfig::get('keyAutoRenew10Sent')) {
208
  wfConfig::set('keyAutoRenew10Sent', 1);
209
+ $email = "Your Premium Wordfence License is set to auto-renew in 10 days.";
210
+ self::alert($email, "$email To update your license settings please visit http://www.wordfence.com/zz9/dashboard", false);
211
  }
212
  } else {
213
  if($keyExpDays > 15){
219
  } else if($keyExpDays <= 15 && $keyExpDays > 0){
220
  if($keyExpDays <= 15 && $keyExpDays >= 11 && (! wfConfig::get('keyExp15Sent'))){
221
  wfConfig::set('keyExp15Sent', 1);
222
+ self::keyAlert("Your Premium Wordfence License expires in less than 2 weeks.");
223
  } else if($keyExpDays <= 7 && $keyExpDays >= 4 && (! wfConfig::get('keyExp7Sent'))){
224
  wfConfig::set('keyExp7Sent', 1);
225
+ self::keyAlert("Your Premium Wordfence License expires in less than a week.");
226
  } else if($keyExpDays == 2 && (! wfConfig::get('keyExp2Sent'))){
227
  wfConfig::set('keyExp2Sent', 1);
228
+ self::keyAlert("Your Premium Wordfence License expires in 2 days.");
229
  } else if($keyExpDays == 1 && (! wfConfig::get('keyExp1Sent'))){
230
  wfConfig::set('keyExp1Sent', 1);
231
+ self::keyAlert("Your Premium Wordfence License expires in 1 day.");
232
  }
233
  } else if($keyIsExpired && (! wfConfig::get('keyExpFinalSent')) ){
234
  wfConfig::set('keyExpFinalSent', 1);
235
+ self::keyAlert("Your Wordfence Premium License has Expired!");
236
  }
237
  }
238
  }
254
  wfConfig::set('keyType', $keyType);
255
  }
256
  catch(Exception $e){
257
+ wordfence::status(4, 'error', "Could not verify Wordfence License: " . $e->getMessage());
258
  wfConfig::set('useNoc3Secure', false);
259
  }
260
 
478
  wfConfig::set('keyType', wfAPI::KEY_TYPE_FREE);
479
  $freshAPIKey = true;
480
  } else {
481
+ throw new Exception("Could not understand the response we received from the Wordfence servers when applying for a free license key.");
482
  }
483
  } catch(Exception $e){
484
+ error_log("Could not fetch free license key from Wordfence: " . $e->getMessage());
485
  return;
486
  }
487
  }
3064
  return array('ok' => 1);
3065
  }
3066
  public static function ajax_sendActivityLog_callback(){
3067
+ $content = "SITE: " . site_url() . "\nPLUGIN VERSION: " . WORDFENCE_VERSION . "\nWP VERSION: " . wfUtils::getWPVersion() . "\nLICENSE KEY: " . wfConfig::get('apiKey') . "\nADMIN EMAIL: " . get_option('admin_email') . "\nLOG:\n\n";
3068
  $wfdb = new wfDB();
3069
  $table_wfStatus = wfDB::networkTable('wfStatus');
3070
  $q = $wfdb->querySelect("select ctime, level, type, msg from {$table_wfStatus} order by ctime desc limit 10000");
3168
  wfConfig::set('keyType', wfAPI::KEY_TYPE_FREE);
3169
  //When downgrading we must disable all two factor authentication because it can lock an admin out if we don't.
3170
  wfConfig::set_ser('twoFactorUsers', array());
3171
+ wfConfig::remove('premiumAutoRenew');
3172
+ wfConfig::remove('premiumNextRenew');
3173
+ wfConfig::remove('premiumPaymentExpiring');
3174
+ wfConfig::remove('premiumPaymentExpired');
3175
+ wfConfig::remove('premiumPaymentMissing');
3176
+ wfConfig::remove('premiumPaymentHold');
3177
  self::licenseStatusChanged();
3178
  if (method_exists(wfWAF::getInstance()->getStorageEngine(), 'purgeIPBlocks')) {
3179
  wfWAF::getInstance()->getStorageEngine()->purgeIPBlocks(wfWAFStorageInterface::IP_BLOCKS_BLACKLIST);
3180
  }
3181
  } else {
3182
+ throw new Exception("Could not understand the response we received from the Wordfence servers when applying for a free license key.");
3183
  }
3184
  } catch(Exception $e){
3185
+ return array('errorMsg' => "Could not fetch free license key from Wordfence: " . wp_kses($e->getMessage(), array()));
3186
  }
3187
  return array('ok' => 1);
3188
  }
3596
  'success' => 1,
3597
  );
3598
  }
3599
+ public static function ajax_mailingSignup_callback() {
3600
+ if (isset($_POST['emails'])) {
3601
+ $emails = @json_decode(stripslashes($_POST['emails']), true);
3602
+ if (is_array($emails) && count($emails)) {
3603
+ $api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
3604
+ $result = $api->call('mailing_signup', array(), array('signup' => json_encode(array('emails' => $emails))));
3605
+ }
3606
+ }
3607
+
3608
+ return array(
3609
+ 'success' => 1,
3610
+ );
3611
+ }
3612
  public static function ajax_enableAllOptionsPage_callback() {
3613
  wfConfig::set('displayTopLevelOptions', 1);
3614
  $n = wfNotification::getNotificationForCategory('wfplugin_devalloptions');
5043
  'dismissNotification', 'utilityScanForBlacklisted', 'dashboardShowMore',
5044
  'saveOptions', 'restoreDefaults', 'enableAllOptionsPage', 'createBlock', 'deleteBlocks', 'makePermanentBlocks', 'getBlocks',
5045
  'installAutoPrepend', 'uninstallAutoPrepend',
5046
+ 'installLicense', 'recordTOUPP', 'mailingSignup',
5047
  ) as $func){
5048
  add_action('wp_ajax_wordfence_' . $func, 'wordfence::ajaxReceiver');
5049
  }
6711
  }
6712
 
6713
  try {
6714
+ if ((!isset($_POST['iniModified']) || (isset($_POST['iniModified']) && !$_POST['iniModified']))) { //Uses .user.ini but not yet modified
6715
  $hasPreviousAutoPrepend = $helper->performIniRemoval($wp_filesystem);
6716
 
6717
  $iniTTL = intval(ini_get('user_ini.cache_ttl'));
6718
  if ($iniTTL == 0) {
6719
  $iniTTL = 300; //The PHP default
6720
  }
6721
+ if (!$helper->usesUserIni()) {
6722
+ $iniTTL = 0; //.htaccess
6723
+ }
6724
  $timeout = max(30, $iniTTL);
6725
  $timeoutString = wfUtils::makeDuration($timeout);
6726
 
6751
  }
6752
  return $response;
6753
  }
6754
+ else { //.user.ini and .htaccess modified if applicable and waiting period elapsed or otherwise ready to advance to next step
6755
+ if (WFWAF_AUTO_PREPEND && !WFWAF_SUBDIRECTORY_INSTALL) { //.user.ini modified, but the WAF is still enabled
6756
+ $retryAttempted = (isset($_POST['retryAttempted']) && $_POST['retryAttempted']);
6757
+ $userIniError = '<p class="wf-error">';
6758
+ $userIniError .= __('Extended Protection Mode has not been disabled. This may be because <code>auto_prepend_file</code> is configured somewhere else or the value is still cached by PHP.', 'wordfence');
6759
+ if ($retryAttempted) {
6760
+ $userIniError .= ' <strong>' . __('Retrying Failed.', 'wordfence') . '</strong>';
6761
+ }
6762
+ $userIniError .= ' <a href="#" class="wf-waf-uninstall-try-again">' . __('Try Again', 'wordfence') . '</a>';
6763
+ $userIniError .= '</p>';
6764
  $html = wfView::create('waf/waf-modal-wrapper', array(
6765
  'title' => __('Unable to Uninstall', 'wordfence'),
6766
  'html' => $userIniError,
6767
  'helpHTML' => sprintf(__('If you cannot complete the uninstall process, <a target="_blank" rel="noopener noreferrer" href="%s">click here for help</a>', 'wordfence'), wfSupportController::esc_supportURL(wfSupportController::ITEM_FIREWALL_WAF_REMOVE_MANUALLY)),
6768
  'footerButtonTitle' => __('Cancel', 'wordfence'),
6769
  ))->render();
6770
+
6771
+ $response = array('uninstallationFailed' => 1, 'html' => $html, 'serverConfiguration' => $_POST['serverConfiguration']);
6772
+ if (isset($credentials) && is_array($credentials)) {
6773
+ $salt = wp_salt('logged_in');
6774
+ $json = json_encode($credentials);
6775
+ $encrypted = wfUtils::encrypt($json);
6776
+ $signature = hash_hmac('sha256', $encrypted, $salt);
6777
+ $response['credentials'] = $encrypted;
6778
+ $response['credentialsSignature'] = $signature;
6779
+ }
6780
+ return $response;
6781
  }
6782
 
6783
  $helper->performAutoPrependFileRemoval($wp_filesystem);
readme.txt CHANGED
@@ -4,7 +4,7 @@ Tags: security, firewall, malware scanner, web application firewall, antivirus,
4
  Requires at least: 3.9
5
  Requires PHP: 5.2
6
  Tested up to: 4.9.6
7
- Stable tag: 7.1.7
8
 
9
  Secure your website with the most comprehensive WordPress security plugin. Firewall, malware scan, blocking, live traffic, login security & more.
10
 
@@ -172,6 +172,13 @@ Secure your website with Wordfence.
172
 
173
  == Changelog ==
174
 
 
 
 
 
 
 
 
175
  = 7.1.7 =
176
  * Improvement: Added better support for keyboard navigation of options.
177
  * Improvement: staging. and dev. subdomains are now supported for sharing premium licenses.
4
  Requires at least: 3.9
5
  Requires PHP: 5.2
6
  Tested up to: 4.9.6
7
+ Stable tag: 7.1.8
8
 
9
  Secure your website with the most comprehensive WordPress security plugin. Firewall, malware scan, blocking, live traffic, login security & more.
10
 
172
 
173
  == Changelog ==
174
 
175
+ = 7.1.8 =
176
+ * Improvement: Better detection of removal status when uninstalling the WAF's auto-prepend file.
177
+ * Improvement: Switched optional mailing list signup to go directly through our servers rather than a third party.
178
+ * Fix: Fixed the dashboard erroneously showing the payment method as missing for some payment methods.
179
+ * Fix: If a premium license is deleted from wordfence.com, the plugin will now automatically downgrade rather than get stuck in an intermediate state.
180
+ * Fix: Changed some wording to consistently use "License" or "License Key".
181
+
182
  = 7.1.7 =
183
  * Improvement: Added better support for keyboard navigation of options.
184
  * Improvement: staging. and dev. subdomains are now supported for sharing premium licenses.
views/onboarding/fresh-install.php CHANGED
@@ -30,7 +30,6 @@ if (!defined('WORDFENCE_VERSION')) { exit; }
30
  <li><a href="#" class="wf-onboarding-btn wf-onboarding-btn-primary wf-disabled" id="wf-onboarding-continue"><?php _e('Continue', 'wordfence'); ?></a></li>
31
  </ul>
32
  </div>
33
- <div style="display: none;"><img src="https://forms.aweber.com/form/displays.htm?id=jCxMHAzMLAzsjA==" alt="" /></div>
34
  </div>
35
  <div id="wf-onboarding-fresh-install-2" class="wf-onboarding-modal-content"<?php if (wfConfig::get('onboardingAttempt1') != wfOnboardingController::ONBOARDING_FIRST_EMAILS) { echo ' style="display: none;"'; } ?>>
36
  <div class="wf-onboarding-logo"><img src="<?php echo esc_attr(wfUtils::getBaseURL() . 'images/logo.png'); ?>" alt="<?php _e('Wordfence - Securing your WordPress Website', 'wordfence'); ?>"></div>
30
  <li><a href="#" class="wf-onboarding-btn wf-onboarding-btn-primary wf-disabled" id="wf-onboarding-continue"><?php _e('Continue', 'wordfence'); ?></a></li>
31
  </ul>
32
  </div>
 
33
  </div>
34
  <div id="wf-onboarding-fresh-install-2" class="wf-onboarding-modal-content"<?php if (wfConfig::get('onboardingAttempt1') != wfOnboardingController::ONBOARDING_FIRST_EMAILS) { echo ' style="display: none;"'; } ?>>
35
  <div class="wf-onboarding-logo"><img src="<?php echo esc_attr(wfUtils::getBaseURL() . 'images/logo.png'); ?>" alt="<?php _e('Wordfence - Securing your WordPress Website', 'wordfence'); ?>"></div>
views/onboarding/modal-final-attempt.php CHANGED
@@ -28,7 +28,6 @@ if (!defined('WORDFENCE_VERSION')) { exit; }
28
  <p><?php _e('(Choose One)', 'wordfence'); ?></p>
29
  </div>
30
  </div>
31
- <div style="display: none;"><img src="https://forms.aweber.com/form/displays.htm?id=jCxMHAzMLAzsjA==" alt="" /></div>
32
  </div>
33
  <div id="wf-onboarding-final-attempt-2" class="wf-onboarding-modal-content"<?php if (wfConfig::get('onboardingAttempt3') != wfOnboardingController::ONBOARDING_THIRD_EMAILS) { echo ' style="display: none;"'; } ?>>
34
  <h3><?php _e('Activate Premium', 'wordfence'); ?></h3>
28
  <p><?php _e('(Choose One)', 'wordfence'); ?></p>
29
  </div>
30
  </div>
 
31
  </div>
32
  <div id="wf-onboarding-final-attempt-2" class="wf-onboarding-modal-content"<?php if (wfConfig::get('onboardingAttempt3') != wfOnboardingController::ONBOARDING_THIRD_EMAILS) { echo ' style="display: none;"'; } ?>>
33
  <h3><?php _e('Activate Premium', 'wordfence'); ?></h3>
views/waf/options-group-basic-firewall.php CHANGED
@@ -232,6 +232,24 @@ if (!isset($collapseable)) {
232
  WFAD.colorboxClose();
233
  });
234
  $.wfcolorbox.resize();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
  }
236
  else if (res.uninstallationWaiting) {
237
  var replacement = $(res.html);
232
  WFAD.colorboxClose();
233
  });
234
  $.wfcolorbox.resize();
235
+
236
+ var payload = {serverConfiguration: res.serverConfiguration, iniModified: 1};
237
+ if (res.credentials) {
238
+ payload['credentials'] = res.credentials;
239
+ payload['credentialsSignature'] = res.credentialsSignature;
240
+ }
241
+
242
+ $('.wf-waf-uninstall-try-again').on('click', function(e) {
243
+ e.preventDefault();
244
+ e.stopPropagation();
245
+
246
+ $(this).text('Retrying');
247
+ payload['retryAttempted'] = 1;
248
+
249
+ WFAD.ajax(action, payload, function(res) {
250
+ installUninstallResponseHandler(action, res);
251
+ });
252
+ });
253
  }
254
  else if (res.uninstallationWaiting) {
255
  var replacement = $(res.html);
wordfence.php CHANGED
@@ -4,15 +4,15 @@ Plugin Name: Wordfence Security
4
  Plugin URI: http://www.wordfence.com/
5
  Description: Wordfence Security - Anti-virus, Firewall and Malware Scan
6
  Author: Wordfence
7
- Version: 7.1.7
8
  Author URI: http://www.wordfence.com/
9
  Network: true
10
  */
11
  if(defined('WP_INSTALLING') && WP_INSTALLING){
12
  return;
13
  }
14
- define('WORDFENCE_VERSION', '7.1.7');
15
- define('WORDFENCE_BUILD_NUMBER', '1528224180');
16
  define('WORDFENCE_BASENAME', function_exists('plugin_basename') ? plugin_basename(__FILE__) :
17
  basename(dirname(__FILE__)) . '/' . basename(__FILE__));
18
 
4
  Plugin URI: http://www.wordfence.com/
5
  Description: Wordfence Security - Anti-virus, Firewall and Malware Scan
6
  Author: Wordfence
7
+ Version: 7.1.8
8
  Author URI: http://www.wordfence.com/
9
  Network: true
10
  */
11
  if(defined('WP_INSTALLING') && WP_INSTALLING){
12
  return;
13
  }
14
+ define('WORDFENCE_VERSION', '7.1.8');
15
+ define('WORDFENCE_BUILD_NUMBER', '1530033614');
16
  define('WORDFENCE_BASENAME', function_exists('plugin_basename') ? plugin_basename(__FILE__) :
17
  basename(dirname(__FILE__)) . '/' . basename(__FILE__));
18