First Bjorn Commit !
120
web/bjorn.html
Normal file
@@ -0,0 +1,120 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Bjorn Cyberviking - Bjorn</title>
|
||||
<link rel="icon" href="web/images/favicon.ico" type="image/x-icon">
|
||||
<link rel="stylesheet" href="web/css/styles.css">
|
||||
<link rel="manifest" href="manifest.json">
|
||||
<link rel="apple-touch-icon" href="images/apple-touch-icon.png">
|
||||
<script defer>
|
||||
var delay = 5000; // Default value in case the fetch fails
|
||||
var intervalId;
|
||||
|
||||
function fetchWebDelay() {
|
||||
fetch('/get_web_delay')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
delay = data.web_delay;
|
||||
startLiveview(); // Start live view after setting the delay
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error fetching web delay:', error);
|
||||
startLiveview(); // Start live view even if fetch fails
|
||||
});
|
||||
}
|
||||
|
||||
function updateImage() {
|
||||
var image = document.getElementById("screenImage_Home");
|
||||
var newImage = new Image();
|
||||
newImage.onload = function() {
|
||||
image.src = newImage.src; // Update only if the new image loads successfully
|
||||
};
|
||||
newImage.onerror = function() {
|
||||
console.warn("New image could not be loaded, keeping the previous image.");
|
||||
};
|
||||
newImage.src = "screen.png?t=" + new Date().getTime(); // Prevent caching
|
||||
}
|
||||
|
||||
function startLiveview() {
|
||||
updateImage(); // Immediately update the image
|
||||
intervalId = setInterval(updateImage, delay); // Then update at the specified interval
|
||||
}
|
||||
|
||||
function stopLiveview() {
|
||||
clearInterval(intervalId);
|
||||
}
|
||||
|
||||
function resizeImage(event) {
|
||||
var image = document.getElementById("screenImage_Home");
|
||||
var height = parseFloat(window.getComputedStyle(image).height);
|
||||
if (event.deltaY < 0) {
|
||||
// Scroll up, increase height
|
||||
height *= 1.1;
|
||||
} else {
|
||||
// Scroll down, decrease height
|
||||
height /= 1.1;
|
||||
}
|
||||
image.style.height = height + 'px';
|
||||
image.style.width = 'auto'; // Ensure aspect ratio is maintained
|
||||
}
|
||||
|
||||
function toggleMenu() {
|
||||
var toolbar = document.querySelector('.toolbar');
|
||||
var imageContainer = document.querySelector('.image-container');
|
||||
if (toolbar.style.display === 'flex') {
|
||||
toolbar.style.display = 'none';
|
||||
imageContainer.style.width = '100%'; // Adjust width when toolbar is hidden
|
||||
} else {
|
||||
toolbar.style.display = 'flex';
|
||||
imageContainer.style.width = 'calc(100%)'; // Adjust width when toolbar is visible
|
||||
}
|
||||
adjustImageHeight(); // Adjust image height after toggling toolbar
|
||||
}
|
||||
|
||||
function adjustImageHeight() {
|
||||
var windowHeight = window.innerHeight;
|
||||
var image = document.getElementById("screenImage_Home");
|
||||
image.style.height = windowHeight + 'px';
|
||||
image.style.width = 'auto'; // Maintain aspect ratio
|
||||
}
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
fetchWebDelay(); // Fetch web delay on load
|
||||
adjustImageHeight();
|
||||
});
|
||||
window.addEventListener('beforeunload', stopLiveview);
|
||||
window.addEventListener('wheel', resizeImage);
|
||||
window.addEventListener('resize', adjustImageHeight); // Adjust height on window resize
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="toolbar" id="mainToolbar">
|
||||
<button type="button" onclick="window.location.href='/index.html'" title="Playground">
|
||||
<img src="/web/images/console_icon.png" alt="Bjorn" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/config.html'" title="Config">
|
||||
<img src="/web/images/config_icon.png" alt="Icon_config" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/network.html'" title="Network">
|
||||
<img src="/web/images/network_icon.png" alt="Icon_network" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/netkb.html'" title="NetKB">
|
||||
<img src="/web/images/netkb_icon.png" alt="Icon_netkb" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/credentials.html'" title="Credentials">
|
||||
<img src="/web/images/cred_icon.png" alt="Icon_cred" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/loot.html'" title="Loot">
|
||||
<img src="/web/images/loot_icon.png" alt="Icon_loot" style="height: 50px;">
|
||||
</button>
|
||||
</div>
|
||||
<div class="image-container">
|
||||
<img id="screenImage_Home" src="screen.png" onclick="toggleMenu()" alt="Bjorn">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
65
web/config.html
Normal file
@@ -0,0 +1,65 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Bjorn Cyberviking - Config</title>
|
||||
<link rel="icon" href="web/images/favicon.ico" type="image/x-icon">
|
||||
<link rel="stylesheet" href="web/css/styles.css">
|
||||
<link rel="manifest" href="manifest.json">
|
||||
<link rel="apple-touch-icon" href="images/apple-touch-icon.png">
|
||||
<script src="web/scripts/config.js" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="toolbar" id="mainToolbar">
|
||||
<button type="button" onclick="window.location.href='/index.html'" title="Playground">
|
||||
<img src="/web/images/console_icon.png" alt="Bjorn" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/config.html'" title="Config">
|
||||
<img src="/web/images/config_icon.png" alt="Icon_config" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/network.html'" title="Network">
|
||||
<img src="/web/images/network_icon.png" alt="Icon_network" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/netkb.html'" title="NetKB">
|
||||
<img src="/web/images/netkb_icon.png" alt="Icon_netkb" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/credentials.html'" title="Credentials">
|
||||
<img src="/web/images/cred_icon.png" alt="Icon_cred" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/loot.html'" title="Loot">
|
||||
<img src="/web/images/loot_icon.png" alt="Icon_loot" style="height: 50px;">
|
||||
</button>
|
||||
</div>
|
||||
<div class="console-toolbar">
|
||||
<button type="button" class="toolbar-button" onclick="adjustConfigFontSize(-1)" title="-">
|
||||
<img src="/web/images/less.png" alt="Icon_less" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" class="toolbar-button" onclick="saveConfig()" title="Save">
|
||||
<img src="/web/images/save.png" alt="Icon_plus" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" class="toolbar-button" onclick="restoreDefault()" title="Restore Default">
|
||||
<img src="/web/images/restore.png" alt="Icon_plus" style="height: 50px;">
|
||||
</button>
|
||||
<button id="toggle-toolbar" type="button" class="toolbar-button" onclick="toggleConfigToolbar()" data-open="false">
|
||||
<img id="toggle-icon" src="/web/images/hide.png" alt="Toggle Toolbar" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" class="toolbar-button" onclick="toggleWifiPanel()">
|
||||
<img src="/web/images/wifi.png" alt="wifi" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" class="toolbar-button" onclick="adjustConfigFontSize(1)" title="+">
|
||||
<img src="/web/images/plus.png" alt="Icon_plus" style="height: 50px;">
|
||||
</button>
|
||||
</div>
|
||||
<div class="config-container">
|
||||
<form class="config-form"></form>
|
||||
</div>
|
||||
<div id="wifi-panel" class="wifi-panel">
|
||||
<div class="wifi-panel-header">
|
||||
<h3>Available Wi-Fi Networks</h3>
|
||||
<button class="close-btn" onclick="closeWifiPanel()">✖</button>
|
||||
</div>
|
||||
<ul id="wifi-list"></ul>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
53
web/credentials.html
Normal file
@@ -0,0 +1,53 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Bjorn Cyberviking - Credentials</title>
|
||||
<link rel="icon" href="web/images/favicon.ico" type="image/x-icon">
|
||||
<link rel="stylesheet" href="web/css/styles.css">
|
||||
<link rel="manifest" href="manifest.json">
|
||||
<link rel="apple-touch-icon" href="images/apple-touch-icon.png">
|
||||
<script src="web/scripts/credentials.js" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="toolbar" id="mainToolbar">
|
||||
<button type="button" onclick="window.location.href='/index.html'" title="Playground">
|
||||
<img src="/web/images/console_icon.png" alt="Bjorn" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/config.html'" title="Config">
|
||||
<img src="/web/images/config_icon.png" alt="Icon_config" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/network.html'" title="Network">
|
||||
<img src="/web/images/network_icon.png" alt="Icon_network" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/netkb.html'" title="NetKB">
|
||||
<img src="/web/images/netkb_icon.png" alt="Icon_netkb" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/credentials.html'" title="Credentials">
|
||||
<img src="/web/images/cred_icon.png" alt="Icon_cred" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/loot.html'" title="Loot">
|
||||
<img src="/web/images/loot_icon.png" alt="Icon_loot" style="height: 50px;">
|
||||
</button>
|
||||
</div>
|
||||
<div class="console-toolbar">
|
||||
<button type="button" class="toolbar-button" onclick="adjustCredFontSize(-1)" title="-">
|
||||
<img src="/web/images/less.png" alt="Icon_less" style="height: 50px;">
|
||||
</button>
|
||||
<button id="toggle-toolbar" type="button" class="toolbar-button" onclick="toggleCredToolbar()" data-open="false">
|
||||
<img id="toggle-icon" src="/web/images/hide.png" alt="Toggle Toolbar" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" class="toolbar-button" onclick="adjustCredFontSize(1)" title="+">
|
||||
<img src="/web/images/plus.png" alt="Icon_plus" style="height: 50px;">
|
||||
</button>
|
||||
</div>
|
||||
<div class="credentials-container">
|
||||
<h1 id="cred-title">Credentials</h1>
|
||||
<div id="credentials-table">
|
||||
<!-- Les tableaux seront insérés ici par JavaScript -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
589
web/css/styles.css
Normal file
@@ -0,0 +1,589 @@
|
||||
/* General styling */
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
background-color: #333;
|
||||
-ms-overflow-style: -ms-autohiding-scrollbar;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
html {
|
||||
height: 100%;
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: #888 #333;
|
||||
}
|
||||
|
||||
/* Scrollbar styling */
|
||||
::-webkit-scrollbar {
|
||||
width: 12px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: #333;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: #888;
|
||||
border-radius: 10px;
|
||||
border: 3px solid #333;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #555;
|
||||
}
|
||||
|
||||
/* Toolbar styling */
|
||||
|
||||
.toolbar {
|
||||
background-color: #333;
|
||||
display: flex;
|
||||
padding: 0;
|
||||
flex-wrap: wrap;
|
||||
|
||||
}
|
||||
|
||||
.toolbar a, .toolbar button, .toolbar-button {
|
||||
color: rgb(255, 255, 255);
|
||||
text-align: center;
|
||||
padding: 1px 1px;
|
||||
text-decoration: none;
|
||||
margin: 3px;
|
||||
flex: 1 1 auto;
|
||||
border-radius: 20px;
|
||||
border: none;
|
||||
background-color: #444444;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.toolbar a:hover, .toolbar button:hover, .toolbar-button:hover, .action-button:hover {
|
||||
background-color: #e99f00;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.loot-container {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
padding-bottom: 100px;
|
||||
padding-left: 20px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul li {
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
ul li a {
|
||||
color: #e99f00;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
ul li a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
strong {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* Container styling */
|
||||
.network-container, .netkb-container {
|
||||
flex: 1;
|
||||
font-size: 16px;
|
||||
padding-left: 20px;
|
||||
overflow: auto; /* Add scrollbars if needed */
|
||||
color: white;
|
||||
}
|
||||
|
||||
#netkb-table, #network-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse; /* Collapse borders */
|
||||
|
||||
}
|
||||
|
||||
#action-dropdown, #port-dropdown, #ip-dropdown {
|
||||
color: white;
|
||||
background-color: #444444;
|
||||
border-radius: 15%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.console-toolbar {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.console-toolbar button {
|
||||
margin-left: 5px;
|
||||
font-size: 14px;
|
||||
}
|
||||
#cred-title {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.credentials-container {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
padding-bottom: 100px;
|
||||
padding-left: 20px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#credentials-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
color: #ee9025 !important;
|
||||
}
|
||||
|
||||
#credentials-table th {
|
||||
background-color: rgb(99, 99, 99);
|
||||
color: white;
|
||||
}
|
||||
.toobar1-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
background-color: #333;
|
||||
}
|
||||
.config-container {
|
||||
display: flex;
|
||||
flex-direction: column; /* Ensure children are stacked vertically */
|
||||
color: #e0e0e0;
|
||||
background-color: #333;
|
||||
height: calc(100vh - 100px); /* Adjust height considering the toolbar and config buttons */
|
||||
overflow: hidden;
|
||||
padding-left: 10px;
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
.action-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
color: #e0e0e0;
|
||||
flex: 1 1 auto;
|
||||
background-color: #333;
|
||||
height: calc(100vh - 10px);
|
||||
overflow: hidden;
|
||||
padding-left: 2px;
|
||||
padding: 20px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.action-panel {
|
||||
display: flex;
|
||||
flex-wrap: wrap; /* Allow items to wrap to the next line */
|
||||
align-items: flex-start;
|
||||
justify-content: center; /* Center align items horizontally */
|
||||
gap: 10px;
|
||||
margin-top: 20px; /* Add some space between text and buttons */
|
||||
}
|
||||
|
||||
.action-button {
|
||||
color: rgb(255, 255, 255);
|
||||
text-align: center;
|
||||
padding: 20px 20px;
|
||||
text-decoration: none;
|
||||
margin: 5px;
|
||||
border-radius: 50px; /* Adjust the value as needed to get the desired roundness */
|
||||
border: none; /* Remove default border */
|
||||
background-color: rgb(19, 109, 0); /* Background color for the buttons */
|
||||
cursor: pointer; /* Add a pointer cursor on hover */
|
||||
}
|
||||
|
||||
.image-container {
|
||||
background-color: #333;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-grow: 1;
|
||||
width: 100%; /* Ensure the container takes full width */
|
||||
padding-bottom: 80px;
|
||||
}
|
||||
|
||||
/* Image styling */
|
||||
.image-container img {
|
||||
height: 100%; /* Ensure image takes full height */
|
||||
width: auto; /* Ensure aspect ratio is maintained */
|
||||
}
|
||||
|
||||
#screenImage_Home {
|
||||
max-height: 100%;
|
||||
width: auto;
|
||||
display: block;
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Form styling */
|
||||
.config-form {
|
||||
font-size: 11px;
|
||||
display: flex;
|
||||
flex-grow: 1; /* Allow the form to grow and occupy available space */
|
||||
min-width: 275px; /* Set a minimum width */
|
||||
overflow-y: auto;
|
||||
|
||||
padding: 5px;
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
|
||||
.right-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-end;
|
||||
align-content: stretch;
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
.left-column,
|
||||
.right-column {
|
||||
flex: 1; /* Allow these items to grow and fill available space */
|
||||
padding: 10px; /* Add some padding for better appearance */
|
||||
box-sizing: border-box; /* Include padding in the element's total width and height */
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.left-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.label-switch {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: rgb(255, 255, 255);
|
||||
margin-bottom: 20px; /* Space between switches */
|
||||
}
|
||||
|
||||
.label-switch label {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
color: rgb(255, 255, 255);
|
||||
margin-bottom: 20px; /* Space below the section title */
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.section-item {
|
||||
font-weight: bold;
|
||||
font-size: 15px;
|
||||
color: rgb(255, 255, 255);
|
||||
margin-bottom: 20px; /* Space below each section item */
|
||||
}
|
||||
|
||||
.config-buttons {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
background-color: #333;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
/* Switch styling */
|
||||
.switch {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 60px;
|
||||
height: 34px;
|
||||
margin: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.switch input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.slider {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #ccc;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
.slider:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 26px;
|
||||
width: 26px;
|
||||
left: 4px;
|
||||
bottom: 4px;
|
||||
background-color: white;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
input:checked + .slider {
|
||||
background-color: #e99f00;
|
||||
}
|
||||
|
||||
input:checked + .slider:before {
|
||||
transform: translateX(26px);
|
||||
}
|
||||
|
||||
.slider.round {
|
||||
border-radius: 34px;
|
||||
}
|
||||
|
||||
.slider.round:before {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
/* Wi-Fi panel styling */
|
||||
.wifi-panel {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
right: 20px;
|
||||
background: #333;
|
||||
padding: 20px;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
#bjorn_home {
|
||||
border-radius: 11% !important;
|
||||
}
|
||||
|
||||
.current-wifi {
|
||||
color: blue !important;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.wifi-panel-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.wifi-panel-header h3 {
|
||||
margin: 0;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.wifi-panel .close-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
color: white;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#wifi-list {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#wifi-list li {
|
||||
background: #e0e0e0;
|
||||
margin: 10px 0;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s, color 0.3s;
|
||||
}
|
||||
|
||||
#wifi-list li:hover {
|
||||
background-color: #e99f00;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Config buttons styling */
|
||||
.config-buttons {
|
||||
position: -webkit-sticky;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
background: #333;
|
||||
padding: 10px;
|
||||
z-index: 100;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
|
||||
/* Table and cell styling */
|
||||
table.styled-table {
|
||||
width: 100%;
|
||||
color: rgb(255, 255, 255);
|
||||
border-collapse: collapse;
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
table.styled-table th, table.styled-table td {
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
table.styled-table th {
|
||||
background-color: rgb(10, 9, 9);
|
||||
color: white;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
table.styled-table td.green {
|
||||
color: rgb(0, 255, 0);
|
||||
}
|
||||
|
||||
table.styled-table td.red {
|
||||
background-color: rgb(163, 50, 50);
|
||||
color: white;
|
||||
}
|
||||
|
||||
table.styled-table td.grey {
|
||||
color: grey;
|
||||
}
|
||||
|
||||
.blue-row {
|
||||
color: rgb(18, 0, 184);
|
||||
}
|
||||
|
||||
.green {
|
||||
color: rgb(0, 255, 0);
|
||||
}
|
||||
|
||||
.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.scrollable-table {
|
||||
overflow: auto;
|
||||
max-height: 80vh;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
td:first-child, th:first-child {
|
||||
position: sticky;
|
||||
left: 0;
|
||||
background-color: rgb(10, 9, 9);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
|
||||
/* Dropdown menu styling */
|
||||
#dropdown {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.dropdown-content {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: #333;
|
||||
min-width: 160px;
|
||||
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
||||
z-index: 1;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.dropdown-content button {
|
||||
color: white;
|
||||
padding: 10px 20px;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
width: 100%;
|
||||
border: none;
|
||||
background-color: #333;
|
||||
text-align: left;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.dropdown-content button:hover {
|
||||
background-color: #e99f00;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.dropdown:hover .dropdown-content {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.dropdown.show .dropdown-content {
|
||||
display: block; /* Afficher le menu déroulant */
|
||||
}
|
||||
|
||||
.action-button img {
|
||||
height: 40px;
|
||||
margin-right: 8px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.action-button span {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* Additional styles from inline CSS */
|
||||
body, html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
||||
#log-console {
|
||||
background-color: black;
|
||||
color: white;
|
||||
overflow-y: scroll;
|
||||
font-family: monospace;
|
||||
border: 10px solid #333;
|
||||
font-size: 16px;
|
||||
height: calc(100% - 120px);
|
||||
width: calc(100% - 20px);
|
||||
}
|
||||
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.visible {
|
||||
display: block;
|
||||
height: 50px;
|
||||
background-color: #f4f4f4;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
.debug { color: rgb(173, 173, 173); }
|
||||
.info { color: blue; }
|
||||
.warning { color: yellow; }
|
||||
.error { color: red; }
|
||||
.critical { color: magenta; }
|
||||
.success { color: green; }
|
||||
.line-number { color: #888888; } /* Color for line numbers */
|
||||
.number { color: #42ced3; } /* Color for numbers */
|
||||
|
||||
|
||||
.dropdown-content img {
|
||||
display: block;
|
||||
width: 33%; /* 1/3 of the width */
|
||||
height: auto;
|
||||
}
|
||||
|
||||
|
||||
BIN
web/images/actions_icon.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
web/images/ai.png
Normal file
|
After Width: | Height: | Size: 56 KiB |
BIN
web/images/apple-touch-icon.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
web/images/bjorn_icon.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
web/images/config_icon.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
web/images/console_icon.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
web/images/cred_icon.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
web/images/favicon.ico
Normal file
|
After Width: | Height: | Size: 122 KiB |
BIN
web/images/file.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
web/images/hide.png
Normal file
|
After Width: | Height: | Size: 253 KiB |
BIN
web/images/home.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
web/images/icon-128x128.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
web/images/icon-144x144.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
web/images/icon-152x152.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
web/images/icon-192x192.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
web/images/icon-384x384.png
Normal file
|
After Width: | Height: | Size: 149 KiB |
BIN
web/images/icon-512x512.png
Normal file
|
After Width: | Height: | Size: 238 KiB |
BIN
web/images/icon-60x60.png
Normal file
|
After Width: | Height: | Size: 6.6 KiB |
BIN
web/images/icon-72x72.png
Normal file
|
After Width: | Height: | Size: 8.9 KiB |
BIN
web/images/icon-96x96.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
web/images/less.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
web/images/loot_icon.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
web/images/mainfolder.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
web/images/manual.png
Normal file
|
After Width: | Height: | Size: 56 KiB |
BIN
web/images/manual_icon.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
web/images/netkb_icon.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
web/images/network_icon.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
web/images/off.png
Normal file
|
After Width: | Height: | Size: 79 KiB |
BIN
web/images/on.png
Normal file
|
After Width: | Height: | Size: 80 KiB |
BIN
web/images/plus.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
web/images/restore.png
Normal file
|
After Width: | Height: | Size: 75 KiB |
BIN
web/images/reveal.png
Normal file
|
After Width: | Height: | Size: 252 KiB |
BIN
web/images/save.png
Normal file
|
After Width: | Height: | Size: 93 KiB |
BIN
web/images/subfolder.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
web/images/vulns_icon.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
web/images/wifi.png
Normal file
|
After Width: | Height: | Size: 62 KiB |
173
web/index.html
Normal file
@@ -0,0 +1,173 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Bjorn Cyberviking - Playground</title>
|
||||
<link rel="icon" href="web/images/favicon.ico" type="image/x-icon">
|
||||
<link rel="stylesheet" href="web/css/styles.css">
|
||||
<link rel="manifest" href="manifest.json">
|
||||
<link rel="apple-touch-icon" sizes="192x192" href="web/images/icon-192x192.png">
|
||||
<script src="web/scripts/index.js" defer></script>
|
||||
<script src="https://cdn3.devexpress.com/jslib/20.2.5/js/dx.all.js"></script>
|
||||
<link rel="stylesheet" href="https://cdn3.devexpress.com/jslib/20.2.5/css/dx.common.css">
|
||||
<link rel="stylesheet" href="https://cdn3.devexpress.com/jslib/20.2.5/css/dx.light.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="toolbar" id="mainToolbar">
|
||||
<button type="button" onclick="window.location.href='/index.html'" title="Playground">
|
||||
<img src="/web/images/console_icon.png" alt="Bjorn" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/config.html'" title="Config">
|
||||
<img src="/web/images/config_icon.png" alt="Icon_config" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/network.html'" title="Network">
|
||||
<img src="/web/images/network_icon.png" alt="Icon_network" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/netkb.html'" title="NetKB">
|
||||
<img src="/web/images/netkb_icon.png" alt="Icon_netkb" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/credentials.html'" title="Credentials">
|
||||
<img src="/web/images/cred_icon.png" alt="Icon_cred" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/loot.html'" title="Loot">
|
||||
<img src="/web/images/loot_icon.png" alt="Icon_loot" style="height: 50px;">
|
||||
</button>
|
||||
</div>
|
||||
<div class="console-toolbar">
|
||||
<button type="button" class="toolbar-button" onclick="adjustFontSize(-1)" title="-">
|
||||
<img src="/web/images/less.png" alt="Icon_less" style="height: 50px;">
|
||||
</button>
|
||||
<div id="bjorn-dropdown-container" class="toolbar-button"></div>
|
||||
<button id="toggle-toolbar" type="button" class="toolbar-button" onclick="toggleToolbar()" data-open="false">
|
||||
<img id="toggle-icon" src="/web/images/hide.png" alt="Toggle Toolbar" style="height: 50px;">
|
||||
</button>
|
||||
<div id="dropdown-container" class="toolbar-button"></div>
|
||||
<button type="button" class="toolbar-button" onclick="adjustFontSize(1)" title="+">
|
||||
<img src="/web/images/plus.png" alt="Icon_plus" style="height: 50px;">
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="console-toolbar">
|
||||
<button id="toggle-console-button" class="toolbar-button" type="button" onclick="toggleConsole()">
|
||||
<img id="toggle-console-image" src="/web/images/off.png" alt="Toggle Console" style="height: 30px;">
|
||||
</button>
|
||||
<button id="manual-mode-button" type="button" class="toolbar-button" onclick="toggleManualMode()" title="Manual Mode">
|
||||
<img id="manual-mode-icon" src="/web/images/manual.png" alt="Manual Mode" style="height: 50px;">
|
||||
</button>
|
||||
</div>
|
||||
<div id="manual-mode-panel" class="toolbar-button hidden" class="hidden">
|
||||
<select id="ip-dropdown" onchange="updatePortsAndActions()"></select>
|
||||
<select id="port-dropdown"></select>
|
||||
<select id="action-dropdown"></select>
|
||||
<button type="button" onclick="executeManualAttack()">Execute Attack</button>
|
||||
</div>
|
||||
<div id="log-console"></div>
|
||||
<div id="popupContainer"></div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
adjustLogConsoleHeight();
|
||||
loadManualModeOptions();
|
||||
});
|
||||
|
||||
function loadManualModeOptions() {
|
||||
fetch('/netkb_data_json')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
const ipDropdown = document.getElementById('ip-dropdown');
|
||||
const actionDropdown = document.getElementById('action-dropdown');
|
||||
|
||||
ipDropdown.innerHTML = data.ips.map(ip => `<option value="${ip}">${ip}</option>`).join('');
|
||||
actionDropdown.innerHTML = data.actions.map(action => `<option value="${action}">${action}</option>`).join('');
|
||||
})
|
||||
.catch(error => console.error('Error loading netkb data:', error));
|
||||
}
|
||||
|
||||
function updatePortsAndActions() {
|
||||
const ipDropdown = document.getElementById('ip-dropdown');
|
||||
const selectedIp = ipDropdown.value;
|
||||
|
||||
fetch('/netkb_data_json')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
const portDropdown = document.getElementById('port-dropdown');
|
||||
portDropdown.innerHTML = data.ports[selectedIp].map(port => `<option value="${port}">${port}</option>`).join('');
|
||||
})
|
||||
.catch(error => console.error('Error updating ports:', error));
|
||||
}
|
||||
|
||||
function executeManualAttack() {
|
||||
const ip = document.getElementById('ip-dropdown').value;
|
||||
const port = document.getElementById('port-dropdown').value;
|
||||
const action = document.getElementById('action-dropdown').value;
|
||||
|
||||
fetch('/execute_manual_attack', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ ip, port, action })
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.status === 'success') {
|
||||
console.log('Manual attack executed successfully:', data.message);
|
||||
} else {
|
||||
console.error('Failed to execute manual attack:', data.message);
|
||||
}
|
||||
loadRecentLogs(); // Charger les logs récents après l'exécution de l'attaque
|
||||
})
|
||||
.catch(error => console.error('Error executing manual attack:', error));
|
||||
}
|
||||
|
||||
function loadRecentLogs() {
|
||||
fetch('/recent_logs')
|
||||
.then(response => response.text())
|
||||
.then(data => {
|
||||
const logConsole = document.getElementById('log-console');
|
||||
logConsole.innerHTML = `<pre>${data}</pre>`;
|
||||
})
|
||||
.catch(error => console.error('Error loading recent logs:', error));
|
||||
}
|
||||
|
||||
function toggleManualMode() {
|
||||
const panel = document.getElementById('manual-mode-panel');
|
||||
const icon = document.getElementById('manual-mode-icon');
|
||||
if (panel.classList.contains('hidden')) {
|
||||
panel.classList.remove('hidden');
|
||||
panel.classList.add('visible');
|
||||
icon.src = '/web/images/ai.png';
|
||||
stop_orchestrator();
|
||||
} else {
|
||||
panel.classList.remove('visible');
|
||||
panel.classList.add('hidden');
|
||||
icon.src = '/web/images/manual.png';
|
||||
start_orchestrator();
|
||||
}
|
||||
adjustLogConsoleHeight();
|
||||
}
|
||||
|
||||
function adjustLogConsoleHeight() {
|
||||
const panel = document.getElementById('manual-mode-panel');
|
||||
const logConsole = document.getElementById('log-console');
|
||||
if (panel.classList.contains('visible')) {
|
||||
logConsole.style.height = `calc(100vh - ${panel.offsetHeight}px - 100px)`;
|
||||
} else {
|
||||
logConsole.style.height = 'calc(100vh - 100px)';
|
||||
}
|
||||
}
|
||||
|
||||
function stop_orchestrator() {
|
||||
fetch('/stop_orchestrator', { method: 'POST' })
|
||||
.catch(error => console.error('Failed to stop orchestrator:', error));
|
||||
}
|
||||
|
||||
function start_orchestrator() {
|
||||
fetch('/start_orchestrator', { method: 'POST' })
|
||||
.catch(error => console.error('Failed to start orchestrator:', error));
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
95
web/loot.html
Normal file
@@ -0,0 +1,95 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Bjorn Cyberviking - Loot</title>
|
||||
<link rel="icon" href="web/images/favicon.ico" type="image/x-icon">
|
||||
<link rel="stylesheet" href="web/css/styles.css">
|
||||
<link rel="manifest" href="manifest.json">
|
||||
<link rel="apple-touch-icon" href="images/apple-touch-icon.png">
|
||||
<script src="web/scripts/loot.js" defer></script>
|
||||
|
||||
</head>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const fileList = document.getElementById("file-list");
|
||||
|
||||
let currentPath = "/"; // Start at root
|
||||
|
||||
function fetchFiles(path) {
|
||||
fetch(`/list_files?path=${encodeURIComponent(path)}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
displayFiles(data, path);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error fetching files:', error);
|
||||
});
|
||||
}
|
||||
|
||||
function displayFiles(files, path) {
|
||||
currentPath = path;
|
||||
fileList.innerHTML = "";
|
||||
|
||||
files.forEach(file => {
|
||||
const div = document.createElement("div");
|
||||
div.textContent = file.name;
|
||||
div.classList.add(file.is_directory ? "folder" : "file");
|
||||
|
||||
div.addEventListener("click", () => {
|
||||
if (file.is_directory) {
|
||||
fetchFiles(`${path}/${file.name}`);
|
||||
} else {
|
||||
window.open(`${path}/${file.name}`, '_blank');
|
||||
}
|
||||
});
|
||||
|
||||
fileList.appendChild(div);
|
||||
});
|
||||
}
|
||||
|
||||
fetchFiles(currentPath);
|
||||
});
|
||||
</script>
|
||||
<body>
|
||||
<div class="toolbar" id="mainToolbar">
|
||||
<button type="button" onclick="window.location.href='/index.html'" title="Playground">
|
||||
<img src="/web/images/console_icon.png" alt="Bjorn" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/config.html'" title="Config">
|
||||
<img src="/web/images/config_icon.png" alt="Icon_config" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/network.html'" title="Network">
|
||||
<img src="/web/images/network_icon.png" alt="Icon_network" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/netkb.html'" title="NetKB">
|
||||
<img src="/web/images/netkb_icon.png" alt="Icon_netkb" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/credentials.html'" title="Credentials">
|
||||
<img src="/web/images/cred_icon.png" alt="Icon_cred" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/loot.html'" title="Loot">
|
||||
<img src="/web/images/loot_icon.png" alt="Icon_loot" style="height: 50px;">
|
||||
</button>
|
||||
</div>
|
||||
<div class="console-toolbar">
|
||||
<button type="button" class="toolbar-button" onclick="adjustLootFontSize(-1)" title="-">
|
||||
<img src="/web/images/less.png" alt="Icon_less" style="height: 50px;">
|
||||
</button>
|
||||
|
||||
<button id="toggle-toolbar" type="button" class="toolbar-button" onclick="toggleLootToolbar()" data-open="false">
|
||||
<img id="toggle-icon" src="/web/images/hide.png" alt="Toggle Toolbar" style="height: 50px;">
|
||||
</button>
|
||||
|
||||
<button type="button" class="toolbar-button" onclick="adjustLootFontSize(1)" title="+">
|
||||
<img src="/web/images/plus.png" alt="Icon_plus" style="height: 50px;">
|
||||
</button>
|
||||
</div>
|
||||
<div class="loot-container">
|
||||
<div id="file-list">
|
||||
<!-- The file list will be inserted here by JavaScript -->
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
57
web/manifest.json
Normal file
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"name": "Bjorn Cyberviking",
|
||||
"short_name": "Bjorn",
|
||||
"description": "Bjorn Cyberviking",
|
||||
"start_url": "/index.html",
|
||||
"display": "standalone",
|
||||
"background_color": "#333",
|
||||
"theme_color": "#333",
|
||||
"icons": [
|
||||
{
|
||||
"src": "images/icon-60x60.png",
|
||||
"sizes": "60x60",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "images/icon-72x72.png",
|
||||
"sizes": "72x72",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "images/icon-96x96.png",
|
||||
"sizes": "96x96",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "images/icon-128x128.png",
|
||||
"sizes": "128x128",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "images/icon-144x144.png",
|
||||
"sizes": "144x144",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "images/icon-152x152.png",
|
||||
"sizes": "152x152",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "images/icon-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "images/icon-384x384.png",
|
||||
"sizes": "384x384",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "images/icon-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
54
web/netkb.html
Normal file
@@ -0,0 +1,54 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Bjorn Cyberviking - NetKB</title>
|
||||
<link rel="icon" href="web/images/favicon.ico" type="image/x-icon">
|
||||
<link rel="stylesheet" href="web/css/styles.css">
|
||||
<link rel="manifest" href="manifest.json">
|
||||
<link rel="apple-touch-icon" href="images/apple-touch-icon.png">
|
||||
<script src="web/scripts/netkb.js" defer></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div class="toolbar" id="mainToolbar">
|
||||
<button type="button" onclick="window.location.href='/index.html'" title="Playground">
|
||||
<img src="/web/images/console_icon.png" alt="Bjorn" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/config.html'" title="Config">
|
||||
<img src="/web/images/config_icon.png" alt="Icon_config" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/network.html'" title="Network">
|
||||
<img src="/web/images/network_icon.png" alt="Icon_network" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/netkb.html'" title="NetKB">
|
||||
<img src="/web/images/netkb_icon.png" alt="Icon_netkb" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/credentials.html'" title="Credentials">
|
||||
<img src="/web/images/cred_icon.png" alt="Icon_cred" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/loot.html'" title="Loot">
|
||||
<img src="/web/images/loot_icon.png" alt="Icon_loot" style="height: 50px;">
|
||||
</button>
|
||||
</div>
|
||||
<div class="console-toolbar">
|
||||
<button type="button" class="toolbar-button" onclick="adjustNetkbFontSize(-1)" title="-">
|
||||
<img src="/web/images/less.png" alt="Icon_less" style="height: 50px;">
|
||||
</button>
|
||||
|
||||
<button id="toggle-toolbar" type="button" class="toolbar-button" onclick="toggleNetkbToolbar()" data-open="false">
|
||||
<img id="toggle-icon" src="/web/images/hide.png" alt="Toggle Toolbar" style="height: 50px;">
|
||||
</button>
|
||||
|
||||
<button type="button" class="toolbar-button" onclick="adjustNetkbFontSize(1)" title="+">
|
||||
<img src="/web/images/plus.png" alt="Icon_plus" style="height: 50px;">
|
||||
</button>
|
||||
</div>
|
||||
<div class="netkb-container">
|
||||
<div id="netkb-table" class="scrollable-table">
|
||||
<!-- The table will be inserted here by JavaScript -->
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
55
web/network.html
Normal file
@@ -0,0 +1,55 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Bjorn Cyberviking - Network</title>
|
||||
<link rel="icon" href="web/images/favicon.ico" type="image/x-icon">
|
||||
<link rel="stylesheet" href="web/css/styles.css">
|
||||
<link rel="manifest" href="manifest.json">
|
||||
<link rel="apple-touch-icon" href="images/apple-touch-icon.png">
|
||||
<script src="web/scripts/network.js" defer></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div class="toolbar" id="mainToolbar">
|
||||
<button type="button" onclick="window.location.href='/index.html'" title="Playground">
|
||||
<img src="/web/images/console_icon.png" alt="Bjorn" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/config.html'" title="Config">
|
||||
<img src="/web/images/config_icon.png" alt="Icon_config" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/network.html'" title="Network">
|
||||
<img src="/web/images/network_icon.png" alt="Icon_network" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/netkb.html'" title="NetKB">
|
||||
<img src="/web/images/netkb_icon.png" alt="Icon_netkb" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/credentials.html'" title="Credentials">
|
||||
<img src="/web/images/cred_icon.png" alt="Icon_cred" style="height: 50px;">
|
||||
</button>
|
||||
<button type="button" onclick="window.location.href='/loot.html'" title="Loot">
|
||||
<img src="/web/images/loot_icon.png" alt="Icon_loot" style="height: 50px;">
|
||||
</button>
|
||||
</div>
|
||||
<div class="console-toolbar">
|
||||
<button type="button" class="toolbar-button" onclick="adjustNetworkFontSize(-1)" title="-">
|
||||
<img src="/web/images/less.png" alt="Icon_less" style="height: 50px;">
|
||||
</button>
|
||||
|
||||
<button id="toggle-toolbar" type="button" class="toolbar-button" onclick="toggleNetworkToolbar()" data-open="false">
|
||||
<img id="toggle-icon" src="/web/images/hide.png" alt="Toggle Toolbar" style="height: 50px;">
|
||||
</button>
|
||||
|
||||
<button type="button" class="toolbar-button" onclick="adjustNetworkFontSize(1)" title="+">
|
||||
<img src="/web/images/plus.png" alt="Icon_plus" style="height: 50px;">
|
||||
</button>
|
||||
|
||||
</div>
|
||||
<div class="network-container">
|
||||
<div id="network-table" class="scrollable-table">
|
||||
<!-- The table will be inserted here by JavaScript -->
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
BIN
web/screen.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
292
web/scripts/config.js
Normal file
@@ -0,0 +1,292 @@
|
||||
|
||||
function generateConfigForm(config) {
|
||||
const formElement = document.querySelector(".config-form");
|
||||
formElement.innerHTML = ''; // Clear the form
|
||||
|
||||
const leftColumn = document.createElement('div');
|
||||
leftColumn.classList.add('left-column');
|
||||
|
||||
const rightColumn = document.createElement('div');
|
||||
rightColumn.classList.add('right-column');
|
||||
|
||||
for (const [key, value] of Object.entries(config)) {
|
||||
if (key.startsWith("__title_")) {
|
||||
rightColumn.innerHTML += `<div class="section-title"><b>${value}</b></div>`;
|
||||
} else if (typeof value === "boolean") {
|
||||
const checked = value ? "checked" : "";
|
||||
leftColumn.innerHTML += `
|
||||
|
||||
<div class="label-switch">
|
||||
<label class="switch">
|
||||
<input type="checkbox" id="${key}" name="${key}" ${checked}>
|
||||
<span class="slider round"></span>
|
||||
</label>
|
||||
<label for="${key}">${key}</label>
|
||||
</div>
|
||||
`;
|
||||
} else if (Array.isArray(value)) {
|
||||
const listValue = value.join(',');
|
||||
rightColumn.innerHTML += `
|
||||
<div class="section-item">
|
||||
<label for="${key}">${key}:</label>
|
||||
<input type="text" id="${key}" name="${key}" value="${listValue}">
|
||||
</div>
|
||||
`;
|
||||
} else if (!isNaN(value) && !key.toLowerCase().includes("ip") && !key.toLowerCase().includes("mac")) {
|
||||
rightColumn.innerHTML += `
|
||||
<div class="section-item">
|
||||
<label for="${key}">${key}:</label>
|
||||
<input type="number" id="${key}" name="${key}" value="${value}">
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
rightColumn.innerHTML += `
|
||||
<div class="section-item">
|
||||
<label for="${key}">${key}:</label>
|
||||
<input type="text" id="${key}" name="${key}" value="${value}">
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
formElement.appendChild(leftColumn);
|
||||
formElement.appendChild(rightColumn);
|
||||
|
||||
// Add a spacer div at the end for better scrolling experience
|
||||
formElement.innerHTML += '<div style="height: 50px;"></div>';
|
||||
}
|
||||
|
||||
|
||||
function saveConfig() {
|
||||
console.log("Saving configuration...");
|
||||
const formElement = document.querySelector(".config-form");
|
||||
|
||||
if (!formElement) {
|
||||
console.error("Form element not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = new FormData(formElement);
|
||||
const formDataObj = {};
|
||||
|
||||
formData.forEach((value, key) => {
|
||||
if (value.includes(',')) {
|
||||
formDataObj[key] = value.split(',').map(item => {
|
||||
const trimmedItem = item.trim();
|
||||
return isNaN(trimmedItem) ? trimmedItem : parseFloat(trimmedItem);
|
||||
});
|
||||
} else {
|
||||
formDataObj[key] = value === 'on' ? true : (isNaN(value) ? value : parseFloat(value));
|
||||
}
|
||||
});
|
||||
|
||||
formElement.querySelectorAll('input[type="checkbox"]').forEach((checkbox) => {
|
||||
if (!formData.has(checkbox.name)) {
|
||||
formDataObj[checkbox.name] = false;
|
||||
}
|
||||
});
|
||||
|
||||
console.log("Form data:", formDataObj);
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", "/save_config", true);
|
||||
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
|
||||
xhr.onreadystatechange = function () {
|
||||
if (xhr.readyState == 4) {
|
||||
console.log("Response status: " + xhr.status);
|
||||
if (xhr.status == 200) {
|
||||
loadConfig();
|
||||
} else {
|
||||
console.error("Failed to save configuration");
|
||||
alert("Failed to save configuration");
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.send(JSON.stringify(formDataObj));
|
||||
}
|
||||
|
||||
function restoreDefault() {
|
||||
fetch('/restore_default_config').then(response => response.json()).then(data => {
|
||||
generateConfigForm(data);
|
||||
});
|
||||
}
|
||||
|
||||
function loadConfig() {
|
||||
fetch('/load_config').then(response => response.json()).then(data => {
|
||||
generateConfigForm(data);
|
||||
});
|
||||
}
|
||||
|
||||
function toggleWifiPanel() {
|
||||
let wifiPanel = document.getElementById('wifi-panel');
|
||||
if (wifiPanel.style.display === 'block') {
|
||||
clearInterval(wifiIntervalId);
|
||||
wifiPanel.style.display = 'none';
|
||||
} else {
|
||||
scanWifi(true); // Pass true to start the update interval
|
||||
}
|
||||
}
|
||||
|
||||
function closeWifiPanel() {
|
||||
clearInterval(wifiIntervalId);
|
||||
let wifiPanel = document.getElementById('wifi-panel');
|
||||
wifiPanel.style.display = 'none';
|
||||
}
|
||||
|
||||
|
||||
let wifiIntervalId;
|
||||
|
||||
function scanWifi(update = false) {
|
||||
fetch('/scan_wifi')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
console.log("Current SSID:", data.current_ssid); // Debugging
|
||||
let wifiPanel = document.getElementById('wifi-panel');
|
||||
let wifiList = document.getElementById('wifi-list');
|
||||
wifiList.innerHTML = '';
|
||||
data.networks.forEach(network => {
|
||||
let li = document.createElement('li');
|
||||
li.innerText = network;
|
||||
li.setAttribute('data-ssid', network);
|
||||
li.onclick = () => connectWifi(network);
|
||||
if (network === data.current_ssid) {
|
||||
li.classList.add('current-wifi'); // Apply the class if it's the current SSID
|
||||
li.innerText += " ✅"; // Add the checkmark icon
|
||||
}
|
||||
wifiList.appendChild(li);
|
||||
});
|
||||
if (data.networks.length > 0) {
|
||||
wifiPanel.style.display = 'block';
|
||||
if (update) {
|
||||
clearInterval(wifiIntervalId);
|
||||
wifiIntervalId = setInterval(() => scanWifi(true), 5000);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
function connectWifi(ssid) {
|
||||
let password = prompt("Enter the password for " + ssid);
|
||||
if (password) {
|
||||
fetch('/connect_wifi', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ ssid: ssid, password: password }),
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => alert(data.message))
|
||||
.catch(error => alert('Error: ' + error));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function adjustFormPadding() {
|
||||
const toolbarHeight = document.querySelector('.toolbar').offsetHeight;
|
||||
const formElement = document.querySelector('.config-form');
|
||||
formElement.style.paddingBottom = toolbarHeight + 'px';
|
||||
}
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
adjustFormPadding();
|
||||
});
|
||||
window.addEventListener('resize', () => {
|
||||
adjustFormPadding();
|
||||
}); // Adjust size on window resize
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
loadConfig();
|
||||
|
||||
});
|
||||
|
||||
let fontSize = 12;
|
||||
|
||||
// Adjust font size based on device type
|
||||
if (/Mobi|Android/i.test(navigator.userAgent)) {
|
||||
fontSize = 7; // size for mobile devices
|
||||
}
|
||||
|
||||
function adjustConfigFontSize(change) {
|
||||
fontSize += change;
|
||||
|
||||
// Retrieve all elements with the class 'section-item'
|
||||
var sectionItems = document.getElementsByClassName('section-item');
|
||||
|
||||
// Loop through each element and apply the style
|
||||
for (var i = 0; i < sectionItems.length; i++) {
|
||||
// Apply the style to the section element
|
||||
sectionItems[i].style.fontSize = fontSize + 'px';
|
||||
|
||||
// Retrieve all inputs inside this section element
|
||||
var inputs = sectionItems[i].getElementsByTagName('input');
|
||||
|
||||
// Loop through each input and apply the style
|
||||
for (var j = 0; j < inputs.length; j++) {
|
||||
inputs[j].style.fontSize = fontSize + 'px';
|
||||
}
|
||||
|
||||
// Retrieve all elements with the class 'switch' inside this section element
|
||||
var switches = sectionItems[i].getElementsByClassName('switch');
|
||||
|
||||
// Loop through each switch and apply the style
|
||||
for (var k = 0; k < switches.length; k++) {
|
||||
switches[k].style.fontSize = fontSize + 'px';
|
||||
}
|
||||
|
||||
// Retrieve all elements with the class 'slider round' inside this section element
|
||||
var sliders = sectionItems[i].getElementsByClassName('slider round');
|
||||
|
||||
// Loop through each slider and apply the style
|
||||
for (var l = 0; l < sliders.length; l++) {
|
||||
sliders[l].style.width = fontSize * 2 + 'px'; // Adjust width based on fontSize
|
||||
sliders[l].style.height = fontSize + 'px'; // Adjust height based on fontSize
|
||||
sliders[l].style.borderRadius = fontSize / 2 + 'px'; // Adjust border-radius based on fontSize
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve all elements with the class 'section-title'
|
||||
var sectionTitles = document.getElementsByClassName('section-title');
|
||||
|
||||
// Loop through each element and apply the style
|
||||
for (var i = 0; i < sectionTitles.length; i++) {
|
||||
sectionTitles[i].style.fontSize = fontSize + 'px';
|
||||
}
|
||||
|
||||
// Retrieve all elements with the class 'label-switch'
|
||||
var labelSwitches = document.getElementsByClassName('label-switch');
|
||||
|
||||
// Loop through each element and apply the style
|
||||
for (var i = 0; i < labelSwitches.length; i++) {
|
||||
labelSwitches[i].style.fontSize = fontSize + 'px';
|
||||
}
|
||||
|
||||
// Apply the style to the element with the class 'config-form'
|
||||
document.querySelector('.config-form').style.fontSize = fontSize + 'px';
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function toggleConfigToolbar() {
|
||||
const mainToolbar = document.querySelector('.toolbar');
|
||||
const toggleButton = document.getElementById('toggle-toolbar')
|
||||
const toggleIcon = document.getElementById('toggle-icon');
|
||||
if (mainToolbar.classList.contains('hidden')) {
|
||||
mainToolbar.classList.remove('hidden');
|
||||
toggleIcon.src = '/web/images/hide.png';
|
||||
toggleButton.setAttribute('data-open', 'false');
|
||||
} else {
|
||||
mainToolbar.classList.add('hidden');
|
||||
toggleIcon.src = '/web/images/reveal.png';
|
||||
toggleButton.setAttribute('data-open', 'true');
|
||||
|
||||
}
|
||||
}
|
||||
51
web/scripts/credentials.js
Normal file
@@ -0,0 +1,51 @@
|
||||
let fontSize = 12;
|
||||
// Adjust font size based on device type
|
||||
if (/Mobi|Android/i.test(navigator.userAgent)) {
|
||||
fontSize = 7; // size for mobile
|
||||
}
|
||||
function fetchCredentials() {
|
||||
fetch('/list_credentials')
|
||||
.then(response => response.text())
|
||||
.then(data => {
|
||||
document.getElementById('credentials-table').innerHTML = data;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
fetchCredentials();
|
||||
setInterval(fetchCredentials, 20000); // 20000 ms = 20 seconds
|
||||
});
|
||||
function adjustCredFontSize(change) {
|
||||
fontSize += change;
|
||||
document.getElementById('credentials-table').style.fontSize = fontSize + 'px';
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function toggleCredToolbar() {
|
||||
const mainToolbar = document.querySelector('.toolbar');
|
||||
const toggleButton = document.getElementById('toggle-toolbar')
|
||||
const toggleIcon = document.getElementById('toggle-icon');
|
||||
if (mainToolbar.classList.contains('hidden')) {
|
||||
mainToolbar.classList.remove('hidden');
|
||||
toggleIcon.src = '/web/images/hide.png';
|
||||
toggleButton.setAttribute('data-open', 'false');
|
||||
} else {
|
||||
mainToolbar.classList.add('hidden');
|
||||
toggleIcon.src = '/web/images/reveal.png';
|
||||
toggleButton.setAttribute('data-open', 'true');
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
fetchCredentials(); // Initial fetch
|
||||
setInterval(fetchCredentials, 10000); // Refresh every 10 seconds
|
||||
});
|
||||
|
||||
|
||||
|
||||
399
web/scripts/index.js
Normal file
@@ -0,0 +1,399 @@
|
||||
const logConsole = document.getElementById('log-console');
|
||||
const mainToolbar = document.querySelector('.toolbar');
|
||||
const toggleButton = document.getElementById('toggle-toolbar');
|
||||
let fontSize = 16; // size for desktop
|
||||
const maxLines = 2000; // Number of lines to keep in the console
|
||||
const fileColors = new Map();
|
||||
const levelClasses = {
|
||||
"DEBUG": "debug",
|
||||
"INFO": "info",
|
||||
"WARNING": "warning",
|
||||
"ERROR": "error",
|
||||
"CRITICAL": "critical",
|
||||
"SUCCESS": "success"
|
||||
};
|
||||
|
||||
// Adjust font size based on device type
|
||||
if (/Mobi|Android/i.test(navigator.userAgent)) {
|
||||
fontSize = 7; // size for mobile
|
||||
}
|
||||
logConsole.style.fontSize = fontSize + 'px';
|
||||
|
||||
function getRandomColor() {
|
||||
const letters = '89ABCDEF'; // Using only hex value for lighter colors
|
||||
let color = '#';
|
||||
for (let i = 0; i < 6; i++) {
|
||||
color += letters[Math.floor(Math.random() * letters.length)];
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
let logInterval;
|
||||
let isConsoleOn = false;
|
||||
|
||||
function fetchLogs() {
|
||||
fetch('/get_logs')
|
||||
.then(response => response.text())
|
||||
.then(data => {
|
||||
const lines = data.split('\n');
|
||||
const newContent = [];
|
||||
|
||||
lines.forEach(line => {
|
||||
let modifiedLine = line;
|
||||
const regexFile = /(\w+\.py)/g;
|
||||
let matchFile;
|
||||
while ((matchFile = regexFile.exec(line)) !== null) {
|
||||
const fileName = matchFile[1];
|
||||
if (line.includes('==>') || line.includes('<=='))
|
||||
return;
|
||||
if (!fileColors.has(fileName)) {
|
||||
fileColors.set(fileName, getRandomColor());
|
||||
}
|
||||
modifiedLine = modifiedLine.replace(fileName, `<span style="color: ${fileColors.get(fileName)};">${fileName}</span>`);
|
||||
}
|
||||
|
||||
const regexLevel = /\b(DEBUG|INFO|WARNING|ERROR|CRITICAL|SUCCESS)\b/g;
|
||||
modifiedLine = modifiedLine.replace(regexLevel, (match) => {
|
||||
return `<span class="${levelClasses[match]}">${match}</span>`;
|
||||
});
|
||||
|
||||
const regexLineNumber = /^\d+/;
|
||||
modifiedLine = modifiedLine.replace(regexLineNumber, (match) => {
|
||||
return `<span class="line-number">${match}</span>`;
|
||||
});
|
||||
|
||||
const regexNumbers = /\b\d+\b/g;
|
||||
modifiedLine = modifiedLine.replace(regexNumbers, (match) => {
|
||||
return `<span class="number">${match}</span>`;
|
||||
});
|
||||
|
||||
newContent.push(modifiedLine);
|
||||
});
|
||||
|
||||
logConsole.innerHTML += newContent.join('<br>') + '<br>';
|
||||
|
||||
let allLines = logConsole.innerHTML.split('<br>');
|
||||
if (allLines.length > maxLines) {
|
||||
allLines = allLines.slice(allLines.length - maxLines);
|
||||
logConsole.innerHTML = allLines.join('<br>');
|
||||
}
|
||||
logConsole.scrollTop = logConsole.scrollHeight;
|
||||
})
|
||||
.catch(error => console.error('Error fetching logs:', error));
|
||||
}
|
||||
|
||||
// setInterval(fetchLogs, 1500); /
|
||||
function startConsole() {
|
||||
// Start fetching logs every 1.5 seconds
|
||||
logInterval = setInterval(fetchLogs, 1500); // Fetch logs every 1.5 seconds
|
||||
}
|
||||
function stopConsole() {
|
||||
clearInterval(logInterval);
|
||||
}
|
||||
function toggleConsole() {
|
||||
const toggleImage = document.getElementById('toggle-console-image');
|
||||
|
||||
if (isConsoleOn) {
|
||||
stopConsole();
|
||||
toggleImage.src = '/web/images/off.png';
|
||||
} else {
|
||||
startConsole();
|
||||
toggleImage.src = '/web/images/on.png';
|
||||
}
|
||||
|
||||
isConsoleOn = !isConsoleOn;
|
||||
}
|
||||
function adjustFontSize(change) {
|
||||
fontSize += change;
|
||||
logConsole.style.fontSize = fontSize + 'px';
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const mainToolbar = document.getElementById('mainToolbar');
|
||||
const toggleButton = document.getElementById('toggle-toolbar');
|
||||
const toggleIcon = document.getElementById('toggle-icon');
|
||||
|
||||
toggleButton.addEventListener('click', toggleToolbar);
|
||||
|
||||
function toggleToolbar() {
|
||||
const isOpen = toggleButton.getAttribute('data-open') === 'true';
|
||||
if (isOpen) {
|
||||
mainToolbar.classList.add('hidden');
|
||||
toggleIcon.src = '/web/images/reveal.png';
|
||||
toggleButton.setAttribute('data-open', 'false');
|
||||
} else {
|
||||
mainToolbar.classList.remove('hidden');
|
||||
toggleIcon.src = '/web/images/hide.png';
|
||||
toggleButton.setAttribute('data-open', 'true');
|
||||
}
|
||||
toggleConsoleSize();
|
||||
}
|
||||
|
||||
function toggleConsoleSize() {
|
||||
//Function to adjust the size of the console based on the toolbar visibility
|
||||
}
|
||||
});
|
||||
|
||||
function loadDropdown() {
|
||||
const dropdownContent = `
|
||||
<div class="dropdown">
|
||||
<button type="button" class="toolbar-button" onclick="toggleDropdown()" data-open="false">
|
||||
<img src="/web/images/manual_icon.png" alt="Icon_actions" style="height: 50px;">
|
||||
</button>
|
||||
<div class="dropdown-content">
|
||||
<button type="button" onclick="clear_files()">Clear Files</button>
|
||||
<button type="button" onclick="clear_files_light()">Clear Files Light</button>
|
||||
<button type="button" onclick="reboot_system()">Reboot</button>
|
||||
<button type="button" onclick="disconnect_wifi()">Disconnect Wi-Fi</button>
|
||||
<button type="button" onclick="shutdown_system()">Shutdown</button>
|
||||
<button type="button" onclick="restart_bjorn_service()">Restart Bjorn Service</button>
|
||||
<button type="button" onclick="backup_data()">Backup</button>
|
||||
<button type="button" onclick="restore_data()">Restore</button>
|
||||
<button type="button" onclick="stop_orchestrator()">Stop Orchestrator</button>
|
||||
<button type="button" onclick="start_orchestrator()">Start Orchestrator</button>
|
||||
<button type="button" onclick="initialize_csv()">Create Livestatus, Actions & Netkb CSVs</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
document.getElementById('dropdown-container').innerHTML = dropdownContent;
|
||||
}
|
||||
|
||||
function loadBjornDropdown() {
|
||||
const bjornDropdownContent = `
|
||||
<div class="dropdown bjorn-dropdown">
|
||||
<button type="button" class="toolbar-button" onclick="toggleBjornDropdown()" data-open="false">
|
||||
<img src="/web/images/bjorn_icon.png" alt="Icon_bjorn" style="height: 50px;">
|
||||
</button>
|
||||
<div class="dropdown-content">
|
||||
<img id="screenImage_Home" onclick="window.location.href='/bjorn.html'" src="screen.png" alt="Bjorn" style="width: 100%;">
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
document.getElementById('bjorn-dropdown-container').innerHTML = bjornDropdownContent;
|
||||
startLiveview(); // Start live view when Bjorn dropdown is loaded
|
||||
}
|
||||
|
||||
// Call the function to load the dropdowns when the DOM is loaded
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
loadDropdown();
|
||||
loadBjornDropdown();
|
||||
});
|
||||
|
||||
|
||||
function clear_files() {
|
||||
fetch('/clear_files', { method: 'POST' })
|
||||
.then(response => response.json())
|
||||
.then(data => alert(data.message))
|
||||
.catch(error => alert('Failed to clear files: ' + error.message));
|
||||
}
|
||||
|
||||
function clear_files_light() {
|
||||
fetch('/clear_files_light', { method: 'POST' })
|
||||
.then(response => response.json())
|
||||
.then(data => alert(data.message))
|
||||
.catch(error => alert('Failed to clear files: ' + error.message));
|
||||
}
|
||||
|
||||
function reboot_system() {
|
||||
fetch('/reboot', { method: 'POST' })
|
||||
.then(response => response.json())
|
||||
.then(data => alert(data.message))
|
||||
.catch(error => alert('Failed to reboot: ' + error.message));
|
||||
}
|
||||
|
||||
function shutdown_system() {
|
||||
fetch('/shutdown', { method: 'POST' })
|
||||
.then(response => response.json())
|
||||
.then(data => alert(data.message))
|
||||
.catch(error => alert('Failed to shutdown: ' + error.message));
|
||||
}
|
||||
|
||||
function restart_bjorn_service() {
|
||||
fetch('/restart_bjorn_service', { method: 'POST' })
|
||||
.then(response => response.json())
|
||||
.then(data => alert(data.message))
|
||||
.catch(error => alert('Failed to restart service: ' + error.message));
|
||||
}
|
||||
|
||||
function backup_data() {
|
||||
fetch('/backup', { method: 'POST' })
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.status === 'success') {
|
||||
const link = document.createElement('a');
|
||||
link.href = data.url;
|
||||
link.download = data.filename;
|
||||
link.click();
|
||||
alert('Backup completed successfully');
|
||||
} else {
|
||||
alert('Backup failed: ' + data.message);
|
||||
}
|
||||
})
|
||||
.catch(error => alert('Backup failed: ' + error.message));
|
||||
}
|
||||
|
||||
function restore_data() {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'file';
|
||||
input.accept = '.zip';
|
||||
input.onchange = () => {
|
||||
const file = input.files[0];
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
|
||||
fetch('/restore', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => alert(data.message))
|
||||
.catch(error => alert('Restore failed: ' + error.message));
|
||||
};
|
||||
input.click();
|
||||
}
|
||||
|
||||
function stop_orchestrator() {
|
||||
fetch('/stop_orchestrator', { method: 'POST' })
|
||||
.then(response => response.json())
|
||||
.then(data => alert(data.message))
|
||||
.catch(error => alert('Failed to stop orchestrator: ' + error.message));
|
||||
}
|
||||
|
||||
function start_orchestrator() {
|
||||
fetch('/start_orchestrator', { method: 'POST' })
|
||||
.then(response => response.json())
|
||||
.then(data => alert(data.message))
|
||||
.catch(error => alert('Failed to start orchestrator: ' + error.message));
|
||||
}
|
||||
|
||||
function disconnect_wifi() {
|
||||
fetch('/disconnect_wifi', { method: 'POST' })
|
||||
.then(response => response.json())
|
||||
.then(data => alert(data.message))
|
||||
.catch(error => alert('Failed to disconnect: ' + error.message));
|
||||
}
|
||||
|
||||
function initialize_csv() {
|
||||
fetch('/initialize_csv', { method: 'POST' })
|
||||
.then(response => response.json())
|
||||
.then(data => alert(data.message))
|
||||
.catch(error => alert('Failed to initialize CSV: ' + error.message));
|
||||
}
|
||||
|
||||
// Dropdown toggle logic
|
||||
function toggleDropdown() {
|
||||
const dropdown = document.querySelector('.dropdown');
|
||||
const button = document.querySelector('.action-button');
|
||||
const isOpen = button.getAttribute('data-open') === 'true';
|
||||
|
||||
if (isOpen) {
|
||||
dropdown.classList.remove('show');
|
||||
button.setAttribute('data-open', 'false');
|
||||
} else {
|
||||
dropdown.classList.add('show');
|
||||
button.setAttribute('data-open', 'true');
|
||||
}
|
||||
}
|
||||
|
||||
function closeDropdownIfOpen(event) {
|
||||
const dropdown = document.querySelector('.dropdown');
|
||||
const button = document.querySelector('.action-button');
|
||||
const isOpen = button.getAttribute('data-open') === 'true';
|
||||
|
||||
if (!event.target.closest('.dropdown') && isOpen) {
|
||||
dropdown.classList.remove('show');
|
||||
button.setAttribute('data-open', 'false');
|
||||
}
|
||||
}
|
||||
|
||||
// actions.js
|
||||
|
||||
let imageIntervalId;
|
||||
let intervalId;
|
||||
const delay = 2000 // Adjust this value to match your delay
|
||||
|
||||
let lastUpdate = 0;
|
||||
|
||||
function updateImage() {
|
||||
const now = Date.now();
|
||||
if (now - lastUpdate >= delay) {
|
||||
lastUpdate = now;
|
||||
const image = document.getElementById("screenImage_Home");
|
||||
const newImage = new Image();
|
||||
newImage.onload = function() {
|
||||
image.src = newImage.src; // Update only if the new image loads successfully
|
||||
};
|
||||
newImage.onerror = function() {
|
||||
console.warn("New image could not be loaded, keeping the previous image.");
|
||||
};
|
||||
newImage.src = "screen.png?t=" + new Date().getTime(); // Prevent caching
|
||||
}
|
||||
}
|
||||
|
||||
function startLiveview() {
|
||||
updateImage(); // Immediately update the image
|
||||
intervalId = setInterval(updateImage, delay); // Then update at the specified interval
|
||||
}
|
||||
|
||||
function stopLiveview() {
|
||||
clearInterval(intervalId);
|
||||
}
|
||||
|
||||
// Dropdown toggle logic for Bjorn
|
||||
function toggleBjornDropdown() {
|
||||
const dropdown = document.querySelector('.bjorn-dropdown');
|
||||
const button = document.querySelector('.bjorn-button');
|
||||
const isOpen = button.getAttribute('data-open') === 'true';
|
||||
|
||||
if (isOpen) {
|
||||
dropdown.classList.remove('show');
|
||||
button.setAttribute('data-open', 'false');
|
||||
stopLiveview(); // Stop image refresh when closing
|
||||
} else {
|
||||
dropdown.classList.add('show');
|
||||
button.setAttribute('data-open', 'true');
|
||||
startLiveview(); // Start image refresh when opening
|
||||
}
|
||||
}
|
||||
|
||||
function closeBjornDropdownIfOpen(event) {
|
||||
const dropdown = document.querySelector('.bjorn-dropdown');
|
||||
const button = document.querySelector('.bjorn-button');
|
||||
const isOpen = button.getAttribute('data-open') === 'true';
|
||||
|
||||
if (!event.target.closest('.bjorn-dropdown') && isOpen) {
|
||||
dropdown.classList.remove('show');
|
||||
button.setAttribute('data-open', 'false');
|
||||
stopLiveview(); // Stop image refresh when closing
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('click', closeBjornDropdownIfOpen);
|
||||
document.addEventListener('touchstart', closeBjornDropdownIfOpen);
|
||||
|
||||
// Existing logic for Actions dropdown
|
||||
function toggleDropdown() {
|
||||
const dropdown = document.querySelector('.dropdown');
|
||||
const button = document.querySelector('.action-button');
|
||||
const isOpen = button.getAttribute('data-open') === 'true';
|
||||
|
||||
if (isOpen) {
|
||||
dropdown.classList.remove('show');
|
||||
button.setAttribute('data-open', 'false');
|
||||
} else {
|
||||
dropdown.classList.add('show');
|
||||
button.setAttribute('data-open', 'true');
|
||||
}
|
||||
}
|
||||
|
||||
function closeDropdownIfOpen(event) {
|
||||
const dropdown = document.querySelector('.dropdown');
|
||||
const button = document.querySelector('.action-button');
|
||||
const isOpen = button.getAttribute('data-open') === 'true';
|
||||
|
||||
if (!event.target.closest('.dropdown') && isOpen) {
|
||||
dropdown.classList.remove('show');
|
||||
button.setAttribute('data-open', 'false');
|
||||
}
|
||||
}
|
||||
|
||||
75
web/scripts/loot.js
Normal file
@@ -0,0 +1,75 @@
|
||||
let fontSize = 14;
|
||||
// Adjust font size based on device type
|
||||
if (/Mobi|Android/i.test(navigator.userAgent)) {
|
||||
fontSize = 7; // size for mobile
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
fetch('/list_files')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
document.getElementById('file-list').innerHTML = generateFileListHTML(data, "/", 0);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
});
|
||||
|
||||
function generateFileListHTML(files, path, indent) {
|
||||
let html = '<ul>';
|
||||
files.forEach(file => {
|
||||
if (file.is_directory) {
|
||||
const icon = path === "/" ? "web/images/mainfolder.png" : "web/images/subfolder.png";
|
||||
html += `
|
||||
<li style="margin-left: ${indent * 5}px;">
|
||||
<img src="${icon}" alt="Folder Icon" style="height: 20px;">
|
||||
<strong>${file.name}</strong>
|
||||
<ul>
|
||||
${generateFileListHTML(file.children || [], `${path}/${file.name}`, indent + 1)}
|
||||
</ul>
|
||||
</li>`;
|
||||
} else {
|
||||
const icon = "web/images/file.png";
|
||||
html += `
|
||||
<li style="margin-left: ${indent * 5}px;">
|
||||
<img src="${icon}" alt="File Icon" style="height: 20px;">
|
||||
<a href="/download_file?path=${encodeURIComponent(file.path)}">${file.name}</a>
|
||||
</li>`;
|
||||
}
|
||||
});
|
||||
html += '</ul>';
|
||||
return html;
|
||||
}
|
||||
|
||||
function adjustLootFontSize(change) {
|
||||
fontSize += change;
|
||||
document.getElementById('file-list').style.fontSize = fontSize + 'px';
|
||||
}
|
||||
|
||||
function toggleLootToolbar() {
|
||||
const mainToolbar = document.querySelector('.toolbar');
|
||||
const toggleButton = document.getElementById('toggle-toolbar');
|
||||
const toggleIcon = document.getElementById('toggle-icon');
|
||||
if (mainToolbar.classList.contains('hidden')) {
|
||||
mainToolbar.classList.remove('hidden');
|
||||
toggleIcon.src = '/web/images/hide.png';
|
||||
toggleButton.setAttribute('data-open', 'false');
|
||||
} else {
|
||||
mainToolbar.classList.add('hidden');
|
||||
toggleIcon.src = '/web/images/reveal.png';
|
||||
toggleButton.setAttribute('data-open', 'true');
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
setInterval(() => {
|
||||
fetch('/list_files')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
document.getElementById('file-list').innerHTML = generateFileListHTML(data, "/", 0);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
}, 10000); // Refresh every 10 seconds
|
||||
});
|
||||
45
web/scripts/netkb.js
Normal file
@@ -0,0 +1,45 @@
|
||||
let fontSize = 12;
|
||||
// Adjust font size based on device type
|
||||
if (/Mobi|Android/i.test(navigator.userAgent)) {
|
||||
fontSize = 7; // size for mobile
|
||||
}
|
||||
function fetchNetkbData() {
|
||||
fetch('/netkb_data')
|
||||
.then(response => response.text())
|
||||
.then(data => {
|
||||
document.getElementById('netkb-table').innerHTML = data;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
}
|
||||
function adjustNetkbFontSize(change) {
|
||||
fontSize += change;
|
||||
document.getElementById('netkb-table').style.fontSize = fontSize + 'px';
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function toggleNetkbToolbar() {
|
||||
const mainToolbar = document.querySelector('.toolbar');
|
||||
const toggleButton = document.getElementById('toggle-toolbar')
|
||||
const toggleIcon = document.getElementById('toggle-icon');
|
||||
if (mainToolbar.classList.contains('hidden')) {
|
||||
mainToolbar.classList.remove('hidden');
|
||||
toggleIcon.src = '/web/images/hide.png';
|
||||
toggleButton.setAttribute('data-open', 'false');
|
||||
} else {
|
||||
mainToolbar.classList.add('hidden');
|
||||
toggleIcon.src = '/web/images/reveal.png';
|
||||
toggleButton.setAttribute('data-open', 'true');
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
fetchNetkbData(); // Initial fetch
|
||||
setInterval(fetchNetkbData, 10000); // Refresh every 10 seconds
|
||||
});
|
||||
|
||||
|
||||
47
web/scripts/network.js
Normal file
@@ -0,0 +1,47 @@
|
||||
let fontSize = 12;
|
||||
// Adjust font size based on device type
|
||||
if (/Mobi|Android/i.test(navigator.userAgent)) {
|
||||
fontSize = 7; // size for mobile
|
||||
}
|
||||
|
||||
function fetchNetworkData() {
|
||||
fetch('/network_data')
|
||||
.then(response => response.text())
|
||||
.then(data => {
|
||||
document.getElementById('network-table').innerHTML = data;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
}
|
||||
|
||||
function adjustNetworkFontSize(change) {
|
||||
fontSize += change;
|
||||
document.getElementById('network-table').style.fontSize = fontSize + 'px';
|
||||
}
|
||||
|
||||
function toggleNetworkToolbar() {
|
||||
const mainToolbar = document.querySelector('.toolbar');
|
||||
const toggleButton = document.getElementById('toggle-toolbar');
|
||||
const toggleIcon = document.getElementById('toggle-icon');
|
||||
|
||||
if (mainToolbar.classList.contains('hidden')) {
|
||||
mainToolbar.classList.remove('hidden');
|
||||
toggleIcon.src = '/web/images/hide.png';
|
||||
toggleButton.setAttribute('data-open', 'true');
|
||||
} else {
|
||||
mainToolbar.classList.add('hidden');
|
||||
toggleIcon.src = '/web/images/reveal.png';
|
||||
toggleButton.setAttribute('data-open', 'false');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
fetchNetworkData(); // Initial fetch
|
||||
setInterval(fetchNetworkData, 60000); // Refresh every 60 seconds
|
||||
});
|
||||