using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using SimpleHttp; using System.Xml.Linq; using Newtonsoft; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using BodyshopPartner.Models; using ToastNotifications.Messages; using System.Threading; using System.Reflection; namespace BodyshopPartner.Utils { public static class HTTPServer { private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); public delegate void HttpLogger(string s); private static HttpLogger hlog; public static CancellationTokenSource tokenSource = new CancellationTokenSource(); public static CancellationToken token = tokenSource.Token; public static void InitHttpServer(HttpLogger HttpLogger) { //Adding local routes. //QuickBooks Execution Routes. Route.Add("/qb/", (req, res, props) => { hlog("Received a QuickBooks request from ImEX.online"); res.WithCORS(); res.Close(); }, "OPTIONS"); Route.Add("/qb/", (req, res, props) => { HandleQbPost(req, res); } , "POST"); //Pinging based routes. Route.Add("/ping/", (req, res, props) => { hlog("Received a ping from ImEX.online"); res.WithCORS(); res.Close(); }, "OPTIONS"); Route.Add("/ping/", (req, res, props) => { HandlePing(req, res); } , "POST"); //FileScanning Routes Route.Add("/scan/", (req, res, props) => { hlog("Received a scan request from ImEX.online"); res.WithCORS(); res.Close(); }, "OPTIONS"); Route.Add("/scan/", (req, res, props) => { HandleScan(req, res); } , "POST"); Route.Add("/import/", (req, res, props) => { hlog("Received an import request from ImEX.online"); res.WithCORS(); res.Close(); }, "OPTIONS"); Route.Add("/import/", (req, res, props) => { HandleImport(req, res); } , "POST"); Route.Add("/oec/", (req, res, props) => { hlog("Received an OEC from ImEX.online"); res.WithCORS(); res.Close(); }, "OPTIONS"); Route.Add("/oec/", (req, res, props) => { HandleOec(req, res); } , "POST"); logger.Trace("Starting HTTP server..."); hlog = HttpLogger; try { hlog("ImEX Online connection server starting..."); HttpServer.ListenAsync(1337, token, Route.OnHttpRequestAsync).Wait(); } catch (Exception Ex) { logger.Fatal("Unable to start HTTP server. " + Ex.ToString()); hlog("ImEX Online connection server could not start. Please restart the partner to try again."); App.Current.Dispatcher.Invoke(() => { string msg = "Unable to connect to ImEX Online Web App. Please ensure your firewall allows the connection."; Utils.Notifications.notifier.ShowError(msg); }); Utils.SquirrelAwareHelper.AddHttpExcetion(); HttpServer.ListenAsync(1337, token, Route.OnHttpRequestAsync).Wait(); } } private static void HandleOec(System.Net.HttpListenerRequest req, System.Net.HttpListenerResponse res) { logger.Trace("/oec/ - POST"); //Input will be an array of objects containing XMLs. var requestBody = ParseBody(req); JObject HttpResponse = new JObject(); try { Utils.OEConnection.SendToOEConnection(requestBody); HttpResponse.Add("success", true); } catch (Exception Ex) { logger.Error(Ex, "Error encountered while handling import requests."); hlog("Error encountered while handling import requests."); HttpResponse.Add("success", false); HttpResponse.Add("error", Ex.ToString()); } res.WithCORS().AsText(JsonConvert.SerializeObject(HttpResponse)); } private static void HandleQbPost(System.Net.HttpListenerRequest req, System.Net.HttpListenerResponse res) { logger.Trace("/qb/ - POST"); hlog("Received QuickBooks Receivable request."); //Input will be an array of objects containing XMLs. List AllRequests = ParseRequest(req); List HttpResponse = new List(); try { hlog("Connecting to QuickBooks. This may take a moment..."); QuickBooksInterop.ConnectToQuickBooks(); foreach (QbRequestItem request in AllRequests) { try { hlog("Processing QuickBooks request. ImEX Online Record ID:" + request.Id); XDocument response = XDocument.Parse(QuickBooksInterop.ProcessQBXmlRequestUnManaged(request.QbXML)); QbXmlResponse ResponseStatus = QuickBooksInterop.ParseResponseXml(response); logger.Trace(response.ToString()); logger.Debug(ResponseStatus.ToString()); hlog(ResponseStatus.ToString()); QbResponseItem r = new QbResponseItem() { Id = request.Id, Success = ResponseStatus.StatusCode == "0" || request.OkStatusCodes.Contains(ResponseStatus.StatusCode), ErrorMessage = ResponseStatus.StatusMessage }; HttpResponse.Add(r); } catch (Exception Ex) { //Shouldn't really get here unless something is malformed. logger.Error(Ex, "Error encountered when processing QbXML Request.\n {0}", request.QbXML); QbResponseItem r = new QbResponseItem() { Id = request.Id, Success = false, ErrorMessage = Ex.Message }; HttpResponse.Add(r); } } QuickBooksInterop.DisconnectFromQuickBooks(); hlog("Completed QuickBooks requests."); } catch (Exception Ex) { logger.Error(Ex, "Error encountered while processing QuickBooks requests."); hlog("Error encountered while processing QuickBooks requests."); HttpResponse.Add(new QbResponseItem() { Id = "-1", Success = false, ErrorMessage = Ex.Message }); } res.WithCORS().AsText(JsonConvert.SerializeObject(HttpResponse)); } private static async void HandleScan(System.Net.HttpListenerRequest req, System.Net.HttpListenerResponse res) { logger.Trace("/scan/ - POST"); //Input will be an array of objects containing XMLs. List HttpResponse = new List(); try { //Do the scan //Add the items to the response list. HttpResponse = await Utils.DiskScan.ScanDiskForEstimates(); } catch (Exception Ex) { logger.Error(Ex, "Error encountered while scanning for estimates on disk.", Ex.ToString()); hlog("Error encountered while scanning for estimates on disk. " + Ex.Message); HttpResponse.Add(new ScanResponseItem() { Id = "-1", Success = false, ErrorMessage = Ex.Message }); } res.WithCORS().AsText(JsonConvert.SerializeObject(HttpResponse)); } private static async void HandleImport(System.Net.HttpListenerRequest req, System.Net.HttpListenerResponse res) { logger.Trace("/import/ - POST"); //Input will be an array of objects containing XMLs. var requestBody = ParseBody(req); JObject HttpResponse = new JObject(); try { //Do the scan //Add the items to the response list. await JobProcessingQueue.UploadJob(new DTO_QueueItem() { FilePath = requestBody.filepath }); HttpResponse.Add("success", true); } catch (Exception Ex) { logger.Error(Ex, "Error encountered while handling import requests."); hlog("Error encountered while handling import requests."); HttpResponse.Add("success" , false); HttpResponse.Add("error", Ex.ToString()); } res.WithCORS().AsText(JsonConvert.SerializeObject(HttpResponse)); } private static void HandlePing(System.Net.HttpListenerRequest req, System.Net.HttpListenerResponse res) { logger.Trace("/ping/ - POST"); dynamic response = new JObject(); response.appver = Assembly.GetExecutingAssembly().GetName().Version.ToString(); response.qbpath = Properties.Settings.Default.QuickBooksFilePath; var t = JsonConvert.SerializeObject(response); res.WithCORS().AsText((string)t.ToString()); } public static dynamic ParseBody(System.Net.HttpListenerRequest req) { System.IO.Stream body = req.InputStream; System.Text.Encoding encoding = req.ContentEncoding; System.IO.StreamReader reader = new System.IO.StreamReader(body, encoding); string s = reader.ReadToEnd(); body.Close(); reader.Close(); return JsonConvert.DeserializeObject(s); } public static List ParseRequest(System.Net.HttpListenerRequest req) { System.IO.Stream body = req.InputStream; System.Text.Encoding encoding = req.ContentEncoding; System.IO.StreamReader reader = new System.IO.StreamReader(body, encoding); string s = reader.ReadToEnd(); body.Close(); reader.Close(); return JsonConvert.DeserializeObject>(s); } public static string[] ParseBodyToArray(System.Net.HttpListenerRequest req) { System.IO.Stream body = req.InputStream; System.Text.Encoding encoding = req.ContentEncoding; System.IO.StreamReader reader = new System.IO.StreamReader(body, encoding); string s = reader.ReadToEnd(); body.Close(); reader.Close(); return JArray.Parse(s).Select(jv => jv.ToString()).ToArray(); } public static string ParseBodyToString(System.Net.HttpListenerRequest req) { System.IO.Stream body = req.InputStream; System.Text.Encoding encoding = req.ContentEncoding; System.IO.StreamReader reader = new System.IO.StreamReader(body, encoding); string s = reader.ReadToEnd(); body.Close(); return s; } public static XDocument ParseStringToXml(string input) { return XDocument.Parse(input); } } }