mirror of
https://github.com/midoks/mdserver-web.git
synced 2026-10-18 23:45:52 +08:00
update
This commit is contained in:
@@ -3,10 +3,12 @@
|
||||
import sys
|
||||
import io
|
||||
import os
|
||||
from route import app
|
||||
from route import app, socketio
|
||||
|
||||
try:
|
||||
if __name__ == "__main__":
|
||||
app.run()
|
||||
PORT = 7200
|
||||
HOST = '0.0.0.0'
|
||||
socketio.run(app, host=HOST, port=PORT)
|
||||
except Exception as ex:
|
||||
print ex
|
||||
|
||||
@@ -851,3 +851,34 @@ def get_string_arr(t):
|
||||
if s1 == s_arr[i][j]:
|
||||
t_arr.append(str(i) + str(j))
|
||||
return t_arr
|
||||
|
||||
|
||||
def getSSHPort():
|
||||
try:
|
||||
file = '/etc/ssh/sshd_config'
|
||||
conf = ReadFile(file)
|
||||
rep = "#*Port\s+([0-9]+)\s*\n"
|
||||
port = re.search(rep, conf).groups(0)[0]
|
||||
return int(port)
|
||||
except:
|
||||
return 22
|
||||
|
||||
|
||||
def getSSHStatus():
|
||||
if os.path.exists('/usr/bin/apt-get'):
|
||||
status = execShell("service ssh status | grep -P '(dead|stop)'")
|
||||
else:
|
||||
import system_api
|
||||
version = system_api.system_api().getSystemVersion()
|
||||
if version.find(' Mac ') != -1:
|
||||
return True
|
||||
if version.find(' 7.') != -1:
|
||||
status = execShell("systemctl status sshd.service | grep 'dead'")
|
||||
else:
|
||||
status = execShell(
|
||||
"/etc/init.d/sshd status | grep -e 'stopped' -e '已停'")
|
||||
if len(status[0]) > 3:
|
||||
status = False
|
||||
else:
|
||||
status = True
|
||||
return status
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
<script type="text/javascript">
|
||||
|
||||
resetPluginWinWidth(480);
|
||||
$.getScript( "/plugins/file?name=webssh&f=js/webssh.js", function() {
|
||||
if ($(".term-box #term").text() != 'W') {
|
||||
layer.closeAll();
|
||||
webShell();
|
||||
web_shell2();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
// if ($(".term-box #term").text() != 'W') {
|
||||
// layer.closeAll();
|
||||
// web_shell();
|
||||
// }
|
||||
</script>
|
||||
@@ -1,6 +1,6 @@
|
||||
function web_shell() {
|
||||
var termCols = 100;
|
||||
var termRows = 29;
|
||||
function web_shell2() {
|
||||
var termCols = 50;
|
||||
var termRows = 12;
|
||||
var sendTotal = 0;
|
||||
if(!socket)socket = io.connect();
|
||||
var term = new Terminal({ cols: termCols, rows: termRows, screenKeys: true, useStyle: true});
|
||||
@@ -9,6 +9,7 @@ function web_shell() {
|
||||
term.setOption('cursorBlink', true);
|
||||
|
||||
socket.on('server_response', function (data) {
|
||||
console.log('server_response',data);
|
||||
term.write(data.data);
|
||||
|
||||
if (data.data == '\r\n登出\r\n' || data.data == '登出\r\n' || data.data == '\r\nlogout\r\n' || data.data == 'logout\r\n') {
|
||||
@@ -26,6 +27,7 @@ function web_shell() {
|
||||
}
|
||||
|
||||
term.on('data', function (data) {
|
||||
console.log('data',data);
|
||||
socket.emit('webssh', data);
|
||||
});
|
||||
|
||||
@@ -33,7 +35,7 @@ function web_shell() {
|
||||
var term_box = layer.open({
|
||||
type: 1,
|
||||
title: "宝塔终端",
|
||||
area: ['920px','640px'],
|
||||
area: ['480px','360px'],
|
||||
closeBtn: 2,
|
||||
shadeClose: false,
|
||||
content: '<div class="term-box"><div id="term"></div></div>\
|
||||
@@ -109,9 +111,6 @@ function web_shell() {
|
||||
<li>\
|
||||
<a onclick="shell_paste_text()" '+ paste_str+'>粘贴选中项</a>\
|
||||
</li>\
|
||||
<li>\
|
||||
<a onclick="shell_translate_text()" ' + style_str + '>翻译</a>\
|
||||
</li>\
|
||||
<li>\
|
||||
<a onclick="shell_to_baidu()" ' + style_str + '>百度搜索</a>\
|
||||
</li>\
|
||||
@@ -166,17 +165,6 @@ function web_shell() {
|
||||
|
||||
}
|
||||
|
||||
function shell_translate_text() {
|
||||
remove_ssh_menu();
|
||||
var selectText = getCookie('ssh_selection');
|
||||
var loadT = layer.msg('正在翻译...', { icon: 16, time: 1000 * 60, });
|
||||
$.get('https://www.bt.cn/api/index/fanyi', { query: selectText }, function (rdata) {
|
||||
layer.close(loadT);
|
||||
layer.msg("原文: " + rdata.src + '<br>译文: ' + rdata.dst, { time: 1000 * 10, shadeClose: true, shade: 0.01 });
|
||||
}, 'JSONP');
|
||||
gterm.focus();
|
||||
}
|
||||
|
||||
function shell_to_baidu() {
|
||||
var selectText = getCookie('ssh_selection');
|
||||
remove_ssh_menu();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
flask
|
||||
flask_session
|
||||
flask_socketio
|
||||
gunicorn
|
||||
psutil
|
||||
pillow
|
||||
|
||||
+117
-1
@@ -10,6 +10,7 @@ import uuid
|
||||
reload(sys)
|
||||
sys.setdefaultencoding('utf8')
|
||||
|
||||
|
||||
from datetime import timedelta
|
||||
|
||||
from flask import Flask
|
||||
@@ -23,18 +24,25 @@ from flask import url_for
|
||||
|
||||
from flask_session import Session
|
||||
|
||||
|
||||
sys.path.append(os.getcwd() + "/class/core")
|
||||
import db
|
||||
import public
|
||||
import config_api
|
||||
|
||||
|
||||
app = Flask(__name__, template_folder='templates/default')
|
||||
app.config.version = config_api.config_api().getVersion()
|
||||
# app.config['SECRET_KEY'] = os.urandom(24)
|
||||
# app.secret_key = uuid.UUID(int=uuid.getnode()).hex[-12:]
|
||||
app.config['SECRET_KEY'] = uuid.UUID(int=uuid.getnode()).hex[-12:]
|
||||
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=7)
|
||||
|
||||
# socketio
|
||||
sys.path.append("/usr/local/lib/python2.7/site-packages")
|
||||
from flask_socketio import SocketIO, emit, send
|
||||
socketio = SocketIO()
|
||||
socketio.init_app(app)
|
||||
|
||||
try:
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/py_mw_session.db'
|
||||
@@ -195,3 +203,111 @@ def index(reqClass=None, reqAction=None, reqData=None):
|
||||
eval_str = "__import__('" + className + "')." + className + '()'
|
||||
newInstance = eval(eval_str)
|
||||
return publicObject(newInstance, reqAction)
|
||||
|
||||
ssh = None
|
||||
shell = None
|
||||
try:
|
||||
import paramiko
|
||||
ssh = paramiko.SSHClient()
|
||||
except:
|
||||
public.execShell('pip install paramiko==2.0.2 &')
|
||||
|
||||
|
||||
def connect_ssh():
|
||||
global shell, ssh
|
||||
print 'connect_ssh'
|
||||
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
try:
|
||||
ssh.connect('127.0.0.1', public.getSSHPort())
|
||||
except Exception as e:
|
||||
print 'connect_ssh:', str(e)
|
||||
if public.getSSHStatus():
|
||||
try:
|
||||
ssh.connect('localhost', public.getSSHPort())
|
||||
except:
|
||||
return False
|
||||
import firewalls
|
||||
fw = firewalls.firewalls()
|
||||
get = common.dict_obj()
|
||||
get.status = '0'
|
||||
fw.SetSshStatus(get)
|
||||
ssh.connect('127.0.0.1', public.GetSSHPort())
|
||||
get.status = '1'
|
||||
fw.SetSshStatus(get)
|
||||
shell = ssh.invoke_shell(term='xterm', width=100, height=29)
|
||||
shell.setblocking(0)
|
||||
return True
|
||||
|
||||
|
||||
# 取数据对象
|
||||
def get_input_data(data):
|
||||
pdata = common.dict_obj()
|
||||
for key in data.keys():
|
||||
pdata[key] = str(data[key])
|
||||
return pdata
|
||||
|
||||
|
||||
@socketio.on('webssh')
|
||||
def webssh(msg):
|
||||
emit('server_response', {'data': '会话丢失,请重新登陆面板!\r\n'})
|
||||
print 'webssh', msg
|
||||
if not isLogined():
|
||||
emit('server_response', {'data': '会话丢失,请重新登陆面板!\r\n'})
|
||||
return None
|
||||
global shell, ssh
|
||||
ssh_success = True
|
||||
if not shell:
|
||||
ssh_success = connect_ssh()
|
||||
if not shell:
|
||||
emit('server_response', {
|
||||
'data': public.getMsg('INIT_WEBSSH_CONN_ERR')})
|
||||
return
|
||||
if shell.exit_status_ready():
|
||||
ssh_success = connect_ssh()
|
||||
if not ssh_success:
|
||||
emit('server_response', {
|
||||
'data': public.getMsg('INIT_WEBSSH_CONN_ERR')})
|
||||
return
|
||||
shell.send(msg)
|
||||
try:
|
||||
time.sleep(0.005)
|
||||
recv = shell.recv(4096)
|
||||
emit('server_response', {'data': recv.decode("utf-8")})
|
||||
except Exception as ex:
|
||||
pass
|
||||
|
||||
|
||||
@socketio.on('connect_event')
|
||||
def connected_msg(msg):
|
||||
connect_ssh()
|
||||
if not isLogined():
|
||||
print 'not login'
|
||||
emit(pdata.s_response, {'data': public.getMsg('INIT_WEBSSH_LOGOUT')})
|
||||
return None
|
||||
global shell, ssh
|
||||
print 'connect_event:connected_msg', msg
|
||||
try:
|
||||
recv = shell.recv(8192)
|
||||
print recv
|
||||
print recv.decode("utf-8")
|
||||
emit('server_response', {'data': recv.decode("utf-8")})
|
||||
except Exception as e:
|
||||
print 'connect_event:' + str(e)
|
||||
|
||||
|
||||
@socketio.on('panel')
|
||||
def websocket_test(data):
|
||||
pdata = get_input_data(data)
|
||||
if not isLogined():
|
||||
emit(pdata.s_response, {
|
||||
'data': public.returnData(-1, '会话丢失,请重新登陆面板!\r\n')})
|
||||
return None
|
||||
mods = ['site', 'ftp', 'database', 'ajax', 'system', 'crontab', 'files',
|
||||
'config', 'panel_data', 'plugin', 'ssl', 'auth', 'firewall', 'panel_wxapp']
|
||||
if not pdata['s_module'] in mods:
|
||||
result = public.returnMsg(False, "INIT_WEBSOCKET_ERR")
|
||||
else:
|
||||
result = eval("%s(pdata)" % pdata['s_module'])
|
||||
if not hasattr(pdata, 's_response'):
|
||||
pdata.s_response = 'response'
|
||||
emit(pdata.s_response, {'data': result})
|
||||
|
||||
+21
-28
@@ -1201,12 +1201,14 @@ function loadImage(){
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var socket, gterm;
|
||||
function webShell() {
|
||||
var termCols = 100;
|
||||
var termRows = 29;
|
||||
var termCols = 50;
|
||||
var termRows = 12;
|
||||
var sendTotal = 0;
|
||||
if(!socket)socket = io.connect();
|
||||
if(!socket){
|
||||
socket = io.connect();
|
||||
}
|
||||
var term = new Terminal({ cols: termCols, rows: termRows, screenKeys: true, useStyle: true});
|
||||
term.open();
|
||||
gterm = term
|
||||
@@ -1236,8 +1238,8 @@ function webShell() {
|
||||
|
||||
var term_box = layer.open({
|
||||
type: 1,
|
||||
title: "宝塔终端",
|
||||
area: ['920px','640px'],
|
||||
title: "本地终端",
|
||||
area: ['480px','300px'],
|
||||
closeBtn: 2,
|
||||
shadeClose: false,
|
||||
content: '<div class="term-box"><div id="term"></div></div>\
|
||||
@@ -1307,18 +1309,9 @@ function webShell() {
|
||||
|
||||
|
||||
var menudiv = '<ul class="contextmenu">\
|
||||
<li>\
|
||||
<a class="shell_copy_btn menu_ssh" data-clipboard-text="'+ selectText + '" ' + style_str + '>复制到剪切板</a>\
|
||||
</li>\
|
||||
<li>\
|
||||
<a onclick="shell_paste_text()" '+ paste_str+'>粘贴选中项</a>\
|
||||
</li>\
|
||||
<li>\
|
||||
<a onclick="shell_translate_text()" ' + style_str + '>翻译</a>\
|
||||
</li>\
|
||||
<li>\
|
||||
<a onclick="shell_to_baidu()" ' + style_str + '>百度搜索</a>\
|
||||
</li>\
|
||||
<li><a class="shell_copy_btn menu_ssh" data-clipboard-text="'+ selectText + '" ' + style_str + '>复制到剪切板</a></li>\
|
||||
<li><a onclick="shell_paste_text()" '+ paste_str+'>粘贴选中项</a></li>\
|
||||
<li><a onclick="shell_to_baidu()" ' + style_str + '>百度搜索</a></li>\
|
||||
</ul>';
|
||||
$("body").append(menudiv);
|
||||
$(".contextmenu").css({
|
||||
@@ -1370,16 +1363,16 @@ function webShell() {
|
||||
|
||||
}
|
||||
|
||||
function shell_translate_text() {
|
||||
remove_ssh_menu();
|
||||
var selectText = getCookie('ssh_selection');
|
||||
var loadT = layer.msg('正在翻译...', { icon: 16, time: 1000 * 60, });
|
||||
$.get('https://www.bt.cn/api/index/fanyi', { query: selectText }, function (rdata) {
|
||||
layer.close(loadT);
|
||||
layer.msg("原文: " + rdata.src + '<br>译文: ' + rdata.dst, { time: 1000 * 10, shadeClose: true, shade: 0.01 });
|
||||
}, 'JSONP');
|
||||
gterm.focus();
|
||||
}
|
||||
// function shell_translate_text() {
|
||||
// remove_ssh_menu();
|
||||
// var selectText = getCookie('ssh_selection');
|
||||
// var loadT = layer.msg('正在翻译...', { icon: 16, time: 1000 * 60, });
|
||||
// $.get('https://www.bt.cn/api/index/fanyi', { query: selectText }, function (rdata) {
|
||||
// layer.close(loadT);
|
||||
// layer.msg("原文: " + rdata.src + '<br>译文: ' + rdata.dst, { time: 1000 * 10, shadeClose: true, shade: 0.01 });
|
||||
// }, 'JSONP');
|
||||
// gterm.focus();
|
||||
// }
|
||||
|
||||
function shell_to_baidu() {
|
||||
var selectText = getCookie('ssh_selection');
|
||||
|
||||
@@ -4646,4 +4646,34 @@ select[disabled]{
|
||||
}
|
||||
.btswitch-btn.bt-waf-firewall{
|
||||
width:2.4em;height:1.4em;margin-bottom: 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*6.0终端样式*/
|
||||
.term-box{
|
||||
padding:0 10px 10px;
|
||||
background-color:#333333;
|
||||
}
|
||||
.shell-text-input .bt-input-text-shell{
|
||||
width:100%;
|
||||
padding:10px 10px 0;
|
||||
border:0 none;
|
||||
height:60px;
|
||||
overflow:auto;
|
||||
resize:none;
|
||||
}
|
||||
.shell-text-input .bt-input-text-shell:focus,.shell-text-input .bt-input-text-shell:active{
|
||||
border:0 none;
|
||||
outline:none;
|
||||
}
|
||||
.shell-btn-group{
|
||||
height:30px;
|
||||
position:absolute;
|
||||
bottom:10px;
|
||||
right:10px;
|
||||
}
|
||||
.shell_btn_close{
|
||||
margin-right:8px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -39,15 +39,23 @@
|
||||
</div>
|
||||
</div>
|
||||
<button style="display: none;" id="bt_copys" class="bt_copy" data-clipboard-text=""></button>
|
||||
<link rel="stylesheet" href="/static/build/xterm.css?v={{config.version}}">
|
||||
<link rel="stylesheet" href="/static/build/addons/fullscreen/fullscreen.css?v={{config.version}}">
|
||||
<script src="/static/js/jquery-1.10.2.min.js?v={{config.version}}"></script>
|
||||
<script src="/static/js/bootstrap.min.js?v={{config.version}}"></script>
|
||||
<script src="/static/layer/layer.js?v={{config.version}}"></script>
|
||||
<script src="/static/js/jquery.fly.min.js?v={{config.version}}"></script>
|
||||
<script src="/static/js/clipboard.min.js?v={{config.version}}"></script>
|
||||
<script src="/static/build/xterm.js?v={{config.version}}"></script>
|
||||
<script src="/static/build/addons/attach/attach.js?v={{config.version}}"></script>
|
||||
<script src="/static/build/addons/fit/fit.js?v={{config.version}}"></script>
|
||||
<script src="/static/build/addons/fullscreen/fullscreen.js?v={{config.version}}"></script>
|
||||
<script src="/static/js/socket.io.min.js?v={{config.version}}"></script>
|
||||
<script src="/static/build/addons/winptyCompat/winptyCompat.js?v={{config.version}}"></script>
|
||||
<script src="/static/app/public.js?v={{config.version}}"></script>
|
||||
<script src="/static/js/echarts.min.js?v={{config.version}}"></script>
|
||||
<script type="text/javascript" src="/static/js/jquery.dragsort-0.5.2.min.js?v={{config.version}}"></script>
|
||||
<script src="/static/js/socket.io.min.js?v={{config.version}}"></script>
|
||||
<script src="/static/js/jquery.dragsort-0.5.2.min.js?v={{config.version}}"></script>
|
||||
|
||||
{% block content %}{% endblock %}
|
||||
<div class="footer bgw">mdserver-web ©2018-∞ 面板 (<a style="color:#20a53a;" target="_blank" href="//github.com/midoks/mdserver-web">源码</a>)<a style="margin-left:20px;color:#20a53a;" href="//github.com/midoks/mdserver-web/wiki/mdserver-web" target="_blank">wiki</a>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user