diff --git a/client/tp_assist_win/ts_http_rpc.cpp b/client/tp_assist_win/ts_http_rpc.cpp index 6238c89..85b557a 100644 --- a/client/tp_assist_win/ts_http_rpc.cpp +++ b/client/tp_assist_win/ts_http_rpc.cpp @@ -16,22 +16,22 @@ /* 1. -SecureCRT支持设置标签页的标题,命令行参数 /N "tab name"就可以 +SecureCRT鏀寔璁剧疆鏍囩椤电殑鏍囬锛屽懡浠よ鍙傛暟 /N "tab name"灏卞彲浠 Example: To launch a new Telnet session, displaying the name "Houston, TX" on the tab, use the following: /T /N "Houston, TX" /TELNET 192.168.0.6 2. -多次启动的SecureCRT放到一个窗口的不同标签页中,使用参数: /T +澶氭鍚姩鐨凷ecureCRT鏀惧埌涓涓獥鍙g殑涓嶅悓鏍囩椤典腑锛屼娇鐢ㄥ弬鏁帮細 /T SecureCRT.exe /T /N "TP#ssh://192.168.1.3" /SSH2 /L root /PASSWORD 1234 120.26.109.25 3. -telnet客户端的启动: +telnet瀹㈡埛绔殑鍚姩锛 putty.exe telnet://administrator@127.0.0.1:52389 -如果是SecureCRT,则需要 +濡傛灉鏄疭ecureCRT锛屽垯闇瑕 SecureCRT.exe /T /N "TP#telnet://192.168.1.3" /SCRIPT X:\path\to\startup.vbs /TELNET 127.0.0.1 52389 -其中,startup.vbs的内容为: ----------文件开始--------- +鍏朵腑锛宻tartup.vbs鐨勫唴瀹逛负锛 +---------鏂囦欢寮濮--------- #$language = "VBScript" #$interface = "1.0" Sub main @@ -40,11 +40,11 @@ Sub main crt.Screen.Send "SESSION-ID" & VbCr crt.Screen.Synchronous = False End Sub ----------文件结束--------- +---------鏂囦欢缁撴潫--------- -4. 为了让putty的窗口标签显示正常的IP,可以尝试在连接成功后,主动向服务端发送下列命令: +4. 涓轰簡璁﹑utty鐨勭獥鍙f爣绛炬樉绀烘甯哥殑IP锛屽彲浠ュ皾璇曞湪杩炴帴鎴愬姛鍚庯紝涓诲姩鍚戞湇鍔$鍙戦佷笅鍒楀懡浠わ細 PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@192.168.1.2: \w\a\]$PS1" -手工测试了,ubuntu服务器可以,不知道是否能够支持所有的Linux。SecureCRT对此表示忽略。 +鎵嬪伐娴嬭瘯浜嗭紝ubuntu鏈嶅姟鍣ㄥ彲浠ワ紝涓嶇煡閬撴槸鍚﹁兘澶熸敮鎸佹墍鏈夌殑Linux銆係ecureCRT瀵规琛ㄧず蹇界暐銆 */ //#define RDP_CLIENT_SYSTEM_BUILTIN @@ -203,6 +203,40 @@ bool calc_psw51b(const char* password, std::string& ret) return true; } +bool isDegital(std::string str) { + for (int i = 0; i < str.size(); i++) { + if (str.at(i) == '-' && str.size() > 1) // 鏈夊彲鑳藉嚭鐜拌礋鏁 + continue; + if (str.at(i) > '9' || str.at(i) < '0') + return false; + } + return true; +} + +std::string strtolower(std::string str) { + for (int i = 0; i < str.size(); i++) + { + str[i] = tolower(str[i]); + } + return str; +} + +void SplitString(const std::string& s, std::vector& v, const std::string& c) +{ + std::string::size_type pos1, pos2; + pos2 = s.find(c); + pos1 = 0; + while (std::string::npos != pos2) + { + v.push_back(s.substr(pos1, pos2 - pos1)); + + pos1 = pos2 + c.size(); + pos2 = s.find(c, pos1); + } + if (pos1 != s.length()) + v.push_back(s.substr(pos1)); +} + TsHttpRpc::TsHttpRpc() { m_stop = false; @@ -317,7 +351,7 @@ void TsHttpRpc::_mg_event_handler(struct mg_connection *nc, int ev, void *ev_dat if (uri == "/") { - ex_wstr page = L"Teleport助手\n\n
Teleport助手工作正常!
"; + ex_wstr page = L"Teleport鍔╂墜\n\n
Teleport鍔╂墜宸ヤ綔姝e父锛
"; ex_wstr2astr(page, ret_buf, EX_CODEPAGE_UTF8); mg_printf(nc, "HTTP/1.0 200 OK\r\nAccess-Control-Allow-Origin: *\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n%s", ret_buf.size() - 1, &ret_buf[0]); @@ -424,7 +458,7 @@ int TsHttpRpc::_parse_request(struct http_message* req, ex_astr& func_cmd, ex_as ex_astrs strs; - size_t pos_start = 1; // 跳过第一个字节,一定是 '/' + size_t pos_start = 1; // 璺宠繃绗竴涓瓧鑺傦紝涓瀹氭槸 '/' size_t i = 0; for (i = pos_start; i < req->uri.len; ++i) @@ -437,7 +471,7 @@ int TsHttpRpc::_parse_request(struct http_message* req, ex_astr& func_cmd, ex_as tmp_uri.assign(req->uri.p + pos_start, i - pos_start); strs.push_back(tmp_uri); } - pos_start = i + 1; // 跳过当前找到的分隔符 + pos_start = i + 1; // 璺宠繃褰撳墠鎵惧埌鐨勫垎闅旂 } } if (pos_start < req->uri.len) @@ -485,7 +519,7 @@ int TsHttpRpc::_parse_request(struct http_message* req, ex_astr& func_cmd, ex_as if (func_args.length() > 0) { - // 将参数进行 url-decode 解码 + // 灏嗗弬鏁拌繘琛 url-decode 瑙g爜 int len = func_args.length() * 2; ex_chars sztmp; sztmp.resize(len); @@ -536,7 +570,7 @@ void TsHttpRpc::_process_js_request(const ex_astr& func_cmd, const ex_astr& func void TsHttpRpc::_create_json_ret(ex_astr& buf, int errcode) { - // 返回: {"code":123} + // 杩斿洖锛 {"code":123} Json::FastWriter jr_writer; Json::Value jr_root; @@ -551,13 +585,65 @@ void TsHttpRpc::_create_json_ret(ex_astr& buf, Json::Value& jr_root) buf = jr_writer.write(jr_root); } +void TsHttpRpc::_rpc_func_url_protocol(const ex_astr& args, ex_astr& buf) +{ + //澶勭悊urlprotocol璋冪敤璁垮紡 + // 灏嗗弬鏁拌繘琛 url-decode 瑙g爜 + std::string func_args = args; + if (func_args.length() > 0) + { + int len = func_args.length() * 2; + ex_chars sztmp; + sztmp.resize(len); + memset(&sztmp[0], 0, len); + if (-1 == ts_url_decode(func_args.c_str(), func_args.length(), &sztmp[0], len, 0)) + return ; + + func_args = &sztmp[0]; + } + EXLOGD(("%s\n"), func_args.c_str()); + //澶勭悊浼犲弬杩囨潵鐨則eleport://{}/,鍙繚鐣欏弬鏁伴儴浠 + std::string urlproto_appname = TP_URLPROTO_APP_NAME; + urlproto_appname += "://{"; + func_args.erase(0, urlproto_appname.length());//鍘婚櫎绗竴涓猆RLPROTO_APP_NAME浠ュ強://瀛楃 + int pos = func_args.length() - 1; + if (func_args.substr(pos, 1) == "/") + func_args.erase(pos - 1, 2);//鍘婚櫎鏈鍚庝竴涓獇/瀛楃 + else + func_args.erase(pos, 1); + + //鐢变簬鍛戒护琛屻乮e娴忚鍣ㄥ弬鏁颁紶閫掓椂浼氭妸鍘熸潵json缁撴瀯涓殑"鍙峰幓鎺夛紝闇瑕侀噸鏂版牸寮忓寲鍙傛暟涓簀son鏍煎紡 + if (func_args.find("\"", 0) == std::string::npos) { + std::vector strv; + SplitString(func_args, strv, ","); + func_args = ""; + for (std::vector::size_type i = 0; i < strv.size(); i++) { + std::vector strv1; + SplitString(strv[i], strv1, ":"); + strv1[0] = "\"" + strv1[0] + "\""; + if (!isDegital(strv1[1]) && strtolower(strv1[1]) != "true" && strtolower(strv1[1]) != "false") + strv1[1] = "\"" + strv1[1] + "\""; + + strv[i] = strv1[0] + ":" + strv1[1]; + if (i == 0) + func_args = strv[i]; + else + func_args += "," + strv[i]; + } + } + func_args = "{" + func_args + "}"; + EXLOGD(("%s\n"), func_args.c_str()); + //璋冪敤TsHttpRpc绫婚噷鐨刜rpc_func_run_client鍚姩瀹㈡埛绔 + _rpc_func_run_client(func_args, buf); +} + void TsHttpRpc::_rpc_func_run_client(const ex_astr& func_args, ex_astr& buf) { - // 入参:{"ip":"192.168.5.11","port":22,"uname":"root","uauth":"abcdefg","authmode":1,"protocol":2} + // 鍏ュ弬锛歿"ip":"192.168.5.11","port":22,"uname":"root","uauth":"abcdefg","authmode":1,"protocol":2} // authmode: 1=password, 2=private-key // protocol: 1=rdp, 2=ssh - // SSH返回: {"code":0, "data":{"sid":"0123abcde"}} - // RDP返回: {"code":0, "data":{"sid":"0123abcde0A"}} + // SSH杩斿洖锛 {"code":0, "data":{"sid":"0123abcde"}} + // RDP杩斿洖锛 {"code":0, "data":{"sid":"0123abcde0A"}} Json::Reader jreader; Json::Value jsRoot; @@ -573,7 +659,7 @@ void TsHttpRpc::_rpc_func_run_client(const ex_astr& func_args, ex_astr& buf) return; } - // 判断参数是否正确 + // 鍒ゆ柇鍙傛暟鏄惁姝g‘ if (!jsRoot["teleport_ip"].isString() || !jsRoot["teleport_port"].isNumeric() || !jsRoot["remote_host_ip"].isString() || !jsRoot["session_id"].isString() || !jsRoot["protocol_type"].isNumeric() || !jsRoot["protocol_sub_type"].isNumeric() @@ -688,7 +774,7 @@ void TsHttpRpc::_rpc_func_run_client(const ex_astr& func_args, ex_astr& buf) int iHeight = GetSystemMetrics(SM_CYSCREEN); if (rdp_w == 0 || rdp_h == 0) { - //全屏 + //鍏ㄥ睆 width = iWidth; higth = iHeight; display = 2; @@ -763,7 +849,7 @@ void TsHttpRpc::_rpc_func_run_client(const ex_astr& func_args, ex_astr& buf) fclose(f); ex_astr2wstr(sz_file_name, tmp_rdp_file); - // 变量替换 + // 鍙橀噺鏇挎崲 ex_replace_all(w_exe_path, _T("{tmp_rdp_file}"), tmp_rdp_file); } else if (g_cfg.rdp_name == L"freerdp") { @@ -773,7 +859,7 @@ void TsHttpRpc::_rpc_func_run_client(const ex_astr& func_args, ex_astr& buf) ex_wstr w_screen; if (rdp_w == 0 || rdp_h == 0) { - //全屏 + //鍏ㄥ睆 w_screen = _T("/f"); } else { @@ -800,10 +886,10 @@ void TsHttpRpc::_rpc_func_run_client(const ex_astr& func_args, ex_astr& buf) w_sid = L"02" + w_sid; - w_exe_path += L" /gdi:sw"; // 使用软件渲染,gdi:hw使用硬件加速,但是会出现很多黑块(录像回放时又是正常的!) - w_exe_path += L" -grab-keyboard"; // [new style] 防止启动FreeRDP后,失去本地键盘响应,必须得先最小化一下FreeRDP窗口(不过貌似不起作用) + w_exe_path += L" /gdi:sw"; // 浣跨敤杞欢娓叉煋锛実di:hw浣跨敤纭欢鍔犻燂紝浣嗘槸浼氬嚭鐜板緢澶氶粦鍧楋紙褰曞儚鍥炴斁鏃跺張鏄甯哥殑锛侊級 + w_exe_path += L" -grab-keyboard"; // [new style] 闃叉鍚姩FreeRDP鍚庯紝澶卞幓鏈湴閿洏鍝嶅簲锛屽繀椤诲緱鍏堟渶灏忓寲涓涓婩reeRDP绐楀彛锛堜笉杩囪矊浼间笉璧蜂綔鐢級 - // 变量替换 + // 鍙橀噺鏇挎崲 ex_replace_all(w_exe_path, _T("{size}"), w_screen); if (flag_console && rdp_console) @@ -899,7 +985,7 @@ void TsHttpRpc::_rpc_func_rdp_play(const ex_astr& func_args, ex_astr& buf) return; } - // 判断参数是否正确 + // 鍒ゆ柇鍙傛暟鏄惁姝g‘ if (!jsRoot["rid"].isInt() || !jsRoot["web"].isString() || !jsRoot["sid"].isString() @@ -924,9 +1010,9 @@ void TsHttpRpc::_rpc_func_rdp_play(const ex_astr& func_args, ex_astr& buf) char cmd_args[1024] = { 0 }; ex_strformat(cmd_args, 1023, "%d \"%s\" \"%09d-%s-%s-%s-%s\"", rid, a_sid.c_str(), rid, a_user.c_str(), a_acc.c_str(), a_host.c_str(), a_start.c_str()); - // TODO: 理论上不应该由助手来提前做域名转为IP这样的操作,而是应该讲域名发送给播放器,由播放器自己去处理 - // 但是在改造FreeRDP制作的播放器时,为了从服务器上下载文件,使用了Mongoose库,如果传入的是域名,会出现问题(貌似是异步查询DNS的问题) - // 所以暂时先由助手进行域名IP转换。 + // TODO: 鐞嗚涓婁笉搴旇鐢卞姪鎵嬫潵鎻愬墠鍋氬煙鍚嶈浆涓篒P杩欐牱鐨勬搷浣滐紝鑰屾槸搴旇璁插煙鍚嶅彂閫佺粰鎾斁鍣紝鐢辨挱鏀惧櫒鑷繁鍘诲鐞 + // 浣嗘槸鍦ㄦ敼閫燜reeRDP鍒朵綔鐨勬挱鏀惧櫒鏃讹紝涓轰簡浠庢湇鍔″櫒涓婁笅杞芥枃浠讹紝浣跨敤浜哅ongoose搴擄紝濡傛灉浼犲叆鐨勬槸鍩熷悕锛屼細鍑虹幇闂锛堣矊浼兼槸寮傛鏌ヨDNS鐨勯棶棰橈級 + // 鎵浠ユ殏鏃跺厛鐢卞姪鎵嬭繘琛屽煙鍚岻P杞崲銆 { unsigned int port_i = 0; struct mg_str scheme, query, fragment, user_info, host, path; @@ -942,7 +1028,7 @@ void TsHttpRpc::_rpc_func_rdp_play(const ex_astr& func_args, ex_astr& buf) ex_astr _scheme; _scheme.assign(scheme.p, scheme.len); - // 将host从域名转换为IP + // 灏唄ost浠庡煙鍚嶈浆鎹负IP ex_astr str_tp_host; str_tp_host.assign(host.p, host.len); struct hostent *tp_host = gethostbyname(str_tp_host.c_str()); @@ -1052,7 +1138,7 @@ void TsHttpRpc::_rpc_func_file_action(const ex_astr& func_args, ex_astr& buf) { _create_json_ret(buf, TPE_JSON_FORMAT); return; } - // 判断参数是否正确 + // 鍒ゆ柇鍙傛暟鏄惁姝g‘ if (!jsRoot["action"].isNumeric()) { _create_json_ret(buf, TPE_PARAM); @@ -1077,9 +1163,9 @@ void TsHttpRpc::_rpc_func_file_action(const ex_astr& func_args, ex_astr& buf) { ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); - ofn.lpstrTitle = _T("选择文件"); + ofn.lpstrTitle = _T("閫夋嫨鏂囦欢"); ofn.hwndOwner = hParent; - ofn.lpstrFilter = _T("可执行程序 (*.exe)\0*.exe\0"); + ofn.lpstrFilter = _T("鍙墽琛岀▼搴 (*.exe)\0*.exe\0"); ofn.lpstrFile = wszReturnPath; ofn.nMaxFile = MAX_PATH; ofn.lpstrInitialDir = wsDefaultPath.c_str(); @@ -1102,12 +1188,12 @@ void TsHttpRpc::_rpc_func_file_action(const ex_astr& func_args, ex_astr& buf) { ZeroMemory(&bi, sizeof(BROWSEINFO)); bi.hwndOwner = NULL; bi.pidlRoot = NULL; - bi.pszDisplayName = wszReturnPath; //此参数如为NULL则不能显示对话框 - bi.lpszTitle = _T("选择目录"); + bi.pszDisplayName = wszReturnPath; //姝ゅ弬鏁板涓篘ULL鍒欎笉鑳芥樉绀哄璇濇 + bi.lpszTitle = _T("閫夋嫨鐩綍"); bi.ulFlags = BIF_RETURNONLYFSDIRS; bi.lpfn = NULL; - bi.iImage = 0; //初始化入口参数bi结束 - LPITEMIDLIST pIDList = SHBrowseForFolder(&bi);//调用显示选择对话框 + bi.iImage = 0; //鍒濆鍖栧叆鍙e弬鏁癰i缁撴潫 + LPITEMIDLIST pIDList = SHBrowseForFolder(&bi);//璋冪敤鏄剧ず閫夋嫨瀵硅瘽妗 if (pIDList) { ret = true;