: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
'wfBlocks', //Removed in 7.0.1 but left in in case migrating from really old
foreach ($tables_with_ips as $ip_table) {
$ptable = wfDB::networkTable($ip_table);
$tableExists = $wpdb->get_col($wpdb->prepare(<<<SQL
SELECT TABLE_NAME FROM information_schema.TABLES
WHERE TABLE_SCHEMA=DATABASE()
$result = $wpdb->get_row("SHOW FIELDS FROM {$ptable} where field = 'IP'");
if (!$result || strtolower($result->Type) == 'binary(16)') {
$db->queryWriteIgnoreError("ALTER TABLE {$ptable} MODIFY IP BINARY(16)");
// Just to be sure we don't corrupt the data if the alter fails.
$result = $wpdb->get_row("SHOW FIELDS FROM {$ptable} where field = 'IP'");
if (!$result || strtolower($result->Type) != 'binary(16)') {
$db->queryWriteIgnoreError("UPDATE {$ptable} SET IP = CONCAT(LPAD(CHAR(0xff, 0xff), 12, CHAR(0)), LPAD(
CAST(IP as UNSIGNED) >> 24 & 0xFF,
CAST(IP as UNSIGNED) >> 16 & 0xFF,
CAST(IP as UNSIGNED) >> 8 & 0xFF,
CAST(IP as UNSIGNED) & 0xFF
//Country reassignment moved to the GeoIP file sync segment
if (wfConfig::get('other_hideWPVersion')) {
'attackLogTime' => '`attackLogTime` double(17,6) unsigned NOT NULL AFTER `id`',
'statusCode' => '`statusCode` int(11) NOT NULL DEFAULT 0 AFTER `jsRun`',
'action' => "`action` varchar(64) NOT NULL DEFAULT '' AFTER `UA`",
'actionDescription' => '`actionDescription` text AFTER `action`',
'actionData' => '`actionData` text AFTER `actionDescription`',
$hitTable = wfDB::networkTable('wfHits');
foreach ($colsFor610 as $col => $colDefintion) {
$count = $wpdb->get_col($wpdb->prepare(<<<SQL
SELECT * FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA=DATABASE()
$wpdb->query("ALTER TABLE $hitTable ADD COLUMN $colDefintion");
$has404 = $wpdb->get_col($wpdb->prepare(<<<SQL
SELECT * FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA=DATABASE()
$wpdb->query("ALTER TABLE $hitTable DROP COLUMN `is404`");
$loginsTable = wfDB::networkTable('wfLogins');
$hasHitID = $wpdb->get_col($wpdb->prepare(<<<SQL
SELECT * FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA=DATABASE()
$wpdb->query("ALTER TABLE $loginsTable ADD COLUMN hitID int(11) DEFAULT NULL AFTER `id`, ADD INDEX(hitID)");
if (!WFWAF_SUBDIRECTORY_INSTALL) {
wfWAFConfig::set('wafDisabled', false);
// Call this before creating the index in cases where the wp-cron isn't running.
$hitsTable = wfDB::networkTable('wfHits');
$hasAttackLogTimeIndex = $wpdb->get_var($wpdb->prepare(<<<SQL
SELECT COLUMN_KEY FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND COLUMN_NAME = 'attackLogTime'
if (!$hasAttackLogTimeIndex) {
$wpdb->query("ALTER TABLE $hitsTable ADD INDEX `attackLogTime` (`attackLogTime`)");
$allowed404s = wfConfig::get('allowed404s', '');
if (!wfConfig::get('allowed404s6116Migration', false)) {
if (!preg_match('/(?:^|\b)browserconfig\.xml(?:\b|$)/i', $allowed404s)) {
if (strlen($allowed404s) > 0) {
$allowed404s .= "/browserconfig.xml";
wfConfig::set('allowed404s', $allowed404s);
wfConfig::set('allowed404s6116Migration', 1);
if (wfConfig::get('email_summary_interval') == 'biweekly') {
wfConfig::set('email_summary_interval', 'weekly');
wfConfig::migrateCodeExecutionForUploadsPHP7();
if (!WFWAF_SUBDIRECTORY_INSTALL && class_exists('wfWAFIPBlocksController')) {
wfWAFIPBlocksController::setNeedsSynchronizeConfigSettings(); //changed slightly for 7.0.1
wfCache::removeCaching();
$snipCacheTable = wfDB::networkTable('wfSNIPCache');
$hasType = $wpdb->get_col($wpdb->prepare(<<<SQL
SELECT * FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA=DATABASE()
$wpdb->query("ALTER TABLE `{$snipCacheTable}` ADD `type` INT UNSIGNED NOT NULL DEFAULT '0'");
$wpdb->query("ALTER TABLE `{$snipCacheTable}` ADD INDEX (`type`)");
$fileModsTable = wfDB::networkTable('wfFileMods');
$hasStoppedOn = $wpdb->get_col($wpdb->prepare(<<<SQL
SELECT * FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA=DATABASE()
AND COLUMN_NAME='stoppedOnSignature'
$wpdb->query("ALTER TABLE {$fileModsTable} ADD COLUMN stoppedOnSignature VARCHAR(255) NOT NULL DEFAULT ''");
$wpdb->query("ALTER TABLE {$fileModsTable} ADD COLUMN stoppedOnPosition INT UNSIGNED NOT NULL DEFAULT '0'");
$blockedIPLogTable = wfDB::networkTable('wfBlockedIPLog');
$hasType = $wpdb->get_col($wpdb->prepare(<<<SQL
SELECT * FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA=DATABASE()
AND COLUMN_NAME='blockType'
$wpdb->query("ALTER TABLE {$blockedIPLogTable} ADD blockType VARCHAR(50) NOT NULL DEFAULT 'generic'");
$wpdb->query("ALTER TABLE {$blockedIPLogTable} DROP PRIMARY KEY");
$wpdb->query("ALTER TABLE {$blockedIPLogTable} ADD PRIMARY KEY (IP, unixday, blockType)");
if (!wfConfig::get('migration636_email_summary_excluded_directories')) {
$excluded_directories = explode(',', (string) wfConfig::get('email_summary_excluded_directories'));
$key = array_search('wp-content/plugins/wordfence/tmp', $excluded_directories); if ($key !== false) { unset($excluded_directories[$key]); }
$key = array_search('wp-content/wflogs', $excluded_directories); if ($key === false) { $excluded_directories[] = 'wp-content/wflogs'; }
wfConfig::set('email_summary_excluded_directories', implode(',', $excluded_directories));
wfConfig::set('migration636_email_summary_excluded_directories', 1, wfConfig::DONT_AUTOLOAD);
$fileModsTable = wfDB::networkTable('wfFileMods');
$hasSHAC = $wpdb->get_col($wpdb->prepare(<<<SQL
SELECT * FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA=DATABASE()
$wpdb->query("ALTER TABLE {$fileModsTable} ADD COLUMN `SHAC` BINARY(32) NOT NULL DEFAULT '' AFTER `newMD5`");
$wpdb->query("ALTER TABLE {$fileModsTable} ADD COLUMN `isSafeFile` VARCHAR(1) NOT NULL DEFAULT '?' AFTER `stoppedOnPosition`");
$hooverTable = wfDB::networkTable('wfHoover');
$hostKeySize = $wpdb->get_var($wpdb->prepare(<<<SQL
SELECT CHARACTER_MAXIMUM_LENGTH FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA=DATABASE()
AND COLUMN_NAME='hostKey'
if ($hostKeySize < 124) {
$wpdb->query("ALTER TABLE {$hooverTable} CHANGE `hostKey` `hostKey` VARBINARY(124) NULL DEFAULT NULL");
$scanFileContents = wfConfig::get('scansEnabled_fileContents', false);
if (!wfConfig::get('fileContentsGSB6315Migration', false)) {
if (!$scanFileContents) {
wfConfig::set('scansEnabled_fileContentsGSB', false);
wfConfig::set('fileContentsGSB6315Migration', 1);
$lastBlockAggregation = wfConfig::get('lastBlockAggregation', 0);
if ($lastBlockAggregation == 0) {
wfConfig::set('lastBlockAggregation', time());
if (!wfConfig::get('config701Migration', false)) {
//loginSec_strongPasswds gains a toggle
if (wfConfig::get('loginSec_strongPasswds') == '') {
wfConfig::set('loginSec_strongPasswds', 'pubs');
wfConfig::set('loginSec_strongPasswds_enabled', false);
$limitedOptions = wfScanner::limitedScanTypeOptions();
$standardOptions = wfScanner::standardScanTypeOptions();
$highSensitivityOptions = wfScanner::highSensitivityScanTypeOptions();
$settings = wfScanner::customScanTypeOptions();
if ($settings == $limitedOptions) { wfConfig::set('scanType', wfScanner::SCAN_TYPE_LIMITED); }
else if ($settings == $standardOptions) { wfConfig::set('scanType', wfScanner::SCAN_TYPE_STANDARD); }
else if ($settings == $highSensitivityOptions) { wfConfig::set('scanType', wfScanner::SCAN_TYPE_HIGH_SENSITIVITY); }
else { wfConfig::set('scanType', wfScanner::SCAN_TYPE_CUSTOM); }
if (wfConfig::get('isPaid')) {
wfConfig::set('keyType', wfLicense::KEY_TYPE_PAID_CURRENT);
wfConfig::remove('premiumAutoRenew');
wfConfig::remove('premiumNextRenew');
wfConfig::remove('premiumPaymentExpiring');
wfConfig::remove('premiumPaymentExpired');
wfConfig::remove('premiumPaymentMissing');
wfConfig::remove('premiumPaymentHold');
wfConfig::set('config701Migration', 1);
//---- wfBlocks migration
$oldBlocksTable = wfDB::networkTable('wfBlocks');
$blocksTable = wfBlock::blocksTable();
$oldBlocksExist = $wpdb->get_col($wpdb->prepare(<<<SQL
SELECT TABLE_NAME FROM information_schema.TABLES
WHERE TABLE_SCHEMA=DATABASE()
if ($oldBlocksExist && !wfConfig::get('blocks701Migration', false)) {
$query = $wpdb->prepare("INSERT INTO `{$blocksTable}` (`type`, `IP`, `blockedTime`, `reason`, `lastAttempt`, `blockedHits`, `expiration`) SELECT CASE
WHEN wfsn = 1 AND permanent = 0 THEN %d
WHEN wfsn = 0 AND permanent = 0 THEN %d
WHEN wfsn = 0 AND permanent = 1 THEN %d
END AS `type`, `IP`, `blockedTime`, `reason`, `lastAttempt`, `blockedHits`, CASE
WHEN wfsn = 1 AND permanent = 0 THEN (`blockedTime` + 600)
WHEN wfsn = 0 AND permanent = 0 THEN (`blockedTime` + %d)
WHEN wfsn = 0 AND permanent = 1 THEN 0
END AS `expiration` FROM `{$oldBlocksTable}`", wfBlock::TYPE_WFSN_TEMPORARY, wfBlock::TYPE_RATE_BLOCK, wfBlock::TYPE_IP_AUTOMATIC_PERMANENT, wfConfig::get('blockedTime'));
$advancedBlocksTable = wfDB::networkTable('wfBlocksAdv');
$advancedBlocks = $wpdb->get_results("SELECT * FROM {$advancedBlocksTable}", ARRAY_A);
foreach ($advancedBlocks as $b) {
$blockType = $b['blockType']; //unused
$blockString = $b['blockString'];
$ctime = (int) $b['ctime'];
$totalBlocked = (int) $b['totalBlocked'];
$lastBlocked = (int) $b['lastBlocked'];
list($ipRange, $uaRange, $referrer, $hostname) = explode('|', $blockString);
wfBlock::createPattern($reason, $ipRange, $hostname, $uaRange, $referrer, wfBlock::DURATION_FOREVER, $ctime, $lastBlocked, $totalBlocked);
$throttleTable = wfDB::networkTable('wfThrottleLog');
$throttles = $wpdb->get_results("SELECT * FROM {$throttleTable}", ARRAY_A);
foreach ($throttles as $t) {
$ip = wfUtils::inet_ntop($t['IP']);
$startTime = (int) $t['startTime'];
$endTime = (int) $t['endTime'];
$timesThrottled = (int) $t['timesThrottled'];
$reason = $t['lastReason'];
wfBlock::createRateThrottle($reason, $ip, wfBlock::rateLimitThrottleDuration(), $startTime, $endTime, $timesThrottled);
$lockoutTable = wfDB::networkTable('wfLockedOut');
$lockouts = $wpdb->get_results("SELECT * FROM {$lockoutTable}", ARRAY_A);
foreach ($lockouts as $l) {
$ip = wfUtils::inet_ntop($l['IP']);
$blockedTime = (int) $l['blockedTime'];
$lastAttempt = (int) $l['lastAttempt'];
$blockedHits = (int) $l['blockedHits'];
wfBlock::createLockout($reason, $ip, wfBlock::lockoutDuration(), $blockedTime, $lastAttempt, $blockedHits);
//country blocking migration
$countries = wfConfig::get('cbl_countries', false);
$countries = explode(',', $countries);
wfBlock::createCountry(__('Automatically generated from previous country blocking settings', 'wordfence'), wfConfig::get('cbl_loginFormBlocked', false), wfConfig::get('cbl_restOfSiteBlocked', false), $countries);
wfConfig::set('blocks701Migration', 1);
//---- wfIssues/wfPendingIssues Schema Change
$issuesTable = wfDB::networkTable('wfIssues');
$pendingIssuesTable = wfDB::networkTable('wfPendingIssues');
$hasLastUpdated = $wpdb->get_col($wpdb->prepare(<<<SQL
SELECT * FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA=DATABASE()
AND COLUMN_NAME='lastUpdated'
$wpdb->query("ALTER TABLE `{$issuesTable}` ADD `lastUpdated` INT UNSIGNED NOT NULL AFTER `time`");
$wpdb->query("ALTER TABLE `{$issuesTable}` ADD INDEX (`lastUpdated`)");
$wpdb->query("ALTER TABLE `{$issuesTable}` ADD INDEX (`status`)");
$wpdb->query("ALTER TABLE `{$issuesTable}` ADD INDEX (`ignoreP`)");
$wpdb->query("ALTER TABLE `{$issuesTable}` ADD INDEX (`ignoreC`)");
$wpdb->query("UPDATE `{$issuesTable}` SET `lastUpdated` = `time` WHERE `lastUpdated` = 0");
$wpdb->query("ALTER TABLE `{$pendingIssuesTable}` ADD `lastUpdated` INT UNSIGNED NOT NULL AFTER `time`");
$wpdb->query("ALTER TABLE `{$pendingIssuesTable}` ADD INDEX (`lastUpdated`)");
$wpdb->query("ALTER TABLE `{$pendingIssuesTable}` ADD INDEX (`status`)");
$wpdb->query("ALTER TABLE `{$pendingIssuesTable}` ADD INDEX (`ignoreP`)");
$wpdb->query("ALTER TABLE `{$pendingIssuesTable}` ADD INDEX (`ignoreC`)");
//---- Scheduled scan start hour and manual type
if (wfConfig::get('schedStartHour') < 0) {
wfConfig::set('schedStartHour', wfWAFUtils::random_int(0, 23));
if (wfConfig::get('schedMode') == 'manual') {
$sched = wfConfig::get_ser('scanSched', array());
if (is_array($sched) && is_array($sched[0])) { //Try to determine the closest matching value for manualScanType
$hours = array_fill(0, 24, 0);
$distinctHours = array();
$days = array_fill(0, 7, 0);
foreach ($sched as $dayIndex => $day) {
foreach ($day as $h => $enabled) {
if (in_array($h, $distinctHours)) {
if (in_array($dayIndex, $distinctDays)) {
$distinctDays[] = $dayIndex;
sort($distinctHours, SORT_NUMERIC);
sort($distinctDays, SORT_NUMERIC);
if (count($distinctDays) == 7) {
if (count($distinctHours) == 1) {
wfConfig::set('manualScanType', wfScanner::MANUAL_SCHEDULING_ONCE_DAILY);
wfConfig::set('schedStartHour', $distinctHours[0]);
else if (count($distinctHours) == 2) {
$matchesTwiceDaily = false;
if ($distinctHours[0] + 12 == $distinctHours[1]) {
$matchesTwiceDaily = true;
foreach ($sched as $dayIndex => $day) {
if (!$day[$distinctHours[0]] || !$day[$distinctHours[1]]) {
$matchesTwiceDaily = false;
if ($matchesTwiceDaily) {
wfConfig::set('manualScanType', wfScanner::MANUAL_SCHEDULING_TWICE_DAILY);
wfConfig::set('schedStartHour', $distinctHours[0]);
wfConfig::set('manualScanType', wfScanner::MANUAL_SCHEDULING_CUSTOM);
wfConfig::set('manualScanType', wfScanner::MANUAL_SCHEDULING_CUSTOM);
else if (count($distinctDays) == 5 && count($distinctHours) == 1) {
if ($days[2] == 0 && $days[4] == 0 && $hours[$distinctHours[0]] == 5) {
wfConfig::set('manualScanType', wfScanner::MANUAL_SCHEDULING_ODD_DAYS_WEEKENDS);
wfConfig::set('schedStartHour', $distinctHours[0]);
else if ($days[0] == 0 && $days[6] == 0 && $hours[$distinctHours[0]] == 5) {
wfConfig::set('manualScanType', wfScanner::MANUAL_SCHEDULING_WEEKDAYS);
wfConfig::set('schedStartHour', $distinctHours[0]);
wfConfig::set('manualScanType', wfScanner::MANUAL_SCHEDULING_CUSTOM);
else if (count($distinctDays) == 2 && count($distinctHours) == 1) {
if ($distinctDays[0] == 0 && $distinctDays[1] == 6 && $hours[$distinctHours[0]] == 2) {
wfConfig::set('manualScanType', wfScanner::MANUAL_SCHEDULING_WEEKENDS);
wfConfig::set('schedStartHour', $distinctHours[0]);
wfConfig::set('manualScanType', wfScanner::MANUAL_SCHEDULING_CUSTOM);
wfConfig::set('manualScanType', wfScanner::MANUAL_SCHEDULING_CUSTOM);
wfOnboardingController::migrateOnboarding();
if (!wfConfig::get('blocks702Migration')) {
$blocksTable = wfBlock::blocksTable();
$query = "UPDATE `{$blocksTable}` SET `type` = %d WHERE `type` = %d AND `parameters` IS NOT NULL AND `parameters` LIKE '%\"ipRange\"%'";
$wpdb->query($wpdb->prepare($query, wfBlock::TYPE_PATTERN, wfBlock::TYPE_IP_AUTOMATIC_PERMANENT));
$countryBlock = wfBlock::countryBlocks();
if (!count($countryBlock)) {
$query = "UPDATE `{$blocksTable}` SET `type` = %d WHERE `type` = %d AND `parameters` IS NOT NULL AND `parameters` LIKE '%\"blockLogin\"%' LIMIT 1";
$wpdb->query($wpdb->prepare($query, wfBlock::TYPE_COUNTRY, wfBlock::TYPE_IP_AUTOMATIC_PERMANENT));
$query = "DELETE FROM `{$blocksTable}` WHERE `type` = %d AND `parameters` IS NOT NULL AND `parameters` LIKE '%\"blockLogin\"%'";
$wpdb->query($wpdb->prepare($query, wfBlock::TYPE_IP_AUTOMATIC_PERMANENT));
wfConfig::set('blocks702Migration', 1);
/*if (!wfConfig::get('generateAllOptionsNotification')) {
new wfNotification(null, wfNotification::PRIORITY_HIGH_WARNING, '<p>Developers: If you prefer to edit all Wordfence options on one page, you can enable the "All Options" page here:</p>
<p><a href="javascript:WFAD.enableAllOptionsPage();" class="wf-btn wf-btn-primary wf-btn-callout-subtle">Enable "All Options" Page</a></p>', 'wfplugin_devalloptions');
wfConfig::set('generateAllOptionsNotification', 1);
if (wfConfig::get('loginSec_maxFailures') == 1) {
wfConfig::set('loginSec_maxFailures', 2);
$blocksTable = wfBlock::blocksTable();
$patternBlocks = wfBlock::patternBlocks();