Python SFTP Server and Network Monitor
Python SFTP Server and Network Monitor
# ====================
# GLOBAL CONFIGURATION
# ====================
SERVER_PORT = 6499
LOG_PREFIX = "LSE"
NETWORK_SETTINGS = {
'ip': '[Link]',
'mask': '[Link]',
'gateway': '[Link]',
'dns1': '[Link]',
'dns2': '[Link]'
}
# CPU monitoring
cpu_percent = 0
def monitor_cpu():
global cpu_percent
while True:
cpu_percent = psutil.cpu_percent(interval=1)
# Ping monitoring
ping_status = "Disconnected"
ping_time = "0ms"
def monitor_ping():
global ping_status, ping_time
while True:
try:
response_time = [Link]('[Link]', timeout=2)
if response_time is not None:
ping_status = "Connected"
ping_time = f"{int(response_time * 1000)}ms"
else:
ping_status = "Disconnected"
ping_time = "Timeout"
except:
ping_status = "Disconnected"
ping_time = "Error"
[Link](5)
# =================
# LOGGING MECHANISM
# =================
class LogSync:
def __init__(self):
[Link] = []
[Link] = [Link]()
log_sync = LogSync()
# ===================
# SYSTEM INFO HELPERS
# ===================
def get_system_specs():
return {
"hostname": [Link](),
"os": f"{[Link]()} {[Link]()}",
"processor": [Link](),
"ram": f"{round(psutil.virtual_memory().total / (1024**3), 2)} GB",
"architecture": [Link]()[0]
}
def get_performance_data():
global prev_bytes_sent, prev_bytes_recv, prev_time
return {
"cpu": cpu_percent,
"memory": psutil.virtual_memory().percent,
"network": network_usage,
"ping_status": ping_status,
"ping_time": ping_time,
"sftp_status": sftp_status
}
# =========================
# NETWORK CONFIGURATION
# =========================
def get_network_interfaces():
"""Get all network interfaces using netsh command"""
try:
# Run netsh command to get interfaces
result = subprocess.check_output(
'netsh interface show interface',
shell=True,
text=True,
encoding='utf-8',
errors='ignore'
)
interfaces = []
lines = [Link]().split('\n')
if header_index == -1:
return ["Ethernet"] # Fallback
parts = [Link]()
if len(parts) < 4:
continue
def set_dhcp_ip(interface):
"""Set DHCP IP using netsh commands - with visible console window"""
try:
# Create a command that will open in a visible console window
cmd = f'cmd /c "netsh interface ip set address name=\\"{interface}\\"
source=dhcp"'
def set_dhcp_dns(interface):
"""Set DHCP DNS using netsh commands"""
try:
# Run commands in background without showing console window
startupinfo = [Link]()
[Link] |= subprocess.STARTF_USESHOWWINDOW
def get_network_info():
"""Get detailed network information using ipconfig"""
net_info = []
try:
# Get ipconfig output
result = subprocess.check_output('ipconfig /all', shell=True, text=True,
encoding='utf-8', errors='ignore')
current_adapter = ""
adapter_info = {}
current_adapter = [Link](':')[0].strip()
adapter_info = {
'name': current_adapter,
'ipv4': [],
'ipv6': [],
'mac': None,
'dns': [],
'gateway': []
}
return net_info
except Exception as e:
log_sync.add_log(f"Error getting network info: {str(e)}")
return []
# =========================
# SFTP SERVER IMPLEMENTATION
# =========================
class StubSFTPServer(SFTPServerInterface):
def __init__(self, server, *args, **kwargs):
super().__init__(*args, **kwargs)
[Link] = server
[Link] = SFTP_CONFIG['root_path']
self.list_hidden = SFTP_CONFIG['list_hidden_files']
self.utf8 = SFTP_CONFIG['utf8']
class StubServer(ServerInterface):
def check_auth_password(self, username, password):
if username == SFTP_CONFIG['username'] and password ==
SFTP_CONFIG['password']:
return paramiko.AUTH_SUCCESSFUL
return paramiko.AUTH_FAILED
def run_sftp_server():
global sftp_server
try:
host = SFTP_CONFIG['host']
port = SFTP_CONFIG['port']
while SFTP_CONFIG['enabled']:
client, addr = [Link]()
log_sync.add_log(f"SFTP connection from {addr[0]}:{addr[1]}")
try:
transport = Transport(client)
if SFTP_CONFIG['enable_zlib']:
transport.use_compression(True)
transport.add_server_key(host_key)
transport.set_subsystem_handler('sftp', [Link],
StubSFTPServer)
server = StubServer()
transport.start_server(server=server)
channel = [Link]()
if channel is None:
log_sync.add_log("SFTP client closed connection during
negotiation")
continue
except Exception as e:
log_sync.add_log(f"SFTP error: {str(e)}")
finally:
try:
[Link]()
except:
pass
[Link]()
log_sync.add_log("SFTP server stopped")
except Exception as e:
log_sync.add_log(f"SFTP server failed: {str(e)}")
def start_sftp_server():
global sftp_server, sftp_server_thread
# Validate configuration
if not SFTP_CONFIG['root_path'] or not [Link](SFTP_CONFIG['root_path']):
log_sync.add_log("SFTP root path is invalid or not set")
return False
def stop_sftp_server():
global sftp_server, sftp_server_thread
SFTP_CONFIG['enabled'] = False
# =========================
# FLASK WEB PANEL (Backend)
# =========================
app = Flask(__name__, template_folder='', static_folder='')
@[Link]('/')
def index():
return render_template('[Link]')
@[Link]('/system_info')
def system_info():
return jsonify({
"specs": get_system_specs(),
"performance": get_performance_data()
})
@[Link]('/get_logs')
def get_logs():
return jsonify(logs=log_sync.logs)
@[Link]('/get_interfaces')
def get_interfaces():
return jsonify(interfaces=get_network_interfaces())
@[Link]('/get_network_info')
def get_network_info_route():
return jsonify(network_info=get_network_info())
@[Link]('/get_sftp_config')
def get_sftp_config():
return jsonify(config=SFTP_CONFIG)
@[Link]('/update_sftp_config', methods=['POST'])
def update_sftp_config():
global SFTP_CONFIG
data = [Link]
# Update configuration
SFTP_CONFIG.update({
'username': [Link]('username', 'rbs'),
'password': [Link]('password', 'rbs'),
'port': int([Link]('port', 22)),
'root_path': [Link]('root_path', ''),
'host': [Link]('host', '[Link]'),
'enable_zlib': [Link]('enable_zlib', True),
'enable_nagle': [Link]('enable_nagle', False),
'enable_scp': [Link]('enable_scp', True),
'fips_mode': [Link]('fips_mode', False),
'list_hidden_files': [Link]('list_hidden_files', False),
'utf8': [Link]('utf8', True)
})
@[Link]('/toggle_sftp_server', methods=['POST'])
def toggle_sftp_server():
data = [Link]
action = [Link]('action')
if action == 'start':
success = start_sftp_server()
message = "SFTP server started" if success else "Failed to start SFTP
server"
else:
success = stop_sftp_server()
message = "SFTP server stopped" if success else "Failed to stop SFTP
server"
@[Link]('/browse_folder')
def browse_folder():
# This is a placeholder - in a real app you'd have a file browser
# For simplicity, we'll just return the user's home directory
home_dir = [Link]("~")
return jsonify(path=home_dir)
@[Link]('/update_ip_settings', methods=['POST'])
def update_ip_settings():
data = [Link]
interface = [Link]('interface')
mode = [Link]('mode')
ip = [Link]('ip')
mask = [Link]('mask')
gateway = [Link]('gateway')
if mode == 'static':
success, message = set_static_ip(interface, ip, mask, gateway)
else:
success, message = set_dhcp_ip(interface)
@[Link]('/update_dns_settings', methods=['POST'])
def update_dns_settings():
data = [Link]
interface = [Link]('interface')
mode = [Link]('mode')
dns1 = [Link]('dns1')
dns2 = [Link]('dns2')
if mode == 'static':
success, message = set_static_dns(interface, dns1, dns2)
else:
success, message = set_dhcp_dns(interface)
@[Link]('/update_datetime', methods=['POST'])
def update_datetime():
data = [Link]
date_str = [Link]('date')
time_str = [Link]('time')
try:
# Create datetime object
dt = [Link](f"{date_str} {time_str}", "%Y/%m/%d %H:%M:
%S")
@[Link]('/reset_datetime', methods=['POST'])
def reset_datetime():
try:
# Get current date/time
now = [Link]()
date_cmd = [Link]("%m/%d/%Y")
time_cmd = [Link]("%H:%M:%S")
@[Link]('/export_logs')
def export_logs():
log_content = "\n".join(log_sync.logs)
filename = f"panel_logs_{[Link]().strftime('%Y%m%d_%H%M
%S')}.txt"
# =====================
# TKINTER CONTROL PANEL
# =====================
class ControlPanel:
def __init__(self, root):
[Link] = root
[Link]("Teknir Control Panel")
[Link]("800x500")
[Link](bg='#2d2d39')
self.create_widgets()
self.server_running = False
self.server_thread = None
self.status_frame = None
def create_widgets(self):
# Header
header = [Link]([Link], bg='#1e1e2d', height=50)
[Link](fill='x')
# Control buttons
btn_frame = [Link](header, bg='#1e1e2d')
btn_frame.pack(side='right', padx=20)
# Log display
log_frame = [Link]([Link], text="Server Logs", font=("System",
10),
fg="white", bg='#2d2d39', bd=1, relief='sunken')
log_frame.pack(fill='both', expand=True, padx=10, pady=10)
def toggle_server(self):
if not self.server_running:
self.start_server()
else:
self.stop_server()
def start_server(self):
def run_flask():
[Link](port=SERVER_PORT, debug=False, use_reloader=False)
def update_log_display(self):
self.log_area.config(state='normal')
self.log_area.delete(1.0, [Link])
for log in log_sync.logs:
self.log_area.insert([Link], log + '\n')
self.log_area.config(state='disabled')
self.log_area.yview([Link])
[Link](1000, self.update_log_display)
# ===================
# HTML/CSS/JS CONTENT
# ===================
html_content = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Teknir Web Panel</title>
<style>
:root {
--bg-primary: #2d2d39;
--bg-secondary: #1e1e2d;
--bg-tertiary: #252533;
--text-primary: #e0e0e0;
--text-secondary: #a0a0b0;
--accent: #4d7cff;
--success: #4CAF50;
--error: #f44336;
--warning: #FF9800;
--sidebar-width: 250px;
--transition-speed: 0.3s;
}
[data-theme="light"] {
--bg-primary: #f5f5f7;
--bg-secondary: #ffffff;
--bg-tertiary: #eaeaea;
--text-primary: #333333;
--text-secondary: #666666;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'system-ui', -apple-system, BlinkMacSystemFont,
'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell,
'Open Sans', 'Helvetica Neue', sans-serif;
}
body {
background-color: var(--bg-primary);
color: var(--text-primary);
display: flex;
min-height: 100vh;
overflow: hidden;
transition: background-color var(--transition-speed);
}
.sidebar {
width: var(--sidebar-width);
background: var(--bg-secondary);
height: 100vh;
padding: 20px 0;
transition: width var(--transition-speed);
overflow-y: auto;
box-shadow: 2px 0 10px rgba(0, 0, 0, 0.2);
z-index: 100;
}
.[Link] {
width: 60px;
}
.sidebar-header {
padding: 0 20px 20px;
border-bottom: 1px solid var(--bg-tertiary);
margin-bottom: 20px;
}
.sidebar-header h2 {
font-size: 1.2rem;
white-space: nowrap;
overflow: hidden;
}
.[Link] .sidebar-header h2 {
display: none;
}
.section-title {
padding: 10px 20px;
color: var(--text-secondary);
font-size: 0.8rem;
text-transform: uppercase;
letter-spacing: 1px;
white-space: nowrap;
}
.[Link] .section-title {
display: none;
}
.nav-item {
display: flex;
align-items: center;
padding: 12px 20px;
color: var(--text-primary);
text-decoration: none;
transition: all 0.2s;
white-space: nowrap;
}
.nav-item:hover {
background: var(--bg-tertiary);
}
.[Link] {
background: var(--bg-tertiary);
border-left: 4px solid var(--accent);
}
.nav-icon {
margin-right: 15px;
font-size: 1.2rem;
}
.[Link] .nav-text {
display: none;
}
.main-content {
flex: 1;
display: flex;
flex-direction: column;
overflow-y: auto;
height: 100vh;
transition: margin-left var(--transition-speed);
}
.topbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px;
background: var(--bg-secondary);
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
z-index: 10;
}
.theme-toggle {
background: var(--bg-tertiary);
border: none;
color: var(--text-primary);
padding: 8px 15px;
border-radius: 20px;
cursor: pointer;
display: flex;
align-items: center;
transition: background 0.3s;
}
.sidebar-toggle {
background: none;
border: none;
color: var(--text-primary);
font-size: 1.5rem;
cursor: pointer;
margin-right: 15px;
}
.controls {
display: flex;
align-items: center;
}
.tehran-time {
margin: 0 15px;
font-size: 0.9rem;
font-weight: 500;
}
.ping-status {
margin: 0 15px;
padding: 5px 10px;
border-radius: 20px;
font-size: 0.9rem;
font-weight: 500;
}
.ping-connected {
background: rgba(76, 175, 80, 0.2);
border: 1px solid #4CAF50;
color: #4CAF50;
}
.ping-disconnected {
background: rgba(244, 67, 54, 0.2);
border: 1px solid #f44336;
color: #f44336;
}
.content-area {
padding: 20px;
flex: 1;
overflow-y: auto;
}
/* Hide scrollbars */
.content-area::-webkit-scrollbar,
.sidebar::-webkit-scrollbar,
.log-container::-webkit-scrollbar {
width: 0;
height: 0;
background: transparent;
}
.card {
background: var(--bg-secondary);
border-radius: 10px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1);
}
.card-title {
font-size: 1.2rem;
margin-bottom: 20px;
display: flex;
align-items: center;
}
.card-title i {
margin-right: 10px;
}
.metrics {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
}
.metric-card {
background: var(--bg-tertiary);
border-radius: 8px;
padding: 15px;
}
.metric-header {
display: flex;
justify-content: space-between;
margin-bottom: 10px;
}
.metric-title {
font-weight: 500;
}
.metric-value {
font-size: 1.8rem;
font-weight: bold;
margin: 10px 0;
}
.progress-bar {
height: 10px;
background: var(--bg-primary);
border-radius: 5px;
overflow: hidden;
}
.progress {
height: 100%;
background: var(--accent);
border-radius: 5px;
transition: width 0.5s;
}
.specs-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 15px;
}
.spec-item {
background: var(--bg-tertiary);
padding: 15px;
border-radius: 8px;
}
.spec-label {
color: var(--text-secondary);
font-size: 0.9rem;
margin-bottom: 5px;
}
.spec-value {
font-weight: 500;
}
.log-container {
background: var(--bg-tertiary);
border-radius: 8px;
padding: 15px;
height: 400px;
overflow-y: auto;
font-family: monospace;
font-size: 0.9rem;
white-space: pre-wrap;
}
.log-entry {
margin-bottom: 5px;
line-height: 1.4;
}
.form-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
}
.form-group {
margin-bottom: 15px;
}
.form-label {
display: block;
margin-bottom: 5px;
font-weight: 500;
}
.form-input, .form-select {
width: 100%;
padding: 10px;
background: var(--bg-tertiary);
border: 1px solid var(--bg-primary);
border-radius: 5px;
color: var(--text-primary);
}
.btn {
padding: 10px 20px;
background: var(--accent);
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
font-weight: 500;
transition: background 0.3s;
margin-right: 10px;
}
.btn:hover {
background: #3a6bff;
}
.btn-secondary {
background: var(--bg-tertiary);
}
.btn-secondary:hover {
background: #333342;
}
.hidden {
display: none;
}
.mode-toggle {
display: flex;
align-items: center;
margin-bottom: 15px;
}
.mode-option {
margin-right: 15px;
}
.netinfo-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
gap: 20px;
}
.netinfo-card {
background: var(--bg-tertiary);
border-radius: 8px;
padding: 15px;
margin-bottom: 15px;
}
.netinfo-header {
font-weight: bold;
margin-bottom: 10px;
border-bottom: 1px solid var(--bg-primary);
padding-bottom: 5px;
}
.netinfo-item {
margin-bottom: 8px;
}
.netinfo-label {
font-weight: 500;
color: var(--text-secondary);
}
.status-message {
padding: 10px;
margin-bottom: 15px;
border-radius: 5px;
font-weight: 500;
}
.status-success {
background: rgba(76, 175, 80, 0.2);
border: 1px solid #4CAF50;
color: #4CAF50;
}
.status-error {
background: rgba(244, 67, 54, 0.2);
border: 1px solid #f44336;
color: #f44336;
}
.sftp-status {
padding: 8px 15px;
border-radius: 20px;
font-weight: 500;
display: inline-block;
margin-bottom: 15px;
}
.sftp-running {
background: rgba(76, 175, 80, 0.2);
border: 1px solid #4CAF50;
color: #4CAF50;
}
.sftp-stopped {
background: rgba(244, 67, 54, 0.2);
border: 1px solid #f44336;
color: #f44336;
}
.option-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 15px;
margin-bottom: 20px;
}
.option-item {
display: flex;
align-items: center;
}
.option-item input {
margin-right: 10px;
}
</style>
</head>
<body>
<!-- Sidebar -->
<div class="sidebar" id="sidebar">
<div class="sidebar-header">
<h2>Teknir Panel</h2>
</div>
<div class="content-area">
<!-- Dashboard Page -->
<div id="dashboardPage">
<div class="card">
<div class="card-title">📈 Performance Metrics</div>
<div class="metrics">
<div class="metric-card">
<div class="metric-header">
<div class="metric-title">CPU Usage</div>
<div id="cpuValue">0%</div>
</div>
<div class="progress-bar">
<div class="progress" id="cpuProgress"
style="width: 0%"></div>
</div>
</div>
<div class="metric-card">
<div class="metric-header">
<div class="metric-title">Memory Usage</div>
<div id="memValue">0%</div>
</div>
<div class="progress-bar">
<div class="progress" id="memProgress"
style="width: 0%"></div>
</div>
</div>
<div class="metric-card">
<div class="metric-header">
<div class="metric-title">Network Activity</div>
<div id="netValue">0 KB/s</div>
</div>
<div class="progress-bar">
<div class="progress" id="netProgress"
style="width: 0%"></div>
</div>
</div>
</div>
</div>
<div class="card">
<div class="card-title"> System Specifications</div>
<div class="specs-grid" id="specsGrid">
<!-- Dynamically populated -->
</div>
</div>
</div>
<div class="form-group">
<label class="form-label">Interface Name</label>
<select class="form-select" id="ipInterface">
<!-- Populated by JavaScript -->
</select>
</div>
<div class="mode-toggle">
<div class="mode-option">
<input type="radio" id="ipModeStatic" name="ipMode"
value="static" checked>
<label for="ipModeStatic">Static IP</label>
</div>
<div class="mode-option">
<input type="radio" id="ipModeDHCP" name="ipMode"
value="dhcp">
<label for="ipModeDHCP">DHCP (Automatic)</label>
</div>
</div>
<div id="ipStaticSettings">
<div class="form-grid">
<div class="form-group">
<label class="form-label">IP Address</label>
<input type="text" class="form-input"
id="ipAddress" value="[Link]">
</div>
<div class="form-group">
<label class="form-label">Subnet Mask</label>
<input type="text" class="form-input"
id="subnetMask" value="[Link]">
</div>
<div class="form-group">
<label class="form-label">Default Gateway</label>
<input type="text" class="form-input"
id="defaultGateway" value="[Link]">
</div>
</div>
</div>
<div class="form-group">
<button class="btn" id="saveIPv4">Save Settings</button>
<button class="btn btn-secondary" id="resetIPv4">Reset to
Default</button>
</div>
<div id="ipResult" class="form-group"></div>
</div>
</div>
<div class="form-group">
<label class="form-label">Interface Name</label>
<select class="form-select" id="dnsInterface">
<!-- Populated by JavaScript -->
</select>
</div>
<div class="mode-toggle">
<div class="mode-option">
<input type="radio" id="dnsModeStatic" name="dnsMode"
value="static" checked>
<label for="dnsModeStatic">Static DNS</label>
</div>
<div class="mode-option">
<input type="radio" id="dnsModeDHCP" name="dnsMode"
value="dhcp">
<label for="dnsModeDHCP">DHCP (Automatic)</label>
</div>
</div>
<div id="dnsStaticSettings">
<div class="form-grid">
<div class="form-group">
<label class="form-label">Primary DNS</label>
<input type="text" class="form-input" id="dns1"
value="[Link]">
</div>
<div class="form-group">
<label class="form-label">Secondary DNS</label>
<input type="text" class="form-input" id="dns2"
value="[Link]">
</div>
</div>
</div>
<div class="form-group">
<button class="btn" id="saveDNS">Save Settings</button>
<button class="btn btn-secondary" id="resetDNS">Reset to
Default</button>
</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Username</label>
<input type="text" class="form-input" id="sftpUser"
value="rbs">
</div>
<div class="form-group">
<label class="form-label">Password</label>
<input type="password" class="form-input" id="sftpPass"
value="rbs">
</div>
<div class="form-group">
<label class="form-label">Port</label>
<input type="number" class="form-input" id="sftpPort"
value="22">
</div>
<div class="form-group">
<label class="form-label">Root Path</label>
<div style="display: flex;">
<input type="text" class="form-input" id="sftpRoot"
placeholder="Select root directory" style="flex: 1;">
<button class="btn" id="browseRoot" style="margin-
left: 10px;">Browse</button>
</div>
</div>
<div class="form-group">
<label class="form-label">IP Address</label>
<input type="text" class="form-input" id="sftpHost"
value="[Link]">
</div>
</div>
<div class="form-group">
<button class="btn" id="saveSftpConfig">Save
Configuration</button>
<button class="btn" id="startSftp">Start Server</button>
<button class="btn btn-secondary" id="stopSftp">Stop
Server</button>
</div>
<script>
// DOM Elements
const sidebar = [Link]('sidebar');
const sidebarToggle = [Link]('sidebarToggle');
const themeToggle = [Link]('themeToggle');
const themeIcon = [Link]('themeIcon');
const navItems = [Link]('.nav-item');
const pages = {
dashboard: [Link]('dashboardPage'),
logs: [Link]('logsPage'),
ipv4: [Link]('ipv4Page'),
dns: [Link]('dnsPage'),
sftp: [Link]('sftpPage'),
datetime: [Link]('datetimePage'),
report: [Link]('reportPage'),
netinfo: [Link]('netinfoPage')
};
const pageTitle = [Link]('pageTitle');
const tehranTime = [Link]('tehranTime');
const pingStatus = [Link]('pingStatus');
const pingText = [Link]('pingText');
const pingTime = [Link]('pingTime');
// Toggle Sidebar
[Link]('click', () => {
[Link]('collapsed');
});
// Theme Toggle
[Link]('click', () => {
const isDark = [Link]('data-theme') !== 'light';
[Link]('data-theme', isDark ? 'light' : '');
[Link] = isDark ? '☀️' : '';
[Link] = `${[Link]} ${isDark ? 'Light' :
'Dark'} Mode`;
});
// Navigation
[Link](item => {
[Link]('click', (e) => {
[Link]();
const page = [Link]('data-page');
if (pages[page]) {
pages[page].[Link]('hidden');
[Link] = [Link]('.nav-
text').textContent;
// Tehran Time
function updateTehranTime() {
const now = new Date();
const tehranTimeStr = [Link]("en-US", {
timeZone: "Asia/Tehran",
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false
});
[Link]('tehranTime').textContent = `Tehran $
{tehranTimeStr}`;
}
// Ping Status
function updatePingStatus() {
if (!pingStatus || !pingText || !pingTime) return;
[Link] = ping_status;
[Link] = ` ${ping_time}`;
[Link]('dateInput').value = `${year}/${month}/${day}`;
[Link]('timeInput').value = `${hours}:${minutes}:$
{seconds}`;
}
// Performance Metrics
async function updatePerformance() {
try {
const response = await fetch('/system_info');
const data = await [Link]();
// CPU
const cpuPercent = [Link] || 0;
[Link]('cpuValue').textContent = `${cpuPercent}%`;
[Link]('cpuProgress').[Link] = `${cpuPercent}
%`;
// Memory
const memPercent = [Link] || 0;
[Link]('memValue').textContent = `${memPercent}%`;
[Link]('memProgress').[Link] = `${memPercent}
%`;
// Network - show KB/s and use dynamic scaling for progress bar
const netKB = [Link]([Link] || 0);
[Link]('netValue').textContent = `${netKB} KB/s`;
// Update specs
const specsGrid = [Link]('specsGrid');
if (specsGrid) {
[Link] = '';
} catch (error) {
[Link]('Failed to fetch system info:', error);
}
}
// Logs Display
async function updateLogs() {
try {
const response = await fetch('/get_logs');
const data = await [Link]();
const logContainer = [Link]('logContainer');
if (logContainer) {
[Link] = [Link](log =>
`<div class="log-entry">${log}</div>`
).join('');
// Auto-scroll to bottom
[Link] = [Link];
}
} catch (error) {
[Link]('Failed to fetch logs:', error);
}
}
} catch (error) {
[Link]('Failed to load interfaces:', error);
}
}
[Link]('sftpUser').value = [Link];
[Link]('sftpPass').value = [Link];
[Link]('sftpPort').value = [Link];
[Link]('sftpRoot').value = [Link].root_path;
[Link]('sftpHost').value = [Link];
[Link]('enableZlib').checked =
[Link].enable_zlib;
[Link]('enableNagle').checked =
[Link].enable_nagle;
[Link]('enableScp').checked =
[Link].enable_scp;
[Link]('fipsMode').checked =
[Link].fips_mode;
[Link]('listHidden').checked =
[Link].list_hidden_files;
[Link]('utf8').checked = [Link].utf8;
} catch (error) {
[Link]('Failed to load SFTP config:', error);
}
}
try {
const response = await fetch('/update_ip_settings', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: [Link]({ interface, mode, ip, mask, gateway })
});
try {
const response = await fetch('/update_dns_settings', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: [Link]({ interface, mode, dns1, dns2 })
});
try {
const response = await fetch('/update_datetime', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: [Link]({ date, time })
});
try {
const response = await fetch('/reset_datetime', {
method: 'POST'
});
// Export Logs
[Link]('exportLogs').addEventListener('click', () => {
[Link] = '/export_logs';
});
try {
const response = await fetch('/update_sftp_config', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: [Link](config)
});
const data = await [Link]();
const statusClass = [Link] ? 'status-success' : 'status-
error';
[Link] = `<div class="status-message ${statusClass}">$
{[Link]}</div>`;
updateLogs();
} catch (error) {
[Link] = `<div class="status-message status-
error">Error: ${[Link]}</div>`;
}
});
try {
const response = await fetch('/toggle_sftp_server', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: [Link]({ action: 'start' })
});
try {
const response = await fetch('/toggle_sftp_server', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: [Link]({ action: 'stop' })
});
if (!netinfoContent) return;
[Link] = '';
data.network_info.forEach(iface => {
const card = [Link]('div');
[Link] = 'netinfo-card';
if ([Link]) {
content += `<div class="netinfo-item"><span class="netinfo-
label">MAC Address:</span> ${[Link]}</div>`;
}
[Link] = content;
[Link](card);
});
} catch (error) {
[Link] = `<div class="status-message status-
error">Error loading network info: ${[Link]}</div>`;
}
}
[Link]('ipModeStatic').addEventListener('change', ()
=> {
[Link]('ipStaticSettings').[Link] =
'block';
});
}
if ([Link]('dnsModeDHCP')) {
[Link]('dnsModeDHCP').addEventListener('change', () =>
{
[Link]('dnsStaticSettings').[Link] =
'none';
});
[Link]('dnsModeStatic').addEventListener('change', ()
=> {
[Link]('dnsStaticSettings').[Link] =
'block';
});
}
// Initialize
updatePerformance();
updateLogs();
updateTehranTime();
updatePingStatus();
updateDateTimeForm();
setInterval(updatePerformance, 1000);
setInterval(updateLogs, 3000);
setInterval(updateTehranTime, 1000);
loadInterfaces();
</script>
</body>
</html>
"""
# =====================
# MAIN APPLICATION
# =====================
if __name__ == "__main__":
# Check for admin privileges
if [Link] == 'nt':
try:
if not [Link]():
[Link](0, "This application must be run
as administrator", "Permission Error", 0x10)
[Link](1)
except:
pass