: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
if (!empty($_REQUEST['endDate'])) {
$query->setEndDate(is_numeric($_REQUEST['endDate']) ? $_REQUEST['endDate'] : strtotime($_REQUEST['endDate']));
array_key_exists('param', $_REQUEST) && is_array($_REQUEST['param']) &&
array_key_exists('operator', $_REQUEST) && is_array($_REQUEST['operator']) &&
array_key_exists('value', $_REQUEST) && is_array($_REQUEST['value'])
for ($i = 0; $i < count($_REQUEST['param']); $i++) {
array_key_exists($i, $_REQUEST['param']) &&
array_key_exists($i, $_REQUEST['operator']) &&
array_key_exists($i, $_REQUEST['value'])
$param = $_REQUEST['param'][$i];
$operator = $_REQUEST['operator'][$i];
$value = $_REQUEST['value'][$i];
switch (strtolower($param)) {
$value = strtolower($value) === 'human' ? 1 : 0;
if (strpos($ip, '*') !== false) { //If the IP contains a *, treat it as a wildcard for that segment and silently adjust the rule
if (preg_match('/^(?:(?:\d{1,3}|\*)(?:\.|$)){2,4}/', $ip)) { //IPv4
$value = array('00', '00', '00', '00', '00', '00', '00', '00', '00', '00', 'FF', 'FF');
$octets = explode('.', $ip);
if (strpos($o, '*') !== false) {
$value[] = strtoupper(str_pad(dechex($o), 2, '0', STR_PAD_LEFT));
$value = '^' . implode('', array_pad($value, 16, '..')) . '$';
$operator = ($operator == '!=' ? 'hnotregexp' : 'hregexp');
else if (!empty($ip) && preg_match('/^((?:[\da-f*]{1,4}(?::|)){0,8})(::)?((?:[\da-f*]{1,4}(?::|)){0,8})$/i', $ip)) { //IPv6
$value = '^' . str_repeat('00', 16) . '$';
$colon_count = substr_count($ip, ':');
$dbl_colon_pos = strpos($ip, '::');
if ($dbl_colon_pos !== false) {
$ip = str_replace('::', str_repeat(':0000', (($dbl_colon_pos === 0 || $dbl_colon_pos === strlen($ip) - 2) ? 9 : 8) - $colon_count) . ':', $ip);
$ip_groups = explode(':', $ip);
foreach ($ip_groups as $ip_group) {
if (strpos($ip_group, '*') !== false) {
$ip_group = strtoupper(str_pad($ip_group, 4, '0', STR_PAD_LEFT));
$value[] = substr($ip_group, 0, 2);
$value[] = substr($ip_group, -2);
$value = '^' . implode('', array_pad($value, 16, '..')) . '$';
$operator = ($operator == '=' ? 'hregexp' : 'hnotregexp');
else if (preg_match('/^((?:0{1,4}(?::|)){0,5})(::)?ffff:((?:\d{1,3}(?:\.|$)){4})$/i', $ip, $matches)) { //IPv4 mapped IPv6
$value = array('00', '00', '00', '00', '00', '00', '00', '00', '00', '00', 'FF', 'FF');
$octets = explode('.', $matches[3]);
if (strpos($o, '*') !== false) {
$value[] = strtoupper(str_pad(dechex($o), 2, '0', STR_PAD_LEFT));
$value = '^' . implode('', array_pad($value, 16, '.')) . '$';
$operator = ($operator == '=' ? 'hregexp' : 'hnotregexp');
$value = wfUtils::inet_pton($ip);
if ($operator === 'match' && $param !== 'ip') {
$value = str_replace('*', '%', $value);
$filters->addFilter(new wfLiveTrafficQueryFilter($query, $param, $operator, $value));
$return['data'] = $query->execute();
/*if (defined('WP_DEBUG') && WP_DEBUG) {
$return['sql'] = $query->buildQuery();
} catch (wfLiveTrafficQueryException $e) {
$return['data'] = array();
$return['sql'] = $e->getMessage();
$return['success'] = true;
public static function ajax_whitelistWAFParamKey_callback() {
if (class_exists('wfWAF') && $waf = wfWAF::getInstance()) {
if (isset($_POST['path']) && isset($_POST['paramKey']) && isset($_POST['failedRules'])) {
'description' => __('Allowlisted via Live Traffic', 'wordfence'),
'source' => 'live-traffic',
'ip' => wfUtils::getIP(),
if (function_exists('get_current_user_id')) {
$data['userID'] = get_current_user_id();
$waf->whitelistRuleForParam(base64_decode($_POST['path']), base64_decode($_POST['paramKey']),
$_POST['failedRules'], $data);
public static function ajax_whitelistBulkDelete_callback() {
if (class_exists('wfWAF') && $waf = wfWAF::getInstance()) {
if (!empty($_POST['items']) && ($items = json_decode(stripslashes($_POST['items']), true)) !== false) {
$whitelist = (array) $waf->getStorageEngine()->getConfig('whitelistedURLParams', null, 'livewaf');
if (!is_array($whitelist)) {
foreach ($items as $key) {
list($path, $paramKey, ) = $key;
$whitelistKey = $path . '|' . $paramKey;
if (array_key_exists($whitelistKey, $whitelist)) {
unset($whitelist[$whitelistKey]);
$waf->getStorageEngine()->setConfig('whitelistedURLParams', $whitelist, 'livewaf');
'data' => self::_getWAFData(),
public static function ajax_whitelistBulkEnable_callback() {
if (class_exists('wfWAF') && $waf = wfWAF::getInstance()) {
if (!empty($_POST['items']) && ($items = json_decode(stripslashes($_POST['items']), true)) !== false) {
self::_whitelistBulkToggle($items, true);
'data' => self::_getWAFData(),
public static function ajax_whitelistBulkDisable_callback() {
if (class_exists('wfWAF') && $waf = wfWAF::getInstance()) {
if (!empty($_POST['items']) && ($items = json_decode(stripslashes($_POST['items']), true)) !== false) {
self::_whitelistBulkToggle($items, false);
'data' => self::_getWAFData(),
private static function _whitelistBulkToggle($items, $enabled) {
$waf = wfWAF::getInstance();
$whitelist = (array) $waf->getStorageEngine()->getConfig('whitelistedURLParams', null, 'livewaf');
if (!is_array($whitelist)) {
foreach ($items as $key) {
list($path, $paramKey, ) = $key;
$whitelistKey = $path . '|' . $paramKey;
if (array_key_exists($whitelistKey, $whitelist) && is_array($whitelist[$whitelistKey])) {
foreach ($whitelist[$whitelistKey] as $ruleID => $data) {
$whitelist[$whitelistKey][$ruleID]['disabled'] = !$enabled;
$waf->getStorageEngine()->setConfig('whitelistedURLParams', $whitelist, 'livewaf');
private static function _getWAFData($updated = null, $failureReason = false) {
$data['learningMode'] = wfWAF::getInstance()->isInLearningMode();
$data['rules'] = wfWAF::getInstance()->getRules();
/** @var wfWAFRule $rule */
foreach ($data['rules'] as $ruleID => $rule) {
$data['rules'][$ruleID] = $rule->toArray();
$whitelistedURLParams = (array) wfWAF::getInstance()->getStorageEngine()->getConfig('whitelistedURLParams', array(), 'livewaf');
$data['whitelistedURLParams'] = array();
if (is_array($whitelistedURLParams)) {
foreach ($whitelistedURLParams as $urlParamKey => $rules) {
list($path, $paramKey) = explode('|', $urlParamKey);
foreach ($rules as $ruleID => $whitelistedData) {
if ($whitelistData === null) {
$whitelistData = $whitelistedData;
$whitelistData = $whitelistedData;
if (is_array($whitelistData) && array_key_exists('userID', $whitelistData) && function_exists('get_user_by')) {
$user = get_user_by('id', $whitelistData['userID']);
$whitelistData['username'] = $user->user_login;
$data['whitelistedURLParams'][] = array(
'ruleID' => array_keys($rules),
'data' => $whitelistData,
$data['disabledRules'] = (array) wfWAF::getInstance()->getStorageEngine()->getConfig('disabledRules');
if ($lastUpdated = wfWAF::getInstance()->getStorageEngine()->getConfig('rulesLastUpdated', null, 'transient')) {
$data['rulesLastUpdated'] = $lastUpdated;
$data['isPaid'] = (bool) wfConfig::get('isPaid', 0);
$data['updated'] = (bool) $updated;
$data['failure'] = $failureReason;
public static function ajax_wafStatus_callback() {
if (!empty($_REQUEST['nonce']) && hash_equals($_REQUEST['nonce'], wfConfig::get('wafStatusCallbackNonce', ''))) {
wfConfig::set('wafStatusCallbackNonce', '');
wfUtils::send_json(array('active' => WFWAF_AUTO_PREPEND, 'subdirectory' => WFWAF_SUBDIRECTORY_INSTALL));
wfUtils::send_json(false);
public static function ajax_installAutoPrepend_callback() {
$currentAutoPrependFile = ini_get('auto_prepend_file');
$currentAutoPrepend = null;
if (isset($_POST['currentAutoPrepend']) && !WF_IS_WP_ENGINE && !WF_IS_PRESSABLE && !WF_IS_FLYWHEEL) {
$currentAutoPrepend = $_POST['currentAutoPrepend'];
$serverConfiguration = null;
if (isset($_POST['serverConfiguration']) && wfWAFAutoPrependHelper::isValidServerConfig($_POST['serverConfiguration'])) {
$serverConfiguration = $_POST['serverConfiguration'];
if ($serverConfiguration === null) {
return array('errorMsg' => __('A valid server configuration was not provided.', 'wordfence'));
$helper = new wfWAFAutoPrependHelper($serverConfiguration, $currentAutoPrepend === 'override' ? null : $currentAutoPrependFile);
$ajaxURL = admin_url('admin-ajax.php');
$allow_relaxed_file_ownership = true;
if (false === ($credentials = request_filesystem_credentials($ajaxURL, '', false, ABSPATH, array('version', 'locale', 'action', 'serverConfiguration', 'currentAutoPrepend'), $allow_relaxed_file_ownership))) {
$credentialsContent = ob_get_clean();
$html = wfView::create('waf/waf-modal-wrapper', array(
'title' => __('Filesystem Credentials Required', 'wordfence'),
'html' => $credentialsContent,
'helpHTML' => wp_kses(sprintf(/* translators: Support URL. */ __('If you cannot complete the setup process, <a target="_blank" rel="noopener noreferrer" href="%s">click here for help<span class="screen-reader-text"> (opens in new tab)</span></a>', 'wordfence'), wfSupportController::esc_supportURL(wfSupportController::ITEM_FIREWALL_WAF_INSTALL_MANUALLY)), array('a' => array('href' => array(), 'target' => array(), 'rel' => array()), 'span' => array('class' => array()))),
'footerHTML' => esc_html__('Once you have entered credentials, click Continue to complete the setup.', 'wordfence'),
return array('needsCredentials' => 1, 'html' => $html);
if (!WP_Filesystem($credentials, ABSPATH, $allow_relaxed_file_ownership) && $wp_filesystem->errors->get_error_code()) {
foreach ($wp_filesystem->errors->get_error_messages() as $message) {
if (is_wp_error($message)) {
if ($message->get_error_data() && is_string($message->get_error_data())) {
$message = $message->get_error_message() . ': ' . $message->get_error_data();
$message = $message->get_error_message();
$credentialsError .= "<p>$message</p>\n";
$html = wfView::create('waf/waf-modal-wrapper', array(
'title' => __('Filesystem Permission Error', 'wordfence'),
'html' => $credentialsError,
'helpHTML' => wp_kses(sprintf(/* translators: Support URL. */ __('If you cannot complete the setup process, <a target="_blank" rel="noopener noreferrer" href="%s">click here for help<span class="screen-reader-text"> (opens in new tab)</span></a>', 'wordfence'), wfSupportController::esc_supportURL(wfSupportController::ITEM_FIREWALL_WAF_INSTALL_MANUALLY)), array('a' => array('href' => array(), 'target' => array(), 'rel' => array()), 'span' => array('class' => array()))),
'footerButtonTitle' => __('Cancel', 'wordfence'),
return array('credentialsFailed' => 1, 'html' => $html);
$helper->performInstallation($wp_filesystem);
$nonce = bin2hex(wfWAFUtils::random_bytes(32));
wfConfig::set('wafStatusCallbackNonce', $nonce);
$verifyURL = add_query_arg(array('action' => 'wordfence_wafStatus', 'nonce' => $nonce), $ajaxURL);
$response = wp_remote_get($verifyURL, array('headers' => array('Referer' => false/*, 'Cookie' => 'XDEBUG_SESSION=1'*/)));
if (!is_wp_error($response)) {
$wafStatus = @json_decode(wp_remote_retrieve_body($response), true);
if (isset($wafStatus['active']) && isset($wafStatus['subdirectory'])) {
$active = $wafStatus['active'] && !$wafStatus['subdirectory'];
if ($serverConfiguration == 'manual') {
$html = wfView::create('waf/waf-modal-wrapper', array(
'title' => __('Manual Installation Instructions', 'wordfence'),
'html' => wfView::create('waf/waf-install-manual')->render(),
'footerButtonTitle' => __('Close', 'wordfence'),
$html = wfView::create('waf/waf-modal-wrapper', array(
'title' => __('Installation Successful', 'wordfence'),
'html' => wfView::create('waf/waf-install-success', array('active' => $active))->render(),
'footerButtonTitle' => __('Close', 'wordfence'),
return array('ok' => 1, 'html' => $html);
catch (wfWAFAutoPrependHelperException $e) {
$installError = "<p>" . $e->getMessage() . "</p>";
$html = wfView::create('waf/waf-modal-wrapper', array(
'title' => __('Installation Failed', 'wordfence'),
'helpHTML' => wp_kses(sprintf(/* translators: Support URL. */ __('If you cannot complete the setup process, <a target="_blank" rel="noopener noreferrer" href="%s">click here for help<span class="screen-reader-text"> (opens in new tab)</span></a>', 'wordfence'), wfSupportController::esc_supportURL(wfSupportController::ITEM_FIREWALL_WAF_INSTALL_MANUALLY)), array('a' => array('href' => array(), 'target' => array(), 'rel' => array()), 'span' => array('class' => array()))),
'footerButtonTitle' => __('Cancel', 'wordfence'),
return array('installationFailed' => 1, 'html' => $html);
public static function ajax_uninstallAutoPrepend_callback() {
$serverConfiguration = null;
if (isset($_POST['serverConfiguration']) && wfWAFAutoPrependHelper::isValidServerConfig($_POST['serverConfiguration'])) {
$serverConfiguration = $_POST['serverConfiguration'];
if ($serverConfiguration === null) {
return array('errorMsg' => __('A valid server configuration was not provided.', 'wordfence'));
$helper = new wfWAFAutoPrependHelper($serverConfiguration, null);
if (isset($_POST['credentials']) && isset($_POST['credentialsSignature'])) {
$salt = wp_salt('logged_in');
$expectedSignature = hash_hmac('sha256', $_POST['credentials'], $salt);
if (hash_equals($expectedSignature, $_POST['credentialsSignature'])) {
$decrypted = wfUtils::decrypt($_POST['credentials']);
$credentials = @json_decode($decrypted, true);
$ajaxURL = admin_url('admin-ajax.php');
if (!isset($credentials)) {
$allow_relaxed_file_ownership = true;
if (false === ($credentials = request_filesystem_credentials($ajaxURL, '', false, ABSPATH, array('version', 'locale', 'action', 'serverConfiguration', 'iniModified'), $allow_relaxed_file_ownership))) {
$credentialsContent = ob_get_clean();
$html = wfView::create('waf/waf-modal-wrapper', array(
'title' => __('Filesystem Credentials Required', 'wordfence'),
'html' => $credentialsContent,
'helpHTML' => wp_kses(sprintf(/* translators: Support URL. */ __('If you cannot complete the uninstall process, <a target="_blank" rel="noopener noreferrer" href="%s">click here for help<span class="screen-reader-text"> (opens in new tab)</span></a>', 'wordfence'), wfSupportController::esc_supportURL(wfSupportController::ITEM_FIREWALL_WAF_REMOVE_MANUALLY)), array('a' => array('href' => array(), 'target' => array(), 'rel' => array()), 'span' => array('class' => array()))),
'footerHTML' => esc_html__('Once you have entered credentials, click Continue to complete uninstallation.', 'wordfence'),
return array('needsCredentials' => 1, 'html' => $html);
if (!WP_Filesystem($credentials, ABSPATH, $allow_relaxed_file_ownership) && $wp_filesystem->errors->get_error_code()) {
foreach ($wp_filesystem->errors->get_error_messages() as $message) {
if (is_wp_error($message)) {
if ($message->get_error_data() && is_string($message->get_error_data())) {
$message = $message->get_error_message() . ': ' . $message->get_error_data();
$message = $message->get_error_message();
$credentialsError .= "<p>$message</p>\n";
$html = wfView::create('waf/waf-modal-wrapper', array(
'title' => __('Filesystem Permission Error', 'wordfence'),
'html' => $credentialsError,
'helpHTML' => wp_kses(sprintf(/* translators: Support URL. */ __('If you cannot complete the uninstall process, <a target="_blank" rel="noopener noreferrer" href="%s">click here for help<span class="screen-reader-text"> (opens in new tab)</span></a>', 'wordfence'), wfSupportController::esc_supportURL(wfSupportController::ITEM_FIREWALL_WAF_REMOVE_MANUALLY)), array('a' => array('href' => array(), 'target' => array(), 'rel' => array()), 'span' => array('class' => array()))),
'footerButtonTitle' => __('Cancel', 'wordfence'),
return array('credentialsFailed' => 1, 'html' => $html);
if ((!isset($_POST['iniModified']) || (isset($_POST['iniModified']) && !$_POST['iniModified'])) && !WF_IS_PRESSABLE) { //Uses .user.ini but not yet modified
$hasPreviousAutoPrepend = $helper->performIniRemoval($wp_filesystem);
$iniTTL = intval(ini_get('user_ini.cache_ttl'));
$iniTTL = 300; //The PHP default
if (!$helper->usesUserIni()) {
$timeout = max(30, $iniTTL);
$timeoutString = wfUtils::makeDuration($timeout);
$waitingResponse = '<p>' . __('The <code>auto_prepend_file</code> setting has been successfully removed from <code>.htaccess</code> and <code>.user.ini</code>. Once this change takes effect, Extended Protection Mode will be disabled.', 'wordfence') . '</p>';
if ($hasPreviousAutoPrepend) {
$waitingResponse .= '<p>' . __('Any previous value for <code>auto_prepend_file</code> will need to be re-enabled manually if still needed.', 'wordfence') . '</p>';
$spinner = wfView::create('common/indeterminate-progress', array('size' => 32))->render();
$waitingResponse .= '<ul class="wf-flex-horizontal"><li>' . $spinner . '</li><li class="wf-padding-add-left">' . sprintf(/* translators: Time until. */ __('Waiting for it to take effect. This may take up to %s.', 'wordfence'), $timeoutString) . '</li></ul>';
$html = wfView::create('waf/waf-modal-wrapper', array(
'title' => __('Waiting for Changes', 'wordfence'),
'html' => $waitingResponse,
'helpHTML' => wp_kses(sprintf(/* translators: Support URL. */ __('If you cannot complete the uninstall process, <a target="_blank" rel="noopener noreferrer" href="%s">click here for help<span class="screen-reader-text"> (opens in new tab)</span></a>', 'wordfence'), wfSupportController::esc_supportURL(wfSupportController::ITEM_FIREWALL_WAF_REMOVE_MANUALLY)), array('a' => array('href' => array(), 'target' => array(), 'rel' => array()), 'span' => array('class' => array()))),
'footerButtonTitle' => __('Close', 'wordfence'),
$response = array('uninstallationWaiting' => 1, 'html' => $html, 'timeout' => $timeout, 'serverConfiguration' => $_POST['serverConfiguration']);
if (isset($credentials) && is_array($credentials)) {
$salt = wp_salt('logged_in');
$json = json_encode($credentials);
$encrypted = wfUtils::encrypt($json);
$signature = hash_hmac('sha256', $encrypted, $salt);
$response['credentials'] = $encrypted;
$response['credentialsSignature'] = $signature;
else { //.user.ini and .htaccess modified if applicable and waiting period elapsed or otherwise ready to advance to next step
if (WFWAF_AUTO_PREPEND && !WFWAF_SUBDIRECTORY_INSTALL && !WF_IS_WP_ENGINE && !WF_IS_PRESSABLE) { //.user.ini modified, but the WAF is still enabled
$retryAttempted = (isset($_POST['retryAttempted']) && $_POST['retryAttempted']);
$userIniError = '<p class="wf-error">';
$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');
$userIniError .= ' <strong>' . __('Retrying Failed.', 'wordfence') . '</strong>';
$userIniError .= ' <a href="#" class="wf-waf-uninstall-try-again" role="button">' . __('Try Again', 'wordfence') . '</a>';
$html = wfView::create('waf/waf-modal-wrapper', array(
'title' => __('Unable to Uninstall', 'wordfence'),
'helpHTML' => wp_kses(sprintf(/* translators: Support URL. */ __('If you cannot complete the uninstall process, <a target="_blank" rel="noopener noreferrer" href="%s">click here for help<span class="screen-reader-text"> (opens in new tab)</span></a>', 'wordfence'), wfSupportController::esc_supportURL(wfSupportController::ITEM_FIREWALL_WAF_REMOVE_MANUALLY)), array('a' => array('href' => array(), 'target' => array(), 'rel' => array()), 'span' => array('class' => array()))),
'footerButtonTitle' => __('Cancel', 'wordfence'),