From f973c74c87c7ec9f58665823a23ec61053c64b32 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Thu, 6 Oct 2011 21:36:47 -0700 Subject: [PATCH 1/3] ConfigFileProvider will now add missing config values automatically, with a default value. Added Handbrake and AtomicParsley wrappers for iPod video conversion. --- NzbDrone.Core.Test/ConfigFileProviderTest.cs | 63 ++++++++++- NzbDrone.Core/CentralDispatch.cs | 1 + NzbDrone.Core/Model/AtomicParsleyTitleType.cs | 9 ++ NzbDrone.Core/Model/AuthenticationType.cs | 13 +++ NzbDrone.Core/NzbDrone.Core.csproj | 5 + .../Converting/AtomicParsleyProvider.cs | 74 ++++++++++++ .../Providers/Converting/HandbrakeProvider.cs | 105 ++++++++++++++++++ .../Providers/Core/ConfigFileProvider.cs | 71 +++++++++--- .../Providers/Jobs/ConvertEpisodeJob.cs | 53 +++++++++ 9 files changed, 375 insertions(+), 19 deletions(-) create mode 100644 NzbDrone.Core/Model/AtomicParsleyTitleType.cs create mode 100644 NzbDrone.Core/Model/AuthenticationType.cs create mode 100644 NzbDrone.Core/Providers/Converting/AtomicParsleyProvider.cs create mode 100644 NzbDrone.Core/Providers/Converting/HandbrakeProvider.cs create mode 100644 NzbDrone.Core/Providers/Jobs/ConvertEpisodeJob.cs diff --git a/NzbDrone.Core.Test/ConfigFileProviderTest.cs b/NzbDrone.Core.Test/ConfigFileProviderTest.cs index 471bec774..cf02dae96 100644 --- a/NzbDrone.Core.Test/ConfigFileProviderTest.cs +++ b/NzbDrone.Core.Test/ConfigFileProviderTest.cs @@ -2,6 +2,7 @@ using AutoMoq; using FluentAssertions; using NUnit.Framework; +using NzbDrone.Core.Model; using NzbDrone.Core.Providers.Core; using NzbDrone.Core.Repository; using NzbDrone.Core.Test.Framework; @@ -32,7 +33,7 @@ namespace NzbDrone.Core.Test var mocker = new AutoMoqer(); //Act - var result = mocker.Resolve().GetValue(key); + var result = mocker.Resolve().GetValue(key, value); //Assert result.Should().Be(value); @@ -47,7 +48,7 @@ namespace NzbDrone.Core.Test var mocker = new AutoMoqer(); //Act - var result = mocker.Resolve().GetValueInt(key); + var result = mocker.Resolve().GetValueInt(key, value); //Assert result.Should().Be(value); @@ -57,11 +58,12 @@ namespace NzbDrone.Core.Test public void GetBool_Success() { const string key = "LaunchBrowser"; + const bool value = true; var mocker = new AutoMoqer(); //Act - var result = mocker.Resolve().GetValueBoolean(key); + var result = mocker.Resolve().GetValueBoolean(key, value); //Assert result.Should().BeTrue(); @@ -124,5 +126,60 @@ namespace NzbDrone.Core.Test var result = mocker.Resolve().Port; result.Should().Be(value); } + + [Test] + public void GetValue_New_Key() + { + const string key = "Hello"; + const string value = "World"; + + var mocker = new AutoMoqer(); + + //Act + var result = mocker.Resolve().GetValue(key, value); + + //Assert + result.Should().Be(value); + } + + [Test] + public void GetValue_New_Key_with_new_parent() + { + const string key = "Hello"; + const string value = "World"; + + var mocker = new AutoMoqer(); + + //Act + var result = mocker.Resolve().GetValue(key, value, "Universe"); + + //Assert + result.Should().Be(value); + } + + [Test] + public void GetAuthenticationType_No_Existing_Value() + { + var mocker = new AutoMoqer(); + + //Act + var result = mocker.Resolve().AuthenticationType; + + //Assert + result.Should().Be(AuthenticationType.Anonymous); + } + + [Test] + public void GetAuthenticationType_Windows() + { + var mocker = new AutoMoqer(); + mocker.Resolve().SetValue("AuthenticationType", 1); + + //Act + var result = mocker.Resolve().AuthenticationType; + + //Assert + result.Should().Be(AuthenticationType.Windows); + } } } \ No newline at end of file diff --git a/NzbDrone.Core/CentralDispatch.cs b/NzbDrone.Core/CentralDispatch.cs index ca707daa5..6eccb3a2c 100644 --- a/NzbDrone.Core/CentralDispatch.cs +++ b/NzbDrone.Core/CentralDispatch.cs @@ -113,6 +113,7 @@ namespace NzbDrone.Core _kernel.Bind().To().InSingletonScope(); _kernel.Bind().To().InSingletonScope(); _kernel.Bind().To().InSingletonScope(); + _kernel.Bind().To().InSingletonScope(); _kernel.Get().Initialize(); _kernel.Get().StartTimer(30); diff --git a/NzbDrone.Core/Model/AtomicParsleyTitleType.cs b/NzbDrone.Core/Model/AtomicParsleyTitleType.cs new file mode 100644 index 000000000..d133b977a --- /dev/null +++ b/NzbDrone.Core/Model/AtomicParsleyTitleType.cs @@ -0,0 +1,9 @@ +namespace NzbDrone.Core.Model +{ + public enum AtomicParsleyTitleType + { + None = 0, + EpisodeNumber = 1, + Both = 2 + } +} \ No newline at end of file diff --git a/NzbDrone.Core/Model/AuthenticationType.cs b/NzbDrone.Core/Model/AuthenticationType.cs new file mode 100644 index 000000000..0ffc02991 --- /dev/null +++ b/NzbDrone.Core/Model/AuthenticationType.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NzbDrone.Core.Model +{ + public enum AuthenticationType + { + Anonymous = 0, + Windows = 1 + } +} diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index ea2d903c2..5a958d2e4 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -189,6 +189,8 @@ + + @@ -203,10 +205,13 @@ + + + diff --git a/NzbDrone.Core/Providers/Converting/AtomicParsleyProvider.cs b/NzbDrone.Core/Providers/Converting/AtomicParsleyProvider.cs new file mode 100644 index 000000000..ae99c9258 --- /dev/null +++ b/NzbDrone.Core/Providers/Converting/AtomicParsleyProvider.cs @@ -0,0 +1,74 @@ +using System; +using System.Diagnostics; +using System.IO; +using NLog; +using NzbDrone.Core.Model; +using NzbDrone.Core.Providers.Core; +using NzbDrone.Core.Repository; + +namespace NzbDrone.Core.Providers.Converting +{ + public class AtomicParsleyProvider + { + private readonly ConfigProvider _configProvider; + + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + + public AtomicParsleyProvider(ConfigProvider configProvider) + { + _configProvider = configProvider; + } + + public AtomicParsleyProvider() + { + + } + + public virtual bool RunAtomicParsley(Episode episode, string outputFile) + { + throw new NotImplementedException(); + + var atomicParsleyLocation = _configProvider.GetValue("AtomicParsleyLocation", ""); + var atomicParsleyTitleType = (AtomicParsleyTitleType) System.Convert.ToInt32(_configProvider.GetValue("AtomicParsley", 0)); + + var atomicParsleyCommand = String.Format("\"{0}\" --overWrite --title \"{1}\" --genre \"TV Shows\" --stik \"TV Show\" --TVShowName \"{2}\" --TVEpisodeNum \"{3}\" --TVSeason \"{4}\"", + outputFile, episode.Title, episode.Series.Title, episode.EpisodeNumber, episode.SeasonNumber); + + //If Episode Number + Name should be in Episode Title (Number - Title) + if (atomicParsleyTitleType == AtomicParsleyTitleType.EpisodeNumber) + { + atomicParsleyCommand = String.Format("\"{0}\" --overWrite --title \"{3} - {1}\" --genre \"TV Shows\" --stik \"TV Show\" --TVShowName \"{2}\" --TVEpisodeNum \"{3}\" --TVSeason \"{4}\"", + outputFile, episode.Title, episode.Series.Title, episode.EpisodeNumber, episode.SeasonNumber); + } + + //If Season/Episode Number + Name should be in Episode Title (SeasonNumber'x'EpisodeNumber - Title) + else if (atomicParsleyTitleType == AtomicParsleyTitleType.Both) + { + atomicParsleyCommand = String.Format("\"{0}\" --overWrite --title \"{4}x{3:00} - {1}\" --genre \"TV Shows\" --stik \"TV Show\" --TVShowName \"{2}\" --TVEpisodeNum \"{3}\" --TVSeason \"{4}\"", + outputFile, episode.Title, episode.Series.Title, episode.EpisodeNumber, episode.SeasonNumber); + } + + try + { + var process = new Process(); + process.StartInfo.FileName = Path.Combine(atomicParsleyLocation, "AtomicParsley.exe"); + process.StartInfo.Arguments = atomicParsleyCommand; + process.StartInfo.UseShellExecute = false; + process.StartInfo.CreateNoWindow = true; + process.StartInfo.RedirectStandardOutput = true; + //process.OutputDataReceived += new DataReceivedEventHandler(HandBrakeOutputDataReceived); + process.Start(); + //process.BeginOutputReadLine(); + process.WaitForExit(); + } + + catch (Exception ex) + { + Logger.DebugException(ex.Message, ex); + return false; + } + + return true; + } + } +} diff --git a/NzbDrone.Core/Providers/Converting/HandbrakeProvider.cs b/NzbDrone.Core/Providers/Converting/HandbrakeProvider.cs new file mode 100644 index 000000000..0379730ca --- /dev/null +++ b/NzbDrone.Core/Providers/Converting/HandbrakeProvider.cs @@ -0,0 +1,105 @@ +using System; +using System.Diagnostics; +using System.Text.RegularExpressions; +using NLog; +using NzbDrone.Core.Model.Notification; +using NzbDrone.Core.Providers.Core; +using NzbDrone.Core.Repository; + +namespace NzbDrone.Core.Providers.Converting +{ + public class HandbrakeProvider + { + //Interacts with Handbrake + private readonly ConfigProvider _configProvider; + private ProgressNotification _notification; + private Episode _currentEpisode; + + private Regex _processingRegex = + new Regex(@"^(?:Encoding).+?(?:\,\s(?\d{1,3}\.\d{2})\s\%)(?:.+?ETA\s(?\d{2})h(?\d{2})m(?\d{2})s)?", + RegexOptions.IgnoreCase | RegexOptions.Compiled); + + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + + public HandbrakeProvider(ConfigProvider configProvider) + { + _configProvider = configProvider; + } + + public HandbrakeProvider() + { + + } + + public virtual string ConvertFile(Episode episode, ProgressNotification notification) + { + _notification = notification; + _currentEpisode = episode; + + var outputFile = _configProvider.GetValue("iPodConvertDir", ""); + + var handBrakePreset = _configProvider.GetValue("HandBrakePreset", "iPhone & iPod Touch"); + var handBrakeCommand = String.Format("-i \"{0}\" -o \"{1}\" --preset=\"{2}\"", episode.EpisodeFile.Path, outputFile, handBrakePreset); + var handBrakeFile = @"C:\Program Files (x86)\Handbrake\HandBrakeCLI.exe"; + + try + { + var process = new Process(); + process.StartInfo.FileName = handBrakeFile; + process.StartInfo.Arguments = handBrakeCommand; + process.StartInfo.UseShellExecute = false; + process.StartInfo.CreateNoWindow = true; + process.StartInfo.RedirectStandardOutput = true; + process.OutputDataReceived += new DataReceivedEventHandler(HandBrakeOutputDataReceived); + process.Start(); + process.BeginOutputReadLine(); + process.WaitForExit(); + } + + catch (Exception ex) + { + Logger.DebugException(ex.Message, ex); + return String.Empty; + } + + return outputFile; + } + + private void HandBrakeOutputDataReceived(object obj, DataReceivedEventArgs args) + { + throw new NotImplementedException(); + + //args.Data contains the line writen + + var match = _processingRegex.Matches(args.Data); + + if (match.Count != 1) + return; + + var episodeString = String.Format("{0} - {1}x{2:00}", + _currentEpisode.Series.Title, + _currentEpisode.SeasonNumber, + _currentEpisode.EpisodeNumber); + + var percent = System.Convert.ToDecimal(match[0].Groups["percent"].Value); + int hours; + int minutes; + int seconds; + + Int32.TryParse(match[0].Groups["hours"].Value, out hours); + Int32.TryParse(match[0].Groups["minutes"].Value, out minutes); + Int32.TryParse(match[0].Groups["seconds"].Value, out seconds); + + if (seconds > 0 || minutes > 0 || hours > 0) + { + var eta = DateTime.Now.Add(new TimeSpan(0, hours, minutes, seconds)); + _notification.CurrentMessage = String.Format("Converting: {0}, {1}%. ETA: {2}", episodeString, percent, eta); + } + + else + _notification.CurrentMessage = String.Format("Converting: {0}, {1}%.", episodeString, percent); + + Console.WriteLine(args.Data); + } + } +} diff --git a/NzbDrone.Core/Providers/Core/ConfigFileProvider.cs b/NzbDrone.Core/Providers/Core/ConfigFileProvider.cs index 193c126a3..e6fdc787a 100644 --- a/NzbDrone.Core/Providers/Core/ConfigFileProvider.cs +++ b/NzbDrone.Core/Providers/Core/ConfigFileProvider.cs @@ -5,29 +5,39 @@ using System.Linq; using System.Reflection; using System.Text; using System.Xml.Linq; +using NzbDrone.Core.Model; namespace NzbDrone.Core.Providers.Core { public class ConfigFileProvider { + private string _configFile = Path.Combine(CentralDispatch.AppPath, "App_Data", "Config.xml"); + public string ConfigFile { - get { return Path.Combine(CentralDispatch.AppPath, "App_Data", "Config.xml"); } + get { return _configFile; } + set { _configFile = value; } } public virtual int Port { - get { return GetValueInt("Port"); } + get { return GetValueInt("Port", 8989); } set { SetValue("Port", value); } } public virtual bool LaunchBrowser { - get { return GetValueBoolean("LaunchBrowser"); } + get { return GetValueBoolean("LaunchBrowser", true); } set { SetValue("LaunchBrowser", value); } } - public virtual string GetValue(string key, string parent = null) + public virtual AuthenticationType AuthenticationType + { + get { return (AuthenticationType)GetValueInt("AuthenticationType", 0); } + set { SetValue("AuthenticationType", (int)value); } + } + + public virtual string GetValue(string key, object defaultValue, string parent = null) { var xDoc = XDocument.Load(ConfigFile); var config = xDoc.Descendants("Config").Single(); @@ -35,21 +45,40 @@ namespace NzbDrone.Core.Providers.Core var parentContainer = config; if (!String.IsNullOrEmpty(parent)) + { + //Add the parent + if (config.Descendants(parent).Count() != 1) + { + SetValue(key, defaultValue, parent); + + //Reload the configFile + xDoc = XDocument.Load(ConfigFile); + config = xDoc.Descendants("Config").Single(); + } + parentContainer = config.Descendants(parent).Single(); + } + + var valueHolder = parentContainer.Descendants(key).ToList(); + + if (valueHolder.Count() == 1) + return valueHolder.First().Value; - var value = parentContainer.Descendants(key).Single().Value; + //Save the value + SetValue(key, defaultValue, parent); - return value; + //return the default value + return defaultValue.ToString(); } - public virtual int GetValueInt(string key, string parent = null) + public virtual int GetValueInt(string key, int defaultValue, string parent = null) { - return Convert.ToInt32(GetValue(key, parent)); + return Convert.ToInt32(GetValue(key, defaultValue, parent)); } - public virtual bool GetValueBoolean(string key, string parent = null) + public virtual bool GetValueBoolean(string key, bool defaultValue, string parent = null) { - return Convert.ToBoolean(GetValue(key, parent)); + return Convert.ToBoolean(GetValue(key, defaultValue, parent)); } public virtual void SetValue(string key, object value, string parent = null) @@ -60,9 +89,23 @@ namespace NzbDrone.Core.Providers.Core var parentContainer = config; if (!String.IsNullOrEmpty(parent)) + { + //Add the parent container if it doesn't already exist + if (config.Descendants(parent).Count() != 1) + { + config.Add(new XElement(parent)); + } + parentContainer = config.Descendants(parent).Single(); + } + + var keyHolder = parentContainer.Descendants(key); + + if (keyHolder.Count() != 1) + parentContainer.Add(new XElement(key, value)); - parentContainer.Descendants(key).Single().Value = value.ToString(); + else + parentContainer.Descendants(key).Single().Value = value.ToString(); xDoc.Save(ConfigFile); } @@ -82,11 +125,7 @@ namespace NzbDrone.Core.Providers.Core { var xDoc = new XDocument(new XDeclaration("1.0", "utf-8", "yes")); - xDoc.Add(new XElement("Config", - new XElement("Port", 8989), - new XElement("LaunchBrowser", true) - ) - ); + xDoc.Add(new XElement("Config")); xDoc.Save(ConfigFile); } diff --git a/NzbDrone.Core/Providers/Jobs/ConvertEpisodeJob.cs b/NzbDrone.Core/Providers/Jobs/ConvertEpisodeJob.cs new file mode 100644 index 000000000..5363fc3e9 --- /dev/null +++ b/NzbDrone.Core/Providers/Jobs/ConvertEpisodeJob.cs @@ -0,0 +1,53 @@ +using System; +using Ninject; +using NLog; +using NzbDrone.Core.Model.Notification; +using NzbDrone.Core.Providers.Converting; + +namespace NzbDrone.Core.Providers.Jobs +{ + public class ConvertEpisodeJob : IJob + { + private readonly HandbrakeProvider _handbrakeProvider; + private readonly AtomicParsleyProvider _atomicParsleyProvider; + private readonly EpisodeProvider _episodeProvider; + + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + + [Inject] + public ConvertEpisodeJob(HandbrakeProvider handbrakeProvider, AtomicParsleyProvider atomicParsleyProvider, + EpisodeProvider episodeProvider) + { + _handbrakeProvider = handbrakeProvider; + _atomicParsleyProvider = atomicParsleyProvider; + _episodeProvider = episodeProvider; + } + + public string Name + { + get { return "Convert Episode"; } + } + + public int DefaultInterval + { + get { return 0; } + } + + public void Start(ProgressNotification notification, int targetId, int secondaryTargetId) + { + if (targetId <= 0) + throw new ArgumentOutOfRangeException("targetId"); + + var episode = _episodeProvider.GetEpisode(targetId); + notification.CurrentMessage = String.Format("Starting Conversion for {0}", episode); + var outputFile = _handbrakeProvider.ConvertFile(episode, notification); + + if (String.IsNullOrEmpty(outputFile)) + notification.CurrentMessage = String.Format("Conversion failed for {0}", episode); + + _atomicParsleyProvider.RunAtomicParsley(episode, outputFile); + + notification.CurrentMessage = String.Format("Conversion completed for {0}", episode); + } + } +} \ No newline at end of file From f627b551fc23cc636a22911f7d66e92ec39ef63e Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Fri, 7 Oct 2011 16:24:28 -0700 Subject: [PATCH 2/3] AuthenticationType is now configurable from /Settings/System. --- NzbDrone.Web/Controllers/SettingsController.cs | 13 +++++++++++++ NzbDrone.Web/Models/SystemSettingsModel.cs | 8 ++++++++ NzbDrone.Web/Views/Settings/System.cshtml | 5 +++++ 3 files changed, 26 insertions(+) diff --git a/NzbDrone.Web/Controllers/SettingsController.cs b/NzbDrone.Web/Controllers/SettingsController.cs index 0620b792c..84bf6f023 100644 --- a/NzbDrone.Web/Controllers/SettingsController.cs +++ b/NzbDrone.Web/Controllers/SettingsController.cs @@ -189,9 +189,21 @@ namespace NzbDrone.Web.Controllers public ActionResult System() { + var selectedAuthenticationType = _configFileProvider.AuthenticationType; + var authenticationTypes = new List(); + + foreach (AuthenticationType authenticationType in Enum.GetValues(typeof(AuthenticationType))) + { + authenticationTypes.Add(authenticationType); + } + + var authTypeSelectList = new SelectList(authenticationTypes, selectedAuthenticationType); + var model = new SystemSettingsModel(); model.Port = _configFileProvider.Port; model.LaunchBrowser = _configFileProvider.LaunchBrowser; + model.AuthenticationType = selectedAuthenticationType; + model.AuthTypeSelectList = authTypeSelectList; return View(model); } @@ -455,6 +467,7 @@ namespace NzbDrone.Web.Controllers { _configFileProvider.Port = data.Port; _configFileProvider.LaunchBrowser = data.LaunchBrowser; + _configFileProvider.AuthenticationType = data.AuthenticationType; return GetSuccessResult(); } diff --git a/NzbDrone.Web/Models/SystemSettingsModel.cs b/NzbDrone.Web/Models/SystemSettingsModel.cs index 25615eb77..19a17791d 100644 --- a/NzbDrone.Web/Models/SystemSettingsModel.cs +++ b/NzbDrone.Web/Models/SystemSettingsModel.cs @@ -4,6 +4,8 @@ using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Web; +using System.Web.Mvc; +using NzbDrone.Core.Model; namespace NzbDrone.Web.Models { @@ -17,5 +19,11 @@ namespace NzbDrone.Web.Models [DisplayName("Launch Browser")] [Description("Start default webrowser when NzbDrone starts?")] public bool LaunchBrowser { get; set; } + + [DisplayName("Authentication")] + [Description("Secure the webserver with Authentication?")] + public AuthenticationType AuthenticationType { get; set; } + + public SelectList AuthTypeSelectList { get; set; } } } \ No newline at end of file diff --git a/NzbDrone.Web/Views/Settings/System.cshtml b/NzbDrone.Web/Views/Settings/System.cshtml index 2bfc9a5cb..7af233bd2 100644 --- a/NzbDrone.Web/Views/Settings/System.cshtml +++ b/NzbDrone.Web/Views/Settings/System.cshtml @@ -31,6 +31,11 @@ @Html.DescriptionFor(m => m.Port) @Html.TextBoxFor(m => m.Port, new { @class = "inputClass" }) + + + @Html.DropDownListFor(m => m.AuthenticationType, Model.AuthTypeSelectList, new { @class = "inputClass" }) } From e941aef9f2edc490a95dfbb84ebb8900785b4c2f Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Fri, 7 Oct 2011 17:17:46 -0700 Subject: [PATCH 3/3] Configuring the AuthenticationType from the WebUI will now work, just restart and NzbDrone will change the AuthenticationType on start. --- IISExpress/AppServer/applicationhost.config | 10 ++ NzbDrone/Model/AuthenticationType.cs | 13 +++ NzbDrone/NzbDrone.csproj | 2 + NzbDrone/Providers/ConfigProvider.cs | 110 ++++++++++++++++---- 4 files changed, 115 insertions(+), 20 deletions(-) create mode 100644 NzbDrone/Model/AuthenticationType.cs diff --git a/IISExpress/AppServer/applicationhost.config b/IISExpress/AppServer/applicationhost.config index 93f26b580..93879e48b 100644 --- a/IISExpress/AppServer/applicationhost.config +++ b/IISExpress/AppServer/applicationhost.config @@ -694,4 +694,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/NzbDrone/Model/AuthenticationType.cs b/NzbDrone/Model/AuthenticationType.cs new file mode 100644 index 000000000..243154383 --- /dev/null +++ b/NzbDrone/Model/AuthenticationType.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NzbDrone.Model +{ + public enum AuthenticationType + { + Anonymous = 0, + Windows = 1 + } +} diff --git a/NzbDrone/NzbDrone.csproj b/NzbDrone/NzbDrone.csproj index b7f3cdc3f..0a0f3c79a 100644 --- a/NzbDrone/NzbDrone.csproj +++ b/NzbDrone/NzbDrone.csproj @@ -86,6 +86,7 @@ + @@ -132,6 +133,7 @@ true + diff --git a/NzbDrone/Providers/ConfigProvider.cs b/NzbDrone/Providers/ConfigProvider.cs index fe1524da6..4b65078cf 100644 --- a/NzbDrone/Providers/ConfigProvider.cs +++ b/NzbDrone/Providers/ConfigProvider.cs @@ -6,6 +6,7 @@ using System.Xml.Linq; using System.Xml.XPath; using NLog; using NLog.Config; +using NzbDrone.Model; namespace NzbDrone.Providers { @@ -31,12 +32,12 @@ namespace NzbDrone.Providers public virtual int Port { - get { return GetValueInt("Port"); } + get { return GetValueInt("Port", 8989); } } public virtual bool LaunchBrowser { - get { return GetValueBoolean("LaunchBrowser"); } + get { return GetValueBoolean("LaunchBrowser", true); } } public virtual string AppDataDirectory @@ -64,6 +65,12 @@ namespace NzbDrone.Providers get { return Path.Combine(IISFolder, "AppServer", "applicationhost.config"); } } + public virtual AuthenticationType AuthenticationType + { + get { return (AuthenticationType)GetValueInt("AuthenticationType", 0); } + set { SetValue("AuthenticationType", (int)value); } + } + public virtual void ConfigureNlog() { LogManager.Configuration = new XmlLoggingConfiguration( @@ -93,6 +100,25 @@ namespace NzbDrone.Providers new XAttribute("bindingInformation", String.Format("*:{0}:", Port)) )); + //Update the authenticationTypes + + var location = configXml.XPathSelectElement("configuration").Elements("location").Where( + d => d.Attribute("path").Value.ToLowerInvariant() == "nzbdrone").First(); + + + var authenticationTypes = location.XPathSelectElements("system.webServer/security/authentication").First().Descendants(); + + //Set all authentication types enabled to false + foreach (var child in authenticationTypes) + { + child.Attribute("enabled").Value = "false"; + } + + var configuredAuthType = String.Format("{0}Authentication", AuthenticationType.ToString()).ToLowerInvariant(); + + //Set the users authenticationType to true + authenticationTypes.Where(t => t.Name.ToString().ToLowerInvariant() == configuredAuthType).Single().Attribute("enabled").Value = "true"; + configXml.Save(configPath); } @@ -107,42 +133,86 @@ namespace NzbDrone.Providers } } - public virtual void WriteDefaultConfig() + public virtual string GetValue(string key, object defaultValue, string parent = null) { - var xDoc = new XDocument(new XDeclaration("1.0", "utf-8", "yes")); + var xDoc = XDocument.Load(ConfigFile); + var config = xDoc.Descendants("Config").Single(); - xDoc.Add(new XElement("Config", - new XElement("Port", 8989), - new XElement("LaunchBrowser", true) - ) - ); + var parentContainer = config; - xDoc.Save(ConfigFile); + if (!String.IsNullOrEmpty(parent)) + { + //Add the parent + if (config.Descendants(parent).Count() != 1) + { + SetValue(key, defaultValue, parent); + + //Reload the configFile + xDoc = XDocument.Load(ConfigFile); + config = xDoc.Descendants("Config").Single(); + } + + parentContainer = config.Descendants(parent).Single(); + } + + var valueHolder = parentContainer.Descendants(key).ToList(); + + if (valueHolder.Count() == 1) + return valueHolder.First().Value; + + //Save the value + SetValue(key, defaultValue, parent); + + //return the default value + return defaultValue.ToString(); + } + + public virtual int GetValueInt(string key, int defaultValue, string parent = null) + { + return Convert.ToInt32(GetValue(key, defaultValue, parent)); + } + + public virtual bool GetValueBoolean(string key, bool defaultValue, string parent = null) + { + return Convert.ToBoolean(GetValue(key, defaultValue, parent)); } - private string GetValue(string key, string parent = null) + public virtual void SetValue(string key, object value, string parent = null) { var xDoc = XDocument.Load(ConfigFile); var config = xDoc.Descendants("Config").Single(); var parentContainer = config; - if (parent != null) + if (!String.IsNullOrEmpty(parent)) + { + //Add the parent container if it doesn't already exist + if (config.Descendants(parent).Count() != 1) + { + config.Add(new XElement(parent)); + } + parentContainer = config.Descendants(parent).Single(); + } - string value = parentContainer.Descendants(key).Single().Value; + var keyHolder = parentContainer.Descendants(key); - return value; - } + if (keyHolder.Count() != 1) + parentContainer.Add(new XElement(key, value)); - private int GetValueInt(string key, string parent = null) - { - return Convert.ToInt32(GetValue(key, parent)); + else + parentContainer.Descendants(key).Single().Value = value.ToString(); + + xDoc.Save(ConfigFile); } - private bool GetValueBoolean(string key, string parent = null) + public virtual void WriteDefaultConfig() { - return Convert.ToBoolean(GetValue(key, parent)); + var xDoc = new XDocument(new XDeclaration("1.0", "utf-8", "yes")); + + xDoc.Add(new XElement("Config")); + + xDoc.Save(ConfigFile); } } } \ No newline at end of file