0% found this document useful (0 votes)
12 views40 pages

Python SFTP Server and Network Monitor

Uploaded by

moin.nikchre89
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views40 pages

Python SFTP Server and Network Monitor

Uploaded by

moin.nikchre89
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

import tkinter as tk

from tkinter import ttk, scrolledtext, messagebox, filedialog


import threading
import socket
import time
import psutil
import platform
import datetime
from flask import Flask, render_template, request, jsonify, send_file
import json
import subprocess
import os
import re
import sys
import ctypes
import winreg
import select
import ping3
import paramiko
from paramiko import Transport, ServerInterface, SFTPServerInterface,
SFTPAttributes, SFTPHandle
from [Link] import SFTP_OK, SFTP_FAILURE
import stat
import logging

# ====================
# GLOBAL CONFIGURATION
# ====================
SERVER_PORT = 6499
LOG_PREFIX = "LSE"
NETWORK_SETTINGS = {
'ip': '[Link]',
'mask': '[Link]',
'gateway': '[Link]',
'dns1': '[Link]',
'dns2': '[Link]'
}

# SFTP Server Configuration


SFTP_CONFIG = {
'enabled': False,
'username': 'rbs',
'password': 'rbs',
'port': 22,
'root_path': '',
'host': '[Link]',
'enable_zlib': True,
'enable_nagle': False,
'enable_scp': True,
'fips_mode': False,
'list_hidden_files': False,
'utf8': True
}

# Network monitoring variables


prev_bytes_sent = 0
prev_bytes_recv = 0
prev_time = [Link]()
# SFTP server instance
sftp_server = None
sftp_server_thread = None

# CPU monitoring
cpu_percent = 0
def monitor_cpu():
global cpu_percent
while True:
cpu_percent = psutil.cpu_percent(interval=1)

# Start CPU monitoring thread


cpu_thread = [Link](target=monitor_cpu, daemon=True)
cpu_thread.start()

# 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)

# Start ping monitoring thread


ping_thread = [Link](target=monitor_ping, daemon=True)
ping_thread.start()

# =================
# LOGGING MECHANISM
# =================
class LogSync:
def __init__(self):
[Link] = []
[Link] = [Link]()

def add_log(self, message):


with [Link]:
timestamp = [Link]().strftime("%H:%M:%S")
entry = f"[{timestamp}] {LOG_PREFIX} {message}"
[Link](entry)
return entry

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

# Get current time


current_time = [Link]()
time_diff = current_time - prev_time

# Get current network stats


net_io = psutil.net_io_counters()
current_bytes_sent = net_io.bytes_sent
current_bytes_recv = net_io.bytes_recv

# Calculate network usage (KB/s)


if prev_bytes_sent == 0 or prev_bytes_recv == 0 or time_diff < 0.1:
network_usage = 0
else:
sent_diff = current_bytes_sent - prev_bytes_sent
recv_diff = current_bytes_recv - prev_bytes_recv
network_usage = (sent_diff + recv_diff) / 1024 / time_diff # KB/s

# Update previous values


prev_bytes_sent = current_bytes_sent
prev_bytes_recv = current_bytes_recv
prev_time = current_time

# SFTP server status


sftp_status = "Running" if sftp_server and sftp_server.is_alive() else
"Stopped"

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')

# Find the header line


header_index = -1
for i, line in enumerate(lines):
if 'State' in line and 'Type' in line and 'Name' in line:
header_index = i
break

if header_index == -1:
return ["Ethernet"] # Fallback

# Process interface lines


for line in lines[header_index+1:]:
if not [Link]():
continue

parts = [Link]()
if len(parts) < 4:
continue

# Interface name is everything after the first 3 columns


interface_name = ' '.join(parts[3:]).strip()
[Link](interface_name)

return interfaces if interfaces else ["Ethernet"]


except Exception as e:
log_sync.add_log(f"Error getting interfaces: {str(e)}")
return ["Ethernet"]

def set_static_ip(interface, ip, mask, gateway):


