diff --git a/.gitignore b/.gitignore
index afe635295d088eaaca932a16be52df005d392231..9942656753a4a16413fd54c42e040a36ee880f9e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,13 +14,15 @@ bin-release/
*.apk
.venv/
.data/config/
+panel.json
+ssh.json
.data/log/
main.spec
.build/
/running.lock
-./pid.txt
main.spec
*.txt
+pid.txt
# Project files, i.e. `.project`, `.actionScriptProperties` and `.flexProperties`
# should NOT be excluded as they contain compiler settings and other important
# information for Eclipse / Flash Builder.
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 83487dc6313c616eaa333ef4d72004121e99a1d4..81c5bf1d615ec283bce8d45cb02360264ae5ee27 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -4,21 +4,27 @@
-
-
-
-
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
@@ -54,6 +60,11 @@
"settings.editor.selected.configurable": "preferences.pluginManager"
}
}
+
+
+
+
+
@@ -147,7 +158,39 @@
1716027227309
-
+
+
+ 1716204311712
+
+
+
+ 1716204311712
+
+
+
+ 1716216173977
+
+
+
+ 1716216173977
+
+
+
+ 1716613697069
+
+
+
+ 1716613697069
+
+
+
+ 1716613872061
+
+
+
+ 1716613872061
+
+
@@ -158,6 +201,10 @@
-
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index b596332c465698ddc8f3cd84ab1771c8087ffbd6..5974c4b2bb6c98669975f217e769ae541e8a9bab 100644
--- a/README.md
+++ b/README.md
@@ -1,17 +1,19 @@
-# QuickPanel
+## 🚀 QuickPanel
+[](https://gitee.com/codekpy/quick-panel/stargazers)
+## 📝 简介
+QuickPanel 是使用 Python 和 Flask 框架构建的服务器管理仪表板。
-#### 介绍
-使用Python+flask框架搭建的服务器管理面板
+## 🏗️ 软件架构
+QuickPanel 后端采用 Python 3.8 开发,前端使用 Node.js 和 Vue3 构建。
-#### 软件架构
-使用Python 3.8环境,flask作为后端框架开发,node.js+Vue3作为前端框架开发。
+## 📖 使用指南
+详细的使用说明请访问 [QPanel 官方网站](https://qpanel.cloudroo.top/)。
-#### 使用教程
-前往[QPanel官网](https://qpanel.cloudroo.top/)
+## 🤝 参与贡献
+如果您想为 QuickPanel 做出贡献,请按照以下步骤:
+1. Fork 该仓库。
+2. 创建一个名为 `Feat_xxx` 的新分支。
+3. 提交您的代码更改。
+4. 创建一个新的 Pull Request。
-#### 参与贡献
-
-1. Fork 本仓库
-2. 新建 Feat_xxx 分支
-3. 提交代码
-4. 新建 Pull Request
\ No newline at end of file
+您的贡献将不胜感激!
\ No newline at end of file
diff --git a/app/controller/Api.py b/app/controller/Api.py
index 415d12bd5b9ff86c8b8af532f978cbce5a66d454..ecf76d05f8843e411fe61dbe77a574ed6ac47147 100644
--- a/app/controller/Api.py
+++ b/app/controller/Api.py
@@ -5,7 +5,10 @@ import hashlib
import psutil
import platform
from app.utils import System
+from app.utils import File
import json
+
+
def get_cpu_brand():
if platform.system() == 'Windows':
return platform.processor()
@@ -16,7 +19,8 @@ def get_cpu_brand():
return line.split(':')[1].strip()
return 'Unknown'
-def service(path, cfg, data):
+
+def service(path, cfg, data, request):
if path == "post/login":
print(data)
print(cfg)
@@ -25,7 +29,7 @@ def service(path, cfg, data):
data = json.loads(data)
if data["username"] in cfg:
# 登录用户名正确
- #print(hashlib.sha256(data["pw"].encode()).hexdigest())
+ # print(hashlib.sha256(data["pw"].encode()).hexdigest())
if hashlib.sha256(data["pw"].encode()).hexdigest() == cfg[data["username"]]:
# 密码正确
session['username'] = data["username"]
@@ -87,15 +91,23 @@ def service(path, cfg, data):
elif path == "get/off_system":
System.off_system()
return jsonify({'code': 200, 'msg': 'System restarting'})
-
elif path == "post/set_port":
data = data.decode('utf-8')
data = json.loads(data)
- System.set_firewall_rule(port=int(data["port"]), system=System.get_system_name(), status=data["status"], protocol=data["protocol"], source_ip=data["source_ip"])
+ System.set_firewall_rule(port=int(data["port"]), system=System.get_system_name(), status=data["status"],
+ protocol=data["protocol"], source_ip=data["source_ip"])
return jsonify({'code': 200, 'msg': 'Port set successfully'})
elif path == "get/port_rules":
-
data = System.get_firewall_rules(System.get_system_name())
if json.loads(data):
- print("yes")
- return jsonify({"code": 200, "data": json.loads(data)})
+ if System.get_system_name() == "Windows":
+ system_type = "win"
+ else:
+ system_type = "linux"
+ return jsonify({"code": 200, "data": json.loads(data), "type": system_type})
+ else:
+ return jsonify({"code": 404, "data": "No rules found"})
+ elif path == "post/get_file_data":
+ data = request.get_json()
+ data = File.get_directory_tree(data["path"])
+ return jsonify({"code": 200, "data": data})
\ No newline at end of file
diff --git a/app/controller/__pycache__/Api.cpython-38.pyc b/app/controller/__pycache__/Api.cpython-38.pyc
index 15f8c7fd395fd862409525ddbd87e9f226a5055e..08f3a0305f297f5c059697267292f68460ad8ac9 100644
Binary files a/app/controller/__pycache__/Api.cpython-38.pyc and b/app/controller/__pycache__/Api.cpython-38.pyc differ
diff --git a/app/controller/__pycache__/index.cpython-38.pyc b/app/controller/__pycache__/index.cpython-38.pyc
index d54844b9f007b2afa5c83ec60c81d70176718f56..275fbc9d0d12e1e8d02ca09038b824b1172e3d54 100644
Binary files a/app/controller/__pycache__/index.cpython-38.pyc and b/app/controller/__pycache__/index.cpython-38.pyc differ
diff --git a/app/controller/__pycache__/install.cpython-36.pyc b/app/controller/__pycache__/install.cpython-36.pyc
deleted file mode 100644
index 50118b4a59d76f26e43e8ea6096d1cdaf015c848..0000000000000000000000000000000000000000
Binary files a/app/controller/__pycache__/install.cpython-36.pyc and /dev/null differ
diff --git a/app/controller/__pycache__/install.cpython-38.pyc b/app/controller/__pycache__/install.cpython-38.pyc
index 07b04fd7d85f7710b292cc1b9b10e0dcbfb564cd..8eb70da15b546f1c2ace716031224d8fbadaf79b 100644
Binary files a/app/controller/__pycache__/install.cpython-38.pyc and b/app/controller/__pycache__/install.cpython-38.pyc differ
diff --git a/app/controller/index.py b/app/controller/index.py
index 37278bed29b1dbd6361006e3d6dedb71230def14..1cda713e602bfea70c395093a67fbac376c3343f 100644
--- a/app/controller/index.py
+++ b/app/controller/index.py
@@ -30,10 +30,11 @@ def service_start(ROOT_PATH):
# 可以在路径内以/<参数名>的形式指定参数,默认接收到的参数类型是string
Route.get_route(app, cfg, ROOT_PATH, ws=socketio)
- # 开启单独线程启动WebSocket服务
- websocket_thread = threading.Thread(target=start_websocket)
- websocket_thread.start()
-
- # 使用gevent启动HTTP服务器
- server = pywsgi.WSGIServer(('0.0.0.0', cfg["port"]), app)
- server.serve_forever()
+ """ # 开启单独线程启动WebSocket服务
+ websocket_thread = threading.Thread(target=start_websocket)
+ websocket_thread.start()"""
+ """
+ # 使用gevent启动HTTP服务器
+ server = pywsgi.WSGIServer(('0.0.0.0', cfg["port"]), app)
+ server.serve_forever()"""
+ start_websocket()
\ No newline at end of file
diff --git a/app/controller/install.py b/app/controller/install.py
index 8025b203d3d5fa577b133e9b6ebf70d9d21f7c7b..c8faa8687c1f4486ae846cf2488a77a3efbd2002 100644
--- a/app/controller/install.py
+++ b/app/controller/install.py
@@ -4,12 +4,26 @@ import json
import random
import string
import hashlib
-from app.utils import Service, File, System
+from app.utils import Service, File
+import ntsecuritycon
-
-def install():
+def PanelInstall(ROOT_PATH):
system = sy.get_system_name()
print("正在安装", system, "系统版本的面板...")
+ print("请输入您的系统SSH信息:")
+ ssh_name = input("您的系统SSH用户为: ")
+ ssh_port = input("您的系统SSH端口为: ")
+ ssh_pw = input("您的系统SSH密码为: ")
+ # 写入文件
+ json_data = {
+ "ip": "127.0.0.1",
+ "name": ssh_name,
+ "port": ssh_port,
+ "pw": ssh_pw
+ }
+ with open("./data/config/ssh.json", 'w') as file:
+ json.dump(json_data, file)
+ File.SetAuthority(ROOT_PATH +"./data/config/ssh.json", system)
# 生成数据
# 生成随机字母
@@ -33,7 +47,7 @@ def install():
with open("./data/config/panel.json", 'w') as file:
json.dump(json_data, file)
- File.SetAuthority(os.getcwd() + "/../../" + "./data/config/panel.json", system)
+ File.SetAuthority(ROOT_PATH + "./data/config/panel.json", system)
# 设置开机自启动
service_name = "QPanel_Service"
diff --git a/app/utils/Cmd.py b/app/utils/Cmd.py
index 024e57a65e169dd8c78960c39198aad0e2632108..8b165887a34c4736b6aa0cc0bb0345702641ded6 100644
--- a/app/utils/Cmd.py
+++ b/app/utils/Cmd.py
@@ -1,11 +1,10 @@
import subprocess
-def execute_command(command):
+"""def execute_command(command):
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, universal_newlines=True)
- return process
+ return process"""
-
-def run_command(command, ws, id, list, id_list):
+"""def run_command(command, ws, id, list, id_list):
command = command.strip()
if id not in list:
@@ -73,6 +72,82 @@ def run_command(command, ws, id, list, id_list):
ws.emit("response", {"value": f"[shell]({id_list[id]}) # "}, namespace="/Shell")
if output:
ws.emit("response", {"value": output.strip()}, namespace="/Shell")
- return list, id_list
+ return list, id_list"""
+
+import os
+import shlex
+import subprocess
+import sys
+import time
+
+# 初始化当前工作目录
+cwd = os.getcwd()
+
+
+def run_command(command, ws, id, list, id_list):
+ # 显示命令提示符
+ if id not in list:
+ cwd = os.getcwd()
+ id_list[id] = cwd
+
+ else:
+ print(id_list[id])
+ current_directory = id_list[id]
+ print("存在该进程")
+ cwd = current_directory
+ prompt = f"{cwd}># "
+
+ parts = shlex.split(command)
+ if len(parts) == 0:
+ ws.emit("response", {"value": prompt}, namespace="/Shell")
+ return list, id_list
+ elif parts[0].lower() == "exit":
+ pass
+
+ # 处理 cd 命令
+ if parts[0].lower() == "cd":
+ try:
+ # 切换目录
+ if len(parts) > 1:
+ os.chdir(parts[1])
+ else:
+ os.chdir(os.path.expanduser("~"))
+ cwd = os.getcwd()
+ id_list[id] = cwd
+ ws.emit("response", {"value": f"{cwd}># "}, namespace="/Shell")
+ return list, id_list
+ except Exception as e:
+ print(f"无法切换目录: {e}")
+ ws.emit("response", {"value": f"{cwd}># "}, namespace="/Shell")
+ return list, id_list
+ else:
+ try:
+ # 启动新的子进程,并执行命令
+ list[id] = subprocess.Popen(parts, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+ universal_newlines=True, cwd=cwd)
+
+ # 循环读取输出并实时输出
+ for line in iter(list[id].stdout.readline, ''):
+ print(line.rstrip())
+ ws.emit("response", {"value": line.rstrip()}, namespace="/Shell")
+
+
+ # 等待子进程结束
+ list[id].wait()
+
+
+ # 打印错误信息
+ errors = list[id].stderr.read()
+ print(errors.strip())
+
+ # 更新当前工作目录
+ cwd = os.getcwd()
+ id_list[id] = cwd
+ ws.emit("response", {"value": f"{cwd}># "}, namespace="/Shell")
+ return list, id_list
+ except FileNotFoundError:
+ print(f"找不到命令: {command}")
+ ws.emit("response", {"value": f"找不到命令: {command}"}, namespace="/Shell")
+ return list, id_list
diff --git a/app/utils/Config.py b/app/utils/Config.py
index 091c8fb4fa278548da57ebdfc4747b7c2a58d426..650311296157462170b6375128af0ea8a886d1d0 100644
--- a/app/utils/Config.py
+++ b/app/utils/Config.py
@@ -9,6 +9,12 @@ def get_config():
with open(file_path, "r") as json_file:
# 使用 json 模块的 load() 方法将 JSON 数据解析为 Python 对象
json_data = json.load(json_file)
+ file_path = "./data/config/ssh.json"
+ # 打开 JSON 文件并读取数据
+ with open(file_path, "r") as json_file:
+ # 使用 json 模块的 load() 方法将 JSON 数据解析为 Python 对象
+ json_data1 = json.load(json_file)
+ json_data["ssh_config"] = json_data1
# 打印 JSON 对象
return json_data
diff --git a/app/utils/File.py b/app/utils/File.py
index d4207c38332b6b053742fbb538a08ac5d1239c2c..520acfe7abf610f1a10c6ee887b481cd3681322f 100644
--- a/app/utils/File.py
+++ b/app/utils/File.py
@@ -1,4 +1,9 @@
import os
+import json
+import time
+import stat
+import ntsecuritycon
+
def Had(path):
@@ -27,6 +32,7 @@ def Add(path, text):
except Exception as e:
return False
+
def Del(path):
file_path = path
# 检查文件是否存在
@@ -37,6 +43,7 @@ def Del(path):
else:
return False
+
def Read(path):
if Had(path):
with open(path, 'r') as f:
@@ -45,11 +52,14 @@ def Read(path):
else:
return False
+
def SetAuthority(path, system):
if system == "Windows":
- import subprocess
+ import win32file
+ import win32security
+ """import subprocess
# 构建命令
- command = ['icacls', path, '/grant', '*S-1-5-32-544:(OI)(CI)F']
+ command = ['icacls', path, '/grant', 'administrators:(F)', '/deny', 'Everyone:(RD)']
# 执行命令
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
@@ -59,9 +69,86 @@ def SetAuthority(path, system):
if process.returncode == 0:
print("文件权限设置成功")
else:
- print("文件权限设置失败:", error.decode('utf-8'))
- return False
+ print("文件权限设置失败:", error)
+ return False"""
+ # 获取管理员权限SID
+ admins_sid = win32security.LookupAccountName("", "Administrators")[0]
+ filename = path
+ # 打开现有文件对象
+ file_handle = win32file.CreateFile(
+ filename,
+ win32file.GENERIC_READ | win32file.GENERIC_WRITE,
+ win32file.FILE_SHARE_READ | win32file.FILE_SHARE_WRITE,
+ None,
+ win32file.OPEN_EXISTING,
+ win32file.FILE_ATTRIBUTE_NORMAL,
+ None
+ )
+
+ # 获取文件的安全描述符
+ security_descriptor = win32security.GetFileSecurity(filename, win32security.DACL_SECURITY_INFORMATION)
+
+ # 创建新的DACL,并添加允许访问的ACE
+ dacl = win32security.ACL()
+ dacl.AddAccessAllowedAce(win32security.ACL_REVISION, ntsecuritycon.FILE_ALL_ACCESS, admins_sid)
+
+ # 更新文件的安全描述符中的DACL
+ security_descriptor.SetSecurityDescriptorDacl(1, dacl, 0)
+
+ # 设置文件的安全描述符
+ win32security.SetFileSecurity(filename, win32security.DACL_SECURITY_INFORMATION, security_descriptor)
else:
# 设置文件权限为root可读写,其它用户无法读写
os.chmod("./data/config/panel.json", 0o600)
+
+def get_file_info(path):
+ file_info = {
+ "type": None,
+ "path": path,
+ "name": os.path.basename(path),
+ "auth": None,
+ "size": None,
+ "time": None
+ }
+
+ if os.path.isfile(path):
+ file_info["type"] = "file"
+ file_info["size"] = os.path.getsize(path)
+ elif os.path.isdir(path):
+ file_info["type"] = "folder"
+
+ # Get permissions
+ try:
+ if os.name == 'nt': # Windows
+ import win32security
+ security_info = win32security.GetFileSecurity(path, win32security.OWNER_SECURITY_INFORMATION)
+ owner_sid = security_info.GetSecurityDescriptorOwner()
+ file_info["auth"] = str(owner_sid) # Convert PySID to string
+ else: # Unix/Linux
+ file_info["auth"] = oct(os.stat(path).st_mode)[-3:]
+ except Exception as e:
+ file_info["auth"] = str(e)
+
+ # Get last modified time
+ try:
+ file_info["time"] = time.ctime(os.path.getmtime(path))
+ except Exception as e:
+ file_info["time"] = str(e)
+
+ return file_info
+
+
+def get_directory_tree(root_path):
+ directory_tree = []
+ for item in os.listdir(root_path):
+ item_path = os.path.join(root_path, item)
+ directory_tree.append(get_file_info(item_path))
+
+ # print(directory_tree)
+ return directory_tree
+
+"""path = "/your/path/here"
+json_data = json.dumps(get_directory_tree(path), indent=4)
+print(json_data)"""
+
diff --git a/app/utils/Route.py b/app/utils/Route.py
index 5402c254b78e0bf44d07ee0449a1ca18844fd445..08183db94d1c782bf75baa7075395f3232ecc58b 100644
--- a/app/utils/Route.py
+++ b/app/utils/Route.py
@@ -4,7 +4,7 @@ from flask import render_template, send_from_directory, request, session, abort,
from app.controller import Api
import subprocess
-from app.utils import Cmd
+from app.utils import Shell
list = {}
id_list = {}
@@ -48,6 +48,9 @@ def get_route(app, cfg, ROOT_PATH, ws):
@app.route("/safe")
@app.route("/shell")
@app.route("/soft")
+ @app.route("/set")
+ @app.route("/file")
+ @app.route("/safe/port")
def home():
return send_from_directory(os.getcwd() + "/vue/dist", "index.html")
@@ -76,12 +79,12 @@ def get_route(app, cfg, ROOT_PATH, ws):
@app.route('/api/', methods=['POST', 'GET'])
def api_controller(path):
- return Api.service(path, cfg, request.data)
+ return Api.service(path, cfg, request.data, request)
# 出现消息后,率先执行此处
@ws.on("message", namespace="/Shell")
def socket(message):
- global list, id_list
+ global list
if cfg["safe_entry"] not in str(request.path):
if "username" in session and "pw" in session:
@@ -114,11 +117,11 @@ def get_route(app, cfg, ROOT_PATH, ws):
ws.emit("response", {"value": "\n[shell] # "}, namespace="/Shell")
else:
- list, id_list = Cmd.run_command(command, ws, id, list=list, id_list=id_list)
- print(list, id_list)
+ list = Shell.Shell(command, ws, id, list=list)
+ print(list)
else:
- list, id_list = Cmd.run_command(command, ws, id, list=list, id_list=id_list)
- print(list, id_list)
+ list= Shell.Shell(command, ws, id, list=list)
+ print(list)
# 当websocket连接成功时,自动触发connect默认方法
@ws.on("connect", namespace="/Shell")
diff --git a/app/utils/Shell.py b/app/utils/Shell.py
new file mode 100644
index 0000000000000000000000000000000000000000..edb7f83a15bbf5a2b240e785e7d8c73520d84c51
--- /dev/null
+++ b/app/utils/Shell.py
@@ -0,0 +1,47 @@
+import paramiko
+import time
+import _thread
+from app.utils import Config
+
+cfg = Config.get_config()["ssh_config"]
+hostname = cfg['ip']
+port = cfg['port']
+username = cfg['name']
+password = cfg['pw']
+timeout = 10
+
+web_socket = None
+chan = None
+
+def recvThread(): # 开启一个多线程负责读取返回信息
+ global chan
+ global web_socket
+ while True:
+ while chan.recv_ready():
+ info = chan.recv(1024).decode('utf-8')
+ web_socket.emit("response", {"value": info}, namespace="/Shell")
+ time.sleep(0.1)
+
+
+
+def Shell(command, ws, id, list):
+ global web_socket
+ global chan
+ web_socket = ws
+ if id not in list:
+ ssh = paramiko.SSHClient()
+ ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+ ssh.connect(hostname, port, username, password)
+ chan = ssh.invoke_shell() # 创建一个交互式的shell窗口
+ chan.settimeout(1000)
+ _thread.start_new_thread(recvThread, ())
+ list[id] = chan
+ else:
+ chan = list[id]
+ time.sleep(0.5)
+
+ """if command == 'quitshell':
+ print('Bye Bye!')
+ exit(0)"""
+ list[id].send(command + '\n')
+ return list
\ No newline at end of file
diff --git a/app/utils/System.py b/app/utils/System.py
index ef44b40bc1647779dba670f204f5312651bd1da3..522055e3998a72008902ea247da883f210f1cf05 100644
--- a/app/utils/System.py
+++ b/app/utils/System.py
@@ -85,37 +85,61 @@ def set_firewall_rule(port, system, status, protocol, source_ip=None):
def get_firewall_rules(system):
if system == "Linux":
- # 在Linux下使用iptables获取防火墙规则
- result = subprocess.run(['iptables', '-L', '-n'], capture_output=True, text=True)
- firewall_rules = result.stdout
+ try:
+ # 调用 iptables 命令获取端口规则信息
+ output = subprocess.check_output('iptables -L INPUT -n --line-numbers', shell=True)
+
+ # 将输出按行分割
+ output_lines = output.decode('utf-8').splitlines()
+
+ # 解析规则信息
+ rules = []
+ for line in output_lines[2:]:
+ rule_info = line.split()
+ if len(rule_info) >= 6:
+ rule = rule_info
+ rules.append(rule)
+
+ # 将规则信息转换为 JSON 格式
+ json_rules = json.dumps(rules, indent=4)
+ return json_rules
+
+ except Exception as e:
+ return f"An error occurred: {e}"
elif system == "Windows":
- # 在Windows下使用netsh获取防火墙规则
- result = os.popen('netsh advfirewall firewall show rule name=all').read()
- firewall_rules = repr(result)
+
+ try:
+ # 调用 netsh 命令获取防火墙规则信息
+ output = subprocess.check_output('netsh advfirewall firewall show rule name=all', shell=True)
+
+ # 将输出按行分割
+ output_lines = output.decode('gbk').splitlines()
+
+ # 解析规则信息
+ rules = []
+ current_rule = {}
+ for line in output_lines:
+ if line.strip() == '':
+ if current_rule:
+ rules.append(current_rule)
+ current_rule = {}
+ else:
+ key_value = line.split(':', 1)
+ if len(key_value) == 2:
+ key = key_value[0].strip()
+ value = key_value[1].strip()
+ current_rule[key] = value
+
+ # 将规则信息转换为 JSON 格式
+ json_rules = json.dumps(rules, ensure_ascii=False, indent=4)
+ return json_rules
+
+ except Exception as e:
+ return f"An error occurred: {e}"
else:
print("Unsupported system. Please specify either 'Linux' or 'Windows'.")
return
- # 解析获取到的规则数据
- rules_list = []
-
- def split_list_into_sublists(main_list, sublist_size):
- sublists = []
- for i in range(0, len(main_list), sublist_size):
- temp = []
- for j in main_list[i:i + sublist_size]:
- temp.append(j.replace("\n", "").replace(" ", ""))
- sublists.append(temp)
- return sublists
-
- sublists = split_list_into_sublists(re.sub(r'\s+', ' ', firewall_rules).split('\\n'), 13)
- # print(sublists)
- del sublists[0]
- del sublists[-1]
-
- # 将规则数据转换为JSON格式并返回
- return json.dumps(sublists, indent=4)
-
def off_system():
if get_system_name() == 'Windows':
os.system("shutdown /s /t 1")
diff --git a/app/utils/__pycache__/Cmd.cpython-38.pyc b/app/utils/__pycache__/Cmd.cpython-38.pyc
deleted file mode 100644
index b910fd4457874056c732d9ef85feee90a0cd281b..0000000000000000000000000000000000000000
Binary files a/app/utils/__pycache__/Cmd.cpython-38.pyc and /dev/null differ
diff --git a/app/utils/__pycache__/Config.cpython-38.pyc b/app/utils/__pycache__/Config.cpython-38.pyc
index 3dc2024d4148157d3653ea8d00db6038c68d3faf..cf7c4b5fdc0a4742570f1dba9d483ca9016bc981 100644
Binary files a/app/utils/__pycache__/Config.cpython-38.pyc and b/app/utils/__pycache__/Config.cpython-38.pyc differ
diff --git a/app/utils/__pycache__/File.cpython-36.pyc b/app/utils/__pycache__/File.cpython-36.pyc
deleted file mode 100644
index 9c7f40b307d40e6fe32b23b39e67780569408306..0000000000000000000000000000000000000000
Binary files a/app/utils/__pycache__/File.cpython-36.pyc and /dev/null differ
diff --git a/app/utils/__pycache__/File.cpython-38.pyc b/app/utils/__pycache__/File.cpython-38.pyc
index 9dd3710ddb44cd040aa3b3203f9286b9dd6170ab..cad08dc929eb1d8438dfc6ac6aa61397886bc376 100644
Binary files a/app/utils/__pycache__/File.cpython-38.pyc and b/app/utils/__pycache__/File.cpython-38.pyc differ
diff --git a/app/utils/__pycache__/Route.cpython-38.pyc b/app/utils/__pycache__/Route.cpython-38.pyc
index 07035e84ab1fa2b475da5a5cb260517111d3fc56..741fec94d96794d31dbbe4588d70932ec74ddfdd 100644
Binary files a/app/utils/__pycache__/Route.cpython-38.pyc and b/app/utils/__pycache__/Route.cpython-38.pyc differ
diff --git a/app/utils/__pycache__/Shell.cpython-38.pyc b/app/utils/__pycache__/Shell.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..4247babbfefef799f21cfd41d18fa87c05e29053
Binary files /dev/null and b/app/utils/__pycache__/Shell.cpython-38.pyc differ
diff --git a/app/utils/__pycache__/System.cpython-36.pyc b/app/utils/__pycache__/System.cpython-36.pyc
deleted file mode 100644
index edad6602355ff96ebf8b49996e0315bb9f75c7bb..0000000000000000000000000000000000000000
Binary files a/app/utils/__pycache__/System.cpython-36.pyc and /dev/null differ
diff --git a/app/utils/__pycache__/System.cpython-38.pyc b/app/utils/__pycache__/System.cpython-38.pyc
index a36b7c2828a7be7afbc19f350c19f7d782b68f39..46de71d7265661c7e3339f79eb0628f41d49772f 100644
Binary files a/app/utils/__pycache__/System.cpython-38.pyc and b/app/utils/__pycache__/System.cpython-38.pyc differ
diff --git a/build/main/localpycs/pyimod01_archive.pyc b/build/main/localpycs/pyimod01_archive.pyc
deleted file mode 100644
index fb4271d37666577da7d1345148c257cb40f82770..0000000000000000000000000000000000000000
Binary files a/build/main/localpycs/pyimod01_archive.pyc and /dev/null differ
diff --git a/build/main/localpycs/pyimod02_importers.pyc b/build/main/localpycs/pyimod02_importers.pyc
deleted file mode 100644
index 67abbe05eb85a939f0131f7d500b09e2906c609f..0000000000000000000000000000000000000000
Binary files a/build/main/localpycs/pyimod02_importers.pyc and /dev/null differ
diff --git a/build/main/localpycs/pyimod03_ctypes.pyc b/build/main/localpycs/pyimod03_ctypes.pyc
deleted file mode 100644
index 4a02029a66bc3048477caa3a1f6000fbf20ee408..0000000000000000000000000000000000000000
Binary files a/build/main/localpycs/pyimod03_ctypes.pyc and /dev/null differ
diff --git a/build/main/localpycs/pyimod04_pywin32.pyc b/build/main/localpycs/pyimod04_pywin32.pyc
deleted file mode 100644
index 16a54b73900578bb142fa4d1c076b66a0f38e678..0000000000000000000000000000000000000000
Binary files a/build/main/localpycs/pyimod04_pywin32.pyc and /dev/null differ
diff --git a/build/main/localpycs/struct.pyc b/build/main/localpycs/struct.pyc
deleted file mode 100644
index 22ee72eda3a46ebf9086725901fe3e0b5dc0b979..0000000000000000000000000000000000000000
Binary files a/build/main/localpycs/struct.pyc and /dev/null differ
diff --git a/input.py b/input.py
deleted file mode 100644
index 3b715ce634b16722e7123bb7943c0365b2337661..0000000000000000000000000000000000000000
--- a/input.py
+++ /dev/null
@@ -1,3 +0,0 @@
-print("hello")
-a = input("test")
-print(a)
\ No newline at end of file
diff --git a/main.py b/main.py
index 391240cc5060288f346570568afddb214f18d5b4..9d6dacfc1d89c2d68fe205abc3cf4bd36a7d8417 100644
--- a/main.py
+++ b/main.py
@@ -1,8 +1,8 @@
import ctypes
import subprocess
import psutil
-import app.controller.install as paninstall
from app.controller import index
+from app.controller import Install
from app.utils import Log
from app.utils import System
from app.utils import File
@@ -13,35 +13,43 @@ LOCK_FILE = "running.lock"
ROOT_PATH = os.getcwd()
Log.New("----------------启动程序----------------")
+
+
+# 检查权限
+def check_permission():
+ if System.get_system_name() == "Linux":
+ if os.getuid() != 0:
+ Log.New("exit: Use ROOT to run")
+ print("请使用ROOT用户运行此程序")
+ else:
+ try:
+ # 使用 ctypes.windll.shell32.IsUserAnAdmin 来检查当前用户是否是管理员
+ if ctypes.windll.shell32.IsUserAnAdmin() == 0:
+ Log.New("exit: Use Admin to run")
+ sys.exit("请使用管理员用户运行此程序")
+ except AttributeError:
+ # 如果 IsUserAnAdmin 函数不可用,则当前系统不支持该方法,因此返回 False
+ Log.New("exit: Use Admin to run")
+ sys.exit("请使用管理员用户运行此程序")
+
+
# 工作函数
def main():
if File.Had("data/config/panel.json"):
print("欢迎使用QPanel服务器管理面板")
+ check_permission() # 检查权限
print("正在启动面板...")
Log.New("Start QPanel")
print("------------------------------------")
index.service_start(ROOT_PATH)
else:
print("未安装面板")
- if System.get_system_name() == "Linux":
- if os.getuid() != 0:
- Log.New("exit: Use ROOT to run")
- print("请使用ROOT用户运行此程序")
- else:
- try:
- # 使用 ctypes.windll.shell32.IsUserAnAdmin 来检查当前用户是否是管理员
- if ctypes.windll.shell32.IsUserAnAdmin() == 0:
- Log.New("exit: Use Admin to run")
- sys.exit("请使用管理员用户运行此程序")
- except AttributeError:
- # 如果 IsUserAnAdmin 函数不可用,则当前系统不支持该方法,因此返回 False
- Log.New("exit: Use Admin to run")
- sys.exit("请使用管理员用户运行此程序")
- install = input("是否安装面板(y/n):")
- if install == "y":
+ check_permission() # 检查权限
+ input_install = input("是否安装面板(y/n):")
+ if input_install == "y":
# 安装面板
print("开始安装面板...")
- if paninstall.install():
+ if Install.PanelInstall(ROOT_PATH):
print("安装成功")
Log.New("Install True")
# 获取当前可执行文件的路径
@@ -61,16 +69,13 @@ def main():
print("退出程序")
-if System.get_system_name() == "Linux":
- pass
-else:
+if System.get_system_name() == "Windows":
import win32file
import win32con
import pywintypes
import winerror
import sys
-
class SingleInstanceGuardian:
def __init__(self, lock_file_path):
self._lock_file_path = lock_file_path
@@ -126,7 +131,7 @@ if (len(sys.argv) > 1 and sys.argv[1] == "start") or len(sys.argv) == 1:
if File.Had('./pid.txt'):
pid = File.Read('./pid.txt')
pid_info = System.get_process_info(int(pid))
- if pid_info != False:
+ if pid_info:
if pid_info["status"] == "running":
print("程序已经在运行中")
sys.exit(1)
@@ -175,7 +180,7 @@ elif len(sys.argv) > 1 and sys.argv[1] == "stop":
if File.Had('./pid.txt'):
pid = File.Read('./pid.txt')
pid_info = System.get_process_info(int(pid))
- if pid_info != False:
+ if pid_info:
if pid_info["status"] == "running":
print("程序已经在运行中")
try:
@@ -192,7 +197,7 @@ elif len(sys.argv) > 1 and sys.argv[1] == "stop":
guardian._release_lock()
elif len(sys.argv) > 1 and sys.argv[1] == "run":
- if(System.get_system_name() == "Linux"):
+ if System.get_system_name() == "Linux":
subprocess.run(['bash', 'run.sh'])
else:
subprocess.run(['cscript', '//NoLogo', 'run.vbs'])
diff --git a/pid.txt b/pid.txt
index b5f4b30d27f7dc045bfb1c63b44ee28734fc4e1c..bad03301d2dc107e5b254ca2d031b4a35cc2dfaa 100644
--- a/pid.txt
+++ b/pid.txt
@@ -1 +1 @@
-18972
\ No newline at end of file
+19748
\ No newline at end of file
diff --git a/ping.py b/ping.py
deleted file mode 100644
index a98f78fa349c57c1cfcb468db4d40e02d4b3590d..0000000000000000000000000000000000000000
--- a/ping.py
+++ /dev/null
@@ -1,52 +0,0 @@
-import subprocess
-
-def execute_command(command):
- process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, universal_newlines=True)
- return process
-
-def main():
- current_directory = '.' # 初始目录为当前目录
-
- while True:
- user_input = input("[shell] 输入命令 (输入 exit 退出): ")
-
- # 如果用户输入 "exit",则退出程序
- if user_input.lower() == "exit":
- break
-
- # 获取当前命令
- command = user_input.strip()
-
- # 如果是 cd 命令,则更新当前目录
- if command.startswith('cd '):
- directory = command.split(' ', 1)[-1].strip() # 获取 cd 命令后面的目录
- try:
- # 尝试切换目录
- subprocess.Popen(f'cd "{directory}"', shell=True).communicate()
- current_directory = directory
- except Exception as e:
- print(f"无法切换到目录 '{directory}':{e}")
- continue
-
- # 在当前目录执行命令
- process = execute_command(f'cd "{current_directory}" && {command}')
-
- # 实时打印命令的输出
- while True:
- output = process.stdout.readline() # 读取输出流
- if output == '' and process.poll() is not None: # 没有新的输出并且进程已经结束
- break
- if output:
- print(output.strip()) # 打印输出
- process.stdout.close()
-
- # 从终端输入并传递给子进程
- user_input = input() # 获取用户输入
- if user_input.lower() == "exit":
- process.terminate() # 终止子进程
- break
- process.stdin.write(user_input + '\n') # 将用户输入传递给子进程
- process.stdin.flush() # 刷新输入流
-
-# 执行主程序
-main()
diff --git a/run.bat b/run.bat
index 00549404b8cb25f2003825afb9615a84b749ff52..a55ebcc6f3ebf00a95a0a100f8895471d11b24a7 100644
--- a/run.bat
+++ b/run.bat
@@ -1 +1,2 @@
-start /B main.py
\ No newline at end of file
+cd "C:\Users\PKK-1\Desktop\program\StarBit\code\quick-panel"
+"C:\Users\PKK-1\Desktop\program\StarBit\code\quick-panel\main.exe"
\ No newline at end of file
diff --git a/run.vbs b/run.vbs
index 9d8604ca71dac8116426aea30a33f294832991e7..620661a02beb50be384fa392fcb46d6981f0444f 100644
--- a/run.vbs
+++ b/run.vbs
@@ -1,2 +1,8 @@
-Set ws = CreateObject("Wscript.Shell")
-ws.run "cmd /c run.bat",0
+
+Set ws = CreateObject("WScript.Shell")
+
+' лָĿ¼
+ws.CurrentDirectory = "C:\Users\PKK-1\Desktop\program\StarBit\code\quick-panel"
+
+' run.bat
+ws.Run "run.bat", 0, True'
\ No newline at end of file
diff --git a/templates/p/shell.html b/templates/p/shell.html
index 8c517cfffbf16ecf51612484592feb34488294e5..5ff063be6e2dffec54407b70ea11704157916c2e 100644
--- a/templates/p/shell.html
+++ b/templates/p/shell.html
@@ -11,68 +11,41 @@
-
-