mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-06-27 01:41:44 +02:00
Added missing web folder
This commit is contained in:
191
src/web/tools/ipscan.html
Normal file
191
src/web/tools/ipscan.html
Normal file
@ -0,0 +1,191 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1"/>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="theme-color" content="#4b75ff">
|
||||
<link rel="icon" type="image/png" href="./favicon.png" />
|
||||
<title>IP Scanner | Zoraxy</title>
|
||||
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
|
||||
<script src="../script/jquery-3.6.0.min.js"></script>
|
||||
<script src="../../script/ao_module.js"></script>
|
||||
<script src="../script/semantic/semantic.min.js"></script>
|
||||
<script src="../script/tablesort.js"></script>
|
||||
<link rel="stylesheet" href="../main.css">
|
||||
<style>
|
||||
.offlinehost{
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="ui container">
|
||||
<br>
|
||||
<div class="ui segment">
|
||||
<div style="padding: 1em;">
|
||||
<div class="ui stackable grid">
|
||||
<div class="eight wide column">
|
||||
<h4 class="ui dividing header">Scan IP Range</h4>
|
||||
<div class="ui form">
|
||||
<div class="field">
|
||||
<label>Start IP</label>
|
||||
<input type="text" id="start-ip" name="start-ip">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>End IP</label>
|
||||
<input type="text" id="end-ip" name="end-ip">
|
||||
</div>
|
||||
<button class="ui basic button scanbtn" id="ip-scan-btn"><i class="blue search icon"></i> Scan</button>
|
||||
</div>
|
||||
<br>
|
||||
</div>
|
||||
<div class="eight wide column">
|
||||
<h4 class="ui dividing header">Scan CIDR Range</h4>
|
||||
<div class="ui form">
|
||||
<div class="field">
|
||||
<label>CIDR</label>
|
||||
<input type="text" id="cidr" name="cidr">
|
||||
</div>
|
||||
<button class="ui basic button scanbtn" id="cidr-scan-btn"><i class="blue search icon"></i> Scan</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="ui basic button" onclick="toggleOfflineHost();"><i class="grey eye icon"></i>View Offline Hosts</button>
|
||||
<div class="ui divider"></div>
|
||||
<br>
|
||||
<div id="scan-results" style="overflow-x: auto;">
|
||||
|
||||
</div>
|
||||
<br>
|
||||
<div style="float: right;">
|
||||
<button class="ui basic button" style="margin-right: 1em;" onclick="window.open('', '_self', ''); window.close();"><i class="ui red remove icon"></i> Close</button>
|
||||
</div>
|
||||
<br><br><br>
|
||||
</div>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('#ip-scan-btn').click(function(event) {
|
||||
event.preventDefault();
|
||||
var start = $('#start-ip').val().trim();
|
||||
var end = $('#end-ip').val().trim();
|
||||
if (start === '' || end === '') {
|
||||
alert('Please enter start and end IP range');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isValidIPv4(start) || !isValidIPv4(end)){
|
||||
alert('Invalid start or end ip address');
|
||||
return;
|
||||
}
|
||||
|
||||
$(".scanbtn").addClass("disabled");
|
||||
$("#scan-results").html(`
|
||||
<div class="ui basic segment" align="center">
|
||||
<i class="loading spinner icon"></i> Scanning
|
||||
</div>`);
|
||||
$.post("/api/tools/ipscan", {start: start, end: end}, function(data) {
|
||||
displayResults(data);
|
||||
$(".scanbtn").removeClass("disabled");
|
||||
});
|
||||
});
|
||||
|
||||
$('#cidr-scan-btn').click(function(event) {
|
||||
event.preventDefault();
|
||||
var cidr = $('#cidr').val().trim();
|
||||
if (cidr === '') {
|
||||
alert('Please enter CIDR notation');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isValidCIDR(cidr)){
|
||||
alert("Invalid CIDR notation string given");
|
||||
return;
|
||||
}
|
||||
$(".scanbtn").addClass("disabled");
|
||||
$("#scan-results").html(`
|
||||
<div class="ui basic segment" align="center">
|
||||
<i class="loading spinner icon"></i> Scanning
|
||||
</div>`);
|
||||
$.post("/api/tools/ipscan", {cidr: cidr}, function(data) {
|
||||
displayResults(data);
|
||||
$(".scanbtn").removeClass("disabled");
|
||||
});
|
||||
});
|
||||
|
||||
function isValidCIDR(str) {
|
||||
const cidrRegex = /^(\d{1,3}\.){3}\d{1,3}\/\d{1,2}$/;
|
||||
return cidrRegex.test(str);
|
||||
}
|
||||
|
||||
|
||||
function isValidIPv4(ip) {
|
||||
var regex = /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/;
|
||||
if (!regex.test(ip)) {
|
||||
return false;
|
||||
}
|
||||
var parts = ip.split(".");
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
if (parseInt(parts[i], 10) > 255) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function displayResults(data) {
|
||||
var table = $('<table class="ui celled unstackable table"></table>');
|
||||
var header = $('<thead><tr><th>IP Address</th><th>Ping</th><th>Hostname</th><th>HTTP Detected</th><th>HTTPS Detected</th></tr></thead>');
|
||||
table.append(header);
|
||||
var body = $('<tbody></tbody>');
|
||||
var offlineHostCounter = 0;
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var classname = "offlinehost";
|
||||
if (data[i].Ping>=0){
|
||||
classname = "onlinehost";
|
||||
}else{
|
||||
offlineHostCounter++;
|
||||
}
|
||||
var row = $('<tr class="' + classname + '"></tr>');
|
||||
var status = data[i].Ping >= 0 ? '<i class="green circle icon"></i>' : '<i class="grey circle icon"></i>';
|
||||
row.append($('<td>' + status + data[i].IP + '</td>'));
|
||||
row.append($('<td>' + ((data[i].Ping>=0)?data[i].Ping+"ms":"Host Unreachable") + '</td>'));
|
||||
row.append($('<td>' + data[i].Hostname + '</td>'));
|
||||
row.append($('<td>' + (data[i].HttpPortDetected ? '<i class="green check icon"></i>' : '') + '</td>'));
|
||||
row.append($('<td>' + (data[i].HttpsPortDetected ? '<i class="green check icon"></i>' : '') + '</td>'));
|
||||
body.append(row);
|
||||
}
|
||||
|
||||
if (data.length == 0){
|
||||
var body = $(`<tbody>
|
||||
<tr>
|
||||
<td colspan="5">
|
||||
<i class="green circle check icon"></i> Discover no devices in given IP range
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>`);
|
||||
}
|
||||
|
||||
if (offlineHostCounter == data.length){
|
||||
//All offline
|
||||
var body = $(`<tbody>
|
||||
<tr>
|
||||
<td colspan="5">
|
||||
<i class="green circle check icon"></i> All hosts in given IP range are offline
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>`);
|
||||
}
|
||||
table.append(body);
|
||||
$('#scan-results').empty().append(table);
|
||||
}
|
||||
});
|
||||
|
||||
function toggleOfflineHost(){
|
||||
$(".offlinehost").toggle();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
131
src/web/tools/mdns.html
Normal file
131
src/web/tools/mdns.html
Normal file
@ -0,0 +1,131 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1"/>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="theme-color" content="#4b75ff">
|
||||
<link rel="icon" type="image/png" href="./favicon.png" />
|
||||
<title>mDNS Discovery | Zoraxy</title>
|
||||
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
|
||||
<script src="../script/jquery-3.6.0.min.js"></script>
|
||||
<script src="../../script/ao_module.js"></script>
|
||||
<script src="../script/semantic/semantic.min.js"></script>
|
||||
<script src="../script/tablesort.js"></script>
|
||||
<link rel="stylesheet" href="../main.css">
|
||||
<style>
|
||||
body{
|
||||
overflow-x: auto;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="mdns-hosts">
|
||||
|
||||
</div>
|
||||
<br>
|
||||
<div class="ui container">
|
||||
<h4>Scan with custom domain filter</h4>
|
||||
<div class="ui form">
|
||||
<div class="field">
|
||||
<label for="domain">Domain</label>
|
||||
<input type="text" id="domain" name="domain" placeholder="domain.example.com"/>
|
||||
</div>
|
||||
<button id="discover" class="ui basic button">Discover</button>
|
||||
<small><span id="countdownTimer"></span></small>
|
||||
</div>
|
||||
<br>
|
||||
</div>
|
||||
|
||||
<div style="float: right;">
|
||||
<button class="ui basic button" onclick="initMDNSScan()"><i class="ui green refresh icon"></i> Refresh</button>
|
||||
<button class="ui basic button" style="margin-right: 1em;" onclick="window.open('', '_self', ''); window.close();"><i class="ui red remove icon"></i> Close</button>
|
||||
</div>
|
||||
<br><br><br>
|
||||
<script>
|
||||
function initMDNSScan(){
|
||||
$.get("/api/mdns/list", function(data){
|
||||
renderMDNSHosts(data);
|
||||
});
|
||||
}
|
||||
initMDNSScan();
|
||||
|
||||
$("#discover").on("click", function() {
|
||||
var domain = $("#domain").val();
|
||||
$("#discover").addClass("loading").addClass('disabled');
|
||||
setCountdown();
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/api/mdns/discover",
|
||||
data: { domain: domain },
|
||||
success: function(data) {
|
||||
$("#discover").removeClass("loading").removeClass('disabled');
|
||||
renderMDNSHosts(data);
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error(error);
|
||||
// Handle error response here
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function setCountdown() {
|
||||
var timeLeft = 29;
|
||||
var countdownTimer = document.getElementById("countdownTimer");
|
||||
|
||||
// Update the timer every second
|
||||
var countdownInterval = setInterval(function() {
|
||||
if (timeLeft <= 0) {
|
||||
clearInterval(countdownInterval);
|
||||
countdownTimer.innerHTML = "Scan Completed";
|
||||
} else {
|
||||
countdownTimer.innerHTML = "Estimated Remaining Time: " + timeLeft + " seconds";
|
||||
timeLeft--;
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function renderMDNSHosts(data) {
|
||||
// Create table header
|
||||
var tableHeader = $('<thead>').append(
|
||||
$('<tr>').append(
|
||||
$('<th>').text('Host Name'),
|
||||
$('<th>').text('IP Address'),
|
||||
$('<th>').text('MAC Address'),
|
||||
$('<th>').text('Model'),
|
||||
$('<th>').text('Vendor')
|
||||
)
|
||||
);
|
||||
|
||||
// Create table body
|
||||
var tableBody = $('<tbody>');
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var host = data[i];
|
||||
var ipAddresses = host.IPv4.join('<br> ');
|
||||
var macAddresses = host.MacAddr.join('<br> ');
|
||||
if (macAddresses.trim() == ""){
|
||||
macAddresses = '<i class="ui red remove icon"></i> Not Supported'
|
||||
}
|
||||
var row = $('<tr>').append(
|
||||
$('<td>').html(`<a target="_blank" href="//${host.HostName}:${host.Port}">${host.HostName}</a>`),
|
||||
$('<td>').html(ipAddresses),
|
||||
$('<td>').html(macAddresses),
|
||||
$('<td>').text(host.Model),
|
||||
$('<td>').text(host.Vendor)
|
||||
);
|
||||
tableBody.append(row);
|
||||
}
|
||||
|
||||
// Create table with header and body
|
||||
var table = $('<table>').addClass('ui celled unstackable table').append(tableHeader, tableBody);
|
||||
|
||||
// Render table in HTML element with ID 'mdns-hosts'
|
||||
$('#mdns-hosts').html(table);
|
||||
|
||||
if (data.length == 0){
|
||||
$('#mdns-hosts').find("tbody").append(`<tr><td colspan="5"><i class="ui green circle check icon"></i> No scan results</td></tr>`);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
201
src/web/tools/sshconn.html
Normal file
201
src/web/tools/sshconn.html
Normal file
@ -0,0 +1,201 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1"/>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="theme-color" content="#4b75ff">
|
||||
<link rel="icon" type="image/png" href="./favicon.png" />
|
||||
<title>Web SSH | Zoraxy</title>
|
||||
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
|
||||
<script src="../script/jquery-3.6.0.min.js"></script>
|
||||
<script src="../../script/ao_module.js"></script>
|
||||
<script src="../script/semantic/semantic.min.js"></script>
|
||||
<script src="../script/tablesort.js"></script>
|
||||
<link rel="stylesheet" href="../main.css">
|
||||
<style>
|
||||
#loadingUI{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: black;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display:none;
|
||||
}
|
||||
|
||||
#loadingUI div{
|
||||
color: white;
|
||||
font-family: monospace;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="loadingUI">
|
||||
<div style="margin-top: 2em; margin-left: 2em; color: white;">
|
||||
<i class="ui loading spinner icon"></i> <b>Creating virtual terminal session</b><br>
|
||||
<div id="counter" style="color: white; margin-left: 1.9em;">Setting Up Environment</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="connectionSettings">
|
||||
<div class="ui container">
|
||||
<br>
|
||||
<div class="ui form">
|
||||
<div class="two fields">
|
||||
<div class="field">
|
||||
<label>Server Name or IP Address</label>
|
||||
<input type="text" name="server" placeholder="e.g. example.com or 192.168.1.1">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>Port Number</label>
|
||||
<input type="number" name="port" placeholder="e.g. 22 or 2022">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>Username</label>
|
||||
<input type="text" name="username" placeholder="root">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="ui error message">
|
||||
|
||||
</div>
|
||||
|
||||
<div style="float: right;">
|
||||
<button class="ui basic button" onclick="connectSSH()"><i class="ui blue exchange icon"></i> Connect</button>
|
||||
<button class="ui basic button" onclick="window.open('', '_self', ''); window.close();"><i class="ui red remove icon"></i> Close</button>
|
||||
</div>
|
||||
</div>
|
||||
<br><br><br>
|
||||
</div>
|
||||
<script>
|
||||
/*
|
||||
SSHCONN
|
||||
|
||||
This interface is designed to start a ssh connection instance
|
||||
and brige the virtual terminal to the web front-end
|
||||
|
||||
Example Usage:
|
||||
let settingPayload = {
|
||||
server: "192.168.1.100",
|
||||
port: 2022,
|
||||
username: "pi"
|
||||
}
|
||||
|
||||
let settings = encodeURIComponent(JSON.stringify(settingPayload));
|
||||
window.open("sshconn.html#" + settings)
|
||||
*/
|
||||
|
||||
if (window.location.hash.length > 1){
|
||||
try{
|
||||
var c = JSON.parse(decodeURIComponent((window.location.hash.substr(1))));
|
||||
$('input[name="server"]').val(c.server);
|
||||
$('input[name="port"]').val(c.port);
|
||||
$('input[name="username"]').val(c.username);
|
||||
connectSSH();
|
||||
}catch(ex){
|
||||
alert("invalid usage")
|
||||
}
|
||||
}
|
||||
|
||||
//Start the SSH connection process
|
||||
function connectSSH() {
|
||||
const serverValue = $('input[name="server"]').val().trim();
|
||||
var portString = $('input[name="port"]').val().trim();
|
||||
if (portString.trim() == ""){
|
||||
portString = "22";
|
||||
}
|
||||
const portValue = parseInt(portString, 10);
|
||||
const username = $('input[name="username"]').val().trim();
|
||||
if (username == ""){
|
||||
username = "root";
|
||||
}
|
||||
// Validate server name or IP address
|
||||
const validServer = isValidServerNameOrIPAddress(serverValue);
|
||||
|
||||
// Validate port number
|
||||
const validPort = (portValue >= 1 && portValue <= 65535);
|
||||
|
||||
if (validServer && validPort) {
|
||||
// Call doSomething function if both inputs are valid
|
||||
createSSHProxy(serverValue, portValue, username);
|
||||
} else {
|
||||
// Display an error message if either input is invalid
|
||||
const errorLabel = $('<div>').addClass('ui red basic label');
|
||||
if (!validServer) {
|
||||
$('input[name="server"]').parent().addClass('error');
|
||||
} else{
|
||||
$('input[name="server"]').parent().removeClass('error');
|
||||
}
|
||||
|
||||
if (!validPort) {
|
||||
$('input[name="port"]').parent().addClass('error');
|
||||
}else{
|
||||
$('input[name="port"]').parent().removeClass('error');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function redirectWithCountdown(url) {
|
||||
$("#loadingUI").show();
|
||||
$("#connectionSettings").hide();
|
||||
var count = 3;
|
||||
var interval = setInterval(function() {
|
||||
$("#counter").html("ETA " + count + " seconds");
|
||||
count--;
|
||||
if (count === 0) {
|
||||
clearInterval(interval);
|
||||
window.location.href = url;
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
|
||||
//Try to ask the server side to create a ssh proxy object
|
||||
function createSSHProxy(remoteAddr, remotePort, username){
|
||||
//Request to create a ssh session instance
|
||||
$.ajax({
|
||||
url: "/api/tools/webssh",
|
||||
data: {ipaddr: remoteAddr, port: remotePort, username:username},
|
||||
method: "POST",
|
||||
success: function(sessionToken){
|
||||
if (sessionToken.error != undefined){
|
||||
alert(sessionToken.error);
|
||||
}else{
|
||||
//Session created. Redirect to ssh terminal
|
||||
redirectWithCountdown("/web.ssh/" + sessionToken + "/");
|
||||
}
|
||||
},
|
||||
error: function(){
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function isValidServerNameOrIPAddress(str) {
|
||||
//loopback
|
||||
if (str == "localhost"){
|
||||
return true;
|
||||
}
|
||||
|
||||
// First, check if the string is a valid IP address
|
||||
const ipAddressRegex = /^(\d{1,3}\.){3}\d{1,3}$/;
|
||||
if (ipAddressRegex.test(str)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the string is not an IP address, check if it is a valid domain name or server name
|
||||
const serverNameRegex = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z]{2,})+$/;
|
||||
if (serverNameRegex.test(str)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// If the string is neither an IP address nor a server name, return false
|
||||
return false;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Reference in New Issue
Block a user