"""Set static IP using netsh commands"""
try:
# Run commands in background without showing console window
startupinfo = [Link]()
[Link] |= subprocess.STARTF_USESHOWWINDOW

# Build the command


cmd = f'netsh interface ip set address name="{interface}" source=static
addr={ip} mask={mask} gateway={gateway}'
[Link](cmd, startupinfo=startupinfo, shell=True, check=True)

return True, f"Static IP set: {ip} on {interface}"


except [Link] as e:
return False, f"Error updating IP: {e}"

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"'

# Run with CREATE_NEW_CONSOLE to show the command prompt window


[Link](cmd, shell=True, check=True,
creationflags=subprocess.CREATE_NEW_CONSOLE)
return True, f"DHCP enabled on {interface}"
except [Link] as e:
return False, f"Error setting DHCP: {e}"

def set_static_dns(interface, dns1, dns2=None):


"""Set static DNS using netsh commands"""
try:
# Run commands in background without showing console window
startupinfo = [Link]()
[Link] |= subprocess.STARTF_USESHOWWINDOW

# Set primary DNS


cmd = f'netsh interface ip set dns name="{interface}" source=static
addr={dns1}'
[Link](cmd, startupinfo=startupinfo, shell=True, check=True)

# Set secondary DNS if provided


if dns2:
cmd = f'netsh interface ip add dns name="{interface}" addr={dns2}
index=2'
[Link](cmd, startupinfo=startupinfo, shell=True, check=True)

return True, f"Static DNS set: {dns1}, {dns2} on {interface}"


except [Link] as e:
return False, f"Error updating DNS: {e}"

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

# Build the command


cmd = f'netsh interface ip set dns name="{interface}" source=dhcp'
[Link](cmd, startupinfo=startupinfo, shell=True, check=True)

return True, f"DHCP DNS enabled on {interface}"


except [Link] as e:
return False, f"Error setting DNS to DHCP: {e}"

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 = {}

for line in [Link]('\n'):


# Check for adapter name
if 'adapter' in [Link]() and ':' in line:
if current_adapter:
net_info.append(adapter_info)
adapter_info = {}

current_adapter = [Link](':')[0].strip()
adapter_info = {
'name': current_adapter,
'ipv4': [],
'ipv6': [],
'mac': None,
'dns': [],
'gateway': []
}

# Parse MAC address


if 'physical address' in [Link]():
mac_match = [Link](r'([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})',
line)
if mac_match:
adapter_info['mac'] = mac_match.group(0)

# Parse IPv4 address


if 'ipv4 address' in [Link]():
ip_match = [Link](r'(\d+\.\d+\.\d+\.\d+)', line)
subnet_match = [Link](r'Subnet Mask[ .:]+(\d+\.\d+\.\d+\.\d+)',
line)
if ip_match:
adapter_info['ipv4'].append({
'address': ip_match.group(1),
'netmask': subnet_match.group(1) if subnet_match else
'[Link]'
})

# Parse DNS servers


if 'dns servers' in [Link]():
dns_match = [Link](r'(\d+\.\d+\.\d+\.\d+)', line)
if dns_match:
adapter_info['dns'].append(dns_match.group(1))

# Parse default gateway


if 'default gateway' in [Link]():
gw_match = [Link](r'(\d+\.\d+\.\d+\.\d+)', line)
if gw_match:
adapter_info['gateway'].append(gw_match.group(1))

# Add last adapter


if current_adapter:
net_info.append(adapter_info)

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']

def _realpath(self, path):


# Convert SFTP path to real filesystem path
if not path or path == '.':
return [Link]
return [Link]([Link], [Link]('/'))

def list_folder(self, path):


real_path = self._realpath(path)
try:
out = []
for filename in [Link](real_path):
if not self.list_hidden and [Link]('.'):
continue
filepath = [Link](real_path, filename)
attr = SFTPAttributes.from_stat([Link](filepath))
[Link] = [Link]('utf-8') if self.utf8 else filename
[Link](attr)
return out
except OSError as e:
return [Link].convert_errno([Link])

def stat(self, path):


