diff --git a/NzbDrone.App.Test/MonitoringProviderTest.cs b/NzbDrone.App.Test/MonitoringProviderTest.cs index 2d504b072..f1e4b0a9b 100644 --- a/NzbDrone.App.Test/MonitoringProviderTest.cs +++ b/NzbDrone.App.Test/MonitoringProviderTest.cs @@ -4,6 +4,7 @@ using Moq; using NUnit.Framework; using NzbDrone.Common; using NzbDrone.Common.Model; +using NzbDrone.Common.Processes; using NzbDrone.Host; using NzbDrone.Test.Common; diff --git a/NzbDrone.Common.Test/ProcessProviderTests.cs b/NzbDrone.Common.Test/ProcessProviderTests.cs index 4155ab4d0..099defbe9 100644 --- a/NzbDrone.Common.Test/ProcessProviderTests.cs +++ b/NzbDrone.Common.Test/ProcessProviderTests.cs @@ -6,6 +6,7 @@ using System.Linq; using FluentAssertions; using NUnit.Framework; using NzbDrone.Common.Model; +using NzbDrone.Common.Processes; using NzbDrone.Test.Common; using NzbDrone.Test.Dummy; diff --git a/NzbDrone.Common/NzbDrone.Common.csproj b/NzbDrone.Common/NzbDrone.Common.csproj index 8fe4ab3af..0d76e91a2 100644 --- a/NzbDrone.Common/NzbDrone.Common.csproj +++ b/NzbDrone.Common/NzbDrone.Common.csproj @@ -98,6 +98,7 @@ + @@ -122,7 +123,7 @@ - + diff --git a/NzbDrone.Common/Processes/ProcessOutput.cs b/NzbDrone.Common/Processes/ProcessOutput.cs new file mode 100644 index 000000000..231b6097e --- /dev/null +++ b/NzbDrone.Common/Processes/ProcessOutput.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; + +namespace NzbDrone.Common.Processes +{ + public class ProcessOutput + { + public List Standard { get; set; } + public List Error { get; set; } + + public ProcessOutput() + { + Standard = new List(); + Error = new List(); + } + } +} diff --git a/NzbDrone.Common/ProcessProvider.cs b/NzbDrone.Common/Processes/ProcessProvider.cs similarity index 94% rename from NzbDrone.Common/ProcessProvider.cs rename to NzbDrone.Common/Processes/ProcessProvider.cs index e93edd781..75bde50f8 100644 --- a/NzbDrone.Common/ProcessProvider.cs +++ b/NzbDrone.Common/Processes/ProcessProvider.cs @@ -9,7 +9,7 @@ using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.Instrumentation; using NzbDrone.Common.Model; -namespace NzbDrone.Common +namespace NzbDrone.Common.Processes { public interface IProcessProvider { @@ -23,6 +23,7 @@ namespace NzbDrone.Common ProcessPriorityClass GetCurrentProcessPriority(); Process Start(string path, string args = null, Action onOutputDataReceived = null, Action onErrorDataReceived = null); Process SpawnNewProcess(string path, string args = null); + ProcessOutput StartAndCapture(string path, string args = null); } public class ProcessProvider : IProcessProvider @@ -88,11 +89,8 @@ namespace NzbDrone.Common process.Start(); } - - public Process Start(string path, string args = null, Action onOutputDataReceived = null, Action onErrorDataReceived = null) { - if (OsInfo.IsMono && path.EndsWith(".exe", StringComparison.InvariantCultureIgnoreCase)) { args = path + " " + args; @@ -147,7 +145,6 @@ namespace NzbDrone.Common process.BeginErrorReadLine(); process.BeginOutputReadLine(); - return process; } @@ -172,6 +169,16 @@ namespace NzbDrone.Common return process; } + public ProcessOutput StartAndCapture(string path, string args = null) + { + var output = new ProcessOutput(); + var process = Start(path, args, s => output.Standard.Add(s), error => output.Error.Add(error)); + + WaitForExit(process); + + return output; + } + public void WaitForExit(Process process) { Logger.Trace("Waiting for process {0} to exit.", process.ProcessName); @@ -225,7 +232,6 @@ namespace NzbDrone.Common return null; } - private static string GetExeFileName(Process process) { if (process.MainModule.FileName != "mono.exe") diff --git a/NzbDrone.Core.Test/UpdateTests/UpdateServiceFixture.cs b/NzbDrone.Core.Test/UpdateTests/UpdateServiceFixture.cs index 31ebee3e5..32b0c49ea 100644 --- a/NzbDrone.Core.Test/UpdateTests/UpdateServiceFixture.cs +++ b/NzbDrone.Core.Test/UpdateTests/UpdateServiceFixture.cs @@ -6,6 +6,7 @@ using NUnit.Framework; using NzbDrone.Common; using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.Model; +using NzbDrone.Common.Processes; using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Update; using NzbDrone.Core.Update.Commands; diff --git a/NzbDrone.Core/Update/InstallUpdateService.cs b/NzbDrone.Core/Update/InstallUpdateService.cs index 262806e05..b0088ee87 100644 --- a/NzbDrone.Core/Update/InstallUpdateService.cs +++ b/NzbDrone.Core/Update/InstallUpdateService.cs @@ -3,6 +3,7 @@ using System.IO; using NLog; using NzbDrone.Common; using NzbDrone.Common.EnvironmentInfo; +using NzbDrone.Common.Processes; using NzbDrone.Core.Messaging.Commands; using NzbDrone.Core.Update.Commands; using NzbDrone.Core.Instrumentation; diff --git a/NzbDrone.Host/AccessControl/UrlAclAdapter.cs b/NzbDrone.Host/AccessControl/UrlAclAdapter.cs index e536fffbd..dff7d1f19 100644 --- a/NzbDrone.Host/AccessControl/UrlAclAdapter.cs +++ b/NzbDrone.Host/AccessControl/UrlAclAdapter.cs @@ -1,7 +1,9 @@ using System; +using System.Linq; using NLog; using NzbDrone.Common; using NzbDrone.Common.EnvironmentInfo; +using NzbDrone.Common.Processes; using NzbDrone.Core.Configuration; namespace NzbDrone.Host.AccessControl @@ -9,11 +11,15 @@ namespace NzbDrone.Host.AccessControl public interface IUrlAclAdapter { void RefreshRegistration(); + bool IsRegistered(); string UrlAcl { get; } + string LocalUrlAcl { get; } } public class UrlAclAdapter : IUrlAclAdapter { + private const string URL_ACL = "http://{0}:{1}/"; + private readonly IProcessProvider _processProvider; private readonly IConfigFileProvider _configFileProvider; private readonly Logger _logger; @@ -25,11 +31,29 @@ namespace NzbDrone.Host.AccessControl _logger = logger; } + public bool IsRegistered() + { + var arguments = String.Format("http show urlacl {0}", UrlAcl); + var output = RunNetsh(arguments); + + if (output == null || !output.Standard.Any()) return false; + + return output.Standard.Any(line => line.Contains(UrlAcl)); + } + public string UrlAcl { get { - return "http://*:" + _configFileProvider.Port + "/"; + return String.Format(URL_ACL, "*", _configFileProvider.Port); + } + } + + public string LocalUrlAcl + { + get + { + return String.Format(URL_ACL, "localhost", _configFileProvider.Port); } } @@ -47,17 +71,20 @@ namespace NzbDrone.Host.AccessControl RunNetsh(arguments); } - private void RunNetsh(string arguments) + private ProcessOutput RunNetsh(string arguments) { try { - var process = _processProvider.Start("netsh.exe", arguments); - process.WaitForExit(5000); + var output = _processProvider.StartAndCapture("netsh.exe", arguments); + + return output; } catch (Exception ex) { _logger.WarnException("Error executing netsh with arguments: " + arguments, ex); } + + return null; } } } \ No newline at end of file diff --git a/NzbDrone.Host/ApplicationServer.cs b/NzbDrone.Host/ApplicationServer.cs index d6e1e3625..ab0ee6f6e 100644 --- a/NzbDrone.Host/ApplicationServer.cs +++ b/NzbDrone.Host/ApplicationServer.cs @@ -3,6 +3,7 @@ using System.ServiceProcess; using NLog; using NzbDrone.Common; using NzbDrone.Common.EnvironmentInfo; +using NzbDrone.Common.Processes; using NzbDrone.Core.Configuration; using NzbDrone.Host.Owin; diff --git a/NzbDrone.Host/Owin/OwinHostController.cs b/NzbDrone.Host/Owin/OwinHostController.cs index b4d8d24ba..14d5d331c 100644 --- a/NzbDrone.Host/Owin/OwinHostController.cs +++ b/NzbDrone.Host/Owin/OwinHostController.cs @@ -38,19 +38,14 @@ namespace NzbDrone.Host.Owin public void StartServer() { IgnoreCertErrorPolicy.Register(); + var urlAcl = DetermineUrlAcl(); - if (OsInfo.IsWindows && _runtimeInfo.IsAdmin) - { - _urlAclAdapter.RefreshRegistration(); - _firewallAdapter.MakeAccessible(); - } - - var options = new StartOptions(_urlAclAdapter.UrlAcl) + var options = new StartOptions(urlAcl) { ServerFactory = "Microsoft.Owin.Host.HttpListener" }; - _logger.Info("starting server on {0}", _urlAclAdapter.UrlAcl); + _logger.Info("starting server on {0}", urlAcl); try { @@ -100,5 +95,26 @@ namespace NzbDrone.Host.Owin _logger.Info("Host has stopped"); } + private string DetermineUrlAcl() + { + if (OsInfo.IsWindows && _runtimeInfo.IsAdmin) + { + if (_runtimeInfo.IsAdmin) + { + _urlAclAdapter.RefreshRegistration(); + _firewallAdapter.MakeAccessible(); + } + + else + { + if (!_urlAclAdapter.IsRegistered()) + { + return _urlAclAdapter.LocalUrlAcl; + } + } + } + + return _urlAclAdapter.UrlAcl; + } } } \ No newline at end of file diff --git a/NzbDrone.Host/PriorityMonitor.cs b/NzbDrone.Host/PriorityMonitor.cs index 28caf28ac..9d2533791 100644 --- a/NzbDrone.Host/PriorityMonitor.cs +++ b/NzbDrone.Host/PriorityMonitor.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.Threading; using NLog; using NzbDrone.Common; +using NzbDrone.Common.Processes; namespace NzbDrone.Host { diff --git a/NzbDrone.Integration.Test/NzbDroneRunner.cs b/NzbDrone.Integration.Test/NzbDroneRunner.cs index 5955166ff..b4bb8fa85 100644 --- a/NzbDrone.Integration.Test/NzbDroneRunner.cs +++ b/NzbDrone.Integration.Test/NzbDroneRunner.cs @@ -5,6 +5,7 @@ using System.Threading; using NUnit.Framework; using NzbDrone.Common; using NzbDrone.Common.EnvironmentInfo; +using NzbDrone.Common.Processes; using RestSharp; namespace NzbDrone.Integration.Test diff --git a/NzbDrone.Update.Test/ProgramFixture.cs b/NzbDrone.Update.Test/ProgramFixture.cs index 2a955e7f6..bace6d3ae 100644 --- a/NzbDrone.Update.Test/ProgramFixture.cs +++ b/NzbDrone.Update.Test/ProgramFixture.cs @@ -3,6 +3,7 @@ using Moq; using NUnit.Framework; using NzbDrone.Common; using NzbDrone.Common.Model; +using NzbDrone.Common.Processes; using NzbDrone.Test.Common; using NzbDrone.Update.UpdateEngine; diff --git a/NzbDrone.Update.Test/StartNzbDroneService.cs b/NzbDrone.Update.Test/StartNzbDroneService.cs index 4b1c0c4bb..3051e529f 100644 --- a/NzbDrone.Update.Test/StartNzbDroneService.cs +++ b/NzbDrone.Update.Test/StartNzbDroneService.cs @@ -3,6 +3,7 @@ using Moq; using NUnit.Framework; using NzbDrone.Common; using NzbDrone.Common.EnvironmentInfo; +using NzbDrone.Common.Processes; using NzbDrone.Test.Common; using NzbDrone.Update.UpdateEngine; using IServiceProvider = NzbDrone.Common.IServiceProvider; diff --git a/NzbDrone.Update/UpdateApp.cs b/NzbDrone.Update/UpdateApp.cs index 3a882cd74..3e1c89442 100644 --- a/NzbDrone.Update/UpdateApp.cs +++ b/NzbDrone.Update/UpdateApp.cs @@ -5,6 +5,7 @@ using NzbDrone.Common; using NzbDrone.Common.Composition; using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.Instrumentation; +using NzbDrone.Common.Processes; using NzbDrone.Common.Security; using NzbDrone.Update.UpdateEngine; diff --git a/NzbDrone.Update/UpdateEngine/DetectApplicationType.cs b/NzbDrone.Update/UpdateEngine/DetectApplicationType.cs index 68a60b004..ec9a80a96 100644 --- a/NzbDrone.Update/UpdateEngine/DetectApplicationType.cs +++ b/NzbDrone.Update/UpdateEngine/DetectApplicationType.cs @@ -1,4 +1,5 @@ using NzbDrone.Common; +using NzbDrone.Common.Processes; namespace NzbDrone.Update.UpdateEngine { diff --git a/NzbDrone.Update/UpdateEngine/StartNzbDrone.cs b/NzbDrone.Update/UpdateEngine/StartNzbDrone.cs index e7ad7753c..211961a83 100644 --- a/NzbDrone.Update/UpdateEngine/StartNzbDrone.cs +++ b/NzbDrone.Update/UpdateEngine/StartNzbDrone.cs @@ -3,6 +3,7 @@ using System.IO; using NLog; using NzbDrone.Common; using NzbDrone.Common.EnvironmentInfo; +using NzbDrone.Common.Processes; using IServiceProvider = NzbDrone.Common.IServiceProvider; namespace NzbDrone.Update.UpdateEngine diff --git a/NzbDrone.Update/UpdateEngine/TerminateNzbDrone.cs b/NzbDrone.Update/UpdateEngine/TerminateNzbDrone.cs index 80ae0e91b..329c9555e 100644 --- a/NzbDrone.Update/UpdateEngine/TerminateNzbDrone.cs +++ b/NzbDrone.Update/UpdateEngine/TerminateNzbDrone.cs @@ -1,6 +1,7 @@ using System; using NLog; using NzbDrone.Common; +using NzbDrone.Common.Processes; using IServiceProvider = NzbDrone.Common.IServiceProvider; namespace NzbDrone.Update.UpdateEngine diff --git a/NzbDrone/SysTray/SysTrayApp.cs b/NzbDrone/SysTray/SysTrayApp.cs index 595a53f16..74270f09b 100644 --- a/NzbDrone/SysTray/SysTrayApp.cs +++ b/NzbDrone/SysTray/SysTrayApp.cs @@ -3,6 +3,7 @@ using System.ComponentModel; using System.Windows.Forms; using NzbDrone.Common; using NzbDrone.Common.EnvironmentInfo; +using NzbDrone.Common.Processes; using NzbDrone.Host.Owin; namespace NzbDrone.SysTray