167 lines
7.0 KiB
PHP
167 lines
7.0 KiB
PHP
@extends('layouts.app')
|
|
|
|
@section('content')
|
|
<div class="container py-5">
|
|
<div class="row justify-content-center">
|
|
<div class="col-md-8">
|
|
<div class="card shadow-sm">
|
|
<div class="card-body p-4">
|
|
<div class="text-center mb-5">
|
|
<h2 class="display-5 fw-bold mb-3">Port Scanner</h2>
|
|
<p class="lead text-muted">Check if a port is open on any IP address</p>
|
|
</div>
|
|
|
|
<div class="mb-5">
|
|
<form id="portScanForm" class="needs-validation" novalidate>
|
|
<div class="row g-4">
|
|
<div class="col-md-6">
|
|
<div class="form-floating">
|
|
<input type="text" class="form-control" id="ip" name="ip" required
|
|
placeholder="IP Address">
|
|
<label for="ip">IP Address</label>
|
|
<div class="invalid-feedback">
|
|
Please enter a valid IP address
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-floating">
|
|
<input type="number" class="form-control" id="port" name="port" required
|
|
min="1" max="65535" placeholder="Port">
|
|
<label for="port">Port</label>
|
|
<div class="invalid-feedback">
|
|
Please enter a valid port number (1-65535)
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="text-center mt-4">
|
|
<button type="submit" class="btn btn-primary btn-lg px-5">
|
|
<i class="bi bi-search me-2"></i>Scan Port
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<div id="result" class="d-none">
|
|
<div class="card bg-light border-0">
|
|
<div class="card-body">
|
|
<div class="d-flex align-items-center">
|
|
<div class="flex-shrink-0">
|
|
<i id="statusIcon" class="bi bi-circle-fill fs-1"></i>
|
|
</div>
|
|
<div class="flex-grow-1 ms-3">
|
|
<h3 id="resultTitle" class="h5 mb-2"></h3>
|
|
<div id="resultDetails" class="text-muted"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="loading" class="d-none">
|
|
<div class="text-center py-4">
|
|
<div class="spinner-border text-primary" role="status">
|
|
<span class="visually-hidden">Loading...</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
@push('scripts')
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const form = document.getElementById('portScanForm');
|
|
const result = document.getElementById('result');
|
|
const loading = document.getElementById('loading');
|
|
const statusIcon = document.getElementById('statusIcon');
|
|
const resultTitle = document.getElementById('resultTitle');
|
|
const resultDetails = document.getElementById('resultDetails');
|
|
|
|
// Form validation
|
|
form.addEventListener('submit', async function(e) {
|
|
e.preventDefault();
|
|
|
|
if (!form.checkValidity()) {
|
|
e.stopPropagation();
|
|
form.classList.add('was-validated');
|
|
return;
|
|
}
|
|
|
|
// Show loading, hide result
|
|
loading.classList.remove('d-none');
|
|
result.classList.add('d-none');
|
|
|
|
try {
|
|
const response = await fetch('/port-scanner/scan', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
|
|
},
|
|
body: JSON.stringify({
|
|
ip: document.getElementById('ip').value,
|
|
port: document.getElementById('port').value
|
|
})
|
|
});
|
|
|
|
const data = await response.json();
|
|
|
|
// Set icon based on status
|
|
if (data.status === 'open') {
|
|
statusIcon.className = 'bi bi-check-circle-fill text-success fs-1';
|
|
} else {
|
|
statusIcon.className = 'bi bi-x-circle-fill text-danger fs-1';
|
|
}
|
|
|
|
// Set result content
|
|
resultTitle.textContent = data.message;
|
|
resultDetails.innerHTML = `
|
|
<div class="row g-3">
|
|
<div class="col-md-4">
|
|
<div class="p-2 bg-white rounded">
|
|
<small class="d-block text-muted">Response Time</small>
|
|
<strong>${data.response_time}ms</strong>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="p-2 bg-white rounded">
|
|
<small class="d-block text-muted">IP Address</small>
|
|
<strong>${data.ip}</strong>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="p-2 bg-white rounded">
|
|
<small class="d-block text-muted">Port</small>
|
|
<strong>${data.port}</strong>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
// Show result, hide loading
|
|
result.classList.remove('d-none');
|
|
loading.classList.add('d-none');
|
|
} catch (error) {
|
|
// Show error
|
|
statusIcon.className = 'bi bi-exclamation-circle-fill text-danger fs-1';
|
|
resultTitle.textContent = 'Error';
|
|
resultDetails.innerHTML = `
|
|
<div class="alert alert-danger mb-0">
|
|
An error occurred while scanning the port. Please try again.
|
|
</div>
|
|
`;
|
|
|
|
// Show result, hide loading
|
|
result.classList.remove('d-none');
|
|
loading.classList.add('d-none');
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
@endpush
|
|
@endsection
|