real_path = self._realpath(path)
try:
return SFTPAttributes.from_stat([Link](real_path))
except OSError as e:
return [Link].convert_errno([Link])

def open(self, path, flags, attr):


real_path = self._realpath(path)
try:
# Handle file creation flags
if flags & os.O_CREAT:
if not [Link](real_path):
open(real_path, 'w').close()

# Open the file


fd = [Link](real_path, flags)
handle = SFTPHandle(flags)
[Link] = real_path
[Link] = [Link](fd, 'rb')
[Link] = [Link](fd, 'wb')
return handle
except OSError as e:
return [Link].convert_errno([Link])

def remove(self, path):


real_path = self._realpath(path)
try:
[Link](real_path)
return SFTP_OK
except OSError as e:
return [Link].convert_errno([Link])

def mkdir(self, path, attr):


real_path = self._realpath(path)
try:
[Link](real_path)
return SFTP_OK
except OSError as e:
return [Link].convert_errno([Link])

def rmdir(self, path):


real_path = self._realpath(path)
try:
[Link](real_path)
return SFTP_OK
except OSError as e:
return [Link].convert_errno([Link])

def rename(self, oldpath, newpath):


old_real = self._realpath(oldpath)
new_real = self._realpath(newpath)
try:
[Link](old_real, new_real)
return SFTP_OK
except OSError as e:
return [Link].convert_errno([Link])

def chattr(self, path, attr):


# This is a simplified implementation
return SFTP_OK

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 check_channel_request(self, kind, chanid):


if kind == 'session':
return paramiko.OPEN_SUCCEEDED
return paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED

def check_channel_sftp_request(self, channel, path):


return [Link]

def get_allowed_auths(self, username):


return 'password'

def run_sftp_server():
global sftp_server
try:
host = SFTP_CONFIG['host']
port = SFTP_CONFIG['port']

# Create socket server


sock = [Link](socket.AF_INET, socket.SOCK_STREAM)
[Link](socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
[Link]((host, port))
[Link](5)

log_sync.add_log(f"SFTP server listening on {host}:{port}")


# Set Nagle algorithm based on configuration
if SFTP_CONFIG['enable_nagle']:
[Link](socket.IPPROTO_TCP, socket.TCP_NODELAY, 0)
else:
[Link](socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)

# Generate host key if needed


host_key = [Link](2048)

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

# Process SFTP requests


while transport.is_active():
[Link](0.1)

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

if sftp_server_thread and sftp_server_thread.is_alive():


log_sync.add_log("SFTP server is already running")
return True

# Create and start server thread


SFTP_CONFIG['enabled'] = True
sftp_server_thread = [Link](target=run_sftp_server, daemon=True)
sftp_server_thread.start()
log_sync.add_log("SFTP server started")
return True

def stop_sftp_server():
global sftp_server, sftp_server_thread
SFTP_CONFIG['enabled'] = False

# Create a dummy connection to break the accept() call


try:
with [Link](socket.AF_INET, socket.SOCK_STREAM) as s:
[Link]((SFTP_CONFIG['host'], SFTP_CONFIG['port']))
[Link]()
except:
pass

if sftp_server_thread and sftp_server_thread.is_alive():


sftp_server_thread.join(2.0)

log_sync.add_log("SFTP server stopped")


return True

# =========================
# 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)
})

log_sync.add_log("SFTP configuration updated")


return jsonify(success=True, message="SFTP configuration updated")

