: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
public static function doNotCache(){ //Call this to prevent Wordfence from caching the current page.
public static function whitelistIP($IP){ //IP as a string in dotted quad notation e.g. '10.11.12.13'
$user_range = new wfUserIPRange($IP);
if (!$user_range->isValidRange()) {
throw new Exception(__("The IP you provided must be in dotted quad notation or use ranges with square brackets. e.g. 10.11.12.13 or 10.11.12.[1-50]", 'wordfence'));
$whites = wfConfig::get('whitelisted', '');
$arr = explode(',', $whites);
wfConfig::set('whitelisted', implode(',', $arr2));
public static function ajax_email_summary_email_address_debug_callback() {
$email = !empty($_REQUEST['email']) ? $_REQUEST['email'] : null;
if (!wfUtils::isValidEmail($email)) {
return array('result' => __('Invalid email address provided', 'wordfence'));
$report = new wfActivityReport();
return $report->sendReportViaEmail($email) ?
array('ok' => 1, 'result' => __('Test email sent successfully', 'wordfence')) :
array('result' => __("Test email failed to send", 'wordfence'));
public static function addDashboardWidget() {
if (wfUtils::isAdmin() && (is_network_admin() || !is_multisite()) && wfConfig::get('email_summary_dashboard_widget_enabled')) {
wp_enqueue_style('wordfence-activity-report-widget', wfUtils::getBaseURL() . wfUtils::versionedAsset('css/activity-report-widget.css'), '', WORDFENCE_VERSION);
$report_date_range = 'week';
switch (wfConfig::get('email_summary_interval')) {
$report_date_range = 'day';
$report_date_range = 'month';
'wordfence_activity_report_widget',
sprintf(/* translators: Localized date range. */ __('Wordfence activity in the past %s', 'wordfence'), $report_date_range),
array('wfActivityReport', 'outputDashboardWidget')
public static function hasGDLimitLoginsMUPlugin() {
return defined('GD_SYSTEM_PLUGIN_DIR') && file_exists(GD_SYSTEM_PLUGIN_DIR . 'limit-login-attempts/limit-login-attempts.php')
&& defined('LIMIT_LOGIN_DIRECT_ADDR');
public static function fixGDLimitLoginsErrors($content) {
$content = str_replace(wp_kses(__('<strong>ERROR</strong>: Incorrect username or password.', 'limit-login-attempts'), array('strong'=>array())) . "<br />\n", '', $content);
$content .= '<br />' . self::$authError->get_error_message();
public static function ajax_deleteAdminUser_callback() {
$issueID = absint(!empty($_POST['issueID']) ? $_POST['issueID'] : 0);
$wfIssues = new wfIssues();
$issue = $wfIssues->getIssueByID($issueID);
return array('errorMsg' => __("We could not find that issue in our database.", 'wordfence'));
if (empty($data['userID'])) {
return array('errorMsg' => __("We could not find that user in the database.", 'wordfence'));
$user = new WP_User($data['userID']);
return array('errorMsg' => __("We could not find that user in the database.", 'wordfence'));
$userLogin = $user->user_login;
if (is_multisite() && strcasecmp($user->user_email, get_site_option('admin_email')) === 0) {
return array('errorMsg' => __("This user's email is the network admin email. It will need to be changed before deleting this user.", 'wordfence'));
revoke_super_admin($data['userID']);
wp_delete_user($data['userID']);
$wpdb->delete($wpdb->users, array('ID' => $data['userID']));
$wfIssues->deleteIssue($issueID);
wfScanEngine::refreshScanNotification($wfIssues);
'user_login' => $userLogin,
public static function ajax_revokeAdminUser_callback() {
$issueID = absint(!empty($_POST['issueID']) ? $_POST['issueID'] : 0);
$wfIssues = new wfIssues();
$issue = $wfIssues->getIssueByID($issueID);
return array('errorMsg' => __("We could not find that issue in our database.", 'wordfence'));
if (empty($data['userID'])) {
return array('errorMsg' => __("We could not find that user in the database.", 'wordfence'));
$user = new WP_User($data['userID']);
$userLogin = $user->user_login;
wp_revoke_user($data['userID']);
revoke_super_admin($data['userID']);
$wfIssues->deleteIssue($issueID);
wfScanEngine::refreshScanNotification($wfIssues);
'user_login' => $userLogin,
public static function ajax_acknowledgeAdminUser_callback() {
$issueID = absint(!empty($_POST['issueID']) ? $_POST['issueID'] : 0);
$wfIssues = new wfIssues();
$issue = $wfIssues->getIssueByID($issueID);
return array('errorMsg' => __("We could not find that issue in the database.", 'wordfence'));
if (empty($data['userID'])) {
return array('errorMsg' => __("We could not find that user in the database.", 'wordfence'));
$user = new WP_User($data['userID']);
return array('errorMsg' => __("We could not find that user in the database.", 'wordfence'));
$userLogin = $user->user_login;
$adminUsers = new wfAdminUserMonitor();
$adminUsers->addAdmin($data['userID']);
$wfIssues->deleteIssue($issueID);
wfScanEngine::refreshScanNotification($wfIssues);
'user_login' => $userLogin,
public static function ajax_disableDirectoryListing_callback() {
$issueID = absint($_POST['issueID']);
$wfIssues = new wfIssues();
$issue = $wfIssues->getIssueByID($issueID);
'errorMsg' => __("We could not find that issue in our database.", 'wordfence'),
$wfIssues->deleteIssue($issueID);
$htaccessPath = wfCache::getHtaccessPath();
'errorMsg' => __("Wordfence could not find your .htaccess file.", 'wordfence'),
$fileContents = file_get_contents($htaccessPath);
if (file_put_contents($htaccessPath, "# Added by Wordfence " . date('r') . "\nOptions -Indexes\n\n" . $fileContents, LOCK_EX)) {
$uploadPaths = wp_upload_dir();
if (!wfScanEngine::isDirectoryListingEnabled($uploadPaths['baseurl'])) {
// Revert any changes done to .htaccess
file_put_contents($htaccessPath, $fileContents, LOCK_EX);
'errorMsg' => __("Updating the .htaccess did not fix the issue. You may need to add <code>Options -Indexes</code> to your httpd.conf if using Apache, or find documentation on how to disable directory listing for your web server.", 'wordfence'),
'errorMsg' => __("There was an error writing to your .htaccess file.", 'wordfence'),
* Modify the query to prevent username enumeration.
* @param array $query_vars
public static function preventAuthorNScans($query_vars) {
if (wfConfig::get('loginSec_disableAuthorScan') && !is_admin() &&
!empty($query_vars['author']) && (is_array($query_vars['author']) || is_numeric(preg_replace('/[^0-9]/', '', $query_vars['author']))) &&
(isset($_GET['author']) && (is_array($_GET['author']) || is_numeric(preg_replace('/[^0-9]/', '', $_GET['author'])))) ||
(isset($_POST['author']) && (is_array($_POST['author']) || is_numeric(preg_replace('/[^0-9]/', '', $_POST['author']))))
$template = get_404_template();
if ($template && file_exists($template)) {
* @param WP_Upgrader $updater
* @param array $hook_extra
public static function hideReadme($updater, $hook_extra = null) {
if (wfConfig::get('other_hideWPVersion')) {
public static function ajax_saveDisclosureState_callback() {
if (isset($_POST['name']) && isset($_POST['state'])) {
$name = preg_replace('/[^a-zA-Z0-9_\-]/', '', $_POST['name']);
$state = wfUtils::truthyToBoolean($_POST['state']);
$disclosureStates = wfConfig::get_ser('disclosureStates', array());
$disclosureStates[$name] = $state;
wfConfig::set_ser('disclosureStates', $disclosureStates);
else if (isset($_POST['names']) && isset($_POST['state'])) {
$rawNames = $_POST['names'];
if (is_array($rawNames)) {
$filteredNames = array();
foreach ($rawNames as $name) {
$name = preg_replace('/[^a-zA-Z0-9_\-]/', '', $name);
$filteredNames[] = $name;
$state = wfUtils::truthyToBoolean($_POST['state']);
if (!empty($filteredNames)) {
$disclosureStates = wfConfig::get_ser('disclosureStates', array());
foreach ($filteredNames as $name) {
$disclosureStates[$name] = $state;
wfConfig::set_ser('disclosureStates', $disclosureStates);
'errorMsg' => __("Required parameters not sent.", 'wordfence'),
public static function ajax_saveWAFConfig_callback() {
if (isset($_POST['wafConfigAction'])) {
$waf = wfWAF::getInstance();
if (method_exists($waf, 'isReadOnly') && $waf->isReadOnly()) {
'errorMsg' => __("The WAF is currently in read-only mode and will not save any configuration changes.", 'wordfence'),
switch ($_POST['wafConfigAction']) {
if (!empty($_POST['wafStatus']) && in_array($_POST['wafStatus'], array(wfFirewall::FIREWALL_MODE_DISABLED, wfFirewall::FIREWALL_MODE_LEARNING, wfFirewall::FIREWALL_MODE_ENABLED))) {
if ($_POST['wafStatus'] == 'learning-mode' && !empty($_POST['learningModeGracePeriodEnabled'])) {
$gracePeriodEnd = strtotime(isset($_POST['learningModeGracePeriod']) ? $_POST['learningModeGracePeriod'] : '');
if ($gracePeriodEnd > time()) {
wfWAF::getInstance()->getStorageEngine()->setConfig('learningModeGracePeriodEnabled', 1);
wfWAF::getInstance()->getStorageEngine()->setConfig('learningModeGracePeriod', $gracePeriodEnd);
'errorMsg' => __("The grace period end time must be in the future.", 'wordfence'),
wfWAF::getInstance()->getStorageEngine()->setConfig('learningModeGracePeriodEnabled', 0);
wfWAF::getInstance()->getStorageEngine()->unsetConfig('learningModeGracePeriod');
wfWAF::getInstance()->getStorageEngine()->setConfig('wafStatus', $_POST['wafStatus']);
$firewall = new wfFirewall();
$firewall->syncStatus(true);
if (isset($_POST['whitelistedPath']) && isset($_POST['whitelistedParam'])) {
$path = stripslashes($_POST['whitelistedPath']);
$paramKey = stripslashes($_POST['whitelistedParam']);
if (!$path || !$paramKey) {
'description' => __('Allowlisted via Firewall Options page', 'wordfence'),
'ip' => wfUtils::getIP(),
'disabled' => empty($_POST['whitelistedEnabled']),
if (function_exists('get_current_user_id')) {
$data['userID'] = get_current_user_id();
wfWAF::getInstance()->whitelistRuleForParam($path, $paramKey, 'all', $data);
!empty($_POST['oldWhitelistedPath']) && !empty($_POST['oldWhitelistedParam']) &&
!empty($_POST['newWhitelistedPath']) && !empty($_POST['newWhitelistedParam'])
$oldWhitelistedPath = stripslashes($_POST['oldWhitelistedPath']);
$oldWhitelistedParam = stripslashes($_POST['oldWhitelistedParam']);
$newWhitelistedPath = stripslashes($_POST['newWhitelistedPath']);
$newWhitelistedParam = stripslashes($_POST['newWhitelistedParam']);
$savedWhitelistedURLParams = (array) wfWAF::getInstance()->getStorageEngine()->getConfig('whitelistedURLParams', null, 'livewaf');
// These are already base64'd
$oldKey = $oldWhitelistedPath . '|' . $oldWhitelistedParam;
$newKey = base64_encode($newWhitelistedPath) . '|' . base64_encode($newWhitelistedParam);
$savedWhitelistedURLParams = wfUtils::arrayReplaceKey($savedWhitelistedURLParams, $oldKey, $newKey);
error_log("Caught exception from 'wfUtils::arrayReplaceKey' with message: " . $e->getMessage());
wfWAF::getInstance()->getStorageEngine()->setConfig('whitelistedURLParams', $savedWhitelistedURLParams, 'livewaf');
isset($_POST['deletedWhitelistedPath']) && is_string($_POST['deletedWhitelistedPath']) &&
isset($_POST['deletedWhitelistedParam']) && is_string($_POST['deletedWhitelistedParam'])
$deletedWhitelistedPath = stripslashes($_POST['deletedWhitelistedPath']);
$deletedWhitelistedParam = stripslashes($_POST['deletedWhitelistedParam']);
$savedWhitelistedURLParams = (array) wfWAF::getInstance()->getStorageEngine()->getConfig('whitelistedURLParams', null, 'livewaf');
$key = $deletedWhitelistedPath . '|' . $deletedWhitelistedParam;
unset($savedWhitelistedURLParams[$key]);
wfWAF::getInstance()->getStorageEngine()->setConfig('whitelistedURLParams', $savedWhitelistedURLParams, 'livewaf');
if (isset($_POST['whitelistedPath']) && isset($_POST['whitelistedParam'])) {
$path = stripslashes($_POST['whitelistedPath']);
$paramKey = stripslashes($_POST['whitelistedParam']);
if (!$path || !$paramKey) {
$enabled = !empty($_POST['whitelistedEnabled']);
$savedWhitelistedURLParams = (array) wfWAF::getInstance()->getStorageEngine()->getConfig('whitelistedURLParams', null, 'livewaf');
$key = $path . '|' . $paramKey;
if (array_key_exists($key, $savedWhitelistedURLParams) && is_array($savedWhitelistedURLParams[$key])) {
foreach ($savedWhitelistedURLParams[$key] as $ruleID => $data) {
$savedWhitelistedURLParams[$key][$ruleID]['disabled'] = !$enabled;
wfWAF::getInstance()->getStorageEngine()->setConfig('whitelistedURLParams', $savedWhitelistedURLParams, 'livewaf');
$ruleEnabled = !empty($_POST['ruleEnabled']);
$ruleID = !empty($_POST['ruleID']) ? (int) $_POST['ruleID'] : false;
$disabledRules = (array) wfWAF::getInstance()->getStorageEngine()->getConfig('disabledRules');
unset($disabledRules[$ruleID]);
$disabledRules[$ruleID] = true;
wfWAF::getInstance()->getStorageEngine()->setConfig('disabledRules', $disabledRules);
case 'disableWAFBlacklistBlocking':
if (isset($_POST['disableWAFBlacklistBlocking'])) {
$disableWAFBlacklistBlocking = (int) $_POST['disableWAFBlacklistBlocking'];
wfWAF::getInstance()->getStorageEngine()->setConfig('disableWAFBlacklistBlocking', $disableWAFBlacklistBlocking);
if (method_exists(wfWAF::getInstance()->getStorageEngine(), 'purgeIPBlocks')) {
wfWAF::getInstance()->getStorageEngine()->purgeIPBlocks(wfWAFStorageInterface::IP_BLOCKS_BLACKLIST);
'data' => self::_getWAFData(),
public static function ajax_updateWAFRules_callback() {
$event = new wfWAFCronFetchRulesEvent(time() - 2, true);
$event->setWaf(wfWAF::getInstance());
$success = $event->fire();
if (!$success && method_exists($event, 'getResponse')) {
$response = $event->getResponse();
if ($response === false) {
$failureReason = wfFirewall::UPDATE_FAILURE_UNREACHABLE;
$jsonData = @json_decode($response->getBody(), true);
if (isset($jsonData['errorMessage']) && strpos($jsonData['errorMessage'], 'rate limit') !== false) {
$failureReason = wfFirewall::UPDATE_FAILURE_RATELIMIT;
else if (isset($jsonData['data']['signature'])) {
$failureReason = wfFirewall::UPDATE_FAILURE_FILESYSTEM;
return self::_getWAFData($success, $failureReason);
'whitelistedURLParams' => array(),
'disabledRules' => array(),
'isPaid' => (bool) wfConfig::get('isPaid', 0),
public static function ajax_loadLiveTraffic_callback() {
$filters = new wfLiveTrafficQueryFilterCollection();
$query = new wfLiveTrafficQuery(self::getLog());
$query->setFilters($filters);
if (array_key_exists('groupby', $_REQUEST)) {
$param = $_REQUEST['groupby'];
$query->setGroupBy(new wfLiveTrafficQueryGroupBy($query, $param));
$query->setLimit(isset($_REQUEST['limit']) ? absint($_REQUEST['limit']) : 20);
$query->setOffset(isset($_REQUEST['offset']) ? absint($_REQUEST['offset']) : 0);
if (!empty($_REQUEST['since'])) {
$query->setStartDate($_REQUEST['since']);
} else if (!empty($_REQUEST['startDate'])) {
$query->setStartDate(is_numeric($_REQUEST['startDate']) ? $_REQUEST['startDate'] : strtotime($_REQUEST['startDate']));