diff --git a/RZ.Server/RZ.Catalog.Plugin.Proxy/RZ.Catalog.Plugin.Proxy.cs b/RZ.Server/RZ.Catalog.Plugin.Proxy/RZ.Catalog.Plugin.Proxy.cs index e688a4b..5aafb08 100644 --- a/RZ.Server/RZ.Catalog.Plugin.Proxy/RZ.Catalog.Plugin.Proxy.cs +++ b/RZ.Server/RZ.Catalog.Plugin.Proxy/RZ.Catalog.Plugin.Proxy.cs @@ -56,6 +56,7 @@ public JArray GetCatalog(string customerid = "", bool nocache = false) //Try to get value from Memory if (_cache.TryGetValue("swcat", out jResult)) { + Console.WriteLine("GetCatalog..."); return jResult; } } @@ -67,6 +68,7 @@ public JArray GetCatalog(string customerid = "", bool nocache = false) var cacheEntryOptions = new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromMinutes(30)); //cache catalog for 30 Minutes _cache.Set("swcat", jResult, cacheEntryOptions); + Console.WriteLine("GetCatalog..."); return jResult; } diff --git a/RZ.Server/RZ.Plugin.Feedback.Azure/RZ.Plugin.Feedback.Azure.csproj b/RZ.Server/RZ.Plugin.Feedback.Azure/RZ.Plugin.Feedback.Azure.csproj index 92281a5..fe6f5b1 100644 --- a/RZ.Server/RZ.Plugin.Feedback.Azure/RZ.Plugin.Feedback.Azure.csproj +++ b/RZ.Server/RZ.Plugin.Feedback.Azure/RZ.Plugin.Feedback.Azure.csproj @@ -6,7 +6,7 @@ - + all runtime; build; native; contentfiles; analyzers diff --git a/RZ.Server/RZ.Plugin.Feedback.Proxy/FodyWeavers.xml b/RZ.Server/RZ.Plugin.Feedback.Proxy/FodyWeavers.xml new file mode 100644 index 0000000..a5dcf04 --- /dev/null +++ b/RZ.Server/RZ.Plugin.Feedback.Proxy/FodyWeavers.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/RZ.Server/RZ.Plugin.Feedback.Proxy/FodyWeavers.xsd b/RZ.Server/RZ.Plugin.Feedback.Proxy/FodyWeavers.xsd new file mode 100644 index 0000000..44a5374 --- /dev/null +++ b/RZ.Server/RZ.Plugin.Feedback.Proxy/FodyWeavers.xsd @@ -0,0 +1,111 @@ + + + + + + + + + + + + A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks + + + + + A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks. + + + + + A list of unmanaged 32 bit assembly names to include, delimited with line breaks. + + + + + A list of unmanaged 64 bit assembly names to include, delimited with line breaks. + + + + + The order of preloaded assemblies, delimited with line breaks. + + + + + + This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file. + + + + + Controls if .pdbs for reference assemblies are also embedded. + + + + + Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option. + + + + + As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off. + + + + + Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code. + + + + + Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior. + + + + + A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with | + + + + + A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |. + + + + + A list of unmanaged 32 bit assembly names to include, delimited with |. + + + + + A list of unmanaged 64 bit assembly names to include, delimited with |. + + + + + The order of preloaded assemblies, delimited with |. + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/RZ.Server/RZ.Plugin.Feedback.Proxy/RZ.Plugin.Feedback.Proxy.cs b/RZ.Server/RZ.Plugin.Feedback.Proxy/RZ.Plugin.Feedback.Proxy.cs new file mode 100644 index 0000000..1db45c4 --- /dev/null +++ b/RZ.Server/RZ.Plugin.Feedback.Proxy/RZ.Plugin.Feedback.Proxy.cs @@ -0,0 +1,86 @@ +using Microsoft.Azure.ServiceBus; +using Microsoft.Extensions.Caching.Memory; +using Newtonsoft.Json.Linq; +using RZ.Server; +using RZ.Server.Interfaces; +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace RZ.Plugin.Feedback.Azure +{ + public class Plugin_Feedback : IFeedback + { + private IMemoryCache _cache; + + public string Name + { + get + { + return Assembly.GetExecutingAssembly().ManifestModule.Name; + } + } + + public Dictionary Settings { get; set; } + + public void Init(string PluginPath) + { + //Check if MemoryCache is initialized + if (_cache != null) + { + _cache.Dispose(); + } + + _cache = new MemoryCache(new MemoryCacheOptions()); + + if (Settings == null) + Settings = new Dictionary(); + + } + + public Task StoreFeedback(string name = "", string ver = "", string man = "", string shortname = "", string feedback = "", string user = "", bool? failure = null) + { + var tFeedback = Task.Run(() => + { + string ok = "false"; + if (failure == false) + ok = "true"; + + if(failure == true) + { + Console.WriteLine("Failure: " + name + " " + ver + " Error:" + feedback); + } + else + { + Console.WriteLine("Success: " + name + " " + ver); + } + + RZRestAPIv2.StoreFeedback(name, ver, man, ok, user, feedback); + return true; + }); + + return tFeedback; + } + + public void PushBullet(string Message, string Body) + { + } + + public Task SendNotification(string message = "", string body = "") + { + Task t = Task.Run(() => + { + PushBullet(message, body); + return true; + }); + + return t; + } + } +} diff --git a/RZ.Server/RZ.Plugin.Feedback.Proxy/RZ.Plugin.Feedback.Proxy.csproj b/RZ.Server/RZ.Plugin.Feedback.Proxy/RZ.Plugin.Feedback.Proxy.csproj new file mode 100644 index 0000000..fe6f5b1 --- /dev/null +++ b/RZ.Server/RZ.Plugin.Feedback.Proxy/RZ.Plugin.Feedback.Proxy.csproj @@ -0,0 +1,20 @@ + + + + netcoreapp2.2 + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + + + + + + diff --git a/RZ.Server/RZ.Plugin.Feedback.Proxy/RZRestAPIv2_min.cs b/RZ.Server/RZ.Plugin.Feedback.Proxy/RZRestAPIv2_min.cs new file mode 100644 index 0000000..f207681 --- /dev/null +++ b/RZ.Server/RZ.Plugin.Feedback.Proxy/RZRestAPIv2_min.cs @@ -0,0 +1,65 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.IO; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; + +namespace RZ.Plugin.Feedback.Azure +{ + class RZRestAPIv2 + { + private static string _sURL = ""; + private static HttpClient oClient = new HttpClient(); //thx https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/ + + public static string sURL + { + get + { + if (!string.IsNullOrEmpty(_sURL)) + return _sURL; + + _sURL = GetURL(""); + return _sURL; + } + set + { + _sURL = value; + } + } + + public static string GetURL(string customerid) + { + using (HttpClient hClient = new HttpClient()) + { + Task tReq; + if (string.IsNullOrEmpty(customerid)) + tReq = hClient.GetStringAsync("https://ruckzuck.tools/rest/v2/geturl"); + else + tReq = hClient.GetStringAsync("https://ruckzuck.tools/rest/v2/geturl?customerid=" + customerid); + + tReq.Wait(5000); //wait max 5s + + if (tReq.IsCompleted) + { + _sURL = tReq.Result; + return _sURL; + } + else + { + _sURL = "https://ruckzuck.azurewebsites.net"; + return _sURL; + } + } + } + + public static bool StoreFeedback(string name, string ver, string man, string ok, string user, string text) + { + oClient.GetStringAsync(sURL + "/rest/v2/feedback?name=" + name + "&ver=" + ver + "&man=" + man + "&text=" + text + "&user=" + user + "&ok=" + ok); + + return true; + } + } +} diff --git a/RZ.Server/RZ.Plugin.Software.Azure/RZ.Plugin.Software.Azure.cs b/RZ.Server/RZ.Plugin.Software.Azure/RZ.Plugin.Software.Azure.cs index 4b6918a..4095e34 100644 --- a/RZ.Server/RZ.Plugin.Software.Azure/RZ.Plugin.Software.Azure.cs +++ b/RZ.Server/RZ.Plugin.Software.Azure/RZ.Plugin.Software.Azure.cs @@ -466,7 +466,7 @@ private void UpdateURLs(ref JArray jSource) if (FileNames.Contains(oFiles["FileName"].Value().ToLower())) { //oFiles["URL"] = Base.localURL + "/rest/v2/GetFile/" + sContentID + "/" + oFiles["FileName"].ToString().Replace("\\", "/"); - oFiles["URL"] = "https://ruckzuck.azureedge.net/rest/v2/GetFile/" + sContentID + "/" + oFiles["FileName"].ToString().Replace("\\", "/"); + oFiles["URL"] = "https://cdn.ruckzuck.tools/rest/v2/GetFile/" + sContentID + "/" + oFiles["FileName"].ToString().Replace("\\", "/"); } } diff --git a/RZ.Server/RZ.Plugin.Software.Proxy/FodyWeavers.xml b/RZ.Server/RZ.Plugin.Software.Proxy/FodyWeavers.xml new file mode 100644 index 0000000..a5dcf04 --- /dev/null +++ b/RZ.Server/RZ.Plugin.Software.Proxy/FodyWeavers.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/RZ.Server/RZ.Plugin.Software.Proxy/FodyWeavers.xsd b/RZ.Server/RZ.Plugin.Software.Proxy/FodyWeavers.xsd new file mode 100644 index 0000000..44a5374 --- /dev/null +++ b/RZ.Server/RZ.Plugin.Software.Proxy/FodyWeavers.xsd @@ -0,0 +1,111 @@ + + + + + + + + + + + + A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks + + + + + A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks. + + + + + A list of unmanaged 32 bit assembly names to include, delimited with line breaks. + + + + + A list of unmanaged 64 bit assembly names to include, delimited with line breaks. + + + + + The order of preloaded assemblies, delimited with line breaks. + + + + + + This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file. + + + + + Controls if .pdbs for reference assemblies are also embedded. + + + + + Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option. + + + + + As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off. + + + + + Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code. + + + + + Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior. + + + + + A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with | + + + + + A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |. + + + + + A list of unmanaged 32 bit assembly names to include, delimited with |. + + + + + A list of unmanaged 64 bit assembly names to include, delimited with |. + + + + + The order of preloaded assemblies, delimited with |. + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/RZ.Server/RZ.Plugin.Software.Proxy/RZ.Plugin.Software.Proxy.cs b/RZ.Server/RZ.Plugin.Software.Proxy/RZ.Plugin.Software.Proxy.cs new file mode 100644 index 0000000..8d4aedd --- /dev/null +++ b/RZ.Server/RZ.Plugin.Software.Proxy/RZ.Plugin.Software.Proxy.cs @@ -0,0 +1,468 @@ +using Microsoft.Extensions.Caching.Memory; +using Newtonsoft.Json.Linq; +using RZ.Server; +using RZ.Server.Interfaces; +using System; +using System.Collections.Generic; +using System.IO; +using System.Net.Http; +using System.Reflection; +using System.Threading.Tasks; + +namespace Plugin_Software +{ + public class Plugin_Software : ISoftware + { + private IMemoryCache _cache; + private long SlidingExpiration = 1800; //30min cache for Softwares + + public string Name + { + get + { + return Assembly.GetExecutingAssembly().ManifestModule.Name; + } + } + + public Dictionary Settings { get; set; } + + public void Init(string PluginPath) + { + //Check if MemoryCache is initialized + if (_cache != null) + { + _cache.Dispose(); + } + + _cache = new MemoryCache(new MemoryCacheOptions()); + + if (Settings == null) + Settings = new Dictionary(); + + string wwwpath = Settings["wwwPath"] ?? PluginPath; + + string repository = Path.Combine(wwwpath, "repository"); + if (!Directory.Exists(repository)) + Directory.CreateDirectory(repository); + + string content = Path.Combine(wwwpath, "content"); + if (!Directory.Exists(content)) + Directory.CreateDirectory(content); + + string icons = Path.Combine(wwwpath, "icons"); + if (!Directory.Exists(icons)) + Directory.CreateDirectory(icons); + + Settings.Add("repository", repository); + Settings.Add("content", content); + Settings.Add("icons", icons); + } + + public JArray GetSoftwares(string shortname) + { + JArray jResult = new JArray(); + //Try to get value from Memory + if (_cache.TryGetValue("sn-" + shortname.ToLower(), out jResult)) + { + return jResult; + } + + jResult = RZRestAPIv2.GetSoftwares(shortname); + + if(jResult.Count > 0) + { + var cacheEntryOptions = new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromSeconds(SlidingExpiration)); //cache hash for x Seconds + _cache.Set("sn-" + shortname.ToLower(), jResult, cacheEntryOptions); + + return jResult; + } + + return new JArray(); + } + + public JArray GetSoftwares(string name = "", string ver = "", string man = "_unknown") + { + JArray jResult = new JArray(); + + try + { + if (string.IsNullOrEmpty(man)) + man = "_unknown"; + + //Try to get value from Memory + if (_cache.TryGetValue("mnv-" + Base.clean(man).ToLower() + Base.clean(name).ToLower() + Base.clean(ver).ToLower(), out jResult)) + { + return jResult; + } + + jResult = RZRestAPIv2.GetSoftwares(name, ver, man); + + if (jResult.Count > 0) + { + UpdateURLs(ref jResult); //Update URL's before caching to cache the change... + + var cacheEntryOptions = new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromSeconds(SlidingExpiration)); //cache hash for x Seconds + _cache.Set("mnv-" + Base.clean(man).ToLower() + Base.clean(name).ToLower() + Base.clean(ver).ToLower(), jResult, cacheEntryOptions); + + return jResult; + } + } + catch(Exception ex) + { + Console.WriteLine("ERROR: GetSoftwares - " + ex.Message); + } + + return new JArray(); + } + + public bool UploadSoftware(JArray Software) + { + return false; + } + + public async Task GetIcon(string shortname) + { + Stream bResult; + byte[] bCache; + + //ry to get value from Memory + if (_cache.TryGetValue("ico-" + shortname.ToLower(), out bCache)) + { + return new MemoryStream(bCache); + } + + JArray jFull = GetSoftwares(shortname.ToLower()); + foreach (JObject jObj in jFull) + { + try + { + if (jObj["Image"] != null) + { + bResult = new MemoryStream(jObj["Image"].ToObject(typeof(byte[])) as byte[]); + MemoryStream ms = new MemoryStream(); + bResult.CopyTo(ms); + + var cacheEntryOptions = new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromMinutes(90)); //cache icon for 90 Minutes + _cache.Set("ico-" + shortname.ToLower(), ms.ToArray(), cacheEntryOptions); + + return bResult; + } + else + { + if (jObj["IconHash"] != null) + { + bResult = await GetIcon(0, jObj["IconHash"].ToString()); + MemoryStream ms = new MemoryStream(); + bResult.CopyTo(ms); + + var cacheEntryOptions = new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromMinutes(90)); //cache icon for 90 Minutes + _cache.Set("ico-" + shortname.ToLower(), ms.ToArray(), cacheEntryOptions); + + return bResult; + } + } + } + catch { } + } + + return null; + } + + public async Task GetIcon(Int32 iconid = 0, string iconhash = "") + { + string sico = iconhash; + + if (iconid > 0) + sico = iconid.ToString(); + + //Stream bResult; + byte[] bCache; + + //Try to get value from Memory + if (_cache.TryGetValue("ico-" + sico, out bCache)) + { + var cacheEntryOptions = new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromMinutes(95)); //cache icon for other 90 Minutes + _cache.Set("ico-" + sico, bCache, cacheEntryOptions); + + return new MemoryStream(bCache); + } + + //Try to load Icon from Disk + if (File.Exists(Path.Combine(Settings["icons"], sico + ".jpg"))) + { + + bCache = File.ReadAllBytes(Path.Combine(Settings["icons"], sico + ".jpg")); + + var cacheEntryOptions = new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromMinutes(95)); //cache icon for other 90 Minutes + _cache.Set("ico-" + sico, bCache, cacheEntryOptions); + + return new MemoryStream(bCache); + } + + try + { + using (MemoryStream ms = new MemoryStream()) + { + Stream x = await RZRestAPIv2.GetIcon(iconid, iconhash); + await x.CopyToAsync(ms); + bCache = ms.ToArray(); + } + + if (bCache.Length > 0) + { + + var cacheEntryOptions = new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromMinutes(95)); //cache icon for 90 Minutes + _cache.Set("ico-" + sico, bCache, cacheEntryOptions); + + try + { + File.WriteAllBytes(Path.Combine(Settings["icons"], sico + ".jpg"), bCache); + } + catch { } + } + + return new MemoryStream(bCache); + } + catch { } + + return null; + } + + private void UpdateURLs(ref JArray jSource) + { + foreach (JObject jObj in jSource) + { + try + { + JToken oContentID; + + //Empty PreRequisites should be handled by the Client; Fix after 1.6.2.14! + try + { + if (jObj["PreRequisites"] == null) + { + string[] oReq = new string[0]; + jObj.Add("PreRequisites", JToken.FromObject(oReq)); + } + + if (!jObj["PreRequisites"].HasValues) + { + string[] oReq = new string[0]; + jObj["PreRequisites"] = JToken.FromObject(oReq); + } + } + catch { } + + try + { + jObj["Manufacturer"] = Base.clean(jObj["Manufacturer"].Value()); + jObj["ProductName"] = Base.clean(jObj["ProductName"].Value()); + jObj["ProductVersion"] = Base.clean(jObj["ProductVersion"].Value()); + } + catch { } + + if (jObj.TryGetValue("ContentID", out oContentID)) + { + string sContentID = oContentID.Value(); + + List FileNames = new List(); + string sDir = Path.Combine(Settings["content"], sContentID); + if (Directory.Exists(sDir)) + { + foreach (var oFile in Directory.GetFiles(sDir, "*.*", SearchOption.TopDirectoryOnly)) + { + FileNames.Add(Path.GetFileName(oFile).ToLower()); + } + } + + foreach (JObject oFiles in jObj["Files"]) + { + if (FileNames.Contains(oFiles["FileName"].Value().ToLower())) + { + //oFiles["URL"] = Base.localURL + "/rest/v2/GetFile/" + sContentID + "/" + oFiles["FileName"].ToString().Replace("\\", "/"); + oFiles["URL"] = Base.localURL + "/rest/v2/GetFile/" + sContentID + "/" + oFiles["FileName"].ToString().Replace("\\", "/"); + + } + else + { + oFiles["URL"] = Base.localURL + "/rest/v2/GetFile/proxy/" + jObj["ShortName"].ToString() + "/" + sContentID + "/" + oFiles["FileName"].ToString().Replace("\\", "/"); + } + } + } + else + continue; + } + catch { } + } + } + + public async Task GetFile(string FilePath) + { + string sPath = Path.Combine(Settings["content"], FilePath); + if (File.Exists(sPath)) + { + return File.OpenRead(sPath); + } + + if (FilePath.StartsWith("proxy")) + { + FilePath = FilePath.Replace("\\", "/"); + string sShortName = FilePath.Split('/')[1]; + string sContentID = FilePath.Split('/')[2]; + string sFile = FilePath.Split('/')[3]; + + JArray aSW = GetSoftwares(sShortName); + + foreach (JObject jObj in aSW) + { + if (jObj["ContentID"].ToString() == sContentID) + { + foreach (JObject jFiles in jObj["Files"]) + { + if (sFile.ToLower() == jFiles["FileName"].ToString().ToLower()) + { + string URL = jFiles["URL"].ToString(); + string sFileName = jFiles["FileName"].ToString(); + string sHashType = jFiles["HashType"].ToString(); + string sFileHash = jFiles["FileHash"].ToString(); + + if (!Directory.Exists(Path.Combine(Settings["content"], sContentID))) + { + Directory.CreateDirectory(Path.Combine(Settings["content"], sContentID)); + } + + try + { + using (HttpClient oClient = new HttpClient()) + { + using (var response = await oClient.GetAsync(URL, HttpCompletionOption.ResponseHeadersRead)) + { + + using (Stream streamToReadFrom = await response.Content.ReadAsStreamAsync()) + { + string fileToWriteTo = Path.Combine(Settings["content"], sContentID, sFileName); + using (Stream streamToWriteTo = File.Open(fileToWriteTo, FileMode.Create)) + { + await streamToReadFrom.CopyToAsync(streamToWriteTo); + } + } + } + } + + if (File.Exists(Path.Combine(Settings["content"], sContentID, sFileName))) + { + if (new FileInfo(Path.Combine(Settings["content"], sContentID, sFileName)).Length > 1024) + { + return File.OpenRead(Path.Combine(Settings["content"], sContentID, sFileName)); + } + else + { + File.Delete(Path.Combine(Settings["content"], sContentID, sFileName)); + } + } + } + catch + { + File.Delete(Path.Combine(Settings["content"], sContentID, sFileName)); + } + } + } + } + } + + + } + + return null; + } + + public string GetShortname(string name = "", string ver = "", string man = "") + { + string sResult = ""; + string sID = (Base.clean(man.ToLower()) + Base.clean(name.ToLower()) + Base.clean(ver.ToLower())).Trim(); + string sRowKey = Hash.CalculateMD5HashString(sID); + + //Try to get value from Memory + if (_cache.TryGetValue("lookup-" + sID, out sResult)) + { + return sResult; + } + + JArray jSW = GetSoftwares(name, ver, man); + foreach(JObject jObj in jSW) + { + if (jObj["ShortName"] != null) + return jObj["ShortName"].ToString(); + + if (jObj["Shortname"] != null) + return jObj["Shortname"].ToString(); + } + + return ""; + + } + + public bool IncCounter(string ShortName = "", string counter = "DL", string Customer = "known") + { + return false; + } + + //Upload SW and wait for approval + public bool UploadSoftwareWaiting(JArray Software) + { + try + { + string ProductName = Base.clean(Software[0]["ProductName"].ToString()).Trim(); + string ProductVersion = Base.clean(Software[0]["ProductVersion"].ToString()).Trim(); + string Manufacturer = Base.clean(Software[0]["Manufacturer"].ToString()).Trim(); + + string sIconId = DateTime.Now.Year.ToString().Substring(2, 2) + DateTime.Now.DayOfYear.ToString("D" + 3) + Convert.ToInt32(DateTime.Now.TimeOfDay.TotalMinutes).ToString(); + int iIconID = int.Parse(sIconId); + + foreach (JObject jObj in Software) + { + try + { + if (jObj["SWId"] == null) + jObj.Add("SWId", iIconID); + else + jObj["SWId"] = iIconID; + + //only used for V <= 1.6.2.x + if (jObj["IconId"] == null) + jObj.Add("IconId", iIconID); + else + jObj["IconId"] = iIconID; + } + catch { } + } + + return RZRestAPIv2.UploadSoftware(Software); + } + catch { } + + return false; + } + + public List GetPendingApproval() + { + List lRes = new List(); + return lRes; + } + + public bool Approve(string Software) + { + return false; + } + + public bool Decline(string Software) + { + return false; + } + + public string GetPending(string Software) + { + return ""; + } + } +} diff --git a/RZ.Server/RZ.Plugin.Software.Proxy/RZ.Plugin.Software.Proxy.csproj b/RZ.Server/RZ.Plugin.Software.Proxy/RZ.Plugin.Software.Proxy.csproj new file mode 100644 index 0000000..e444ce5 --- /dev/null +++ b/RZ.Server/RZ.Plugin.Software.Proxy/RZ.Plugin.Software.Proxy.csproj @@ -0,0 +1,29 @@ + + + + netcoreapp2.2 + true + RZ.Plugin.Software.Proxy + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + + + + + + + + + C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.hosting.abstractions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Hosting.Abstractions.dll + + + + diff --git a/RZ.Server/RZ.Plugin.Software.Proxy/RZRestAPIv2_min.cs b/RZ.Server/RZ.Plugin.Software.Proxy/RZRestAPIv2_min.cs new file mode 100644 index 0000000..9c969e3 --- /dev/null +++ b/RZ.Server/RZ.Plugin.Software.Proxy/RZRestAPIv2_min.cs @@ -0,0 +1,95 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; + +namespace Plugin_Software +{ + class RZRestAPIv2 + { + private static string _sURL = ""; + private static HttpClient oClient = new HttpClient(); //thx https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/ + + public static string sURL + { + get + { + if (!string.IsNullOrEmpty(_sURL)) + return _sURL; + + _sURL = GetURL(""); + return _sURL; + } + set + { + _sURL = value; + } + } + + public static string GetURL(string customerid) + { + using (HttpClient hClient = new HttpClient()) + { + Task tReq; + if (string.IsNullOrEmpty(customerid)) + tReq = hClient.GetStringAsync("https://ruckzuck.tools/rest/v2/geturl"); + else + tReq = hClient.GetStringAsync("https://ruckzuck.tools/rest/v2/geturl?customerid=" + customerid); + + tReq.Wait(5000); //wait max 5s + + if (tReq.IsCompleted) + { + _sURL = tReq.Result; + return _sURL; + } + else + { + _sURL = "https://ruckzuck.azurewebsites.net"; + return _sURL; + } + } + } + + public static Task GetIcon(Int32 iconid = 0, string iconhash = "") + { + string IcoURL = sURL + "/rest/v2/geticon?iconhash=" + iconhash; + + if (string.IsNullOrEmpty(iconhash)) + IcoURL = sURL + "/rest/v2/geticon?iconid=" + iconid.ToString(); + + return oClient.GetStreamAsync(IcoURL); + + } + + public static JArray GetSoftwares(string shortname) + { + string sRes = oClient.GetStringAsync(sURL + "/rest/v2/getsoftwares?shortname=" + shortname).Result; + return JArray.Parse(sRes); + } + + public static JArray GetSoftwares(string name = "", string ver = "", string man = "_unknown") + { + string sRes = oClient.GetStringAsync(sURL + "/rest/v2/getsoftwares?name=" + WebUtility.UrlEncode(name) + "&ver=" + WebUtility.UrlEncode(ver) + "&man=" + WebUtility.UrlEncode(man)).Result; + return JArray.Parse(sRes); + } + + public static bool UploadSoftware(JArray Software) + { + HttpContent oCont = new StringContent(Software.ToString(Formatting.None)); + + var oStat = oClient.PutAsync(sURL + "rest/v2/uploadsoftware", oCont); + oStat.Wait(10000); + + if (oStat.IsCompleted) + return true; + else + return false; + } + } +} diff --git a/RZ.Server/RZ.SWLookup.Plugin.Azure/RZ.Plugin.SWLookup.Azure.cs b/RZ.Server/RZ.SWLookup.Plugin.Azure/RZ.Plugin.SWLookup.Azure.cs index a7f1e02..630c88d 100644 --- a/RZ.Server/RZ.SWLookup.Plugin.Azure/RZ.Plugin.SWLookup.Azure.cs +++ b/RZ.Server/RZ.SWLookup.Plugin.Azure/RZ.Plugin.SWLookup.Azure.cs @@ -31,6 +31,11 @@ public string Name public System.Collections.Generic.Dictionary Settings { get; set; } + public bool Forward + { + get { return false; } + } + public void Init(string PluginPath) { //Check if MemoryCache is initialized @@ -404,5 +409,10 @@ private JArray getAutoMap(string url, string Customer = "automap") return new JArray(); } + + public JArray CheckForUpdates(JArray Softwares) + { + return new JArray(); + } } } diff --git a/RZ.Server/RZ.SWLookup.Plugin.Proxy/FodyWeavers.xml b/RZ.Server/RZ.SWLookup.Plugin.Proxy/FodyWeavers.xml new file mode 100644 index 0000000..a5dcf04 --- /dev/null +++ b/RZ.Server/RZ.SWLookup.Plugin.Proxy/FodyWeavers.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/RZ.Server/RZ.SWLookup.Plugin.Proxy/FodyWeavers.xsd b/RZ.Server/RZ.SWLookup.Plugin.Proxy/FodyWeavers.xsd new file mode 100644 index 0000000..44a5374 --- /dev/null +++ b/RZ.Server/RZ.SWLookup.Plugin.Proxy/FodyWeavers.xsd @@ -0,0 +1,111 @@ + + + + + + + + + + + + A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks + + + + + A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks. + + + + + A list of unmanaged 32 bit assembly names to include, delimited with line breaks. + + + + + A list of unmanaged 64 bit assembly names to include, delimited with line breaks. + + + + + The order of preloaded assemblies, delimited with line breaks. + + + + + + This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file. + + + + + Controls if .pdbs for reference assemblies are also embedded. + + + + + Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option. + + + + + As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off. + + + + + Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code. + + + + + Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior. + + + + + A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with | + + + + + A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |. + + + + + A list of unmanaged 32 bit assembly names to include, delimited with |. + + + + + A list of unmanaged 64 bit assembly names to include, delimited with |. + + + + + The order of preloaded assemblies, delimited with |. + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/RZ.Server/RZ.SWLookup.Plugin.Proxy/RZ.Plugin.SWLookup.Proxy.cs b/RZ.Server/RZ.SWLookup.Plugin.Proxy/RZ.Plugin.SWLookup.Proxy.cs new file mode 100644 index 0000000..18ea34c --- /dev/null +++ b/RZ.Server/RZ.SWLookup.Plugin.Proxy/RZ.Plugin.SWLookup.Proxy.cs @@ -0,0 +1,79 @@ +using Microsoft.Extensions.Caching.Memory; +using Newtonsoft.Json.Linq; +using RZ.Server; +using RZ.Server.Interfaces; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; + +namespace RZ.SWLookup.Plugin +{ + public class Plugin_SWLookup : ISWLookup + { + private IMemoryCache _cache; + private long SlidingExpiration = 900; //15min cache for Softwares + + public string Name + { + get + { + return Assembly.GetExecutingAssembly().ManifestModule.Name; + } + } + + public System.Collections.Generic.Dictionary Settings { get; set; } + + public void Init(string PluginPath) + { + //Check if MemoryCache is initialized + if (_cache != null) + { + _cache.Dispose(); + } + + _cache = new MemoryCache(new MemoryCacheOptions()); + + if (Settings == null) + Settings = new Dictionary(); + + string wwwpath = Settings["wwwPath"] ?? PluginPath; + string swlookup = Path.Combine(wwwpath, "swlookup"); + if (!Directory.Exists(swlookup)) + Directory.CreateDirectory(swlookup); + + Settings.Add("swlookup", swlookup); + + } + + public bool Forward + { + get { return true; } + } + + + public string GetShortname(string name = "", string ver = "", string man = "") + { + return ""; + } + + public bool SetShortname(string name = "", string ver = "", string man = "", string shortname = "") + { + return false; + } + + + public IEnumerable SWLookupItems(string filter) + { + return null; + } + + public JArray CheckForUpdates(JArray Softwares) + { + JArray jRes = RZRestAPIv2.CheckForUpdates(Softwares); + Console.WriteLine("CheckForUpdates:" + jRes.Count.ToString() + " updates detected."); + return jRes; + } + } +} diff --git a/RZ.Server/RZ.SWLookup.Plugin.Proxy/RZ.Plugin.SWLookup.Proxy.csproj b/RZ.Server/RZ.SWLookup.Plugin.Proxy/RZ.Plugin.SWLookup.Proxy.csproj new file mode 100644 index 0000000..cd28b34 --- /dev/null +++ b/RZ.Server/RZ.SWLookup.Plugin.Proxy/RZ.Plugin.SWLookup.Proxy.csproj @@ -0,0 +1,21 @@ + + + + netcoreapp2.2 + RZ.Plugin.SWLookup.Proxy + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + + + + + + diff --git a/RZ.Server/RZ.SWLookup.Plugin.Proxy/RZRestAPIv2_min.cs b/RZ.Server/RZ.SWLookup.Plugin.Proxy/RZRestAPIv2_min.cs new file mode 100644 index 0000000..f304e14 --- /dev/null +++ b/RZ.Server/RZ.SWLookup.Plugin.Proxy/RZRestAPIv2_min.cs @@ -0,0 +1,72 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.IO; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; + +namespace RZ.SWLookup.Plugin +{ + class RZRestAPIv2 + { + private static string _sURL = ""; + private static HttpClient oClient = new HttpClient(); //thx https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/ + + public static string sURL + { + get + { + if (!string.IsNullOrEmpty(_sURL)) + return _sURL; + + _sURL = GetURL(""); + return _sURL; + } + set + { + _sURL = value; + } + } + + public static string GetURL(string customerid) + { + using (HttpClient hClient = new HttpClient()) + { + Task tReq; + if (string.IsNullOrEmpty(customerid)) + tReq = hClient.GetStringAsync("https://ruckzuck.tools/rest/v2/geturl"); + else + tReq = hClient.GetStringAsync("https://ruckzuck.tools/rest/v2/geturl?customerid=" + customerid); + + tReq.Wait(5000); //wait max 5s + + if (tReq.IsCompleted) + { + _sURL = tReq.Result; + return _sURL; + } + else + { + _sURL = "https://ruckzuck.azurewebsites.net"; + return _sURL; + } + } + } + + public static JArray CheckForUpdates(JArray Softwares) + { + HttpContent oCont = new StringContent(Softwares.ToString(Formatting.None), Encoding.UTF8, "application/json"); + var tChek = oClient.PostAsync(sURL + "/rest/v2/checkforupdate", oCont); + tChek.Wait(90000); + if (tChek.IsCompleted) + { + return JArray.Parse(tChek.Result.Content.ReadAsStringAsync().Result); + } + else + return new JArray(); + } + + } +} diff --git a/RZ.Server/RZ.SWLookup.Plugin/RZ.SWLookup.Plugin.cs b/RZ.Server/RZ.SWLookup.Plugin/RZ.SWLookup.Plugin.cs index 6dd4d8d..dd01f73 100644 --- a/RZ.Server/RZ.SWLookup.Plugin/RZ.SWLookup.Plugin.cs +++ b/RZ.Server/RZ.SWLookup.Plugin/RZ.SWLookup.Plugin.cs @@ -1,4 +1,5 @@ using Microsoft.Extensions.Caching.Memory; +using Newtonsoft.Json.Linq; using RZ.Server; using RZ.Server.Interfaces; using System; @@ -42,6 +43,11 @@ public void Init(string PluginPath) Settings.Add("swlookup", swlookup); } + public bool Forward + { + get { return false; } + } + public string GetShortname(string name = "", string ver = "", string man = "") { string sResult = ""; @@ -154,5 +160,10 @@ public IEnumerable SWLookupItems(string filter) yield return sOut; } } + + public JArray CheckForUpdates(JArray Softwares) + { + return new JArray(); + } } } diff --git a/RZ.Server/RZ.Server.Interfaces/Interfaces.cs b/RZ.Server/RZ.Server.Interfaces/Interfaces.cs index 5a6976a..c38d139 100644 --- a/RZ.Server/RZ.Server.Interfaces/Interfaces.cs +++ b/RZ.Server/RZ.Server.Interfaces/Interfaces.cs @@ -66,6 +66,8 @@ public interface ISWLookup string Name { get; } + bool Forward { get; } + Dictionary Settings { get; set; } string GetShortname(string name = "", string ver = "", string man = ""); @@ -74,6 +76,8 @@ public interface ISWLookup IEnumerable SWLookupItems(string filter); + JArray CheckForUpdates(JArray Softwares); + } public interface IFeedback diff --git a/RZ.Server/RZ.Server.Interfaces/base.cs b/RZ.Server/RZ.Server.Interfaces/base.cs index f91e6c9..faff9e1 100644 --- a/RZ.Server/RZ.Server.Interfaces/base.cs +++ b/RZ.Server/RZ.Server.Interfaces/base.cs @@ -411,10 +411,48 @@ public static bool SetShortname(string name = "", string ver = "", string man = return false; } + internal static bool? bForward = null; public static JArray CheckForUpdates(JArray Softwares) { + if (bForward == null) + { + try + { + foreach (var item in Plugins._SWLookupPlugins.OrderBy(t => t.Key)) + { + try + { + if (item.Value.Forward) + bForward = true; + } + catch { } + } + } + catch { bForward = false; } + + if (bForward == null) + bForward = false; + } + + if(bForward == true) + { + try + { + foreach (var item in Plugins._SWLookupPlugins.OrderBy(t => t.Key)) + { + try + { + return item.Value.CheckForUpdates(Softwares); + } + catch { } + } + } + catch {} + } + JArray jResult = new JArray(); + foreach (JObject jObj in Softwares) { bool bFound = false; diff --git a/RZ.Server/RZ.Server.sln b/RZ.Server/RZ.Server.sln index b890e41..0ef7088 100644 --- a/RZ.Server/RZ.Server.sln +++ b/RZ.Server/RZ.Server.sln @@ -21,6 +21,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RZ.Plugin.SWLookup.Azure", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RZ.Plugin.Catalog.Proxy", "RZ.Catalog.Plugin.Proxy\RZ.Plugin.Catalog.Proxy.csproj", "{96045409-FAFF-4354-BE2A-F1EE55340344}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RZ.Plugin.Software.Proxy", "RZ.Plugin.Software.Proxy\RZ.Plugin.Software.Proxy.csproj", "{1E93159B-260A-449E-8346-8080BF5F8A04}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RZ.Plugin.Feedback.Azure", "RZ.Plugin.Feedback.Azure\RZ.Plugin.Feedback.Azure.csproj", "{9717EE20-5AA6-4F92-BA69-9A2D9C9D5277}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RZ.Plugin.Feedback.Proxy", "RZ.Plugin.Feedback.Proxy\RZ.Plugin.Feedback.Proxy.csproj", "{74187EFB-07F0-477B-BFD2-01C47EF9B2EA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RZ.Plugin.SWLookup.Proxy", "RZ.SWLookup.Plugin.Proxy\RZ.Plugin.SWLookup.Proxy.csproj", "{CDD709A8-2863-4686-BC27-80AF3B048CBC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -63,6 +71,22 @@ Global {96045409-FAFF-4354-BE2A-F1EE55340344}.Debug|Any CPU.Build.0 = Debug|Any CPU {96045409-FAFF-4354-BE2A-F1EE55340344}.Release|Any CPU.ActiveCfg = Release|Any CPU {96045409-FAFF-4354-BE2A-F1EE55340344}.Release|Any CPU.Build.0 = Release|Any CPU + {1E93159B-260A-449E-8346-8080BF5F8A04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1E93159B-260A-449E-8346-8080BF5F8A04}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1E93159B-260A-449E-8346-8080BF5F8A04}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1E93159B-260A-449E-8346-8080BF5F8A04}.Release|Any CPU.Build.0 = Release|Any CPU + {9717EE20-5AA6-4F92-BA69-9A2D9C9D5277}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9717EE20-5AA6-4F92-BA69-9A2D9C9D5277}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9717EE20-5AA6-4F92-BA69-9A2D9C9D5277}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9717EE20-5AA6-4F92-BA69-9A2D9C9D5277}.Release|Any CPU.Build.0 = Release|Any CPU + {74187EFB-07F0-477B-BFD2-01C47EF9B2EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {74187EFB-07F0-477B-BFD2-01C47EF9B2EA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {74187EFB-07F0-477B-BFD2-01C47EF9B2EA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {74187EFB-07F0-477B-BFD2-01C47EF9B2EA}.Release|Any CPU.Build.0 = Release|Any CPU + {CDD709A8-2863-4686-BC27-80AF3B048CBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CDD709A8-2863-4686-BC27-80AF3B048CBC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CDD709A8-2863-4686-BC27-80AF3B048CBC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CDD709A8-2863-4686-BC27-80AF3B048CBC}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/RZ.Server/RZ.Server/Controllers/RZController.cs b/RZ.Server/RZ.Server/Controllers/RZController.cs index 48bee9d..a592cc7 100644 --- a/RZ.Server/RZ.Server/Controllers/RZController.cs +++ b/RZ.Server/RZ.Server/Controllers/RZController.cs @@ -253,12 +253,12 @@ public bool UploadSoftware() var oGet = new StreamReader(Request.Body).ReadToEndAsync(); string sJson = oGet.Result; if(sJson.TrimStart().StartsWith('[')) - return Base.UploadSoftware(JArray.Parse(oGet.Result)); + return Base.UploadSoftwareWaiting(JArray.Parse(oGet.Result)); else { JArray jResult = new JArray(); jResult.Add(JObject.Parse(oGet.Result)); - return Base.UploadSoftware(jResult); + return Base.UploadSoftwareWaiting(jResult); } } catch { } @@ -268,10 +268,13 @@ public bool UploadSoftware() [HttpGet] [Route("rest/v2/GetFile")] [Route("rest/v2/GetFile/{contentid}/{filename}")] + [Route("rest/v2/GetFile/proxy/{shortname}/{contentid}/{filename}")] [Route("wcf/RZService.svc/rest/v2/GetFile/{contentid}/{filename}")] - public async Task GetFile(string contentid, string filename) + public async Task GetFile(string contentid, string filename, string shortname = "") { string sPath = Path.Combine(contentid, filename); + if (!string.IsNullOrEmpty(shortname)) + sPath = Path.Combine("proxy", shortname, contentid, filename); return File(await Base.GetFile(sPath), "application/octet-stream"); } diff --git a/RZ.Server/RZ.Server/Program.cs b/RZ.Server/RZ.Server/Program.cs index b488f92..797cb9b 100644 --- a/RZ.Server/RZ.Server/Program.cs +++ b/RZ.Server/RZ.Server/Program.cs @@ -26,32 +26,40 @@ public static void Main(string[] args) //Broadcast listener (UDP) Task.Run(() => { - while (true) + try { - var ClientEp = new IPEndPoint(IPAddress.Any, 0); - var ClientRequestData = Server.Receive(ref ClientEp); - var ClientRequest = Encoding.ASCII.GetString(ClientRequestData); - - Console.WriteLine("Discovery request from {0}...", ClientRequest); - string sLocalURL = Base.localURL; - if(string.IsNullOrEmpty(sLocalURL)) + Console.WriteLine("Starting UDP Listener on Port: " + (Environment.GetEnvironmentVariable("UDPPort") ?? "5001")); + while (true) { - string sIP = "localhost"; + var ClientEp = new IPEndPoint(IPAddress.Any, 0); + var ClientRequestData = Server.Receive(ref ClientEp); + var ClientRequest = Encoding.ASCII.GetString(ClientRequestData); - try + Console.WriteLine("Discovery request from {0}...", ClientRequest); + string sLocalURL = Base.localURL; + if (string.IsNullOrEmpty(sLocalURL)) { - foreach (NetworkInterface f in NetworkInterface.GetAllNetworkInterfaces().Where(t => t.OperationalStatus == OperationalStatus.Up)) - foreach (GatewayIPAddressInformation d in f.GetIPProperties().GatewayAddresses.Where(t => t.Address.AddressFamily == AddressFamily.InterNetwork)) - { - sIP = f.GetIPProperties().UnicastAddresses.Where(t => t.Address.AddressFamily == AddressFamily.InterNetwork).First().Address.ToString(); - } - } - catch { } + string sIP = "localhost"; + + try + { + foreach (NetworkInterface f in NetworkInterface.GetAllNetworkInterfaces().Where(t => t.OperationalStatus == OperationalStatus.Up)) + foreach (GatewayIPAddressInformation d in f.GetIPProperties().GatewayAddresses.Where(t => t.Address.AddressFamily == AddressFamily.InterNetwork)) + { + sIP = f.GetIPProperties().UnicastAddresses.Where(t => t.Address.AddressFamily == AddressFamily.InterNetwork).First().Address.ToString(); + } + } + catch { } - sLocalURL = "http://" + sIP + ":" + (Environment.GetEnvironmentVariable("WebPort") ?? "5000"); + sLocalURL = "http://" + sIP + ":" + (Environment.GetEnvironmentVariable("WebPort") ?? "5000"); + } + var ResponseData = Encoding.ASCII.GetBytes(sLocalURL); + Server.Send(ResponseData, ResponseData.Length, ClientEp); } - var ResponseData = Encoding.ASCII.GetBytes(sLocalURL); - Server.Send(ResponseData, ResponseData.Length, ClientEp); + } + catch(Exception ex) + { + Console.WriteLine("ERROR: UDP Listener - " + ex.Message); } }); diff --git a/RZ.Server/RZ.Server/RZ.Server.csproj b/RZ.Server/RZ.Server/RZ.Server.csproj index d0a302c..c2c7c9f 100644 --- a/RZ.Server/RZ.Server/RZ.Server.csproj +++ b/RZ.Server/RZ.Server/RZ.Server.csproj @@ -2,13 +2,15 @@ netcoreapp2.2 - + RZ.Server.Program 2.0.0 0 (c) 2019 by Roger Zander https://github.com/rzander/ruckzuck 2.0.0.11 2.0.0.11 + wwwroot\favicon.ico + WinExe @@ -34,7 +36,7 @@ - + @@ -50,6 +52,9 @@ PreserveNewest + + Always +