@[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"

return jsonify(success=success, message=message)

@[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)

log_sync.add_log(f"IP settings updated: {message}")


return jsonify(success=success, message=message)

@[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)

log_sync.add_log(f"DNS settings updated: {message}")


return jsonify(success=success, message=message)

@[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")

# Format for Windows command


date_cmd = [Link]("%m/%d/%Y")
time_cmd = [Link]("%H:%M:%S")

# Run commands in background


startupinfo = [Link]()
[Link] |= subprocess.STARTF_USESHOWWINDOW

[Link](f'date {date_cmd}', startupinfo=startupinfo, shell=True,


check=True)
[Link](f'time {time_cmd}', startupinfo=startupinfo, shell=True,
check=True)

message = f"System date/time updated to {date_str} {time_str}"


log_sync.add_log(message)
return jsonify(success=True, message=message)
except Exception as e:
message = f"Error updating date/time: {str(e)}"
log_sync.add_log(message)
return jsonify(success=False, message=message)

@[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")

# Run commands in background


startupinfo = [Link]()
[Link] |= subprocess.STARTF_USESHOWWINDOW

[Link](f'date {date_cmd}', startupinfo=startupinfo, shell=True,


check=True)
[Link](f'time {time_cmd}', startupinfo=startupinfo, shell=True,
check=True)

message = f"System date/time reset to current: {[Link]('%Y/%m/%d %H:


%M:%S')}"
log_sync.add_log(message)
return jsonify(success=True, message=message)
except Exception as e:
message = f"Error resetting date/time: {str(e)}"
log_sync.add_log(message)
return jsonify(success=False, message=message)

@[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"

with open(filename, "w") as f:


[Link](log_content)

return send_file(filename, as_attachment=True)

# =====================
# 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')

[Link](header, text="TEKNIR CONTROL PANEL", font=("System", 14),


fg="white", bg='#1e1e2d').pack(side='left', padx=20)

# Control buttons
btn_frame = [Link](header, bg='#1e1e2d')
btn_frame.pack(side='right', padx=20)

self.start_btn = [Link](btn_frame, text="Start Server",


command=self.toggle_server,
bg='#4CAF50', fg='white', relief='flat')
self.start_btn.pack(side='right', padx=5)

# 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)

self.log_area = [Link](log_frame, bg='#1e1e2d',


fg='#e0e0e0',
font=("Consolas", 10), wrap='word')
self.log_area.pack(fill='both', expand=True, padx=5, pady=5)
self.log_area.config(state='disabled')

# Add initial logs


log_sync.add_log("Control panel initialized")
self.update_log_display()

# Status frame for messages


self.status_frame = [Link]([Link], bg='#2d2d39')
self.status_frame.pack(fill='x', padx=10, pady=(0, 10))

def show_status(self, message, is_error=False):


if not self.status_frame:
return

for widget in self.status_frame.winfo_children():


[Link]()

color = '#f44336' if is_error else '#4CAF50'


lbl = [Link](self.status_frame, text=message, fg='white', bg=color,
font=("System", 10), padx=10, pady=5)
[Link](fill='x', ipady=5)

# Auto-hide after 5 seconds


[Link](5000, lambda: [Link]() if lbl.winfo_exists() else
None)

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)

self.server_thread = [Link](target=run_flask, daemon=True)


self.server_thread.start()
self.server_running = True
self.start_btn.config(text="Stop Server", bg='#f44336')
log_sync.add_log(f"Web server started on port {SERVER_PORT}")
log_sync.add_log(f"Access panel at: [Link]
self.update_log_display()
self.show_status("Server started successfully", False)
def stop_server(self):
self.server_running = False
self.start_btn.config(text="Start Server", bg='#4CAF50')
log_sync.add_log("Web server stopped")
self.update_log_display()
self.show_status("Server stopped", 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>

<!-- STATUS Section -->


<div class="section-title">STATUS</div>
<a href="#" class="nav-item active" data-page="dashboard">
<span class="nav-icon">📊</span>
<span class="nav-text">Dashboard</span>
</a>
<a href="#" class="nav-item" data-page="logs">
<span class="nav-icon">📝</span>
<span class="nav-text">Panel Logs</span>
</a>

<!-- INBOUND Section -->


<div class="section-title">INBOUND</div>
<a href="#" class="nav-item" data-page="ipv4">
<span class="nav-icon">🔌</span>
<span class="nav-text">IPv4 Settings</span>
</a>
<a href="#" class="nav-item" data-page="dns">
<span class="nav-icon">🌐</span>
<span class="nav-text">DNS Configuration</span>
</a>
<a href="#" class="nav-item" data-page="sftp">
<span class="nav-icon">📁</span>
<span class="nav-text">XlsCore SFTP</span>
</a>

<!-- SYSTEM Section -->


<div class="section-title">SYSTEM</div>
<a href="#" class="nav-item" data-page="datetime">
<span class="nav-icon">🕒</span>
<span class="nav-text">Date & Time</span>
</a>
<a href="#" class="nav-item" data-page="report">
<span class="nav-icon">📋</span>
<span class="nav-text">Report</span>
</a>

<!-- Netinf Section -->


<div class="section-title">NETINF</div>
<a href="#" class="nav-item" data-page="netinfo">
<span class="nav-icon">📡</span>
<span class="nav-text">Network Info</span>
</a>
</div>

<!-- Main Content -->


<div class="main-content">
<div class="topbar">
<div class="controls">
<button class="sidebar-toggle" id="sidebarToggle">☰</button>
<h3 id="pageTitle">Dashboard</h3>
</div>
<div class="tehran-time" id="tehranTime">Tehran 00:00:00</div>
<div id="pingStatus" class="ping-status ping-disconnected">
<span id="pingText">Disconnected</span>
<span id="pingTime">0ms</span>
</div>
<button class="theme-toggle" id="themeToggle">
<span id="themeIcon">🌙</span> Dark Mode
</button>
</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>

<!-- Logs Page -->


<div id="logsPage" class="hidden">
<div class="card">
<div class="card-title">📋 Panel Logs</div>
<div class="log-container" id="logContainer">
<!-- Logs will be populated here -->
</div>
</div>
</div>

<!-- IPv4 Settings Page -->


<div id="ipv4Page" class="hidden">
<div class="card">
<div class="card-title">🔌 IPv4 Configuration</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>

<!-- DNS Settings Page -->


<div id="dnsPage" class="hidden">
<div class="card">
<div class="card-title">🌐 DNS Configuration</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 id="dnsResult" class="form-group"></div>


</div>
</div>

<!-- SFTP Server Page -->


<div id="sftpPage" class="hidden">
<div class="card">
<div class="card-title">📁 XlsCore SFTP Server</div>
<div id="sftpStatus" class="sftp-status sftp-stopped">Status:
Stopped</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="card-title" style="margin-top: 20px;">⚙️ Server


Options</div>
<div class="option-grid">
<div class="option-item">
<input type="checkbox" id="enableZlib" checked>
<label for="enableZlib">Enable Zlib Compression</label>
</div>
<div class="option-item">
<input type="checkbox" id="enableNagle">
<label for="enableNagle">Enable Nagle Algorithm</label>
</div>
<div class="option-item">
<input type="checkbox" id="enableScp" checked>
<label for="enableScp">Enable SCP</label>
</div>
<div class="option-item">
<input type="checkbox" id="fipsMode">
<label for="fipsMode">FIPS Mode</label>
</div>
<div class="option-item">
<input type="checkbox" id="listHidden">
<label for="listHidden">List Hidden Files</label>
</div>
<div class="option-item">
<input type="checkbox" id="utf8" checked>
<label for="utf8">UTF-8 Filenames</label>
</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>

<div id="sftpResult" class="form-group"></div>


</div>
</div>

<!-- Date & Time Page -->


<div id="datetimePage" class="hidden">
<div class="card">
<div class="card-title">🕒 Date & Time Settings</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Date (YYYY/MM/DD)</label>
<input type="text" class="form-input" id="dateInput"
placeholder="YYYY/MM/DD">
</div>
<div class="form-group">
<label class="form-label">Time (HH:MM:SS)</label>
<input type="text" class="form-input" id="timeInput"
placeholder="HH:MM:SS">
</div>
</div>
<div class="form-group">
<button class="btn" id="saveDateTime">Save
Settings</button>
<button class="btn" id="resetDateTime">Reset to Current
Time</button>
<button class="btn btn-secondary" id="defaultDateTime">Set
Default</button>
</div>
<div id="datetimeResult" class="form-group"></div>
</div>
</div>

<!-- Report Page -->


<div id="reportPage" class="hidden">
<div class="card">
<div class="card-title">📋 System Report</div>
<div class="log-container" id="reportContainer">
<!-- Report will be populated here -->
</div>
<button class="btn" id="exportLogs" style="margin-top:
20px;">Export Logs</button>
</div>
</div>

<!-- Network Info Page -->


<div id="netinfoPage" class="hidden">
<div class="card">
<div class="card-title">📡 Network Information</div>
<div id="netinfoContent" class="netinfo-grid">
<!-- Will be populated by JavaScript -->
</div>
</div>
</div>
</div>
</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');

// Update active nav item


[Link](nav => [Link]('active'));
[Link]('active');

// Show selected page


[Link](pages).forEach(p => {
if (p) [Link]('hidden');
});

if (pages[page]) {
pages[page].[Link]('hidden');
[Link] = [Link]('.nav-
text').textContent;

// Special handling for certain pages


if (page === 'netinfo') {
updateNetworkInfo();
} else if (page === 'ipv4' || page === 'dns') {
loadInterfaces();
} else if (page === 'sftp') {
loadSftpConfig();
} else if (page === 'datetime') {
updateDateTimeForm();
}
}
});
});

// 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}`;

if (ping_status === "Connected") {


[Link] = 'ping-status ping-connected';
[Link] = 'ping-connected-text';
[Link] = 'ping-connected-time';
} else {
[Link] = 'ping-status ping-disconnected';
[Link] = 'ping-disconnected-text';
[Link] = 'ping-disconnected-time';
}
}

// Update Date/Time form with current values


function updateDateTimeForm() {
const now = new Date();
const year = [Link]();
const month = String([Link]() + 1).padStart(2, '0');
const day = String([Link]()).padStart(2, '0');
const hours = String([Link]()).padStart(2, '0');
const minutes = String([Link]()).padStart(2, '0');
const seconds = String([Link]()).padStart(2, '0');

[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`;

// Dynamic scaling for network progress bar (0-500 KB/s range)


const netPercentage = [Link](netKB / 5, 100); // 500 KB/s = 100%
[Link]('netProgress').[Link] = `$
{netPercentage}%`;

// Update specs
const specsGrid = [Link]('specsGrid');
if (specsGrid) {
[Link] = '';

for (const [key, value] of [Link]([Link] || {})) {


const specItem = [Link]('div');
[Link] = 'spec-item';
[Link] = `
<div class="spec-label">${[Link](/_/g, '
').toUpperCase()}</div>
<div class="spec-value">${value}</div>
`;
[Link](specItem);
}
}

// Update ping status


updatePingStatus();

// Update SFTP status


const sftpStatus = [Link]('sftpStatus');
if (sftpStatus) {
[Link] = `Status: $
{[Link].sftp_status}`;
[Link] = [Link].sftp_status ===
'Running' ?
'sftp-status sftp-running' : 'sftp-status sftp-stopped';
}

} 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];
}

// Also update report page if it's open


const reportContainer = [Link]('reportContainer');
if (reportContainer) {
[Link] = [Link](log =>
`<div class="log-entry">${log}</div>`
).join('');
}

} catch (error) {
[Link]('Failed to fetch logs:', error);
}
}

// Load network interfaces


async function loadInterfaces() {
try {
const response = await fetch('/get_interfaces');
const data = await [Link]();

const ipSelect = [Link]('ipInterface');


const dnsSelect = [Link]('dnsInterface');

// Clear existing options


if (ipSelect) [Link] = '';
if (dnsSelect) [Link] = '';

// Add new options


if ([Link] && [Link] > 0) {
[Link](iface => {
const option = [Link]('option');
[Link] = iface;
[Link] = iface;
if (ipSelect) [Link]([Link](true));
if (dnsSelect) [Link](option);
});

// Select first interface by default


if (ipSelect) [Link] = 0;
if (dnsSelect) [Link] = 0;
} else {
// Fallback if no interfaces found
const option = [Link]('option');
[Link] = 'No interfaces found';
if (ipSelect) [Link]([Link](true));
if (dnsSelect) [Link](option);
}

} catch (error) {
[Link]('Failed to load interfaces:', error);
}
}

// Load SFTP configuration


async function loadSftpConfig() {
try {
const response = await fetch('/get_sftp_config');
const data = await [Link]();

[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);
}
}

// Save IPv4 Settings


[Link]('saveIPv4').addEventListener('click', async () => {
const interface = [Link]('ipInterface').value;
const mode =
[Link]('input[name="ipMode"]:checked').value;
const ip = [Link]('ipAddress').value;
const mask = [Link]('subnetMask').value;
const gateway = [Link]('defaultGateway').value;
const resultDiv = [Link]('ipResult');
[Link] = '<div class="status-message status-
success">Applying settings...</div>';

try {
const response = await fetch('/update_ip_settings', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: [Link]({ interface, mode, ip, mask, gateway })
});

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>`;
}
});

// Reset IPv4 Settings


[Link]('resetIPv4').addEventListener('click', () => {
[Link]('ipAddress').value = '[Link]';
[Link]('subnetMask').value = '[Link]';
[Link]('defaultGateway').value = '[Link]';
[Link]('ipResult').innerHTML = '';
});

// Save DNS Settings


[Link]('saveDNS').addEventListener('click', async () => {
const interface = [Link]('dnsInterface').value;
const mode =
[Link]('input[name="dnsMode"]:checked').value;
const dns1 = [Link]('dns1').value;
const dns2 = [Link]('dns2').value;

const resultDiv = [Link]('dnsResult');


[Link] = '<div class="status-message status-
success">Applying settings...</div>';

try {
const response = await fetch('/update_dns_settings', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: [Link]({ interface, mode, dns1, dns2 })
});

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>`;
}
});

// Reset DNS Settings


[Link]('resetDNS').addEventListener('click', () => {
[Link]('dns1').value = '[Link]';
[Link]('dns2').value = '[Link]';
[Link]('dnsResult').innerHTML = '';
});

// Save Date & Time


[Link]('saveDateTime').addEventListener('click', async ()
=> {
const date = [Link]('dateInput').value;
const time = [Link]('timeInput').value;

const resultDiv = [Link]('datetimeResult');


[Link] = '<div class="status-message status-
success">Applying settings...</div>';

try {
const response = await fetch('/update_datetime', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: [Link]({ date, time })
});

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>`;
}
});

// Reset Date & Time to current


[Link]('resetDateTime').addEventListener('click', async ()
=> {
const resultDiv = [Link]('datetimeResult');
[Link] = '<div class="status-message status-
success">Resetting to current time...</div>';

try {
const response = await fetch('/reset_datetime', {
method: 'POST'
});

const data = await [Link]();


const statusClass = [Link] ? 'status-success' : 'status-
error';
[Link] = `<div class="status-message ${statusClass}">$
{[Link]}</div>`;
updateLogs();
updateDateTimeForm();
} catch (error) {
[Link] = `<div class="status-message status-
error">Error: ${[Link]}</div>`;
}
});

// Set default Date & Time


[Link]('defaultDateTime').addEventListener('click', () =>
{
[Link]('dateInput').value = '2038/01/01';
[Link]('timeInput').value = '00:00:00';
[Link]('datetimeResult').innerHTML = '';
});

// Export Logs
[Link]('exportLogs').addEventListener('click', () => {
[Link] = '/export_logs';
});

// Browse for SFTP root folder


[Link]('browseRoot').addEventListener('click', async () =>
{
try {
const response = await fetch('/browse_folder');
const data = await [Link]();
[Link]('sftpRoot').value = [Link];
} catch (error) {
[Link]('Error getting folder:', error);
}
});

// Save SFTP Configuration


[Link]('saveSftpConfig').addEventListener('click', async
() => {
const config = {
username: [Link]('sftpUser').value,
password: [Link]('sftpPass').value,
port: parseInt([Link]('sftpPort').value),
root_path: [Link]('sftpRoot').value,
host: [Link]('sftpHost').value,
enable_zlib: [Link]('enableZlib').checked,
enable_nagle: [Link]('enableNagle').checked,
enable_scp: [Link]('enableScp').checked,
fips_mode: [Link]('fipsMode').checked,
list_hidden_files: [Link]('listHidden').checked,
utf8: [Link]('utf8').checked
};

const resultDiv = [Link]('sftpResult');


[Link] = '<div class="status-message status-
success">Saving configuration...</div>';

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>`;
}
});

// Start SFTP Server


[Link]('startSftp').addEventListener('click', async () =>
{
const resultDiv = [Link]('sftpResult');
[Link] = '<div class="status-message status-
success">Starting server...</div>';

try {
const response = await fetch('/toggle_sftp_server', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: [Link]({ action: 'start' })
});

const data = await [Link]();


const statusClass = [Link] ? 'status-success' : 'status-
error';
[Link] = `<div class="status-message ${statusClass}">$
{[Link]}</div>`;
updateLogs();
// Refresh status after a moment
setTimeout(updatePerformance, 1000);
} catch (error) {
[Link] = `<div class="status-message status-
error">Error: ${[Link]}</div>`;
}
});

