mirror of https://github.com/tp4a/teleport
commit
26d0b79017
|
@ -88,16 +88,35 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmd
|
|||
if (0 == g_ulSingleInstanceMsgId)
|
||||
return FALSE;
|
||||
|
||||
LPWSTR szCmdLine=(LPWSTR)::GetCommandLineW(); //获取命令行参数;
|
||||
g_argv=CommandLineToArgvW(szCmdLine, &g_argc); //拆分命令行参数字符串;
|
||||
|
||||
LPWSTR szCmdLine=(LPWSTR)::GetCommandLineW(); //获取命令行参数;
|
||||
g_argv=CommandLineToArgvW(szCmdLine, &g_argc); //拆分命令行参数字符串;
|
||||
std::wstring arg;
|
||||
for (int i=0; i < g_argc; ++i) {
|
||||
arg = g_argv[i];
|
||||
if (0 == lstrcmp(g_argv[i], _T("--stop"))) {
|
||||
PostMessage(HWND_BROADCAST, g_ulSingleInstanceMsgId, WMU_INSTANCE_EXIT, 0);
|
||||
LocalFree(g_argv);
|
||||
g_argv=NULL;
|
||||
return -1;
|
||||
}
|
||||
}else if (arg.find(L"teleport_ip",0) !=std::wstring::npos && arg.find(L"teleport_port") != std::wstring::npos && arg.find(L"remote_host_ip") != std::wstring::npos && arg.find(L"session_id") != std::wstring::npos) {
|
||||
//把wchar_t **转换为std::string
|
||||
size_t len = wcslen(g_argv[i]) + 1;
|
||||
size_t converted = 0;
|
||||
char *CStr;
|
||||
CStr = (char*)malloc(len * sizeof(char));
|
||||
wcstombs_s(&converted, CStr, len, g_argv[i], _TRUNCATE);
|
||||
std::string func_args = CStr;
|
||||
|
||||
//调用TsHttpRpc类里的_rpc_func_run_client启动客户端
|
||||
TsHttpRpc ts_http_rpc;
|
||||
ex_astr buf;
|
||||
ts_http_rpc._rpc_func_url_protocol(func_args, buf);
|
||||
|
||||
free(CStr);
|
||||
LocalFree(g_argv);
|
||||
g_argv = NULL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// make sure run single instance.
|
||||
|
|
|
@ -17,22 +17,22 @@
|
|||
|
||||
/*
|
||||
1.
|
||||
SecureCRT支持设置标签页的标题,命令行参数 /N "tab name"就可以
|
||||
SecureCRT支持设置标签页的标题,命令行参数 /N "tab name"就可以
|
||||
Example:
|
||||
To launch a new Telnet session, displaying the name "Houston, TX" on the tab, use the following:
|
||||
/T /N "Houston, TX" /TELNET 192.168.0.6
|
||||
|
||||
2.
|
||||
多次启动的SecureCRT放到一个窗口的不同标签页中,使用参数: /T
|
||||
多次启动的SecureCRT放到一个窗口的不同标签页中,使用参数: /T
|
||||
SecureCRT.exe /T /N "TP#ssh://192.168.1.3" /SSH2 /L root /PASSWORD 1234 120.26.109.25
|
||||
|
||||
3.
|
||||
telnet客户端的启动:
|
||||
telnet客户端的启动:
|
||||
putty.exe telnet://administrator@127.0.0.1:52389
|
||||
如果是SecureCRT,则需要
|
||||
如果是SecureCRT,则需要
|
||||
SecureCRT.exe /T /N "TP#telnet://192.168.1.3" /SCRIPT X:\path\to\startup.vbs /TELNET 127.0.0.1 52389
|
||||
其中,startup.vbs的内容为:
|
||||
---------文件开始---------
|
||||
其中,startup.vbs的内容为:
|
||||
---------文件开始---------
|
||||
#$language = "VBScript"
|
||||
#$interface = "1.0"
|
||||
Sub main
|
||||
|
@ -41,11 +41,11 @@ Sub main
|
|||
crt.Screen.Send "SESSION-ID" & VbCr
|
||||
crt.Screen.Synchronous = False
|
||||
End Sub
|
||||
---------文件结束---------
|
||||
---------文件结束---------
|
||||
|
||||
4. 为了让putty的窗口标签显示正常的IP,可以尝试在连接成功后,主动向服务端发送下列命令:
|
||||
4. 为了让putty的窗口标签显示正常的IP,可以尝试在连接成功后,主动向服务端发送下列命令:
|
||||
PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@192.168.1.2: \w\a\]$PS1"
|
||||
手工测试了,ubuntu服务器可以,不知道是否能够支持所有的Linux。SecureCRT对此表示忽略。
|
||||
手工测试了,ubuntu服务器可以,不知道是否能够支持所有的Linux。SecureCRT对此表示忽略。
|
||||
*/
|
||||
|
||||
//#define RDP_CLIENT_SYSTEM_BUILTIN
|
||||
|
@ -208,6 +208,40 @@ bool calc_psw51b(const char* password, std::string& ret) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool isDegital(std::string str) {
|
||||
for (int i = 0; i < str.size(); i++) {
|
||||
if (str.at(i) == '-' && str.size() > 1) // 有可能出现负数
|
||||
continue;
|
||||
if (str.at(i) > '9' || str.at(i) < '0')
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string strtolower(std::string str) {
|
||||
for (int i = 0; i < str.size(); i++)
|
||||
{
|
||||
str[i] = tolower(str[i]);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
void SplitString(const std::string& s, std::vector<std::string>& v, const std::string& c)
|
||||
{
|
||||
std::string::size_type pos1, pos2;
|
||||
pos2 = s.find(c);
|
||||
pos1 = 0;
|
||||
while (std::string::npos != pos2)
|
||||
{
|
||||
v.push_back(s.substr(pos1, pos2 - pos1));
|
||||
|
||||
pos1 = pos2 + c.size();
|
||||
pos2 = s.find(c, pos1);
|
||||
}
|
||||
if (pos1 != s.length())
|
||||
v.push_back(s.substr(pos1));
|
||||
}
|
||||
|
||||
TsHttpRpc::TsHttpRpc() {
|
||||
m_stop = false;
|
||||
mg_mgr_init(&m_mg_mgr, nullptr);
|
||||
|
@ -344,7 +378,7 @@ void TsHttpRpc::_mg_event_handler(struct mg_connection *nc, int ev, void *ev_dat
|
|||
bool b_is_index = false;
|
||||
|
||||
if (uri == "/") {
|
||||
ex_wstr page = L"<html lang=\"zh_CN\"><head><meta charset=\"utf-8\"/><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/><title>Teleport助手</title>\n<style type=\"text/css\">\n.box{padding:20px;margin:40px;border:1px solid #78b17c;background-color:#e4ffe5;}\n</style>\n</head><body><div class=\"box\">Teleport助手工作正常!</div></body></html>";
|
||||
ex_wstr page = L"<html lang=\"zh_CN\"><head><meta charset=\"utf-8\"/><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/><title>Teleport助手</title>\n<style type=\"text/css\">\n.box{padding:20px;margin:40px;border:1px solid #78b17c;background-color:#e4ffe5;}\n</style>\n</head><body><div class=\"box\">Teleport助手工作正常!</div></body></html>";
|
||||
ex_wstr2astr(page, ret_buf, EX_CODEPAGE_UTF8);
|
||||
|
||||
mg_printf(nc, "HTTP/1.0 200 OK\r\nAccess-Control-Allow-Origin: *\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n%s", ret_buf.size() - 1, &ret_buf[0]);
|
||||
|
@ -441,7 +475,7 @@ int TsHttpRpc::_parse_request(struct http_message* req, ex_astr& func_cmd, ex_as
|
|||
|
||||
ex_astrs strs;
|
||||
|
||||
size_t pos_start = 1; // 跳过第一个字节,一定是 '/'
|
||||
size_t pos_start = 1; // 跳过第一个字节,一定是 '/'
|
||||
|
||||
size_t i = 0;
|
||||
for (i = pos_start; i < req->uri.len; ++i) {
|
||||
|
@ -451,7 +485,7 @@ int TsHttpRpc::_parse_request(struct http_message* req, ex_astr& func_cmd, ex_as
|
|||
tmp_uri.assign(req->uri.p + pos_start, i - pos_start);
|
||||
strs.push_back(tmp_uri);
|
||||
}
|
||||
pos_start = i + 1; // 跳过当前找到的分隔符
|
||||
pos_start = i + 1; // 跳过当前找到的分隔符
|
||||
}
|
||||
}
|
||||
if (pos_start < req->uri.len) {
|
||||
|
@ -485,7 +519,7 @@ int TsHttpRpc::_parse_request(struct http_message* req, ex_astr& func_cmd, ex_as
|
|||
}
|
||||
|
||||
if (func_args.length() > 0) {
|
||||
// 将参数进行 url-decode 解码
|
||||
// 将参数进行 url-decode 解码
|
||||
int len = func_args.length() * 2;
|
||||
ex_chars sztmp;
|
||||
sztmp.resize(len);
|
||||
|
@ -521,7 +555,7 @@ void TsHttpRpc::_process_js_request(const ex_astr& func_cmd, const ex_astr& func
|
|||
}
|
||||
|
||||
void TsHttpRpc::_create_json_ret(ex_astr& buf, int errcode) {
|
||||
// 返回: {"code":123}
|
||||
// 返回: {"code":123}
|
||||
|
||||
Json::FastWriter jr_writer;
|
||||
Json::Value jr_root;
|
||||
|
@ -535,12 +569,64 @@ void TsHttpRpc::_create_json_ret(ex_astr& buf, Json::Value& jr_root) {
|
|||
buf = jr_writer.write(jr_root);
|
||||
}
|
||||
|
||||
void TsHttpRpc::_rpc_func_url_protocol(const ex_astr& args, ex_astr& buf)
|
||||
{
|
||||
//处理urlprotocol调用访式
|
||||
// 将参数进行 url-decode 解码
|
||||
std::string func_args = args;
|
||||
if (func_args.length() > 0)
|
||||
{
|
||||
int len = func_args.length() * 2;
|
||||
ex_chars sztmp;
|
||||
sztmp.resize(len);
|
||||
memset(&sztmp[0], 0, len);
|
||||
if (-1 == ts_url_decode(func_args.c_str(), func_args.length(), &sztmp[0], len, 0))
|
||||
return ;
|
||||
|
||||
func_args = &sztmp[0];
|
||||
}
|
||||
EXLOGD(("%s\n"), func_args.c_str());
|
||||
//处理传参过来的teleport://{}/,只保留参数部份
|
||||
std::string urlproto_appname = TP_URLPROTO_APP_NAME;
|
||||
urlproto_appname += "://{";
|
||||
func_args.erase(0, urlproto_appname.length());//去除第一个URLPROTO_APP_NAME以及://字符
|
||||
int pos = func_args.length() - 1;
|
||||
if (func_args.substr(pos, 1) == "/")
|
||||
func_args.erase(pos - 1, 2);//去除最后一个}/字符
|
||||
else
|
||||
func_args.erase(pos, 1);
|
||||
|
||||
//由于命令行、ie浏览器参数传递时会把原来json结构中的"号去掉,需要重新格式化参数为json格式
|
||||
if (func_args.find("\"", 0) == std::string::npos) {
|
||||
std::vector<std::string> strv;
|
||||
SplitString(func_args, strv, ",");
|
||||
func_args = "";
|
||||
for (std::vector<std::string>::size_type i = 0; i < strv.size(); i++) {
|
||||
std::vector<std::string> strv1;
|
||||
SplitString(strv[i], strv1, ":");
|
||||
strv1[0] = "\"" + strv1[0] + "\"";
|
||||
if (!isDegital(strv1[1]) && strtolower(strv1[1]) != "true" && strtolower(strv1[1]) != "false")
|
||||
strv1[1] = "\"" + strv1[1] + "\"";
|
||||
|
||||
strv[i] = strv1[0] + ":" + strv1[1];
|
||||
if (i == 0)
|
||||
func_args = strv[i];
|
||||
else
|
||||
func_args += "," + strv[i];
|
||||
}
|
||||
}
|
||||
func_args = "{" + func_args + "}";
|
||||
EXLOGD(("%s\n"), func_args.c_str());
|
||||
//调用TsHttpRpc类里的_rpc_func_run_client启动客户端
|
||||
_rpc_func_run_client(func_args, buf);
|
||||
}
|
||||
|
||||
void TsHttpRpc::_rpc_func_run_client(const ex_astr& func_args, ex_astr& buf) {
|
||||
// 入参:{"ip":"192.168.5.11","port":22,"uname":"root","uauth":"abcdefg","authmode":1,"protocol":2}
|
||||
// 入参:{"ip":"192.168.5.11","port":22,"uname":"root","uauth":"abcdefg","authmode":1,"protocol":2}
|
||||
// authmode: 1=password, 2=private-key
|
||||
// protocol: 1=rdp, 2=ssh
|
||||
// SSH返回: {"code":0, "data":{"sid":"0123abcde"}}
|
||||
// RDP返回: {"code":0, "data":{"sid":"0123abcde0A"}}
|
||||
// SSH返回: {"code":0, "data":{"sid":"0123abcde"}}
|
||||
// RDP返回: {"code":0, "data":{"sid":"0123abcde0A"}}
|
||||
|
||||
Json::Reader jreader;
|
||||
Json::Value jsRoot;
|
||||
|
@ -554,7 +640,7 @@ void TsHttpRpc::_rpc_func_run_client(const ex_astr& func_args, ex_astr& buf) {
|
|||
return;
|
||||
}
|
||||
|
||||
// 判断参数是否正确
|
||||
// 判断参数是否正确
|
||||
if (!jsRoot["teleport_ip"].isString()
|
||||
|| !jsRoot["teleport_port"].isNumeric() || !jsRoot["remote_host_ip"].isString()
|
||||
|| !jsRoot["session_id"].isString() || !jsRoot["protocol_type"].isNumeric() || !jsRoot["protocol_sub_type"].isNumeric()
|
||||
|
@ -663,7 +749,7 @@ void TsHttpRpc::_rpc_func_run_client(const ex_astr& func_args, ex_astr& buf) {
|
|||
int iHeight = GetSystemMetrics(SM_CYSCREEN);
|
||||
|
||||
if (rdp_w == 0 || rdp_h == 0) {
|
||||
//全屏
|
||||
//全屏
|
||||
width = iWidth;
|
||||
higth = iHeight;
|
||||
display = 2;
|
||||
|
@ -732,7 +818,7 @@ void TsHttpRpc::_rpc_func_run_client(const ex_astr& func_args, ex_astr& buf) {
|
|||
fclose(f);
|
||||
ex_astr2wstr(sz_file_name, tmp_rdp_file);
|
||||
|
||||
// 变量替换
|
||||
// 变量替换
|
||||
ex_replace_all(w_exe_path, _T("{tmp_rdp_file}"), tmp_rdp_file);
|
||||
} else if (g_cfg.rdp_name == L"freerdp") {
|
||||
w_exe_path += L"{size} {console} {clipboard} {drives} ";
|
||||
|
@ -741,7 +827,7 @@ void TsHttpRpc::_rpc_func_run_client(const ex_astr& func_args, ex_astr& buf) {
|
|||
ex_wstr w_screen;
|
||||
|
||||
if (rdp_w == 0 || rdp_h == 0) {
|
||||
//全屏
|
||||
//全屏
|
||||
w_screen = _T("/f");
|
||||
} else {
|
||||
char sz_size[64] = { 0 };
|
||||
|
@ -767,10 +853,10 @@ void TsHttpRpc::_rpc_func_run_client(const ex_astr& func_args, ex_astr& buf) {
|
|||
|
||||
w_sid = L"02" + w_sid;
|
||||
|
||||
w_exe_path += L" /gdi:sw"; // 使用软件渲染,gdi:hw使用硬件加速,但是会出现很多黑块(录像回放时又是正常的!)
|
||||
w_exe_path += L" -grab-keyboard"; // [new style] 防止启动FreeRDP后,失去本地键盘响应,必须得先最小化一下FreeRDP窗口(不过貌似不起作用)
|
||||
w_exe_path += L" /gdi:sw"; // 使用软件渲染,gdi:hw使用硬件加速,但是会出现很多黑块(录像回放时又是正常的!)
|
||||
w_exe_path += L" -grab-keyboard"; // [new style] 防止启动FreeRDP后,失去本地键盘响应,必须得先最小化一下FreeRDP窗口(不过貌似不起作用)
|
||||
|
||||
// 变量替换
|
||||
// 变量替换
|
||||
ex_replace_all(w_exe_path, _T("{size}"), w_screen);
|
||||
|
||||
if (flag_console && rdp_console)
|
||||
|
@ -855,7 +941,7 @@ void TsHttpRpc::_rpc_func_rdp_play(const ex_astr& func_args, ex_astr& buf) {
|
|||
return;
|
||||
}
|
||||
|
||||
// 判断参数是否正确
|
||||
// 判断参数是否正确
|
||||
if (!jsRoot["rid"].isInt()
|
||||
|| !jsRoot["web"].isString()
|
||||
|| !jsRoot["sid"].isString()
|
||||
|
@ -879,9 +965,9 @@ void TsHttpRpc::_rpc_func_rdp_play(const ex_astr& func_args, ex_astr& buf) {
|
|||
char cmd_args[1024] = { 0 };
|
||||
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());
|
||||
|
||||
// TODO: 理论上不应该由助手来提前做域名转为IP这样的操作,而是应该将域名发送给播放器,由播放器自己去处理
|
||||
// 但是在改造FreeRDP制作的播放器时,为了从服务器上下载文件,使用了Mongoose库,如果传入的是域名,会出现问题(貌似是异步查询DNS的问题)
|
||||
// 所以暂时先由助手进行域名IP转换。
|
||||
// TODO: 理论上不应该由助手来提前做域名转为IP这样的操作,而是应该将域名发送给播放器,由播放器自己去处理
|
||||
// 但是在改造FreeRDP制作的播放器时,为了从服务器上下载文件,使用了Mongoose库,如果传入的是域名,会出现问题(貌似是异步查询DNS的问题)
|
||||
// 所以暂时先由助手进行域名IP转换。
|
||||
{
|
||||
unsigned int port_i = 0;
|
||||
struct mg_str scheme, query, fragment, user_info, host, path;
|
||||
|
@ -897,7 +983,7 @@ void TsHttpRpc::_rpc_func_rdp_play(const ex_astr& func_args, ex_astr& buf) {
|
|||
ex_astr _scheme;
|
||||
_scheme.assign(scheme.p, scheme.len);
|
||||
|
||||
// 将host从域名转换为IP
|
||||
// 将host从域名转换为IP
|
||||
ex_astr str_tp_host;
|
||||
str_tp_host.assign(host.p, host.len);
|
||||
struct hostent *tp_host = gethostbyname(str_tp_host.c_str());
|
||||
|
@ -1001,7 +1087,7 @@ void TsHttpRpc::_rpc_func_file_action(const ex_astr& func_args, ex_astr& buf) {
|
|||
_create_json_ret(buf, TPE_JSON_FORMAT);
|
||||
return;
|
||||
}
|
||||
// 判断参数是否正确
|
||||
// 判断参数是否正确
|
||||
if (!jsRoot["action"].isNumeric()) {
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
|
@ -1024,9 +1110,9 @@ void TsHttpRpc::_rpc_func_file_action(const ex_astr& func_args, ex_astr& buf) {
|
|||
ZeroMemory(&ofn, sizeof(ofn));
|
||||
|
||||
ofn.lStructSize = sizeof(ofn);
|
||||
ofn.lpstrTitle = _T("选择文件");
|
||||
ofn.lpstrTitle = _T("选择文件");
|
||||
ofn.hwndOwner = hParent;
|
||||
ofn.lpstrFilter = _T("可执行程序 (*.exe)\0*.exe\0");
|
||||
ofn.lpstrFilter = _T("可执行程序 (*.exe)\0*.exe\0");
|
||||
ofn.lpstrFile = wszReturnPath;
|
||||
ofn.nMaxFile = MAX_PATH;
|
||||
ofn.lpstrInitialDir = wsDefaultPath.c_str();
|
||||
|
@ -1044,12 +1130,12 @@ void TsHttpRpc::_rpc_func_file_action(const ex_astr& func_args, ex_astr& buf) {
|
|||
ZeroMemory(&bi, sizeof(BROWSEINFO));
|
||||
bi.hwndOwner = NULL;
|
||||
bi.pidlRoot = NULL;
|
||||
bi.pszDisplayName = wszReturnPath; //此参数如为NULL则不能显示对话框
|
||||
bi.lpszTitle = _T("选择目录");
|
||||
bi.pszDisplayName = wszReturnPath; //此参数如为NULL则不能显示对话框
|
||||
bi.lpszTitle = _T("选择目录");
|
||||
bi.ulFlags = BIF_RETURNONLYFSDIRS;
|
||||
bi.lpfn = NULL;
|
||||
bi.iImage = 0; //初始化入口参数bi结束
|
||||
LPITEMIDLIST pIDList = SHBrowseForFolder(&bi);//调用显示选择对话框
|
||||
bi.iImage = 0; //初始化入口参数bi结束
|
||||
LPITEMIDLIST pIDList = SHBrowseForFolder(&bi);//调用显示选择对话框
|
||||
if (pIDList) {
|
||||
ret = true;
|
||||
SHGetPathFromIDList(pIDList, wszReturnPath);
|
||||
|
|
|
@ -15,28 +15,28 @@
|
|||
|
||||
/*
|
||||
//=================================================================
|
||||
接口使用说明:
|
||||
接口使用说明:
|
||||
|
||||
本程序启动后,监听 localhost:50022,接收http请求,请求格式要求如下:
|
||||
本程序启动后,监听 localhost:50022,接收http请求,请求格式要求如下:
|
||||
|
||||
GET 方式
|
||||
GET 方式
|
||||
http://localhost:50022/method/json_param
|
||||
其中json_param是使用url_encode进行编码后的json格式字符串
|
||||
其中json_param是使用url_encode进行编码后的json格式字符串
|
||||
|
||||
POST 方式
|
||||
POST 方式
|
||||
http://localhost:50022/method
|
||||
post的数据区域是json_param
|
||||
post的数据区域是json_param
|
||||
|
||||
其中,URI分为三个部分:
|
||||
method 请求执行的任务方法。
|
||||
json_param 此任务方法的附加参数,如果没有附加参数,这部分可以省略。
|
||||
其中,URI分为三个部分:
|
||||
method 请求执行的任务方法。
|
||||
json_param 此任务方法的附加参数,如果没有附加参数,这部分可以省略。
|
||||
|
||||
返回格式:执行结束后,返回一个json格式的字符串给请求者,格式如下:
|
||||
返回格式:执行结束后,返回一个json格式的字符串给请求者,格式如下:
|
||||
|
||||
{"code":0,"data":varb}
|
||||
|
||||
其中,code是必有的,其值是一个错误编码,0表示成功。如果失败,则可能没有data域。操作成功时,data域就是
|
||||
操作的返回数据,其格式根据具体执行的任务方法不同而不同。
|
||||
其中,code是必有的,其值是一个错误编码,0表示成功。如果失败,则可能没有data域。操作成功时,data域就是
|
||||
操作的返回数据,其格式根据具体执行的任务方法不同而不同。
|
||||
|
||||
*/
|
||||
|
||||
|
@ -57,6 +57,7 @@ public:
|
|||
bool init_https();
|
||||
void run(void);
|
||||
void stop(void);
|
||||
void _rpc_func_url_protocol(const ex_astr& func_args, ex_astr& buf);
|
||||
|
||||
ex_astr get_content_type(ex_astr file_suffix) {
|
||||
content_type_map::iterator it=m_content_type_map.find(file_suffix);
|
||||
|
|
|
@ -1,29 +1,34 @@
|
|||
#ifndef __TELEPORT_CONST_H__
|
||||
#define __TELEPORT_CONST_H__
|
||||
|
||||
// 注意同步更新三个不同语言的const文件
|
||||
// 注意同步更新三个不同语言的const文件
|
||||
|
||||
// 本文件设定teleport各个模块之间通讯时的错误值(JSON数据),包括:
|
||||
// - WEB界面与助手
|
||||
// - WEB界面与WEB后台
|
||||
// - WEB后台与CORE核心服务
|
||||
// 本文件设定teleport各个模块之间通讯时的错误值(JSON数据),包括:
|
||||
// - WEB界面与助手
|
||||
// - WEB界面与WEB后台
|
||||
// - WEB后台与CORE核心服务
|
||||
|
||||
//=======================================================
|
||||
// 远程连接认证方式
|
||||
// Urlprotocol相关
|
||||
//=======================================================
|
||||
#define TP_URLPROTO_APP_NAME "teleport"
|
||||
|
||||
//=======================================================
|
||||
// 远程连接认证方式
|
||||
//=======================================================
|
||||
#define TP_AUTH_TYPE_NONE 0
|
||||
#define TP_AUTH_TYPE_PASSWORD 1
|
||||
#define TP_AUTH_TYPE_PRIVATE_KEY 2
|
||||
|
||||
//=======================================================
|
||||
// 远程连接协议
|
||||
// 远程连接协议
|
||||
//=======================================================
|
||||
#define TP_PROTOCOL_TYPE_RDP 1
|
||||
#define TP_PROTOCOL_TYPE_SSH 2
|
||||
#define TP_PROTOCOL_TYPE_TELNET 3
|
||||
|
||||
//=======================================================
|
||||
// 远程连接子协议
|
||||
// 远程连接子协议
|
||||
//=======================================================
|
||||
#define TP_PROTOCOL_TYPE_RDP_DESKTOP 100
|
||||
#define TP_PROTOCOL_TYPE_SSH_SHELL 200
|
||||
|
@ -32,114 +37,114 @@
|
|||
|
||||
|
||||
//=======================================================
|
||||
// 远程主机操作系统
|
||||
// 远程主机操作系统
|
||||
//=======================================================
|
||||
#define TP_OS_TYPE_WINDOWS 1
|
||||
#define TP_OS_TYPE_LINUX 2
|
||||
|
||||
//=======================================================
|
||||
// 远程连接会话状态
|
||||
// 远程连接会话状态
|
||||
//=======================================================
|
||||
#define TP_SESS_STAT_RUNNING 0 // 会话开始了,正在连接
|
||||
#define TP_SESS_STAT_END 9999 // 会话成功结束
|
||||
#define TP_SESS_STAT_ERR_AUTH_DENIED 1 // 会话结束,因为认证失败
|
||||
#define TP_SESS_STAT_ERR_CONNECT 2 // 会话结束,因为无法连接到远程主机
|
||||
#define TP_SESS_STAT_ERR_BAD_SSH_KEY 3 // 会话结束,因为无法识别SSH私钥
|
||||
#define TP_SESS_STAT_ERR_INTERNAL 4 // 会话结束,因为内部错误
|
||||
#define TP_SESS_STAT_ERR_UNSUPPORT_PROTOCOL 5 // 会话结束,因为协议不支持(RDP)
|
||||
#define TP_SESS_STAT_ERR_BAD_PKG 6 // 会话结束,因为收到错误的报文
|
||||
#define TP_SESS_STAT_ERR_RESET 7 // 会话结束,因为teleport核心服务重置了
|
||||
#define TP_SESS_STAT_ERR_IO 8 // 会话结束,因为网络中断
|
||||
#define TP_SESS_STAT_ERR_SESSION 9 // 会话结束,因为无效的会话ID
|
||||
#define TP_SESS_STAT_ERR_AUTH_TYPE 10 // 会话结束,因为不被允许的认证方式
|
||||
#define TP_SESS_STAT_STARTED 100 // 已经连接成功了,开始记录录像了
|
||||
#define TP_SESS_STAT_ERR_START_INTERNAL 104 // 会话结束,因为内部错误
|
||||
#define TP_SESS_STAT_ERR_START_BAD_PKG 106 // 会话结束,因为收到错误的报文
|
||||
#define TP_SESS_STAT_ERR_START_RESET 107 // 会话结束,因为teleport核心服务重置了
|
||||
#define TP_SESS_STAT_ERR_START_IO 108 // 会话结束,因为网络中断
|
||||
#define TP_SESS_STAT_RUNNING 0 // 会话开始了,正在连接
|
||||
#define TP_SESS_STAT_END 9999 // 会话成功结束
|
||||
#define TP_SESS_STAT_ERR_AUTH_DENIED 1 // 会话结束,因为认证失败
|
||||
#define TP_SESS_STAT_ERR_CONNECT 2 // 会话结束,因为无法连接到远程主机
|
||||
#define TP_SESS_STAT_ERR_BAD_SSH_KEY 3 // 会话结束,因为无法识别SSH私钥
|
||||
#define TP_SESS_STAT_ERR_INTERNAL 4 // 会话结束,因为内部错误
|
||||
#define TP_SESS_STAT_ERR_UNSUPPORT_PROTOCOL 5 // 会话结束,因为协议不支持(RDP)
|
||||
#define TP_SESS_STAT_ERR_BAD_PKG 6 // 会话结束,因为收到错误的报文
|
||||
#define TP_SESS_STAT_ERR_RESET 7 // 会话结束,因为teleport核心服务重置了
|
||||
#define TP_SESS_STAT_ERR_IO 8 // 会话结束,因为网络中断
|
||||
#define TP_SESS_STAT_ERR_SESSION 9 // 会话结束,因为无效的会话ID
|
||||
#define TP_SESS_STAT_ERR_AUTH_TYPE 10 // 会话结束,因为不被允许的认证方式
|
||||
#define TP_SESS_STAT_STARTED 100 // 已经连接成功了,开始记录录像了
|
||||
#define TP_SESS_STAT_ERR_START_INTERNAL 104 // 会话结束,因为内部错误
|
||||
#define TP_SESS_STAT_ERR_START_BAD_PKG 106 // 会话结束,因为收到错误的报文
|
||||
#define TP_SESS_STAT_ERR_START_RESET 107 // 会话结束,因为teleport核心服务重置了
|
||||
#define TP_SESS_STAT_ERR_START_IO 108 // 会话结束,因为网络中断
|
||||
|
||||
|
||||
//=======================================================
|
||||
// 授权标记
|
||||
// 授权标记
|
||||
//=======================================================
|
||||
#define TP_FLAG_ALL 0xFFFFFFFF
|
||||
// 会话记录相关
|
||||
#define TP_FLAG_RECORD_REPLAY 0x00000001 // 允许记录历史(录像回放)
|
||||
#define TP_FLAG_RECORD_REAL_TIME 0x00000002 // 允许实时监控
|
||||
// RDP相关
|
||||
#define TP_FLAG_RDP_DESKTOP 0x00000001 // 允许远程桌面
|
||||
#define TP_FLAG_RDP_CLIPBOARD 0x00000002 // 允许剪贴板
|
||||
#define TP_FLAG_RDP_DISK 0x00000004 // 允许磁盘映射
|
||||
#define TP_FLAG_RDP_APP 0x00000008 // 允许远程APP(尚未实现)
|
||||
#define TP_FLAG_RDP_CONSOLE 0x00001000 //允许连接到管理员会话(RDP的console选项)
|
||||
// SSH相关
|
||||
#define TP_FLAG_SSH_SHELL 0x00000001 // 允许SHELL
|
||||
#define TP_FLAG_SSH_SFTP 0x00000002 // 允许SFTP
|
||||
#define TP_FLAG_SSH_X11 0x00000004 // 允许X11转发(尚未实现)
|
||||
#define TP_FLAG_SSH_EXEC 0x00000008 // 允许exec执行远程命令(尚未实现)
|
||||
// 会话记录相关
|
||||
#define TP_FLAG_RECORD_REPLAY 0x00000001 // 允许记录历史(录像回放)
|
||||
#define TP_FLAG_RECORD_REAL_TIME 0x00000002 // 允许实时监控
|
||||
// RDP相关
|
||||
#define TP_FLAG_RDP_DESKTOP 0x00000001 // 允许远程桌面
|
||||
#define TP_FLAG_RDP_CLIPBOARD 0x00000002 // 允许剪贴板
|
||||
#define TP_FLAG_RDP_DISK 0x00000004 // 允许磁盘映射
|
||||
#define TP_FLAG_RDP_APP 0x00000008 // 允许远程APP(尚未实现)
|
||||
#define TP_FLAG_RDP_CONSOLE 0x00001000 //允许连接到管理员会话(RDP的console选项)
|
||||
// SSH相关
|
||||
#define TP_FLAG_SSH_SHELL 0x00000001 // 允许SHELL
|
||||
#define TP_FLAG_SSH_SFTP 0x00000002 // 允许SFTP
|
||||
#define TP_FLAG_SSH_X11 0x00000004 // 允许X11转发(尚未实现)
|
||||
#define TP_FLAG_SSH_EXEC 0x00000008 // 允许exec执行远程命令(尚未实现)
|
||||
#define TP_FLAG_SSH_TUNNEL 0x00000010 // allow ssh tunnel. (not impl.)
|
||||
|
||||
|
||||
//=======================================================
|
||||
// 错误值
|
||||
// 错误值
|
||||
//=======================================================
|
||||
#define TPE_OK 0 // 成功
|
||||
#define TPE_OK 0 // 成功
|
||||
//-------------------------------------------------------
|
||||
// 通用错误值
|
||||
// 通用错误值
|
||||
//-------------------------------------------------------
|
||||
#define TPE_NEED_MORE_DATA 1 // 需要更多数据(不一定是错误)
|
||||
#define TPE_NEED_LOGIN 2 // 需要登录
|
||||
#define TPE_PRIVILEGE 3 // 没有操作权限
|
||||
#define TPE_NOT_IMPLEMENT 7 // 功能尚未实现
|
||||
#define TPE_EXISTS 8 // 目标已经存在
|
||||
#define TPE_NOT_EXISTS 9 // 目标不存在
|
||||
#define TPE_NEED_MORE_DATA 1 // 需要更多数据(不一定是错误)
|
||||
#define TPE_NEED_LOGIN 2 // 需要登录
|
||||
#define TPE_PRIVILEGE 3 // 没有操作权限
|
||||
#define TPE_NOT_IMPLEMENT 7 // 功能尚未实现
|
||||
#define TPE_EXISTS 8 // 目标已经存在
|
||||
#define TPE_NOT_EXISTS 9 // 目标不存在
|
||||
|
||||
// 100~299是通用错误值
|
||||
// 100~299是通用错误值
|
||||
|
||||
#define TPE_FAILED 100 // 内部错误
|
||||
#define TPE_NETWORK 101 // 网络错误
|
||||
#define TPE_DATABASE 102 // 数据库操作失败
|
||||
#define TPE_FAILED 100 // 内部错误
|
||||
#define TPE_NETWORK 101 // 网络错误
|
||||
#define TPE_DATABASE 102 // 数据库操作失败
|
||||
|
||||
// HTTP请求相关错误
|
||||
#define TPE_HTTP_METHOD 120 // 无效的请求方法(不是GET/POST等),或者错误的请求方法(例如需要POST,却使用GET方式请求)
|
||||
#define TPE_HTTP_URL_ENCODE 121 // URL编码错误(无法解码)
|
||||
//#define TPE_HTTP_URI 122 // 无效的URI
|
||||
// HTTP请求相关错误
|
||||
#define TPE_HTTP_METHOD 120 // 无效的请求方法(不是GET/POST等),或者错误的请求方法(例如需要POST,却使用GET方式请求)
|
||||
#define TPE_HTTP_URL_ENCODE 121 // URL编码错误(无法解码)
|
||||
//#define TPE_HTTP_URI 122 // 无效的URI
|
||||
|
||||
#define TPE_UNKNOWN_CMD 124 // 未知的命令
|
||||
#define TPE_JSON_FORMAT 125 // 错误的JSON格式(需要JSON格式数据,但是却无法按JSON格式解码)
|
||||
#define TPE_PARAM 126 // 参数错误
|
||||
#define TPE_DATA 127 // 数据错误
|
||||
#define TPE_UNKNOWN_CMD 124 // 未知的命令
|
||||
#define TPE_JSON_FORMAT 125 // 错误的JSON格式(需要JSON格式数据,但是却无法按JSON格式解码)
|
||||
#define TPE_PARAM 126 // 参数错误
|
||||
#define TPE_DATA 127 // 数据错误
|
||||
|
||||
// #define TPE_OPENFILE_ERROR 0x1007 // 无法打开文件
|
||||
// #define TPE_OPENFILE_ERROR 0x1007 // 无法打开文件
|
||||
// #define TPE_GETTEMPPATH_ERROR 0x1007
|
||||
#define TPE_OPENFILE 300
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// WEB服务专用错误值
|
||||
// WEB服务专用错误值
|
||||
//-------------------------------------------------------
|
||||
#define TPE_CAPTCHA_EXPIRED 10000 // 验证码已过期
|
||||
#define TPE_CAPTCHA_MISMATCH 10001 // 验证码错误
|
||||
#define TPE_OATH_MISMATCH 10002 // 身份验证器动态验证码错误
|
||||
#define TPE_SYS_MAINTENANCE 10003 // 系统维护中
|
||||
#define TPE_CAPTCHA_EXPIRED 10000 // 验证码已过期
|
||||
#define TPE_CAPTCHA_MISMATCH 10001 // 验证码错误
|
||||
#define TPE_OATH_MISMATCH 10002 // 身份验证器动态验证码错误
|
||||
#define TPE_SYS_MAINTENANCE 10003 // 系统维护中
|
||||
|
||||
#define TPE_USER_LOCKED 10100 // 用户已经被锁定(连续多次错误密码)
|
||||
#define TPE_USER_DISABLED 10101 // 用户已经被禁用
|
||||
#define TPE_USER_AUTH 10102 // 身份验证失败
|
||||
#define TPE_USER_LOCKED 10100 // 用户已经被锁定(连续多次错误密码)
|
||||
#define TPE_USER_DISABLED 10101 // 用户已经被禁用
|
||||
#define TPE_USER_AUTH 10102 // 身份验证失败
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 助手程序专用错误值
|
||||
// 助手程序专用错误值
|
||||
//-------------------------------------------------------
|
||||
#define TPE_NO_ASSIST 100000 // 未能检测到助手程序
|
||||
#define TPE_OLD_ASSIST 100001 // 助手程序版本太低
|
||||
#define TPE_START_CLIENT 100002 // 无法启动客户端程序(无法创建进程)
|
||||
#define TPE_NO_ASSIST 100000 // 未能检测到助手程序
|
||||
#define TPE_OLD_ASSIST 100001 // 助手程序版本太低
|
||||
#define TPE_START_CLIENT 100002 // 无法启动客户端程序(无法创建进程)
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 核心服务专用错误值
|
||||
// 核心服务专用错误值
|
||||
//-------------------------------------------------------
|
||||
#define TPE_NO_CORE_SERVER 200000 // 未能检测到核心服务
|
||||
#define TPE_NO_CORE_SERVER 200000 // 未能检测到核心服务
|
||||
|
||||
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -90,6 +90,71 @@ $app.create_info_table = function () {
|
|||
return _info;
|
||||
};
|
||||
|
||||
$app.create_config_global = function () {
|
||||
var _global = {};
|
||||
|
||||
_global.dom = {
|
||||
btn_save: $('#btn-save-global-config'),
|
||||
|
||||
btn_global_use_url_protocol: $('#global-use-url-protocol')
|
||||
};
|
||||
|
||||
_global.init = function (cb_stack) {
|
||||
_global.update_dom_global_cfg($app.options.sys_cfg.glob);
|
||||
|
||||
$('#tab-global').find('.tp-checkbox.tp-editable').click(function () {
|
||||
if ($(this).hasClass('tp-selected'))
|
||||
$(this).removeClass('tp-selected');
|
||||
else
|
||||
$(this).addClass('tp-selected');
|
||||
});
|
||||
|
||||
_global.dom.btn_save.click(function () {
|
||||
_global.on_btn_save();
|
||||
});
|
||||
|
||||
cb_stack.exec();
|
||||
};
|
||||
|
||||
_global.update_dom_global_cfg = function (global) {
|
||||
_global.dom.btn_global_use_url_protocol.removeClass('tp-selected');
|
||||
if (global.url_proto)
|
||||
_global.dom.btn_global_use_url_protocol.addClass('tp-selected');
|
||||
|
||||
};
|
||||
|
||||
_global.on_btn_save = function () {
|
||||
|
||||
var _url_proto = _global.dom.btn_global_use_url_protocol.hasClass('tp-selected'); // now we always need record replay.
|
||||
|
||||
_global.dom.btn_save.attr('disabled', 'disabled');
|
||||
$tp.ajax_post_json('/system/save-cfg',
|
||||
{
|
||||
global: {
|
||||
url_proto: _url_proto
|
||||
}
|
||||
},
|
||||
function (ret) {
|
||||
_global.dom.btn_save.removeAttr('disabled');
|
||||
if (ret.code === TPE_OK) {
|
||||
$tp.notify_success('全局设置更新成功!');
|
||||
|
||||
} else {
|
||||
$tp.notify_error('全局设置更新失败:' + tp_error_msg(ret.code, ret.message));
|
||||
}
|
||||
},
|
||||
function () {
|
||||
_global.dom.btn_save.removeAttr('disabled');
|
||||
$tp.notify_error('网路故障,全局连接控制设置更新失败!');
|
||||
}
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
return _global;
|
||||
};
|
||||
|
||||
|
||||
$app.create_dlg_result = function () {
|
||||
var _dlg = {};
|
||||
|
||||
|
|
|
@ -127,25 +127,35 @@ $assist.do_teleport = function (args, func_success, func_error) {
|
|||
|
||||
// console.log('---', data);
|
||||
var args_ = encodeURIComponent(JSON.stringify(data));
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
timeout: 5000,
|
||||
//url: 'http://localhost:50022/ts_op/' + args_,
|
||||
url: $assist.api_url + '/run/' + args_,
|
||||
jsonp: 'callback',
|
||||
dataType: 'json',
|
||||
success: function (ret) {
|
||||
console.log('ret', ret);
|
||||
if (ret.code === TPE_OK) {
|
||||
func_success();
|
||||
} else {
|
||||
func_error(ret.code, ret.message);
|
||||
//判断是否使用urlprocotol处理方式
|
||||
if ($app.options.url_proto){
|
||||
|
||||
if(!$("#urlproto").length) {
|
||||
var _html = "<div id='urlproto' style='display:none;z-index=-1;'><iframe src=''/></div>";
|
||||
$('body').append($(_html));
|
||||
}
|
||||
$("#urlproto").find("iframe").attr("src",'teleport://' + JSON.stringify(data));
|
||||
}else{
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
timeout: 5000,
|
||||
//url: 'http://localhost:50022/ts_op/' + args_,
|
||||
url: $assist.api_url + '/run/' + args_,
|
||||
jsonp: 'callback',
|
||||
dataType: 'json',
|
||||
success: function (ret) {
|
||||
console.log('ret', ret);
|
||||
if (ret.code === TPE_OK) {
|
||||
func_success();
|
||||
} else {
|
||||
func_error(ret.code, ret.message);
|
||||
}
|
||||
},
|
||||
error: function () {
|
||||
func_error(TPE_NO_ASSIST, '无法连接到teleport助手,可能尚未启动!');
|
||||
}
|
||||
},
|
||||
error: function () {
|
||||
func_error(TPE_NO_ASSIST, '无法连接到teleport助手,可能尚未启动!');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (ret.code === TPE_NO_CORE_SERVER) {
|
||||
func_error(ret.code, '远程连接请求失败,可能teleport核心服务尚未启动!' + ret.message);
|
||||
|
|
|
@ -95,6 +95,11 @@ var TP_POLICY_AUTH_gUSER_gACC = 6; // 6=用户组:账号组
|
|||
var TP_POLICY_AUTH_gUSER_HOST = 7; // 7=用户组:主机
|
||||
var TP_POLICY_AUTH_gUSER_gHOST = 8; // 8=用户组:主机组
|
||||
|
||||
// =======================================================
|
||||
// 全局配置
|
||||
// =======================================================
|
||||
var TP_ASSIST_STARTUP_URLPROTO = 1; // 启用urlprotocol功能
|
||||
|
||||
// =======================================================
|
||||
// 授权标记
|
||||
// =======================================================
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
<div class="box box-nav-tabs">
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="active"><a href="#tab-info" data-toggle="tab">基本信息</a></li>
|
||||
<li><a href="#tab-global" data-toggle="tab">全局配置</a></li>
|
||||
<li><a href="#tab-security" data-toggle="tab">安全</a></li>
|
||||
<li><a href="#tab-session" data-toggle="tab">连接控制</a></li>
|
||||
<li><a href="#tab-smtp" data-toggle="tab">邮件系统</a></li>
|
||||
|
@ -34,6 +35,29 @@
|
|||
<h4>核心服务配置</h4>
|
||||
<table id="core-info-kv" class="table table-info-list"></table>
|
||||
</div>
|
||||
|
||||
<!-- panel for glabal config -->
|
||||
<div class="tab-pane" id="tab-global">
|
||||
<div class="alert alert-warning">
|
||||
注意:该配置影响全局,请小心修改。
|
||||
</div>
|
||||
<table class="table table-config-list">
|
||||
<tr>
|
||||
<td colspan="2" class="title">
|
||||
<hr class="hr-sm"/>
|
||||
远程启动方式
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="key"></td>
|
||||
<td class="value">
|
||||
<div id="global-use-url-protocol" class="tp-checkbox tp-editable">使用UrlProtocl启动远程</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr/>
|
||||
<button id="btn-save-global-config" class="btn btn-sm btn-primary"><i class="fa fa-check-circle fa-fw"></i> 保存设置</button>
|
||||
</div>
|
||||
|
||||
<!-- panel for security config -->
|
||||
<div class="tab-pane" id="tab-security">
|
||||
|
|
|
@ -459,7 +459,20 @@ class AppConfig(BaseAppConfig):
|
|||
if conf_data is None:
|
||||
log.w('system default config info is empty.\n')
|
||||
# return True
|
||||
|
||||
# =====================================
|
||||
# 全局设置相关
|
||||
# =====================================
|
||||
try:
|
||||
_glob = json.loads(conf_data['global'])
|
||||
except:
|
||||
log.w('password config not set or invalid, use default.\n')
|
||||
_glob = {}
|
||||
|
||||
self.sys.glob = tp_convert_to_attr_dict(_glob)
|
||||
if not self.sys.glob.is_exists('url_proto'):
|
||||
self.sys.glob.url_proto = False
|
||||
|
||||
# =====================================
|
||||
# 密码策略相关
|
||||
# =====================================
|
||||
|
|
|
@ -36,9 +36,11 @@ class RemoteHandler(TPBaseHandler):
|
|||
return
|
||||
|
||||
err, groups = group.get_host_groups_for_user(self.current_user['id'], self.current_user['privilege'])
|
||||
_cfg = tp_cfg()
|
||||
param = {
|
||||
'host_groups': groups,
|
||||
'core_cfg': tp_cfg().core
|
||||
'core_cfg': _cfg.core,
|
||||
'url_proto': _cfg.sys.glob.url_proto
|
||||
}
|
||||
|
||||
# param = {
|
||||
|
|
|
@ -256,8 +256,21 @@ class DoSaveCfgHandler(TPBaseJsonHandler):
|
|||
tp_cfg().sys.smtp.sender = _sender
|
||||
# 特殊处理,防止前端拿到密码
|
||||
tp_cfg().sys_smtp_password = _password
|
||||
else:
|
||||
return self.write_json(err)
|
||||
|
||||
#增加urlprotocol的配置
|
||||
if 'global' in args:
|
||||
processed = True
|
||||
_cfg = args['global']
|
||||
_url_proto = _cfg['url_proto']
|
||||
|
||||
err = system_model.save_config(self, '更新全局设置', 'global', _cfg)
|
||||
if err == TPE_OK:
|
||||
tp_cfg().sys.glob.url_proto = _url_proto
|
||||
else:
|
||||
return self.write_json(err)
|
||||
|
||||
|
||||
if 'password' in args:
|
||||
processed = True
|
||||
|
|
Loading…
Reference in New Issue