mirror of https://github.com/tp4a/teleport
支持记录SFTP操作日志了,能记录文件打开、删除,目录创建、删除,改名以及创建符号链接等操作。
parent
428dc323f3
commit
ef23397be8
File diff suppressed because it is too large
Load Diff
|
@ -1,133 +1,134 @@
|
||||||
#ifndef __SSH_SESSION_H__
|
#ifndef __SSH_SESSION_H__
|
||||||
#define __SSH_SESSION_H__
|
#define __SSH_SESSION_H__
|
||||||
|
|
||||||
#include "ssh_recorder.h"
|
#include "ssh_recorder.h"
|
||||||
|
|
||||||
#include <ex.h>
|
#include <ex.h>
|
||||||
|
|
||||||
#include <libssh/libssh.h>
|
#include <libssh/libssh.h>
|
||||||
#include <libssh/server.h>
|
#include <libssh/server.h>
|
||||||
#include <libssh/callbacks.h>
|
#include <libssh/callbacks.h>
|
||||||
#include <libssh/sftp.h>
|
#include <libssh/sftp.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
#define TS_SSH_CHANNEL_TYPE_UNKNOWN 0
|
#define TS_SSH_CHANNEL_TYPE_UNKNOWN 0
|
||||||
#define TS_SSH_CHANNEL_TYPE_SHELL 1
|
#define TS_SSH_CHANNEL_TYPE_SHELL 1
|
||||||
#define TS_SSH_CHANNEL_TYPE_SFTP 2
|
#define TS_SSH_CHANNEL_TYPE_SFTP 2
|
||||||
|
|
||||||
#define TS_SSH_DATA_FROM_CLIENT 1
|
#define TS_SSH_DATA_FROM_CLIENT 1
|
||||||
#define TS_SSH_DATA_FROM_SERVER 2
|
#define TS_SSH_DATA_FROM_SERVER 2
|
||||||
|
|
||||||
typedef struct TS_SSH_CHANNEL_INFO
|
typedef struct TS_SSH_CHANNEL_INFO
|
||||||
{
|
{
|
||||||
int type; // TS_SSH_CHANNEL_TYPE_SHELL or TS_SSH_CHANNEL_TYPE_SFTP
|
int type; // TS_SSH_CHANNEL_TYPE_SHELL or TS_SSH_CHANNEL_TYPE_SFTP
|
||||||
ssh_channel channel;
|
ssh_channel channel;
|
||||||
|
|
||||||
TS_SSH_CHANNEL_INFO()
|
TS_SSH_CHANNEL_INFO()
|
||||||
{
|
{
|
||||||
type = TS_SSH_CHANNEL_TYPE_UNKNOWN;
|
type = TS_SSH_CHANNEL_TYPE_UNKNOWN;
|
||||||
channel = NULL;
|
channel = NULL;
|
||||||
}
|
}
|
||||||
}TS_SSH_CHANNEL_INFO;
|
}TS_SSH_CHANNEL_INFO;
|
||||||
|
|
||||||
typedef std::map<ssh_channel, TS_SSH_CHANNEL_INFO*> ts_ssh_channel_map;
|
typedef std::map<ssh_channel, TS_SSH_CHANNEL_INFO*> ts_ssh_channel_map;
|
||||||
|
|
||||||
class SshProxy;
|
class SshProxy;
|
||||||
|
|
||||||
class SshSession : public ExThreadBase
|
class SshSession : public ExThreadBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SshSession(SshProxy* proxy, ssh_session sess_client);
|
SshSession(SshProxy* proxy, ssh_session sess_client);
|
||||||
virtual ~SshSession();
|
virtual ~SshSession();
|
||||||
|
|
||||||
SshProxy* get_proxy(void) { return m_proxy; }
|
SshProxy* get_proxy(void) { return m_proxy; }
|
||||||
|
|
||||||
|
|
||||||
TS_SSH_CHANNEL_INFO* _get_cli_channel(ssh_channel srv_channel);
|
TS_SSH_CHANNEL_INFO* _get_cli_channel(ssh_channel srv_channel);
|
||||||
TS_SSH_CHANNEL_INFO* _get_srv_channel(ssh_channel cli_channel);
|
TS_SSH_CHANNEL_INFO* _get_srv_channel(ssh_channel cli_channel);
|
||||||
|
|
||||||
void client_ip(const char* ip) { m_client_ip = ip; }
|
void client_ip(const char* ip) { m_client_ip = ip; }
|
||||||
const char* client_ip(void) const { return m_client_ip.c_str(); }
|
const char* client_ip(void) const { return m_client_ip.c_str(); }
|
||||||
void client_port(ex_u16 port) { m_client_port = port; }
|
void client_port(ex_u16 port) { m_client_port = port; }
|
||||||
ex_u16 client_port(void) const { return m_client_port; }
|
ex_u16 client_port(void) const { return m_client_port; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// 继承自 TppSessionBase
|
// 继承自 TppSessionBase
|
||||||
bool _on_session_begin(const TPP_SESSION_INFO* info);
|
bool _on_session_begin(const TPP_SESSION_INFO* info);
|
||||||
bool _on_session_end(void);
|
bool _on_session_end(void);
|
||||||
|
|
||||||
|
|
||||||
void _thread_loop(void);
|
void _thread_loop(void);
|
||||||
void _set_stop_flag(void);
|
void _set_stop_flag(void);
|
||||||
|
|
||||||
void _process_command(int from, const ex_u8* data, int len);
|
void _process_ssh_command(int from, const ex_u8* data, int len);
|
||||||
|
void _process_sftp_command(const ex_u8* data, int len);
|
||||||
private:
|
|
||||||
void _run(void);
|
private:
|
||||||
|
void _run(void);
|
||||||
void _close_channels(void);
|
|
||||||
|
void _close_channels(void);
|
||||||
void _enter_sftp_mode(void);
|
|
||||||
|
void _enter_sftp_mode(void);
|
||||||
static int _on_auth_password_request(ssh_session session, const char *user, const char *password, void *userdata);
|
|
||||||
static ssh_channel _on_new_channel_request(ssh_session session, void *userdata);
|
static int _on_auth_password_request(ssh_session session, const char *user, const char *password, void *userdata);
|
||||||
static int _on_client_pty_request(ssh_session session, ssh_channel channel, const char *term, int x, int y, int px, int py, void *userdata);
|
static ssh_channel _on_new_channel_request(ssh_session session, void *userdata);
|
||||||
static int _on_client_shell_request(ssh_session session, ssh_channel channel, void *userdata);
|
static int _on_client_pty_request(ssh_session session, ssh_channel channel, const char *term, int x, int y, int px, int py, void *userdata);
|
||||||
static void _on_client_channel_close(ssh_session session, ssh_channel channel, void* userdata);
|
static int _on_client_shell_request(ssh_session session, ssh_channel channel, void *userdata);
|
||||||
static int _on_client_channel_data(ssh_session session, ssh_channel channel, void *data, unsigned int len, int is_stderr, void *userdata);
|
static void _on_client_channel_close(ssh_session session, ssh_channel channel, void* userdata);
|
||||||
static int _on_client_pty_win_change(ssh_session session, ssh_channel channel, int width, int height, int pxwidth, int pwheight, void *userdata);
|
static int _on_client_channel_data(ssh_session session, ssh_channel channel, void *data, unsigned int len, int is_stderr, void *userdata);
|
||||||
|
static int _on_client_pty_win_change(ssh_session session, ssh_channel channel, int width, int height, int pxwidth, int pwheight, void *userdata);
|
||||||
static int _on_client_channel_subsystem_request(ssh_session session, ssh_channel channel, const char *subsystem, void *userdata);
|
|
||||||
static int _on_client_channel_exec_request(ssh_session session, ssh_channel channel, const char *command, void *userdata);
|
static int _on_client_channel_subsystem_request(ssh_session session, ssh_channel channel, const char *subsystem, void *userdata);
|
||||||
|
static int _on_client_channel_exec_request(ssh_session session, ssh_channel channel, const char *command, void *userdata);
|
||||||
static int _on_server_channel_data(ssh_session session, ssh_channel channel, void *data, unsigned int len, int is_stderr, void *userdata);
|
|
||||||
static void _on_server_channel_close(ssh_session session, ssh_channel channel, void* userdata);
|
static int _on_server_channel_data(ssh_session session, ssh_channel channel, void *data, unsigned int len, int is_stderr, void *userdata);
|
||||||
|
static void _on_server_channel_close(ssh_session session, ssh_channel channel, void* userdata);
|
||||||
private:
|
|
||||||
int m_retcode;
|
private:
|
||||||
int m_db_id;
|
int m_retcode;
|
||||||
|
int m_db_id;
|
||||||
TppSshRec m_rec;
|
|
||||||
|
TppSshRec m_rec;
|
||||||
SshProxy* m_proxy;
|
|
||||||
ssh_session m_cli_session;
|
SshProxy* m_proxy;
|
||||||
ssh_session m_srv_session;
|
ssh_session m_cli_session;
|
||||||
|
ssh_session m_srv_session;
|
||||||
ExThreadLock m_lock;
|
|
||||||
|
ExThreadLock m_lock;
|
||||||
ex_astr m_client_ip;
|
|
||||||
ex_u16 m_client_port;
|
ex_astr m_client_ip;
|
||||||
|
ex_u16 m_client_port;
|
||||||
ex_astr m_sid;
|
|
||||||
ex_astr m_server_ip;
|
ex_astr m_sid;
|
||||||
ex_u16 m_server_port;
|
ex_astr m_server_ip;
|
||||||
ex_astr m_user_name;
|
ex_u16 m_server_port;
|
||||||
ex_astr m_user_auth;
|
ex_astr m_user_name;
|
||||||
int m_auth_mode;
|
ex_astr m_user_auth;
|
||||||
|
int m_auth_mode;
|
||||||
bool m_is_first_server_data;
|
|
||||||
bool m_is_sftp;
|
bool m_is_first_server_data;
|
||||||
|
bool m_is_sftp;
|
||||||
bool m_is_logon;
|
|
||||||
// 一个ssh_session中可以打开多个ssh_channel
|
bool m_is_logon;
|
||||||
ts_ssh_channel_map m_channel_cli_srv; // 通过客户端通道查找服务端通道
|
// 一个ssh_session中可以打开多个ssh_channel
|
||||||
ts_ssh_channel_map m_channel_srv_cli; // 通过服务端通道查找客户端通道
|
ts_ssh_channel_map m_channel_cli_srv; // 通过客户端通道查找服务端通道
|
||||||
|
ts_ssh_channel_map m_channel_srv_cli; // 通过服务端通道查找客户端通道
|
||||||
bool m_have_error;
|
|
||||||
|
bool m_have_error;
|
||||||
bool m_recving_from_srv; // 是否正在从服务器接收数据?
|
|
||||||
bool m_recving_from_cli; // 是否正在从客户端接收数据?
|
bool m_recving_from_srv; // 是否正在从服务器接收数据?
|
||||||
|
bool m_recving_from_cli; // 是否正在从客户端接收数据?
|
||||||
struct ssh_server_callbacks_struct m_srv_cb;
|
|
||||||
struct ssh_channel_callbacks_struct m_cli_channel_cb;
|
struct ssh_server_callbacks_struct m_srv_cb;
|
||||||
struct ssh_channel_callbacks_struct m_srv_channel_cb;
|
struct ssh_channel_callbacks_struct m_cli_channel_cb;
|
||||||
|
struct ssh_channel_callbacks_struct m_srv_channel_cb;
|
||||||
int m_command_flag;
|
|
||||||
|
int m_command_flag;
|
||||||
std::list<char> m_cmd_char_list;
|
|
||||||
std::list<char>::iterator m_cmd_char_pos;
|
std::list<char> m_cmd_char_list;
|
||||||
};
|
std::list<char>::iterator m_cmd_char_pos;
|
||||||
|
};
|
||||||
#endif // __SSH_SESSION_H__
|
|
||||||
|
#endif // __SSH_SESSION_H__
|
||||||
|
|
|
@ -80,10 +80,20 @@ class ReplayStaticFileHandler(tornado.web.StaticFileHandler):
|
||||||
class ComandLogHandler(TPBaseAdminAuthHandler):
|
class ComandLogHandler(TPBaseAdminAuthHandler):
|
||||||
def get(self, protocol, record_id):
|
def get(self, protocol, record_id):
|
||||||
|
|
||||||
|
header = record.read_record_head(record_id)
|
||||||
|
if header is None:
|
||||||
|
return self.write_json(-3, '操作失败')
|
||||||
|
|
||||||
|
# ret = dict()
|
||||||
|
# ret['header'] = header
|
||||||
|
# return self.write_json(0, data=ret)
|
||||||
|
|
||||||
param = dict()
|
param = dict()
|
||||||
|
param['header'] = header
|
||||||
param['count'] = 0
|
param['count'] = 0
|
||||||
param['op'] = list()
|
param['op'] = list()
|
||||||
|
|
||||||
|
cmd_type = 0 # 0 = ssh, 1 = sftp
|
||||||
protocol = int(protocol)
|
protocol = int(protocol)
|
||||||
if protocol == 1:
|
if protocol == 1:
|
||||||
pass
|
pass
|
||||||
|
@ -94,12 +104,26 @@ class ComandLogHandler(TPBaseAdminAuthHandler):
|
||||||
file = open(file_info, 'r')
|
file = open(file_info, 'r')
|
||||||
data = file.readlines()
|
data = file.readlines()
|
||||||
for i in range(len(data)):
|
for i in range(len(data)):
|
||||||
param['op'].append({'t': data[i][1:20], 'c': data[i][22:-1]})
|
if 0 == i:
|
||||||
|
cmd = data[i][22:-1]
|
||||||
|
if 'SFTP INITIALIZE' == cmd:
|
||||||
|
cmd_type = 1
|
||||||
|
continue
|
||||||
|
if cmd_type == 0:
|
||||||
|
param['op'].append({'t': data[i][1:20], 'c': data[i][22:-1]})
|
||||||
|
else:
|
||||||
|
cmd_info = data[i][22:-1].split(':')
|
||||||
|
if len(cmd_info) != 4:
|
||||||
|
continue
|
||||||
|
param['op'].append({'t': data[i][1:20], 'c': cmd_info[0], 'p1': cmd_info[2], 'p2': cmd_info[3]})
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
param['count'] = len(param['op'])
|
param['count'] = len(param['op'])
|
||||||
|
|
||||||
self.render('log/record-ssh-cmd.mako', page_param=json.dumps(param))
|
if cmd_type == 0:
|
||||||
|
self.render('log/record-ssh-cmd.mako', page_param=json.dumps(param))
|
||||||
|
else:
|
||||||
|
self.render('log/record-sftp-cmd.mako', page_param=json.dumps(param))
|
||||||
|
|
||||||
|
|
||||||
class RecordGetHeader(TPBaseAdminAuthJsonHandler):
|
class RecordGetHeader(TPBaseAdminAuthJsonHandler):
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
<%!
|
||||||
|
page_title_ = 'SFTP操作记录'
|
||||||
|
%>
|
||||||
|
|
||||||
|
<%inherit file="../page_no_sidebar_base.mako"/>
|
||||||
|
<%block name="extend_js">
|
||||||
|
</%block>
|
||||||
|
|
||||||
|
<%block name="breadcrumb">
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li><i class="fa fa-file-text-o"></i> ${self.attr.page_title_}</li>
|
||||||
|
<li><span id="recorder-info"></span></li>
|
||||||
|
</ol>
|
||||||
|
</%block>
|
||||||
|
|
||||||
|
<%block name="extend_css">
|
||||||
|
<style type="text/css">
|
||||||
|
#no-op-msg {
|
||||||
|
display: none;
|
||||||
|
padding: 20px;
|
||||||
|
margin: 50px;
|
||||||
|
background-color: #fffed5;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-size: 120%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#op-list {
|
||||||
|
display: none;
|
||||||
|
padding: 20px;
|
||||||
|
margin: 20px 10px 20px 10px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
font-size: 14px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.op-item {
|
||||||
|
margin-bottom: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time, .cmd, .path {
|
||||||
|
font-family: Consolas, Lucida Console, Monaco, Courier, 'Courier New', monospace;
|
||||||
|
font-size:13px;
|
||||||
|
line-height: 15px;
|
||||||
|
padding: 0 5px;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time {
|
||||||
|
margin-right: 15px;
|
||||||
|
background-color: #d8d8d8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.path {
|
||||||
|
margin:0 5px 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmd-danger {
|
||||||
|
background-color: #ffbba6;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmd-info {
|
||||||
|
background-color: #b4fdb1;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</%block>
|
||||||
|
|
||||||
|
<div class="page-content">
|
||||||
|
<div id="no-op-msg">
|
||||||
|
他悄悄地来,又悄悄地走,挥一挥衣袖,没有留下任何操作~~~~
|
||||||
|
</div>
|
||||||
|
<div id="op-list"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<%block name="embed_js">
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
ywl.add_page_options(${page_param});
|
||||||
|
|
||||||
|
ywl.on_init = function (cb_stack, cb_args) {
|
||||||
|
|
||||||
|
if (ywl.page_options.count === 0) {
|
||||||
|
$('#no-op-msg').show();
|
||||||
|
} else {
|
||||||
|
var header = ywl.page_options.header;
|
||||||
|
$('#recorder-info').html(header.account + ' 于 ' + format_datetime(header.start) + ' 访问 ' + header.user_name + '@' + header.ip + ':' + header.port);
|
||||||
|
|
||||||
|
var dom_op_list = $('#op-list');
|
||||||
|
var html = [];
|
||||||
|
for (var i = 0; i < ywl.page_options.count; i++) {
|
||||||
|
html.push('<div class="op-item"><span class="time">' + ywl.page_options.op[i].t + '</span> ');
|
||||||
|
|
||||||
|
if (ywl.page_options.op[i].c === '3') {
|
||||||
|
html.push('<span class="cmd">打开文件</span>');
|
||||||
|
html.push('<span class="path">' + ywl.page_options.op[i].p1 + '</span>');
|
||||||
|
} else if (ywl.page_options.op[i].c === '13') {
|
||||||
|
html.push('<span class="cmd cmd-danger">删除文件</span>');
|
||||||
|
html.push('<span class="path cmd-danger">' + ywl.page_options.op[i].p1 + '</span>');
|
||||||
|
} else if (ywl.page_options.op[i].c === '14') {
|
||||||
|
html.push('<span class="cmd">创建目录</span>');
|
||||||
|
html.push('<span class="path">' + ywl.page_options.op[i].p1 + '</span>');
|
||||||
|
} else if (ywl.page_options.op[i].c === '15') {
|
||||||
|
html.push('<span class="cmd cmd-danger">删除目录</span>');
|
||||||
|
html.push('<span class="path cmd-danger">' + ywl.page_options.op[i].p1 + '</span>');
|
||||||
|
} else if (ywl.page_options.op[i].c === '18') {
|
||||||
|
html.push('<span class="cmd cmd-info">更改名称</span>');
|
||||||
|
html.push('<span class="path cmd-info">' + ywl.page_options.op[i].p1 + '</span>');
|
||||||
|
html.push('<i class="fa fa-arrow-circle-right"></i>');
|
||||||
|
html.push('<span class="path cmd-info">' + ywl.page_options.op[i].p2 + '</span>');
|
||||||
|
} else if (ywl.page_options.op[i].c === '21') {
|
||||||
|
html.push('<span class="cmd">创建链接</span>');
|
||||||
|
html.push('<span class="path">' + ywl.page_options.op[i].p2 + '</span>');
|
||||||
|
html.push('<i class="fa fa-arrow-right"></i>');
|
||||||
|
html.push('<span class="path">' + ywl.page_options.op[i].p1 + '</span>');
|
||||||
|
}
|
||||||
|
|
||||||
|
html.push('</div>');
|
||||||
|
}
|
||||||
|
dom_op_list.append(html.join(''));
|
||||||
|
dom_op_list.show();
|
||||||
|
}
|
||||||
|
cb_stack.exec();
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
</%block>
|
|
@ -1,101 +1,105 @@
|
||||||
<%!
|
<%!
|
||||||
page_title_ = '操作记录'
|
page_title_ = 'SSH操作记录'
|
||||||
%>
|
%>
|
||||||
|
|
||||||
<%inherit file="../page_no_sidebar_base.mako"/>
|
<%inherit file="../page_no_sidebar_base.mako"/>
|
||||||
<%block name="extend_js">
|
<%block name="extend_js">
|
||||||
</%block>
|
</%block>
|
||||||
|
|
||||||
<%block name="breadcrumb">
|
<%block name="breadcrumb">
|
||||||
<ol class="breadcrumb">
|
<ol class="breadcrumb">
|
||||||
<li><i class="fa fa-server"></i> ${self.attr.page_title_}</li>
|
<li><i class="fa fa-file-text-o"></i> ${self.attr.page_title_}</li>
|
||||||
</ol>
|
<li><span id="recorder-info"></span></li>
|
||||||
</%block>
|
</ol>
|
||||||
|
</%block>
|
||||||
<%block name="extend_css">
|
|
||||||
<style type="text/css">
|
<%block name="extend_css">
|
||||||
#no-op-msg {
|
<style type="text/css">
|
||||||
display: none;
|
#no-op-msg {
|
||||||
padding: 20px;
|
display: none;
|
||||||
margin: 50px;
|
padding: 20px;
|
||||||
background-color: #fffed5;
|
margin: 50px;
|
||||||
border-radius: 5px;
|
background-color: #fffed5;
|
||||||
font-size: 120%;
|
border-radius: 5px;
|
||||||
}
|
font-size: 120%;
|
||||||
|
}
|
||||||
#op-list {
|
|
||||||
display: none;
|
#op-list {
|
||||||
padding: 20px;
|
display: none;
|
||||||
margin: 20px 10px 20px 10px;
|
padding: 20px;
|
||||||
background-color: #ffffff;
|
margin: 20px 10px 20px 10px;
|
||||||
font-size: 14px;
|
background-color: #ffffff;
|
||||||
border-radius: 5px;
|
font-size: 14px;
|
||||||
}
|
border-radius: 5px;
|
||||||
|
}
|
||||||
.op-item {
|
|
||||||
margin-bottom: 3px;
|
.op-item {
|
||||||
}
|
margin-bottom: 3px;
|
||||||
|
}
|
||||||
.time, .cmd {
|
|
||||||
font-family: Consolas, Lucida Console, Monaco, Courier, 'Courier New', monospace;
|
.time, .cmd {
|
||||||
line-height: 15px;
|
font-family: Consolas, Lucida Console, Monaco, Courier, 'Courier New', monospace;
|
||||||
padding: 0 5px;
|
line-height: 15px;
|
||||||
border-radius: 3px;
|
padding: 0 5px;
|
||||||
}
|
border-radius: 3px;
|
||||||
|
}
|
||||||
.time {
|
|
||||||
margin-right: 15px;
|
.time {
|
||||||
background-color: #d8d8d8;
|
margin-right: 15px;
|
||||||
}
|
background-color: #d8d8d8;
|
||||||
|
}
|
||||||
.cmd-danger {
|
|
||||||
background-color: #ffbba6;
|
.cmd-danger {
|
||||||
font-weight: bold;
|
background-color: #ffbba6;
|
||||||
}
|
font-weight: bold;
|
||||||
|
}
|
||||||
.cmd-info {
|
|
||||||
background-color: #b4fdb1;
|
.cmd-info {
|
||||||
}
|
background-color: #b4fdb1;
|
||||||
</style>
|
}
|
||||||
</%block>
|
</style>
|
||||||
|
</%block>
|
||||||
<div class="page-content">
|
|
||||||
<div id="no-op-msg">
|
<div class="page-content">
|
||||||
他悄悄地来,又悄悄地走,挥一挥衣袖,没有留下任何操作~~~~
|
<div id="no-op-msg">
|
||||||
</div>
|
他悄悄地来,又悄悄地走,挥一挥衣袖,没有留下任何操作~~~~
|
||||||
<div id="op-list"></div>
|
</div>
|
||||||
</div>
|
<div id="op-list"></div>
|
||||||
|
</div>
|
||||||
<%block name="embed_js">
|
|
||||||
<script type="text/javascript">
|
<%block name="embed_js">
|
||||||
|
<script type="text/javascript">
|
||||||
ywl.add_page_options(${page_param});
|
|
||||||
|
ywl.add_page_options(${page_param});
|
||||||
var danger_cmd = ['chmod', 'chown', 'kill', 'rm', 'su', 'sudo'];
|
|
||||||
var info_cmd = ['exit'];
|
var danger_cmd = ['chmod', 'chown', 'kill', 'rm', 'su', 'sudo'];
|
||||||
|
var info_cmd = ['exit'];
|
||||||
ywl.on_init = function (cb_stack, cb_args) {
|
|
||||||
if (ywl.page_options.count == 0) {
|
ywl.on_init = function (cb_stack, cb_args) {
|
||||||
$('#no-op-msg').show();
|
if (ywl.page_options.count === 0) {
|
||||||
} else {
|
$('#no-op-msg').show();
|
||||||
var dom_op_list = $('#op-list');
|
} else {
|
||||||
var html = [];
|
var header = ywl.page_options.header;
|
||||||
for (var i = 0; i < ywl.page_options.count; i++) {
|
$('#recorder-info').html(header.account + ' 于 ' + format_datetime(header.start) + ' 访问 ' + header.user_name + '@' + header.ip + ':' + header.port);
|
||||||
var cmd_list = ywl.page_options.op[i].c.split(' ');
|
|
||||||
|
var dom_op_list = $('#op-list');
|
||||||
var cmd_class = '';
|
var html = [];
|
||||||
if (_.intersection(cmd_list, danger_cmd).length > 0) {
|
for (var i = 0; i < ywl.page_options.count; i++) {
|
||||||
cmd_class = ' cmd-danger';
|
var cmd_list = ywl.page_options.op[i].c.split(' ');
|
||||||
} else if (_.intersection(cmd_list, info_cmd).length > 0) {
|
|
||||||
cmd_class = ' cmd-info';
|
var cmd_class = '';
|
||||||
}
|
if (_.intersection(cmd_list, danger_cmd).length > 0) {
|
||||||
|
cmd_class = ' cmd-danger';
|
||||||
html.push('<div class="op-item"><span class="time">' + ywl.page_options.op[i].t + '</span> <span class="cmd' + cmd_class + '">' + ywl.page_options.op[i].c + '</span></li></div>');
|
} else if (_.intersection(cmd_list, info_cmd).length > 0) {
|
||||||
}
|
cmd_class = ' cmd-info';
|
||||||
dom_op_list.append(html.join(''));
|
}
|
||||||
dom_op_list.show();
|
|
||||||
}
|
html.push('<div class="op-item"><span class="time">' + ywl.page_options.op[i].t + '</span> <span class="cmd' + cmd_class + '">' + ywl.page_options.op[i].c + '</span></div>');
|
||||||
cb_stack.exec();
|
}
|
||||||
};
|
dom_op_list.append(html.join(''));
|
||||||
</script>
|
dom_op_list.show();
|
||||||
|
}
|
||||||
|
cb_stack.exec();
|
||||||
|
};
|
||||||
|
</script>
|
||||||
</%block>
|
</%block>
|
Loading…
Reference in New Issue