: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
return array('ok' => 1, 'data' => $data);
else if ($grouping == 'logins') {
if ($period == 'success') { $data = $dashboard->loginsSuccess; }
else if ($period == 'fail') { $data = $dashboard->loginsFail; }
$data = array_slice($data, 0, 100);
$d['ip'] = esc_html($d['ip']);
$d['name'] = esc_html($d['name']);
if (time() - $d['t'] < 86400) {
$d['t'] = esc_html(wfUtils::makeTimeAgo(time() - $d['t']) . ' ago');
$d['t'] = esc_html(wfUtils::formatLocalTime(get_option('date_format') . ' ' . get_option('time_format'), (int) $d['t']));
return array('ok' => 1, 'data' => $data);
return array('error' => __('Unknown dashboard data set.', 'wordfence'));
public static function startScan(){
wfScanEngine::startScan();
public static function templateRedir(){
if (!empty($_GET['wordfence_lh'])) {
self::ajax_lh_callback();
if (!empty($_GET['wfcentral_admin_redirect'])) {
wp_safe_redirect(remove_query_arg('wfcentral_admin_redirect', network_admin_url('admin.php?page=Wordfence' . rawurlencode(ucwords(preg_replace('/\W/', '', $_GET['wfcentral_admin_redirect']))) . '&' . $_SERVER['QUERY_STRING'])));
$wfFunc = !empty($_GET['_wfsf']) && is_string($_GET['_wfsf']) ? $_GET['_wfsf'] : '';
self::doEarlyAccessLogging();
if(! ($wfFunc == 'diff' || $wfFunc == 'view' || $wfFunc == 'viewOption' || $wfFunc == 'sysinfo' || $wfFunc == 'IPTraf' || $wfFunc == 'viewActivityLog' || $wfFunc == 'testmem' || $wfFunc == 'testtime' || $wfFunc == 'download' || $wfFunc == 'blockedIPs' || ($wfFunc == 'debugWAF' && WFWAF_DEBUG))){
if(! wfUtils::isAdmin()){
if(! wp_verify_nonce($nonce, 'wp-ajax')){
_e("Bad security token. It may have been more than 12 hours since you reloaded the page you came from. Try reloading the page you came from. If that doesn't work, please sign out and sign-in again.", 'wordfence');
} else if($wfFunc == 'view'){
} else if($wfFunc == 'viewOption'){
self::wfFunc_viewOption();
} else if($wfFunc == 'sysinfo') {
require(dirname(__FILE__) . '/sysinfo.php' );
} else if($wfFunc == 'IPTraf'){
} else if($wfFunc == 'viewActivityLog'){
self::wfFunc_viewActivityLog();
} else if($wfFunc == 'testmem'){
} else if($wfFunc == 'testtime'){
} else if($wfFunc == 'download'){
} else if($wfFunc == 'blockedIPs'){
self::wfFunc_blockedIPs();
} else if($wfFunc == 'debugWAF' && WFWAF_DEBUG){
public static function memtest_error_handler($errno, $errstr, $errfile, $errline){
echo "Error received: $errstr\n";
private static function wfFunc_testtime(){
header('Content-Type: text/plain');
wfUtils::iniSet('display_errors','On');
set_error_handler('wordfence::memtest_error_handler', E_ALL);
echo "Wordfence process duration benchmarking utility version " . WORDFENCE_VERSION . ".\n";
echo "This utility tests how long your WordPress host allows a process to run.\n\n--Starting test--\n";
echo "Starting timed test. This will take at least three minutes. Seconds elapsed are printed below.\nAn error after this line is not unusual. Read it and the elapsed seconds to determine max process running time on your host.\n";
for($i = 1; $i <= 180; $i++){
for($j = 0; $j < 1000; $j++){
echo "\n--Test complete.--\n\nCongratulations, your web host allows your PHP processes to run at least 3 minutes.\n";
private static function wfFunc_testmem(){
header('Content-Type: text/plain');
wfUtils::iniSet('display_errors','On');
set_error_handler('wordfence::memtest_error_handler', E_ALL);
$maxMemory = ini_get('memory_limit');
$last = strtolower(substr($maxMemory, -1));
$maxMemory = (int) $maxMemory;
$configuredMax = wfConfig::get('maxMem', 0);
if ($configuredMax <= 0) {
if ($last == 'g') { $configuredMax = $maxMemory * 1024; }
else if ($last == 'm') { $configuredMax = $maxMemory; }
else if ($last == 'k') { $configuredMax = $maxMemory / 1024; }
$configuredMax = floor($configuredMax);
$stepSize = 5242880; //5 MB
echo "Wordfence Memory benchmarking utility version " . WORDFENCE_VERSION . ".\n";
echo "This utility tests if your WordPress host respects the maximum memory configured\nin their php.ini file, or if they are using other methods to limit your access to memory.\n\n--Starting test--\n";
echo "Current maximum memory configured in php.ini: " . ini_get('memory_limit') . "\n";
echo "Current memory usage: " . sprintf('%.2f', memory_get_usage(true) / (1024 * 1024)) . "M\n";
echo "Attempting to set max memory to {$configuredMax}M.\n";
wfUtils::iniSet('memory_limit', ($configuredMax + 5) . 'M'); //Allow a little extra for testing overhead
echo "Starting memory benchmark. Seeing an error after this line is not unusual. Read the error carefully\nto determine how much memory your host allows. We have requested {$configuredMax} megabytes.\n";
if (memory_get_usage(true) < 1) {
echo "Exiting test because memory_get_usage() returned a negative number\n";
if (memory_get_usage(true) > (1024 * 1024 * 1024)) {
echo "Exiting because current memory usage is greater than a gigabyte.\n";
if (!defined('WP_SANDBOX_SCRAPING')) { define('WP_SANDBOX_SCRAPING', true); } //Disables the WP error handler in somewhat of a hacky way
$accumulatedMemory = array_fill(0, ceil($configuredMax / $stepSize), '');
$currentUsage = memory_get_usage(true);
$tenMB = 10 * 1024 * 1024;
$start = ceil($currentUsage / $tenMB) * $tenMB - $currentUsage; //Start at the closest 10 MB increment to the current usage
$configuredMax = $configuredMax * 1048576; //Bytes
$testLimit = $configuredMax - memory_get_usage(true);
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678900000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111222222222222222222233333333333333334444444444444444444444444555555555555666666666666666666";
while ($start <= $testLimit) {
$accumulatedMemory[$index] = str_repeat($chars, ($start - $previous) / 256);
$finalUsage = sprintf('%.2f', (memory_get_usage(true) / 1024 / 1024));
echo "Tested up to " . $finalUsage . " megabytes.\n";
if ($start == $testLimit) { break; }
$start = min($start + $stepSize, $testLimit);
if (memory_get_usage(true) > $configuredMax) { break; }
echo "--Test complete.--\n\nYour web host allows you to use at least {$finalUsage} megabytes of memory for each PHP process hosting your WordPress site.\n";
public static function wfLogHumanHeader(){
//Final check in case this was added as an action before the request was fully initialized
if (self::getLog()->getCurrentRequest()->jsRun || !wfConfig::liveTrafficEnabled()) {
self::$hitID = self::getLog()->logHit();
$URL = home_url('/?wordfence_lh=1&hid=' . wfUtils::encrypt(self::$hitID));
$URL = addslashes(preg_replace('/^https?:/i', '', $URL));
#Load as external script async so we don't slow page down.
<script type="text/javascript">
if(/(?:Chrome\/26\.0\.1410\.63 Safari\/537\.31|WordfenceTestMonBot)/.test(navigator.userAgent)){ return; }
var addEvent = function(evt, handler) {
if (window.addEventListener) {
document.addEventListener(evt, handler, false);
} else if (window.attachEvent) {
document.attachEvent('on' + evt, handler);
var removeEvent = function(evt, handler) {
if (window.removeEventListener) {
document.removeEventListener(evt, handler, false);
} else if (window.detachEvent) {
document.detachEvent('on' + evt, handler);
var evts = 'contextmenu dblclick drag dragend dragenter dragleave dragover dragstart drop keydown keypress keyup mousedown mousemove mouseout mouseover mouseup mousewheel scroll'.split(' ');
var logHuman = function() {
if (window.wfLogHumanRan) { return; }
window.wfLogHumanRan = true;
var wfscr = document.createElement('script');
wfscr.type = 'text/javascript';
wfscr.src = url + '&r=' + Math.random();
(document.getElementsByTagName('head')[0]||document.getElementsByTagName('body')[0]).appendChild(wfscr);
for (var i = 0; i < evts.length; i++) {
removeEvent(evts[i], logHuman);
for (var i = 0; i < evts.length; i++) {
addEvent(evts[i], logHuman);
public static function shutdownAction(){
public static function wfFunc_viewActivityLog(){
require(dirname(__FILE__) . '/viewFullActivityLog.php');
public static function wfFunc_IPTraf(){
$response = self::IPTraf($IP);
$reverseLookup = $response['reverseLookup'];
$results = $response['results'];
require(dirname(__FILE__) . '/IPTraf.php');
} catch (InvalidArgumentException $e) {
private static function IPTraf($ip) {
if(!wfUtils::isValidIP($ip)){
throw new InvalidArgumentException(__("An invalid IP address was specified.", 'wordfence'));
$reverseLookup = wfUtils::reverseLookup($ip);
$wfLog = wfLog::shared();
$wfLog->getHits('hits', '404', 0, 10000, $ip),
$wfLog->getHits('hits', 'hit', 0, 10000, $ip)
usort($results, 'wordfence::iptrafsort');
foreach ($results as $k => $r) {
if (isset($ids[$r['id']])) {
$results = array_values($results);
for ($i = 0; $i < count($results); $i++){
if(array_key_exists($i + 1, $results)){
$results[$i]['timeSinceLastHit'] = sprintf('%.4f', $results[$i]['ctime'] - $results[$i + 1]['ctime']);
$results[$i]['timeSinceLastHit'] = '';
return compact('reverseLookup', 'results');
public static function iptrafsort($b, $a){
if($a['ctime'] == $b['ctime']){ return 0; }
return ($a['ctime'] < $b['ctime']) ? -1 : 1;
private static function checkRealFileParameters() {
if (array_key_exists('realFile', $_GET)) {
$realFile = stripslashes($_GET['realFile']);
$token = array_key_exists('realFileToken', $_GET) ? $_GET['realFileToken'] : '';
if (!wfIssues::verifyRealFileToken($token, $realFile)) {
esc_html_e('This link has expired. Refresh the scan results page and try again.', 'wordfence');
public static function wfFunc_viewOption() {
$site_id = !empty($_GET['site_id']) ? absint($_GET['site_id']) : get_current_blog_id();
$option_name = !empty($_GET['option']) ? $_GET['option'] : false;
$table_options = wfDB::blogTable('options', $site_id);
$option_value = $wpdb->get_var($wpdb->prepare("SELECT option_value FROM {$table_options} WHERE option_name = %s", $option_name));
header('Content-type: text/plain');
public static function wfFunc_view(){
if (WORDFENCE_DISABLE_FILE_VIEWER) {
_e("File access blocked. (WORDFENCE_DISABLE_FILE_VIEWER is true)", 'wordfence');
$localFile = self::checkRealFileParameters();
$localFile = ABSPATH . preg_replace('/^(?:\.\.|[\/]+)/', '', sanitize_text_field($_GET['file']));
if(strpos($localFile, '..') !== false){
_e("Invalid file requested. (Relative paths not allowed)", 'wordfence');
if(preg_match('/[\'\"<>\!\{\}\(\)\&\@\%\$\*\+\[\]\?]+/', $localFile)){
_e("File contains illegal characters.", 'wordfence');
$cont = @file_get_contents($localFile);
if(file_exists($localFile) && filesize($localFile) === 0){ //There's a remote possibility that very large files on 32 bit systems will return 0 here, but it's about 1 in 2 billion
printf(/* translators: Error message. */ __("We could not open the requested file for reading. The error was: %s", 'wordfence'), $err['message']);
$fileMTime = @filemtime($localFile);
$fileMTime = date('l jS \of F Y h:i:s A', $fileMTime);
if(wfUtils::fileOver2Gigs($localFile)){
$fileSize = __("Greater than 2 Gigs", 'wordfence');
$fileSize = @filesize($localFile); //Checked if over 2 gigs above
$fileSize = number_format($fileSize, 0, '', ',') . ' bytes';
} catch(Exception $e){ $fileSize = __('Unknown file size.', 'wordfence'); }
require(dirname(__FILE__) . '/wfViewResult.php');
public static function wfFunc_diff(){
if (WORDFENCE_DISABLE_FILE_VIEWER) {
esc_html_e("File access blocked. (WORDFENCE_DISABLE_FILE_VIEWER is true)", 'wordfence');
if(preg_match('/[\'\"<>\!\{\}\(\)\&\@\%\$\*\+\[\]\?]+/', $_GET['file'])){
esc_html_e("File contains illegal characters.", 'wordfence');
$result = self::getWPFileContent($_GET['file'], $_GET['cType'], wp_unslash($_GET['cName']), $_GET['cVersion']);
if( isset( $result['errorMsg'] ) && $result['errorMsg']){
echo wp_kses($result['errorMsg'], array());
} else if(! $result['fileContent']){
esc_html_e("We could not get the contents of the original file to do a comparison.", 'wordfence');
$localFile = self::checkRealFileParameters();
if ($localFile === null) {
$localFile = realpath(ABSPATH . '/' . preg_replace('/^[\.\/]+/', '', $_GET['file']));
esc_html_e('Empty file path provided', 'wordfence');
$localContents = file_get_contents($localFile);
if ($localContents === false) {
esc_html_e('Unable to read file contents', 'wordfence');
if($localContents == $result['fileContent']){
//Treat DOS and Unix files the same
preg_split("/(?:\r\n|\n)/", $result['fileContent']),
preg_split("/(?:\r\n|\n)/", $localContents),
$renderer = new Diff_Renderer_Html_SideBySide;
$diffResult = $diff->Render($renderer);
require(dirname(__FILE__) . '/diffResult.php');
public static function wfFunc_download() {
if (WORDFENCE_DISABLE_FILE_VIEWER) {
esc_html_e("File access blocked. (WORDFENCE_DISABLE_FILE_VIEWER is true)", 'wordfence');
$localFile = self::checkRealFileParameters();
$localFile = ABSPATH . preg_replace('/^(?:\.\.|[\/]+)/', '', sanitize_text_field($_GET['file']));
if (strpos($localFile, '..') !== false) {
esc_html_e("Invalid file requested. (Relative paths not allowed)", 'wordfence');
if (preg_match('/[\'\"<>\!\{\}\(\)\&\@\%\$\*\+\[\]\?]+/', $localFile)) {
esc_html_e("File contains illegal characters.", 'wordfence');
if (!file_exists($localFile)) {
_e('File does not exist.', 'wordfence');
$filename = basename($localFile);
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Content-Length: ' . filesize($localFile));
public static function wfFunc_blockedIPs() {
$blocks = wfBlock::ipBlocks(true);
foreach ($blocks as $entry) {
$output .= $entry->ip . "\n";
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . get_bloginfo('name', 'raw') . ' - Blocked IPs.txt"');
header('Content-Length: ' . strlen($output));
public static function wfFunc_debugWAF() {
if (!empty($_GET['hitid'])) {
$data['hit'] = new wfRequestModel($_GET['hitid']);
if ($data['hit']->actionData) {
$data['hitData'] = (object) wfRequestModel::unserializeActionData($data['hit']->actionData);
echo wfView::create('waf/debug', $data);
public static function isWafFailureLoggingEnabled() {
return wfConfig::get('other_WFNet', true);
private static function purgeWafFailures() {
$table = wfDB::networkTable('wfWafFailures');
$wpdb->query("DELETE FROM {$table} WHERE `timestamp` < DATE_SUB(NOW(), INTERVAL 1 DAY)");
private static function capWafFailures() {
$table = wfDB::networkTable('wfWafFailures');
$highestDeletableId = $wpdb->get_var("SELECT id FROM {$table} ORDER BY id DESC LIMIT 1 OFFSET 25");
if ($highestDeletableId === null)
"DELETE FROM {$table} WHERE id <= %d",
public static function logWafFailure() {
global $wf_waf_failure, $wpdb;
if (!self::isWafFailureLoggingEnabled())
if (is_array($wf_waf_failure) && array_key_exists('throwable', $wf_waf_failure)) {
$throwable = $wf_waf_failure['throwable'];
if (!($throwable instanceof Throwable || $throwable instanceof Exception))
$table = wfDB::networkTable('wfWafFailures');
'throwable' => (string) $throwable
if (array_key_exists('rule_id', $wf_waf_failure)) {
$ruleId = $wf_waf_failure['rule_id'];
if (is_int($ruleId) || $ruleId >= 0)
$data['rule_id'] = (int) $ruleId;