Edit File by line

Deprecated: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in /home/sportsfever/public_html/filemanger/function.php on line 93
/home/sportsfe.../httpdocs/clone/wp-conte.../plugins/wordfenc.../lib
File: wordfenceHash.php
<?php
[0] Fix | Delete
require_once(dirname(__FILE__) . '/wordfenceClass.php');
[1] Fix | Delete
class wordfenceHash {
[2] Fix | Delete
[3] Fix | Delete
const KNOWN_FILE_CORE = 'core';
[4] Fix | Delete
const KNOWN_FILE_PLUGIN = 'plugins';
[5] Fix | Delete
const KNOWN_FILE_THEME = 'themes';
[6] Fix | Delete
const KNOWN_FILE_OTHER = 'other';
[7] Fix | Delete
const MAX_QUEUED_RECORDS = 500;
[8] Fix | Delete
[9] Fix | Delete
private static $KNOWN_FILE_TYPES = [
[10] Fix | Delete
self::KNOWN_FILE_CORE,
[11] Fix | Delete
self::KNOWN_FILE_PLUGIN,
[12] Fix | Delete
self::KNOWN_FILE_THEME
[13] Fix | Delete
];
[14] Fix | Delete
[15] Fix | Delete
private $engine = false;
[16] Fix | Delete
private $db = false;
[17] Fix | Delete
private $startTime = false;
[18] Fix | Delete
private $currentFile = null;
[19] Fix | Delete
private $scanFileLogger;
[20] Fix | Delete
private $knownFileExclude;
[21] Fix | Delete
private $fileRecords = [];
[22] Fix | Delete
private $fileRecordCount = 0;
[23] Fix | Delete
[24] Fix | Delete
//Begin serialized vars
[25] Fix | Delete
public $totalFiles = 0;
[26] Fix | Delete
public $totalDirs = 0;
[27] Fix | Delete
public $totalData = 0; //To do a sanity check, don't use 'du' because it gets sparse files wrong and reports blocks used on disk. Use : find . -type f -ls | awk '{total += $7} END {print total}'
[28] Fix | Delete
public $stoppedOnFile = false;
[29] Fix | Delete
private $coreEnabled = false;
[30] Fix | Delete
private $pluginsEnabled = false;
[31] Fix | Delete
private $themesEnabled = false;
[32] Fix | Delete
private $malwareEnabled = false;
[33] Fix | Delete
private $coreUnknownEnabled = false;
[34] Fix | Delete
private $knownFiles = false;
[35] Fix | Delete
private $malwareData = "";
[36] Fix | Delete
private $coreHashesData = '';
[37] Fix | Delete
private $haveIssues = array();
[38] Fix | Delete
private $status = array();
[39] Fix | Delete
private $possibleMalware = array();
[40] Fix | Delete
private $scannedFiles;
[41] Fix | Delete
private $totalForks = 0;
[42] Fix | Delete
private $alertedOnUnknownWordPressVersion = false;
[43] Fix | Delete
private $foldersEntered = array();
[44] Fix | Delete
private $foldersProcessed = array();
[45] Fix | Delete
private $suspectedFiles = array();
[46] Fix | Delete
private $indexed = false;
[47] Fix | Delete
private $indexSize = 0;
[48] Fix | Delete
private $currentIndex = 0;
[49] Fix | Delete
private $coalescingIssues = array();
[50] Fix | Delete
private $pathMap = array();
[51] Fix | Delete
[52] Fix | Delete
/**
[53] Fix | Delete
* @param string $path
[54] Fix | Delete
* @param array $only
[55] Fix | Delete
* @param array $themes
[56] Fix | Delete
* @param array $plugins
[57] Fix | Delete
* @param wfScanEngine $engine
[58] Fix | Delete
* @throws Exception
[59] Fix | Delete
*/
[60] Fix | Delete
public function __construct($scannedFiles, $engine, $malwarePrefixesHash, $coreHashesHash, $scanMode) {
[61] Fix | Delete
$this->scannedFiles = $scannedFiles;
[62] Fix | Delete
$this->engine = $engine;
[63] Fix | Delete
[64] Fix | Delete
$this->startTime = microtime(true);
[65] Fix | Delete
[66] Fix | Delete
$options = $this->engine->scanController()->scanOptions();
[67] Fix | Delete
if ($options['scansEnabled_core']) { $this->coreEnabled = true; }
[68] Fix | Delete
if ($options['scansEnabled_plugins']) { $this->pluginsEnabled = true; }
[69] Fix | Delete
if ($options['scansEnabled_themes']) { $this->themesEnabled = true; }
[70] Fix | Delete
if ($options['scansEnabled_malware']) { $this->malwareEnabled = true; }
[71] Fix | Delete
if ($options['scansEnabled_coreUnknown']) { $this->coreUnknownEnabled = true; }
[72] Fix | Delete
[73] Fix | Delete
$this->db = new wfDB();
[74] Fix | Delete
[75] Fix | Delete
//Doing a delete for now. Later we can optimize this to only scan modified files.
[76] Fix | Delete
//$this->db->queryWrite("update " . wfDB::networkTable('wfFileMods') . " set oldMD5 = newMD5");
[77] Fix | Delete
$this->db->truncate(wfDB::networkTable('wfFileMods'));
[78] Fix | Delete
$this->db->truncate(wfDB::networkTable('wfKnownFileList'));
[79] Fix | Delete
$this->db->truncate(wfDB::networkTable('wfPendingIssues'));
[80] Fix | Delete
$fetchCoreHashesStatus = wfIssues::statusStart(__("Fetching core, theme and plugin file signatures from Wordfence", 'wordfence'));
[81] Fix | Delete
try {
[82] Fix | Delete
$this->knownFiles = $this->engine->getKnownFilesLoader()->getKnownFiles();
[83] Fix | Delete
} catch (wfScanKnownFilesException $e) {
[84] Fix | Delete
wfIssues::statusEndErr();
[85] Fix | Delete
throw $e;
[86] Fix | Delete
}
[87] Fix | Delete
wfIssues::statusEnd($fetchCoreHashesStatus, wfIssues::STATUS_SUCCESS);
[88] Fix | Delete
if ($this->malwareEnabled) {
[89] Fix | Delete
$malwarePrefixStatus = wfIssues::statusStart(__("Fetching list of known malware files from Wordfence", 'wordfence'));
[90] Fix | Delete
[91] Fix | Delete
$stored = wfConfig::get_ser('malwarePrefixes', array(), false);
[92] Fix | Delete
if (is_array($stored) && isset($stored['hash']) && $stored['hash'] == $malwarePrefixesHash && isset($stored['prefixes']) && wfWAFUtils::strlen($stored['prefixes']) % 4 == 0) {
[93] Fix | Delete
wordfence::status(4, 'info', __("Using cached malware prefixes", 'wordfence'));
[94] Fix | Delete
}
[95] Fix | Delete
else {
[96] Fix | Delete
wordfence::status(4, 'info', __("Fetching fresh malware prefixes", 'wordfence'));
[97] Fix | Delete
[98] Fix | Delete
$malwareData = $engine->api->getStaticURL('/malwarePrefixes.bin');
[99] Fix | Delete
if (!$malwareData) {
[100] Fix | Delete
wfIssues::statusEndErr();
[101] Fix | Delete
throw new Exception(__("Could not fetch malware signatures from Wordfence servers.", 'wordfence'));
[102] Fix | Delete
}
[103] Fix | Delete
[104] Fix | Delete
if (wfWAFUtils::strlen($malwareData) % 4 != 0) {
[105] Fix | Delete
wfIssues::statusEndErr();
[106] Fix | Delete
throw new Exception(__("Malware data received from Wordfence servers was not valid.", 'wordfence'));
[107] Fix | Delete
}
[108] Fix | Delete
[109] Fix | Delete
$stored = array('hash' => $malwarePrefixesHash, 'prefixes' => $malwareData);
[110] Fix | Delete
wfConfig::set_ser('malwarePrefixes', $stored, true, wfConfig::DONT_AUTOLOAD);
[111] Fix | Delete
}
[112] Fix | Delete
[113] Fix | Delete
$this->malwareData = $stored['prefixes'];
[114] Fix | Delete
wfIssues::statusEnd($malwarePrefixStatus, wfIssues::STATUS_SUCCESS);
[115] Fix | Delete
}
[116] Fix | Delete
[117] Fix | Delete
if ($this->coreUnknownEnabled) {
[118] Fix | Delete
$coreHashesStatus = wfIssues::statusStart(__("Fetching list of known core files from Wordfence", 'wordfence'));
[119] Fix | Delete
[120] Fix | Delete
$stored = wfConfig::get_ser('coreHashes', array(), false);
[121] Fix | Delete
if (is_array($stored) && isset($stored['hash']) && $stored['hash'] == $coreHashesHash && isset($stored['hashes']) && wfWAFUtils::strlen($stored['hashes']) > 0 && wfWAFUtils::strlen($stored['hashes']) % 32 == 0) {
[122] Fix | Delete
wordfence::status(4, 'info', __("Using cached core hashes", 'wordfence'));
[123] Fix | Delete
}
[124] Fix | Delete
else {
[125] Fix | Delete
wordfence::status(4, 'info', __("Fetching fresh core hashes", 'wordfence'));
[126] Fix | Delete
[127] Fix | Delete
$coreHashesData = $engine->api->getStaticURL('/coreHashes.bin');
[128] Fix | Delete
if (!$coreHashesData) {
[129] Fix | Delete
wfIssues::statusEndErr();
[130] Fix | Delete
throw new Exception(__("Could not fetch core hashes from Wordfence servers.", 'wordfence'));
[131] Fix | Delete
}
[132] Fix | Delete
[133] Fix | Delete
if (wfWAFUtils::strlen($coreHashesData) % 32 != 0) {
[134] Fix | Delete
wfIssues::statusEndErr();
[135] Fix | Delete
throw new Exception(__("Core hashes data received from Wordfence servers was not valid.", 'wordfence'));
[136] Fix | Delete
}
[137] Fix | Delete
[138] Fix | Delete
$stored = array('hash' => $coreHashesHash, 'hashes' => $coreHashesData);
[139] Fix | Delete
wfConfig::set_ser('coreHashes', $stored, true, wfConfig::DONT_AUTOLOAD);
[140] Fix | Delete
}
[141] Fix | Delete
[142] Fix | Delete
$this->coreHashesData = $stored['hashes'];
[143] Fix | Delete
wfIssues::statusEnd($coreHashesStatus, wfIssues::STATUS_SUCCESS);
[144] Fix | Delete
}
[145] Fix | Delete
[146] Fix | Delete
$this->haveIssues = array(
[147] Fix | Delete
'core' => wfIssues::STATUS_SECURE,
[148] Fix | Delete
'coreUnknown' => wfIssues::STATUS_SECURE,
[149] Fix | Delete
'themes' => wfIssues::STATUS_SECURE,
[150] Fix | Delete
'plugins' => wfIssues::STATUS_SECURE,
[151] Fix | Delete
'malware' => wfIssues::STATUS_SECURE,
[152] Fix | Delete
);
[153] Fix | Delete
if($this->coreEnabled){ $this->status['core'] = wfIssues::statusStart(__("Comparing core WordPress files against originals in repository", 'wordfence')); $this->engine->scanController()->startStage(wfScanner::STAGE_FILE_CHANGES); } else { wfIssues::statusDisabled(__("Skipping core scan", 'wordfence')); }
[154] Fix | Delete
if($this->themesEnabled){ $this->status['themes'] = wfIssues::statusStart(__("Comparing open source themes against WordPress.org originals", 'wordfence')); $this->engine->scanController()->startStage(wfScanner::STAGE_FILE_CHANGES); } else { wfIssues::statusDisabled(__("Skipping theme scan", 'wordfence')); }
[155] Fix | Delete
if($this->pluginsEnabled){ $this->status['plugins'] = wfIssues::statusStart(__("Comparing plugins against WordPress.org originals", 'wordfence')); $this->engine->scanController()->startStage(wfScanner::STAGE_FILE_CHANGES); } else { wfIssues::statusDisabled(__("Skipping plugin scan", 'wordfence')); }
[156] Fix | Delete
if($this->malwareEnabled){ $this->status['malware'] = wfIssues::statusStart(__("Scanning for known malware files", 'wordfence')); $this->engine->scanController()->startStage(wfScanner::STAGE_MALWARE_SCAN); } else { wfIssues::statusDisabled(__("Skipping malware scan", 'wordfence')); }
[157] Fix | Delete
if($this->coreUnknownEnabled){ $this->status['coreUnknown'] = wfIssues::statusStart(__("Scanning for unknown files in wp-admin and wp-includes", 'wordfence')); $this->engine->scanController()->startStage(wfScanner::STAGE_FILE_CHANGES); } else { wfIssues::statusDisabled(__("Skipping unknown core file scan", 'wordfence')); }
[158] Fix | Delete
[159] Fix | Delete
if ($options['scansEnabled_fileContents']) { $this->engine->scanController()->startStage(wfScanner::STAGE_MALWARE_SCAN); }
[160] Fix | Delete
if ($options['scansEnabled_fileContentsGSB']) { $this->engine->scanController()->startStage(wfScanner::STAGE_CONTENT_SAFETY); }
[161] Fix | Delete
[162] Fix | Delete
if ($this->coreUnknownEnabled && !$this->alertedOnUnknownWordPressVersion && empty($this->knownFiles['core'])) {
[163] Fix | Delete
require(ABSPATH . 'wp-includes/version.php'); /* @var string $wp_version */
[164] Fix | Delete
$this->alertedOnUnknownWordPressVersion = true;
[165] Fix | Delete
$added = $this->engine->addIssue(
[166] Fix | Delete
'coreUnknown',
[167] Fix | Delete
wfIssues::SEVERITY_MEDIUM,
[168] Fix | Delete
'coreUnknown' . $wp_version,
[169] Fix | Delete
'coreUnknown' . $wp_version,
[170] Fix | Delete
sprintf(/* translators: WordPress version. */ __('Unknown WordPress core version: %s', 'wordfence'), $wp_version),
[171] Fix | Delete
__("The core files scan will not be run because this version of WordPress is not currently indexed by Wordfence. This may be due to using a prerelease version or because the servers are still indexing a new release. If you are using an official WordPress release, this issue will automatically dismiss once the version is indexed and another scan is run.", 'wordfence'),
[172] Fix | Delete
array()
[173] Fix | Delete
);
[174] Fix | Delete
[175] Fix | Delete
if ($added == wfIssues::ISSUE_ADDED || $added == wfIssues::ISSUE_UPDATED) { $this->haveIssues['coreUnknown'] = wfIssues::STATUS_PROBLEM; }
[176] Fix | Delete
else if ($this->haveIssues['coreUnknown'] != wfIssues::STATUS_PROBLEM && ($added == wfIssues::ISSUE_IGNOREP || $added == wfIssues::ISSUE_IGNOREC)) { $this->haveIssues['coreUnknown'] = wfIssues::STATUS_IGNORED; }
[177] Fix | Delete
}
[178] Fix | Delete
$this->initializeProperties();
[179] Fix | Delete
}
[180] Fix | Delete
private function initializeProperties() {
[181] Fix | Delete
$this->scanFileLogger = $this->getScanFileLogger();
[182] Fix | Delete
$this->knownFileExclude = wordfenceScanner::getExcludeFilePattern(wordfenceScanner::EXCLUSION_PATTERNS_KNOWN_FILES);
[183] Fix | Delete
}
[184] Fix | Delete
public function __sleep(){
[185] Fix | Delete
return array('totalFiles', 'totalDirs', 'totalData', 'stoppedOnFile', 'coreEnabled', 'pluginsEnabled', 'themesEnabled', 'malwareEnabled', 'coreUnknownEnabled', 'knownFiles', 'haveIssues', 'status', 'possibleMalware', 'scannedFiles', 'totalForks', 'alertedOnUnknownWordPressVersion', 'foldersProcessed', 'suspectedFiles', 'indexed', 'indexSize', 'currentIndex', 'coalescingIssues', 'pathMap');
[186] Fix | Delete
}
[187] Fix | Delete
public function __wakeup(){
[188] Fix | Delete
$this->db = new wfDB();
[189] Fix | Delete
$this->startTime = microtime(true);
[190] Fix | Delete
$this->totalForks++;
[191] Fix | Delete
[192] Fix | Delete
$stored = wfConfig::get_ser('malwarePrefixes', array(), false);
[193] Fix | Delete
if (!isset($stored['prefixes'])) {
[194] Fix | Delete
$stored['prefixes'] = '';
[195] Fix | Delete
}
[196] Fix | Delete
$this->malwareData = $stored['prefixes'];
[197] Fix | Delete
[198] Fix | Delete
$stored = wfConfig::get_ser('coreHashes', array(), false);
[199] Fix | Delete
if (!isset($stored['hashes'])) {
[200] Fix | Delete
$stored['hashes'] = '';
[201] Fix | Delete
}
[202] Fix | Delete
$this->coreHashesData = $stored['hashes'];
[203] Fix | Delete
$this->initializeProperties();
[204] Fix | Delete
}
[205] Fix | Delete
public function getSuspectedFiles() {
[206] Fix | Delete
return array_keys($this->suspectedFiles);
[207] Fix | Delete
}
[208] Fix | Delete
public function run($engine) {
[209] Fix | Delete
if($this->totalForks > 1000){
[210] Fix | Delete
throw new Exception(sprintf(/* translators: File path. */ __("Wordfence file scanner detected a possible infinite loop. Exiting on file: %s", 'wordfence'), $this->stoppedOnFile));
[211] Fix | Delete
}
[212] Fix | Delete
$this->engine = $engine;
[213] Fix | Delete
if (!$this->indexed) {
[214] Fix | Delete
$start = microtime(true);
[215] Fix | Delete
$indexedFiles = array();
[216] Fix | Delete
foreach ($this->scannedFiles as $file) {
[217] Fix | Delete
$this->_dirIndex($file, $indexedFiles);
[218] Fix | Delete
}
[219] Fix | Delete
$this->_serviceIndexQueue($indexedFiles, true);
[220] Fix | Delete
$this->indexed = true;
[221] Fix | Delete
unset($this->foldersEntered); $this->foldersEntered = array();
[222] Fix | Delete
unset($this->foldersProcessed); $this->foldersProcessed = array();
[223] Fix | Delete
$end = microtime(true);
[224] Fix | Delete
wordfence::status(4, 'info', sprintf(/* translators: Time in seconds. */ __("Index time: %s", 'wordfence'), ($end - $start)));
[225] Fix | Delete
}
[226] Fix | Delete
[227] Fix | Delete
$this->_checkForTimeout();
[228] Fix | Delete
[229] Fix | Delete
wordfence::status(4, 'info', __("Beginning file hashing", 'wordfence'));
[230] Fix | Delete
while ($file = $this->_nextFile()) {
[231] Fix | Delete
$this->processFile($file);
[232] Fix | Delete
wfUtils::afterProcessingFile();
[233] Fix | Delete
$this->_checkForTimeout($file);
[234] Fix | Delete
}
[235] Fix | Delete
[236] Fix | Delete
$this->processFileRecords(); // Ensure all file records have actually been inserted before processing pending issues
[237] Fix | Delete
[238] Fix | Delete
wordfence::status(4, 'info', __("Processing pending issues", 'wordfence'));
[239] Fix | Delete
$this->_processPendingIssues();
[240] Fix | Delete
[241] Fix | Delete
wordfence::status(2, 'info', sprintf(/* translators: 1. Number of files. 2. Data in bytes. */ __('Analyzed %1$d files containing %2$s of data.', 'wordfence'), $this->totalFiles, wfUtils::formatBytes($this->totalData)));
[242] Fix | Delete
if($this->coreEnabled){ wfIssues::statusEnd($this->status['core'], $this->haveIssues['core']); $this->engine->scanController()->completeStage(wfScanner::STAGE_FILE_CHANGES, $this->haveIssues['core']); }
[243] Fix | Delete
if($this->themesEnabled){ wfIssues::statusEnd($this->status['themes'], $this->haveIssues['themes']); $this->engine->scanController()->completeStage(wfScanner::STAGE_FILE_CHANGES, $this->haveIssues['themes']); }
[244] Fix | Delete
if($this->pluginsEnabled){ wfIssues::statusEnd($this->status['plugins'], $this->haveIssues['plugins']); $this->engine->scanController()->completeStage(wfScanner::STAGE_FILE_CHANGES, $this->haveIssues['plugins']); }
[245] Fix | Delete
if($this->coreUnknownEnabled){ wfIssues::statusEnd($this->status['coreUnknown'], $this->haveIssues['coreUnknown']); $this->engine->scanController()->completeStage(wfScanner::STAGE_FILE_CHANGES, $this->haveIssues['coreUnknown']); }
[246] Fix | Delete
if(sizeof($this->possibleMalware) > 0){
[247] Fix | Delete
$malwareResp = $engine->api->binCall('check_possible_malware', json_encode($this->possibleMalware));
[248] Fix | Delete
if($malwareResp['code'] != 200){
[249] Fix | Delete
wfIssues::statusEndErr();
[250] Fix | Delete
throw new Exception(__("Invalid response from Wordfence API during check_possible_malware", 'wordfence'));
[251] Fix | Delete
}
[252] Fix | Delete
$malwareList = json_decode($malwareResp['data'], true);
[253] Fix | Delete
if(is_array($malwareList) && sizeof($malwareList) > 0){
[254] Fix | Delete
for($i = 0; $i < sizeof($malwareList); $i++){
[255] Fix | Delete
$file = $malwareList[$i][0];
[256] Fix | Delete
$md5 = $malwareList[$i][1];
[257] Fix | Delete
$name = $malwareList[$i][2];
[258] Fix | Delete
$added = $this->engine->addIssue(
[259] Fix | Delete
'file',
[260] Fix | Delete
wfIssues::SEVERITY_CRITICAL,
[261] Fix | Delete
$file,
[262] Fix | Delete
$md5,
[263] Fix | Delete
sprintf(/* translators: File path. */ __('This file is suspected malware: %s', 'wordfence'), $file),
[264] Fix | Delete
sprintf(/* translators: Malware name/title. */ __("This file's signature matches a known malware file. The title of the malware is '%s'. Immediately inspect this file using the 'View' option below and consider deleting it from your server.", 'wordfence'), $name),
[265] Fix | Delete
array(
[266] Fix | Delete
'file' => $file,
[267] Fix | Delete
'realFile' => array_key_exists($file, $this->pathMap) ? $this->pathMap[$file] : null,
[268] Fix | Delete
'cType' => 'unknown',
[269] Fix | Delete
'canDiff' => false,
[270] Fix | Delete
'canFix' => false,
[271] Fix | Delete
'canDelete' => true
[272] Fix | Delete
)
[273] Fix | Delete
);
[274] Fix | Delete
[275] Fix | Delete
if ($added == wfIssues::ISSUE_ADDED || $added == wfIssues::ISSUE_UPDATED) { $this->haveIssues['malware'] = wfIssues::STATUS_PROBLEM; }
[276] Fix | Delete
else if ($this->haveIssues['malware'] != wfIssues::STATUS_PROBLEM && ($added == wfIssues::ISSUE_IGNOREP || $added == wfIssues::ISSUE_IGNOREC)) { $this->haveIssues['malware'] = wfIssues::STATUS_IGNORED; }
[277] Fix | Delete
}
[278] Fix | Delete
}
[279] Fix | Delete
}
[280] Fix | Delete
if($this->malwareEnabled){ wfIssues::statusEnd($this->status['malware'], $this->haveIssues['malware']); $this->engine->scanController()->completeStage(wfScanner::STAGE_MALWARE_SCAN, $this->haveIssues['malware']); }
[281] Fix | Delete
unset($this->knownFiles); $this->knownFiles = false;
[282] Fix | Delete
}
[283] Fix | Delete
private function _dirIndex($file, &$indexedFiles) {
[284] Fix | Delete
$realPath = $file->getRealPath();
[285] Fix | Delete
//Applies to files and dirs
[286] Fix | Delete
if (!is_readable($realPath))
[287] Fix | Delete
return;
[288] Fix | Delete
if (!$this->_shouldProcessFile($file))
[289] Fix | Delete
return;
[290] Fix | Delete
if (is_dir($realPath)) {
[291] Fix | Delete
if (isset($this->foldersEntered[$realPath]))
[292] Fix | Delete
return;
[293] Fix | Delete
[294] Fix | Delete
$this->foldersEntered[$file->getRealPath()] = 1;
[295] Fix | Delete
[296] Fix | Delete
$this->totalDirs++;
[297] Fix | Delete
try {
[298] Fix | Delete
foreach (wfFileUtils::getContents($realPath) as $child) {
[299] Fix | Delete
if (wfFileUtils::isCurrentOrParentDirectory($child)) {
[300] Fix | Delete
continue;
[301] Fix | Delete
}
[302] Fix | Delete
try {
[303] Fix | Delete
$child = $file->createChild($child);
[304] Fix | Delete
}
[305] Fix | Delete
catch (wfInvalidPathException $e) {
[306] Fix | Delete
wordfence::status(4, 'info', sprintf(__("Ignoring invalid scan file child: %s", 'wordfence'), $e->getPath()));
[307] Fix | Delete
continue;
[308] Fix | Delete
}
[309] Fix | Delete
if (is_file($child->getRealPath())) {
[310] Fix | Delete
$relativeFile = $child->getWordpressPath();
[311] Fix | Delete
if ($this->stoppedOnFile && $child->getRealPath() != $this->stoppedOnFile) {
[312] Fix | Delete
continue;
[313] Fix | Delete
}
[314] Fix | Delete
[315] Fix | Delete
if (preg_match('/\.suspected$/i', $relativeFile)) { //Already iterating over all files in the search areas so generate this list here
[316] Fix | Delete
wordfence::status(4, 'info', sprintf(/* translators: File path. */ __("Found .suspected file: %s", 'wordfence'), $relativeFile));
[317] Fix | Delete
$this->suspectedFiles[$relativeFile] = 1;
[318] Fix | Delete
}
[319] Fix | Delete
[320] Fix | Delete
$this->_checkForTimeout($child, $indexedFiles);
[321] Fix | Delete
if ($this->_shouldHashFile($child)) {
[322] Fix | Delete
$indexedFiles[] = $child;
[323] Fix | Delete
}
[324] Fix | Delete
else {
[325] Fix | Delete
wordfence::status(4, 'info', sprintf(/* translators: File path. */ __("Skipping unneeded hash: %s", 'wordfence'), (string) $child));
[326] Fix | Delete
}
[327] Fix | Delete
$this->_serviceIndexQueue($indexedFiles);
[328] Fix | Delete
}
[329] Fix | Delete
elseif (is_dir($child->getRealPath())) {
[330] Fix | Delete
$this->_dirIndex($child, $indexedFiles);
[331] Fix | Delete
}
[332] Fix | Delete
}
[333] Fix | Delete
}
[334] Fix | Delete
catch (wfInaccessibleDirectoryException $e) {
[335] Fix | Delete
wordfence::status(4, 'info', sprintf(/* translators: File path. */ __("Skipping inaccessible directory: %s", 'wordfence'), (string) $file));
[336] Fix | Delete
}
[337] Fix | Delete
[338] Fix | Delete
$this->foldersProcessed[$realPath] = 1;
[339] Fix | Delete
unset($this->foldersEntered[$realPath]);
[340] Fix | Delete
}
[341] Fix | Delete
else {
[342] Fix | Delete
if (is_file($realPath)) {
[343] Fix | Delete
$relativeFile = $file->getWordpressPath();
[344] Fix | Delete
if ($this->stoppedOnFile && $realPath != $this->stoppedOnFile) {
[345] Fix | Delete
return;
[346] Fix | Delete
}
[347] Fix | Delete
[348] Fix | Delete
if (preg_match('/\.suspected$/i', $relativeFile)) { //Already iterating over all files in the search areas so generate this list here
[349] Fix | Delete
wordfence::status(4, 'info', sprintf(/* translators: File path. */ __("Found .suspected file: %s", 'wordfence'), $relativeFile));
[350] Fix | Delete
$this->suspectedFiles[$relativeFile] = 1;
[351] Fix | Delete
}
[352] Fix | Delete
[353] Fix | Delete
$this->_checkForTimeout($file, $indexedFiles);
[354] Fix | Delete
if ($this->_shouldHashFile($file)) {
[355] Fix | Delete
$indexedFiles[] = $file;
[356] Fix | Delete
}
[357] Fix | Delete
else {
[358] Fix | Delete
wordfence::status(4, 'info', sprintf(/* translators: File path. */ __("Skipping unneeded hash: %s", 'wordfence'), (string) $file));
[359] Fix | Delete
}
[360] Fix | Delete
$this->_serviceIndexQueue($indexedFiles);
[361] Fix | Delete
}
[362] Fix | Delete
}
[363] Fix | Delete
}
[364] Fix | Delete
private function _serviceIndexQueue(&$indexedFiles, $final = false) {
[365] Fix | Delete
$files = array();
[366] Fix | Delete
if (count($indexedFiles) > 500) {
[367] Fix | Delete
$files = array_splice($indexedFiles, 0, 500);
[368] Fix | Delete
}
[369] Fix | Delete
else if ($final) {
[370] Fix | Delete
$files = $indexedFiles;
[371] Fix | Delete
$indexedFiles = array();
[372] Fix | Delete
}
[373] Fix | Delete
[374] Fix | Delete
$fileCount = count($files);
[375] Fix | Delete
if ($fileCount > 0) {
[376] Fix | Delete
$payload = array();
[377] Fix | Delete
foreach ($files as $file) {
[378] Fix | Delete
$payload[] = (string) $file;
[379] Fix | Delete
$payload[] = $file->getWordpressPath();
[380] Fix | Delete
}
[381] Fix | Delete
global $wpdb;
[382] Fix | Delete
$table_wfKnownFileList = wfDB::networkTable('wfKnownFileList');
[383] Fix | Delete
$query = substr("INSERT INTO {$table_wfKnownFileList} (path, wordpress_path) VALUES " . str_repeat("('%s', '%s'), ", count($files)), 0, -2);
[384] Fix | Delete
$wpdb->query($wpdb->prepare($query, $payload));
[385] Fix | Delete
$this->indexSize += $fileCount;
[386] Fix | Delete
wordfence::status(2, 'info', sprintf(/* translators: Number of files. */ __("%d files indexed", 'wordfence'), $this->indexSize));
[387] Fix | Delete
}
[388] Fix | Delete
}
[389] Fix | Delete
private function _loadFileBatch() {
[390] Fix | Delete
global $wpdb;
[391] Fix | Delete
$table_wfKnownFileList = wfDB::networkTable('wfKnownFileList');
[392] Fix | Delete
$rows = $wpdb->get_results($wpdb->prepare("SELECT id, path, wordpress_path FROM {$table_wfKnownFileList} WHERE id > %d ORDER BY id ASC LIMIT 500", $this->currentIndex));
[393] Fix | Delete
end($rows);
[394] Fix | Delete
while (($row = prev($rows)) !== false) {
[395] Fix | Delete
$this->currentFile = new wfScanFileListItem($row->id, $row->path, $row->wordpress_path, $this->currentFile);
[396] Fix | Delete
}
[397] Fix | Delete
}
[398] Fix | Delete
private function _nextFile() {
[399] Fix | Delete
if ($this->currentFile !== null)
[400] Fix | Delete
$this->currentFile = $this->currentFile->getNext();
[401] Fix | Delete
if ($this->currentFile === null) {
[402] Fix | Delete
$this->_loadFileBatch();
[403] Fix | Delete
}
[404] Fix | Delete
if ($this->currentFile !== null)
[405] Fix | Delete
$this->currentIndex = $this->currentFile->getId();
[406] Fix | Delete
return $this->currentFile;
[407] Fix | Delete
}
[408] Fix | Delete
private function _checkForTimeout($file = null, $indexQueue = false) {
[409] Fix | Delete
$realPath = $file ? $file->getRealPath() : null;
[410] Fix | Delete
if (($this->stoppedOnFile !== $realPath) && $this->engine->shouldFork()) { //max X seconds but don't allow fork if we're looking for the file we stopped on. Search mode is VERY fast.
[411] Fix | Delete
$this->processFileRecords(false);
[412] Fix | Delete
if ($indexQueue !== false) {
[413] Fix | Delete
$this->_serviceIndexQueue($indexQueue, true);
[414] Fix | Delete
$this->stoppedOnFile = $realPath;
[415] Fix | Delete
wordfence::status(4, 'info', sprintf(/* translators: File path. */ __("Forking during indexing: %s", 'wordfence'), (string) $file));
[416] Fix | Delete
}
[417] Fix | Delete
else {
[418] Fix | Delete
wordfence::status(4, 'info', sprintf(/* translators: PHP max execution time. */ __("Calling fork() from wordfenceHash with maxExecTime: %s", 'wordfence'), $this->engine->maxExecTime));
[419] Fix | Delete
}
[420] Fix | Delete
$this->engine->fork();
[421] Fix | Delete
//exits
[422] Fix | Delete
}
[423] Fix | Delete
[424] Fix | Delete
if ($this->stoppedOnFile && $realPath != $this->stoppedOnFile && $indexQueue !== false) {
[425] Fix | Delete
return;
[426] Fix | Delete
}
[427] Fix | Delete
else if ($this->stoppedOnFile && $realPath == $this->stoppedOnFile) {
[428] Fix | Delete
$this->stoppedOnFile = false; //Continue indexing
[429] Fix | Delete
}
[430] Fix | Delete
}
[431] Fix | Delete
private function _shouldProcessFile($file) {
[432] Fix | Delete
$excludePatterns = wordfenceScanner::getExcludeFilePattern(wordfenceScanner::EXCLUSION_PATTERNS_USER);
[433] Fix | Delete
if ($excludePatterns) {
[434] Fix | Delete
foreach ($excludePatterns as $pattern) {
[435] Fix | Delete
if (preg_match($pattern, $file->getWordpressPath())) {
[436] Fix | Delete
return false;
[437] Fix | Delete
}
[438] Fix | Delete
}
[439] Fix | Delete
}
[440] Fix | Delete
[441] Fix | Delete
$realPath = $file->getRealPath();
[442] Fix | Delete
if ($realPath === '/') {
[443] Fix | Delete
return false;
[444] Fix | Delete
}
[445] Fix | Delete
if (isset($this->foldersProcessed[$realPath])) {
[446] Fix | Delete
return false;
[447] Fix | Delete
}
[448] Fix | Delete
[449] Fix | Delete
return true;
[450] Fix | Delete
}
[451] Fix | Delete
private function getScanFileLogger() {
[452] Fix | Delete
if (function_exists('memory_get_usage')) {
[453] Fix | Delete
return function($realPath) {
[454] Fix | Delete
wordfence::status(4, 'info', sprintf(/* translators: 1. File path. 2. Memory in bytes. */ __('Scanning: %1$s (Mem:%2$s)', 'wordfence'), $realPath, sprintf('%.1fM', memory_get_usage(true) / (1024 * 1024))));
[455] Fix | Delete
};
[456] Fix | Delete
}
[457] Fix | Delete
else {
[458] Fix | Delete
return function($realPath) {
[459] Fix | Delete
wordfence::status(4, 'info', sprintf(/* translators: File path. */ __("Scanning: %s", 'wordfence'), $realPath));
[460] Fix | Delete
};
[461] Fix | Delete
}
[462] Fix | Delete
}
[463] Fix | Delete
private function isKnownFileScanAllowed($realPath) {
[464] Fix | Delete
if ($this->knownFileExclude) {
[465] Fix | Delete
foreach ($this->knownFileExclude as $pattern) {
[466] Fix | Delete
if (preg_match($pattern, $realPath)) {
[467] Fix | Delete
return false;
[468] Fix | Delete
}
[469] Fix | Delete
}
[470] Fix | Delete
}
[471] Fix | Delete
return true;
[472] Fix | Delete
}
[473] Fix | Delete
private function getKnownFileType($properties) {
[474] Fix | Delete
if ($this->isKnownFileScanAllowed($properties->realPath)) {
[475] Fix | Delete
foreach (self::$KNOWN_FILE_TYPES as $type) {
[476] Fix | Delete
if (isset($this->knownFiles[$type][$properties->wordpressPath]))
[477] Fix | Delete
return $type;
[478] Fix | Delete
}
[479] Fix | Delete
if ($this->coreUnknownEnabled && !$this->alertedOnUnknownWordPressVersion)
[480] Fix | Delete
return self::KNOWN_FILE_OTHER;
[481] Fix | Delete
}
[482] Fix | Delete
return null;
[483] Fix | Delete
}
[484] Fix | Delete
private function checkKnownCoreFile($properties) {
[485] Fix | Delete
if (strtoupper($this->knownFiles['core'][$properties->wordpressPath]) == $properties->shac) {
[486] Fix | Delete
$properties->freeContent();
[487] Fix | Delete
return true;
[488] Fix | Delete
}
[489] Fix | Delete
else {
[490] Fix | Delete
if ($this->coreEnabled) {
[491] Fix | Delete
if ($properties->loadContent() && (!preg_match('/<\?' . 'php[\r\n\s\t]*\/\/[\r\n\s\t]*Silence is golden\.[\r\n\s\t]*(?:\?>)?[\r\n\s\t]*$/s', $properties->content))) {
[492] Fix | Delete
$this->engine->addPendingIssue(
[493] Fix | Delete
'knownfile',
[494] Fix | Delete
wfIssues::SEVERITY_HIGH,
[495] Fix | Delete
'coreModified' . $properties->wordpressPath,
[496] Fix | Delete
'coreModified' . $properties->wordpressPath . $properties->md5,
[497] Fix | Delete
sprintf(/* translators: File path. */ __('WordPress core file modified: %s', 'wordfence'), $properties->wordpressPath),
[498] Fix | Delete
__("This WordPress core file has been modified and differs from the original file distributed with this version of WordPress.", 'wordfence'),
[499] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function