Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
C
coco
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ops
coco
Commits
d403c73b
Commit
d403c73b
authored
Oct 10, 2018
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Update] 支持命令过滤
parent
fd13430e
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
148 additions
and
367 deletions
+148
-367
app.py
coco/app.py
+0
-5
char.py
coco/char.py
+1
-0
auth.py
coco/httpd/auth.py
+3
-2
view.py
coco/httpd/view.py
+2
-0
models.py
coco/models.py
+96
-40
session.py
coco/session.py
+4
-0
sshd.py
coco/sshd.py
+1
-1
cocod
cocod
+8
-6
coco.mo
locale/en/LC_MESSAGES/coco.mo
+0
-0
coco.po
locale/en/LC_MESSAGES/coco.po
+12
-12
coco.po~
locale/en/LC_MESSAGES/coco.po~
+0
-137
coco.mo
locale/zh_CN/LC_MESSAGES/coco.mo
+0
-0
coco.po
locale/zh_CN/LC_MESSAGES/coco.po
+15
-15
coco.po~
locale/zh_CN/LC_MESSAGES/coco.po~
+0
-143
messages.sh
utils/messages.sh
+6
-6
No files found.
coco/app.py
View file @
d403c73b
...
...
@@ -2,11 +2,6 @@
# -*- coding: utf-8 -*-
#
import
eventlet
from
eventlet.debug
import
hub_prevent_multiple_readers
eventlet
.
monkey_patch
()
hub_prevent_multiple_readers
(
False
)
import
datetime
import
os
import
time
...
...
coco/char.py
View file @
d403c73b
...
...
@@ -5,6 +5,7 @@
BACKSPACE_CHAR
=
{
b
'
\x08
'
:
b
'
\x08\x1b
[K'
,
b
'
\x7f
'
:
b
'
\x08\x1b
[K'
}
ENTER_CHAR
=
[
b
'
\r
'
,
b
'
\n
'
,
b
'
\r\n
'
]
ENTER_CHAR_ORDER
=
[
ord
(
b
'
\r
'
),
ord
(
b
'
\n
'
)]
CLEAR_LINE_CHAR
=
b
'
\x15
'
UNSUPPORTED_CHAR
=
{
b
'
\x15
'
:
'Ctrl-U'
,
b
'
\x0c
'
:
'Ctrl-L'
,
b
'
\x05
'
:
'Ctrl-E'
}
CLEAR_CHAR
=
b
'
\x1b
[H
\x1b
[2J'
BELL_CHAR
=
b
'
\x07
'
...
...
coco/httpd/auth.py
View file @
d403c73b
...
...
@@ -2,7 +2,7 @@
#
from
functools
import
wraps
from
flask
import
request
,
abort
from
flask
import
request
,
abort
,
redirect
from
..ctx
import
app_service
...
...
@@ -23,7 +23,8 @@ def login_required(func):
user
=
app_service
.
check_user_cookie
(
session_id
,
csrf_token
)
request
.
current_user
=
user
if
not
hasattr
(
request
,
'current_user'
)
or
not
request
.
current_user
:
return
abort
(
403
)
url
=
'/users/login/?next={}'
.
format
(
request
.
path
)
return
redirect
(
url
)
response
=
func
(
*
args
,
**
kwargs
)
return
response
return
wrapper
coco/httpd/view.py
View file @
d403c73b
...
...
@@ -50,11 +50,13 @@ def sftp_host_connector_view(host):
@app.route
(
'/coco/elfinder/sftp/<host>/'
)
@login_required
def
sftp_host_finder
(
host
):
return
render_template
(
'elfinder/file_manager.html'
,
host
=
host
)
@app.route
(
'/coco/elfinder/sftp/'
)
@login_required
def
sftp_finder
():
return
render_template
(
'elfinder/file_manager.html'
,
host
=
'_'
)
...
...
coco/models.py
View file @
d403c73b
...
...
@@ -4,7 +4,9 @@ import weakref
import
uuid
import
socket
from
.service
import
app_service
from
.struct
import
SizedList
,
SelectEvent
from
.utils
import
wrap_with_line_feed
as
wr
,
wrap_with_warning
as
warning
from
.
import
char
from
.
import
utils
...
...
@@ -140,6 +142,11 @@ class Client:
return
"<
%
s from
%
s:
%
s>"
%
(
self
.
user
,
self
.
addr
[
0
],
self
.
addr
[
1
])
class
ServerFilter
:
def
run
(
self
,
data
):
pass
class
BaseServer
:
"""
Base Server
...
...
@@ -147,18 +154,23 @@ class BaseServer:
sub-class: Server, Telnet Server
"""
def
__init__
(
self
):
self
.
chan
=
None
def
__init__
(
self
,
chan
=
None
):
self
.
chan
=
chan
self
.
_session_ref
=
None
self
.
input_data
=
SizedList
(
maxsize
=
1024
)
self
.
output_data
=
SizedList
(
maxsize
=
1024
)
self
.
_pre_input_state
=
True
self
.
_in_input_state
=
True
self
.
_input_initial
=
False
self
.
_enter_vim_mark
=
b
'
\x1b
[?25l
\x1b
[37;1H
\x1b
[1m'
self
.
_exit_vim_mark
=
b
'
\x1b
[37;1H
\x1b
[K
\x1b
'
self
.
_in_vim_state
=
False
self
.
input_data
=
SizedList
(
maxsize
=
1024
)
self
.
output_data
=
SizedList
(
maxsize
=
1024
)
self
.
_input
=
""
self
.
_output
=
""
self
.
_session_ref
=
None
self
.
_zmodem_recv_start_mark
=
b
'rz waiting to receive.**
\x18
B0100'
self
.
_zmodem_send_start_mark
=
b
'**
\x18
B00000000000000'
self
.
_zmodem_cancel_mark
=
b
'
\x18\x18\x18\x18\x18
'
...
...
@@ -167,6 +179,15 @@ class BaseServer:
self
.
_zmodem_state_recv
=
'recv'
self
.
_zmodem_state
=
''
self
.
_cmd_parser
=
utils
.
TtyIOParser
()
self
.
_cmd_filter_rules
=
self
.
get_system_user_cmd_filter_rules
()
def
get_system_user_cmd_filter_rules
(
self
):
rules
=
app_service
.
get_system_user_cmd_filter_rules
(
self
.
system_user
.
id
)
return
rules
def
set_session
(
self
,
session
):
self
.
_session_ref
=
weakref
.
ref
(
session
)
...
...
@@ -177,51 +198,79 @@ class BaseServer:
else
:
return
None
def
initial_filter
(
self
):
def
s_initial_filter
(
self
,
data
):
if
not
self
.
_input_initial
:
self
.
_input_initial
=
True
return
data
def
parse_cmd
_filter
(
self
,
data
):
# 输入了回车键, 开始计算输入的内容
if
self
.
_
have_enter_char
(
data
)
:
def
s_input_state
_filter
(
self
,
data
):
self
.
_pre_input_state
=
self
.
_in_input_state
if
self
.
_
in_vim_state
:
self
.
_in_input_state
=
False
self
.
_input
=
self
.
_parse_input
()
# 输入了回车键
elif
self
.
_have_enter_char
(
data
):
self
.
_in_input_state
=
False
else
:
self
.
_in_input_state
=
True
return
data
# 用户输入了内容,但是如果没在输入状态,也就是用户刚开始输入了,结算上次输出内容
def
s_parse_input_output_filter
(
self
,
data
):
# 输入了回车键, 计算输入的命令
if
not
self
.
_in_input_state
:
self
.
_input
=
self
.
_parse_input
()
# 用户输入了内容,但是上次没在输入状态,也就是用户刚开始输入了,结算上次输出内容
if
not
self
.
_pre_input_state
and
self
.
_in_input_state
:
self
.
_output
=
self
.
_parse_output
()
logger
.
debug
(
"
\n
{}
\n
Input: {}
\n
Output: {}
\n
{}"
.
format
(
"#"
*
30
+
" Command "
+
"#"
*
30
,
self
.
_input
,
self
.
_output
,
"#"
*
30
+
" End "
+
"#"
*
30
,
))
#
logger.debug("\n{}\nInput: {}\nOutput: {}\n{}".format(
#
"#" * 30 + " Command " + "#" * 30,
#
self._input, self._output,
#
"#" * 30 + " End " + "#" * 30,
#
))
if
self
.
_input
:
self
.
session
.
put_command
(
self
.
_input
,
self
.
_output
)
self
.
input_data
.
clean
()
self
.
output_data
.
clean
()
self
.
_in_input_state
=
True
return
data
def
send
(
self
,
data
):
self
.
initial_filter
()
self
.
parse_cmd_filter
(
data
)
return
self
.
chan
.
send
(
data
)
def
s_filter_cmd_filter
(
self
,
data
):
if
self
.
_in_input_state
:
return
data
for
rule
in
self
.
_cmd_filter_rules
:
action
,
msg
=
rule
.
match
(
self
.
_input
)
if
action
==
rule
.
DENY
:
data
=
char
.
CLEAR_LINE_CHAR
+
b
'
\r
'
msg
=
wr
(
warning
(
msg
.
encode
()),
before
=
1
,
after
=
0
)
self
.
output_data
.
append
(
msg
)
self
.
session
.
send_to_clients
(
msg
)
elif
action
==
rule
.
ACCEPT
:
break
return
data
def
replay_filter
(
self
,
data
):
def
r
_r
eplay_filter
(
self
,
data
):
if
not
self
.
_zmodem_state
:
self
.
session
.
put_replay
(
data
)
def
input_output_filter
(
self
,
data
):
def
r_vim_state_filter
(
self
,
data
):
if
self
.
_zmodem_state
:
return
data
if
self
.
_in_vim_state
and
data
[:
11
]
==
self
.
_exit_vim_mark
:
self
.
_in_vim_state
=
False
elif
not
self
.
_in_vim_state
and
data
[:
17
]
==
self
.
_enter_vim_mark
:
self
.
_in_vim_state
=
True
return
data
def
r_input_output_data_filter
(
self
,
data
):
if
not
self
.
_input_initial
:
return
return
data
if
self
.
_zmodem_state
:
return
return
data
if
self
.
_in_input_state
:
self
.
input_data
.
append
(
data
)
else
:
self
.
output_data
.
append
(
data
)
return
data
def
zmodem_state_filter
(
self
,
data
):
def
r_
zmodem_state_filter
(
self
,
data
):
if
not
self
.
_zmodem_state
:
if
data
[:
50
]
.
find
(
self
.
_zmodem_recv_start_mark
)
!=
-
1
:
logger
.
debug
(
"Zmodem state => recv"
)
...
...
@@ -237,18 +286,29 @@ class BaseServer:
logger
.
debug
(
"Zmodem state => cancel"
)
self
.
_zmodem_state
=
''
def
zmodem_cancel_filter
(
self
):
def
r_zmodem_disable_filter
(
self
,
data
=
''
):
if
self
.
_zmodem_state
:
pass
# self.chan.send(self._zmodem_cancel_mark)
# self.chan.send("Zmodem disabled")
def
send
(
self
,
data
):
self
.
s_initial_filter
(
data
)
self
.
s_input_state_filter
(
data
)
try
:
self
.
s_parse_input_output_filter
(
data
)
data
=
self
.
s_filter_cmd_filter
(
data
)
except
Exception
as
e
:
logger
.
exception
(
e
)
return
self
.
chan
.
send
(
data
)
def
recv
(
self
,
size
):
data
=
self
.
chan
.
recv
(
size
)
self
.
zmodem_state_filter
(
data
)
self
.
zmodem_cancel_filter
()
self
.
replay_filter
(
data
)
self
.
input_output_filter
(
data
)
self
.
r_zmodem_state_filter
(
data
)
self
.
r_vim_state_filter
(
data
)
self
.
r_zmodem_disable_filter
(
data
)
self
.
r_replay_filter
(
data
)
self
.
r_input_output_data_filter
(
data
)
return
data
@staticmethod
...
...
@@ -261,21 +321,19 @@ class BaseServer:
def
_parse_output
(
self
):
if
not
self
.
output_data
:
return
''
parser
=
utils
.
TtyIOParser
()
return
parser
.
parse_output
(
self
.
output_data
)
return
self
.
_cmd_parser
.
parse_output
(
self
.
output_data
)
def
_parse_input
(
self
):
if
not
self
.
input_data
:
return
parser
=
utils
.
TtyIOParser
()
return
parser
.
parse_input
(
self
.
input_data
)
return
self
.
_cmd_parser
.
parse_input
(
self
.
input_data
)
def
fileno
(
self
):
return
self
.
chan
.
fileno
()
def
close
(
self
):
logger
.
info
(
"Closed server {}"
.
format
(
self
))
self
.
input_output
_filter
(
b
''
)
self
.
r_input_output_data
_filter
(
b
''
)
self
.
chan
.
close
()
def
__getattr__
(
self
,
item
):
...
...
@@ -290,10 +348,9 @@ class TelnetServer(BaseServer):
Telnet server
"""
def
__init__
(
self
,
sock
,
asset
,
system_user
):
super
(
TelnetServer
,
self
)
.
__init__
()
self
.
chan
=
sock
self
.
asset
=
asset
self
.
system_user
=
system_user
super
(
TelnetServer
,
self
)
.
__init__
(
chan
=
sock
)
class
Server
(
BaseServer
):
...
...
@@ -306,11 +363,10 @@ class Server(BaseServer):
# Todo: Server name is not very suitable
def
__init__
(
self
,
chan
,
sock
,
asset
,
system_user
):
super
(
Server
,
self
)
.
__init__
()
self
.
chan
=
chan
self
.
sock
=
sock
self
.
asset
=
asset
self
.
system_user
=
system_user
super
(
Server
,
self
)
.
__init__
(
chan
=
chan
)
def
close
(
self
):
super
()
.
close
()
...
...
coco/session.py
View file @
d403c73b
...
...
@@ -147,6 +147,10 @@ class Session:
pass
self
.
stop_evt
.
set
()
def
send_to_clients
(
self
,
data
):
for
watcher
in
[
self
.
client
]
+
self
.
_watchers
+
self
.
_sharers
:
watcher
.
send
(
data
)
def
bridge
(
self
):
"""
Bridge clients with server
...
...
coco/sshd.py
View file @
d403c73b
...
...
@@ -90,7 +90,7 @@ class SSHServer:
continue
if
not
server
.
event
.
is_set
():
logger
.
warning
(
"Client not request
a valid request
, exiting"
)
logger
.
warning
(
"Client not request
invalid
, exiting"
)
sock
.
close
()
return
else
:
...
...
cocod
View file @
d403c73b
...
...
@@ -2,6 +2,11 @@
# -*- coding: utf-8 -*-
#
import
eventlet
from
eventlet.debug
import
hub_prevent_multiple_readers
eventlet
.
monkey_patch
()
hub_prevent_multiple_readers
(
False
)
import
os
import
sys
import
argparse
...
...
@@ -16,12 +21,9 @@ except ImportError:
print
(
"Please prepare config file `cp conf_example.py conf.py`"
)
sys
.
exit
(
1
)
try
:
os
.
mkdir
(
"logs"
)
os
.
mkdir
(
"keys"
)
os
.
mkdir
(
"sessions"
)
except
:
pass
dirs
=
(
'logs'
,
'keys'
,
'sessions'
)
for
d
in
dirs
:
os
.
makedirs
(
d
,
exist_ok
=
True
)
BASE_DIR
=
os
.
path
.
dirname
(
os
.
path
.
abspath
(
__file__
))
DAEMON
=
False
...
...
locale/en/LC_MESSAGES/coco.mo
View file @
d403c73b
No preview for this file type
locale/en/LC_MESSAGES/coco.po
View file @
d403c73b
...
...
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-
09-03 10:39
+0800\n"
"POT-Creation-Date: 2018-
10-10 15:22
+0800\n"
"PO-Revision-Date: 2018-08-10 10:42+0800\n"
"Last-Translator: BaiJiangjie <bugatti_it@163.com>\n"
"Language-Team: Language locale/en/LC\n"
...
...
@@ -16,7 +16,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: coco/app.py:14
7
#: coco/app.py:14
1
msgid "Connect idle more than {} minutes, disconnect"
msgstr ""
...
...
@@ -91,44 +91,44 @@ msgstr ""
msgid "Total: {}"
msgstr ""
#: coco/interactive.py:1
59
#: coco/interactive.py:1
61
msgid "There is no matched node, please re-enter"
msgstr ""
#: coco/interactive.py:17
0
#: coco/interactive.py:17
2
msgid "ID"
msgstr ""
#: coco/interactive.py:17
0
#: coco/interactive.py:17
2
msgid "Hostname"
msgstr ""
#: coco/interactive.py:17
0
#: coco/interactive.py:17
2
msgid "IP"
msgstr ""
#: coco/interactive.py:17
0
#: coco/interactive.py:17
2
msgid "LoginAs"
msgstr ""
#: coco/interactive.py:18
4
#: coco/interactive.py:18
6
msgid "Comment"
msgstr ""
#: coco/interactive.py:19
2
#: coco/interactive.py:19
4
msgid "Total: {} Match: {}"
msgstr ""
#: coco/interactive.py:23
5
#: coco/interactive.py:23
7
msgid "Select a login:: "
msgstr ""
#: coco/interactive.py:2
58
#: coco/interactive.py:2
60
msgid ""
"Terminal does not support login Windows, please use web terminal to access"
msgstr ""
#: coco/interactive.py:2
69
#: coco/interactive.py:2
71
msgid "No system user"
msgstr ""
...
...
locale/en/LC_MESSAGES/coco.po~
deleted
100644 → 0
View file @
fd13430e
# Language locale/en/LC translations for PACKAGE package.
# Copyright (C) 2018 THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# BaiJiangjie <bugatti_it@163.com>, 2018.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-09-03 10:36+0800\n"
"PO-Revision-Date: 2018-08-10 10:42+0800\n"
"Last-Translator: BaiJiangjie <bugatti_it@163.com>\n"
"Language-Team: Language locale/en/LC\n"
"Language: locale/en/LC_MESSAGES/coco\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: coco/app.py:147
msgid "Connect idle more than {} minutes, disconnect"
msgstr ""
#: coco/interactive.py:61
#, python-brace-format
msgid ""
"\n"
"{T}{T}{title} {user}, Welcome to use Jumpserver open source fortress system "
"{end}{R}{R}"
msgstr ""
#: coco/interactive.py:63
#, python-brace-format
msgid ""
"{T}1) Enter {green}ID{end} directly login or enter {green}part IP, Hostname, "
"Comment{end} to search login(if unique).{R}"
msgstr ""
#: coco/interactive.py:64
#, python-brace-format
msgid ""
"{T}2) Enter {green}/{end} + {green}IP, Hostname{end} or {green}Comment {end} "
"search, such as: /ip.{R}"
msgstr ""
#: coco/interactive.py:65
#, python-brace-format
msgid "{T}3) Enter {green}p{end} to display the host you have permission.{R}"
msgstr ""
#: coco/interactive.py:66
#, python-brace-format
msgid ""
"{T}4) Enter {green}g{end} to display the node that you have permission.{R}"
msgstr ""
#: coco/interactive.py:67
#, python-brace-format
msgid ""
"{T}5) Enter {green}g{end} + {green}Group ID{end} to display the host under "
"the node, such as g1.{R}"
msgstr ""
#: coco/interactive.py:68
#, python-brace-format
msgid "{T}6) Enter {green}s{end} Chinese-english switch.{R}"
msgstr ""
#: coco/interactive.py:69
#, python-brace-format
msgid "{T}7) Enter {green}h{end} help.{R}"
msgstr ""
#: coco/interactive.py:70
#, python-brace-format
msgid "{T}0) Enter {green}q{end} exit.{R}"
msgstr ""
#: coco/interactive.py:142
msgid "No"
msgstr ""
#: coco/interactive.py:149
msgid "Name"
msgstr ""
#: coco/interactive.py:149
msgid "Assets"
msgstr ""
#: coco/interactive.py:155
msgid "Total: {}"
msgstr ""
#: coco/interactive.py:159
msgid "There is no matched node, please re-enter"
msgstr ""
#: coco/interactive.py:170
msgid "ID"
msgstr ""
#: coco/interactive.py:170
msgid "Hostname"
msgstr ""
#: coco/interactive.py:170
msgid "IP"
msgstr ""
#: coco/interactive.py:170
msgid "LoginAs"
msgstr ""
#: coco/interactive.py:184
msgid "Comment"
msgstr ""
#: coco/interactive.py:192
msgid "Total: {} Match: {}"
msgstr ""
#: coco/interactive.py:235
msgid "Select a login:: "
msgstr ""
#: coco/interactive.py:258
msgid ""
"Terminal does not support login Windows, please use web terminal to access"
msgstr ""
#: coco/interactive.py:269
msgid "No system user"
msgstr ""
#: coco/session.py:143
msgid "Terminated by administrator"
msgstr ""
locale/zh_CN/LC_MESSAGES/coco.mo
View file @
d403c73b
No preview for this file type
locale/zh_CN/LC_MESSAGES/coco.po
View file @
d403c73b
...
...
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-
09-03 10:39
+0800\n"
"POT-Creation-Date: 2018-
10-10 15:22
+0800\n"
"PO-Revision-Date: 2018-08-10 10:42+0800\n"
"Last-Translator: BaiJiangjie <bugatti_it@163.com>\n"
"Language-Team: Language locale/zh\n"
...
...
@@ -16,7 +16,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: coco/app.py:14
7
#: coco/app.py:14
1
msgid "Connect idle more than {} minutes, disconnect"
msgstr "空闲时间超过 {} 分钟,断开连接"
...
...
@@ -77,9 +77,9 @@ msgid "{T}7) Enter {green}h{end} help.{R}"
msgstr "{T}7) 输入 {green}h{end} 帮助.{R}"
#: coco/interactive.py:70
#,
fuzzy,
python-brace-format
#, python-brace-format
msgid "{T}0) Enter {green}q{end} exit.{R}"
msgstr "{T}0) 输入 {green}q{end} 退出.{R}
\n
"
msgstr "{T}0) 输入 {green}q{end} 退出.{R}"
#: coco/interactive.py:142
msgid "No"
...
...
@@ -97,44 +97,44 @@ msgstr "资产"
msgid "Total: {}"
msgstr "总共: {}"
#: coco/interactive.py:1
59
#: coco/interactive.py:1
61
msgid "There is no matched node, please re-enter"
msgstr "没有匹配分组,请重新输入"
#: coco/interactive.py:17
0
#: coco/interactive.py:17
2
msgid "ID"
msgstr ""
#: coco/interactive.py:17
0
#: coco/interactive.py:17
2
msgid "Hostname"
msgstr "主机名"
#: coco/interactive.py:17
0
#: coco/interactive.py:17
2
msgid "IP"
msgstr ""
#: coco/interactive.py:17
0
#: coco/interactive.py:17
2
msgid "LoginAs"
msgstr ""
msgstr "
登录用户
"
#: coco/interactive.py:18
4
#: coco/interactive.py:18
6
msgid "Comment"
msgstr "备注"
#: coco/interactive.py:19
2
#: coco/interactive.py:19
4
msgid "Total: {} Match: {}"
msgstr "总共: {} 匹配: {}"
#: coco/interactive.py:23
5
#: coco/interactive.py:23
7
msgid "Select a login:: "
msgstr "选择一个登录:"
#: coco/interactive.py:2
58
#: coco/interactive.py:2
60
msgid ""
"Terminal does not support login Windows, please use web terminal to access"
msgstr "终端不支持登录windows, 请使用web terminal访问"
#: coco/interactive.py:2
69
#: coco/interactive.py:2
71
msgid "No system user"
msgstr "没有系统用户"
...
...
locale/zh_CN/LC_MESSAGES/coco.po~
deleted
100644 → 0
View file @
fd13430e
# Language locale/zh translations for PACKAGE package.
# Copyright (C) 2018 THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# BaiJiangjie <bugatti_it@163.com>, 2018.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-09-03 10:36+0800\n"
"PO-Revision-Date: 2018-08-10 10:42+0800\n"
"Last-Translator: BaiJiangjie <bugatti_it@163.com>\n"
"Language-Team: Language locale/zh\n"
"Language: locale/zh_CN/LC_MESSAGES/coco\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: coco/app.py:147
msgid "Connect idle more than {} minutes, disconnect"
msgstr "空闲时间超过 {} 分钟,断开连接"
#: coco/interactive.py:61
#, python-brace-format
msgid ""
"\n"
"{T}{T}{title} {user}, Welcome to use Jumpserver open source fortress system "
"{end}{R}{R}"
msgstr ""
"\n"
"{T}{T}{title} {user}, 欢迎使用Jumpserver开源跳板机系统 {end}{R}{R}"
#: coco/interactive.py:63
#, python-brace-format
msgid ""
"{T}1) Enter {green}ID{end} directly login or enter {green}part IP, Hostname, "
"Comment{end} to search login(if unique).{R}"
msgstr ""
"{T}1) 输入 {green}ID{end} 直接登录 或 输入{green}部分 IP,主机名,备注{end} 进"
"行搜索登录(如果唯一).{R}"
#: coco/interactive.py:64
#, python-brace-format
msgid ""
"{T}2) Enter {green}/{end} + {green}IP, Hostname{end} or {green}Comment {end} "
"search, such as: /ip.{R}"
msgstr ""
"{T}2) 输入 {green}/{end} + {green}IP, 主机名{end} or {green}备注 {end}搜索. "
"如: /ip{R}"
#: coco/interactive.py:65
#, python-brace-format
msgid "{T}3) Enter {green}p{end} to display the host you have permission.{R}"
msgstr "{T}3) 输入 {green}p{end} 显示您有权限的主机.{R}"
#: coco/interactive.py:66
#, python-brace-format
msgid ""
"{T}4) Enter {green}g{end} to display the node that you have permission.{R}"
msgstr "{T}4) 输入 {green}g{end} 显示您有权限的节点.{R}"
#: coco/interactive.py:67
#, python-brace-format
msgid ""
"{T}5) Enter {green}g{end} + {green}Group ID{end} to display the host under "
"the node, such as g1.{R}"
msgstr "{T}5) 输入 {green}g{end} + {green}组ID{end} 显示节点下主机. 如: g1{R}"
#: coco/interactive.py:68
#, python-brace-format
msgid "{T}6) Enter {green}s{end} Chinese-english switch.{R}"
msgstr "{T}6) 输入 {green}s{end} 中/英文切换.{R}"
#: coco/interactive.py:69
#, python-brace-format
msgid "{T}7) Enter {green}h{end} help.{R}"
msgstr "{T}7) 输入 {green}h{end} 帮助.{R}"
#: coco/interactive.py:70
#, fuzzy, python-brace-format
msgid "{T}0) Enter {green}q{end} exit.{R}"
msgstr "{T}0) 输入 {green}q{end} 退出.{R}\n"
#: coco/interactive.py:142
msgid "No"
msgstr "无"
#: coco/interactive.py:149
msgid "Name"
msgstr "名称"
#: coco/interactive.py:149
msgid "Assets"
msgstr "资产"
#: coco/interactive.py:155
msgid "Total: {}"
msgstr "总共: {}"
#: coco/interactive.py:159
msgid "There is no matched node, please re-enter"
msgstr "没有匹配分组,请重新输入"
#: coco/interactive.py:170
msgid "ID"
msgstr ""
#: coco/interactive.py:170
msgid "Hostname"
msgstr "主机名"
#: coco/interactive.py:170
msgid "IP"
msgstr ""
#: coco/interactive.py:170
msgid "LoginAs"
msgstr ""
#: coco/interactive.py:184
msgid "Comment"
msgstr "备注"
#: coco/interactive.py:192
msgid "Total: {} Match: {}"
msgstr "总共: {} 匹配: {}"
#: coco/interactive.py:235
msgid "Select a login:: "
msgstr "选择一个登录:"
#: coco/interactive.py:258
msgid ""
"Terminal does not support login Windows, please use web terminal to access"
msgstr "终端不支持登录windows, 请使用web terminal访问"
#: coco/interactive.py:269
msgid "No system user"
msgstr "没有系统用户"
#: coco/session.py:143
msgid "Terminated by administrator"
msgstr "被管理员中断"
utils/messages.sh
View file @
d403c73b
...
...
@@ -2,15 +2,15 @@
#
function
init_message
()
{
xgettext
-k_
-o
pot
/coco.pot
--from-code
=
UTF-8 coco/
*
.py
msginit
-l
locale/zh_CN/LC_MESSAGES/coco
-i
pot
/coco.pot
msginit
-l
locale/en/LC_MESSAGES/coco
-i
pot
/coco.pot
xgettext
-k_
-o
/tmp
/coco.pot
--from-code
=
UTF-8 coco/
*
.py
msginit
-l
locale/zh_CN/LC_MESSAGES/coco
-i
/tmp
/coco.pot
msginit
-l
locale/en/LC_MESSAGES/coco
-i
/tmp
/coco.pot
}
function
make_message
()
{
xgettext
-k_
-o
pot
/coco.pot
--from-code
=
UTF-8 coco/
*
.py
msgmerge
-U
locale/zh_CN/LC_MESSAGES/coco.po
pot
/coco.pot
msgmerge
-U
locale/en/LC_MESSAGES/coco.po
pot
/coco.pot
xgettext
-k_
-o
/tmp
/coco.pot
--from-code
=
UTF-8 coco/
*
.py
msgmerge
-U
locale/zh_CN/LC_MESSAGES/coco.po
/tmp
/coco.pot
msgmerge
-U
locale/en/LC_MESSAGES/coco.po
/tmp
/coco.pot
}
function
compile_message
()
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment