rdp播放功能部分可用(支持播放FreeRDP的录像,但是不能播放MSCST的录像)。

pull/105/head
Apex Liu 2017-12-11 01:02:19 +08:00
parent a3e0fea4d4
commit d6bcdeb42d
10 changed files with 359 additions and 220 deletions

View File

@ -1174,92 +1174,124 @@ void TsHttpRpc::_rpc_func_rdp_play(const ex_astr& func_args, ex_astr& buf)
} }
// 判断参数是否正确 // 判断参数是否正确
if (!jsRoot["host"].isString()) // if (!jsRoot["host"].isString())
{ // {
_create_json_ret(buf, TPE_PARAM); // _create_json_ret(buf, TPE_PARAM);
return; // return;
} // }
if (!jsRoot["port"].isInt()) // if (!jsRoot["port"].isInt())
{ // {
_create_json_ret(buf, TPE_PARAM); // _create_json_ret(buf, TPE_PARAM);
return; // return;
} // }
if (!jsRoot["tail"].isString())
if (!jsRoot["rid"].isInt()
|| !jsRoot["web"].isString()
|| !jsRoot["sid"].isString()
|| !jsRoot["user"].isString()
|| !jsRoot["acc"].isString()
|| !jsRoot["host"].isString()
|| !jsRoot["start"].isString()
)
{ {
_create_json_ret(buf, TPE_PARAM); _create_json_ret(buf, TPE_PARAM);
return; return;
} }
// if (!jsRoot["tail"].isString())
// {
// _create_json_ret(buf, TPE_PARAM);
// return;
// }
int rid = jsRoot["rid"].asInt();
ex_astr a_url_base = jsRoot["web"].asCString();
ex_astr a_sid = jsRoot["sid"].asCString();
ex_astr a_user = jsRoot["user"].asCString();
ex_astr a_acc = jsRoot["acc"].asCString();
ex_astr a_host = jsRoot["host"].asCString(); ex_astr a_host = jsRoot["host"].asCString();
int port = jsRoot["port"].asInt(); ex_astr a_start = jsRoot["start"].asCString();
ex_astr a_tail = jsRoot["tail"].asCString(); //ex_astr a_tail = jsRoot["tail"].asCString();
ex_astr server_ip;
if (isIPAddress(a_host.c_str()))
{
server_ip = a_host;
}
else
{
char *ptr, **pptr;
struct hostent *hptr;
char IP[128] = { 0 };
/* 取得命令后第一个参数,即要解析的域名或主机名 */
ptr = (char*)a_host.c_str();
/* 调用gethostbyname()。调用结果都存在hptr中 */
if ((hptr = gethostbyname(ptr)) == NULL)
{
//printf("gethostbyname error for host:%s/n", ptr);
_create_json_ret(buf, TPE_PARAM);
return;
}
/* 将主机的规范名打出来 */
//printf("official hostname:%s/n", hptr->h_name);
/* 主机可能有多个别名,将所有别名分别打出来 */
//for (pptr = hptr->h_aliases; *pptr != NULL; pptr++)
// printf(" alias:%s/n", *pptr);
/* 根据地址类型,将地址打出来 */
char szbuf[1204] = { 0 };
switch (hptr->h_addrtype)
{
case AF_INET:
case AF_INET6:
pptr = hptr->h_addr_list;
/* 将刚才得到的所有地址都打出来。其中调用了inet_ntop()函数 */
for (; *pptr != NULL; pptr++) char cmd_args[1024] = { 0 };
inet_ntop(hptr->h_addrtype, *pptr, IP, sizeof(IP)); ex_strformat(cmd_args, 1023, "%d \"%s\" \"%09d-%s-%s-%s-%s\"", rid, a_sid.c_str(), rid, a_user.c_str(), a_acc.c_str(), a_host.c_str(), a_start.c_str());
server_ip = IP;
break;
default:
printf("unknown address type/n");
break;
}
}
char szURL[256] = { 0 };
sprintf_s(szURL, 256, "http://%s:%d/%s", server_ip.c_str(), port, a_tail.c_str());
ex_astr a_url = szURL;
ex_wstr w_url;
ex_astr2wstr(a_url, w_url);
char szHost[256] = { 0 };
sprintf_s(szHost, 256, "%s:%d", a_host.c_str(), port);
a_host = szHost; // ex_astr a_host = jsRoot["host"].asCString();
ex_wstr w_host; // int port = jsRoot["port"].asInt();
ex_astr2wstr(a_host, w_host); // ex_astr a_tail = jsRoot["tail"].asCString();
// ex_astr server_ip;
// if (isIPAddress(a_host.c_str()))
// {
// server_ip = a_host;
// }
// else
// {
// char *ptr, **pptr;
// struct hostent *hptr;
// char IP[128] = { 0 };
// // 取得命令后第一个参数,即要解析的域名或主机名
// ptr = (char*)a_host.c_str();
// // 调用gethostbyname()。调用结果都存在hptr中
// if ((hptr = gethostbyname(ptr)) == NULL)
// {
// //printf("gethostbyname error for host:%s/n", ptr);
// _create_json_ret(buf, TPE_PARAM);
// return;
// }
// // 将主机的规范名打出来
// //printf("official hostname:%s/n", hptr->h_name);
// // 主机可能有多个别名,将所有别名分别打出来
// //for (pptr = hptr->h_aliases; *pptr != NULL; pptr++)
// // printf(" alias:%s/n", *pptr);
// // 根据地址类型,将地址打出来
// char szbuf[1204] = { 0 };
// switch (hptr->h_addrtype)
// {
// case AF_INET:
// case AF_INET6:
// pptr = hptr->h_addr_list;
// // 将刚才得到的所有地址都打出来。其中调用了inet_ntop()函数
//
// for (; *pptr != NULL; pptr++)
// inet_ntop(hptr->h_addrtype, *pptr, IP, sizeof(IP));
// server_ip = IP;
// break;
// default:
// printf("unknown address type/n");
// break;
// }
// }
// char szURL[256] = { 0 };
// sprintf_s(szURL, 256, "http://%s:%d/%s", server_ip.c_str(), port, a_tail.c_str());
// ex_astr a_url = szURL;
ex_wstr w_url_base;
ex_astr2wstr(a_url_base, w_url_base);
ex_wstr w_cmd_args;
ex_astr2wstr(cmd_args, w_cmd_args);
// char szHost[256] = { 0 };
// sprintf_s(szHost, 256, "%s:%d", a_host.c_str(), port);
//
// a_host = szHost;
// ex_wstr w_host;
// ex_astr2wstr(a_host, w_host);
ex_wstr w_exe_path; ex_wstr w_exe_path;
w_exe_path = _T("\""); w_exe_path = _T("\"");
w_exe_path += g_env.m_tools_path + _T("\\tprdp\\tprdp-replay.exe\""); w_exe_path += g_env.m_tools_path + _T("\\tprdp\\tprdp-replay.exe\"");
w_exe_path += _T(" "); w_exe_path += _T(" \"");
w_exe_path += w_url; w_exe_path += w_url_base;
w_exe_path += _T("\" ");
w_exe_path += _T(" "); w_exe_path += w_cmd_args;
w_exe_path += w_host;
Json::Value root_ret; Json::Value root_ret;
ex_astr utf8_path; ex_astr utf8_path;
ex_wstr2astr(w_exe_path, utf8_path, EX_CODEPAGE_UTF8); ex_wstr2astr(w_exe_path, utf8_path, EX_CODEPAGE_UTF8);
root_ret["path"] = utf8_path; root_ret["cmdline"] = utf8_path;
STARTUPINFO si; STARTUPINFO si;
PROCESS_INFORMATION pi; PROCESS_INFORMATION pi;

