/**
  * Returns directory contents
  *
  * @since 4.3
  *
  * @param string $dir    the directory to scan
  * @param string $parent the parent directory (if needed
  *
  * @return array
  */
 private function get_files($dir = '', $parent = null)
 {
     if ($parent === null) {
         $parent = ITSEC_Lib::get_home_path();
     }
     $rel_dir = trim(sanitize_text_field($dir));
     $directory = trim(trailingslashit(urldecode(trailingslashit(sanitize_text_field($parent)) . $rel_dir)));
     $dir_contents = array();
     if (file_exists($directory)) {
         $files = scandir($directory);
         natcasesort($files);
         if (count($files) > 2) {
             /* The 2 accounts for . and .. */
             //two loops keep directories sorted before files
             // All dirs
             foreach ($files as $file) {
                 if (file_exists($directory . $file) && $file != '.' && $file != '..' && is_dir($directory . $file)) {
                     //echo $dir . ', ' . $directory . PHP_EOL;
                     $dir_contents[$file] = $this->get_files($file, $directory);
                 }
             }
             // All files
             foreach ($files as $file) {
                 if (file_exists($directory . $file) && $file != '.' && $file != '..' && !is_dir($directory . $file)) {
                     //echo $file . PHP_EOL;
                     $dir_contents[] = $file;
                 }
             }
         }
     }
     return $dir_contents;
 }
 /**
  * Add Files Admin Javascript
  *
  * @since 4.0
  *
  * @return void
  */
 public function admin_enqueue_scripts()
 {
     global $itsec_globals;
     wp_enqueue_script('itsec_file_change_warning_js', $this->module_path . 'js/admin-file-change-warning.js', array('jquery'), $itsec_globals['plugin_build']);
     wp_localize_script('itsec_file_change_warning_js', 'itsec_file_change_warning', array('nonce' => wp_create_nonce('itsec_file_change_warning'), 'url' => admin_url() . 'admin.php?page=toplevel_page_itsec_logs&itsec_log_filter=file_change'));
     if (isset(get_current_screen()->id) && (strpos(get_current_screen()->id, 'security_page_toplevel_page_itsec_settings') !== false || strpos(get_current_screen()->id, 'security_page_toplevel_page_itsec_logs') !== false || strpos(get_current_screen()->id, 'dashboard') !== false)) {
         wp_enqueue_script('itsec_file_change_js', $this->module_path . 'js/admin-file-change.js', array('jquery'), $itsec_globals['plugin_build']);
         wp_localize_script('itsec_file_change_js', 'itsec_file_change', array('mem_limit' => ITSEC_Lib::get_memory_limit(), 'text' => __('Warning: Your server has less than 128MB of RAM dedicated to PHP. If you have many files in your installation or a lot of active plugins activating this feature may result in your site becoming disabled with a memory error. See the plugin homepage for more information.', 'it-l10n-better-wp-security'), 'module_path' => $this->module_path, 'button_text' => isset($this->settings['split']) && $this->settings['split'] === true ? __('Scan Next File Chunk', 'it-l10n-better-wp-security') : __('Scan Files Now', 'it-l10n-better-wp-security'), 'scanning_button_text' => __('Scanning...', 'it-l10n-better-wp-security'), 'no_changes' => __('No changes were detected.', 'it-l10n-better-wp-security'), 'changes' => __('Changes were detected. Please check the log page for details.', 'it-l10n-better-wp-security'), 'error' => __('An error occured. Please try again later', 'it-l10n-better-wp-security'), 'ABSPATH' => ITSEC_Lib::get_home_path(), 'nonce' => wp_create_nonce('itsec_do_file_check')));
         wp_enqueue_script('itsec_jquery_filetree', $this->module_path . 'filetree/jqueryFileTree.js', array('jquery'), '1.01');
         wp_localize_script('itsec_jquery_filetree', 'itsec_jquery_filetree', array('nonce' => wp_create_nonce('itsec_jquery_filetree')));
         wp_register_style('itsec_jquery_filetree_style', $this->module_path . 'filetree/jqueryFileTree.css', array(), $itsec_globals['plugin_build']);
         //add multi-select css
         wp_enqueue_style('itsec_jquery_filetree_style');
         wp_register_style('itsec_file_change_css', $this->module_path . 'css/admin-file-change.css', array(), $itsec_globals['plugin_build']);
         //add multi-select css
         wp_enqueue_style('itsec_file_change_css');
     }
 }
 /**
  * Gets location of .htaccess
  *
  * Finds and returns path to .htaccess or nginx.conf if appropriate
  *
  * @since 4.0.0
  *
  * @return string path to .htaccess
  */
 public static function get_htaccess()
 {
     global $itsec_globals;
     if ('nginx' === ITSEC_Lib::get_server()) {
         return $itsec_globals['settings']['nginx_file'];
     } else {
         return ITSEC_Lib::get_home_path() . '.htaccess';
     }
 }
 /**
  * Gets file list for tree.
  *
  * Processes the ajax request for retreiving the list of files and folders that can later either
  * excluded or included.
  *
  * @since 4.0.0
  *
  * @return void
  */
 public function wp_ajax_itsec_jquery_filetree_ajax()
 {
     global $itsec_globals;
     if (!wp_verify_nonce(sanitize_text_field($_POST['nonce']), 'itsec_jquery_filetree') || !current_user_can($itsec_globals['plugin_access_lvl'])) {
         die(__('Security error!', 'better-wp-security'));
     }
     $directory = sanitize_text_field($_POST['dir']);
     $directory = urldecode($directory);
     $directory = realpath($directory);
     $base_directory = realpath(ITSEC_Lib::get_home_path());
     // Ensure that requests cannot traverse arbitrary directories.
     if (0 !== strpos($directory, $base_directory)) {
         $directory = $base_directory;
     }
     $directory .= '/';
     if (file_exists($directory)) {
         $files = scandir($directory);
         natcasesort($files);
         if (2 < count($files)) {
             /* The 2 accounts for . and .. */
             echo "<ul class=\"jqueryFileTree\" style=\"display: none;\">";
             //two loops keep directories sorted before files
             // All files and directories (alphabetical sorting)
             foreach ($files as $file) {
                 if ('.' != $file && '..' != $file && file_exists($directory . $file) && is_dir($directory . $file)) {
                     echo '<li class="directory collapsed"><a href="#" rel="' . htmlentities($directory . $file) . '/">' . htmlentities($file) . '<div class="itsec_treeselect_control"><img src="' . plugins_url('images/redminus.png', __FILE__) . '" style="vertical-align: -3px;" title="Add to exclusions..." class="itsec_filetree_exclude"></div></a></li>';
                 } elseif ('.' != $file && '..' != $file && file_exists($directory . $file) && !is_dir($directory . $file)) {
                     $ext = preg_replace('/^.*\\./', '', $file);
                     echo '<li class="file ext_' . $ext . '"><a href="#" rel="' . htmlentities($directory . $file) . '">' . htmlentities($file) . '<div class="itsec_treeselect_control"><img src="' . plugins_url('images/redminus.png', __FILE__) . '" style="vertical-align: -3px;" title="Add to exclusions..." class="itsec_filetree_exclude"></div></a></li>';
                 }
             }
             echo "</ul>";
         }
     }
     exit;
 }
 /**
  * Scans all files in a given path
  *
  * @since 4.0
  *
  * @param string $path           [optional] path to scan, defaults to WordPress root
  * @param bool   $scheduled_call is this a scheduled call
  * @param mixed  $chunk          the current chunk or false
  *
  * @return array array of files found and their information
  *
  */
 private function scan_files($path = '', $scheduled_call, $chunk)
 {
     if ($chunk !== false) {
         $content_dir = explode('/', WP_CONTENT_DIR);
         $plugin_dir = explode('/', WP_PLUGIN_DIR);
         $dirs = array('wp-admin/', 'wp-includes/', $content_dir[sizeof($content_dir) - 1] . '/', $content_dir[sizeof($content_dir) - 1] . '/uploads/', $content_dir[sizeof($content_dir) - 1] . '/themes/', $content_dir[sizeof($content_dir) - 1] . '/' . $plugin_dir[sizeof($plugin_dir) - 1] . '/', '');
         $path = $dirs[$chunk];
         unset($dirs[$chunk]);
         $this->excludes = $dirs;
     }
     $time_offset = get_option('gmt_offset') * 60 * 60;
     $data = array();
     $clean_path = sanitize_text_field($path);
     if ($directory_handle = opendir(ITSEC_Lib::get_home_path() . $clean_path)) {
         //get the directory
         while (($item = readdir($directory_handle)) !== false) {
             // loop through dirs
             if ($item != '.' && $item != '..') {
                 //don't scan parent/etc
                 $relname = $path . $item;
                 $absname = ITSEC_Lib::get_home_path() . $relname;
                 if (is_dir($absname) && filetype($absname) == 'dir') {
                     $is_dir = true;
                     $check_name = trailingslashit($relname);
                 } else {
                     $is_dir = false;
                     $check_name = $relname;
                 }
                 if ($this->is_checkable_file($check_name) === true) {
                     //make sure the user wants this file scanned
                     if ($is_dir === true) {
                         //if directory scan it
                         $data = array_merge($data, $this->scan_files($relname . '/', $scheduled_call, false));
                     } else {
                         //is file so add to array
                         $data[$relname] = array();
                         $data[$relname]['d'] = @filemtime($absname);
                         $data[$relname]['h'] = @md5_file($absname);
                     }
                 }
             }
         }
         @closedir($directory_handle);
         //close the directory we're working with
     }
     return $data;
     // return the files we found in this dir
 }
 /**
  * Sanitize and validate input
  *
  * @since 1.6
  *
  * @param  Array $input array of input fields
  *
  * @return Array         Sanitized array
  */
 public function sanitize_module_input($input)
 {
     $input['enabled'] = isset($input['enabled']) && intval($input['enabled'] == 1) ? true : false;
     $input['standard'] = isset($input['standard']) && intval($input['standard'] == 1) ? true : false;
     $input['standard_interval'] = isset($input['standard_interval']) ? absint($input['standard_interval']) : 5;
     //Build an array of items for individual scan
     if (isset($input['individual'])) {
         foreach ($input['individual'] as $index => $item) {
             if (strlen(sanitize_text_field($input['individual'][$index]['resource'])) > 0) {
                 $input['individual'][$index]['type'] = isset($item['type']) && $item['type'] == 1 ? 1 : 0;
                 $input['individual'][$index]['resource'] = sanitize_text_field($input['individual'][$index]['resource']);
                 if ($input['individual'][$index]['type'] === 1) {
                     if (file_exists(trailingslashit(ITSEC_Lib::get_home_path()) . $input['individual'][$index]['resource']) !== true) {
                         $input['enabled'] = false;
                         $type = 'error';
                         $message = sprintf('%s <strong>%s</strong> %s<br />', __('The resource ', 'it-l10n-ithemes-security-pro'), sanitize_text_field($input['individual'][$index]['resource']), __('is not valid. Please try again.', 'it-l10n-ithemes-security-pro'));
                         add_settings_error('itsec', esc_attr('settings_updated'), $message, $type);
                     }
                 } else {
                     if (ITSEC_Lib::validate_url($input['individual'][$index]['resource']) != true) {
                         $input['enabled'] = false;
                         $type = 'error';
                         $message = sprintf('%s <strong>%s</strong> %s<br />', __('The resource ', 'it-l10n-ithemes-security-pro'), sanitize_text_field($input['individual'][$index]['resource']), __('is not valid. Please try again.', 'it-l10n-ithemes-security-pro'));
                         add_settings_error('itsec', esc_attr('settings_updated'), $message, $type);
                     }
                 }
             } else {
                 unset($input['individual'][$index]);
             }
         }
     } else {
         $input['individual'] = array();
     }
     //Clean out extras from last scans
     if ($input['enabled'] === true) {
         $last_scans = get_site_option('itsec_malware_scheduling_last_scans');
         if (is_array($last_scans) && sizeof($last_scans) > 0 && is_array($input['individual']) && sizeof($input['individual']) > 0) {
             foreach ($last_scans as $resource => $scan) {
                 $found = false;
                 //Assume we're no longer scheduling a scan for the item previously scanned
                 if ($resource === 'standard' || $resource === 'overall') {
                     $found = true;
                     //Overall and standard last scans should always be true
                 }
                 if ($found === false) {
                     foreach ($input['individual'] as $item) {
                         if ($resource == $item['resource']) {
                             $found = true;
                         }
                     }
                     if ($found === false) {
                         unset($last_scans[$resource]);
                         //Remove the resource from last scans if not found
                     }
                 }
             }
             update_site_option('itsec_malware_scheduling_last_scans', $last_scans);
         }
     } else {
         delete_site_option('itsec_malware_scheduling_last_scans');
         //If scanned malware scheduling isn't enabled delete the "last scans" data from the options table
     }
     if (is_multisite()) {
         $this->core->show_network_admin_notice(false);
         $this->settings = $input;
     }
     return $input;
 }