mirror of https://github.com/tp4a/teleport
[assist] refactor assist, communicate with web-app through web-socket.
[web] fix: shown invalid date when select valid from/to date in user-edit UI.feature/assist-websocket
parent
d11476ad5c
commit
15e85d61ef
|
@ -2,7 +2,9 @@
|
|||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/client/tp_assist_linux/ts_const.h" charset="GBK" />
|
||||
<file url="file://$PROJECT_DIR$/client/tp_assist_win/dlg_main.cpp" charset="GBK" />
|
||||
<file url="file://$PROJECT_DIR$/client/tp_assist_win/msocketx.h" charset="GBK" />
|
||||
<file url="file://$PROJECT_DIR$/client/tp_assist_win/tp_assist.cpp" charset="GBK" />
|
||||
<file url="file://$PROJECT_DIR$/common/libex/include/ex/ex_log.h" charset="GBK" />
|
||||
<file url="file://$PROJECT_DIR$/common/libex/include/ex/ex_path.h" charset="GBK" />
|
||||
<file url="file://$PROJECT_DIR$/common/libex/include/ex/ex_thread.h" charset="GBK" />
|
||||
|
@ -34,6 +36,7 @@
|
|||
<file url="file://$PROJECT_DIR$/server/tp_core/common/ts_memstream.h" charset="GBK" />
|
||||
<file url="file://$PROJECT_DIR$/server/tp_core/core/main.cpp" charset="GBK" />
|
||||
<file url="file://$PROJECT_DIR$/server/tp_core/core/tp_tpp_mgr.h" charset="GBK" />
|
||||
<file url="file://$PROJECT_DIR$/server/tp_core/core/ts_crypto.cpp" charset="GBK" />
|
||||
<file url="file://$PROJECT_DIR$/server/tp_core/core/ts_env.cpp" charset="GBK" />
|
||||
<file url="file://$PROJECT_DIR$/server/tp_core/core/ts_http_rpc.cpp" charset="GBK" />
|
||||
<file url="file://$PROJECT_DIR$/server/tp_core/core/ts_http_rpc.h" charset="GBK" />
|
||||
|
|
|
@ -76,6 +76,9 @@ class BuilderWin(BuilderBase):
|
|||
utils.copy_file(os.path.join(env.root_path, 'server', 'share', 'etc'), os.path.join(self.path_tmp_data, 'tmp', 'etc'), ('web.ini.in', 'web.ini'))
|
||||
utils.copy_file(os.path.join(env.root_path, 'server', 'share', 'etc'), os.path.join(self.path_tmp_data, 'tmp', 'etc'), ('core.ini.in', 'core.ini'))
|
||||
utils.copy_file(os.path.join(env.root_path, 'server', 'share', 'etc'), os.path.join(self.path_tmp_data, 'tmp', 'etc'), 'tp_ssh_server.key')
|
||||
utils.copy_file(os.path.join(env.root_path, 'server', 'share', 'etc'), os.path.join(self.path_tmp_data, 'tmp', 'etc'), 'tp_rdp_ca.crt')
|
||||
utils.copy_file(os.path.join(env.root_path, 'server', 'share', 'etc'), os.path.join(self.path_tmp_data, 'tmp', 'etc'), 'tp_rdp_server.crt')
|
||||
utils.copy_file(os.path.join(env.root_path, 'server', 'share', 'etc'), os.path.join(self.path_tmp_data, 'tmp', 'etc'), 'tp_rdp_server.key')
|
||||
|
||||
out_path = os.path.join(env.root_path, 'out', 'server', ctx.bits_path, ctx.target_path)
|
||||
bin_path = os.path.join(self.path_tmp_data, 'bin')
|
||||
|
@ -125,6 +128,9 @@ class BuilderLinux(BuilderBase):
|
|||
utils.copy_file(os.path.join(env.root_path, 'server', 'share', 'etc'), os.path.join(self.path_tmp_data, 'tmp', 'etc'), ('web.ini.in', 'web.ini'))
|
||||
utils.copy_file(os.path.join(env.root_path, 'server', 'share', 'etc'), os.path.join(self.path_tmp_data, 'tmp', 'etc'), ('core.ini.in', 'core.ini'))
|
||||
utils.copy_file(os.path.join(env.root_path, 'server', 'share', 'etc'), os.path.join(self.path_tmp_data, 'tmp', 'etc'), 'tp_ssh_server.key')
|
||||
utils.copy_file(os.path.join(env.root_path, 'server', 'share', 'etc'), os.path.join(self.path_tmp_data, 'tmp', 'etc'), 'tp_rdp_ca.crt')
|
||||
utils.copy_file(os.path.join(env.root_path, 'server', 'share', 'etc'), os.path.join(self.path_tmp_data, 'tmp', 'etc'), 'tp_rdp_server.crt')
|
||||
utils.copy_file(os.path.join(env.root_path, 'server', 'share', 'etc'), os.path.join(self.path_tmp_data, 'tmp', 'etc'), 'tp_rdp_server.key')
|
||||
|
||||
# fix new line flag
|
||||
utils.fix_new_line_flag(os.path.join(self.path_tmp_data, 'tmp', 'etc', 'web.ini'))
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
7AAE4B242390EE5C007EDDE7 /* libmbedtls.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7AF9BF222199E32B00BE5DBC /* libmbedtls.a */; };
|
||||
7AAE4B252390EE7D007EDDE7 /* libmbedcrypto.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7AF9BF232199E32B00BE5DBC /* libmbedcrypto.a */; };
|
||||
7AAE4B262390EE7D007EDDE7 /* libmbedx509.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7AF9BF212199E32B00BE5DBC /* libmbedx509.a */; };
|
||||
7AF6593E27398C7400057A00 /* ts_ws_client.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7AF6593C27398C7400057A00 /* ts_ws_client.cpp */; };
|
||||
7AF659412739939E00057A00 /* ts_utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7AF6593F2739939E00057A00 /* ts_utils.cpp */; };
|
||||
A1B7B9DD1DB53ED200809327 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = A1B7B9DF1DB53ED200809327 /* Localizable.strings */; };
|
||||
A1D700071A5DCE8D003563E4 /* AboutWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = A1D700061A5DCE8D003563E4 /* AboutWindowController.m */; };
|
||||
C149EBFE15D5214600B1F558 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C149EBFD15D5214600B1F558 /* Cocoa.framework */; };
|
||||
|
@ -109,6 +111,10 @@
|
|||
7AA2CD561F6ABA2E0074C92B /* mongoose.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mongoose.c; path = ../../../../external/mongoose/mongoose.c; sourceTree = "<group>"; };
|
||||
7AA2CD581F6AC0DA0074C92B /* site */ = {isa = PBXFileReference; lastKnownFileType = folder; path = site; sourceTree = "<group>"; };
|
||||
7AAE4B232390E642007EDDE7 /* mongoose.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mongoose.h; path = ../../../../external/mongoose/mongoose.h; sourceTree = "<group>"; };
|
||||
7AF6593C27398C7400057A00 /* ts_ws_client.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ts_ws_client.cpp; sourceTree = "<group>"; };
|
||||
7AF6593D27398C7400057A00 /* ts_ws_client.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ts_ws_client.h; sourceTree = "<group>"; };
|
||||
7AF6593F2739939E00057A00 /* ts_utils.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ts_utils.cpp; sourceTree = "<group>"; };
|
||||
7AF659402739939E00057A00 /* ts_utils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ts_utils.h; sourceTree = "<group>"; };
|
||||
7AF9BF212199E32B00BE5DBC /* libmbedx509.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libmbedx509.a; path = ../../external/macos/release/lib/libmbedx509.a; sourceTree = "<group>"; };
|
||||
7AF9BF222199E32B00BE5DBC /* libmbedtls.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libmbedtls.a; path = ../../external/macos/release/lib/libmbedtls.a; sourceTree = "<group>"; };
|
||||
7AF9BF232199E32B00BE5DBC /* libmbedcrypto.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libmbedcrypto.a; path = ../../external/macos/release/lib/libmbedcrypto.a; sourceTree = "<group>"; };
|
||||
|
@ -246,6 +252,10 @@
|
|||
7A27E4A81F6A8EEC004FDE5D /* ts_env.h */,
|
||||
7A27E4A61F6A899B004FDE5D /* ts_const.h */,
|
||||
7A7C6CA12197786B006869D9 /* ts_ver.h */,
|
||||
7AF6593C27398C7400057A00 /* ts_ws_client.cpp */,
|
||||
7AF6593D27398C7400057A00 /* ts_ws_client.h */,
|
||||
7AF6593F2739939E00057A00 /* ts_utils.cpp */,
|
||||
7AF659402739939E00057A00 /* ts_utils.h */,
|
||||
);
|
||||
path = csrc;
|
||||
sourceTree = "<group>";
|
||||
|
@ -428,6 +438,7 @@
|
|||
7AA2CD4A1F6AB9750074C92B /* ex_winsrv.cpp in Sources */,
|
||||
7AA2CD3B1F6A955A0074C92B /* ts_cfg.cpp in Sources */,
|
||||
A1D700071A5DCE8D003563E4 /* AboutWindowController.m in Sources */,
|
||||
7AF659412739939E00057A00 /* ts_utils.cpp in Sources */,
|
||||
7AA2CD521F6AB9F10074C92B /* json_value.cpp in Sources */,
|
||||
C149EC0A15D5214600B1F558 /* main.m in Sources */,
|
||||
7AA2CD381F6A92620074C92B /* ts_http_rpc.cpp in Sources */,
|
||||
|
@ -441,6 +452,7 @@
|
|||
7AA2CD461F6AB9750074C92B /* ex_path.cpp in Sources */,
|
||||
7AA2CD441F6AB9750074C92B /* ex_ini.cpp in Sources */,
|
||||
7AA2CD451F6AB9750074C92B /* ex_log.cpp in Sources */,
|
||||
7AF6593E27398C7400057A00 /* ts_ws_client.cpp in Sources */,
|
||||
7AA2CD491F6AB9750074C92B /* ex_util.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -600,6 +612,7 @@
|
|||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 3.6.0;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "src/TP-Assist-Prefix.pch";
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
|
@ -617,6 +630,7 @@
|
|||
INFOPLIST_FILE = "src/TP-Assist-Info.plist";
|
||||
LIBRARY_SEARCH_PATHS = ../../external/macos/release/lib;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
MARKETING_VERSION = 3.6.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "teleport.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
VALID_ARCHS = x86_64;
|
||||
|
@ -629,6 +643,7 @@
|
|||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 3.6.0;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "src/TP-Assist-Prefix.pch";
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
|
@ -645,6 +660,7 @@
|
|||
INFOPLIST_FILE = "src/TP-Assist-Info.plist";
|
||||
LIBRARY_SEARCH_PATHS = ../../external/macos/release/lib;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
MARKETING_VERSION = 3.6.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "teleport.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
VALID_ARCHS = x86_64;
|
||||
|
|
|
@ -53,7 +53,6 @@
|
|||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
<hr/>
|
||||
<p class="cfg-title">本地 SSH 客户端配置</p>
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "csrc/ts_env.h"
|
||||
#include "csrc/ts_cfg.h"
|
||||
#include "csrc/ts_http_rpc.h"
|
||||
#include "csrc/ts_ws_client.h"
|
||||
|
||||
int cpp_main(void* _self, const char* bundle_path, const char* cfg_file, const char* res_path) {
|
||||
if(!g_env.init(bundle_path, cfg_file, res_path))
|
||||
|
@ -16,8 +17,22 @@ int cpp_main(void* _self, const char* bundle_path, const char* cfg_file, const c
|
|||
if(!g_cfg.init())
|
||||
return -2;
|
||||
|
||||
if(0 != http_rpc_start(_self))
|
||||
return -3;
|
||||
|
||||
// if(0 != http_rpc_start(_self))
|
||||
// return -3;
|
||||
//
|
||||
TsWsClient::init_app(_self);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//uint64_t cpp_getpid()
|
||||
//{
|
||||
// pid_t pid = getpid();
|
||||
//
|
||||
// return static_cast<uint64_t>(pid);
|
||||
//}
|
||||
|
||||
void url_scheme_handler(const std::string& url)
|
||||
{
|
||||
TsWsClient::url_scheme_handler(url);
|
||||
}
|
||||
|
|
|
@ -8,10 +8,19 @@
|
|||
#ifndef wrap_c_objc_h
|
||||
#define wrap_c_objc_h
|
||||
|
||||
#include <string>
|
||||
|
||||
extern void* g_app;
|
||||
|
||||
int AppDelegate_start_ssh_client (void *_self, const char* cmd_line, const char* term_type, const char* term_theme, const char* term_title);
|
||||
int AppDelegate_select_app (void *_self);
|
||||
|
||||
// for cpp global object initialize.
|
||||
int cpp_main(void* _self, const char* bundle_path, const char* cfg_file, const char* res_path);
|
||||
|
||||
//unsigned long long cpp_getpid();
|
||||
|
||||
void url_scheme_handler(const std::string& url);
|
||||
|
||||
|
||||
#endif /* wrap_c_objc_h */
|
||||
|
|
|
@ -24,7 +24,8 @@
|
|||
#import "AboutWindowController.h"
|
||||
|
||||
#include "AppDelegate-C-Interface.h"
|
||||
#include "csrc/ts_http_rpc.h"
|
||||
// #include "csrc/ts_http_rpc.h"
|
||||
#include "csrc/ts_ws_client.h"
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
|
@ -79,7 +80,8 @@ int AppDelegate_select_app (void *_self) {
|
|||
|
||||
int ret = cpp_main((__bridge void*)self, bundle_path.c_str(), cpp_cfg_file.c_str(), cpp_res_path.c_str());
|
||||
if(ret != 0) {
|
||||
http_rpc_stop();
|
||||
// http_rpc_stop();
|
||||
TsWsClient::stop_all_client();
|
||||
|
||||
NSString *msg = Nil;
|
||||
if(ret == -1)
|
||||
|
@ -216,10 +218,43 @@ int AppDelegate_select_app (void *_self) {
|
|||
}
|
||||
|
||||
- (IBAction)quit:(id)sender {
|
||||
http_rpc_stop();
|
||||
// http_rpc_stop();
|
||||
TsWsClient::stop_all_client();
|
||||
|
||||
[[NSStatusBar systemStatusBar] removeStatusItem:statusItem];
|
||||
[NSApp terminate:NSApp];
|
||||
}
|
||||
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)notification
|
||||
{
|
||||
// once the program start, register URL scheme handler.
|
||||
[[NSAppleEventManager sharedAppleEventManager] setEventHandler:self andSelector:@selector(handleURLEvent:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL];
|
||||
}
|
||||
|
||||
- (void)handleURLEvent:(NSAppleEventDescriptor*)theEvent withReplyEvent:(NSAppleEventDescriptor*)replyEvent {
|
||||
// Process URL Request
|
||||
NSString* url = [[theEvent paramDescriptorForKeyword:keyDirectObject] stringValue];
|
||||
// unsigned long long pid = cpp_getpid();
|
||||
//
|
||||
// NSAlert *alert = [[NSAlert alloc] init];
|
||||
// alert.icon = [NSImage imageNamed:@"tpassist"];
|
||||
// [alert addButtonWithTitle:@"确定"];
|
||||
// [alert setMessageText:@"URL Request"];
|
||||
// [alert setInformativeText:[NSString stringWithFormat:@"%@, pid=%llu", url, pid]];
|
||||
// [alert runModal];
|
||||
//
|
||||
// [self my_alert:@"URL Request" msg:url];
|
||||
std::string _url = [url cStringUsingEncoding:NSUTF8StringEncoding];
|
||||
url_scheme_handler(_url);
|
||||
}
|
||||
|
||||
- (void)my_alert:(NSString*) title msg:(NSString*)message {
|
||||
NSAlert *alert = [[NSAlert alloc] init];
|
||||
alert.icon = [NSImage imageNamed:@"tpassist"];
|
||||
[alert addButtonWithTitle:@"确定"];
|
||||
[alert setMessageText:title];
|
||||
[alert setInformativeText:[NSString stringWithFormat:@"%@", message]];
|
||||
[alert runModal];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -11,4 +11,4 @@
|
|||
"version" = "";
|
||||
"app_full_name" = "Teleport Assist";
|
||||
"copyright" = "Copyright © 2017~2019, tp4a.com. All rights reserved.";
|
||||
"visit_tp4a_website" = "Visit Teleport Website"
|
||||
"visit_tp4a_website" = "Visit Teleport Website";
|
||||
|
|
|
@ -17,11 +17,26 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>3.5.6</string>
|
||||
<string>$(MARKETING_VERSION)</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
<key>CFBundleURLIconFile</key>
|
||||
<string>tpassist</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>com.tp4a.assist</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>teleport</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>3.5.6</string>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.productivity</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
|
|
|
@ -42,6 +42,8 @@ bool TsCfg::save(const ex_astr& new_value)
|
|||
return false;
|
||||
|
||||
Json::StreamWriterBuilder jwb;
|
||||
jwb["indentation"] = " ";
|
||||
jwb["emitUTF8"] = true;
|
||||
std::unique_ptr<Json::StreamWriter> jwriter(jwb.newStreamWriter());
|
||||
ex_aoss os;
|
||||
jwriter->write(m_root, &os);
|
||||
|
|
|
@ -21,8 +21,8 @@ public:
|
|||
virtual ~TsCfg();
|
||||
|
||||
bool init(void);
|
||||
bool save(const ex_astr& new_value);
|
||||
|
||||
bool save(const ex_astr& new_value);
|
||||
|
||||
Json::Value& get_root() {return m_root;}
|
||||
|
||||
APP_CONFIG ssh;
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "ts_ver.h"
|
||||
#include "ts_env.h"
|
||||
#include "ts_cfg.h"
|
||||
#include "ts_utils.h"
|
||||
|
||||
// #define RDP_CLIENT_SYSTEM_BUILTIN
|
||||
// #define RDP_CLIENT_SYSTEM_ACTIVE_CONTROL
|
||||
|
@ -20,7 +21,7 @@
|
|||
TsHttpRpc g_http_interface;
|
||||
TsHttpRpc g_https_interface;
|
||||
|
||||
void* g_app = NULL;
|
||||
//void* g_app = NULL;
|
||||
|
||||
int http_rpc_start(void* app) {
|
||||
g_app = app;
|
||||
|
@ -58,43 +59,6 @@ void http_rpc_stop(void)
|
|||
g_https_interface.stop();
|
||||
}
|
||||
|
||||
#define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W')
|
||||
|
||||
int ts_url_decode(const char *src, int src_len, char *dst, int dst_len, int is_form_url_encoded)
|
||||
{
|
||||
int i, j, a, b;
|
||||
|
||||
for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++)
|
||||
{
|
||||
if (src[i] == '%')
|
||||
{
|
||||
if (i < src_len - 2 && isxdigit(*(const unsigned char *)(src + i + 1)) &&
|
||||
isxdigit(*(const unsigned char *)(src + i + 2))) {
|
||||
a = tolower(*(const unsigned char *)(src + i + 1));
|
||||
b = tolower(*(const unsigned char *)(src + i + 2));
|
||||
dst[j] = (char)((HEXTOI(a) << 4) | HEXTOI(b));
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (is_form_url_encoded && src[i] == '+')
|
||||
{
|
||||
dst[j] = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
dst[j] = src[i];
|
||||
}
|
||||
}
|
||||
|
||||
dst[j] = '\0'; /* Null-terminate the destination */
|
||||
|
||||
return i >= src_len ? j : -1;
|
||||
}
|
||||
|
||||
TsHttpRpc::TsHttpRpc() :
|
||||
ExThreadBase("http-rpc-thread")
|
||||
{
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
#include <unistd.h>
|
||||
#include "ts_utils.h"
|
||||
|
||||
#define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W')
|
||||
|
||||
int ts_url_decode(const char *src, int src_len, char *dst, int dst_len, int is_form_url_encoded)
|
||||
{
|
||||
int i, j, a, b;
|
||||
|
||||
for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++)
|
||||
{
|
||||
if (src[i] == '%')
|
||||
{
|
||||
if (i < src_len - 2 && isxdigit(*(const unsigned char *)(src + i + 1)) &&
|
||||
isxdigit(*(const unsigned char *)(src + i + 2))) {
|
||||
a = tolower(*(const unsigned char *)(src + i + 1));
|
||||
b = tolower(*(const unsigned char *)(src + i + 2));
|
||||
dst[j] = (char)((HEXTOI(a) << 4) | HEXTOI(b));
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (is_form_url_encoded && src[i] == '+')
|
||||
{
|
||||
dst[j] = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
dst[j] = src[i];
|
||||
}
|
||||
}
|
||||
|
||||
dst[j] = '\0'; /* Null-terminate the destination */
|
||||
|
||||
return i >= src_len ? j : -1;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef __TS_UTILS_H__
|
||||
#define __TS_UTILS_H__
|
||||
|
||||
#include <ex.h>
|
||||
|
||||
int ts_url_decode(const char *src, int src_len, char *dst, int dst_len, int is_form_url_encoded);
|
||||
|
||||
#endif // __TS_UTILS_H__
|
|
@ -1,6 +1,6 @@
|
|||
#ifndef __TS_ASSIST_VER_H__
|
||||
#define __TS_ASSIST_VER_H__
|
||||
|
||||
#define TP_ASSIST_VER L"3.5.6"
|
||||
#define TP_ASSIST_VER L"3.6.0"
|
||||
|
||||
#endif // __TS_ASSIST_VER_H__
|
||||
|
|
|
@ -0,0 +1,836 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include <teleport_const.h>
|
||||
|
||||
#ifndef MAX_PATH
|
||||
# define MAX_PATH 1024
|
||||
#endif
|
||||
|
||||
#include "../AppDelegate-C-Interface.h"
|
||||
|
||||
#include "ts_ws_client.h"
|
||||
#include "ts_ver.h"
|
||||
#include "ts_env.h"
|
||||
#include "ts_cfg.h"
|
||||
#include "ts_utils.h"
|
||||
|
||||
TsWsClient g_ws_client;
|
||||
TsWsClient g_wss_client;
|
||||
|
||||
void* g_app = NULL;
|
||||
|
||||
// static
|
||||
void TsWsClient::init_app(void* app)
|
||||
{
|
||||
g_app = app;
|
||||
}
|
||||
|
||||
void TsWsClient::stop_all_client()
|
||||
{
|
||||
g_ws_client.stop();
|
||||
g_wss_client.stop();
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// static
|
||||
void TsWsClient::url_scheme_handler(const std::string& url)
|
||||
{
|
||||
// url: teleport://register?param={"ws_url":"ws://127.0.0.1:7190/ws/assist/","assist_id":1234,"session_id":"tp_5678"}
|
||||
|
||||
std::string protocol;
|
||||
std::string method;
|
||||
std::string param;
|
||||
|
||||
std::string::size_type pos_protocol = url.find("://");
|
||||
if (pos_protocol == std::string::npos)
|
||||
{
|
||||
EXLOGE("[ws] invalid url: %s\n", url.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
std::string::size_type pos_method = url.find('?');
|
||||
if (pos_method == std::string::npos)
|
||||
{
|
||||
EXLOGE("[ws] invalid url: %s\n", url.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
protocol.assign(url, 0, pos_protocol);
|
||||
if (protocol != "teleport")
|
||||
{
|
||||
EXLOGE("[ws] invalid protocol: %s\n", protocol.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// now we support 'register' method only.
|
||||
method.assign(url, pos_protocol + 3, pos_method - pos_protocol - 3);
|
||||
if (method != "register")
|
||||
{
|
||||
EXLOGE("[ws] unknown method: %s\n", method.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
param.assign(url, pos_method + 7); // ?param=
|
||||
if (param.empty())
|
||||
{
|
||||
EXLOGE("[ws] invalid protocol: %s\n", protocol.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// decode param with url-decode.
|
||||
size_t len = param.length() * 2;
|
||||
ex_chars sztmp;
|
||||
sztmp.resize(len);
|
||||
memset(&sztmp[0], 0, len);
|
||||
if (-1 == ts_url_decode(param.c_str(), (int)param.length(), &sztmp[0], (int)len, 0))
|
||||
{
|
||||
EXLOGE("[ws] url-decode param failed: %s\n", param.c_str());
|
||||
return;
|
||||
}
|
||||
param = &sztmp[0];
|
||||
|
||||
EXLOGV("[rpc] method=%s, json_param=%s\n", method.c_str(), param.c_str());
|
||||
|
||||
Json::CharReaderBuilder jcrb;
|
||||
std::unique_ptr<Json::CharReader> const jreader(jcrb.newCharReader());
|
||||
const char* str_json_begin = param.c_str();
|
||||
|
||||
Json::Value js_root;
|
||||
ex_astr err;
|
||||
if (!jreader->parse(str_json_begin, str_json_begin + param.length(), &js_root, &err))
|
||||
{
|
||||
EXLOGE("[ws] param not in json format: %s\n", param.c_str());
|
||||
return;
|
||||
}
|
||||
if (!js_root.isObject())
|
||||
{
|
||||
EXLOGE("[ws] invalid param, need json object: %s\n", param.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// now we support 'register' method only.
|
||||
_process_register(param, js_root);
|
||||
}
|
||||
|
||||
// static
|
||||
void TsWsClient::_process_register(const std::string& param, Json::Value& js_root)
|
||||
{
|
||||
// {"ws_url":"ws://127.0.0.1:7190/ws/assist/","assist_id":1234,"session_id":"tp_5678"}
|
||||
|
||||
// check param
|
||||
if (!js_root["ws_url"].isString() || !js_root["assist_id"].isNumeric() || !js_root["session_id"].isString())
|
||||
{
|
||||
EXLOGE("[ws] invalid param: %s\n", param.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
std::string ws_url = js_root["ws_url"].asCString();
|
||||
uint32_t assist_id = js_root["assist_id"].asUInt();
|
||||
std::string session_id = js_root["session_id"].asCString();
|
||||
|
||||
std::string protocol;
|
||||
protocol.assign(ws_url, 0, 3);
|
||||
if (protocol == "ws:")
|
||||
{
|
||||
g_ws_client._register(ws_url, assist_id, session_id);
|
||||
}
|
||||
else if (protocol == "wss")
|
||||
{
|
||||
g_wss_client._register(ws_url, assist_id, session_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
EXLOGE("[ws] invalid ws_url: %s\n", ws_url.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================
|
||||
|
||||
TsWsClient::TsWsClient() :
|
||||
ExThreadBase("ws-client-thread"),
|
||||
m_nc(NULL),
|
||||
m_assist_id(0)
|
||||
{
|
||||
mg_mgr_init(&m_mg_mgr, NULL);
|
||||
}
|
||||
|
||||
TsWsClient::~TsWsClient()
|
||||
{
|
||||
mg_mgr_free(&m_mg_mgr);
|
||||
}
|
||||
|
||||
void TsWsClient::_thread_loop(void)
|
||||
{
|
||||
while (!m_need_stop)
|
||||
{
|
||||
mg_mgr_poll(&m_mg_mgr, 500);
|
||||
}
|
||||
|
||||
EXLOGV("[ws] main loop end.\n");
|
||||
}
|
||||
|
||||
void TsWsClient::_register(const std::string& ws_url, uint32_t assist_id, const std::string& session_id)
|
||||
{
|
||||
if (m_assist_id == 0)
|
||||
m_assist_id = assist_id;
|
||||
|
||||
ex_wstr w_ver(TP_ASSIST_VER);
|
||||
ex_astr a_ver;
|
||||
ex_wstr2astr(w_ver, a_ver);
|
||||
|
||||
//
|
||||
char msg[256] = {0};
|
||||
ex_strformat(
|
||||
msg, 256, "{\"type\":0,\"method\":\"register\",\"param\":{\"client\":\"assist\",\"sid\":\"%s\",\"request_assist_id\":%u,\"assist_id\":%u,\"assist_ver\":\"%s\"}}",
|
||||
session_id.c_str(), assist_id, m_assist_id, a_ver.c_str());
|
||||
|
||||
if (!m_is_running)
|
||||
{
|
||||
// not start yet.
|
||||
std::string url = ws_url;
|
||||
url += msg;
|
||||
|
||||
m_nc = mg_connect_ws(&m_mg_mgr, _mg_event_handler, url.c_str(), NULL, NULL);
|
||||
if (!m_nc)
|
||||
{
|
||||
EXLOGE("[ws] TsWsClient::init failed: %s\n", url.c_str());
|
||||
return;
|
||||
}
|
||||
m_nc->user_data = this;
|
||||
|
||||
start();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
EXLOGV("[ws] send: %s\n", msg);
|
||||
mg_send_websocket_frame(m_nc, WEBSOCKET_OP_TEXT, msg, strlen(msg));
|
||||
}
|
||||
|
||||
// static
|
||||
void TsWsClient::_mg_event_handler(struct mg_connection* nc, int ev, void* ev_data)
|
||||
{
|
||||
auto* _this = (TsWsClient*)nc->user_data;
|
||||
if (NULL == _this)
|
||||
{
|
||||
EXLOGE("[ERROR] invalid request.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ev)
|
||||
{
|
||||
case MG_EV_CONNECT:
|
||||
{
|
||||
int status = *((int*)ev_data);
|
||||
if (status != 0)
|
||||
{
|
||||
EXLOGE("[ERROR] -- connect to ws server failed: %d\n", status);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case MG_EV_WEBSOCKET_HANDSHAKE_DONE:
|
||||
{
|
||||
auto* hm = (struct http_message*)ev_data;
|
||||
if (hm->resp_code == 101)
|
||||
{
|
||||
EXLOGV("-- ws server connected\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
EXLOGE("[ERROR] -- connect to ws server failed, HTTP code: %d\n", hm->resp_code);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case MG_EV_WEBSOCKET_FRAME:
|
||||
{
|
||||
// on_message().
|
||||
auto* wm = (struct websocket_message*)ev_data;
|
||||
// EXLOGV("%d: %s\n", wm->size, wm->data);
|
||||
std::string message;
|
||||
message.assign((const char*)wm->data, wm->size);
|
||||
std::string buf;
|
||||
_this->_on_message(message, buf);
|
||||
|
||||
if (!buf.empty())
|
||||
{
|
||||
mg_send_websocket_frame(nc, WEBSOCKET_OP_TEXT, buf.c_str(), buf.length());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case MG_EV_CLOSE:
|
||||
{
|
||||
EXLOGV("-- ws server disconnected\n");
|
||||
_this->m_need_stop = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TsWsClient::_create_response(ex_astr& buf, const AssistMessage& msg_ret, int err_code)
|
||||
{
|
||||
Json::Value js_data(Json::objectValue);
|
||||
_create_response(buf, msg_ret, err_code, "", js_data);
|
||||
}
|
||||
|
||||
void TsWsClient::_create_response(ex_astr& buf, const AssistMessage& msg_ret, int err_code, const std::string& message)
|
||||
{
|
||||
Json::Value js_data(Json::objectValue);
|
||||
_create_response(buf, msg_ret, err_code, message, js_data);
|
||||
}
|
||||
|
||||
void TsWsClient::_create_response(ex_astr& buf, const AssistMessage& msg_ret, int err_code, const std::string& message, Json::Value& data)
|
||||
{
|
||||
Json::Value js_ret;
|
||||
js_ret["type"] = MESSAGE_TYPE_RESPONSE;
|
||||
js_ret["command_id"] = msg_ret.command_id;
|
||||
js_ret["method"] = msg_ret.method;
|
||||
js_ret["code"] = err_code;
|
||||
js_ret["message"] = message;
|
||||
js_ret["data"] = data;
|
||||
|
||||
Json::StreamWriterBuilder jwb;
|
||||
jwb["indentation"] = ""; // 压缩格式,没有换行和不必要的空白字符
|
||||
std::unique_ptr<Json::StreamWriter> js_writer(jwb.newStreamWriter());
|
||||
ex_aoss os;
|
||||
js_writer->write(js_ret, &os);
|
||||
buf = os.str();
|
||||
}
|
||||
|
||||
void TsWsClient::_on_message(const std::string& message, std::string& buf)
|
||||
{
|
||||
// {
|
||||
// "type":0,
|
||||
// "method":"run",
|
||||
// "param":{
|
||||
// "teleport_ip":"127.0.0.1","teleport_port":52189,"remote_host_ip":"39.97.125.170",
|
||||
// "remote_host_name":"tp4a.com","session_id":"9DE744","protocol_type":2,
|
||||
// "protocol_sub_type":200,"protocol_flag":4294967295
|
||||
// }
|
||||
// }
|
||||
|
||||
AssistMessage msg_req;
|
||||
|
||||
Json::CharReaderBuilder jrb;
|
||||
std::unique_ptr<Json::CharReader> const js_reader(jrb.newCharReader());
|
||||
const char* str_json_begin = message.c_str();
|
||||
|
||||
Json::Value js_root;
|
||||
ex_astr err;
|
||||
if (!js_reader->parse(str_json_begin, str_json_begin + message.length(), &js_root, &err))
|
||||
{
|
||||
_create_response(buf, msg_req, TPE_JSON_FORMAT);
|
||||
return;
|
||||
}
|
||||
if (!js_root.isObject())
|
||||
{
|
||||
_create_response(buf, msg_req, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
|
||||
if (js_root["type"].isNull() || !js_root["type"].isInt())
|
||||
{
|
||||
_create_response(buf, msg_req, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
|
||||
int cmd_type = js_root["type"].asInt();
|
||||
if (!(cmd_type == MESSAGE_TYPE_REQUEST || cmd_type == MESSAGE_TYPE_RESPONSE))
|
||||
{
|
||||
_create_response(buf, msg_req, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
|
||||
// 收到的信息已经是“返回值”了,说明已经是一条命令的结束了,不用继续处理
|
||||
// todo: 可能需要记录日志,或者展示结果。
|
||||
if (cmd_type == MESSAGE_TYPE_RESPONSE)
|
||||
return;
|
||||
|
||||
if (js_root["method"].isNull() || !js_root["method"].isString() || js_root["command_id"].isNull() || !js_root["command_id"].isInt())
|
||||
{
|
||||
_create_response(buf, msg_req, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
|
||||
msg_req.command_id = js_root["command_id"].asInt();
|
||||
msg_req.method = js_root["method"].asString();
|
||||
|
||||
if (msg_req.command_id == 0 || msg_req.method.empty())
|
||||
{
|
||||
_create_response(buf, msg_req, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg_req.method == "run")
|
||||
{
|
||||
_rpc_func_run_client(buf, msg_req, js_root);
|
||||
}
|
||||
else if(msg_req.method == "get_config")
|
||||
{
|
||||
_rpc_func_get_config(buf, msg_req, js_root);
|
||||
}
|
||||
else if(msg_req.method == "set_config")
|
||||
{
|
||||
_rpc_func_set_config(buf, msg_req, js_root);
|
||||
}
|
||||
else if(msg_req.method == "select_file")
|
||||
{
|
||||
_rpc_func_select_file(buf, msg_req, js_root);
|
||||
}
|
||||
else
|
||||
{
|
||||
EXLOGE("[ws] got unknown command: %s\n", msg_req.method.c_str());
|
||||
_create_response(buf, msg_req, TPE_UNKNOWN_CMD);
|
||||
}
|
||||
}
|
||||
|
||||
void TsWsClient::_rpc_func_get_config(ex_astr& buf, AssistMessage& msg_req, Json::Value& js_root)
|
||||
{
|
||||
Json::Value& ret = g_cfg.get_root();
|
||||
if(ret["os_type"].isNull())
|
||||
ret["os_type"] = "macos";
|
||||
|
||||
_create_response(buf, msg_req, TPE_OK, "", ret);
|
||||
}
|
||||
|
||||
void TsWsClient::_rpc_func_set_config(ex_astr& buf, AssistMessage& msg_req, Json::Value& js_root)
|
||||
{
|
||||
if (js_root["param"].isNull() || !js_root["param"].isObject())
|
||||
{
|
||||
_create_response(buf, msg_req, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
Json::Value& js_param = js_root["param"];
|
||||
|
||||
Json::StreamWriterBuilder jwb;
|
||||
std::unique_ptr<Json::StreamWriter> js_writer(jwb.newStreamWriter());
|
||||
ex_aoss os;
|
||||
js_writer->write(js_param, &os);
|
||||
|
||||
if (!g_cfg.save(os.str()))
|
||||
_create_response(buf, msg_req, TPE_FAILED);
|
||||
else
|
||||
_create_response(buf, msg_req, TPE_OK);
|
||||
}
|
||||
|
||||
void TsWsClient::_rpc_func_select_file(ex_astr& buf, AssistMessage& msg_req, Json::Value& js_root)
|
||||
{
|
||||
// AppDelegate_select_app(g_app);
|
||||
_create_response(buf, msg_req, TPE_FAILED, "尚不支持在macOS平台选择应用,请手动填写应用程序路径!");
|
||||
}
|
||||
|
||||
void TsWsClient::_rpc_func_run_client(ex_astr& buf, AssistMessage& msg_req, Json::Value& js_root)
|
||||
{
|
||||
// {
|
||||
// "method":"run",
|
||||
// "param":{
|
||||
// "teleport_ip":"127.0.0.1","teleport_port":52189,"remote_host_ip":"39.97.125.170",
|
||||
// "remote_host_name":"tp4a.com","session_id":"9DE744","protocol_type":2,
|
||||
// "protocol_sub_type":200,"protocol_flag":4294967295
|
||||
// }
|
||||
// }
|
||||
|
||||
if (js_root["param"].isNull() || !js_root["param"].isObject())
|
||||
{
|
||||
_create_response(buf, msg_req, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
Json::Value& js_param = js_root["param"];
|
||||
|
||||
// check param
|
||||
if (!js_param["teleport_ip"].isString()
|
||||
|| !js_param["teleport_port"].isNumeric() || !js_param["remote_host_ip"].isString()
|
||||
|| !js_param["session_id"].isString() || !js_param["protocol_type"].isNumeric() || !js_param["protocol_sub_type"].isNumeric()
|
||||
|| !js_param["protocol_flag"].isNumeric()
|
||||
)
|
||||
{
|
||||
_create_response(buf, msg_req, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
|
||||
int pro_type = js_param["protocol_type"].asUInt();
|
||||
int pro_sub = js_param["protocol_sub_type"].asInt();
|
||||
ex_u32 protocol_flag = js_param["protocol_flag"].asUInt();
|
||||
|
||||
ex_astr teleport_ip = js_param["teleport_ip"].asCString();
|
||||
int teleport_port = js_param["teleport_port"].asUInt();
|
||||
char _port[64] = {0};
|
||||
ex_strformat(_port, 64, "%d", teleport_port);
|
||||
ex_astr str_teleport_port = _port;
|
||||
|
||||
ex_astr real_host_ip = js_param["remote_host_ip"].asCString();
|
||||
ex_astr real_host_name = js_param["remote_host_name"].asCString();
|
||||
ex_astr sid = js_param["session_id"].asCString();
|
||||
|
||||
|
||||
ex_astr s_exec;
|
||||
ex_astr s_arg;
|
||||
ex_astrs s_argv;
|
||||
|
||||
|
||||
if (pro_type == TP_PROTOCOL_TYPE_RDP)
|
||||
{
|
||||
//==============================================
|
||||
// RDP
|
||||
//==============================================
|
||||
|
||||
if (g_cfg.rdp.application.length() == 0)
|
||||
{
|
||||
_create_response(buf, msg_req, TPE_NOT_EXISTS, "助手未配置本地RDP客户端,请检查您的助手设置。");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ex_is_file_exists(g_cfg.rdp.application.c_str()))
|
||||
{
|
||||
_create_response(buf, msg_req, TPE_NOT_EXISTS, "无法定位助手配置的RDP客户端,请检查您的助手设置。");
|
||||
return;
|
||||
}
|
||||
|
||||
bool flag_clipboard = ((protocol_flag & TP_FLAG_RDP_CLIPBOARD) == TP_FLAG_RDP_CLIPBOARD);
|
||||
bool flag_disk = ((protocol_flag & TP_FLAG_RDP_DISK) == TP_FLAG_RDP_DISK);
|
||||
bool flag_console = ((protocol_flag & TP_FLAG_RDP_CONSOLE) == TP_FLAG_RDP_CONSOLE);
|
||||
|
||||
int rdp_w = 800;
|
||||
int rdp_h = 640;
|
||||
bool rdp_console = false;
|
||||
|
||||
if (!js_param["rdp_width"].isNull())
|
||||
{
|
||||
if (js_param["rdp_width"].isNumeric())
|
||||
{
|
||||
rdp_w = js_param["rdp_width"].asUInt();
|
||||
}
|
||||
else
|
||||
{
|
||||
_create_response(buf, msg_req, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!js_param["rdp_height"].isNull())
|
||||
{
|
||||
if (js_param["rdp_height"].isNumeric())
|
||||
{
|
||||
rdp_h = js_param["rdp_height"].asUInt();
|
||||
}
|
||||
else
|
||||
{
|
||||
_create_response(buf, msg_req, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!js_param["rdp_console"].isNull())
|
||||
{
|
||||
if (js_param["rdp_console"].isBool())
|
||||
{
|
||||
rdp_console = js_param["rdp_console"].asBool();
|
||||
}
|
||||
else
|
||||
{
|
||||
_create_response(buf, msg_req, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!flag_console)
|
||||
rdp_console = false;
|
||||
|
||||
|
||||
size_t split_pos = sid.length() - 2;
|
||||
ex_astr real_sid = sid.substr(0, split_pos);
|
||||
ex_astr str_pwd_len = sid.substr(split_pos, sid.length());
|
||||
size_t n_pwd_len = strtol(str_pwd_len.c_str(), NULL, 16);
|
||||
n_pwd_len -= real_sid.length();
|
||||
n_pwd_len -= 2;
|
||||
char szPwd[256] = {0};
|
||||
for (int i = 0; i < n_pwd_len; i++)
|
||||
{
|
||||
szPwd[i] = '*';
|
||||
}
|
||||
|
||||
//ex_astr2wstr(real_sid, w_sid);
|
||||
|
||||
//w_exe_path = _T("\"");
|
||||
//w_exe_path += g_cfg.rdp_app + _T("\" ");
|
||||
//w_exe_path += g_cfg.rdp_cmdline;
|
||||
//w_exe_path = _T("xfreerdp -u {user_name} {size} {console} {clipboard} {drives} ");
|
||||
//w_exe_path = _T("/usr/local/Cellar/freerdp/1.0.2_1/bin/xfreerdp -u {user_name} {size} {console} ");
|
||||
//w_exe_path = _T("xfreerdp -u {user_name} {size} {console} ");
|
||||
//s_exec = "/usr/local/Cellar/freerdp/1.0.2_1/bin/xfreerdp";
|
||||
s_exec = g_cfg.rdp.application;
|
||||
s_arg = g_cfg.rdp.cmdline;
|
||||
|
||||
sid = "02" + real_sid;
|
||||
// s_argv.push_back("/f");
|
||||
|
||||
s_argv.push_back("/sec:tls");
|
||||
s_argv.push_back("-wallpaper");
|
||||
s_argv.push_back("-themes");
|
||||
// Ignore certificate
|
||||
s_argv.push_back("/cert-ignore");
|
||||
// Automatically accept certificate on first connect
|
||||
s_argv.push_back("/cert-tofu");
|
||||
|
||||
ex_astr _tmp_pass = "/p:PLACEHOLDER";
|
||||
//_tmp_pass += szPwd;
|
||||
s_argv.push_back(_tmp_pass);
|
||||
|
||||
//#if 0
|
||||
//s_argv.push_back(s_exec.c_str());
|
||||
|
||||
{
|
||||
// ex_astr username = "02" + real_sid;
|
||||
// s_argv.push_back("/u:");
|
||||
// s_argv.push_back(username.c_str());
|
||||
|
||||
|
||||
if (rdp_w == 0 || rdp_h == 0)
|
||||
{
|
||||
s_argv.push_back("/f");
|
||||
}
|
||||
else
|
||||
{
|
||||
// char sz_size[64] = {0};
|
||||
// ex_strformat(sz_size, 63, "%dx%d", rdp_w, rdp_h);
|
||||
// s_argv.push_back("-g");
|
||||
// s_argv.push_back(sz_size);
|
||||
char sz_width[64] = {0};
|
||||
ex_strformat(sz_width, 63, "/w:%d", rdp_w);
|
||||
s_argv.push_back(sz_width);
|
||||
|
||||
char sz_height[64] = {0};
|
||||
ex_strformat(sz_height, 63, "/h:%d", rdp_h);
|
||||
s_argv.push_back(sz_height);
|
||||
}
|
||||
|
||||
if (flag_console && rdp_console)
|
||||
s_argv.push_back("/admin");
|
||||
|
||||
// if(flag_clipboard)
|
||||
// s_argv.push_back("+clipboard");
|
||||
// else
|
||||
// s_argv.push_back("-clipboard");
|
||||
|
||||
// if(flag_disk)
|
||||
// s_argv.push_back("+drives");
|
||||
// else
|
||||
// s_argv.push_back("-drives");
|
||||
//
|
||||
// {
|
||||
// char sz_temp[128] = {0};
|
||||
// ex_strformat(sz_temp, 127, "%s:%d", teleport_ip.c_str(), teleport_port);
|
||||
// s_argv.push_back(sz_temp);
|
||||
// }
|
||||
}
|
||||
//#endif
|
||||
}
|
||||
else if (pro_type == TP_PROTOCOL_TYPE_SSH)
|
||||
{
|
||||
//==============================================
|
||||
// SSH
|
||||
//==============================================
|
||||
|
||||
if (pro_sub == TP_PROTOCOL_TYPE_SSH_SHELL)
|
||||
{
|
||||
if (g_cfg.ssh.name == "terminal" || g_cfg.ssh.name == "iterm2")
|
||||
{
|
||||
char szCmd[1024] = {0};
|
||||
ex_strformat(szCmd, 1023, "ssh %s@%s -p %d -o \"StrictHostKeyChecking no\"", sid.c_str(), teleport_ip.c_str(), teleport_port);
|
||||
|
||||
char szTitle[128] = {0};
|
||||
ex_strformat(szTitle, 127, "TP#%s", real_host_ip.c_str());
|
||||
|
||||
int ret = AppDelegate_start_ssh_client(g_app, szCmd, g_cfg.ssh.name.c_str(), g_cfg.ssh.cmdline.c_str(), szTitle);
|
||||
if (ret == 0)
|
||||
_create_response(buf, msg_req, TPE_OK);
|
||||
else
|
||||
_create_response(buf, msg_req, TPE_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_cfg.ssh.application.length() == 0)
|
||||
{
|
||||
_create_response(buf, msg_req, TPE_NOT_EXISTS);
|
||||
return;
|
||||
}
|
||||
|
||||
s_exec = g_cfg.ssh.application;
|
||||
s_argv.push_back(s_exec.c_str());
|
||||
|
||||
s_arg = g_cfg.ssh.cmdline;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// sorry, SFTP not supported yet for macOS.
|
||||
// _create_json_ret(buf, TPE_NOT_IMPLEMENT);
|
||||
// return;
|
||||
|
||||
if (g_cfg.sftp.application.length() == 0)
|
||||
{
|
||||
_create_response(buf, msg_req, TPE_NOT_EXISTS);
|
||||
return;
|
||||
}
|
||||
|
||||
s_exec = g_cfg.sftp.application;
|
||||
s_argv.push_back(s_exec.c_str());
|
||||
|
||||
s_arg = g_cfg.sftp.cmdline;
|
||||
}
|
||||
}
|
||||
else if (pro_type == TP_PROTOCOL_TYPE_TELNET)
|
||||
{
|
||||
//==============================================
|
||||
// TELNET
|
||||
//==============================================
|
||||
|
||||
// sorry, TELNET not supported yet for macOS.
|
||||
// _create_json_ret(buf, TPE_NOT_IMPLEMENT);
|
||||
// return;
|
||||
|
||||
g_cfg.telnet.name = "iterm2";
|
||||
|
||||
if (g_cfg.telnet.name == "terminal" || g_cfg.telnet.name == "iterm2")
|
||||
{
|
||||
char szCmd[1024] = {0};
|
||||
ex_strformat(szCmd, 1023, "telnet -l %s %s %d", sid.c_str(), teleport_ip.c_str(), teleport_port);
|
||||
|
||||
char szTitle[128] = {0};
|
||||
ex_strformat(szTitle, 127, "TP#%s", real_host_ip.c_str());
|
||||
|
||||
int ret = AppDelegate_start_ssh_client(g_app, szCmd, g_cfg.telnet.name.c_str(), g_cfg.telnet.cmdline.c_str(), szTitle);
|
||||
if (ret == 0)
|
||||
_create_response(buf, msg_req, TPE_OK);
|
||||
else
|
||||
_create_response(buf, msg_req, TPE_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_cfg.telnet.application.length() == 0)
|
||||
{
|
||||
_create_response(buf, msg_req, TPE_NOT_EXISTS);
|
||||
return;
|
||||
}
|
||||
|
||||
s_exec = g_cfg.telnet.application;
|
||||
s_argv.push_back(s_exec.c_str());
|
||||
|
||||
s_arg = g_cfg.telnet.cmdline;
|
||||
}
|
||||
|
||||
|
||||
//---- split s_arg and push to s_argv ---
|
||||
ex_astr::size_type p1 = 0;
|
||||
ex_astr::size_type p2 = 0;
|
||||
ex_astr tmp = s_arg;
|
||||
for (;;)
|
||||
{
|
||||
ex_remove_white_space(tmp, EX_RSC_BEGIN);
|
||||
if (tmp.empty())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (tmp[0] == '"')
|
||||
{
|
||||
p1 = 1;
|
||||
p2 = tmp.find('"', p1);
|
||||
|
||||
if (p2 == ex_astr::npos)
|
||||
{
|
||||
_create_response(buf, msg_req, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
|
||||
ex_astr _t;
|
||||
_t.assign(tmp, p1, p2 - p1);
|
||||
tmp.erase(0, p2 + 2);
|
||||
|
||||
s_argv.push_back(_t);
|
||||
}
|
||||
else
|
||||
{
|
||||
p1 = 0;
|
||||
p2 = tmp.find(' ', p1);
|
||||
|
||||
if (p2 == ex_astr::npos)
|
||||
{
|
||||
s_argv.push_back(tmp);
|
||||
tmp.clear();
|
||||
break;
|
||||
}
|
||||
|
||||
ex_astr _t;
|
||||
_t.assign(tmp, p1, p2 - p1);
|
||||
tmp.erase(0, p2 + 1);
|
||||
|
||||
s_argv.push_back(_t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Json::Value js_data;
|
||||
ex_astr utf8_path = s_exec;
|
||||
|
||||
ex_astrs::iterator it = s_argv.begin();
|
||||
for (; it != s_argv.end(); ++it)
|
||||
{
|
||||
ex_replace_all((*it), "{host_port}", str_teleport_port);
|
||||
ex_replace_all((*it), "{host_ip}", teleport_ip);
|
||||
ex_replace_all((*it), "{user_name}", sid);
|
||||
ex_replace_all((*it), "{real_ip}", real_host_ip);
|
||||
ex_replace_all((*it), "{host_name}", real_host_name);
|
||||
//ex_replace_all(utf8_path, _T("{assist_tools_path}"), g_env.m_tools_path.c_str());
|
||||
|
||||
utf8_path += " ";
|
||||
utf8_path += (*it);
|
||||
}
|
||||
|
||||
js_data["path"] = utf8_path;
|
||||
|
||||
// for macOS, Create Process should be fork()/exec()...
|
||||
pid_t processId;
|
||||
if ((processId = fork()) == 0)
|
||||
{
|
||||
|
||||
int i = 0;
|
||||
char** _argv = (char**)calloc(s_argv.size() + 1, sizeof(char*));
|
||||
if (!_argv)
|
||||
return;
|
||||
|
||||
for (i = 0; i < s_argv.size(); ++i)
|
||||
{
|
||||
_argv[i] = ex_strdup(s_argv[i].c_str());
|
||||
}
|
||||
_argv[i] = NULL;
|
||||
|
||||
execv(s_exec.c_str(), _argv);
|
||||
|
||||
for (i = 0; i < s_argv.size(); ++i)
|
||||
{
|
||||
if (_argv[i] != NULL)
|
||||
{
|
||||
free(_argv[i]);
|
||||
}
|
||||
}
|
||||
free(_argv);
|
||||
}
|
||||
else if (processId < 0)
|
||||
{
|
||||
_create_response(buf, msg_req, TPE_FAILED);
|
||||
}
|
||||
else
|
||||
{
|
||||
_create_response(buf, msg_req, TPE_OK, "", js_data);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
#ifndef __TS_WS_CLIENT_H__
|
||||
#define __TS_WS_CLIENT_H__
|
||||
|
||||
#include "ts_const.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include <ex.h>
|
||||
#include <json/json.h>
|
||||
#include <teleport_const.h>
|
||||
|
||||
#include "../../external/mongoose/mongoose.h"
|
||||
|
||||
#define MESSAGE_TYPE_REQUEST 0
|
||||
#define MESSAGE_TYPE_RESPONSE 1
|
||||
|
||||
typedef struct AssistMessage
|
||||
{
|
||||
int command_id;
|
||||
std::string method;
|
||||
|
||||
AssistMessage() :
|
||||
command_id(0),
|
||||
method("UNKNOWN") {}
|
||||
} AssistMessage;
|
||||
|
||||
class TsWsClient : public ExThreadBase
|
||||
{
|
||||
public:
|
||||
TsWsClient();
|
||||
|
||||
~TsWsClient();
|
||||
|
||||
static void init_app(void* app);
|
||||
static void stop_all_client();
|
||||
|
||||
static void url_scheme_handler(const std::string& url);
|
||||
|
||||
protected:
|
||||
void _thread_loop(void);
|
||||
|
||||
bool _on_init();
|
||||
|
||||
private:
|
||||
void _register(const std::string& ws_url, uint32_t assist_id, const std::string& session_id);
|
||||
|
||||
void _on_message(const std::string& message, std::string& buf);
|
||||
|
||||
void _rpc_func_run_client(ex_astr& buf, AssistMessage& msg_req, Json::Value& js_root);
|
||||
|
||||
void _rpc_func_get_config(ex_astr& buf, AssistMessage& msg_req, Json::Value& js_root);
|
||||
|
||||
void _rpc_func_set_config(ex_astr& buf, AssistMessage& msg_req, Json::Value& js_root);
|
||||
|
||||
void _rpc_func_select_file(ex_astr& buf, AssistMessage& msg_req, Json::Value& js_root);
|
||||
|
||||
void _send_result(int err_code, Json::Value& jr_root);
|
||||
|
||||
|
||||
void _create_response(ex_astr& buf, const AssistMessage& msg_ret, int err_code);
|
||||
|
||||
void _create_response(ex_astr& buf, const AssistMessage& msg_ret, int err_code, const std::string& message);
|
||||
|
||||
void _create_response(ex_astr& buf, const AssistMessage& msg_ret, int err_code, const std::string& message, Json::Value& data);
|
||||
|
||||
// void _rpc_func_check(const ex_astr& func_args, ex_astr& buf);
|
||||
// void _rpc_func_rdp_play(const ex_astr& func_args, ex_astr& buf);
|
||||
// void _rpc_func_file_action(const ex_astr& func_args, ex_astr& buf);
|
||||
// void _rpc_func_get_version(const ex_astr& func_args, ex_astr& buf);
|
||||
|
||||
|
||||
|
||||
static void _mg_event_handler(struct mg_connection* nc, int ev, void* ev_data);
|
||||
|
||||
static void _process_register(const std::string& param, Json::Value& js_root);
|
||||
|
||||
private:
|
||||
struct mg_mgr m_mg_mgr;
|
||||
struct mg_connection* m_nc;
|
||||
uint32_t m_assist_id;
|
||||
};
|
||||
|
||||
#endif // __TS_WS_CLIENT_H__
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __LIB_EX_PATH_H__
|
||||
#ifndef __LIB_EX_PATH_H__
|
||||
#define __LIB_EX_PATH_H__
|
||||
|
||||
#include "ex_platform.h"
|
||||
|
@ -18,6 +18,8 @@ wchar_t* ex_dirname(const wchar_t* in_filename); // must use ex_free() to releas
|
|||
|
||||
EX_BOOL ex_is_dir_exists(const wchar_t* in_path);
|
||||
EX_BOOL ex_is_file_exists(const wchar_t* in_file);
|
||||
EX_BOOL ex_is_dir_exists(const char* in_path);
|
||||
EX_BOOL ex_is_file_exists(const char* in_file);
|
||||
|
||||
EX_BOOL ex_rename_file(const wchar_t* from_name, const wchar_t* to_name);
|
||||
EX_BOOL ex_remove_file(const wchar_t* file_name);
|
||||
|
|
|
@ -125,7 +125,7 @@ EX_BOOL ex_is_dir_exists(const wchar_t* in_path)
|
|||
if (!PathIsDirectory(in_path))
|
||||
return false;
|
||||
#else
|
||||
struct stat si;
|
||||
struct stat si{};
|
||||
ex_astr _in_path;
|
||||
ex_wstr2astr(in_path, _in_path);
|
||||
if (0 != stat(_in_path.c_str(), &si))
|
||||
|
@ -136,6 +136,25 @@ EX_BOOL ex_is_dir_exists(const wchar_t* in_path)
|
|||
return true;
|
||||
}
|
||||
|
||||
EX_BOOL ex_is_dir_exists(const char* in_path)
|
||||
{
|
||||
#ifdef EX_OS_WIN32
|
||||
ex_wstr _in_path;
|
||||
ex_astr2wstr(in_path, _in_path);
|
||||
if (!PathFileExists(_in_path.c_str()))
|
||||
return false;
|
||||
if (!PathIsDirectory(_in_path.c_str()))
|
||||
return false;
|
||||
#else
|
||||
struct stat si{};
|
||||
if (0 != stat(in_path, &si))
|
||||
return false;
|
||||
if (!S_ISDIR(si.st_mode))
|
||||
return false;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
EX_BOOL ex_is_file_exists(const wchar_t* in_file)
|
||||
{
|
||||
#ifdef EX_OS_WIN32
|
||||
|
@ -144,7 +163,7 @@ EX_BOOL ex_is_file_exists(const wchar_t* in_file)
|
|||
if (PathIsDirectory(in_file))
|
||||
return EX_FALSE;
|
||||
#else
|
||||
struct stat si;
|
||||
struct stat si{};
|
||||
ex_astr _in_file;
|
||||
ex_wstr2astr(in_file, _in_file);
|
||||
if (0 != stat(_in_file.c_str(), &si))
|
||||
|
@ -155,6 +174,25 @@ EX_BOOL ex_is_file_exists(const wchar_t* in_file)
|
|||
return EX_TRUE;
|
||||
}
|
||||
|
||||
EX_BOOL ex_is_file_exists(const char* in_file)
|
||||
{
|
||||
#ifdef EX_OS_WIN32
|
||||
ex_wstr _in_path;
|
||||
ex_astr2wstr(in_path, _in_path);
|
||||
if (!PathFileExists(_in_file.c_str()))
|
||||
return EX_FALSE;
|
||||
if (PathIsDirectory(_in_file.c_str()))
|
||||
return EX_FALSE;
|
||||
#else
|
||||
struct stat si{};
|
||||
if (0 != stat(in_file, &si))
|
||||
return EX_FALSE;
|
||||
if (!S_ISREG(si.st_mode))
|
||||
return EX_FALSE;
|
||||
#endif
|
||||
return EX_TRUE;
|
||||
}
|
||||
|
||||
EX_BOOL ex_rename_file(const wchar_t* from_name, const wchar_t* to_name)
|
||||
{
|
||||
#ifdef EX_OS_WIN32
|
||||
|
|
|
@ -8,7 +8,7 @@ fi
|
|||
DAEMON_PATH={daemon_path}
|
||||
|
||||
if [ $SRV == all ] || [ $SRV == web ] ; then
|
||||
echo -n "stoping teleport web ... "
|
||||
echo -n "stopping teleport web ... "
|
||||
result=$( ps ax | grep "$DAEMON_PATH/bin/tp_web start" | grep -v grep | wc -l )
|
||||
if [ $result -gt 0 ]; then
|
||||
ps ax | grep "$DAEMON_PATH/bin/tp_web start" | grep -v grep | kill `awk '{{print $1}}'`
|
||||
|
@ -19,7 +19,7 @@ if [ $SRV == all ] || [ $SRV == web ] ; then
|
|||
fi
|
||||
|
||||
if [ $SRV == all ] || [ $SRV == core ] ; then
|
||||
echo -n "stoping teleport core server ... "
|
||||
echo -n "stopping teleport core server ... "
|
||||
result=$( ps ax | grep "$DAEMON_PATH/bin/tp_core start" | grep -v grep | wc -l )
|
||||
if [ $result -gt 0 ]; then
|
||||
ps ax | grep "$DAEMON_PATH/bin/tp_core start" | grep -v grep | kill `awk '{{print $1}}'`
|
||||
|
|
|
@ -13,182 +13,187 @@ extern TppManager g_tpp_mgr;
|
|||
|
||||
|
||||
#define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W')
|
||||
int ts_url_decode(const char *src, int src_len, char *dst, int dst_len, int is_form_url_encoded)
|
||||
|
||||
int ts_url_decode(const char* src, int src_len, char* dst, int dst_len, int is_form_url_encoded)
|
||||
{
|
||||
int i, j, a, b;
|
||||
int i, j, a, b;
|
||||
|
||||
for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++)
|
||||
{
|
||||
if (src[i] == '%')
|
||||
{
|
||||
if (i < src_len - 2 && isxdigit(*(const unsigned char *)(src + i + 1)) &&
|
||||
isxdigit(*(const unsigned char *)(src + i + 2))) {
|
||||
a = tolower(*(const unsigned char *)(src + i + 1));
|
||||
b = tolower(*(const unsigned char *)(src + i + 2));
|
||||
dst[j] = (char)((HEXTOI(a) << 4) | HEXTOI(b));
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (is_form_url_encoded && src[i] == '+')
|
||||
{
|
||||
dst[j] = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
dst[j] = src[i];
|
||||
}
|
||||
}
|
||||
for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++)
|
||||
{
|
||||
if (src[i] == '%')
|
||||
{
|
||||
if (i < src_len - 2 && isxdigit(*(const unsigned char*)(src + i + 1)) &&
|
||||
isxdigit(*(const unsigned char*)(src + i + 2)))
|
||||
{
|
||||
a = tolower(*(const unsigned char*)(src + i + 1));
|
||||
b = tolower(*(const unsigned char*)(src + i + 2));
|
||||
dst[j] = (char)((HEXTOI(a) << 4) | HEXTOI(b));
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (is_form_url_encoded && src[i] == '+')
|
||||
{
|
||||
dst[j] = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
dst[j] = src[i];
|
||||
}
|
||||
}
|
||||
|
||||
dst[j] = '\0'; /* Null-terminate the destination */
|
||||
dst[j] = '\0'; /* Null-terminate the destination */
|
||||
|
||||
return i >= src_len ? j : -1;
|
||||
return i >= src_len ? j : -1;
|
||||
}
|
||||
|
||||
TsHttpRpc::TsHttpRpc() :
|
||||
ExThreadBase("http-rpc-thread")
|
||||
ExThreadBase("http-rpc-thread")
|
||||
{
|
||||
mg_mgr_init(&m_mg_mgr, NULL);
|
||||
mg_mgr_init(&m_mg_mgr, NULL);
|
||||
}
|
||||
|
||||
TsHttpRpc::~TsHttpRpc()
|
||||
{
|
||||
mg_mgr_free(&m_mg_mgr);
|
||||
mg_mgr_free(&m_mg_mgr);
|
||||
}
|
||||
|
||||
void TsHttpRpc::_thread_loop(void)
|
||||
{
|
||||
EXLOGI("[core] TeleportServer-RPC ready on %s:%d\n", m_host_ip.c_str(), m_host_port);
|
||||
EXLOGI("[core] TeleportServer-RPC ready on %s:%d\n", m_host_ip.c_str(), m_host_port);
|
||||
|
||||
while (!m_need_stop)
|
||||
{
|
||||
mg_mgr_poll(&m_mg_mgr, 500);
|
||||
}
|
||||
while (!m_need_stop)
|
||||
{
|
||||
mg_mgr_poll(&m_mg_mgr, 500);
|
||||
}
|
||||
|
||||
EXLOGV("[core] rpc main loop end.\n");
|
||||
EXLOGV("[core] rpc main loop end.\n");
|
||||
}
|
||||
|
||||
|
||||
bool TsHttpRpc::init(void)
|
||||
{
|
||||
struct mg_connection* nc = NULL;
|
||||
struct mg_connection* nc = NULL;
|
||||
|
||||
m_host_ip = g_env.rpc_bind_ip;
|
||||
m_host_port = g_env.rpc_bind_port;
|
||||
m_host_ip = g_env.rpc_bind_ip;
|
||||
m_host_port = g_env.rpc_bind_port;
|
||||
|
||||
char addr[128] = { 0 };
|
||||
// if (0 == strcmp(m_host_ip.c_str(), "127.0.0.1") || 0 == strcmp(m_host_ip.c_str(), "localhost"))
|
||||
// ex_strformat(addr, 128, ":%d", m_host_port);
|
||||
// else
|
||||
// ex_strformat(addr, 128, "%s:%d", m_host_ip.c_str(), m_host_port);
|
||||
if (0 == strcmp(m_host_ip.c_str(), "0.0.0.0"))
|
||||
ex_strformat(addr, 128, ":%d", m_host_port);
|
||||
else
|
||||
ex_strformat(addr, 128, "%s:%d", m_host_ip.c_str(), m_host_port);
|
||||
char addr[128] = {0};
|
||||
// if (0 == strcmp(m_host_ip.c_str(), "127.0.0.1") || 0 == strcmp(m_host_ip.c_str(), "localhost"))
|
||||
// ex_strformat(addr, 128, ":%d", m_host_port);
|
||||
// else
|
||||
// ex_strformat(addr, 128, "%s:%d", m_host_ip.c_str(), m_host_port);
|
||||
if (0 == strcmp(m_host_ip.c_str(), "0.0.0.0"))
|
||||
ex_strformat(addr, 128, ":%d", m_host_port);
|
||||
else
|
||||
ex_strformat(addr, 128, "%s:%d", m_host_ip.c_str(), m_host_port);
|
||||
|
||||
nc = mg_bind(&m_mg_mgr, addr, _mg_event_handler);
|
||||
if (NULL == nc)
|
||||
{
|
||||
EXLOGE("[core] rpc listener failed to bind at %s.\n", addr);
|
||||
return false;
|
||||
}
|
||||
nc = mg_bind(&m_mg_mgr, addr, _mg_event_handler);
|
||||
if (NULL == nc)
|
||||
{
|
||||
EXLOGE("[core] rpc listener failed to bind at %s.\n", addr);
|
||||
return false;
|
||||
}
|
||||
|
||||
nc->user_data = this;
|
||||
nc->user_data = this;
|
||||
|
||||
mg_set_protocol_http_websocket(nc);
|
||||
mg_set_protocol_http_websocket(nc);
|
||||
|
||||
// 导致内存泄露的地方(每次请求约消耗1KB内存)
|
||||
// DO NOT USE MULTITHREADING OF MG.
|
||||
// cpq (one of the authors of MG) commented on 3 Feb: Multithreading support has been removed.
|
||||
// https://github.com/cesanta/mongoose/commit/707b9ed2d6f177b3ad8787cb16a1bff90ddad992
|
||||
//mg_enable_multithreading(nc);
|
||||
// 导致内存泄露的地方(每次请求约消耗1KB内存)
|
||||
// DO NOT USE MULTITHREADING OF MG.
|
||||
// cpq (one of the authors of MG) commented on 3 Feb: Multithreading support has been removed.
|
||||
// https://github.com/cesanta/mongoose/commit/707b9ed2d6f177b3ad8787cb16a1bff90ddad992
|
||||
//mg_enable_multithreading(nc);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void TsHttpRpc::_mg_event_handler(struct mg_connection *nc, int ev, void *ev_data)
|
||||
void TsHttpRpc::_mg_event_handler(struct mg_connection* nc, int ev, void* ev_data)
|
||||
{
|
||||
struct http_message *hm = (struct http_message*)ev_data;
|
||||
struct http_message* hm = (struct http_message*)ev_data;
|
||||
|
||||
TsHttpRpc* _this = (TsHttpRpc*)nc->user_data;
|
||||
if (NULL == _this)
|
||||
{
|
||||
EXLOGE("[core] rpc invalid http request.\n");
|
||||
return;
|
||||
}
|
||||
TsHttpRpc* _this = (TsHttpRpc*)nc->user_data;
|
||||
if (NULL == _this)
|
||||
{
|
||||
EXLOGE("[core] rpc invalid http request.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ev)
|
||||
{
|
||||
case MG_EV_HTTP_REQUEST:
|
||||
{
|
||||
ex_astr ret_buf;
|
||||
switch (ev)
|
||||
{
|
||||
case MG_EV_HTTP_REQUEST:
|
||||
{
|
||||
ex_astr ret_buf;
|
||||
|
||||
ex_astr uri;
|
||||
uri.assign(hm->uri.p, hm->uri.len);
|
||||
ex_astr uri;
|
||||
uri.assign(hm->uri.p, hm->uri.len);
|
||||
|
||||
//EXLOGD("[core] rpc got request: %s\n", uri.c_str());
|
||||
//EXLOGD("[core] rpc got request: %s\n", uri.c_str());
|
||||
|
||||
if (uri == "/rpc")
|
||||
{
|
||||
ex_astr method;
|
||||
Json::Value json_param;
|
||||
if (uri == "/rpc")
|
||||
{
|
||||
ex_astr method;
|
||||
Json::Value json_param;
|
||||
|
||||
ex_rv rv = _this->_parse_request(hm, method, json_param);
|
||||
if (TPE_OK != rv)
|
||||
{
|
||||
EXLOGE("[core] rpc got invalid request.\n");
|
||||
_this->_create_json_ret(ret_buf, rv);
|
||||
}
|
||||
else
|
||||
{
|
||||
EXLOGD("[core] rpc got request method `%s`\n", method.c_str());
|
||||
_this->_process_request(method, json_param, ret_buf);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EXLOGE("[core] rpc got invalid request: not `rpc` uri.\n");
|
||||
_this->_create_json_ret(ret_buf, TPE_PARAM, "not a `rpc` request.");
|
||||
}
|
||||
ex_rv rv = _this->_parse_request(hm, method, json_param);
|
||||
if (TPE_OK != rv)
|
||||
{
|
||||
EXLOGE("[core] rpc got invalid request.\n");
|
||||
_this->_create_json_ret(ret_buf, rv);
|
||||
}
|
||||
else
|
||||
{
|
||||
EXLOGD("[core] rpc got request method `%s`\n", method.c_str());
|
||||
_this->_process_request(method, json_param, ret_buf);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EXLOGE("[core] rpc got invalid request: not `rpc` uri.\n");
|
||||
_this->_create_json_ret(ret_buf, TPE_PARAM, "not a `rpc` request.");
|
||||
}
|
||||
|
||||
mg_printf(nc, "HTTP/1.0 200 OK\r\nAccess-Control-Allow-Origin: *\r\nContent-Length: %d\r\nContent-Type: application/json\r\n\r\n%s", (int)ret_buf.length(), &ret_buf[0]);
|
||||
nc->flags |= MG_F_SEND_AND_CLOSE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
mg_printf(nc, "HTTP/1.0 200 OK\r\nAccess-Control-Allow-Origin: *\r\nContent-Length: %d\r\nContent-Type: application/json\r\n\r\n%s", (int)ret_buf.length(), &ret_buf[0]);
|
||||
nc->flags |= MG_F_SEND_AND_CLOSE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ex_rv TsHttpRpc::_parse_request(struct http_message* req, ex_astr& func_cmd, Json::Value& json_param)
|
||||
{
|
||||
if (NULL == req)
|
||||
return TPE_PARAM;
|
||||
if (NULL == req)
|
||||
return TPE_PARAM;
|
||||
|
||||
bool is_get = true;
|
||||
if (req->method.len == 3 && 0 == memcmp(req->method.p, "GET", req->method.len))
|
||||
is_get = true;
|
||||
else if (req->method.len == 4 && 0 == memcmp(req->method.p, "POST", req->method.len))
|
||||
is_get = false;
|
||||
else
|
||||
return TPE_HTTP_METHOD;
|
||||
bool is_get = true;
|
||||
if (req->method.len == 3 && 0 == memcmp(req->method.p, "GET", req->method.len))
|
||||
is_get = true;
|
||||
else if (req->method.len == 4 && 0 == memcmp(req->method.p, "POST", req->method.len))
|
||||
is_get = false;
|
||||
else
|
||||
return TPE_HTTP_METHOD;
|
||||
|
||||
ex_astr json_str;
|
||||
ex_astr json_str;
|
||||
bool need_decode = false;
|
||||
if (is_get) {
|
||||
if (is_get)
|
||||
{
|
||||
json_str.assign(req->query_string.p, req->query_string.len);
|
||||
need_decode = true;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
json_str.assign(req->body.p, req->body.len);
|
||||
if (json_str.length() > 0 && json_str[0] == '%')
|
||||
need_decode = true;
|
||||
}
|
||||
|
||||
if (need_decode) {
|
||||
if (need_decode)
|
||||
{
|
||||
// 将参数进行 url-decode 解码
|
||||
int len = json_str.length() * 2;
|
||||
ex_chars sztmp;
|
||||
|
@ -200,40 +205,40 @@ ex_rv TsHttpRpc::_parse_request(struct http_message* req, ex_astr& func_cmd, Jso
|
|||
json_str = &sztmp[0];
|
||||
}
|
||||
|
||||
if (0 == json_str.length())
|
||||
return TPE_PARAM;
|
||||
if (0 == json_str.length())
|
||||
return TPE_PARAM;
|
||||
|
||||
//Json::Reader jreader;
|
||||
Json::CharReaderBuilder jcrb;
|
||||
std::unique_ptr<Json::CharReader> const jreader(jcrb.newCharReader());
|
||||
const char *str_json_begin = json_str.c_str();
|
||||
const char* str_json_begin = json_str.c_str();
|
||||
ex_astr err;
|
||||
|
||||
//if (!jreader.parse(json_str.c_str(), json_param))
|
||||
//if (!jreader.parse(json_str.c_str(), json_param))
|
||||
if (!jreader->parse(str_json_begin, str_json_begin + json_str.length(), &json_param, &err))
|
||||
return TPE_JSON_FORMAT;
|
||||
return TPE_JSON_FORMAT;
|
||||
|
||||
if (json_param.isArray())
|
||||
return TPE_PARAM;
|
||||
if (json_param.isArray())
|
||||
return TPE_PARAM;
|
||||
|
||||
if (json_param["method"].isNull() || !json_param["method"].isString())
|
||||
return TPE_PARAM;
|
||||
if (json_param["method"].isNull() || !json_param["method"].isString())
|
||||
return TPE_PARAM;
|
||||
|
||||
func_cmd = json_param["method"].asCString();
|
||||
json_param = json_param["param"];
|
||||
func_cmd = json_param["method"].asCString();
|
||||
json_param = json_param["param"];
|
||||
|
||||
return TPE_OK;
|
||||
return TPE_OK;
|
||||
}
|
||||
|
||||
void TsHttpRpc::_create_json_ret(ex_astr& buf, int errcode, const Json::Value& jr_data)
|
||||
{
|
||||
// 返回: {"code":errcode, "data":{jr_data}}
|
||||
// 返回: {"code":errcode, "data":{jr_data}}
|
||||
|
||||
//Json::FastWriter jr_writer;
|
||||
Json::Value jr_root;
|
||||
jr_root["code"] = errcode;
|
||||
jr_root["data"] = jr_data;
|
||||
//buf = jr_writer.write(jr_root);
|
||||
//Json::FastWriter jr_writer;
|
||||
Json::Value jr_root;
|
||||
jr_root["code"] = errcode;
|
||||
jr_root["data"] = jr_data;
|
||||
//buf = jr_writer.write(jr_root);
|
||||
Json::StreamWriterBuilder jwb;
|
||||
std::unique_ptr<Json::StreamWriter> jwriter(jwb.newStreamWriter());
|
||||
ex_aoss os;
|
||||
|
@ -243,12 +248,12 @@ void TsHttpRpc::_create_json_ret(ex_astr& buf, int errcode, const Json::Value& j
|
|||
|
||||
void TsHttpRpc::_create_json_ret(ex_astr& buf, int errcode)
|
||||
{
|
||||
// 返回: {"code":errcode}
|
||||
// 返回: {"code":errcode}
|
||||
|
||||
//Json::FastWriter jr_writer;
|
||||
Json::Value jr_root;
|
||||
jr_root["code"] = errcode;
|
||||
//buf = jr_writer.write(jr_root);
|
||||
//Json::FastWriter jr_writer;
|
||||
Json::Value jr_root;
|
||||
jr_root["code"] = errcode;
|
||||
//buf = jr_writer.write(jr_root);
|
||||
Json::StreamWriterBuilder jwb;
|
||||
std::unique_ptr<Json::StreamWriter> jwriter(jwb.newStreamWriter());
|
||||
ex_aoss os;
|
||||
|
@ -258,13 +263,13 @@ void TsHttpRpc::_create_json_ret(ex_astr& buf, int errcode)
|
|||
|
||||
void TsHttpRpc::_create_json_ret(ex_astr& buf, int errcode, const char* message)
|
||||
{
|
||||
// 返回: {"code":errcode, "message":message}
|
||||
// 返回: {"code":errcode, "message":message}
|
||||
|
||||
//Json::FastWriter jr_writer;
|
||||
Json::Value jr_root;
|
||||
jr_root["code"] = errcode;
|
||||
jr_root["message"] = message;
|
||||
//buf = jr_writer.write(jr_root);
|
||||
//Json::FastWriter jr_writer;
|
||||
Json::Value jr_root;
|
||||
jr_root["code"] = errcode;
|
||||
jr_root["message"] = message;
|
||||
//buf = jr_writer.write(jr_root);
|
||||
Json::StreamWriterBuilder jwb;
|
||||
std::unique_ptr<Json::StreamWriter> jwriter(jwb.newStreamWriter());
|
||||
ex_aoss os;
|
||||
|
@ -274,242 +279,272 @@ void TsHttpRpc::_create_json_ret(ex_astr& buf, int errcode, const char* message)
|
|||
|
||||
void TsHttpRpc::_process_request(const ex_astr& func_cmd, const Json::Value& json_param, ex_astr& buf)
|
||||
{
|
||||
if (func_cmd == "request_session") {
|
||||
_rpc_func_request_session(json_param, buf);
|
||||
}
|
||||
else if (func_cmd == "kill_sessions") {
|
||||
_rpc_func_kill_sessions(json_param, buf);
|
||||
}
|
||||
else if (func_cmd == "get_config") {
|
||||
_rpc_func_get_config(json_param, buf);
|
||||
}
|
||||
else if (func_cmd == "set_config") {
|
||||
_rpc_func_set_config(json_param, buf);
|
||||
}
|
||||
else if (func_cmd == "enc") {
|
||||
_rpc_func_enc(json_param, buf);
|
||||
}
|
||||
else if (func_cmd == "exit") {
|
||||
_rpc_func_exit(json_param, buf);
|
||||
}
|
||||
else {
|
||||
EXLOGE("[core] rpc got unknown command: %s\n", func_cmd.c_str());
|
||||
_create_json_ret(buf, TPE_UNKNOWN_CMD);
|
||||
}
|
||||
if (func_cmd == "request_session")
|
||||
{
|
||||
_rpc_func_request_session(json_param, buf);
|
||||
}
|
||||
else if (func_cmd == "kill_sessions")
|
||||
{
|
||||
_rpc_func_kill_sessions(json_param, buf);
|
||||
}
|
||||
else if (func_cmd == "get_config")
|
||||
{
|
||||
_rpc_func_get_config(json_param, buf);
|
||||
}
|
||||
else if (func_cmd == "set_config")
|
||||
{
|
||||
_rpc_func_set_config(json_param, buf);
|
||||
}
|
||||
else if (func_cmd == "enc")
|
||||
{
|
||||
_rpc_func_enc(json_param, buf);
|
||||
}
|
||||
else if (func_cmd == "exit")
|
||||
{
|
||||
_rpc_func_exit(json_param, buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
EXLOGE("[core] rpc got unknown command: %s\n", func_cmd.c_str());
|
||||
_create_json_ret(buf, TPE_UNKNOWN_CMD);
|
||||
}
|
||||
}
|
||||
|
||||
extern bool g_exit_flag; // 要求整个TS退出的标志(用于停止各个工作线程)
|
||||
extern bool g_exit_flag; // 要求整个TS退出的标志(用于停止各个工作线程)
|
||||
void TsHttpRpc::_rpc_func_exit(const Json::Value& json_param, ex_astr& buf)
|
||||
{
|
||||
// 设置一个全局退出标志
|
||||
g_exit_flag = true;
|
||||
_create_json_ret(buf, TPE_OK);
|
||||
// 设置一个全局退出标志
|
||||
g_exit_flag = true;
|
||||
_create_json_ret(buf, TPE_OK);
|
||||
}
|
||||
|
||||
void TsHttpRpc::_rpc_func_get_config(const Json::Value& json_param, ex_astr& buf)
|
||||
{
|
||||
Json::Value jr_data;
|
||||
Json::Value jr_data;
|
||||
|
||||
ex_astr _replay_name;
|
||||
ex_wstr2astr(g_env.m_replay_path, _replay_name);
|
||||
jr_data["replay-path"] = _replay_name;
|
||||
ex_astr _replay_name;
|
||||
ex_wstr2astr(g_env.m_replay_path, _replay_name);
|
||||
jr_data["replay-path"] = _replay_name;
|
||||
|
||||
jr_data["web-server-rpc"] = g_env.web_server_rpc;
|
||||
jr_data["web-server-rpc"] = g_env.web_server_rpc;
|
||||
|
||||
ex_astr _version;
|
||||
ex_wstr2astr(TP_SERVER_VER, _version);
|
||||
jr_data["version"] = _version;
|
||||
ex_astr _version;
|
||||
ex_wstr2astr(TP_SERVER_VER, _version);
|
||||
jr_data["version"] = _version;
|
||||
|
||||
ExIniFile& ini = g_env.get_ini();
|
||||
ex_ini_sections& secs = ini.GetAllSections();
|
||||
ex_ini_sections::iterator it = secs.begin();
|
||||
for (; it != secs.end(); ++it)
|
||||
{
|
||||
if (it->first.length() > 9 && 0 == wcsncmp(it->first.c_str(), L"protocol-", 9))
|
||||
{
|
||||
ex_wstr name;
|
||||
name.assign(it->first, 9, it->first.length() - 9);
|
||||
ex_astr _name;
|
||||
ex_wstr2astr(name, _name);
|
||||
ExIniFile& ini = g_env.get_ini();
|
||||
ex_ini_sections& secs = ini.GetAllSections();
|
||||
ex_ini_sections::iterator it = secs.begin();
|
||||
for (; it != secs.end(); ++it)
|
||||
{
|
||||
if (it->first.length() > 9 && 0 == wcsncmp(it->first.c_str(), L"protocol-", 9))
|
||||
{
|
||||
ex_wstr name;
|
||||
name.assign(it->first, 9, it->first.length() - 9);
|
||||
ex_astr _name;
|
||||
ex_wstr2astr(name, _name);
|
||||
|
||||
bool enabled = false;
|
||||
it->second->GetBool(L"enabled", enabled, false);
|
||||
bool enabled = false;
|
||||
it->second->GetBool(L"enabled", enabled, false);
|
||||
|
||||
ex_wstr ip;
|
||||
if (!it->second->GetStr(L"bind-ip", ip))
|
||||
continue;
|
||||
ex_astr _ip;
|
||||
ex_wstr2astr(ip, _ip);
|
||||
ex_wstr ip;
|
||||
if (!it->second->GetStr(L"bind-ip", ip))
|
||||
continue;
|
||||
ex_astr _ip;
|
||||
ex_wstr2astr(ip, _ip);
|
||||
|
||||
int port;
|
||||
it->second->GetInt(L"bind-port", port, 52189);
|
||||
int port;
|
||||
it->second->GetInt(L"bind-port", port, 52189);
|
||||
|
||||
jr_data[_name.c_str()]["enable"] = enabled;
|
||||
jr_data[_name.c_str()]["ip"] = _ip;
|
||||
jr_data[_name.c_str()]["port"] = port;
|
||||
}
|
||||
}
|
||||
jr_data[_name.c_str()]["enable"] = enabled;
|
||||
jr_data[_name.c_str()]["ip"] = _ip;
|
||||
jr_data[_name.c_str()]["port"] = port;
|
||||
}
|
||||
}
|
||||
|
||||
_create_json_ret(buf, TPE_OK, jr_data);
|
||||
_create_json_ret(buf, TPE_OK, jr_data);
|
||||
}
|
||||
|
||||
void TsHttpRpc::_rpc_func_request_session(const Json::Value& json_param, ex_astr& buf)
|
||||
{
|
||||
// https://github.com/tp4a/teleport/wiki/TELEPORT-CORE-JSON-RPC#request_session
|
||||
// https://github.com/tp4a/teleport/wiki/TELEPORT-CORE-JSON-RPC#request_session
|
||||
|
||||
int conn_id = 0;
|
||||
ex_rv rv = TPE_OK;
|
||||
int conn_id = 0;
|
||||
ex_rv rv = TPE_OK;
|
||||
|
||||
if (json_param["conn_id"].isNull())
|
||||
{
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
if (!json_param["conn_id"].isInt())
|
||||
{
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
if (json_param["conn_id"].isNull())
|
||||
{
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
if (!json_param["conn_id"].isInt())
|
||||
{
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
|
||||
conn_id = json_param["conn_id"].asInt();
|
||||
if (0 == conn_id)
|
||||
{
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
conn_id = json_param["conn_id"].asInt();
|
||||
if (0 == conn_id)
|
||||
{
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
|
||||
TS_CONNECT_INFO* info = new TS_CONNECT_INFO;
|
||||
if ((rv = ts_web_rpc_get_conn_info(conn_id, *info)) != TPE_OK)
|
||||
{
|
||||
_create_json_ret(buf, rv);
|
||||
TS_CONNECT_INFO* info = new TS_CONNECT_INFO;
|
||||
if ((rv = ts_web_rpc_get_conn_info(conn_id, *info)) != TPE_OK)
|
||||
{
|
||||
_create_json_ret(buf, rv);
|
||||
delete info;
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// info->ref_count = 0;
|
||||
// info->ticket_start = ex_get_tick_count();
|
||||
//
|
||||
// 生成一个session-id(内部会避免重复)
|
||||
ex_astr sid;
|
||||
if (!g_session_mgr.request_session(sid, info)) {
|
||||
_create_json_ret(buf, TPE_FAILED);
|
||||
// info->ref_count = 0;
|
||||
// info->ticket_start = ex_get_tick_count();
|
||||
//
|
||||
// 生成一个session-id(内部会避免重复)
|
||||
ex_astr sid;
|
||||
if (!g_session_mgr.request_session(sid, info))
|
||||
{
|
||||
_create_json_ret(buf, TPE_FAILED);
|
||||
delete info;
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
EXLOGD("[core] rpc new session-id: %s\n", sid.c_str());
|
||||
EXLOGD("[core] rpc new session-id: %s\n", sid.c_str());
|
||||
|
||||
Json::Value jr_data;
|
||||
jr_data["sid"] = sid;
|
||||
Json::Value jr_data;
|
||||
jr_data["sid"] = sid;
|
||||
|
||||
_create_json_ret(buf, TPE_OK, jr_data);
|
||||
_create_json_ret(buf, TPE_OK, jr_data);
|
||||
}
|
||||
|
||||
void TsHttpRpc::_rpc_func_kill_sessions(const Json::Value& json_param, ex_astr& buf) {
|
||||
/*
|
||||
{
|
||||
"sessions": ["0123456", "ABCDEF", ...]
|
||||
}
|
||||
*/
|
||||
void TsHttpRpc::_rpc_func_kill_sessions(const Json::Value& json_param, ex_astr& buf)
|
||||
{
|
||||
/*
|
||||
{
|
||||
"sessions": ["0123456", "ABCDEF", ...]
|
||||
}
|
||||
*/
|
||||
|
||||
if (json_param.isArray()) {
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
if (json_param.isArray())
|
||||
{
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
|
||||
if (json_param["sessions"].isNull() || !json_param["sessions"].isArray()) {
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
if (json_param["sessions"].isNull() || !json_param["sessions"].isArray())
|
||||
{
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
|
||||
Json::Value s = json_param["sessions"];
|
||||
int cnt = s.size();
|
||||
for (int i = 0; i < cnt; ++i) {
|
||||
if (!s[i].isString()) {
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Json::Value s = json_param["sessions"];
|
||||
int cnt = s.size();
|
||||
for (int i = 0; i < cnt; ++i)
|
||||
{
|
||||
if (!s[i].isString())
|
||||
{
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
EXLOGV("[core] try to kill %d sessions.\n", cnt);
|
||||
ex_astr sp = s.toStyledString();
|
||||
g_tpp_mgr.kill_sessions(sp);
|
||||
EXLOGV("[core] try to kill %d sessions.\n", cnt);
|
||||
ex_astr sp = s.toStyledString();
|
||||
g_tpp_mgr.kill_sessions(sp);
|
||||
|
||||
_create_json_ret(buf, TPE_OK);
|
||||
_create_json_ret(buf, TPE_OK);
|
||||
}
|
||||
|
||||
void TsHttpRpc::_rpc_func_enc(const Json::Value& json_param, ex_astr& buf)
|
||||
{
|
||||
// https://github.com/tp4a/teleport/wiki/TELEPORT-CORE-JSON-RPC#enc
|
||||
// 加密一个字符串 [ p=plain-text, c=cipher-text ]
|
||||
// 入参: {"p":"need be encrypt"}
|
||||
// 示例: {"p":"this-is-a-password"}
|
||||
// p: 被加密的字符串
|
||||
// 返回:
|
||||
// data域中的"c"的内容是加密后密文的base64编码结果
|
||||
// 示例: {"code":0, "data":{"c":"Mxs340a9r3fs+3sdf=="}}
|
||||
// 错误返回: {"code":1234}
|
||||
// https://github.com/tp4a/teleport/wiki/TELEPORT-CORE-JSON-RPC#enc
|
||||
// 加密一个字符串 [ p=plain-text, c=cipher-text ]
|
||||
// 入参: {"p":"need be encrypt"}
|
||||
// 示例: {"p":"this-is-a-password"}
|
||||
// p: 被加密的字符串
|
||||
// 返回:
|
||||
// data域中的"c"的内容是加密后密文的base64编码结果
|
||||
// 示例: {"code":0, "data":{"c":"Mxs340a9r3fs+3sdf=="}}
|
||||
// 错误返回: {"code":1234}
|
||||
|
||||
if (json_param.isArray())
|
||||
{
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
if (json_param.isArray())
|
||||
{
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
|
||||
ex_astr plain_text;
|
||||
ex_astr plain_text;
|
||||
|
||||
if (json_param["p"].isNull() || !json_param["p"].isString())
|
||||
{
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
if (json_param["p"].isNull() || !json_param["p"].isString())
|
||||
{
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
|
||||
plain_text = json_param["p"].asCString();
|
||||
if (plain_text.length() == 0)
|
||||
{
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
ex_astr cipher_text;
|
||||
bool is_enc = true;
|
||||
if (!json_param["d"].isNull() && json_param["d"].isInt() && json_param["d"].asInt() == 1)
|
||||
is_enc = false;
|
||||
|
||||
if (!ts_db_field_encrypt(plain_text, cipher_text))
|
||||
{
|
||||
_create_json_ret(buf, TPE_FAILED);
|
||||
return;
|
||||
}
|
||||
plain_text = json_param["p"].asCString();
|
||||
if (plain_text.length() == 0)
|
||||
{
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
ex_astr cipher_text;
|
||||
|
||||
Json::Value jr_data;
|
||||
jr_data["c"] = cipher_text;
|
||||
_create_json_ret(buf, TPE_OK, jr_data);
|
||||
if (is_enc)
|
||||
{
|
||||
if (!ts_db_field_encrypt(plain_text, cipher_text))
|
||||
{
|
||||
_create_json_ret(buf, TPE_FAILED);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ts_db_field_decrypt(plain_text, cipher_text))
|
||||
{
|
||||
_create_json_ret(buf, TPE_FAILED);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Json::Value jr_data;
|
||||
jr_data["c"] = cipher_text;
|
||||
_create_json_ret(buf, TPE_OK, jr_data);
|
||||
}
|
||||
|
||||
void TsHttpRpc::_rpc_func_set_config(const Json::Value& json_param, ex_astr& buf)
|
||||
{
|
||||
// https://github.com/tp4a/teleport/wiki/TELEPORT-CORE-JSON-RPC#set_config
|
||||
/*
|
||||
{
|
||||
"noop-timeout": 15 # 按分钟计
|
||||
}
|
||||
*/
|
||||
// https://github.com/tp4a/teleport/wiki/TELEPORT-CORE-JSON-RPC#set_config
|
||||
/*
|
||||
{
|
||||
"noop-timeout": 15 # 按分钟计
|
||||
}
|
||||
*/
|
||||
|
||||
if (json_param.isArray()) {
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
if (json_param.isArray())
|
||||
{
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
|
||||
if (json_param["noop_timeout"].isNull() || !json_param["noop_timeout"].isUInt()) {
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
if (json_param["noop_timeout"].isNull() || !json_param["noop_timeout"].isUInt())
|
||||
{
|
||||
_create_json_ret(buf, TPE_PARAM);
|
||||
return;
|
||||
}
|
||||
|
||||
int noop_timeout = json_param["noop_timeout"].asUInt();
|
||||
EXLOGV("[core] set run-time config:\n");
|
||||
EXLOGV("[core] noop_timeout = %dm\n", noop_timeout);
|
||||
int noop_timeout = json_param["noop_timeout"].asUInt();
|
||||
EXLOGV("[core] set run-time config:\n");
|
||||
EXLOGV("[core] noop_timeout = %dm\n", noop_timeout);
|
||||
|
||||
ex_astr sp = json_param.toStyledString();
|
||||
g_tpp_mgr.set_runtime_config(sp);
|
||||
ex_astr sp = json_param.toStyledString();
|
||||
g_tpp_mgr.set_runtime_config(sp);
|
||||
|
||||
_create_json_ret(buf, TPE_OK);
|
||||
_create_json_ret(buf, TPE_OK);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -806,14 +806,6 @@ int SshSession::_do_auth(const char* user, const char* secret)
|
|||
}
|
||||
|
||||
EXLOGE("[%s] failed to login with password mode, got %d.\n", m_dbg_name.c_str(), rc);
|
||||
|
||||
// if(!m_auth_err_msg.empty())
|
||||
// m_auth_err_msg += "\r\n";
|
||||
// m_auth_err_msg += "login remote host ";
|
||||
// m_auth_err_msg += m_dbg_server;
|
||||
// m_auth_err_msg += " with password authorize method failed, ";
|
||||
// m_auth_err_msg += ssh_get_error(m_rs_tp2srv);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -4,6 +4,6 @@ $tp.assist_checked = function () {
|
|||
if ($tp.assist.running) {
|
||||
$('#sidebar-tp-assist-ver').html('v'+$tp.assist.version);
|
||||
} else {
|
||||
$('#sidebar-tp-assist-ver').html('未能检测到');
|
||||
$('#sidebar-tp-assist-ver').html('未连接');
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1772,7 +1772,7 @@ $app.create_dlg_edit_account = function () {
|
|||
},
|
||||
function (code, message) {
|
||||
if (code === TPE_NO_ASSIST)
|
||||
$assist.alert_assist_not_found();
|
||||
$assist.alert_assist_not_found(code);
|
||||
else
|
||||
$tp.notify_error('远程连接失败:' + tp_error_msg(code, message));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,209 @@
|
|||
"use strict";
|
||||
|
||||
$app.on_init = function (cb_stack) {
|
||||
$app.dom = {
|
||||
version: $('#version'),
|
||||
|
||||
ssh_type: $('#ssh-type'),
|
||||
ssh_app: $('#ssh-app'),
|
||||
ssh_cmdline: $('#ssh-cmdline'),
|
||||
ssh_desc: $('#ssh-desc'),
|
||||
ssh_select_app: $('#ssh-select-app'),
|
||||
|
||||
sftp_type: $('#sftp-type'),
|
||||
sftp_app: $('#sftp-app'),
|
||||
sftp_cmdline: $('#sftp-cmdline'),
|
||||
sftp_desc: $('#sftp-desc'),
|
||||
sftp_select_app: $('#sftp-select-app'),
|
||||
|
||||
|
||||
telnet_type: $('#telnet-type'),
|
||||
telnet_app: $('#telnet-app'),
|
||||
telnet_cmdline: $('#telnet-cmdline'),
|
||||
telnet_desc: $('#telnet-desc'),
|
||||
telnet_select_app: $('#telnet-select-app'),
|
||||
|
||||
rdp_type: $('#rdp-type'),
|
||||
rdp_app: $('#rdp-app'),
|
||||
rdp_cmdline: $('#rdp-cmdline'),
|
||||
rdp_desc: $('#rdp-desc'),
|
||||
rdp_select_app: $('#rdp-select-app'),
|
||||
|
||||
btn_save: $('#btn-save')
|
||||
};
|
||||
|
||||
$app.cfg = null;
|
||||
|
||||
$assist.register_response_handler('get_config', $app.on_assist_config_loaded);
|
||||
$assist.register_response_handler('set_config', $app.on_assist_config_saved);
|
||||
$assist.register_response_handler('select_file', $app.on_local_file_selected);
|
||||
|
||||
$assist.add_next_command({
|
||||
type: ASSIST_WS_COMMAND_TYPE_REQUEST,
|
||||
method: 'get_config',
|
||||
param: {
|
||||
username: $app.options.username
|
||||
}
|
||||
});
|
||||
|
||||
cb_stack
|
||||
.add($app.init_dom_event)
|
||||
.exec();
|
||||
};
|
||||
|
||||
$app.notify_error = function (message_, title_) {
|
||||
let _title = title_ || '';
|
||||
$tp.notify_error(message_, _title);
|
||||
console.error('错误=[', _title, '] ', message_);
|
||||
};
|
||||
|
||||
$app._on_type_change = function (cfg, dom_type, dom_app, dom_cmdline, dom_desc) {
|
||||
cfg.selected = dom_type.val();
|
||||
for (let i = 0; i < cfg.available.length; i++) {
|
||||
let item = cfg.available[i];
|
||||
if (item.name === cfg.selected) {
|
||||
dom_app.val(item.app);
|
||||
dom_cmdline.val(item.cmdline);
|
||||
|
||||
let html = [];
|
||||
for (let j = 0; j < item.desc.length; j++) {
|
||||
html.push('<div class="desc"><i class="fa fa-info-circle"></i> ' + item.desc[j] + '</div>');
|
||||
}
|
||||
dom_desc.html(html.join(''));
|
||||
return;
|
||||
}
|
||||
}
|
||||
$app.notify_error('所选的配置项不存在!');
|
||||
};
|
||||
|
||||
$app.init_dom_event = function (cb_stack) {
|
||||
$app.dom.ssh_type.change(function () {
|
||||
$app._on_type_change($app.cfg.ssh, $app.dom.ssh_type, $app.dom.ssh_app, $app.dom.ssh_cmdline, $app.dom.ssh_desc);
|
||||
});
|
||||
$app.dom.sftp_type.change(function () {
|
||||
$app._on_type_change($app.cfg.sftp, $app.dom.sftp_type, $app.dom.sftp_app, $app.dom.sftp_cmdline, $app.dom.sftp_desc);
|
||||
});
|
||||
$app.dom.telnet_type.change(function () {
|
||||
$app._on_type_change($app.cfg.telnet, $app.dom.telnet_type, $app.dom.telnet_app, $app.dom.telnet_cmdline, $app.dom.telnet_desc);
|
||||
});
|
||||
$app.dom.rdp_type.change(function () {
|
||||
$app._on_type_change($app.cfg.rdp, $app.dom.rdp_type, $app.dom.rdp_app, $app.dom.rdp_cmdline, $app.dom.rdp_desc);
|
||||
});
|
||||
$app.dom.ssh_select_app.click(function () {
|
||||
$assist.select_local_file('ssg');
|
||||
});
|
||||
$app.dom.sftp_select_app.click(function () {
|
||||
$assist.select_local_file('sftp');
|
||||
});
|
||||
$app.dom.telnet_select_app.click(function () {
|
||||
$assist.select_local_file('telnet');
|
||||
});
|
||||
$app.dom.rdp_select_app.click(function () {
|
||||
$assist.select_local_file('rdp');
|
||||
});
|
||||
|
||||
$app.dom.btn_save.click(function () {
|
||||
$app.on_save();
|
||||
});
|
||||
|
||||
cb_stack.exec();
|
||||
};
|
||||
|
||||
$app._fill_config_dom = function (cfg, dom_type, dom_app, dom_cmdline) {
|
||||
dom_type.html('');
|
||||
if (!_.isUndefined(cfg)) {
|
||||
if (_.isUndefined(cfg.selected)) {
|
||||
cfg.selected = '';
|
||||
}
|
||||
|
||||
if (!_.isUndefined(cfg.available) && cfg.available.length > 0) {
|
||||
let selected = '';
|
||||
let app = '';
|
||||
let cmdline = '';
|
||||
|
||||
let html = [];
|
||||
for (let i = 0; i < cfg.available.length; i++) {
|
||||
let item = cfg.available[i];
|
||||
|
||||
if (selected === '' || item.name === cfg.selected) {
|
||||
selected = item.name;
|
||||
app = item.app;
|
||||
cmdline = item.cmdline;
|
||||
}
|
||||
|
||||
html.push('<option value="' + item.name + '">' + item.display + '</option>');
|
||||
}
|
||||
|
||||
dom_type.html(html.join(''));
|
||||
|
||||
dom_type.val(selected);
|
||||
dom_app.val(app);
|
||||
dom_cmdline.val(cmdline);
|
||||
|
||||
$(dom_type).trigger('change');
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
$app.on_assist_config_loaded = function (code, message, ret) {
|
||||
console.log('on_assist_config_loaded(), ', code, message, ret);
|
||||
$app.cfg = ret;
|
||||
|
||||
$app._fill_config_dom($app.cfg.ssh, $app.dom.ssh_type, $app.dom.ssh_app, $app.dom.ssh_cmdline);
|
||||
$app._fill_config_dom($app.cfg.sftp, $app.dom.sftp_type, $app.dom.sftp_app, $app.dom.sftp_cmdline);
|
||||
$app._fill_config_dom($app.cfg.telnet, $app.dom.telnet_type, $app.dom.telnet_app, $app.dom.telnet_cmdline);
|
||||
$app._fill_config_dom($app.cfg.rdp, $app.dom.rdp_type, $app.dom.rdp_app, $app.dom.rdp_cmdline);
|
||||
};
|
||||
|
||||
$app.on_assist_config_saved = function (code, message, ret) {
|
||||
console.log('on_assist_config_saved(), ', code, message, ret);
|
||||
if (code !== TPE_OK)
|
||||
$tp.notify_error(tp_error_msg(code, message));
|
||||
else
|
||||
$tp.notify_success('助手配置保存成功!');
|
||||
};
|
||||
|
||||
$app.on_local_file_selected = function (code, message, ret) {
|
||||
console.log('on_local_file_selected(), ', code, message, ret);
|
||||
if (code !== TPE_OK) {
|
||||
$tp.notify_error(tp_error_msg(code, message));
|
||||
return;
|
||||
}
|
||||
|
||||
let app_type = ret.app_type;
|
||||
$('#' + app_type + '-app').val(ret.app_path);
|
||||
};
|
||||
|
||||
$app._read_dom_value = function (cfg, dom_app, dom_cmdline) {
|
||||
let i = 0;
|
||||
for (i = 0; i < cfg.available.length; i++) {
|
||||
let item = cfg.available[i];
|
||||
if (item.name === cfg.selected) {
|
||||
item.app = dom_app.val();
|
||||
item.cmdline = dom_cmdline.val();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$app.on_save = function () {
|
||||
if ($app.cfg === null)
|
||||
return;
|
||||
|
||||
$app._read_dom_value($app.cfg.ssh, $app.dom.ssh_app, $app.dom.ssh_cmdline);
|
||||
$app._read_dom_value($app.cfg.sftp, $app.dom.sftp_app, $app.dom.sftp_cmdline);
|
||||
$app._read_dom_value($app.cfg.telnet, $app.dom.telnet_app, $app.dom.telnet_cmdline);
|
||||
$app._read_dom_value($app.cfg.rdp, $app.dom.rdp_app, $app.dom.rdp_cmdline);
|
||||
|
||||
console.log('save: ', $app.cfg);
|
||||
|
||||
let cmd = {
|
||||
type: ASSIST_WS_COMMAND_TYPE_REQUEST,
|
||||
method: 'set_config',
|
||||
param: $app.cfg
|
||||
}
|
||||
|
||||
$assist.ws.send(JSON.stringify(cmd));
|
||||
|
||||
}
|
|
@ -371,8 +371,8 @@ $app.do_replay_rdp = function (record_id, user_username, acc_username, host_ip,
|
|||
return;
|
||||
}
|
||||
|
||||
if(!$assist.check())
|
||||
return;
|
||||
// if(!$assist.check())
|
||||
// return;
|
||||
|
||||
$assist.do_rdp_replay(
|
||||
record_id
|
||||
|
@ -381,8 +381,7 @@ $app.do_replay_rdp = function (record_id, user_username, acc_username, host_ip,
|
|||
}
|
||||
, function (code, message) {
|
||||
if (code === TPE_NO_ASSIST) {
|
||||
$assist.errcode = TPE_NO_ASSIST;
|
||||
$assist.alert_assist_not_found();
|
||||
$assist.alert_assist_not_found(code);
|
||||
}
|
||||
else
|
||||
$tp.notify_error('播放RDP操作录像失败:' + tp_error_msg(code, message));
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
"use strict";
|
||||
|
||||
$app.on_init = function (cb_stack) {
|
||||
var record_id = $app.options.record_id;
|
||||
let record_id = $app.options.record_id;
|
||||
|
||||
$app.record_hdr = null;
|
||||
$app.record_data = [];
|
||||
|
@ -78,7 +78,7 @@ $app.on_init = function (cb_stack) {
|
|||
$app.dom.btn_big_font.click(function () {
|
||||
if (_.isNull($app.dom.xterm_terminal))
|
||||
return;
|
||||
var _size = parseInt($app.dom.xterm_terminal.css('font-size'));
|
||||
let _size = parseInt($app.dom.xterm_terminal.css('font-size'));
|
||||
if (_size >= 24)
|
||||
return;
|
||||
|
||||
|
@ -92,7 +92,7 @@ $app.on_init = function (cb_stack) {
|
|||
if (_.isNull($app.dom.xterm_terminal))
|
||||
return;
|
||||
|
||||
var _size = parseInt($app.dom.xterm_terminal.css('font-size'));
|
||||
let _size = parseInt($app.dom.xterm_terminal.css('font-size'));
|
||||
if (_size <= 12)
|
||||
return;
|
||||
|
||||
|
@ -110,7 +110,7 @@ $app.on_init = function (cb_stack) {
|
|||
});
|
||||
|
||||
$app.dom.btn_skip.click(function () {
|
||||
var obj = $('#btn-skip i');
|
||||
let obj = $('#btn-skip i');
|
||||
if ($app.need_skip) {
|
||||
$app.need_skip = false;
|
||||
obj.removeClass('fa-check-square').addClass('fa-square');
|
||||
|
@ -129,7 +129,7 @@ $app.on_init = function (cb_stack) {
|
|||
$app.speed_offset = 0;
|
||||
$app.dom.btn_speed.text($app.speed_table[$app.speed_offset].name);
|
||||
$app.dom.btn_speed.click(function () {
|
||||
var length = $app.speed_table.length;
|
||||
let length = $app.speed_table.length;
|
||||
$app.speed_offset += 1;
|
||||
if ($app.speed_offset === length) {
|
||||
$app.speed_offset = 0;
|
||||
|
@ -204,7 +204,7 @@ $app.init_and_play = function () {
|
|||
|
||||
if (_.isNull($app.canvas)) {
|
||||
// $app.canvas = $app.dom.canvas[0].getContext('2d');
|
||||
var h = '<canvas id="canvas" width="' + $app.record_hdr.width + '" height="' + $app.record_hdr.height + '"></canvas>';
|
||||
let h = '<canvas id="canvas" width="' + $app.record_hdr.width + '" height="' + $app.record_hdr.height + '"></canvas>';
|
||||
$app.dom.screen.append($(h));
|
||||
$app.canvas = document.getElementById('canvas').getContext('2d');
|
||||
} else {
|
||||
|
@ -212,8 +212,8 @@ $app.init_and_play = function () {
|
|||
}
|
||||
|
||||
// $app._draw_cursor(100, 100);
|
||||
var x = ($app.record_hdr.width - 500) / 2;
|
||||
var y = ($app.record_hdr.height - 360) / 2;
|
||||
let x = ($app.record_hdr.width - 500) / 2;
|
||||
let y = ($app.record_hdr.height - 360) / 2;
|
||||
$app.canvas.drawImage($app.player_bg_img, x, y);
|
||||
|
||||
|
||||
|
@ -234,7 +234,7 @@ $app.init_and_play = function () {
|
|||
};
|
||||
|
||||
$app.decompress = function (bitmap) {
|
||||
var fName = null;
|
||||
let fName = null;
|
||||
switch (bitmap.bit_per_pixel) {
|
||||
case 15:
|
||||
fName = 'bitmap_decompress_15';
|
||||
|
@ -252,25 +252,25 @@ $app.decompress = function (bitmap) {
|
|||
throw 'invalid bitmap data format';
|
||||
}
|
||||
|
||||
var input = new Uint8Array(bitmap.img_data);
|
||||
var inputPtr = Module._malloc(input.length);
|
||||
var inputHeap = new Uint8Array(Module.HEAPU8.buffer, inputPtr, input.length);
|
||||
let input = new Uint8Array(bitmap.img_data);
|
||||
let inputPtr = Module._malloc(input.length);
|
||||
let inputHeap = new Uint8Array(Module.HEAPU8.buffer, inputPtr, input.length);
|
||||
inputHeap.set(input);
|
||||
|
||||
var output_width = bitmap.right - bitmap.left + 1;
|
||||
var output_height = bitmap.bottom - bitmap.top + 1;
|
||||
var ouputSize = output_width * output_height * 4;
|
||||
var outputPtr = Module._malloc(ouputSize);
|
||||
let output_width = bitmap.right - bitmap.left + 1;
|
||||
let output_height = bitmap.bottom - bitmap.top + 1;
|
||||
let ouputSize = output_width * output_height * 4;
|
||||
let outputPtr = Module._malloc(ouputSize);
|
||||
|
||||
var outputHeap = new Uint8Array(Module.HEAPU8.buffer, outputPtr, ouputSize);
|
||||
let outputHeap = new Uint8Array(Module.HEAPU8.buffer, outputPtr, ouputSize);
|
||||
|
||||
var res = Module.ccall(fName,
|
||||
let res = Module.ccall(fName,
|
||||
'number',
|
||||
['number', 'number', 'number', 'number', 'number', 'number', 'number', 'number'],
|
||||
[outputHeap.byteOffset, output_width, output_height, bitmap.width, bitmap.height, inputHeap.byteOffset, input.length]
|
||||
);
|
||||
|
||||
var output = new Uint8ClampedArray(outputHeap.buffer, outputHeap.byteOffset, ouputSize);
|
||||
let output = new Uint8ClampedArray(outputHeap.buffer, outputHeap.byteOffset, ouputSize);
|
||||
|
||||
Module._free(inputPtr);
|
||||
Module._free(outputPtr);
|
||||
|
@ -293,13 +293,13 @@ $app.do_play = function () {
|
|||
$app.dom.status.text("正在播放");
|
||||
$app.player_current_time += $app.record_tick * $app.speed_table[$app.speed_offset].speed;
|
||||
|
||||
var _record_tick = $app.record_tick;
|
||||
let _record_tick = $app.record_tick;
|
||||
|
||||
for (var i = $app.played_pkg_count; i < $app.record_data.length; i++) {
|
||||
for (let i = $app.played_pkg_count; i < $app.record_data.length; i++) {
|
||||
if ($app.is_need_stop)
|
||||
break;
|
||||
|
||||
var play_data = $app.record_data[i];
|
||||
let play_data = $app.record_data[i];
|
||||
|
||||
if (play_data.t < $app.player_current_time) {
|
||||
if (play_data.a === 0x10) {
|
||||
|
@ -313,21 +313,21 @@ $app.do_play = function () {
|
|||
}
|
||||
else if(play_data.a === 0x12) {
|
||||
//$app.player_console_term.write(tp_base64_decode(play_data.d));
|
||||
var _data = tp_base64_to_binarray(play_data.d);
|
||||
let _data = tp_base64_to_bin(play_data.d);
|
||||
console.log('pkg size:', _data.length);
|
||||
|
||||
var s = Uint8Array.from(_data);
|
||||
let s = Uint8Array.from(_data);
|
||||
// console.log(s);
|
||||
var offset = 0;
|
||||
var update_type = s[offset + 1] * 256 + s[offset];
|
||||
let offset = 0;
|
||||
let update_type = s[offset + 1] * 256 + s[offset];
|
||||
offset += 2;
|
||||
var update_count = s[offset + 1] * 256 + s[offset];
|
||||
let update_count = s[offset + 1] * 256 + s[offset];
|
||||
offset += 2;
|
||||
console.log('type:', update_type, 'count:', update_count)
|
||||
|
||||
var bc;
|
||||
let bc;
|
||||
for (bc = 0; bc < update_count; ++bc) {
|
||||
var bitmap = {};
|
||||
let bitmap = {};
|
||||
|
||||
bitmap.left = s[offset + 1] * 256 + s[offset];
|
||||
offset += 2;
|
||||
|
@ -344,12 +344,12 @@ $app.do_play = function () {
|
|||
bitmap.bit_per_pixel = s[offset + 1] * 256 + s[offset];
|
||||
offset += 2;
|
||||
|
||||
var _flag = s[offset + 1] * 256 + s[offset];
|
||||
let _flag = s[offset + 1] * 256 + s[offset];
|
||||
offset += 2;
|
||||
|
||||
bitmap.isCompress = (_flag & 0x0001) === 0x0001;
|
||||
|
||||
var _length = s[offset + 1] * 256 + s[offset];
|
||||
let _length = s[offset + 1] * 256 + s[offset];
|
||||
offset += 2;
|
||||
|
||||
bitmap.img_data = s.subarray(offset, offset + _length);
|
||||
|
@ -357,14 +357,14 @@ $app.do_play = function () {
|
|||
|
||||
//console.log(dest_left, dest_top, dest_right, dest_bottom, dest_width, dest_height, dest_bit_per_pixel, dest_flag, dest_length);
|
||||
// console.log(bitmap);
|
||||
var output = null;
|
||||
let output = null;
|
||||
if(bitmap.isCompress)
|
||||
output = $app.decompress(bitmap);
|
||||
else
|
||||
output = {width : bitmap.width, height : bitmap.height, data : new Uint8ClampedArray(bitmap.data)};
|
||||
// console.log(output);
|
||||
|
||||
var img = $app.canvas.createImageData(output.width, output.height);
|
||||
let img = $app.canvas.createImageData(output.width, output.height);
|
||||
img.data.set(output.data);
|
||||
$app.canvas.putImageData(img, bitmap.left, bitmap.top);
|
||||
|
||||
|
@ -401,9 +401,9 @@ $app.do_play = function () {
|
|||
}
|
||||
|
||||
// sync progress bar.
|
||||
var _progress = parseInt($app.player_current_time * 100 / $app.record_hdr.time_used);
|
||||
let _progress = parseInt($app.player_current_time * 100 / $app.record_hdr.time_used);
|
||||
$app.dom.progress.val(_progress);
|
||||
var temp = parseInt($app.player_current_time / 1000);
|
||||
let temp = parseInt($app.player_current_time / 1000);
|
||||
$app.dom.time.text(temp + '/' + parseInt($app.record_hdr.time_used / 1000) + '秒');
|
||||
|
||||
// if all packages played
|
||||
|
|
|
@ -458,9 +458,9 @@ $app.init_ws = function () {
|
|||
|
||||
var _sid = Cookies.get('_sid');
|
||||
if(location.protocol === 'http:') {
|
||||
$app.ws = new WebSocket('ws://' + location.host + '/ws/' + _sid);
|
||||
$app.ws = new WebSocket('ws://' + location.host + '/ws/dashboard/' + _sid);
|
||||
} else {
|
||||
$app.ws = new WebSocket('wss://' + location.host + '/ws/' + _sid);
|
||||
$app.ws = new WebSocket('wss://' + location.host + '/ws/dashboard/' + _sid);
|
||||
}
|
||||
|
||||
$app.ws.onopen = function (e) {
|
||||
|
|
|
@ -192,126 +192,3 @@ $app.on_init = function (cb_stack, cb_args) {
|
|||
|
||||
cb_stack.exec();
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ywl.on_init = function (cb_stack, cb_args) {
|
||||
ywl.dom = {
|
||||
btn_upgrade_db: $('#btn-upgrade-db'),
|
||||
steps_detail: $('#steps-detail')
|
||||
};
|
||||
|
||||
ywl.dom.btn_upgrade_db.click(function () {
|
||||
|
||||
ywl.dom.btn_upgrade_db.attr('disabled', 'disabled').hide();
|
||||
ywl.dom.steps_detail.show();
|
||||
|
||||
console.log('upgrade-db-click');
|
||||
ywl.ajax_post_json('/maintenance/rpc', {cmd: 'upgrade_db'},
|
||||
function (ret) {
|
||||
console.log('upgrade-db:', ret);
|
||||
if (ret.code === 0) {
|
||||
|
||||
var cb_stack = CALLBACK_STACK.create();
|
||||
cb_stack
|
||||
.add(ywl.get_task_ret, {task_id: ret.data.task_id})
|
||||
.add(ywl.delay_exec, {delay_ms: 500})
|
||||
.exec();
|
||||
}
|
||||
|
||||
},
|
||||
function () {
|
||||
ywl.show_message('error', '无法连接到服务器!');
|
||||
}
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
ywl.get_task_ret = function (cb_stack, cb_args) {
|
||||
var task_id = cb_args.task_id || 0;
|
||||
if (task_id === 0) {
|
||||
console.log('task-id', task_id);
|
||||
return;
|
||||
}
|
||||
|
||||
ywl.ajax_post_json('/maintenance/rpc', {cmd: 'get_task_ret', 'tid': task_id},
|
||||
function (ret) {
|
||||
console.log('get_task_ret:', ret);
|
||||
if (ret.code === 0) {
|
||||
|
||||
// show step progress.
|
||||
var steps = ret.data.steps;
|
||||
ywl.dom.steps_detail.empty();
|
||||
|
||||
var html = [];
|
||||
var icon_class = '';
|
||||
var err_class = '';
|
||||
for(var i = 0; i < steps.length; ++i) {
|
||||
if(steps[i].code !== 0) {
|
||||
err_class = ' class="error"';
|
||||
icon_class = 'fa-times-circle';
|
||||
}
|
||||
else {
|
||||
err_class = '';
|
||||
icon_class = 'fa-check';
|
||||
}
|
||||
|
||||
if(steps[i].stat === 0)
|
||||
;//icon_class = 'fa-check';
|
||||
else
|
||||
icon_class = 'fa-cog fa-spin';
|
||||
|
||||
html.push('<p');
|
||||
html.push(err_class);
|
||||
html.push('><i class="fa ');
|
||||
html.push(icon_class);
|
||||
html.push('"></i> ');
|
||||
html.push(steps[i].msg);
|
||||
html.push('</p>')
|
||||
}
|
||||
ywl.dom.steps_detail.html(html.join(''));
|
||||
|
||||
|
||||
if (!ret.data.running) {
|
||||
$('#step2').show('fast');
|
||||
return;
|
||||
}
|
||||
|
||||
cb_stack
|
||||
.add(ywl.get_task_ret, {task_id: task_id})
|
||||
.add(ywl.delay_exec, {delay_ms: 500})
|
||||
.exec();
|
||||
}
|
||||
|
||||
},
|
||||
function () {
|
||||
ywl.show_message('error', '无法连接到服务器!');
|
||||
}
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
cb_stack.exec();
|
||||
};
|
||||
|
|
|
@ -459,7 +459,7 @@ $app.connect_remote = function (uni_id, acc_id, host_id, protocol_type, protocol
|
|||
},
|
||||
function (code, message) {
|
||||
if (code === TPE_NO_ASSIST)
|
||||
$assist.alert_assist_not_found();
|
||||
$assist.alert_assist_not_found(code);
|
||||
else
|
||||
$tp.notify_error('远程连接失败:' + tp_error_msg(code, message));
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
"use strict";
|
||||
|
||||
// 构造一个回调函数栈,遵循先进后出的原则进行顺序调用。
|
||||
var CALLBACK_STACK = {
|
||||
let CALLBACK_STACK = {
|
||||
create: function () {
|
||||
var self = {};
|
||||
let self = {};
|
||||
|
||||
self.cb_stack = [];
|
||||
|
||||
|
@ -24,7 +24,7 @@ var CALLBACK_STACK = {
|
|||
self.add(cb_func, cb_args);
|
||||
// 然后加一个定时器来做等待
|
||||
self.add(function (cb_stack, cb_args) {
|
||||
var _delay_ms = cb_args.delay_ms || 500;
|
||||
let _delay_ms = cb_args.delay_ms || 500;
|
||||
setTimeout(function () {
|
||||
cb_stack.exec();
|
||||
}, _delay_ms);
|
||||
|
@ -35,8 +35,8 @@ var CALLBACK_STACK = {
|
|||
|
||||
self.exec = function (ex_args) {
|
||||
if (self.cb_stack.length > 0) {
|
||||
var cb = self.cb_stack.pop();
|
||||
var ex_ = ex_args || {};
|
||||
let cb = self.cb_stack.pop();
|
||||
let ex_ = ex_args || {};
|
||||
cb.func(self, cb.args, ex_);
|
||||
}
|
||||
};
|
||||
|
@ -56,7 +56,7 @@ var CALLBACK_STACK = {
|
|||
// console.log(window.location, window.location.protocol+'://'+window.location.host);
|
||||
|
||||
// Teleport核心JS
|
||||
var $tp = {
|
||||
let $tp = {
|
||||
web_server: window.location.protocol+'//'+window.location.host
|
||||
|
||||
// Teleport页面应用对象,放置页面自身特有的属性和函数
|
||||
|
@ -95,7 +95,7 @@ $tp.init = function () {
|
|||
// {id: 3, name: '其它', style: 'info'}
|
||||
];
|
||||
|
||||
var cs = CALLBACK_STACK.create();
|
||||
let cs = CALLBACK_STACK.create();
|
||||
|
||||
|
||||
if(!_.isUndefined($tp.assist)) {
|
||||
|
@ -112,8 +112,8 @@ $tp.logout = function () {
|
|||
};
|
||||
|
||||
$tp.ajax_post_json = function (url, args, success, error, timeout) {
|
||||
var timeout_ = timeout || 3000;
|
||||
var _args = JSON.stringify(args);
|
||||
let timeout_ = timeout || 3000;
|
||||
let _args = JSON.stringify(args);
|
||||
|
||||
$.ajax({
|
||||
url: url,
|
||||
|
@ -127,7 +127,7 @@ $tp.ajax_post_json = function (url, args, success, error, timeout) {
|
|||
};
|
||||
|
||||
// $app 是 $tp.app 的别名,方便使用。
|
||||
var $app = $tp.app;
|
||||
let $app = $tp.app;
|
||||
|
||||
$app.add_options = function (options) {
|
||||
_.extend($app.options, options);
|
||||
|
@ -146,12 +146,12 @@ $app.init = function (cb_stack) {
|
|||
$app.active_menu = function (menu_id) {
|
||||
if (_.isUndefined($app._make_sidebar_menu)) {
|
||||
$app._make_sidebar_menu = function (menu_id) {
|
||||
var _menu = {};
|
||||
let _menu = {};
|
||||
_menu.active_menu_id = menu_id;
|
||||
_menu.current_expand_menu_id = '';
|
||||
|
||||
_menu.toggle_submenu = function (id_) {
|
||||
var obj = $('#sidebar_menu_' + id_);
|
||||
let obj = $('#sidebar_menu_' + id_);
|
||||
if (obj.hasClass('expand')) {
|
||||
obj.removeClass('expand');
|
||||
$('#sidebar_submenu_' + id_).slideUp(300);
|
||||
|
@ -234,7 +234,7 @@ $app.id2name = function(_list, _id) {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
for (var i = 0; i < _list.length; ++i) {
|
||||
for (let i = 0; i < _list.length; ++i) {
|
||||
if (_list[i].id === _id)
|
||||
return _list[i].name;
|
||||
}
|
||||
|
@ -248,7 +248,7 @@ $app.role_id2name = function (id) {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
for (var i = 0; i < $app.role_list.length; ++i) {
|
||||
for (let i = 0; i < $app.role_list.length; ++i) {
|
||||
if ($app.role_list[i].id === id)
|
||||
return $app.role_list[i].name;
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
"use strict";
|
||||
|
||||
$tp.notify_error = function (message_, title_, timeout_) {
|
||||
var _title = title_ || '';
|
||||
var _t = timeout_ || 15000;
|
||||
let _title = title_ || '';
|
||||
let _t = timeout_ || 15000;
|
||||
$.gritter.add({
|
||||
//sticky:true,
|
||||
class_name: 'gritter-error',
|
||||
|
@ -18,7 +18,7 @@ $tp.notify_error = function (message_, title_, timeout_) {
|
|||
};
|
||||
|
||||
$tp.notify_success = function (message_, title_) {
|
||||
var _title = title_ || null;
|
||||
let _title = title_ || null;
|
||||
if (_title !== null)
|
||||
_title = '<i class="far fa-check-square fa-fw"></i> ' + _title;
|
||||
$.gritter.add({
|
||||
|
@ -32,7 +32,7 @@ $tp.notify_success = function (message_, title_) {
|
|||
|
||||
// 切换一个dom节点显示与否
|
||||
$tp.toggle_display = function (selector) {
|
||||
var obj = $(selector);
|
||||
let obj = $(selector);
|
||||
if (_.isUndefined(obj))
|
||||
return;
|
||||
|
||||
|
@ -45,18 +45,18 @@ $tp.toggle_display = function (selector) {
|
|||
|
||||
$tp.disable_dom = function (dom_selector, message) {
|
||||
// 计算被禁用的DOM对象的位置和大小
|
||||
var obj = $(dom_selector);
|
||||
var pad_left = parseInt(obj.css("padding-left"), 10);
|
||||
var pad_right = parseInt(obj.css("padding-right"), 10);
|
||||
var pad_top = parseInt(obj.css("padding-top"), 10);
|
||||
var pad_bottom = parseInt(obj.css("padding-bottom"), 10);
|
||||
var w = obj.width() + pad_left + pad_right;
|
||||
var h = obj.height() + pad_top + pad_bottom;
|
||||
let obj = $(dom_selector);
|
||||
let pad_left = parseInt(obj.css("padding-left"), 10);
|
||||
let pad_right = parseInt(obj.css("padding-right"), 10);
|
||||
let pad_top = parseInt(obj.css("padding-top"), 10);
|
||||
let pad_bottom = parseInt(obj.css("padding-bottom"), 10);
|
||||
let w = obj.width() + pad_left + pad_right;
|
||||
let h = obj.height() + pad_top + pad_bottom;
|
||||
|
||||
// var html = '<div id="tp-dom-disable-obj" class="disable-bg"></div>';
|
||||
var html = [];
|
||||
// let html = '<div id="tp-dom-disable-obj" class="disable-bg"></div>';
|
||||
let html = [];
|
||||
html.push('<div id="tp-dom-disable-overlay" class="disable-bg"></div>');
|
||||
var has_message = false;
|
||||
let has_message = false;
|
||||
if (!_.isUndefined(message) && !_.isNull(message) && message.length > 0) {
|
||||
html.push('<div id="tp-dom-disable-message" class="disable-message"><i class="fas fa-exclamation-triangle fa-fw"></i> ' + message + '</div>');
|
||||
has_message = true;
|
||||
|
@ -71,13 +71,13 @@ $tp.disable_dom = function (dom_selector, message) {
|
|||
);
|
||||
|
||||
if (has_message) {
|
||||
var obj_msg = $('#tp-dom-disable-message');
|
||||
var _pad_left = parseInt(obj_msg.css("padding-left"), 10);
|
||||
var _pad_right = parseInt(obj_msg.css("padding-right"), 10);
|
||||
var _pad_top = parseInt(obj_msg.css("padding-top"), 10);
|
||||
var _pad_bottom = parseInt(obj_msg.css("padding-bottom"), 10);
|
||||
var _w = obj_msg.width() + _pad_left + _pad_right;
|
||||
var _h = obj_msg.height() + _pad_top + _pad_bottom;
|
||||
let obj_msg = $('#tp-dom-disable-message');
|
||||
let _pad_left = parseInt(obj_msg.css("padding-left"), 10);
|
||||
let _pad_right = parseInt(obj_msg.css("padding-right"), 10);
|
||||
let _pad_top = parseInt(obj_msg.css("padding-top"), 10);
|
||||
let _pad_bottom = parseInt(obj_msg.css("padding-bottom"), 10);
|
||||
let _w = obj_msg.width() + _pad_left + _pad_right;
|
||||
let _h = obj_msg.height() + _pad_top + _pad_bottom;
|
||||
|
||||
console.log(_w, _h);
|
||||
|
||||
|
@ -95,7 +95,7 @@ $tp.disable_dom = function (dom_selector, message) {
|
|||
// Dialog-box for confirm operation.
|
||||
//======================================================
|
||||
$tp.dlg_confirm = function (cb_stack, cb_args) {
|
||||
var self = {};
|
||||
let self = {};
|
||||
self._cb_stack = cb_stack;
|
||||
self._title = cb_args.title || '<i class="fas fa-exclamation-triangle"></i> 操作确认';
|
||||
self._msg = cb_args.msg || '';
|
||||
|
@ -108,7 +108,7 @@ $tp.dlg_confirm = function (cb_stack, cb_args) {
|
|||
self.dom = {};
|
||||
|
||||
self._make_message_box = function () {
|
||||
var _html = [
|
||||
let _html = [
|
||||
'<div class="modal fade" id="' + self._dlg_id + '" tabindex="-1">',
|
||||
'<div class="modal-dialog" role="document">',
|
||||
'<div class="modal-content">',
|
||||
|
@ -173,7 +173,7 @@ $tp.dlg_confirm = function (cb_stack, cb_args) {
|
|||
// Dialog-box for modify host description
|
||||
//======================================================
|
||||
$tp.create_dlg_modify_host_desc = function (tbl, row_id, host_id, host_ip, host_desc) {
|
||||
var self = {};
|
||||
let self = {};
|
||||
|
||||
self.dlg_id = _.uniqueId('dlg-modify-host-desc-');
|
||||
self._table_ctrl = tbl;
|
||||
|
@ -195,19 +195,19 @@ $tp.create_dlg_modify_host_desc = function (tbl, row_id, host_id, host_ip, host_
|
|||
self._destroy();
|
||||
});
|
||||
|
||||
var t_obj = $('#' + self.dlg_id + ' .popover');
|
||||
let t_obj = $('#' + self.dlg_id + ' .popover');
|
||||
t_obj.css({
|
||||
'top': pos_obj.offset().top + pos_obj.height() - 5,
|
||||
'left': pos_obj.offset().left
|
||||
}).show();
|
||||
|
||||
$('#' + self.dlg_id + " [ywl-input='desc']").focus();
|
||||
$('#' + self.dlg_id + " [tp-input='desc']").focus();
|
||||
};
|
||||
|
||||
self._save = function () {
|
||||
var dlg_dom_id = "[ywl-dlg='modify-host-desc']";
|
||||
let dlg_dom_id = "[tp-dlg='modify-host-desc']";
|
||||
|
||||
var val = $(dlg_dom_id + " input[ywl-input='desc']").val();
|
||||
let val = $(dlg_dom_id + " input[tp-input='desc']").val();
|
||||
if (val === self.host_desc) {
|
||||
self._destroy();
|
||||
return;
|
||||
|
@ -239,20 +239,20 @@ $tp.create_dlg_modify_host_desc = function (tbl, row_id, host_id, host_ip, host_
|
|||
};
|
||||
|
||||
self._make_dialog_box = function () {
|
||||
var _html = [
|
||||
let _html = [
|
||||
'<div class="popover-inline-edit" id="' + self.dlg_id + '">',
|
||||
' <div class="popover fade bottom in" ywl-dlg="modify-host-desc">',
|
||||
' <div class="popover fade bottom in" tp-dlg="modify-host-desc">',
|
||||
' <div class="arrow" style="left:70px;"></div>',
|
||||
' <h3 class="popover-title">编辑备注</h3>',
|
||||
' <div class="popover-content">',
|
||||
' <div>为主机 ' + self.host_ip + ' 设置备注,以便识别:</div>',
|
||||
' <div style="display:inline-block;float:right;">',
|
||||
// ' <a href="javascript:;" class="btn btn-success btn-sm" ywl-btn="ok"><i class="glyphicon glyphicon-ok"></i></a>',
|
||||
' <a href="javascript:;" class="btn btn-success btn-sm" ywl-btn="ok"><i class="fa fa-check"></i> 确定</a>',
|
||||
' <a href="javascript:;" class="btn btn-danger btn-sm" ywl-btn="cancel"><i class="fa fa-times"></i> 取消</a>',
|
||||
// ' <a href="javascript:;" class="btn btn-success btn-sm" tp-btn="ok"><i class="glyphicon glyphicon-ok"></i></a>',
|
||||
' <a href="javascript:;" class="btn btn-success btn-sm" tp-btn="ok"><i class="fa fa-check"></i> 确定</a>',
|
||||
' <a href="javascript:;" class="btn btn-danger btn-sm" tp-btn="cancel"><i class="fa fa-times"></i> 取消</a>',
|
||||
' </div>',
|
||||
' <div style="padding-right:120px;">',
|
||||
' <input type="text" ywl-input="desc" class="form-control" value="' + self.host_desc + '">',
|
||||
' <input type="text" tp-input="desc" class="form-control" value="' + self.host_desc + '">',
|
||||
' </div>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
|
@ -261,14 +261,14 @@ $tp.create_dlg_modify_host_desc = function (tbl, row_id, host_id, host_ip, host_
|
|||
$('body').append($(_html));
|
||||
|
||||
// “修改主机描述” 对话框上的两个按钮的点击事件
|
||||
$('#' + self.dlg_id + " [ywl-btn='ok']").click(function () {
|
||||
$('#' + self.dlg_id + " [tp-btn='ok']").click(function () {
|
||||
self._save();
|
||||
});
|
||||
$('#' + self.dlg_id + " [ywl-btn='cancel']").click(function () {
|
||||
$('#' + self.dlg_id + " [tp-btn='cancel']").click(function () {
|
||||
self._destroy();
|
||||
});
|
||||
// 绑定“修改主机描述” 对话框中的输入框的回车事件
|
||||
$('#' + self.dlg_id + " [ywl-input='desc']").keydown(function (event) {
|
||||
$('#' + self.dlg_id + " [tp-input='desc']").keydown(function (event) {
|
||||
if (event.which === 13) {
|
||||
self._save();
|
||||
} else if (event.which === 27) {
|
||||
|
@ -282,7 +282,7 @@ $tp.create_dlg_modify_host_desc = function (tbl, row_id, host_id, host_ip, host_
|
|||
};
|
||||
|
||||
$tp.create_dlg_show_rdp_advance = function (row_data) {
|
||||
var self = {};
|
||||
let self = {};
|
||||
|
||||
self.dlg_id = _.uniqueId('dlg-rdp-advance-');
|
||||
// self._table_ctrl = tbl;
|
||||
|
@ -304,19 +304,19 @@ $tp.create_dlg_show_rdp_advance = function (row_data) {
|
|||
self._destroy();
|
||||
});
|
||||
|
||||
var t_obj = $('#' + self.dlg_id + ' .popover');
|
||||
let t_obj = $('#' + self.dlg_id + ' .popover');
|
||||
t_obj.css({
|
||||
'top': pos_obj.offset().top + pos_obj.height() + 5,
|
||||
'left': pos_obj.offset().left - 10
|
||||
}).show();
|
||||
|
||||
//$('#' + self.dlg_id + " [ywl-input='desc']").focus();
|
||||
//$('#' + self.dlg_id + " [tp-input='desc']").focus();
|
||||
};
|
||||
|
||||
self._save = function () {
|
||||
var dlg_dom_id = '[data-dlg="show-rdp-advance"]';
|
||||
let dlg_dom_id = '[data-dlg="show-rdp-advance"]';
|
||||
|
||||
var val = $(dlg_dom_id + " input[ywl-input='desc']").val();
|
||||
let val = $(dlg_dom_id + " input[tp-input='desc']").val();
|
||||
if (val === self.host_desc) {
|
||||
self._destroy();
|
||||
return;
|
||||
|
@ -348,14 +348,14 @@ $tp.create_dlg_show_rdp_advance = function (row_data) {
|
|||
};
|
||||
|
||||
self._make_dialog_box = function () {
|
||||
var _html = [
|
||||
let _html = [
|
||||
'<div class="xx-popover-inline-edit" id="' + self.dlg_id + '">',
|
||||
' <div class="popover fade bottom in" role="tooltip" data-dlg="show-rdp-advance" style="width:300px;">',
|
||||
' <div class="arrow" style="left:50px;"></div>',
|
||||
' <h3 class="popover-title" style="font-weight:bold;">RDP连接选项(仅本次连接有效)</h3>',
|
||||
' <div class="popover-content">',
|
||||
// ' <div style="">',
|
||||
// ' <input type="text" ywl-input="desc" class="form-control" value="' + self.host_desc + '">',
|
||||
// ' <input type="text" tp-input="desc" class="form-control" value="' + self.host_desc + '">',
|
||||
// ' </div>',
|
||||
|
||||
' <div style="">',
|
||||
|
@ -398,7 +398,7 @@ $tp.create_dlg_show_rdp_advance = function (row_data) {
|
|||
});
|
||||
|
||||
// // 绑定“修改主机描述” 对话框中的输入框的回车事件
|
||||
// $('#' + self.dlg_id + " [ywl-input='desc']").keydown(function (event) {
|
||||
// $('#' + self.dlg_id + " [tp-input='desc']").keydown(function (event) {
|
||||
// if (event.which == 13) {
|
||||
// self._save();
|
||||
// } else if (event.which == 27) {
|
||||
|
|
|
@ -600,9 +600,6 @@ $tp.create_table = function (options) {
|
|||
}
|
||||
|
||||
if (!_is_duplicated) {
|
||||
//if(_.isUndefined(rows[i].ywl_row_id)) {
|
||||
// rows[i].ywl_row_id = _.uniqueId();
|
||||
//}
|
||||
rows[i]._row_id = _.uniqueId();
|
||||
ret_row_id.push(rows[i]._row_id);
|
||||
|
||||
|
@ -915,29 +912,6 @@ $tp.create_table_render = function (tbl, on_created) {
|
|||
// console.log('create_table_render', tbl, on_created);
|
||||
var _tbl_render = {};
|
||||
|
||||
// _tbl_render.fs_name = function (row_id, fields) {
|
||||
// //if(fields.type == 2) {
|
||||
// // return '<a href="javascript:void(0);" onclick="open_folder();"><span class="icon icon16 icon-' + fields.icon + '"></span> <span ywl-field="name">' + fields.name + '</span></a>';
|
||||
// //}
|
||||
// //
|
||||
// return '<span ywl-field="icon-and-name"><span class="icon icon16 icon-' + fields.icon + '"></span> <span ywl-field="name">' + fields.name + '</span></span>';
|
||||
// };
|
||||
// _tbl_render.pl_desc = function (row_id, fields) {
|
||||
// //if(fields.type == 2) {
|
||||
// // return '<a href="javascript:void(0);" onclick="open_folder();"><span class="icon icon16 icon-' + fields.icon + '"></span> <span ywl-field="name">' + fields.name + '</span></a>';
|
||||
// //}
|
||||
// //
|
||||
// var _desc = '未知';
|
||||
// if (fields.pl == 0) {
|
||||
// _desc = '来宾';
|
||||
// } else if (fields.pl == 1) {
|
||||
// _desc = '普通用户';
|
||||
// } else if (fields.pl == 2) {
|
||||
// _desc = '管理员';
|
||||
// }
|
||||
// return '<span ywl-field="pl-desc">' + _desc + '</span>';
|
||||
// };
|
||||
|
||||
_tbl_render.fs_size = function (row_id, fields) {
|
||||
if (fields.type === 0 || fields.type === 2)
|
||||
return '';
|
||||
|
@ -956,17 +930,6 @@ $tp.create_table_render = function (tbl, on_created) {
|
|||
return '<span class="datetime">' + tp_format_datetime(fields.timestamp) + '</span>';
|
||||
};
|
||||
|
||||
// _tbl_render.log_content = function (row_id, fields) {
|
||||
// var _func = ywl_log_analysis[fields.cmd_id];
|
||||
// var _content;
|
||||
// if (_.isFunction(_func)) {
|
||||
// _content = _func(fields.content);
|
||||
// } else {
|
||||
// _content = fields.content;
|
||||
// }
|
||||
// return '<span class="log-content">' + _content + '</span>';
|
||||
// };
|
||||
|
||||
_tbl_render.host_id = function (row_id, fields) {
|
||||
var ret = '';
|
||||
ret = '<span class="host-id">' + fields.id + '</span>';
|
||||
|
@ -974,21 +937,6 @@ $tp.create_table_render = function (tbl, on_created) {
|
|||
return ret;
|
||||
};
|
||||
|
||||
// _tbl_render.host_status = function (row_id, fields) {
|
||||
// if (fields.status == HOST_STAT_ACTIVE) {
|
||||
// switch (fields.online) {
|
||||
// case AGENT_STAT_ONLINE:
|
||||
// return '<span class="badge badge-success">在线</span>';
|
||||
// case AGENT_STAT_OFFLINE:
|
||||
// return '<span class="badge badge-danger">离线</span>';
|
||||
// default:
|
||||
// return '<span class="badge badge-warning">未知</span>';
|
||||
// }
|
||||
// } else {
|
||||
// return '<span class="badge badge-ignore">- 未使用 -</span>';
|
||||
// }
|
||||
// };
|
||||
|
||||
_tbl_render.os_type = function (row_id, fields) {
|
||||
switch (fields.os_type) {
|
||||
case 1:
|
||||
|
@ -1015,163 +963,13 @@ $tp.create_table_render = function (tbl, on_created) {
|
|||
};
|
||||
|
||||
_tbl_render.record_id = function (row_id, fields) {
|
||||
return '<span ywl-record-id="' + row_id + '">' + fields.r_id + '</span>';
|
||||
return '<span tp-record-id="' + row_id + '">' + fields.r_id + '</span>';
|
||||
};
|
||||
|
||||
// _tbl_render.host_group = function (row_id, fields) {
|
||||
// if (fields.status == HOST_STAT_NOT_ACTIVE)
|
||||
// return '-';
|
||||
// var g = get_host_group_by_id(fields.group);
|
||||
// if (g.id == 0)
|
||||
// return '- 未知分组 -';
|
||||
// else
|
||||
// return g.group_name;
|
||||
// };
|
||||
|
||||
// _tbl_render.command_info = function (row_id, fields) {
|
||||
// var command = get_command_name_by_id(fields.cmd_id);
|
||||
// if (command === null)
|
||||
// return '命令 ' + fields.cmd_id;
|
||||
// else
|
||||
// //return '<a href="#" data-toggle="tooltip" title=\"' + command.cmd_name + '\">' + command.cmd_desc + '</a>';
|
||||
// return '<span data-toggle="tooltip" title=\"' + command.cmd_name + '\">' + command.cmd_desc + '</span>';
|
||||
// //var info = command.cmd_name + ' '+ command.cmd_desc;
|
||||
// //return info;
|
||||
// };
|
||||
// _tbl_render.user_info = function (row_id, fields) {
|
||||
// var user_info = get_user_info_by_id(fields.u_id);
|
||||
// if (user_info === null)
|
||||
// return '用户名:' + fields.u_id;
|
||||
// else
|
||||
// return user_info.nickname;
|
||||
// //var info = command.cmd_name + ' '+ command.cmd_desc;
|
||||
// //return info;
|
||||
// };
|
||||
// // _tbl_render.event_type = function (row_id, fields) {
|
||||
// // var _e_id = fields.id1 + '-' + fields.id2 + '-' + fields.id3 + '-' + fields.id4;
|
||||
// // var content = '';
|
||||
// // if (_e_id == '3-1-1-100') {
|
||||
// // content = '系统性能监控';
|
||||
// // return '<a href="#"> ' + content + '</a>';
|
||||
// // } else if (_e_id == '3-1-1-107') {
|
||||
// // content = 'TCP监听白名单监控';
|
||||
// // return '<a href="#"> ' + content + '</a>';
|
||||
// // } else if (_e_id == '3-1-1-108') {
|
||||
// // content = 'UDP白名单监控';
|
||||
// // return '<a href="#"> ' + content + '</a>';
|
||||
// // } else if (_e_id == '3-1-1-109') {
|
||||
// // content = 'TCP连接白名单监控';
|
||||
// // return '<a href="#"> ' + content + '</a>';
|
||||
// // } else if (_e_id == '3-1-1-110') {
|
||||
// // content = '进程白名单监控';
|
||||
// // return '<a href="#"> ' + content + '</a>';
|
||||
// // } else if (_e_id == '3-1-1-7') {
|
||||
// // content = '系统用户监控';
|
||||
// // return '<a href="#"> ' + content + '</a>';
|
||||
// // } else {
|
||||
// // content = '未知';
|
||||
// // return '<a href="#"> ' + content + '</a>';
|
||||
// // }
|
||||
// //
|
||||
// //
|
||||
// // //var info = command.cmd_name + ' '+ command.cmd_desc;
|
||||
// // //return info;
|
||||
// // };
|
||||
// // _tbl_render.event_code = function (row_id, fields) {
|
||||
// // var _e_id = fields.id1 + '-' + fields.id2 + '-' + fields.id3 + '-' + fields.id4;
|
||||
// // var _e_info = get_event_code_by_id(_e_id);
|
||||
// // var _tip = '';
|
||||
// // if (_e_info === null)
|
||||
// // _tip = '未知';
|
||||
// // else
|
||||
// // _tip = _e_info.event_desc;
|
||||
// //
|
||||
// // return '<a href="#" ywl-eventcode=\"' + _e_id + '\" data-toggle="tooltip" title=\"' + _tip + '\">' + _e_id + '</a>';
|
||||
// // };
|
||||
// //
|
||||
// // _tbl_render.ret_code = function (row_id, fields) {
|
||||
// // if (fields.code === 0)
|
||||
// // return '<span class="label label-success">成功</span>';
|
||||
// // else
|
||||
// // var message = '失败(' + fields.code + ',' + fields.param1 + ',' + fields.param2 + ')';
|
||||
// // return '<span class="label label-danger" data-toggle="tooltip" title= \"' + message + '\">' + message + '</span>';
|
||||
// // //var info = command.cmd_name + ' '+ command.cmd_desc;
|
||||
// // //return info;
|
||||
// // };
|
||||
// //
|
||||
// // _tbl_render.memory = function (row_id, fields) {
|
||||
// // if (fields.status == HOST_STAT_NOT_ACTIVE)
|
||||
// // return '-';
|
||||
// // if (0 == fields.value)
|
||||
// // return '';
|
||||
// // return '<span class="badge bg-normal">' + size2str(fields.value, 0) + '</span>';
|
||||
// // };
|
||||
// //
|
||||
// // _tbl_render.ip = function (row_id, fields) {
|
||||
// // if (fields.status == HOST_STAT_NOT_ACTIVE)
|
||||
// // return '-';
|
||||
// //
|
||||
// // var ret = '';
|
||||
// // var _this_id = _.uniqueId('ip-list-');
|
||||
// //
|
||||
// // if (fields.ip.length > 2) {
|
||||
// // ret += '<div class="td-ip-show-more"><a href="javascript:;" onclick="$tp.toggle_display(\'#' + _this_id + '\');"><i class="fa fa-angle-down"></i></a></div>';
|
||||
// // }
|
||||
// //
|
||||
// // ret += '<div class="td-ip-list"><div class="td-ip">';
|
||||
// //
|
||||
// // var idx, loop;
|
||||
// // (fields.ip.length > 2) ? loop = 2 : loop = fields.ip.length;
|
||||
// // for (idx = 0; idx < loop; ++idx) {
|
||||
// // ret += '<div class="td-ip-item"><span>' + fields.ip[idx] + '</span>';
|
||||
// // if (fields.ip.length > 1) {
|
||||
// // // TODO:暂不支持调整IP列表顺序功能
|
||||
// // //ret += '<a href="#"><i class="fa fa-arrow-circle-up fa-fw"></i></a>';
|
||||
// // }
|
||||
// // ret += '</div>';
|
||||
// // }
|
||||
// //
|
||||
// // ret += '</div>';
|
||||
// //
|
||||
// // if (fields.ip.length > 2) {
|
||||
// // ret += '<div id="' + _this_id + '" class="td-ip-more" style="display:none;">';
|
||||
// // for (idx = 2; idx < fields.ip.length; ++idx) {
|
||||
// // ret += '<div class="td-ip-item"><span>' + fields.ip[idx] + '</span>';
|
||||
// // // TODO:暂不支持调整IP列表顺序功能
|
||||
// // //ret += '<a href="#"><i class="fa fa-arrow-circle-up fa-fw"></i></a>';
|
||||
// // ret += '</div>';
|
||||
// // }
|
||||
// // ret += '</div>';
|
||||
// // }
|
||||
// //
|
||||
// // return ret;
|
||||
// // };
|
||||
// //
|
||||
// // _tbl_render.disk = function (row_id, fields) {
|
||||
// // if (fields.status == HOST_STAT_NOT_ACTIVE)
|
||||
// // return '-';
|
||||
// //
|
||||
// // var ret = '';
|
||||
// // $.each(fields.disk, function (i, disk_size) {
|
||||
// // ret += '<span class="badge bg-normal">' + size2str(disk_size, 2) + '</span> ';
|
||||
// // });
|
||||
// // return ret;
|
||||
// // };
|
||||
// //
|
||||
_tbl_render.second2str = function (row_id, fields) {
|
||||
return '<i class="far fa-clock fa-fw"></i> ' + tp_second2str(fields.seconds);
|
||||
};
|
||||
|
||||
// _tbl_render.host_rate_show = function (row_id, fields) {
|
||||
// if (fields.value >= 90) {
|
||||
// return '<span class="badge badge-danger">' + fields.value + '</span>';
|
||||
// } else if (fields.value >= 50) {
|
||||
// return '<span class="badge badge-warning">' + fields.value + '</span>';
|
||||
// } else {
|
||||
// return '<span class="badge badge-success">' + fields.value + '</span>';
|
||||
// }
|
||||
// };
|
||||
|
||||
if (_.isFunction(on_created)) {
|
||||
on_created(_tbl_render);
|
||||
} else if (!_.isUndefined(on_created)) {
|
||||
|
|
|
@ -1,94 +1,261 @@
|
|||
"use strict";
|
||||
|
||||
// 页面访问助手的流程:
|
||||
// 1. 通过ajax查询当前是否有已经绑定的助手连接可用,有则直接使用(避免每次刷新页面都调用一次url-protocol)
|
||||
// 2. 如果没有,则打开ws通道,服务端会返回一个临时的助手id,页面再通过url-protocol去调用助手
|
||||
// 3. 调用成功的话,ws通道会返回当前会话实际绑定的助手连接,后续操作可以通过助手连接来向助手发送操作命令
|
||||
|
||||
$tp.assist = {
|
||||
running: false,
|
||||
assist_id: 0,
|
||||
version: '',
|
||||
ver_require: '0.0.0',
|
||||
errcode: TPE_OK,
|
||||
api_url: '',
|
||||
teleport_ip: window.location.hostname,
|
||||
url_scheme: '',
|
||||
ws_url: '',
|
||||
ws: null,
|
||||
|
||||
next_commands: [],
|
||||
|
||||
dom: {
|
||||
msg_box_title: null,
|
||||
msg_box_info: null,
|
||||
msg_box_desc: null
|
||||
},
|
||||
|
||||
ws_response_callback: {
|
||||
start_assist: null,
|
||||
update_assist_info: null,
|
||||
assist_disconnected: null,
|
||||
run: null
|
||||
}
|
||||
};
|
||||
|
||||
// console.log(window.location.protocol);
|
||||
|
||||
// $assist 是 $tp.assist 的别名,方便使用。
|
||||
var $assist = $tp.assist;
|
||||
let $assist = $tp.assist;
|
||||
|
||||
$assist.init = function (cb_stack) {
|
||||
if(location.protocol === 'http:') {
|
||||
$assist.api_url = 'http://localhost:50022/api';
|
||||
} else {
|
||||
$assist.api_url = 'https://localhost:50023/api';
|
||||
}
|
||||
console.log('assist.init().');
|
||||
|
||||
$assist._make_message_box();
|
||||
$('#dialog-need-assist-a').modal();
|
||||
|
||||
$assist.ws_response_callback['start_assist'] = $assist._on_ret_start_assist;
|
||||
$assist.ws_response_callback['update_assist_info'] = $assist._on_ret_update_assist_info;
|
||||
$assist.ws_response_callback['assist_disconnected'] = $assist._on_ret_assist_disconnected;
|
||||
$assist.ws_response_callback['run'] = $assist._on_ret_run;
|
||||
|
||||
// var data = {};
|
||||
// var args_ = encodeURIComponent(JSON.stringify(data));
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
timeout: 3000,
|
||||
//url: 'http://localhost:50022/ts_get_version/' + args_,
|
||||
url: $assist.api_url + '/get_version',
|
||||
jsonp: 'callback',
|
||||
url: '/assist/get-assist-info',
|
||||
type: 'POST',
|
||||
timeout: 5000,
|
||||
//data: {_xsrf: get_cookie('_xsrf'), args: args_},
|
||||
data: {},
|
||||
dataType: 'json',
|
||||
success: function (ret) {
|
||||
$assist.running = true;
|
||||
$assist.version = ret.version;
|
||||
console.log('get-assist-info', ret);
|
||||
if (ret.code === TPE_OK) {
|
||||
$assist.running = true;
|
||||
$assist.assist_id = ret.data.assist_id;
|
||||
$assist.version = ret.data.assist_ver;
|
||||
|
||||
if (_.isFunction($tp.assist_checked)) {
|
||||
$tp.assist_checked();
|
||||
if (_.isFunction($tp.assist_checked)) {
|
||||
$tp.assist_checked();
|
||||
}
|
||||
|
||||
if ($assist.next_commands.length > 0) {
|
||||
$assist._bind_assist_and_exec(null);
|
||||
}
|
||||
} else if (ret.code === TPE_NOT_EXISTS) {
|
||||
// 还没有绑定助手,需要通过 url-protocol 方式启动一下
|
||||
$assist._bind_assist_and_exec(null);
|
||||
} else {
|
||||
// 其他错误
|
||||
$tp.notify_error('无法获取助手信息:' + tp_error_msg(ret.code, ret.message));
|
||||
}
|
||||
// if (version_compare()) {
|
||||
// error_process(ret, func_success, func_error);
|
||||
// } else {
|
||||
// func_error(ret, TPE_OLD_ASSIST, '助手版本太低,请<a style="color:#aaaaff;" target="_blank" href="http://tp4a.com/download">下载最新版本</a>!');
|
||||
// }
|
||||
},
|
||||
error: function () {
|
||||
$assist.running = false;
|
||||
if (_.isFunction($tp.assist_checked)) {
|
||||
$tp.assist_checked();
|
||||
}
|
||||
// func_error({}, TPE_NO_ASSIST, '无法连接到teleport助手,可能尚未启动!');
|
||||
// $tp.notify_error('无法连接到teleport助手,可能尚未启动!');
|
||||
// $assist.alert_assist_not_found();
|
||||
console.error('无法连接到teleport助手,可能其尚未运行!');
|
||||
$tp.notify_error('无法获取助手信息:远程网络通讯失败!');
|
||||
}
|
||||
});
|
||||
|
||||
cb_stack.exec();
|
||||
};
|
||||
|
||||
$assist.check = function() {
|
||||
$assist.add_next_command = function (cmd) {
|
||||
$assist.next_commands.push(cmd);
|
||||
}
|
||||
|
||||
$assist.exec_next_command = function () {
|
||||
while ($assist.next_commands.length > 0) {
|
||||
console.log('send command: ', $assist.next_commands[0]);
|
||||
$assist.ws.send(JSON.stringify($assist.next_commands[0]));
|
||||
$assist.next_commands.pop();
|
||||
}
|
||||
}
|
||||
|
||||
$assist.register_response_handler = function (method, fn) {
|
||||
$assist.ws_response_callback[method] = fn;
|
||||
};
|
||||
|
||||
$assist._bind_assist_and_exec = function (cmd) {
|
||||
let msg_obj = {
|
||||
'type': ASSIST_WS_COMMAND_TYPE_REQUEST,
|
||||
'method': 'register',
|
||||
'param': {
|
||||
'client': 'web'
|
||||
}
|
||||
}
|
||||
|
||||
if (!_.isNull(cmd)) {
|
||||
$assist.add_next_command(cmd);
|
||||
}
|
||||
|
||||
if (!$assist.running && !_.isNull($assist.ws)) {
|
||||
console.log('ws-send:', msg_obj);
|
||||
$assist.ws.send(JSON.stringify(msg_obj));
|
||||
return;
|
||||
}
|
||||
|
||||
if (_.isNull($assist.ws)) {
|
||||
console.log('create web-ws.');
|
||||
|
||||
if (location.protocol === 'http:') {
|
||||
$assist.ws_url = 'ws://' + location.host + '/ws/assist/';
|
||||
} else {
|
||||
$assist.ws_url = 'wss://' + location.host + '/ws/assist/';
|
||||
}
|
||||
|
||||
|
||||
$assist.ws = new WebSocket($assist.ws_url + encodeURIComponent(JSON.stringify(msg_obj)));
|
||||
|
||||
$assist.ws.onopen = function (e) {
|
||||
console.log('web-ws: connected.');
|
||||
};
|
||||
|
||||
$assist.ws.onclose = function (e) {
|
||||
console.log('web-ws: disconnected.');
|
||||
$assist.ws = null;
|
||||
$assist.assist_id = 0;
|
||||
$assist.assist_ver = '';
|
||||
};
|
||||
|
||||
$assist.ws.onmessage = function (e) {
|
||||
let t = JSON.parse(e.data);
|
||||
|
||||
if (_.isUndefined(t.type)) {
|
||||
console.log('invalid message format: ', e.data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (t.type === ASSIST_WS_COMMAND_TYPE_RESPONSE) {
|
||||
if (!_.isUndefined($assist.ws_response_callback[t.method])) {
|
||||
let fn = $assist.ws_response_callback[t.method];
|
||||
fn(t.code, t.message, t.data);
|
||||
} else {
|
||||
console.error('There are no callback for method: ', t.method);
|
||||
// return;
|
||||
}
|
||||
} else {
|
||||
console.log('unknown type:', t.type)
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
$assist._on_ret_start_assist = function (code, message, ret) {
|
||||
if (code !== TPE_OK) {
|
||||
console.log('show error: code=', code, ', message=', message);
|
||||
$tp.notify_error('发生错误:' + tp_error_msg(code, message));
|
||||
return;
|
||||
}
|
||||
|
||||
let session_id = Cookies.get('_sid');
|
||||
let data = {'method': 'register', 'ws_url': $assist.ws_url, 'assist_id': ret.request_assist_id, 'session_id': session_id}
|
||||
$assist.url_scheme = 'teleport://register?param=' + JSON.stringify(data);
|
||||
if (!$('#url-protocol').length) {
|
||||
let _html = '<div id="url-protocol" style="display:none;z-index=-1;"><iframe src=""/></div>';
|
||||
$('body').append($(_html));
|
||||
}
|
||||
console.log($assist.url_scheme);
|
||||
$('#url-protocol').find("iframe").attr("src", $assist.url_scheme);
|
||||
|
||||
// 在macOS平台,如果助手尚未运行,首次通过 teleport:// 调起助手,只会运行助手,并不会触发其连接服务端
|
||||
// 试图5秒后,检查是否获取到助手版本,如果没有,再尝试一次启动助手,会被浏览器安全设置限制
|
||||
// 错误原因:由于用户并未触发,或此 iframe 上次加载以来的时间不足,已屏蔽使用外部协议的 iframe。
|
||||
// 这种情况下,只能再次刷新页面来触发一次,即可正常连接上。
|
||||
setTimeout($assist.check_assist, 3000);
|
||||
};
|
||||
|
||||
$assist._on_ret_update_assist_info = function (code, message, ret) {
|
||||
if (code !== TPE_OK) {
|
||||
console.log('show error: code=', code, ', message=', message);
|
||||
$tp.notify_error('发生错误:' + tp_error_msg(code, message));
|
||||
return;
|
||||
}
|
||||
|
||||
if (ret.assist_ver === '') {
|
||||
console.log("so bad.");
|
||||
} else {
|
||||
$assist.running = true;
|
||||
$assist.version = ret.assist_ver;
|
||||
|
||||
if (_.isFunction($tp.assist_checked)) {
|
||||
$tp.assist_checked();
|
||||
}
|
||||
|
||||
$assist.exec_next_command();
|
||||
}
|
||||
}
|
||||
|
||||
$assist._on_ret_assist_disconnected = function (code, message, ret) {
|
||||
console.log('assist-ws disconnected.');
|
||||
$assist.running = false;
|
||||
$assist.version = '';
|
||||
$assist.url_scheme = '';
|
||||
|
||||
if (_.isFunction($tp.assist_checked)) {
|
||||
$tp.assist_checked();
|
||||
}
|
||||
}
|
||||
|
||||
$assist._on_ret_run = function (code, message, ret) {
|
||||
console.log('_on_ret_run(), code=', code, 'message=', message, 'ret=', ret);
|
||||
|
||||
if (code !== TPE_OK) {
|
||||
console.log('show error: code=', code, ', message=', message);
|
||||
$tp.notify_error('发生错误:' + tp_error_msg(code, message));
|
||||
return;
|
||||
}
|
||||
|
||||
$tp.notify_success('已启动本地客户端进行远程连接!');
|
||||
}
|
||||
|
||||
$assist.check_assist = function () {
|
||||
console.log('check assist...');
|
||||
if (!$assist.running) {
|
||||
$assist.errcode = TPE_NO_ASSIST;
|
||||
$assist.alert_assist_not_found();
|
||||
$assist.alert_assist_not_found(TPE_NO_ASSIST);
|
||||
return false;
|
||||
} else if (!$assist._version_compare()) {
|
||||
$assist.errcode = TPE_OLD_ASSIST;
|
||||
$assist.alert_assist_not_found();
|
||||
$assist.alert_assist_not_found(TPE_OLD_ASSIST);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
$assist.alert_assist_not_found = function () {
|
||||
if($assist.errcode === TPE_NO_ASSIST) {
|
||||
$assist.dom.msg_box_title.html('未检测到TELEPORT助手');
|
||||
$assist.dom.msg_box_info.html('需要TELEPORT助手来辅助远程连接,请确认本机运行了TELEPORT助手!');
|
||||
$assist.dom.msg_box_desc.html('如果您尚未运行TELEPORT助手,请 <a href="/static/download/teleport-assist-windows.exe" target="_blank"><strong>下载最新版TELEPORT助手安装包</strong></a> 并安装。一旦运行了TELEPORT助手,即可刷新页面,重新进行远程连接。');
|
||||
} else if($assist.errcode === TPE_OLD_ASSIST) {
|
||||
$assist.dom.msg_box_title.html('TELEPORT助手需要升级');
|
||||
$assist.dom.msg_box_info.html('检测到TELEPORT助手版本 v'+ $assist.version +',但需要最低版本 v'+ $assist.ver_require+'。');
|
||||
$assist.dom.msg_box_desc.html('请 <a href="/static/download/teleport-assist-windows.exe" target="_blank"><strong>下载最新版TELEPORT助手安装包</strong></a> 并安装。一旦升级了TELEPORT助手,即可刷新页面,重新进行远程连接。');
|
||||
$assist.alert_assist_not_found = function (errcode) {
|
||||
if (errcode === TPE_NO_ASSIST) {
|
||||
$assist.dom.msg_box_title.html('未检测到Teleport助手');
|
||||
$assist.dom.msg_box_info.html('需要Teleport助手来辅助远程连接,请确认本机运行了TELEPORT助手!');
|
||||
$assist.dom.msg_box_desc.html(
|
||||
'<p>如果您已经安装运行了Teleport助手(系统托盘区可见到 <img src="/static/favicon.png" width="18"/> 图标),可尝试刷新页面。如果本提示持续出现,请联系管理员。</p>' +
|
||||
'<p>如果您尚未运行Teleport助手,请先下载Teleport助手安装包并安装。一旦运行了Teleport助手,即可刷新页面,重新进行远程连接。</p>');
|
||||
} else if (errcode === TPE_OLD_ASSIST) {
|
||||
$assist.dom.msg_box_title.html('Teleport助手需要升级');
|
||||
$assist.dom.msg_box_info.html('检测到Teleport助手版本 v' + $assist.version + ',但需要最低版本 v' + $assist.ver_require + '。');
|
||||
$assist.dom.msg_box_desc.html('<p>请下载最新版Teleport助手安装包并安装、运行。一旦升级了Teleport助手,即可刷新页面,重新进行远程连接。</p>');
|
||||
}
|
||||
|
||||
$('#dialog-need-assist').modal();
|
||||
|
@ -99,18 +266,17 @@ $assist.alert_assist_not_found = function () {
|
|||
// 2.1.1 > 1.2.9
|
||||
// 2.1.10 > 2.1.9
|
||||
$assist._version_compare = function () {
|
||||
var ver_current = $assist.version.split(".");
|
||||
var ver_require = $assist.ver_require.split(".");
|
||||
let ver_current = $assist.version.split(".");
|
||||
let ver_require = $assist.ver_require.split(".");
|
||||
|
||||
var count = ver_current.length;
|
||||
if(ver_require.length > count)
|
||||
let count = ver_current.length;
|
||||
if (ver_require.length > count)
|
||||
count = ver_require.length;
|
||||
|
||||
var c, r;
|
||||
for(var i = 0; i < count; ++i) {
|
||||
c = ver_current[i] || 0;
|
||||
r = ver_require[i] || 0;
|
||||
if(c < r)
|
||||
for (let i = 0; i < count; ++i) {
|
||||
let c = ver_current[i] || 0;
|
||||
let r = ver_require[i] || 0;
|
||||
if (c < r)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -118,7 +284,7 @@ $assist._version_compare = function () {
|
|||
};
|
||||
|
||||
$assist._make_message_box = function () {
|
||||
var _html = [
|
||||
let _html = [
|
||||
'<div class="modal fade" id="dialog-need-assist">',
|
||||
'<div class="modal-dialog" role="document">',
|
||||
'<div class="modal-content">',
|
||||
|
@ -129,16 +295,37 @@ $assist._make_message_box = function () {
|
|||
'<div class="alert alert-danger" role="alert">',
|
||||
'<p id="assist-msg-box-info"></p>',
|
||||
'</div>',
|
||||
'<p id="assist-msg-box-desc"></p>',
|
||||
'<div id="assist-msg-box-desc">',
|
||||
'</div>',
|
||||
'<div>',
|
||||
'<hr/>',
|
||||
'<p class="bold">下载安装Teleport助手</p>',
|
||||
'<div class="raw">',
|
||||
'<div class="col-sm-6 center">',
|
||||
'<a class="btn btn-success" type="button" style="width:100%;" href="/assist/download/windows">',
|
||||
'<i class="fab fa-windows fa-fw" style="font-size:36px"></i><br/>',
|
||||
'<i class="fa fa-download fa-fw"></i> 下载 Windows 版本助手',
|
||||
'</a>',
|
||||
'</div>',
|
||||
'<div class="col-sm-6 center">',
|
||||
'<a class="btn btn-info" type="button" style="width:100%;" href="/assist/download/macos">',
|
||||
'<i class="fab fa-apple fa-fw" style="font-size:36px"></i><br/>',
|
||||
'<i class="fa fa-download fa-fw"></i> 下载 macOS 版本助手',
|
||||
'</a>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'<div class="clear-float"></div>',
|
||||
'</div>',
|
||||
'<div class="modal-footer">',
|
||||
'<button type="button" class="btn btn-sm btn-primary" id="btn-assist-reload-page"><i class="fa fa-sync fa-fw"></i> 刷新页面</button>',
|
||||
'<button type="button" class="btn btn-sm btn-default" data-dismiss="modal"><i class="fa fa-times fa-fw"></i> 我知道了</button>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'</div>'
|
||||
].join('\n');
|
||||
].join('');
|
||||
$('body').append($(_html));
|
||||
|
||||
$assist.dom.msg_box_title = $('#assist-msg-box-tittle');
|
||||
|
@ -146,14 +333,23 @@ $assist._make_message_box = function () {
|
|||
$assist.dom.msg_box_desc = $('#assist-msg-box-desc');
|
||||
};
|
||||
|
||||
$assist.select_local_file = function (app_type) {
|
||||
let cmd = {
|
||||
type: ASSIST_WS_COMMAND_TYPE_REQUEST,
|
||||
method: 'select_file',
|
||||
param: {
|
||||
app_type: app_type
|
||||
}
|
||||
};
|
||||
|
||||
$assist.ws.send(JSON.stringify(cmd));
|
||||
};
|
||||
|
||||
$assist.do_teleport = function (args, func_success, func_error) {
|
||||
if(!$app.options.url_proto){
|
||||
if(!$assist.check())
|
||||
return;
|
||||
}
|
||||
// todo: 将args传给服务端,由服务端直接组一个命令发给对应的assist-websocket进行执行即可,无需再返回到页面中转一次。
|
||||
|
||||
// 第一步:将参数传递给web服务,准备获取一个远程连接会话ID
|
||||
var args_ = JSON.stringify(args);
|
||||
let args_ = JSON.stringify(args);
|
||||
$.ajax({
|
||||
url: '/ops/get-session-id',
|
||||
type: 'POST',
|
||||
|
@ -165,11 +361,11 @@ $assist.do_teleport = function (args, func_success, func_error) {
|
|||
console.log('get-session-id:', ret);
|
||||
if (ret.code === TPE_OK) {
|
||||
// 第二步:获取到临时会话ID后,将此ID传递给助手,准备开启一次远程会话
|
||||
var session_id = ret.data.session_id;
|
||||
var remote_host_ip = ret.data.host_ip;
|
||||
var remote_host_name = ret.data.host_name;
|
||||
var teleport_port = ret.data.teleport_port;
|
||||
var data = {
|
||||
let session_id = ret.data.session_id;
|
||||
let remote_host_ip = ret.data.host_ip;
|
||||
let remote_host_name = ret.data.host_name;
|
||||
let teleport_port = ret.data.teleport_port;
|
||||
let data = {
|
||||
//server_ip: g_host_name, //args.server_ip,
|
||||
//server_port: parseInt(args.server_port),
|
||||
teleport_ip: $assist.teleport_ip,
|
||||
|
@ -185,40 +381,25 @@ $assist.do_teleport = function (args, func_success, func_error) {
|
|||
protocol_flag: parseInt(ret.data.protocol_flag)
|
||||
};
|
||||
|
||||
if(args.protocol_type === TP_PROTOCOL_TYPE_RDP) {
|
||||
if (args.protocol_type === TP_PROTOCOL_TYPE_RDP) {
|
||||
data.rdp_width = args.rdp_width;
|
||||
data.rdp_height = args.rdp_height;
|
||||
data.rdp_console = args.rdp_console;
|
||||
}
|
||||
|
||||
// console.log('---', data);
|
||||
var args_ = encodeURIComponent(JSON.stringify(data));
|
||||
// 判断是否使用 url-protocol 处理方式
|
||||
if ($app.options.url_proto){
|
||||
if(!$("#url-protocol").length) {
|
||||
var _html = '<div id="url-protocol" style="display:none;z-index=-1;"><iframe src=""/></div>';
|
||||
$('body').append($(_html));
|
||||
}
|
||||
$("#url-protocol").find("iframe").attr("src",'teleport://' + JSON.stringify(data));
|
||||
}else{
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
timeout: 5000,
|
||||
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助手,可能尚未启动!');
|
||||
}
|
||||
});
|
||||
console.log('---run---', data);
|
||||
let _exec = {type: ASSIST_WS_COMMAND_TYPE_REQUEST, method: 'run', param: data};
|
||||
|
||||
// 注意:这里不能在再用iframe调用teleport://的方式来让助手启动本地程序了,web页面先于助手启动时,点击远程连接
|
||||
// 会导致连续两次调用url-protocol,第一次是让助手进行ws注册,此处是第二次,因为是连续调用,会导致firefox报错:
|
||||
// 错误:由于用户并未触发,或此 iframe 上次加载以来的时间不足,已屏蔽使用外部协议的 iframe。
|
||||
// 因此直接通过ws到TP服务端转发给助手。
|
||||
|
||||
if (_.isNull($assist.ws) || !$assist.running) {
|
||||
$assist._bind_assist_and_exec(_exec);
|
||||
} else {
|
||||
// _exec($assist);
|
||||
$assist.ws.send(JSON.stringify(_exec));
|
||||
}
|
||||
} else {
|
||||
if (ret.code === TPE_NO_CORE_SERVER) {
|
||||
|
@ -238,13 +419,13 @@ $assist.do_rdp_replay = function (rid, func_success, func_error) {
|
|||
// rid: (int) - record-id in database.
|
||||
|
||||
// now make the args.
|
||||
var args = {rid: rid};
|
||||
let args = {rid: rid};
|
||||
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.
|
||||
|
||||
console.log('do-rdp-replay:', args);
|
||||
|
||||
var args_ = encodeURIComponent(JSON.stringify(args));
|
||||
let args_ = encodeURIComponent(JSON.stringify(args));
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
timeout: 6000,
|
||||
|
|
|
@ -1,163 +1,162 @@
|
|||
"use strict";
|
||||
|
||||
|
||||
var TP_LOGIN_AUTH_SYS_DEFAULT = 0; // 系统默认
|
||||
var TP_LOGIN_AUTH_USERNAME_PASSWORD = 0x0001; // 用户名+密码
|
||||
var TP_LOGIN_AUTH_USERNAME_PASSWORD_CAPTCHA = 0x0002; // 用户名+密码+验证码
|
||||
var TP_LOGIN_AUTH_USERNAME_OATH = 0x0004; // 用户名+OATH
|
||||
var TP_LOGIN_AUTH_USERNAME_PASSWORD_OATH = 0x0008; // 用户名+密码+OATH
|
||||
const TP_LOGIN_AUTH_SYS_DEFAULT = 0; // 系统默认
|
||||
const TP_LOGIN_AUTH_USERNAME_PASSWORD = 0x0001; // 用户名+密码
|
||||
const TP_LOGIN_AUTH_USERNAME_PASSWORD_CAPTCHA = 0x0002; // 用户名+密码+验证码
|
||||
const TP_LOGIN_AUTH_USERNAME_OATH = 0x0004; // 用户名+OATH
|
||||
const TP_LOGIN_AUTH_USERNAME_PASSWORD_OATH = 0x0008; // 用户名+密码+OATH
|
||||
|
||||
//=======================================================
|
||||
// 远程连接认证方式
|
||||
//=======================================================
|
||||
var TP_AUTH_TYPE_NONE = 0;
|
||||
var TP_AUTH_TYPE_PASSWORD = 1;
|
||||
var TP_AUTH_TYPE_PRIVATE_KEY = 2;
|
||||
const TP_AUTH_TYPE_NONE = 0;
|
||||
const TP_AUTH_TYPE_PASSWORD = 1;
|
||||
const TP_AUTH_TYPE_PRIVATE_KEY = 2;
|
||||
|
||||
//=======================================================
|
||||
// 远程连接协议
|
||||
//=======================================================
|
||||
var TP_PROTOCOL_TYPE_RDP = 1;
|
||||
var TP_PROTOCOL_TYPE_SSH = 2;
|
||||
var TP_PROTOCOL_TYPE_TELNET = 3;
|
||||
const TP_PROTOCOL_TYPE_RDP = 1;
|
||||
const TP_PROTOCOL_TYPE_SSH = 2;
|
||||
const TP_PROTOCOL_TYPE_TELNET = 3;
|
||||
|
||||
//=======================================================
|
||||
// 远程连接子协议
|
||||
//=======================================================
|
||||
var TP_PROTOCOL_TYPE_RDP_DESKTOP = 100;
|
||||
var TP_PROTOCOL_TYPE_SSH_SHELL = 200;
|
||||
var TP_PROTOCOL_TYPE_SSH_SFTP = 201;
|
||||
var TP_PROTOCOL_TYPE_TELNET_SHELL = 300;
|
||||
const TP_PROTOCOL_TYPE_RDP_DESKTOP = 100;
|
||||
const TP_PROTOCOL_TYPE_SSH_SHELL = 200;
|
||||
const TP_PROTOCOL_TYPE_SSH_SFTP = 201;
|
||||
const TP_PROTOCOL_TYPE_TELNET_SHELL = 300;
|
||||
|
||||
//=======================================================
|
||||
// 远程主机操作系统
|
||||
//=======================================================
|
||||
var TP_OS_TYPE_WINDOWS = 1;
|
||||
var TP_OS_TYPE_LINUX = 2;
|
||||
const TP_OS_TYPE_WINDOWS = 1;
|
||||
const TP_OS_TYPE_LINUX = 2;
|
||||
|
||||
// =======================================================
|
||||
// 远程连接会话状态
|
||||
// =======================================================
|
||||
var TP_SESS_STAT_RUNNING = 0; // 会话开始了,尚未结束,还在连接过程中
|
||||
var TP_SESS_STAT_ERR_AUTH_DENIED = 1; // 会话结束,因为认证失败
|
||||
var TP_SESS_STAT_ERR_CONNECT = 2; // 会话结束,因为无法连接到远程主机
|
||||
var TP_SESS_STAT_ERR_BAD_SSH_KEY = 3; // 会话结束,因为无法识别SSH私钥
|
||||
var TP_SESS_STAT_ERR_INTERNAL = 4; // 会话结束,因为内部错误
|
||||
var TP_SESS_STAT_ERR_UNSUPPORT_PROTOCOL = 5; // 会话结束,因为协议不支持(RDP)
|
||||
var TP_SESS_STAT_ERR_BAD_PKG = 6; // 会话结束,因为收到错误的报文
|
||||
var TP_SESS_STAT_ERR_RESET = 7; // 会话结束,因为teleport核心服务重置了
|
||||
var TP_SESS_STAT_ERR_IO = 8; // 会话结束,因为网络中断
|
||||
var TP_SESS_STAT_ERR_SESSION = 9; // 会话结束,因为无效的会话ID
|
||||
var TP_SESS_STAT_ERR_AUTH_TYPE = 10; // 会话结束,因为服务端不支持此认证方式
|
||||
var TP_SESS_STAT_ERR_CREATE_CHANNEL = 11; // 会话结束,因为创建通道失败
|
||||
const TP_SESS_STAT_RUNNING = 0; // 会话开始了,尚未结束,还在连接过程中
|
||||
const TP_SESS_STAT_ERR_AUTH_DENIED = 1; // 会话结束,因为认证失败
|
||||
const TP_SESS_STAT_ERR_CONNECT = 2; // 会话结束,因为无法连接到远程主机
|
||||
const TP_SESS_STAT_ERR_BAD_SSH_KEY = 3; // 会话结束,因为无法识别SSH私钥
|
||||
const TP_SESS_STAT_ERR_INTERNAL = 4; // 会话结束,因为内部错误
|
||||
const TP_SESS_STAT_ERR_UNSUPPORT_PROTOCOL = 5; // 会话结束,因为协议不支持(RDP)
|
||||
const TP_SESS_STAT_ERR_BAD_PKG = 6; // 会话结束,因为收到错误的报文
|
||||
const TP_SESS_STAT_ERR_RESET = 7; // 会话结束,因为teleport核心服务重置了
|
||||
const TP_SESS_STAT_ERR_IO = 8; // 会话结束,因为网络中断
|
||||
const TP_SESS_STAT_ERR_SESSION = 9; // 会话结束,因为无效的会话ID
|
||||
const TP_SESS_STAT_ERR_AUTH_TYPE = 10; // 会话结束,因为服务端不支持此认证方式
|
||||
const TP_SESS_STAT_ERR_CREATE_CHANNEL = 11; // 会话结束,因为创建通道失败
|
||||
|
||||
var TP_SESS_STAT_STARTED = 100; // 已经连接成功了,开始记录录像了
|
||||
var TP_SESS_STAT_ERR_START_INTERNAL = 104; // 会话结束,因为内部错误
|
||||
var TP_SESS_STAT_ERR_START_BAD_PKG = 106; // 会话结束,因为收到错误的报文
|
||||
var TP_SESS_STAT_ERR_START_RESET = 107; // 会话结束,因为teleport核心服务重置了
|
||||
var TP_SESS_STAT_ERR_START_IO = 108; // 会话结束,因为网络中断
|
||||
const TP_SESS_STAT_STARTED = 100; // 已经连接成功了,开始记录录像了
|
||||
const TP_SESS_STAT_ERR_START_INTERNAL = 104; // 会话结束,因为内部错误
|
||||
const TP_SESS_STAT_ERR_START_BAD_PKG = 106; // 会话结束,因为收到错误的报文
|
||||
const TP_SESS_STAT_ERR_START_RESET = 107; // 会话结束,因为teleport核心服务重置了
|
||||
const TP_SESS_STAT_ERR_START_IO = 108; // 会话结束,因为网络中断
|
||||
|
||||
var TP_SESS_STAT_END = 9999; // 会话成功结束
|
||||
const TP_SESS_STAT_END = 9999; // 会话成功结束
|
||||
|
||||
// ==========================================================================
|
||||
// 对象类型
|
||||
// ==========================================================================
|
||||
var TP_USER = 1;
|
||||
var TP_GROUP_USER = 2;
|
||||
var TP_ACCOUNT = 3;
|
||||
var TP_GROUP_ACCOUNT = 4;
|
||||
var TP_HOST = 5;
|
||||
var TP_GROUP_HOST = 6;
|
||||
const TP_USER = 1;
|
||||
const TP_GROUP_USER = 2;
|
||||
const TP_ACCOUNT = 3;
|
||||
const TP_GROUP_ACCOUNT = 4;
|
||||
const TP_HOST = 5;
|
||||
const TP_GROUP_HOST = 6;
|
||||
|
||||
// =======================================================
|
||||
// 对象状态(用户/用户组/主机/主机组/账号/账号组/运维授权策略/审计授权策略/...)
|
||||
// =======================================================
|
||||
var TP_STATE_NORMAL = 1; // 正常
|
||||
var TP_STATE_DISABLED = 2; // 禁用
|
||||
var TP_STATE_LOCKED = 3; // 临时禁用(用于用户登录连续错误n次)
|
||||
const TP_STATE_NORMAL = 1; // 正常
|
||||
const TP_STATE_DISABLED = 2; // 禁用
|
||||
const TP_STATE_LOCKED = 3; // 临时禁用(用于用户登录连续错误n次)
|
||||
|
||||
var TP_USER_TYPE_LOCAL = 1;
|
||||
var TP_USER_TYPE_LDAP = 2;
|
||||
const TP_USER_TYPE_LOCAL = 1;
|
||||
const TP_USER_TYPE_LDAP = 2;
|
||||
|
||||
// =======================================================
|
||||
// 授权策略对象
|
||||
// =======================================================
|
||||
var TP_POLICY_OPERATOR = 0; // 授权(操作者:用户/用户组)
|
||||
var TP_POLICY_ASSET = 1; // 被授权(资产:主机/主机组/账号/账号组)
|
||||
const TP_POLICY_OPERATOR = 0; // 授权(操作者:用户/用户组)
|
||||
const TP_POLICY_ASSET = 1; // 被授权(资产:主机/主机组/账号/账号组)
|
||||
|
||||
// =======================================================
|
||||
// 授权策略方式
|
||||
// =======================================================
|
||||
var TP_POLICY_AUTH_UNKNOWN = 0; // 0=未知
|
||||
var TP_POLICY_AUTH_USER_ACC = 1; // 1=用户:账号
|
||||
var TP_POLICY_AUTH_USER_gACC = 2; // 2=用户:账号组
|
||||
var TP_POLICY_AUTH_USER_HOST = 3; // 3=用户:主机
|
||||
var TP_POLICY_AUTH_USER_gHOST = 4; // 4=用户:主机组
|
||||
var TP_POLICY_AUTH_gUSER_ACC = 5; // 5=用户组:账号
|
||||
var TP_POLICY_AUTH_gUSER_gACC = 6; // 6=用户组:账号组
|
||||
var TP_POLICY_AUTH_gUSER_HOST = 7; // 7=用户组:主机
|
||||
var TP_POLICY_AUTH_gUSER_gHOST = 8; // 8=用户组:主机组
|
||||
const TP_POLICY_AUTH_UNKNOWN = 0; // 0=未知
|
||||
const TP_POLICY_AUTH_USER_ACC = 1; // 1=用户:账号
|
||||
const TP_POLICY_AUTH_USER_gACC = 2; // 2=用户:账号组
|
||||
const TP_POLICY_AUTH_USER_HOST = 3; // 3=用户:主机
|
||||
const TP_POLICY_AUTH_USER_gHOST = 4; // 4=用户:主机组
|
||||
const TP_POLICY_AUTH_gUSER_ACC = 5; // 5=用户组:账号
|
||||
const TP_POLICY_AUTH_gUSER_gACC = 6; // 6=用户组:账号组
|
||||
const TP_POLICY_AUTH_gUSER_HOST = 7; // 7=用户组:主机
|
||||
const TP_POLICY_AUTH_gUSER_gHOST = 8; // 8=用户组:主机组
|
||||
|
||||
// =======================================================
|
||||
// 全局配置
|
||||
// =======================================================
|
||||
var TP_ASSIST_STARTUP_URLPROTO = 1; // 启用 url-protocol 功能
|
||||
const TP_ASSIST_STARTUP_URLPROTO = 1; // 启用 url-protocol 功能
|
||||
|
||||
// =======================================================
|
||||
// 授权标记
|
||||
// =======================================================
|
||||
var TP_FLAG_ALL = 0xFFFFFFFF;
|
||||
const TP_FLAG_ALL = 0xFFFFFFFF;
|
||||
// 会话记录相关
|
||||
var TP_FLAG_RECORD_REPLAY = 0x0001; // 允许记录历史(录像回放)
|
||||
var TP_FLAG_RECORD_REAL_TIME = 0x0002; // 允许实时监控
|
||||
const TP_FLAG_RECORD_REPLAY = 0x0001; // 允许记录历史(录像回放)
|
||||
const TP_FLAG_RECORD_REAL_TIME = 0x0002; // 允许实时监控
|
||||
// RDP相关
|
||||
var TP_FLAG_RDP_DESKTOP = 0x0001; // 0x1=允许远程桌面
|
||||
var TP_FLAG_RDP_CLIPBOARD = 0x0002; // 0x2=允许剪贴板
|
||||
var TP_FLAG_RDP_DISK = 0x0004; // 0x4=允许磁盘映射
|
||||
var TP_FLAG_RDP_APP = 0x0008; // 0x8=允许远程APP(尚未实现)
|
||||
var TP_FLAG_RDP_CONSOLE = 0x1000; // 0x1000=允许连接到管理员会话(RDP的console选项)
|
||||
const TP_FLAG_RDP_DESKTOP = 0x0001; // 0x1=允许远程桌面
|
||||
const TP_FLAG_RDP_CLIPBOARD = 0x0002; // 0x2=允许剪贴板
|
||||
const TP_FLAG_RDP_DISK = 0x0004; // 0x4=允许磁盘映射
|
||||
const TP_FLAG_RDP_APP = 0x0008; // 0x8=允许远程APP(尚未实现)
|
||||
const TP_FLAG_RDP_CONSOLE = 0x1000; // 0x1000=允许连接到管理员会话(RDP的console选项)
|
||||
// SSH相关
|
||||
var TP_FLAG_SSH_SHELL = 0x0001; // 0x1=允许SHELL
|
||||
var TP_FLAG_SSH_SFTP = 0x0002; // 0x2=允许SFTP
|
||||
var TP_FLAG_SSH_X11 = 0x0004; // 0x4=允许X11转发(尚未实现)
|
||||
var TP_FLAG_SSH_EXEC = 0x0008; // 0x8=允许exec执行远程命令(尚未实现)
|
||||
var TP_FLAG_SSH_TUNNEL = 0x0010; // 0x10=allow ssh tunnel. (not impl.)
|
||||
const TP_FLAG_SSH_SHELL = 0x0001; // 0x1=允许SHELL
|
||||
const TP_FLAG_SSH_SFTP = 0x0002; // 0x2=允许SFTP
|
||||
const TP_FLAG_SSH_X11 = 0x0004; // 0x4=允许X11转发(尚未实现)
|
||||
const TP_FLAG_SSH_EXEC = 0x0008; // 0x8=允许exec执行远程命令(尚未实现)
|
||||
const TP_FLAG_SSH_TUNNEL = 0x0010; // 0x10=allow ssh tunnel. (not impl.)
|
||||
|
||||
// ==========================================================================
|
||||
// 权限定义(因为权限是可以组合的,所以使用按位或的方式,目前最多能够支持32个权限粒度)
|
||||
// ==========================================================================
|
||||
var TP_PRIVILEGE_NONE = 0;
|
||||
var TP_PRIVILEGE_ALL = 0xFFFFFFFF;// # 具有所有权限(仅限系统管理员角色)
|
||||
const TP_PRIVILEGE_NONE = 0;
|
||||
const TP_PRIVILEGE_ALL = 0xFFFFFFFF;// # 具有所有权限(仅限系统管理员角色)
|
||||
|
||||
var TP_PRIVILEGE_LOGIN_WEB = 0x00000001;// # 允许登录WEB
|
||||
const TP_PRIVILEGE_LOGIN_WEB = 0x00000001;// # 允许登录WEB
|
||||
|
||||
var TP_PRIVILEGE_USER_CREATE = 0x00000002;// # 创建/编辑用户
|
||||
var TP_PRIVILEGE_USER_DELETE = 0x00000004;// # 删除用户
|
||||
var TP_PRIVILEGE_USER_LOCK = 0x00000008;// # 锁定/解锁用户
|
||||
var TP_PRIVILEGE_USER_GROUP = 0x00000010;// # 用户分组管理
|
||||
const TP_PRIVILEGE_USER_CREATE = 0x00000002;// # 创建/编辑用户
|
||||
const TP_PRIVILEGE_USER_DELETE = 0x00000004;// # 删除用户
|
||||
const TP_PRIVILEGE_USER_LOCK = 0x00000008;// # 锁定/解锁用户
|
||||
const TP_PRIVILEGE_USER_GROUP = 0x00000010;// # 用户分组管理
|
||||
|
||||
var TP_PRIVILEGE_ASSET_CREATE = 0x00000020;// # 创建/编辑资产
|
||||
var TP_PRIVILEGE_ASSET_DELETE = 0x00000040;// # 删除资产
|
||||
var TP_PRIVILEGE_ASSET_LOCK = 0x00000080;// # 锁定/解锁资产
|
||||
var TP_PRIVILEGE_ASSET_GROUP = 0x00000100;// # 资产分组管理
|
||||
const TP_PRIVILEGE_ASSET_CREATE = 0x00000020;// # 创建/编辑资产
|
||||
const TP_PRIVILEGE_ASSET_DELETE = 0x00000040;// # 删除资产
|
||||
const TP_PRIVILEGE_ASSET_LOCK = 0x00000080;// # 锁定/解锁资产
|
||||
const TP_PRIVILEGE_ASSET_GROUP = 0x00000100;// # 资产分组管理
|
||||
|
||||
var TP_PRIVILEGE_OPS = 0x00000200;// # 远程主机运维
|
||||
var TP_PRIVILEGE_ACCOUNT = 0x00000400;// # 远程主机账号管理(增删改查)
|
||||
var TP_PRIVILEGE_ACCOUNT_GROUP = 0x00000800;// # 远程主机账号分组管理
|
||||
var TP_PRIVILEGE_OPS_AUZ = 0x00001000;// # 远程主机运维授权管理
|
||||
var TP_PRIVILEGE_SESSION_BLOCK = 0x00002000;// # 阻断在线会话
|
||||
var TP_PRIVILEGE_SESSION_VIEW = 0x00004000;// # 查看在线会话
|
||||
const TP_PRIVILEGE_OPS = 0x00000200;// # 远程主机运维
|
||||
const TP_PRIVILEGE_ACCOUNT = 0x00000400;// # 远程主机账号管理(增删改查)
|
||||
const TP_PRIVILEGE_ACCOUNT_GROUP = 0x00000800;// # 远程主机账号分组管理
|
||||
const TP_PRIVILEGE_OPS_AUZ = 0x00001000;// # 远程主机运维授权管理
|
||||
const TP_PRIVILEGE_SESSION_BLOCK = 0x00002000;// # 阻断在线会话
|
||||
const TP_PRIVILEGE_SESSION_VIEW = 0x00004000;// # 查看在线会话
|
||||
|
||||
var TP_PRIVILEGE_AUDIT = 0x00008000;// # 审计(查看历史会话)
|
||||
var TP_PRIVILEGE_AUDIT_AUZ = 0x00010000;// # 审计策略授权管理
|
||||
//var TP_PRIVILEGE_AUDIT_SYSLOG = 0x00020000;// # 查看系统日志
|
||||
const TP_PRIVILEGE_AUDIT = 0x00008000;// # 审计(查看历史会话)
|
||||
const TP_PRIVILEGE_AUDIT_AUZ = 0x00010000;// # 审计策略授权管理
|
||||
//const TP_PRIVILEGE_AUDIT_SYSLOG = 0x00020000;// # 查看系统日志
|
||||
|
||||
var TP_PRIVILEGE_SYS_ROLE = 0x00040000;// # 角色管理
|
||||
var TP_PRIVILEGE_SYS_CONFIG = 0x00080000;// # 系统配置维护
|
||||
//var TP_PRIVILEGE_SYS_OPS_HISTORY = 0x00100000;// # 历史会话管理(例如删除历史会话、设定多长时间之前的历史会话自动删除等)
|
||||
var TP_PRIVILEGE_SYS_LOG = 0x00200000;// # 查看系统日志
|
||||
const TP_PRIVILEGE_SYS_ROLE = 0x00040000;// # 角色管理
|
||||
const TP_PRIVILEGE_SYS_CONFIG = 0x00080000;// # 系统配置维护
|
||||
//const TP_PRIVILEGE_SYS_OPS_HISTORY = 0x00100000;// # 历史会话管理(例如删除历史会话、设定多长时间之前的历史会话自动删除等)
|
||||
const TP_PRIVILEGE_SYS_LOG = 0x00200000;// # 查看系统日志
|
||||
|
||||
var TP_PRIVILEGES = [
|
||||
const TP_PRIVILEGES = [
|
||||
TP_PRIVILEGE_LOGIN_WEB,
|
||||
TP_PRIVILEGE_USER_CREATE,
|
||||
TP_PRIVILEGE_USER_DELETE,
|
||||
|
@ -182,78 +181,15 @@ var TP_PRIVILEGES = [
|
|||
TP_PRIVILEGE_SYS_LOG
|
||||
];
|
||||
|
||||
//========================================================
|
||||
// 错误值(请参考源代码/common/teleport/teleport_const.h)
|
||||
//========================================================
|
||||
var TPE_OK = 0;
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 通用错误值
|
||||
//-------------------------------------------------------
|
||||
var TPE_NEED_MORE_DATA = 1; // 需要更多数据(不一定是错误)
|
||||
|
||||
var TPE_NEED_LOGIN = 2;
|
||||
var TPE_PRIVILEGE = 3;
|
||||
|
||||
var TPE_NOT_IMPLEMENT = 7; // 尚未实现
|
||||
var TPE_EXISTS = 8;
|
||||
var TPE_NOT_EXISTS = 9;
|
||||
var TPE_NO_MORE_DATA = 10; // 没有更多的数据了(不一定是错误)
|
||||
var TPE_INCOMPATIBLE_VERSION = 11; // 版本不兼容
|
||||
|
||||
// 100~299是通用错误值
|
||||
|
||||
var TPE_FAILED = 100; // 内部错误
|
||||
var TPE_NETWORK = 101; // 网络错误
|
||||
var TPE_DATABASE = 102; // 数据库操作失败
|
||||
var TPE_EXPIRED = 103; // 数据/操作等已过期
|
||||
|
||||
// HTTP请求相关错误
|
||||
var TPE_HTTP_METHOD = 120; // 无效的请求方法(不是GET/POST等),或者错误的请求方法(例如需要POST,却使用GET方式请求)
|
||||
var TPE_HTTP_URL_ENCODE = 121; // URL编码错误(无法解码)
|
||||
|
||||
var TPE_UNKNOWN_CMD = 124; // 未知的命令
|
||||
var TPE_JSON_FORMAT = 125; // 错误的JSON格式(需要JSON格式数据,但是却无法按JSON格式解码)
|
||||
var TPE_PARAM = 126; // 参数错误
|
||||
var TPE_DATA = 127; // 数据错误
|
||||
|
||||
|
||||
var TPE_OPENFILE = 300; // 无法打开文件
|
||||
|
||||
var TPE_HTTP_404_NOT_FOUND = 404;
|
||||
|
||||
var TPE_CAPTCHA_EXPIRED = 10000;
|
||||
var TPE_CAPTCHA_MISMATCH = 10001;
|
||||
var TPE_OATH_MISMATCH = 10002;
|
||||
var TPE_SYS_MAINTENANCE = 10003;
|
||||
var TPE_OATH_ALREADY_BIND = 10004;
|
||||
|
||||
var TPE_USER_LOCKED = 10100;
|
||||
var TPE_USER_DISABLED = 10101;
|
||||
var TPE_USER_AUTH = 10102;
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 助手程序专用错误值
|
||||
//-------------------------------------------------------
|
||||
var TPE_NO_ASSIST = 100000; // 未能检测到助手程序
|
||||
var TPE_OLD_ASSIST = 100001; // 助手程序版本太低
|
||||
var TPE_START_CLIENT = 100002; // 无法启动客户端程序(无法创建进程)
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 核心服务专用错误值
|
||||
//-------------------------------------------------------
|
||||
var TPE_NO_CORE_SERVER = 200000; // 未能检测到核心服务
|
||||
|
||||
|
||||
// ==========================================================================
|
||||
// 数据库类型
|
||||
// ==========================================================================
|
||||
var DB_TYPE_UNKNOWN = 0;
|
||||
var DB_TYPE_SQLITE = 1;
|
||||
var DB_TYPE_MYSQL = 2;
|
||||
const DB_TYPE_UNKNOWN = 0;
|
||||
const DB_TYPE_SQLITE = 1;
|
||||
const DB_TYPE_MYSQL = 2;
|
||||
|
||||
var PAGING_SELECTOR = {
|
||||
const PAGING_SELECTOR = {
|
||||
// use_cookie: true,
|
||||
default_select: '25',
|
||||
selections: [
|
||||
|
@ -263,8 +199,75 @@ var PAGING_SELECTOR = {
|
|||
{name: "100", val: 100}]
|
||||
};
|
||||
|
||||
const ASSIST_WS_COMMAND_TYPE_REQUEST = 0;
|
||||
const ASSIST_WS_COMMAND_TYPE_RESPONSE = 1;
|
||||
|
||||
//========================================================
|
||||
// 错误值(请参考源代码/common/teleport/teleport_const.h)
|
||||
//========================================================
|
||||
const TPE_OK = 0;
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 通用错误值
|
||||
//-------------------------------------------------------
|
||||
const TPE_NEED_MORE_DATA = 1; // 需要更多数据(不一定是错误)
|
||||
|
||||
const TPE_NEED_LOGIN = 2;
|
||||
const TPE_PRIVILEGE = 3;
|
||||
|
||||
const TPE_NOT_IMPLEMENT = 7; // 尚未实现
|
||||
const TPE_EXISTS = 8;
|
||||
const TPE_NOT_EXISTS = 9;
|
||||
const TPE_NO_MORE_DATA = 10; // 没有更多的数据了(不一定是错误)
|
||||
const TPE_INCOMPATIBLE_VERSION = 11; // 版本不兼容
|
||||
|
||||
// 100~299是通用错误值
|
||||
|
||||
const TPE_FAILED = 100; // 内部错误
|
||||
const TPE_NETWORK = 101; // 网络错误
|
||||
const TPE_DATABASE = 102; // 数据库操作失败
|
||||
const TPE_EXPIRED = 103; // 数据/操作等已过期
|
||||
|
||||
// HTTP请求相关错误
|
||||
const TPE_HTTP_METHOD = 120; // 无效的请求方法(不是GET/POST等),或者错误的请求方法(例如需要POST,却使用GET方式请求)
|
||||
const TPE_HTTP_URL_ENCODE = 121; // URL编码错误(无法解码)
|
||||
|
||||
const TPE_UNKNOWN_CMD = 124; // 未知的命令
|
||||
const TPE_JSON_FORMAT = 125; // 错误的JSON格式(需要JSON格式数据,但是却无法按JSON格式解码)
|
||||
const TPE_PARAM = 126; // 参数错误
|
||||
const TPE_DATA = 127; // 数据错误
|
||||
|
||||
|
||||
const TPE_OPENFILE = 300; // 无法打开文件
|
||||
|
||||
const TPE_HTTP_404_NOT_FOUND = 404;
|
||||
|
||||
const TPE_CAPTCHA_EXPIRED = 10000;
|
||||
const TPE_CAPTCHA_MISMATCH = 10001;
|
||||
const TPE_OATH_MISMATCH = 10002;
|
||||
const TPE_SYS_MAINTENANCE = 10003;
|
||||
const TPE_OATH_ALREADY_BIND = 10004;
|
||||
|
||||
const TPE_USER_LOCKED = 10100;
|
||||
const TPE_USER_DISABLED = 10101;
|
||||
const TPE_USER_AUTH = 10102;
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 助手程序专用错误值
|
||||
//-------------------------------------------------------
|
||||
const TPE_NO_ASSIST = 100000; // 未能检测到助手程序
|
||||
const TPE_OLD_ASSIST = 100001; // 助手程序版本太低
|
||||
const TPE_START_CLIENT = 100002; // 无法启动客户端程序(无法创建进程)
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 核心服务专用错误值
|
||||
//-------------------------------------------------------
|
||||
const TPE_NO_CORE_SERVER = 200000; // 未能检测到核心服务
|
||||
|
||||
|
||||
function tp_error_msg(error_code, message) {
|
||||
var msg = '';
|
||||
let msg;
|
||||
switch (error_code) {
|
||||
case TPE_NEED_LOGIN:
|
||||
msg = '需要刷新页面,重新登录';
|
||||
|
@ -375,6 +378,6 @@ function tp_error_msg(error_code, message) {
|
|||
msg = '未知错误';
|
||||
break;
|
||||
}
|
||||
var ret_msg = message || msg;
|
||||
const ret_msg = message || msg;
|
||||
return ret_msg + ' (' + error_code + ')';
|
||||
}
|
||||
|
|
|
@ -29,8 +29,8 @@ if (!String.prototype.startsWith) {
|
|||
|
||||
if (!String.prototype.realLength) {
|
||||
String.prototype.realLength = function () {
|
||||
var _len = 0;
|
||||
for (var i = 0; i < this.length; i++) {
|
||||
let _len = 0;
|
||||
for (let i = 0; i < this.length; i++) {
|
||||
if (this.charCodeAt(i) > 255) _len += 2; else _len += 1;
|
||||
}
|
||||
return _len;
|
||||
|
@ -42,7 +42,7 @@ if (!String.prototype.realLength) {
|
|||
//===================================================
|
||||
// http://jsfiddle.net/ghvj4gy9/embedded/result,js/
|
||||
function tp_is_email(email) {
|
||||
//var re = /^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/;
|
||||
//let re = /^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/;
|
||||
let re = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i;
|
||||
return re.test(email);
|
||||
}
|
||||
|
@ -204,7 +204,7 @@ function tp_base64_encode(input) {
|
|||
return output;
|
||||
}
|
||||
|
||||
function tp_base64_to_binarray(data) {
|
||||
function tp_base64_to_bin(data) {
|
||||
let o1, o2, o3, h1, h2, h3, h4, bits, i = 0,
|
||||
ac = 0,
|
||||
tmp_arr = [];
|
||||
|
@ -297,7 +297,7 @@ function htmlEncode(_s) {
|
|||
///*2.用正则表达式实现html解码*/
|
||||
//function htmlDecode(_s) {
|
||||
// if (_s.length == 0) return "";
|
||||
// var s = str.replace(/&/g, "&");
|
||||
// let s = str.replace(/&/g, "&");
|
||||
// s = s.replace(/</g, "<");
|
||||
// s = s.replace(/>/g, ">");
|
||||
// s = s.replace(/ /g, " ");
|
||||
|
@ -360,3 +360,21 @@ function tp_check_strong_password(p) {
|
|||
|
||||
return !!((s & 1) && (s & 2) && (s & 4));
|
||||
}
|
||||
|
||||
// 简单判断操作系统
|
||||
function tp_get_os_type() {
|
||||
let p = navigator.platform;
|
||||
console.log('navigator.platform:', p);
|
||||
let isWin = (p === "Win32") || (p === "Windows");
|
||||
let isMac = (p === "Mac68K") || (p === "MacPPC") || (p === "Macintosh") || (p === "MacIntel");
|
||||
if (isMac)
|
||||
return "macos";
|
||||
let isUnix = (p === "X11") && !isWin;
|
||||
let isLinux = (String(p).indexOf("Linux") > -1);
|
||||
if (isLinux || isUnix)
|
||||
return "linux";
|
||||
if (isWin)
|
||||
return 'windows'
|
||||
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ $app.create_controls = function (cb_stack) {
|
|||
//-------------------------------
|
||||
// 用户列表表格
|
||||
//-------------------------------
|
||||
var table_users_options = {
|
||||
let table_users_options = {
|
||||
dom_id: 'table-user-list',
|
||||
data_source: {
|
||||
type: 'ajax-post',
|
||||
|
@ -166,7 +166,7 @@ $app.create_controls = function (cb_stack) {
|
|||
$app.dom.dlg_import_user.modal({backdrop: 'static'});
|
||||
});
|
||||
$app.dom.chkbox_user_list_select_all.click(function () {
|
||||
var _objects = $('#' + $app.table_users.dom_id + ' tbody').find('[data-check-box]');
|
||||
let _objects = $('#' + $app.table_users.dom_id + ' tbody').find('[data-check-box]');
|
||||
if ($(this).is(':checked')) {
|
||||
$.each(_objects, function (i, _obj) {
|
||||
$(_obj).prop('checked', true);
|
||||
|
@ -206,13 +206,13 @@ $app.create_controls = function (cb_stack) {
|
|||
$app.dom.btn_unlock_user.click($app.on_btn_unlock_user_click);
|
||||
$app.dom.btn_remove_user.click($app.on_btn_remove_user_click);
|
||||
|
||||
var html = [];
|
||||
let html = [];
|
||||
$.each($app.role_list, function (i, role) {
|
||||
html.push('<li><a href="javascript:;" data-tp-selector="' + role.id + '" data-name="' + role.name + '"><i class="fa fa-caret-right fa-fw"></i> ' + role.name + '</a></li>');
|
||||
});
|
||||
$app.dom.role_list_for_set.append($(html.join('')));
|
||||
$app.dom.role_list_for_set.find('a[data-tp-selector]').click(function () {
|
||||
var obj = $(this);
|
||||
let obj = $(this);
|
||||
$app.set_selected_to_role(parseInt(obj.attr('data-tp-selector')), obj.attr('data-name'));
|
||||
});
|
||||
|
||||
|
@ -226,8 +226,8 @@ $app.on_table_users_cell_created = function (tbl, row_id, col_key, cell_obj) {
|
|||
});
|
||||
} else if (col_key === 'action') {
|
||||
cell_obj.find('[data-action]').click(function () {
|
||||
var user = $app.table_users.get_row(row_id);
|
||||
var action = $(this).attr('data-action');
|
||||
let user = $app.table_users.get_row(row_id);
|
||||
let action = $(this).attr('data-action');
|
||||
if (action === 'edit') {
|
||||
$app.dlg_edit_user.show_edit(row_id);
|
||||
} else if (action === 'reset-password') {
|
||||
|
@ -253,8 +253,8 @@ $app.on_table_users_cell_created = function (tbl, row_id, col_key, cell_obj) {
|
|||
};
|
||||
|
||||
$app.check_user_list_all_selected = function (cb_stack) {
|
||||
var _all_checked = true;
|
||||
var _objs = $('#' + $app.table_users.dom_id + ' tbody').find('[data-check-box]');
|
||||
let _all_checked = true;
|
||||
let _objs = $('#' + $app.table_users.dom_id + ' tbody').find('[data-check-box]');
|
||||
if (_objs.length === 0) {
|
||||
_all_checked = false;
|
||||
} else {
|
||||
|
@ -278,12 +278,12 @@ $app.check_user_list_all_selected = function (cb_stack) {
|
|||
|
||||
$app.on_table_users_render_created = function (render) {
|
||||
render.filter_role = function (header, title, col) {
|
||||
var _ret = ['<div class="tp-table-filter tp-table-filter-' + col.cell_align + '">'];
|
||||
let _ret = ['<div class="tp-table-filter tp-table-filter-' + col.cell_align + '">'];
|
||||
_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('role');
|
||||
let filter_ctrl = header._table_ctrl.get_filter_ctrl('role');
|
||||
_ret.push(filter_ctrl.render());
|
||||
|
||||
_ret.push('</div></div>');
|
||||
|
@ -292,12 +292,12 @@ $app.on_table_users_render_created = function (render) {
|
|||
};
|
||||
|
||||
render.filter_type = function (header, title, col) {
|
||||
var _ret = ['<div class="tp-table-filter tp-table-filter-' + col.cell_align + '">'];
|
||||
let _ret = ['<div class="tp-table-filter tp-table-filter-' + col.cell_align + '">'];
|
||||
_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('type');
|
||||
let filter_ctrl = header._table_ctrl.get_filter_ctrl('type');
|
||||
_ret.push(filter_ctrl.render());
|
||||
|
||||
_ret.push('</div></div>');
|
||||
|
@ -306,12 +306,12 @@ $app.on_table_users_render_created = function (render) {
|
|||
};
|
||||
|
||||
render.filter_state = function (header, title, col) {
|
||||
var _ret = ['<div class="tp-table-filter tp-table-filter-' + col.cell_align + '">'];
|
||||
let _ret = ['<div class="tp-table-filter tp-table-filter-' + col.cell_align + '">'];
|
||||
_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('state');
|
||||
let filter_ctrl = header._table_ctrl.get_filter_ctrl('state');
|
||||
_ret.push(filter_ctrl.render());
|
||||
|
||||
_ret.push('</div></div>');
|
||||
|
@ -320,12 +320,12 @@ $app.on_table_users_render_created = function (render) {
|
|||
};
|
||||
|
||||
render.filter_search = function (header, title, col) {
|
||||
var _ret = ['<div class="tp-table-filter tp-table-filter-input">'];
|
||||
let _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');
|
||||
let filter_ctrl = header._table_ctrl.get_filter_ctrl('search');
|
||||
_ret.push(filter_ctrl.render());
|
||||
|
||||
_ret.push('</div></div>');
|
||||
|
@ -340,7 +340,7 @@ $app.on_table_users_render_created = function (render) {
|
|||
};
|
||||
|
||||
render.user_info = function (row_id, fields) {
|
||||
var ret = [];
|
||||
let ret = [];
|
||||
ret.push('<a href="javascript:;" onclick="$app.show_user_info(' + row_id + ');" class="user-username">');
|
||||
ret.push(fields.username);
|
||||
ret.push('</a><span class="user-surname">');
|
||||
|
@ -363,7 +363,7 @@ $app.on_table_users_render_created = function (render) {
|
|||
};
|
||||
|
||||
render.role = function (row_id, fields) {
|
||||
for (var i = 0; i < $app.role_list.length; ++i) {
|
||||
for (let i = 0; i < $app.role_list.length; ++i) {
|
||||
if ($app.role_list[i].id === fields.role_id)
|
||||
return $app.role_list[i].name;
|
||||
}
|
||||
|
@ -371,9 +371,10 @@ $app.on_table_users_render_created = function (render) {
|
|||
};
|
||||
|
||||
render.user_state = function (row_id, fields) {
|
||||
var _style, _state;
|
||||
let _style, _state;
|
||||
|
||||
for (var i = 0; i < $app.obj_states.length; ++i) {
|
||||
let i = 0;
|
||||
for (i = 0; i < $app.obj_states.length; ++i) {
|
||||
if ($app.obj_states[i].id === fields.state) {
|
||||
_style = $app.obj_states[i].style;
|
||||
_state = $app.obj_states[i].name;
|
||||
|
@ -392,14 +393,14 @@ $app.on_table_users_render_created = function (render) {
|
|||
if (fields.id === 1) {
|
||||
return '';
|
||||
}
|
||||
var h = [];
|
||||
let h = [];
|
||||
h.push('<div class="btn-group btn-group-sm">');
|
||||
h.push('<button type="button" class="btn btn-no-border dropdown-toggle" data-toggle="dropdown">');
|
||||
h.push('<span data-selected-action>操作</span> <i class="fa fa-caret-right"></i></button>');
|
||||
h.push('<ul class="dropdown-menu dropdown-menu-right dropdown-menu-sm">');
|
||||
h.push('<li><a href="javascript:;" data-action="edit"><i class="fa fa-edit fa-fw"></i> 编辑</a></li>');
|
||||
|
||||
var class_lock = '', class_unlock = '';
|
||||
let class_lock = '', class_unlock = '';
|
||||
if (fields.state === TP_STATE_NORMAL) {
|
||||
class_unlock = ' class="disabled"';
|
||||
} else {
|
||||
|
@ -411,7 +412,7 @@ $app.on_table_users_render_created = function (render) {
|
|||
|
||||
h.push('<li role="separator" class="divider"></li>');
|
||||
|
||||
var class_user_type = '';
|
||||
let class_user_type = '';
|
||||
if (fields.user_type === TP_USER_TYPE_LDAP) {
|
||||
class_user_type = ' class="disabled"';
|
||||
} else {
|
||||
|
@ -438,7 +439,7 @@ $app.on_table_users_header_created = function (header) {
|
|||
});
|
||||
|
||||
// // TODO: 当过滤器不是默认值时,让“重置过滤器按钮”有呼吸效果,避免用户混淆 - 实验性质
|
||||
// var t1 = function(){
|
||||
// let t1 = function(){
|
||||
// $app.dom.btn_table_users_reset_filter.fadeTo(1000, 1.0, function(){
|
||||
// $app.dom.btn_table_users_reset_filter.fadeTo(1000, 0.2, t1);
|
||||
// });
|
||||
|
@ -454,18 +455,18 @@ $app.on_table_users_header_created = function (header) {
|
|||
|
||||
$app.on_btn_select_file_click = function () {
|
||||
|
||||
var html = '<input id="file-selector" type="file" name="csvfile" accept=".csv,text/csv,text/comma-separated-values" class="hidden" value="" style="display: none;"/>';
|
||||
let html = '<input id="file-selector" type="file" name="csvfile" accept=".csv,text/csv,text/comma-separated-values" class="hidden" value="" style="display: none;"/>';
|
||||
$('body').after($(html));
|
||||
var btn_file_selector = $("#file-selector");
|
||||
let btn_file_selector = $("#file-selector");
|
||||
|
||||
btn_file_selector.change(function () {
|
||||
$app.dom.upload_file_message.hide();
|
||||
// var dom_file_name = $('#upload-file-name');
|
||||
// let dom_file_name = $('#upload-file-name');
|
||||
|
||||
// console.log(btn_file_selector[0]);
|
||||
// console.log(btn_file_selector[0].files);
|
||||
|
||||
var file = null;
|
||||
let file = null;
|
||||
if (btn_file_selector[0].files && btn_file_selector[0].files[0]) {
|
||||
file = btn_file_selector[0].files[0];
|
||||
} else if (btn_file_selector[0].files && btn_file_selector[0].files.item(0)) {
|
||||
|
@ -479,7 +480,7 @@ $app.on_btn_select_file_click = function () {
|
|||
return;
|
||||
}
|
||||
|
||||
var _ext = file.name.substring(file.name.lastIndexOf('.')).toLocaleLowerCase();
|
||||
let _ext = file.name.substring(file.name.lastIndexOf('.')).toLocaleLowerCase();
|
||||
if (_ext !== '.csv') {
|
||||
$app.dom.upload_file_info.html('抱歉,仅支持导入 csv 格式的文件!');
|
||||
return;
|
||||
|
@ -490,7 +491,7 @@ $app.on_btn_select_file_click = function () {
|
|||
return;
|
||||
}
|
||||
|
||||
var fileInfo = '';
|
||||
let fileInfo = '';
|
||||
fileInfo += file.name;
|
||||
fileInfo += '<br/>';
|
||||
fileInfo += tp_size2str(file.size, 2);
|
||||
|
@ -512,7 +513,7 @@ $app.on_btn_do_upload_click = function () {
|
|||
.html('<i class="fa fa-cog fa-spin fa-fw"></i> 正在导入,请稍候...')
|
||||
.show();
|
||||
|
||||
var param = {};
|
||||
let param = {};
|
||||
$.ajaxFileUpload({
|
||||
url: "/user/upload-import",// 需要链接到服务器地址
|
||||
fileElementId: "file-selector", // 文件选择框的id属性
|
||||
|
@ -523,7 +524,7 @@ $app.on_btn_do_upload_click = function () {
|
|||
success: function (data) {
|
||||
$('#file-selector').remove();
|
||||
|
||||
var ret = JSON.parse(data);
|
||||
let ret = JSON.parse(data);
|
||||
|
||||
// console.log('import ret', ret);
|
||||
|
||||
|
@ -535,10 +536,10 @@ $app.on_btn_do_upload_click = function () {
|
|||
|
||||
$app.table_users.load_data();
|
||||
} else {
|
||||
var err_msg = ['<i class="far fa-times-circle fa-fw"></i> 用户导入失败:' + ret.message];
|
||||
let err_msg = ['<i class="far fa-times-circle fa-fw"></i> 用户导入失败:' + ret.message];
|
||||
if (!_.isUndefined(ret.data)) {
|
||||
err_msg.push('<div style="max-height:280px;overflow:auto;margin-left:20px;">');
|
||||
var err_lines = [];
|
||||
let err_lines = [];
|
||||
$.each(ret.data, function (i, item) {
|
||||
err_lines.push('第' + item.line + '行:' + item.error);
|
||||
});
|
||||
|
@ -566,11 +567,11 @@ $app.show_user_info = function (row_id) {
|
|||
};
|
||||
|
||||
$app.get_selected_user = function () {
|
||||
var items = [];
|
||||
var _objs = $('#' + $app.table_users.dom_id + ' tbody tr td input[data-check-box]');
|
||||
let items = [];
|
||||
let _objs = $('#' + $app.table_users.dom_id + ' tbody tr td input[data-check-box]');
|
||||
$.each(_objs, function (i, _obj) {
|
||||
if ($(_obj).is(':checked')) {
|
||||
var _row_data = $app.table_users.get_row(_obj);
|
||||
let _row_data = $app.table_users.get_row(_obj);
|
||||
items.push(_row_data.id);
|
||||
}
|
||||
});
|
||||
|
@ -578,7 +579,7 @@ $app.get_selected_user = function () {
|
|||
};
|
||||
|
||||
$app.on_btn_set_role_click = function () {
|
||||
var items = $app.get_selected_user();
|
||||
let items = $app.get_selected_user();
|
||||
if (items.length === 0) {
|
||||
$tp.notify_error('请先选择用户!');
|
||||
return false;
|
||||
|
@ -586,12 +587,12 @@ $app.on_btn_set_role_click = function () {
|
|||
};
|
||||
|
||||
$app.set_selected_to_role = function (role_id, role_name) {
|
||||
var users = $app.get_selected_user($app.table_users);
|
||||
let users = $app.get_selected_user($app.table_users);
|
||||
if (users.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var _fn_sure = function (cb_stack, cb_args) {
|
||||
let _fn_sure = function (cb_stack, cb_args) {
|
||||
$tp.ajax_post_json('/user/set-role', {users: users, role_id: role_id},
|
||||
function (ret) {
|
||||
if (ret.code === TPE_OK) {
|
||||
|
@ -611,7 +612,7 @@ $app.set_selected_to_role = function (role_id, role_name) {
|
|||
);
|
||||
};
|
||||
|
||||
var cb_stack = CALLBACK_STACK.create();
|
||||
let cb_stack = CALLBACK_STACK.create();
|
||||
$tp.dlg_confirm(cb_stack, {
|
||||
msg: '<p>您确定要将选定的 <strong>' + users.length + '个</strong> 用户设置为 <strong>' + role_name + '</strong> 角色吗?</p>',
|
||||
fn_yes: _fn_sure
|
||||
|
@ -654,7 +655,7 @@ $app._lock_users = function (users) {
|
|||
};
|
||||
|
||||
$app.on_btn_lock_user_click = function () {
|
||||
var users = $app.get_selected_user($app.table_users);
|
||||
let users = $app.get_selected_user($app.table_users);
|
||||
if (users.length === 0) {
|
||||
$tp.notify_error('请选择要禁用的用户!');
|
||||
return;
|
||||
|
@ -683,7 +684,7 @@ $app._unlock_users = function (users) {
|
|||
};
|
||||
|
||||
$app.on_btn_unlock_user_click = function () {
|
||||
var users = $app.get_selected_user($app.table_users);
|
||||
let users = $app.get_selected_user($app.table_users);
|
||||
if (users.length === 0) {
|
||||
$tp.notify_error('请选择要解禁的用户!');
|
||||
return;
|
||||
|
@ -693,7 +694,7 @@ $app.on_btn_unlock_user_click = function () {
|
|||
};
|
||||
|
||||
$app._remove_users = function (users) {
|
||||
var _fn_sure = function (cb_stack, cb_args) {
|
||||
let _fn_sure = function (cb_stack, cb_args) {
|
||||
$tp.ajax_post_json('/user/update-users', {action: 'remove', users: users},
|
||||
function (ret) {
|
||||
if (ret.code === TPE_OK) {
|
||||
|
@ -713,7 +714,7 @@ $app._remove_users = function (users) {
|
|||
);
|
||||
};
|
||||
|
||||
var cb_stack = CALLBACK_STACK.create();
|
||||
let 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>' + users.length + '个</strong> 用户账号吗?</p>',
|
||||
fn_yes: _fn_sure
|
||||
|
@ -721,7 +722,7 @@ $app._remove_users = function (users) {
|
|||
};
|
||||
|
||||
$app.on_btn_remove_user_click = function () {
|
||||
var users = $app.get_selected_user($app.table_users);
|
||||
let users = $app.get_selected_user($app.table_users);
|
||||
if (users.length === 0) {
|
||||
$tp.notify_error('请选择要删除的用户!');
|
||||
return;
|
||||
|
@ -731,7 +732,7 @@ $app.on_btn_remove_user_click = function () {
|
|||
};
|
||||
|
||||
$app.create_dlg_edit_user = function () {
|
||||
var dlg = {};
|
||||
let dlg = {};
|
||||
dlg.dom_id = 'dlg-edit-user';
|
||||
dlg.field_id = -1; // 用户id(仅编辑模式)
|
||||
dlg.field_role = -1;
|
||||
|
@ -770,8 +771,9 @@ $app.create_dlg_edit_user = function () {
|
|||
};
|
||||
|
||||
dlg.init = function (cb_stack) {
|
||||
console.log('init');
|
||||
// 创建角色选择框
|
||||
var _ret = [];
|
||||
let _ret = [];
|
||||
_ret.push('<button type="button" class="btn btn-sm dropdown-toggle" data-toggle="dropdown">');
|
||||
_ret.push('<span data-selected-role>选择角色</span> <i class="fa fa-caret-right"></i></button>');
|
||||
_ret.push('<ul class="dropdown-menu dropdown-menu-sm">');
|
||||
|
@ -786,11 +788,11 @@ $app.create_dlg_edit_user = function () {
|
|||
|
||||
// 绑定角色选择框事件
|
||||
$('#' + dlg.dom_id + ' li a[data-tp-selector]').click(function () {
|
||||
var select = parseInt($(this).attr('data-tp-selector'));
|
||||
let select = parseInt($(this).attr('data-tp-selector'));
|
||||
if (dlg.field_role === select)
|
||||
return;
|
||||
|
||||
var name = $app.role_id2name(select);
|
||||
let name = $app.role_id2name(select);
|
||||
if (_.isUndefined(name)) {
|
||||
name = '选择角色';
|
||||
dlg.field_role = -1;
|
||||
|
@ -806,19 +808,28 @@ $app.create_dlg_edit_user = function () {
|
|||
dlg.dom.edit_valid_from.datetimepicker({format: "yyyy-mm-dd hh:ii", autoclose: true, todayHighlight: true, todayBtn: true, language: "zh-CN"});
|
||||
dlg.dom.edit_valid_to.datetimepicker({format: "yyyy-mm-dd hh:ii", autoclose: true, todayHighlight: true, todayBtn: true, language: "zh-CN"});
|
||||
|
||||
dlg.dom.edit_valid_from.on('changeDate', function (ev) {
|
||||
var start_time = dlg.dom.edit_valid_from.find('input').val();
|
||||
dlg._on_valid_time_changed = function () {
|
||||
let start_time = dlg.dom.edit_valid_from.find('input').val();
|
||||
let end_time = dlg.dom.edit_valid_to.find('input').val();
|
||||
console.log('[' + start_time + '],[' + end_time + ']');
|
||||
|
||||
if (start_time === '')
|
||||
dlg.dom.edit_valid_to.datetimepicker('setStartDate', '1000-01-01 00:00');
|
||||
dlg.dom.edit_valid_to.datetimepicker('setStartDate', '1970-01-01 00:00');
|
||||
else
|
||||
dlg.dom.edit_valid_to.datetimepicker('setStartDate', start_time);
|
||||
|
||||
if (end_time === '') {
|
||||
console.log('end-time: [' + end_time + ']');
|
||||
|
||||
dlg.dom.edit_valid_from.datetimepicker('setEndDate', '9999-12-30 23:59');
|
||||
} else
|
||||
dlg.dom.edit_valid_from.datetimepicker('setEndDate', end_time);
|
||||
};
|
||||
dlg.dom.edit_valid_from.on('changeDate', function (ev) {
|
||||
dlg._on_valid_time_changed();
|
||||
});
|
||||
dlg.dom.edit_valid_to.on('changeDate', function (ev) {
|
||||
var end_time = dlg.dom.edit_valid_to.find('input').val();
|
||||
if (end_time === '')
|
||||
dlg.dom.edit_valid_from.datetimepicker('setEndDate', '9999-12-12 00:00');
|
||||
else
|
||||
dlg.dom.edit_valid_from.datetimepicker('setEndDate', end_time);
|
||||
dlg._on_valid_time_changed();
|
||||
});
|
||||
|
||||
dlg.dom.btn_auth_use_sys_config.click(function () {
|
||||
|
@ -859,7 +870,7 @@ $app.create_dlg_edit_user = function () {
|
|||
// dlg.dom.btn_auth_username_oath.removeClass('tp-editable tp-selected');
|
||||
dlg.dom.btn_auth_username_password_oath.removeClass('tp-editable tp-selected');
|
||||
|
||||
var auth_type = $app.options.sys_cfg.login.auth;
|
||||
let auth_type = $app.options.sys_cfg.login.auth;
|
||||
// if (auth_type & TP_LOGIN_AUTH_USERNAME_PASSWORD)
|
||||
// dlg.dom.btn_auth_username_password.addClass('tp-selected');
|
||||
if (auth_type & TP_LOGIN_AUTH_USERNAME_PASSWORD_CAPTCHA)
|
||||
|
@ -887,7 +898,8 @@ $app.create_dlg_edit_user = function () {
|
|||
};
|
||||
|
||||
dlg.init_fields = function (user) {
|
||||
var role_name = '选择角色';
|
||||
console.log('init_fields');
|
||||
let role_name = '选择角色';
|
||||
dlg.field_role = -1;
|
||||
dlg.field_auth_type = 0;
|
||||
|
||||
|
@ -897,6 +909,8 @@ $app.create_dlg_edit_user = function () {
|
|||
// dlg.dom.btn_auth_username_oath.removeClass('tp-selected');
|
||||
// dlg.dom.btn_auth_username_password_oath.removeClass('tp-selected');
|
||||
|
||||
let time_now = tp_timestamp_sec();
|
||||
|
||||
if (_.isUndefined(user)) {
|
||||
dlg.dom.dlg_title.html('创建用户账号');
|
||||
dlg.field_id = -1;
|
||||
|
@ -910,12 +924,14 @@ $app.create_dlg_edit_user = function () {
|
|||
dlg.dom.edit_desc.val('');
|
||||
dlg.dom.edit_valid_from.find('input').val('');
|
||||
dlg.dom.edit_valid_to.find('input').val('');
|
||||
dlg.dom.edit_valid_to.datetimepicker('setStartDate', null);
|
||||
dlg.dom.edit_valid_to.datetimepicker('setEndDate', null);
|
||||
} else {
|
||||
dlg.field_id = user.id;
|
||||
dlg.field_auth_type = user.auth_type;
|
||||
dlg.dom.dlg_title.html('编辑:' + user.surname);
|
||||
|
||||
var _name = $app.role_id2name(user.role_id);
|
||||
let _name = $app.role_id2name(user.role_id);
|
||||
if (!_.isUndefined(_name)) {
|
||||
role_name = _name;
|
||||
dlg.field_role = user.role_id;
|
||||
|
@ -930,17 +946,17 @@ $app.create_dlg_edit_user = function () {
|
|||
dlg.dom.edit_desc.val(user.desc);
|
||||
if (user.valid_from === 0) {
|
||||
dlg.dom.edit_valid_from.find('input').val('');
|
||||
dlg.dom.edit_valid_to.datetimepicker('setStartDate', '9999-12-12 00:00');
|
||||
dlg.dom.edit_valid_to.datetimepicker('setStartDate', '1970-01-01 00:00');
|
||||
} else {
|
||||
var start_time = tp_format_datetime(user.valid_from, 'yyyy-MM-dd HH:mm');
|
||||
let start_time = tp_format_datetime(user.valid_from, 'yyyy-MM-dd HH:mm');
|
||||
dlg.dom.edit_valid_from.find('input').val(start_time);
|
||||
dlg.dom.edit_valid_to.datetimepicker('setStartDate', start_time);
|
||||
}
|
||||
if (user.valid_to === 0) {
|
||||
dlg.dom.edit_valid_to.find('input').val('');
|
||||
dlg.dom.edit_valid_from.datetimepicker('setEndDate', '1000-01-01 00:00');
|
||||
dlg.dom.edit_valid_from.datetimepicker('setEndDate', '9999-12-30 23:59');
|
||||
} else {
|
||||
var end_time = tp_format_datetime(user.valid_to, 'yyyy-MM-dd HH:mm');
|
||||
let end_time = tp_format_datetime(user.valid_to, 'yyyy-MM-dd HH:mm');
|
||||
dlg.dom.edit_valid_to.find('input').val(end_time);
|
||||
dlg.dom.edit_valid_from.datetimepicker('setEndDate', end_time);
|
||||
}
|
||||
|
@ -951,7 +967,7 @@ $app.create_dlg_edit_user = function () {
|
|||
dlg._use_sys_auth_config(true);
|
||||
} else {
|
||||
dlg._use_sys_auth_config(false);
|
||||
var auth_type = dlg.field_auth_type;
|
||||
let auth_type = dlg.field_auth_type;
|
||||
// if (auth_type & TP_LOGIN_AUTH_USERNAME_PASSWORD)
|
||||
// dlg.dom.btn_auth_username_password.addClass('tp-selected');
|
||||
if (auth_type & TP_LOGIN_AUTH_USERNAME_PASSWORD_CAPTCHA)
|
||||
|
@ -969,7 +985,7 @@ $app.create_dlg_edit_user = function () {
|
|||
};
|
||||
|
||||
dlg.show_edit = function (row_id) {
|
||||
var user = $app.table_users.get_row(row_id);
|
||||
let user = $app.table_users.get_row(row_id);
|
||||
// console.log(user);
|
||||
dlg.init_fields(user);
|
||||
dlg.dom.dialog.modal({backdrop: 'static'});
|
||||
|
@ -1029,8 +1045,8 @@ $app.create_dlg_edit_user = function () {
|
|||
if (!dlg.check_input())
|
||||
return;
|
||||
|
||||
var action = (dlg.field_id === -1) ? '创建' : '更新';
|
||||
var timeout = (dlg.field_id === -1) ? 60000 : 30000;
|
||||
let action = (dlg.field_id === -1) ? '创建' : '更新';
|
||||
let timeout = (dlg.field_id === -1) ? 60000 : 30000;
|
||||
|
||||
// 如果id为-1表示创建,否则表示更新
|
||||
$tp.ajax_post_json('/user/update-user', {
|
||||
|
@ -1071,7 +1087,7 @@ $app.create_dlg_edit_user = function () {
|
|||
};
|
||||
|
||||
$app.create_dlg_user_info = function () {
|
||||
var dlg = {};
|
||||
let dlg = {};
|
||||
dlg.dom_id = 'dlg-user-info';
|
||||
dlg.row_id = -1;
|
||||
dlg.need_edit = false;
|
||||
|
@ -1102,7 +1118,7 @@ $app.create_dlg_user_info = function () {
|
|||
dlg.row_id = row_id;
|
||||
dlg.need_edit = false;
|
||||
|
||||
var _row_data = $app.table_users.get_row(dlg.row_id);
|
||||
let _row_data = $app.table_users.get_row(dlg.row_id);
|
||||
|
||||
// 表格加载时,是不会读取用户的 desc 字段的,因此可以判断此用户是否已经读取过详细信息了
|
||||
if (_.isUndefined(_row_data.desc)) {
|
||||
|
@ -1129,16 +1145,18 @@ $app.create_dlg_user_info = function () {
|
|||
// 更新对话框中显示的信息
|
||||
dlg.dom.dlg_title.html('<i class="far fa-id-card fa-fw"></i> ' + user.surname);
|
||||
|
||||
var info = [];
|
||||
let info = [];
|
||||
|
||||
var not_set = '<span class="label label-sm label-ignore">未设置</span>';
|
||||
var mobile = (user.mobile.length === 0) ? not_set : user.mobile;
|
||||
var qq = (user.qq.length === 0) ? not_set : user.qq;
|
||||
var wechat = (user.wechat.length === 0) ? not_set : user.wechat;
|
||||
var desc = (user.desc.length === 0) ? not_set : user.desc;
|
||||
let not_set = '<span class="label label-sm label-ignore">未设置</span>';
|
||||
let surname = (_.isUndefined(user.surname) || (user.surname.length === 0)) ? not_set : user.surname;
|
||||
let email = (_.isUndefined(user.email) || (user.email.length === 0)) ? not_set : user.email;
|
||||
let mobile = (_.isUndefined(user.mobile) || (user.mobile.length === 0)) ? not_set : user.mobile;
|
||||
let qq = (_.isUndefined(user.qq) || (user.qq.length === 0)) ? not_set : user.qq;
|
||||
let wechat = (_.isUndefined(user.wechat) || (user.wechat.length === 0)) ? not_set : user.wechat;
|
||||
let desc = (_.isUndefined(user.desc) || (user.desc.length === 0)) ? not_set : user.desc;
|
||||
info.push('<tr><td class="key">账号:</td><td class="value">' + user.username + '</td></tr>');
|
||||
info.push('<tr><td class="key">姓名:</td><td class="value">' + user.surname + '</td></tr>');
|
||||
info.push('<tr><td class="key">邮箱:</td><td class="value">' + user.email + '</td></tr>');
|
||||
info.push('<tr><td class="key">姓名:</td><td class="value">' + surname + '</td></tr>');
|
||||
info.push('<tr><td class="key">邮箱:</td><td class="value">' + email + '</td></tr>');
|
||||
info.push('<tr><td class="key">电话:</td><td class="value">' + mobile + '</td></tr>');
|
||||
info.push('<tr><td class="key">QQ:</td><td class="value">' + qq + '</td></tr>');
|
||||
info.push('<tr><td class="key">微信:</td><td class="value">' + wechat + '</td></tr>');
|
||||
|
@ -1153,7 +1171,7 @@ $app.create_dlg_user_info = function () {
|
|||
};
|
||||
|
||||
$app.create_dlg_reset_password = function () {
|
||||
var dlg = {};
|
||||
let dlg = {};
|
||||
dlg.dom_id = 'dlg-reset-password';
|
||||
dlg.field_id = -1;
|
||||
dlg.field_email = '';
|
||||
|
@ -1221,7 +1239,7 @@ $app.create_dlg_reset_password = function () {
|
|||
};
|
||||
|
||||
dlg.show_edit = function (row_id) {
|
||||
var user = $app.table_users.get_row(row_id);
|
||||
let user = $app.table_users.get_row(row_id);
|
||||
dlg.init_fields(user);
|
||||
dlg.dom.dialog.modal({backdrop: 'static'});
|
||||
};
|
||||
|
@ -1282,7 +1300,7 @@ $app.create_dlg_reset_password = function () {
|
|||
};
|
||||
|
||||
$app.create_dlg_ldap_config = function () {
|
||||
var dlg = {};
|
||||
let dlg = {};
|
||||
dlg.dom_id = 'dlg-ldap-config';
|
||||
dlg.mode = 'set'; // edit or set
|
||||
dlg.ldap_config = {
|
||||
|
@ -1401,7 +1419,7 @@ $app.create_dlg_ldap_config = function () {
|
|||
$tp.notify_error('请正确填写LDAP主机端口!');
|
||||
return false;
|
||||
} else {
|
||||
var _port = parseInt(dlg.ldap_config.port);
|
||||
let _port = parseInt(dlg.ldap_config.port);
|
||||
if (_port <= 0 || _port >= 65535) {
|
||||
dlg.dom.port.focus();
|
||||
$tp.notify_error('请正确填写LDAP主机端口!');
|
||||
|
@ -1539,7 +1557,7 @@ $app.create_dlg_ldap_config = function () {
|
|||
};
|
||||
|
||||
$app.create_dlg_ldap_list_attr_result = function () {
|
||||
var dlg = {};
|
||||
let dlg = {};
|
||||
dlg.dom_id = 'dlg-ldap-list-attr-result';
|
||||
|
||||
dlg.dom = {
|
||||
|
@ -1554,9 +1572,9 @@ $app.create_dlg_ldap_list_attr_result = function () {
|
|||
dlg.show = function (data) {
|
||||
dlg.dom.msg_ret.html('');
|
||||
|
||||
var h = [];
|
||||
let h = [];
|
||||
|
||||
var attr_name;
|
||||
let attr_name;
|
||||
for (attr_name in data) {
|
||||
h.push('<div style="white-space:nowrap;"><span class="mono important">' + attr_name + '</span>: ');
|
||||
// h.push('<span>'+data[attr_name]+'</span></div>');
|
||||
|
@ -1574,7 +1592,7 @@ $app.create_dlg_ldap_list_attr_result = function () {
|
|||
};
|
||||
|
||||
$app.create_dlg_ldap_test_result = function () {
|
||||
var dlg = {};
|
||||
let dlg = {};
|
||||
dlg.dom_id = 'dlg-ldap-test-result';
|
||||
|
||||
dlg.dom = {
|
||||
|
@ -1589,21 +1607,21 @@ $app.create_dlg_ldap_test_result = function () {
|
|||
dlg.show = function (data) {
|
||||
dlg.dom.table.empty();
|
||||
|
||||
var h = [];
|
||||
let h = [];
|
||||
h.push('<thead>');
|
||||
h.push('<th style="text-align:left;" class="mono">登录名</th>');
|
||||
h.push('<th style="text-align:left;" class="mono">姓名</th>');
|
||||
h.push('<th style="text-align:left;" class="mono">邮箱</th>');
|
||||
h.push('</thead>');
|
||||
|
||||
var _mktd = function (h, d) {
|
||||
let _mktd = function (h, d) {
|
||||
if ((!_.isUndefined(d)) && !_.isEmpty(d))
|
||||
h.push('<td style="text-align:left;" class="mono">' + d + '</td>');
|
||||
else
|
||||
h.push('<td></td>');
|
||||
};
|
||||
|
||||
var dn;
|
||||
let dn;
|
||||
for (dn in data) {
|
||||
h.push('<tr>');
|
||||
// console.log(data[dn]);
|
||||
|
@ -1621,7 +1639,7 @@ $app.create_dlg_ldap_test_result = function () {
|
|||
};
|
||||
|
||||
$app.create_dlg_ldap_import = function () {
|
||||
var dlg = {};
|
||||
let dlg = {};
|
||||
dlg.dom_id = 'dlg-ldap-import';
|
||||
|
||||
dlg.dom = {
|
||||
|
@ -1639,7 +1657,7 @@ $app.create_dlg_ldap_import = function () {
|
|||
//-------------------------------
|
||||
// LDAP用户列表表格
|
||||
//-------------------------------
|
||||
var table_ldap_users_options = {
|
||||
let table_ldap_users_options = {
|
||||
dom_id: 'table-ldap-user-list',
|
||||
data_source: {
|
||||
type: 'none'
|
||||
|
@ -1699,7 +1717,7 @@ $app.create_dlg_ldap_import = function () {
|
|||
});
|
||||
|
||||
dlg.dom.chkbox_user_list_select_all.click(function () {
|
||||
var _objects = $('#' + $app.table_ldap_users.dom_id + ' tbody').find('[data-check-box]');
|
||||
let _objects = $('#' + $app.table_ldap_users.dom_id + ' tbody').find('[data-check-box]');
|
||||
if ($(this).is(':checked')) {
|
||||
$.each(_objects, function (i, _obj) {
|
||||
$(_obj).prop('checked', true);
|
||||
|
@ -1717,11 +1735,11 @@ $app.create_dlg_ldap_import = function () {
|
|||
};
|
||||
|
||||
dlg.get_selected_user = function (tbl) {
|
||||
var items = [];
|
||||
var _objs = $('#' + tbl.dom_id + ' tbody tr td input[data-check-box]');
|
||||
let items = [];
|
||||
let _objs = $('#' + tbl.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);
|
||||
let _row_data = tbl.get_row(_obj);
|
||||
items.push(_row_data.id);
|
||||
}
|
||||
});
|
||||
|
@ -1750,8 +1768,8 @@ $app.create_dlg_ldap_import = function () {
|
|||
};
|
||||
|
||||
dlg.check_user_list_all_selected = function (cb_stack) {
|
||||
var _all_checked = true;
|
||||
var _objs = $('#' + $app.table_ldap_users.dom_id + ' tbody').find('[data-check-box]');
|
||||
let _all_checked = true;
|
||||
let _objs = $('#' + $app.table_ldap_users.dom_id + ' tbody').find('[data-check-box]');
|
||||
if (_objs.length === 0) {
|
||||
_all_checked = false;
|
||||
} else {
|
||||
|
@ -1788,8 +1806,8 @@ $app.create_dlg_ldap_import = function () {
|
|||
if (ret.code === TPE_OK) {
|
||||
// console.log(ret.data);
|
||||
|
||||
var _d = [];
|
||||
for (var i = 0; i < ret.data.length; ++i) {
|
||||
let _d = [];
|
||||
for (let i = 0; i < ret.data.length; ++i) {
|
||||
_d.push(ret.data[i]);
|
||||
}
|
||||
|
||||
|
@ -1808,7 +1826,7 @@ $app.create_dlg_ldap_import = function () {
|
|||
};
|
||||
|
||||
dlg.do_import = function () {
|
||||
var items = dlg.get_selected_user($app.table_ldap_users);
|
||||
let items = dlg.get_selected_user($app.table_ldap_users);
|
||||
if (items.length === 0) {
|
||||
$tp.notify_error('请选择要导入的账号!');
|
||||
return;
|
||||
|
|
|
@ -228,24 +228,26 @@ hr.small {
|
|||
// icons.
|
||||
//=============================================
|
||||
.os-icon-windows:after {
|
||||
color: #00bcf6;
|
||||
//color: #00bcf6;
|
||||
font-style: normal;
|
||||
content: "\f17a";
|
||||
font-size: 18px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
//font-size: 18px;
|
||||
//width: 24px;
|
||||
//height: 24px;
|
||||
//line-height: 24px;
|
||||
display: inline-block;
|
||||
font-family: 'Font Awesome 5 Brands';
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.os-icon-linux:after {
|
||||
color: #fff;
|
||||
//color: #fff;
|
||||
font-style: normal;
|
||||
content: "\f17c";
|
||||
font-size: 18px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
//font-size: 18px;
|
||||
//width: 24px;
|
||||
//height: 24px;
|
||||
//line-height: 24px;
|
||||
background-color: #333;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
|
@ -254,12 +256,13 @@ hr.small {
|
|||
}
|
||||
|
||||
.os-icon-macos:after {
|
||||
color: #a7a7a7;
|
||||
//color: #a7a7a7;
|
||||
font-style: normal;
|
||||
content: "\f179";
|
||||
font-size: 20px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
//font-size: 20px;
|
||||
//width: 24px;
|
||||
//height: 24px;
|
||||
//line-height: 24px;
|
||||
display: inline-block;
|
||||
font-family: 'Font Awesome 5 Brands';
|
||||
font-weight: 400;
|
||||
|
@ -316,3 +319,7 @@ hr.small {
|
|||
|
||||
z-index: 991;
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
|
|
@ -25,11 +25,13 @@ body {
|
|||
&.page-header-fixed {
|
||||
padding-top: @header-height;
|
||||
}
|
||||
|
||||
// 左侧功能导航栏
|
||||
&.page-sidebar-fixed {
|
||||
.page-sidebar {
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
.page-content {
|
||||
margin-left: @sidebar-width;
|
||||
}
|
||||
|
@ -88,6 +90,7 @@ body {
|
|||
& > li {
|
||||
font-size: @text-size-normal;
|
||||
}
|
||||
|
||||
& > li + li:before {
|
||||
//content: "\f105";
|
||||
//font-family: 'FontAwesome';
|
||||
|
@ -188,6 +191,7 @@ body {
|
|||
.nav-menu li .menu-caret:after {
|
||||
content: '\f105';
|
||||
}
|
||||
|
||||
.nav-menu li.expand .menu-caret:after {
|
||||
content: '\f107';
|
||||
}
|
||||
|
@ -277,6 +281,7 @@ body {
|
|||
color: #fff;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
@ -306,6 +311,7 @@ body {
|
|||
padding-top: 3px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.role {
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
|
@ -315,9 +321,11 @@ body {
|
|||
&.active {
|
||||
background-color: @color-menu-bg-normal;
|
||||
color: #fff;
|
||||
|
||||
.name, .role {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: "\e251";
|
||||
font-family: 'Glyphicons Halflings';
|
||||
|
@ -462,6 +470,7 @@ body {
|
|||
& > li {
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
& > li > a {
|
||||
margin-right: 5px;
|
||||
border-top-left-radius: 3px;
|
||||
|
@ -474,6 +483,7 @@ body {
|
|||
//border-top-color: transparent;
|
||||
border-bottom-color: transparent;
|
||||
}
|
||||
|
||||
& > li.active > a {
|
||||
font-weight: bold;
|
||||
//border-radius: 0;
|
||||
|
@ -507,6 +517,7 @@ body {
|
|||
.box-btn-bar {
|
||||
//height: 30px;
|
||||
line-height: 30px;
|
||||
|
||||
a.btn {
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
@ -685,6 +696,7 @@ body {
|
|||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
&.tp-table-filter-center {
|
||||
.tp-table-filter-inner {
|
||||
margin: 0 auto;
|
||||
|
@ -703,6 +715,7 @@ body {
|
|||
width: 1px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.search-input, .search-select {
|
||||
display: table-cell;
|
||||
text-align: left;
|
||||
|
@ -715,10 +728,12 @@ body {
|
|||
border: none;
|
||||
padding: 0 0 0 8px;
|
||||
border-radius: 0;
|
||||
|
||||
&:active {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
//& > input[type="text"].form-control {
|
||||
|
||||
.dropdown-menu {
|
||||
|
@ -755,6 +770,7 @@ body {
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
.search-input {
|
||||
width: 100%;
|
||||
padding-left: 10px;
|
||||
|
@ -774,6 +790,7 @@ body {
|
|||
font-size: @text-size-normal;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
input.form-control {
|
||||
//margin-left:10px;
|
||||
font-size: @text-size-normal;
|
||||
|
@ -793,6 +810,7 @@ body {
|
|||
border: none;
|
||||
padding: 0 0 0 8px;
|
||||
border-radius: 0;
|
||||
|
||||
&:active {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
@ -800,6 +818,7 @@ body {
|
|||
|
||||
.table > tbody > tr.table-footer-action {
|
||||
background-color: transparent;
|
||||
|
||||
& > td {
|
||||
border-color: transparent;
|
||||
padding-top: 15px;
|
||||
|
@ -836,6 +855,7 @@ body {
|
|||
|
||||
.pagination {
|
||||
margin: 0 0;
|
||||
|
||||
& > li > span, a {
|
||||
padding: 3px 8px;
|
||||
font-size: 12px;
|
||||
|
@ -846,11 +866,13 @@ body {
|
|||
&.checkbox-select-all {
|
||||
width: 36px;
|
||||
text-align: center;
|
||||
|
||||
input {
|
||||
position: relative;
|
||||
top: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
&.group-actions {
|
||||
& > .btn-group {
|
||||
.btn {
|
||||
|
@ -859,6 +881,7 @@ body {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.table-item-counter {
|
||||
text-align: right;
|
||||
|
||||
|
@ -869,6 +892,7 @@ body {
|
|||
border: none;
|
||||
background-color: transparent;
|
||||
color: #666;
|
||||
|
||||
& > li {
|
||||
display: inline-block;
|
||||
padding-left: 10px;
|
||||
|
@ -877,6 +901,7 @@ body {
|
|||
|
||||
.btn {
|
||||
margin-top: -3px;
|
||||
|
||||
.caret {
|
||||
margin-top: -3px;
|
||||
}
|
||||
|
@ -888,6 +913,7 @@ body {
|
|||
|
||||
.table-prefix-area {
|
||||
margin-bottom: 10px;
|
||||
|
||||
.table-extend-cell {
|
||||
padding: 0;
|
||||
}
|
||||
|
@ -1039,9 +1065,11 @@ textarea.cert_pub {
|
|||
list-style: none;
|
||||
margin: 0 0 10px 0;
|
||||
padding: 0;
|
||||
|
||||
li {
|
||||
padding: 3px 3px 3px 20px;
|
||||
margin-left: 10px;
|
||||
|
||||
&:before {
|
||||
color: #999;
|
||||
position: absolute;
|
||||
|
@ -1051,6 +1079,7 @@ textarea.cert_pub {
|
|||
font-family: 'Font Awesome 5 Free';
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
em {
|
||||
color: #3374b0;
|
||||
font-style: normal;
|
||||
|
@ -1090,9 +1119,11 @@ textarea.cert_pub {
|
|||
&.tp-editable {
|
||||
cursor: pointer;
|
||||
color: #459dee;
|
||||
|
||||
&:hover {
|
||||
color: #53af43;
|
||||
}
|
||||
|
||||
&.tp-selected, &.tp-checked {
|
||||
color: #3374b0;
|
||||
}
|
||||
|
@ -1102,10 +1133,67 @@ textarea.cert_pub {
|
|||
i.upload-button {
|
||||
font-size: 128px;
|
||||
color: #b1b1b1;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
color: #709cff;
|
||||
}
|
||||
}
|
||||
|
||||
/* assist */
|
||||
|
||||
.assist-config {
|
||||
//margin: 20px 0 50px 0;
|
||||
|
||||
.cfg-title {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11 {
|
||||
padding-left: 3px;
|
||||
padding-right: 3px;
|
||||
}
|
||||
|
||||
.arg-detail {
|
||||
ol, ul {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.arg-detail-common {
|
||||
//border:1px solid #f33;
|
||||
background-color: #edfedf;
|
||||
//color:#fff;
|
||||
border-radius: 5px;
|
||||
padding: 15px;
|
||||
//margin-bottom:10px;
|
||||
}
|
||||
|
||||
select, .input-args {
|
||||
font-family: @font-family-mono;
|
||||
}
|
||||
|
||||
.desc {
|
||||
// display:inline-block;
|
||||
margin-top: 5px;
|
||||
color: rgb(107, 107, 107);
|
||||
}
|
||||
|
||||
.arg-varb {
|
||||
//color: #0a6aa1;
|
||||
color: #393939;
|
||||
font-weight: bold;
|
||||
font-family: @font-family-mono;
|
||||
display: inline-block;
|
||||
width: 180px;
|
||||
//margin-right:20px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@import "_overwrite_gritter";
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1 @@
|
|||
underscore 1.13.1
|
|
@ -137,7 +137,7 @@
|
|||
{
|
||||
'privilege': const.TP_PRIVILEGE_LOGIN_WEB,
|
||||
'id': 'assist',
|
||||
'link': 'http://127.0.0.1:50022/config',
|
||||
'link': '/assist/config',
|
||||
'target': '_blank',
|
||||
'name': '助手设置',
|
||||
'icon': 'fas fa-bolt'
|
||||
|
@ -217,7 +217,7 @@
|
|||
<hr style="border:none;border-bottom:1px dotted #4a4a4a;margin-bottom:0;"/>
|
||||
<div style="color:#717171;font-size:90%;margin-top:5px;text-align:center;">
|
||||
<div style="color:#717171;font-size:90%;margin-top:5px;"><span style="display:inline-block;width:50px;text-align: right">服务端:</span><span class="mono">v${app_ver.TP_SERVER_VER}${_ver_state}</span></div>
|
||||
<div style="color:#717171;font-size:90%;margin-top:5px;"><span style="display:inline-block;width:50px;text-align: right">助手:</span><span class="mono"><span id="sidebar-tp-assist-ver"><i class="fa fa-cog fa-spin"></i></span></span></div>
|
||||
<div style="color:#717171;font-size:90%;margin-top:5px;"><span style="display:inline-block;width:50px;text-align: right">助手:</span><span class="mono"><span id="sidebar-tp-assist-ver">未连接</span></span></div>
|
||||
</div>
|
||||
<hr style="border:none;border-bottom:1px dotted #4a4a4a;margin-bottom:20px;margin-top:5px;"/>
|
||||
|
||||
|
|
|
@ -0,0 +1,179 @@
|
|||
<%!
|
||||
page_icon_class_ = 'fas fa-bolt fa-fw'
|
||||
page_title_ = ['助手设置']
|
||||
page_id_ = ['assist']
|
||||
%>
|
||||
<%inherit file="../page_base.mako"/>
|
||||
|
||||
<%block name="extend_js_file">
|
||||
<script type="text/javascript" src="${ static_url('js/assist/config.js') }"></script>
|
||||
</%block>
|
||||
<%block name="embed_js">
|
||||
<script type="text/javascript">
|
||||
$app.add_options(${page_param});
|
||||
</script>
|
||||
</%block>
|
||||
|
||||
## Begin Main Body.
|
||||
|
||||
<div class="page-content-inner">
|
||||
|
||||
<!-- begin box -->
|
||||
<div class="box assist-config">
|
||||
<div class="alert alert-warning">
|
||||
<p><strong><i class="fa fa-exclamation-circle fa-fw"></i> 注意:</strong>助手设置读取和保存的是您当前工作机上的助手设置。如果您更换了工作机,则需要重新对助手进行设置。</p>
|
||||
</div>
|
||||
## <div class="arg-detail arg-detail-common">
|
||||
|
||||
<div class="alert alert-info">
|
||||
<p>在命令行参数设置中,可以用以下变量替换需要在命令行中填写的内容(注意大小写!):</p>
|
||||
<ul>
|
||||
<li><span class="arg-varb">{host_ip}</span> 替换远程主机IP地址</li>
|
||||
<li><span class="arg-varb">{host_port}</span> 替换远程主机端口号</li>
|
||||
<li><span class="arg-varb">{host_name}</span> 替换远程主机名称</li>
|
||||
<li><span class="arg-varb">{user_name}</span> 替换远程登录账号名</li>
|
||||
<li><span class="arg-varb">{real_ip}</span> 替换为远程主机真实IP(仅用于显示,例如客户端的窗口标题或标签页标题等)</li>
|
||||
<li><span class="arg-varb">{assist_tools_path}</span> 替换为助手工具所在的tools目录的绝对路径</li>
|
||||
</ul>
|
||||
<p>例如,命令行中需要指定用户名,则直接填写 {user_name} 即可。</p>
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
<p class="cfg-title">本地 SSH 客户端配置</p>
|
||||
|
||||
<div class="form-horizontal">
|
||||
<div class="form-group form-group-sm">
|
||||
<label for="ssh-type" class="col-sm-2 control-label"><strong>客户端:</strong></label>
|
||||
<div class="col-sm-4">
|
||||
<select id="ssh-type" class="form-control"></select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group form-group-sm">
|
||||
<label for="ssh-app" class="col-sm-2 control-label"><strong>程序路径:</strong></label>
|
||||
<div class="col-sm-9">
|
||||
<div class="input-group">
|
||||
<input id="ssh-app" type="text" class="form-control input-args" placeholder="客户端可执行程序文件路径"/>
|
||||
<span class="input-group-btn"><button class="btn btn-sm btn-primary" type="button" id="ssh-select-app">选择...</button></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group form-group-sm">
|
||||
<label for="ssh-cmdline" class="col-sm-2 control-label"><strong>命令参数:</strong></label>
|
||||
<div class="col-sm-9">
|
||||
<input id="ssh-cmdline" type="text" class="form-control input-args" placeholder="客户端启动所需命令行参数"/>
|
||||
<div id="ssh-desc"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<hr/>
|
||||
<p class="cfg-title">本地 SFTP 客户端配置</p>
|
||||
|
||||
|
||||
<div class="form-horizontal">
|
||||
<div class="form-group form-group-sm">
|
||||
<label for="sftp-type" class="col-sm-2 control-label"><strong>客户端:</strong></label>
|
||||
<div class="col-sm-4">
|
||||
<select id="sftp-type" class="form-control"></select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group form-group-sm">
|
||||
<label for="sftp-app" class="col-sm-2 control-label"><strong>程序路径:</strong></label>
|
||||
<div class="col-sm-9">
|
||||
<div class="input-group">
|
||||
<input id="sftp-app" type="text" class="form-control input-args" placeholder="客户端可执行程序文件路径"/>
|
||||
<span class="input-group-btn"><button class="btn btn-sm btn-primary" type="button" id="sftp-select-app">选择...</button></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group form-group-sm">
|
||||
<label for="sftp-cmdline" class="col-sm-2 control-label"><strong>命令参数:</strong></label>
|
||||
<div class="col-sm-9">
|
||||
<input id="sftp-cmdline" type="text" class="form-control input-args" placeholder="客户端启动所需命令行参数"/>
|
||||
<div id="sftp-desc"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<hr/>
|
||||
<p class="cfg-title">本地 TELNET 客户端配置</p>
|
||||
|
||||
<div class="form-horizontal">
|
||||
<div class="form-group form-group-sm">
|
||||
<label for="telnet-type" class="col-sm-2 control-label"><strong>客户端:</strong></label>
|
||||
<div class="col-sm-4">
|
||||
<select id="telnet-type" class="form-control"></select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group form-group-sm">
|
||||
<label for="telnet-app" class="col-sm-2 control-label"><strong>程序路径:</strong></label>
|
||||
<div class="col-sm-9">
|
||||
<div class="input-group">
|
||||
<input id="telnet-app" type="text" class="form-control input-args" placeholder="客户端可执行程序文件路径"/>
|
||||
<span class="input-group-btn"><button class="btn btn-sm btn-primary" type="button" id="telnet-select-app">选择...</button></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group form-group-sm">
|
||||
<label for="telnet-cmdline" class="col-sm-2 control-label"><strong>命令参数:</strong></label>
|
||||
<div class="col-sm-9">
|
||||
<input id="telnet-cmdline" type="text" class="form-control input-args" placeholder="客户端启动所需命令行参数"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<hr/>
|
||||
<p class="cfg-title">本地 RDP 客户端配置</p>
|
||||
|
||||
<div class="form-horizontal">
|
||||
<div class="form-group form-group-sm">
|
||||
<label for="rdp-type" class="col-sm-2 control-label">客户端:</label>
|
||||
<div class="col-sm-4">
|
||||
<select id="rdp-type" class="form-control"></select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group form-group-sm">
|
||||
<label for="rdp-app" class="col-sm-2 control-label">程序路径:</label>
|
||||
<div class="col-sm-9">
|
||||
<div class="input-group">
|
||||
<input id="rdp-app" type="text" class="form-control input-args" placeholder="客户端可执行程序文件路径"/>
|
||||
<span class="input-group-btn"><button class="btn btn-sm btn-primary" type="button" id="rdp-select-app">选择...</button></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group form-group-sm">
|
||||
<label for="rdp-cmdline" class="col-sm-2 control-label">命令参数:</label>
|
||||
<div class="col-sm-9">
|
||||
<input id="rdp-cmdline" type="text" class="form-control input-args" placeholder="客户端启动所需命令行参数"/>
|
||||
<div id="rdp-desc"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<hr/>
|
||||
<div class="form-horizontal">
|
||||
<div class="form-group form-group-sm">
|
||||
<div class="col-sm-2"></div>
|
||||
<div class="col-sm-6">
|
||||
<a id="btn-save" class="btn btn-primary" href="javascript:"><i class="fa fa-check fa-fw"></i> 保存设置!</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
|
@ -105,6 +105,6 @@
|
|||
|
||||
<%block name="embed_js">
|
||||
<script type="text/javascript">
|
||||
## ywl.add_page_options(${ page_param });
|
||||
## $app.add_page_options(${ page_param });
|
||||
</script>
|
||||
</%block>
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
<%inherit file="../page_base.mako"/>
|
||||
|
||||
<%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/ops/remote-list.js') }"></script>
|
||||
</%block>
|
||||
<%block name="embed_js">
|
||||
|
@ -16,11 +14,6 @@
|
|||
</script>
|
||||
</%block>
|
||||
|
||||
<%block name="embed_css">
|
||||
<style>
|
||||
</style>
|
||||
</%block>
|
||||
|
||||
## Begin Main Body.
|
||||
|
||||
<div class="page-content-inner">
|
||||
|
@ -110,8 +103,3 @@
|
|||
</div>
|
||||
</div>
|
||||
</%block>
|
||||
|
||||
## <%block name="embed_js">
|
||||
## <script type="text/javascript">
|
||||
## </script>
|
||||
## </%block>
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
<!-- end #page-content -->
|
||||
|
||||
<%block name="extend_content" />
|
||||
<script type="text/javascript" src="${ static_url('plugins/underscore/underscore.js') }"></script>
|
||||
<script type="text/javascript" src="${ static_url('plugins/underscore/underscore-min.js') }"></script>
|
||||
<script type="text/javascript" src="${ static_url('plugins/jquery/jquery-2.2.3.min.js') }"></script>
|
||||
<script type="text/javascript" src="${ static_url('plugins/jquery/js.cookie.js') }"></script>
|
||||
<script type="text/javascript" src="${ static_url('plugins/bootstrap/js/bootstrap.min.js') }"></script>
|
||||
|
|
|
@ -9,12 +9,6 @@
|
|||
<script type="text/javascript" src="${ static_url('js/system/syslog.js') }"></script>
|
||||
</%block>
|
||||
|
||||
## <%block name="breadcrumb">
|
||||
## <ol class="breadcrumb">
|
||||
## <li><i class="fa fa-database fa-fw"></i> ${self.attr.page_title_}</li>
|
||||
## </ol>
|
||||
## </%block>
|
||||
|
||||
## Begin Main Body.
|
||||
|
||||
<div class="page-content-inner">
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|- app
|
||||
|- res
|
||||
|- static
|
||||
\- view
|
||||
-- view
|
||||
"""
|
||||
|
||||
import os
|
||||
|
@ -46,11 +46,5 @@ if _ext_path not in sys.path:
|
|||
|
||||
# 确定一些路径
|
||||
PATH_DATA = os.path.abspath(os.path.join(PATH_APP_ROOT, '..', '..', 'share'))
|
||||
# if os.path.exists(os.path.join(os.path.dirname(sys.executable), 'dev_mode')):
|
||||
# # 开发调试模式
|
||||
# PATH_DATA = os.path.abspath(os.path.join(PATH_APP_ROOT, '..', '..', 'share'))
|
||||
#
|
||||
# else:
|
||||
# PATH_DATA = os.path.abspath(os.path.join(PATH_APP_ROOT, '..', '..', 'data'))
|
||||
if not os.path.exists(PATH_DATA):
|
||||
PATH_DATA = os.path.abspath(os.path.join(PATH_APP_ROOT, '..', '..', 'data'))
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# -*- coding: utf8 -*-
|
||||
TP_SERVER_VER = "3.5.6"
|
||||
TP_ASSIST_REQUIRE_VER = "3.5.5"
|
||||
TP_ASSIST_REQUIRE_VER = "3.6.0"
|
||||
TP_STATE_VER = "rc6"
|
||||
|
|
|
@ -0,0 +1,255 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from typing import Optional, Dict
|
||||
import json
|
||||
import threading
|
||||
|
||||
import app.controller.ws
|
||||
from app.const import *
|
||||
from app.base.utils import tp_unique_id, tp_timestamp_sec
|
||||
from app.base.logger import *
|
||||
|
||||
|
||||
# 页面多个session-id可能对应同一个助手实例
|
||||
# assist attributes:
|
||||
# - assist_id
|
||||
# - assist_ws_client 助手的ws连接
|
||||
# - last_transfer_time 最后一次通讯时间(用于超时断开助手的ws连接)[此功能可选]
|
||||
|
||||
|
||||
# 命令请求/响应的格式:
|
||||
# request
|
||||
# {"type": 0, "method": "METHOD, like register", "command_id": 1234, "param": {} }
|
||||
# response
|
||||
# {"type": 1, "code" 0, "message": "", "method": "METHOD", "command_id": 1234, "data": {} }
|
||||
|
||||
|
||||
class AssistMessage(object):
|
||||
"""request/response between web-ws-client and assist-ws-client.
|
||||
"""
|
||||
|
||||
MESSAGE_TYPE_REQUEST = 0
|
||||
MESSAGE_TYPE_RESPONSE = 1
|
||||
|
||||
def __init__(self, caller, method):
|
||||
super().__init__()
|
||||
|
||||
# 命令的全局唯一id
|
||||
self.cmd_id: int = tp_unique_id()
|
||||
self.method: str = method
|
||||
# 命令发送给被调用端时的时间戳,错过一定时间未完结的命令,将会被扔掉
|
||||
self.start_time: int = tp_timestamp_sec()
|
||||
self.caller: app.controller.ws.AssistHandler = caller
|
||||
self.callee: Optional[app.controller.ws.AssistHandler] = None
|
||||
|
||||
def send_request(self, callee, param=None):
|
||||
self.callee = callee
|
||||
#
|
||||
tp_assist_bridge().handle_assist_message(self)
|
||||
|
||||
self.callee.send_request(self, param)
|
||||
|
||||
|
||||
class AssistInfo(object):
|
||||
WS_CLIENT_UNKNOWN = 0
|
||||
WS_CLIENT_WEB = 1
|
||||
WS_CLIENT_ASSIST = 2
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self.assist_id = 0
|
||||
self.assist_ver = ''
|
||||
self.assist_ws = None
|
||||
|
||||
|
||||
class TPAssistBridge(object):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
import builtins
|
||||
if '__tp_assist_bridge__' in builtins.__dict__:
|
||||
raise RuntimeError('TPAssistBridge object exists, you can not create more than one instance.')
|
||||
|
||||
self._lock = threading.RLock()
|
||||
|
||||
# 会话ID对应的助手ID,多对一
|
||||
# SESSION-ID --> assist-id
|
||||
self._sid_to_assist = dict()
|
||||
|
||||
# 助手ID对应的助手信息,一对一
|
||||
# assist_id --> AssistInfo
|
||||
self._assists = dict()
|
||||
|
||||
# 页面会话的ws客户端连接
|
||||
# AssistHandler --> assist-id
|
||||
self._ws_web = dict()
|
||||
|
||||
# 助手会话的ws客户端连接
|
||||
# AssistHandler --> assist-id
|
||||
self._ws_assist = dict()
|
||||
|
||||
# 未完结的命令
|
||||
self._commands: Dict[int, AssistMessage] = dict()
|
||||
|
||||
def get_assist_bridge(self, s_id):
|
||||
with self._lock:
|
||||
assist_id = self._sid_to_assist[s_id] if s_id in self._sid_to_assist else 0
|
||||
if assist_id == 0:
|
||||
return None
|
||||
assist_info = self._assists[assist_id] if assist_id in self._assists else None
|
||||
return assist_info
|
||||
|
||||
def handle_assist_message(self, msg_req: AssistMessage):
|
||||
log.v('add message, cmd_id={}\n'.format(msg_req.cmd_id))
|
||||
self._commands[msg_req.cmd_id] = msg_req
|
||||
|
||||
def on_web_client_connect(self, msg_req: AssistMessage, s_id: str, param: dict) -> None:
|
||||
with self._lock:
|
||||
assist_id = self._sid_to_assist[s_id] if s_id in self._sid_to_assist else 0
|
||||
if assist_id != 0:
|
||||
assist_info = self._assists[assist_id] if assist_id in self._assists else None
|
||||
if assist_info is not None:
|
||||
self._ws_web[msg_req.caller] = assist_id
|
||||
msg_req.caller.set_assist_id(assist_id)
|
||||
|
||||
assist_msg = AssistMessage(msg_req.caller, 'update_assist_info')
|
||||
msg_param = {'assist_id': assist_id, 'assist_ver': assist_info.assist_ver}
|
||||
msg_req.caller.send_response(assist_msg, TPE_OK, data=msg_param)
|
||||
|
||||
if 'exec' in param:
|
||||
exec_param = param['exec']
|
||||
assist_msg = AssistMessage(msg_req.caller, exec_param['method'])
|
||||
msg_param = exec_param['param']
|
||||
# assist_info.assist_ws.send_request(assist_msg, msg_param)
|
||||
assist_msg.send_request(assist_info.assist_ws, msg_param)
|
||||
|
||||
return
|
||||
else:
|
||||
del self._sid_to_assist[s_id]
|
||||
|
||||
# 页面登录后首次连接此ws,此时当前会话还没有对应的助手ws,因此返回一个 request_assist_id,让页面通过url-protocol
|
||||
# 的方式调起助手。但是助手有可能已经在别的会话中存在ws连接,并且有另外的assist_id,因此助手会回一个正确的assist_id,
|
||||
# 然后才能完成 assist_id 与 web页面的绑定。
|
||||
assist_id = tp_unique_id()
|
||||
log.w('ws-web connected, but no assist bind, try to bind assist-id: {}\n'.format(assist_id))
|
||||
self._ws_web[msg_req.caller] = assist_id
|
||||
msg_req.caller.set_assist_id(assist_id)
|
||||
assist_msg = AssistMessage(msg_req.caller, 'start_assist')
|
||||
msg_param = {'request_assist_id': assist_id}
|
||||
if 'exec' in param:
|
||||
msg_param['exec'] = param['exec']
|
||||
msg_req.caller.send_response(assist_msg, TPE_OK, data=msg_param)
|
||||
|
||||
def on_assist_connect(self, msg_req, param):
|
||||
try:
|
||||
s_id = param['sid']
|
||||
request_assist_id = param['request_assist_id']
|
||||
assist_id = param['assist_id']
|
||||
assist_ver = param['assist_ver']
|
||||
except Exception as e:
|
||||
log.e(e.__str__())
|
||||
return
|
||||
|
||||
msg_req.caller.set_assist_id(assist_id)
|
||||
|
||||
with self._lock:
|
||||
if assist_id in self._assists:
|
||||
assist_info = self._assists[assist_id]
|
||||
else:
|
||||
assist_info = AssistInfo()
|
||||
assist_info.assist_id = assist_id
|
||||
self._assists[assist_id] = assist_info
|
||||
|
||||
assist_info.assist_ws = msg_req.caller
|
||||
assist_info.assist_ver = assist_ver
|
||||
|
||||
self._ws_assist[msg_req.caller] = assist_id
|
||||
self._sid_to_assist[s_id] = assist_id
|
||||
|
||||
# notify the web-client that assist connected.
|
||||
self._on_assist_info_changed(assist_info, request_assist_id)
|
||||
|
||||
def _on_assist_info_changed(self, assist_info, request_assist_id):
|
||||
param = {'assist_id': assist_info.assist_id, 'assist_ver': assist_info.assist_ver}
|
||||
with self._lock:
|
||||
for caller in self._ws_web:
|
||||
if self._ws_web[caller] == assist_info.assist_id or self._ws_web[caller] == request_assist_id:
|
||||
log.v('ws-web bind assist-id: {} -> {}\n'.format(request_assist_id, assist_info.assist_id))
|
||||
assist_msg = AssistMessage(assist_info.assist_ws, 'update_assist_info')
|
||||
self._ws_web[caller] = assist_info.assist_id
|
||||
caller.set_assist_id(assist_info.assist_id)
|
||||
caller.send_response(assist_msg, TPE_OK, data=param)
|
||||
|
||||
def on_disconnect(self, caller):
|
||||
print('assist-ws-disconnect:', caller)
|
||||
with self._lock:
|
||||
if caller.client_type == AssistInfo.WS_CLIENT_WEB:
|
||||
if caller in self._ws_web:
|
||||
del self._ws_web[caller]
|
||||
return
|
||||
elif caller.client_type == AssistInfo.WS_CLIENT_ASSIST:
|
||||
if caller not in self._ws_assist:
|
||||
log.e('assist-ws disconnected, but not in charge.\n')
|
||||
return
|
||||
assist_id = self._ws_assist[caller]
|
||||
del self._ws_assist[caller]
|
||||
if assist_id in self._assists:
|
||||
del self._assists[assist_id]
|
||||
|
||||
need_remove = list()
|
||||
for sid in self._sid_to_assist:
|
||||
if self._sid_to_assist[sid] == assist_id:
|
||||
need_remove.append(sid)
|
||||
for sid in need_remove:
|
||||
del self._sid_to_assist[sid]
|
||||
|
||||
# 通知相关的web页面,绑定的助手已经退出了
|
||||
for c in self._ws_web:
|
||||
if self._ws_web[c] == assist_id:
|
||||
assist_msg = AssistMessage(caller, 'assist_disconnected')
|
||||
msg_param = {'assist_id': assist_id}
|
||||
c.send_response(assist_msg, TPE_OK, data=msg_param)
|
||||
|
||||
def on_request(self, msg_req: AssistMessage, param):
|
||||
with self._lock:
|
||||
if msg_req.caller.client_type == AssistInfo.WS_CLIENT_WEB:
|
||||
assist_id = self._ws_web[msg_req.caller] if msg_req.caller in self._ws_web else 0
|
||||
if assist_id != 0:
|
||||
assist_info = self._assists[assist_id] if assist_id in self._assists else None
|
||||
if assist_info is not None:
|
||||
# assist_info.assist_ws.send_request(msg_req, param)
|
||||
msg_req.send_request(assist_info.assist_ws, param)
|
||||
return
|
||||
log.e('caller not bind assist.\n')
|
||||
elif msg_req.caller.client_type == AssistInfo.WS_CLIENT_ASSIST:
|
||||
log.w('got request from assist ?!\n')
|
||||
|
||||
def forward_response(self, caller, msg):
|
||||
with self._lock:
|
||||
if caller.client_type == AssistInfo.WS_CLIENT_WEB:
|
||||
log.w('got response from web ?!\n')
|
||||
elif caller.client_type == AssistInfo.WS_CLIENT_ASSIST:
|
||||
message_id = msg['command_id']
|
||||
msg_req = self._commands[message_id] if message_id in self._commands else None
|
||||
if msg_req is None:
|
||||
log.e('got response but command_id {} not known.\n'.format(message_id))
|
||||
return
|
||||
if msg_req.caller is None:
|
||||
log.e('got response but caller unknown.\n')
|
||||
return
|
||||
msg_req.caller.send_response(msg_req, msg['code'], msg['message'], msg['data'])
|
||||
|
||||
# remove finished message
|
||||
log.v('remove message, cmd_id={}\n'.format(msg_req.cmd_id))
|
||||
del self._commands[msg_req.cmd_id]
|
||||
|
||||
|
||||
def tp_assist_bridge() -> TPAssistBridge:
|
||||
"""取得 TPAssistBridge 管理器的唯一实例
|
||||
"""
|
||||
|
||||
import builtins
|
||||
if '__tp_assist_bridge__' not in builtins.__dict__:
|
||||
builtins.__dict__['__tp_assist_bridge__'] = TPAssistBridge()
|
||||
return builtins.__dict__['__tp_assist_bridge__']
|
|
@ -216,7 +216,8 @@ def tp_gen_password(length=8):
|
|||
random.seed()
|
||||
|
||||
# 生成一个随机密码
|
||||
_chars = ['ABCDEFGHJKMNPQRSTWXYZ', 'abcdefhijkmnprstwxyz', '2345678'] # 默认去掉了容易混淆的字符oO,Ll,9gq,Vv,Uu,I1
|
||||
# 默认去掉了容易混淆的字符oO,Ll,9gq,Vv,Uu,I1
|
||||
_chars = ['ABCDEFGHJKMNPQRSTWXYZ', 'abcdefhijkmnprstwxyz', '2345678']
|
||||
|
||||
have_CHAR = False
|
||||
have_char = False
|
||||
|
@ -263,11 +264,11 @@ def tp_check_strong_password(p):
|
|||
|
||||
class UniqueId:
|
||||
def __init__(self):
|
||||
import builtins
|
||||
if '__tp_unique_id__' in builtins.__dict__:
|
||||
raise RuntimeError('UniqueId object exists, can not create more than one instance.')
|
||||
# import builtins
|
||||
# if '__tp_unique_id__' in builtins.__dict__:
|
||||
# raise RuntimeError('UniqueId object exists, can not create more than one instance.')
|
||||
|
||||
self._id = tp_timestamp_sec()
|
||||
self._id = tp_timestamp_sec() % 100000
|
||||
self._locker = threading.RLock()
|
||||
|
||||
def generate(self):
|
||||
|
@ -276,8 +277,13 @@ class UniqueId:
|
|||
return self._id
|
||||
|
||||
|
||||
g_unique_id_generator = UniqueId()
|
||||
del UniqueId
|
||||
|
||||
|
||||
def tp_unique_id():
|
||||
import builtins
|
||||
if '__tp_unique_id__' not in builtins.__dict__:
|
||||
builtins.__dict__['__tp_unique_id__'] = UniqueId()
|
||||
return builtins.__dict__['__tp_unique_id__'].generate()
|
||||
# import builtins
|
||||
# if '__tp_unique_id__' not in builtins.__dict__:
|
||||
# builtins.__dict__['__tp_unique_id__'] = UniqueId()
|
||||
# return builtins.__dict__['__tp_unique_id__'].generate()
|
||||
return g_unique_id_generator.generate()
|
||||
|
|
|
@ -14,6 +14,7 @@ from . import rpc
|
|||
from . import system
|
||||
from . import user
|
||||
from . import ws
|
||||
from . import assist
|
||||
from . import api_v1
|
||||
from . import api_v2
|
||||
|
||||
|
@ -286,7 +287,14 @@ controllers = [
|
|||
|
||||
# WebSocket for real-time information
|
||||
# ws-client call 'http://ip:7190/ws/action/'
|
||||
(r'/ws/(.*)', ws.WebSocketHandler),
|
||||
(r'/ws/dashboard/(.*)', ws.DashboardHandler),
|
||||
|
||||
# 助手相关
|
||||
(r'/assist/config', assist.ConfigHandler),
|
||||
(r'/assist/get-assist-info', assist.DoGetAssistInfoHandler),
|
||||
(r'/ws/assist/(.*)', ws.AssistHandler),
|
||||
# 下载助手
|
||||
(r'/assist/download/(.*)', assist.DoDownloadAssistHandler),
|
||||
|
||||
# api v1
|
||||
(r'/api/v1/get_host', api_v1.GetHostHandler),
|
||||
|
|
|
@ -27,12 +27,12 @@ def pkcs7unpadding(data):
|
|||
|
||||
@tornado.gen.coroutine
|
||||
def _parse_api_args(handler):
|
||||
raw_req = handler.request.body.decode('utf-8')
|
||||
if raw_req == '':
|
||||
req_body = handler.request.body.decode('utf-8')
|
||||
if req_body == '':
|
||||
return False, handler.write_json(TPE_PARAM)
|
||||
|
||||
try:
|
||||
raw_req = json.loads(raw_req)
|
||||
raw_req = json.loads(req_body)
|
||||
|
||||
if 'auth' not in raw_req or 'arg' not in raw_req or 'sign' not in raw_req:
|
||||
return False, handler.write_json(TPE_PARAM)
|
||||
|
@ -43,7 +43,7 @@ def _parse_api_args(handler):
|
|||
if len(_auth) <= 1:
|
||||
return False, handler.write_json(TPE_PARAM)
|
||||
|
||||
if _auth[0] == '2': # 目前的API请求格式版本为1
|
||||
if _auth[0] == '2': # 目前的API请求格式版本为2
|
||||
if len(_auth) != 4: # VERSION:ACCESS_KEY:TIMESTAMP:EXPIRES
|
||||
return False, handler.write_json(TPE_PARAM)
|
||||
req_access_key = _auth[1]
|
||||
|
@ -59,8 +59,8 @@ def _parse_api_args(handler):
|
|||
access_secret = sec_info['secret']
|
||||
|
||||
# 是否超时
|
||||
# if tp_timestamp_sec() > req_timestamp + req_expires:
|
||||
# return False, handler.write_json(TPE_EXPIRED)
|
||||
if tp_timestamp_sec() > req_timestamp + req_expires:
|
||||
return False, handler.write_json(TPE_EXPIRED)
|
||||
|
||||
# 验证
|
||||
be_sign = '{}|{}'.format(raw_req['auth'], raw_req['arg'])
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import json
|
||||
import os
|
||||
|
||||
import tornado.ioloop
|
||||
import tornado.gen
|
||||
from app.base.controller import TPBaseHandler, TPBaseJsonHandler
|
||||
from app.base.logger import log
|
||||
from app.base.configs import tp_cfg
|
||||
from app.base.assist_bridge import tp_assist_bridge
|
||||
from app.const import *
|
||||
from tornado.escape import json_encode
|
||||
|
||||
|
||||
class ConfigHandler(TPBaseHandler):
|
||||
def get(self):
|
||||
ret = self.check_privilege(TP_PRIVILEGE_LOGIN_WEB)
|
||||
if ret != TPE_OK:
|
||||
return
|
||||
|
||||
param = {'username': self._user['username']}
|
||||
self.render('assist/config.mako', page_param=json.dumps(param))
|
||||
|
||||
|
||||
class DoGetAssistInfoHandler(TPBaseJsonHandler):
|
||||
def post(self):
|
||||
user_info = self.get_current_user()
|
||||
if not user_info['_is_login']:
|
||||
return self.write_json(TPE_NEED_LOGIN)
|
||||
|
||||
assist = tp_assist_bridge().get_assist_bridge(self._s_id)
|
||||
if assist is None:
|
||||
return self.write_json(TPE_NOT_EXISTS)
|
||||
|
||||
return self.write_json(TPE_OK, data={'assist_id': assist.assist_id, 'assist_ver': assist.assist_ver})
|
||||
|
||||
|
||||
class DoDownloadAssistHandler(TPBaseHandler):
|
||||
@tornado.gen.coroutine
|
||||
def get(self, os_type):
|
||||
cfg = tp_cfg()
|
||||
dl_path = os.path.join(cfg.data_path, 'assist')
|
||||
files = os.listdir(dl_path)
|
||||
name = None
|
||||
for f in files:
|
||||
if f.startswith('teleport-assist-{}-'.format(os_type)):
|
||||
name = f
|
||||
break
|
||||
if not name:
|
||||
self.set_status(404)
|
||||
return
|
||||
filename = os.path.join(dl_path, name)
|
||||
file_size = os.path.getsize(filename)
|
||||
|
||||
self.set_header('Content-Type', 'application/octet-stream')
|
||||
self.set_header('Content-Disposition', 'attachment; filename="{}"'.format(name))
|
||||
self.set_header('Content-Length', file_size)
|
||||
|
||||
# read most 8192 bytes one time.
|
||||
BULK_SIZE = 8192
|
||||
total_read = 0
|
||||
with open(filename, 'rb') as f:
|
||||
read_this_time = BULK_SIZE if (file_size - total_read) > BULK_SIZE else (file_size - total_read)
|
||||
while read_this_time > 0:
|
||||
self.write(f.read(read_this_time))
|
||||
self.flush()
|
||||
total_read += read_this_time
|
||||
if total_read >= file_size:
|
||||
break
|
||||
read_this_time = BULK_SIZE if (file_size - total_read) > BULK_SIZE else (file_size - total_read)
|
|
@ -3,13 +3,17 @@
|
|||
import json
|
||||
|
||||
import tornado.websocket
|
||||
from tornado.escape import json_encode
|
||||
from app.base.session import tp_session
|
||||
from app.base.logger import *
|
||||
from app.base.wss import tp_wss
|
||||
from app.base.assist_bridge import tp_assist_bridge, AssistInfo, AssistMessage
|
||||
from app.const import *
|
||||
|
||||
|
||||
class WebSocketHandler(tornado.websocket.WebSocketHandler):
|
||||
class DashboardHandler(tornado.websocket.WebSocketHandler):
|
||||
def check_origin(self, origin): # 针对websocket处理类重写同源检查的方法
|
||||
print('ws-dashboard origin:', origin)
|
||||
return True
|
||||
|
||||
# 接受websocket链接,保存链接实例
|
||||
|
@ -35,3 +39,143 @@ class WebSocketHandler(tornado.websocket.WebSocketHandler):
|
|||
self.write_message(json.dumps(ret))
|
||||
return
|
||||
tp_wss().on_message(self, message)
|
||||
|
||||
|
||||
class AssistHandler(tornado.websocket.WebSocketHandler):
|
||||
def __init__(self, application, request, **kwargs):
|
||||
super().__init__(application, request, **kwargs)
|
||||
|
||||
self.client_type: int = AssistInfo.WS_CLIENT_UNKNOWN
|
||||
self.assist_id: int = 0
|
||||
|
||||
def check_origin(self, origin): # 针对websocket处理类重写同源检查的方法
|
||||
# print('ws-assist origin:', origin)
|
||||
return True
|
||||
|
||||
# todo: send_request()/send_response()...
|
||||
def send_request(self, msg: AssistMessage, param=None):
|
||||
if param is None:
|
||||
param = {}
|
||||
data = {
|
||||
'type': AssistMessage.MESSAGE_TYPE_REQUEST,
|
||||
'command_id': msg.cmd_id,
|
||||
'method': msg.method,
|
||||
'param': param
|
||||
}
|
||||
log.w('send ws request: {}\n'.format(json_encode(data)))
|
||||
self.write_message(json_encode(data))
|
||||
|
||||
def send_response(self, msg: AssistMessage, code, message='', data=None):
|
||||
if data is None:
|
||||
data = {}
|
||||
ret = {
|
||||
'type': AssistMessage.MESSAGE_TYPE_RESPONSE,
|
||||
'command_id': msg.cmd_id,
|
||||
'method': msg.method,
|
||||
'code': code,
|
||||
'message': message,
|
||||
'data': data
|
||||
}
|
||||
log.w('send ws response: {}\n'.format(json_encode(ret)))
|
||||
self.write_message(json_encode(ret))
|
||||
|
||||
def set_assist_id(self, assist_id: int) -> None:
|
||||
self.assist_id = assist_id
|
||||
|
||||
# def write_json(self, code, message='', data=None):
|
||||
# if not isinstance(code, int):
|
||||
# raise RuntimeError('`code` must be a integer.')
|
||||
# if not isinstance(message, str):
|
||||
# raise RuntimeError('`msg` must be a string.')
|
||||
#
|
||||
# if data is None:
|
||||
# data = dict()
|
||||
#
|
||||
# _ret = {
|
||||
# 'type': AssistMessage.MESSAGE_TYPE_RESPONSE,
|
||||
# 'command_id': 0,
|
||||
# 'method': '',
|
||||
# 'code': code,
|
||||
# 'message': message,
|
||||
# 'data': data
|
||||
# }
|
||||
# log.w('send ws message: {}\n'.format(json_encode(_ret)))
|
||||
# self.write_message(json_encode(_ret))
|
||||
|
||||
# 接受websocket连接,保存连接实例
|
||||
def open(self, message):
|
||||
log.w('message on_open: {}\n'.format(message))
|
||||
self.on_message(message)
|
||||
|
||||
def on_close(self):
|
||||
tp_assist_bridge().on_disconnect(self)
|
||||
|
||||
def on_message(self, message):
|
||||
log.w('raw on_message: {}\n'.format(message))
|
||||
msg_req = AssistMessage(self, 'UNKNOWN')
|
||||
|
||||
try:
|
||||
msg = json.loads(message)
|
||||
except Exception as e:
|
||||
log.e('need json format: {}\n'.format(e.__str__()))
|
||||
return self.send_response(msg_req, TPE_JSON_FORMAT)
|
||||
|
||||
if 'type' not in msg:
|
||||
log.e('need `type` fields: {}\n'.format(message))
|
||||
return self.send_response(msg_req, TPE_PARAM)
|
||||
|
||||
if 'method' not in msg:
|
||||
log.e('need `method` fields: {}\n'.format(message))
|
||||
return self.send_response(msg_req, TPE_PARAM)
|
||||
msg_req.method = msg['method']
|
||||
|
||||
if msg['type'] == AssistMessage.MESSAGE_TYPE_REQUEST:
|
||||
param = msg['param'] if 'param' in msg else None
|
||||
|
||||
if msg['method'] == 'register':
|
||||
if param is None:
|
||||
log.e('need `param` field: {}\n'.format(message))
|
||||
return self.send_response(msg_req, TPE_PARAM)
|
||||
|
||||
if 'client' not in param:
|
||||
log.e('need `client` field: {}\n'.format(message))
|
||||
return self.send_response(msg_req, TPE_PARAM)
|
||||
|
||||
if param['client'] == 'web':
|
||||
self.client_type = AssistInfo.WS_CLIENT_WEB
|
||||
self._on_web_client_connected(msg_req, param)
|
||||
elif param['client'] == 'assist':
|
||||
self.client_type = AssistInfo.WS_CLIENT_ASSIST
|
||||
tp_assist_bridge().on_assist_connect(msg_req, param)
|
||||
else:
|
||||
log.e('未知的客户端类型:{}\n'.format(msg['client']))
|
||||
return self.send_response(msg_req, TPE_PARAM)
|
||||
|
||||
else:
|
||||
# return self.write_json(TPE_PARAM, message='未知的操作:{}'.format(param['method']))
|
||||
tp_assist_bridge().on_request(msg_req, param)
|
||||
|
||||
elif msg['type'] == AssistMessage.MESSAGE_TYPE_RESPONSE:
|
||||
if 'command_id' not in msg or msg['command_id'] == 0:
|
||||
log.e('invalid response, need `command_id`: {}\n'.format(message))
|
||||
return
|
||||
log.v('forward: {}\n'.format(message))
|
||||
tp_assist_bridge().forward_response(self, msg)
|
||||
else:
|
||||
log.e('unknown `type` field in message: {}\n'.format(message))
|
||||
return self.send_response(msg_req, TPE_PARAM)
|
||||
|
||||
def _on_web_client_connected(self, msg_req, param):
|
||||
s_id = self.get_cookie('_sid')
|
||||
if s_id is None:
|
||||
# return self.write_json(TPE_NEED_LOGIN, '需要登录')
|
||||
return self.send_response(msg_req, TPE_NEED_LOGIN, '需要登录')
|
||||
|
||||
k = 'user-{}'.format(s_id)
|
||||
user_info = tp_session().get(k, None)
|
||||
if user_info is None or not user_info['_is_login']:
|
||||
# return self.write_json(TPE_NEED_LOGIN, '需要登录')
|
||||
return self.send_response(msg_req, TPE_NEED_LOGIN, '需要登录')
|
||||
|
||||
# print('user-info:', user_info)
|
||||
tp_assist_bridge().on_web_client_connect(msg_req, s_id, param)
|
||||
|
|
|
@ -58,8 +58,6 @@ def get_by_username(username):
|
|||
def login(handler, username, login_type=None, password=None, oath_code=None, check_bind_oath=False):
|
||||
sys_cfg = tp_cfg().sys
|
||||
msg = ''
|
||||
current_unix_time = int(time.mktime(datetime.datetime.now().timetuple()))
|
||||
# log.e('current:',current_unix_time,'validfrom:', user_info['valid_from'])
|
||||
|
||||
err, user_info = get_by_username(username)
|
||||
if err != TPE_OK:
|
||||
|
@ -83,10 +81,11 @@ def login(handler, username, login_type=None, password=None, oath_code=None, che
|
|||
if check_bind_oath and len(oath_db) != 0:
|
||||
return TPE_OATH_ALREADY_BIND, None, msg
|
||||
|
||||
time_now = tp_timestamp_sec()
|
||||
if user_info['state'] == TP_STATE_LOCKED:
|
||||
# 用户已经被锁定,如果系统配置为一定时间后自动解锁,则更新一下用户信息
|
||||
if sys_cfg.login.lock_timeout != 0:
|
||||
if tp_timestamp_sec() - user_info.lock_time > sys_cfg.login.lock_timeout * 60:
|
||||
if time_now - user_info.lock_time > sys_cfg.login.lock_timeout * 60:
|
||||
user_info.fail_count = 0
|
||||
user_info.state = TP_STATE_NORMAL
|
||||
update_fail_count(handler, user_info)
|
||||
|
@ -99,7 +98,7 @@ def login(handler, username, login_type=None, password=None, oath_code=None, che
|
|||
elif user_info['state'] != TP_STATE_NORMAL:
|
||||
syslog.sys_log(user_info, handler.request.remote_ip, TPE_FAILED, msg)
|
||||
return TPE_FAILED, None, '登录失败,用户状态异常'
|
||||
elif current_unix_time < user_info['valid_from'] or (current_unix_time > user_info['valid_to'] and user_info['valid_to'] != 0):
|
||||
elif (time_now < user_info['valid_from']) or (time_now > user_info['valid_to'] != 0):
|
||||
syslog.sys_log(user_info, handler.request.remote_ip, TPE_FAILED, msg)
|
||||
return TPE_FAILED, None, '登录失败,用户已过期'
|
||||
|
||||
|
@ -108,8 +107,7 @@ def login(handler, username, login_type=None, password=None, oath_code=None, che
|
|||
if user_info['type'] == TpUserType.LOCAL:
|
||||
# 如果系统配置了密码有效期,则检查用户的密码是否失效
|
||||
if sys_cfg.password.timeout != 0:
|
||||
_time_now = tp_timestamp_sec()
|
||||
if user_info['last_chpass'] + (sys_cfg.password.timeout * 60 * 60 * 24) < _time_now:
|
||||
if user_info['last_chpass'] + (sys_cfg.password.timeout * 60 * 60 * 24) < time_now:
|
||||
syslog.sys_log(user_info, handler.request.remote_ip, TPE_USER_AUTH, msg)
|
||||
return TPE_EXPIRED, None, '登录失败,用户密码已过期'
|
||||
|
||||
|
@ -180,7 +178,7 @@ def login(handler, username, login_type=None, password=None, oath_code=None, che
|
|||
def get_users(sql_filter, sql_order, sql_limit, sql_restrict, sql_exclude):
|
||||
dbtp = get_db().table_prefix
|
||||
s = SQL(get_db())
|
||||
s.select_from('user', ['id', 'type', 'auth_type', 'username', 'surname', 'role_id', 'state', 'email', 'last_login', 'valid_from', 'valid_to'],
|
||||
s.select_from('user', ['id', 'type', 'auth_type', 'username', 'surname', 'role_id', 'state', 'email', 'last_login', 'valid_from', 'valid_to', 'desc'],
|
||||
alt_name='u')
|
||||
s.left_join('role', ['name', 'privilege'], join_on='r.id=u.role_id', alt_name='r', out_map={'name': 'role'})
|
||||
|
||||
|
|
Loading…
Reference in New Issue