diff --git a/CLI/HttpServer/SecondBotHttpServer.cs b/CLI/HttpServer/SecondBotHttpServer.cs index 30aaac2..c7dd8bd 100644 --- a/CLI/HttpServer/SecondBotHttpServer.cs +++ b/CLI/HttpServer/SecondBotHttpServer.cs @@ -15,6 +15,7 @@ using System.Runtime.CompilerServices; using System.Text; using System.Threading; using System.Threading.Tasks; +using System.Web; namespace BetterSecondBot.HttpServer { @@ -104,10 +105,20 @@ namespace BetterSecondBot.HttpServer HttpListenerRequest req = ctx.Request; HttpListenerResponse resp = ctx.Response; resp.Cookies = req.Cookies; - string test = req.Url.AbsolutePath.Substring(1); + string test = req.Url.AbsoluteUri; if (helpers.notempty(Config.Http_PublicUrl) == true) { + // normal mapped test = test.Replace(Config.Http_PublicUrl, ""); + + //rproxy weirdness + string use_http_url = Config.Http_PublicUrl.Replace("http://", ""); + use_http_url = Config.Http_PublicUrl.Replace("https://", ""); + test = test.Replace(":" + Config.Http_Port.ToString(), ""); + test = test.Replace(use_http_url, ""); + test = test.Replace("https://", ""); + test = test.Replace("http://", ""); + } json_http_reply reply = new json_http_reply(); List http_args = test.Split('/', StringSplitOptions.RemoveEmptyEntries).ToList(); @@ -149,7 +160,7 @@ namespace BetterSecondBot.HttpServer string[] bits = B.Split('=', StringSplitOptions.RemoveEmptyEntries); if (bits.Length == 2) { - post_args.Add(bits[0].Trim(), bits[1].Trim()); + post_args.Add(bits[0].Trim(), HttpUtility.UrlDecode(bits[1].Trim())); } } resp.StatusCode = 200; @@ -195,13 +206,20 @@ namespace BetterSecondBot.HttpServer reply.message = String.Join("###", post_controler.Call(command, arg)); } } - if(reply.redirect != "") + if (reply.redirect != "") { - if(reply.redirect == "/") + if (reply.redirect != null) { - reply.redirect = ""; + if (reply.redirect == "/") + { + reply.redirect = Config.Http_PublicUrl; + } + else + { + reply.redirect = Config.Http_PublicUrl + reply.redirect; + } } - reply.redirect = "" + Config.Http_PublicUrl + "" + reply.redirect + ""; + } data = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(reply)); resp.ContentLength64 = data.LongLength; @@ -230,15 +248,21 @@ namespace BetterSecondBot.HttpServer } if (ok == true) { - try + bool clean_exit = false; + ConsoleLog.Status("Listening for connections on " + url + ""); + while (clean_exit == false) { - ConsoleLog.Status("Listening for connections on " + url + ""); - Task listenTask = HandleIncomingConnections(); - listenTask.GetAwaiter().GetResult(); - } - catch(Exception e) - { - ConsoleLog.Status("Http interface killed itself: "+e.ToString()+""); + try + { + ConsoleLog.Status("HTTP ready"); + Task listenTask = HandleIncomingConnections(); + listenTask.GetAwaiter().GetResult(); + } + catch (Exception e) + { + ConsoleLog.Status("HTTP died"); + //ConsoleLog.Status("Http interface killed itself: " + e.ToString() + ""); + } } } listener.Close(); diff --git a/CLI/HttpWebUi/webui.cs b/CLI/HttpWebUi/webui.cs index 48a9b03..66e925d 100644 --- a/CLI/HttpWebUi/webui.cs +++ b/CLI/HttpWebUi/webui.cs @@ -2,12 +2,16 @@ using BetterSecondBotShared.Json; using BetterSecondBotShared.Static; using BSB.bottypes; +using Microsoft.VisualBasic.CompilerServices; +using Newtonsoft.Json; +using OpenMetaverse; using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Reflection; using System.Text; +using System.Threading; namespace BetterSecondBot.HttpWebUi { @@ -16,7 +20,7 @@ namespace BetterSecondBot.HttpWebUi JsonConfig siteconfig; SecondBot bot; Dictionary vaildlogincookies = new Dictionary(); - public webui(JsonConfig setconfig,SecondBot setbot) + public webui(JsonConfig setconfig, SecondBot setbot) { bot = setbot; siteconfig = setconfig; @@ -25,7 +29,7 @@ namespace BetterSecondBot.HttpWebUi { return logincookievaild(reqs, resp, false); } - protected KeyValuePair logincookievaild(HttpListenerRequest reqs, HttpListenerResponse resp,bool force_logout) + protected KeyValuePair logincookievaild(HttpListenerRequest reqs, HttpListenerResponse resp, bool force_logout) { foreach (Cookie C in resp.Cookies) { @@ -38,7 +42,6 @@ namespace BetterSecondBot.HttpWebUi { vaildlogincookies.Remove(C.Value); } - Console.WriteLine("Cookie wiped"); } else { @@ -46,17 +49,8 @@ namespace BetterSecondBot.HttpWebUi { if (vaildlogincookies[C.Value] > helpers.UnixTimeNow()) { - Console.WriteLine("Cookie ok"); return new KeyValuePair(true, true); } - else - { - Console.WriteLine("Cookie expired"); - } - } - else - { - Console.WriteLine("Cookie not vaild"); } } resp.Cookies.Remove(C); @@ -65,17 +59,16 @@ namespace BetterSecondBot.HttpWebUi return new KeyValuePair(true, false); } } - Console.WriteLine("No cookie"); return new KeyValuePair(false, false); } - public bool Post_process(json_http_reply reply,HttpListenerRequest reqs, HttpListenerResponse resp,List args, Dictionary post_args) + public bool Post_process(json_http_reply reply, HttpListenerRequest reqs, HttpListenerResponse resp, List args, Dictionary post_args) { bool processed = false; if (args != null) { - if(args.Count >= 1) + if (args.Count >= 1) { - if(args[0] == "ajax") + if (args[0] == "ajax") { processed = true; // webui only cares about ajax post requests @@ -110,22 +103,25 @@ namespace BetterSecondBot.HttpWebUi logincookie.Expires = DateTime.Now.AddDays(1); logincookie.Path = "/"; resp.Cookies.Add(logincookie); - Console.WriteLine("Cookie created: "+ logincookie.Value+" <=> "+ newcookiecode+""); + Console.WriteLine("Cookie created: " + logincookie.Value + " <=> " + newcookiecode + ""); reply.message = "ok"; reply.redirect = "/"; } else { + reply.status = false; reply.message = "fail"; } } else { + reply.status = false; reply.message = "Missing code"; } } else { + reply.status = false; reply.message = "No access"; } } @@ -139,15 +135,228 @@ namespace BetterSecondBot.HttpWebUi { logincookievaild(reqs, resp, true); reply.message = "logged-out"; + reply.redirect = "/"; + reply.status = false; + } + else if(mod == "interface") + { + if (area == "get") + { + reply.message = JsonConvert.SerializeObject(bot.GetLastCommands(30)); + } + else if(area == "send") + { + if (post_args.ContainsKey("message") == true) + { + string[] bits = post_args["message"].Split("|||"); + if(bits.Length == 2) + { + reply.status = bot.GetCommandsInterface.Call(bits[0], bits[1]); + if(reply.status == true) + { + reply.message = "ok"; + } + else + { + reply.message = "Failed"; + } + } + else + { + reply.status = bot.GetCommandsInterface.Call(post_args["message"]); + if (reply.status == true) + { + reply.message = "ok"; + } + else + { + reply.message = "Failed"; + } + } + } + else + { + reply.message = "No message"; + reply.status = false; + } + } + else + { + reply.message = "Unknown area"; + reply.status = false; + } + } + else if (mod == "localchat") + { + if (area == "get") + { + reply.message = JsonConvert.SerializeObject(bot.getLocalChatHistory()); + } + else if (area == "send") + { + if (post_args.ContainsKey("message") == true) + { + bot.AddToLocalChat("{Via WebGUI}", post_args["message"]); + bot.GetClient.Self.Chat("{Via WebGUI} "+ post_args["message"], 0,ChatType.Normal); + reply.message = "ok"; + reply.status = true; + } + else + { + reply.message = "No message"; + reply.status = false; + } + } + else + { + reply.message = "Unknown area"; + reply.status = false; + } + } + else if (mod == "groupchat") + { + if (area == "list") + { + Dictionary groupname_uuid = new Dictionary(); + foreach (KeyValuePair entry in bot.MyGroups) + { + groupname_uuid.Add(entry.Key.ToString(), entry.Value.Name); + } + reply.message = JsonConvert.SerializeObject(groupname_uuid); + } + if (area == "get") + { + if (post_args.ContainsKey("groupuuid") == true) + { + if (UUID.TryParse(post_args["groupuuid"], out UUID groupuuid) == true) + { + reply.message = JsonConvert.SerializeObject(bot.GetGroupchat(groupuuid)); + } + else + { + reply.message = "Unable to process group uuid"; + reply.status = false; + } + } + else + { + reply.message = "No groupuuid"; + reply.status = false; + } + } + else if (area == "send") + { + if (post_args.ContainsKey("groupuuid") == true) + { + if (UUID.TryParse(post_args["groupuuid"], out UUID groupuuid) == true) + { + if (post_args.ContainsKey("message") == true) + { + bot.GetClient.Self.RequestJoinGroupChat(groupuuid); + Thread.Sleep(100); + bot.GetClient.Self.InstantMessageGroup(groupuuid, "{Via WebGUI} " + post_args["message"]); + bot.AddToGroupchat(groupuuid, "{Via WebGUI}", post_args["message"]); + reply.message = "ok"; + reply.status = true; + } + else + { + reply.message = "No message"; + reply.status = false; + } + } + else + { + reply.message = "Unable to process group uuid"; + reply.status = false; + } + } + else + { + reply.message = "No groupuuid"; + reply.status = false; + } + } + else + { + reply.message = "Unknown area"; + reply.status = false; + } + } + else if (mod == "im") + { + if (area == "list") + { + reply.message = JsonConvert.SerializeObject(bot.GetIMChatWindowKeyNames()); + } + else if (area == "send") + { + if (post_args.ContainsKey("avataruuid") == true) + { + if (UUID.TryParse(post_args["avataruuid"], out UUID avataruuid) == true) + { + if (post_args.ContainsKey("message") == true) + { + bot.GetCommandsInterface.Call("im", "" + avataruuid.ToString() + "~#~{Via WebGUI} " + post_args["message"]); + reply.message = "ok"; + reply.status = true; + } + else + { + reply.message = "No message"; + + } + } + else + { + reply.message = "Unable to process avatar uuid"; + reply.status = false; + } + } + else + { + reply.message = "No avataruuid"; + reply.status = false; + } + } + else if (area == "get") + { + if (post_args.ContainsKey("avataruuid") == true) + { + if (UUID.TryParse(post_args["avataruuid"], out UUID avataruuid) == true) + { + reply.message = JsonConvert.SerializeObject(bot.GetIMChatWindow(avataruuid)); + } + else + { + reply.message = "Unable to process avatar uuid"; + reply.status = false; + } + } + else + { + reply.message = "No avataruuid"; + reply.status = false; + } + } + else + { + reply.message = "Unknown area"; + reply.status = false; + } + } + else + { + reply.message = "No action"; + reply.status = false; } - reply.message = "No action"; } else { // login expired reply.message = "login-expired"; reply.redirect = "/"; - logincookievaild(reqs, resp,true); + logincookievaild(reqs, resp, true); } } } @@ -155,22 +364,83 @@ namespace BetterSecondBot.HttpWebUi } return !processed; } + public string html_logged_in(string mod, string area) + { + string layout = helpers.ReadResourceFile(Assembly.GetExecutingAssembly(), "sidemenu.layout"); + Dictionary swaps = new Dictionary(); - public KeyValuePair html_logged_out() + + string pagetitle = "Dashboard"; + string pagecontent = ""; + string pageactions = ""; + string js_onready = ""; + string[] menu_text = new string[] { "Localchat", "Groupchat", "IMs", "Interface" }; + string[] menu_links = new string[] { "localchat", "groupchat", "im", "interface" }; + string[] meni_icons = new string[] { "fas fa-comment", "fas fa-comments", "fas fa-users","fas fa-robot" }; + int loop = 0; + string menu = ""; + while (loop < menu_text.Count()) + { + string active = ""; + if (menu_links[loop] == mod) active = "active"; + menu = "" + menu + "
  • " + menu_text[loop] + "
  • "; + loop++; + } + swaps.Add("html_menu", menu); + menu = ""; + if (mod == "none") + { + pagecontent = "

    Please select a menu item on the left

    "; + } + else if(mod == "localchat") + { + pagetitle = "Localchat"; + pagecontent = "
    " + + "
    " + + "" + + ""+ + "
    "; + js_onready = "setInterval(function(){ update_localchat(\"" + siteconfig.Http_PublicUrl+"\"); },400);"; + + } + else if (mod == "groupchat") + { + pagetitle = "Group chat"; + pagecontent = ""; + if (area == "none") + { + + } + + + + } + swaps.Add("html_title", pagetitle); + swaps.Add("page_actions", pageactions); + swaps.Add("page_content", pagecontent); + swaps.Add("page_title", pagetitle); + swaps.Add("html_cs_top", ""); + swaps.Add("html_js_bottom", ""); + swaps.Add("html_js_onready", js_onready); + foreach (KeyValuePair A in swaps) + { + layout = layout.Replace("[[" + A.Key + "]]", A.Value); + } + return layout; + } + public string html_logged_out() { string layout = helpers.ReadResourceFile(Assembly.GetExecutingAssembly(), "full.layout"); layout = layout.Replace("[[page_content]]", helpers.ReadResourceFile(Assembly.GetExecutingAssembly(), "login.block")); - layout = layout.Replace("[[url_base]]", siteconfig.Http_PublicUrl); - layout = layout.Replace("[[html_title_after]]", "Secondbot web UI"); - layout = layout.Replace("[[html_title]]", siteconfig.Basic_BotUserName); - layout = layout.Replace("[[html_cs_top]]", helpers.ReadResourceFile(Assembly.GetExecutingAssembly(), "cdn.css.layout")); - layout = layout.Replace("[[html_js_bottom]]", helpers.ReadResourceFile(Assembly.GetExecutingAssembly(), "cdn.js.layout")); - layout = layout.Replace("[[html_js_onready]]", ""); - return new KeyValuePair("text/html", Encoding.UTF8.GetBytes(layout)); + layout = layout.Replace("[[html_cs_top]]", ""); + layout = layout.Replace("[[html_js_bottom]]", ""); + layout = layout.Replace("[[html_title]]", siteconfig.Basic_BotUserName); + return layout; } - public KeyValuePair Get_Process(HttpListenerRequest reqs, HttpListenerResponse resp, List args) + public KeyValuePair Get_Process(HttpListenerRequest reqs, HttpListenerResponse resp, List args) { + // get content if (args != null) { @@ -198,16 +468,17 @@ namespace BetterSecondBot.HttpWebUi } // get display KeyValuePair logincheck = logincookievaild(reqs, resp); - if(logincheck.Key == true) + if (logincheck.Key == true) { - if(logincheck.Value == false) + if (logincheck.Value == false) { logincookievaild(reqs, resp, true); } } + string reply_with = ""; if (logincheck.Value == false) { - return html_logged_out(); + reply_with = html_logged_out(); } else { @@ -221,18 +492,23 @@ namespace BetterSecondBot.HttpWebUi { area = args[1]; } + if (mod == "logout") { logincookievaild(reqs, resp, true); - return html_logged_out(); + reply_with = html_logged_out(); } else { // logged in - return new KeyValuePair("text/html", Encoding.UTF8.GetBytes("logged in")); + reply_with = html_logged_in(mod, area); } } + reply_with = reply_with.Replace("[[url_base]]", siteconfig.Http_PublicUrl); + reply_with = reply_with.Replace("[[html_title_after]]", "Secondbot web UI"); + reply_with = reply_with.Replace("[[html_cs_top_cdn]]", helpers.ReadResourceFile(Assembly.GetExecutingAssembly(), "cdn.css.layout")); + reply_with = reply_with.Replace("[[html_js_bottom_cdn]]", helpers.ReadResourceFile(Assembly.GetExecutingAssembly(), "cdn.js.layout")); + return new KeyValuePair("text/html", Encoding.UTF8.GetBytes(reply_with)); } } - }