Changeset 3483103
- Timestamp:
- 03/15/2026 01:16:49 PM (3 weeks ago)
- Location:
- vulntitan/trunk
- Files:
-
- 12 edited
-
CHANGELOG.md (modified) (1 diff)
-
assets/css/admin.css (modified) (1 diff)
-
assets/css/admin.min.css (modified) (1 diff)
-
assets/js/integrity-scanner.js (modified) (6 diffs)
-
assets/js/integrity-scanner.min.js (modified) (6 diffs)
-
assets/js/malware-scanner.js (modified) (9 diffs)
-
assets/js/malware-scanner.min.js (modified) (9 diffs)
-
assets/js/vulnerability-scanner.js (modified) (7 diffs)
-
assets/js/vulnerability-scanner.min.js (modified) (7 diffs)
-
includes/Admin/Pages/Dashboard.php (modified) (1 diff)
-
readme.txt (modified) (2 diffs)
-
vulntitan.php (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
vulntitan/trunk/CHANGELOG.md
r3483084 r3483103 5 5 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), 6 6 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 8 ## [2.1.6] - 2026-03-15 9 ### Added 10 - Added scan progress status notes that highlight the current component or file during Malware, Vulnerability, and Integrity scans. 7 11 8 12 ## [2.1.5] - 2026-03-15 -
vulntitan/trunk/assets/css/admin.css
r3483084 r3483103 2018 2018 } 2019 2019 2020 #vulntitan-scan-progress-bar-container { 2021 height: auto; 2022 overflow: visible; 2023 } 2024 2025 .vulntitan-scan-progress-note { 2026 margin-top: 8px; 2027 font-size: 12px; 2028 color: #93c5fd; 2029 letter-spacing: 0.02em; 2030 display: none; 2031 } 2032 2020 2033 .vulntitan-integrity-legend-grid { 2021 2034 display: grid; -
vulntitan/trunk/assets/css/admin.min.css
r3483084 r3483103 2018 2018 } 2019 2019 2020 #vulntitan-scan-progress-bar-container { 2021 height: auto; 2022 overflow: visible; 2023 } 2024 2025 .vulntitan-scan-progress-note { 2026 margin-top: 8px; 2027 font-size: 12px; 2028 color: #93c5fd; 2029 letter-spacing: 0.02em; 2030 display: none; 2031 } 2032 2020 2033 .vulntitan-integrity-legend-grid { 2021 2034 display: grid; -
vulntitan/trunk/assets/js/integrity-scanner.js
r3482704 r3483103 20 20 const $resultsList = $('#vulntitan-scan-results'); 21 21 const $progressBarContainer = $('#vulntitan-scan-progress-bar-container'); 22 const $progressNote = $('#vulntitan-scan-progress-note'); 22 23 const problematicFiles = []; 23 24 const statusColors = { … … 44 45 }[m]; 45 46 }); 47 } 48 49 function setProgressNote(text) { 50 if (!$progressNote.length) { 51 return; 52 } 53 54 if (text) { 55 $progressNote.text(text).show(); 56 return; 57 } 58 59 $progressNote.text('').hide(); 60 } 61 62 function formatScanTarget(path) { 63 if (!path) { 64 return ''; 65 } 66 67 const normalized = String(path).replace(/\\/g, '/'); 68 if (normalized.indexOf('wp-config.php') !== -1) { 69 return 'wp-config.php'; 70 } 71 72 const pluginRoot = 'wp-content/plugins/'; 73 const themeRoot = 'wp-content/themes/'; 74 75 if (normalized.indexOf(pluginRoot) !== -1) { 76 const slug = normalized.split(pluginRoot)[1].split('/')[0]; 77 if (slug) { 78 return `${VulnTitan.i18n.vuln_type_plugin || 'Plugin'}: ${slug}`; 79 } 80 } 81 82 if (normalized.indexOf(themeRoot) !== -1) { 83 const slug = normalized.split(themeRoot)[1].split('/')[0]; 84 if (slug) { 85 return `${VulnTitan.i18n.vuln_type_theme || 'Theme'}: ${slug}`; 86 } 87 } 88 89 const basename = normalized.split('/').pop(); 90 return basename || normalized; 46 91 } 47 92 … … 225 270 $('#vulntitan-scan-progress-bar').css('width', '0%'); 226 271 $('#vulntitan-scan-progress-text').text('0%'); 272 setProgressNote(VulnTitan.i18n.preparing || 'Preparing...'); 227 273 $resultsList.html(`<p>${VulnTitan.i18n.preparing}</p>`); 228 274 … … 281 327 consecutiveFailures = 0; 282 328 const batchCount = res.data.results.length; 329 const scanPrefix = VulnTitan.i18n.scanning || 'Scanning'; 330 331 if (batchCount) { 332 const lastResult = res.data.results[batchCount - 1]; 333 const lastLabel = formatScanTarget(lastResult.file_path || ''); 334 if (lastLabel) { 335 setProgressNote(`${scanPrefix}: ${lastLabel}`); 336 } 337 } 283 338 284 339 res.data.results.forEach(result => { … … 328 383 if (res.data.done) { 329 384 $('#vulntitan-scan-progress-text').text(VulnTitan.i18n.scan_finished); 385 setProgressNote(VulnTitan.i18n.scan_finished || 'Scan finished.'); 330 386 renderProblematicFiles(); 331 387 resetUI(); … … 361 417 $btnMlw.prop('disabled', false); 362 418 $progressBarContainer.hide(); 419 setProgressNote(''); 363 420 } 364 421 }); -
vulntitan/trunk/assets/js/integrity-scanner.min.js
r3482704 r3483103 20 20 const $resultsList = $('#vulntitan-scan-results'); 21 21 const $progressBarContainer = $('#vulntitan-scan-progress-bar-container'); 22 const $progressNote = $('#vulntitan-scan-progress-note'); 22 23 const problematicFiles = []; 23 24 const statusColors = { … … 44 45 }[m]; 45 46 }); 47 } 48 49 function setProgressNote(text) { 50 if (!$progressNote.length) { 51 return; 52 } 53 54 if (text) { 55 $progressNote.text(text).show(); 56 return; 57 } 58 59 $progressNote.text('').hide(); 60 } 61 62 function formatScanTarget(path) { 63 if (!path) { 64 return ''; 65 } 66 67 const normalized = String(path).replace(/\\/g, '/'); 68 if (normalized.indexOf('wp-config.php') !== -1) { 69 return 'wp-config.php'; 70 } 71 72 const pluginRoot = 'wp-content/plugins/'; 73 const themeRoot = 'wp-content/themes/'; 74 75 if (normalized.indexOf(pluginRoot) !== -1) { 76 const slug = normalized.split(pluginRoot)[1].split('/')[0]; 77 if (slug) { 78 return `${VulnTitan.i18n.vuln_type_plugin || 'Plugin'}: ${slug}`; 79 } 80 } 81 82 if (normalized.indexOf(themeRoot) !== -1) { 83 const slug = normalized.split(themeRoot)[1].split('/')[0]; 84 if (slug) { 85 return `${VulnTitan.i18n.vuln_type_theme || 'Theme'}: ${slug}`; 86 } 87 } 88 89 const basename = normalized.split('/').pop(); 90 return basename || normalized; 46 91 } 47 92 … … 225 270 $('#vulntitan-scan-progress-bar').css('width', '0%'); 226 271 $('#vulntitan-scan-progress-text').text('0%'); 272 setProgressNote(VulnTitan.i18n.preparing || 'Preparing...'); 227 273 $resultsList.html(`<p>${VulnTitan.i18n.preparing}</p>`); 228 274 … … 281 327 consecutiveFailures = 0; 282 328 const batchCount = res.data.results.length; 329 const scanPrefix = VulnTitan.i18n.scanning || 'Scanning'; 330 331 if (batchCount) { 332 const lastResult = res.data.results[batchCount - 1]; 333 const lastLabel = formatScanTarget(lastResult.file_path || ''); 334 if (lastLabel) { 335 setProgressNote(`${scanPrefix}: ${lastLabel}`); 336 } 337 } 283 338 284 339 res.data.results.forEach(result => { … … 328 383 if (res.data.done) { 329 384 $('#vulntitan-scan-progress-text').text(VulnTitan.i18n.scan_finished); 385 setProgressNote(VulnTitan.i18n.scan_finished || 'Scan finished.'); 330 386 renderProblematicFiles(); 331 387 resetUI(); … … 361 417 $btnMlw.prop('disabled', false); 362 418 $progressBarContainer.hide(); 419 setProgressNote(''); 363 420 } 364 421 }); -
vulntitan/trunk/assets/js/malware-scanner.js
r3482704 r3483103 20 20 const $resultsList = $('#vulntitan-scan-results'); 21 21 const $progressBarContainer = $('#vulntitan-scan-progress-bar-container'); 22 const $progressNote = $('#vulntitan-scan-progress-note'); 22 23 const statusColors = { 23 24 clean: '#10b981', … … 27 28 unknown: '#94a3b8' 28 29 }; 30 const scanPrefix = VulnTitan.i18n.scanning_for_malware || VulnTitan.i18n.scanning || 'Scanning'; 29 31 const stats = { 30 32 total: 0, … … 60 62 $('#vulntitan-scan-progress-bar').css('width', '0%'); 61 63 $('#vulntitan-scan-progress-text').text('0%'); 64 setProgressNote(VulnTitan.i18n.preparing || 'Preparing...'); 62 65 renderLayout(); 63 66 updateOverview(); … … 73 76 }[m]; 74 77 }); 78 } 79 80 function setProgressNote(text) { 81 if (!$progressNote.length) { 82 return; 83 } 84 85 if (text) { 86 $progressNote.text(text).show(); 87 return; 88 } 89 90 $progressNote.text('').hide(); 91 } 92 93 function formatScanTarget(path) { 94 if (!path) { 95 return ''; 96 } 97 98 const normalized = String(path).replace(/\\/g, '/'); 99 if (normalized.indexOf('wp-config.php') !== -1) { 100 return 'wp-config.php'; 101 } 102 103 const pluginRoot = 'wp-content/plugins/'; 104 const themeRoot = 'wp-content/themes/'; 105 106 if (normalized.indexOf(pluginRoot) !== -1) { 107 const slug = normalized.split(pluginRoot)[1].split('/')[0]; 108 if (slug) { 109 return `${VulnTitan.i18n.vuln_type_plugin || 'Plugin'}: ${slug}`; 110 } 111 } 112 113 if (normalized.indexOf(themeRoot) !== -1) { 114 const slug = normalized.split(themeRoot)[1].split('/')[0]; 115 if (slug) { 116 return `${VulnTitan.i18n.vuln_type_theme || 'Theme'}: ${slug}`; 117 } 118 } 119 120 const basename = normalized.split('/').pop(); 121 return basename || normalized; 75 122 } 76 123 … … 465 512 renderProblematicSummary(); 466 513 resetUI(); 514 setProgressNote(''); 467 515 return; 468 516 } … … 475 523 </div> 476 524 `); 525 setProgressNote(VulnTitan.i18n.scan_finished || 'Scan finished.'); 477 526 renderProblematicSummary(); 478 527 resetUI(); … … 482 531 const batch = files.slice(currentIndex, currentIndex + batchSize); 483 532 const $detailsList = $('#vulntitan-malware-details-list'); 533 const scanLabel = formatScanTarget(batch[0]); 534 setProgressNote(scanLabel ? `${scanPrefix}: ${scanLabel}` : scanPrefix + '...'); 484 535 485 536 $.post(ajaxurl, { … … 489 540 }, function (res) { 490 541 if (res.success && Array.isArray(res.data.results)) { 542 if (res.data.results.length) { 543 const lastResult = res.data.results[res.data.results.length - 1]; 544 const lastLabel = formatScanTarget(lastResult.file || ''); 545 if (lastLabel) { 546 setProgressNote(`${scanPrefix}: ${lastLabel}`); 547 } 548 } 491 549 const scopeInfo = { 492 550 scope: res.data.scope, … … 551 609 $btnInt.prop('disabled', false); 552 610 $progressBarContainer.hide(); 611 setProgressNote(''); 553 612 } 554 613 }); -
vulntitan/trunk/assets/js/malware-scanner.min.js
r3482704 r3483103 20 20 const $resultsList = $('#vulntitan-scan-results'); 21 21 const $progressBarContainer = $('#vulntitan-scan-progress-bar-container'); 22 const $progressNote = $('#vulntitan-scan-progress-note'); 22 23 const statusColors = { 23 24 clean: '#10b981', … … 27 28 unknown: '#94a3b8' 28 29 }; 30 const scanPrefix = VulnTitan.i18n.scanning_for_malware || VulnTitan.i18n.scanning || 'Scanning'; 29 31 const stats = { 30 32 total: 0, … … 60 62 $('#vulntitan-scan-progress-bar').css('width', '0%'); 61 63 $('#vulntitan-scan-progress-text').text('0%'); 64 setProgressNote(VulnTitan.i18n.preparing || 'Preparing...'); 62 65 renderLayout(); 63 66 updateOverview(); … … 73 76 }[m]; 74 77 }); 78 } 79 80 function setProgressNote(text) { 81 if (!$progressNote.length) { 82 return; 83 } 84 85 if (text) { 86 $progressNote.text(text).show(); 87 return; 88 } 89 90 $progressNote.text('').hide(); 91 } 92 93 function formatScanTarget(path) { 94 if (!path) { 95 return ''; 96 } 97 98 const normalized = String(path).replace(/\\/g, '/'); 99 if (normalized.indexOf('wp-config.php') !== -1) { 100 return 'wp-config.php'; 101 } 102 103 const pluginRoot = 'wp-content/plugins/'; 104 const themeRoot = 'wp-content/themes/'; 105 106 if (normalized.indexOf(pluginRoot) !== -1) { 107 const slug = normalized.split(pluginRoot)[1].split('/')[0]; 108 if (slug) { 109 return `${VulnTitan.i18n.vuln_type_plugin || 'Plugin'}: ${slug}`; 110 } 111 } 112 113 if (normalized.indexOf(themeRoot) !== -1) { 114 const slug = normalized.split(themeRoot)[1].split('/')[0]; 115 if (slug) { 116 return `${VulnTitan.i18n.vuln_type_theme || 'Theme'}: ${slug}`; 117 } 118 } 119 120 const basename = normalized.split('/').pop(); 121 return basename || normalized; 75 122 } 76 123 … … 465 512 renderProblematicSummary(); 466 513 resetUI(); 514 setProgressNote(''); 467 515 return; 468 516 } … … 475 523 </div> 476 524 `); 525 setProgressNote(VulnTitan.i18n.scan_finished || 'Scan finished.'); 477 526 renderProblematicSummary(); 478 527 resetUI(); … … 482 531 const batch = files.slice(currentIndex, currentIndex + batchSize); 483 532 const $detailsList = $('#vulntitan-malware-details-list'); 533 const scanLabel = formatScanTarget(batch[0]); 534 setProgressNote(scanLabel ? `${scanPrefix}: ${scanLabel}` : scanPrefix + '...'); 484 535 485 536 $.post(ajaxurl, { … … 489 540 }, function (res) { 490 541 if (res.success && Array.isArray(res.data.results)) { 542 if (res.data.results.length) { 543 const lastResult = res.data.results[res.data.results.length - 1]; 544 const lastLabel = formatScanTarget(lastResult.file || ''); 545 if (lastLabel) { 546 setProgressNote(`${scanPrefix}: ${lastLabel}`); 547 } 548 } 491 549 const scopeInfo = { 492 550 scope: res.data.scope, … … 551 609 $btnInt.prop('disabled', false); 552 610 $progressBarContainer.hide(); 611 setProgressNote(''); 553 612 } 554 613 }); -
vulntitan/trunk/assets/js/vulnerability-scanner.js
r3482704 r3483103 20 20 const $progressBarContainer = $('#vulntitan-scan-progress-bar-container'); 21 21 const $progressBar = $('#vulntitan-scan-progress-bar'); 22 const $progressNote = $('#vulntitan-scan-progress-note'); 22 23 const $resultsContainer = $('#vulntitan-scan-results-container'); 23 24 const items = VulnTitan.scanItems || []; … … 70 71 $progressBar.css('width', '0%'); 71 72 $('#vulntitan-scan-progress-text').text('0%'); 73 setProgressNote(VulnTitan.i18n.preparing || 'Preparing...'); 72 74 73 75 if (!items.length) { … … 75 77 resetUI(); 76 78 $resultsContainer.removeClass('is-vulnerability-layout'); 79 setProgressNote(''); 77 80 return; 78 81 } … … 94 97 }[match]; 95 98 }); 99 } 100 101 function setProgressNote(text) { 102 if (!$progressNote.length) { 103 return; 104 } 105 106 if (text) { 107 $progressNote.text(text).show(); 108 return; 109 } 110 111 $progressNote.text('').hide(); 96 112 } 97 113 … … 396 412 if (currentIndex >= total) { 397 413 updateProgress(); 414 setProgressNote(VulnTitan.i18n.scan_finished || 'Scan finished.'); 398 415 $detailsList.append(` 399 416 <article class="vulntitan-vuln-detail-item is-finished"> … … 407 424 const item = items[currentIndex]; 408 425 const rowId = 'scan-item-' + currentIndex; 426 setProgressNote(`${VulnTitan.i18n.scanning || 'Scanning'}: ${componentDisplayName(item)}`); 409 427 410 428 $detailsList.append(renderDetailItem(item, { … … 430 448 updateOverview(); 431 449 updateProgress(); 450 setProgressNote(VulnTitan.i18n.scan_stopped || 'Scan stopped due to error.'); 432 451 resetUI(); 433 452 $detailsList.append(` -
vulntitan/trunk/assets/js/vulnerability-scanner.min.js
r3482704 r3483103 20 20 const $progressBarContainer = $('#vulntitan-scan-progress-bar-container'); 21 21 const $progressBar = $('#vulntitan-scan-progress-bar'); 22 const $progressNote = $('#vulntitan-scan-progress-note'); 22 23 const $resultsContainer = $('#vulntitan-scan-results-container'); 23 24 const items = VulnTitan.scanItems || []; … … 70 71 $progressBar.css('width', '0%'); 71 72 $('#vulntitan-scan-progress-text').text('0%'); 73 setProgressNote(VulnTitan.i18n.preparing || 'Preparing...'); 72 74 73 75 if (!items.length) { … … 75 77 resetUI(); 76 78 $resultsContainer.removeClass('is-vulnerability-layout'); 79 setProgressNote(''); 77 80 return; 78 81 } … … 94 97 }[match]; 95 98 }); 99 } 100 101 function setProgressNote(text) { 102 if (!$progressNote.length) { 103 return; 104 } 105 106 if (text) { 107 $progressNote.text(text).show(); 108 return; 109 } 110 111 $progressNote.text('').hide(); 96 112 } 97 113 … … 396 412 if (currentIndex >= total) { 397 413 updateProgress(); 414 setProgressNote(VulnTitan.i18n.scan_finished || 'Scan finished.'); 398 415 $detailsList.append(` 399 416 <article class="vulntitan-vuln-detail-item is-finished"> … … 407 424 const item = items[currentIndex]; 408 425 const rowId = 'scan-item-' + currentIndex; 426 setProgressNote(`${VulnTitan.i18n.scanning || 'Scanning'}: ${componentDisplayName(item)}`); 409 427 410 428 $detailsList.append(renderDetailItem(item, { … … 430 448 updateOverview(); 431 449 updateProgress(); 450 setProgressNote(VulnTitan.i18n.scan_stopped || 'Scan stopped due to error.'); 432 451 resetUI(); 433 452 $detailsList.append(` -
vulntitan/trunk/includes/Admin/Pages/Dashboard.php
r3482704 r3483103 126 126 <span id="vulntitan-scan-progress-text">0%</span> 127 127 </div> 128 <div id="vulntitan-scan-progress-note" class="vulntitan-scan-progress-note" aria-live="polite"></div> 128 129 </div> 129 130 -
vulntitan/trunk/readme.txt
r3483090 r3483103 4 4 Tested up to: 6.9 5 5 Requires PHP: 7.4 6 Stable tag: 2.1. 56 Stable tag: 2.1.6 7 7 License: GPLv2 8 8 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 165 165 == Changelog == 166 166 167 = v2.1.6 - 15 Mar, 2026 = 168 * Added scan progress status notes that highlight the current component or file during Malware, Vulnerability, and Integrity scans. 169 167 170 = v2.1.5 - 15 Mar, 2026 = 168 171 * Added role-based 2FA enforcement so selected roles must enroll before using the admin dashboard, with a direct setup shortcut. -
vulntitan/trunk/vulntitan.php
r3483084 r3483103 4 4 * Plugin URI: https://vulntitan.com/vulntitan/ 5 5 * Description: VulnTitan is a WordPress security plugin with vulnerability scanning, malware detection, file integrity monitoring, comment anti-spam protection, and a built-in firewall with WAF payload rules and login protection. 6 * Version: 2.1. 56 * Version: 2.1.6 7 7 * Author: Jaroslav Svetlik 8 8 * Author URI: https://vulntitan.com … … 30 30 31 31 // Define plugin constants 32 define('VULNTITAN_PLUGIN_VERSION', VULNTITAN_DEVELOPMENT ? uniqid() : '2.1. 5');32 define('VULNTITAN_PLUGIN_VERSION', VULNTITAN_DEVELOPMENT ? uniqid() : '2.1.6'); 33 33 define('VULNTITAN_PLUGIN_BASENAME', plugin_basename(__FILE__)); 34 34 define('VULNTITAN_PLUGIN_DIR', untrailingslashit(plugin_dir_path(__FILE__)));
Note: See TracChangeset
for help on using the changeset viewer.