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
0c3d0a45
Commit
0c3d0a45
authored
Oct 19, 2018
by
ibuler
Browse files
Options
Browse Files
Download
Plain Diff
merge
parents
9f053fba
eeeca2d8
Hide whitespace changes
Inline
Side-by-side
Showing
31 changed files
with
186 additions
and
410 deletions
+186
-410
__init__.py
coco/__init__.py
+1
-0
app.py
coco/app.py
+2
-13
char.py
coco/char.py
+1
-0
connection.py
coco/connection.py
+3
-2
ctx.py
coco/ctx.py
+0
-6
auth.py
coco/httpd/auth.py
+4
-3
base.py
coco/httpd/base.py
+1
-1
sftp.py
coco/httpd/elfinder/volumes/sftp.py
+1
-12
theme-gray.css
coco/httpd/static/plugins/elfinder/css/theme-gray.css
+7
-1
elfinder.zh_CN.js
coco/httpd/static/plugins/elfinder/i18n/elfinder.zh_CN.js
+1
-1
view.py
coco/httpd/view.py
+2
-0
ws.py
coco/httpd/ws.py
+1
-1
interactive.py
coco/interactive.py
+1
-1
interface.py
coco/interface.py
+1
-1
logger.py
coco/logger.py
+1
-1
models.py
coco/models.py
+106
-41
proxy.py
coco/proxy.py
+2
-1
recorder.py
coco/recorder.py
+1
-1
session.py
coco/session.py
+5
-1
sftp.py
coco/sftp.py
+1
-1
sshd.py
coco/sshd.py
+1
-1
tasks.py
coco/tasks.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
requirements.txt
requirements/requirements.txt
+1
-1
messages.sh
utils/messages.sh
+6
-6
No files found.
coco/__init__.py
View file @
0c3d0a45
...
...
@@ -2,4 +2,5 @@
# -*- coding: utf-8 -*-
#
from
.
import
logger
from
.app
import
Coco
coco/app.py
View file @
0c3d0a45
...
...
@@ -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
...
...
@@ -17,16 +12,15 @@ import signal
from
.config
import
config
from
.sshd
import
SSHServer
from
.httpd
import
HttpServer
from
.logger
import
create_logger
from
.tasks
import
TaskHandler
from
.utils
import
get_logger
,
ugettext
as
_
,
ignore_error
from
.
ctx
import
app_service
from
.
service
import
app_service
from
.recorder
import
get_replay_recorder
from
.session
import
Session
from
.models
import
Connection
__version__
=
'1.4.
1
'
__version__
=
'1.4.
3
'
BASE_DIR
=
os
.
path
.
dirname
(
os
.
path
.
dirname
(
__file__
))
logger
=
get_logger
(
__file__
)
...
...
@@ -61,9 +55,6 @@ class Coco:
self
.
_task_handler
=
TaskHandler
()
return
self
.
_task_handler
def
make_logger
(
self
):
create_logger
()
@staticmethod
def
load_extra_conf_from_server
():
configs
=
app_service
.
load_config_from_server
()
...
...
@@ -73,8 +64,6 @@ class Coco:
config
.
update
(
configs
)
def
bootstrap
(
self
):
self
.
make_logger
()
# app_service.initial()
self
.
load_extra_conf_from_server
()
self
.
keep_heartbeat
()
self
.
monitor_sessions
()
...
...
coco/char.py
View file @
0c3d0a45
...
...
@@ -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/connection.py
View file @
0c3d0a45
...
...
@@ -10,7 +10,7 @@ import telnetlib
import
paramiko
from
paramiko.ssh_exception
import
SSHException
from
.
ctx
import
app_service
from
.
service
import
app_service
from
.config
import
config
from
.utils
import
get_logger
,
get_private_key_fingerprint
...
...
@@ -22,7 +22,8 @@ AUTO_LOGIN = 'auto'
class
SSHConnection
:
def
get_system_user_auth
(
self
,
system_user
):
@staticmethod
def
get_system_user_auth
(
system_user
):
"""
获取系统用户的认证信息,密码或秘钥
:return: system user have full info
...
...
coco/ctx.py
View file @
0c3d0a45
...
...
@@ -4,9 +4,6 @@
from
werkzeug.local
import
LocalProxy
from
functools
import
partial
from
.config
import
config
from
jms.service
import
AppService
stack
=
{}
__db_sessions
=
[]
...
...
@@ -18,7 +15,4 @@ def _find(name):
raise
ValueError
(
"Not found in stack: {}"
.
format
(
name
))
app_service
=
AppService
(
config
)
app_service
.
initial
()
current_app
=
LocalProxy
(
partial
(
_find
,
'current_app'
))
# app_service = LocalProxy(partial(_find, 'app_service'))
coco/httpd/auth.py
View file @
0c3d0a45
...
...
@@ -2,9 +2,9 @@
#
from
functools
import
wraps
from
flask
import
request
,
abort
from
flask
import
request
,
abort
,
redirect
from
..
ctx
import
app_service
from
..
service
import
app_service
def
login_required
(
func
):
...
...
@@ -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/base.py
View file @
0c3d0a45
...
...
@@ -9,7 +9,7 @@ from flask import Flask, request
from
..models
import
Connection
,
WSProxy
from
..proxy
import
ProxyServer
from
..utils
import
get_logger
from
..
ctx
import
app_service
from
..
service
import
app_service
from
..config
import
config
BASE_DIR
=
os
.
path
.
dirname
(
os
.
path
.
dirname
(
__file__
))
...
...
coco/httpd/elfinder/volumes/sftp.py
View file @
0c3d0a45
import
stat
import
threading
import
tempfile
from
flask
import
send_file
import
requests
...
...
@@ -231,17 +230,7 @@ class SFTPVolume(BaseVolume):
return
target
def
upload_as_url
(
self
,
url
,
parent
):
added
=
[]
parent_path
=
self
.
_path
(
parent
)
path
=
self
.
_join
(
parent_path
,
self
.
_base_name
(
url
))
remote_path
=
self
.
_remote_path
(
path
)
r
=
requests
.
get
(
url
,
stream
=
True
)
with
self
.
sftp
.
open
(
remote_path
,
'w'
)
as
rf
:
for
chunk
in
r
.
iter_content
(
chunk_size
=
1024
):
if
chunk
:
# filter out keep-alive new chunks
rf
.
write
(
chunk
)
added
.
append
(
self
.
_info
(
path
))
return
{
'added'
:
added
}
raise
PermissionError
(
"Not support upload from url"
)
def
upload
(
self
,
files
,
parent
):
""" For now, this uses a very naive way of storing files - the entire
...
...
coco/httpd/static/plugins/elfinder/css/theme-gray.css
View file @
0c3d0a45
...
...
@@ -1528,9 +1528,15 @@ a.ui-button:active .ui-icon,
.std42-dialog
.ui-dialog-titlebar
.elfinder-titlebar-minimize
:hover
.ui-icon
{
background-color
:
#ff9800
;
}
.elfinder-dialog-title
{
.elfinder-dialog-title
{
color
:
#f1f1f1
;
}
.ui-dialog-buttonpane
{
background
:
#fff
;
}
.std42-dialog
.ui-dialog-content
{
background
:
#fff
;
}
...
...
coco/httpd/static/plugins/elfinder/i18n/elfinder.zh_CN.js
View file @
0c3d0a45
...
...
@@ -375,7 +375,7 @@
'pass'
:
'密码'
,
// added 18.04.2012
'confirmUnmount'
:
'确实要卸载 $1?'
,
// from v2.1 added 30.04.2012
'dropFilesBrowser'
:
'从浏览器中拖放或粘贴文件'
,
// from v2.1 added 30.05.2012
'dropPasteFiles'
:
'拖放文件,
粘贴网址或
剪贴板图像'
,
// from v2.1 added 07.04.2014
'dropPasteFiles'
:
'拖放文件,
或粘贴
剪贴板图像'
,
// from v2.1 added 07.04.2014
'encoding'
:
'编码'
,
// from v2.1 added 19.12.2014
'locale'
:
'语言环境'
,
// from v2.1 added 19.12.2014
'searchTarget'
:
'目标: $1'
,
// from v2.1 added 22.5.2015
...
...
coco/httpd/view.py
View file @
0c3d0a45
...
...
@@ -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/httpd/ws.py
View file @
0c3d0a45
...
...
@@ -9,7 +9,7 @@ from flask import request
from
..models
import
Connection
,
WSProxy
from
..proxy
import
ProxyServer
from
..utils
import
get_logger
from
..
ctx
import
app_service
from
..
service
import
app_service
from
.base
import
BaseNamespace
from
.utils
import
get_cached_volume
...
...
coco/interactive.py
View file @
0c3d0a45
...
...
@@ -12,7 +12,7 @@ from .utils import wrap_with_line_feed as wr, wrap_with_title as title, \
wrap_with_warning
as
warning
,
is_obj_attr_has
,
is_obj_attr_eq
,
\
sort_assets
,
ugettext
as
_
,
get_logger
,
net_input
,
format_with_zh
,
\
item_max_length
,
size_of_str_with_zh
,
switch_lang
from
.
ctx
import
app_service
from
.
service
import
app_service
from
.proxy
import
ProxyServer
logger
=
get_logger
(
__file__
)
...
...
coco/interface.py
View file @
0c3d0a45
...
...
@@ -8,7 +8,7 @@ from collections import Iterable
from
.utils
import
get_logger
from
.config
import
config
from
.
ctx
import
app_service
from
.
service
import
app_service
logger
=
get_logger
(
__file__
)
...
...
coco/logger.py
View file @
0c3d0a45
...
...
@@ -57,9 +57,9 @@ def create_logger():
# 'engineio': main_setting,
}
)
dictConfig
(
config
)
logger
=
logging
.
getLogger
()
return
logger
create_logger
()
coco/models.py
View file @
0c3d0a45
...
...
@@ -4,7 +4,10 @@ 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
,
\
ugettext
as
_
from
.
import
char
from
.
import
utils
...
...
@@ -140,6 +143,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 +155,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 +180,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 +199,86 @@ 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
()
return
data
# 用户输入了内容,但是如果没在输入状态,也就是用户刚开始输入了,结算上次输出内容
# 输入了回车键
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
if
not
self
.
_input
:
return
data
for
rule
in
self
.
_cmd_filter_rules
:
action
,
cmd
=
rule
.
match
(
self
.
_input
)
if
action
==
rule
.
ALLOW
:
break
elif
action
==
rule
.
DENY
:
data
=
char
.
CLEAR_LINE_CHAR
+
b
'
\r
'
msg
=
_
(
"Command `{}` is forbidden ........"
)
.
format
(
cmd
)
msg
=
wr
(
warning
(
msg
.
encode
()),
before
=
1
,
after
=
1
)
self
.
output_data
.
append
(
msg
)
self
.
session
.
send_to_clients
(
msg
)
self
.
session
.
put_command
(
self
.
_input
,
msg
.
decode
())
self
.
session
.
put_replay
(
msg
)
self
.
input_data
.
clean
()
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 +294,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 +329,20 @@ 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
):
print
(
"Parse input: {}"
.
format
(
self
.
input_data
))
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 +357,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 +372,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/proxy.py
View file @
0c3d0a45
...
...
@@ -8,7 +8,7 @@ import time
from
.session
import
Session
from
.models
import
Server
,
TelnetServer
from
.connection
import
SSHConnection
,
TelnetConnection
from
.
ctx
import
app_service
from
.
service
import
app_service
from
.config
import
config
from
.utils
import
wrap_with_line_feed
as
wr
,
wrap_with_warning
as
warning
,
\
get_logger
,
net_input
,
ugettext
as
_
...
...
@@ -39,6 +39,7 @@ class ProxyServer:
or
(
not
password
and
not
private_key
):
prompt
=
"{}'s password: "
.
format
(
self
.
system_user
.
username
)
password
=
net_input
(
self
.
client
,
prompt
=
prompt
,
sensitive
=
True
)
private_key
=
None
self
.
system_user
.
password
=
password
self
.
system_user
.
private_key
=
private_key
...
...
coco/recorder.py
View file @
0c3d0a45
...
...
@@ -15,7 +15,7 @@ import jms_storage
from
.config
import
config
from
.utils
import
get_logger
,
Singleton
from
.struct
import
MemoryQueue
from
.
ctx
import
app_service
from
.
service
import
app_service
logger
=
get_logger
(
__file__
)
BUF_SIZE
=
1024
...
...
coco/session.py
View file @
0c3d0a45
...
...
@@ -8,7 +8,7 @@ import time
from
.utils
import
get_logger
,
wrap_with_warning
as
warn
,
\
wrap_with_line_feed
as
wr
,
ugettext
as
_
,
ignore_error
from
.
ctx
import
app_service
from
.
service
import
app_service
from
.struct
import
SelectEvent
from
.recorder
import
get_recorder
...
...
@@ -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/sftp.py
View file @
0c3d0a45
...
...
@@ -9,7 +9,7 @@ from paramiko.sftp import SFTP_PERMISSION_DENIED, SFTP_NO_SUCH_FILE, \
from
coco.utils
import
get_logger
from
.config
import
config
from
.
ctx
import
app_service
from
.
service
import
app_service
from
.connection
import
SSHConnection
CURRENT_DIR
=
os
.
path
.
dirname
(
__file__
)
...
...
coco/sshd.py
View file @
0c3d0a45
...
...
@@ -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
:
...
...
coco/tasks.py
View file @
0c3d0a45
...
...
@@ -2,7 +2,7 @@
# -*- coding: utf-8 -*-
#
from
.
ctx
import
app_service
from
.
service
import
app_service
from
.utils
import
get_logger
from
.session
import
Session
...
...
cocod
View file @
0c3d0a45
...
...
@@ -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'
)
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 @
0c3d0a45
No preview for this file type
locale/en/LC_MESSAGES/coco.po
View file @
0c3d0a45
...
...
@@ -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 @
9f053fba
# 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 @
0c3d0a45
No preview for this file type
locale/zh_CN/LC_MESSAGES/coco.po
View file @
0c3d0a45
...
...
@@ -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 @
9f053fba
# 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 "被管理员中断"
requirements/requirements.txt
View file @
0c3d0a45
...
...
@@ -19,7 +19,7 @@ itsdangerous==0.24
Jinja2==2.10
jmespath==0.9.3
jms-storage==0.0.19
jumpserver-python-sdk==0.0.
48
jumpserver-python-sdk==0.0.
50
MarkupSafe==1.0
oss2==2.4.0
paramiko==2.4.1
...
...
utils/messages.sh
View file @
0c3d0a45
...
...
@@ -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