: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
$content = self::_menu_tools_livetraffic();
$content = self::_menu_tools_whois();
$content = self::_menu_tools_diagnostics();
$content = self::_menu_tools_importexport();
if (wfCredentialsController::allowLegacy2FA()) {
$content = self::_menu_tools_twofactor();
$subpage = 'livetraffic';
$content = self::_menu_tools_livetraffic();
require(dirname(__FILE__) . '/menu_tools.php');
private static function _menu_tools_livetraffic() {
wp_enqueue_style('wordfence-jquery-ui-css', wfUtils::getBaseURL() . wfUtils::versionedAsset('css/jquery-ui.min.css'), array(), WORDFENCE_VERSION);
wp_enqueue_style('wordfence-jquery-ui-structure-css', wfUtils::getBaseURL() . wfUtils::versionedAsset('css/jquery-ui.structure.min.css'), array(), WORDFENCE_VERSION);
wp_enqueue_style('wordfence-jquery-ui-theme-css', wfUtils::getBaseURL() . wfUtils::versionedAsset('css/jquery-ui.theme.min.css'), array(), WORDFENCE_VERSION);
wp_enqueue_style('wordfence-jquery-ui-timepicker-css', wfUtils::getBaseURL() . wfUtils::versionedAsset('css/jquery-ui-timepicker-addon.css'), array(), WORDFENCE_VERSION);
wp_enqueue_script('wordfence-timepicker-js', wfUtils::getBaseURL() . wfUtils::versionedAsset('js/jquery-ui-timepicker-addon.js'), array('jquery', 'jquery-ui-datepicker', 'jquery-ui-slider'), WORDFENCE_VERSION);
wp_enqueue_script('wordfence-knockout-js', wfUtils::getBaseURL() . wfUtils::versionedAsset('js/knockout-3.5.1.js'), array(), WORDFENCE_VERSION);
wp_enqueue_script('wordfence-live-traffic-js', wfUtils::getBaseURL() . wfUtils::versionedAsset('js/admin.liveTraffic.js'), array('jquery', 'jquery-ui-tooltip'), WORDFENCE_VERSION);
require(dirname(__FILE__) . '/menu_tools_livetraffic.php');
$content = ob_get_clean();
private static function _menu_tools_whois() {
require(dirname(__FILE__) . '/menu_tools_whois.php');
$content = ob_get_clean();
private static function _menu_tools_diagnostics() {
require(dirname(__FILE__) . '/menu_tools_diagnostic.php');
$content = ob_get_clean();
private static function _menu_tools_importexport() {
require(dirname(__FILE__) . '/menu_tools_importExport.php');
$content = ob_get_clean();
private static function _menu_tools_twofactor() {
require(dirname(__FILE__) . '/menu_tools_twoFactor.php');
$content = ob_get_clean();
public static function menu_options() {
wp_enqueue_style('wordfence-jquery-ui-css', wfUtils::getBaseURL() . wfUtils::versionedAsset('css/jquery-ui.min.css'), array(), WORDFENCE_VERSION);
wp_enqueue_style('wordfence-jquery-ui-structure-css', wfUtils::getBaseURL() . wfUtils::versionedAsset('css/jquery-ui.structure.min.css'), array(), WORDFENCE_VERSION);
wp_enqueue_style('wordfence-jquery-ui-theme-css', wfUtils::getBaseURL() . wfUtils::versionedAsset('css/jquery-ui.theme.min.css'), array(), WORDFENCE_VERSION);
wp_enqueue_style('wordfence-jquery-ui-timepicker-css', wfUtils::getBaseURL() . wfUtils::versionedAsset('css/jquery-ui-timepicker-addon.css'), array(), WORDFENCE_VERSION);
wp_enqueue_style('wordfence-select2-css');
wp_enqueue_script('wordfence-timepicker-js', wfUtils::getBaseURL() . wfUtils::versionedAsset('js/jquery-ui-timepicker-addon.js'), array('jquery', 'jquery-ui-datepicker', 'jquery-ui-slider'), WORDFENCE_VERSION);
wp_enqueue_script('wordfence-select2-js');
$wafData = self::_getWAFData();
catch (wfWAFStorageFileConfigException $e) {
// We don't have anywhere to write files in this scenario. Let's notify the user to update the permissions.
'whitelistedURLParams' => array(),
'disabledRules' => array(),
'isPaid' => (bool) wfConfig::get('isPaid', 0),
$logPath = str_replace(ABSPATH, '~/', WFWAF_LOG_PATH);
if (function_exists('network_admin_url') && is_multisite()) {
$wafMenuURL = network_admin_url('admin.php?page=WordfenceWAF&wafconfigrebuild=1');
$wafMenuURL = admin_url('admin.php?page=WordfenceWAF&wafconfigrebuild=1');
$wafMenuURL = add_query_arg(array(
'waf-nonce' => wp_create_nonce('wafconfigrebuild'),
$storageExceptionMessage = $e->getMessage() . ' ' . sprintf(__('<a href="%s">Click here</a> to rebuild the configuration file.', 'wordfence'), esc_url($wafMenuURL));
} catch (wfWAFStorageFileException $e) {
// We don't have anywhere to write files in this scenario. Let's notify the user to update the permissions.
'whitelistedURLParams' => array(),
'disabledRules' => array(),
'isPaid' => (bool) wfConfig::get('isPaid', 0),
$logPath = str_replace(ABSPATH, '~/', WFWAF_LOG_PATH);
$storageExceptionMessage = sprintf(/* translators: File path. */ __('We were unable to write to %s which the WAF uses for storage. Please update permissions on the parent directory so the web server can write to it.', 'wordfence'), $logPath);
} catch (wfWAFStorageEngineMySQLiException $e) {
'whitelistedURLParams' => array(),
'disabledRules' => array(),
'isPaid' => (bool) wfConfig::get('isPaid', 0),
$storageExceptionMessage = __('An error occured when fetching the WAF configuration from the database.', 'wordfence') . ' <pre>' . esc_html($e->getMessage()) . '</pre>';
require(dirname(__FILE__) . '/menu_options.php');
public static function menu_blocking() {
// Do nothing -- this action is forwarded in admin_init
public static function menu_firewall() {
wp_enqueue_style('wordfence-jquery-ui-css', wfUtils::getBaseURL() . wfUtils::versionedAsset('css/jquery-ui.min.css'), array(), WORDFENCE_VERSION);
wp_enqueue_style('wordfence-jquery-ui-structure-css', wfUtils::getBaseURL() . wfUtils::versionedAsset('css/jquery-ui.structure.min.css'), array(), WORDFENCE_VERSION);
wp_enqueue_style('wordfence-jquery-ui-theme-css', wfUtils::getBaseURL() . wfUtils::versionedAsset('css/jquery-ui.theme.min.css'), array(), WORDFENCE_VERSION);
wp_enqueue_style('wordfence-jquery-ui-timepicker-css', wfUtils::getBaseURL() . wfUtils::versionedAsset('css/jquery-ui-timepicker-addon.css'), array(), WORDFENCE_VERSION);
wp_enqueue_style('wordfence-select2-css');
wp_enqueue_script('wordfence-timepicker-js', wfUtils::getBaseURL() . wfUtils::versionedAsset('js/jquery-ui-timepicker-addon.js'), array('jquery', 'jquery-ui-datepicker', 'jquery-ui-slider'), WORDFENCE_VERSION);
wp_enqueue_script('wordfence-select2-js');
wp_enqueue_script('chart-js');
$wafData = self::_getWAFData();
} catch (wfWAFStorageFileConfigException $e) {
// We don't have anywhere to write files in this scenario. Let's notify the user to update the permissions.
'whitelistedURLParams' => array(),
'disabledRules' => array(),
'isPaid' => (bool) wfConfig::get('isPaid', 0),
$logPath = str_replace(ABSPATH, '~/', WFWAF_LOG_PATH);
if (function_exists('network_admin_url') && is_multisite()) {
$wafMenuURL = network_admin_url('admin.php?page=WordfenceWAF&wafconfigrebuild=1');
$wafMenuURL = admin_url('admin.php?page=WordfenceWAF&wafconfigrebuild=1');
$wafMenuURL = add_query_arg(array(
'waf-nonce' => wp_create_nonce('wafconfigrebuild'),
$storageExceptionMessage = $e->getMessage() . ' ' . sprintf(/* translators: WordPress admin panel URL. */ __('<a href="%s">Click here</a> to rebuild the configuration file.', 'wordfence'), esc_url($wafMenuURL));
} catch (wfWAFStorageFileException $e) {
// We don't have anywhere to write files in this scenario. Let's notify the user to update the permissions.
'whitelistedURLParams' => array(),
'disabledRules' => array(),
'isPaid' => (bool) wfConfig::get('isPaid', 0),
$logPath = str_replace(ABSPATH, '~/', WFWAF_LOG_PATH);
$storageExceptionMessage = sprintf(/* translators: File path. */ __('We were unable to write to %s which the WAF uses for storage. Please update permissions on the parent directory so the web server can write to it.', 'wordfence'), $logPath);
} catch (wfWAFStorageEngineMySQLiException $e) {
'whitelistedURLParams' => array(),
'disabledRules' => array(),
'isPaid' => (bool) wfConfig::get('isPaid', 0),
$storageExceptionMessage = __('An error occured when fetching the WAF configuration from the database.', 'wordfence') . ' <pre>' . esc_html($e->getMessage()) . '</pre>';
if (isset($_GET['subpage']) && $_GET['subpage'] == 'waf_options') {
require(dirname(__FILE__) . '/menu_firewall_waf_options.php');
else if (isset($_GET['subpage']) && $_GET['subpage'] == 'blocking_options') {
require(dirname(__FILE__) . '/menu_firewall_blocking_options.php');
require(dirname(__FILE__) . '/menu_firewall.php');
public static function liveTrafficW3TCWarning() {
echo self::cachingWarning("W3 Total Cache");
public static function liveTrafficSuperCacheWarning(){
echo self::cachingWarning("WP Super Cache");
public static function cachingWarning($plugin){
return '<div id="wordfenceConfigWarning" class="error fade"><p><strong>' .
sprintf(/* translators: Plugin name. */ __('The Wordfence Live Traffic feature has been disabled because you have %s active which is not compatible with Wordfence Live Traffic.', 'wordfence'), $plugin)
sprintf(/* translators: 1. Plugin name. */ __('If you want to reenable Wordfence Live Traffic, you need to deactivate %1$s and then go to the Wordfence options page and reenable Live Traffic there. Wordfence does work with %1$s, however Live Traffic will be disabled and the Wordfence firewall will also count less hits per visitor because of the %1$s caching function. All other functions should work correctly.', 'wordfence'), $plugin)
public static function menu_dashboard() {
wp_enqueue_style('wordfence-select2-css');
wp_enqueue_script('wordfence-select2-js');
wp_enqueue_script('chart-js');
if (wfConfig::get('keyType') == wfLicense::KEY_TYPE_PAID_EXPIRED || (wfConfig::get('keyType') == wfLicense::KEY_TYPE_PAID_CURRENT && wfConfig::get('keyExpDays') < 30)) {
$api = new wfAPI(wfConfig::get('apiKey', ''), wfUtils::getWPVersion());
$api->call('check_api_key', array(), array(), false, 2);
if (isset($_GET['subpage']) && $_GET['subpage'] == 'global_options') {
require(dirname(__FILE__) . '/menu_dashboard_options.php');
require(dirname(__FILE__) . '/menu_dashboard.php');
public static function menu_scan() {
wp_enqueue_style('wordfence-select2-css');
wp_enqueue_script('wordfence-select2-js');
if (isset($_GET['subpage']) && $_GET['subpage'] == 'scan_options') {
require(dirname(__FILE__) . '/menu_scanner_options.php');
else if (isset($_GET['subpage']) && $_GET['subpage'] == 'scan_credentials') {
require(dirname(__FILE__) . '/menu_scanner_credentials.php');
require(dirname(__FILE__) . '/menu_scanner.php');
public static function menu_support() {
wp_enqueue_style('wordfence-select2-css');
wp_enqueue_script('wordfence-select2-js');
require(dirname(__FILE__) . '/menu_support.php');
public static function menu_wordfence_central() {
wfConfig::set('showWfCentralUI', 1);
wp_enqueue_style('wordfence-select2-css');
wp_enqueue_script('wordfence-select2-js');
require(dirname(__FILE__) . '/menu_wordfence_central.php');
public static function menu_install() {
$token = array_key_exists('token', $_GET) ? $_GET['token'] : null;
$payload = array_key_exists('payload', $_GET) ? $_GET['payload'] : null;
$payloadException = null;
if ($shouldShowOnboarding = wfOnboardingController::shouldShowAnyAttempt()) {
if (!empty($token) && !empty($payload)) {
if (wfLicense::validateRegistrationToken($token)) {
$wfWebsite = wfWebsite::getInstance();
$data = $wfWebsite->retrievePayload($payload, $expiredPayload);
$data = json_decode($data, true);
if (is_array($data) && array_key_exists('email', $data) && array_key_exists('license', $data)) {
$email = (string) $data['email'];
$license = (string) $data['license'];
catch (wfWebsiteEphemeralPayloadRetrievalException $e) {
require(__DIR__ . '/menu_install.php');
public static function fsActionRestoreFileCallback() {
$issueID = filter_input(INPUT_GET, 'issueID', FILTER_SANITIZE_NUMBER_INT);
$response = self::ajax_restoreFile_callback($issueID);
if (!empty($response['ok'])) {
$result = sprintf('<p>' . /* translators: File path. */ __('The file <code>%s</code> was restored successfully.', 'wordfence') . '</p>',
esc_html(strpos($response['file'], ABSPATH) === 0 ? substr($response['file'], strlen(ABSPATH) + 1) : $response['file']));
} else if (!empty($response['cerrorMessage'])) {
$result = sprintf('<div class="wfSummaryErr">%s</div>', esc_html($response['cerrorMessage']));
$result = '<div class="wfSummaryErr">' . __('There was an error restoring the file.', 'wordfence') . '</div>';
<p><a href="%s">%s</a></p>
esc_url(network_admin_url('admin.php?page=WordfenceScan')),
__('Return to scan results', 'wordfence')
wfScanEngine::refreshScanNotification();
public static function fsActionDeleteFileCallback() {
$issueID = filter_input(INPUT_GET, 'issueID', FILTER_SANITIZE_NUMBER_INT);
$response = self::ajax_deleteFile_callback($issueID);
if (!empty($response['ok'])) {
$result = sprintf('<p>' . /* translators: File path. */ __('The file <code>%s</code> was deleted successfully.', 'wordfence') . '</p>', esc_html($response['file']));
} else if (!empty($response['errorMessage'])) {
$result = sprintf('<div class="wfSummaryErr">%s</div>', esc_html($response['errorMessage']));
$result = '<div class="wfSummaryErr">' . __('There was an error deleting the file.', 'wordfence') . '</div>';
<p><a href="%s">%s</a></p>
esc_url(network_admin_url('admin.php?page=WordfenceScan')),
__('Return to scan results', 'wordfence')
wfScanEngine::refreshScanNotification();
public static function status($level /* 1 has highest visibility */, $type /* info|error */, $msg){
if($level > 3 && $level < 10 && (! self::isDebugOn())){ //level 10 and higher is for summary messages
if($type != 'info' && $type != 'error'){ error_log("Invalid status type: $type"); return; }
echo "STATUS: $level : $type : ".esc_html($msg)."\n";
self::getLog()->addStatus($level, $type, $msg);
public static function profileUpdateAction($userID, $newDat = false){
if(wfConfig::get('other_pwStrengthOnUpdate')){
$oldDat = get_userdata($userID);
if($newDat->user_pass != $oldDat->user_pass){
$wf = new wfScanEngine();
$wf->scanUserPassword($userID);
public static function replaceVersion($url) {
return preg_replace_callback("/([&;\?]ver)=(.+?)(&|$)/", "wordfence::replaceVersionCallback", $url);
public static function replaceVersionCallback($matches) {
return $matches[1] . '=' . ($wp_version === $matches[2] ? wp_hash($matches[2]) : $matches[2]) . $matches[3];
public static function genFilter($gen, $type){
if(wfConfig::get('other_hideWPVersion')){
public static function getMyHomeURL(){
return wfUtils::wpAdminURL('admin.php?page=Wordfence');
public static function getMyOptionsURL(){
return wfUtils::wpAdminURL('admin.php?page=Wordfence&subpage=global_options');
public static function alert($subject, $alertMsg, $IP) {
wfConfig::inc('totalAlertsSent');
$emails = wfConfig::getAlertEmails();
if (sizeof($emails) < 1) { return false; }
$IPMsg = sprintf(/* translators: IP address. */ __("User IP: %s\n", 'wordfence'), $IP);
$reverse = wfUtils::reverseLookup($IP);
$IPMsg .= sprintf(/* translators: Domain name. */ __("User hostname: %s\n", 'wordfence'), $reverse);
$userLoc = wfUtils::getIPGeo($IP);
$IPMsg .= __('User location: ', 'wordfence');
$IPMsg .= $userLoc['city'] . ', ';
if ($userLoc['region'] && wfUtils::shouldDisplayRegion($userLoc['countryName'])) {
$IPMsg .= $userLoc['region'] . ', ';
$IPMsg .= $userLoc['countryName'] . "\n";
$content = wfUtils::tmpl('email_genericAlert.php', array(
'isPaid' => wfConfig::get('isPaid'),
'blogName' => get_bloginfo('name', 'raw'),
'adminURL' => get_admin_url(),
'date' => wfUtils::localHumanDate(),
'myHomeURL' => self::getMyHomeURL(),
'myOptionsURL' => self::getMyOptionsURL()
$shortSiteURL = preg_replace('/^https?:\/\//i', '', site_url());
$subject = "[Wordfence Alert] $shortSiteURL " . $subject;
$sendMax = wfConfig::get('alert_maxHourly', 0);
$sendArr = wfConfig::get_ser('alertFreqTrack', array());
if(! is_array($sendArr)){
$minuteTime = floor(time() / 60);
for($i = $minuteTime; $i > $minuteTime - 60; $i--){
$totalSent += isset($sendArr[$i]) ? $sendArr[$i] : 0;
if($totalSent >= $sendMax){
$sendArr[$minuteTime] = isset($sendArr[$minuteTime]) ? $sendArr[$minuteTime] + 1 : 1;
wfConfig::set_ser('alertFreqTrack', $sendArr);
//Prevent duplicate emails within 1 hour:
$hash = md5(implode(',', $emails) . ':' . $subject . ':' . $alertMsg . ':' . $IP); //Hex
$lastHash = wfConfig::get('lastEmailHash', false);
$lastHashDat = explode(':', $lastHash); //[time, hash]
if(time() - $lastHashDat[0] < 3600){
if($lastHashDat[1] == $hash){
return false; //Don't send because this email is identical to the previous email which was sent within the last hour.
wfConfig::set('lastEmailHash', time() . ':' . $hash);
foreach ($emails as $email) {
$uniqueContent = $content . "\n\n" . sprintf(/* translators: WordPress admin panel URL. */ __('No longer an administrator for this site? Click here to stop receiving security alerts: %s', 'wordfence'), wfUtils::getSiteBaseURL() . '?_wfsf=removeAlertEmail&jwt=' . wfUtils::generateJWT(array('email' => $email)));
wp_mail($email, $subject, $uniqueContent);
public static function getLog(){
$wfLog = wfLog::shared();
public static function wfSchemaExists(){
$exists = $wpdb->get_col($wpdb->prepare(<<<SQL
SELECT TABLE_NAME FROM information_schema.TABLES
WHERE TABLE_SCHEMA=DATABASE()
, wfDB::networkTable('wfConfig')));
return $exists ? true : false;
public static function isDebugOn(){
if(is_null(self::$debugOn)){
if(wfConfig::get('debugOn')){