public ThinWebClientProfile CloneAsDefault() { ThinWebClientProfile ret = this._CloneWithJson(); ret.Pcid = ""; ret.Preference = ret.Preference.CloneAsDefault(); ret.Normalize(); return(ret); }
public void Add(ThinWebClientProfile profile) { var clone = profile._CloneWithJson(); clone.Normalize(); if (clone.Pcid._IsEmpty()) { return; } var deleteList = this.Items.Where(x => x.Pcid._IsSamei(clone.Pcid)).ToList(); deleteList.ForEach(x => this.Items.Remove(x)); this.Items.Add(clone); while (this.Items.Count >= 1 && this.Items.Count > ThinWebClientConsts.MaxHistory) { this.Items.RemoveAt(0); } }
public async Task AcceptWebSocketAsync(string?id, string?width, string?height) { await using (TaskUtil.CreateCombinedCancellationToken(out CancellationToken cancel, this._GetRequestCancellationToken(), this.Client.GrandCancel)) { if (HttpContext.WebSockets.IsWebSocketRequest) { // 指定されたセッション ID を元に検索 var session = this.Client.SessionManager.GetSessionById(id._NonNull()); if (session != null) { ThinClientConnectOptions connectOptions = (ThinClientConnectOptions)session.Param !; ThinWebClientProfile profile = (ThinWebClientProfile)connectOptions.AppParams !; if (connectOptions.DebugGuacMode == false) { throw new CoresLibException("connectOptions.DebugGuacMode == false"); } var req = session.GetFinalAnswerRequest(); if (req?.RequestData is ThinClientAcceptReadyNotification ready) { var pref = profile.Preference._CloneWithJson(); // ws 接続時に width と height がパラメータとして指定されていた場合は、preference の内容を更新する int widthInt = width._ToInt(); int heightInt = height._ToInt(); if (widthInt >= 1 && heightInt >= 1) { pref.ScreenWidth = widthInt; pref.ScreenHeight = heightInt; } await using var guaClient = new GuaClient( new GuaClientSettings( Client.SettingsFastSnapshot.Debug_GuacdMode_GuacdHostname, Client.SettingsFastSnapshot.Debug_GuacdPort, ready.FirstConnection !.SvcType.ToString().StrToGuaProtocol(), "", ready.ListenEndPoint !.Port, //"pc37.sec.softether.co.jp", 3333, // testtest pref, connectOptions.IsWebpSupported, ready.FirstConnection.Caps.Bit(ThinServerCaps.AudioInSupported))); var readyPacket = await guaClient.StartAsync(cancel); await using var gcStream = guaClient.Stream._NullCheck(); using var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync("guacamole"); //if (true) //{ // MemoryStream ms = new MemoryStream(); // await readyPacket.SendPacketAsync(ms); // //var tmp = ms.ToArray(); // var tmp = "6.hello;"._GetBytes_Ascii(); // await webSocket.SendAsync(tmp, WebSocketMessageType.Text, true, cancel); //} await GuaWebSocketUtil.RelayBetweenWebSocketAndStreamDuplex(gcStream, webSocket, cancel : cancel); return; } } } HttpContext.Response.StatusCode = 400; } }
public async Task <IActionResult> SessionAsync(string?id, string?requestid, string?formtype, string?password, string?username, string?otp, string?pcid) { var cancel = Request._GetRequestCancellationToken(); id = id._NonNullTrim(); // 指定されたセッション ID を元に検索 var session = this.Client.SessionManager.GetSessionById(id); if (session == null) { // セッション ID が見つからない。トップページに戻る return(Redirect("/" + (pcid._IsFilled() ? "?pcid=" + pcid._MakeVerySafeAsciiOnlyNonSpaceString() : ""))); } else { ThinClientConnectOptions connectOptions = (ThinClientConnectOptions)session.Param !; ThinWebClientProfile profile = (ThinWebClientProfile)connectOptions.AppParams !; if (requestid._IsFilled() && formtype._IsFilled()) { IDialogResponseData?responseData = null; switch (formtype) { case "SessionAuthPassword": responseData = new ThinClientAuthResponse { Username = "", Password = password._NonNull() }; break; case "SessionAuthAdvanced": responseData = new ThinClientAuthResponse { Username = username._NonNull(), Password = password._NonNull() }; break; case "SessionOtp": responseData = new ThinClientOtpResponse { Otp = otp._NonNull() }; break; } if (responseData != null) { session.SetResponseData(requestid, responseData); } } L_GET_NEXT: var req = await session.GetNextRequestAsync(cancel : cancel); if (req != null) { session.SendHeartBeat(req.RequestId); switch (req.RequestData) { case ThinClientAuthRequest authReq: switch (authReq.AuthType) { case ThinAuthType.None: session.SetResponseData(req.RequestId, new ThinClientAuthResponse()); goto L_GET_NEXT; case ThinAuthType.Password: ThinWebClientModelSessionAuthPassword page = new ThinWebClientModelSessionAuthPassword { SessionId = session.SessionId, RequestId = req.RequestId, ConnectOptions = connectOptions, Request = authReq, Profile = profile._CloneWithJson(), }; return(View("SessionAuthPassword", page)); case ThinAuthType.Advanced: ThinWebClientModelSessionAuthPassword page2 = new ThinWebClientModelSessionAuthPassword { SessionId = session.SessionId, RequestId = req.RequestId, ConnectOptions = connectOptions, Request = authReq, Profile = profile._CloneWithJson(), }; return(View("SessionAuthAdvanced", page2)); default: throw new CoresException($"authReq.AuthType = {authReq.AuthType}: Unsupported auth type."); } case ThinClientOtpRequest otpReq: ThinWebClientModelOtp page3 = new ThinWebClientModelOtp { SessionId = session.SessionId, RequestId = req.RequestId, ConnectOptions = connectOptions, Profile = profile._CloneWithJson(), }; return(View("SessionOtp", page3)); case ThinClientAcceptReadyNotification ready: if (ready.IsStandaloneMode) { if (Request.Headers._GetStrFirst("X-Original-For")._IsEmpty()) { var ss = Page.Stb["THINWEB_STANDALONE_MUST_VIA_PROXY"]; throw new CoresException(ss); } } if (connectOptions.DebugGuacMode) { connectOptions.UpdateConnectedSvcType(ready.FirstConnection !.SvcType); connectOptions.UpdateWatermarkStr(ready.FirstConnection !.WatermarkStr1, ready.FirstConnection !.WatermarkStr2); connectOptions.UpdateMiscParams(ready.FirstConnection.Misc); connectOptions.UpdateCaps(ready.FirstConnection.Caps); } else { connectOptions.UpdateConnectedSvcType(ready.SvcType !.Value); ready.WebSocketFullUrl._NotEmptyCheck(); connectOptions.UpdateWebSocketUrl(ready.WebSocketFullUrl); connectOptions.UpdateConnectPacketData(ready.ConnectPacketData); connectOptions.UpdateWatermarkStr(ready.WatermarkStr1, ready.WatermarkStr2); connectOptions.UpdateMiscParams(ready.Misc); connectOptions.UpdateCaps(ready.Caps); } if (ready.WebSocketFullUrl._IsFilled()) { $"ready.WebSocketFullUrl = {ready.WebSocketFullUrl?.ToString()}"._Debug(); } else { $"ready.ListenEndPoint = {ready.ListenEndPoint?.ToString()}"._Debug(); } req.SetResponseDataEmpty(); return(Redirect($"/ThinWebClient/Remote/{session.SessionId}/" + (pcid._IsFilled() ? "?pcid=" + pcid._MakeVerySafeAsciiOnlyNonSpaceString() : ""))); case ThinClientInspectRequest inspect: ThinClientInspectResponse insRes = new ThinClientInspectResponse { AntiVirusOk = true, Ticket = "", WindowsUpdateOk = true, MacAddressList = Str.NormalizeMac(profile.Preference.MacAddress, style: MacAddressStyle.Windows), }; session.SetResponseData(req.RequestId, insRes); goto L_GET_NEXT; default: throw new CoresException($"Unknown request data: {req.RequestData.GetType().ToString()}"); } } else { Dbg.Where(); } } return(Redirect("/" + (pcid._IsFilled() ? "?pcid=" + pcid._MakeVerySafeAsciiOnlyNonSpaceString() : ""))); }
public async Task <IActionResult> RemoteAsync(string?id, string?pcid) { var cancel = Request._GetRequestCancellationToken(); id = id._NonNullTrim(); // 指定されたセッション ID を元に検索 var session = this.Client.SessionManager.GetSessionById(id); if (session != null) { ThinClientConnectOptions connectOptions = (ThinClientConnectOptions)session.Param !; ThinWebClientProfile profile = (ThinWebClientProfile)connectOptions.AppParams !; var req = session.GetFinalAnswerRequest(); if (req != null) { var misc2 = new ThinWebClientRemoteMisc2(); var caps = connectOptions.Caps; // VNC の場合にメッセージを表示する if (connectOptions.ConnectedSvcType !.Value == ThinSvcType.Vnc) { if (caps.Bit(ThinServerCaps.UrdpVeryLimited)) { misc2.OnceMsg = Page.Stb["DU_ONCEMSG_1"]; } else { if (caps.Bit(ThinServerCaps.WinRdpEnabled)) { misc2.OnceMsg = Page.Stb["DU_ONCEMSG_3"]; } else { misc2.OnceMsg = Page.Stb["DU_ONCEMSG_2"]; } } misc2.OnceMsg = misc2.OnceMsg._FormatC(profile.Pcid); misc2.OnceMsgTitle = "操作のヒント"; } ThinWebClientModelRemote main = new ThinWebClientModelRemote() { ConnectOptions = connectOptions, WebSocketUrl = connectOptions.WebSocketUrl, SessionId = session.SessionId, Profile = profile, SvcType = connectOptions.ConnectedSvcType !.Value, ConnectPacketData = connectOptions.ConnectPacketData, WatermarkStr1 = connectOptions.WatermarkStr1, WatermarkStr2 = connectOptions.WatermarkStr2, Misc = connectOptions.MiscParams, Misc2 = misc2, }; return(View(main)); } } await TaskCompleted; return(Redirect("/" + (pcid._IsFilled() ? "?pcid=" + pcid._MakeVerySafeAsciiOnlyNonSpaceString() : ""))); }
public async Task <IActionResult> IndexAsync(ThinWebClientModelIndex form, string?pcid, string?deleteAll, string?button_wol) { ThinWebClientProfile?historySelectedProfile = null; ThinWebClientProfile profile = form.CurrentProfile; profile.Normalize(); ThinWebClientHistory history = ThinWebClientHistory.LoadFromCookie(this, this.Client.SettingsFastSnapshot.CookieEncryptPassword); if (this._IsPostBack()) { if (profile.Pcid._IsFilled()) { // 現在のプロファイルの保存 this._EasySaveCookie("thin_current_profile", profile.CloneAsDefault(), GetCookieOption(), true, this.Client.SettingsFastSnapshot.CookieEncryptPassword); // ヒストリへの追加 history.Add(profile); history.SaveToCookie(this, GetCookieOption(), this.Client.SettingsFastSnapshot.CookieEncryptPassword); // thin_last_pcid の保存 this._EasySaveCookie("thin_last_pcid", profile.Pcid, GetCookieOption()); var clientIp = Request.HttpContext.Connection.RemoteIpAddress._UnmapIPv4() !; var clientPort = Request.HttpContext.Connection.RemotePort; string clientFqdn = await Client.DnsResolver.GetHostNameSingleOrIpAsync(clientIp); // Rate limit if (this.Client.RateLimit.TryInput(clientIp.ToString(), out _) == false) { throw new CoresException(this.Page.Stb["THINWEB_RATELIMIT_EXCEEDED"]); } var tc = this.Client.CreateThinClient(this.StrTable); if (button_wol._ToBool() == false) { // 普通の接続 WideTunnelClientOptions wideOptions = new WideTunnelClientOptions(WideTunnelClientFlags.None, clientIp.ToString(), clientFqdn, clientPort); // セッションの開始 var session = tc.StartConnect(new ThinClientConnectOptions(profile.Pcid, clientIp, clientFqdn, this.Client.SettingsFastSnapshot.Debug_EnableGuacdMode, wideOptions, form.IsWebpSupported, profile.Preference, profile._CloneWithJson()), this.Client.SettingsFastSnapshot.MaxConcurrentSessionsPerClientIp); string sessionId = session.SessionId; // セッション ID をもとにした URL にリダイレクト return(Redirect($"/ThinWebClient/Session/{sessionId}/?pcid={profile.Pcid._MakeVerySafeAsciiOnlyNonSpaceString()}")); } else { try { // WoL 信号の発射 WideTunnelClientOptions wideOptions = new WideTunnelClientOptions(WideTunnelClientFlags.WoL, clientIp.ToString(), clientFqdn, clientPort); await tc.ExecuteWoLAsync(new ThinClientConnectOptions(profile.Preference.WoLTriggerPcid, clientIp, clientFqdn, false, wideOptions, form.IsWebpSupported, profile.Preference, profile._CloneWithJson()), profile.Pcid, this._GetRequestCancellationToken()); // WoL OK メッセージ form.WolOkMessage = this.Page.Stb["DU_WOL_MSG"]._FormatC(profile.Pcid, profile.Preference.WoLTriggerPcid); } catch (Exception ex) { // WoL エラーメッセージの文字列化 string msg = ThinWebClientErrorUtil.GetFriendlyErrorMessage(ex, this.Page); form.WolErrorMessage = msg; form.JumpToWol = true; } } } } else { if (pcid._IsEmpty()) { // Query String の pcid が空の場合、Cookie から読み出す pcid = this._EasyLoadCookie <string>("thin_last_pcid")._NonNullTrim(); } if (deleteAll._ToBool()) { // History をすべて消去するよう指示された // Cookie の History をすべて消去する history.Clear(); history.SaveToCookie(this, GetCookieOption(), this.Client.SettingsFastSnapshot.CookieEncryptPassword); this._EasySaveCookie("thin_last_pcid", "", GetCookieOption()); // トップページにリダイレクトする return(Redirect("/")); } else if (pcid._IsFilled()) { // History から履歴を指定された。id を元に履歴からプロファイルを読み出す historySelectedProfile = history.Items.Where(h => h.Pcid._IsSamei(pcid)).FirstOrDefault(); } if (historySelectedProfile == null) { // デフォルト値 GuaKeyboardLayout defaultKeyboardLayout = GuaKeyboardLayout.Japanese; if (Page.CurrentLanguage.Key._IsSamei("ja") == false) { // 日本語以外の環境では英語キーボードをデフォルトで選択する defaultKeyboardLayout = GuaKeyboardLayout.EnglishUs; } profile = this._EasyLoadCookie <ThinWebClientProfile>("thin_current_profile", true, this.Client.SettingsFastSnapshot.CookieEncryptPassword) ?? new ThinWebClientProfile(defaultKeyboardLayout); } else { // History で選択された値 profile = historySelectedProfile; } profile.Normalize(); form.CurrentProfile = profile; // GET の場合は必ず PCID 入力ボックスをフォーカスする form.FocusToPcid = true; } form.FillHistory(history); if (historySelectedProfile != null) { form.SelectedHistory = form.HistoryItems.Where(x => x.Text._IsSamei(historySelectedProfile.Pcid)).FirstOrDefault()?.Value ?? ""; } return(View(form)); }