: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
$storage = $this->getStorageEngine();
$cron = (array) $storage->getConfig('cron', null, 'livewaf');
/** @var wfWAFCronEvent $event */
$cronDeduplication = array();
foreach ($cron as $index => $event) {
if (is_object($event) && $event instanceof wfWAFCronEvent) {
if ($event->isInPast()) {
$newEvent = $event->reschedule();
$className = get_class($newEvent);
if ($newEvent instanceof wfWAFCronEvent && $newEvent !== $event && !in_array($className, $cronDeduplication)) {
$cron[$index] = $newEvent;
$cronDeduplication[] = $className;
$className = get_class($event);
if (in_array($className, $cronDeduplication)) {
$cronDeduplication[] = $className;
else { //Remove bad/corrupt records
$storage->setConfig('cron', $cron, 'livewaf');
if ($updated && method_exists($storage, 'saveConfig')) {
$storage->saveConfig('livewaf');
foreach ($run as $index => $event) {
public function whitelistFailedRulesIfNot404() {
/** @var WP_Query $wp_query */
if (defined('ABSPATH') &&
isset($wp_query) && class_exists('WP_Query') && $wp_query instanceof WP_Query &&
method_exists($wp_query, 'is_404') && $wp_query->is_404() &&
function_exists('is_admin') && !is_admin()) {
$this->whitelistFailedRules();
public function isIPBlocked($ip) {
return parent::isIPBlocked($ip);
* @param wfWAFRequest $request
* @return bool|string false if it should not be blocked, otherwise true or a reason for blocking
public function willPerformFinalAction($request) {
$disableWAFIPBlocking = $this->getStorageEngine()->getConfig('disableWAFIPBlocking', null, 'synced');
$advancedBlockingEnabled = $this->getStorageEngine()->getConfig('advancedBlockingEnabled', null, 'synced');
if ($disableWAFIPBlocking || !$advancedBlockingEnabled) {
return wfWAFIPBlocksController::currentController()->shouldBlockRequest($request);
public function uninstall() {
@unlink(rtrim(WFWAF_LOG_PATH, '/') . '/.htaccess');
@unlink(rtrim(WFWAF_LOG_PATH, '/') . '/template.php');
@unlink(rtrim(WFWAF_LOG_PATH, '/') . '/GeoLite2-Country.mmdb');
self::_recursivelyRemoveWflogs(''); //Removes any remaining files and the directory itself
* Removes a path within wflogs, recursing as necessary.
* @param array $processedDirs
* @return array The list of removed files/folders.
private static function _recursivelyRemoveWflogs($file, $processedDirs = array()) {
if (preg_match('~(?:^|/|\\\\)\.\.(?:/|\\\\|$)~', $file)) {
if (stripos(WFWAF_LOG_PATH, 'wflogs') === false) { //Sanity check -- if not in a wflogs folder, user will have to do removal manually
$path = rtrim(WFWAF_LOG_PATH, '/') . '/' . $file;
if (in_array($real, $processedDirs)) {
$processedDirs[] = $real;
while ($sub = readdir($dir)) {
if ($sub == '.' || $sub == '..') { continue; }
foreach ($contents as $f) {
$removed = self::_recursivelyRemoveWflogs($file . '/' . $f, $processedDirs);
$filesRemoved = array($filesRemoved, $removed);
public function fileList() {
$fileList = parent::fileList();
$fileList[] = rtrim(WFWAF_LOG_PATH, '/') . '/.htaccess';
$fileList[] = rtrim(WFWAF_LOG_PATH, '/') . '/template.php';
$fileList[] = rtrim(WFWAF_LOG_PATH, '/') . '/GeoLite2-Country.mmdb';
* @return wfWAFRunException
public function getLearningModeAttackException() {
return $this->learningModeAttackException;
* @param wfWAFRunException $learningModeAttackException
public function setLearningModeAttackException($learningModeAttackException) {
$this->learningModeAttackException = $learningModeAttackException;
public static function permissions() {
if (defined('WFWAF_LOG_FILE_MODE')) {
return WFWAF_LOG_FILE_MODE;
if (class_exists('wfWAFStorageFile') && method_exists('wfWAFStorageFile', 'permissions')) {
return wfWAFStorageFile::permissions();
static $_cachedPermissions = null;
if ($_cachedPermissions === null) {
if (defined('WFWAF_LOG_PATH')) {
$template = rtrim(WFWAF_LOG_PATH . '/') . '/template.php';
if (file_exists($template)) {
$stat = @stat($template);
if (($mode & 0020) == 0020) {
$updatedMode = $updatedMode | 0060;
$_cachedPermissions = $updatedMode;
return $_cachedPermissions;
public static function writeHtaccess() {
@file_put_contents(rtrim(WFWAF_LOG_PATH, '/') . '/.htaccess', <<<APACHE
<IfModule mod_authz_core.c>
<IfModule !mod_authz_core.c>
@chmod(rtrim(WFWAF_LOG_PATH, '/') . '/.htaccess', (wfWAFWordPress::permissions() | 0444));
public function getGlobal($global) {
if (wfWAFUtils::strpos($global, '.') === false) {
list($prefix, $_global) = explode('.', $global);
if ($_global === 'core') {
return $this->getStorageEngine()->getConfig('wordpressVersion', null, 'synced');
} else if ($_global === 'plugins') {
return $this->getStorageEngine()->getConfig('wordpressPluginVersions', null, 'synced');
} else if ($_global === 'themes') {
return $this->getStorageEngine()->getConfig('wordpressThemeVersions', null, 'synced');
return parent::getGlobal($global);
class wfWAFWordPressStorageMySQL extends wfWAFStorageMySQL {
public function getSerializedParams() {
$params = parent::getSerializedParams();
$params[] = 'wordpressPluginVersions';
$params[] = 'wordpressThemeVersions';
public function getAutoloadParams() {
$params = parent::getAutoloadParams();
$params['synced'][] = 'wordpressVersion';
$params['synced'][] = 'wordpressPluginVersions';
$params['synced'][] = 'wordpressThemeVersions';
class wfWAFWordPressI18n implements wfWAFI18nEngine {
/** @var wfWAFStorageInterface */
* @param wfWAFStorageInterface $storageEngine
public function __construct($storageEngine) {
$this->storageEngine = $storageEngine;
$this->loadTranslations();
public function __($text) {
if (!$this->storageEngine->getConfig('wordfenceI18n', true, 'synced')) {
$translated = $this->mo->translate($text);
protected function loadTranslations() {
require_once dirname(__FILE__) . '/pomo/mo.php';
$currentLocale = $this->storageEngine->getConfig('WPLANG', '', 'synced');
// Find translation file for the current language.
$mofile = dirname(__FILE__) . '/../languages/wordfence-' . $currentLocale . '.mo';
if (!file_exists($mofile)) {
// No translation, use the default
$mofile = dirname(__FILE__) . '/../languages/wordfence.mo';
return $this->mo->import_from_file( $mofile );
if (!defined('WFWAF_LOG_PATH')) {
if (!defined('WP_CONTENT_DIR')) { //Loading before WordPress
define('WFWAF_LOG_PATH', WP_CONTENT_DIR . '/wflogs/');
if (!is_dir(WFWAF_LOG_PATH)) {
@mkdir(WFWAF_LOG_PATH, (wfWAFWordPress::permissions() | 0755));
@chmod(WFWAF_LOG_PATH, (wfWAFWordPress::permissions() | 0755));
wfWAFWordPress::writeHtaccess();
if (!defined('WFWAF_STORAGE_ENGINE') && isset($_SERVER['WFWAF_STORAGE_ENGINE'])) {
define('WFWAF_STORAGE_ENGINE', $_SERVER['WFWAF_STORAGE_ENGINE']);
else if (!defined('WFWAF_STORAGE_ENGINE') && (WF_IS_WP_ENGINE || WF_IS_FLYWHEEL)) {
define('WFWAF_STORAGE_ENGINE', 'mysqli');
$specifiedStorageEngine = defined('WFWAF_STORAGE_ENGINE');
$fallbackStorageEngine = false;
if ($specifiedStorageEngine) {
switch (WFWAF_STORAGE_ENGINE) {
$wfWAFDBCredentials = array();
$overrideConstants = array(
'wfWAFDBCredentials' => array(
'WFWAF_DB_NAME' => 'database',
'WFWAF_DB_USER' => 'user',
'WFWAF_DB_PASSWORD' => 'pass',
'WFWAF_DB_HOST' => 'host',
'WFWAF_DB_CHARSET' => 'charset',
'WFWAF_DB_COLLATE' => 'collation',
'WFWAF_MYSQL_CLIENT_FLAGS' => 'flags',
'WFWAF_TABLE_PREFIX' => 'tablePrefix'
'WFWAF_DB_SSL_KEY' => 'key',
'WFWAF_DB_SSL_CERTIFICATE' => 'certificate',
'WFWAF_DB_SSL_CA_CERTIFICATE' => 'ca_certificate',
'WFWAF_DB_SSL_CA_PATH' => 'ca_path',
'WFWAF_DB_SSL_CIPHER_ALGOS' => 'cipher_algos'
foreach ($overrideConstants as $variable => $constants) {
foreach ($constants as $constant => $key) {
if (defined($constant)) {
${$variable}[$key] = constant($constant);
// Find the wp-config.php
if (is_dir(dirname(WFWAF_LOG_PATH))) {
if (file_exists(dirname(WFWAF_LOG_PATH) . '/../wp-config.php')) {
wfWAFUtils::extractCredentialsWPConfig(dirname(WFWAF_LOG_PATH) . '/../wp-config.php', $wfWAFDBCredentials);
} else if (file_exists(dirname(WFWAF_LOG_PATH) . '/../../wp-config.php')) {
wfWAFUtils::extractCredentialsWPConfig(dirname(WFWAF_LOG_PATH) . '/../../wp-config.php', $wfWAFDBCredentials);
} else if (!empty($_SERVER['DOCUMENT_ROOT'])) {
if (file_exists($_SERVER['DOCUMENT_ROOT'] . '/wp-config.php')) {
wfWAFUtils::extractCredentialsWPConfig($_SERVER['DOCUMENT_ROOT'] . '/wp-config.php', $wfWAFDBCredentials);
} else if (file_exists($_SERVER['DOCUMENT_ROOT'] . '/../wp-config.php')) {
wfWAFUtils::extractCredentialsWPConfig($_SERVER['DOCUMENT_ROOT'] . '/../wp-config.php', $wfWAFDBCredentials);
$wfWAFDBCredentials = false;
if (!empty($wfWAFDBCredentials)) {
$wfWAFStorageEngine = new wfWAFWordPressStorageMySQL(new wfWAFStorageEngineMySQLi(), $wfWAFDBCredentials['tablePrefix'], wfShutdownRegistry::getDefaultInstance());
$wfWAFStorageEngine->getDb()->connect(
$wfWAFDBCredentials['user'],
$wfWAFDBCredentials['pass'],
$wfWAFDBCredentials['database'],
!empty($wfWAFDBCredentials['ipv6']) ? '[' . $wfWAFDBCredentials['host'] . ']' : $wfWAFDBCredentials['host'],
!empty($wfWAFDBCredentials['port']) ? $wfWAFDBCredentials['port'] : null,
!empty($wfWAFDBCredentials['socket']) ? $wfWAFDBCredentials['socket'] : null,
array_key_exists('flags', $wfWAFDBCredentials) ? $wfWAFDBCredentials['flags'] : 0,
if (array_key_exists('charset', $wfWAFDBCredentials)) {
$wfWAFStorageEngine->getDb()
->setCharset($wfWAFDBCredentials['charset'],
!empty($wfWAFDBCredentials['collation']) ? $wfWAFDBCredentials['collation'] : '');
if (defined('ABSPATH')) {
$optionName = 'wordfence_installed'; //Also exists in wfConfig.php
if (is_multisite() && function_exists('get_network_option')) {
$tableExists = get_network_option(null, $optionName, null);
$tableExists = get_option($optionName, null);
$wfWAFStorageEngine->installing = !$tableExists;
$wfWAFStorageEngine->getDb()->installing = $wfWAFStorageEngine->installing;
unset($wfWAFDBCredentials);
if (empty($wfWAFStorageEngine)) {
$wfWAFStorageEngine = new wfWAFStorageFile(
WFWAF_LOG_PATH . 'attack-data.php',
WFWAF_LOG_PATH . 'ips.php',
WFWAF_LOG_PATH . 'config.php',
WFWAF_LOG_PATH . 'rules.php',
WFWAF_LOG_PATH . 'wafRules.rules'
if ($specifiedStorageEngine)
$fallbackStorageEngine = true;
wfWAF::setSharedStorageEngine($wfWAFStorageEngine, $fallbackStorageEngine);
wfWAF::setInstance(new wfWAFWordPress(wfWAFWordPressRequest::createFromGlobals(), wfWAF::getSharedStorageEngine()));
wfWAF::getInstance()->getEventBus()->attach(new wfWAFWordPressObserver(wfWAF::getInstance()));
if ($wfWAFStorageEngine instanceof wfWAFStorageFile) {
WFWAF_LOG_PATH . 'rules.php',
// WFWAF_PATH . 'rules.php',
foreach ($rulesFiles as $rulesFile) {
if (!file_exists($rulesFile) && !wfWAF::getInstance()->isReadOnly()) {
@chmod($rulesFile, (wfWAFWordPress::permissions() | 0444));
if (is_writable($rulesFile)) {
wfWAF::getInstance()->setCompiledRulesFile($rulesFile);
} else if ($wfWAFStorageEngine instanceof wfWAFStorageMySQL) {
$wfWAFStorageEngine->runMigrations();
$wfWAFStorageEngine->setDefaults();
if (!wfWAF::getInstance()->isReadOnly()) {
if (wfWAF::getInstance()->getStorageEngine()->needsInitialRules()) {
if (wfWAF::getInstance()->getStorageEngine()->getConfig('apiKey', null, 'synced') !== null &&
wfWAF::getInstance()->getStorageEngine()->getConfig('createInitialRulesDelay', null, 'transient') < time()
$event = new wfWAFCronFetchRulesEvent(time() - 60);
$event->setWaf(wfWAF::getInstance());
wfWAF::getInstance()->getStorageEngine()->setConfig('createInitialRulesDelay', time() + (5 * 60), 'transient');
} catch (wfWAFBuildRulesException $e) {
error_log($e->getMessage());
error_log($e->getMessage());
if (WFWAF_DEBUG && file_exists(wfWAF::getInstance()->getStorageEngine()->getRulesDSLCacheFile())) {
wfWAF::getInstance()->updateRuleSet(file_get_contents(wfWAF::getInstance()->getStorageEngine()->getRulesDSLCacheFile()), false);
} catch (wfWAFBuildRulesException $e) {
$GLOBALS['wfWAFDebugBuildException'] = $e;
$GLOBALS['wfWAFDebugBuildException'] = $e;