Download src/static/script.js from Fred808/NSL: direct link, hf CLI and curl.
- Browser
- Download file 11.1 kB
-
https://huggingface.co/spaces/Fred808/NSL/resolve/main/src/static/script.js
- Command line
-
hf download hf://spaces/Fred808/NSL/src/static/script.js
-
curl -L -o script.js https://huggingface.co/spaces/Fred808/NSL/resolve/main/src/static/script.js
11.1 kB
| class PortScanner { | |
| constructor() { | |
| this.isScanning = false; | |
| this.progressInterval = null; | |
| this.initializeEventListeners(); | |
| } | |
| initializeEventListeners() { | |
| // Form elements | |
| this.targetIpInput = document.getElementById('target-ip'); | |
| this.startPortInput = document.getElementById('start-port'); | |
| this.endPortInput = document.getElementById('end-port'); | |
| this.timeoutInput = document.getElementById('timeout'); | |
| this.threadsInput = document.getElementById('threads'); | |
| // Buttons | |
| this.scanBtn = document.getElementById('scan-btn'); | |
| this.pingBtn = document.getElementById('ping-btn'); | |
| this.exportBtn = document.getElementById('export-btn'); | |
| this.clearBtn = document.getElementById('clear-btn'); | |
| // Sections | |
| this.progressSection = document.getElementById('progress-section'); | |
| this.resultsSection = document.getElementById('results-section'); | |
| // Event listeners | |
| this.scanBtn.addEventListener('click', () => this.startScan()); | |
| this.pingBtn.addEventListener('click', () => this.pingHost()); | |
| this.exportBtn.addEventListener('click', () => this.exportResults()); | |
| this.clearBtn.addEventListener('click', () => this.clearResults()); | |
| // Preset buttons | |
| document.querySelectorAll('.preset-btn').forEach(btn => { | |
| btn.addEventListener('click', (e) => { | |
| const start = e.target.dataset.start; | |
| const end = e.target.dataset.end; | |
| this.startPortInput.value = start; | |
| this.endPortInput.value = end; | |
| }); | |
| }); | |
| // Form validation | |
| this.targetIpInput.addEventListener('input', () => this.validateForm()); | |
| this.startPortInput.addEventListener('input', () => this.validateForm()); | |
| this.endPortInput.addEventListener('input', () => this.validateForm()); | |
| } | |
| validateForm() { | |
| const ip = this.targetIpInput.value.trim(); | |
| const startPort = parseInt(this.startPortInput.value); | |
| const endPort = parseInt(this.endPortInput.value); | |
| let isValid = true; | |
| // IP validation | |
| if (!ip || !this.isValidIP(ip)) { | |
| isValid = false; | |
| } | |
| // Port validation | |
| if (startPort < 1 || endPort > 65535 || startPort > endPort) { | |
| isValid = false; | |
| } | |
| this.scanBtn.disabled = !isValid || this.isScanning; | |
| return isValid; | |
| } | |
| isValidIP(ip) { | |
| const ipRegex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; | |
| return ipRegex.test(ip); | |
| } | |
| async pingHost() { | |
| const ip = this.targetIpInput.value.trim(); | |
| if (!ip || !this.isValidIP(ip)) { | |
| this.showNotification('Please enter a valid IP address', 'error'); | |
| return; | |
| } | |
| this.pingBtn.disabled = true; | |
| this.pingBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Pinging...'; | |
| try { | |
| const response = await fetch('/api/ping', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| body: JSON.stringify({ ip: ip }) | |
| }); | |
| const data = await response.json(); | |
| if (response.ok) { | |
| const status = data.status === 'reachable' ? 'Host is reachable' : 'Host appears unreachable'; | |
| const type = data.status === 'reachable' ? 'success' : 'error'; | |
| this.showNotification(status, type); | |
| } else { | |
| this.showNotification(data.error || 'Ping failed', 'error'); | |
| } | |
| } catch (error) { | |
| this.showNotification('Network error during ping', 'error'); | |
| } finally { | |
| this.pingBtn.disabled = false; | |
| this.pingBtn.innerHTML = '<i class="fas fa-satellite-dish"></i> Ping'; | |
| } | |
| } | |
| async startScan() { | |
| if (!this.validateForm()) { | |
| this.showNotification('Please check your input values', 'error'); | |
| return; | |
| } | |
| const scanData = { | |
| ip: this.targetIpInput.value.trim(), | |
| start_port: parseInt(this.startPortInput.value), | |
| end_port: parseInt(this.endPortInput.value), | |
| timeout: parseFloat(this.timeoutInput.value), | |
| threads: parseInt(this.threadsInput.value) | |
| }; | |
| // Check port range limit | |
| const portRange = scanData.end_port - scanData.start_port + 1; | |
| if (portRange > 10000) { | |
| this.showNotification('Port range too large (max 10000 ports)', 'error'); | |
| return; | |
| } | |
| this.isScanning = true; | |
| this.scanBtn.disabled = true; | |
| this.scanBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Scanning...'; | |
| // Show progress section | |
| this.progressSection.style.display = 'block'; | |
| this.resultsSection.style.display = 'none'; | |
| // Start progress monitoring | |
| this.startProgressMonitoring(); | |
| try { | |
| const response = await fetch('/api/scan', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| body: JSON.stringify(scanData) | |
| }); | |
| const data = await response.json(); | |
| if (response.ok) { | |
| this.displayResults(data); | |
| this.showNotification(`Scan completed! Found ${data.total_open} open ports`, 'success'); | |
| } else { | |
| this.showNotification(data.error || 'Scan failed', 'error'); | |
| } | |
| } catch (error) { | |
| this.showNotification('Network error during scan', 'error'); | |
| } finally { | |
| this.stopProgressMonitoring(); | |
| this.isScanning = false; | |
| this.scanBtn.disabled = false; | |
| this.scanBtn.innerHTML = '<i class="fas fa-search"></i> Start Scan'; | |
| this.progressSection.style.display = 'none'; | |
| } | |
| } | |
| startProgressMonitoring() { | |
| this.progressInterval = setInterval(async () => { | |
| try { | |
| const response = await fetch('/api/progress'); | |
| const data = await response.json(); | |
| const progressFill = document.getElementById('progress-fill'); | |
| const progressText = document.getElementById('progress-text'); | |
| progressFill.style.width = `${data.percentage}%`; | |
| progressText.textContent = `Scanning... ${data.progress}/${data.total} ports (${data.percentage}%)`; | |
| } catch (error) { | |
| console.error('Error fetching progress:', error); | |
| } | |
| }, 500); | |
| } | |
| stopProgressMonitoring() { | |
| if (this.progressInterval) { | |
| clearInterval(this.progressInterval); | |
| this.progressInterval = null; | |
| } | |
| } | |
| displayResults(data) { | |
| const resultsSection = document.getElementById('results-section'); | |
| const resultsSummary = document.getElementById('results-summary'); | |
| const resultsTableBody = document.getElementById('results-tbody'); | |
| // Update summary | |
| resultsSummary.innerHTML = ` | |
| <strong>Target:</strong> ${data.target_ip} | | |
| <strong>Range:</strong> ${data.scan_range} | | |
| <strong>Open Ports:</strong> ${data.total_open}/${data.total_scanned} | | |
| <strong>Duration:</strong> ${data.scan_duration}s | |
| `; | |
| // Clear previous results | |
| resultsTableBody.innerHTML = ''; | |
| // Add results to table | |
| if (data.open_ports && data.open_ports.length > 0) { | |
| data.open_ports.forEach(port => { | |
| const row = document.createElement('tr'); | |
| row.innerHTML = ` | |
| <td><strong>${port.port}</strong></td> | |
| <td><span class="status-${port.status}">${port.status.toUpperCase()}</span></td> | |
| <td>${port.service || 'unknown'}</td> | |
| <td>TCP</td> | |
| `; | |
| resultsTableBody.appendChild(row); | |
| }); | |
| } else { | |
| const row = document.createElement('tr'); | |
| row.innerHTML = '<td colspan="4" style="text-align: center; color: #666;">No open ports found</td>'; | |
| resultsTableBody.appendChild(row); | |
| } | |
| // Show results section | |
| resultsSection.style.display = 'block'; | |
| // Store results for export | |
| this.lastScanResults = data; | |
| } | |
| exportResults() { | |
| if (!this.lastScanResults) { | |
| this.showNotification('No results to export', 'error'); | |
| return; | |
| } | |
| const data = this.lastScanResults; | |
| let csvContent = 'Port,Status,Service,Protocol\n'; | |
| if (data.open_ports && data.open_ports.length > 0) { | |
| data.open_ports.forEach(port => { | |
| csvContent += `${port.port},${port.status},${port.service || 'unknown'},TCP\n`; | |
| }); | |
| } | |
| // Create and download file | |
| const blob = new Blob([csvContent], { type: 'text/csv' }); | |
| const url = window.URL.createObjectURL(blob); | |
| const a = document.createElement('a'); | |
| a.href = url; | |
| a.download = `port_scan_${data.target_ip}_${new Date().toISOString().slice(0, 19).replace(/:/g, '-')}.csv`; | |
| document.body.appendChild(a); | |
| a.click(); | |
| document.body.removeChild(a); | |
| window.URL.revokeObjectURL(url); | |
| this.showNotification('Results exported successfully', 'success'); | |
| } | |
| clearResults() { | |
| this.resultsSection.style.display = 'none'; | |
| this.lastScanResults = null; | |
| this.showNotification('Results cleared', 'info'); | |
| } | |
| showNotification(message, type = 'info') { | |
| const notification = document.getElementById('notification'); | |
| notification.textContent = message; | |
| notification.className = `notification ${type}`; | |
| notification.classList.add('show'); | |
| setTimeout(() => { | |
| notification.classList.remove('show'); | |
| }, 4000); | |
| } | |
| } | |
| // Initialize the application when DOM is loaded | |
| document.addEventListener('DOMContentLoaded', () => { | |
| new PortScanner(); | |
| }); | |
| // Add some utility functions for better UX | |
| document.addEventListener('keydown', (e) => { | |
| if (e.key === 'Enter' && e.target.tagName === 'INPUT') { | |
| const scanner = new PortScanner(); | |
| if (scanner.validateForm()) { | |
| scanner.startScan(); | |
| } | |
| } | |
| }); | |
| // Auto-focus on IP input when page loads | |
| window.addEventListener('load', () => { | |
| document.getElementById('target-ip').focus(); | |
| }); | |