Commit b5221652 authored by ibuler's avatar ibuler

[Update] 优化coco中文显示

parent 0755d134
...@@ -19,7 +19,6 @@ logger = get_logger(__file__) ...@@ -19,7 +19,6 @@ logger = get_logger(__file__)
class BaseNamespace(Namespace): class BaseNamespace(Namespace):
clients = None
current_user = None current_user = None
def on_connect(self): def on_connect(self):
...@@ -39,12 +38,6 @@ class BaseNamespace(Namespace): ...@@ -39,12 +38,6 @@ class BaseNamespace(Namespace):
user = app_service.check_user_with_token(token) user = app_service.check_user_with_token(token)
return user return user
def close(self):
try:
self.clients[request.sid]["client"].close()
except IndexError:
pass
class ProxyNamespace(BaseNamespace): class ProxyNamespace(BaseNamespace):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
...@@ -235,13 +228,6 @@ class ProxyNamespace(BaseNamespace): ...@@ -235,13 +228,6 @@ class ProxyNamespace(BaseNamespace):
del self.connections[request.sid][room_id] del self.connections[request.sid][room_id]
del room del room
@staticmethod
def on_error_default(e):
traceback.print_exc()
logger.warn(e)
error_handler = on_error_default
class HttpServer: class HttpServer:
# prepare may be rewrite it # prepare may be rewrite it
...@@ -264,13 +250,17 @@ class HttpServer: ...@@ -264,13 +250,17 @@ class HttpServer:
self.flask_app.config.update(config) self.flask_app.config.update(config)
self.socket_io = SocketIO() self.socket_io = SocketIO()
self.register_routes() self.register_routes()
self.add_error_handler()
def register_routes(self): def register_routes(self):
self.socket_io.on_namespace(ProxyNamespace('/ssh')) self.socket_io.on_namespace(ProxyNamespace('/ssh'))
def add_error_handler(self): @staticmethod
self.socket_io.on_error_default(ProxyNamespace.on_error_default) def on_error_default(e):
traceback.print_exc()
logger.warn(e)
def register_error_handler(self):
self.socket_io.on_error_default(self.on_error_default)
def run(self): def run(self):
host = self.flask_app.config["BIND_HOST"] host = self.flask_app.config["BIND_HOST"]
...@@ -282,4 +272,4 @@ class HttpServer: ...@@ -282,4 +272,4 @@ class HttpServer:
self.socket_io.run(self.flask_app, port=port, host=host, debug=False) self.socket_io.run(self.flask_app, port=port, host=host, debug=False)
def shutdown(self): def shutdown(self):
pass self.socket_io.server.close()
...@@ -12,7 +12,8 @@ from . import char ...@@ -12,7 +12,8 @@ from . import char
from .utils import wrap_with_line_feed as wr, wrap_with_title as title, \ from .utils import wrap_with_line_feed as wr, wrap_with_title as title, \
wrap_with_warning as warning, is_obj_attr_has, \ wrap_with_warning as warning, is_obj_attr_has, \
is_obj_attr_eq, sort_assets, TtyIOParser, \ is_obj_attr_eq, sort_assets, TtyIOParser, \
ugettext as _, get_logger, net_input ugettext as _, get_logger, net_input, format_with_zh, item_max_length, \
size_of_str_with_zh
from .ctx import current_app, app_service from .ctx import current_app, app_service
from .proxy import ProxyServer from .proxy import ProxyServer
...@@ -56,11 +57,11 @@ class InteractiveServer: ...@@ -56,11 +57,11 @@ class InteractiveServer:
banner = _("""\n {title} {user}, 欢迎使用Jumpserver开源跳板机系统 {end}\r\n\r banner = _("""\n {title} {user}, 欢迎使用Jumpserver开源跳板机系统 {end}\r\n\r
1) 输入 {green}ID{end} 直接登录 或 输入{green}部分 IP,主机名,备注{end} 进行搜索登录(如果唯一).\r 1) 输入 {green}ID{end} 直接登录 或 输入{green}部分 IP,主机名,备注{end} 进行搜索登录(如果唯一).\r
2) 输入 {green}/{end} + {green}IP, 主机名{end} or {green}备注 {end}搜索. 如: /ip\r 2) 输入 {green}/{end} + {green}IP, 主机名{end} or {green}备注 {end}搜索. 如: /ip\r
3) 输入 {green}P/p{end} 显示您有权限的主机.\r 3) 输入 {green}p{end} 显示您有权限的主机.\r
4) 输入 {green}G/g{end} 显示您有权限的主机组.\r 4) 输入 {green}g{end} 显示您有权限的主机组.\r
5) 输入 {green}G/g{end} + {green}组ID{end} 显示该组下主机. 如: g1\r 5) 输入 {green}g{end} + {green}组ID{end} 显示该节点下主机. 如: g1\r
6) 输入 {green}H/h{end} 帮助.\r 6) 输入 {green}h{end} 帮助.\r
0) 输入 {green}Q/q{end} 退出.\r\n""").format( 0) 输入 {green}q{end} 退出.\r\n""").format(
title="\033[1;32m", green="\033[32m", title="\033[1;32m", green="\033[32m",
end="\033[0m", user=self.client.user end="\033[0m", user=self.client.user
) )
...@@ -123,17 +124,25 @@ class InteractiveServer: ...@@ -123,17 +124,25 @@ class InteractiveServer:
self.client.send(warning(_("无"))) self.client.send(warning(_("无")))
return return
fake_group = AssetGroup(name=_("Name"), assets_amount=_("Assets"), comment=_("Comment")) id_length = max(len(str(len(self.asset_groups))), 5)
id_max_length = max(len(str(len(self.asset_groups))), 5) name_length = item_max_length(self.asset_groups, 15, key=lambda x: x.name)
name_max_length = max(max([len(group.name) for group in self.asset_groups]), 15) amount_length = item_max_length(self.asset_groups, 10,
amount_max_length = max(len(str(max([group.assets_amount for group in self.asset_groups]))), 10) key=lambda x: x.assets_amount)
header = '{1:>%d} {0.name:%d} {0.assets_amount:<%s} ' % (id_max_length, name_max_length, amount_max_length) size_list = [id_length, name_length, amount_length]
comment_length = max(self.request.meta["width"] - len(header.format(fake_group, id_max_length)), 2) fake_data = ['ID', _("Name"), _("Assets")]
line = header + '{0.comment:%s}' % (comment_length // 2) # comment中可能有中文 header_without_comment = format_with_zh(size_list, *fake_data)
header += "{0.comment:%s}" % comment_length comment_length = max(
self.client.send(title(header.format(fake_group, "ID"))) self.request.meta["width"] -
size_of_str_with_zh(header_without_comment) - 1,
2
)
size_list.append(comment_length)
fake_data.append(_("Comment"))
self.client.send(title(format_with_zh(size_list, *fake_data)))
for index, group in enumerate(self.asset_groups, 1): for index, group in enumerate(self.asset_groups, 1):
self.client.send(wr(line.format(group, index))) data = [index, group.name, group.assets_amount, group.comment]
self.client.send(wr(format_with_zh(size_list, *data)))
self.client.send(wr(_("总共: {}").format(len(self.asset_groups)), before=1)) self.client.send(wr(_("总共: {}").format(len(self.asset_groups)), before=1))
def display_group_assets(self, _id): def display_group_assets(self, _id):
...@@ -146,21 +155,30 @@ class InteractiveServer: ...@@ -146,21 +155,30 @@ class InteractiveServer:
self.display_search_result() self.display_search_result()
def display_search_result(self): def display_search_result(self):
self.search_result = sort_assets(self.search_result, current_app.config["ASSET_LIST_SORT_BY"]) sort_by = current_app.config["ASSET_LIST_SORT_BY"]
fake_asset = Asset(hostname=_("Hostname"), ip=_("IP"), _system_users_name_list=_("LoginAs"), self.search_result = sort_assets(self.search_result, sort_by)
comment=_("Comment")) fake_data = [_("ID"), _("Hostname"), _("IP"), _("LoginAs")]
id_max_length = max(len(str(len(self.search_result))), 3) id_length = max(len(str(len(self.search_result))), 4)
hostname_max_length = max(max([len(asset.hostname) for asset in self.search_result + [fake_asset]]), 15) hostname_length = item_max_length(self.search_result, 15,
sysuser_max_length = max([len(asset.system_users_name_list) for asset in self.search_result + [fake_asset]]) key=lambda x: x.hostname)
header = '{1:>%d} {0.hostname:%d} {0.ip:15} {0.system_users_name_list:%d} ' % \ sysuser_length = item_max_length(self.search_result,
(id_max_length, hostname_max_length, sysuser_max_length) key=lambda x: x.system_users_name_list)
comment_length = self.request.meta["width"] - len(header.format(fake_asset, id_max_length)) size_list = [id_length, hostname_length, 16, sysuser_length]
comment_length = max([comment_length, 2]) header_without_comment = format_with_zh(size_list, *fake_data)
line = header + '{0.comment:.%d}' % (comment_length // 2) # comment中可能有中文 comment_length = max(
header += '{0.comment:%s}' % comment_length self.request.meta["width"] -
self.client.send(wr(title(header.format(fake_asset, "ID")))) size_of_str_with_zh(header_without_comment) - 1,
2
)
size_list.append(comment_length)
fake_data.append(_("Comment"))
self.client.send(wr(title(format_with_zh(size_list, *fake_data))))
for index, asset in enumerate(self.search_result, 1): for index, asset in enumerate(self.search_result, 1):
self.client.send(wr(line.format(asset, index))) data = [
index, asset.hostname, asset.ip,
asset.system_users_name_list, asset.comment
]
self.client.send(wr(format_with_zh(size_list, *data)))
self.client.send(wr(_("总共: {} 匹配: {}").format( self.client.send(wr(_("总共: {} 匹配: {}").format(
len(self.assets), len(self.search_result)), before=1) len(self.assets), len(self.search_result)), before=1)
) )
...@@ -242,7 +260,7 @@ class InteractiveServer: ...@@ -242,7 +260,7 @@ class InteractiveServer:
self.display_banner() self.display_banner()
while True: while True:
try: try:
opt = net_input(self.client) opt = net_input(self.client, prompt='Opt>', before=1)
rv = self.dispatch(opt) rv = self.dispatch(opt)
if rv is self._sentinel: if rv is self._sentinel:
break break
......
...@@ -294,27 +294,14 @@ def get_logger(file_name): ...@@ -294,27 +294,14 @@ def get_logger(file_name):
return logging.getLogger('coco.'+file_name) return logging.getLogger('coco.'+file_name)
zh_pattern = re.compile(u'[\u4e00-\u9fa5]+') def net_input(client, prompt='Opt> ', sensitive=False, before=0, after=0):
def len_display(s):
length = 0
for i in s:
if zh_pattern.match(i):
length += 2
else:
length += 1
return length
def net_input(client, prompt='Opt> ', sensitive=False):
"""实现了一个ssh input, 提示用户输入, 获取并返回 """实现了一个ssh input, 提示用户输入, 获取并返回
:return user input string :return user input string
""" """
input_data = [] input_data = []
parser = TtyIOParser() parser = TtyIOParser()
client.send(wrap_with_line_feed(prompt, before=0, after=0)) client.send(wrap_with_line_feed(prompt, before=before, after=after))
while True: while True:
data = client.recv(10) data = client.recv(10)
...@@ -377,11 +364,59 @@ def register_service(service): ...@@ -377,11 +364,59 @@ def register_service(service):
stack['service'] = service stack['service'] = service
def get_app(): zh_pattern = re.compile(r'[\u4e00-\u9fa5]')
if stack.get("app"):
return stack["app"]
else: def find_chinese(s):
return ValueError("No app found") return zh_pattern.findall(s)
def align_with_zh(s, length, addin=' '):
if not isinstance(s, str):
s = str(s)
zh_len = len(find_chinese(s))
padding = length - (len(s) - zh_len) - zh_len*2
padding_content = ''
if padding > 0:
padding_content = addin*padding
return s + padding_content
def format_with_zh(size_list, *args):
data = []
for length, s in zip(size_list, args):
data.append(align_with_zh(s, length))
return ' '.join(data)
def size_of_str_with_zh(s):
if isinstance(s, int):
s = str(s)
try:
chinese = find_chinese(s)
except TypeError:
print(type(s))
raise
return len(s) + len(chinese)
def item_max_length(_iter, maxi=None, mini=None, key=None):
if key:
_iter = [key(i) for i in _iter]
length = [size_of_str_with_zh(s) for s in _iter]
if maxi:
length.append(maxi)
length = max(length)
if mini and length < mini:
length = mini
return length
def int_length(i):
return len(str(i))
ugettext = _gettext() ugettext = _gettext()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment