diff --git a/.idea/encodings.xml b/.idea/encodings.xml index 822fd6c..a7f20b6 100644 --- a/.idea/encodings.xml +++ b/.idea/encodings.xml @@ -2,7 +2,9 @@ + + @@ -34,6 +36,7 @@ + diff --git a/build/builder/build-installer.py b/build/builder/build-installer.py index 2d66158..30408d8 100644 --- a/build/builder/build-installer.py +++ b/build/builder/build-installer.py @@ -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')) diff --git a/client/tp_assist_macos/TP-Assist.xcodeproj/project.pbxproj b/client/tp_assist_macos/TP-Assist.xcodeproj/project.pbxproj index c86b523..efd8eee 100644 --- a/client/tp_assist_macos/TP-Assist.xcodeproj/project.pbxproj +++ b/client/tp_assist_macos/TP-Assist.xcodeproj/project.pbxproj @@ -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 = ""; }; 7AA2CD581F6AC0DA0074C92B /* site */ = {isa = PBXFileReference; lastKnownFileType = folder; path = site; sourceTree = ""; }; 7AAE4B232390E642007EDDE7 /* mongoose.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mongoose.h; path = ../../../../external/mongoose/mongoose.h; sourceTree = ""; }; + 7AF6593C27398C7400057A00 /* ts_ws_client.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ts_ws_client.cpp; sourceTree = ""; }; + 7AF6593D27398C7400057A00 /* ts_ws_client.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ts_ws_client.h; sourceTree = ""; }; + 7AF6593F2739939E00057A00 /* ts_utils.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ts_utils.cpp; sourceTree = ""; }; + 7AF659402739939E00057A00 /* ts_utils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ts_utils.h; sourceTree = ""; }; 7AF9BF212199E32B00BE5DBC /* libmbedx509.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libmbedx509.a; path = ../../external/macos/release/lib/libmbedx509.a; sourceTree = ""; }; 7AF9BF222199E32B00BE5DBC /* libmbedtls.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libmbedtls.a; path = ../../external/macos/release/lib/libmbedtls.a; sourceTree = ""; }; 7AF9BF232199E32B00BE5DBC /* libmbedcrypto.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libmbedcrypto.a; path = ../../external/macos/release/lib/libmbedcrypto.a; sourceTree = ""; }; @@ -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 = ""; @@ -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; diff --git a/client/tp_assist_macos/site/index.html b/client/tp_assist_macos/site/index.html index caecd17..2adb9ed 100644 --- a/client/tp_assist_macos/site/index.html +++ b/client/tp_assist_macos/site/index.html @@ -53,7 +53,6 @@ -

本地 SSH 客户端配置

