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
510513c1
Commit
510513c1
authored
Aug 08, 2019
by
ibuler
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'dev' of github.com:jumpserver/coco into dev
parents
a2592688
61bae649
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
64 additions
and
23 deletions
+64
-23
conf.py
coco/conf.py
+2
-0
connection.py
coco/connection.py
+11
-4
connector.py
coco/httpd/elfinder/connector.py
+7
-6
base.py
coco/httpd/elfinder/volumes/base.py
+4
-2
sftp.py
coco/httpd/elfinder/volumes/sftp.py
+18
-10
elfinder.zh_CN.js
coco/httpd/static/plugins/elfinder/i18n/elfinder.zh_CN.js
+1
-1
sftp.py
coco/sftp.py
+15
-0
config_example.yml
config_example.yml
+6
-0
No files found.
coco/conf.py
View file @
510513c1
...
...
@@ -376,6 +376,8 @@ defaults = {
'SFTP_SHOW_HIDDEN_FILE'
:
False
,
'UPLOAD_FAILED_REPLAY_ON_START'
:
True
,
'REUSE_CONNECTION'
:
True
,
'FORCE_REMOVE_FOLDER'
:
False
,
'TELNET_TTYPE'
:
'XTERM-256COLOR'
,
}
...
...
coco/connection.py
View file @
510513c1
...
...
@@ -300,10 +300,16 @@ class TelnetConnection:
logger
.
info
(
msg
)
return
None
,
msg
if
data
.
startswith
(
telnetlib
.
IAC
):
self
.
option_negotiate
(
data
)
# 将数据以 \r\n 进行分割
_data_list
=
data
.
split
(
b
'
\r\n
'
)
for
_data
in
_data_list
:
if
not
_data
:
continue
if
_data
.
startswith
(
telnetlib
.
IAC
):
self
.
option_negotiate
(
_data
)
else
:
result
=
self
.
login_auth
(
data
)
result
=
self
.
login_auth
(
_
data
)
if
result
:
msg
=
'Successful asset connection.<{}>/<{}>/<{}>.'
.
format
(
self
.
client
.
user
,
self
.
system_user
.
username
,
...
...
@@ -338,7 +344,8 @@ class TelnetConnection:
elif
x
==
telnetlib
.
DO
+
telnetlib
.
TTYPE
:
new_data_list
.
append
(
telnetlib
.
WILL
+
telnetlib
.
TTYPE
)
elif
x
==
telnetlib
.
SB
+
telnetlib
.
TTYPE
+
b
'
\x01
'
:
new_data_list
.
append
(
telnetlib
.
SB
+
telnetlib
.
TTYPE
+
b
'
\x00
'
+
b
'XTERM-256COLOR'
)
terminal_type
=
bytes
(
config
.
TELNET_TTYPE
,
encoding
=
'utf-8'
)
new_data_list
.
append
(
telnetlib
.
SB
+
telnetlib
.
TTYPE
+
b
'
\x00
'
+
terminal_type
)
elif
telnetlib
.
DO
in
x
:
new_data_list
.
append
(
x
.
replace
(
telnetlib
.
DO
,
telnetlib
.
WONT
))
elif
telnetlib
.
WILL
in
x
:
...
...
coco/httpd/elfinder/connector.py
View file @
510513c1
...
...
@@ -31,7 +31,7 @@ class ElFinderConnector:
_allowed_args
=
[
'cmd'
,
'target'
,
'targets[]'
,
'current'
,
'tree'
,
'name'
,
'content'
,
'src'
,
'dst'
,
'cut'
,
'init'
,
'type'
,
'width'
,
'height'
,
'upload[]'
,
'dirs[]'
,
'type'
,
'width'
,
'height'
,
'upload[]'
,
'
upload_path[]'
,
'
dirs[]'
,
'targets'
,
"chunk"
,
"range"
,
"cid"
,
'reload'
,
]
...
...
@@ -125,7 +125,7 @@ class ElFinderConnector:
# Copy allowed parameters from the given request's GET to self.data
for
field
in
self
.
_allowed_args
:
if
field
in
request_data
:
if
field
in
[
"targets[]"
,
"targets"
,
"dirs[]"
]:
if
field
in
[
"targets[]"
,
"targets"
,
"dirs[]"
,
'upload_path[]'
]:
self
.
data
[
field
]
=
request_data
.
getlist
(
field
)
else
:
self
.
data
[
field
]
=
request_data
[
field
]
...
...
@@ -270,20 +270,21 @@ class ElFinderConnector:
parent
=
self
.
data
[
'target'
]
volume
=
self
.
get_volume
(
parent
)
upload
=
self
.
data
.
get
(
'upload[]'
)
upload_paths
=
self
.
data
.
get
(
'upload_path[]'
)
if
self
.
data
.
get
(
'chunk'
)
and
self
.
data
.
get
(
'cid'
):
self
.
response
.
update
(
volume
.
upload_as_chunk
(
self
.
request
.
files
,
self
.
data
.
get
(
'chunk'
),
parent
self
.
request
.
files
,
self
.
data
.
get
(
'chunk'
),
parent
,
upload_paths
)
)
elif
self
.
data
.
get
(
'chunk'
):
self
.
response
.
update
(
volume
.
upload_chunk_merge
(
parent
,
self
.
data
.
get
(
'chunk'
)
)
volume
.
upload_chunk_merge
(
parent
,
self
.
data
.
get
(
'chunk'
)
,
upload_paths
),
)
elif
isinstance
(
upload
,
str
):
self
.
response
.
update
(
volume
.
upload_as_url
(
upload
,
parent
))
self
.
response
.
update
(
volume
.
upload_as_url
(
upload
,
parent
,
upload
))
else
:
self
.
response
.
update
(
volume
.
upload
(
self
.
request
.
files
,
parent
))
self
.
response
.
update
(
volume
.
upload
(
self
.
request
.
files
,
parent
,
upload_paths
))
def
__size
(
self
):
target
=
self
.
data
[
'targets[]'
]
...
...
coco/httpd/elfinder/volumes/base.py
View file @
510513c1
...
...
@@ -214,23 +214,25 @@ class BaseVolume:
"""
raise
NotImplementedError
def
upload
(
self
,
files
,
parent
):
def
upload
(
self
,
files
,
parent
,
upload_path
):
""" Uploads one or more files in to the parent directory.
:param files: A list of uploaded file objects, as described here:
https://docs.djangoproject.com/en/dev/topics/http/file-uploads/
:param parent: The hash of the directory in which to create the
new files.
:param upload_path:
:returns: TODO
"""
raise
NotImplementedError
def
upload_as_chunk
(
self
,
files
,
chunk_name
,
parent
):
def
upload_as_chunk
(
self
,
files
,
chunk_name
,
parent
,
upload_path
):
"""
Upload a large file as chunk
:param files:
:param chunk_name:
:param cid:
:param parent:
:param upload_path:
:return:
"""
coco/httpd/elfinder/volumes/sftp.py
View file @
510513c1
...
...
@@ -4,7 +4,7 @@ import stat
import
threading
from
flask
import
send_file
import
request
s
import
o
s
from
coco.utils
import
get_logger
from
.base
import
BaseVolume
...
...
@@ -222,10 +222,10 @@ class SFTPVolume(BaseVolume):
self
.
sftp
.
unlink
(
remote_path
)
return
target
def
upload_as_url
(
self
,
url
,
parent
):
def
upload_as_url
(
self
,
url
,
parent
,
upload_path
):
raise
PermissionError
(
"Not support upload from url"
)
def
upload
(
self
,
files
,
parent
):
def
upload
(
self
,
files
,
parent
,
upload_path
):
""" For now, this uses a very naive way of storing files - the entire
file is read in to the File model's content field in one go.
...
...
@@ -234,10 +234,13 @@ class SFTPVolume(BaseVolume):
"""
added
=
[]
parent_path
=
self
.
_path
(
parent
)
item
=
files
.
get
(
'upload[]'
)
for
i
,
item
in
enumerate
(
files
.
getlist
(
"upload[]"
)):
if
upload_path
and
(
parent
!=
upload_path
[
i
])
and
(
item
.
filename
in
upload_path
[
i
]):
path
=
self
.
_join
(
parent_path
,
upload_path
[
i
]
.
lstrip
(
self
.
path_sep
))
else
:
path
=
self
.
_join
(
parent_path
,
item
.
filename
)
remote_path
=
self
.
_remote_path
(
path
)
infos
=
self
.
_list
(
parent_path
)
infos
=
self
.
_list
(
os
.
path
.
dirname
(
path
)
)
files_exist
=
[
d
[
'name'
]
for
d
in
infos
]
if
item
.
filename
in
files_exist
:
raise
OSError
(
"File {} exits"
.
format
(
remote_path
))
...
...
@@ -247,7 +250,7 @@ class SFTPVolume(BaseVolume):
added
.
append
(
self
.
_info
(
path
))
return
{
'added'
:
added
}
def
upload_as_chunk
(
self
,
files
,
chunk_name
,
parent
):
def
upload_as_chunk
(
self
,
files
,
chunk_name
,
parent
,
upload_path
):
added
=
[]
parent_path
=
self
.
_path
(
parent
)
item
=
files
.
get
(
'upload[]'
)
...
...
@@ -255,11 +258,13 @@ class SFTPVolume(BaseVolume):
filename
=
'.'
.
join
(
__tmp
[:
-
2
])
num
,
total
=
__tmp
[
-
2
]
.
split
(
'_'
)
num
,
total
=
int
(
num
),
int
(
total
)
path
=
self
.
_join
(
parent_path
,
filename
)
if
len
(
upload_path
)
==
1
and
(
parent
!=
upload_path
[
0
])
and
(
filename
in
upload_path
[
0
]):
path
=
self
.
_join
(
parent_path
,
upload_path
[
0
]
.
lstrip
(
self
.
path_sep
))
else
:
path
=
self
.
_join
(
parent_path
,
upload_path
[
0
]
.
lstrip
(
self
.
path_sep
),
filename
)
remote_path
=
self
.
_remote_path
(
path
)
if
num
==
0
:
infos
=
self
.
_list
(
parent_path
)
infos
=
self
.
_list
(
os
.
path
.
dirname
(
path
)
)
files_exist
=
[
d
[
'name'
]
for
d
in
infos
]
if
item
.
filename
in
files_exist
:
raise
OSError
(
"File {} exits"
.
format
(
remote_path
))
...
...
@@ -271,8 +276,11 @@ class SFTPVolume(BaseVolume):
else
:
return
{
'added'
:
added
,
'_chunkmerged'
:
filename
,
'_name'
:
filename
}
def
upload_chunk_merge
(
self
,
parent
,
chunk
):
def
upload_chunk_merge
(
self
,
parent
,
chunk
,
upload_path
):
parent_path
=
self
.
_path
(
parent
)
if
len
(
upload_path
)
==
1
and
(
parent
!=
upload_path
[
0
]):
path
=
self
.
_join
(
parent_path
,
upload_path
[
0
]
.
lstrip
(
self
.
path_sep
))
else
:
path
=
self
.
_join
(
parent_path
,
chunk
)
return
{
"added"
:
[
self
.
_info
(
path
)]}
...
...
coco/httpd/static/plugins/elfinder/i18n/elfinder.zh_CN.js
View file @
510513c1
...
...
@@ -422,7 +422,7 @@
'minsLeft'
:
'剩余 $1 分钟'
,
// from v2.1.17 added 13.11.2016
'openAsEncoding'
:
'使用所选编码重新打开'
,
// from v2.1.19 added 2.12.2016
'saveAsEncoding'
:
'使用所选编码保存'
,
// from v2.1.19 added 2.12.2016
'selectFolder'
:
'选择目录
(暂不支持)
'
,
// from v2.1.20 added 13.12.2016
'selectFolder'
:
'选择目录'
,
// from v2.1.20 added 13.12.2016
'firstLetterSearch'
:
'首字母搜索'
,
// from v2.1.23 added 24.3.2017
'presets'
:
'预置'
,
// from v2.1.25 added 26.5.2017
'tooManyToTrash'
:
'项目太多,不能移动到回收站.'
,
// from v2.1.25 added 9.6.2017
...
...
coco/sftp.py
View file @
510513c1
import
os
import
stat
import
paramiko
import
time
from
datetime
import
datetime
...
...
@@ -47,6 +48,7 @@ def convert_error(func):
if
isinstance
(
error
,
Exception
):
logger
.
error
(
error
)
return
response
return
wrapper
...
...
@@ -74,6 +76,7 @@ class SFTPServer(paramiko.SFTPServerInterface):
self
.
_sftp
=
{}
self
.
hosts
=
self
.
get_permed_hosts
()
self
.
is_finished
=
False
self
.
force_rm_folder
=
config
.
FORCE_REMOVE_FOLDER
def
get_user_assets
(
self
):
user_id
=
self
.
server
.
connection
.
user
.
id
...
...
@@ -392,12 +395,24 @@ class SFTPServer(paramiko.SFTPServerInterface):
success
=
False
try
:
if
self
.
force_rm_folder
:
self
.
_rmdir
(
client
,
rpath
)
else
:
client
.
rmdir
(
rpath
)
success
=
True
return
paramiko
.
SFTP_OK
finally
:
self
.
create_ftp_log
(
path
,
"Rmdir"
,
success
)
def
_rmdir
(
self
,
sftp_client
,
path
):
for
item
in
list
(
sftp_client
.
listdir_iter
(
path
)):
filepath
=
"/"
.
join
([
path
,
item
.
filename
])
if
stat
.
S_IFMT
(
item
.
st_mode
)
==
stat
.
S_IFDIR
:
self
.
_rmdir
(
sftp_client
,
filepath
)
continue
sftp_client
.
remove
(
filepath
)
sftp_client
.
rmdir
(
path
)
class
FakeServer
:
pass
...
...
config_example.yml
View file @
510513c1
...
...
@@ -60,3 +60,9 @@ BOOTSTRAP_TOKEN: <PleasgeChangeSameWithJumpserver>
# 是否复用和用户后端资产已建立的连接(用户不会复用其他用户的连接)
# REUSE_CONNECTION: true
# 是否强制删除文件夹:(default false)
# FORCE_REMOVE_FOLDER: false
# Telnet连接协商使用的终端类型
# TELNET_TTYPE: XTERM-256COLOR
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