: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
if (empty($issues)) { return; }
$emailed_issues = wfConfig::get_ser('emailedIssuesList', array());
if (!is_array($emailed_issues)) { return; }
foreach ($emailed_issues as $ei) {
foreach ($issues as $issue) {
if ($issue['ignoreP'] == $ei['ignoreP'] || $issue['ignoreC'] == $ei['ignoreC']) {
wfConfig::set_ser('emailedIssuesList', $updated, false, wfConfig::DONT_AUTOLOAD);
public function deleteIssue($id){
$this->clearEmailedStatus(array($this->getIssueByID($id)));
$this->getDB()->queryWrite("delete from " . $this->issuesTable . " where id=%d", $id);
if (wfCentral::isConnected()) {
wfCentral::deleteIssue($id);
public function deleteUpdateIssues($type) {
$issues = $this->getDB()->querySelect("SELECT id, status, ignoreP, ignoreC FROM {$this->issuesTable} WHERE status = 'new' AND type = '%s'", $type);
$this->clearEmailedStatus($issues);
$this->getDB()->queryWrite("DELETE FROM {$this->issuesTable} WHERE status = 'new' AND type = '%s'", $type);
if (wfCentral::isConnected()) {
wfCentral::deleteIssueTypes(array($type));
public function deleteAllUpdateIssues() {
$issues = $this->getDB()->querySelect("SELECT id, status, ignoreP, ignoreC FROM {$this->issuesTable} WHERE status = 'new' AND (type = 'wfUpgrade' OR type = 'wfUpgradeError' OR type = 'wfPluginUpgrade' OR type = 'wfThemeUpgrade')");
$this->clearEmailedStatus($issues);
$this->getDB()->queryWrite("DELETE FROM {$this->issuesTable} WHERE status = 'new' AND (type = 'wfUpgrade' OR type = 'wfUpgradeError' OR type = 'wfPluginUpgrade' OR type = 'wfThemeUpgrade')");
if (wfCentral::isConnected()) {
wfCentral::deleteIssueTypes(array('wfUpgrade', 'wfUpgradeError', 'wfPluginUpgrade', 'wfThemeUpgrade'));
public function updateIssue($id, $status){ //ignoreC, ignoreP, delete or new
if (wfCentral::isConnected()) {
wfCentral::deleteIssue($id);
$this->clearEmailedStatus(array($this->getIssueByID($id)));
$this->getDB()->queryWrite("delete from " . $this->issuesTable . " where id=%d", $id);
} else if($status == 'ignoreC' || $status == 'ignoreP' || $status == 'new'){
$this->getDB()->queryWrite("update " . $this->issuesTable . " set status='%s' where id=%d", $status, $id);
if (wfCentral::isConnected()) {
$issue = $this->getDB()->querySelect('SELECT * FROM ' . $this->issuesTable . ' where id=%d', $id);
wfCentral::sendIssues($issue);
public function getIssueByID($id) {
$rec = $this->getDB()->querySingleRec("select * from " . $this->issuesTable . " where id=%d", $id);
$rec['data'] = unserialize($rec['data']);
public function getIssueCounts() {
$counts = $wpdb->get_results('SELECT COUNT(*) AS c, status FROM ' . $this->issuesTable . ' WHERE status = "new" OR status = "ignoreP" OR status = "ignoreC" GROUP BY status', ARRAY_A);
foreach ($counts as $row) {
$result[$row['status']] = $row['c'];
public function getIssues($offset = 0, $limit = 100, $ignoredOffset = 0, $ignoredLimit = 100) {
$siteCleaningTypes = array('file', 'checkGSB', 'checkSpamIP', 'commentBadURL', 'knownfile', 'optionBadURL', 'postBadTitle', 'postBadURL', 'spamvertizeCheck', 'suspiciousAdminUsers');
foreach ($siteCleaningTypes as $index => $t) {
$sortTagging .= ' WHEN type = \'' . esc_sql($t) . '\' THEN ' . ((int) $index);
$sortTagging .= ' ELSE 999 END';
$userIni = ini_get('user_ini.filename');
$q1 = $this->getDB()->querySelect("SELECT *, {$sortTagging} AS sortTag FROM " . $this->issuesTable . " WHERE status = 'new' ORDER BY severity DESC, sortTag ASC, type ASC, time DESC LIMIT %d,%d", $offset, $limit);
$q2 = $this->getDB()->querySelect("SELECT *, {$sortTagging} AS sortTag FROM " . $this->issuesTable . " WHERE status = 'ignoreP' OR status = 'ignoreC' ORDER BY severity DESC, sortTag ASC, type ASC, time DESC LIMIT %d,%d", $ignoredOffset, $ignoredLimit);
$q = array_merge($q1, $q2);
$i['data'] = unserialize($i['data']);
$i['timeAgo'] = wfUtils::makeTimeAgo(time() - $i['time']);
$i['displayTime'] = wfUtils::formatLocalTime(get_option('date_format') . ' ' . get_option('time_format'), $i['time']);
$i['longMsg'] = wp_kses($i['longMsg'], 'post');
if($i['status'] == 'new'){
} else if($i['status'] == 'ignoreP' || $i['status'] == 'ignoreC'){
error_log("Issue has bad status: " . $i['status']);
foreach($ret as $status => &$issueList){
for($i = 0; $i < sizeof($issueList); $i++){
if ($issueList[$i]['type'] == 'file' || $issueList[$i]['type'] == 'knownfile') {
if (array_key_exists('realFile', $issueList[$i]['data'])) {
$localFile = $issueList[$i]['data']['realFile'];
$issueList[$i]['data']['realFileToken'] = self::generateRealFileToken($localFile);
$localFile = $issueList[$i]['data']['file'];
if ($localFile != '.htaccess' && $localFile != $userIni) {
$localFile = ABSPATH . '/' . preg_replace('/^[\.\/]+/', '', $localFile);
$localFile = ABSPATH . '/' . $localFile;
if(file_exists($localFile)){
$issueList[$i]['data']['fileExists'] = true;
$issueList[$i]['data']['fileExists'] = '';
if ($issueList[$i]['type'] == 'database') {
$issueList[$i]['data']['optionExists'] = false;
if (!empty($issueList[$i]['data']['site_id'])) {
$table_options = wfDB::blogTable('options', $issueList[$i]['data']['site_id']);
$issueList[$i]['data']['optionExists'] = $wpdb->get_var($wpdb->prepare("SELECT count(*) FROM {$table_options} WHERE option_name = %s", $issueList[$i]['data']['option_name'])) > 0;
$issueList[$i]['issueIDX'] = $i;
if (isset($issueList[$i]['data']['cType'])) {
$issueList[$i]['data']['ucType'] = ucwords($issueList[$i]['data']['cType']);
return $ret; //array of lists of issues by status
public function getPendingIssues($offset = 0, $limit = 100){
$issues = $this->getDB()->querySelect("SELECT * FROM {$this->pendingIssuesTable} ORDER BY id ASC LIMIT %d,%d", $offset, $limit);
$i['data'] = unserialize($i['data']);
public function getFixableIssueCount() {
$issues = $this->getDB()->querySelect("SELECT * FROM {$this->issuesTable} WHERE data LIKE '%s:6:\"canFix\";b:1;%'");
foreach ($issues as $i) {
$i['data'] = unserialize($i['data']);
if (isset($i['data']['canFix']) && $i['data']['canFix']) {
public function getDeleteableIssueCount() {
$issues = $this->getDB()->querySelect("SELECT * FROM {$this->issuesTable} WHERE data LIKE '%s:9:\"canDelete\";b:1;%'");
foreach ($issues as $i) {
$i['data'] = unserialize($i['data']);
if (isset($i['data']['canDelete']) && $i['data']['canDelete']) {
public function getIssueCount() {
return (int) $this->getDB()->querySingle("select COUNT(*) from " . $this->issuesTable . " WHERE status = 'new'");
public function getPendingIssueCount() {
return (int) $this->getDB()->querySingle("select COUNT(*) from " . $this->pendingIssuesTable . " WHERE status = 'new'");
public function getLastIssueUpdateTimestamp() {
return (int) $this->getDB()->querySingle("select MAX(lastUpdated) from " . $this->issuesTable);
public function reconcileUpgradeIssues($report = null, $useCachedValued = false) {
$report = new wfActivityReport();
$updatesNeeded = $report->getUpdatesNeeded($useCachedValued);
if (!$updatesNeeded['core']) {
$this->deleteUpdateIssues('wfUpgrade');
if ($updatesNeeded['plugins']) {
foreach ($updatesNeeded['plugins'] as $p) {
$upgradeNames[$name] = 1;
$upgradeIssues = $this->getDB()->querySelect("SELECT * FROM {$this->issuesTable} WHERE status = 'new' AND type = 'wfPluginUpgrade'");
foreach ($upgradeIssues as $issue) {
$data = unserialize($issue['data']);
if (!isset($upgradeNames[$name])) { //Some plugins don't have a slug associated with them, so we anchor on the name
$this->deleteIssue($issue['id']);
$this->deleteUpdateIssues('wfPluginUpgrade');
if ($updatesNeeded['themes']) {
foreach ($updatesNeeded['themes'] as $t) {
$upgradeNames[$name] = 1;
$upgradeIssues = $this->getDB()->querySelect("SELECT * FROM {$this->issuesTable} WHERE status = 'new' AND type = 'wfThemeUpgrade'");
foreach ($upgradeIssues as $issue) {
$data = unserialize($issue['data']);
if (!isset($upgradeNames[$name])) { //Some themes don't have a slug associated with them, so we anchor on the name
$this->deleteIssue($issue['id']);
$this->deleteUpdateIssues('wfThemeUpgrade');
$this->deleteAllUpdateIssues();
wfScanEngine::refreshScanNotification($this);
private function getDB(){
public function getIssuesTable() {
return $this->issuesTable;
private static function getRealFileTokenKey($realFile) {
return 'wf-real-file-' . base64_encode($realFile);
private static function generateRealFileToken($realFile) {
$key = self::getRealFileTokenKey($realFile);
return wp_create_nonce($key);
public static function verifyRealFileToken($token, $realFile) {
$key = self::getRealFileTokenKey($realFile);
return wp_verify_nonce($token, $key);