diff --git a/client/tp_assist_macos/src/AppDelegate-C-Interface.cpp b/client/tp_assist_macos/src/AppDelegate-C-Interface.cpp index 8463e1a..bafac88 100644 --- a/client/tp_assist_macos/src/AppDelegate-C-Interface.cpp +++ b/client/tp_assist_macos/src/AppDelegate-C-Interface.cpp @@ -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(pid); +//} + +void url_scheme_handler(const std::string& url) +{ + TsWsClient::url_scheme_handler(url); +} diff --git a/client/tp_assist_macos/src/AppDelegate-C-Interface.h b/client/tp_assist_macos/src/AppDelegate-C-Interface.h index f6c289f..316e8f7 100644 --- a/client/tp_assist_macos/src/AppDelegate-C-Interface.h +++ b/client/tp_assist_macos/src/AppDelegate-C-Interface.h @@ -8,10 +8,19 @@ #ifndef wrap_c_objc_h #define wrap_c_objc_h +#include + +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 */ diff --git a/client/tp_assist_macos/src/AppDelegate.mm b/client/tp_assist_macos/src/AppDelegate.mm index 0f25ae0..1c2952a 100644 --- a/client/tp_assist_macos/src/AppDelegate.mm +++ b/client/tp_assist_macos/src/AppDelegate.mm @@ -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 diff --git a/client/tp_assist_macos/src/Base.lproj/Localizable.strings b/client/tp_assist_macos/src/Base.lproj/Localizable.strings index 4773301..9f206b9 100644 --- a/client/tp_assist_macos/src/Base.lproj/Localizable.strings +++ b/client/tp_assist_macos/src/Base.lproj/Localizable.strings @@ -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"; diff --git a/client/tp_assist_macos/src/TP-Assist-Info.plist b/client/tp_assist_macos/src/TP-Assist-Info.plist index de9fa1d..cc46df3 100644 --- a/client/tp_assist_macos/src/TP-Assist-Info.plist +++ b/client/tp_assist_macos/src/TP-Assist-Info.plist @@ -17,11 +17,26 @@ CFBundlePackageType APPL CFBundleShortVersionString - 3.5.6 + $(MARKETING_VERSION) CFBundleSignature ???? + CFBundleURLTypes + + + CFBundleTypeRole + Viewer + CFBundleURLIconFile + tpassist + CFBundleURLName + com.tp4a.assist + CFBundleURLSchemes + + teleport + + + CFBundleVersion - 3.5.6 + $(CURRENT_PROJECT_VERSION) LSApplicationCategoryType public.app-category.productivity LSMinimumSystemVersion diff --git a/client/tp_assist_macos/src/csrc/ts_cfg.cpp b/client/tp_assist_macos/src/csrc/ts_cfg.cpp index 4896d37..005c9e9 100644 --- a/client/tp_assist_macos/src/csrc/ts_cfg.cpp +++ b/client/tp_assist_macos/src/csrc/ts_cfg.cpp @@ -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 jwriter(jwb.newStreamWriter()); ex_aoss os; jwriter->write(m_root, &os); diff --git a/client/tp_assist_macos/src/csrc/ts_cfg.h b/client/tp_assist_macos/src/csrc/ts_cfg.h index 741b5d9..97b9033 100644 --- a/client/tp_assist_macos/src/csrc/ts_cfg.h +++ b/client/tp_assist_macos/src/csrc/ts_cfg.h @@ -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; diff --git a/client/tp_assist_macos/src/csrc/ts_http_rpc.cpp b/client/tp_assist_macos/src/csrc/ts_http_rpc.cpp index 79e6344..bba3abf 100644 --- a/client/tp_assist_macos/src/csrc/ts_http_rpc.cpp +++ b/client/tp_assist_macos/src/csrc/ts_http_rpc.cpp @@ -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") { diff --git a/client/tp_assist_macos/src/csrc/ts_utils.cpp b/client/tp_assist_macos/src/csrc/ts_utils.cpp new file mode 100644 index 0000000..b9188cf --- /dev/null +++ b/client/tp_assist_macos/src/csrc/ts_utils.cpp @@ -0,0 +1,39 @@ +#include +#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; +} diff --git a/client/tp_assist_macos/src/csrc/ts_utils.h b/client/tp_assist_macos/src/csrc/ts_utils.h new file mode 100644 index 0000000..d3f83d7 --- /dev/null +++ b/client/tp_assist_macos/src/csrc/ts_utils.h @@ -0,0 +1,8 @@ +#ifndef __TS_UTILS_H__ +#define __TS_UTILS_H__ + +#include + +int ts_url_decode(const char *src, int src_len, char *dst, int dst_len, int is_form_url_encoded); + +#endif // __TS_UTILS_H__ diff --git a/client/tp_assist_macos/src/csrc/ts_ver.h b/client/tp_assist_macos/src/csrc/ts_ver.h index bcff7cb..c86e996 100644 --- a/client/tp_assist_macos/src/csrc/ts_ver.h +++ b/client/tp_assist_macos/src/csrc/ts_ver.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__ diff --git a/client/tp_assist_macos/src/csrc/ts_ws_client.cpp b/client/tp_assist_macos/src/csrc/ts_ws_client.cpp new file mode 100644 index 0000000..0d18030 --- /dev/null +++ b/client/tp_assist_macos/src/csrc/ts_ws_client.cpp @@ -0,0 +1,836 @@ +#include + +#include + +#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 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 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 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 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); + } +} diff --git a/client/tp_assist_macos/src/csrc/ts_ws_client.h b/client/tp_assist_macos/src/csrc/ts_ws_client.h new file mode 100644 index 0000000..c3fc071 --- /dev/null +++ b/client/tp_assist_macos/src/csrc/ts_ws_client.h @@ -0,0 +1,85 @@ +#ifndef __TS_WS_CLIENT_H__ +#define __TS_WS_CLIENT_H__ + +#include "ts_const.h" + +#include +#include +#include + +#include +#include +#include + +#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__ diff --git a/common/libex/include/ex/ex_path.h b/common/libex/include/ex/ex_path.h index 742a0d2..7e8be9a 100644 --- a/common/libex/include/ex/ex_path.h +++ b/common/libex/include/ex/ex_path.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); diff --git a/common/libex/src/ex_path.cpp b/common/libex/src/ex_path.cpp index c9ce1e4..a3ca7b9 100644 --- a/common/libex/src/ex_path.cpp +++ b/common/libex/src/ex_path.cpp @@ -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 diff --git a/dist/server/daemon/stop.sh.in b/dist/server/daemon/stop.sh.in index 4b83ecf..ef0dcec 100644 --- a/dist/server/daemon/stop.sh.in +++ b/dist/server/daemon/stop.sh.in @@ -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}}'` diff --git a/server/tp_core/core/ts_http_rpc.cpp b/server/tp_core/core/ts_http_rpc.cpp index e5feb0f..572dd49 100644 --- a/server/tp_core/core/ts_http_rpc.cpp +++ b/server/tp_core/core/ts_http_rpc.cpp @@ -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 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 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 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 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); } diff --git a/server/tp_core/protocol/ssh/ssh_session.cpp b/server/tp_core/protocol/ssh/ssh_session.cpp index e81e714..b47d317 100644 --- a/server/tp_core/protocol/ssh/ssh_session.cpp +++ b/server/tp_core/protocol/ssh/ssh_session.cpp @@ -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; } } diff --git a/server/www/teleport/static/css/dashboard.css b/server/www/teleport/static/css/dashboard.css index ad92e13..c2646c5 100644 --- a/server/www/teleport/static/css/dashboard.css +++ b/server/www/teleport/static/css/dashboard.css @@ -1 +1 @@ -@charset "utf-8";html{font-size:13px}body{font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;background-color:#e9e9e9;color:#333}html,body{height:100%}#page-container{min-width:1260px}a{text-decoration:none}a:link{text-decoration:none}a:hover{text-decoration:none}a:active{text-decoration:none}a:visited{text-decoration:none}select{outline:none}label{font-weight:normal}.clear-float{clear:both}.bigger{font-size:120%}.normal-text{font-size:13px;color:#333}.mono{font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace}.important{color:#d45f1c}.error{color:#d34242}.bold{font-weight:bold}hr.hr-sm{padding:1px 0;margin:5px 0;border-top:1px dashed #c4c4c4}ul{list-style:none}ul.list{margin:0;padding:3px 0 5px 0}ul.list li{margin:3px 3px 5px 10px}.btn-single-line{white-space:nowrap}.btn-single-line .btn:first-child{border-top-left-radius:3px;border-bottom-left-radius:3px}.btn-single-line .btn:last-child{border-top-right-radius:3px;border-bottom-right-radius:3px}hr.small{margin:5px 0}.dlg-protocol-group{margin-bottom:3px}.dlg-protocol-group ul{display:block;height:28px;margin:0;padding:0}.dlg-protocol-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;background-color:#eee;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.dlg-protocol-group ul li.item-name{width:120px}.dlg-protocol-group ul li.item-btn{background:none;padding:0;border:none}.dlg-protocol-group ul li.item-input{background:none;border:none;padding:0}.dlg-protocol-group ul li .form-control{line-height:1.5;margin:0;padding:4px 5px;font-size:12px;height:28px;border-radius:0;border-left:none;width:100px}.dlg-protocol-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.dlg-protocol-group ul li input[type=checkbox]{display:block;float:left;margin:3px 5px 0 0}.dlg-protocol-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:first-child .btn,.dlg-protocol-group ul li:first-child .form-control{border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}.dlg-protocol-group ul li:last-child .btn,.dlg-protocol-group ul li:last-child .form-control{border-top-right-radius:4px;border-bottom-right-radius:4px}.os-icon-windows:after{color:#00bcf6;content:"\f17a";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;content:"\f17c";font-size:18px;width:24px;height:24px;line-height:24px;background-color:#333;border-radius:50%;display:inline-block;font-family:'Font Awesome 5 Brands';font-weight:400}.os-icon-macos:after{color:#a7a7a7;content:"\f179";font-size:20px;width:24px;height:24px;line-height:24px;display:inline-block;font-family:'Font Awesome 5 Brands';font-weight:400}.os-icon-ubuntu:after,.os-icon-debian:after,.os-icon-centos:after,.os-icon-redhat:after{content:" ";width:24px;height:24px;line-height:24px;display:inline-block}.os-icon-ubuntu:after{background:url(../img/os-icon/ubuntu-24x24.png) no-repeat}.os-icon-debian:after{background:url(../img/os-icon/debian-24x24.png) no-repeat}.os-icon-centos:after{background:url(../img/os-icon/centos-24x24.png) no-repeat}.os-icon-redhat:after{background:url(../img/os-icon/redhat-24x24.png) no-repeat}.disable-bg{position:absolute;background:url(../img/css/disable-bg.png) repeat;opacity:.45;z-index:990}.disable-message{display:inline-block;font-size:160%;position:absolute;padding:20px 40px;border:1px solid #2b0002;background-color:#65181a;color:#fff;opacity:.85;z-index:991}.btn-group-sm>.btn{padding:3px 5px;font-size:12px}.pop-menu-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040}.form-group{margin-bottom:5px}.badge{padding:3px 6px;border-radius:10px;font-size:13px;font-weight:400;background-color:#999}.badge.badge-sm{font-size:12px;padding:3px 5px;margin-top:0;border-radius:8px;text-shadow:none}.badge.badge-sup{margin-left:-8px;margin-top:-16px}.badge.badge-ignore{background-color:#e5e5e5;color:#999}.badge.badge-info{background-color:#33b7d0}.badge.badge-primary{background-color:#348fe2}.badge.badge-success{background-color:#368142}.badge.badge-warning{background-color:#f57523}.badge.badge-danger{background-color:#d34242}.btn-success .badge{color:#fff}.label{display:inline-block;padding:5px 10px;margin:2px;font-size:13px;font-weight:400;background-color:#999}.label.label-sm{font-size:12px;padding:3px 8px 4px 8px;margin-top:0;border-radius:3px}.label.label-ignore{background-color:#e5e5e5;color:#aaa;text-shadow:-1px -1px 1px #fff}.label.label-info{background-color:#33b7d0}.label.label-primary{background-color:#348fe2}.label.label-success{background-color:#368142}.label.label-warning{background-color:#f57523}.label.label-danger{background-color:#d34242}.progress.progress-sm{height:18px;margin-bottom:2px;background-color:#aaa}.progress.progress-sm.button{cursor:pointer}.progress.progress-sm .progress-bar{display:block;font-size:11px;float:none}.modal-dialog .modal-content .modal-header{background-color:#f7f7f7}.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,.col-sm-12{padding-right:5px;padding-left:5px}.input-group :-moz-placeholder{color:#d2d2d2}.input-group ::-moz-placeholder{color:#d2d2d2}.input-group input:-ms-input-placeholder,.input-group textarea:-ms-input-placeholder{color:#d2d2d2}.input-group input::-webkit-input-placeholder,.input-group textarea::-webkit-input-placeholder{color:#d2d2d2}.modal .modal-content{border-radius:0}.modal .modal-header .close{margin-top:-4px;margin-right:-6px}.modal .modal-header .close:hover{color:#9c3023;opacity:1}.modal .modal-header .close:active,.modal .modal-header .close:focus,.modal .modal-header .close:visited{-webkit-appearance:none}.modal .form-horizontal .form-group,.modal .row{margin-left:0;margin-right:0;padding-bottom:8px}.alert{border-radius:0;padding:5px;margin-bottom:10px}.dropdown-menu{min-width:0;font-size:13px}.form-control-sm{padding:3px 5px;font-size:13px;height:inherit}.form-group .control-label.require{color:#505050;font-weight:bold}.form-group .control-label.require:before{color:#ac4e43;position:absolute;margin-left:-1.2em;margin-top:1px;content:"\f069";font-size:8px;font-family:'Font Awesome 5 Free';font-weight:900}.form-group .control-desc{padding-top:6px;color:#999}.form-group .control-desc-sm{color:#999;padding-top:3px;font-size:12px}label.form-control-static input{display:inline-block;position:relative;margin-top:4px}.control-desc .popover{max-width:none;font-size:13px}.table-extend-cell .btn-group-sm .btn,.table-prefix-area .btn-group-sm .btn{padding:5px 5px}#gritter-notice-wrapper{z-index:9999}.gritter-bottom,.gritter-item,.gritter-top{background:rgba(0,0,0,0.8) !important}.gritter-top{border-top-left-radius:3px;border-top-right-radius:3px}.gritter-bottom{border-bottom-left-radius:3px;border-bottom-right-radius:3px}.gritter-close,.gritter-light .gritter-close{left:auto !important;right:5px !important;top:5px !important;width:16px !important;height:16px !important;line-height:16px !important;display:block !important;border-radius:50%}.gritter-close:before,.gritter-light .gritter-close:before{content:'\f00d' !important;font-family:'Font Awesome 5 Free' !important;font-weight:900 !important;font-size:9px !important;width:16px !important;height:16px !important;line-height:16px !important;color:#fff !important;text-indent:0 !important;position:absolute !important;text-align:center !important;right:0 !important;top:0 !important}.gritter-title{font-size:13px !important;line-height:16px !important;padding-bottom:5px !important;font-weight:400 !important;color:#fff !important;text-shadow:none !important}.gritter-item{color:#aaa !important;font-size:13px !important;padding:2px 15px 5px !important}.gritter-error .gritter-bottom,.gritter-error .gritter-item,.gritter-error .gritter-top{background:rgba(123,32,32,0.9) !important}.gritter-error .gritter-title{color:#fff !important}.gritter-error .gritter-item{color:#ddd !important}.gritter-error .gritter-close{left:auto !important;right:5px !important;top:5px !important;width:16px !important;height:16px !important;line-height:16px !important;display:block !important;border-radius:50%;background:#e33b3b !important}.gritter-success .gritter-bottom,.gritter-success .gritter-item,.gritter-success .gritter-top{background:rgba(1,65,16,0.9) !important}.gritter-success .gritter-title{color:#ddd !important}.gritter-success .gritter-item{color:#ccc !important}.gritter-success .gritter-close{background:#0eb320 !important}#gritter-notice-wrapper{width:320px;max-width:480px}.page-content-dashboard{padding:20px 25px}.sys-msg{border:1px solid #ff8987;border-radius:5px;background-color:#ffbdb7;padding:10px;margin-bottom:10px;text-align:center;display:none}.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,.col-sm-12{padding-right:10px;padding-left:10px}.stats{overflow:hidden;color:#686868;background-color:#fff;margin-bottom:10px}.stats.stats-id-host{border-top:5px solid #348fe2;background-color:#e7f1fb}.stats.stats-id-user{border-top:5px solid #f57523;background-color:#feefe6}.stats.stats-id-account{border-top:5px solid #d34242;background-color:#fae7e7}.stats.stats-id-connect{border-top:5px solid #368142;background-color:#def1e1}.stats.stats-box{position:relative;height:98px;box-shadow:1px 1px 2px rgba(0,0,0,0.3)}.stats.stats-box .stats-content{padding-left:20px}.stats.stats-box .stats-icon{font-size:130px;line-height:130px;top:5px;right:-40px;position:absolute;color:rgba(0,0,0,0.07)}.stats.stats-box .stats-name{font-size:16px;font-weight:500;padding-top:10px;color:rgba(0,0,0,0.6)}.stats.stats-box .stats-value{display:inline;color:rgba(0,0,0,0.6);cursor:pointer;font-size:42px;font-weight:300;white-space:nowrap;padding-left:20px}.stats.stats-bar{position:relative;height:200px;padding:8px;box-shadow:1px 1px 2px rgba(0,0,0,0.3)}.stats.stats-bar .stats-value{margin-top:5px;height:180px}.stats.stats-first{border-left:none}.stats a{color:#eee;color:rgba(255,255,255,0.7)}.stats a:hover{color:#fff}/*# sourceMappingURL=dashboard.css.map */ \ No newline at end of file +@charset "utf-8";html{font-size:13px}body{font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;background-color:#e9e9e9;color:#333}html,body{height:100%}#page-container{min-width:1260px}a{text-decoration:none}a:link{text-decoration:none}a:hover{text-decoration:none}a:active{text-decoration:none}a:visited{text-decoration:none}select{outline:none}label{font-weight:normal}.clear-float{clear:both}.bigger{font-size:120%}.normal-text{font-size:13px;color:#333}.mono{font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace}.important{color:#d45f1c}.error{color:#d34242}.bold{font-weight:bold}hr.hr-sm{padding:1px 0;margin:5px 0;border-top:1px dashed #c4c4c4}ul{list-style:none}ul.list{margin:0;padding:3px 0 5px 0}ul.list li{margin:3px 3px 5px 10px}.btn-single-line{white-space:nowrap}.btn-single-line .btn:first-child{border-top-left-radius:3px;border-bottom-left-radius:3px}.btn-single-line .btn:last-child{border-top-right-radius:3px;border-bottom-right-radius:3px}hr.small{margin:5px 0}.dlg-protocol-group{margin-bottom:3px}.dlg-protocol-group ul{display:block;height:28px;margin:0;padding:0}.dlg-protocol-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;background-color:#eee;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.dlg-protocol-group ul li.item-name{width:120px}.dlg-protocol-group ul li.item-btn{background:none;padding:0;border:none}.dlg-protocol-group ul li.item-input{background:none;border:none;padding:0}.dlg-protocol-group ul li .form-control{line-height:1.5;margin:0;padding:4px 5px;font-size:12px;height:28px;border-radius:0;border-left:none;width:100px}.dlg-protocol-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.dlg-protocol-group ul li input[type=checkbox]{display:block;float:left;margin:3px 5px 0 0}.dlg-protocol-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:first-child .btn,.dlg-protocol-group ul li:first-child .form-control{border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}.dlg-protocol-group ul li:last-child .btn,.dlg-protocol-group ul li:last-child .form-control{border-top-right-radius:4px;border-bottom-right-radius:4px}.os-icon-windows:after{font-style:normal;content:"\f17a";display:inline-block;font-family:'Font Awesome 5 Brands';font-weight:400}.os-icon-linux:after{font-style:normal;content:"\f17c";background-color:#333;border-radius:50%;display:inline-block;font-family:'Font Awesome 5 Brands';font-weight:400}.os-icon-macos:after{font-style:normal;content:"\f179";display:inline-block;font-family:'Font Awesome 5 Brands';font-weight:400}.os-icon-ubuntu:after,.os-icon-debian:after,.os-icon-centos:after,.os-icon-redhat:after{content:" ";width:24px;height:24px;line-height:24px;display:inline-block}.os-icon-ubuntu:after{background:url(../img/os-icon/ubuntu-24x24.png) no-repeat}.os-icon-debian:after{background:url(../img/os-icon/debian-24x24.png) no-repeat}.os-icon-centos:after{background:url(../img/os-icon/centos-24x24.png) no-repeat}.os-icon-redhat:after{background:url(../img/os-icon/redhat-24x24.png) no-repeat}.disable-bg{position:absolute;background:url(../img/css/disable-bg.png) repeat;opacity:.45;z-index:990}.disable-message{display:inline-block;font-size:160%;position:absolute;padding:20px 40px;border:1px solid #2b0002;background-color:#65181a;color:#fff;opacity:.85;z-index:991}.center{text-align:center}.btn-group-sm>.btn{padding:3px 5px;font-size:12px}.pop-menu-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040}.form-group{margin-bottom:5px}.badge{padding:3px 6px;border-radius:10px;font-size:13px;font-weight:400;background-color:#999}.badge.badge-sm{font-size:12px;padding:3px 5px;margin-top:0;border-radius:8px;text-shadow:none}.badge.badge-sup{margin-left:-8px;margin-top:-16px}.badge.badge-ignore{background-color:#e5e5e5;color:#999}.badge.badge-info{background-color:#33b7d0}.badge.badge-primary{background-color:#348fe2}.badge.badge-success{background-color:#368142}.badge.badge-warning{background-color:#f57523}.badge.badge-danger{background-color:#d34242}.btn-success .badge{color:#fff}.label{display:inline-block;padding:5px 10px;margin:2px;font-size:13px;font-weight:400;background-color:#999}.label.label-sm{font-size:12px;padding:3px 8px 4px 8px;margin-top:0;border-radius:3px}.label.label-ignore{background-color:#e5e5e5;color:#aaa;text-shadow:-1px -1px 1px #fff}.label.label-info{background-color:#33b7d0}.label.label-primary{background-color:#348fe2}.label.label-success{background-color:#368142}.label.label-warning{background-color:#f57523}.label.label-danger{background-color:#d34242}.progress.progress-sm{height:18px;margin-bottom:2px;background-color:#aaa}.progress.progress-sm.button{cursor:pointer}.progress.progress-sm .progress-bar{display:block;font-size:11px;float:none}.modal-dialog .modal-content .modal-header{background-color:#f7f7f7}.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,.col-sm-12{padding-right:5px;padding-left:5px}.input-group :-moz-placeholder{color:#d2d2d2}.input-group ::-moz-placeholder{color:#d2d2d2}.input-group input:-ms-input-placeholder,.input-group textarea:-ms-input-placeholder{color:#d2d2d2}.input-group input::-webkit-input-placeholder,.input-group textarea::-webkit-input-placeholder{color:#d2d2d2}.modal .modal-content{border-radius:0}.modal .modal-header .close{margin-top:-4px;margin-right:-6px}.modal .modal-header .close:hover{color:#9c3023;opacity:1}.modal .modal-header .close:active,.modal .modal-header .close:focus,.modal .modal-header .close:visited{-webkit-appearance:none}.modal .form-horizontal .form-group,.modal .row{margin-left:0;margin-right:0;padding-bottom:8px}.alert{border-radius:0;padding:5px;margin-bottom:10px}.dropdown-menu{min-width:0;font-size:13px}.form-control-sm{padding:3px 5px;font-size:13px;height:inherit}.form-group .control-label.require{color:#505050;font-weight:bold}.form-group .control-label.require:before{color:#ac4e43;position:absolute;margin-left:-1.2em;margin-top:1px;content:"\f069";font-size:8px;font-family:'Font Awesome 5 Free';font-weight:900}.form-group .control-desc{padding-top:6px;color:#999}.form-group .control-desc-sm{color:#999;padding-top:3px;font-size:12px}label.form-control-static input{display:inline-block;position:relative;margin-top:4px}.control-desc .popover{max-width:none;font-size:13px}.table-extend-cell .btn-group-sm .btn,.table-prefix-area .btn-group-sm .btn{padding:5px 5px}#gritter-notice-wrapper{z-index:9999}.gritter-bottom,.gritter-item,.gritter-top{background:rgba(0,0,0,0.8) !important}.gritter-top{border-top-left-radius:3px;border-top-right-radius:3px}.gritter-bottom{border-bottom-left-radius:3px;border-bottom-right-radius:3px}.gritter-close,.gritter-light .gritter-close{left:auto !important;right:5px !important;top:5px !important;width:16px !important;height:16px !important;line-height:16px !important;display:block !important;border-radius:50%}.gritter-close:before,.gritter-light .gritter-close:before{content:'\f00d' !important;font-family:'Font Awesome 5 Free' !important;font-weight:900 !important;font-size:9px !important;width:16px !important;height:16px !important;line-height:16px !important;color:#fff !important;text-indent:0 !important;position:absolute !important;text-align:center !important;right:0 !important;top:0 !important}.gritter-title{font-size:13px !important;line-height:16px !important;padding-bottom:5px !important;font-weight:400 !important;color:#fff !important;text-shadow:none !important}.gritter-item{color:#aaa !important;font-size:13px !important;padding:2px 15px 5px !important}.gritter-error .gritter-bottom,.gritter-error .gritter-item,.gritter-error .gritter-top{background:rgba(123,32,32,0.9) !important}.gritter-error .gritter-title{color:#fff !important}.gritter-error .gritter-item{color:#ddd !important}.gritter-error .gritter-close{left:auto !important;right:5px !important;top:5px !important;width:16px !important;height:16px !important;line-height:16px !important;display:block !important;border-radius:50%;background:#e33b3b !important}.gritter-success .gritter-bottom,.gritter-success .gritter-item,.gritter-success .gritter-top{background:rgba(1,65,16,0.9) !important}.gritter-success .gritter-title{color:#ddd !important}.gritter-success .gritter-item{color:#ccc !important}.gritter-success .gritter-close{background:#0eb320 !important}#gritter-notice-wrapper{width:320px;max-width:480px}.page-content-dashboard{padding:20px 25px}.sys-msg{border:1px solid #ff8987;border-radius:5px;background-color:#ffbdb7;padding:10px;margin-bottom:10px;text-align:center;display:none}.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,.col-sm-12{padding-right:10px;padding-left:10px}.stats{overflow:hidden;color:#686868;background-color:#fff;margin-bottom:10px}.stats.stats-id-host{border-top:5px solid #348fe2;background-color:#e7f1fb}.stats.stats-id-user{border-top:5px solid #f57523;background-color:#feefe6}.stats.stats-id-account{border-top:5px solid #d34242;background-color:#fae7e7}.stats.stats-id-connect{border-top:5px solid #368142;background-color:#def1e1}.stats.stats-box{position:relative;height:98px;box-shadow:1px 1px 2px rgba(0,0,0,0.3)}.stats.stats-box .stats-content{padding-left:20px}.stats.stats-box .stats-icon{font-size:130px;line-height:130px;top:5px;right:-40px;position:absolute;color:rgba(0,0,0,0.07)}.stats.stats-box .stats-name{font-size:16px;font-weight:500;padding-top:10px;color:rgba(0,0,0,0.6)}.stats.stats-box .stats-value{display:inline;color:rgba(0,0,0,0.6);cursor:pointer;font-size:42px;font-weight:300;white-space:nowrap;padding-left:20px}.stats.stats-bar{position:relative;height:200px;padding:8px;box-shadow:1px 1px 2px rgba(0,0,0,0.3)}.stats.stats-bar .stats-value{margin-top:5px;height:180px}.stats.stats-first{border-left:none}.stats a{color:#eee;color:rgba(255,255,255,0.7)}.stats a:hover{color:#fff}/*# sourceMappingURL=dashboard.css.map */ \ No newline at end of file diff --git a/server/www/teleport/static/css/login.css b/server/www/teleport/static/css/login.css index 8a7157b..2bc9e82 100644 --- a/server/www/teleport/static/css/login.css +++ b/server/www/teleport/static/css/login.css @@ -1 +1 @@ -@charset "utf-8";html{font-size:13px}body{font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;background-color:#e9e9e9;color:#333}html,body{height:100%}#page-container{min-width:1260px}a{text-decoration:none}a:link{text-decoration:none}a:hover{text-decoration:none}a:active{text-decoration:none}a:visited{text-decoration:none}select{outline:none}label{font-weight:normal}.clear-float{clear:both}.bigger{font-size:120%}.normal-text{font-size:13px;color:#333}.mono{font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace}.important{color:#d45f1c}.error{color:#d34242}.bold{font-weight:bold}hr.hr-sm{padding:1px 0;margin:5px 0;border-top:1px dashed #c4c4c4}ul{list-style:none}ul.list{margin:0;padding:3px 0 5px 0}ul.list li{margin:3px 3px 5px 10px}.btn-single-line{white-space:nowrap}.btn-single-line .btn:first-child{border-top-left-radius:3px;border-bottom-left-radius:3px}.btn-single-line .btn:last-child{border-top-right-radius:3px;border-bottom-right-radius:3px}hr.small{margin:5px 0}.dlg-protocol-group{margin-bottom:3px}.dlg-protocol-group ul{display:block;height:28px;margin:0;padding:0}.dlg-protocol-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;background-color:#eee;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.dlg-protocol-group ul li.item-name{width:120px}.dlg-protocol-group ul li.item-btn{background:none;padding:0;border:none}.dlg-protocol-group ul li.item-input{background:none;border:none;padding:0}.dlg-protocol-group ul li .form-control{line-height:1.5;margin:0;padding:4px 5px;font-size:12px;height:28px;border-radius:0;border-left:none;width:100px}.dlg-protocol-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.dlg-protocol-group ul li input[type=checkbox]{display:block;float:left;margin:3px 5px 0 0}.dlg-protocol-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:first-child .btn,.dlg-protocol-group ul li:first-child .form-control{border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}.dlg-protocol-group ul li:last-child .btn,.dlg-protocol-group ul li:last-child .form-control{border-top-right-radius:4px;border-bottom-right-radius:4px}.os-icon-windows:after{color:#00bcf6;content:"\f17a";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;content:"\f17c";font-size:18px;width:24px;height:24px;line-height:24px;background-color:#333;border-radius:50%;display:inline-block;font-family:'Font Awesome 5 Brands';font-weight:400}.os-icon-macos:after{color:#a7a7a7;content:"\f179";font-size:20px;width:24px;height:24px;line-height:24px;display:inline-block;font-family:'Font Awesome 5 Brands';font-weight:400}.os-icon-ubuntu:after,.os-icon-debian:after,.os-icon-centos:after,.os-icon-redhat:after{content:" ";width:24px;height:24px;line-height:24px;display:inline-block}.os-icon-ubuntu:after{background:url(../img/os-icon/ubuntu-24x24.png) no-repeat}.os-icon-debian:after{background:url(../img/os-icon/debian-24x24.png) no-repeat}.os-icon-centos:after{background:url(../img/os-icon/centos-24x24.png) no-repeat}.os-icon-redhat:after{background:url(../img/os-icon/redhat-24x24.png) no-repeat}.disable-bg{position:absolute;background:url(../img/css/disable-bg.png) repeat;opacity:.45;z-index:990}.disable-message{display:inline-block;font-size:160%;position:absolute;padding:20px 40px;border:1px solid #2b0002;background-color:#65181a;color:#fff;opacity:.85;z-index:991}body{padding:0;margin:0;overflow:hidden}.bg-blur{position:fixed;top:-20px;left:-20px}.bg-blur-overlay{position:absolute;width:100%;height:100%;background-image:url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSI0NiUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wOCIvPjxzdG9wIG9mZnNldD0iNTklIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMDgiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC45Ii8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNncmFkKSIgLz48L3N2Zz4g');background-size:100%;background-image:-webkit-gradient(linear, 50% 0, 50% 100%, color-stop(46%, rgba(0,0,0,0.08)), color-stop(59%, rgba(0,0,0,0.08)), color-stop(100%, rgba(0,0,0,0.9)));background-image:-moz-linear-gradient(top, rgba(0,0,0,0.08) 46%, rgba(0,0,0,0.08) 59%, rgba(0,0,0,0.9) 100%);background-image:-webkit-linear-gradient(top, rgba(0,0,0,0.08) 46%, rgba(0,0,0,0.08) 59%, rgba(0,0,0,0.9) 100%);background-image:linear-gradient(to bottom, rgba(0,0,0,0.08) 46%, rgba(0,0,0,0.08) 59%, rgba(0,0,0,0.9) 100%)}.container{min-width:460px}#page-header nav.navbar{height:70px;margin-bottom:0;border:none;background-color:rgba(0,0,0,0.6);color:#fff}#page-header nav li{display:inline-block;float:left}#page-header .logo{position:relative;margin-top:10px;display:inline-block}#page-header .desc{position:relative;display:inline-block;color:#ccc;top:32px;font-size:24px;vertical-align:baseline;font-family:"Kai","华文楷体","楷体","Microsoft YaHei","微软雅黑",Helvetica,Arial,sans-serif}#page-footer nav.navbar{min-height:36px;height:36px;line-height:36px;background-color:rgba(0,0,0,0.6);font-size:12px;color:#6d6d6d}#page-footer nav.navbar .container{height:24px}#page-footer nav.navbar p{margin:0 auto;text-align:center}.auth-box-container{position:fixed;left:0;top:70px;width:100%}.auth-box-container .auth-box{margin:80px auto 0 auto;width:450px;border:1px solid #fff;border-radius:8px;background-color:rgba(255,255,255,0.6);box-shadow:0 5px 50px rgba(0,0,0,0.9)}.auth-box-container .auth-box .header{min-height:50px;height:50px;border:none;box-shadow:none;border-bottom:1px solid rgba(255,255,255,0.3)}.auth-box-container .auth-box .header .title{display:inline-block;float:left;margin-left:60px;height:24px;margin-top:25px;line-height:16px;font-size:20px;color:#484848}.auth-box-container .auth-box .header .title:hover{border-bottom:2px solid #5396eb}.auth-box-container .auth-box .header .selected{border-bottom:2px solid #4882cc;color:#262b40}.auth-box-container .auth-box .inputarea{margin:30px}.auth-box-container .auth-box .inputarea .input-group-addon{padding:0 10px}.auth-box-container .auth-box .inputarea p.input-addon-desc{text-align:right;padding:0 5px 0 5px;color:#636363}.auth-box-container .auth-box .inputbox{margin-bottom:20px}.auth-box-container .auth-box .op_box{display:block;padding:5px;border-radius:3px;text-align:center;margin:5px 20px 10px 20px}.auth-box-container .auth-box .op_error{background:rgba(255,5,0,0.5);color:#fff}.auth-box-container .auth-box .op_wait{background:rgba(255,255,255,0.3)}#slogan-box{padding-top:80px}#msg-slogan{text-align:right;font-size:24px;line-height:48px;font-family:"Kai","华文楷体","楷体","Microsoft YaHei","微软雅黑",Helvetica,Arial,sans-serif;color:rgba(255,255,255,0.5)}@media screen and (max-width:990px){#slogan-box{display:none}.auth-box{margin:30px auto 0 auto}}.btn-group-sm>.btn{padding:3px 5px;font-size:12px}.pop-menu-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040}.form-group{margin-bottom:5px}.badge{padding:3px 6px;border-radius:10px;font-size:13px;font-weight:400;background-color:#999}.badge.badge-sm{font-size:12px;padding:3px 5px;margin-top:0;border-radius:8px;text-shadow:none}.badge.badge-sup{margin-left:-8px;margin-top:-16px}.badge.badge-ignore{background-color:#e5e5e5;color:#999}.badge.badge-info{background-color:#33b7d0}.badge.badge-primary{background-color:#348fe2}.badge.badge-success{background-color:#368142}.badge.badge-warning{background-color:#f57523}.badge.badge-danger{background-color:#d34242}.btn-success .badge{color:#fff}.label{display:inline-block;padding:5px 10px;margin:2px;font-size:13px;font-weight:400;background-color:#999}.label.label-sm{font-size:12px;padding:3px 8px 4px 8px;margin-top:0;border-radius:3px}.label.label-ignore{background-color:#e5e5e5;color:#aaa;text-shadow:-1px -1px 1px #fff}.label.label-info{background-color:#33b7d0}.label.label-primary{background-color:#348fe2}.label.label-success{background-color:#368142}.label.label-warning{background-color:#f57523}.label.label-danger{background-color:#d34242}.progress.progress-sm{height:18px;margin-bottom:2px;background-color:#aaa}.progress.progress-sm.button{cursor:pointer}.progress.progress-sm .progress-bar{display:block;font-size:11px;float:none}.modal-dialog .modal-content .modal-header{background-color:#f7f7f7}.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,.col-sm-12{padding-right:5px;padding-left:5px}.input-group :-moz-placeholder{color:#d2d2d2}.input-group ::-moz-placeholder{color:#d2d2d2}.input-group input:-ms-input-placeholder,.input-group textarea:-ms-input-placeholder{color:#d2d2d2}.input-group input::-webkit-input-placeholder,.input-group textarea::-webkit-input-placeholder{color:#d2d2d2}.modal .modal-content{border-radius:0}.modal .modal-header .close{margin-top:-4px;margin-right:-6px}.modal .modal-header .close:hover{color:#9c3023;opacity:1}.modal .modal-header .close:active,.modal .modal-header .close:focus,.modal .modal-header .close:visited{-webkit-appearance:none}.modal .form-horizontal .form-group,.modal .row{margin-left:0;margin-right:0;padding-bottom:8px}.alert{border-radius:0;padding:5px;margin-bottom:10px}.dropdown-menu{min-width:0;font-size:13px}.form-control-sm{padding:3px 5px;font-size:13px;height:inherit}.form-group .control-label.require{color:#505050;font-weight:bold}.form-group .control-label.require:before{color:#ac4e43;position:absolute;margin-left:-1.2em;margin-top:1px;content:"\f069";font-size:8px;font-family:'Font Awesome 5 Free';font-weight:900}.form-group .control-desc{padding-top:6px;color:#999}.form-group .control-desc-sm{color:#999;padding-top:3px;font-size:12px}label.form-control-static input{display:inline-block;position:relative;margin-top:4px}.control-desc .popover{max-width:none;font-size:13px}.table-extend-cell .btn-group-sm .btn,.table-prefix-area .btn-group-sm .btn{padding:5px 5px}/*# sourceMappingURL=login.css.map */ \ No newline at end of file +@charset "utf-8";html{font-size:13px}body{font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;background-color:#e9e9e9;color:#333}html,body{height:100%}#page-container{min-width:1260px}a{text-decoration:none}a:link{text-decoration:none}a:hover{text-decoration:none}a:active{text-decoration:none}a:visited{text-decoration:none}select{outline:none}label{font-weight:normal}.clear-float{clear:both}.bigger{font-size:120%}.normal-text{font-size:13px;color:#333}.mono{font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace}.important{color:#d45f1c}.error{color:#d34242}.bold{font-weight:bold}hr.hr-sm{padding:1px 0;margin:5px 0;border-top:1px dashed #c4c4c4}ul{list-style:none}ul.list{margin:0;padding:3px 0 5px 0}ul.list li{margin:3px 3px 5px 10px}.btn-single-line{white-space:nowrap}.btn-single-line .btn:first-child{border-top-left-radius:3px;border-bottom-left-radius:3px}.btn-single-line .btn:last-child{border-top-right-radius:3px;border-bottom-right-radius:3px}hr.small{margin:5px 0}.dlg-protocol-group{margin-bottom:3px}.dlg-protocol-group ul{display:block;height:28px;margin:0;padding:0}.dlg-protocol-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;background-color:#eee;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.dlg-protocol-group ul li.item-name{width:120px}.dlg-protocol-group ul li.item-btn{background:none;padding:0;border:none}.dlg-protocol-group ul li.item-input{background:none;border:none;padding:0}.dlg-protocol-group ul li .form-control{line-height:1.5;margin:0;padding:4px 5px;font-size:12px;height:28px;border-radius:0;border-left:none;width:100px}.dlg-protocol-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.dlg-protocol-group ul li input[type=checkbox]{display:block;float:left;margin:3px 5px 0 0}.dlg-protocol-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:first-child .btn,.dlg-protocol-group ul li:first-child .form-control{border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}.dlg-protocol-group ul li:last-child .btn,.dlg-protocol-group ul li:last-child .form-control{border-top-right-radius:4px;border-bottom-right-radius:4px}.os-icon-windows:after{font-style:normal;content:"\f17a";display:inline-block;font-family:'Font Awesome 5 Brands';font-weight:400}.os-icon-linux:after{font-style:normal;content:"\f17c";background-color:#333;border-radius:50%;display:inline-block;font-family:'Font Awesome 5 Brands';font-weight:400}.os-icon-macos:after{font-style:normal;content:"\f179";display:inline-block;font-family:'Font Awesome 5 Brands';font-weight:400}.os-icon-ubuntu:after,.os-icon-debian:after,.os-icon-centos:after,.os-icon-redhat:after{content:" ";width:24px;height:24px;line-height:24px;display:inline-block}.os-icon-ubuntu:after{background:url(../img/os-icon/ubuntu-24x24.png) no-repeat}.os-icon-debian:after{background:url(../img/os-icon/debian-24x24.png) no-repeat}.os-icon-centos:after{background:url(../img/os-icon/centos-24x24.png) no-repeat}.os-icon-redhat:after{background:url(../img/os-icon/redhat-24x24.png) no-repeat}.disable-bg{position:absolute;background:url(../img/css/disable-bg.png) repeat;opacity:.45;z-index:990}.disable-message{display:inline-block;font-size:160%;position:absolute;padding:20px 40px;border:1px solid #2b0002;background-color:#65181a;color:#fff;opacity:.85;z-index:991}.center{text-align:center}body{padding:0;margin:0;overflow:hidden}.bg-blur{position:fixed;top:-20px;left:-20px}.bg-blur-overlay{position:absolute;width:100%;height:100%;background-image:url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSI0NiUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wOCIvPjxzdG9wIG9mZnNldD0iNTklIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMDgiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC45Ii8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNncmFkKSIgLz48L3N2Zz4g');background-size:100%;background-image:-webkit-gradient(linear, 50% 0, 50% 100%, color-stop(46%, rgba(0,0,0,0.08)), color-stop(59%, rgba(0,0,0,0.08)), color-stop(100%, rgba(0,0,0,0.9)));background-image:-moz-linear-gradient(top, rgba(0,0,0,0.08) 46%, rgba(0,0,0,0.08) 59%, rgba(0,0,0,0.9) 100%);background-image:-webkit-linear-gradient(top, rgba(0,0,0,0.08) 46%, rgba(0,0,0,0.08) 59%, rgba(0,0,0,0.9) 100%);background-image:linear-gradient(to bottom, rgba(0,0,0,0.08) 46%, rgba(0,0,0,0.08) 59%, rgba(0,0,0,0.9) 100%)}.container{min-width:460px}#page-header nav.navbar{height:70px;margin-bottom:0;border:none;background-color:rgba(0,0,0,0.6);color:#fff}#page-header nav li{display:inline-block;float:left}#page-header .logo{position:relative;margin-top:10px;display:inline-block}#page-header .desc{position:relative;display:inline-block;color:#ccc;top:32px;font-size:24px;vertical-align:baseline;font-family:"Kai","华文楷体","楷体","Microsoft YaHei","微软雅黑",Helvetica,Arial,sans-serif}#page-footer nav.navbar{min-height:36px;height:36px;line-height:36px;background-color:rgba(0,0,0,0.6);font-size:12px;color:#6d6d6d}#page-footer nav.navbar .container{height:24px}#page-footer nav.navbar p{margin:0 auto;text-align:center}.auth-box-container{position:fixed;left:0;top:70px;width:100%}.auth-box-container .auth-box{margin:80px auto 0 auto;width:450px;border:1px solid #fff;border-radius:8px;background-color:rgba(255,255,255,0.6);box-shadow:0 5px 50px rgba(0,0,0,0.9)}.auth-box-container .auth-box .header{min-height:50px;height:50px;border:none;box-shadow:none;border-bottom:1px solid rgba(255,255,255,0.3)}.auth-box-container .auth-box .header .title{display:inline-block;float:left;margin-left:60px;height:24px;margin-top:25px;line-height:16px;font-size:20px;color:#484848}.auth-box-container .auth-box .header .title:hover{border-bottom:2px solid #5396eb}.auth-box-container .auth-box .header .selected{border-bottom:2px solid #4882cc;color:#262b40}.auth-box-container .auth-box .inputarea{margin:30px}.auth-box-container .auth-box .inputarea .input-group-addon{padding:0 10px}.auth-box-container .auth-box .inputarea p.input-addon-desc{text-align:right;padding:0 5px 0 5px;color:#636363}.auth-box-container .auth-box .inputbox{margin-bottom:20px}.auth-box-container .auth-box .op_box{display:block;padding:5px;border-radius:3px;text-align:center;margin:5px 20px 10px 20px}.auth-box-container .auth-box .op_error{background:rgba(255,5,0,0.5);color:#fff}.auth-box-container .auth-box .op_wait{background:rgba(255,255,255,0.3)}#slogan-box{padding-top:80px}#msg-slogan{text-align:right;font-size:24px;line-height:48px;font-family:"Kai","华文楷体","楷体","Microsoft YaHei","微软雅黑",Helvetica,Arial,sans-serif;color:rgba(255,255,255,0.5)}@media screen and (max-width:990px){#slogan-box{display:none}.auth-box{margin:30px auto 0 auto}}.btn-group-sm>.btn{padding:3px 5px;font-size:12px}.pop-menu-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040}.form-group{margin-bottom:5px}.badge{padding:3px 6px;border-radius:10px;font-size:13px;font-weight:400;background-color:#999}.badge.badge-sm{font-size:12px;padding:3px 5px;margin-top:0;border-radius:8px;text-shadow:none}.badge.badge-sup{margin-left:-8px;margin-top:-16px}.badge.badge-ignore{background-color:#e5e5e5;color:#999}.badge.badge-info{background-color:#33b7d0}.badge.badge-primary{background-color:#348fe2}.badge.badge-success{background-color:#368142}.badge.badge-warning{background-color:#f57523}.badge.badge-danger{background-color:#d34242}.btn-success .badge{color:#fff}.label{display:inline-block;padding:5px 10px;margin:2px;font-size:13px;font-weight:400;background-color:#999}.label.label-sm{font-size:12px;padding:3px 8px 4px 8px;margin-top:0;border-radius:3px}.label.label-ignore{background-color:#e5e5e5;color:#aaa;text-shadow:-1px -1px 1px #fff}.label.label-info{background-color:#33b7d0}.label.label-primary{background-color:#348fe2}.label.label-success{background-color:#368142}.label.label-warning{background-color:#f57523}.label.label-danger{background-color:#d34242}.progress.progress-sm{height:18px;margin-bottom:2px;background-color:#aaa}.progress.progress-sm.button{cursor:pointer}.progress.progress-sm .progress-bar{display:block;font-size:11px;float:none}.modal-dialog .modal-content .modal-header{background-color:#f7f7f7}.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,.col-sm-12{padding-right:5px;padding-left:5px}.input-group :-moz-placeholder{color:#d2d2d2}.input-group ::-moz-placeholder{color:#d2d2d2}.input-group input:-ms-input-placeholder,.input-group textarea:-ms-input-placeholder{color:#d2d2d2}.input-group input::-webkit-input-placeholder,.input-group textarea::-webkit-input-placeholder{color:#d2d2d2}.modal .modal-content{border-radius:0}.modal .modal-header .close{margin-top:-4px;margin-right:-6px}.modal .modal-header .close:hover{color:#9c3023;opacity:1}.modal .modal-header .close:active,.modal .modal-header .close:focus,.modal .modal-header .close:visited{-webkit-appearance:none}.modal .form-horizontal .form-group,.modal .row{margin-left:0;margin-right:0;padding-bottom:8px}.alert{border-radius:0;padding:5px;margin-bottom:10px}.dropdown-menu{min-width:0;font-size:13px}.form-control-sm{padding:3px 5px;font-size:13px;height:inherit}.form-group .control-label.require{color:#505050;font-weight:bold}.form-group .control-label.require:before{color:#ac4e43;position:absolute;margin-left:-1.2em;margin-top:1px;content:"\f069";font-size:8px;font-family:'Font Awesome 5 Free';font-weight:900}.form-group .control-desc{padding-top:6px;color:#999}.form-group .control-desc-sm{color:#999;padding-top:3px;font-size:12px}label.form-control-static input{display:inline-block;position:relative;margin-top:4px}.control-desc .popover{max-width:none;font-size:13px}.table-extend-cell .btn-group-sm .btn,.table-prefix-area .btn-group-sm .btn{padding:5px 5px}/*# sourceMappingURL=login.css.map */ \ No newline at end of file diff --git a/server/www/teleport/static/css/single.css b/server/www/teleport/static/css/single.css index 29c2e47..00b0d7e 100644 --- a/server/www/teleport/static/css/single.css +++ b/server/www/teleport/static/css/single.css @@ -1 +1 @@ -@charset "utf-8";html{font-size:13px}body{font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;background-color:#e9e9e9;color:#333}html,body{height:100%}#page-container{min-width:1260px}a{text-decoration:none}a:link{text-decoration:none}a:hover{text-decoration:none}a:active{text-decoration:none}a:visited{text-decoration:none}select{outline:none}label{font-weight:normal}.clear-float{clear:both}.bigger{font-size:120%}.normal-text{font-size:13px;color:#333}.mono{font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace}.important{color:#d45f1c}.error{color:#d34242}.bold{font-weight:bold}hr.hr-sm{padding:1px 0;margin:5px 0;border-top:1px dashed #c4c4c4}ul{list-style:none}ul.list{margin:0;padding:3px 0 5px 0}ul.list li{margin:3px 3px 5px 10px}.btn-single-line{white-space:nowrap}.btn-single-line .btn:first-child{border-top-left-radius:3px;border-bottom-left-radius:3px}.btn-single-line .btn:last-child{border-top-right-radius:3px;border-bottom-right-radius:3px}hr.small{margin:5px 0}.dlg-protocol-group{margin-bottom:3px}.dlg-protocol-group ul{display:block;height:28px;margin:0;padding:0}.dlg-protocol-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;background-color:#eee;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.dlg-protocol-group ul li.item-name{width:120px}.dlg-protocol-group ul li.item-btn{background:none;padding:0;border:none}.dlg-protocol-group ul li.item-input{background:none;border:none;padding:0}.dlg-protocol-group ul li .form-control{line-height:1.5;margin:0;padding:4px 5px;font-size:12px;height:28px;border-radius:0;border-left:none;width:100px}.dlg-protocol-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.dlg-protocol-group ul li input[type=checkbox]{display:block;float:left;margin:3px 5px 0 0}.dlg-protocol-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:first-child .btn,.dlg-protocol-group ul li:first-child .form-control{border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}.dlg-protocol-group ul li:last-child .btn,.dlg-protocol-group ul li:last-child .form-control{border-top-right-radius:4px;border-bottom-right-radius:4px}.os-icon-windows:after{color:#00bcf6;content:"\f17a";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;content:"\f17c";font-size:18px;width:24px;height:24px;line-height:24px;background-color:#333;border-radius:50%;display:inline-block;font-family:'Font Awesome 5 Brands';font-weight:400}.os-icon-macos:after{color:#a7a7a7;content:"\f179";font-size:20px;width:24px;height:24px;line-height:24px;display:inline-block;font-family:'Font Awesome 5 Brands';font-weight:400}.os-icon-ubuntu:after,.os-icon-debian:after,.os-icon-centos:after,.os-icon-redhat:after{content:" ";width:24px;height:24px;line-height:24px;display:inline-block}.os-icon-ubuntu:after{background:url(../img/os-icon/ubuntu-24x24.png) no-repeat}.os-icon-debian:after{background:url(../img/os-icon/debian-24x24.png) no-repeat}.os-icon-centos:after{background:url(../img/os-icon/centos-24x24.png) no-repeat}.os-icon-redhat:after{background:url(../img/os-icon/redhat-24x24.png) no-repeat}.disable-bg{position:absolute;background:url(../img/css/disable-bg.png) repeat;opacity:.45;z-index:990}.disable-message{display:inline-block;font-size:160%;position:absolute;padding:20px 40px;border:1px solid #2b0002;background-color:#65181a;color:#fff;opacity:.85;z-index:991}.table{margin-bottom:10px}.table>thead>tr>th{vertical-align:middle;border-bottom:2px solid #ddd}.table.table-info-list{width:auto}.table.table-info-list td{border-top:1px dotted #ddd;padding:5px 5px;vertical-align:top}.table.table-info-list td.key{text-align:right;width:1px;white-space:nowrap}.table.table-info-list td.value{text-align:left;font-weight:bold;font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace;color:#3e3e3e}.table.table-info-list td .error{color:#cc3632;font-weight:bold}.table.table-info-list td .disabled{color:#848484}.table.table-info-list.table-info-list-lite{width:100%}.table.table-info-list.table-info-list-lite td{padding:5px 5px}.table.table-info-list.table-info-list-lite td.value{font-weight:normal}.table.table-info-list tr:first-child td{border-top:none}.table.table-config-list{width:100%}.table.table-config-list td{border:none;padding:5px}.table.table-config-list td.title{text-align:left;font-size:110%;font-weight:bolder}.table.table-config-list td.key{width:1px;white-space:nowrap;text-align:right;padding-right:15px}.table.table-config-list td.value{text-align:left}.table.table-config-list td.value input{width:4em;padding:0 5px;text-align:right}.table.table-config-list td.value .unit{margin-left:5px}.table.table-config-list td.value .desc{color:#999;margin-left:15px;display:inline-block}.table>thead>tr>th{padding:5px 5px;outline:none;white-space:nowrap;font-weight:normal;text-align:center;background-color:#ededed}.table>tbody>tr>td{padding:5px;text-align:center;vertical-align:middle}.table>tbody>tr>td .nowrap{white-space:nowrap}.table-data td.loading{text-align:left;padding:20px}.table-data .btn-group.open .dropdown-toggle{-webkit-box-shadow:none;box-shadow:none}.table.table-data thead .sorting,.table.table-data thead .sorting_asc,.table.table-data thead .sorting_desc{cursor:pointer}.table.table-data thead .sorting:after,.table.table-data thead .sorting_asc:after,.table.table-data thead .sorting_desc:after{bottom:4px;padding-left:5px;display:inline-block;font-family:'Font Awesome 5 Free';font-weight:900;opacity:.8}.table.table-data thead .sorting:after{opacity:.2;content:"\f0dc"}.table.table-data thead .sorting_asc:after{content:"\f0de"}.table.table-data thead .sorting_desc:after{content:"\f0dd"}.host-name{font-size:16px}.host-name-desc{cursor:pointer}.host-ip{font-size:12px;color:#999;display:inline-block;white-space:nowrap;font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace;overflow:hidden;text-overflow:ellipsis}.td-ip-list{padding-right:20px;padding-left:5px}.td-ip-show-more{font-size:14px;width:12px;float:right;display:block}.td-ip-item{min-width:12em;width:12em;height:18px;padding:2px 4px;margin:1px 0;color:#333;text-align:center;white-space:nowrap;border-radius:9px;line-height:11px;font-size:11px;background:#dfdfdf !important}.td-ip-item span{display:inline-block;font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace;font-size:11px;font-weight:400}.td-ip-item a{display:inline-block;width:14px;float:right;font-size:14px}.btn-group-sm>.btn{padding:3px 5px;font-size:12px}.pop-menu-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040}.form-group{margin-bottom:5px}.badge{padding:3px 6px;border-radius:10px;font-size:13px;font-weight:400;background-color:#999}.badge.badge-sm{font-size:12px;padding:3px 5px;margin-top:0;border-radius:8px;text-shadow:none}.badge.badge-sup{margin-left:-8px;margin-top:-16px}.badge.badge-ignore{background-color:#e5e5e5;color:#999}.badge.badge-info{background-color:#33b7d0}.badge.badge-primary{background-color:#348fe2}.badge.badge-success{background-color:#368142}.badge.badge-warning{background-color:#f57523}.badge.badge-danger{background-color:#d34242}.btn-success .badge{color:#fff}.label{display:inline-block;padding:5px 10px;margin:2px;font-size:13px;font-weight:400;background-color:#999}.label.label-sm{font-size:12px;padding:3px 8px 4px 8px;margin-top:0;border-radius:3px}.label.label-ignore{background-color:#e5e5e5;color:#aaa;text-shadow:-1px -1px 1px #fff}.label.label-info{background-color:#33b7d0}.label.label-primary{background-color:#348fe2}.label.label-success{background-color:#368142}.label.label-warning{background-color:#f57523}.label.label-danger{background-color:#d34242}.progress.progress-sm{height:18px;margin-bottom:2px;background-color:#aaa}.progress.progress-sm.button{cursor:pointer}.progress.progress-sm .progress-bar{display:block;font-size:11px;float:none}.modal-dialog .modal-content .modal-header{background-color:#f7f7f7}.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,.col-sm-12{padding-right:5px;padding-left:5px}.input-group :-moz-placeholder{color:#d2d2d2}.input-group ::-moz-placeholder{color:#d2d2d2}.input-group input:-ms-input-placeholder,.input-group textarea:-ms-input-placeholder{color:#d2d2d2}.input-group input::-webkit-input-placeholder,.input-group textarea::-webkit-input-placeholder{color:#d2d2d2}.modal .modal-content{border-radius:0}.modal .modal-header .close{margin-top:-4px;margin-right:-6px}.modal .modal-header .close:hover{color:#9c3023;opacity:1}.modal .modal-header .close:active,.modal .modal-header .close:focus,.modal .modal-header .close:visited{-webkit-appearance:none}.modal .form-horizontal .form-group,.modal .row{margin-left:0;margin-right:0;padding-bottom:8px}.alert{border-radius:0;padding:5px;margin-bottom:10px}.dropdown-menu{min-width:0;font-size:13px}.form-control-sm{padding:3px 5px;font-size:13px;height:inherit}.form-group .control-label.require{color:#505050;font-weight:bold}.form-group .control-label.require:before{color:#ac4e43;position:absolute;margin-left:-1.2em;margin-top:1px;content:"\f069";font-size:8px;font-family:'Font Awesome 5 Free';font-weight:900}.form-group .control-desc{padding-top:6px;color:#999}.form-group .control-desc-sm{color:#999;padding-top:3px;font-size:12px}label.form-control-static input{display:inline-block;position:relative;margin-top:4px}.control-desc .popover{max-width:none;font-size:13px}.table-extend-cell .btn-group-sm .btn,.table-prefix-area .btn-group-sm .btn{padding:5px 5px}body{padding:0;margin:0}#page-content{margin-bottom:44px}#page-footer nav.navbar{min-height:24px;height:24px;line-height:24px;background-color:#cdcdcd;font-size:12px;color:#6d6d6d}#page-footer nav.navbar .container{height:24px}#page-footer nav.navbar p{margin:0 auto;text-align:center}.page-header{box-shadow:0 0 3px rgba(0,0,0,0.5);min-height:48px;top:0;width:100%;height:48px;margin:0 0 10px;border:none;background-color:#2a2a2a}.page-header .top-navbar{min-height:48px;height:48px;line-height:47px;background-color:#3a3a3a;color:#ccc}.page-header .top-navbar a{color:#d5d5d5}.page-header .top-navbar a:hover{color:#5a8fee}.page-header .top-navbar .brand{float:left;display:inline-block;padding:12px 0;margin:0}.page-header .top-navbar .brand .site-logo{display:block;width:86px;height:24px;background:url(../img/site-logo-small.png) no-repeat}.page-header .top-navbar .breadcrumb-container{float:left;display:inline-block;margin:0;padding:0}.page-header .top-navbar .breadcrumb-container .breadcrumb{background-color:#3a3a3a;margin:0;border-radius:0;border:none;padding:0 0 0 20px;font-size:16px;color:#ccc}.page-header .top-navbar .breadcrumb-container .breadcrumb>li+li:before{font-size:18px;padding:0 5px;color:#555;content:'|'}.page-header .top-navbar .breadcrumb-container .breadcrumb>li.title{font-size:18px}.page-header .top-navbar .breadcrumb-container .breadcrumb>li.sub-title{font-size:14px;color:#b3b3b3;line-height:44px}.page-header .top-navbar .status-container{float:right}.op_box{display:block;padding:5px;margin:0}.op_box.op_error{background-color:#ffb8b5;border:1px solid #d47e7b;color:#333}.op_box.op_wait{background:#e5e5e5;border:1px solid #a8a8a8;color:#333}.op_box.op_success{background:#acf1b2;border:1px solid #82df82;color:#333}.info-box{width:100%;margin:30px auto}.info-box .info-icon-box{z-index:-1;position:absolute;min-height:194px;overflow:hidden}.info-box .info-icon-box>.fas,.info-box .info-icon-box .fa{margin-top:30px;font-size:164px}.info-box .info-message-box{min-height:328px;border:1px solid #fff;background-color:rgba(255,255,255,0.76);box-shadow:2px 2px 3px rgba(0,0,0,0.3);padding:15px 20px 35px 30px;margin-left:98.4px}.info-box .info-message-box .title{font-size:180%;margin:15px 0}.info-box .info-message-box hr{border-top:none;border-bottom:1px dashed #d3d3d3}.info-box .op_box{margin:5px 0;text-align:center}.content-box{background-color:#fff;padding:20px;box-shadow:1px 1px 1px rgba(0,0,0,0.3)}.content-box .welcome-message .fa{display:block;color:#ff272a;font-size:18px;float:left}.content-box .welcome-message span{display:block;line-height:18px;padding-left:23px}.content-box .table{width:auto;margin-left:20px}.content-box .table td{border-top:1px dotted #ddd;padding:5px}.content-box .table td.key{text-align:right}.content-box .table td.value{text-align:left;font-weight:bold}.content-box .table tr:first-child td{border-top:none}.content-box table.form{width:auto;margin-left:20px}.content-box table.form td{padding:5px;line-height:1.42857143;vertical-align:middle}.content-box table.form td.key{text-align:right}.content-box table.form td label{margin-bottom:0}.content-box table.form td .form-control{height:30px;padding:5px 10px;font-size:inherit;line-height:inherit}.content-box h1 .fa-spin{color:#aaa}.content-box h1{font-size:180%}.content-box h2{font-size:140%}.content-box .op_box{margin:5px 0}.content-box .steps-detail{display:none;margin:10px;padding:10px;border:1px solid #b4b4b4;background-color:#dcdcdc}.content-box .steps-detail p{padding-left:5px;margin:2px 0 2px 1px}.content-box .steps-detail p.error{color:#fff;margin:2px 0 2px 0;background-color:#cc3632;border:1px solid #9c2a26}.content-box .alert.alert-warning{color:#6a542d;border:1px solid #e2cab4;background-color:#ffe4cb}.content-box .error{color:#cc3632}#gritter-notice-wrapper{z-index:9999}.gritter-bottom,.gritter-item,.gritter-top{background:rgba(0,0,0,0.8) !important}.gritter-top{border-top-left-radius:3px;border-top-right-radius:3px}.gritter-bottom{border-bottom-left-radius:3px;border-bottom-right-radius:3px}.gritter-close,.gritter-light .gritter-close{left:auto !important;right:5px !important;top:5px !important;width:16px !important;height:16px !important;line-height:16px !important;display:block !important;border-radius:50%}.gritter-close:before,.gritter-light .gritter-close:before{content:'\f00d' !important;font-family:'Font Awesome 5 Free' !important;font-weight:900 !important;font-size:9px !important;width:16px !important;height:16px !important;line-height:16px !important;color:#fff !important;text-indent:0 !important;position:absolute !important;text-align:center !important;right:0 !important;top:0 !important}.gritter-title{font-size:13px !important;line-height:16px !important;padding-bottom:5px !important;font-weight:400 !important;color:#fff !important;text-shadow:none !important}.gritter-item{color:#aaa !important;font-size:13px !important;padding:2px 15px 5px !important}.gritter-error .gritter-bottom,.gritter-error .gritter-item,.gritter-error .gritter-top{background:rgba(123,32,32,0.9) !important}.gritter-error .gritter-title{color:#fff !important}.gritter-error .gritter-item{color:#ddd !important}.gritter-error .gritter-close{left:auto !important;right:5px !important;top:5px !important;width:16px !important;height:16px !important;line-height:16px !important;display:block !important;border-radius:50%;background:#e33b3b !important}.gritter-success .gritter-bottom,.gritter-success .gritter-item,.gritter-success .gritter-top{background:rgba(1,65,16,0.9) !important}.gritter-success .gritter-title{color:#ddd !important}.gritter-success .gritter-item{color:#ccc !important}.gritter-success .gritter-close{background:#0eb320 !important}#gritter-notice-wrapper{width:320px;max-width:480px}/*# sourceMappingURL=single.css.map */ \ No newline at end of file +@charset "utf-8";html{font-size:13px}body{font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;background-color:#e9e9e9;color:#333}html,body{height:100%}#page-container{min-width:1260px}a{text-decoration:none}a:link{text-decoration:none}a:hover{text-decoration:none}a:active{text-decoration:none}a:visited{text-decoration:none}select{outline:none}label{font-weight:normal}.clear-float{clear:both}.bigger{font-size:120%}.normal-text{font-size:13px;color:#333}.mono{font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace}.important{color:#d45f1c}.error{color:#d34242}.bold{font-weight:bold}hr.hr-sm{padding:1px 0;margin:5px 0;border-top:1px dashed #c4c4c4}ul{list-style:none}ul.list{margin:0;padding:3px 0 5px 0}ul.list li{margin:3px 3px 5px 10px}.btn-single-line{white-space:nowrap}.btn-single-line .btn:first-child{border-top-left-radius:3px;border-bottom-left-radius:3px}.btn-single-line .btn:last-child{border-top-right-radius:3px;border-bottom-right-radius:3px}hr.small{margin:5px 0}.dlg-protocol-group{margin-bottom:3px}.dlg-protocol-group ul{display:block;height:28px;margin:0;padding:0}.dlg-protocol-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;background-color:#eee;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.dlg-protocol-group ul li.item-name{width:120px}.dlg-protocol-group ul li.item-btn{background:none;padding:0;border:none}.dlg-protocol-group ul li.item-input{background:none;border:none;padding:0}.dlg-protocol-group ul li .form-control{line-height:1.5;margin:0;padding:4px 5px;font-size:12px;height:28px;border-radius:0;border-left:none;width:100px}.dlg-protocol-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.dlg-protocol-group ul li input[type=checkbox]{display:block;float:left;margin:3px 5px 0 0}.dlg-protocol-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:first-child .btn,.dlg-protocol-group ul li:first-child .form-control{border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}.dlg-protocol-group ul li:last-child .btn,.dlg-protocol-group ul li:last-child .form-control{border-top-right-radius:4px;border-bottom-right-radius:4px}.os-icon-windows:after{font-style:normal;content:"\f17a";display:inline-block;font-family:'Font Awesome 5 Brands';font-weight:400}.os-icon-linux:after{font-style:normal;content:"\f17c";background-color:#333;border-radius:50%;display:inline-block;font-family:'Font Awesome 5 Brands';font-weight:400}.os-icon-macos:after{font-style:normal;content:"\f179";display:inline-block;font-family:'Font Awesome 5 Brands';font-weight:400}.os-icon-ubuntu:after,.os-icon-debian:after,.os-icon-centos:after,.os-icon-redhat:after{content:" ";width:24px;height:24px;line-height:24px;display:inline-block}.os-icon-ubuntu:after{background:url(../img/os-icon/ubuntu-24x24.png) no-repeat}.os-icon-debian:after{background:url(../img/os-icon/debian-24x24.png) no-repeat}.os-icon-centos:after{background:url(../img/os-icon/centos-24x24.png) no-repeat}.os-icon-redhat:after{background:url(../img/os-icon/redhat-24x24.png) no-repeat}.disable-bg{position:absolute;background:url(../img/css/disable-bg.png) repeat;opacity:.45;z-index:990}.disable-message{display:inline-block;font-size:160%;position:absolute;padding:20px 40px;border:1px solid #2b0002;background-color:#65181a;color:#fff;opacity:.85;z-index:991}.center{text-align:center}.table{margin-bottom:10px}.table>thead>tr>th{vertical-align:middle;border-bottom:2px solid #ddd}.table.table-info-list{width:auto}.table.table-info-list td{border-top:1px dotted #ddd;padding:5px 5px;vertical-align:top}.table.table-info-list td.key{text-align:right;width:1px;white-space:nowrap}.table.table-info-list td.value{text-align:left;font-weight:bold;font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace;color:#3e3e3e}.table.table-info-list td .error{color:#cc3632;font-weight:bold}.table.table-info-list td .disabled{color:#848484}.table.table-info-list.table-info-list-lite{width:100%}.table.table-info-list.table-info-list-lite td{padding:5px 5px}.table.table-info-list.table-info-list-lite td.value{font-weight:normal}.table.table-info-list tr:first-child td{border-top:none}.table.table-config-list{width:100%}.table.table-config-list td{border:none;padding:5px}.table.table-config-list td.title{text-align:left;font-size:110%;font-weight:bolder}.table.table-config-list td.key{width:1px;white-space:nowrap;text-align:right;padding-right:15px}.table.table-config-list td.value{text-align:left}.table.table-config-list td.value input{width:4em;padding:0 5px;text-align:right}.table.table-config-list td.value .unit{margin-left:5px}.table.table-config-list td.value .desc{color:#999;margin-left:15px;display:inline-block}.table>thead>tr>th{padding:5px 5px;outline:none;white-space:nowrap;font-weight:normal;text-align:center;background-color:#ededed}.table>tbody>tr>td{padding:5px;text-align:center;vertical-align:middle}.table>tbody>tr>td .nowrap{white-space:nowrap}.table-data td.loading{text-align:left;padding:20px}.table-data .btn-group.open .dropdown-toggle{-webkit-box-shadow:none;box-shadow:none}.table.table-data thead .sorting,.table.table-data thead .sorting_asc,.table.table-data thead .sorting_desc{cursor:pointer}.table.table-data thead .sorting:after,.table.table-data thead .sorting_asc:after,.table.table-data thead .sorting_desc:after{bottom:4px;padding-left:5px;display:inline-block;font-family:'Font Awesome 5 Free';font-weight:900;opacity:.8}.table.table-data thead .sorting:after{opacity:.2;content:"\f0dc"}.table.table-data thead .sorting_asc:after{content:"\f0de"}.table.table-data thead .sorting_desc:after{content:"\f0dd"}.host-name{font-size:16px}.host-name-desc{cursor:pointer}.host-ip{font-size:12px;color:#999;display:inline-block;white-space:nowrap;font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace;overflow:hidden;text-overflow:ellipsis}.td-ip-list{padding-right:20px;padding-left:5px}.td-ip-show-more{font-size:14px;width:12px;float:right;display:block}.td-ip-item{min-width:12em;width:12em;height:18px;padding:2px 4px;margin:1px 0;color:#333;text-align:center;white-space:nowrap;border-radius:9px;line-height:11px;font-size:11px;background:#dfdfdf !important}.td-ip-item span{display:inline-block;font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace;font-size:11px;font-weight:400}.td-ip-item a{display:inline-block;width:14px;float:right;font-size:14px}.btn-group-sm>.btn{padding:3px 5px;font-size:12px}.pop-menu-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040}.form-group{margin-bottom:5px}.badge{padding:3px 6px;border-radius:10px;font-size:13px;font-weight:400;background-color:#999}.badge.badge-sm{font-size:12px;padding:3px 5px;margin-top:0;border-radius:8px;text-shadow:none}.badge.badge-sup{margin-left:-8px;margin-top:-16px}.badge.badge-ignore{background-color:#e5e5e5;color:#999}.badge.badge-info{background-color:#33b7d0}.badge.badge-primary{background-color:#348fe2}.badge.badge-success{background-color:#368142}.badge.badge-warning{background-color:#f57523}.badge.badge-danger{background-color:#d34242}.btn-success .badge{color:#fff}.label{display:inline-block;padding:5px 10px;margin:2px;font-size:13px;font-weight:400;background-color:#999}.label.label-sm{font-size:12px;padding:3px 8px 4px 8px;margin-top:0;border-radius:3px}.label.label-ignore{background-color:#e5e5e5;color:#aaa;text-shadow:-1px -1px 1px #fff}.label.label-info{background-color:#33b7d0}.label.label-primary{background-color:#348fe2}.label.label-success{background-color:#368142}.label.label-warning{background-color:#f57523}.label.label-danger{background-color:#d34242}.progress.progress-sm{height:18px;margin-bottom:2px;background-color:#aaa}.progress.progress-sm.button{cursor:pointer}.progress.progress-sm .progress-bar{display:block;font-size:11px;float:none}.modal-dialog .modal-content .modal-header{background-color:#f7f7f7}.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,.col-sm-12{padding-right:5px;padding-left:5px}.input-group :-moz-placeholder{color:#d2d2d2}.input-group ::-moz-placeholder{color:#d2d2d2}.input-group input:-ms-input-placeholder,.input-group textarea:-ms-input-placeholder{color:#d2d2d2}.input-group input::-webkit-input-placeholder,.input-group textarea::-webkit-input-placeholder{color:#d2d2d2}.modal .modal-content{border-radius:0}.modal .modal-header .close{margin-top:-4px;margin-right:-6px}.modal .modal-header .close:hover{color:#9c3023;opacity:1}.modal .modal-header .close:active,.modal .modal-header .close:focus,.modal .modal-header .close:visited{-webkit-appearance:none}.modal .form-horizontal .form-group,.modal .row{margin-left:0;margin-right:0;padding-bottom:8px}.alert{border-radius:0;padding:5px;margin-bottom:10px}.dropdown-menu{min-width:0;font-size:13px}.form-control-sm{padding:3px 5px;font-size:13px;height:inherit}.form-group .control-label.require{color:#505050;font-weight:bold}.form-group .control-label.require:before{color:#ac4e43;position:absolute;margin-left:-1.2em;margin-top:1px;content:"\f069";font-size:8px;font-family:'Font Awesome 5 Free';font-weight:900}.form-group .control-desc{padding-top:6px;color:#999}.form-group .control-desc-sm{color:#999;padding-top:3px;font-size:12px}label.form-control-static input{display:inline-block;position:relative;margin-top:4px}.control-desc .popover{max-width:none;font-size:13px}.table-extend-cell .btn-group-sm .btn,.table-prefix-area .btn-group-sm .btn{padding:5px 5px}body{padding:0;margin:0}#page-content{margin-bottom:44px}#page-footer nav.navbar{min-height:24px;height:24px;line-height:24px;background-color:#cdcdcd;font-size:12px;color:#6d6d6d}#page-footer nav.navbar .container{height:24px}#page-footer nav.navbar p{margin:0 auto;text-align:center}.page-header{box-shadow:0 0 3px rgba(0,0,0,0.5);min-height:48px;top:0;width:100%;height:48px;margin:0 0 10px;border:none;background-color:#2a2a2a}.page-header .top-navbar{min-height:48px;height:48px;line-height:47px;background-color:#3a3a3a;color:#ccc}.page-header .top-navbar a{color:#d5d5d5}.page-header .top-navbar a:hover{color:#5a8fee}.page-header .top-navbar .brand{float:left;display:inline-block;padding:12px 0;margin:0}.page-header .top-navbar .brand .site-logo{display:block;width:86px;height:24px;background:url(../img/site-logo-small.png) no-repeat}.page-header .top-navbar .breadcrumb-container{float:left;display:inline-block;margin:0;padding:0}.page-header .top-navbar .breadcrumb-container .breadcrumb{background-color:#3a3a3a;margin:0;border-radius:0;border:none;padding:0 0 0 20px;font-size:16px;color:#ccc}.page-header .top-navbar .breadcrumb-container .breadcrumb>li+li:before{font-size:18px;padding:0 5px;color:#555;content:'|'}.page-header .top-navbar .breadcrumb-container .breadcrumb>li.title{font-size:18px}.page-header .top-navbar .breadcrumb-container .breadcrumb>li.sub-title{font-size:14px;color:#b3b3b3;line-height:44px}.page-header .top-navbar .status-container{float:right}.op_box{display:block;padding:5px;margin:0}.op_box.op_error{background-color:#ffb8b5;border:1px solid #d47e7b;color:#333}.op_box.op_wait{background:#e5e5e5;border:1px solid #a8a8a8;color:#333}.op_box.op_success{background:#acf1b2;border:1px solid #82df82;color:#333}.info-box{width:100%;margin:30px auto}.info-box .info-icon-box{z-index:-1;position:absolute;min-height:194px;overflow:hidden}.info-box .info-icon-box>.fas,.info-box .info-icon-box .fa{margin-top:30px;font-size:164px}.info-box .info-message-box{min-height:328px;border:1px solid #fff;background-color:rgba(255,255,255,0.76);box-shadow:2px 2px 3px rgba(0,0,0,0.3);padding:15px 20px 35px 30px;margin-left:98.4px}.info-box .info-message-box .title{font-size:180%;margin:15px 0}.info-box .info-message-box hr{border-top:none;border-bottom:1px dashed #d3d3d3}.info-box .op_box{margin:5px 0;text-align:center}.content-box{background-color:#fff;padding:20px;box-shadow:1px 1px 1px rgba(0,0,0,0.3)}.content-box .welcome-message .fa{display:block;color:#ff272a;font-size:18px;float:left}.content-box .welcome-message span{display:block;line-height:18px;padding-left:23px}.content-box .table{width:auto;margin-left:20px}.content-box .table td{border-top:1px dotted #ddd;padding:5px}.content-box .table td.key{text-align:right}.content-box .table td.value{text-align:left;font-weight:bold}.content-box .table tr:first-child td{border-top:none}.content-box table.form{width:auto;margin-left:20px}.content-box table.form td{padding:5px;line-height:1.42857143;vertical-align:middle}.content-box table.form td.key{text-align:right}.content-box table.form td label{margin-bottom:0}.content-box table.form td .form-control{height:30px;padding:5px 10px;font-size:inherit;line-height:inherit}.content-box h1 .fa-spin{color:#aaa}.content-box h1{font-size:180%}.content-box h2{font-size:140%}.content-box .op_box{margin:5px 0}.content-box .steps-detail{display:none;margin:10px;padding:10px;border:1px solid #b4b4b4;background-color:#dcdcdc}.content-box .steps-detail p{padding-left:5px;margin:2px 0 2px 1px}.content-box .steps-detail p.error{color:#fff;margin:2px 0 2px 0;background-color:#cc3632;border:1px solid #9c2a26}.content-box .alert.alert-warning{color:#6a542d;border:1px solid #e2cab4;background-color:#ffe4cb}.content-box .error{color:#cc3632}#gritter-notice-wrapper{z-index:9999}.gritter-bottom,.gritter-item,.gritter-top{background:rgba(0,0,0,0.8) !important}.gritter-top{border-top-left-radius:3px;border-top-right-radius:3px}.gritter-bottom{border-bottom-left-radius:3px;border-bottom-right-radius:3px}.gritter-close,.gritter-light .gritter-close{left:auto !important;right:5px !important;top:5px !important;width:16px !important;height:16px !important;line-height:16px !important;display:block !important;border-radius:50%}.gritter-close:before,.gritter-light .gritter-close:before{content:'\f00d' !important;font-family:'Font Awesome 5 Free' !important;font-weight:900 !important;font-size:9px !important;width:16px !important;height:16px !important;line-height:16px !important;color:#fff !important;text-indent:0 !important;position:absolute !important;text-align:center !important;right:0 !important;top:0 !important}.gritter-title{font-size:13px !important;line-height:16px !important;padding-bottom:5px !important;font-weight:400 !important;color:#fff !important;text-shadow:none !important}.gritter-item{color:#aaa !important;font-size:13px !important;padding:2px 15px 5px !important}.gritter-error .gritter-bottom,.gritter-error .gritter-item,.gritter-error .gritter-top{background:rgba(123,32,32,0.9) !important}.gritter-error .gritter-title{color:#fff !important}.gritter-error .gritter-item{color:#ddd !important}.gritter-error .gritter-close{left:auto !important;right:5px !important;top:5px !important;width:16px !important;height:16px !important;line-height:16px !important;display:block !important;border-radius:50%;background:#e33b3b !important}.gritter-success .gritter-bottom,.gritter-success .gritter-item,.gritter-success .gritter-top{background:rgba(1,65,16,0.9) !important}.gritter-success .gritter-title{color:#ddd !important}.gritter-success .gritter-item{color:#ccc !important}.gritter-success .gritter-close{background:#0eb320 !important}#gritter-notice-wrapper{width:320px;max-width:480px}/*# sourceMappingURL=single.css.map */ \ No newline at end of file diff --git a/server/www/teleport/static/css/style.css b/server/www/teleport/static/css/style.css index d7c5d9d..85d644c 100644 --- a/server/www/teleport/static/css/style.css +++ b/server/www/teleport/static/css/style.css @@ -1 +1 @@ -@charset "utf-8";html{font-size:13px}body{font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;background-color:#e9e9e9;color:#333}html,body{height:100%}#page-container{min-width:1260px}a{text-decoration:none}a:link{text-decoration:none}a:hover{text-decoration:none}a:active{text-decoration:none}a:visited{text-decoration:none}select{outline:none}label{font-weight:normal}.clear-float{clear:both}.bigger{font-size:120%}.normal-text{font-size:13px;color:#333}.mono{font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace}.important{color:#d45f1c}.error{color:#d34242}.bold{font-weight:bold}hr.hr-sm{padding:1px 0;margin:5px 0;border-top:1px dashed #c4c4c4}ul{list-style:none}ul.list{margin:0;padding:3px 0 5px 0}ul.list li{margin:3px 3px 5px 10px}.btn-single-line{white-space:nowrap}.btn-single-line .btn:first-child{border-top-left-radius:3px;border-bottom-left-radius:3px}.btn-single-line .btn:last-child{border-top-right-radius:3px;border-bottom-right-radius:3px}hr.small{margin:5px 0}.dlg-protocol-group{margin-bottom:3px}.dlg-protocol-group ul{display:block;height:28px;margin:0;padding:0}.dlg-protocol-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;background-color:#eee;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.dlg-protocol-group ul li.item-name{width:120px}.dlg-protocol-group ul li.item-btn{background:none;padding:0;border:none}.dlg-protocol-group ul li.item-input{background:none;border:none;padding:0}.dlg-protocol-group ul li .form-control{line-height:1.5;margin:0;padding:4px 5px;font-size:12px;height:28px;border-radius:0;border-left:none;width:100px}.dlg-protocol-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.dlg-protocol-group ul li input[type=checkbox]{display:block;float:left;margin:3px 5px 0 0}.dlg-protocol-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:first-child .btn,.dlg-protocol-group ul li:first-child .form-control{border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}.dlg-protocol-group ul li:last-child .btn,.dlg-protocol-group ul li:last-child .form-control{border-top-right-radius:4px;border-bottom-right-radius:4px}.os-icon-windows:after{color:#00bcf6;content:"\f17a";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;content:"\f17c";font-size:18px;width:24px;height:24px;line-height:24px;background-color:#333;border-radius:50%;display:inline-block;font-family:'Font Awesome 5 Brands';font-weight:400}.os-icon-macos:after{color:#a7a7a7;content:"\f179";font-size:20px;width:24px;height:24px;line-height:24px;display:inline-block;font-family:'Font Awesome 5 Brands';font-weight:400}.os-icon-ubuntu:after,.os-icon-debian:after,.os-icon-centos:after,.os-icon-redhat:after{content:" ";width:24px;height:24px;line-height:24px;display:inline-block}.os-icon-ubuntu:after{background:url(../img/os-icon/ubuntu-24x24.png) no-repeat}.os-icon-debian:after{background:url(../img/os-icon/debian-24x24.png) no-repeat}.os-icon-centos:after{background:url(../img/os-icon/centos-24x24.png) no-repeat}.os-icon-redhat:after{background:url(../img/os-icon/redhat-24x24.png) no-repeat}.disable-bg{position:absolute;background:url(../img/css/disable-bg.png) repeat;opacity:.45;z-index:990}.disable-message{display:inline-block;font-size:160%;position:absolute;padding:20px 40px;border:1px solid #2b0002;background-color:#65181a;color:#fff;opacity:.85;z-index:991}.btn-group-sm>.btn{padding:3px 5px;font-size:12px}.pop-menu-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040}.form-group{margin-bottom:5px}.badge{padding:3px 6px;border-radius:10px;font-size:13px;font-weight:400;background-color:#999}.badge.badge-sm{font-size:12px;padding:3px 5px;margin-top:0;border-radius:8px;text-shadow:none}.badge.badge-sup{margin-left:-8px;margin-top:-16px}.badge.badge-ignore{background-color:#e5e5e5;color:#999}.badge.badge-info{background-color:#33b7d0}.badge.badge-primary{background-color:#348fe2}.badge.badge-success{background-color:#368142}.badge.badge-warning{background-color:#f57523}.badge.badge-danger{background-color:#d34242}.btn-success .badge{color:#fff}.label{display:inline-block;padding:5px 10px;margin:2px;font-size:13px;font-weight:400;background-color:#999}.label.label-sm{font-size:12px;padding:3px 8px 4px 8px;margin-top:0;border-radius:3px}.label.label-ignore{background-color:#e5e5e5;color:#aaa;text-shadow:-1px -1px 1px #fff}.label.label-info{background-color:#33b7d0}.label.label-primary{background-color:#348fe2}.label.label-success{background-color:#368142}.label.label-warning{background-color:#f57523}.label.label-danger{background-color:#d34242}.progress.progress-sm{height:18px;margin-bottom:2px;background-color:#aaa}.progress.progress-sm.button{cursor:pointer}.progress.progress-sm .progress-bar{display:block;font-size:11px;float:none}.modal-dialog .modal-content .modal-header{background-color:#f7f7f7}.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,.col-sm-12{padding-right:5px;padding-left:5px}.input-group :-moz-placeholder{color:#d2d2d2}.input-group ::-moz-placeholder{color:#d2d2d2}.input-group input:-ms-input-placeholder,.input-group textarea:-ms-input-placeholder{color:#d2d2d2}.input-group input::-webkit-input-placeholder,.input-group textarea::-webkit-input-placeholder{color:#d2d2d2}.modal .modal-content{border-radius:0}.modal .modal-header .close{margin-top:-4px;margin-right:-6px}.modal .modal-header .close:hover{color:#9c3023;opacity:1}.modal .modal-header .close:active,.modal .modal-header .close:focus,.modal .modal-header .close:visited{-webkit-appearance:none}.modal .form-horizontal .form-group,.modal .row{margin-left:0;margin-right:0;padding-bottom:8px}.alert{border-radius:0;padding:5px;margin-bottom:10px}.dropdown-menu{min-width:0;font-size:13px}.form-control-sm{padding:3px 5px;font-size:13px;height:inherit}.form-group .control-label.require{color:#505050;font-weight:bold}.form-group .control-label.require:before{color:#ac4e43;position:absolute;margin-left:-1.2em;margin-top:1px;content:"\f069";font-size:8px;font-family:'Font Awesome 5 Free';font-weight:900}.form-group .control-desc{padding-top:6px;color:#999}.form-group .control-desc-sm{color:#999;padding-top:3px;font-size:12px}label.form-control-static input{display:inline-block;position:relative;margin-top:4px}.control-desc .popover{max-width:none;font-size:13px}.table-extend-cell .btn-group-sm .btn,.table-prefix-area .btn-group-sm .btn{padding:5px 5px}.table.table-role .header{font-size:120%;margin-top:8px}.table.table-role td{text-align:left;vertical-align:top;padding:0}.table.table-role td.role-name{min-width:160px}.table.table-role td.role-name ul{list-style:none;margin:0;padding:0}.table.table-role td.role-name ul li{padding:8px 30px 8px 6px;white-space:nowrap}.table.table-role td.role-name ul li:first-child{margin-top:10px}.table.table-role td.role-name ul li.active{color:#fff;background-color:#4091dd}.table.table-role td.role-name ul li.active:hover{background-color:#4091dd;cursor:auto}.table.table-role td.role-name ul li:hover{background-color:#81b6e9;cursor:pointer}.table.table-role td.role-privilege{padding:0 0 10px 10px;border-left:3px solid #4091dd}.table.table-role td.role-privilege hr{margin:8px 0;border-bottom:1px solid rgba(255,255,255,0.3)}.table.table-role td.role-privilege .title{font-size:110%;margin:5px 0}.table.table-role td.role-privilege ul{list-style:none;margin:0;padding:0}.table.table-role td.role-privilege ul li{display:inline-block;width:180px;margin-bottom:5px;margin-left:10px}.table.table-role td.role-privilege ul li span{color:#8e8e8e}.table.table-role td.role-privilege ul li span:before{display:inline-block;width:16px;content:"\f0c8";font-family:'Font Awesome 5 Free';font-weight:400}.table.table-role td.role-privilege ul li span.enabled{color:#3374b0}.table.table-role td.role-privilege ul li span.enabled:before{content:"\f14a";font-family:'Font Awesome 5 Free';font-weight:400}.table.table-role td.role-privilege.editable li span{cursor:pointer}.table.table-role tr:first-child td{border-top:none}#btn-create-role{margin-top:15px}.table{margin-bottom:10px}.table>thead>tr>th{vertical-align:middle;border-bottom:2px solid #ddd}.table.table-info-list{width:auto}.table.table-info-list td{border-top:1px dotted #ddd;padding:5px 5px;vertical-align:top}.table.table-info-list td.key{text-align:right;width:1px;white-space:nowrap}.table.table-info-list td.value{text-align:left;font-weight:bold;font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace;color:#3e3e3e}.table.table-info-list td .error{color:#cc3632;font-weight:bold}.table.table-info-list td .disabled{color:#848484}.table.table-info-list.table-info-list-lite{width:100%}.table.table-info-list.table-info-list-lite td{padding:5px 5px}.table.table-info-list.table-info-list-lite td.value{font-weight:normal}.table.table-info-list tr:first-child td{border-top:none}.table.table-config-list{width:100%}.table.table-config-list td{border:none;padding:5px}.table.table-config-list td.title{text-align:left;font-size:110%;font-weight:bolder}.table.table-config-list td.key{width:1px;white-space:nowrap;text-align:right;padding-right:15px}.table.table-config-list td.value{text-align:left}.table.table-config-list td.value input{width:4em;padding:0 5px;text-align:right}.table.table-config-list td.value .unit{margin-left:5px}.table.table-config-list td.value .desc{color:#999;margin-left:15px;display:inline-block}.table>thead>tr>th{padding:5px 5px;outline:none;white-space:nowrap;font-weight:normal;text-align:center;background-color:#ededed}.table>tbody>tr>td{padding:5px;text-align:center;vertical-align:middle}.table>tbody>tr>td .nowrap{white-space:nowrap}.table-data td.loading{text-align:left;padding:20px}.table-data .btn-group.open .dropdown-toggle{-webkit-box-shadow:none;box-shadow:none}.table.table-data thead .sorting,.table.table-data thead .sorting_asc,.table.table-data thead .sorting_desc{cursor:pointer}.table.table-data thead .sorting:after,.table.table-data thead .sorting_asc:after,.table.table-data thead .sorting_desc:after{bottom:4px;padding-left:5px;display:inline-block;font-family:'Font Awesome 5 Free';font-weight:900;opacity:.8}.table.table-data thead .sorting:after{opacity:.2;content:"\f0dc"}.table.table-data thead .sorting_asc:after{content:"\f0de"}.table.table-data thead .sorting_desc:after{content:"\f0dd"}.host-name{font-size:16px}.host-name-desc{cursor:pointer}.host-ip{font-size:12px;color:#999;display:inline-block;white-space:nowrap;font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace;overflow:hidden;text-overflow:ellipsis}.td-ip-list{padding-right:20px;padding-left:5px}.td-ip-show-more{font-size:14px;width:12px;float:right;display:block}.td-ip-item{min-width:12em;width:12em;height:18px;padding:2px 4px;margin:1px 0;color:#333;text-align:center;white-space:nowrap;border-radius:9px;line-height:11px;font-size:11px;background:#dfdfdf !important}.td-ip-item span{display:inline-block;font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace;font-size:11px;font-weight:400}.td-ip-item a{display:inline-block;width:14px;float:right;font-size:14px}.remote-action-group{margin-bottom:3px;height:28px}.remote-action-group .btn-group-sm>.btn{margin:0;padding:6px 6px;font-size:12px;height:28px;min-width:80px}.remote-action-group .btn-group-sm>.btn.dropdown-toggle{min-width:0}.remote-action-group>li{float:left;position:relative;display:block;height:28px;padding:4px 5px;background-color:#eee;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc;font-size:12px}.remote-action-group>li.remote-action-state{text-align:center;white-space:nowrap}.remote-action-group>li.remote-action-state.state-disabled{background-color:#e5e5e5;color:#aaa;text-shadow:-1px -1px 1px #fff}.remote-action-group>li.remote-action-state.state-disabled>i.fa{color:#b53a2f}.remote-action-group>li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.remote-action-group>li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}.remote-info-group{margin-bottom:3px;height:28px}.remote-info-group ul{display:inline-block;height:28px;margin:0;padding:0}.remote-info-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.remote-info-group ul li.remote-action-btn{background:none;padding:0;border:none}.remote-info-group ul li.remote-action-input{background:none;padding:4px 0}.remote-info-group ul li.remote-action-input select{border:none}.remote-info-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.remote-info-group ul li select{margin-top:-3px}.remote-info-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.remote-info-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}.rdp-options{position:absolute;display:none;left:10px;top:30px;border:1px solid rgba(0,0,0,0.25);z-index:9999;background-color:#fff;border-radius:4px;box-shadow:0 6px 12px rgba(0,0,0,0.2);font-size:13px}.rdp-options hr{margin:3px 0}.rdp-options .title{background-color:#eee;padding:3px 5px}.rdp-options .item{width:100%;padding:3px 20px}.rdp-options .item .radio,.rdp-options .item .checkbox{margin:0;font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace}.rdp-options .item .center{text-align:center}body.page-header-fixed{padding-top:48px}body.page-sidebar-fixed .page-sidebar{position:fixed}body.page-sidebar-fixed .page-content{margin-left:180px}.page-header{border:none;box-shadow:0 0 3px rgba(0,0,0,0.5)}.page-header.navbar{overflow:hidden;min-height:48px;height:48px;margin:0}.page-header.navbar .brand{display:inline-block;float:left;width:180px;height:48px;padding:12px 0 0;text-align:center;margin:0 auto;background-color:#3a3a3a}.page-header.navbar .brand .logo{display:inline-block;width:93px;height:30px;background:url(../img/site-logo-small.png) no-repeat}.page-header.navbar .breadcrumb-container{display:inline-block;padding-top:6px}.page-header.navbar .breadcrumb-container .breadcrumb{background-color:transparent;padding-left:20px;font-size:16px}.page-header.navbar .breadcrumb-container .breadcrumb>li+li:before{content:"\f105";font-family:'Font Awesome 5 Free';font-style:normal;font-weight:900}.page-header.navbar .breadcrumb-container .breadcrumb.breadcrumb-list>li{font-size:13px}.page-header.navbar .breadcrumb-container .breadcrumb.breadcrumb-list>li+li:before{content:" ";margin:0 5px}.page-header .container-fluid{padding-left:0}.page-sidebar{top:48px;bottom:0;left:0;width:180px;padding-top:0;z-index:1010;background-color:#3a3a3a}.page-sidebar .nav-menu>li>a{padding:8px 0 8px 20px;line-height:24px;font-size:13px;color:#c2c2c2;border-left:5px solid #3a3a3a}.page-sidebar .nav-menu>li>a:focus{background-color:#3a3a3a;border-left:5px solid #3a3a3a}.page-sidebar .nav-menu>li>a:hover{background-color:#2d2d2d;border-left:5px solid #005c74}.page-sidebar .nav-menu>li>a.selected{border-left:5px solid #00485b}.page-sidebar .nav-menu>li>a.selected:focus{border-left:5px solid #00485b}.page-sidebar .nav-menu>li>a.active{color:#fff;background-color:#0084a7;border-left:5px solid #0084a7}.page-sidebar .nav-menu>li>a.active:hover{border-left:5px solid #00acda}.page-sidebar .nav-menu>li>a.active:after{content:"\e251";font-family:'Glyphicons Halflings';position:relative;top:1px;display:inline-block;font-style:normal;font-weight:400;float:right;color:#e9e9e9;font-size:20px;line-height:24px;margin-right:-6px}.page-sidebar .nav-menu li .menu-caret:after{display:inline-block;width:12px;height:12px;margin-left:5px;top:1px;position:relative;border:none;font-family:'Font Awesome 5 Free';font-style:normal;font-weight:900}.page-sidebar .nav-menu li .menu-caret:after{content:'\f105'}.page-sidebar .nav-menu li.expand .menu-caret:after{content:'\f107'}.page-sidebar .nav-menu>li>a>i.icon{float:left;margin-top:1px;margin-right:15px;text-align:center;line-height:24px;font-size:14px}.page-sidebar .sub-menu{padding:0;margin:0;background-color:#292929;position:relative;list-style-type:none;border-top:1px solid #202020;border-bottom:1px solid #464646}.page-sidebar .sub-menu>li>a{padding:8px 0 8px 40px;line-height:20px;font-size:13px;display:block;position:relative;color:#889097;border-left:5px solid #292929}.page-sidebar .sub-menu>li>a:before{display:inline-block;padding-right:8px;line-height:20px;content:"\f0da";font-family:'Font Awesome 5 Free';font-style:normal;font-weight:900}.page-sidebar .sub-menu>li>a:hover{color:#fff;border-left:5px solid #005c74}.page-sidebar .sub-menu>li>a.active{color:#fff;background-color:#0084a7;border-left:5px solid #0084a7}.page-sidebar .sub-menu>li>a.active:hover{border-left:5px solid #00acda}.page-sidebar .sub-menu>li>a.active:after{content:"\e251";font-family:'Glyphicons Halflings';position:relative;top:-1px;display:inline-block;font-style:normal;font-weight:400;float:right;color:#e9e9e9;font-size:18px;line-height:24px;margin-right:-6px}.page-sidebar .nav-menu>li.profile{padding:10px 10px;color:#ccc;background-color:#333;border-bottom:1px solid #464646}.page-sidebar .nav-menu>li.profile a.title{color:#ccc}.page-sidebar .nav-menu>li.profile a.title:hover{color:#fff;background-color:transparent}.page-sidebar .nav-menu>li.profile a.title:focus{background-color:transparent}.page-sidebar .nav-menu>li.profile .image{float:left;margin-top:3px;font-size:24px;color:#69f;width:36px;height:36px;border-radius:6px;background-color:#eee;text-align:center;margin-right:10px;overflow:hidden}.page-sidebar .nav-menu>li.profile .image img{margin-top:-3px}.page-sidebar .nav-menu>li.profile .name{display:block;padding-top:3px;font-size:14px}.page-sidebar .nav-menu>li.profile .role{display:block;font-size:12px;color:#999}.page-sidebar .nav-menu>li.profile.active{background-color:#0084a7;color:#fff}.page-sidebar .nav-menu>li.profile.active .name,.page-sidebar .nav-menu>li.profile.active .role{color:#fff}.page-sidebar .nav-menu>li.profile.active:after{content:"\e251";font-family:'Glyphicons Halflings';position:absolute;top:0;right:-1px;display:inline-block;font-style:normal;font-weight:400;color:#e9e9e9;font-size:24px;line-height:61px;margin-right:-6px}.page-sidebar .nav-menu>li.profile .dropdown-menu{min-width:0;font-size:13px}.page-sidebar .nav-menu>li.profile .dropdown-menu>li>a{padding-right:30px}.page-sidebar .nav-menu>li.profile .dropdown-menu>li>a:hover{background-color:#ccc}.page-sidebar .nav-menu>li.profile .dropdown-menu .divider{margin:5px 0}.page-sidebar .badge{margin-top:-10px;margin-left:5px}.page-content-inner{padding:15px}.box{border:none;box-shadow:1px 1px 2px rgba(0,0,0,0.2);background-color:#fff;padding:15px;margin-bottom:15px}.box .nav-tabs{font-size:14px;font-weight:bold}.box .nav-tabs>li:first-child{margin-left:30px}.box .tab-content>.tab-pane{background-color:#fff;padding:20px;border:1px solid #ddd;border-top:none;border-bottom-left-radius:3px;border-bottom-right-radius:3px}.box.box-nav-tabs{padding:0;background-color:#f5f5f5}.box.box-nav-tabs .nav-tabs{font-size:inherit;font-weight:inherit}.box.box-nav-tabs .nav-tabs>li{padding-top:8px}.box.box-nav-tabs .nav-tabs>li>a{margin-right:5px;border-top-left-radius:3px;border-top-right-radius:3px;padding:3px 15px;background-color:#e6e6e6;border:1px solid #ddd;border-bottom-color:transparent}.box.box-nav-tabs .nav-tabs>li.active>a{font-weight:bold;border:1px solid #ddd;border-bottom-color:transparent;background-color:#fff}.box.box-nav-tabs .tab-content>.tab-pane{padding:20px;border:none}.box-btn-bar{line-height:30px}.box-btn-bar a.btn{margin-right:20px}.page-filter{height:36px;line-height:36px;margin-bottom:10px}.page-filter .form-control{margin-top:5px;margin-right:4px}.form-group .input-group{margin-bottom:5px}.op_box{display:block;padding:5px;border-radius:3px;text-align:center;margin-top:5px}.op_error{background:#fbb}.op_wait{background:#ccc}.more-action{position:absolute !important}.more-action .dropdown-menu{background-color:rgba(60,60,60,0.9);color:#fff;font-size:13px}.more-action .dropdown-menu.dropdown-menu-left{margin-left:-120px}.more-action .dropdown-menu>li>a{padding:5px 20px;color:#fff}.more-action .dropdown-menu>li>a:hover,.more-action .dropdown-menu>li>a:active,.more-action .dropdown-menu>li>a:visited{background-color:#0084a7}.more-action .dropdown-menu .divider{margin:5px 0;background-color:#666}.popover-inline-edit input,.popover-inline-edit .btn{height:30px}.popover-inline-edit .popover-title{background-color:#ddd}.popover-inline-edit .popover-content{padding:20px 10px}.popover-inline-edit .popover{padding:0;max-width:500px}.popover-inline-edit .popover .popover-content{padding:10px 10px 20px 10px}.popover-inline-edit .popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#ddd}.tp-table-filter{width:100%;height:25px;margin:0;padding:0}.tp-table-filter .tp-table-filter-inner{display:table;margin:0;padding:0}.tp-table-filter.tp-table-filter-input .tp-table-filter-inner{width:100%}.tp-table-filter.tp-table-filter-left .tp-table-filter-inner,.tp-table-filter.tp-table-filter-right .tp-table-filter-inner{width:auto}.tp-table-filter.tp-table-filter-center .tp-table-filter-inner{margin:0 auto}.tp-table-filter .search-title{display:table-cell;vertical-align:middle;height:25px;line-height:25px;color:#555;white-space:nowrap;width:1px;text-align:left}.tp-table-filter .search-input,.tp-table-filter .search-select{display:table-cell;text-align:left;height:25px}.tp-table-filter .search-input>.btn,.tp-table-filter .search-select>.btn{font-size:13px;background-color:transparent;border:none;padding:0 0 0 8px;border-radius:0}.tp-table-filter .search-input>.btn:active,.tp-table-filter .search-select>.btn:active{box-shadow:none}.tp-table-filter .search-input .dropdown-menu,.tp-table-filter .search-select .dropdown-menu{min-width:0;background-color:rgba(0,0,0,0.8);color:#fff;font-size:13px;box-shadow:0 3px 6px rgba(0,0,0,0.3);border:none}.tp-table-filter .search-input .dropdown-menu>li>a,.tp-table-filter .search-select .dropdown-menu>li>a{padding-right:30px;min-width:100px;color:#fff}.tp-table-filter .search-input .dropdown-menu>li>a:hover,.tp-table-filter .search-select .dropdown-menu>li>a:hover,.tp-table-filter .search-input .dropdown-menu>li>a:active,.tp-table-filter .search-select .dropdown-menu>li>a:active,.tp-table-filter .search-input .dropdown-menu>li>a:visited,.tp-table-filter .search-select .dropdown-menu>li>a:visited{background-color:rgba(255,255,255,0.2)}.tp-table-filter .search-input .dropdown-menu .divider,.tp-table-filter .search-select .dropdown-menu .divider{margin:5px 0;background-color:#666}.tp-table-filter .search-input{width:100%;padding-left:10px}.tp-table-filter .search-input>.input-group .input-group-addon{font-size:13px;padding:0 5px}.tp-table-filter .search-input>.input-group input.form-control{font-size:13px;height:25px;width:100%;padding:0 5px}.btn.btn-no-border{font-size:13px;background-color:transparent;border:none;padding:0 0 0 8px;border-radius:0}.btn.btn-no-border:active{box-shadow:none}.table>tbody>tr.table-footer-action{background-color:transparent}.table>tbody>tr.table-footer-action>td{border-color:transparent;padding-top:15px;vertical-align:middle}.table-extend-area,.table-prefix-area{display:table;width:100%}.table-extend-area .table-extend-cell,.table-prefix-area .table-extend-cell{display:table-cell;height:24px;line-height:24px;padding:3px}.table-extend-area .table-extend-cell.table-extend-cell-right,.table-prefix-area .table-extend-cell.table-extend-cell-right{text-align:right}.table-extend-area .table-extend-cell .table-name,.table-prefix-area .table-extend-cell .table-name{font-size:120%;position:relative;top:3px;padding-right:10px}.table-extend-area .table-extend-cell .pagination,.table-prefix-area .table-extend-cell .pagination{margin:0 0}.table-extend-area .table-extend-cell .pagination>li>span,.table-prefix-area .table-extend-cell .pagination>li>span,.table-extend-area .table-extend-cell .pagination a,.table-prefix-area .table-extend-cell .pagination a{padding:3px 8px;font-size:12px;line-height:1.5}.table-extend-area .table-extend-cell.checkbox-select-all,.table-prefix-area .table-extend-cell.checkbox-select-all{width:36px;text-align:center}.table-extend-area .table-extend-cell.checkbox-select-all input,.table-prefix-area .table-extend-cell.checkbox-select-all input{position:relative;top:3px}.table-extend-area .table-extend-cell.group-actions>.btn-group .btn,.table-prefix-area .table-extend-cell.group-actions>.btn-group .btn{padding:5px 5px;font-size:12px}.table-extend-area .table-extend-cell.table-item-counter,.table-prefix-area .table-extend-cell.table-item-counter{text-align:right}.table-extend-area .table-extend-cell.table-item-counter ol,.table-prefix-area .table-extend-cell.table-item-counter ol{list-style:none;padding:0;margin:0;border:none;background-color:transparent;color:#666}.table-extend-area .table-extend-cell.table-item-counter ol>li,.table-prefix-area .table-extend-cell.table-item-counter ol>li{display:inline-block;padding-left:10px}.table-extend-area .table-extend-cell.table-item-counter .btn,.table-prefix-area .table-extend-cell.table-item-counter .btn{margin-top:-3px}.table-extend-area .table-extend-cell.table-item-counter .btn .caret,.table-prefix-area .table-extend-cell.table-item-counter .btn .caret{margin-top:-3px}.table-prefix-area{margin-bottom:10px}.table-prefix-area .table-extend-cell{padding:0}.btn-group.pagination .btn.dropdown-toggle{background-color:transparent;border:1px solid #999}textarea.textarea-resize-y{resize:vertical}textarea.textarea-resize-none{resize:none}textarea.textarea-code{font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace}textarea.cert_pub{width:100%;height:64px;border:1px solid #e2e2e2;background-color:#e4ffe5}.box ul.help-list{list-style:none;margin:0 0 10px 0;padding:0}.box ul.help-list li{padding:3px 3px 3px 20px;margin-left:10px}.box ul.help-list li:before{color:#999;position:absolute;margin-left:-1.2em;margin-top:1px;content:"\f05a";font-family:'Font Awesome 5 Free';font-weight:900}.box ul.help-list li em{color:#3374b0;font-style:normal}.tp-checkbox{display:inline-block;color:#747474}.tp-checkbox.tp-disabled{cursor:not-allowed;color:#c2c2c2}.tp-checkbox:before{display:inline-block;position:relative;top:1px;width:16px;content:"\f0c8";font-family:'Font Awesome 5 Free';font-weight:400}.tp-checkbox.tp-selected:before,.tp-checkbox.tp-checked:before{content:"\f14a";font-family:'Font Awesome 5 Free';font-weight:400}.tp-checkbox.tp-editable{cursor:pointer;color:#459dee}.tp-checkbox.tp-editable:hover{color:#53af43}.tp-checkbox.tp-editable.tp-selected,.tp-checkbox.tp-editable.tp-checked{color:#3374b0}i.upload-button{font-size:128px;color:#b1b1b1}i.upload-button:hover{cursor:pointer;color:#709cff}#gritter-notice-wrapper{z-index:9999}.gritter-bottom,.gritter-item,.gritter-top{background:rgba(0,0,0,0.8) !important}.gritter-top{border-top-left-radius:3px;border-top-right-radius:3px}.gritter-bottom{border-bottom-left-radius:3px;border-bottom-right-radius:3px}.gritter-close,.gritter-light .gritter-close{left:auto !important;right:5px !important;top:5px !important;width:16px !important;height:16px !important;line-height:16px !important;display:block !important;border-radius:50%}.gritter-close:before,.gritter-light .gritter-close:before{content:'\f00d' !important;font-family:'Font Awesome 5 Free' !important;font-weight:900 !important;font-size:9px !important;width:16px !important;height:16px !important;line-height:16px !important;color:#fff !important;text-indent:0 !important;position:absolute !important;text-align:center !important;right:0 !important;top:0 !important}.gritter-title{font-size:13px !important;line-height:16px !important;padding-bottom:5px !important;font-weight:400 !important;color:#fff !important;text-shadow:none !important}.gritter-item{color:#aaa !important;font-size:13px !important;padding:2px 15px 5px !important}.gritter-error .gritter-bottom,.gritter-error .gritter-item,.gritter-error .gritter-top{background:rgba(123,32,32,0.9) !important}.gritter-error .gritter-title{color:#fff !important}.gritter-error .gritter-item{color:#ddd !important}.gritter-error .gritter-close{left:auto !important;right:5px !important;top:5px !important;width:16px !important;height:16px !important;line-height:16px !important;display:block !important;border-radius:50%;background:#e33b3b !important}.gritter-success .gritter-bottom,.gritter-success .gritter-item,.gritter-success .gritter-top{background:rgba(1,65,16,0.9) !important}.gritter-success .gritter-title{color:#ddd !important}.gritter-success .gritter-item{color:#ccc !important}.gritter-success .gritter-close{background:#0eb320 !important}#gritter-notice-wrapper{width:320px;max-width:480px}/*# sourceMappingURL=style.css.map */ \ No newline at end of file +@charset "utf-8";html{font-size:13px}body{font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;background-color:#e9e9e9;color:#333}html,body{height:100%}#page-container{min-width:1260px}a{text-decoration:none}a:link{text-decoration:none}a:hover{text-decoration:none}a:active{text-decoration:none}a:visited{text-decoration:none}select{outline:none}label{font-weight:normal}.clear-float{clear:both}.bigger{font-size:120%}.normal-text{font-size:13px;color:#333}.mono{font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace}.important{color:#d45f1c}.error{color:#d34242}.bold{font-weight:bold}hr.hr-sm{padding:1px 0;margin:5px 0;border-top:1px dashed #c4c4c4}ul{list-style:none}ul.list{margin:0;padding:3px 0 5px 0}ul.list li{margin:3px 3px 5px 10px}.btn-single-line{white-space:nowrap}.btn-single-line .btn:first-child{border-top-left-radius:3px;border-bottom-left-radius:3px}.btn-single-line .btn:last-child{border-top-right-radius:3px;border-bottom-right-radius:3px}hr.small{margin:5px 0}.dlg-protocol-group{margin-bottom:3px}.dlg-protocol-group ul{display:block;height:28px;margin:0;padding:0}.dlg-protocol-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;background-color:#eee;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.dlg-protocol-group ul li.item-name{width:120px}.dlg-protocol-group ul li.item-btn{background:none;padding:0;border:none}.dlg-protocol-group ul li.item-input{background:none;border:none;padding:0}.dlg-protocol-group ul li .form-control{line-height:1.5;margin:0;padding:4px 5px;font-size:12px;height:28px;border-radius:0;border-left:none;width:100px}.dlg-protocol-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.dlg-protocol-group ul li input[type=checkbox]{display:block;float:left;margin:3px 5px 0 0}.dlg-protocol-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:first-child .btn,.dlg-protocol-group ul li:first-child .form-control{border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}.dlg-protocol-group ul li:last-child .btn,.dlg-protocol-group ul li:last-child .form-control{border-top-right-radius:4px;border-bottom-right-radius:4px}.os-icon-windows:after{font-style:normal;content:"\f17a";display:inline-block;font-family:'Font Awesome 5 Brands';font-weight:400}.os-icon-linux:after{font-style:normal;content:"\f17c";background-color:#333;border-radius:50%;display:inline-block;font-family:'Font Awesome 5 Brands';font-weight:400}.os-icon-macos:after{font-style:normal;content:"\f179";display:inline-block;font-family:'Font Awesome 5 Brands';font-weight:400}.os-icon-ubuntu:after,.os-icon-debian:after,.os-icon-centos:after,.os-icon-redhat:after{content:" ";width:24px;height:24px;line-height:24px;display:inline-block}.os-icon-ubuntu:after{background:url(../img/os-icon/ubuntu-24x24.png) no-repeat}.os-icon-debian:after{background:url(../img/os-icon/debian-24x24.png) no-repeat}.os-icon-centos:after{background:url(../img/os-icon/centos-24x24.png) no-repeat}.os-icon-redhat:after{background:url(../img/os-icon/redhat-24x24.png) no-repeat}.disable-bg{position:absolute;background:url(../img/css/disable-bg.png) repeat;opacity:.45;z-index:990}.disable-message{display:inline-block;font-size:160%;position:absolute;padding:20px 40px;border:1px solid #2b0002;background-color:#65181a;color:#fff;opacity:.85;z-index:991}.center{text-align:center}.btn-group-sm>.btn{padding:3px 5px;font-size:12px}.pop-menu-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040}.form-group{margin-bottom:5px}.badge{padding:3px 6px;border-radius:10px;font-size:13px;font-weight:400;background-color:#999}.badge.badge-sm{font-size:12px;padding:3px 5px;margin-top:0;border-radius:8px;text-shadow:none}.badge.badge-sup{margin-left:-8px;margin-top:-16px}.badge.badge-ignore{background-color:#e5e5e5;color:#999}.badge.badge-info{background-color:#33b7d0}.badge.badge-primary{background-color:#348fe2}.badge.badge-success{background-color:#368142}.badge.badge-warning{background-color:#f57523}.badge.badge-danger{background-color:#d34242}.btn-success .badge{color:#fff}.label{display:inline-block;padding:5px 10px;margin:2px;font-size:13px;font-weight:400;background-color:#999}.label.label-sm{font-size:12px;padding:3px 8px 4px 8px;margin-top:0;border-radius:3px}.label.label-ignore{background-color:#e5e5e5;color:#aaa;text-shadow:-1px -1px 1px #fff}.label.label-info{background-color:#33b7d0}.label.label-primary{background-color:#348fe2}.label.label-success{background-color:#368142}.label.label-warning{background-color:#f57523}.label.label-danger{background-color:#d34242}.progress.progress-sm{height:18px;margin-bottom:2px;background-color:#aaa}.progress.progress-sm.button{cursor:pointer}.progress.progress-sm .progress-bar{display:block;font-size:11px;float:none}.modal-dialog .modal-content .modal-header{background-color:#f7f7f7}.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,.col-sm-12{padding-right:5px;padding-left:5px}.input-group :-moz-placeholder{color:#d2d2d2}.input-group ::-moz-placeholder{color:#d2d2d2}.input-group input:-ms-input-placeholder,.input-group textarea:-ms-input-placeholder{color:#d2d2d2}.input-group input::-webkit-input-placeholder,.input-group textarea::-webkit-input-placeholder{color:#d2d2d2}.modal .modal-content{border-radius:0}.modal .modal-header .close{margin-top:-4px;margin-right:-6px}.modal .modal-header .close:hover{color:#9c3023;opacity:1}.modal .modal-header .close:active,.modal .modal-header .close:focus,.modal .modal-header .close:visited{-webkit-appearance:none}.modal .form-horizontal .form-group,.modal .row{margin-left:0;margin-right:0;padding-bottom:8px}.alert{border-radius:0;padding:5px;margin-bottom:10px}.dropdown-menu{min-width:0;font-size:13px}.form-control-sm{padding:3px 5px;font-size:13px;height:inherit}.form-group .control-label.require{color:#505050;font-weight:bold}.form-group .control-label.require:before{color:#ac4e43;position:absolute;margin-left:-1.2em;margin-top:1px;content:"\f069";font-size:8px;font-family:'Font Awesome 5 Free';font-weight:900}.form-group .control-desc{padding-top:6px;color:#999}.form-group .control-desc-sm{color:#999;padding-top:3px;font-size:12px}label.form-control-static input{display:inline-block;position:relative;margin-top:4px}.control-desc .popover{max-width:none;font-size:13px}.table-extend-cell .btn-group-sm .btn,.table-prefix-area .btn-group-sm .btn{padding:5px 5px}.table.table-role .header{font-size:120%;margin-top:8px}.table.table-role td{text-align:left;vertical-align:top;padding:0}.table.table-role td.role-name{min-width:160px}.table.table-role td.role-name ul{list-style:none;margin:0;padding:0}.table.table-role td.role-name ul li{padding:8px 30px 8px 6px;white-space:nowrap}.table.table-role td.role-name ul li:first-child{margin-top:10px}.table.table-role td.role-name ul li.active{color:#fff;background-color:#4091dd}.table.table-role td.role-name ul li.active:hover{background-color:#4091dd;cursor:auto}.table.table-role td.role-name ul li:hover{background-color:#81b6e9;cursor:pointer}.table.table-role td.role-privilege{padding:0 0 10px 10px;border-left:3px solid #4091dd}.table.table-role td.role-privilege hr{margin:8px 0;border-bottom:1px solid rgba(255,255,255,0.3)}.table.table-role td.role-privilege .title{font-size:110%;margin:5px 0}.table.table-role td.role-privilege ul{list-style:none;margin:0;padding:0}.table.table-role td.role-privilege ul li{display:inline-block;width:180px;margin-bottom:5px;margin-left:10px}.table.table-role td.role-privilege ul li span{color:#8e8e8e}.table.table-role td.role-privilege ul li span:before{display:inline-block;width:16px;content:"\f0c8";font-family:'Font Awesome 5 Free';font-weight:400}.table.table-role td.role-privilege ul li span.enabled{color:#3374b0}.table.table-role td.role-privilege ul li span.enabled:before{content:"\f14a";font-family:'Font Awesome 5 Free';font-weight:400}.table.table-role td.role-privilege.editable li span{cursor:pointer}.table.table-role tr:first-child td{border-top:none}#btn-create-role{margin-top:15px}.table{margin-bottom:10px}.table>thead>tr>th{vertical-align:middle;border-bottom:2px solid #ddd}.table.table-info-list{width:auto}.table.table-info-list td{border-top:1px dotted #ddd;padding:5px 5px;vertical-align:top}.table.table-info-list td.key{text-align:right;width:1px;white-space:nowrap}.table.table-info-list td.value{text-align:left;font-weight:bold;font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace;color:#3e3e3e}.table.table-info-list td .error{color:#cc3632;font-weight:bold}.table.table-info-list td .disabled{color:#848484}.table.table-info-list.table-info-list-lite{width:100%}.table.table-info-list.table-info-list-lite td{padding:5px 5px}.table.table-info-list.table-info-list-lite td.value{font-weight:normal}.table.table-info-list tr:first-child td{border-top:none}.table.table-config-list{width:100%}.table.table-config-list td{border:none;padding:5px}.table.table-config-list td.title{text-align:left;font-size:110%;font-weight:bolder}.table.table-config-list td.key{width:1px;white-space:nowrap;text-align:right;padding-right:15px}.table.table-config-list td.value{text-align:left}.table.table-config-list td.value input{width:4em;padding:0 5px;text-align:right}.table.table-config-list td.value .unit{margin-left:5px}.table.table-config-list td.value .desc{color:#999;margin-left:15px;display:inline-block}.table>thead>tr>th{padding:5px 5px;outline:none;white-space:nowrap;font-weight:normal;text-align:center;background-color:#ededed}.table>tbody>tr>td{padding:5px;text-align:center;vertical-align:middle}.table>tbody>tr>td .nowrap{white-space:nowrap}.table-data td.loading{text-align:left;padding:20px}.table-data .btn-group.open .dropdown-toggle{-webkit-box-shadow:none;box-shadow:none}.table.table-data thead .sorting,.table.table-data thead .sorting_asc,.table.table-data thead .sorting_desc{cursor:pointer}.table.table-data thead .sorting:after,.table.table-data thead .sorting_asc:after,.table.table-data thead .sorting_desc:after{bottom:4px;padding-left:5px;display:inline-block;font-family:'Font Awesome 5 Free';font-weight:900;opacity:.8}.table.table-data thead .sorting:after{opacity:.2;content:"\f0dc"}.table.table-data thead .sorting_asc:after{content:"\f0de"}.table.table-data thead .sorting_desc:after{content:"\f0dd"}.host-name{font-size:16px}.host-name-desc{cursor:pointer}.host-ip{font-size:12px;color:#999;display:inline-block;white-space:nowrap;font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace;overflow:hidden;text-overflow:ellipsis}.td-ip-list{padding-right:20px;padding-left:5px}.td-ip-show-more{font-size:14px;width:12px;float:right;display:block}.td-ip-item{min-width:12em;width:12em;height:18px;padding:2px 4px;margin:1px 0;color:#333;text-align:center;white-space:nowrap;border-radius:9px;line-height:11px;font-size:11px;background:#dfdfdf !important}.td-ip-item span{display:inline-block;font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace;font-size:11px;font-weight:400}.td-ip-item a{display:inline-block;width:14px;float:right;font-size:14px}.remote-action-group{margin-bottom:3px;height:28px}.remote-action-group .btn-group-sm>.btn{margin:0;padding:6px 6px;font-size:12px;height:28px;min-width:80px}.remote-action-group .btn-group-sm>.btn.dropdown-toggle{min-width:0}.remote-action-group>li{float:left;position:relative;display:block;height:28px;padding:4px 5px;background-color:#eee;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc;font-size:12px}.remote-action-group>li.remote-action-state{text-align:center;white-space:nowrap}.remote-action-group>li.remote-action-state.state-disabled{background-color:#e5e5e5;color:#aaa;text-shadow:-1px -1px 1px #fff}.remote-action-group>li.remote-action-state.state-disabled>i.fa{color:#b53a2f}.remote-action-group>li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.remote-action-group>li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}.remote-info-group{margin-bottom:3px;height:28px}.remote-info-group ul{display:inline-block;height:28px;margin:0;padding:0}.remote-info-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.remote-info-group ul li.remote-action-btn{background:none;padding:0;border:none}.remote-info-group ul li.remote-action-input{background:none;padding:4px 0}.remote-info-group ul li.remote-action-input select{border:none}.remote-info-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.remote-info-group ul li select{margin-top:-3px}.remote-info-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.remote-info-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}.rdp-options{position:absolute;display:none;left:10px;top:30px;border:1px solid rgba(0,0,0,0.25);z-index:9999;background-color:#fff;border-radius:4px;box-shadow:0 6px 12px rgba(0,0,0,0.2);font-size:13px}.rdp-options hr{margin:3px 0}.rdp-options .title{background-color:#eee;padding:3px 5px}.rdp-options .item{width:100%;padding:3px 20px}.rdp-options .item .radio,.rdp-options .item .checkbox{margin:0;font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace}.rdp-options .item .center{text-align:center}body.page-header-fixed{padding-top:48px}body.page-sidebar-fixed .page-sidebar{position:fixed}body.page-sidebar-fixed .page-content{margin-left:180px}.page-header{border:none;box-shadow:0 0 3px rgba(0,0,0,0.5)}.page-header.navbar{overflow:hidden;min-height:48px;height:48px;margin:0}.page-header.navbar .brand{display:inline-block;float:left;width:180px;height:48px;padding:12px 0 0;text-align:center;margin:0 auto;background-color:#3a3a3a}.page-header.navbar .brand .logo{display:inline-block;width:93px;height:30px;background:url(../img/site-logo-small.png) no-repeat}.page-header.navbar .breadcrumb-container{display:inline-block;padding-top:6px}.page-header.navbar .breadcrumb-container .breadcrumb{background-color:transparent;padding-left:20px;font-size:16px}.page-header.navbar .breadcrumb-container .breadcrumb>li+li:before{content:"\f105";font-family:'Font Awesome 5 Free';font-style:normal;font-weight:900}.page-header.navbar .breadcrumb-container .breadcrumb.breadcrumb-list>li{font-size:13px}.page-header.navbar .breadcrumb-container .breadcrumb.breadcrumb-list>li+li:before{content:" ";margin:0 5px}.page-header .container-fluid{padding-left:0}.page-sidebar{top:48px;bottom:0;left:0;width:180px;padding-top:0;z-index:1010;background-color:#3a3a3a}.page-sidebar .nav-menu>li>a{padding:8px 0 8px 20px;line-height:24px;font-size:13px;color:#c2c2c2;border-left:5px solid #3a3a3a}.page-sidebar .nav-menu>li>a:focus{background-color:#3a3a3a;border-left:5px solid #3a3a3a}.page-sidebar .nav-menu>li>a:hover{background-color:#2d2d2d;border-left:5px solid #005c74}.page-sidebar .nav-menu>li>a.selected{border-left:5px solid #00485b}.page-sidebar .nav-menu>li>a.selected:focus{border-left:5px solid #00485b}.page-sidebar .nav-menu>li>a.active{color:#fff;background-color:#0084a7;border-left:5px solid #0084a7}.page-sidebar .nav-menu>li>a.active:hover{border-left:5px solid #00acda}.page-sidebar .nav-menu>li>a.active:after{content:"\e251";font-family:'Glyphicons Halflings';position:relative;top:1px;display:inline-block;font-style:normal;font-weight:400;float:right;color:#e9e9e9;font-size:20px;line-height:24px;margin-right:-6px}.page-sidebar .nav-menu li .menu-caret:after{display:inline-block;width:12px;height:12px;margin-left:5px;top:1px;position:relative;border:none;font-family:'Font Awesome 5 Free';font-style:normal;font-weight:900}.page-sidebar .nav-menu li .menu-caret:after{content:'\f105'}.page-sidebar .nav-menu li.expand .menu-caret:after{content:'\f107'}.page-sidebar .nav-menu>li>a>i.icon{float:left;margin-top:1px;margin-right:15px;text-align:center;line-height:24px;font-size:14px}.page-sidebar .sub-menu{padding:0;margin:0;background-color:#292929;position:relative;list-style-type:none;border-top:1px solid #202020;border-bottom:1px solid #464646}.page-sidebar .sub-menu>li>a{padding:8px 0 8px 40px;line-height:20px;font-size:13px;display:block;position:relative;color:#889097;border-left:5px solid #292929}.page-sidebar .sub-menu>li>a:before{display:inline-block;padding-right:8px;line-height:20px;content:"\f0da";font-family:'Font Awesome 5 Free';font-style:normal;font-weight:900}.page-sidebar .sub-menu>li>a:hover{color:#fff;border-left:5px solid #005c74}.page-sidebar .sub-menu>li>a.active{color:#fff;background-color:#0084a7;border-left:5px solid #0084a7}.page-sidebar .sub-menu>li>a.active:hover{border-left:5px solid #00acda}.page-sidebar .sub-menu>li>a.active:after{content:"\e251";font-family:'Glyphicons Halflings';position:relative;top:-1px;display:inline-block;font-style:normal;font-weight:400;float:right;color:#e9e9e9;font-size:18px;line-height:24px;margin-right:-6px}.page-sidebar .nav-menu>li.profile{padding:10px 10px;color:#ccc;background-color:#333;border-bottom:1px solid #464646}.page-sidebar .nav-menu>li.profile a.title{color:#ccc}.page-sidebar .nav-menu>li.profile a.title:hover{color:#fff;background-color:transparent}.page-sidebar .nav-menu>li.profile a.title:focus{background-color:transparent}.page-sidebar .nav-menu>li.profile .image{float:left;margin-top:3px;font-size:24px;color:#69f;width:36px;height:36px;border-radius:6px;background-color:#eee;text-align:center;margin-right:10px;overflow:hidden}.page-sidebar .nav-menu>li.profile .image img{margin-top:-3px}.page-sidebar .nav-menu>li.profile .name{display:block;padding-top:3px;font-size:14px}.page-sidebar .nav-menu>li.profile .role{display:block;font-size:12px;color:#999}.page-sidebar .nav-menu>li.profile.active{background-color:#0084a7;color:#fff}.page-sidebar .nav-menu>li.profile.active .name,.page-sidebar .nav-menu>li.profile.active .role{color:#fff}.page-sidebar .nav-menu>li.profile.active:after{content:"\e251";font-family:'Glyphicons Halflings';position:absolute;top:0;right:-1px;display:inline-block;font-style:normal;font-weight:400;color:#e9e9e9;font-size:24px;line-height:61px;margin-right:-6px}.page-sidebar .nav-menu>li.profile .dropdown-menu{min-width:0;font-size:13px}.page-sidebar .nav-menu>li.profile .dropdown-menu>li>a{padding-right:30px}.page-sidebar .nav-menu>li.profile .dropdown-menu>li>a:hover{background-color:#ccc}.page-sidebar .nav-menu>li.profile .dropdown-menu .divider{margin:5px 0}.page-sidebar .badge{margin-top:-10px;margin-left:5px}.page-content-inner{padding:15px}.box{border:none;box-shadow:1px 1px 2px rgba(0,0,0,0.2);background-color:#fff;padding:15px;margin-bottom:15px}.box .nav-tabs{font-size:14px;font-weight:bold}.box .nav-tabs>li:first-child{margin-left:30px}.box .tab-content>.tab-pane{background-color:#fff;padding:20px;border:1px solid #ddd;border-top:none;border-bottom-left-radius:3px;border-bottom-right-radius:3px}.box.box-nav-tabs{padding:0;background-color:#f5f5f5}.box.box-nav-tabs .nav-tabs{font-size:inherit;font-weight:inherit}.box.box-nav-tabs .nav-tabs>li{padding-top:8px}.box.box-nav-tabs .nav-tabs>li>a{margin-right:5px;border-top-left-radius:3px;border-top-right-radius:3px;padding:3px 15px;background-color:#e6e6e6;border:1px solid #ddd;border-bottom-color:transparent}.box.box-nav-tabs .nav-tabs>li.active>a{font-weight:bold;border:1px solid #ddd;border-bottom-color:transparent;background-color:#fff}.box.box-nav-tabs .tab-content>.tab-pane{padding:20px;border:none}.box-btn-bar{line-height:30px}.box-btn-bar a.btn{margin-right:20px}.page-filter{height:36px;line-height:36px;margin-bottom:10px}.page-filter .form-control{margin-top:5px;margin-right:4px}.form-group .input-group{margin-bottom:5px}.op_box{display:block;padding:5px;border-radius:3px;text-align:center;margin-top:5px}.op_error{background:#fbb}.op_wait{background:#ccc}.more-action{position:absolute !important}.more-action .dropdown-menu{background-color:rgba(60,60,60,0.9);color:#fff;font-size:13px}.more-action .dropdown-menu.dropdown-menu-left{margin-left:-120px}.more-action .dropdown-menu>li>a{padding:5px 20px;color:#fff}.more-action .dropdown-menu>li>a:hover,.more-action .dropdown-menu>li>a:active,.more-action .dropdown-menu>li>a:visited{background-color:#0084a7}.more-action .dropdown-menu .divider{margin:5px 0;background-color:#666}.popover-inline-edit input,.popover-inline-edit .btn{height:30px}.popover-inline-edit .popover-title{background-color:#ddd}.popover-inline-edit .popover-content{padding:20px 10px}.popover-inline-edit .popover{padding:0;max-width:500px}.popover-inline-edit .popover .popover-content{padding:10px 10px 20px 10px}.popover-inline-edit .popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#ddd}.tp-table-filter{width:100%;height:25px;margin:0;padding:0}.tp-table-filter .tp-table-filter-inner{display:table;margin:0;padding:0}.tp-table-filter.tp-table-filter-input .tp-table-filter-inner{width:100%}.tp-table-filter.tp-table-filter-left .tp-table-filter-inner,.tp-table-filter.tp-table-filter-right .tp-table-filter-inner{width:auto}.tp-table-filter.tp-table-filter-center .tp-table-filter-inner{margin:0 auto}.tp-table-filter .search-title{display:table-cell;vertical-align:middle;height:25px;line-height:25px;color:#555;white-space:nowrap;width:1px;text-align:left}.tp-table-filter .search-input,.tp-table-filter .search-select{display:table-cell;text-align:left;height:25px}.tp-table-filter .search-input>.btn,.tp-table-filter .search-select>.btn{font-size:13px;background-color:transparent;border:none;padding:0 0 0 8px;border-radius:0}.tp-table-filter .search-input>.btn:active,.tp-table-filter .search-select>.btn:active{box-shadow:none}.tp-table-filter .search-input .dropdown-menu,.tp-table-filter .search-select .dropdown-menu{min-width:0;background-color:rgba(0,0,0,0.8);color:#fff;font-size:13px;box-shadow:0 3px 6px rgba(0,0,0,0.3);border:none}.tp-table-filter .search-input .dropdown-menu>li>a,.tp-table-filter .search-select .dropdown-menu>li>a{padding-right:30px;min-width:100px;color:#fff}.tp-table-filter .search-input .dropdown-menu>li>a:hover,.tp-table-filter .search-select .dropdown-menu>li>a:hover,.tp-table-filter .search-input .dropdown-menu>li>a:active,.tp-table-filter .search-select .dropdown-menu>li>a:active,.tp-table-filter .search-input .dropdown-menu>li>a:visited,.tp-table-filter .search-select .dropdown-menu>li>a:visited{background-color:rgba(255,255,255,0.2)}.tp-table-filter .search-input .dropdown-menu .divider,.tp-table-filter .search-select .dropdown-menu .divider{margin:5px 0;background-color:#666}.tp-table-filter .search-input{width:100%;padding-left:10px}.tp-table-filter .search-input>.input-group .input-group-addon{font-size:13px;padding:0 5px}.tp-table-filter .search-input>.input-group input.form-control{font-size:13px;height:25px;width:100%;padding:0 5px}.btn.btn-no-border{font-size:13px;background-color:transparent;border:none;padding:0 0 0 8px;border-radius:0}.btn.btn-no-border:active{box-shadow:none}.table>tbody>tr.table-footer-action{background-color:transparent}.table>tbody>tr.table-footer-action>td{border-color:transparent;padding-top:15px;vertical-align:middle}.table-extend-area,.table-prefix-area{display:table;width:100%}.table-extend-area .table-extend-cell,.table-prefix-area .table-extend-cell{display:table-cell;height:24px;line-height:24px;padding:3px}.table-extend-area .table-extend-cell.table-extend-cell-right,.table-prefix-area .table-extend-cell.table-extend-cell-right{text-align:right}.table-extend-area .table-extend-cell .table-name,.table-prefix-area .table-extend-cell .table-name{font-size:120%;position:relative;top:3px;padding-right:10px}.table-extend-area .table-extend-cell .pagination,.table-prefix-area .table-extend-cell .pagination{margin:0 0}.table-extend-area .table-extend-cell .pagination>li>span,.table-prefix-area .table-extend-cell .pagination>li>span,.table-extend-area .table-extend-cell .pagination a,.table-prefix-area .table-extend-cell .pagination a{padding:3px 8px;font-size:12px;line-height:1.5}.table-extend-area .table-extend-cell.checkbox-select-all,.table-prefix-area .table-extend-cell.checkbox-select-all{width:36px;text-align:center}.table-extend-area .table-extend-cell.checkbox-select-all input,.table-prefix-area .table-extend-cell.checkbox-select-all input{position:relative;top:3px}.table-extend-area .table-extend-cell.group-actions>.btn-group .btn,.table-prefix-area .table-extend-cell.group-actions>.btn-group .btn{padding:5px 5px;font-size:12px}.table-extend-area .table-extend-cell.table-item-counter,.table-prefix-area .table-extend-cell.table-item-counter{text-align:right}.table-extend-area .table-extend-cell.table-item-counter ol,.table-prefix-area .table-extend-cell.table-item-counter ol{list-style:none;padding:0;margin:0;border:none;background-color:transparent;color:#666}.table-extend-area .table-extend-cell.table-item-counter ol>li,.table-prefix-area .table-extend-cell.table-item-counter ol>li{display:inline-block;padding-left:10px}.table-extend-area .table-extend-cell.table-item-counter .btn,.table-prefix-area .table-extend-cell.table-item-counter .btn{margin-top:-3px}.table-extend-area .table-extend-cell.table-item-counter .btn .caret,.table-prefix-area .table-extend-cell.table-item-counter .btn .caret{margin-top:-3px}.table-prefix-area{margin-bottom:10px}.table-prefix-area .table-extend-cell{padding:0}.btn-group.pagination .btn.dropdown-toggle{background-color:transparent;border:1px solid #999}textarea.textarea-resize-y{resize:vertical}textarea.textarea-resize-none{resize:none}textarea.textarea-code{font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace}textarea.cert_pub{width:100%;height:64px;border:1px solid #e2e2e2;background-color:#e4ffe5}.box ul.help-list{list-style:none;margin:0 0 10px 0;padding:0}.box ul.help-list li{padding:3px 3px 3px 20px;margin-left:10px}.box ul.help-list li:before{color:#999;position:absolute;margin-left:-1.2em;margin-top:1px;content:"\f05a";font-family:'Font Awesome 5 Free';font-weight:900}.box ul.help-list li em{color:#3374b0;font-style:normal}.tp-checkbox{display:inline-block;color:#747474}.tp-checkbox.tp-disabled{cursor:not-allowed;color:#c2c2c2}.tp-checkbox:before{display:inline-block;position:relative;top:1px;width:16px;content:"\f0c8";font-family:'Font Awesome 5 Free';font-weight:400}.tp-checkbox.tp-selected:before,.tp-checkbox.tp-checked:before{content:"\f14a";font-family:'Font Awesome 5 Free';font-weight:400}.tp-checkbox.tp-editable{cursor:pointer;color:#459dee}.tp-checkbox.tp-editable:hover{color:#53af43}.tp-checkbox.tp-editable.tp-selected,.tp-checkbox.tp-editable.tp-checked{color:#3374b0}i.upload-button{font-size:128px;color:#b1b1b1}i.upload-button:hover{cursor:pointer;color:#709cff}.assist-config .cfg-title{font-size:16px;font-weight:bold}.assist-config .form-group{margin-bottom:5px}.assist-config .col-sm-1,.assist-config .col-sm-2,.assist-config .col-sm-3,.assist-config .col-sm-4,.assist-config .col-sm-5,.assist-config .col-sm-6,.assist-config .col-sm-7,.assist-config .col-sm-8,.assist-config .col-sm-9,.assist-config .col-sm-10,.assist-config .col-sm-11{padding-left:3px;padding-right:3px}.assist-config .arg-detail ol,.assist-config .arg-detail ul{margin-bottom:0}.assist-config .arg-detail-common{background-color:#edfedf;border-radius:5px;padding:15px}.assist-config select,.assist-config .input-args{font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace}.assist-config .desc{margin-top:5px;color:#6b6b6b}.assist-config .arg-varb{color:#393939;font-weight:bold;font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace;display:inline-block;width:180px}#gritter-notice-wrapper{z-index:9999}.gritter-bottom,.gritter-item,.gritter-top{background:rgba(0,0,0,0.8) !important}.gritter-top{border-top-left-radius:3px;border-top-right-radius:3px}.gritter-bottom{border-bottom-left-radius:3px;border-bottom-right-radius:3px}.gritter-close,.gritter-light .gritter-close{left:auto !important;right:5px !important;top:5px !important;width:16px !important;height:16px !important;line-height:16px !important;display:block !important;border-radius:50%}.gritter-close:before,.gritter-light .gritter-close:before{content:'\f00d' !important;font-family:'Font Awesome 5 Free' !important;font-weight:900 !important;font-size:9px !important;width:16px !important;height:16px !important;line-height:16px !important;color:#fff !important;text-indent:0 !important;position:absolute !important;text-align:center !important;right:0 !important;top:0 !important}.gritter-title{font-size:13px !important;line-height:16px !important;padding-bottom:5px !important;font-weight:400 !important;color:#fff !important;text-shadow:none !important}.gritter-item{color:#aaa !important;font-size:13px !important;padding:2px 15px 5px !important}.gritter-error .gritter-bottom,.gritter-error .gritter-item,.gritter-error .gritter-top{background:rgba(123,32,32,0.9) !important}.gritter-error .gritter-title{color:#fff !important}.gritter-error .gritter-item{color:#ddd !important}.gritter-error .gritter-close{left:auto !important;right:5px !important;top:5px !important;width:16px !important;height:16px !important;line-height:16px !important;display:block !important;border-radius:50%;background:#e33b3b !important}.gritter-success .gritter-bottom,.gritter-success .gritter-item,.gritter-success .gritter-top{background:rgba(1,65,16,0.9) !important}.gritter-success .gritter-title{color:#ddd !important}.gritter-success .gritter-item{color:#ccc !important}.gritter-success .gritter-close{background:#0eb320 !important}#gritter-notice-wrapper{width:320px;max-width:480px}/*# sourceMappingURL=style.css.map */ \ No newline at end of file diff --git a/server/www/teleport/static/js/_sidebar_nav_menu.js b/server/www/teleport/static/js/_sidebar_nav_menu.js index beacf6e..b83b478 100644 --- a/server/www/teleport/static/js/_sidebar_nav_menu.js +++ b/server/www/teleport/static/js/_sidebar_nav_menu.js @@ -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('未连接'); } }; diff --git a/server/www/teleport/static/js/asset/host-list.js b/server/www/teleport/static/js/asset/host-list.js index 8416d60..373c9b9 100644 --- a/server/www/teleport/static/js/asset/host-list.js +++ b/server/www/teleport/static/js/asset/host-list.js @@ -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)); } diff --git a/server/www/teleport/static/js/assist/config.js b/server/www/teleport/static/js/assist/config.js new file mode 100644 index 0000000..585088b --- /dev/null +++ b/server/www/teleport/static/js/assist/config.js @@ -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('
' + item.desc[j] + '
'); + } + 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(''); + } + + 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)); + +} diff --git a/server/www/teleport/static/js/audit/record-list.js b/server/www/teleport/static/js/audit/record-list.js index a336107..cf1be26 100644 --- a/server/www/teleport/static/js/audit/record-list.js +++ b/server/www/teleport/static/js/audit/record-list.js @@ -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)); diff --git a/server/www/teleport/static/js/audit/replay-rdp.js b/server/www/teleport/static/js/audit/replay-rdp.js index 6494dc8..5707401 100644 --- a/server/www/teleport/static/js/audit/replay-rdp.js +++ b/server/www/teleport/static/js/audit/replay-rdp.js @@ -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 = ''; + let h = ''; $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 diff --git a/server/www/teleport/static/js/dashboard/dashboard.js b/server/www/teleport/static/js/dashboard/dashboard.js index ff09a35..1f6f39d 100644 --- a/server/www/teleport/static/js/dashboard/dashboard.js +++ b/server/www/teleport/static/js/dashboard/dashboard.js @@ -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) { diff --git a/server/www/teleport/static/js/maintenance/upgrade.js b/server/www/teleport/static/js/maintenance/upgrade.js index 8d8e4bb..b26e726 100644 --- a/server/www/teleport/static/js/maintenance/upgrade.js +++ b/server/www/teleport/static/js/maintenance/upgrade.js @@ -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(' '); - html.push(steps[i].msg); - html.push('

') - } - 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(); - }; diff --git a/server/www/teleport/static/js/ops/remote-list.js b/server/www/teleport/static/js/ops/remote-list.js index b2eb43b..49fe86e 100644 --- a/server/www/teleport/static/js/ops/remote-list.js +++ b/server/www/teleport/static/js/ops/remote-list.js @@ -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)); } diff --git a/server/www/teleport/static/js/teleport.js b/server/www/teleport/static/js/teleport.js index e470ac5..3b9f7b0 100644 --- a/server/www/teleport/static/js/teleport.js +++ b/server/www/teleport/static/js/teleport.js @@ -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; } diff --git a/server/www/teleport/static/js/teleport/common.js b/server/www/teleport/static/js/teleport/common.js index bcfb70e..8c363a4 100644 --- a/server/www/teleport/static/js/teleport/common.js +++ b/server/www/teleport/static/js/teleport/common.js @@ -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 = ' ' + _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 = '
'; - var html = []; + // let html = '
'; + let html = []; html.push('
'); - var has_message = false; + let has_message = false; if (!_.isUndefined(message) && !_.isNull(message) && message.length > 0) { html.push('
' + message + '
'); 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 || ' 操作确认'; 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 = [ '