// Stop SFTP Server


[Link]('stopSftp').addEventListener('click', async () => {
const resultDiv = [Link]('sftpResult');
[Link] = '<div class="status-message status-
success">Stopping server...</div>';

try {
const response = await fetch('/toggle_sftp_server', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: [Link]({ action: 'stop' })
});

const data = await [Link]();


const statusClass = [Link] ? 'status-success' : 'status-
error';
[Link] = `<div class="status-message ${statusClass}">$
{[Link]}</div>`;
updateLogs();
// Refresh status after a moment
setTimeout(updatePerformance, 1000);
} catch (error) {
[Link] = `<div class="status-message status-
error">Error: ${[Link]}</div>`;
}
});

// Update Network Info


async function updateNetworkInfo() {
try {
const response = await fetch('/get_network_info');
const data = await [Link]();
const netinfoContent = [Link]('netinfoContent');

if (!netinfoContent) return;

[Link] = '';

if (!data.network_info || data.network_info.length === 0) {


[Link] = '<div class="status-message status-
error">No network information available</div>';
return;
}

data.network_info.forEach(iface => {
const card = [Link]('div');
[Link] = 'netinfo-card';

let content = `<div


class="netinfo-header">${[Link]}</div>`;

if ([Link]) {
content += `<div class="netinfo-item"><span class="netinfo-
label">MAC Address:</span> ${[Link]}</div>`;
}

if (iface.ipv4 && [Link] > 0) {


content += '<div class="netinfo-item"><span class="netinfo-
label">IPv4:</span></div>';
[Link](addr => {
content += `<div class="netinfo-item">- Address: $
{[Link] || 'N/A'}</div>`;
content += `<div class="netinfo-item">- Netmask: $
{[Link] || 'N/A'}</div>`;
});
}

if ([Link] && [Link] > 0) {


content += '<div class="netinfo-item"><span class="netinfo-
label">DNS Servers:</span></div>';
[Link](dns => {
content += `<div class="netinfo-item">- ${dns}</div>`;
});
}

if ([Link] && [Link] > 0) {


content += '<div class="netinfo-item"><span class="netinfo-
label">Gateway:</span></div>';
[Link](gw => {
content += `<div class="netinfo-item">- ${gw}</div>`;
});
}

[Link] = content;
[Link](card);
});

} catch (error) {
[Link] = `<div class="status-message status-
error">Error loading network info: ${[Link]}</div>`;
}
}

// Toggle DHCP/Static fields


if ([Link]('ipModeDHCP')) {
[Link]('ipModeDHCP').addEventListener('change', () =>
{
[Link]('ipStaticSettings').[Link] = 'none';
});

[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

# Initialize network monitoring


net_io = psutil.net_io_counters()
prev_bytes_sent = net_io.bytes_sent
prev_bytes_recv = net_io.bytes_recv
prev_time = [Link]()

# Create temporary files for Flask


with open("[Link]", "w", encoding="utf-8") as f:
[Link](html_content)

# Start Tkinter control panel


root = [Link]()
app_ui = ControlPanel(root)
[Link]()

You might also like