| @@ -1829,9 +1829,8 @@ | ||
| 1829 | 1829 | 'scanComplete' => __( 'Scan complete', 'vigilante' ), |
| 1830 | 1830 | 'loading' => __( 'Loading...', 'vigilante' ), |
| 1831 | 1831 | 'searching' => __( 'Searching...', 'vigilante' ), |
| 1832 | 1832 | 'noUsersFound' => __( 'No users found', 'vigilante' ), |
| 1833 | - 'searchError' => __( 'Error searching users', 'vigilante' ), | |
| 1834 | 1833 | 'sending' => __( 'Sending...', 'vigilante' ), |
| 1835 | 1834 | 'sendNotification' => __( 'Send notification now', 'vigilante' ), |
| 1836 | 1835 | 'notificationsSent' => __( 'notifications sent', 'vigilante' ), |
| 1837 | 1836 | 'skipped' => __( 'skipped', 'vigilante' ), |
| @@ -1850,9 +1849,9 @@ | ||
| 1850 | 1849 | 'modified' => __( 'Modified', 'vigilante' ), |
| 1851 | 1850 | 'suspicious' => __( 'Suspicious', 'vigilante' ), |
| 1852 | 1851 | 'totalScanned' => __( 'Total Scanned', 'vigilante' ), |
| 1853 | 1852 | 'suspiciousFiles' => __( 'Suspicious Files', 'vigilante' ), |
| 1854 | - 'suspiciousWarning' => __( 'These files may contain malicious code or are in unexpected locations. Review immediately!', 'vigilante' ), | |
| 1853 | + 'suspiciousWarning' => __( 'Files that can run code where none is expected, or that contain code written the way malware hides itself. Real infections show up here, and so do harmless files that plugins generate. Check the path and the reason before acting.', 'vigilante' ), | |
| 1855 | 1854 | 'file' => __( 'File', 'vigilante' ), |
| 1856 | 1855 | 'reason' => __( 'Reason', 'vigilante' ), |
| 1857 | 1856 | 'type' => __( 'Type', 'vigilante' ), |
| 1858 | 1857 | 'unknown' => __( 'Unknown', 'vigilante' ), |
| @@ -1861,13 +1860,13 @@ | ||
| 1861 | 1860 | 'logWhatItMeans' => __( 'What it means', 'vigilante' ), |
| 1862 | 1861 | 'logWhatToDo' => __( 'What to do', 'vigilante' ), |
| 1863 | 1862 | 'logSelfSeeDetails' => __( 'Open File Integrity for the full detail', 'vigilante' ), |
| 1864 | 1863 | 'modifiedFiles' => __( 'Modified Files', 'vigilante' ), |
| 1865 | - 'modifiedDescription' => __( 'These files (apparently) differ from the original WordPress or plugin versions.', 'vigilante' ), | |
| 1864 | + 'modifiedDescription' => __( 'These files do not match the copy WordPress.org publishes for the installed version.', 'vigilante' ), | |
| 1866 | 1865 | 'extraFiles' => __( 'Extra Files', 'vigilante' ), |
| 1867 | 1866 | 'extra' => __( 'Extra', 'vigilante' ), |
| 1868 | 1867 | 'ignored' => __( 'Ignored', 'vigilante' ), |
| 1869 | - 'extraDescription' => __( 'PHP files found in plugins or themes that are not part of the original distribution from WordPress.org.', 'vigilante' ), | |
| 1868 | + 'extraDescription' => __( 'Files that are not part of WordPress, or of the plugin or theme they sit in. Many are legitimate, and an injected file looks the same from here, so confirm where each one comes from.', 'vigilante' ), | |
| 1870 | 1869 | 'actions' => __( 'Actions', 'vigilante' ), |
| 1871 | 1870 | 'ignore' => __( 'Ignore', 'vigilante' ), |
| 1872 | 1871 | 'ignoring' => __( 'Ignoring...', 'vigilante' ), |
| 1873 | 1872 | 'fileIgnored' => __( 'File added to ignored list.', 'vigilante' ), |
| @@ -1875,9 +1874,8 @@ | ||
| 1875 | 1874 | 'confirmClearIgnored' => __( 'Remove all files from the ignored list? They will appear in scan results again.', 'vigilante' ), |
| 1876 | 1875 | 'ignoredCleared' => __( 'Ignored files list cleared. Page will reload...', 'vigilante' ), |
| 1877 | 1876 | 'selectAll' => __( 'Select all', 'vigilante' ), |
| 1878 | 1877 | 'bulkIgnoreSelected' => __( 'Ignore selected', 'vigilante' ), |
| 1879 | - 'bulkUnignoreSelected'=> __( 'Stop ignoring selected', 'vigilante' ), | |
| 1880 | 1878 | 'bulkNoSelection' => __( 'Select at least one file first.', 'vigilante' ), |
| 1881 | 1879 | 'bulkConfirmIgnore' => __( 'Ignore the selected files? They will be hidden from future scan results until you remove them from the ignored list.', 'vigilante' ), |
| 1882 | 1880 | 'bulkConfirmUnignore' => __( 'Remove the selected files from the ignored list? They will appear in scan results again.', 'vigilante' ), |
| 1883 | 1881 | 'bulkProcessing' => __( 'Processing...', 'vigilante' ), |
| @@ -1882,11 +1880,11 @@ | ||
| 1882 | 1880 | 'bulkConfirmUnignore' => __( 'Remove the selected files from the ignored list? They will appear in scan results again.', 'vigilante' ), |
| 1883 | 1881 | 'bulkProcessing' => __( 'Processing...', 'vigilante' ), |
| 1884 | 1882 | /* translators: %d: number of files selected for bulk action. */ |
| 1885 | 1883 | 'bulkSelectedCount' => __( '%d selected', 'vigilante' ), |
| 1886 | - 'allClear' => __( 'All files verified - no issues found!', 'vigilante' ), | |
| 1884 | + 'allClear' => __( 'Good job! Nothing to report in the files that were checked.', 'vigilante' ), | |
| 1887 | 1885 | 'criticalConfigTitle' => __( 'Critical config files modified', 'vigilante' ), |
| 1888 | - 'criticalConfigDesc' => __( 'These files are common targets for code injection. Review the changes and approve if they are legitimate. Vigilant\'s own blocks are excluded from this check.', 'vigilante' ), | |
| 1886 | + 'criticalConfigDesc' => __( 'These files changed since you last approved them. They are a common target for code injection, and they are also rewritten by cache, security and redirection plugins, often on every update. Review the changes and approve them if they belong to something you use: approving records the current content as the reference and does not touch the file. Vigilant\'s own blocks are excluded from this check, and Vigilant never restores these files by itself.', 'vigilante' ), | |
| 1889 | 1887 | 'approve' => __( 'Approve', 'vigilante' ), |
| 1890 | 1888 | 'approving' => __( 'Approving...', 'vigilante' ), |
| 1891 | 1889 | 'approvalLockedNotice' => $this->critical_approval_notice(), |
| 1892 | 1890 | 'criticalApproved' => __( 'Change approved. Next scan will use the current state as baseline.', 'vigilante' ), |
| @@ -1979,13 +1977,10 @@ | ||
| 1979 | 1977 | 'noLogsToExport' => __( 'No logs to export', 'vigilante' ), |
| 1980 | 1978 | 'exportFailed' => __( 'Export failed', 'vigilante' ), |
| 1981 | 1979 | 'exportLogs' => __( 'Export Logs', 'vigilante' ), |
| 1982 | 1980 | // Backup strings |
| 1983 | - 'backupCreated' => __( 'Backup created successfully.', 'vigilante' ), | |
| 1984 | 1981 | 'createBackupNow' => __( 'Download Backup', 'vigilante' ), |
| 1985 | 1982 | 'downloadBackup' => __( 'Download Backup (.zip)', 'vigilante' ), |
| 1986 | - /* translators: %d: number of tables */ | |
| 1987 | - 'tablesCount' => __( '%d tables', 'vigilante' ), | |
| 1988 | 1983 | /* translators: 1: table count, 2: human-readable size */ |
| 1989 | 1984 | 'dbTablesTotal' => __( '%1$d tables total (%2$s)', 'vigilante' ), |
| 1990 | 1985 | /* translators: 1: selected count, 2: human-readable size */ |
| 1991 | 1986 | 'dbTablesSelected' => __( '%1$d tables selected (%2$s)', 'vigilante' ), |
| @@ -1992,9 +1987,8 @@ | ||
| 1992 | 1987 | // Settings search strings |
| 1993 | 1988 | 'searchNoResults' => __( 'No matching settings found.', 'vigilante' ), |
| 1994 | 1989 | /* translators: %d: number of results that did not fit in the list. */ |
| 1995 | 1990 | 'searchMoreResults' => __( '%d more results. Refine the search to see them.', 'vigilante' ), |
| 1996 | - 'searchInTab' => __( 'in', 'vigilante' ), | |
| 1997 | 1991 | // Modules string |
| 1998 | 1992 | /* translators: 1: enabled count, 2: total count */ |
| 1999 | 1993 | 'modulesEnabled' => __( '%1$d / %2$d modules enabled', 'vigilante' ), |
| 2000 | 1994 | // Activity log label maps for JS rendering |
| @@ -1999,8 +1993,9 @@ | ||
| 1999 | 1993 | 'modulesEnabled' => __( '%1$d / %2$d modules enabled', 'vigilante' ), |
| 2000 | 1994 | // Activity log label maps for JS rendering |
| 2001 | 1995 | 'eventTypeLabels' => array( |
| 2002 | 1996 | 'login' => __( 'Login', 'vigilante' ), |
| 1997 | + '2fa' => __( 'Two-factor', 'vigilante' ), | |
| 2003 | 1998 | 'user' => __( 'User', 'vigilante' ), |
| 2004 | 1999 | 'content' => __( 'Content', 'vigilante' ), |
| 2005 | 2000 | 'plugin' => __( 'Plugin', 'vigilante' ), |
| 2006 | 2001 | 'theme' => __( 'Theme', 'vigilante' ), |
| @@ -2066,10 +2061,8 @@ | ||
| 2066 | 2061 | /* translators: 1: first item number, 2: last item number, 3: total items */ |
| 2067 | 2062 | 'paginationOf' => __( '%1$d–%2$d of %3$d', 'vigilante' ), |
| 2068 | 2063 | 'paginationEmpty' => __( '0 items', 'vigilante' ), |
| 2069 | 2064 | // Security Analyzer strings |
| 2070 | - 'analyzerScanNow' => __( 'Scan now', 'vigilante' ), | |
| 2071 | - 'analyzerScanning' => __( 'Scanning…', 'vigilante' ), | |
| 2072 | 2065 | 'analyzerFastPhase' => __( 'Running fast checks…', 'vigilante' ), |
| 2073 | 2066 | 'analyzerSlowPhase' => __( 'Running remote checks…', 'vigilante' ), |
| 2074 | 2067 | 'analyzerScanComplete' => __( 'Security scan complete.', 'vigilante' ), |
| 2075 | 2068 | 'analyzerScanFailed' => __( 'Security scan failed.', 'vigilante' ), |
| @@ -2075,11 +2068,8 @@ | ||
| 2075 | 2068 | 'analyzerScanFailed' => __( 'Security scan failed.', 'vigilante' ), |
| 2076 | 2069 | 'analyzerShowDetails' => __( 'Show detailed breakdown', 'vigilante' ), |
| 2077 | 2070 | 'analyzerHideDetails' => __( 'Hide detailed breakdown', 'vigilante' ), |
| 2078 | 2071 | 'analyzerGoToSetting' => __( 'Go to setting', 'vigilante' ), |
| 2079 | - 'analyzerNoData' => __( 'No data yet — run a scan to populate this category.', 'vigilante' ), | |
| 2080 | - 'analyzerJustNow' => __( 'just now', 'vigilante' ), | |
| 2081 | - 'analyzerAgo' => __( 'ago', 'vigilante' ), | |
| 2082 | 2072 | 'analyzerSettingsSaved' => __( 'Analyzer settings saved.', 'vigilante' ), |
| 2083 | 2073 | 'analyzerLastScanJustNow' => __( 'Last scan just now', 'vigilante' ), |
| 2084 | 2074 | 'analyzerQualityExcellent' => __( 'Excellent', 'vigilante' ), |
| 2085 | 2075 | 'analyzerQualityGood' => __( 'Good', 'vigilante' ), |
| @@ -2085,9 +2075,8 @@ | ||
| 2085 | 2075 | 'analyzerQualityGood' => __( 'Good', 'vigilante' ), |
| 2086 | 2076 | 'analyzerQualityFair' => __( 'Fair', 'vigilante' ), |
| 2087 | 2077 | 'analyzerQualityPoor' => __( 'Poor', 'vigilante' ), |
| 2088 | 2078 | 'analyzerQualityCritical' => __( 'Critical', 'vigilante' ), |
| 2089 | - 'analyzerPts' => __( 'pts', 'vigilante' ), | |
| 2090 | 2079 | 'analyzerLearnMore' => __( 'Learn more', 'vigilante' ), |
| 2091 | 2080 | 'analyzerInfoAllClear' => __( 'All clear', 'vigilante' ), |
| 2092 | 2081 | /* translators: %d: number of findings in an info-only category */ |
| 2093 | 2082 | 'analyzerInfoFindings' => __( '%d findings', 'vigilante' ), |
| @@ -3741,8 +3730,9 @@ | ||
| 3741 | 3730 | <label> |
| 3742 | 3731 | <input type="checkbox" name="firewall[block_bad_bots]" value="1" <?php disabled( $vg_main_locked ); ?> <?php checked( ! empty( $options['block_bad_bots'] ) ); ?>> |
| 3743 | 3732 | <?php esc_html_e( 'Block known malicious bots and scanners', 'vigilante' ); ?> |
| 3744 | 3733 | </label> |
| 3734 | + <p class="description"><?php esc_html_e( 'The list also stops SEO crawlers such as Ahrefs, Semrush, Majestic and Screaming Frog, and command line clients such as curl, wget and python-requests. To let one of them through, add its name to the User-Agent Whitelist below. On Apache part of the list is applied in .htaccess, before WordPress loads, so those requests get a 403 and do not appear in the Security Audit.', 'vigilante' ); ?></p> | |
| 3745 | 3735 | </td> |
| 3746 | 3736 | </tr> |
| 3747 | 3737 | </table> |
| 3748 | 3738 | |
| @@ -4055,9 +4045,9 @@ | ||
| 4055 | 4045 | <th scope="row"><?php esc_html_e( 'Limit HTTP Methods', 'vigilante' ); ?></th> |
| 4056 | 4046 | <td> |
| 4057 | 4047 | <label> |
| 4058 | 4048 | <input type="checkbox" name="firewall[limit_http_methods]" value="1" <?php checked( ! empty( $options['limit_http_methods'] ) ); ?>> |
| 4059 | - <?php esc_html_e( 'Allow only GET, POST, HEAD (blocks PUT, DELETE, TRACE, etc.)', 'vigilante' ); ?> | |
| 4049 | + <?php esc_html_e( 'Block the HTTP methods WordPress does not use (TRACE, TRACK, CONNECT and any unknown one). GET, POST, HEAD, OPTIONS, PUT, PATCH and DELETE keep working.', 'vigilante' ); ?> | |
| 4060 | 4050 | </label> |
| 4061 | 4051 | </td> |
| 4062 | 4052 | </tr> |
| 4063 | 4053 | </table> |
| @@ -6338,9 +6328,9 @@ | ||
| 6338 | 6328 | <select id="vigilante-f-audit-alerts-immediate-min-severity" name="audit_alerts[immediate][min_severity]"> |
| 6339 | 6329 | <option value="critical" <?php selected( $alert_severity, 'critical' ); ?>><?php esc_html_e( 'Critical only (recommended)', 'vigilante' ); ?></option> |
| 6340 | 6330 | <option value="warning" <?php selected( $alert_severity, 'warning' ); ?>><?php esc_html_e( 'Warning and Critical', 'vigilante' ); ?></option> |
| 6341 | 6331 | </select> |
| 6342 | - <p class="description"><?php esc_html_e( 'A new administrator, a closed plugin or a privilege escalation are all logged as Critical, so "Critical only" already covers them.', 'vigilante' ); ?></p> | |
| 6332 | + <p class="description"><?php esc_html_e( 'A closed plugin is logged as Critical, so "Critical only" covers it. A new administrator and a change of role are logged as Warning: they have their own emails, in Users > Admin monitoring, and reach this alert only with "Warning and Critical".', 'vigilante' ); ?></p> | |
| 6343 | 6333 | </td> |
| 6344 | 6334 | </tr> |
| 6345 | 6335 | <tr id="field-audit-alerts-threshold"> |
| 6346 | 6336 | <th scope="row"><?php esc_html_e( 'Threshold alerts', 'vigilante' ); ?></th> |
| @@ -6433,8 +6423,9 @@ | ||
| 6433 | 6423 | |
| 6434 | 6424 | // Label maps for translated display |
| 6435 | 6425 | $type_labels = array( |
| 6436 | 6426 | 'login' => __( 'Login', 'vigilante' ), |
| 6427 | + '2fa' => __( 'Two-factor', 'vigilante' ), | |
| 6437 | 6428 | 'user' => __( 'User', 'vigilante' ), |
| 6438 | 6429 | 'content' => __( 'Content', 'vigilante' ), |
| 6439 | 6430 | 'plugin' => __( 'Plugin', 'vigilante' ), |
| 6440 | 6431 | 'theme' => __( 'Theme', 'vigilante' ), |
| @@ -6463,8 +6454,9 @@ | ||
| 6463 | 6454 | <input type="text" id="vigilante-log-search" aria-label="<?php esc_attr_e( 'Search the activity log', 'vigilante' ); ?>" size="1" placeholder="<?php esc_attr_e( 'Search logs (min. 3 characters)...', 'vigilante' ); ?>" class="vigilante-log-search-input"> |
| 6464 | 6455 | <select id="vigilante-log-type-filter" aria-label="<?php esc_attr_e( 'Filter the log by event type', 'vigilante' ); ?>"> |
| 6465 | 6456 | <option value=""><?php esc_html_e( 'All Types', 'vigilante' ); ?></option> |
| 6466 | 6457 | <option value="login"><?php esc_html_e( 'Login', 'vigilante' ); ?></option> |
| 6458 | + <option value="2fa"><?php esc_html_e( 'Two-factor', 'vigilante' ); ?></option> | |
| 6467 | 6459 | <option value="user"><?php esc_html_e( 'User', 'vigilante' ); ?></option> |
| 6468 | 6460 | <option value="content"><?php esc_html_e( 'Content', 'vigilante' ); ?></option> |
| 6469 | 6461 | <option value="plugin"><?php esc_html_e( 'Plugin', 'vigilante' ); ?></option> |
| 6470 | 6462 | <option value="theme"><?php esc_html_e( 'Theme', 'vigilante' ); ?></option> |
| @@ -7008,8 +7000,49 @@ | ||
| 7008 | 7000 | </details> |
| 7009 | 7001 | <?php |
| 7010 | 7002 | } |
| 7011 | 7003 | |
| 7004 | + /** | |
| 7005 | + * Print what each kind of finding in a list usually is and what to do | |
| 7006 | + * | |
| 7007 | + * One line per kind actually present in the list, from the single source | |
| 7008 | + * of that text, Vigilante_File_Integrity::finding_guidance(). | |
| 7009 | + * | |
| 7010 | + * @param array $items Findings of one section of the last scan. | |
| 7011 | + */ | |
| 7012 | + private function render_fi_guidance( $items ) { | |
| 7013 | + $seen = array(); | |
| 7014 | + $guides = array(); | |
| 7015 | + | |
| 7016 | + foreach ( (array) $items as $item ) { | |
| 7017 | + $type = is_array( $item ) ? (string) ( $item['type'] ?? '' ) : ''; | |
| 7018 | + | |
| 7019 | + if ( '' === $type || 'vigilante_self' === $type || isset( $seen[ $type ] ) ) { | |
| 7020 | + continue; | |
| 7021 | + } | |
| 7022 | + $seen[ $type ] = true; | |
| 7023 | + | |
| 7024 | + $guide = Vigilante_File_Integrity::finding_guidance( $type ); | |
| 7025 | + | |
| 7026 | + if ( '' !== $guide['advice'] ) { | |
| 7027 | + // A plugin and a theme share their text: one line for both, | |
| 7028 | + // under the two names. | |
| 7029 | + $guides[ $guide['advice'] ][] = $guide['label']; | |
| 7030 | + } | |
| 7031 | + } | |
| 7032 | + | |
| 7033 | + if ( empty( $guides ) ) { | |
| 7034 | + return; | |
| 7035 | + } | |
| 7036 | + ?> | |
| 7037 | + <ul class="vigilante-fi-guidance" style="margin: 8px 0 12px 18px; list-style: disc;"> | |
| 7038 | + <?php foreach ( $guides as $advice => $labels ) : ?> | |
| 7039 | + <li><strong><?php echo esc_html( implode( ', ', $labels ) ); ?>:</strong> <?php echo esc_html( $advice ); ?></li> | |
| 7040 | + <?php endforeach; ?> | |
| 7041 | + </ul> | |
| 7042 | + <?php | |
| 7043 | + } | |
| 7044 | + | |
| 7012 | 7045 | private function render_tab_file_integrity() { |
| 7013 | 7046 | $is_disabled = $this->render_module_disabled_notice( 'file_integrity' ); |
| 7014 | 7047 | $options = $this->settings->get_section( 'file_integrity' ); |
| 7015 | 7048 | // On the main site of a network the critical-file scan is the network's |
| @@ -7081,9 +7114,10 @@ | ||
| 7081 | 7114 | <h2> |
| 7082 | 7115 | <?php esc_html_e( 'File Integrity Monitoring', 'vigilante' ); ?> |
| 7083 | 7116 | <span class="vigilante-method-badge php"><?php esc_html_e( 'PHP', 'vigilante' ); ?></span> |
| 7084 | 7117 | </h2> |
| 7085 | - <p><?php esc_html_e( 'Detects file modifications using WordPress.org checksums.', 'vigilante' ); ?></p> | |
| 7118 | + <p><?php esc_html_e( 'Compares WordPress, and the plugins and themes that come from WordPress.org, with the official copy of each file, looks for code where there should be none (uploads and the site root) and watches wp-config.php and .htaccess for changes.', 'vigilante' ); ?></p> | |
| 7119 | + <p class="description"><?php esc_html_e( 'What it cannot compare: plugins and themes that are not on WordPress.org, must-use plugins, drop-ins (advanced-cache.php, object-cache.php and the like) and the other folders of wp-content have no official copy. They are searched for hidden code, which finds malware that disguises itself and misses most code written in the open. The results name what could not be compared.', 'vigilante' ); ?></p> | |
| 7086 | 7120 | |
| 7087 | 7121 | <table class="form-table"> |
| 7088 | 7122 | <tr> |
| 7089 | 7123 | <th scope="row"><?php esc_html_e( 'Automatic Scans', 'vigilante' ); ?></th> |
| @@ -7106,13 +7140,13 @@ | ||
| 7106 | 7140 | <tr> |
| 7107 | 7141 | <th scope="row"><label for="vigilante-f-file-integrity-notify-level"><?php esc_html_e( 'Email Notifications', 'vigilante' ); ?></label></th> |
| 7108 | 7142 | <td> |
| 7109 | 7143 | <select id="vigilante-f-file-integrity-notify-level" name="file_integrity[notify_level]"> |
| 7110 | - <option value="all" <?php selected( $notify_level, 'all' ); ?>><?php esc_html_e( 'All issues (modified + suspicious)', 'vigilante' ); ?></option> | |
| 7111 | - <option value="suspicious_only" <?php selected( $notify_level, 'suspicious_only' ); ?>><?php esc_html_e( 'Suspicious files only', 'vigilante' ); ?></option> | |
| 7144 | + <option value="all" <?php selected( $notify_level, 'all' ); ?>><?php esc_html_e( 'Every finding, modified files included', 'vigilante' ); ?></option> | |
| 7145 | + <option value="suspicious_only" <?php selected( $notify_level, 'suspicious_only' ); ?>><?php esc_html_e( 'Serious findings only', 'vigilante' ); ?></option> | |
| 7112 | 7146 | <option value="disabled" <?php selected( $notify_level, 'disabled' ); ?>><?php esc_html_e( 'Disabled', 'vigilante' ); ?></option> |
| 7113 | 7147 | </select> |
| 7114 | - <p class="description"><?php esc_html_e( '"Suspicious files only" reduces noise by skipping modified file notifications. Recommended for most sites.', 'vigilante' ); ?></p> | |
| 7148 | + <p class="description"><?php esc_html_e( 'Serious findings are suspicious and extra files, changes in wp-config.php or .htaccess and closed plugins. That is the recommended choice: a file that is only modified is rarely more than an update that did not finish. The email goes out when a scan finds something new: a finding you were already told about is not sent again, unless the file changes once more.', 'vigilante' ); ?></p> | |
| 7115 | 7149 | </td> |
| 7116 | 7150 | </tr> |
| 7117 | 7151 | <tr> |
| 7118 | 7152 | <th scope="row"><?php esc_html_e( 'Instant Alert', 'vigilante' ); ?></th> |
| @@ -7118,11 +7152,11 @@ | ||
| 7118 | 7152 | <th scope="row"><?php esc_html_e( 'Instant Alert', 'vigilante' ); ?></th> |
| 7119 | 7153 | <td> |
| 7120 | 7154 | <label> |
| 7121 | 7155 | <input type="checkbox" name="file_integrity[instant_alert]" value="1" <?php checked( ! empty( $options['instant_alert'] ) ); ?>> |
| 7122 | - <?php esc_html_e( 'Send immediate alert when modified, suspicious or additional files are detected, or when a closed plugin is found', 'vigilante' ); ?> | |
| 7156 | + <?php esc_html_e( 'Email every finding when a scan ends, modified files included, and email a closed plugin as soon as the daily check finds it', 'vigilante' ); ?> | |
| 7123 | 7157 | </label> |
| 7124 | - <p class="description"><?php esc_html_e( 'Fires even if the Email Notifications setting above is set to Disabled.', 'vigilante' ); ?></p> | |
| 7158 | + <p class="description"><?php esc_html_e( 'This takes precedence over the choice above, Disabled included.', 'vigilante' ); ?></p> | |
| 7125 | 7159 | <p class="description"> |
| 7126 | 7160 | <?php |
| 7127 | 7161 | printf( |
| 7128 | 7162 | /* translators: %s: Link to notification settings */ |
| @@ -7148,29 +7182,29 @@ | ||
| 7148 | 7182 | <td> |
| 7149 | 7183 | <fieldset> |
| 7150 | 7184 | <label> |
| 7151 | 7185 | <input type="checkbox" name="file_integrity[scan_core]" value="1" <?php checked( $options['scan_core'] ?? true ); ?>> |
| 7152 | - <?php esc_html_e( 'Core files (compare against WordPress.org checksums)', 'vigilante' ); ?> | |
| 7186 | + <?php esc_html_e( 'WordPress core (compared with WordPress.org) and the other files in the site root', 'vigilante' ); ?> | |
| 7153 | 7187 | </label> |
| 7154 | 7188 | <br> |
| 7155 | 7189 | <label> |
| 7156 | 7190 | <input type="checkbox" name="file_integrity[scan_plugins]" value="1" <?php checked( $options['scan_plugins'] ?? true ); ?>> |
| 7157 | - <?php esc_html_e( 'Plugins (WordPress.org repository plugins)', 'vigilante' ); ?> | |
| 7191 | + <?php esc_html_e( 'Plugins (compared with WordPress.org; the rest, and the other folders of wp-content, are only searched for hidden code)', 'vigilante' ); ?> | |
| 7158 | 7192 | </label> |
| 7159 | 7193 | <br> |
| 7160 | 7194 | <label> |
| 7161 | 7195 | <input type="checkbox" name="file_integrity[scan_themes]" value="1" <?php checked( $options['scan_themes'] ?? true ); ?>> |
| 7162 | - <?php esc_html_e( 'Themes (WordPress.org repository themes)', 'vigilante' ); ?> | |
| 7196 | + <?php esc_html_e( 'Themes (compared with WordPress.org; the rest are only searched for hidden code)', 'vigilante' ); ?> | |
| 7163 | 7197 | </label> |
| 7164 | 7198 | <br> |
| 7165 | 7199 | <label> |
| 7166 | 7200 | <input type="checkbox" name="file_integrity[scan_uploads]" value="1" <?php checked( $options['scan_uploads'] ?? true ); ?>> |
| 7167 | - <?php esc_html_e( 'Uploads directory (detect PHP files, double extensions, .htaccess)', 'vigilante' ); ?> | |
| 7201 | + <?php esc_html_e( 'Uploads directory (PHP and other scripts, double extensions, .htaccess and PHP configuration files)', 'vigilante' ); ?> | |
| 7168 | 7202 | </label> |
| 7169 | 7203 | <br> |
| 7170 | 7204 | <label> |
| 7171 | 7205 | <input type="checkbox" name="file_integrity[scan_critical_config]" value="1" <?php disabled( $vg_main_locked ); ?> <?php checked( $options['scan_critical_config'] ?? true ); ?>> |
| 7172 | - <?php esc_html_e( 'Critical config files (wp-config.php, .htaccess baseline monitoring)', 'vigilante' ); ?> | |
| 7206 | + <?php esc_html_e( 'wp-config.php and .htaccess (any change since you last approved them)', 'vigilante' ); ?> | |
| 7173 | 7207 | <?php if ( $vg_main_locked ) : ?> |
| 7174 | 7208 | <span class="description" style="display:block;margin-left:24px;"><?php echo esc_html( Vigilante_Settings::get_shared_files_notice() ); ?></span> |
| 7175 | 7209 | <?php endif; ?> |
| 7176 | 7210 | </label> |
| @@ -7184,10 +7218,10 @@ | ||
| 7184 | 7218 | </tr> |
| 7185 | 7219 | <tr> |
| 7186 | 7220 | <th scope="row"><label for="vigilante-f-file-integrity-excluded-paths"><?php esc_html_e( 'Excluded Paths', 'vigilante' ); ?></label></th> |
| 7187 | 7221 | <td> |
| 7188 | - <textarea id="vigilante-f-file-integrity-excluded-paths" name="file_integrity[excluded_paths]" rows="4" class="large-text code" placeholder="wp-content/cache wp-content/languages"><?php echo esc_textarea( implode( "\n", $options['excluded_paths'] ?? array() ) ); ?></textarea> | |
| 7189 | - <p class="description"><?php esc_html_e( 'One path per line, relative to the WordPress root. A path such as wp-content/cache excludes exactly that folder and everything under it. A name on its own, such as cache, excludes any folder called exactly that, wherever it is.', 'vigilante' ); ?></p> | |
| 7222 | + <textarea id="vigilante-f-file-integrity-excluded-paths" name="file_integrity[excluded_paths]" rows="4" class="large-text code" placeholder="wp-content/backups"><?php echo esc_textarea( implode( "\n", $options['excluded_paths'] ?? array() ) ); ?></textarea> | |
| 7223 | + <p class="description"><?php esc_html_e( 'One path per line, relative to the WordPress root. A path such as wp-content/backups excludes exactly that folder and everything under it. A name on its own, such as backups, excludes any folder called exactly that, wherever it is. Nothing in an excluded folder is looked at, so keep the list short.', 'vigilante' ); ?></p> | |
| 7190 | 7224 | </td> |
| 7191 | 7225 | </tr> |
| 7192 | 7226 | <tr> |
| 7193 | 7227 | <th scope="row"><label for="vigilante-f-file-integrity-excluded-extensions"><?php esc_html_e( 'Excluded Extensions', 'vigilante' ); ?></label></th> |
| @@ -7230,11 +7264,49 @@ | ||
| 7230 | 7264 | <div id="vigilante-scan-results" class="vigilante-settings-section" style="display:none;"></div> |
| 7231 | 7265 | |
| 7232 | 7266 | <?php $this->render_self_protection_box( $options ); ?> |
| 7233 | 7267 | |
| 7268 | + <?php | |
| 7269 | + // Whole folders of code left out of every scan. A partial scan tells | |
| 7270 | + // how to check the rest by excluding what it did check, and those | |
| 7271 | + // lines have to come out afterwards: with them in place a scan comes | |
| 7272 | + // out complete and clean without having looked there. Said for as | |
| 7273 | + // long as they are in the list, whoever put them there and why. | |
| 7274 | + $vg_fi_tool = new Vigilante_File_Integrity( $this->settings, $this->database ); | |
| 7275 | + $vg_excluded_code = $vg_fi_tool->excluded_code_folders(); | |
| 7276 | + $vg_folders_to_skip = $vg_fi_tool->folders_to_exclude( $last_results ); | |
| 7277 | + ?> | |
| 7278 | + <?php if ( ! empty( $vg_excluded_code ) ) : ?> | |
| 7279 | + <div id="vigilante-fi-excluded-code" class="notice notice-warning inline"> | |
| 7280 | + <p> | |
| 7281 | + <strong> | |
| 7282 | + <?php | |
| 7283 | + printf( | |
| 7284 | + /* translators: %s: Comma separated list of folders */ | |
| 7285 | + esc_html__( 'Excluded Paths holds whole folders of plugins or themes, or the uploads folder: %s.', 'vigilante' ), | |
| 7286 | + esc_html( implode( ', ', $vg_excluded_code ) ) | |
| 7287 | + ); | |
| 7288 | + ?> | |
| 7289 | + </strong> | |
| 7290 | + <?php esc_html_e( 'No scan looks inside them, the scheduled one included, and a scan can come out complete and clean without having checked them. If you added them to check the rest of a large site, take them out once that scan is done.', 'vigilante' ); ?> | |
| 7291 | + </p> | |
| 7292 | + </div> | |
| 7293 | + <?php endif; ?> | |
| 7294 | + | |
| 7234 | 7295 | <?php if ( $last_scan || $has_closed || $closed_last_check > 0 ) : ?> |
| 7235 | 7296 | <div id="vigilante-section-fi-last-scan" class="vigilante-settings-section"> |
| 7236 | 7297 | <h2><?php esc_html_e( 'Last Scan Results', 'vigilante' ); ?></h2> |
| 7298 | + <?php | |
| 7299 | + // A scan the server stops halfway stores nothing, and neither | |
| 7300 | + // does one WordPress never starts: the tab kept showing the | |
| 7301 | + // last result that did finish, with nothing to say that scans | |
| 7302 | + // had stopped. Its date is the only sign. | |
| 7303 | + if ( $last_scan && $this->settings->is_module_enabled( 'file_integrity' ) && Vigilante_File_Integrity::is_scan_overdue( $last_scan, $options['scan_frequency'] ?? 'daily' ) ) : | |
| 7304 | + ?> | |
| 7305 | + <div class="notice notice-warning inline"> | |
| 7306 | + <p><strong><?php esc_html_e( 'Scans are scheduled, and none has finished since the date below.', 'vigilante' ); ?></strong> <?php esc_html_e( 'Either WordPress is not running its scheduled tasks, or the server stops the scan before it ends, and a scan that is stopped stores no result. What you see here is old. Run a scan now: if it finishes, the scheduled tasks are what is failing. If it does not, the site is too large for the time the server gives a request, and adding large folders that do not need checking to Excluded Paths leaves more time for the rest.', 'vigilante' ); ?></p> | |
| 7307 | + </div> | |
| 7308 | + <?php endif; ?> | |
| 7237 | 7309 | <?php if ( $last_scan ) : ?> |
| 7238 | 7310 | <p> |
| 7239 | 7311 | <?php |
| 7240 | 7312 | // Build the "X files scanned" hint inline with the date so it doesn't |
| @@ -7317,12 +7389,112 @@ | ||
| 7317 | 7389 | </div> |
| 7318 | 7390 | <?php endif; ?> |
| 7319 | 7391 | </div> |
| 7320 | 7392 | |
| 7393 | + <?php | |
| 7394 | + // A scan that could not finish, or could not get the official | |
| 7395 | + // copy to compare with, checked less than it seems. Until now | |
| 7396 | + // its errors were stored and never shown, and the tab could | |
| 7397 | + // say that every file had passed. | |
| 7398 | + $vg_scan_errors = ( $last_results && ! empty( $last_results['errors'] ) && is_array( $last_results['errors'] ) ) ? $last_results['errors'] : array(); | |
| 7399 | + $vg_scan_partial = ! empty( $vg_scan_errors ) || ( $last_results && ! empty( $last_results['incomplete'] ) ); | |
| 7400 | + | |
| 7401 | + // Files of the official copies that are not on the server. Core | |
| 7402 | + // files under wp-content are left out: results stored before | |
| 7403 | + // the bundled themes and plugins got their own turn list | |
| 7404 | + // there the ones people delete on purpose. | |
| 7405 | + $vg_missing_core = array(); | |
| 7406 | + if ( $last_results && ! empty( $last_results['missing'] ) && is_array( $last_results['missing'] ) ) { | |
| 7407 | + foreach ( $last_results['missing'] as $item ) { | |
| 7408 | + if ( ! is_array( $item ) || ! isset( $item['file'] ) ) { | |
| 7409 | + continue; | |
| 7410 | + } | |
| 7411 | + | |
| 7412 | + $vg_missing_type = (string) ( $item['type'] ?? '' ); | |
| 7413 | + | |
| 7414 | + if ( in_array( $vg_missing_type, array( 'plugin', 'theme' ), true ) | |
| 7415 | + || ( 'core' === $vg_missing_type && 0 !== strpos( (string) $item['file'], 'wp-content/' ) ) ) { | |
| 7416 | + $vg_missing_core[] = (string) $item['file']; | |
| 7417 | + } | |
| 7418 | + } | |
| 7419 | + } | |
| 7420 | + ?> | |
| 7421 | + | |
| 7422 | + <?php if ( $last_results && ! empty( $last_results['unverified'] ) && is_array( $last_results['unverified'] ) ) : ?> | |
| 7423 | + <p class="description"> | |
| 7424 | + <?php | |
| 7425 | + printf( | |
| 7426 | + /* translators: %s: Comma separated list of plugin and theme names */ | |
| 7427 | + esc_html__( 'No official copy to compare with, so only searched for hidden code: %s.', 'vigilante' ), | |
| 7428 | + esc_html( implode( ', ', array_unique( array_map( 'strval', $last_results['unverified'] ) ) ) ) | |
| 7429 | + ); | |
| 7430 | + ?> | |
| 7431 | + </p> | |
| 7432 | + <?php endif; ?> | |
| 7433 | + | |
| 7434 | + <?php | |
| 7435 | + // What the scan did not get to, by name. A scan starts from | |
| 7436 | + // the beginning every time, so on a site too large for it | |
| 7437 | + // these are the same on every scan, and whoever reads the | |
| 7438 | + // result has to know that nothing here was looked at. | |
| 7439 | + $vg_scan_notes = array_merge( $vg_scan_errors, Vigilante_File_Integrity::not_checked_lines( $last_results ) ); | |
| 7440 | + ?> | |
| 7441 | + <?php if ( $vg_scan_partial ) : ?> | |
| 7442 | + <div class="notice notice-warning inline"> | |
| 7443 | + <p><strong><?php esc_html_e( 'The last scan could not check everything, so its result is partial.', 'vigilante' ); ?></strong></p> | |
| 7444 | + <?php if ( ! empty( $vg_scan_notes ) ) : ?> | |
| 7445 | + <ul style="margin: 0 0 8px 18px; list-style: disc;"> | |
| 7446 | + <?php foreach ( $vg_scan_notes as $vg_scan_note ) : ?> | |
| 7447 | + <li><?php echo esc_html( (string) $vg_scan_note ); ?></li> | |
| 7448 | + <?php endforeach; ?> | |
| 7449 | + </ul> | |
| 7450 | + <?php endif; ?> | |
| 7451 | + <p> | |
| 7452 | + <?php | |
| 7453 | + printf( | |
| 7454 | + /* translators: %d: Seconds a scan runs for at most */ | |
| 7455 | + esc_html__( 'Run the scan again: a second scan is faster, because what it downloads from WordPress.org is kept for a while. If the result is still partial, either the server cannot reach WordPress.org or the site is larger than a scan can check in its %d seconds, and then every scan leaves the same part unchecked. Adding large folders that do not need checking to Excluded Paths leaves more time for the rest.', 'vigilante' ), | |
| 7456 | + (int) Vigilante_File_Integrity::MAX_SCAN_SECONDS | |
| 7457 | + ); | |
| 7458 | + ?> | |
| 7459 | + </p> | |
| 7460 | + <?php if ( ! empty( $vg_folders_to_skip ) ) : ?> | |
| 7461 | + <p><strong><?php esc_html_e( 'To check what was left out:', 'vigilante' ); ?></strong></p> | |
| 7462 | + <ol style="margin: 0 0 8px 18px;"> | |
| 7463 | + <li><?php esc_html_e( 'Deal first with what this scan found in the plugins and themes it did check: the next result will not list it. Then add the lines below, which are their folders, to Excluded Paths, higher up on this page, and save.', 'vigilante' ); ?></li> | |
| 7464 | + <li><?php esc_html_e( 'Press Run Scan Now. The scan spends its time on the rest. If it comes out partial again, repeat with the lines it gives then.', 'vigilante' ); ?></li> | |
| 7465 | + <li><?php esc_html_e( 'Take those lines out of Excluded Paths. While they are there no scan looks inside those folders, the scheduled one included.', 'vigilante' ); ?></li> | |
| 7466 | + </ol> | |
| 7467 | + <textarea id="vigilante-fi-folders-to-exclude" readonly rows="<?php echo (int) min( 12, max( 3, count( $vg_folders_to_skip ) ) ); ?>" class="large-text code" style="margin-bottom: 8px;"><?php echo esc_textarea( implode( "\n", $vg_folders_to_skip ) ); ?></textarea> | |
| 7468 | + <?php endif; ?> | |
| 7469 | + </div> | |
| 7470 | + <?php endif; ?> | |
| 7471 | + | |
| 7472 | + <?php if ( ! empty( $vg_missing_core ) ) : ?> | |
| 7473 | + <div class="vigilante-file-list"> | |
| 7474 | + <h3><?php esc_html_e( 'Missing Files', 'vigilante' ); ?></h3> | |
| 7475 | + <p class="description"><?php esc_html_e( 'These files are in the official copy and not on the server. Reinstall what they belong to (WordPress from Dashboard > Updates, a plugin or a theme from its own screen) and scan again.', 'vigilante' ); ?></p> | |
| 7476 | + <ul style="margin: 8px 0 12px 18px; list-style: disc;"> | |
| 7477 | + <?php foreach ( array_slice( $vg_missing_core, 0, 20 ) as $vg_missing_file ) : ?> | |
| 7478 | + <li><code><?php echo esc_html( $vg_missing_file ); ?></code></li> | |
| 7479 | + <?php endforeach; ?> | |
| 7480 | + </ul> | |
| 7481 | + <?php if ( count( $vg_missing_core ) > 20 ) : ?> | |
| 7482 | + <p class="description"> | |
| 7483 | + <?php | |
| 7484 | + /* translators: %d: Number of additional files */ | |
| 7485 | + printf( esc_html__( '... and %d more', 'vigilante' ), (int) ( count( $vg_missing_core ) - 20 ) ); | |
| 7486 | + ?> | |
| 7487 | + </p> | |
| 7488 | + <?php endif; ?> | |
| 7489 | + </div> | |
| 7490 | + <?php endif; ?> | |
| 7491 | + | |
| 7321 | 7492 | <?php if ( ! empty( $last_results['suspicious'] ) ) : ?> |
| 7322 | 7493 | <div class="vigilante-file-list vigilante-suspicious-files vigilante-paginated-section" data-bulk-mode="ignore"> |
| 7323 | 7494 | <h3 style="color: #d63638;"><?php esc_html_e( 'Suspicious Files', 'vigilante' ); ?></h3> |
| 7324 | - <p class="description" style="color: #d63638;"><?php esc_html_e( '⚠ Warning: These files may contain malicious code or are in unexpected locations. Review immediately!', 'vigilante' ); ?></p> | |
| 7495 | + <p class="description" style="color: #d63638;"><?php esc_html_e( '⚠ Files that can run code where none is expected, or that contain code written the way malware hides itself. Real infections show up here, and so do harmless files that plugins generate. Check the path and the reason before acting.', 'vigilante' ); ?></p> | |
| 7496 | + <?php $this->render_fi_guidance( $last_results['suspicious'] ); ?> | |
| 7325 | 7497 | <div class="vigilante-fi-bulk-bar"> |
| 7326 | 7498 | <button type="button" class="button vigilante-bulk-ignore" disabled><?php esc_html_e( 'Ignore selected', 'vigilante' ); ?></button> |
| 7327 | 7499 | <span class="vigilante-fi-bulk-count" aria-live="polite"></span> |
| 7328 | 7500 | </div> |
| @@ -7358,8 +7530,11 @@ | ||
| 7358 | 7530 | $file_path = (string) $item; |
| 7359 | 7531 | } |
| 7360 | 7532 | if ( 'vigilante_self' === $file_type ) { |
| 7361 | 7533 | $file_type = __( 'Vigilant (self)', 'vigilante' ); |
| 7534 | + } else { | |
| 7535 | + // A name a person can read, instead of the internal slug. | |
| 7536 | + $file_type = Vigilante_File_Integrity::finding_guidance( $file_type )['label']; | |
| 7362 | 7537 | } |
| 7363 | 7538 | ?> |
| 7364 | 7539 | <tr> |
| 7365 | 7540 | <th scope="row" class="check-column"><input type="checkbox" class="vigilante-fi-cb" value="<?php echo esc_attr( $file_path ); ?>"></th> |
| @@ -7378,9 +7553,10 @@ | ||
| 7378 | 7553 | |
| 7379 | 7554 | <?php if ( ! empty( $last_results['extra'] ) ) : ?> |
| 7380 | 7555 | <div class="vigilante-file-list vigilante-extra-files vigilante-paginated-section" data-bulk-mode="ignore"> |
| 7381 | 7556 | <h3 style="color: #b32d2e;"><?php esc_html_e( 'Extra Files', 'vigilante' ); ?></h3> |
| 7382 | - <p class="description"><?php esc_html_e( 'PHP files found in plugins or themes that are not part of the original distribution from WordPress.org. May be legitimate customizations or injected backdoors.', 'vigilante' ); ?></p> | |
| 7557 | + <p class="description"><?php esc_html_e( 'Files that are not part of WordPress, or of the plugin or theme they sit in. Many are legitimate, and an injected file looks the same from here, so confirm where each one comes from.', 'vigilante' ); ?></p> | |
| 7558 | + <?php $this->render_fi_guidance( $last_results['extra'] ); ?> | |
| 7383 | 7559 | <div class="vigilante-fi-bulk-bar"> |
| 7384 | 7560 | <button type="button" class="button vigilante-bulk-ignore" disabled><?php esc_html_e( 'Ignore selected', 'vigilante' ); ?></button> |
| 7385 | 7561 | <span class="vigilante-fi-bulk-count" aria-live="polite"></span> |
| 7386 | 7562 | </div> |
| @@ -7402,8 +7578,11 @@ | ||
| 7402 | 7578 | $file_reason = is_array( $item ) ? ( $item['reason'] ?? __( 'Unknown', 'vigilante' ) ) : __( 'Unknown', 'vigilante' ); |
| 7403 | 7579 | $file_type = is_array( $item ) ? ( $item['type'] ?? 'unknown' ) : 'unknown'; |
| 7404 | 7580 | if ( 'vigilante_self' === $file_type ) { |
| 7405 | 7581 | $file_type = __( 'Vigilant (self)', 'vigilante' ); |
| 7582 | + } else { | |
| 7583 | + // A name a person can read, instead of the internal slug. | |
| 7584 | + $file_type = Vigilante_File_Integrity::finding_guidance( $file_type )['label']; | |
| 7406 | 7585 | } |
| 7407 | 7586 | ?> |
| 7408 | 7587 | <tr> |
| 7409 | 7588 | <th scope="row" class="check-column"><input type="checkbox" class="vigilante-fi-cb" value="<?php echo esc_attr( $file_path ); ?>"></th> |
| @@ -7452,9 +7631,9 @@ | ||
| 7452 | 7631 | <?php if ( ! empty( $critical_modified ) ) : ?> |
| 7453 | 7632 | <div class="vigilante-file-list vigilante-critical-config-files"> |
| 7454 | 7633 | <h3 style="color: #e36210;"><?php esc_html_e( 'Critical config files modified', 'vigilante' ); ?></h3> |
| 7455 | 7634 | <p class="description"> |
| 7456 | - <?php esc_html_e( 'These files are common targets for code injection. Review the changes and approve if they are legitimate. Vigilant\'s own blocks are excluded from this check.', 'vigilante' ); ?> | |
| 7635 | + <?php esc_html_e( 'These files changed since you last approved them. They are a common target for code injection, and they are also rewritten by cache, security and redirection plugins, often on every update. Review the changes and approve them if they belong to something you use: approving records the current content as the reference and does not touch the file. Vigilant\'s own blocks are excluded from this check, and Vigilant never restores these files by itself.', 'vigilante' ); ?> | |
| 7457 | 7636 | </p> |
| 7458 | 7637 | <table class="wp-list-table widefat fixed striped"> |
| 7459 | 7638 | <thead> |
| 7460 | 7639 | <tr> |
| @@ -7615,9 +7794,10 @@ | ||
| 7615 | 7794 | |
| 7616 | 7795 | <?php if ( ! empty( $regular_modified ) ) : ?> |
| 7617 | 7796 | <div class="vigilante-file-list vigilante-paginated-section" data-bulk-mode="ignore"> |
| 7618 | 7797 | <h3><?php esc_html_e( 'Modified Files', 'vigilante' ); ?></h3> |
| 7619 | - <p class="description"><?php esc_html_e( 'These files (apparently) differ from the original WordPress or plugin versions.', 'vigilante' ); ?></p> | |
| 7798 | + <p class="description"><?php esc_html_e( 'These files do not match the copy WordPress.org publishes for the installed version.', 'vigilante' ); ?></p> | |
| 7799 | + <?php $this->render_fi_guidance( $regular_modified ); ?> | |
| 7620 | 7800 | <div class="vigilante-fi-bulk-bar"> |
| 7621 | 7801 | <button type="button" class="button vigilante-bulk-ignore" disabled><?php esc_html_e( 'Ignore selected', 'vigilante' ); ?></button> |
| 7622 | 7802 | <span class="vigilante-fi-bulk-count" aria-live="polite"></span> |
| 7623 | 7803 | </div> |
| @@ -7648,8 +7828,11 @@ | ||
| 7648 | 7828 | $file_path = (string) $item; |
| 7649 | 7829 | } |
| 7650 | 7830 | if ( 'vigilante_self' === $file_type ) { |
| 7651 | 7831 | $file_type = __( 'Vigilant (self)', 'vigilante' ); |
| 7832 | + } else { | |
| 7833 | + // A name a person can read, instead of the internal slug. | |
| 7834 | + $file_type = Vigilante_File_Integrity::finding_guidance( $file_type )['label']; | |
| 7652 | 7835 | } |
| 7653 | 7836 | ?> |
| 7654 | 7837 | <tr> |
| 7655 | 7838 | <th scope="row" class="check-column"><input type="checkbox" class="vigilante-fi-cb" value="<?php echo esc_attr( $file_path ); ?>"></th> |
| @@ -7671,11 +7854,11 @@ | ||
| 7671 | 7854 | // above, this line contradicted it (its findings no longer |
| 7672 | 7855 | // travel in the tables below). |
| 7673 | 7856 | $vg_self_alarm = in_array( $this->self_integrity_summary( $options )['tone'], array( 'critical', 'off', 'warning' ), true ); |
| 7674 | 7857 | ?> |
| 7675 | - <?php if ( $last_results && ! $vg_self_alarm && empty( $critical_modified ) && empty( $regular_modified ) && empty( $last_results['suspicious'] ) && empty( $last_results['extra'] ) && ! $has_closed ) : ?> | |
| 7858 | + <?php if ( $last_results && ! $vg_self_alarm && empty( $critical_modified ) && empty( $regular_modified ) && empty( $last_results['suspicious'] ) && empty( $last_results['extra'] ) && ! $has_closed && ! $vg_scan_partial && empty( $vg_missing_core ) ) : ?> | |
| 7676 | 7859 | <p class="vigilante-all-clear" style="color: #00a32a; font-weight: bold;"> |
| 7677 | - <?php esc_html_e( 'Good Job! All files passed integrity check. No issues found.', 'vigilante' ); ?> | |
| 7860 | + <?php esc_html_e( 'Good job! Nothing to report in the files that were checked.', 'vigilante' ); ?> | |
| 7678 | 7861 | </p> |
| 7679 | 7862 | <?php endif; ?> |
| 7680 | 7863 | <?php endif; ?> |
| 7681 | 7864 | </div> |
| @@ -7724,9 +7907,9 @@ | ||
| 7724 | 7907 | |
| 7725 | 7908 | <?php if ( ! empty( $ignored_files ) ) : ?> |
| 7726 | 7909 | <div id="vigilante-section-fi-ignored" class="vigilante-settings-section"> |
| 7727 | 7910 | <h2><?php esc_html_e( 'Ignored Files', 'vigilante' ); ?></h2> |
| 7728 | - <p class="description"><?php esc_html_e( 'These files are excluded from scan results and email notifications. They will still be scanned but any findings will be hidden.', 'vigilante' ); ?></p> | |
| 7911 | + <p class="description"><?php esc_html_e( 'These files are excluded from scan results and email notifications. They will still be scanned but any findings will be hidden. To leave a whole folder out, add it to Excluded Paths instead.', 'vigilante' ); ?></p> | |
| 7729 | 7912 | <div class="vigilante-paginated-section" data-bulk-mode="unignore"> |
| 7730 | 7913 | <div class="vigilante-fi-bulk-bar"> |
| 7731 | 7914 | <button type="button" class="button vigilante-bulk-unignore" disabled><?php esc_html_e( 'Stop ignoring selected', 'vigilante' ); ?></button> |
| 7732 | 7915 | <span class="vigilante-fi-bulk-count" aria-live="polite"></span> |
| @@ -8959,8 +9142,12 @@ | ||
| 8959 | 9142 | $scanned_at = get_option( 'vigilante_last_integrity_scan' ); |
| 8960 | 9143 | |
| 8961 | 9144 | delete_option( 'vigilante_last_integrity_results' ); |
| 8962 | 9145 | delete_option( 'vigilante_last_integrity_scan' ); |
| 9146 | + | |
| 9147 | + // Starting over also means being told again: the next scan emails | |
| 9148 | + // whatever it finds, as if nothing had been reported before. | |
| 9149 | + delete_option( Vigilante_File_Integrity::NOTIFIED_OPTION ); | |
| 8963 | 9150 | |
| 8964 | 9151 | /* |
| 8965 | 9152 | * A pending change to wp-config.php or the root .htaccess is closed by |
| 8966 | 9153 | * approving it, which takes the network. Clearing the results was one |