public static function runInstall() { if (self::$runInstallCalled) { return; } self::$runInstallCalled = true; if (function_exists('ignore_user_abort')) { ignore_user_abort(true); } $previous_version = get_option('wordfence_version', '0.0.0'); update_option('wordfence_version', WORDFENCE_VERSION); //In case we have a fatal error we don't want to keep running install. //EVERYTHING HERE MUST BE IDEMPOTENT //Remove old legacy cron job if exists wp_clear_scheduled_hook('wordfence_scheduled_scan'); $schema = new wfSchema(); $schema->createAll(); //if not exists wfConfig::setDefaults(); //If not set $restOfSite = wfConfig::get('cbl_restOfSiteBlocked', 'notset'); if ($restOfSite == 'notset') { wfConfig::set('cbl_restOfSiteBlocked', '1'); } //Install new schedule. If schedule config is blank it will install the default 'auto' schedule. wordfence::scheduleScans(); if (wfConfig::get('autoUpdate') == '1') { wfConfig::enableAutoUpdate(); //Sets up the cron } if (!wfConfig::get('apiKey')) { $api = new wfAPI('', wfUtils::getWPVersion()); try { $keyData = $api->call('get_anon_api_key'); if ($keyData['ok'] && $keyData['apiKey']) { wfConfig::set('apiKey', $keyData['apiKey']); } else { throw new Exception("Could not understand the response we received from the Wordfence servers when applying for a free API key."); } } catch (Exception $e) { error_log("Could not fetch free API key from Wordfence: " . $e->getMessage()); return; } } wp_clear_scheduled_hook('wordfence_daily_cron'); wp_clear_scheduled_hook('wordfence_hourly_cron'); if (is_main_site()) { wp_schedule_event(time(), 'daily', 'wordfence_daily_cron'); //'daily' wp_schedule_event(time(), 'hourly', 'wordfence_hourly_cron'); } $db = new wfDB(); if ($db->columnExists('wfHits', 'HTTPHeaders')) { //Upgrade from 3.0.4 global $wpdb; $prefix = $wpdb->base_prefix; $count = $db->querySingle("select count(*) as cnt from {$prefix}" . "wfHits"); if ($count > 20000) { $db->queryWrite("delete from {$prefix}" . "wfHits order by id asc limit " . ($count - 20000)); } $db->dropColumn('wfHits', 'HTTPHeaders'); } //Upgrading from 1.5.6 or earlier needs: $db->createKeyIfNotExists('wfStatus', 'level', 'k2'); if (wfConfig::get('isPaid') == 'free') { wfConfig::set('isPaid', ''); } //End upgrade from 1.5.6 /** @var wpdb $wpdb */ global $wpdb; $prefix = $wpdb->base_prefix; $db->queryWriteIgnoreError("alter table {$prefix}" . "wfConfig modify column val longblob"); $db->queryWriteIgnoreError("alter table {$prefix}" . "wfBlocks add column permanent tinyint UNSIGNED default 0"); $db->queryWriteIgnoreError("alter table {$prefix}" . "wfStatus modify column msg varchar(1000) NOT NULL"); //3.1.2 to 3.1.4 $db->queryWriteIgnoreError("alter table {$prefix}" . "wfBlocks modify column blockedTime bigint signed NOT NULL"); //3.2.1 to 3.2.2 $db->queryWriteIgnoreError("alter table {$prefix}" . "wfLockedOut modify column blockedTime bigint signed NOT NULL"); $db->queryWriteIgnoreError("drop table if exists {$prefix}" . "wfFileQueue"); $db->queryWriteIgnoreError("drop table if exists {$prefix}" . "wfFileChanges"); $result = $wpdb->get_row("SHOW FIELDS FROM {$prefix}wfStatus where field = 'id'"); if (!$result || strtolower($result->Key) != 'pri') { //Adding primary key to this table because some backup apps use primary key during backup. $db->queryWriteIgnoreError("alter table {$prefix}wfStatus add id bigint UNSIGNED NOT NULL auto_increment PRIMARY KEY"); } $optScanEnabled = $db->querySingle("select val from {$prefix}" . "wfConfig where name='scansEnabled_options'"); if ($optScanEnabled != '0' && $optScanEnabled != '1') { $db->queryWrite("update {$prefix}" . "wfConfig set val='1' where name='scansEnabled_options'"); } $optScanEnabled = $db->querySingle("select val from {$prefix}" . "wfConfig where name='scansEnabled_heartbleed'"); if ($optScanEnabled != '0' && $optScanEnabled != '1') { //Enable heartbleed if no value is set. wfConfig::set('scansEnabled_heartbleed', 1); } if (wfConfig::get('cacheType') == 'php' || wfConfig::get('cacheType') == 'falcon') { wfCache::removeCacheDirectoryHtaccess(); } // IPv6 schema changes for 6.0.1 $tables_with_ips = array('wfCrawlers', 'wfBadLeechers', 'wfBlockedIPLog', 'wfBlocks', 'wfHits', 'wfLeechers', 'wfLockedOut', 'wfLocs', 'wfLogins', 'wfReverseCache', 'wfScanners', 'wfThrottleLog', 'wfVulnScanners'); foreach ($tables_with_ips as $ip_table) { $result = $wpdb->get_row("SHOW FIELDS FROM {$prefix}{$ip_table} where field = 'IP'"); if (!$result || strtolower($result->Type) == 'binary(16)') { continue; } $db->queryWriteIgnoreError("ALTER TABLE {$prefix}{$ip_table} 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 {$prefix}{$ip_table} where field = 'IP'"); if (!$result || strtolower($result->Type) != 'binary(16)') { continue; } $db->queryWriteIgnoreError("UPDATE {$prefix}{$ip_table} SET IP = CONCAT(LPAD(CHAR(0xff, 0xff), 12, CHAR(0)), LPAD(\n\tCHAR(\n\t\tCAST(IP as UNSIGNED) >> 24 & 0xFF,\n\t\tCAST(IP as UNSIGNED) >> 16 & 0xFF,\n\t\tCAST(IP as UNSIGNED) >> 8 & 0xFF,\n\t\tCAST(IP as UNSIGNED) & 0xFF\n\t),\n\t4,\n\tCHAR(0)\n))"); } // Fix the data in the country column. // TODO: add version check so this doesn't run on every update. $ip_results = $wpdb->get_results("SELECT * FROM `{$prefix}wfBlockedIPLog` GROUP BY IP"); if ($ip_results) { foreach ($ip_results as $ip_row) { $wpdb->query($wpdb->prepare("UPDATE `{$prefix}wfBlockedIPLog` SET countryCode = %s WHERE IP = %s", wfUtils::IP2Country(wfUtils::inet_ntop($ip_row->IP)), $ip_row->IP)); } } //Must be the final line }
public static function runInstall() { if (self::$runInstallCalled) { return; } self::$runInstallCalled = true; if (function_exists('ignore_user_abort')) { ignore_user_abort(true); } $previous_version = get_option('wordfence_version', '0.0.0'); update_option('wordfence_version', WORDFENCE_VERSION); //In case we have a fatal error we don't want to keep running install. //EVERYTHING HERE MUST BE IDEMPOTENT //Remove old legacy cron job if exists wp_clear_scheduled_hook('wordfence_scheduled_scan'); $schema = new wfSchema(); $schema->createAll(); //if not exists wfConfig::setDefaults(); //If not set $restOfSite = wfConfig::get('cbl_restOfSiteBlocked', 'notset'); if ($restOfSite == 'notset') { wfConfig::set('cbl_restOfSiteBlocked', '1'); } //Install new schedule. If schedule config is blank it will install the default 'auto' schedule. wordfence::scheduleScans(); if (wfConfig::get('autoUpdate') == '1') { wfConfig::enableAutoUpdate(); //Sets up the cron } if (!wfConfig::get('apiKey')) { $api = new wfAPI('', wfUtils::getWPVersion()); try { $keyData = $api->call('get_anon_api_key'); if ($keyData['ok'] && $keyData['apiKey']) { wfConfig::set('apiKey', $keyData['apiKey']); } else { throw new Exception("Could not understand the response we received from the Wordfence servers when applying for a free API key."); } } catch (Exception $e) { error_log("Could not fetch free API key from Wordfence: " . $e->getMessage()); return; } } wp_clear_scheduled_hook('wordfence_daily_cron'); wp_clear_scheduled_hook('wordfence_hourly_cron'); if (is_main_site()) { wp_schedule_event(time(), 'daily', 'wordfence_daily_cron'); //'daily' wp_schedule_event(time(), 'hourly', 'wordfence_hourly_cron'); } $db = new wfDB(); if ($db->columnExists('wfHits', 'HTTPHeaders')) { //Upgrade from 3.0.4 global $wpdb; $prefix = $wpdb->base_prefix; $count = $db->querySingle("select count(*) as cnt from {$prefix}" . "wfHits"); if ($count > 20000) { $db->queryWrite("delete from {$prefix}" . "wfHits order by id asc limit " . ($count - 20000)); } $db->dropColumn('wfHits', 'HTTPHeaders'); } //Upgrading from 1.5.6 or earlier needs: $db->createKeyIfNotExists('wfStatus', 'level', 'k2'); if (wfConfig::get('isPaid') == 'free') { wfConfig::set('isPaid', ''); } //End upgrade from 1.5.6 /** @var wpdb $wpdb */ global $wpdb; $prefix = $wpdb->base_prefix; $db->queryWriteIgnoreError("alter table {$prefix}" . "wfConfig modify column val longblob"); $db->queryWriteIgnoreError("alter table {$prefix}" . "wfBlocks add column permanent tinyint UNSIGNED default 0"); $db->queryWriteIgnoreError("alter table {$prefix}" . "wfStatus modify column msg varchar(1000) NOT NULL"); //3.1.2 to 3.1.4 $db->queryWriteIgnoreError("alter table {$prefix}" . "wfBlocks modify column blockedTime bigint signed NOT NULL"); //3.2.1 to 3.2.2 $db->queryWriteIgnoreError("alter table {$prefix}" . "wfLockedOut modify column blockedTime bigint signed NOT NULL"); $db->queryWriteIgnoreError("drop table if exists {$prefix}" . "wfFileQueue"); $db->queryWriteIgnoreError("drop table if exists {$prefix}" . "wfFileChanges"); $result = $wpdb->get_row("SHOW FIELDS FROM {$prefix}wfStatus where field = 'id'"); if (!$result || strtolower($result->Key) != 'pri') { //Adding primary key to this table because some backup apps use primary key during backup. $db->queryWriteIgnoreError("alter table {$prefix}wfStatus add id bigint UNSIGNED NOT NULL auto_increment PRIMARY KEY"); } $optScanEnabled = $db->querySingle("select val from {$prefix}" . "wfConfig where name='scansEnabled_options'"); if ($optScanEnabled != '0' && $optScanEnabled != '1') { $db->queryWrite("update {$prefix}" . "wfConfig set val='1' where name='scansEnabled_options'"); } $optScanEnabled = $db->querySingle("select val from {$prefix}" . "wfConfig where name='scansEnabled_heartbleed'"); if ($optScanEnabled != '0' && $optScanEnabled != '1') { //Enable heartbleed if no value is set. wfConfig::set('scansEnabled_heartbleed', 1); } if (wfConfig::get('cacheType') == 'php' || wfConfig::get('cacheType') == 'falcon') { wfCache::removeCacheDirectoryHtaccess(); } // IPv6 schema changes for 6.0.1 $tables_with_ips = array('wfCrawlers', 'wfBadLeechers', 'wfBlockedIPLog', 'wfBlocks', 'wfHits', 'wfLeechers', 'wfLockedOut', 'wfLocs', 'wfLogins', 'wfReverseCache', 'wfScanners', 'wfThrottleLog', 'wfVulnScanners'); foreach ($tables_with_ips as $ip_table) { $result = $wpdb->get_row("SHOW FIELDS FROM {$prefix}{$ip_table} where field = 'IP'"); if (!$result || strtolower($result->Type) == 'binary(16)') { continue; } $db->queryWriteIgnoreError("ALTER TABLE {$prefix}{$ip_table} 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 {$prefix}{$ip_table} where field = 'IP'"); if (!$result || strtolower($result->Type) != 'binary(16)') { continue; } $db->queryWriteIgnoreError("UPDATE {$prefix}{$ip_table} SET IP = CONCAT(LPAD(CHAR(0xff, 0xff), 12, CHAR(0)), LPAD(\n\tCHAR(\n\t\tCAST(IP as UNSIGNED) >> 24 & 0xFF,\n\t\tCAST(IP as UNSIGNED) >> 16 & 0xFF,\n\t\tCAST(IP as UNSIGNED) >> 8 & 0xFF,\n\t\tCAST(IP as UNSIGNED) & 0xFF\n\t),\n\t4,\n\tCHAR(0)\n))"); } // Fix the data in the country column. // TODO: add version check so this doesn't run on every update. $ip_results = $wpdb->get_results("SELECT * FROM `{$prefix}wfBlockedIPLog` GROUP BY IP"); if ($ip_results) { foreach ($ip_results as $ip_row) { $wpdb->query($wpdb->prepare("UPDATE `{$prefix}wfBlockedIPLog` SET countryCode = %s WHERE IP = %s", wfUtils::IP2Country(wfUtils::inet_ntop($ip_row->IP)), $ip_row->IP)); } } if (wfConfig::get('other_hideWPVersion')) { wfUtils::hideReadme(); } $colsFor610 = array('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 = $wpdb->base_prefix . 'wfHits'; foreach ($colsFor610 as $col => $colDefintion) { $count = $wpdb->get_col($wpdb->prepare(<<<SQL SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND COLUMN_NAME=%s AND TABLE_NAME=%s SQL , $col, $hitTable)); if (!$count) { $wpdb->query("ALTER TABLE {$hitTable} ADD COLUMN {$colDefintion}"); } } $has404 = $wpdb->get_col($wpdb->prepare(<<<SQL SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND COLUMN_NAME='is404' AND TABLE_NAME=%s SQL , $hitTable)); if ($has404) { $wpdb->query(<<<SQL UPDATE {$hitTable} SET statusCode= CASE WHEN is404=1 THEN 404 ELSE 200 END SQL ); $wpdb->query("ALTER TABLE {$hitTable} DROP COLUMN `is404`"); } $loginsTable = "{$wpdb->base_prefix}wfLogins"; $hasHitID = $wpdb->get_col($wpdb->prepare(<<<SQL SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND COLUMN_NAME='hitID' AND TABLE_NAME=%s SQL , $loginsTable)); if (!$hasHitID) { $wpdb->query("ALTER TABLE {$loginsTable} ADD COLUMN hitID int(11) DEFAULT NULL AFTER `id`, ADD INDEX(hitID)"); } if (!WFWAF_SUBDIRECTORY_INSTALL) { try { wfWAF::getInstance()->getStorageEngine()->setConfig('wafDisabled', false); } catch (wfWAFStorageFileException $e) { error_log($e); } } // Call this before creating the index in cases where the wp-cron isn't running. self::trimWfHits(); $hitsTable = "{$wpdb->base_prefix}wfHits"; $hasAttackLogTimeIndex = $wpdb->get_var($wpdb->prepare(<<<SQL SELECT COLUMN_KEY FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s AND COLUMN_NAME = 'attackLogTime' SQL , $hitsTable)); if (!$hasAttackLogTimeIndex) { $wpdb->query("ALTER TABLE {$hitsTable} ADD INDEX `attackLogTime` (`attackLogTime`)"); } //Must be the final line }
public static function runInstall() { if (self::$runInstallCalled) { return; } self::$runInstallCalled = true; update_option('wordfence_version', WORDFENCE_VERSION); //In case we have a fatal error we don't want to keep running install. //EVERYTHING HERE MUST BE IDEMPOTENT //Remove old legacy cron job if exists wp_clear_scheduled_hook('wordfence_scheduled_scan'); $restOfSite = wfConfig::get('cbl_restOfSiteBlocked', 'notset'); if ($restOfSite == 'notset') { wfConfig::set('cbl_restOfSiteBlocked', '1'); } $schema = new wfSchema(); $schema->createAll(); //if not exists wfConfig::setDefaults(); //If not set //Install new schedule. If schedule config is blank it will install the default 'auto' schedule. wordfence::scheduleScans(); if (wfConfig::get('autoUpdate') == '1') { wfConfig::enableAutoUpdate(); //Sets up the cron } if (!wfConfig::get('apiKey')) { $api = new wfAPI('', wfUtils::getWPVersion()); try { $keyData = $api->call('get_anon_api_key'); if ($keyData['ok'] && $keyData['apiKey']) { wfConfig::set('apiKey', $keyData['apiKey']); } else { throw new Exception("Could not understand the response we received from the Wordfence servers when applying for a free API key."); } } catch (Exception $e) { error_log("Could not fetch free API key from Wordfence: " . $e->getMessage()); return; } } wp_clear_scheduled_hook('wordfence_daily_cron'); wp_clear_scheduled_hook('wordfence_hourly_cron'); wp_schedule_event(time(), 'daily', 'wordfence_daily_cron'); //'daily' wp_schedule_event(time(), 'hourly', 'wordfence_hourly_cron'); $db = new wfDB(); if ($db->columnExists('wfHits', 'HTTPHeaders')) { //Upgrade from 3.0.4 global $wpdb; $prefix = $wpdb->base_prefix; $count = $db->querySingle("select count(*) as cnt from {$prefix}" . "wfHits"); if ($count > 20000) { $db->queryWrite("delete from {$prefix}" . "wfHits order by id asc limit " . ($count - 20000)); } $db->dropColumn('wfHits', 'HTTPHeaders'); } //Upgrading from 1.5.6 or earlier needs: $db->createKeyIfNotExists('wfStatus', 'level', 'k2'); if (wfConfig::get('isPaid') == 'free') { wfConfig::set('isPaid', ''); } //End upgrade from 1.5.6 global $wpdb; $prefix = $wpdb->base_prefix; $db->queryWriteIgnoreError("alter table {$prefix}" . "wfConfig modify column val longblob"); $db->queryWriteIgnoreError("alter table {$prefix}" . "wfBlocks add column permanent tinyint UNSIGNED default 0"); $db->queryWriteIgnoreError("alter table {$prefix}" . "wfStatus modify column msg varchar(1000) NOT NULL"); //3.1.2 to 3.1.4 $db->queryWriteIgnoreError("alter table {$prefix}" . "wfBlocks modify column blockedTime bigint signed NOT NULL"); //3.2.1 to 3.2.2 $db->queryWriteIgnoreError("alter table {$prefix}" . "wfLockedOut modify column blockedTime bigint signed NOT NULL"); $db->queryWriteIgnoreError("drop table if exists {$prefix}" . "wfFileQueue"); $db->queryWriteIgnoreError("drop table if exists {$prefix}" . "wfFileChanges"); $optScanEnabled = $db->querySingle("select val from {$prefix}" . "wfConfig where name='scansEnabled_options'"); if ($optScanEnabled != '0' && $optScanEnabled != '1') { $db->queryWrite("update {$prefix}" . "wfConfig set val='1' where name='scansEnabled_options'"); } $optScanEnabled = $db->querySingle("select val from {$prefix}" . "wfConfig where name='scansEnabled_heartbleed'"); if ($optScanEnabled != '0' && $optScanEnabled != '1') { //Enable heartbleed if no value is set. wfConfig::set('scansEnabled_heartbleed', 1); } //Must be the final line }