View File

@ -1,6 +1,8 @@
#ifndef __TS_HTTP_RPC_H__ #ifndef __TS_HTTP_RPC_H__
#define __TS_HTTP_RPC_H__ #define __TS_HTTP_RPC_H__
#include "../../external/mongoose/mongoose.h"
#include "ts_const.h" #include "ts_const.h"
#include <vector> #include <vector>
@ -10,7 +12,6 @@
#include <ex.h> #include <ex.h>
#include <json/json.h> #include <json/json.h>
#include "../../external/mongoose/mongoose.h"
/* /*
//================================================================= //=================================================================

View File

@ -54,6 +54,9 @@ int ts_web_rpc_get_conn_info(int conn_id, TS_CONNECT_INFO& info)
// EXLOGV("\n"); // EXLOGV("\n");
return TPE_NETWORK; return TPE_NETWORK;
} }
if (body.length() == 0) {
return TPE_NETWORK;
}
Json::Reader jreader; Json::Reader jreader;
Json::Value jret; Json::Value jret;

View File

@ -27,21 +27,11 @@ $app.create_controls = function (cb_stack) {
dom_id: 'table-record', dom_id: 'table-record',
data_source: { data_source: {
type: 'ajax-post' type: 'ajax-post'
,url: '/audit/get-records' , url: '/audit/get-records'
//exclude: {'state': [TP_SESS_STAT_RUNNING, TP_SESS_STAT_STARTED]} //exclude: {'state': [TP_SESS_STAT_RUNNING, TP_SESS_STAT_STARTED]}
}, },
column_default: {sort: false, align: 'left'}, column_default: {sort: false, align: 'left'},
columns: [ columns: [
// {
// // title: '<input type="checkbox" id="user-list-select-all" value="">',
// title: '<a href="javascript:;" data-reset-filter><i class="fa fa-rotate-left fa-fw"></i></a>',
// key: 'chkbox',
// sort: false,
// width: 36,
// align: 'center',
// render: 'make_check_box',
// fields: {id: 'id'}
// },
{ {
title: 'ID', title: 'ID',
key: 'id', key: 'id',
@ -59,24 +49,17 @@ $app.create_controls = function (cb_stack) {
{ {
title: '用户', title: '用户',
key: 'user', key: 'user',
//sort: true,
//header_render: 'filter_search_host',
render: 'user', render: 'user',
fields: {user_username: 'user_username', user_surname: 'user_surname'} fields: {user_username: 'user_username', user_surname: 'user_surname'}
}, },
{ {
title: '来源', title: '来源',
key: 'client_ip', key: 'client_ip',
//sort: true,
//header_render: 'filter_search_host',
//render: 'host_info',
fields: {client_ip: 'client_ip'} fields: {client_ip: 'client_ip'}
}, },
{ {
title: '远程连接', title: '远程连接',
key: 'remote', key: 'remote',
//sort: true,
//header_render: 'filter_search_host',
render: 'remote', render: 'remote',
fields: {acc_username: 'acc_username', host_ip: 'host_ip', conn_ip: 'conn_ip', conn_port: 'conn_port'} fields: {acc_username: 'acc_username', host_ip: 'host_ip', conn_ip: 'conn_ip', conn_port: 'conn_port'}
}, },
@ -85,10 +68,6 @@ $app.create_controls = function (cb_stack) {
key: 'protocol_type', key: 'protocol_type',
align: 'center', align: 'center',
width: 80, width: 80,
// align: 'center',
// width: 36,
//sort: true
// header_render: 'filter_os',
render: 'protocol', render: 'protocol',
fields: {protocol_type: 'protocol_type', protocol_sub_type: 'protocol_sub_type'} fields: {protocol_type: 'protocol_type', protocol_sub_type: 'protocol_sub_type'}
}, },
@ -125,12 +104,12 @@ $app.create_controls = function (cb_stack) {
render: 'record_action', render: 'record_action',
fields: {id: 'id', state: 'state', time_end: 'time_end', protocol_sub_type: 'protocol_sub_type'} fields: {id: 'id', state: 'state', time_end: 'time_end', protocol_sub_type: 'protocol_sub_type'}
} }
], ]
// 重载回调函数 // 重载回调函数
on_header_created: $app.on_table_host_header_created, //,on_header_created: $app.on_table_host_header_created
on_render_created: $app.on_table_host_render_created, , on_render_created: $app.on_table_host_render_created
on_cell_created: $app.on_table_host_cell_created , on_cell_created: $app.on_table_host_cell_created
}; };
$app.table_record = $tp.create_table(table_record_options); $app.table_record = $tp.create_table(table_record_options);
@ -141,10 +120,10 @@ $app.create_controls = function (cb_stack) {
//------------------------------- //-------------------------------
// 用户列表相关过滤器 // 用户列表相关过滤器
//------------------------------- //-------------------------------
$tp.create_table_header_filter_search($app.table_record, { // $tp.create_table_header_filter_search($app.table_record, {
name: 'search', // name: 'search',
place_holder: '搜索主机IP/名称/描述/资产编号/等等...' // place_holder: '搜索主机IP/名称/描述/资产编号/等等...'
}); // });
// $app.table_record_role_filter = $tp.create_table_filter_role($app.table_record, $app.role_list); // $app.table_record_role_filter = $tp.create_table_filter_role($app.table_record, $app.role_list);
// $tp.create_table_header_filter_state($app.table_record, 'state', $app.obj_states, [TP_STATE_LOCKED]); // $tp.create_table_header_filter_state($app.table_record, 'state', $app.obj_states, [TP_STATE_LOCKED]);
// 从cookie中读取用户分页限制的选择 // 从cookie中读取用户分页限制的选择
@ -168,11 +147,12 @@ $app.create_controls = function (cb_stack) {
}; };
$app.on_table_host_cell_created = function (tbl, row_id, col_key, cell_obj) { $app.on_table_host_cell_created = function (tbl, row_id, col_key, cell_obj) {
if (col_key === 'chkbox') { // if (col_key === 'chkbox') {
cell_obj.find('[data-check-box]').click(function () { // cell_obj.find('[data-check-box]').click(function () {
$app.check_host_all_selected(); // $app.check_host_all_selected();
}); // });
} else if (col_key === 'action') { // } else
if (col_key === 'action') {
// 绑定系统选择框事件 // 绑定系统选择框事件
cell_obj.find('[data-action]').click(function () { cell_obj.find('[data-action]').click(function () {
@ -183,7 +163,8 @@ $app.on_table_host_cell_created = function (tbl, row_id, col_key, cell_obj) {
if (action === 'replay') { if (action === 'replay') {
//$app.dlg_edit_host.show_edit(row_id); //$app.dlg_edit_host.show_edit(row_id);
if (row_data.protocol_type === TP_PROTOCOL_TYPE_RDP) { if (row_data.protocol_type === TP_PROTOCOL_TYPE_RDP) {
$tp.notify_error('sorry, not impl.'); // $tp.notify_error('sorry, not impl.');
$app.do_replay_rdp(row_data.id, row_data.user_username, row_data.acc_username, row_data.host_ip, row_data.time_begin);
} else if (row_data.protocol_type === TP_PROTOCOL_TYPE_SSH) { } else if (row_data.protocol_type === TP_PROTOCOL_TYPE_SSH) {
window.open('/audit/replay/' + row_data.protocol_type + '/' + row_data.id); window.open('/audit/replay/' + row_data.protocol_type + '/' + row_data.id);
} }
@ -206,36 +187,36 @@ $app.on_table_host_cell_created = function (tbl, row_id, col_key, cell_obj) {
}; };
$app.on_table_host_render_created = function (render) { $app.on_table_host_render_created = function (render) {
render.filter_host_state = function (header, title, col) { // render.filter_host_state = function (header, title, col) {
var _ret = ['<div class="tp-table-filter tp-table-filter-' + col.cell_align + '">']; // var _ret = ['<div class="tp-table-filter tp-table-filter-' + col.cell_align + '">'];
_ret.push('<div class="tp-table-filter-inner">'); // _ret.push('<div class="tp-table-filter-inner">');
_ret.push('<div class="search-title">' + title + '</div>'); // _ret.push('<div class="search-title">' + title + '</div>');
//
// // 表格内嵌过滤器的DOM实体在这时生成
// var filter_ctrl = header._table_ctrl.get_filter_ctrl('state');
// _ret.push(filter_ctrl.render());
//
// _ret.push('</div></div>');
//
// return _ret.join('');
// };
//
// render.filter_search_host = function (header, title, col) {
// var _ret = ['<div class="tp-table-filter tp-table-filter-input">'];
// _ret.push('<div class="tp-table-filter-inner">');
// _ret.push('<div class="search-title">' + title + '</div>');
//
// // 表格内嵌过滤器的DOM实体在这时生成
// var filter_ctrl = header._table_ctrl.get_filter_ctrl('search');
// _ret.push(filter_ctrl.render());
//
// _ret.push('</div></div>');
//
// return _ret.join('');
// };
// 表格内嵌过滤器的DOM实体在这时生成 render.sid = function (row_id, fields) {
var filter_ctrl = header._table_ctrl.get_filter_ctrl('state'); return '<span class="mono">' + fields.sid + '</span>';
_ret.push(filter_ctrl.render());
_ret.push('</div></div>');
return _ret.join('');
};
render.filter_search_host = function (header, title, col) {
var _ret = ['<div class="tp-table-filter tp-table-filter-input">'];
_ret.push('<div class="tp-table-filter-inner">');
_ret.push('<div class="search-title">' + title + '</div>');
// 表格内嵌过滤器的DOM实体在这时生成
var filter_ctrl = header._table_ctrl.get_filter_ctrl('search');
_ret.push(filter_ctrl.render());
_ret.push('</div></div>');
return _ret.join('');
};
render.sid = function(row_id, fields) {
return '<span class="mono">'+fields.sid+'</span>';
}; };
render.user = function (row_id, fields) { render.user = function (row_id, fields) {
@ -270,7 +251,6 @@ $app.on_table_host_render_created = function (render) {
}; };
render.time_begin = function (row_id, fields) { render.time_begin = function (row_id, fields) {
// return tp_format_datetime(tp_utc2local(fields.time_begin), 'MM-dd HH:mm:ss');
return tp_format_datetime(tp_utc2local(fields.time_begin), 'MM-dd HH:mm:ss'); return tp_format_datetime(tp_utc2local(fields.time_begin), 'MM-dd HH:mm:ss');
}; };
@ -373,60 +353,84 @@ $app.on_table_host_render_created = function (render) {
}; };
}; };
$app.on_table_host_header_created = function (header) { $app.do_replay_rdp = function (record_id, user_username, acc_username, host_ip, time_begin) {
$('#' + header._table_ctrl.dom_id + ' a[data-reset-filter]').click(function () { $assist.do_rdp_replay(
CALLBACK_STACK.create() {
.add(header._table_ctrl.load_data) rid: record_id
.add(header._table_ctrl.reset_filters) // , web: $tp.web_server // + '/audit/get_rdp_record/' + record_id // 'http://' + ip + ':' + port + '/log/replay/rdp/' + record_id;
.exec(); // , sid: Cookies.get('_sid')
}); , user: user_username
, acc: acc_username
// 表格内嵌过滤器的事件绑定在这时进行(也可以延期到整个表格创建完成时进行) , host: host_ip
header._table_ctrl.get_filter_ctrl('search').on_created(); , start: time_begin//tp_format_datetime(tp_utc2local(time_begin), 'yyyyMMdd-HHmmss')
};
$app.get_selected_record = function (tbl) {
var records = [];
var _objs = $('#' + $app.table_record.dom_id + ' tbody tr td input[data-check-box]');
$.each(_objs, function (i, _obj) {
if ($(_obj).is(':checked')) {
var _row_data = tbl.get_row(_obj);
records.push(_row_data.id);
} }
}); , function () {
return records; // func_success
}
, function (code, message) {
if (code === TPE_NO_ASSIST)
$assist.alert_assist_not_found();
else
$tp.notify_error('播放RDP操作录像失败' + tp_error_msg(code, message));
}
);
}; };
$app.on_btn_remove_record_click = function () {
// var records = $app.get_selected_record($app.table_record); // $app.on_table_host_header_created = function (header) {
// if (records.length === 0) { // $('#' + header._table_ctrl.dom_id + ' a[data-reset-filter]').click(function () {
// $tp.notify_error('请选择要删除的会话记录!'); // CALLBACK_STACK.create()
// return; // .add(header._table_ctrl.load_data)
// } // .add(header._table_ctrl.reset_filters)
// // .exec();
// var _fn_sure = function (cb_stack, cb_args) { // });
// $tp.ajax_post_json('/user/remove-user', {users: users}, //
// function (ret) { // // 表格内嵌过滤器的事件绑定在这时进行(也可以延期到整个表格创建完成时进行)
// if (ret.code === TPE_OK) { // header._table_ctrl.get_filter_ctrl('search').on_created();
// cb_stack.add($app.check_host_all_selected); // };
// cb_stack.add($app.table_record.load_data);
// $tp.notify_success('删除用户账号操作成功!'); // $app.get_selected_record = function (tbl) {
// } else { // var records = [];
// $tp.notify_error('删除用户账号操作失败:' + tp_error_msg(ret.code, ret.message)); // var _objs = $('#' + $app.table_record.dom_id + ' tbody tr td input[data-check-box]');
// } // $.each(_objs, function (i, _obj) {
// // if ($(_obj).is(':checked')) {
// cb_stack.exec(); // var _row_data = tbl.get_row(_obj);
// }, // records.push(_row_data.id);
// function () { // }
// $tp.notify_error('网络故障,删除用户账号操作失败!'); // });
// cb_stack.exec(); // return records;
// } // };
// );
// }; // $app.on_btn_remove_record_click = function () {
// // var records = $app.get_selected_record($app.table_record);
// var cb_stack = CALLBACK_STACK.create(); // if (records.length === 0) {
// $tp.dlg_confirm(cb_stack, { // $tp.notify_error('请选择要删除的会话记录!');
// msg: '<div class="alert alert-danger"><p><strong>注意:删除操作不可恢复!!</strong></p><p>删除用户账号将同时将其从所在用户组中移除,并且删除所有分配给此用户的授权!</p></div><p>如果您希望禁止某个用户登录本系统,可对其进行“禁用”操作!</p><p>您确定要移除所有选定的 <strong>' + user_list.length + '个</strong> 用户账号吗?</p>', // return;
// fn_yes: _fn_sure // }
// }); //
}; // var _fn_sure = function (cb_stack, cb_args) {
// $tp.ajax_post_json('/user/remove-user', {users: users},
// function (ret) {
// if (ret.code === TPE_OK) {
// cb_stack.add($app.check_host_all_selected);
// cb_stack.add($app.table_record.load_data);
// $tp.notify_success('删除用户账号操作成功!');
// } else {
// $tp.notify_error('删除用户账号操作失败:' + tp_error_msg(ret.code, ret.message));
// }
//
// cb_stack.exec();
// },
// function () {
// $tp.notify_error('网络故障,删除用户账号操作失败!');
// cb_stack.exec();
// }
// );
// };
//
// var cb_stack = CALLBACK_STACK.create();
// $tp.dlg_confirm(cb_stack, {
// msg: '<div class="alert alert-danger"><p><strong>注意:删除操作不可恢复!!</strong></p><p>删除用户账号将同时将其从所在用户组中移除,并且删除所有分配给此用户的授权!</p></div><p>如果您希望禁止某个用户登录本系统,可对其进行“禁用”操作!</p><p>您确定要移除所有选定的 <strong>' + user_list.length + '个</strong> 用户账号吗?</p>',
// fn_yes: _fn_sure
// });
// };

View File

@ -53,13 +53,11 @@ var CALLBACK_STACK = {
} }
}; };
// console.log(window.location, window.location.protocol+'://'+window.location.host); // console.log(window.location, window.location.protocol+'://'+window.location.host);
// Teleport核心JS // Teleport核心JS
var $tp = { var $tp = {
web_server: window.location.protocol+'://'+window.location.host web_server: window.location.protocol+'//'+window.location.host
// Teleport页面应用对象放置页面自身特有的属性和函数 // Teleport页面应用对象放置页面自身特有的属性和函数
, app: { , app: {
@ -79,28 +77,6 @@ $tp.init = function () {
{id: TP_STATE_LOCKED, name: '临时锁定', style: 'warning'} {id: TP_STATE_LOCKED, name: '临时锁定', style: 'warning'}
]; ];
// $app.user_states = [
// {id: 1, name: '正常', style: 'success'},
// {id: 2, name: '临时锁定', style: 'warning'},
// {id: 3, name: '禁用', style: 'danger'}
// ];
//
// $app.acc_states = [
// {id: 1, name: '正常', style: 'success'},
// {id: 2, name: '临时锁定', style: 'warning'},
// {id: 3, name: '禁用', style: 'danger'}
// ];
//
// $app.host_states = [
// {id: 1, name: '正常', style: 'success'},
// {id: 2, name: '禁用', style: 'danger'}
// ];
//
// $app.policy_states = [
// {id: 1, name: '正常', style: 'success'},
// {id: 2, name: '禁用', style: 'danger'}
// ];
$app.host_types = [ $app.host_types = [
{id: 1, name: '物理主机', style: 'success'}, {id: 1, name: '物理主机', style: 'success'},
{id: 2, name: '虚拟主机', style: 'info'}, {id: 2, name: '虚拟主机', style: 'info'},

View File

@ -839,7 +839,8 @@ $tp.create_table_header = function (tbl, on_created) {
if (_.isFunction(on_created)) if (_.isFunction(on_created))
on_created(_tbl_header); on_created(_tbl_header);
else if (!_.isUndefined(on_created)) //else if (!_.isUndefined(on_created))
else if (!_.isNull(on_created))
console.error('create table header, on_created() is not callable.'); console.error('create table header, on_created() is not callable.');
cb_stack.exec(); cb_stack.exec();

View File

@ -27,7 +27,7 @@ $assist.init = function (cb_stack) {
$assist.running = true; $assist.running = true;
$assist.version = ret.version; $assist.version = ret.version;
if(_.isFunction($tp.assist_checked)) { if (_.isFunction($tp.assist_checked)) {
$tp.assist_checked(); $tp.assist_checked();
} }
// if (version_compare()) { // if (version_compare()) {
@ -38,7 +38,7 @@ $assist.init = function (cb_stack) {
}, },
error: function () { error: function () {
$assist.running = false; $assist.running = false;
if(_.isFunction($tp.assist_checked)) { if (_.isFunction($tp.assist_checked)) {
$tp.assist_checked(); $tp.assist_checked();
} }
// func_error({}, TPE_NO_ASSIST, '无法连接到teleport助手可能尚未启动'); // func_error({}, TPE_NO_ASSIST, '无法连接到teleport助手可能尚未启动');
@ -120,7 +120,7 @@ $assist.do_teleport = function (args, func_success, func_error) {
jsonp: 'callback', jsonp: 'callback',
dataType: 'json', dataType: 'json',
success: function (ret) { success: function (ret) {
if(ret.code === TPE_OK) { if (ret.code === TPE_OK) {
func_success(); func_success();
} else { } else {
func_error(ret.code, ret.message); func_error(ret.code, ret.message);
@ -144,6 +144,45 @@ $assist.do_teleport = function (args, func_success, func_error) {
}); });
}; };
$assist.do_rdp_replay = function (args, func_success, func_error) {
// ==================================================
// args is dict with fields shown below:
// rid: (int) - record-id in database.
// user: (string) - who did the RDP connection.
// acc: (string) - account to login to remote RDP server.
// host: (string) - IP of the remote RDP server.
// start: (string) - when start the RDP connection, should be a UTC timestamp.
// ==================================================
// now fix the args.
args.web = $tp.web_server; // (string) - teleport server base address, like "http://127.0.0.1:7190", without end-slash.
args.sid = Cookies.get('_sid'); // (string) - current login user's session-id.
args.start = tp_format_datetime(tp_utc2local(args.start), 'yyyyMMdd-HHmmss'); // (string) - convert UTC timestamp to local human-readable string.
console.log('do-rdp-replay:', args);
var args_ = encodeURIComponent(JSON.stringify(args));
$.ajax({
type: 'GET',
timeout: 6000,
url: $assist.api_url + '/rdp_play/' + args_,
jsonp: 'callback',
dataType: 'json',
success: function (ret) {
console.log('ret', ret);
if (ret.code === TPE_OK) {
func_success();
} else {
// func_error(ret.code, '查看远程桌面操作录像失败!');
func_error(ret.code, ret.message);
}
},
error: function () {
func_error(TPE_NO_ASSIST, '无法连接到teleport助手可能尚未启动');
}
});
};
/* /*
var version_compare = function () { var version_compare = function () {

View File

@ -6,6 +6,7 @@
<%inherit file="../page_base.mako"/> <%inherit file="../page_base.mako"/>
<%block name="extend_js_file"> <%block name="extend_js_file">
<script type="text/javascript" src="${ static_url('js/tp-assist.js') }"></script>
<script type="text/javascript" src="${ static_url('js/audit/record-list.js') }"></script> <script type="text/javascript" src="${ static_url('js/audit/record-list.js') }"></script>
</%block> </%block>

View File

@ -183,6 +183,9 @@ controllers = [
# - [json] 读取录像数据 # - [json] 读取录像数据
(r'/audit/get-record-data', audit.DoGetRecordDataHandler), (r'/audit/get-record-data', audit.DoGetRecordDataHandler),
# - 读取录像文件用于RDP录像回放
(r'/audit/get-file', audit.DoGetFileHandler),
# (r'/host/export-host', host.ExportHostHandler), # (r'/host/export-host', host.ExportHostHandler),
# (r'/config/export-database', config.ExportDatabaseHandler), # (r'/config/export-database', config.ExportDatabaseHandler),
# (r'/config/import-database', config.ImportDatabaseHandler), # (r'/config/import-database', config.ImportDatabaseHandler),

View File

@ -274,3 +274,82 @@ class DoGetRecordDataHandler(TPBaseJsonHandler):
data_list, data_size, err = record.read_record_data(record_id, offset) data_list, data_size, err = record.read_record_data(record_id, offset)
self.write_json(err, data={'data_list': data_list, 'data_size': data_size}) self.write_json(err, data={'data_list': data_list, 'data_size': data_size})
class DoGetFileHandler(TPBaseHandler):
@tornado.gen.coroutine
def get(self):
log.v('--{}\n'.format(self.request.uri))
require_privilege = TP_PRIVILEGE_OPS | TP_PRIVILEGE_OPS_AUZ | TP_PRIVILEGE_AUDIT_AUZ | TP_PRIVILEGE_AUDIT_OPS_HISTORY
# sid = self.get_argument('sid', None)
# if sid is None:
# self.set_status(403)
# return self.write('need login first.')
#
# self._s_id = sid
# _user = self.get_session('user')
# if _user is None:
# self.set_status(403)
# return self.write('need login first.')
# self._user = _user
if not self._user['_is_login']:
self.set_status(401) # 401=未授权, 要求身份验证
return self.write('need login first.')
if (self._user['privilege'] & require_privilege) == 0:
self.set_status(403) # 403=禁止
return self.write('you have no such privilege.')
act = self.get_argument('act', None)
_type = self.get_argument('type', None)
rid = self.get_argument('rid', None)
filename = self.get_argument('f', None)
offset = int(self.get_argument('offset', '0'))
length = int(self.get_argument('length', '-1')) # -1 means read all content.
if act is None or _type is None or rid is None or filename is None:
self.set_status(400) # 400=错误请求
return self.write('invalid param, `rid` and `f` must present.')
if act not in ['size', 'read']:
self.set_status(400)
return self.write('invalid param, `act` should be `size` or `read`.')
if _type not in ['rdp', 'ssh', 'telnet']:
self.set_status(400)
return self.write('invalid param, `type` should be `rdp`, `ssh` or `telnet`.')
file = os.path.join(get_cfg().core.replay_path, 'rdp', '{:09d}'.format(int(rid)), filename)
if not os.path.exists(file):
self.set_status(404)
return self.write('file does not exists.')
file_size = os.path.getsize(file)
if act == 'size':
log.d('--return size:{}\n'.format(file_size))
return self.write('{}'.format(file_size))
if offset >= file_size:
self.set_status(416) # 416=请求范围不符合要求
return self.write('no more data.')
# we read most 4096 bytes one time.
BULK_SIZE = 4096
total_need = file_size - offset
if length != -1 and length < total_need:
total_need = length
total_read = 0
with open(file, 'rb') as f:
f.seek(offset)
read_this_time = BULK_SIZE if total_need > BULK_SIZE else total_need
while read_this_time > 0:
self.write(f.read(read_this_time))
total_read += read_this_time
if total_read >= total_need:
break
read_left = total_need - total_read
read_this_time = BULK_SIZE if read_left > BULK_SIZE else read_left
# all need data read.