/**
  * @param string $striplen
  * @param string $path
  * @param array $only
  * @param array $themes
  * @param array $plugins
  * @param wfScanEngine $engine
  * @throws Exception
  */
 public function __construct($striplen, $path, $only, $themes, $plugins, $engine)
 {
     $this->striplen = $striplen;
     $this->path = $path;
     $this->only = $only;
     $this->startTime = microtime(true);
     if (wfConfig::get('scansEnabled_core')) {
         $this->coreEnabled = true;
     }
     if (wfConfig::get('scansEnabled_plugins')) {
         $this->pluginsEnabled = true;
     }
     if (wfConfig::get('scansEnabled_themes')) {
         $this->themesEnabled = true;
     }
     if (wfConfig::get('scansEnabled_malware')) {
         $this->malwareEnabled = true;
     }
     $this->db = new wfDB();
     //Doing a delete for now. Later we can optimize this to only scan modified files.
     //$this->db->queryWrite("update " . $this->db->prefix() . "wfFileMods set oldMD5 = newMD5");
     $this->db->queryWrite("delete from " . $this->db->prefix() . "wfFileMods");
     $fetchCoreHashesStatus = wordfence::statusStart("Fetching core, theme and plugin file signatures from Wordfence");
     $dataArr = $engine->api->binCall('get_known_files', json_encode(array('plugins' => $plugins, 'themes' => $themes)));
     if ($dataArr['code'] != 200) {
         wordfence::statusEndErr();
         throw new Exception("Got error response from Wordfence servers: " . $dataArr['code']);
     }
     $this->knownFiles = @json_decode($dataArr['data'], true);
     if (!is_array($this->knownFiles)) {
         wordfence::statusEndErr();
         throw new Exception("Invalid response from Wordfence servers.");
     }
     wordfence::statusEnd($fetchCoreHashesStatus, false, true);
     if ($this->malwareEnabled) {
         $malwarePrefixStatus = wordfence::statusStart("Fetching list of known malware files from Wordfence");
         $malwareData = $engine->api->getStaticURL('/malwarePrefixes.bin');
         if (!$malwareData) {
             wordfence::statusEndErr();
             throw new Exception("Could not fetch malware signatures from Wordfence servers.");
         }
         if (strlen($malwareData) % 4 != 0) {
             wordfence::statusEndErr();
             throw new Exception("Malware data received from Wordfence servers was not valid.");
         }
         $this->malwareData = array();
         for ($i = 0; $i < strlen($malwareData); $i += 4) {
             $this->malwareData[substr($malwareData, $i, 4)] = '1';
         }
         wordfence::statusEnd($malwarePrefixStatus, false, true);
     }
     if ($this->path[strlen($this->path) - 1] != '/') {
         $this->path .= '/';
     }
     if (!is_readable($path)) {
         throw new Exception("Could not read directory " . $this->path . " to do scan.");
     }
     $this->haveIssues = array('core' => false, 'themes' => false, 'plugins' => false, 'malware' => false);
     if ($this->coreEnabled) {
         $this->status['core'] = wordfence::statusStart("Comparing core WordPress files against originals in repository");
     } else {
         wordfence::statusDisabled("Skipping core scan");
     }
     if ($this->themesEnabled) {
         $this->status['themes'] = wordfence::statusStart("Comparing open source themes against WordPress.org originals");
     } else {
         wordfence::statusDisabled("Skipping theme scan");
     }
     if ($this->pluginsEnabled) {
         $this->status['plugins'] = wordfence::statusStart("Comparing plugins against WordPress.org originals");
     } else {
         wordfence::statusDisabled("Skipping plugin scan");
     }
     if ($this->malwareEnabled) {
         $this->status['malware'] = wordfence::statusStart("Scanning for known malware files");
     } else {
         wordfence::statusDisabled("Skipping malware scan");
     }
 }
 private function scan_oldVersions()
 {
     $this->statusIDX['oldVersions'] = wordfence::statusStart("Scanning for old themes, plugins and core files");
     if (!function_exists('get_preferred_from_update_core')) {
         require_once ABSPATH . 'wp-admin/includes/update.php';
     }
     $cur = get_preferred_from_update_core();
     $haveIssues = false;
     if (isset($cur->response) && $cur->response == 'upgrade') {
         if ($this->addIssue('wfUpgrade', 1, 'wfUpgrade' . $cur->current, 'wfUpgrade' . $cur->current, "Your WordPress version is out of date", "WordPress version " . $cur->current . " is now available. Please upgrade immediately to get the latest security updates from WordPress.", array('currentVersion' => $this->wp_version, 'newVersion' => $cur->current))) {
             $haveIssues = true;
         }
     }
     $update_plugins = get_site_transient('update_plugins');
     if (isset($update_plugins) && !empty($update_plugins->response)) {
         if (isset($update_plugins) && $update_plugins->response) {
             foreach ($update_plugins->response as $plugin => $vals) {
                 if (!function_exists('get_plugin_data')) {
                     require_once ABSPATH . '/wp-admin/includes/plugin.php';
                 }
                 $pluginFile = wfUtils::getPluginBaseDir() . $plugin;
                 $data = get_plugin_data($pluginFile);
                 $data['newVersion'] = $vals->new_version;
                 $key = 'wfPluginUpgrade' . ' ' . $plugin . ' ' . $data['newVersion'] . ' ' . $data['Version'];
                 if ($this->addIssue('wfPluginUpgrade', 1, $key, $key, "The Plugin \"" . $data['Name'] . "\" needs an upgrade.", "You need to upgrade \"" . $data['Name'] . "\" to the newest version to ensure you have any security fixes the developer has released.", $data)) {
                     $haveIssues = true;
                 }
             }
         }
     }
     $update_themes = get_site_transient('update_themes');
     if (isset($update_themes) && !empty($update_themes->response)) {
         if (!function_exists('get_themes')) {
             require_once ABSPATH . '/wp-includes/theme.php';
         }
         $themes = get_themes();
         foreach ($update_themes->response as $theme => $vals) {
             foreach ($themes as $name => $themeData) {
                 if (strtolower($name) == $theme) {
                     $tData = array('newVersion' => $vals['new_version'], 'package' => $vals['package'], 'URL' => $vals['url'], 'name' => $themeData['Name'], 'version' => $themeData['Version']);
                     $key = 'wfThemeUpgrade' . ' ' . $theme . ' ' . $tData['version'] . ' ' . $tData['newVersion'];
                     if ($this->addIssue('wfThemeUpgrade', 1, $key, $key, "The Theme \"" . $themeData['Name'] . "\" needs an upgrade.", "You need to upgrade \"" . $themeData['Name'] . "\" to the newest version to ensure you have any security fixes the developer has released.", $tData)) {
                         $haveIssues = true;
                     }
                 }
             }
         }
     }
     wordfence::statusEnd($this->statusIDX['oldVersions'], $haveIssues);
 }
 /**
  *
  */
 private function scan_oldVersions()
 {
     $this->statusIDX['oldVersions'] = wordfence::statusStart("Scanning for old themes, plugins and core files");
     $haveIssues = false;
     $update_check = new wfUpdateCheck();
     $update_check->checkAllUpdates();
     // WordPress core updates needed
     if ($update_check->needsCoreUpdate()) {
         if ($this->addIssue('wfUpgrade', 1, 'wfUpgrade' . $update_check->getCoreUpdateVersion(), 'wfUpgrade' . $update_check->getCoreUpdateVersion(), "Your WordPress version is out of date", "WordPress version " . $update_check->getCoreUpdateVersion() . " is now available. Please upgrade immediately to get the latest security updates from WordPress.", array('currentVersion' => $this->wp_version, 'newVersion' => $update_check->getCoreUpdateVersion()))) {
             $haveIssues = true;
         }
     }
     // Plugin updates needed
     if (count($update_check->getPluginUpdates()) > 0) {
         foreach ($update_check->getPluginUpdates() as $plugin) {
             $key = 'wfPluginUpgrade' . ' ' . $plugin['pluginFile'] . ' ' . $plugin['newVersion'] . ' ' . $plugin['Version'];
             if ($this->addIssue('wfPluginUpgrade', 1, $key, $key, "The Plugin \"" . $plugin['Name'] . "\" needs an upgrade.", "You need to upgrade \"" . $plugin['Name'] . "\" to the newest version to ensure you have any security fixes the developer has released.", $plugin)) {
                 $haveIssues = true;
             }
         }
     }
     // Theme updates needed
     if (count($update_check->getThemeUpdates()) > 0) {
         foreach ($update_check->getThemeUpdates() as $theme) {
             $key = 'wfThemeUpgrade' . ' ' . $theme['Name'] . ' ' . $theme['version'] . ' ' . $theme['newVersion'];
             if ($this->addIssue('wfThemeUpgrade', 1, $key, $key, "The Theme \"" . $theme['Name'] . "\" needs an upgrade.", "You need to upgrade \"" . $theme['Name'] . "\" to the newest version to ensure you have any security fixes the developer has released.", $theme)) {
                 $haveIssues = true;
             }
         }
     }
     wordfence::statusEnd($this->statusIDX['oldVersions'], $haveIssues);
 }
 public function scan_suspiciousAdminUsers()
 {
     $this->statusIDX['suspiciousAdminUsers'] = wordfence::statusStart("Scanning for admin users not created through WordPress");
     $haveIssues = false;
     $adminUsers = new wfAdminUserMonitor();
     if ($adminUsers->isEnabled() && ($suspiciousAdmins = $adminUsers->checkNewAdmins())) {
         foreach ($suspiciousAdmins as $userID) {
             $user = new WP_User($userID);
             $key = 'suspiciousAdminUsers' . $userID;
             if ($this->addIssue('suspiciousAdminUsers', 1, $key, $key, "An admin user with the username " . esc_html($user->user_login) . " was created outside of WordPress.", "An admin user with the username " . esc_html($user->user_login) . " was created outside of WordPress. It's\n\t\t\t\tpossible a plugin could have created the account, but if you do not recognize the user, we suggest you remove\n\t\t\t\tit.", array('userID' => $userID))) {
                 $haveIssues = true;
             }
         }
     }
     wordfence::statusEnd($this->statusIDX['suspiciousAdminUsers'], $haveIssues);
 }