2
0
Luke Pulverenti 8 жил өмнө
parent
commit
2729301bff
55 өөрчлөгдсөн 10785 нэмэгдсэн , 169 устгасан
  1. 773 0
      Emby.Common.Implementations/BaseApplicationHost.cs
  2. 178 0
      Emby.Common.Implementations/BaseApplicationPaths.cs
  3. 329 0
      Emby.Common.Implementations/Configuration/BaseConfigurationManager.cs
  4. 60 0
      Emby.Common.Implementations/Configuration/ConfigurationHelper.cs
  5. 30 0
      Emby.Common.Implementations/Cryptography/CryptographyProvider.cs
  6. 109 0
      Emby.Common.Implementations/Devices/DeviceId.cs
  7. 23 0
      Emby.Common.Implementations/Emby.Common.Implementations.xproj
  8. 16 0
      Emby.Common.Implementations/HttpClientManager/HttpClientInfo.cs
  9. 936 0
      Emby.Common.Implementations/HttpClientManager/HttpClientManager.cs
  10. 75 0
      Emby.Common.Implementations/IO/IsoManager.cs
  11. 705 0
      Emby.Common.Implementations/IO/ManagedFileSystem.cs
  12. 13 0
      Emby.Common.Implementations/IO/WindowsFileSystem.cs
  13. 385 0
      Emby.Common.Implementations/Networking/BaseNetworkManager.cs
  14. 19 0
      Emby.Common.Implementations/Properties/AssemblyInfo.cs
  15. 91 0
      Emby.Common.Implementations/ScheduledTasks/DailyTrigger.cs
  16. 112 0
      Emby.Common.Implementations/ScheduledTasks/IntervalTrigger.cs
  17. 782 0
      Emby.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
  18. 67 0
      Emby.Common.Implementations/ScheduledTasks/StartupTrigger.cs
  19. 86 0
      Emby.Common.Implementations/ScheduledTasks/SystemEventTrigger.cs
  20. 358 0
      Emby.Common.Implementations/ScheduledTasks/TaskManager.cs
  21. 215 0
      Emby.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs
  22. 138 0
      Emby.Common.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs
  23. 112 0
      Emby.Common.Implementations/ScheduledTasks/Tasks/ReloadLoggerFileTask.cs
  24. 116 0
      Emby.Common.Implementations/ScheduledTasks/WeeklyTrigger.cs
  25. 130 0
      Emby.Common.Implementations/Serialization/XmlSerializer.cs
  26. 269 0
      Emby.Common.Implementations/Updates/GithubUpdater.cs
  27. 39 0
      Emby.Common.Implementations/project.fragment.lock.json
  28. 48 0
      Emby.Common.Implementations/project.json
  29. 4403 0
      Emby.Common.Implementations/project.lock.json
  30. 7 19
      MediaBrowser.Common.Implementations/BaseApplicationHost.cs
  31. 6 6
      MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs
  32. 5 4
      MediaBrowser.Common.Implementations/Configuration/ConfigurationHelper.cs
  33. 10 1
      MediaBrowser.Common.Implementations/IO/ManagedFileSystem.cs
  34. 0 6
      MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj
  35. 4 4
      MediaBrowser.Common.Implementations/ScheduledTasks/DailyTrigger.cs
  36. 4 4
      MediaBrowser.Common.Implementations/ScheduledTasks/IntervalTrigger.cs
  37. 4 4
      MediaBrowser.Common.Implementations/ScheduledTasks/StartupTrigger.cs
  38. 7 10
      MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs
  39. 1 1
      MediaBrowser.Common.Implementations/ScheduledTasks/WeeklyTrigger.cs
  40. 0 13
      MediaBrowser.Common.Implementations/Security/MbAdmin.cs
  41. 0 14
      MediaBrowser.Common.Implementations/Security/SuppporterInfoResponse.cs
  42. 4 0
      MediaBrowser.Model/IO/IFileSystem.cs
  43. 1 0
      MediaBrowser.Model/MediaBrowser.Model.csproj
  44. 10 0
      MediaBrowser.Model/System/ISystemEvents.cs
  45. 4 0
      MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
  46. 3 3
      MediaBrowser.Server.Implementations/Security/MBLicenseFile.cs
  47. 19 14
      MediaBrowser.Server.Implementations/Security/PluginSecurityManager.cs
  48. 1 1
      MediaBrowser.Server.Implementations/Security/RegRecord.cs
  49. 15 16
      MediaBrowser.Server.Implementations/Updates/InstallationManager.cs
  50. 1 1
      MediaBrowser.Server.Mono/Program.cs
  51. 25 1
      MediaBrowser.Server.Startup.Common/ApplicationHost.cs
  52. 1 1
      MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj
  53. 0 44
      MediaBrowser.Server.Startup.Common/Migrations/MovieDbEpisodeProviderMigration.cs
  54. 34 0
      MediaBrowser.Server.Startup.Common/SystemEvents.cs
  55. 2 2
      MediaBrowser.ServerApplication/MainStartup.cs

+ 773 - 0
Emby.Common.Implementations/BaseApplicationHost.cs

@@ -0,0 +1,773 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Events;
+using Emby.Common.Implementations.Devices;
+using Emby.Common.Implementations.IO;
+using Emby.Common.Implementations.ScheduledTasks;
+using Emby.Common.Implementations.Serialization;
+using Emby.Common.Implementations.Updates;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Common.Plugins;
+using MediaBrowser.Common.Progress;
+using MediaBrowser.Common.Security;
+using MediaBrowser.Common.Updates;
+using MediaBrowser.Model.Events;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Serialization;
+using MediaBrowser.Model.Updates;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Common.Extensions;
+using Emby.Common.Implementations.Cryptography;
+using MediaBrowser.Common;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Model.Cryptography;
+using MediaBrowser.Model.System;
+using MediaBrowser.Model.Tasks;
+
+namespace Emby.Common.Implementations
+{
+    /// <summary>
+    /// Class BaseApplicationHost
+    /// </summary>
+    /// <typeparam name="TApplicationPathsType">The type of the T application paths type.</typeparam>
+    public abstract class BaseApplicationHost<TApplicationPathsType> : IApplicationHost
+        where TApplicationPathsType : class, IApplicationPaths
+    {
+        /// <summary>
+        /// Occurs when [has pending restart changed].
+        /// </summary>
+        public event EventHandler HasPendingRestartChanged;
+
+        /// <summary>
+        /// Occurs when [application updated].
+        /// </summary>
+        public event EventHandler<GenericEventArgs<PackageVersionInfo>> ApplicationUpdated;
+
+        /// <summary>
+        /// Gets or sets a value indicating whether this instance has changes that require the entire application to restart.
+        /// </summary>
+        /// <value><c>true</c> if this instance has pending application restart; otherwise, <c>false</c>.</value>
+        public bool HasPendingRestart { get; private set; }
+
+        /// <summary>
+        /// Gets or sets the logger.
+        /// </summary>
+        /// <value>The logger.</value>
+        protected ILogger Logger { get; private set; }
+
+        /// <summary>
+        /// Gets or sets the plugins.
+        /// </summary>
+        /// <value>The plugins.</value>
+        public IPlugin[] Plugins { get; protected set; }
+
+        /// <summary>
+        /// Gets or sets the log manager.
+        /// </summary>
+        /// <value>The log manager.</value>
+        public ILogManager LogManager { get; protected set; }
+
+        /// <summary>
+        /// Gets the application paths.
+        /// </summary>
+        /// <value>The application paths.</value>
+        protected TApplicationPathsType ApplicationPaths { get; private set; }
+
+        /// <summary>
+        /// The json serializer
+        /// </summary>
+        public IJsonSerializer JsonSerializer { get; private set; }
+
+        /// <summary>
+        /// The _XML serializer
+        /// </summary>
+        protected readonly IXmlSerializer XmlSerializer;
+
+        /// <summary>
+        /// Gets assemblies that failed to load
+        /// </summary>
+        /// <value>The failed assemblies.</value>
+        public List<string> FailedAssemblies { get; protected set; }
+
+        /// <summary>
+        /// Gets all concrete types.
+        /// </summary>
+        /// <value>All concrete types.</value>
+        public Type[] AllConcreteTypes { get; protected set; }
+
+        /// <summary>
+        /// The disposable parts
+        /// </summary>
+        protected readonly List<IDisposable> DisposableParts = new List<IDisposable>();
+
+        /// <summary>
+        /// Gets a value indicating whether this instance is first run.
+        /// </summary>
+        /// <value><c>true</c> if this instance is first run; otherwise, <c>false</c>.</value>
+        public bool IsFirstRun { get; private set; }
+
+        /// <summary>
+        /// Gets the kernel.
+        /// </summary>
+        /// <value>The kernel.</value>
+        protected ITaskManager TaskManager { get; private set; }
+        /// <summary>
+        /// Gets the HTTP client.
+        /// </summary>
+        /// <value>The HTTP client.</value>
+        public IHttpClient HttpClient { get; private set; }
+        /// <summary>
+        /// Gets the network manager.
+        /// </summary>
+        /// <value>The network manager.</value>
+        protected INetworkManager NetworkManager { get; private set; }
+
+        /// <summary>
+        /// Gets the configuration manager.
+        /// </summary>
+        /// <value>The configuration manager.</value>
+        protected IConfigurationManager ConfigurationManager { get; private set; }
+
+        protected IFileSystem FileSystemManager { get; private set; }
+
+        protected IIsoManager IsoManager { get; private set; }
+
+        protected ISystemEvents SystemEvents { get; private set; }
+
+        /// <summary>
+        /// Gets the name.
+        /// </summary>
+        /// <value>The name.</value>
+        public abstract string Name { get; }
+
+        /// <summary>
+        /// Gets a value indicating whether this instance is running as service.
+        /// </summary>
+        /// <value><c>true</c> if this instance is running as service; otherwise, <c>false</c>.</value>
+        public abstract bool IsRunningAsService { get; }
+
+        protected ICryptographyProvider CryptographyProvider = new CryptographyProvider();
+
+        private DeviceId _deviceId;
+        public string SystemId
+        {
+            get
+            {
+                if (_deviceId == null)
+                {
+                    _deviceId = new DeviceId(ApplicationPaths, LogManager.GetLogger("SystemId"), FileSystemManager);
+                }
+
+                return _deviceId.Value;
+            }
+        }
+
+        public virtual string OperatingSystemDisplayName
+        {
+            get { return Environment.OSVersion.VersionString; }
+        }
+
+        public IMemoryStreamProvider MemoryStreamProvider { get; set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BaseApplicationHost{TApplicationPathsType}"/> class.
+        /// </summary>
+        protected BaseApplicationHost(TApplicationPathsType applicationPaths,
+            ILogManager logManager,
+            IFileSystem fileSystem)
+        {
+            // hack alert, until common can target .net core
+            BaseExtensions.CryptographyProvider = CryptographyProvider;
+
+            XmlSerializer = new XmlSerializer(fileSystem, logManager.GetLogger("XmlSerializer"));
+            FailedAssemblies = new List<string>();
+
+            ApplicationPaths = applicationPaths;
+            LogManager = logManager;
+            FileSystemManager = fileSystem;
+
+            ConfigurationManager = GetConfigurationManager();
+
+            // Initialize this early in case the -v command line option is used
+            Logger = LogManager.GetLogger("App");
+        }
+
+        /// <summary>
+        /// Inits this instance.
+        /// </summary>
+        /// <returns>Task.</returns>
+        public virtual async Task Init(IProgress<double> progress)
+        {
+            progress.Report(1);
+
+            JsonSerializer = CreateJsonSerializer();
+
+            MemoryStreamProvider = CreateMemoryStreamProvider();
+            SystemEvents = CreateSystemEvents();
+
+            OnLoggerLoaded(true);
+            LogManager.LoggerLoaded += (s, e) => OnLoggerLoaded(false);
+
+            IsFirstRun = !ConfigurationManager.CommonConfiguration.IsStartupWizardCompleted;
+            progress.Report(2);
+
+            LogManager.LogSeverity = ConfigurationManager.CommonConfiguration.EnableDebugLevelLogging
+                                         ? LogSeverity.Debug
+                                         : LogSeverity.Info;
+
+            progress.Report(3);
+
+            DiscoverTypes();
+            progress.Report(14);
+
+            SetHttpLimit();
+            progress.Report(15);
+
+            var innerProgress = new ActionableProgress<double>();
+            innerProgress.RegisterAction(p => progress.Report(.8 * p + 15));
+
+            await RegisterResources(innerProgress).ConfigureAwait(false);
+
+            FindParts();
+            progress.Report(95);
+
+            await InstallIsoMounters(CancellationToken.None).ConfigureAwait(false);
+
+            progress.Report(100);
+        }
+
+        protected abstract IMemoryStreamProvider CreateMemoryStreamProvider();
+        protected abstract ISystemEvents CreateSystemEvents();
+
+        protected virtual void OnLoggerLoaded(bool isFirstLoad)
+        {
+            Logger.Info("Application version: {0}", ApplicationVersion);
+
+            if (!isFirstLoad)
+            {
+                LogEnvironmentInfo(Logger, ApplicationPaths, false);
+            }
+
+            // Put the app config in the log for troubleshooting purposes
+            Logger.LogMultiline("Application configuration:", LogSeverity.Info, new StringBuilder(JsonSerializer.SerializeToString(ConfigurationManager.CommonConfiguration)));
+
+            if (Plugins != null)
+            {
+                var pluginBuilder = new StringBuilder();
+
+                foreach (var plugin in Plugins)
+                {
+                    pluginBuilder.AppendLine(string.Format("{0} {1}", plugin.Name, plugin.Version));
+                }
+
+                Logger.LogMultiline("Plugins:", LogSeverity.Info, pluginBuilder);
+            }
+        }
+
+        public static void LogEnvironmentInfo(ILogger logger, IApplicationPaths appPaths, bool isStartup)
+        {
+            logger.LogMultiline("Emby", LogSeverity.Info, GetBaseExceptionMessage(appPaths));
+        }
+
+        protected static StringBuilder GetBaseExceptionMessage(IApplicationPaths appPaths)
+        {
+            var builder = new StringBuilder();
+
+            builder.AppendLine(string.Format("Command line: {0}", string.Join(" ", Environment.GetCommandLineArgs())));
+
+            builder.AppendLine(string.Format("Operating system: {0}", Environment.OSVersion));
+            builder.AppendLine(string.Format("Processor count: {0}", Environment.ProcessorCount));
+            builder.AppendLine(string.Format("64-Bit OS: {0}", Environment.Is64BitOperatingSystem));
+            builder.AppendLine(string.Format("64-Bit Process: {0}", Environment.Is64BitProcess));
+            builder.AppendLine(string.Format("Program data path: {0}", appPaths.ProgramDataPath));
+
+            Type type = Type.GetType("Mono.Runtime");
+            if (type != null)
+            {
+                MethodInfo displayName = type.GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static);
+                if (displayName != null)
+                {
+                    builder.AppendLine("Mono: " + displayName.Invoke(null, null));
+                }
+            }
+
+            builder.AppendLine(string.Format("Application Path: {0}", appPaths.ApplicationPath));
+
+            return builder;
+        }
+
+        protected abstract IJsonSerializer CreateJsonSerializer();
+
+        private void SetHttpLimit()
+        {
+            try
+            {
+                // Increase the max http request limit
+                ServicePointManager.DefaultConnectionLimit = Math.Max(96, ServicePointManager.DefaultConnectionLimit);
+            }
+            catch (Exception ex)
+            {
+                Logger.ErrorException("Error setting http limit", ex);
+            }
+        }
+
+        /// <summary>
+        /// Installs the iso mounters.
+        /// </summary>
+        /// <param name="cancellationToken">The cancellation token.</param>
+        /// <returns>Task.</returns>
+        private async Task InstallIsoMounters(CancellationToken cancellationToken)
+        {
+            var list = new List<IIsoMounter>();
+
+            foreach (var isoMounter in GetExports<IIsoMounter>())
+            {
+                try
+                {
+                    if (isoMounter.RequiresInstallation && !isoMounter.IsInstalled)
+                    {
+                        Logger.Info("Installing {0}", isoMounter.Name);
+
+                        await isoMounter.Install(cancellationToken).ConfigureAwait(false);
+                    }
+
+                    list.Add(isoMounter);
+                }
+                catch (Exception ex)
+                {
+                    Logger.ErrorException("{0} failed to load.", ex, isoMounter.Name);
+                }
+            }
+
+            IsoManager.AddParts(list);
+        }
+
+        /// <summary>
+        /// Runs the startup tasks.
+        /// </summary>
+        /// <returns>Task.</returns>
+        public virtual Task RunStartupTasks()
+        {
+            Resolve<ITaskManager>().AddTasks(GetExports<IScheduledTask>(false));
+
+            ConfigureAutorun();
+
+            ConfigurationManager.ConfigurationUpdated += OnConfigurationUpdated;
+
+            return Task.FromResult(true);
+        }
+
+        /// <summary>
+        /// Configures the autorun.
+        /// </summary>
+        private void ConfigureAutorun()
+        {
+            try
+            {
+                ConfigureAutoRunAtStartup(ConfigurationManager.CommonConfiguration.RunAtStartup);
+            }
+            catch (Exception ex)
+            {
+                Logger.ErrorException("Error configuring autorun", ex);
+            }
+        }
+
+        /// <summary>
+        /// Gets the composable part assemblies.
+        /// </summary>
+        /// <returns>IEnumerable{Assembly}.</returns>
+        protected abstract IEnumerable<Assembly> GetComposablePartAssemblies();
+
+        /// <summary>
+        /// Gets the configuration manager.
+        /// </summary>
+        /// <returns>IConfigurationManager.</returns>
+        protected abstract IConfigurationManager GetConfigurationManager();
+
+        /// <summary>
+        /// Finds the parts.
+        /// </summary>
+        protected virtual void FindParts()
+        {
+            ConfigurationManager.AddParts(GetExports<IConfigurationFactory>());
+            Plugins = GetExports<IPlugin>().Select(LoadPlugin).Where(i => i != null).ToArray();
+        }
+
+        private IPlugin LoadPlugin(IPlugin plugin)
+        {
+            try
+            {
+                var assemblyPlugin = plugin as IPluginAssembly;
+
+                if (assemblyPlugin != null)
+                {
+                    var assembly = plugin.GetType().Assembly;
+                    var assemblyName = assembly.GetName();
+
+                    var attribute = (GuidAttribute)assembly.GetCustomAttributes(typeof(GuidAttribute), true)[0];
+                    var assemblyId = new Guid(attribute.Value);
+
+                    var assemblyFileName = assemblyName.Name + ".dll";
+                    var assemblyFilePath = Path.Combine(ApplicationPaths.PluginsPath, assemblyFileName);
+
+                    assemblyPlugin.SetAttributes(assemblyFilePath, assemblyFileName, assemblyName.Version, assemblyId);
+                }
+
+                var isFirstRun = !File.Exists(plugin.ConfigurationFilePath);
+
+                plugin.SetStartupInfo(isFirstRun, File.GetLastWriteTimeUtc, s => Directory.CreateDirectory(s));
+            }
+            catch (Exception ex)
+            {
+                Logger.ErrorException("Error loading plugin {0}", ex, plugin.GetType().FullName);
+                return null;
+            }
+
+            return plugin;
+        }
+
+        /// <summary>
+        /// Discovers the types.
+        /// </summary>
+        protected void DiscoverTypes()
+        {
+            FailedAssemblies.Clear();
+
+            var assemblies = GetComposablePartAssemblies().ToList();
+
+            foreach (var assembly in assemblies)
+            {
+                Logger.Info("Loading {0}", assembly.FullName);
+            }
+
+            AllConcreteTypes = assemblies
+                .SelectMany(GetTypes)
+                .Where(t => t.IsClass && !t.IsAbstract && !t.IsInterface && !t.IsGenericType)
+                .ToArray();
+        }
+
+        /// <summary>
+        /// Registers resources that classes will depend on
+        /// </summary>
+        /// <returns>Task.</returns>
+        protected virtual Task RegisterResources(IProgress<double> progress)
+        {
+            RegisterSingleInstance(ConfigurationManager);
+            RegisterSingleInstance<IApplicationHost>(this);
+
+            RegisterSingleInstance<IApplicationPaths>(ApplicationPaths);
+
+            TaskManager = new TaskManager(ApplicationPaths, JsonSerializer, LogManager.GetLogger("TaskManager"), FileSystemManager, SystemEvents);
+
+            RegisterSingleInstance(JsonSerializer);
+            RegisterSingleInstance(XmlSerializer);
+            RegisterSingleInstance(MemoryStreamProvider);
+            RegisterSingleInstance(SystemEvents);
+
+            RegisterSingleInstance(LogManager);
+            RegisterSingleInstance(Logger);
+
+            RegisterSingleInstance(TaskManager);
+
+            RegisterSingleInstance(FileSystemManager);
+
+            HttpClient = new HttpClientManager.HttpClientManager(ApplicationPaths, LogManager.GetLogger("HttpClient"), FileSystemManager, MemoryStreamProvider);
+            RegisterSingleInstance(HttpClient);
+
+            NetworkManager = CreateNetworkManager(LogManager.GetLogger("NetworkManager"));
+            RegisterSingleInstance(NetworkManager);
+
+            IsoManager = new IsoManager();
+            RegisterSingleInstance(IsoManager);
+
+            return Task.FromResult(true);
+        }
+
+        /// <summary>
+        /// Gets a list of types within an assembly
+        /// This will handle situations that would normally throw an exception - such as a type within the assembly that depends on some other non-existant reference
+        /// </summary>
+        /// <param name="assembly">The assembly.</param>
+        /// <returns>IEnumerable{Type}.</returns>
+        /// <exception cref="System.ArgumentNullException">assembly</exception>
+        protected IEnumerable<Type> GetTypes(Assembly assembly)
+        {
+            if (assembly == null)
+            {
+                throw new ArgumentNullException("assembly");
+            }
+
+            try
+            {
+                return assembly.GetTypes();
+            }
+            catch (ReflectionTypeLoadException ex)
+            {
+                if (ex.LoaderExceptions != null)
+                {
+                    foreach (var loaderException in ex.LoaderExceptions)
+                    {
+                        Logger.Error("LoaderException: " + loaderException.Message);
+                    }
+                }
+
+                // If it fails we can still get a list of the Types it was able to resolve
+                return ex.Types.Where(t => t != null);
+            }
+        }
+
+        protected abstract INetworkManager CreateNetworkManager(ILogger logger);
+
+        /// <summary>
+        /// Creates an instance of type and resolves all constructor dependancies
+        /// </summary>
+        /// <param name="type">The type.</param>
+        /// <returns>System.Object.</returns>
+        public abstract object CreateInstance(Type type);
+
+        /// <summary>
+        /// Creates the instance safe.
+        /// </summary>
+        /// <param name="type">The type.</param>
+        /// <returns>System.Object.</returns>
+        protected abstract object CreateInstanceSafe(Type type);
+
+        /// <summary>
+        /// Registers the specified obj.
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="obj">The obj.</param>
+        /// <param name="manageLifetime">if set to <c>true</c> [manage lifetime].</param>
+        protected abstract void RegisterSingleInstance<T>(T obj, bool manageLifetime = true)
+            where T : class;
+
+        /// <summary>
+        /// Registers the single instance.
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="func">The func.</param>
+        protected abstract void RegisterSingleInstance<T>(Func<T> func)
+            where T : class;
+
+        /// <summary>
+        /// Resolves this instance.
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <returns>``0.</returns>
+        public abstract T Resolve<T>();
+
+        /// <summary>
+        /// Resolves this instance.
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <returns>``0.</returns>
+        public abstract T TryResolve<T>();
+
+        /// <summary>
+        /// Loads the assembly.
+        /// </summary>
+        /// <param name="file">The file.</param>
+        /// <returns>Assembly.</returns>
+        protected Assembly LoadAssembly(string file)
+        {
+            try
+            {
+                return Assembly.Load(File.ReadAllBytes(file));
+            }
+            catch (Exception ex)
+            {
+                FailedAssemblies.Add(file);
+                Logger.ErrorException("Error loading assembly {0}", ex, file);
+                return null;
+            }
+        }
+
+        /// <summary>
+        /// Gets the export types.
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <returns>IEnumerable{Type}.</returns>
+        public IEnumerable<Type> GetExportTypes<T>()
+        {
+            var currentType = typeof(T);
+
+            return AllConcreteTypes.AsParallel().Where(currentType.IsAssignableFrom);
+        }
+
+        /// <summary>
+        /// Gets the exports.
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="manageLiftime">if set to <c>true</c> [manage liftime].</param>
+        /// <returns>IEnumerable{``0}.</returns>
+        public IEnumerable<T> GetExports<T>(bool manageLiftime = true)
+        {
+            var parts = GetExportTypes<T>()
+                .Select(CreateInstanceSafe)
+                .Where(i => i != null)
+                .Cast<T>()
+                .ToList();
+
+            if (manageLiftime)
+            {
+                lock (DisposableParts)
+                {
+                    DisposableParts.AddRange(parts.OfType<IDisposable>());
+                }
+            }
+
+            return parts;
+        }
+
+        /// <summary>
+        /// Gets the application version.
+        /// </summary>
+        /// <value>The application version.</value>
+        public abstract Version ApplicationVersion { get; }
+
+        /// <summary>
+        /// Handles the ConfigurationUpdated event of the ConfigurationManager control.
+        /// </summary>
+        /// <param name="sender">The source of the event.</param>
+        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
+        /// <exception cref="System.NotImplementedException"></exception>
+        protected virtual void OnConfigurationUpdated(object sender, EventArgs e)
+        {
+            ConfigureAutorun();
+        }
+
+        protected abstract void ConfigureAutoRunAtStartup(bool autorun);
+
+        /// <summary>
+        /// Removes the plugin.
+        /// </summary>
+        /// <param name="plugin">The plugin.</param>
+        public void RemovePlugin(IPlugin plugin)
+        {
+            var list = Plugins.ToList();
+            list.Remove(plugin);
+            Plugins = list.ToArray();
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this instance can self restart.
+        /// </summary>
+        /// <value><c>true</c> if this instance can self restart; otherwise, <c>false</c>.</value>
+        public abstract bool CanSelfRestart { get; }
+
+        /// <summary>
+        /// Notifies that the kernel that a change has been made that requires a restart
+        /// </summary>
+        public void NotifyPendingRestart()
+        {
+            var changed = !HasPendingRestart;
+
+            HasPendingRestart = true;
+
+            if (changed)
+            {
+                EventHelper.QueueEventIfNotNull(HasPendingRestartChanged, this, EventArgs.Empty, Logger);
+            }
+        }
+
+        /// <summary>
+        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+        /// </summary>
+        public void Dispose()
+        {
+            Dispose(true);
+        }
+
+        /// <summary>
+        /// Releases unmanaged and - optionally - managed resources.
+        /// </summary>
+        /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+        protected virtual void Dispose(bool dispose)
+        {
+            if (dispose)
+            {
+                var type = GetType();
+
+                Logger.Info("Disposing " + type.Name);
+
+                var parts = DisposableParts.Distinct().Where(i => i.GetType() != type).ToList();
+                DisposableParts.Clear();
+
+                foreach (var part in parts)
+                {
+                    Logger.Info("Disposing " + part.GetType().Name);
+
+                    try
+                    {
+                        part.Dispose();
+                    }
+                    catch (Exception ex)
+                    {
+                        Logger.ErrorException("Error disposing {0}", ex, part.GetType().Name);
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// Restarts this instance.
+        /// </summary>
+        public abstract Task Restart();
+
+        /// <summary>
+        /// Gets or sets a value indicating whether this instance can self update.
+        /// </summary>
+        /// <value><c>true</c> if this instance can self update; otherwise, <c>false</c>.</value>
+        public abstract bool CanSelfUpdate { get; }
+
+        /// <summary>
+        /// Checks for update.
+        /// </summary>
+        /// <param name="cancellationToken">The cancellation token.</param>
+        /// <param name="progress">The progress.</param>
+        /// <returns>Task{CheckForUpdateResult}.</returns>
+        public abstract Task<CheckForUpdateResult> CheckForApplicationUpdate(CancellationToken cancellationToken,
+                                                                          IProgress<double> progress);
+
+        /// <summary>
+        /// Updates the application.
+        /// </summary>
+        /// <param name="package">The package that contains the update</param>
+        /// <param name="cancellationToken">The cancellation token.</param>
+        /// <param name="progress">The progress.</param>
+        /// <returns>Task.</returns>
+        public abstract Task UpdateApplication(PackageVersionInfo package, CancellationToken cancellationToken,
+                                            IProgress<double> progress);
+
+        /// <summary>
+        /// Shuts down.
+        /// </summary>
+        public abstract Task Shutdown();
+
+        /// <summary>
+        /// Called when [application updated].
+        /// </summary>
+        /// <param name="package">The package.</param>
+        protected void OnApplicationUpdated(PackageVersionInfo package)
+        {
+            Logger.Info("Application has been updated to version {0}", package.versionStr);
+
+            EventHelper.FireEventIfNotNull(ApplicationUpdated, this, new GenericEventArgs<PackageVersionInfo>
+            {
+                Argument = package
+
+            }, Logger);
+
+            NotifyPendingRestart();
+        }
+    }
+}

+ 178 - 0
Emby.Common.Implementations/BaseApplicationPaths.cs

@@ -0,0 +1,178 @@
+using System.IO;
+using MediaBrowser.Common.Configuration;
+
+namespace Emby.Common.Implementations
+{
+    /// <summary>
+    /// Provides a base class to hold common application paths used by both the Ui and Server.
+    /// This can be subclassed to add application-specific paths.
+    /// </summary>
+    public abstract class BaseApplicationPaths : IApplicationPaths
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BaseApplicationPaths"/> class.
+        /// </summary>
+        protected BaseApplicationPaths(string programDataPath, string applicationPath)
+        {
+            ProgramDataPath = programDataPath;
+            ApplicationPath = applicationPath;
+        }
+
+        public string ApplicationPath { get; private set; }
+        public string ProgramDataPath { get; private set; }
+
+        /// <summary>
+        /// Gets the path to the system folder
+        /// </summary>
+        public string ProgramSystemPath
+        {
+            get { return Path.GetDirectoryName(ApplicationPath); }
+        }
+
+        /// <summary>
+        /// The _data directory
+        /// </summary>
+        private string _dataDirectory;
+        /// <summary>
+        /// Gets the folder path to the data directory
+        /// </summary>
+        /// <value>The data directory.</value>
+        public string DataPath
+        {
+            get
+            {
+                if (_dataDirectory == null)
+                {
+                    _dataDirectory = Path.Combine(ProgramDataPath, "data");
+
+                    Directory.CreateDirectory(_dataDirectory);
+                }
+
+                return _dataDirectory;
+            }
+        }
+
+        /// <summary>
+        /// Gets the image cache path.
+        /// </summary>
+        /// <value>The image cache path.</value>
+        public string ImageCachePath
+        {
+            get
+            {
+                return Path.Combine(CachePath, "images");
+            }
+        }
+
+        /// <summary>
+        /// Gets the path to the plugin directory
+        /// </summary>
+        /// <value>The plugins path.</value>
+        public string PluginsPath
+        {
+            get
+            {
+                return Path.Combine(ProgramDataPath, "plugins");
+            }
+        }
+
+        /// <summary>
+        /// Gets the path to the plugin configurations directory
+        /// </summary>
+        /// <value>The plugin configurations path.</value>
+        public string PluginConfigurationsPath
+        {
+            get
+            {
+                return Path.Combine(PluginsPath, "configurations");
+            }
+        }
+
+        /// <summary>
+        /// Gets the path to where temporary update files will be stored
+        /// </summary>
+        /// <value>The plugin configurations path.</value>
+        public string TempUpdatePath
+        {
+            get
+            {
+                return Path.Combine(ProgramDataPath, "updates");
+            }
+        }
+
+        /// <summary>
+        /// Gets the path to the log directory
+        /// </summary>
+        /// <value>The log directory path.</value>
+        public string LogDirectoryPath
+        {
+            get
+            {
+                return Path.Combine(ProgramDataPath, "logs");
+            }
+        }
+
+        /// <summary>
+        /// Gets the path to the application configuration root directory
+        /// </summary>
+        /// <value>The configuration directory path.</value>
+        public string ConfigurationDirectoryPath
+        {
+            get
+            {
+                return Path.Combine(ProgramDataPath, "config");
+            }
+        }
+
+        /// <summary>
+        /// Gets the path to the system configuration file
+        /// </summary>
+        /// <value>The system configuration file path.</value>
+        public string SystemConfigurationFilePath
+        {
+            get
+            {
+                return Path.Combine(ConfigurationDirectoryPath, "system.xml");
+            }
+        }
+
+        /// <summary>
+        /// The _cache directory
+        /// </summary>
+        private string _cachePath;
+        /// <summary>
+        /// Gets the folder path to the cache directory
+        /// </summary>
+        /// <value>The cache directory.</value>
+        public string CachePath
+        {
+            get
+            {
+                if (string.IsNullOrEmpty(_cachePath))
+                {
+                    _cachePath = Path.Combine(ProgramDataPath, "cache");
+
+                    Directory.CreateDirectory(_cachePath);
+                }
+
+                return _cachePath;
+            }
+            set
+            {
+                _cachePath = value;
+            }
+        }
+
+        /// <summary>
+        /// Gets the folder path to the temp directory within the cache folder
+        /// </summary>
+        /// <value>The temp directory.</value>
+        public string TempDirectory
+        {
+            get
+            {
+                return Path.Combine(CachePath, "temp");
+            }
+        }
+    }
+}

+ 329 - 0
Emby.Common.Implementations/Configuration/BaseConfigurationManager.cs

@@ -0,0 +1,329 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Events;
+using MediaBrowser.Common.Extensions;
+using Emby.Common.Implementations;
+using MediaBrowser.Model.Configuration;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Serialization;
+
+namespace Emby.Common.Implementations.Configuration
+{
+    /// <summary>
+    /// Class BaseConfigurationManager
+    /// </summary>
+    public abstract class BaseConfigurationManager : IConfigurationManager
+    {
+        /// <summary>
+        /// Gets the type of the configuration.
+        /// </summary>
+        /// <value>The type of the configuration.</value>
+        protected abstract Type ConfigurationType { get; }
+
+        /// <summary>
+        /// Occurs when [configuration updated].
+        /// </summary>
+        public event EventHandler<EventArgs> ConfigurationUpdated;
+
+        /// <summary>
+        /// Occurs when [configuration updating].
+        /// </summary>
+        public event EventHandler<ConfigurationUpdateEventArgs> NamedConfigurationUpdating;
+
+        /// <summary>
+        /// Occurs when [named configuration updated].
+        /// </summary>
+        public event EventHandler<ConfigurationUpdateEventArgs> NamedConfigurationUpdated;
+
+        /// <summary>
+        /// Gets the logger.
+        /// </summary>
+        /// <value>The logger.</value>
+        protected ILogger Logger { get; private set; }
+        /// <summary>
+        /// Gets the XML serializer.
+        /// </summary>
+        /// <value>The XML serializer.</value>
+        protected IXmlSerializer XmlSerializer { get; private set; }
+
+        /// <summary>
+        /// Gets or sets the application paths.
+        /// </summary>
+        /// <value>The application paths.</value>
+        public IApplicationPaths CommonApplicationPaths { get; private set; }
+        public readonly IFileSystem FileSystem;
+
+        /// <summary>
+        /// The _configuration loaded
+        /// </summary>
+        private bool _configurationLoaded;
+        /// <summary>
+        /// The _configuration sync lock
+        /// </summary>
+        private object _configurationSyncLock = new object();
+        /// <summary>
+        /// The _configuration
+        /// </summary>
+        private BaseApplicationConfiguration _configuration;
+        /// <summary>
+        /// Gets the system configuration
+        /// </summary>
+        /// <value>The configuration.</value>
+        public BaseApplicationConfiguration CommonConfiguration
+        {
+            get
+            {
+                // Lazy load
+                LazyInitializer.EnsureInitialized(ref _configuration, ref _configurationLoaded, ref _configurationSyncLock, () => (BaseApplicationConfiguration)ConfigurationHelper.GetXmlConfiguration(ConfigurationType, CommonApplicationPaths.SystemConfigurationFilePath, XmlSerializer, FileSystem));
+                return _configuration;
+            }
+            protected set
+            {
+                _configuration = value;
+
+                _configurationLoaded = value != null;
+            }
+        }
+
+        private ConfigurationStore[] _configurationStores = { };
+        private IConfigurationFactory[] _configurationFactories = { };
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BaseConfigurationManager" /> class.
+        /// </summary>
+        /// <param name="applicationPaths">The application paths.</param>
+        /// <param name="logManager">The log manager.</param>
+        /// <param name="xmlSerializer">The XML serializer.</param>
+        protected BaseConfigurationManager(IApplicationPaths applicationPaths, ILogManager logManager, IXmlSerializer xmlSerializer, IFileSystem fileSystem)
+        {
+            CommonApplicationPaths = applicationPaths;
+            XmlSerializer = xmlSerializer;
+            FileSystem = fileSystem;
+            Logger = logManager.GetLogger(GetType().Name);
+
+            UpdateCachePath();
+        }
+
+        public virtual void AddParts(IEnumerable<IConfigurationFactory> factories)
+        {
+            _configurationFactories = factories.ToArray();
+
+            _configurationStores = _configurationFactories
+                .SelectMany(i => i.GetConfigurations())
+                .ToArray();
+        }
+
+        /// <summary>
+        /// Saves the configuration.
+        /// </summary>
+        public void SaveConfiguration()
+        {
+            Logger.Info("Saving system configuration");
+            var path = CommonApplicationPaths.SystemConfigurationFilePath;
+
+            FileSystem.CreateDirectory(Path.GetDirectoryName(path));
+
+            lock (_configurationSyncLock)
+            {
+                XmlSerializer.SerializeToFile(CommonConfiguration, path);
+            }
+
+            OnConfigurationUpdated();
+        }
+
+        /// <summary>
+        /// Called when [configuration updated].
+        /// </summary>
+        protected virtual void OnConfigurationUpdated()
+        {
+            UpdateCachePath();
+
+            EventHelper.QueueEventIfNotNull(ConfigurationUpdated, this, EventArgs.Empty, Logger);
+        }
+
+        /// <summary>
+        /// Replaces the configuration.
+        /// </summary>
+        /// <param name="newConfiguration">The new configuration.</param>
+        /// <exception cref="System.ArgumentNullException">newConfiguration</exception>
+        public virtual void ReplaceConfiguration(BaseApplicationConfiguration newConfiguration)
+        {
+            if (newConfiguration == null)
+            {
+                throw new ArgumentNullException("newConfiguration");
+            }
+
+            ValidateCachePath(newConfiguration);
+
+            CommonConfiguration = newConfiguration;
+            SaveConfiguration();
+        }
+
+        /// <summary>
+        /// Updates the items by name path.
+        /// </summary>
+        private void UpdateCachePath()
+        {
+            string cachePath;
+
+            if (string.IsNullOrWhiteSpace(CommonConfiguration.CachePath))
+            {
+                cachePath = null;
+            }
+            else
+            {
+                cachePath = Path.Combine(CommonConfiguration.CachePath, "cache");
+            }
+
+            ((BaseApplicationPaths)CommonApplicationPaths).CachePath = cachePath;
+        }
+
+        /// <summary>
+        /// Replaces the cache path.
+        /// </summary>
+        /// <param name="newConfig">The new configuration.</param>
+        /// <exception cref="System.IO.DirectoryNotFoundException"></exception>
+        private void ValidateCachePath(BaseApplicationConfiguration newConfig)
+        {
+            var newPath = newConfig.CachePath;
+
+            if (!string.IsNullOrWhiteSpace(newPath)
+                && !string.Equals(CommonConfiguration.CachePath ?? string.Empty, newPath))
+            {
+                // Validate
+                if (!FileSystem.DirectoryExists(newPath))
+                {
+                    throw new FileNotFoundException(string.Format("{0} does not exist.", newPath));
+                }
+
+                EnsureWriteAccess(newPath);
+            }
+        }
+
+        protected void EnsureWriteAccess(string path)
+        {
+            var file = Path.Combine(path, Guid.NewGuid().ToString());
+
+            FileSystem.WriteAllText(file, string.Empty);
+            FileSystem.DeleteFile(file);
+        }
+
+        private readonly ConcurrentDictionary<string, object> _configurations = new ConcurrentDictionary<string, object>();
+
+        private string GetConfigurationFile(string key)
+        {
+            return Path.Combine(CommonApplicationPaths.ConfigurationDirectoryPath, key.ToLower() + ".xml");
+        }
+
+        public object GetConfiguration(string key)
+        {
+            return _configurations.GetOrAdd(key, k =>
+            {
+                var file = GetConfigurationFile(key);
+
+                var configurationInfo = _configurationStores
+                    .FirstOrDefault(i => string.Equals(i.Key, key, StringComparison.OrdinalIgnoreCase));
+
+                if (configurationInfo == null)
+                {
+                    throw new ResourceNotFoundException("Configuration with key " + key + " not found.");
+                }
+
+                var configurationType = configurationInfo.ConfigurationType;
+
+                lock (_configurationSyncLock)
+                {
+                    return LoadConfiguration(file, configurationType);
+                }
+            });
+        }
+
+        private object LoadConfiguration(string path, Type configurationType)
+        {
+            try
+            {
+                return XmlSerializer.DeserializeFromFile(configurationType, path);
+            }
+            catch (FileNotFoundException)
+            {
+                return Activator.CreateInstance(configurationType);
+            }
+            catch (IOException)
+            {
+                return Activator.CreateInstance(configurationType);
+            }
+            catch (Exception ex)
+            {
+                Logger.ErrorException("Error loading configuration file: {0}", ex, path);
+
+                return Activator.CreateInstance(configurationType);
+            }
+        }
+
+        public void SaveConfiguration(string key, object configuration)
+        {
+            var configurationStore = GetConfigurationStore(key);
+            var configurationType = configurationStore.ConfigurationType;
+
+            if (configuration.GetType() != configurationType)
+            {
+                throw new ArgumentException("Expected configuration type is " + configurationType.Name);
+            }
+
+            var validatingStore = configurationStore as IValidatingConfiguration;
+            if (validatingStore != null)
+            {
+                var currentConfiguration = GetConfiguration(key);
+
+                validatingStore.Validate(currentConfiguration, configuration);
+            }
+
+            EventHelper.FireEventIfNotNull(NamedConfigurationUpdating, this, new ConfigurationUpdateEventArgs
+            {
+                Key = key,
+                NewConfiguration = configuration
+
+            }, Logger);
+
+            _configurations.AddOrUpdate(key, configuration, (k, v) => configuration);
+
+            var path = GetConfigurationFile(key);
+            FileSystem.CreateDirectory(Path.GetDirectoryName(path));
+
+            lock (_configurationSyncLock)
+            {
+                XmlSerializer.SerializeToFile(configuration, path);
+            }
+
+            OnNamedConfigurationUpdated(key, configuration);
+        }
+
+        protected virtual void OnNamedConfigurationUpdated(string key, object configuration)
+        {
+            EventHelper.FireEventIfNotNull(NamedConfigurationUpdated, this, new ConfigurationUpdateEventArgs
+            {
+                Key = key,
+                NewConfiguration = configuration
+
+            }, Logger);
+        }
+
+        public Type GetConfigurationType(string key)
+        {
+            return GetConfigurationStore(key)
+                .ConfigurationType;
+        }
+
+        private ConfigurationStore GetConfigurationStore(string key)
+        {
+            return _configurationStores
+                .First(i => string.Equals(i.Key, key, StringComparison.OrdinalIgnoreCase));
+        }
+    }
+}

+ 60 - 0
Emby.Common.Implementations/Configuration/ConfigurationHelper.cs

@@ -0,0 +1,60 @@
+using System;
+using System.IO;
+using System.Linq;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Serialization;
+
+namespace Emby.Common.Implementations.Configuration
+{
+    /// <summary>
+    /// Class ConfigurationHelper
+    /// </summary>
+    public static class ConfigurationHelper
+    {
+        /// <summary>
+        /// Reads an xml configuration file from the file system
+        /// It will immediately re-serialize and save if new serialization data is available due to property changes
+        /// </summary>
+        /// <param name="type">The type.</param>
+        /// <param name="path">The path.</param>
+        /// <param name="xmlSerializer">The XML serializer.</param>
+        /// <returns>System.Object.</returns>
+        public static object GetXmlConfiguration(Type type, string path, IXmlSerializer xmlSerializer, IFileSystem fileSystem)
+        {
+            object configuration;
+
+            byte[] buffer = null;
+
+            // Use try/catch to avoid the extra file system lookup using File.Exists
+            try
+            {
+                buffer = fileSystem.ReadAllBytes(path);
+
+                configuration = xmlSerializer.DeserializeFromBytes(type, buffer);
+            }
+            catch (Exception)
+            {
+                configuration = Activator.CreateInstance(type);
+            }
+
+            using (var stream = new MemoryStream())
+            {
+                xmlSerializer.SerializeToStream(configuration, stream);
+
+                // Take the object we just got and serialize it back to bytes
+                var newBytes = stream.ToArray();
+
+                // If the file didn't exist before, or if something has changed, re-save
+                if (buffer == null || !buffer.SequenceEqual(newBytes))
+                {
+                    fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+
+                    // Save it after load in case we got new items
+                    fileSystem.WriteAllBytes(path, newBytes);
+                }
+
+                return configuration;
+            }
+        }
+    }
+}

+ 30 - 0
Emby.Common.Implementations/Cryptography/CryptographyProvider.cs

@@ -0,0 +1,30 @@
+using System;
+using System.IO;
+using System.Security.Cryptography;
+using System.Text;
+using MediaBrowser.Model.Cryptography;
+
+namespace Emby.Common.Implementations.Cryptography
+{
+    public class CryptographyProvider : ICryptographyProvider
+    {
+        public Guid GetMD5(string str)
+        {
+            return new Guid(GetMD5Bytes(str));
+        }
+        public byte[] GetMD5Bytes(string str)
+        {
+            using (var provider = MD5.Create())
+            {
+                return provider.ComputeHash(Encoding.Unicode.GetBytes(str));
+            }
+        }
+        public byte[] GetMD5Bytes(Stream str)
+        {
+            using (var provider = MD5.Create())
+            {
+                return provider.ComputeHash(str);
+            }
+        }
+    }
+}

+ 109 - 0
Emby.Common.Implementations/Devices/DeviceId.cs

@@ -0,0 +1,109 @@
+using System;
+using System.IO;
+using System.Text;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Logging;
+
+namespace Emby.Common.Implementations.Devices
+{
+    public class DeviceId
+    {
+        private readonly IApplicationPaths _appPaths;
+		private readonly ILogger _logger;
+		private readonly IFileSystem _fileSystem;
+
+        private readonly object _syncLock = new object();
+
+        private string CachePath
+        {
+            get { return Path.Combine(_appPaths.DataPath, "device.txt"); }
+        }
+
+        private string GetCachedId()
+        {
+            try
+            {
+                lock (_syncLock)
+                {
+					var value = File.ReadAllText(CachePath, Encoding.UTF8);
+
+                    Guid guid;
+                    if (Guid.TryParse(value, out guid))
+                    {
+                        return value;
+                    }
+
+                    _logger.Error("Invalid value found in device id file");
+                }
+            }
+            catch (DirectoryNotFoundException)
+            {
+            }
+            catch (FileNotFoundException)
+            {
+            }
+            catch (Exception ex)
+            {
+                _logger.ErrorException("Error reading file", ex);
+            }
+
+            return null;
+        }
+
+        private void SaveId(string id)
+        {
+            try
+            {
+                var path = CachePath;
+
+				_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+
+                lock (_syncLock)
+                {
+                    _fileSystem.WriteAllText(path, id, Encoding.UTF8);
+                }
+            }
+            catch (Exception ex)
+            {
+                _logger.ErrorException("Error writing to file", ex);
+            }
+        }
+
+        private string GetNewId()
+        {
+            return Guid.NewGuid().ToString("N");
+        }
+
+        private string GetDeviceId()
+        {
+            var id = GetCachedId();
+
+            if (string.IsNullOrWhiteSpace(id))
+            {
+                id = GetNewId();
+                SaveId(id);
+            }
+
+            return id;
+        }
+
+        private string _id;
+
+        public DeviceId(IApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem)
+        {
+			if (fileSystem == null) {
+				throw new ArgumentNullException ("fileSystem");
+			}
+
+            _appPaths = appPaths;
+            _logger = logger;
+			_fileSystem = fileSystem;
+        }
+
+        public string Value
+        {
+            get { return _id ?? (_id = GetDeviceId()); }
+        }
+    }
+}

+ 23 - 0
Emby.Common.Implementations/Emby.Common.Implementations.xproj

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
+    <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
+  </PropertyGroup>
+  <Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>5a27010a-09c6-4e86-93ea-437484c10917</ProjectGuid>
+    <RootNamespace>Emby.Common.Implementations</RootNamespace>
+    <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
+    <OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
+    <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SchemaVersion>2.0</SchemaVersion>
+  </PropertyGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj" />
+    <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj" />
+  </ItemGroup>
+  <Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
+</Project>

+ 16 - 0
Emby.Common.Implementations/HttpClientManager/HttpClientInfo.cs

@@ -0,0 +1,16 @@
+using System;
+
+namespace Emby.Common.Implementations.HttpClientManager
+{
+    /// <summary>
+    /// Class HttpClientInfo
+    /// </summary>
+    public class HttpClientInfo
+    {
+        /// <summary>
+        /// Gets or sets the last timeout.
+        /// </summary>
+        /// <value>The last timeout.</value>
+        public DateTime LastTimeout { get; set; }
+    }
+}

+ 936 - 0
Emby.Common.Implementations/HttpClientManager/HttpClientManager.cs

@@ -0,0 +1,936 @@
+using System.Net.Sockets;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Net;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Net.Cache;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Emby.Common.Implementations.HttpClientManager;
+using MediaBrowser.Model.IO;
+
+namespace Emby.Common.Implementations.HttpClientManager
+{
+    /// <summary>
+    /// Class HttpClientManager
+    /// </summary>
+    public class HttpClientManager : IHttpClient
+    {
+        /// <summary>
+        /// When one request to a host times out, we'll ban all other requests for this period of time, to prevent scans from stalling
+        /// </summary>
+        private const int TimeoutSeconds = 30;
+
+        /// <summary>
+        /// The _logger
+        /// </summary>
+        private readonly ILogger _logger;
+
+        /// <summary>
+        /// The _app paths
+        /// </summary>
+        private readonly IApplicationPaths _appPaths;
+
+        private readonly IFileSystem _fileSystem;
+        private readonly IMemoryStreamProvider _memoryStreamProvider;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="HttpClientManager" /> class.
+        /// </summary>
+        /// <param name="appPaths">The app paths.</param>
+        /// <param name="logger">The logger.</param>
+        /// <param name="fileSystem">The file system.</param>
+        /// <exception cref="System.ArgumentNullException">appPaths
+        /// or
+        /// logger</exception>
+        public HttpClientManager(IApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem, IMemoryStreamProvider memoryStreamProvider)
+        {
+            if (appPaths == null)
+            {
+                throw new ArgumentNullException("appPaths");
+            }
+            if (logger == null)
+            {
+                throw new ArgumentNullException("logger");
+            }
+
+            _logger = logger;
+            _fileSystem = fileSystem;
+            _memoryStreamProvider = memoryStreamProvider;
+            _appPaths = appPaths;
+
+            // http://stackoverflow.com/questions/566437/http-post-returns-the-error-417-expectation-failed-c
+            ServicePointManager.Expect100Continue = false;
+
+            // Trakt requests sometimes fail without this
+            ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;
+        }
+
+        /// <summary>
+        /// Holds a dictionary of http clients by host.  Use GetHttpClient(host) to retrieve or create a client for web requests.
+        /// DON'T dispose it after use.
+        /// </summary>
+        /// <value>The HTTP clients.</value>
+        private readonly ConcurrentDictionary<string, HttpClientInfo> _httpClients = new ConcurrentDictionary<string, HttpClientInfo>();
+
+        /// <summary>
+        /// Gets
+        /// </summary>
+        /// <param name="host">The host.</param>
+        /// <param name="enableHttpCompression">if set to <c>true</c> [enable HTTP compression].</param>
+        /// <returns>HttpClient.</returns>
+        /// <exception cref="System.ArgumentNullException">host</exception>
+        private HttpClientInfo GetHttpClient(string host, bool enableHttpCompression)
+        {
+            if (string.IsNullOrEmpty(host))
+            {
+                throw new ArgumentNullException("host");
+            }
+
+            HttpClientInfo client;
+
+            var key = host + enableHttpCompression;
+
+            if (!_httpClients.TryGetValue(key, out client))
+            {
+                client = new HttpClientInfo();
+
+                _httpClients.TryAdd(key, client);
+            }
+
+            return client;
+        }
+
+        private WebRequest CreateWebRequest(string url)
+        {
+            try
+            {
+                return WebRequest.Create(url);
+            }
+            catch (NotSupportedException)
+            {
+                //Webrequest creation does fail on MONO randomly when using WebRequest.Create
+                //the issue occurs in the GetCreator method here: http://www.oschina.net/code/explore/mono-2.8.1/mcs/class/System/System.Net/WebRequest.cs
+
+                var type = Type.GetType("System.Net.HttpRequestCreator, System, Version=4.0.0.0,Culture=neutral, PublicKeyToken=b77a5c561934e089");
+                var creator = Activator.CreateInstance(type, nonPublic: true) as IWebRequestCreate;
+                return creator.Create(new Uri(url)) as HttpWebRequest;
+            }
+        }
+
+        private void AddIpv4Option(HttpWebRequest request, HttpRequestOptions options)
+        {
+            request.ServicePoint.BindIPEndPointDelegate = (servicePount, remoteEndPoint, retryCount) =>
+            {
+                if (remoteEndPoint.AddressFamily == AddressFamily.InterNetwork)
+                {
+                    return new IPEndPoint(IPAddress.Any, 0);
+                }
+                throw new InvalidOperationException("no IPv4 address");
+            };
+        }
+
+        private WebRequest GetRequest(HttpRequestOptions options, string method)
+        {
+            var url = options.Url;
+
+            var uriAddress = new Uri(url);
+            var userInfo = uriAddress.UserInfo;
+            if (!string.IsNullOrWhiteSpace(userInfo))
+            {
+                _logger.Info("Found userInfo in url: {0} ... url: {1}", userInfo, url);
+                url = url.Replace(userInfo + "@", string.Empty);
+            }
+
+            var request = CreateWebRequest(url);
+            var httpWebRequest = request as HttpWebRequest;
+
+            if (httpWebRequest != null)
+            {
+                if (options.PreferIpv4)
+                {
+                    AddIpv4Option(httpWebRequest, options);
+                }
+
+                AddRequestHeaders(httpWebRequest, options);
+
+                httpWebRequest.AutomaticDecompression = options.EnableHttpCompression ? 
+                    (options.DecompressionMethod ?? DecompressionMethods.Deflate) : 
+                    DecompressionMethods.None;
+            }
+
+            request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache);
+
+            if (httpWebRequest != null)
+            {
+                if (options.EnableKeepAlive)
+                {
+                    httpWebRequest.KeepAlive = true;
+                }
+            }
+
+            request.Method = method;
+            request.Timeout = options.TimeoutMs;
+            
+            if (httpWebRequest != null)
+            {
+                if (!string.IsNullOrEmpty(options.Host))
+                {
+                    httpWebRequest.Host = options.Host;
+                }
+
+                if (!string.IsNullOrEmpty(options.Referer))
+                {
+                    httpWebRequest.Referer = options.Referer;
+                }
+            }
+
+            if (!string.IsNullOrWhiteSpace(userInfo))
+            {
+                var parts = userInfo.Split(':');
+                if (parts.Length == 2)
+                {
+                    request.Credentials = GetCredential(url, parts[0], parts[1]);
+                    request.PreAuthenticate = true;
+                }
+            }
+
+            return request;
+        }
+
+        private CredentialCache GetCredential(string url, string username, string password)
+        {
+            //ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
+            CredentialCache credentialCache = new CredentialCache();
+            credentialCache.Add(new Uri(url), "Basic", new NetworkCredential(username, password));
+            return credentialCache;
+        }
+
+        private void AddRequestHeaders(HttpWebRequest request, HttpRequestOptions options)
+        {
+            foreach (var header in options.RequestHeaders.ToList())
+            {
+                if (string.Equals(header.Key, "Accept", StringComparison.OrdinalIgnoreCase))
+                {
+                    request.Accept = header.Value;
+                }
+                else if (string.Equals(header.Key, "User-Agent", StringComparison.OrdinalIgnoreCase))
+                {
+                    request.UserAgent = header.Value;
+                }
+                else
+                {
+                    request.Headers.Set(header.Key, header.Value);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets the response internal.
+        /// </summary>
+        /// <param name="options">The options.</param>
+        /// <returns>Task{HttpResponseInfo}.</returns>
+        public Task<HttpResponseInfo> GetResponse(HttpRequestOptions options)
+        {
+            return SendAsync(options, "GET");
+        }
+
+        /// <summary>
+        /// Performs a GET request and returns the resulting stream
+        /// </summary>
+        /// <param name="options">The options.</param>
+        /// <returns>Task{Stream}.</returns>
+        public async Task<Stream> Get(HttpRequestOptions options)
+        {
+            var response = await GetResponse(options).ConfigureAwait(false);
+
+            return response.Content;
+        }
+
+        /// <summary>
+        /// Performs a GET request and returns the resulting stream
+        /// </summary>
+        /// <param name="url">The URL.</param>
+        /// <param name="resourcePool">The resource pool.</param>
+        /// <param name="cancellationToken">The cancellation token.</param>
+        /// <returns>Task{Stream}.</returns>
+        public Task<Stream> Get(string url, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
+        {
+            return Get(new HttpRequestOptions
+            {
+                Url = url,
+                ResourcePool = resourcePool,
+                CancellationToken = cancellationToken,
+                BufferContent = resourcePool != null
+            });
+        }
+
+        /// <summary>
+        /// Gets the specified URL.
+        /// </summary>
+        /// <param name="url">The URL.</param>
+        /// <param name="cancellationToken">The cancellation token.</param>
+        /// <returns>Task{Stream}.</returns>
+        public Task<Stream> Get(string url, CancellationToken cancellationToken)
+        {
+            return Get(url, null, cancellationToken);
+        }
+
+        /// <summary>
+        /// send as an asynchronous operation.
+        /// </summary>
+        /// <param name="options">The options.</param>
+        /// <param name="httpMethod">The HTTP method.</param>
+        /// <returns>Task{HttpResponseInfo}.</returns>
+        /// <exception cref="HttpException">
+        /// </exception>
+        public async Task<HttpResponseInfo> SendAsync(HttpRequestOptions options, string httpMethod)
+        {
+            if (options.CacheMode == CacheMode.None)
+            {
+                return await SendAsyncInternal(options, httpMethod).ConfigureAwait(false);
+            }
+
+            var url = options.Url;
+            var urlHash = url.ToLower().GetMD5().ToString("N");
+
+            var responseCachePath = Path.Combine(_appPaths.CachePath, "httpclient", urlHash);
+
+            var response = await GetCachedResponse(responseCachePath, options.CacheLength, url).ConfigureAwait(false);
+            if (response != null)
+            {
+                return response;
+            }
+
+            response = await SendAsyncInternal(options, httpMethod).ConfigureAwait(false);
+
+            if (response.StatusCode == HttpStatusCode.OK)
+            {
+                await CacheResponse(response, responseCachePath).ConfigureAwait(false);
+            }
+
+            return response;
+        }
+
+        private async Task<HttpResponseInfo> GetCachedResponse(string responseCachePath, TimeSpan cacheLength, string url)
+        {
+            _logger.Info("Checking for cache file {0}", responseCachePath);
+
+            try
+            {
+                if (_fileSystem.GetLastWriteTimeUtc(responseCachePath).Add(cacheLength) > DateTime.UtcNow)
+                {
+                    using (var stream = _fileSystem.GetFileStream(responseCachePath, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read, true))
+                    {
+                        var memoryStream = _memoryStreamProvider.CreateNew();
+
+                        await stream.CopyToAsync(memoryStream).ConfigureAwait(false);
+                        memoryStream.Position = 0;
+
+                        return new HttpResponseInfo
+                        {
+                            ResponseUrl = url,
+                            Content = memoryStream,
+                            StatusCode = HttpStatusCode.OK,
+                            ContentLength = memoryStream.Length
+                        };
+                    }
+                }
+            }
+            catch (FileNotFoundException)
+            {
+
+            }
+            catch (DirectoryNotFoundException)
+            {
+
+            }
+
+            return null;
+        }
+
+        private async Task CacheResponse(HttpResponseInfo response, string responseCachePath)
+        {
+            _fileSystem.CreateDirectory(Path.GetDirectoryName(responseCachePath));
+
+            using (var responseStream = response.Content)
+            {
+                var memoryStream = _memoryStreamProvider.CreateNew();
+                await responseStream.CopyToAsync(memoryStream).ConfigureAwait(false);
+                memoryStream.Position = 0;
+
+                using (var fileStream = _fileSystem.GetFileStream(responseCachePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.None, true))
+                {
+                    await memoryStream.CopyToAsync(fileStream).ConfigureAwait(false);
+
+                    memoryStream.Position = 0;
+                    response.Content = memoryStream;
+                }
+            }
+        }
+
+        private async Task<HttpResponseInfo> SendAsyncInternal(HttpRequestOptions options, string httpMethod)
+        {
+            ValidateParams(options);
+
+            options.CancellationToken.ThrowIfCancellationRequested();
+
+            var client = GetHttpClient(GetHostFromUrl(options.Url), options.EnableHttpCompression);
+
+            if ((DateTime.UtcNow - client.LastTimeout).TotalSeconds < TimeoutSeconds)
+            {
+                throw new HttpException(string.Format("Cancelling connection to {0} due to a previous timeout.", options.Url))
+                {
+                    IsTimedOut = true
+                };
+            }
+
+            var httpWebRequest = GetRequest(options, httpMethod);
+
+            if (options.RequestContentBytes != null ||
+                !string.IsNullOrEmpty(options.RequestContent) ||
+                string.Equals(httpMethod, "post", StringComparison.OrdinalIgnoreCase))
+            {
+                var bytes = options.RequestContentBytes ??
+                    Encoding.UTF8.GetBytes(options.RequestContent ?? string.Empty);
+
+                httpWebRequest.ContentType = options.RequestContentType ?? "application/x-www-form-urlencoded";
+
+                httpWebRequest.ContentLength = bytes.Length;
+                httpWebRequest.GetRequestStream().Write(bytes, 0, bytes.Length);
+            }
+
+            if (options.ResourcePool != null)
+            {
+                await options.ResourcePool.WaitAsync(options.CancellationToken).ConfigureAwait(false);
+            }
+
+            if ((DateTime.UtcNow - client.LastTimeout).TotalSeconds < TimeoutSeconds)
+            {
+                if (options.ResourcePool != null)
+                {
+                    options.ResourcePool.Release();
+                }
+
+                throw new HttpException(string.Format("Connection to {0} timed out", options.Url)) { IsTimedOut = true };
+            }
+
+            if (options.LogRequest)
+            {
+                _logger.Info("HttpClientManager {0}: {1}", httpMethod.ToUpper(), options.Url);
+            }
+
+            try
+            {
+                options.CancellationToken.ThrowIfCancellationRequested();
+
+                if (!options.BufferContent)
+                {
+                    var response = await GetResponseAsync(httpWebRequest, TimeSpan.FromMilliseconds(options.TimeoutMs)).ConfigureAwait(false);
+
+                    var httpResponse = (HttpWebResponse)response;
+
+                    EnsureSuccessStatusCode(client, httpResponse, options);
+
+                    options.CancellationToken.ThrowIfCancellationRequested();
+
+                    return GetResponseInfo(httpResponse, httpResponse.GetResponseStream(), GetContentLength(httpResponse), httpResponse);
+                }
+
+                using (var response = await GetResponseAsync(httpWebRequest, TimeSpan.FromMilliseconds(options.TimeoutMs)).ConfigureAwait(false))
+                {
+                    var httpResponse = (HttpWebResponse)response;
+
+                    EnsureSuccessStatusCode(client, httpResponse, options);
+
+                    options.CancellationToken.ThrowIfCancellationRequested();
+
+                    using (var stream = httpResponse.GetResponseStream())
+                    {
+                        var memoryStream = _memoryStreamProvider.CreateNew();
+
+                        await stream.CopyToAsync(memoryStream).ConfigureAwait(false);
+
+                        memoryStream.Position = 0;
+
+                        return GetResponseInfo(httpResponse, memoryStream, memoryStream.Length, null);
+                    }
+                }
+            }
+            catch (OperationCanceledException ex)
+            {
+                throw GetCancellationException(options, client, options.CancellationToken, ex);
+            }
+            catch (Exception ex)
+            {
+                throw GetException(ex, options, client);
+            }
+            finally
+            {
+                if (options.ResourcePool != null)
+                {
+                    options.ResourcePool.Release();
+                }
+            }
+        }
+
+        private HttpResponseInfo GetResponseInfo(HttpWebResponse httpResponse, Stream content, long? contentLength, IDisposable disposable)
+        {
+            var responseInfo = new HttpResponseInfo(disposable)
+            {
+                Content = content,
+
+                StatusCode = httpResponse.StatusCode,
+
+                ContentType = httpResponse.ContentType,
+
+                ContentLength = contentLength,
+
+                ResponseUrl = httpResponse.ResponseUri.ToString()
+            };
+
+            if (httpResponse.Headers != null)
+            {
+                SetHeaders(httpResponse.Headers, responseInfo);
+            }
+
+            return responseInfo;
+        }
+
+        private HttpResponseInfo GetResponseInfo(HttpWebResponse httpResponse, string tempFile, long? contentLength)
+        {
+            var responseInfo = new HttpResponseInfo
+            {
+                TempFilePath = tempFile,
+
+                StatusCode = httpResponse.StatusCode,
+
+                ContentType = httpResponse.ContentType,
+
+                ContentLength = contentLength
+            };
+
+            if (httpResponse.Headers != null)
+            {
+                SetHeaders(httpResponse.Headers, responseInfo);
+            }
+
+            return responseInfo;
+        }
+
+        private void SetHeaders(WebHeaderCollection headers, HttpResponseInfo responseInfo)
+        {
+            foreach (var key in headers.AllKeys)
+            {
+                responseInfo.Headers[key] = headers[key];
+            }
+        }
+
+        public Task<HttpResponseInfo> Post(HttpRequestOptions options)
+        {
+            return SendAsync(options, "POST");
+        }
+
+        /// <summary>
+        /// Performs a POST request
+        /// </summary>
+        /// <param name="options">The options.</param>
+        /// <param name="postData">Params to add to the POST data.</param>
+        /// <returns>stream on success, null on failure</returns>
+        public async Task<Stream> Post(HttpRequestOptions options, Dictionary<string, string> postData)
+        {
+            options.SetPostData(postData);
+
+            var response = await Post(options).ConfigureAwait(false);
+
+            return response.Content;
+        }
+
+        /// <summary>
+        /// Performs a POST request
+        /// </summary>
+        /// <param name="url">The URL.</param>
+        /// <param name="postData">Params to add to the POST data.</param>
+        /// <param name="resourcePool">The resource pool.</param>
+        /// <param name="cancellationToken">The cancellation token.</param>
+        /// <returns>stream on success, null on failure</returns>
+        public Task<Stream> Post(string url, Dictionary<string, string> postData, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
+        {
+            return Post(new HttpRequestOptions
+            {
+                Url = url,
+                ResourcePool = resourcePool,
+                CancellationToken = cancellationToken,
+                BufferContent = resourcePool != null
+
+            }, postData);
+        }
+
+        /// <summary>
+        /// Downloads the contents of a given url into a temporary location
+        /// </summary>
+        /// <param name="options">The options.</param>
+        /// <returns>Task{System.String}.</returns>
+        public async Task<string> GetTempFile(HttpRequestOptions options)
+        {
+            var response = await GetTempFileResponse(options).ConfigureAwait(false);
+
+            return response.TempFilePath;
+        }
+
+        public async Task<HttpResponseInfo> GetTempFileResponse(HttpRequestOptions options)
+        {
+            ValidateParams(options);
+
+            _fileSystem.CreateDirectory(_appPaths.TempDirectory);
+
+            var tempFile = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid() + ".tmp");
+
+            if (options.Progress == null)
+            {
+                throw new ArgumentNullException("progress");
+            }
+
+            options.CancellationToken.ThrowIfCancellationRequested();
+
+            var httpWebRequest = GetRequest(options, "GET");
+
+            if (options.ResourcePool != null)
+            {
+                await options.ResourcePool.WaitAsync(options.CancellationToken).ConfigureAwait(false);
+            }
+
+            options.Progress.Report(0);
+
+            if (options.LogRequest)
+            {
+                _logger.Info("HttpClientManager.GetTempFileResponse url: {0}", options.Url);
+            }
+
+            var client = GetHttpClient(GetHostFromUrl(options.Url), options.EnableHttpCompression);
+
+            try
+            {
+                options.CancellationToken.ThrowIfCancellationRequested();
+
+                using (var response = await httpWebRequest.GetResponseAsync().ConfigureAwait(false))
+                {
+                    var httpResponse = (HttpWebResponse)response;
+
+                    EnsureSuccessStatusCode(client, httpResponse, options);
+
+                    options.CancellationToken.ThrowIfCancellationRequested();
+
+                    var contentLength = GetContentLength(httpResponse);
+
+                    if (!contentLength.HasValue)
+                    {
+                        // We're not able to track progress
+                        using (var stream = httpResponse.GetResponseStream())
+                        {
+                            using (var fs = _fileSystem.GetFileStream(tempFile, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
+                            {
+                                await stream.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, options.CancellationToken).ConfigureAwait(false);
+                            }
+                        }
+                    }
+                    else
+                    {
+                        using (var stream = ProgressStream.CreateReadProgressStream(httpResponse.GetResponseStream(), options.Progress.Report, contentLength.Value))
+                        {
+                            using (var fs = _fileSystem.GetFileStream(tempFile, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
+                            {
+                                await stream.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, options.CancellationToken).ConfigureAwait(false);
+                            }
+                        }
+                    }
+
+                    options.Progress.Report(100);
+
+                    return GetResponseInfo(httpResponse, tempFile, contentLength);
+                }
+            }
+            catch (Exception ex)
+            {
+                DeleteTempFile(tempFile);
+                throw GetException(ex, options, client);
+            }
+            finally
+            {
+                if (options.ResourcePool != null)
+                {
+                    options.ResourcePool.Release();
+                }
+            }
+        }
+
+        private long? GetContentLength(HttpWebResponse response)
+        {
+            var length = response.ContentLength;
+
+            if (length == 0)
+            {
+                return null;
+            }
+
+            return length;
+        }
+
+        protected static readonly CultureInfo UsCulture = new CultureInfo("en-US");
+
+        private Exception GetException(Exception ex, HttpRequestOptions options, HttpClientInfo client)
+        {
+            if (ex is HttpException)
+            {
+                return ex;
+            }
+
+            var webException = ex as WebException
+                ?? ex.InnerException as WebException;
+
+            if (webException != null)
+            {
+                if (options.LogErrors)
+                {
+                    _logger.ErrorException("Error getting response from " + options.Url, ex);
+                }
+
+                var exception = new HttpException(ex.Message, ex);
+
+                var response = webException.Response as HttpWebResponse;
+                if (response != null)
+                {
+                    exception.StatusCode = response.StatusCode;
+
+                    if ((int)response.StatusCode == 429)
+                    {
+                        client.LastTimeout = DateTime.UtcNow;
+                    }
+                }
+
+                return exception;
+            }
+
+            var operationCanceledException = ex as OperationCanceledException
+                ?? ex.InnerException as OperationCanceledException;
+
+            if (operationCanceledException != null)
+            {
+                return GetCancellationException(options, client, options.CancellationToken, operationCanceledException);
+            }
+
+            if (options.LogErrors)
+            {
+                _logger.ErrorException("Error getting response from " + options.Url, ex);
+            }
+
+            return ex;
+        }
+
+        private void DeleteTempFile(string file)
+        {
+            try
+            {
+                _fileSystem.DeleteFile(file);
+            }
+            catch (IOException)
+            {
+                // Might not have been created at all. No need to worry.
+            }
+        }
+
+        private void ValidateParams(HttpRequestOptions options)
+        {
+            if (string.IsNullOrEmpty(options.Url))
+            {
+                throw new ArgumentNullException("options");
+            }
+        }
+
+        /// <summary>
+        /// Gets the host from URL.
+        /// </summary>
+        /// <param name="url">The URL.</param>
+        /// <returns>System.String.</returns>
+        private string GetHostFromUrl(string url)
+        {
+            var index = url.IndexOf("://", StringComparison.OrdinalIgnoreCase);
+
+            if (index != -1)
+            {
+                url = url.Substring(index + 3);
+                var host = url.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
+
+                if (!string.IsNullOrWhiteSpace(host))
+                {
+                    return host;
+                }
+            }
+
+            return url;
+        }
+
+        /// <summary>
+        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+        /// </summary>
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        /// <summary>
+        /// Releases unmanaged and - optionally - managed resources.
+        /// </summary>
+        /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+        protected virtual void Dispose(bool dispose)
+        {
+            if (dispose)
+            {
+                _httpClients.Clear();
+            }
+        }
+
+        /// <summary>
+        /// Throws the cancellation exception.
+        /// </summary>
+        /// <param name="options">The options.</param>
+        /// <param name="client">The client.</param>
+        /// <param name="cancellationToken">The cancellation token.</param>
+        /// <param name="exception">The exception.</param>
+        /// <returns>Exception.</returns>
+        private Exception GetCancellationException(HttpRequestOptions options, HttpClientInfo client, CancellationToken cancellationToken, OperationCanceledException exception)
+        {
+            // If the HttpClient's timeout is reached, it will cancel the Task internally
+            if (!cancellationToken.IsCancellationRequested)
+            {
+                var msg = string.Format("Connection to {0} timed out", options.Url);
+
+                if (options.LogErrors)
+                {
+                    _logger.Error(msg);
+                }
+
+                client.LastTimeout = DateTime.UtcNow;
+
+                // Throw an HttpException so that the caller doesn't think it was cancelled by user code
+                return new HttpException(msg, exception)
+                {
+                    IsTimedOut = true
+                };
+            }
+
+            return exception;
+        }
+
+        private void EnsureSuccessStatusCode(HttpClientInfo client, HttpWebResponse response, HttpRequestOptions options)
+        {
+            var statusCode = response.StatusCode;
+
+            var isSuccessful = statusCode >= HttpStatusCode.OK && statusCode <= (HttpStatusCode)299;
+
+            if (!isSuccessful)
+            {
+                if (options.LogErrorResponseBody)
+                {
+                    try
+                    {
+                        using (var stream = response.GetResponseStream())
+                        {
+                            if (stream != null)
+                            {
+                                using (var reader = new StreamReader(stream))
+                                {
+                                    var msg = reader.ReadToEnd();
+
+                                    _logger.Error(msg);
+                                }
+                            }
+                        }
+                    }
+                    catch
+                    {
+
+                    }
+                }
+                throw new HttpException(response.StatusDescription)
+                {
+                    StatusCode = response.StatusCode
+                };
+            }
+        }
+
+        /// <summary>
+        /// Posts the specified URL.
+        /// </summary>
+        /// <param name="url">The URL.</param>
+        /// <param name="postData">The post data.</param>
+        /// <param name="cancellationToken">The cancellation token.</param>
+        /// <returns>Task{Stream}.</returns>
+        public Task<Stream> Post(string url, Dictionary<string, string> postData, CancellationToken cancellationToken)
+        {
+            return Post(url, postData, null, cancellationToken);
+        }
+
+        private Task<WebResponse> GetResponseAsync(WebRequest request, TimeSpan timeout)
+        {
+            var taskCompletion = new TaskCompletionSource<WebResponse>();
+
+            Task<WebResponse> asyncTask = Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null);
+
+            ThreadPool.RegisterWaitForSingleObject((asyncTask as IAsyncResult).AsyncWaitHandle, TimeoutCallback, request, timeout, true);
+            var callback = new TaskCallback { taskCompletion = taskCompletion };
+            asyncTask.ContinueWith(callback.OnSuccess, TaskContinuationOptions.NotOnFaulted);
+
+            // Handle errors
+            asyncTask.ContinueWith(callback.OnError, TaskContinuationOptions.OnlyOnFaulted);
+
+            return taskCompletion.Task;
+        }
+
+        private static void TimeoutCallback(object state, bool timedOut)
+        {
+            if (timedOut)
+            {
+                WebRequest request = (WebRequest)state;
+                if (state != null)
+                {
+                    request.Abort();
+                }
+            }
+        }
+
+        private class TaskCallback
+        {
+            public TaskCompletionSource<WebResponse> taskCompletion;
+
+            public void OnSuccess(Task<WebResponse> task)
+            {
+                taskCompletion.TrySetResult(task.Result);
+            }
+
+            public void OnError(Task<WebResponse> task)
+            {
+                if (task.Exception != null)
+                {
+                    taskCompletion.TrySetException(task.Exception);
+                }
+                else
+                {
+                    taskCompletion.TrySetException(new List<Exception>());
+                }
+            }
+        }
+    }
+}

+ 75 - 0
Emby.Common.Implementations/IO/IsoManager.cs

@@ -0,0 +1,75 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Model.IO;
+
+namespace Emby.Common.Implementations.IO
+{
+    /// <summary>
+    /// Class IsoManager
+    /// </summary>
+    public class IsoManager : IIsoManager
+    {
+        /// <summary>
+        /// The _mounters
+        /// </summary>
+        private readonly List<IIsoMounter> _mounters = new List<IIsoMounter>();
+
+        /// <summary>
+        /// Mounts the specified iso path.
+        /// </summary>
+        /// <param name="isoPath">The iso path.</param>
+        /// <param name="cancellationToken">The cancellation token.</param>
+        /// <returns>IsoMount.</returns>
+        /// <exception cref="System.ArgumentNullException">isoPath</exception>
+        /// <exception cref="System.ArgumentException"></exception>
+        public Task<IIsoMount> Mount(string isoPath, CancellationToken cancellationToken)
+        {
+            if (string.IsNullOrEmpty(isoPath))
+            {
+                throw new ArgumentNullException("isoPath");
+            }
+
+            var mounter = _mounters.FirstOrDefault(i => i.CanMount(isoPath));
+
+            if (mounter == null)
+            {
+                throw new ArgumentException(string.Format("No mounters are able to mount {0}", isoPath));
+            }
+
+            return mounter.Mount(isoPath, cancellationToken);
+        }
+
+        /// <summary>
+        /// Determines whether this instance can mount the specified path.
+        /// </summary>
+        /// <param name="path">The path.</param>
+        /// <returns><c>true</c> if this instance can mount the specified path; otherwise, <c>false</c>.</returns>
+        public bool CanMount(string path)
+        {
+            return _mounters.Any(i => i.CanMount(path));
+        }
+
+        /// <summary>
+        /// Adds the parts.
+        /// </summary>
+        /// <param name="mounters">The mounters.</param>
+        public void AddParts(IEnumerable<IIsoMounter> mounters)
+        {
+            _mounters.AddRange(mounters);
+        }
+
+        /// <summary>
+        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+        /// </summary>
+        public void Dispose()
+        {
+            foreach (var mounter in _mounters)
+            {
+                mounter.Dispose();
+            }
+        }
+    }
+}

+ 705 - 0
Emby.Common.Implementations/IO/ManagedFileSystem.cs

@@ -0,0 +1,705 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Logging;
+
+namespace Emby.Common.Implementations.IO
+{
+    /// <summary>
+    /// Class ManagedFileSystem
+    /// </summary>
+    public class ManagedFileSystem : IFileSystem
+    {
+        protected ILogger Logger;
+
+        private readonly bool _supportsAsyncFileStreams;
+        private char[] _invalidFileNameChars;
+        private readonly List<IShortcutHandler> _shortcutHandlers = new List<IShortcutHandler>();
+        protected bool EnableFileSystemRequestConcat = true;
+
+        public ManagedFileSystem(ILogger logger, bool supportsAsyncFileStreams, bool enableManagedInvalidFileNameChars)
+        {
+            Logger = logger;
+            _supportsAsyncFileStreams = supportsAsyncFileStreams;
+            SetInvalidFileNameChars(enableManagedInvalidFileNameChars);
+        }
+
+        public void AddShortcutHandler(IShortcutHandler handler)
+        {
+            _shortcutHandlers.Add(handler);
+        }
+
+        protected void SetInvalidFileNameChars(bool enableManagedInvalidFileNameChars)
+        {
+            if (enableManagedInvalidFileNameChars)
+            {
+                _invalidFileNameChars = Path.GetInvalidFileNameChars();
+            }
+            else
+            {
+                // GetInvalidFileNameChars is less restrictive in Linux/Mac than Windows, this mimic Windows behavior for mono under Linux/Mac.
+                _invalidFileNameChars = new char[41] { '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
+            '\x08', '\x09', '\x0A', '\x0B', '\x0C', '\x0D', '\x0E', '\x0F', '\x10', '\x11', '\x12',
+            '\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19', '\x1A', '\x1B', '\x1C', '\x1D',
+            '\x1E', '\x1F', '\x22', '\x3C', '\x3E', '\x7C', ':', '*', '?', '\\', '/' };
+            }
+        }
+
+        public char DirectorySeparatorChar
+        {
+            get
+            {
+                return Path.DirectorySeparatorChar;
+            }
+        }
+
+        public string GetFullPath(string path)
+        {
+            return Path.GetFullPath(path);
+        }
+
+        /// <summary>
+        /// Determines whether the specified filename is shortcut.
+        /// </summary>
+        /// <param name="filename">The filename.</param>
+        /// <returns><c>true</c> if the specified filename is shortcut; otherwise, <c>false</c>.</returns>
+        /// <exception cref="System.ArgumentNullException">filename</exception>
+        public virtual bool IsShortcut(string filename)
+        {
+            if (string.IsNullOrEmpty(filename))
+            {
+                throw new ArgumentNullException("filename");
+            }
+
+            var extension = Path.GetExtension(filename);
+            return _shortcutHandlers.Any(i => string.Equals(extension, i.Extension, StringComparison.OrdinalIgnoreCase));
+        }
+
+        /// <summary>
+        /// Resolves the shortcut.
+        /// </summary>
+        /// <param name="filename">The filename.</param>
+        /// <returns>System.String.</returns>
+        /// <exception cref="System.ArgumentNullException">filename</exception>
+        public virtual string ResolveShortcut(string filename)
+        {
+            if (string.IsNullOrEmpty(filename))
+            {
+                throw new ArgumentNullException("filename");
+            }
+
+            var extension = Path.GetExtension(filename);
+            var handler = _shortcutHandlers.FirstOrDefault(i => string.Equals(extension, i.Extension, StringComparison.OrdinalIgnoreCase));
+
+            if (handler != null)
+            {
+                return handler.Resolve(filename);
+            }
+
+            return null;
+        }
+
+        /// <summary>
+        /// Creates the shortcut.
+        /// </summary>
+        /// <param name="shortcutPath">The shortcut path.</param>
+        /// <param name="target">The target.</param>
+        /// <exception cref="System.ArgumentNullException">
+        /// shortcutPath
+        /// or
+        /// target
+        /// </exception>
+        public void CreateShortcut(string shortcutPath, string target)
+        {
+            if (string.IsNullOrEmpty(shortcutPath))
+            {
+                throw new ArgumentNullException("shortcutPath");
+            }
+
+            if (string.IsNullOrEmpty(target))
+            {
+                throw new ArgumentNullException("target");
+            }
+
+            var extension = Path.GetExtension(shortcutPath);
+            var handler = _shortcutHandlers.FirstOrDefault(i => string.Equals(extension, i.Extension, StringComparison.OrdinalIgnoreCase));
+
+            if (handler != null)
+            {
+                handler.Create(shortcutPath, target);
+            }
+            else
+            {
+                throw new NotImplementedException();
+            }
+        }
+
+        /// <summary>
+        /// Returns a <see cref="FileSystemMetadata"/> object for the specified file or directory path.
+        /// </summary>
+        /// <param name="path">A path to a file or directory.</param>
+        /// <returns>A <see cref="FileSystemMetadata"/> object.</returns>
+        /// <remarks>If the specified path points to a directory, the returned <see cref="FileSystemMetadata"/> object's
+        /// <see cref="FileSystemMetadata.IsDirectory"/> property will be set to true and all other properties will reflect the properties of the directory.</remarks>
+        public FileSystemMetadata GetFileSystemInfo(string path)
+        {
+            if (string.IsNullOrEmpty(path))
+            {
+                throw new ArgumentNullException("path");
+            }
+
+            // Take a guess to try and avoid two file system hits, but we'll double-check by calling Exists
+            if (Path.HasExtension(path))
+            {
+                var fileInfo = new FileInfo(path);
+
+                if (fileInfo.Exists)
+                {
+                    return GetFileSystemMetadata(fileInfo);
+                }
+
+                return GetFileSystemMetadata(new DirectoryInfo(path));
+            }
+            else
+            {
+                var fileInfo = new DirectoryInfo(path);
+
+                if (fileInfo.Exists)
+                {
+                    return GetFileSystemMetadata(fileInfo);
+                }
+
+                return GetFileSystemMetadata(new FileInfo(path));
+            }
+        }
+
+        /// <summary>
+        /// Returns a <see cref="FileSystemMetadata"/> object for the specified file path.
+        /// </summary>
+        /// <param name="path">A path to a file.</param>
+        /// <returns>A <see cref="FileSystemMetadata"/> object.</returns>
+        /// <remarks><para>If the specified path points to a directory, the returned <see cref="FileSystemMetadata"/> object's
+        /// <see cref="FileSystemMetadata.IsDirectory"/> property and the <see cref="FileSystemMetadata.Exists"/> property will both be set to false.</para>
+        /// <para>For automatic handling of files <b>and</b> directories, use <see cref="GetFileSystemInfo"/>.</para></remarks>
+        public FileSystemMetadata GetFileInfo(string path)
+        {
+            if (string.IsNullOrEmpty(path))
+            {
+                throw new ArgumentNullException("path");
+            }
+
+            var fileInfo = new FileInfo(path);
+
+            return GetFileSystemMetadata(fileInfo);
+        }
+
+        /// <summary>
+        /// Returns a <see cref="FileSystemMetadata"/> object for the specified directory path.
+        /// </summary>
+        /// <param name="path">A path to a directory.</param>
+        /// <returns>A <see cref="FileSystemMetadata"/> object.</returns>
+        /// <remarks><para>If the specified path points to a file, the returned <see cref="FileSystemMetadata"/> object's
+        /// <see cref="FileSystemMetadata.IsDirectory"/> property will be set to true and the <see cref="FileSystemMetadata.Exists"/> property will be set to false.</para>
+        /// <para>For automatic handling of files <b>and</b> directories, use <see cref="GetFileSystemInfo"/>.</para></remarks>
+        public FileSystemMetadata GetDirectoryInfo(string path)
+        {
+            if (string.IsNullOrEmpty(path))
+            {
+                throw new ArgumentNullException("path");
+            }
+
+            var fileInfo = new DirectoryInfo(path);
+
+            return GetFileSystemMetadata(fileInfo);
+        }
+
+        private FileSystemMetadata GetFileSystemMetadata(FileSystemInfo info)
+        {
+            var result = new FileSystemMetadata();
+
+            result.Exists = info.Exists;
+            result.FullName = info.FullName;
+            result.Extension = info.Extension;
+            result.Name = info.Name;
+
+            if (result.Exists)
+            {
+                var attributes = info.Attributes;
+                result.IsDirectory = info is DirectoryInfo || (attributes & FileAttributes.Directory) == FileAttributes.Directory;
+                result.IsHidden = (attributes & FileAttributes.Hidden) == FileAttributes.Hidden;
+                result.IsReadOnly = (attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly;
+
+                var fileInfo = info as FileInfo;
+                if (fileInfo != null)
+                {
+                    result.Length = fileInfo.Length;
+                    result.DirectoryName = fileInfo.DirectoryName;
+                }
+
+                result.CreationTimeUtc = GetCreationTimeUtc(info);
+                result.LastWriteTimeUtc = GetLastWriteTimeUtc(info);
+            }
+            else
+            {
+                result.IsDirectory = info is DirectoryInfo;
+            }
+
+            return result;
+        }
+
+        /// <summary>
+        /// The space char
+        /// </summary>
+        private const char SpaceChar = ' ';
+
+        /// <summary>
+        /// Takes a filename and removes invalid characters
+        /// </summary>
+        /// <param name="filename">The filename.</param>
+        /// <returns>System.String.</returns>
+        /// <exception cref="System.ArgumentNullException">filename</exception>
+        public string GetValidFilename(string filename)
+        {
+            if (string.IsNullOrEmpty(filename))
+            {
+                throw new ArgumentNullException("filename");
+            }
+
+            var builder = new StringBuilder(filename);
+
+            foreach (var c in _invalidFileNameChars)
+            {
+                builder = builder.Replace(c, SpaceChar);
+            }
+
+            return builder.ToString();
+        }
+
+        /// <summary>
+        /// Gets the creation time UTC.
+        /// </summary>
+        /// <param name="info">The info.</param>
+        /// <returns>DateTime.</returns>
+        public DateTime GetCreationTimeUtc(FileSystemInfo info)
+        {
+            // This could throw an error on some file systems that have dates out of range
+            try
+            {
+                return info.CreationTimeUtc;
+            }
+            catch (Exception ex)
+            {
+                Logger.ErrorException("Error determining CreationTimeUtc for {0}", ex, info.FullName);
+                return DateTime.MinValue;
+            }
+        }
+
+        /// <summary>
+        /// Gets the creation time UTC.
+        /// </summary>
+        /// <param name="path">The path.</param>
+        /// <returns>DateTime.</returns>
+        public DateTime GetCreationTimeUtc(string path)
+        {
+            return GetCreationTimeUtc(GetFileSystemInfo(path));
+        }
+
+        public DateTime GetCreationTimeUtc(FileSystemMetadata info)
+        {
+            return info.CreationTimeUtc;
+        }
+
+        public DateTime GetLastWriteTimeUtc(FileSystemMetadata info)
+        {
+            return info.LastWriteTimeUtc;
+        }
+
+        /// <summary>
+        /// Gets the creation time UTC.
+        /// </summary>
+        /// <param name="info">The info.</param>
+        /// <returns>DateTime.</returns>
+        public DateTime GetLastWriteTimeUtc(FileSystemInfo info)
+        {
+            // This could throw an error on some file systems that have dates out of range
+            try
+            {
+                return info.LastWriteTimeUtc;
+            }
+            catch (Exception ex)
+            {
+                Logger.ErrorException("Error determining LastAccessTimeUtc for {0}", ex, info.FullName);
+                return DateTime.MinValue;
+            }
+        }
+
+        /// <summary>
+        /// Gets the last write time UTC.
+        /// </summary>
+        /// <param name="path">The path.</param>
+        /// <returns>DateTime.</returns>
+        public DateTime GetLastWriteTimeUtc(string path)
+        {
+            return GetLastWriteTimeUtc(GetFileSystemInfo(path));
+        }
+
+        /// <summary>
+        /// Gets the file stream.
+        /// </summary>
+        /// <param name="path">The path.</param>
+        /// <param name="mode">The mode.</param>
+        /// <param name="access">The access.</param>
+        /// <param name="share">The share.</param>
+        /// <param name="isAsync">if set to <c>true</c> [is asynchronous].</param>
+        /// <returns>FileStream.</returns>
+        public Stream GetFileStream(string path, FileOpenMode mode, FileAccessMode access, FileShareMode share, bool isAsync = false)
+        {
+            if (_supportsAsyncFileStreams && isAsync)
+            {
+                return new FileStream(path, GetFileMode(mode), GetFileAccess(access), GetFileShare(share), 262144, true);
+            }
+
+            return new FileStream(path, GetFileMode(mode), GetFileAccess(access), GetFileShare(share), 262144);
+        }
+
+        private FileMode GetFileMode(FileOpenMode mode)
+        {
+            switch (mode)
+            {
+                case FileOpenMode.Append:
+                    return FileMode.Append;
+                case FileOpenMode.Create:
+                    return FileMode.Create;
+                case FileOpenMode.CreateNew:
+                    return FileMode.CreateNew;
+                case FileOpenMode.Open:
+                    return FileMode.Open;
+                case FileOpenMode.OpenOrCreate:
+                    return FileMode.OpenOrCreate;
+                case FileOpenMode.Truncate:
+                    return FileMode.Truncate;
+                default:
+                    throw new Exception("Unrecognized FileOpenMode");
+            }
+        }
+
+        private FileAccess GetFileAccess(FileAccessMode mode)
+        {
+            var val = (int)mode;
+
+            return (FileAccess)val;
+        }
+
+        private FileShare GetFileShare(FileShareMode mode)
+        {
+            var val = (int)mode;
+
+            return (FileShare)val;
+        }
+
+        public void SetHidden(string path, bool isHidden)
+        {
+            var info = GetFileInfo(path);
+
+            if (info.Exists && info.IsHidden != isHidden)
+            {
+                if (isHidden)
+                {
+                    FileAttributes attributes = File.GetAttributes(path);
+                    attributes = RemoveAttribute(attributes, FileAttributes.Hidden);
+                    File.SetAttributes(path, attributes);
+                }
+                else
+                {
+                    File.SetAttributes(path, File.GetAttributes(path) | FileAttributes.Hidden);
+                }
+            }
+        }
+
+        private static FileAttributes RemoveAttribute(FileAttributes attributes, FileAttributes attributesToRemove)
+        {
+            return attributes & ~attributesToRemove;
+        }
+
+        /// <summary>
+        /// Swaps the files.
+        /// </summary>
+        /// <param name="file1">The file1.</param>
+        /// <param name="file2">The file2.</param>
+        public void SwapFiles(string file1, string file2)
+        {
+            if (string.IsNullOrEmpty(file1))
+            {
+                throw new ArgumentNullException("file1");
+            }
+
+            if (string.IsNullOrEmpty(file2))
+            {
+                throw new ArgumentNullException("file2");
+            }
+
+            var temp1 = Path.GetTempFileName();
+            var temp2 = Path.GetTempFileName();
+
+            // Copying over will fail against hidden files
+            RemoveHiddenAttribute(file1);
+            RemoveHiddenAttribute(file2);
+
+            CopyFile(file1, temp1, true);
+            CopyFile(file2, temp2, true);
+
+            CopyFile(temp1, file2, true);
+            CopyFile(temp2, file1, true);
+
+            DeleteFile(temp1);
+            DeleteFile(temp2);
+        }
+
+        /// <summary>
+        /// Removes the hidden attribute.
+        /// </summary>
+        /// <param name="path">The path.</param>
+        private void RemoveHiddenAttribute(string path)
+        {
+            if (string.IsNullOrEmpty(path))
+            {
+                throw new ArgumentNullException("path");
+            }
+
+            var currentFile = new FileInfo(path);
+
+            // This will fail if the file is hidden
+            if (currentFile.Exists)
+            {
+                if ((currentFile.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
+                {
+                    currentFile.Attributes &= ~FileAttributes.Hidden;
+                }
+            }
+        }
+
+        public bool ContainsSubPath(string parentPath, string path)
+        {
+            if (string.IsNullOrEmpty(parentPath))
+            {
+                throw new ArgumentNullException("parentPath");
+            }
+
+            if (string.IsNullOrEmpty(path))
+            {
+                throw new ArgumentNullException("path");
+            }
+
+            return path.IndexOf(parentPath.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase) != -1;
+        }
+
+        public bool IsRootPath(string path)
+        {
+            if (string.IsNullOrEmpty(path))
+            {
+                throw new ArgumentNullException("path");
+            }
+
+            var parent = Path.GetDirectoryName(path);
+
+            if (!string.IsNullOrEmpty(parent))
+            {
+                return false;
+            }
+
+            return true;
+        }
+
+        public string NormalizePath(string path)
+        {
+            if (string.IsNullOrEmpty(path))
+            {
+                throw new ArgumentNullException("path");
+            }
+
+            if (path.EndsWith(":\\", StringComparison.OrdinalIgnoreCase))
+            {
+                return path;
+            }
+
+            return path.TrimEnd(Path.DirectorySeparatorChar);
+        }
+
+        public string GetFileNameWithoutExtension(FileSystemMetadata info)
+        {
+            if (info.IsDirectory)
+            {
+                return info.Name;
+            }
+
+            return Path.GetFileNameWithoutExtension(info.FullName);
+        }
+
+        public string GetFileNameWithoutExtension(string path)
+        {
+            return Path.GetFileNameWithoutExtension(path);
+        }
+
+        public bool IsPathFile(string path)
+        {
+            if (string.IsNullOrWhiteSpace(path))
+            {
+                throw new ArgumentNullException("path");
+            }
+
+            // Cannot use Path.IsPathRooted because it returns false under mono when using windows-based paths, e.g. C:\\
+
+            if (path.IndexOf("://", StringComparison.OrdinalIgnoreCase) != -1 &&
+                !path.StartsWith("file://", StringComparison.OrdinalIgnoreCase))
+            {
+                return false;
+            }
+            return true;
+
+            //return Path.IsPathRooted(path);
+        }
+
+        public void DeleteFile(string path)
+        {
+            File.Delete(path);
+        }
+
+        public void DeleteDirectory(string path, bool recursive)
+        {
+            Directory.Delete(path, recursive);
+        }
+
+        public void CreateDirectory(string path)
+        {
+            Directory.CreateDirectory(path);
+        }
+
+        public IEnumerable<FileSystemMetadata> GetDirectories(string path, bool recursive = false)
+        {
+            var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
+
+            return ToMetadata(path, new DirectoryInfo(path).EnumerateDirectories("*", searchOption));
+        }
+
+        public IEnumerable<FileSystemMetadata> GetFiles(string path, bool recursive = false)
+        {
+            var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
+
+            return ToMetadata(path, new DirectoryInfo(path).EnumerateFiles("*", searchOption));
+        }
+
+        public IEnumerable<FileSystemMetadata> GetFileSystemEntries(string path, bool recursive = false)
+        {
+            var directoryInfo = new DirectoryInfo(path);
+            var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
+
+            if (EnableFileSystemRequestConcat)
+            {
+                return ToMetadata(path, directoryInfo.EnumerateDirectories("*", searchOption))
+                                .Concat(ToMetadata(path, directoryInfo.EnumerateFiles("*", searchOption)));
+            }
+
+            return ToMetadata(path, directoryInfo.EnumerateFileSystemInfos("*", searchOption));
+        }
+
+        private IEnumerable<FileSystemMetadata> ToMetadata(string parentPath, IEnumerable<FileSystemInfo> infos)
+        {
+            return infos.Select(i =>
+            {
+                try
+                {
+                    return GetFileSystemMetadata(i);
+                }
+                catch (PathTooLongException)
+                {
+                    // Can't log using the FullName because it will throw the PathTooLongExceptiona again
+                    //Logger.Warn("Path too long: {0}", i.FullName);
+                    Logger.Warn("File or directory path too long. Parent folder: {0}", parentPath);
+                    return null;
+                }
+
+            }).Where(i => i != null);
+        }
+
+        public Stream OpenRead(string path)
+        {
+            return File.OpenRead(path);
+        }
+
+        public void CopyFile(string source, string target, bool overwrite)
+        {
+            File.Copy(source, target, overwrite);
+        }
+
+        public void MoveFile(string source, string target)
+        {
+            File.Move(source, target);
+        }
+
+        public void MoveDirectory(string source, string target)
+        {
+            Directory.Move(source, target);
+        }
+
+        public bool DirectoryExists(string path)
+        {
+            return Directory.Exists(path);
+        }
+
+        public bool FileExists(string path)
+        {
+            return File.Exists(path);
+        }
+
+        public string ReadAllText(string path)
+        {
+            return File.ReadAllText(path);
+        }
+
+        public byte[] ReadAllBytes(string path)
+        {
+            return File.ReadAllBytes(path);
+        }
+
+        public void WriteAllText(string path, string text, Encoding encoding)
+        {
+            File.WriteAllText(path, text, encoding);
+        }
+
+        public void WriteAllText(string path, string text)
+        {
+            File.WriteAllText(path, text);
+        }
+
+        public void WriteAllBytes(string path, byte[] bytes)
+        {
+            File.WriteAllBytes(path, bytes);
+        }
+
+        public string ReadAllText(string path, Encoding encoding)
+        {
+            return File.ReadAllText(path, encoding);
+        }
+
+        public IEnumerable<string> GetDirectoryPaths(string path, bool recursive = false)
+        {
+            var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
+            return Directory.EnumerateDirectories(path, "*", searchOption);
+        }
+
+        public IEnumerable<string> GetFilePaths(string path, bool recursive = false)
+        {
+            var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
+            return Directory.EnumerateFiles(path, "*", searchOption);
+        }
+
+        public IEnumerable<string> GetFileSystemEntryPaths(string path, bool recursive = false)
+        {
+            var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
+            return Directory.EnumerateFileSystemEntries(path, "*", searchOption);
+        }
+    }
+}

+ 13 - 0
Emby.Common.Implementations/IO/WindowsFileSystem.cs

@@ -0,0 +1,13 @@
+using MediaBrowser.Model.Logging;
+
+namespace Emby.Common.Implementations.IO
+{
+    public class WindowsFileSystem : ManagedFileSystem
+    {
+        public WindowsFileSystem(ILogger logger)
+            : base(logger, true, true)
+        {
+            EnableFileSystemRequestConcat = false;
+        }
+    }
+}

+ 385 - 0
Emby.Common.Implementations/Networking/BaseNetworkManager.cs

@@ -0,0 +1,385 @@
+using MediaBrowser.Model.Logging;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Net;
+using System.Net.NetworkInformation;
+using System.Net.Sockets;
+using MediaBrowser.Model.Extensions;
+
+namespace Emby.Common.Implementations.Networking
+{
+    public abstract class BaseNetworkManager
+    {
+        protected ILogger Logger { get; private set; }
+        private DateTime _lastRefresh;
+
+        protected BaseNetworkManager(ILogger logger)
+        {
+            Logger = logger;
+        }
+
+		private List<IPAddress> _localIpAddresses;
+        private readonly object _localIpAddressSyncLock = new object();
+
+        /// <summary>
+        /// Gets the machine's local ip address
+        /// </summary>
+        /// <returns>IPAddress.</returns>
+		public IEnumerable<IPAddress> GetLocalIpAddresses()
+        {
+            const int cacheMinutes = 5;
+
+            lock (_localIpAddressSyncLock)
+            {
+                var forceRefresh = (DateTime.UtcNow - _lastRefresh).TotalMinutes >= cacheMinutes;
+
+                if (_localIpAddresses == null || forceRefresh)
+                {
+                    var addresses = GetLocalIpAddressesInternal().ToList();
+
+                    _localIpAddresses = addresses;
+                    _lastRefresh = DateTime.UtcNow;
+
+                    return addresses;
+                }
+            }
+
+            return _localIpAddresses;
+        }
+
+		private IEnumerable<IPAddress> GetLocalIpAddressesInternal()
+        {
+            var list = GetIPsDefault()
+                .ToList();
+
+            if (list.Count == 0)
+            {
+				list.AddRange(GetLocalIpAddressesFallback());
+            }
+
+			return list.Where(FilterIpAddress).DistinctBy(i => i.ToString());
+        }
+
+		private bool FilterIpAddress(IPAddress address)
+        {
+			var addressString = address.ToString ();
+
+			if (addressString.StartsWith("169.", StringComparison.OrdinalIgnoreCase))
+            {
+                return false;
+            }
+
+            return true;
+        }
+
+        public bool IsInPrivateAddressSpace(string endpoint)
+        {
+            if (string.Equals(endpoint, "::1", StringComparison.OrdinalIgnoreCase))
+            {
+                return true;
+            }
+
+            // Handle ipv4 mapped to ipv6
+            endpoint = endpoint.Replace("::ffff:", string.Empty);
+
+            // Private address space:
+            // http://en.wikipedia.org/wiki/Private_network
+
+            if (endpoint.StartsWith("172.", StringComparison.OrdinalIgnoreCase))
+            {
+                return Is172AddressPrivate(endpoint);
+            }
+
+            return
+
+                endpoint.StartsWith("localhost", StringComparison.OrdinalIgnoreCase) ||
+                endpoint.StartsWith("127.", StringComparison.OrdinalIgnoreCase) ||
+                endpoint.StartsWith("10.", StringComparison.OrdinalIgnoreCase) ||
+                endpoint.StartsWith("192.168", StringComparison.OrdinalIgnoreCase) ||
+                endpoint.StartsWith("169.", StringComparison.OrdinalIgnoreCase);
+        }
+
+        private bool Is172AddressPrivate(string endpoint)
+        {
+            for (var i = 16; i <= 31; i++)
+            {
+                if (endpoint.StartsWith("172." + i.ToString(CultureInfo.InvariantCulture) + ".", StringComparison.OrdinalIgnoreCase))
+                {
+                    return true;
+                }
+            }
+
+            return false;
+        }
+
+        public bool IsInLocalNetwork(string endpoint)
+        {
+            return IsInLocalNetworkInternal(endpoint, true);
+        }
+
+        public bool IsInLocalNetworkInternal(string endpoint, bool resolveHost)
+        {
+            if (string.IsNullOrWhiteSpace(endpoint))
+            {
+                throw new ArgumentNullException("endpoint");
+            }
+
+            IPAddress address;
+            if (IPAddress.TryParse(endpoint, out address))
+            {
+                var addressString = address.ToString();
+
+                int lengthMatch = 100;
+                if (address.AddressFamily == AddressFamily.InterNetwork)
+                {
+                    lengthMatch = 4;
+                    if (IsInPrivateAddressSpace(addressString))
+                    {
+                        return true;
+                    }
+                }
+                else if (address.AddressFamily == AddressFamily.InterNetworkV6)
+                {
+                    lengthMatch = 10;
+                    if (IsInPrivateAddressSpace(endpoint))
+                    {
+                        return true;
+                    }
+                }
+
+                // Should be even be doing this with ipv6?
+                if (addressString.Length >= lengthMatch)
+                {
+                    var prefix = addressString.Substring(0, lengthMatch);
+
+					if (GetLocalIpAddresses().Any(i => i.ToString().StartsWith(prefix, StringComparison.OrdinalIgnoreCase)))
+                    {
+                        return true;
+                    }
+                }
+            } 
+            else if (resolveHost)
+            {
+                Uri uri;
+                if (Uri.TryCreate(endpoint, UriKind.RelativeOrAbsolute, out uri))
+                {
+                    try
+                    {
+                        var host = uri.DnsSafeHost;
+                        Logger.Debug("Resolving host {0}", host);
+
+                        address = GetIpAddresses(host).FirstOrDefault();
+
+                        if (address != null)
+                        {
+                            Logger.Debug("{0} resolved to {1}", host, address);
+
+                            return IsInLocalNetworkInternal(address.ToString(), false);
+                        }
+                    }
+                    catch (InvalidOperationException)
+                    {
+                        // Can happen with reverse proxy or IIS url rewriting
+                    }
+                    catch (Exception ex)
+                    {
+                        Logger.ErrorException("Error resovling hostname", ex);
+                    }
+                }
+            }
+
+            return false;
+        }
+
+        public IEnumerable<IPAddress> GetIpAddresses(string hostName)
+        {
+            return Dns.GetHostAddresses(hostName);
+        }
+
+		private List<IPAddress> GetIPsDefault()
+		{
+			NetworkInterface[] interfaces;
+
+			try
+			{
+				interfaces = NetworkInterface.GetAllNetworkInterfaces();
+			}
+			catch (Exception ex)
+			{
+				Logger.ErrorException("Error in GetAllNetworkInterfaces", ex);
+				return new List<IPAddress>();
+			}
+
+			return interfaces.SelectMany(network => {
+
+				try
+				{
+                    Logger.Debug("Querying interface: {0}. Type: {1}. Status: {2}", network.Name, network.NetworkInterfaceType, network.OperationalStatus);
+
+					var properties = network.GetIPProperties();
+
+					return properties.UnicastAddresses
+                        .Where(i => i.IsDnsEligible)
+                        .Select(i => i.Address)
+                        .Where(i => i.AddressFamily == AddressFamily.InterNetwork)
+						.ToList();
+				}
+				catch (Exception ex)
+				{
+					Logger.ErrorException("Error querying network interface", ex);
+					return new List<IPAddress>();
+				}
+
+			}).DistinctBy(i => i.ToString())
+				.ToList();
+		}
+
+		private IEnumerable<IPAddress> GetLocalIpAddressesFallback()
+        {
+            var host = Dns.GetHostEntry(Dns.GetHostName());
+
+            // Reverse them because the last one is usually the correct one
+            // It's not fool-proof so ultimately the consumer will have to examine them and decide
+            return host.AddressList
+                .Where(i => i.AddressFamily == AddressFamily.InterNetwork)
+                .Reverse();
+        }
+
+        /// <summary>
+        /// Gets a random port number that is currently available
+        /// </summary>
+        /// <returns>System.Int32.</returns>
+        public int GetRandomUnusedPort()
+        {
+            var listener = new TcpListener(IPAddress.Any, 0);
+            listener.Start();
+            var port = ((IPEndPoint)listener.LocalEndpoint).Port;
+            listener.Stop();
+            return port;
+        }
+
+        /// <summary>
+        /// Returns MAC Address from first Network Card in Computer
+        /// </summary>
+        /// <returns>[string] MAC Address</returns>
+        public string GetMacAddress()
+        {
+            return NetworkInterface.GetAllNetworkInterfaces()
+                .Where(i => i.NetworkInterfaceType != NetworkInterfaceType.Loopback)
+                .Select(i => BitConverter.ToString(i.GetPhysicalAddress().GetAddressBytes()))
+                .FirstOrDefault();
+        }
+
+        /// <summary>
+        /// Parses the specified endpointstring.
+        /// </summary>
+        /// <param name="endpointstring">The endpointstring.</param>
+        /// <returns>IPEndPoint.</returns>
+        public IPEndPoint Parse(string endpointstring)
+        {
+            return Parse(endpointstring, -1);
+        }
+
+        /// <summary>
+        /// Parses the specified endpointstring.
+        /// </summary>
+        /// <param name="endpointstring">The endpointstring.</param>
+        /// <param name="defaultport">The defaultport.</param>
+        /// <returns>IPEndPoint.</returns>
+        /// <exception cref="System.ArgumentException">Endpoint descriptor may not be empty.</exception>
+        /// <exception cref="System.FormatException"></exception>
+        private static IPEndPoint Parse(string endpointstring, int defaultport)
+        {
+            if (String.IsNullOrEmpty(endpointstring)
+                || endpointstring.Trim().Length == 0)
+            {
+                throw new ArgumentException("Endpoint descriptor may not be empty.");
+            }
+
+            if (defaultport != -1 &&
+                (defaultport < IPEndPoint.MinPort
+                || defaultport > IPEndPoint.MaxPort))
+            {
+                throw new ArgumentException(String.Format("Invalid default port '{0}'", defaultport));
+            }
+
+            string[] values = endpointstring.Split(new char[] { ':' });
+            IPAddress ipaddy;
+            int port = -1;
+          
+            //check if we have an IPv6 or ports
+            if (values.Length <= 2) // ipv4 or hostname
+            {
+                port = values.Length == 1 ? defaultport : GetPort(values[1]);
+
+                //try to use the address as IPv4, otherwise get hostname
+                if (!IPAddress.TryParse(values[0], out ipaddy))
+                    ipaddy = GetIPfromHost(values[0]);
+            }
+            else if (values.Length > 2) //ipv6
+            {
+                //could [a:b:c]:d
+                if (values[0].StartsWith("[") && values[values.Length - 2].EndsWith("]"))
+                {
+                    string ipaddressstring = String.Join(":", values.Take(values.Length - 1).ToArray());
+                    ipaddy = IPAddress.Parse(ipaddressstring);
+                    port = GetPort(values[values.Length - 1]);
+                }
+                else //[a:b:c] or a:b:c
+                {
+                    ipaddy = IPAddress.Parse(endpointstring);
+                    port = defaultport;
+                }
+            }
+            else
+            {
+                throw new FormatException(String.Format("Invalid endpoint ipaddress '{0}'", endpointstring));
+            }
+
+            if (port == -1)
+                throw new ArgumentException(String.Format("No port specified: '{0}'", endpointstring));
+
+            return new IPEndPoint(ipaddy, port);
+        }
+
+        protected static readonly CultureInfo UsCulture = new CultureInfo("en-US");
+
+        /// <summary>
+        /// Gets the port.
+        /// </summary>
+        /// <param name="p">The p.</param>
+        /// <returns>System.Int32.</returns>
+        /// <exception cref="System.FormatException"></exception>
+        private static int GetPort(string p)
+        {
+            int port;
+
+            if (!Int32.TryParse(p, out port)
+             || port < IPEndPoint.MinPort
+             || port > IPEndPoint.MaxPort)
+            {
+                throw new FormatException(String.Format("Invalid end point port '{0}'", p));
+            }
+
+            return port;
+        }
+
+        /// <summary>
+        /// Gets the I pfrom host.
+        /// </summary>
+        /// <param name="p">The p.</param>
+        /// <returns>IPAddress.</returns>
+        /// <exception cref="System.ArgumentException"></exception>
+        private static IPAddress GetIPfromHost(string p)
+        {
+            var hosts = Dns.GetHostAddresses(p);
+
+            if (hosts == null || hosts.Length == 0)
+                throw new ArgumentException(String.Format("Host not found: {0}", p));
+
+            return hosts[0];
+        }
+    }
+}

+ 19 - 0
Emby.Common.Implementations/Properties/AssemblyInfo.cs

@@ -0,0 +1,19 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Emby.Common.Implementations")]
+[assembly: AssemblyTrademark("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components.  If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("5a27010a-09c6-4e86-93ea-437484c10917")]

+ 91 - 0
Emby.Common.Implementations/ScheduledTasks/DailyTrigger.cs

@@ -0,0 +1,91 @@
+using System;
+using System.Globalization;
+using System.Threading;
+using MediaBrowser.Model.Events;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Tasks;
+
+namespace Emby.Common.Implementations.ScheduledTasks
+{
+    /// <summary>
+    /// Represents a task trigger that fires everyday
+    /// </summary>
+    public class DailyTrigger : ITaskTrigger
+    {
+        /// <summary>
+        /// Get the time of day to trigger the task to run
+        /// </summary>
+        /// <value>The time of day.</value>
+        public TimeSpan TimeOfDay { get; set; }
+
+        /// <summary>
+        /// Gets or sets the timer.
+        /// </summary>
+        /// <value>The timer.</value>
+        private Timer Timer { get; set; }
+
+        /// <summary>
+        /// Gets the execution properties of this task.
+        /// </summary>
+        /// <value>
+        /// The execution properties of this task.
+        /// </value>
+        public TaskExecutionOptions TaskOptions { get; set; }
+
+        /// <summary>
+        /// Stars waiting for the trigger action
+        /// </summary>
+        /// <param name="lastResult">The last result.</param>
+        /// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
+        public void Start(TaskResult lastResult, ILogger logger, string taskName, bool isApplicationStartup)
+        {
+            DisposeTimer();
+
+            var now = DateTime.Now;
+
+            var triggerDate = now.TimeOfDay > TimeOfDay ? now.Date.AddDays(1) : now.Date;
+            triggerDate = triggerDate.Add(TimeOfDay);
+
+            var dueTime = triggerDate - now;
+
+            logger.Info("Daily trigger for {0} set to fire at {1}, which is {2} minutes from now.", taskName, triggerDate.ToString(), dueTime.TotalMinutes.ToString(CultureInfo.InvariantCulture));
+
+            Timer = new Timer(state => OnTriggered(), null, dueTime, TimeSpan.FromMilliseconds(-1));
+        }
+
+        /// <summary>
+        /// Stops waiting for the trigger action
+        /// </summary>
+        public void Stop()
+        {
+            DisposeTimer();
+        }
+
+        /// <summary>
+        /// Disposes the timer.
+        /// </summary>
+        private void DisposeTimer()
+        {
+            if (Timer != null)
+            {
+                Timer.Dispose();
+            }
+        }
+
+        /// <summary>
+        /// Occurs when [triggered].
+        /// </summary>
+        public event EventHandler<GenericEventArgs<TaskExecutionOptions>> Triggered;
+
+        /// <summary>
+        /// Called when [triggered].
+        /// </summary>
+        private void OnTriggered()
+        {
+            if (Triggered != null)
+            {
+                Triggered(this, new GenericEventArgs<TaskExecutionOptions>(TaskOptions));
+            }
+        }
+    }
+}

+ 112 - 0
Emby.Common.Implementations/ScheduledTasks/IntervalTrigger.cs

@@ -0,0 +1,112 @@
+using System;
+using System.Linq;
+using System.Threading;
+using MediaBrowser.Model.Events;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Tasks;
+
+namespace Emby.Common.Implementations.ScheduledTasks
+{
+    /// <summary>
+    /// Represents a task trigger that runs repeatedly on an interval
+    /// </summary>
+    public class IntervalTrigger : ITaskTrigger
+    {
+        /// <summary>
+        /// Gets or sets the interval.
+        /// </summary>
+        /// <value>The interval.</value>
+        public TimeSpan Interval { get; set; }
+
+        /// <summary>
+        /// Gets or sets the timer.
+        /// </summary>
+        /// <value>The timer.</value>
+        private Timer Timer { get; set; }
+
+        /// <summary>
+        /// Gets the execution properties of this task.
+        /// </summary>
+        /// <value>
+        /// The execution properties of this task.
+        /// </value>
+        public TaskExecutionOptions TaskOptions { get; set; }
+
+        private DateTime _lastStartDate;
+
+        /// <summary>
+        /// Stars waiting for the trigger action
+        /// </summary>
+        /// <param name="lastResult">The last result.</param>
+        /// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
+        public void Start(TaskResult lastResult, ILogger logger, string taskName, bool isApplicationStartup)
+        {
+            DisposeTimer();
+
+            DateTime triggerDate;
+
+            if (lastResult == null)
+            {
+                // Task has never been completed before
+                triggerDate = DateTime.UtcNow.AddHours(1);
+            }
+            else
+            {
+                triggerDate = new[] { lastResult.EndTimeUtc, _lastStartDate }.Max().Add(Interval);
+            }
+
+            if (DateTime.UtcNow > triggerDate)
+            {
+                triggerDate = DateTime.UtcNow.AddMinutes(1);
+            }
+
+            var dueTime = triggerDate - DateTime.UtcNow;
+            var maxDueTime = TimeSpan.FromDays(7);
+
+            if (dueTime > maxDueTime)
+            {
+                dueTime = maxDueTime;
+            }
+
+            Timer = new Timer(state => OnTriggered(), null, dueTime, TimeSpan.FromMilliseconds(-1));
+        }
+
+        /// <summary>
+        /// Stops waiting for the trigger action
+        /// </summary>
+        public void Stop()
+        {
+            DisposeTimer();
+        }
+
+        /// <summary>
+        /// Disposes the timer.
+        /// </summary>
+        private void DisposeTimer()
+        {
+            if (Timer != null)
+            {
+                Timer.Dispose();
+            }
+        }
+
+        /// <summary>
+        /// Occurs when [triggered].
+        /// </summary>
+        public event EventHandler<GenericEventArgs<TaskExecutionOptions>> Triggered;
+
+        /// <summary>
+        /// Called when [triggered].
+        /// </summary>
+        private void OnTriggered()
+        {
+            DisposeTimer();
+
+            if (Triggered != null)
+            {
+                _lastStartDate = DateTime.UtcNow;
+                Triggered(this, new GenericEventArgs<TaskExecutionOptions>(TaskOptions));
+            }
+        }
+    }
+}

+ 782 - 0
Emby.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs

@@ -0,0 +1,782 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Events;
+using MediaBrowser.Common.Extensions;
+using MediaBrowser.Model.Events;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Serialization;
+using MediaBrowser.Model.System;
+using MediaBrowser.Model.Tasks;
+
+namespace Emby.Common.Implementations.ScheduledTasks
+{
+    /// <summary>
+    /// Class ScheduledTaskWorker
+    /// </summary>
+    public class ScheduledTaskWorker : IScheduledTaskWorker
+    {
+        public event EventHandler<GenericEventArgs<double>> TaskProgress;
+
+        /// <summary>
+        /// Gets or sets the scheduled task.
+        /// </summary>
+        /// <value>The scheduled task.</value>
+        public IScheduledTask ScheduledTask { get; private set; }
+
+        /// <summary>
+        /// Gets or sets the json serializer.
+        /// </summary>
+        /// <value>The json serializer.</value>
+        private IJsonSerializer JsonSerializer { get; set; }
+
+        /// <summary>
+        /// Gets or sets the application paths.
+        /// </summary>
+        /// <value>The application paths.</value>
+        private IApplicationPaths ApplicationPaths { get; set; }
+
+        /// <summary>
+        /// Gets the logger.
+        /// </summary>
+        /// <value>The logger.</value>
+        private ILogger Logger { get; set; }
+
+        /// <summary>
+        /// Gets the task manager.
+        /// </summary>
+        /// <value>The task manager.</value>
+        private ITaskManager TaskManager { get; set; }
+        private readonly IFileSystem _fileSystem;
+        private readonly ISystemEvents _systemEvents;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ScheduledTaskWorker" /> class.
+        /// </summary>
+        /// <param name="scheduledTask">The scheduled task.</param>
+        /// <param name="applicationPaths">The application paths.</param>
+        /// <param name="taskManager">The task manager.</param>
+        /// <param name="jsonSerializer">The json serializer.</param>
+        /// <param name="logger">The logger.</param>
+        /// <exception cref="System.ArgumentNullException">
+        /// scheduledTask
+        /// or
+        /// applicationPaths
+        /// or
+        /// taskManager
+        /// or
+        /// jsonSerializer
+        /// or
+        /// logger
+        /// </exception>
+        public ScheduledTaskWorker(IScheduledTask scheduledTask, IApplicationPaths applicationPaths, ITaskManager taskManager, IJsonSerializer jsonSerializer, ILogger logger, IFileSystem fileSystem, ISystemEvents systemEvents)
+        {
+            if (scheduledTask == null)
+            {
+                throw new ArgumentNullException("scheduledTask");
+            }
+            if (applicationPaths == null)
+            {
+                throw new ArgumentNullException("applicationPaths");
+            }
+            if (taskManager == null)
+            {
+                throw new ArgumentNullException("taskManager");
+            }
+            if (jsonSerializer == null)
+            {
+                throw new ArgumentNullException("jsonSerializer");
+            }
+            if (logger == null)
+            {
+                throw new ArgumentNullException("logger");
+            }
+
+            ScheduledTask = scheduledTask;
+            ApplicationPaths = applicationPaths;
+            TaskManager = taskManager;
+            JsonSerializer = jsonSerializer;
+            Logger = logger;
+            _fileSystem = fileSystem;
+            _systemEvents = systemEvents;
+
+            InitTriggerEvents();
+        }
+
+        private bool _readFromFile = false;
+        /// <summary>
+        /// The _last execution result
+        /// </summary>
+        private TaskResult _lastExecutionResult;
+        /// <summary>
+        /// The _last execution result sync lock
+        /// </summary>
+        private readonly object _lastExecutionResultSyncLock = new object();
+        /// <summary>
+        /// Gets the last execution result.
+        /// </summary>
+        /// <value>The last execution result.</value>
+        public TaskResult LastExecutionResult
+        {
+            get
+            {
+                var path = GetHistoryFilePath();
+
+                lock (_lastExecutionResultSyncLock)
+                {
+                    if (_lastExecutionResult == null && !_readFromFile)
+                    {
+                        try
+                        {
+                            _lastExecutionResult = JsonSerializer.DeserializeFromFile<TaskResult>(path);
+                        }
+                        catch (DirectoryNotFoundException)
+                        {
+                            // File doesn't exist. No biggie
+                        }
+                        catch (FileNotFoundException)
+                        {
+                            // File doesn't exist. No biggie
+                        }
+                        catch (Exception ex)
+                        {
+                            Logger.ErrorException("Error deserializing {0}", ex, path);
+                        }
+                        _readFromFile = true;
+                    }
+                }
+
+                return _lastExecutionResult;
+            }
+            private set
+            {
+                _lastExecutionResult = value;
+
+                var path = GetHistoryFilePath();
+				_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+
+                lock (_lastExecutionResultSyncLock)
+                {
+                    JsonSerializer.SerializeToFile(value, path);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets the name.
+        /// </summary>
+        /// <value>The name.</value>
+        public string Name
+        {
+            get { return ScheduledTask.Name; }
+        }
+
+        /// <summary>
+        /// Gets the description.
+        /// </summary>
+        /// <value>The description.</value>
+        public string Description
+        {
+            get { return ScheduledTask.Description; }
+        }
+
+        /// <summary>
+        /// Gets the category.
+        /// </summary>
+        /// <value>The category.</value>
+        public string Category
+        {
+            get { return ScheduledTask.Category; }
+        }
+
+        /// <summary>
+        /// Gets the current cancellation token
+        /// </summary>
+        /// <value>The current cancellation token source.</value>
+        private CancellationTokenSource CurrentCancellationTokenSource { get; set; }
+
+        /// <summary>
+        /// Gets or sets the current execution start time.
+        /// </summary>
+        /// <value>The current execution start time.</value>
+        private DateTime CurrentExecutionStartTime { get; set; }
+
+        /// <summary>
+        /// Gets the state.
+        /// </summary>
+        /// <value>The state.</value>
+        public TaskState State
+        {
+            get
+            {
+                if (CurrentCancellationTokenSource != null)
+                {
+                    return CurrentCancellationTokenSource.IsCancellationRequested
+                               ? TaskState.Cancelling
+                               : TaskState.Running;
+                }
+
+                return TaskState.Idle;
+            }
+        }
+
+        /// <summary>
+        /// Gets the current progress.
+        /// </summary>
+        /// <value>The current progress.</value>
+        public double? CurrentProgress { get; private set; }
+
+        /// <summary>
+        /// The _triggers
+        /// </summary>
+        private Tuple<TaskTriggerInfo,ITaskTrigger>[] _triggers;
+        /// <summary>
+        /// Gets the triggers that define when the task will run
+        /// </summary>
+        /// <value>The triggers.</value>
+        private Tuple<TaskTriggerInfo, ITaskTrigger>[] InternalTriggers
+        {
+            get
+            {
+                return _triggers;
+            }
+            set
+            {
+                if (value == null)
+                {
+                    throw new ArgumentNullException("value");
+                }
+
+                // Cleanup current triggers
+                if (_triggers != null)
+                {
+                    DisposeTriggers();
+                }
+
+                _triggers = value.ToArray();
+
+                ReloadTriggerEvents(false);
+            }
+        }
+
+        /// <summary>
+        /// Gets the triggers that define when the task will run
+        /// </summary>
+        /// <value>The triggers.</value>
+        /// <exception cref="System.ArgumentNullException">value</exception>
+        public TaskTriggerInfo[] Triggers
+        {
+            get
+            {
+                return InternalTriggers.Select(i => i.Item1).ToArray();
+            }
+            set
+            {
+                if (value == null)
+                {
+                    throw new ArgumentNullException("value");
+                }
+
+                SaveTriggers(value);
+
+                InternalTriggers = value.Select(i => new Tuple<TaskTriggerInfo, ITaskTrigger>(i, GetTrigger(i))).ToArray();
+            }
+        }
+
+        /// <summary>
+        /// The _id
+        /// </summary>
+        private string _id;
+
+        /// <summary>
+        /// Gets the unique id.
+        /// </summary>
+        /// <value>The unique id.</value>
+        public string Id
+        {
+            get
+            {
+                if (_id == null)
+                {
+                    _id = ScheduledTask.GetType().FullName.GetMD5().ToString("N");
+                }
+
+                return _id;
+            }
+        }
+
+        private void InitTriggerEvents()
+        {
+            _triggers = LoadTriggers();
+            ReloadTriggerEvents(true);
+        }
+
+        public void ReloadTriggerEvents()
+        {
+            ReloadTriggerEvents(false);
+        }
+
+        /// <summary>
+        /// Reloads the trigger events.
+        /// </summary>
+        /// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
+        private void ReloadTriggerEvents(bool isApplicationStartup)
+        {
+            foreach (var triggerInfo in InternalTriggers)
+            {
+                var trigger = triggerInfo.Item2;
+
+                trigger.Stop();
+
+                trigger.Triggered -= trigger_Triggered;
+                trigger.Triggered += trigger_Triggered;
+                trigger.Start(LastExecutionResult, Logger, Name, isApplicationStartup);
+            }
+        }
+
+        /// <summary>
+        /// Handles the Triggered event of the trigger control.
+        /// </summary>
+        /// <param name="sender">The source of the event.</param>
+        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
+        async void trigger_Triggered(object sender, GenericEventArgs<TaskExecutionOptions> e)
+        {
+            var trigger = (ITaskTrigger)sender;
+
+            var configurableTask = ScheduledTask as IConfigurableScheduledTask;
+
+            if (configurableTask != null && !configurableTask.IsEnabled)
+            {
+                return;
+            }
+
+            Logger.Info("{0} fired for task: {1}", trigger.GetType().Name, Name);
+
+            trigger.Stop();
+
+            TaskManager.QueueScheduledTask(ScheduledTask, e.Argument);
+
+            await Task.Delay(1000).ConfigureAwait(false);
+
+            trigger.Start(LastExecutionResult, Logger, Name, false);
+        }
+
+        private Task _currentTask;
+
+        /// <summary>
+        /// Executes the task
+        /// </summary>
+        /// <param name="options">Task options.</param>
+        /// <returns>Task.</returns>
+        /// <exception cref="System.InvalidOperationException">Cannot execute a Task that is already running</exception>
+        public async Task Execute(TaskExecutionOptions options)
+        {
+            var task = ExecuteInternal(options);
+
+            _currentTask = task;
+
+            try
+            {
+                await task.ConfigureAwait(false);
+            }
+            finally
+            {
+                _currentTask = null;
+            }
+        }
+
+        private async Task ExecuteInternal(TaskExecutionOptions options)
+        {
+            // Cancel the current execution, if any
+            if (CurrentCancellationTokenSource != null)
+            {
+                throw new InvalidOperationException("Cannot execute a Task that is already running");
+            }
+
+            var progress = new Progress<double>();
+
+            CurrentCancellationTokenSource = new CancellationTokenSource();
+
+            Logger.Info("Executing {0}", Name);
+
+            ((TaskManager)TaskManager).OnTaskExecuting(this);
+
+            progress.ProgressChanged += progress_ProgressChanged;
+
+            TaskCompletionStatus status;
+            CurrentExecutionStartTime = DateTime.UtcNow;
+
+            Exception failureException = null;
+
+            try
+            {
+                if (options != null && options.MaxRuntimeMs.HasValue)
+                {
+                    CurrentCancellationTokenSource.CancelAfter(options.MaxRuntimeMs.Value);
+                }
+
+                var localTask = ScheduledTask.Execute(CurrentCancellationTokenSource.Token, progress);
+
+                await localTask.ConfigureAwait(false);
+
+                status = TaskCompletionStatus.Completed;
+            }
+            catch (OperationCanceledException)
+            {
+                status = TaskCompletionStatus.Cancelled;
+            }
+            catch (Exception ex)
+            {
+                Logger.ErrorException("Error", ex);
+
+                failureException = ex;
+
+                status = TaskCompletionStatus.Failed;
+            }
+
+            var startTime = CurrentExecutionStartTime;
+            var endTime = DateTime.UtcNow;
+
+            progress.ProgressChanged -= progress_ProgressChanged;
+            CurrentCancellationTokenSource.Dispose();
+            CurrentCancellationTokenSource = null;
+            CurrentProgress = null;
+
+            OnTaskCompleted(startTime, endTime, status, failureException);
+        }
+
+        /// <summary>
+        /// Progress_s the progress changed.
+        /// </summary>
+        /// <param name="sender">The sender.</param>
+        /// <param name="e">The e.</param>
+        void progress_ProgressChanged(object sender, double e)
+        {
+            CurrentProgress = e;
+
+            EventHelper.FireEventIfNotNull(TaskProgress, this, new GenericEventArgs<double>
+            {
+                Argument = e
+
+            }, Logger);
+        }
+
+        /// <summary>
+        /// Stops the task if it is currently executing
+        /// </summary>
+        /// <exception cref="System.InvalidOperationException">Cannot cancel a Task unless it is in the Running state.</exception>
+        public void Cancel()
+        {
+            if (State != TaskState.Running)
+            {
+                throw new InvalidOperationException("Cannot cancel a Task unless it is in the Running state.");
+            }
+
+            CancelIfRunning();
+        }
+
+        /// <summary>
+        /// Cancels if running.
+        /// </summary>
+        public void CancelIfRunning()
+        {
+            if (State == TaskState.Running)
+            {
+                Logger.Info("Attempting to cancel Scheduled Task {0}", Name);
+                CurrentCancellationTokenSource.Cancel();
+            }
+        }
+
+        /// <summary>
+        /// Gets the scheduled tasks configuration directory.
+        /// </summary>
+        /// <returns>System.String.</returns>
+        private string GetScheduledTasksConfigurationDirectory()
+        {
+            return Path.Combine(ApplicationPaths.ConfigurationDirectoryPath, "ScheduledTasks");
+        }
+
+        /// <summary>
+        /// Gets the scheduled tasks data directory.
+        /// </summary>
+        /// <returns>System.String.</returns>
+        private string GetScheduledTasksDataDirectory()
+        {
+            return Path.Combine(ApplicationPaths.DataPath, "ScheduledTasks");
+        }
+
+        /// <summary>
+        /// Gets the history file path.
+        /// </summary>
+        /// <value>The history file path.</value>
+        private string GetHistoryFilePath()
+        {
+            return Path.Combine(GetScheduledTasksDataDirectory(), new Guid(Id) + ".js");
+        }
+
+        /// <summary>
+        /// Gets the configuration file path.
+        /// </summary>
+        /// <returns>System.String.</returns>
+        private string GetConfigurationFilePath()
+        {
+            return Path.Combine(GetScheduledTasksConfigurationDirectory(), new Guid(Id) + ".js");
+        }
+
+        /// <summary>
+        /// Loads the triggers.
+        /// </summary>
+        /// <returns>IEnumerable{BaseTaskTrigger}.</returns>
+        private Tuple<TaskTriggerInfo, ITaskTrigger>[] LoadTriggers()
+        {
+            var settings = LoadTriggerSettings();
+
+            return settings.Select(i => new Tuple<TaskTriggerInfo, ITaskTrigger>(i, GetTrigger(i))).ToArray();
+        }
+
+        private TaskTriggerInfo[] LoadTriggerSettings()
+        {
+            try
+            {
+                return JsonSerializer.DeserializeFromFile<IEnumerable<TaskTriggerInfo>>(GetConfigurationFilePath())
+                .ToArray();
+            }
+            catch (FileNotFoundException)
+            {
+                // File doesn't exist. No biggie. Return defaults.
+                return ScheduledTask.GetDefaultTriggers().ToArray();
+            }
+            catch (DirectoryNotFoundException)
+            {
+                // File doesn't exist. No biggie. Return defaults.
+                return ScheduledTask.GetDefaultTriggers().ToArray();
+            }
+        }
+
+        /// <summary>
+        /// Saves the triggers.
+        /// </summary>
+        /// <param name="triggers">The triggers.</param>
+        private void SaveTriggers(TaskTriggerInfo[] triggers)
+        {
+            var path = GetConfigurationFilePath();
+
+			_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+
+            JsonSerializer.SerializeToFile(triggers, path);
+        }
+
+        /// <summary>
+        /// Called when [task completed].
+        /// </summary>
+        /// <param name="startTime">The start time.</param>
+        /// <param name="endTime">The end time.</param>
+        /// <param name="status">The status.</param>
+        private void OnTaskCompleted(DateTime startTime, DateTime endTime, TaskCompletionStatus status, Exception ex)
+        {
+            var elapsedTime = endTime - startTime;
+
+            Logger.Info("{0} {1} after {2} minute(s) and {3} seconds", Name, status, Math.Truncate(elapsedTime.TotalMinutes), elapsedTime.Seconds);
+
+            var result = new TaskResult
+            {
+                StartTimeUtc = startTime,
+                EndTimeUtc = endTime,
+                Status = status,
+                Name = Name,
+                Id = Id
+            };
+
+            result.Key = ScheduledTask.Key;
+
+            if (ex != null)
+            {
+                result.ErrorMessage = ex.Message;
+                result.LongErrorMessage = ex.StackTrace;
+            }
+
+            LastExecutionResult = result;
+
+            ((TaskManager)TaskManager).OnTaskCompleted(this, result);
+        }
+
+        /// <summary>
+        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+        /// </summary>
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        /// <summary>
+        /// Releases unmanaged and - optionally - managed resources.
+        /// </summary>
+        /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+        protected virtual void Dispose(bool dispose)
+        {
+            if (dispose)
+            {
+                DisposeTriggers();
+
+                var wassRunning = State == TaskState.Running;
+                var startTime = CurrentExecutionStartTime;
+
+                var token = CurrentCancellationTokenSource;
+                if (token != null)
+                {
+                    try
+                    {
+                        Logger.Info(Name + ": Cancelling");
+                        token.Cancel();
+                    }
+                    catch (Exception ex)
+                    {
+                        Logger.ErrorException("Error calling CancellationToken.Cancel();", ex);
+                    }
+                }
+                var task = _currentTask;
+                if (task != null)
+                {
+                    try
+                    {
+                        Logger.Info(Name + ": Waiting on Task");
+                        var exited = Task.WaitAll(new[] { task }, 2000);
+
+                        if (exited)
+                        {
+                            Logger.Info(Name + ": Task exited");
+                        }
+                        else
+                        {
+                            Logger.Info(Name + ": Timed out waiting for task to stop");
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        Logger.ErrorException("Error calling Task.WaitAll();", ex);
+                    }
+                }
+
+                if (token != null)
+                {
+                    try
+                    {
+                        Logger.Debug(Name + ": Disposing CancellationToken");
+                        token.Dispose();
+                    }
+                    catch (Exception ex)
+                    {
+                        Logger.ErrorException("Error calling CancellationToken.Dispose();", ex);
+                    }
+                }
+                if (wassRunning)
+                {
+                    OnTaskCompleted(startTime, DateTime.UtcNow, TaskCompletionStatus.Aborted, null);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Converts a TaskTriggerInfo into a concrete BaseTaskTrigger
+        /// </summary>
+        /// <param name="info">The info.</param>
+        /// <returns>BaseTaskTrigger.</returns>
+        /// <exception cref="System.ArgumentNullException"></exception>
+        /// <exception cref="System.ArgumentException">Invalid trigger type:  + info.Type</exception>
+        private ITaskTrigger GetTrigger(TaskTriggerInfo info)
+        {
+            var options = new TaskExecutionOptions
+            {
+                MaxRuntimeMs = info.MaxRuntimeMs
+            };
+
+            if (info.Type.Equals(typeof(DailyTrigger).Name, StringComparison.OrdinalIgnoreCase))
+            {
+                if (!info.TimeOfDayTicks.HasValue)
+                {
+                    throw new ArgumentNullException();
+                }
+
+                return new DailyTrigger
+                {
+                    TimeOfDay = TimeSpan.FromTicks(info.TimeOfDayTicks.Value),
+                    TaskOptions = options
+                };
+            }
+
+            if (info.Type.Equals(typeof(WeeklyTrigger).Name, StringComparison.OrdinalIgnoreCase))
+            {
+                if (!info.TimeOfDayTicks.HasValue)
+                {
+                    throw new ArgumentNullException();
+                }
+
+                if (!info.DayOfWeek.HasValue)
+                {
+                    throw new ArgumentNullException();
+                }
+
+                return new WeeklyTrigger
+                {
+                    TimeOfDay = TimeSpan.FromTicks(info.TimeOfDayTicks.Value),
+                    DayOfWeek = info.DayOfWeek.Value,
+                    TaskOptions = options
+                };
+            }
+
+            if (info.Type.Equals(typeof(IntervalTrigger).Name, StringComparison.OrdinalIgnoreCase))
+            {
+                if (!info.IntervalTicks.HasValue)
+                {
+                    throw new ArgumentNullException();
+                }
+
+                return new IntervalTrigger
+                {
+                    Interval = TimeSpan.FromTicks(info.IntervalTicks.Value),
+                    TaskOptions = options
+                };
+            }
+
+            if (info.Type.Equals(typeof(SystemEventTrigger).Name, StringComparison.OrdinalIgnoreCase))
+            {
+                if (!info.SystemEvent.HasValue)
+                {
+                    throw new ArgumentNullException();
+                }
+
+                return new SystemEventTrigger(_systemEvents)
+                {
+                    SystemEvent = info.SystemEvent.Value,
+                    TaskOptions = options
+                };
+            }
+
+            if (info.Type.Equals(typeof(StartupTrigger).Name, StringComparison.OrdinalIgnoreCase))
+            {
+                return new StartupTrigger();
+            }
+
+            throw new ArgumentException("Unrecognized trigger type: " + info.Type);
+        }
+
+        /// <summary>
+        /// Disposes each trigger
+        /// </summary>
+        private void DisposeTriggers()
+        {
+            foreach (var triggerInfo in InternalTriggers)
+            {
+                var trigger = triggerInfo.Item2;
+                trigger.Triggered -= trigger_Triggered;
+                trigger.Stop();
+            }
+        }
+    }
+}

+ 67 - 0
Emby.Common.Implementations/ScheduledTasks/StartupTrigger.cs

@@ -0,0 +1,67 @@
+using System;
+using System.Threading.Tasks;
+using MediaBrowser.Model.Events;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Tasks;
+
+namespace Emby.Common.Implementations.ScheduledTasks
+{
+    /// <summary>
+    /// Class StartupTaskTrigger
+    /// </summary>
+    public class StartupTrigger : ITaskTrigger
+    {
+        public int DelayMs { get; set; }
+
+        /// <summary>
+        /// Gets the execution properties of this task.
+        /// </summary>
+        /// <value>
+        /// The execution properties of this task.
+        /// </value>
+        public TaskExecutionOptions TaskOptions { get; set; }
+
+        public StartupTrigger()
+        {
+            DelayMs = 3000;
+        }
+
+        /// <summary>
+        /// Stars waiting for the trigger action
+        /// </summary>
+        /// <param name="lastResult">The last result.</param>
+        /// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
+        public async void Start(TaskResult lastResult, ILogger logger, string taskName, bool isApplicationStartup)
+        {
+            if (isApplicationStartup)
+            {
+                await Task.Delay(DelayMs).ConfigureAwait(false);
+
+                OnTriggered();
+            }
+        }
+
+        /// <summary>
+        /// Stops waiting for the trigger action
+        /// </summary>
+        public void Stop()
+        {
+        }
+
+        /// <summary>
+        /// Occurs when [triggered].
+        /// </summary>
+        public event EventHandler<GenericEventArgs<TaskExecutionOptions>> Triggered;
+
+        /// <summary>
+        /// Called when [triggered].
+        /// </summary>
+        private void OnTriggered()
+        {
+            if (Triggered != null)
+            {
+                Triggered(this, new GenericEventArgs<TaskExecutionOptions>(TaskOptions));
+            }
+        }
+    }
+}

+ 86 - 0
Emby.Common.Implementations/ScheduledTasks/SystemEventTrigger.cs

@@ -0,0 +1,86 @@
+using System;
+using System.Threading.Tasks;
+using MediaBrowser.Model.Events;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.System;
+using MediaBrowser.Model.Tasks;
+
+namespace Emby.Common.Implementations.ScheduledTasks
+{
+    /// <summary>
+    /// Class SystemEventTrigger
+    /// </summary>
+    public class SystemEventTrigger : ITaskTrigger
+    {
+        /// <summary>
+        /// Gets or sets the system event.
+        /// </summary>
+        /// <value>The system event.</value>
+        public SystemEvent SystemEvent { get; set; }
+
+        /// <summary>
+        /// Gets the execution properties of this task.
+        /// </summary>
+        /// <value>
+        /// The execution properties of this task.
+        /// </value>
+        public TaskExecutionOptions TaskOptions { get; set; }
+
+        private readonly ISystemEvents _systemEvents;
+
+        public SystemEventTrigger(ISystemEvents systemEvents)
+        {
+            _systemEvents = systemEvents;
+        }
+
+        /// <summary>
+        /// Stars waiting for the trigger action
+        /// </summary>
+        /// <param name="lastResult">The last result.</param>
+        /// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
+        public void Start(TaskResult lastResult, ILogger logger, string taskName, bool isApplicationStartup)
+        {
+            switch (SystemEvent)
+            {
+                case SystemEvent.WakeFromSleep:
+                    _systemEvents.Resume += _systemEvents_Resume;
+                    break;
+            }
+        }
+
+        private async void _systemEvents_Resume(object sender, EventArgs e)
+        {
+            if (SystemEvent == SystemEvent.WakeFromSleep)
+            {
+                // This value is a bit arbitrary, but add a delay to help ensure network connections have been restored before running the task
+                await Task.Delay(10000).ConfigureAwait(false);
+
+                OnTriggered();
+            }
+        }
+
+        /// <summary>
+        /// Stops waiting for the trigger action
+        /// </summary>
+        public void Stop()
+        {
+            _systemEvents.Resume -= _systemEvents_Resume;
+        }
+
+        /// <summary>
+        /// Occurs when [triggered].
+        /// </summary>
+        public event EventHandler<GenericEventArgs<TaskExecutionOptions>> Triggered;
+
+        /// <summary>
+        /// Called when [triggered].
+        /// </summary>
+        private void OnTriggered()
+        {
+            if (Triggered != null)
+            {
+                Triggered(this, new GenericEventArgs<TaskExecutionOptions>(TaskOptions));
+            }
+        }
+    }
+}

+ 358 - 0
Emby.Common.Implementations/ScheduledTasks/TaskManager.cs

@@ -0,0 +1,358 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Events;
+using MediaBrowser.Model.Events;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Serialization;
+using MediaBrowser.Model.Tasks;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.System;
+
+namespace Emby.Common.Implementations.ScheduledTasks
+{
+    /// <summary>
+    /// Class TaskManager
+    /// </summary>
+    public class TaskManager : ITaskManager
+    {
+        public event EventHandler<GenericEventArgs<IScheduledTaskWorker>> TaskExecuting;
+        public event EventHandler<TaskCompletionEventArgs> TaskCompleted;
+
+        /// <summary>
+        /// Gets the list of Scheduled Tasks
+        /// </summary>
+        /// <value>The scheduled tasks.</value>
+        public IScheduledTaskWorker[] ScheduledTasks { get; private set; }
+
+        /// <summary>
+        /// The _task queue
+        /// </summary>
+        private readonly ConcurrentQueue<Tuple<Type, TaskExecutionOptions>> _taskQueue =
+            new ConcurrentQueue<Tuple<Type, TaskExecutionOptions>>();
+
+        /// <summary>
+        /// Gets or sets the json serializer.
+        /// </summary>
+        /// <value>The json serializer.</value>
+        private IJsonSerializer JsonSerializer { get; set; }
+
+        /// <summary>
+        /// Gets or sets the application paths.
+        /// </summary>
+        /// <value>The application paths.</value>
+        private IApplicationPaths ApplicationPaths { get; set; }
+
+        private readonly ISystemEvents _systemEvents;
+
+        /// <summary>
+        /// Gets the logger.
+        /// </summary>
+        /// <value>The logger.</value>
+        private ILogger Logger { get; set; }
+        private readonly IFileSystem _fileSystem;
+
+        private bool _suspendTriggers;
+
+        public bool SuspendTriggers
+        {
+            get { return _suspendTriggers; }
+            set
+            {
+                Logger.Info("Setting SuspendTriggers to {0}", value);
+                var executeQueued = _suspendTriggers && !value;
+
+                _suspendTriggers = value;
+
+                if (executeQueued)
+                {
+                    ExecuteQueuedTasks();
+                }
+            }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="TaskManager" /> class.
+        /// </summary>
+        /// <param name="applicationPaths">The application paths.</param>
+        /// <param name="jsonSerializer">The json serializer.</param>
+        /// <param name="logger">The logger.</param>
+        /// <exception cref="System.ArgumentException">kernel</exception>
+        public TaskManager(IApplicationPaths applicationPaths, IJsonSerializer jsonSerializer, ILogger logger, IFileSystem fileSystem, ISystemEvents systemEvents)
+        {
+            ApplicationPaths = applicationPaths;
+            JsonSerializer = jsonSerializer;
+            Logger = logger;
+            _fileSystem = fileSystem;
+            _systemEvents = systemEvents;
+
+            ScheduledTasks = new IScheduledTaskWorker[] { };
+        }
+
+        private void BindToSystemEvent()
+        {
+            _systemEvents.Resume += _systemEvents_Resume;
+        }
+
+        private void _systemEvents_Resume(object sender, EventArgs e)
+        {
+            foreach (var task in ScheduledTasks)
+            {
+                task.ReloadTriggerEvents();
+            }
+        }
+
+        /// <summary>
+        /// Cancels if running and queue.
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="options">Task options.</param>
+        public void CancelIfRunningAndQueue<T>(TaskExecutionOptions options)
+                 where T : IScheduledTask
+        {
+            var task = ScheduledTasks.First(t => t.ScheduledTask.GetType() == typeof(T));
+            ((ScheduledTaskWorker)task).CancelIfRunning();
+
+            QueueScheduledTask<T>(options);
+        }
+
+        public void CancelIfRunningAndQueue<T>()
+               where T : IScheduledTask
+        {
+            CancelIfRunningAndQueue<T>(new TaskExecutionOptions());
+        }
+
+        /// <summary>
+        /// Cancels if running
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        public void CancelIfRunning<T>()
+                 where T : IScheduledTask
+        {
+            var task = ScheduledTasks.First(t => t.ScheduledTask.GetType() == typeof(T));
+            ((ScheduledTaskWorker)task).CancelIfRunning();
+        }
+
+        /// <summary>
+        /// Queues the scheduled task.
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="options">Task options</param>
+        public void QueueScheduledTask<T>(TaskExecutionOptions options)
+            where T : IScheduledTask
+        {
+            var scheduledTask = ScheduledTasks.FirstOrDefault(t => t.ScheduledTask.GetType() == typeof(T));
+
+            if (scheduledTask == null)
+            {
+                Logger.Error("Unable to find scheduled task of type {0} in QueueScheduledTask.", typeof(T).Name);
+            }
+            else
+            {
+                QueueScheduledTask(scheduledTask, options);
+            }
+        }
+
+        public void QueueScheduledTask<T>()
+            where T : IScheduledTask
+        {
+            QueueScheduledTask<T>(new TaskExecutionOptions());
+        }
+
+        public void QueueIfNotRunning<T>()
+            where T : IScheduledTask
+        {
+            var task = ScheduledTasks.First(t => t.ScheduledTask.GetType() == typeof(T));
+
+            if (task.State != TaskState.Running)
+            {
+                QueueScheduledTask<T>(new TaskExecutionOptions());
+            }
+        }
+
+        public void Execute<T>()
+            where T : IScheduledTask
+        {
+            var scheduledTask = ScheduledTasks.FirstOrDefault(t => t.ScheduledTask.GetType() == typeof(T));
+
+            if (scheduledTask == null)
+            {
+                Logger.Error("Unable to find scheduled task of type {0} in Execute.", typeof(T).Name);
+            }
+            else
+            {
+                var type = scheduledTask.ScheduledTask.GetType();
+
+                Logger.Info("Queueing task {0}", type.Name);
+
+                lock (_taskQueue)
+                {
+                    if (scheduledTask.State == TaskState.Idle)
+                    {
+                        Execute(scheduledTask, new TaskExecutionOptions());
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// Queues the scheduled task.
+        /// </summary>
+        /// <param name="task">The task.</param>
+        /// <param name="options">The task options.</param>
+        public void QueueScheduledTask(IScheduledTask task, TaskExecutionOptions options)
+        {
+            var scheduledTask = ScheduledTasks.FirstOrDefault(t => t.ScheduledTask.GetType() == task.GetType());
+
+            if (scheduledTask == null)
+            {
+                Logger.Error("Unable to find scheduled task of type {0} in QueueScheduledTask.", task.GetType().Name);
+            }
+            else
+            {
+                QueueScheduledTask(scheduledTask, options);
+            }
+        }
+
+        /// <summary>
+        /// Queues the scheduled task.
+        /// </summary>
+        /// <param name="task">The task.</param>
+        /// <param name="options">The task options.</param>
+        private void QueueScheduledTask(IScheduledTaskWorker task, TaskExecutionOptions options)
+        {
+            var type = task.ScheduledTask.GetType();
+
+            Logger.Info("Queueing task {0}", type.Name);
+
+            lock (_taskQueue)
+            {
+                if (task.State == TaskState.Idle && !SuspendTriggers)
+                {
+                    Execute(task, options);
+                    return;
+                }
+
+                _taskQueue.Enqueue(new Tuple<Type, TaskExecutionOptions>(type, options));
+            }
+        }
+
+        /// <summary>
+        /// Adds the tasks.
+        /// </summary>
+        /// <param name="tasks">The tasks.</param>
+        public void AddTasks(IEnumerable<IScheduledTask> tasks)
+        {
+            var myTasks = ScheduledTasks.ToList();
+
+            var list = tasks.ToList();
+            myTasks.AddRange(list.Select(t => new ScheduledTaskWorker(t, ApplicationPaths, this, JsonSerializer, Logger, _fileSystem)));
+
+            ScheduledTasks = myTasks.ToArray();
+
+            BindToSystemEvent();
+        }
+
+        /// <summary>
+        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+        /// </summary>
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        /// <summary>
+        /// Releases unmanaged and - optionally - managed resources.
+        /// </summary>
+        /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+        protected virtual void Dispose(bool dispose)
+        {
+            foreach (var task in ScheduledTasks)
+            {
+                task.Dispose();
+            }
+        }
+
+        public void Cancel(IScheduledTaskWorker task)
+        {
+            ((ScheduledTaskWorker)task).Cancel();
+        }
+
+        public Task Execute(IScheduledTaskWorker task, TaskExecutionOptions options)
+        {
+            return ((ScheduledTaskWorker)task).Execute(options);
+        }
+
+        /// <summary>
+        /// Called when [task executing].
+        /// </summary>
+        /// <param name="task">The task.</param>
+        internal void OnTaskExecuting(IScheduledTaskWorker task)
+        {
+            EventHelper.FireEventIfNotNull(TaskExecuting, this, new GenericEventArgs<IScheduledTaskWorker>
+            {
+                Argument = task
+
+            }, Logger);
+        }
+
+        /// <summary>
+        /// Called when [task completed].
+        /// </summary>
+        /// <param name="task">The task.</param>
+        /// <param name="result">The result.</param>
+        internal void OnTaskCompleted(IScheduledTaskWorker task, TaskResult result)
+        {
+            EventHelper.FireEventIfNotNull(TaskCompleted, task, new TaskCompletionEventArgs
+            {
+                Result = result,
+                Task = task
+
+            }, Logger);
+
+            ExecuteQueuedTasks();
+        }
+
+        /// <summary>
+        /// Executes the queued tasks.
+        /// </summary>
+        private void ExecuteQueuedTasks()
+        {
+            if (SuspendTriggers)
+            {
+                return;
+            }
+
+            Logger.Info("ExecuteQueuedTasks");
+
+            // Execute queued tasks
+            lock (_taskQueue)
+            {
+                var list = new List<Tuple<Type, TaskExecutionOptions>>();
+
+                Tuple<Type, TaskExecutionOptions> item;
+                while (_taskQueue.TryDequeue(out item))
+                {
+                    if (list.All(i => i.Item1 != item.Item1))
+                    {
+                        list.Add(item);
+                    }
+                }
+
+                foreach (var enqueuedType in list)
+                {
+                    var scheduledTask = ScheduledTasks.First(t => t.ScheduledTask.GetType() == enqueuedType.Item1);
+
+                    if (scheduledTask.State == TaskState.Idle)
+                    {
+                        Execute(scheduledTask, enqueuedType.Item2);
+                    }
+                }
+            }
+        }
+    }
+}

+ 215 - 0
Emby.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs

@@ -0,0 +1,215 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Tasks;
+
+namespace Emby.Common.Implementations.ScheduledTasks.Tasks
+{
+    /// <summary>
+    /// Deletes old cache files
+    /// </summary>
+    public class DeleteCacheFileTask : IScheduledTask, IConfigurableScheduledTask
+    {
+        /// <summary>
+        /// Gets or sets the application paths.
+        /// </summary>
+        /// <value>The application paths.</value>
+        private IApplicationPaths ApplicationPaths { get; set; }
+
+        private readonly ILogger _logger;
+
+        private readonly IFileSystem _fileSystem;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="DeleteCacheFileTask" /> class.
+        /// </summary>
+        public DeleteCacheFileTask(IApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem)
+        {
+            ApplicationPaths = appPaths;
+            _logger = logger;
+            _fileSystem = fileSystem;
+        }
+
+        /// <summary>
+        /// Creates the triggers that define when the task will run
+        /// </summary>
+        /// <returns>IEnumerable{BaseTaskTrigger}.</returns>
+        public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
+        {
+            return new[] { 
+            
+                // Every so often
+                new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks}
+            };
+        }
+
+        /// <summary>
+        /// Returns the task to be executed
+        /// </summary>
+        /// <param name="cancellationToken">The cancellation token.</param>
+        /// <param name="progress">The progress.</param>
+        /// <returns>Task.</returns>
+        public Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
+        {
+            var minDateModified = DateTime.UtcNow.AddDays(-30);
+
+            try
+            {
+                DeleteCacheFilesFromDirectory(cancellationToken, ApplicationPaths.CachePath, minDateModified, progress);
+            }
+            catch (DirectoryNotFoundException)
+            {
+                // No biggie here. Nothing to delete
+            }
+
+            progress.Report(90);
+
+            minDateModified = DateTime.UtcNow.AddDays(-1);
+
+            try
+            {
+                DeleteCacheFilesFromDirectory(cancellationToken, ApplicationPaths.TempDirectory, minDateModified, progress);
+            }
+            catch (DirectoryNotFoundException)
+            {
+                // No biggie here. Nothing to delete
+            }
+
+            return Task.FromResult(true);
+        }
+
+
+        /// <summary>
+        /// Deletes the cache files from directory with a last write time less than a given date
+        /// </summary>
+        /// <param name="cancellationToken">The task cancellation token.</param>
+        /// <param name="directory">The directory.</param>
+        /// <param name="minDateModified">The min date modified.</param>
+        /// <param name="progress">The progress.</param>
+        private void DeleteCacheFilesFromDirectory(CancellationToken cancellationToken, string directory, DateTime minDateModified, IProgress<double> progress)
+        {
+            var filesToDelete = _fileSystem.GetFiles(directory, true)
+                .Where(f => _fileSystem.GetLastWriteTimeUtc(f) < minDateModified)
+                .ToList();
+
+            var index = 0;
+
+            foreach (var file in filesToDelete)
+            {
+                double percent = index;
+                percent /= filesToDelete.Count;
+
+                progress.Report(100 * percent);
+
+                cancellationToken.ThrowIfCancellationRequested();
+
+                DeleteFile(file.FullName);
+
+                index++;
+            }
+
+            DeleteEmptyFolders(directory);
+
+            progress.Report(100);
+        }
+
+        private void DeleteEmptyFolders(string parent)
+        {
+            foreach (var directory in _fileSystem.GetDirectoryPaths(parent))
+            {
+                DeleteEmptyFolders(directory);
+                if (!_fileSystem.GetFileSystemEntryPaths(directory).Any())
+                {
+                    try
+                    {
+                        _fileSystem.DeleteDirectory(directory, false);
+                    }
+                    catch (UnauthorizedAccessException ex)
+                    {
+                        _logger.ErrorException("Error deleting directory {0}", ex, directory);
+                    }
+                    catch (IOException ex)
+                    {
+                        _logger.ErrorException("Error deleting directory {0}", ex, directory);
+                    }
+                }
+            }
+        }
+
+        private void DeleteFile(string path)
+        {
+            try
+            {
+                _fileSystem.DeleteFile(path);
+            }
+            catch (UnauthorizedAccessException ex)
+            {
+                _logger.ErrorException("Error deleting file {0}", ex, path);
+            }
+            catch (IOException ex)
+            {
+                _logger.ErrorException("Error deleting file {0}", ex, path);
+            }
+        }
+
+        /// <summary>
+        /// Gets the name of the task
+        /// </summary>
+        /// <value>The name.</value>
+        public string Name
+        {
+            get { return "Cache file cleanup"; }
+        }
+
+        public string Key
+        {
+            get { return "DeleteCacheFiles"; }
+        }
+
+        /// <summary>
+        /// Gets the description.
+        /// </summary>
+        /// <value>The description.</value>
+        public string Description
+        {
+            get { return "Deletes cache files no longer needed by the system"; }
+        }
+
+        /// <summary>
+        /// Gets the category.
+        /// </summary>
+        /// <value>The category.</value>
+        public string Category
+        {
+            get
+            {
+                return "Maintenance";
+            }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this instance is hidden.
+        /// </summary>
+        /// <value><c>true</c> if this instance is hidden; otherwise, <c>false</c>.</value>
+        public bool IsHidden
+        {
+            get { return true; }
+        }
+
+        public bool IsEnabled
+        {
+            get { return true; }
+        }
+
+        public bool IsLogged
+        {
+            get { return true; }
+        }
+    }
+}

+ 138 - 0
Emby.Common.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs

@@ -0,0 +1,138 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Tasks;
+
+namespace Emby.Common.Implementations.ScheduledTasks.Tasks
+{
+    /// <summary>
+    /// Deletes old log files
+    /// </summary>
+    public class DeleteLogFileTask : IScheduledTask, IConfigurableScheduledTask
+    {
+        /// <summary>
+        /// Gets or sets the configuration manager.
+        /// </summary>
+        /// <value>The configuration manager.</value>
+        private IConfigurationManager ConfigurationManager { get; set; }
+
+        private readonly IFileSystem _fileSystem;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="DeleteLogFileTask" /> class.
+        /// </summary>
+        /// <param name="configurationManager">The configuration manager.</param>
+        public DeleteLogFileTask(IConfigurationManager configurationManager, IFileSystem fileSystem)
+        {
+            ConfigurationManager = configurationManager;
+            _fileSystem = fileSystem;
+        }
+
+        /// <summary>
+        /// Creates the triggers that define when the task will run
+        /// </summary>
+        /// <returns>IEnumerable{BaseTaskTrigger}.</returns>
+        public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
+        {
+            return new[] { 
+            
+                // Every so often
+                new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks}
+            };
+        }
+
+        /// <summary>
+        /// Returns the task to be executed
+        /// </summary>
+        /// <param name="cancellationToken">The cancellation token.</param>
+        /// <param name="progress">The progress.</param>
+        /// <returns>Task.</returns>
+        public Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
+        {
+            // Delete log files more than n days old
+            var minDateModified = DateTime.UtcNow.AddDays(-ConfigurationManager.CommonConfiguration.LogFileRetentionDays);
+
+			var filesToDelete = _fileSystem.GetFiles(ConfigurationManager.CommonApplicationPaths.LogDirectoryPath, true)
+                          .Where(f => _fileSystem.GetLastWriteTimeUtc(f) < minDateModified)
+                          .ToList();
+
+            var index = 0;
+
+            foreach (var file in filesToDelete)
+            {
+                double percent = index;
+                percent /= filesToDelete.Count;
+
+                progress.Report(100 * percent);
+
+                cancellationToken.ThrowIfCancellationRequested();
+
+                _fileSystem.DeleteFile(file.FullName);
+
+                index++;
+            }
+
+            progress.Report(100);
+
+            return Task.FromResult(true);
+        }
+
+        public string Key
+        {
+            get { return "CleanLogFiles"; }
+        }
+
+        /// <summary>
+        /// Gets the name of the task
+        /// </summary>
+        /// <value>The name.</value>
+        public string Name
+        {
+            get { return "Log file cleanup"; }
+        }
+
+        /// <summary>
+        /// Gets the description.
+        /// </summary>
+        /// <value>The description.</value>
+        public string Description
+        {
+            get { return string.Format("Deletes log files that are more than {0} days old.", ConfigurationManager.CommonConfiguration.LogFileRetentionDays); }
+        }
+
+        /// <summary>
+        /// Gets the category.
+        /// </summary>
+        /// <value>The category.</value>
+        public string Category
+        {
+            get
+            {
+                return "Maintenance";
+            }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this instance is hidden.
+        /// </summary>
+        /// <value><c>true</c> if this instance is hidden; otherwise, <c>false</c>.</value>
+        public bool IsHidden
+        {
+            get { return true; }
+        }
+
+        public bool IsEnabled
+        {
+            get { return true; }
+        }
+
+        public bool IsLogged
+        {
+            get { return true; }
+        }
+    }
+}

+ 112 - 0
Emby.Common.Implementations/ScheduledTasks/Tasks/ReloadLoggerFileTask.cs

@@ -0,0 +1,112 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Tasks;
+
+namespace Emby.Common.Implementations.ScheduledTasks.Tasks
+{
+    /// <summary>
+    /// Class ReloadLoggerFileTask
+    /// </summary>
+    public class ReloadLoggerFileTask : IScheduledTask, IConfigurableScheduledTask
+    {
+        /// <summary>
+        /// Gets or sets the log manager.
+        /// </summary>
+        /// <value>The log manager.</value>
+        private ILogManager LogManager { get; set; }
+        /// <summary>
+        /// Gets or sets the configuration manager.
+        /// </summary>
+        /// <value>The configuration manager.</value>
+        private IConfigurationManager ConfigurationManager { get; set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ReloadLoggerFileTask" /> class.
+        /// </summary>
+        /// <param name="logManager">The logManager.</param>
+        /// <param name="configurationManager">The configuration manager.</param>
+        public ReloadLoggerFileTask(ILogManager logManager, IConfigurationManager configurationManager)
+        {
+            LogManager = logManager;
+            ConfigurationManager = configurationManager;
+        }
+
+        /// <summary>
+        /// Gets the default triggers.
+        /// </summary>
+        /// <returns>IEnumerable{BaseTaskTrigger}.</returns>
+        public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
+        {
+            var trigger = new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerDaily, TimeOfDayTicks = TimeSpan.FromHours(0).Ticks }; //12am
+
+            return new[] { trigger };
+        }
+
+        /// <summary>
+        /// Executes the internal.
+        /// </summary>
+        /// <param name="cancellationToken">The cancellation token.</param>
+        /// <param name="progress">The progress.</param>
+        /// <returns>Task.</returns>
+        public Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
+        {
+            cancellationToken.ThrowIfCancellationRequested();
+
+            progress.Report(0);
+
+            LogManager.ReloadLogger(ConfigurationManager.CommonConfiguration.EnableDebugLevelLogging
+                                        ? LogSeverity.Debug
+                                        : LogSeverity.Info);
+
+            return Task.FromResult(true);
+        }
+
+        /// <summary>
+        /// Gets the name.
+        /// </summary>
+        /// <value>The name.</value>
+        public string Name
+        {
+            get { return "Start new log file"; }
+        }
+
+        public string Key { get; }
+
+        /// <summary>
+        /// Gets the description.
+        /// </summary>
+        /// <value>The description.</value>
+        public string Description
+        {
+            get { return "Moves logging to a new file to help reduce log file sizes."; }
+        }
+
+        /// <summary>
+        /// Gets the category.
+        /// </summary>
+        /// <value>The category.</value>
+        public string Category
+        {
+            get { return "Application"; }
+        }
+
+        public bool IsHidden
+        {
+            get { return true; }
+        }
+
+        public bool IsEnabled
+        {
+            get { return true; }
+        }
+
+        public bool IsLogged
+        {
+            get { return true; }
+        }
+    }
+}

+ 116 - 0
Emby.Common.Implementations/ScheduledTasks/WeeklyTrigger.cs

@@ -0,0 +1,116 @@
+using System;
+using System.Threading;
+using MediaBrowser.Model.Events;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Tasks;
+
+namespace Emby.Common.Implementations.ScheduledTasks
+{
+    /// <summary>
+    /// Represents a task trigger that fires on a weekly basis
+    /// </summary>
+    public class WeeklyTrigger : ITaskTrigger
+    {
+        /// <summary>
+        /// Get the time of day to trigger the task to run
+        /// </summary>
+        /// <value>The time of day.</value>
+        public TimeSpan TimeOfDay { get; set; }
+
+        /// <summary>
+        /// Gets or sets the day of week.
+        /// </summary>
+        /// <value>The day of week.</value>
+        public DayOfWeek DayOfWeek { get; set; }
+
+        /// <summary>
+        /// Gets the execution properties of this task.
+        /// </summary>
+        /// <value>
+        /// The execution properties of this task.
+        /// </value>
+        public TaskExecutionOptions TaskOptions { get; set; }
+
+        /// <summary>
+        /// Gets or sets the timer.
+        /// </summary>
+        /// <value>The timer.</value>
+        private Timer Timer { get; set; }
+
+        /// <summary>
+        /// Stars waiting for the trigger action
+        /// </summary>
+        /// <param name="lastResult">The last result.</param>
+        /// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
+        public void Start(TaskResult lastResult, ILogger logger, string taskName, bool isApplicationStartup)
+        {
+            DisposeTimer();
+
+            var triggerDate = GetNextTriggerDateTime();
+
+            Timer = new Timer(state => OnTriggered(), null, triggerDate - DateTime.Now, TimeSpan.FromMilliseconds(-1));
+        }
+
+        /// <summary>
+        /// Gets the next trigger date time.
+        /// </summary>
+        /// <returns>DateTime.</returns>
+        private DateTime GetNextTriggerDateTime()
+        {
+            var now = DateTime.Now;
+
+            // If it's on the same day
+            if (now.DayOfWeek == DayOfWeek)
+            {
+                // It's either later today, or a week from now
+                return now.TimeOfDay < TimeOfDay ? now.Date.Add(TimeOfDay) : now.Date.AddDays(7).Add(TimeOfDay);
+            }
+
+            var triggerDate = now.Date;
+
+            // Walk the date forward until we get to the trigger day
+            while (triggerDate.DayOfWeek != DayOfWeek)
+            {
+                triggerDate = triggerDate.AddDays(1);
+            }
+
+            // Return the trigger date plus the time offset
+            return triggerDate.Add(TimeOfDay);
+        }
+
+        /// <summary>
+        /// Stops waiting for the trigger action
+        /// </summary>
+        public void Stop()
+        {
+            DisposeTimer();
+        }
+
+        /// <summary>
+        /// Disposes the timer.
+        /// </summary>
+        private void DisposeTimer()
+        {
+            if (Timer != null)
+            {
+                Timer.Dispose();
+            }
+        }
+
+        /// <summary>
+        /// Occurs when [triggered].
+        /// </summary>
+        public event EventHandler<GenericEventArgs<TaskExecutionOptions>> Triggered;
+
+        /// <summary>
+        /// Called when [triggered].
+        /// </summary>
+        private void OnTriggered()
+        {
+            if (Triggered != null)
+            {
+                Triggered(this, new GenericEventArgs<TaskExecutionOptions>(TaskOptions));
+            }
+        }
+    }
+}

+ 130 - 0
Emby.Common.Implementations/Serialization/XmlSerializer.cs

@@ -0,0 +1,130 @@
+using MediaBrowser.Model.Serialization;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.IO;
+using System.Xml;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Logging;
+
+namespace Emby.Common.Implementations.Serialization
+{
+    /// <summary>
+    /// Provides a wrapper around third party xml serialization.
+    /// </summary>
+    public class XmlSerializer : IXmlSerializer
+    {
+        private readonly IFileSystem _fileSystem;
+        private readonly ILogger _logger;
+
+        public XmlSerializer(IFileSystem fileSystem, ILogger logger)
+        {
+            _fileSystem = fileSystem;
+            _logger = logger;
+        }
+
+        // Need to cache these
+        // http://dotnetcodebox.blogspot.com/2013/01/xmlserializer-class-may-result-in.html
+        private readonly Dictionary<string, System.Xml.Serialization.XmlSerializer> _serializers =
+            new Dictionary<string, System.Xml.Serialization.XmlSerializer>();
+
+        private System.Xml.Serialization.XmlSerializer GetSerializer(Type type)
+        {
+            var key = type.FullName;
+            lock (_serializers)
+            {
+                System.Xml.Serialization.XmlSerializer serializer;
+                if (!_serializers.TryGetValue(key, out serializer))
+                {
+                    serializer = new System.Xml.Serialization.XmlSerializer(type);
+                    _serializers[key] = serializer;
+                }
+                return serializer;
+            }
+        }
+
+        /// <summary>
+        /// Serializes to writer.
+        /// </summary>
+        /// <param name="obj">The obj.</param>
+        /// <param name="writer">The writer.</param>
+        private void SerializeToWriter(object obj, XmlWriter writer)
+        {
+            //writer.Formatting = Formatting.Indented;
+            var netSerializer = GetSerializer(obj.GetType());
+            netSerializer.Serialize(writer, obj);
+        }
+
+        /// <summary>
+        /// Deserializes from stream.
+        /// </summary>
+        /// <param name="type">The type.</param>
+        /// <param name="stream">The stream.</param>
+        /// <returns>System.Object.</returns>
+        public object DeserializeFromStream(Type type, Stream stream)
+        {
+            using (var reader = XmlReader.Create(stream))
+            {
+                var netSerializer = GetSerializer(type);
+                return netSerializer.Deserialize(reader);
+            }
+        }
+
+        /// <summary>
+        /// Serializes to stream.
+        /// </summary>
+        /// <param name="obj">The obj.</param>
+        /// <param name="stream">The stream.</param>
+        public void SerializeToStream(object obj, Stream stream)
+        {
+            using (var writer =  XmlWriter.Create(stream))
+            {
+                SerializeToWriter(obj, writer);
+            }
+        }
+
+        /// <summary>
+        /// Serializes to file.
+        /// </summary>
+        /// <param name="obj">The obj.</param>
+        /// <param name="file">The file.</param>
+        public void SerializeToFile(object obj, string file)
+        {
+            _logger.Debug("Serializing to file {0}", file);
+            using (var stream = new FileStream(file, FileMode.Create))
+            {
+                SerializeToStream(obj, stream);
+            }
+        }
+
+        /// <summary>
+        /// Deserializes from file.
+        /// </summary>
+        /// <param name="type">The type.</param>
+        /// <param name="file">The file.</param>
+        /// <returns>System.Object.</returns>
+        public object DeserializeFromFile(Type type, string file)
+        {
+            _logger.Debug("Deserializing file {0}", file);
+            using (var stream = _fileSystem.OpenRead(file))
+            {
+                return DeserializeFromStream(type, stream);
+            }
+        }
+
+        /// <summary>
+        /// Deserializes from bytes.
+        /// </summary>
+        /// <param name="type">The type.</param>
+        /// <param name="buffer">The buffer.</param>
+        /// <returns>System.Object.</returns>
+        public object DeserializeFromBytes(Type type, byte[] buffer)
+        {
+            using (var stream = new MemoryStream(buffer))
+            {
+                return DeserializeFromStream(type, stream);
+            }
+        }
+    }
+}

+ 269 - 0
Emby.Common.Implementations/Updates/GithubUpdater.cs

@@ -0,0 +1,269 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Model.Serialization;
+using MediaBrowser.Model.Updates;
+
+namespace Emby.Common.Implementations.Updates
+{
+    public class GithubUpdater
+    {
+        private readonly IHttpClient _httpClient;
+        private readonly IJsonSerializer _jsonSerializer;
+
+        public GithubUpdater(IHttpClient httpClient, IJsonSerializer jsonSerializer)
+        {
+            _httpClient = httpClient;
+            _jsonSerializer = jsonSerializer;
+        }
+
+        public async Task<CheckForUpdateResult> CheckForUpdateResult(string organzation, string repository, Version minVersion, PackageVersionClass updateLevel, string assetFilename, string packageName, string targetFilename, TimeSpan cacheLength, CancellationToken cancellationToken)
+        {
+            var url = string.Format("https://api.github.com/repos/{0}/{1}/releases", organzation, repository);
+
+            var options = new HttpRequestOptions
+            {
+                Url = url,
+                EnableKeepAlive = false,
+                CancellationToken = cancellationToken,
+                UserAgent = "Emby/3.0",
+                BufferContent = false
+            };
+
+            if (cacheLength.Ticks > 0)
+            {
+                options.CacheMode = CacheMode.Unconditional;
+                options.CacheLength = cacheLength;
+            }
+
+            using (var stream = await _httpClient.Get(options).ConfigureAwait(false))
+            {
+                var obj = _jsonSerializer.DeserializeFromStream<RootObject[]>(stream);
+
+                return CheckForUpdateResult(obj, minVersion, updateLevel, assetFilename, packageName, targetFilename);
+            }
+        }
+
+        private CheckForUpdateResult CheckForUpdateResult(RootObject[] obj, Version minVersion, PackageVersionClass updateLevel, string assetFilename, string packageName, string targetFilename)
+        {
+            if (updateLevel == PackageVersionClass.Release)
+            {
+                // Technically all we need to do is check that it's not pre-release
+                // But let's addititional checks for -beta and -dev to handle builds that might be temporarily tagged incorrectly.
+                obj = obj.Where(i => !i.prerelease && !i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase) && !i.name.EndsWith("-dev", StringComparison.OrdinalIgnoreCase)).ToArray();
+            }
+            else if (updateLevel == PackageVersionClass.Beta)
+            {
+                obj = obj.Where(i => !i.prerelease || i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase)).ToArray();
+            }
+            else if (updateLevel == PackageVersionClass.Dev)
+            {
+                obj = obj.Where(i => !i.prerelease || i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase) || i.name.EndsWith("-dev", StringComparison.OrdinalIgnoreCase)).ToArray();
+            }
+
+            var availableUpdate = obj
+                .Select(i => CheckForUpdateResult(i, minVersion, assetFilename, packageName, targetFilename))
+                .Where(i => i != null)
+                .OrderByDescending(i => Version.Parse(i.AvailableVersion))
+                .FirstOrDefault();
+
+            return availableUpdate ?? new CheckForUpdateResult
+            {
+                IsUpdateAvailable = false
+            };
+        }
+
+        private bool MatchesUpdateLevel(RootObject i, PackageVersionClass updateLevel)
+        {
+            if (updateLevel == PackageVersionClass.Beta)
+            {
+                return !i.prerelease || i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase);
+            }
+            if (updateLevel == PackageVersionClass.Dev)
+            {
+                return !i.prerelease || i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase) ||
+                       i.name.EndsWith("-dev", StringComparison.OrdinalIgnoreCase);
+            }
+
+            // Technically all we need to do is check that it's not pre-release
+            // But let's addititional checks for -beta and -dev to handle builds that might be temporarily tagged incorrectly.
+            return !i.prerelease && !i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase) &&
+                   !i.name.EndsWith("-dev", StringComparison.OrdinalIgnoreCase);
+        }
+
+        public async Task<List<RootObject>> GetLatestReleases(string organzation, string repository, string assetFilename, CancellationToken cancellationToken)
+        {
+            var list = new List<RootObject>();
+
+            var url = string.Format("https://api.github.com/repos/{0}/{1}/releases", organzation, repository);
+
+            var options = new HttpRequestOptions
+            {
+                Url = url,
+                EnableKeepAlive = false,
+                CancellationToken = cancellationToken,
+                UserAgent = "Emby/3.0",
+                BufferContent = false
+            };
+
+            using (var stream = await _httpClient.Get(options).ConfigureAwait(false))
+            {
+                var obj = _jsonSerializer.DeserializeFromStream<RootObject[]>(stream);
+
+                obj = obj.Where(i => (i.assets ?? new List<Asset>()).Any(a => IsAsset(a, assetFilename))).ToArray();
+
+                list.AddRange(obj.Where(i => MatchesUpdateLevel(i, PackageVersionClass.Release)).OrderByDescending(GetVersion).Take(1));
+                list.AddRange(obj.Where(i => MatchesUpdateLevel(i, PackageVersionClass.Beta)).OrderByDescending(GetVersion).Take(1));
+                list.AddRange(obj.Where(i => MatchesUpdateLevel(i, PackageVersionClass.Dev)).OrderByDescending(GetVersion).Take(1));
+
+                return list;
+            }
+        }
+
+        public Version GetVersion(RootObject obj)
+        {
+            Version version;
+            if (!Version.TryParse(obj.tag_name, out version))
+            {
+                return new Version(1, 0);
+            }
+
+            return version;
+        }
+
+        private CheckForUpdateResult CheckForUpdateResult(RootObject obj, Version minVersion, string assetFilename, string packageName, string targetFilename)
+        {
+            Version version;
+            if (!Version.TryParse(obj.tag_name, out version))
+            {
+                return null;
+            }
+
+            if (version < minVersion)
+            {
+                return null;
+            }
+
+            var asset = (obj.assets ?? new List<Asset>()).FirstOrDefault(i => IsAsset(i, assetFilename));
+
+            if (asset == null)
+            {
+                return null;
+            }
+
+            return new CheckForUpdateResult
+            {
+                AvailableVersion = version.ToString(),
+                IsUpdateAvailable = version > minVersion,
+                Package = new PackageVersionInfo
+                {
+                    classification = obj.prerelease ?
+                        (obj.name.EndsWith("-dev", StringComparison.OrdinalIgnoreCase) ? PackageVersionClass.Dev : PackageVersionClass.Beta) :
+                        PackageVersionClass.Release,
+                    name = packageName,
+                    sourceUrl = asset.browser_download_url,
+                    targetFilename = targetFilename,
+                    versionStr = version.ToString(),
+                    requiredVersionStr = "1.0.0",
+                    description = obj.body,
+                    infoUrl = obj.html_url
+                }
+            };
+        }
+
+        private bool IsAsset(Asset asset, string assetFilename)
+        {
+            var downloadFilename = Path.GetFileName(asset.browser_download_url) ?? string.Empty;
+
+            if (downloadFilename.IndexOf(assetFilename, StringComparison.OrdinalIgnoreCase) != -1)
+            {
+                return true;
+            }
+
+            return string.Equals(assetFilename, downloadFilename, StringComparison.OrdinalIgnoreCase);
+        }
+
+        public class Uploader
+        {
+            public string login { get; set; }
+            public int id { get; set; }
+            public string avatar_url { get; set; }
+            public string gravatar_id { get; set; }
+            public string url { get; set; }
+            public string html_url { get; set; }
+            public string followers_url { get; set; }
+            public string following_url { get; set; }
+            public string gists_url { get; set; }
+            public string starred_url { get; set; }
+            public string subscriptions_url { get; set; }
+            public string organizations_url { get; set; }
+            public string repos_url { get; set; }
+            public string events_url { get; set; }
+            public string received_events_url { get; set; }
+            public string type { get; set; }
+            public bool site_admin { get; set; }
+        }
+
+        public class Asset
+        {
+            public string url { get; set; }
+            public int id { get; set; }
+            public string name { get; set; }
+            public object label { get; set; }
+            public Uploader uploader { get; set; }
+            public string content_type { get; set; }
+            public string state { get; set; }
+            public int size { get; set; }
+            public int download_count { get; set; }
+            public string created_at { get; set; }
+            public string updated_at { get; set; }
+            public string browser_download_url { get; set; }
+        }
+
+        public class Author
+        {
+            public string login { get; set; }
+            public int id { get; set; }
+            public string avatar_url { get; set; }
+            public string gravatar_id { get; set; }
+            public string url { get; set; }
+            public string html_url { get; set; }
+            public string followers_url { get; set; }
+            public string following_url { get; set; }
+            public string gists_url { get; set; }
+            public string starred_url { get; set; }
+            public string subscriptions_url { get; set; }
+            public string organizations_url { get; set; }
+            public string repos_url { get; set; }
+            public string events_url { get; set; }
+            public string received_events_url { get; set; }
+            public string type { get; set; }
+            public bool site_admin { get; set; }
+        }
+
+        public class RootObject
+        {
+            public string url { get; set; }
+            public string assets_url { get; set; }
+            public string upload_url { get; set; }
+            public string html_url { get; set; }
+            public int id { get; set; }
+            public string tag_name { get; set; }
+            public string target_commitish { get; set; }
+            public string name { get; set; }
+            public bool draft { get; set; }
+            public Author author { get; set; }
+            public bool prerelease { get; set; }
+            public string created_at { get; set; }
+            public string published_at { get; set; }
+            public List<Asset> assets { get; set; }
+            public string tarball_url { get; set; }
+            public string zipball_url { get; set; }
+            public string body { get; set; }
+        }
+    }
+}

+ 39 - 0
Emby.Common.Implementations/project.fragment.lock.json

@@ -0,0 +1,39 @@
+{
+  "version": 2,
+  "exports": {
+    "MediaBrowser.Common/1.0.0": {
+      "type": "project",
+      "framework": ".NETPortable,Version=v4.5,Profile=Profile7",
+      "compile": {
+        "bin/Debug/MediaBrowser.Common.dll": {}
+      },
+      "runtime": {
+        "bin/Debug/MediaBrowser.Common.dll": {}
+      },
+      "contentFiles": {
+        "bin/Debug/MediaBrowser.Common.pdb": {
+          "buildAction": "None",
+          "codeLanguage": "any",
+          "copyToOutput": true
+        }
+      }
+    },
+    "MediaBrowser.Model/1.0.0": {
+      "type": "project",
+      "framework": ".NETPortable,Version=v4.5,Profile=Profile7",
+      "compile": {
+        "bin/Debug/MediaBrowser.Model.dll": {}
+      },
+      "runtime": {
+        "bin/Debug/MediaBrowser.Model.dll": {}
+      },
+      "contentFiles": {
+        "bin/Debug/MediaBrowser.Model.pdb": {
+          "buildAction": "None",
+          "codeLanguage": "any",
+          "copyToOutput": true
+        }
+      }
+    }
+  }
+}

+ 48 - 0
Emby.Common.Implementations/project.json

@@ -0,0 +1,48 @@
+{
+  "version": "1.0.0-*",
+
+  "dependencies": {
+    
+  },
+
+  "frameworks": {
+    "net46": {
+      "frameworkAssemblies": {
+        "System.Collections": "4.0.0.0",
+        "System.IO": "4.0.0.0",
+        "System.Net": "4.0.0.0",
+        "System.Net.Http": "4.0.0.0",
+        "System.Net.Http.WebRequest": "4.0.0.0",
+        "System.Net.Primitives": "4.0.0.0",
+        "System.Runtime": "4.0.0.0",
+        "System.Text.Encoding": "4.0.0.0",
+        "System.Threading": "4.0.0.0",
+        "System.Threading.Tasks": "4.0.0.0",
+        "System.Xml": "4.0.0.0",
+        "System.Xml.Serialization": "4.0.0.0"
+      },
+      "dependencies": {
+        "MediaBrowser.Common": {
+          "target": "project"
+        },
+        "MediaBrowser.Model": {
+          "target": "project"
+        }
+      }
+    },
+    "netstandard1.6": {
+      "imports": "dnxcore50",
+      "dependencies": {
+        "NETStandard.Library": "1.6.0",
+		"MediaBrowser.Common": {
+          "target": "project"
+        },
+        "MediaBrowser.Model": {
+          "target": "project"
+        },
+        "System.Net.Requests": "4.0.11",
+		"System.Xml.XmlSerializer": "4.0.11"
+      }
+    }
+  }
+}

+ 4403 - 0
Emby.Common.Implementations/project.lock.json

@@ -0,0 +1,4403 @@
+{
+  "locked": false,
+  "version": 2,
+  "targets": {
+    ".NETFramework,Version=v4.6": {
+      "MediaBrowser.Common/1.0.0": {
+        "type": "project",
+        "framework": ".NETPortable,Version=v4.5,Profile=Profile7",
+        "dependencies": {
+          "MediaBrowser.Model": "1.0.0"
+        }
+      },
+      "MediaBrowser.Model/1.0.0": {
+        "type": "project",
+        "framework": ".NETPortable,Version=v4.5,Profile=Profile7"
+      }
+    },
+    ".NETStandard,Version=v1.6": {
+      "Microsoft.NETCore.Platforms/1.0.1": {
+        "type": "package",
+        "compile": {
+          "lib/netstandard1.0/_._": {}
+        },
+        "runtime": {
+          "lib/netstandard1.0/_._": {}
+        }
+      },
+      "Microsoft.NETCore.Targets/1.0.1": {
+        "type": "package",
+        "compile": {
+          "lib/netstandard1.0/_._": {}
+        },
+        "runtime": {
+          "lib/netstandard1.0/_._": {}
+        }
+      },
+      "Microsoft.Win32.Primitives/4.0.1": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "Microsoft.NETCore.Targets": "1.0.1",
+          "System.Runtime": "4.1.0"
+        },
+        "compile": {
+          "ref/netstandard1.3/Microsoft.Win32.Primitives.dll": {}
+        }
+      },
+      "NETStandard.Library/1.6.0": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "Microsoft.Win32.Primitives": "4.0.1",
+          "System.AppContext": "4.1.0",
+          "System.Collections": "4.0.11",
+          "System.Collections.Concurrent": "4.0.12",
+          "System.Console": "4.0.0",
+          "System.Diagnostics.Debug": "4.0.11",
+          "System.Diagnostics.Tools": "4.0.1",
+          "System.Diagnostics.Tracing": "4.1.0",
+          "System.Globalization": "4.0.11",
+          "System.Globalization.Calendars": "4.0.1",
+          "System.IO": "4.1.0",
+          "System.IO.Compression": "4.1.0",
+          "System.IO.Compression.ZipFile": "4.0.1",
+          "System.IO.FileSystem": "4.0.1",
+          "System.IO.FileSystem.Primitives": "4.0.1",
+          "System.Linq": "4.1.0",
+          "System.Linq.Expressions": "4.1.0",
+          "System.Net.Http": "4.1.0",
+          "System.Net.Primitives": "4.0.11",
+          "System.Net.Sockets": "4.1.0",
+          "System.ObjectModel": "4.0.12",
+          "System.Reflection": "4.1.0",
+          "System.Reflection.Extensions": "4.0.1",
+          "System.Reflection.Primitives": "4.0.1",
+          "System.Resources.ResourceManager": "4.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Runtime.Extensions": "4.1.0",
+          "System.Runtime.Handles": "4.0.1",
+          "System.Runtime.InteropServices": "4.1.0",
+          "System.Runtime.InteropServices.RuntimeInformation": "4.0.0",
+          "System.Runtime.Numerics": "4.0.1",
+          "System.Security.Cryptography.Algorithms": "4.2.0",
+          "System.Security.Cryptography.Encoding": "4.0.0",
+          "System.Security.Cryptography.Primitives": "4.0.0",
+          "System.Security.Cryptography.X509Certificates": "4.1.0",
+          "System.Text.Encoding": "4.0.11",
+          "System.Text.Encoding.Extensions": "4.0.11",
+          "System.Text.RegularExpressions": "4.1.0",
+          "System.Threading": "4.0.11",
+          "System.Threading.Tasks": "4.0.11",
+          "System.Threading.Timer": "4.0.1",
+          "System.Xml.ReaderWriter": "4.0.11",
+          "System.Xml.XDocument": "4.0.11"
+        }
+      },
+      "runtime.native.System/4.0.0": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "Microsoft.NETCore.Targets": "1.0.1"
+        },
+        "compile": {
+          "lib/netstandard1.0/_._": {}
+        },
+        "runtime": {
+          "lib/netstandard1.0/_._": {}
+        }
+      },
+      "runtime.native.System.IO.Compression/4.1.0": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "Microsoft.NETCore.Targets": "1.0.1"
+        },
+        "compile": {
+          "lib/netstandard1.0/_._": {}
+        },
+        "runtime": {
+          "lib/netstandard1.0/_._": {}
+        }
+      },
+      "runtime.native.System.Net.Http/4.0.1": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "Microsoft.NETCore.Targets": "1.0.1"
+        },
+        "compile": {
+          "lib/netstandard1.0/_._": {}
+        },
+        "runtime": {
+          "lib/netstandard1.0/_._": {}
+        }
+      },
+      "runtime.native.System.Security.Cryptography/4.0.0": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "Microsoft.NETCore.Targets": "1.0.1"
+        },
+        "compile": {
+          "lib/netstandard1.0/_._": {}
+        },
+        "runtime": {
+          "lib/netstandard1.0/_._": {}
+        }
+      },
+      "System.AppContext/4.1.0": {
+        "type": "package",
+        "dependencies": {
+          "System.Runtime": "4.1.0"
+        },
+        "compile": {
+          "ref/netstandard1.6/System.AppContext.dll": {}
+        },
+        "runtime": {
+          "lib/netstandard1.6/System.AppContext.dll": {}
+        }
+      },
+      "System.Buffers/4.0.0": {
+        "type": "package",
+        "dependencies": {
+          "System.Diagnostics.Debug": "4.0.11",
+          "System.Diagnostics.Tracing": "4.1.0",
+          "System.Resources.ResourceManager": "4.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Threading": "4.0.11"
+        },
+        "compile": {
+          "lib/netstandard1.1/_._": {}
+        },
+        "runtime": {
+          "lib/netstandard1.1/System.Buffers.dll": {}
+        }
+      },
+      "System.Collections/4.0.11": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "Microsoft.NETCore.Targets": "1.0.1",
+          "System.Runtime": "4.1.0"
+        },
+        "compile": {
+          "ref/netstandard1.3/System.Collections.dll": {}
+        }
+      },
+      "System.Collections.Concurrent/4.0.12": {
+        "type": "package",
+        "dependencies": {
+          "System.Collections": "4.0.11",
+          "System.Diagnostics.Debug": "4.0.11",
+          "System.Diagnostics.Tracing": "4.1.0",
+          "System.Globalization": "4.0.11",
+          "System.Reflection": "4.1.0",
+          "System.Resources.ResourceManager": "4.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Runtime.Extensions": "4.1.0",
+          "System.Threading": "4.0.11",
+          "System.Threading.Tasks": "4.0.11"
+        },
+        "compile": {
+          "ref/netstandard1.3/System.Collections.Concurrent.dll": {}
+        },
+        "runtime": {
+          "lib/netstandard1.3/System.Collections.Concurrent.dll": {}
+        }
+      },
+      "System.Console/4.0.0": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "Microsoft.NETCore.Targets": "1.0.1",
+          "System.IO": "4.1.0",
+          "System.Runtime": "4.1.0",
+          "System.Text.Encoding": "4.0.11"
+        },
+        "compile": {
+          "ref/netstandard1.3/System.Console.dll": {}
+        }
+      },
+      "System.Diagnostics.Debug/4.0.11": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "Microsoft.NETCore.Targets": "1.0.1",
+          "System.Runtime": "4.1.0"
+        },
+        "compile": {
+          "ref/netstandard1.3/System.Diagnostics.Debug.dll": {}
+        }
+      },
+      "System.Diagnostics.DiagnosticSource/4.0.0": {
+        "type": "package",
+        "dependencies": {
+          "System.Collections": "4.0.11",
+          "System.Diagnostics.Tracing": "4.1.0",
+          "System.Reflection": "4.1.0",
+          "System.Runtime": "4.1.0",
+          "System.Threading": "4.0.11"
+        },
+        "compile": {
+          "lib/netstandard1.3/_._": {}
+        },
+        "runtime": {
+          "lib/netstandard1.3/System.Diagnostics.DiagnosticSource.dll": {}
+        }
+      },
+      "System.Diagnostics.Tools/4.0.1": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "Microsoft.NETCore.Targets": "1.0.1",
+          "System.Runtime": "4.1.0"
+        },
+        "compile": {
+          "ref/netstandard1.0/System.Diagnostics.Tools.dll": {}
+        }
+      },
+      "System.Diagnostics.Tracing/4.1.0": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "Microsoft.NETCore.Targets": "1.0.1",
+          "System.Runtime": "4.1.0"
+        },
+        "compile": {
+          "ref/netstandard1.5/System.Diagnostics.Tracing.dll": {}
+        }
+      },
+      "System.Globalization/4.0.11": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "Microsoft.NETCore.Targets": "1.0.1",
+          "System.Runtime": "4.1.0"
+        },
+        "compile": {
+          "ref/netstandard1.3/System.Globalization.dll": {}
+        }
+      },
+      "System.Globalization.Calendars/4.0.1": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "Microsoft.NETCore.Targets": "1.0.1",
+          "System.Globalization": "4.0.11",
+          "System.Runtime": "4.1.0"
+        },
+        "compile": {
+          "ref/netstandard1.3/System.Globalization.Calendars.dll": {}
+        }
+      },
+      "System.Globalization.Extensions/4.0.1": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "System.Globalization": "4.0.11",
+          "System.Resources.ResourceManager": "4.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Runtime.Extensions": "4.1.0",
+          "System.Runtime.InteropServices": "4.1.0"
+        },
+        "compile": {
+          "ref/netstandard1.3/_._": {}
+        },
+        "runtimeTargets": {
+          "runtimes/unix/lib/netstandard1.3/System.Globalization.Extensions.dll": {
+            "assetType": "runtime",
+            "rid": "unix"
+          },
+          "runtimes/win/lib/netstandard1.3/System.Globalization.Extensions.dll": {
+            "assetType": "runtime",
+            "rid": "win"
+          }
+        }
+      },
+      "System.IO/4.1.0": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "Microsoft.NETCore.Targets": "1.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Text.Encoding": "4.0.11",
+          "System.Threading.Tasks": "4.0.11"
+        },
+        "compile": {
+          "ref/netstandard1.5/System.IO.dll": {}
+        }
+      },
+      "System.IO.Compression/4.1.0": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "System.Collections": "4.0.11",
+          "System.Diagnostics.Debug": "4.0.11",
+          "System.IO": "4.1.0",
+          "System.Resources.ResourceManager": "4.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Runtime.Extensions": "4.1.0",
+          "System.Runtime.Handles": "4.0.1",
+          "System.Runtime.InteropServices": "4.1.0",
+          "System.Text.Encoding": "4.0.11",
+          "System.Threading": "4.0.11",
+          "System.Threading.Tasks": "4.0.11",
+          "runtime.native.System": "4.0.0",
+          "runtime.native.System.IO.Compression": "4.1.0"
+        },
+        "compile": {
+          "ref/netstandard1.3/System.IO.Compression.dll": {}
+        },
+        "runtimeTargets": {
+          "runtimes/unix/lib/netstandard1.3/System.IO.Compression.dll": {
+            "assetType": "runtime",
+            "rid": "unix"
+          },
+          "runtimes/win/lib/netstandard1.3/System.IO.Compression.dll": {
+            "assetType": "runtime",
+            "rid": "win"
+          }
+        }
+      },
+      "System.IO.Compression.ZipFile/4.0.1": {
+        "type": "package",
+        "dependencies": {
+          "System.Buffers": "4.0.0",
+          "System.IO": "4.1.0",
+          "System.IO.Compression": "4.1.0",
+          "System.IO.FileSystem": "4.0.1",
+          "System.IO.FileSystem.Primitives": "4.0.1",
+          "System.Resources.ResourceManager": "4.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Runtime.Extensions": "4.1.0",
+          "System.Text.Encoding": "4.0.11"
+        },
+        "compile": {
+          "ref/netstandard1.3/System.IO.Compression.ZipFile.dll": {}
+        },
+        "runtime": {
+          "lib/netstandard1.3/System.IO.Compression.ZipFile.dll": {}
+        }
+      },
+      "System.IO.FileSystem/4.0.1": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "Microsoft.NETCore.Targets": "1.0.1",
+          "System.IO": "4.1.0",
+          "System.IO.FileSystem.Primitives": "4.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Runtime.Handles": "4.0.1",
+          "System.Text.Encoding": "4.0.11",
+          "System.Threading.Tasks": "4.0.11"
+        },
+        "compile": {
+          "ref/netstandard1.3/System.IO.FileSystem.dll": {}
+        }
+      },
+      "System.IO.FileSystem.Primitives/4.0.1": {
+        "type": "package",
+        "dependencies": {
+          "System.Runtime": "4.1.0"
+        },
+        "compile": {
+          "ref/netstandard1.3/System.IO.FileSystem.Primitives.dll": {}
+        },
+        "runtime": {
+          "lib/netstandard1.3/System.IO.FileSystem.Primitives.dll": {}
+        }
+      },
+      "System.Linq/4.1.0": {
+        "type": "package",
+        "dependencies": {
+          "System.Collections": "4.0.11",
+          "System.Diagnostics.Debug": "4.0.11",
+          "System.Resources.ResourceManager": "4.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Runtime.Extensions": "4.1.0"
+        },
+        "compile": {
+          "ref/netstandard1.6/System.Linq.dll": {}
+        },
+        "runtime": {
+          "lib/netstandard1.6/System.Linq.dll": {}
+        }
+      },
+      "System.Linq.Expressions/4.1.0": {
+        "type": "package",
+        "dependencies": {
+          "System.Collections": "4.0.11",
+          "System.Diagnostics.Debug": "4.0.11",
+          "System.Globalization": "4.0.11",
+          "System.IO": "4.1.0",
+          "System.Linq": "4.1.0",
+          "System.ObjectModel": "4.0.12",
+          "System.Reflection": "4.1.0",
+          "System.Reflection.Emit": "4.0.1",
+          "System.Reflection.Emit.ILGeneration": "4.0.1",
+          "System.Reflection.Emit.Lightweight": "4.0.1",
+          "System.Reflection.Extensions": "4.0.1",
+          "System.Reflection.Primitives": "4.0.1",
+          "System.Reflection.TypeExtensions": "4.1.0",
+          "System.Resources.ResourceManager": "4.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Runtime.Extensions": "4.1.0",
+          "System.Threading": "4.0.11"
+        },
+        "compile": {
+          "ref/netstandard1.6/System.Linq.Expressions.dll": {}
+        },
+        "runtime": {
+          "lib/netstandard1.6/System.Linq.Expressions.dll": {}
+        }
+      },
+      "System.Net.Http/4.1.0": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "System.Collections": "4.0.11",
+          "System.Diagnostics.Debug": "4.0.11",
+          "System.Diagnostics.DiagnosticSource": "4.0.0",
+          "System.Diagnostics.Tracing": "4.1.0",
+          "System.Globalization": "4.0.11",
+          "System.Globalization.Extensions": "4.0.1",
+          "System.IO": "4.1.0",
+          "System.IO.FileSystem": "4.0.1",
+          "System.Net.Primitives": "4.0.11",
+          "System.Resources.ResourceManager": "4.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Runtime.Extensions": "4.1.0",
+          "System.Runtime.Handles": "4.0.1",
+          "System.Runtime.InteropServices": "4.1.0",
+          "System.Security.Cryptography.Algorithms": "4.2.0",
+          "System.Security.Cryptography.Encoding": "4.0.0",
+          "System.Security.Cryptography.OpenSsl": "4.0.0",
+          "System.Security.Cryptography.Primitives": "4.0.0",
+          "System.Security.Cryptography.X509Certificates": "4.1.0",
+          "System.Text.Encoding": "4.0.11",
+          "System.Threading": "4.0.11",
+          "System.Threading.Tasks": "4.0.11",
+          "runtime.native.System": "4.0.0",
+          "runtime.native.System.Net.Http": "4.0.1",
+          "runtime.native.System.Security.Cryptography": "4.0.0"
+        },
+        "compile": {
+          "ref/netstandard1.3/System.Net.Http.dll": {}
+        },
+        "runtimeTargets": {
+          "runtimes/unix/lib/netstandard1.6/System.Net.Http.dll": {
+            "assetType": "runtime",
+            "rid": "unix"
+          },
+          "runtimes/win/lib/netstandard1.3/System.Net.Http.dll": {
+            "assetType": "runtime",
+            "rid": "win"
+          }
+        }
+      },
+      "System.Net.Primitives/4.0.11": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "Microsoft.NETCore.Targets": "1.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Runtime.Handles": "4.0.1"
+        },
+        "compile": {
+          "ref/netstandard1.3/System.Net.Primitives.dll": {}
+        }
+      },
+      "System.Net.Requests/4.0.11": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "System.Collections": "4.0.11",
+          "System.Diagnostics.Debug": "4.0.11",
+          "System.Diagnostics.Tracing": "4.1.0",
+          "System.Globalization": "4.0.11",
+          "System.IO": "4.1.0",
+          "System.Net.Http": "4.1.0",
+          "System.Net.Primitives": "4.0.11",
+          "System.Net.WebHeaderCollection": "4.0.1",
+          "System.Resources.ResourceManager": "4.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Threading": "4.0.11",
+          "System.Threading.Tasks": "4.0.11"
+        },
+        "compile": {
+          "ref/netstandard1.3/System.Net.Requests.dll": {}
+        },
+        "runtimeTargets": {
+          "runtimes/unix/lib/netstandard1.3/System.Net.Requests.dll": {
+            "assetType": "runtime",
+            "rid": "unix"
+          },
+          "runtimes/win/lib/netstandard1.3/System.Net.Requests.dll": {
+            "assetType": "runtime",
+            "rid": "win"
+          }
+        }
+      },
+      "System.Net.Sockets/4.1.0": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "Microsoft.NETCore.Targets": "1.0.1",
+          "System.IO": "4.1.0",
+          "System.Net.Primitives": "4.0.11",
+          "System.Runtime": "4.1.0",
+          "System.Threading.Tasks": "4.0.11"
+        },
+        "compile": {
+          "ref/netstandard1.3/System.Net.Sockets.dll": {}
+        }
+      },
+      "System.Net.WebHeaderCollection/4.0.1": {
+        "type": "package",
+        "dependencies": {
+          "System.Collections": "4.0.11",
+          "System.Resources.ResourceManager": "4.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Runtime.Extensions": "4.1.0"
+        },
+        "compile": {
+          "ref/netstandard1.3/System.Net.WebHeaderCollection.dll": {}
+        },
+        "runtime": {
+          "lib/netstandard1.3/System.Net.WebHeaderCollection.dll": {}
+        }
+      },
+      "System.ObjectModel/4.0.12": {
+        "type": "package",
+        "dependencies": {
+          "System.Collections": "4.0.11",
+          "System.Diagnostics.Debug": "4.0.11",
+          "System.Resources.ResourceManager": "4.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Threading": "4.0.11"
+        },
+        "compile": {
+          "ref/netstandard1.3/System.ObjectModel.dll": {}
+        },
+        "runtime": {
+          "lib/netstandard1.3/System.ObjectModel.dll": {}
+        }
+      },
+      "System.Reflection/4.1.0": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "Microsoft.NETCore.Targets": "1.0.1",
+          "System.IO": "4.1.0",
+          "System.Reflection.Primitives": "4.0.1",
+          "System.Runtime": "4.1.0"
+        },
+        "compile": {
+          "ref/netstandard1.5/System.Reflection.dll": {}
+        }
+      },
+      "System.Reflection.Emit/4.0.1": {
+        "type": "package",
+        "dependencies": {
+          "System.IO": "4.1.0",
+          "System.Reflection": "4.1.0",
+          "System.Reflection.Emit.ILGeneration": "4.0.1",
+          "System.Reflection.Primitives": "4.0.1",
+          "System.Runtime": "4.1.0"
+        },
+        "compile": {
+          "ref/netstandard1.1/_._": {}
+        },
+        "runtime": {
+          "lib/netstandard1.3/System.Reflection.Emit.dll": {}
+        }
+      },
+      "System.Reflection.Emit.ILGeneration/4.0.1": {
+        "type": "package",
+        "dependencies": {
+          "System.Reflection": "4.1.0",
+          "System.Reflection.Primitives": "4.0.1",
+          "System.Runtime": "4.1.0"
+        },
+        "compile": {
+          "ref/netstandard1.0/_._": {}
+        },
+        "runtime": {
+          "lib/netstandard1.3/System.Reflection.Emit.ILGeneration.dll": {}
+        }
+      },
+      "System.Reflection.Emit.Lightweight/4.0.1": {
+        "type": "package",
+        "dependencies": {
+          "System.Reflection": "4.1.0",
+          "System.Reflection.Emit.ILGeneration": "4.0.1",
+          "System.Reflection.Primitives": "4.0.1",
+          "System.Runtime": "4.1.0"
+        },
+        "compile": {
+          "ref/netstandard1.0/_._": {}
+        },
+        "runtime": {
+          "lib/netstandard1.3/System.Reflection.Emit.Lightweight.dll": {}
+        }
+      },
+      "System.Reflection.Extensions/4.0.1": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "Microsoft.NETCore.Targets": "1.0.1",
+          "System.Reflection": "4.1.0",
+          "System.Runtime": "4.1.0"
+        },
+        "compile": {
+          "ref/netstandard1.0/System.Reflection.Extensions.dll": {}
+        }
+      },
+      "System.Reflection.Primitives/4.0.1": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "Microsoft.NETCore.Targets": "1.0.1",
+          "System.Runtime": "4.1.0"
+        },
+        "compile": {
+          "ref/netstandard1.0/System.Reflection.Primitives.dll": {}
+        }
+      },
+      "System.Reflection.TypeExtensions/4.1.0": {
+        "type": "package",
+        "dependencies": {
+          "System.Reflection": "4.1.0",
+          "System.Runtime": "4.1.0"
+        },
+        "compile": {
+          "ref/netstandard1.5/_._": {}
+        },
+        "runtime": {
+          "lib/netstandard1.5/System.Reflection.TypeExtensions.dll": {}
+        }
+      },
+      "System.Resources.ResourceManager/4.0.1": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "Microsoft.NETCore.Targets": "1.0.1",
+          "System.Globalization": "4.0.11",
+          "System.Reflection": "4.1.0",
+          "System.Runtime": "4.1.0"
+        },
+        "compile": {
+          "ref/netstandard1.0/System.Resources.ResourceManager.dll": {}
+        }
+      },
+      "System.Runtime/4.1.0": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "Microsoft.NETCore.Targets": "1.0.1"
+        },
+        "compile": {
+          "ref/netstandard1.5/System.Runtime.dll": {}
+        }
+      },
+      "System.Runtime.Extensions/4.1.0": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "Microsoft.NETCore.Targets": "1.0.1",
+          "System.Runtime": "4.1.0"
+        },
+        "compile": {
+          "ref/netstandard1.5/System.Runtime.Extensions.dll": {}
+        }
+      },
+      "System.Runtime.Handles/4.0.1": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "Microsoft.NETCore.Targets": "1.0.1",
+          "System.Runtime": "4.1.0"
+        },
+        "compile": {
+          "ref/netstandard1.3/System.Runtime.Handles.dll": {}
+        }
+      },
+      "System.Runtime.InteropServices/4.1.0": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "Microsoft.NETCore.Targets": "1.0.1",
+          "System.Reflection": "4.1.0",
+          "System.Reflection.Primitives": "4.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Runtime.Handles": "4.0.1"
+        },
+        "compile": {
+          "ref/netstandard1.5/System.Runtime.InteropServices.dll": {}
+        }
+      },
+      "System.Runtime.InteropServices.RuntimeInformation/4.0.0": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "System.Reflection": "4.1.0",
+          "System.Resources.ResourceManager": "4.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Runtime.InteropServices": "4.1.0",
+          "System.Threading": "4.0.11",
+          "runtime.native.System": "4.0.0"
+        },
+        "compile": {
+          "ref/netstandard1.1/System.Runtime.InteropServices.RuntimeInformation.dll": {}
+        },
+        "runtimeTargets": {
+          "runtimes/unix/lib/netstandard1.1/System.Runtime.InteropServices.RuntimeInformation.dll": {
+            "assetType": "runtime",
+            "rid": "unix"
+          },
+          "runtimes/win/lib/netstandard1.1/System.Runtime.InteropServices.RuntimeInformation.dll": {
+            "assetType": "runtime",
+            "rid": "win"
+          }
+        }
+      },
+      "System.Runtime.Numerics/4.0.1": {
+        "type": "package",
+        "dependencies": {
+          "System.Globalization": "4.0.11",
+          "System.Resources.ResourceManager": "4.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Runtime.Extensions": "4.1.0"
+        },
+        "compile": {
+          "ref/netstandard1.1/System.Runtime.Numerics.dll": {}
+        },
+        "runtime": {
+          "lib/netstandard1.3/System.Runtime.Numerics.dll": {}
+        }
+      },
+      "System.Security.Cryptography.Algorithms/4.2.0": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "System.Collections": "4.0.11",
+          "System.IO": "4.1.0",
+          "System.Resources.ResourceManager": "4.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Runtime.Extensions": "4.1.0",
+          "System.Runtime.Handles": "4.0.1",
+          "System.Runtime.InteropServices": "4.1.0",
+          "System.Runtime.Numerics": "4.0.1",
+          "System.Security.Cryptography.Encoding": "4.0.0",
+          "System.Security.Cryptography.Primitives": "4.0.0",
+          "System.Text.Encoding": "4.0.11",
+          "runtime.native.System.Security.Cryptography": "4.0.0"
+        },
+        "compile": {
+          "ref/netstandard1.6/System.Security.Cryptography.Algorithms.dll": {}
+        },
+        "runtimeTargets": {
+          "runtimes/unix/lib/netstandard1.6/System.Security.Cryptography.Algorithms.dll": {
+            "assetType": "runtime",
+            "rid": "unix"
+          },
+          "runtimes/win/lib/netstandard1.6/System.Security.Cryptography.Algorithms.dll": {
+            "assetType": "runtime",
+            "rid": "win"
+          }
+        }
+      },
+      "System.Security.Cryptography.Cng/4.2.0": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "System.IO": "4.1.0",
+          "System.Resources.ResourceManager": "4.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Runtime.Extensions": "4.1.0",
+          "System.Runtime.Handles": "4.0.1",
+          "System.Runtime.InteropServices": "4.1.0",
+          "System.Security.Cryptography.Algorithms": "4.2.0",
+          "System.Security.Cryptography.Encoding": "4.0.0",
+          "System.Security.Cryptography.Primitives": "4.0.0",
+          "System.Text.Encoding": "4.0.11"
+        },
+        "compile": {
+          "ref/netstandard1.6/_._": {}
+        },
+        "runtimeTargets": {
+          "runtimes/unix/lib/netstandard1.6/System.Security.Cryptography.Cng.dll": {
+            "assetType": "runtime",
+            "rid": "unix"
+          },
+          "runtimes/win/lib/netstandard1.6/System.Security.Cryptography.Cng.dll": {
+            "assetType": "runtime",
+            "rid": "win"
+          }
+        }
+      },
+      "System.Security.Cryptography.Csp/4.0.0": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "System.IO": "4.1.0",
+          "System.Reflection": "4.1.0",
+          "System.Resources.ResourceManager": "4.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Runtime.Extensions": "4.1.0",
+          "System.Runtime.Handles": "4.0.1",
+          "System.Runtime.InteropServices": "4.1.0",
+          "System.Security.Cryptography.Algorithms": "4.2.0",
+          "System.Security.Cryptography.Encoding": "4.0.0",
+          "System.Security.Cryptography.Primitives": "4.0.0",
+          "System.Text.Encoding": "4.0.11",
+          "System.Threading": "4.0.11"
+        },
+        "compile": {
+          "ref/netstandard1.3/_._": {}
+        },
+        "runtimeTargets": {
+          "runtimes/unix/lib/netstandard1.3/System.Security.Cryptography.Csp.dll": {
+            "assetType": "runtime",
+            "rid": "unix"
+          },
+          "runtimes/win/lib/netstandard1.3/System.Security.Cryptography.Csp.dll": {
+            "assetType": "runtime",
+            "rid": "win"
+          }
+        }
+      },
+      "System.Security.Cryptography.Encoding/4.0.0": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "System.Collections": "4.0.11",
+          "System.Collections.Concurrent": "4.0.12",
+          "System.Linq": "4.1.0",
+          "System.Resources.ResourceManager": "4.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Runtime.Extensions": "4.1.0",
+          "System.Runtime.Handles": "4.0.1",
+          "System.Runtime.InteropServices": "4.1.0",
+          "System.Security.Cryptography.Primitives": "4.0.0",
+          "System.Text.Encoding": "4.0.11",
+          "runtime.native.System.Security.Cryptography": "4.0.0"
+        },
+        "compile": {
+          "ref/netstandard1.3/System.Security.Cryptography.Encoding.dll": {}
+        },
+        "runtimeTargets": {
+          "runtimes/unix/lib/netstandard1.3/System.Security.Cryptography.Encoding.dll": {
+            "assetType": "runtime",
+            "rid": "unix"
+          },
+          "runtimes/win/lib/netstandard1.3/System.Security.Cryptography.Encoding.dll": {
+            "assetType": "runtime",
+            "rid": "win"
+          }
+        }
+      },
+      "System.Security.Cryptography.OpenSsl/4.0.0": {
+        "type": "package",
+        "dependencies": {
+          "System.Collections": "4.0.11",
+          "System.IO": "4.1.0",
+          "System.Resources.ResourceManager": "4.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Runtime.Extensions": "4.1.0",
+          "System.Runtime.Handles": "4.0.1",
+          "System.Runtime.InteropServices": "4.1.0",
+          "System.Runtime.Numerics": "4.0.1",
+          "System.Security.Cryptography.Algorithms": "4.2.0",
+          "System.Security.Cryptography.Encoding": "4.0.0",
+          "System.Security.Cryptography.Primitives": "4.0.0",
+          "System.Text.Encoding": "4.0.11",
+          "runtime.native.System.Security.Cryptography": "4.0.0"
+        },
+        "compile": {
+          "ref/netstandard1.6/_._": {}
+        },
+        "runtime": {
+          "lib/netstandard1.6/System.Security.Cryptography.OpenSsl.dll": {}
+        },
+        "runtimeTargets": {
+          "runtimes/unix/lib/netstandard1.6/System.Security.Cryptography.OpenSsl.dll": {
+            "assetType": "runtime",
+            "rid": "unix"
+          }
+        }
+      },
+      "System.Security.Cryptography.Primitives/4.0.0": {
+        "type": "package",
+        "dependencies": {
+          "System.Diagnostics.Debug": "4.0.11",
+          "System.Globalization": "4.0.11",
+          "System.IO": "4.1.0",
+          "System.Resources.ResourceManager": "4.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Threading": "4.0.11",
+          "System.Threading.Tasks": "4.0.11"
+        },
+        "compile": {
+          "ref/netstandard1.3/System.Security.Cryptography.Primitives.dll": {}
+        },
+        "runtime": {
+          "lib/netstandard1.3/System.Security.Cryptography.Primitives.dll": {}
+        }
+      },
+      "System.Security.Cryptography.X509Certificates/4.1.0": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "System.Collections": "4.0.11",
+          "System.Diagnostics.Debug": "4.0.11",
+          "System.Globalization": "4.0.11",
+          "System.Globalization.Calendars": "4.0.1",
+          "System.IO": "4.1.0",
+          "System.IO.FileSystem": "4.0.1",
+          "System.IO.FileSystem.Primitives": "4.0.1",
+          "System.Resources.ResourceManager": "4.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Runtime.Extensions": "4.1.0",
+          "System.Runtime.Handles": "4.0.1",
+          "System.Runtime.InteropServices": "4.1.0",
+          "System.Runtime.Numerics": "4.0.1",
+          "System.Security.Cryptography.Algorithms": "4.2.0",
+          "System.Security.Cryptography.Cng": "4.2.0",
+          "System.Security.Cryptography.Csp": "4.0.0",
+          "System.Security.Cryptography.Encoding": "4.0.0",
+          "System.Security.Cryptography.OpenSsl": "4.0.0",
+          "System.Security.Cryptography.Primitives": "4.0.0",
+          "System.Text.Encoding": "4.0.11",
+          "System.Threading": "4.0.11",
+          "runtime.native.System": "4.0.0",
+          "runtime.native.System.Net.Http": "4.0.1",
+          "runtime.native.System.Security.Cryptography": "4.0.0"
+        },
+        "compile": {
+          "ref/netstandard1.4/System.Security.Cryptography.X509Certificates.dll": {}
+        },
+        "runtimeTargets": {
+          "runtimes/unix/lib/netstandard1.6/System.Security.Cryptography.X509Certificates.dll": {
+            "assetType": "runtime",
+            "rid": "unix"
+          },
+          "runtimes/win/lib/netstandard1.6/System.Security.Cryptography.X509Certificates.dll": {
+            "assetType": "runtime",
+            "rid": "win"
+          }
+        }
+      },
+      "System.Text.Encoding/4.0.11": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "Microsoft.NETCore.Targets": "1.0.1",
+          "System.Runtime": "4.1.0"
+        },
+        "compile": {
+          "ref/netstandard1.3/System.Text.Encoding.dll": {}
+        }
+      },
+      "System.Text.Encoding.Extensions/4.0.11": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "Microsoft.NETCore.Targets": "1.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Text.Encoding": "4.0.11"
+        },
+        "compile": {
+          "ref/netstandard1.3/System.Text.Encoding.Extensions.dll": {}
+        }
+      },
+      "System.Text.RegularExpressions/4.1.0": {
+        "type": "package",
+        "dependencies": {
+          "System.Collections": "4.0.11",
+          "System.Globalization": "4.0.11",
+          "System.Resources.ResourceManager": "4.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Runtime.Extensions": "4.1.0",
+          "System.Threading": "4.0.11"
+        },
+        "compile": {
+          "ref/netstandard1.6/System.Text.RegularExpressions.dll": {}
+        },
+        "runtime": {
+          "lib/netstandard1.6/System.Text.RegularExpressions.dll": {}
+        }
+      },
+      "System.Threading/4.0.11": {
+        "type": "package",
+        "dependencies": {
+          "System.Runtime": "4.1.0",
+          "System.Threading.Tasks": "4.0.11"
+        },
+        "compile": {
+          "ref/netstandard1.3/System.Threading.dll": {}
+        },
+        "runtime": {
+          "lib/netstandard1.3/System.Threading.dll": {}
+        }
+      },
+      "System.Threading.Tasks/4.0.11": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "Microsoft.NETCore.Targets": "1.0.1",
+          "System.Runtime": "4.1.0"
+        },
+        "compile": {
+          "ref/netstandard1.3/System.Threading.Tasks.dll": {}
+        }
+      },
+      "System.Threading.Tasks.Extensions/4.0.0": {
+        "type": "package",
+        "dependencies": {
+          "System.Collections": "4.0.11",
+          "System.Runtime": "4.1.0",
+          "System.Threading.Tasks": "4.0.11"
+        },
+        "compile": {
+          "lib/netstandard1.0/_._": {}
+        },
+        "runtime": {
+          "lib/netstandard1.0/System.Threading.Tasks.Extensions.dll": {}
+        }
+      },
+      "System.Threading.Timer/4.0.1": {
+        "type": "package",
+        "dependencies": {
+          "Microsoft.NETCore.Platforms": "1.0.1",
+          "Microsoft.NETCore.Targets": "1.0.1",
+          "System.Runtime": "4.1.0"
+        },
+        "compile": {
+          "ref/netstandard1.2/System.Threading.Timer.dll": {}
+        }
+      },
+      "System.Xml.ReaderWriter/4.0.11": {
+        "type": "package",
+        "dependencies": {
+          "System.Collections": "4.0.11",
+          "System.Diagnostics.Debug": "4.0.11",
+          "System.Globalization": "4.0.11",
+          "System.IO": "4.1.0",
+          "System.IO.FileSystem": "4.0.1",
+          "System.IO.FileSystem.Primitives": "4.0.1",
+          "System.Resources.ResourceManager": "4.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Runtime.Extensions": "4.1.0",
+          "System.Runtime.InteropServices": "4.1.0",
+          "System.Text.Encoding": "4.0.11",
+          "System.Text.Encoding.Extensions": "4.0.11",
+          "System.Text.RegularExpressions": "4.1.0",
+          "System.Threading.Tasks": "4.0.11",
+          "System.Threading.Tasks.Extensions": "4.0.0"
+        },
+        "compile": {
+          "ref/netstandard1.3/System.Xml.ReaderWriter.dll": {}
+        },
+        "runtime": {
+          "lib/netstandard1.3/System.Xml.ReaderWriter.dll": {}
+        }
+      },
+      "System.Xml.XDocument/4.0.11": {
+        "type": "package",
+        "dependencies": {
+          "System.Collections": "4.0.11",
+          "System.Diagnostics.Debug": "4.0.11",
+          "System.Diagnostics.Tools": "4.0.1",
+          "System.Globalization": "4.0.11",
+          "System.IO": "4.1.0",
+          "System.Reflection": "4.1.0",
+          "System.Resources.ResourceManager": "4.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Runtime.Extensions": "4.1.0",
+          "System.Text.Encoding": "4.0.11",
+          "System.Threading": "4.0.11",
+          "System.Xml.ReaderWriter": "4.0.11"
+        },
+        "compile": {
+          "ref/netstandard1.3/System.Xml.XDocument.dll": {}
+        },
+        "runtime": {
+          "lib/netstandard1.3/System.Xml.XDocument.dll": {}
+        }
+      },
+      "System.Xml.XmlDocument/4.0.1": {
+        "type": "package",
+        "dependencies": {
+          "System.Collections": "4.0.11",
+          "System.Diagnostics.Debug": "4.0.11",
+          "System.Globalization": "4.0.11",
+          "System.IO": "4.1.0",
+          "System.Resources.ResourceManager": "4.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Runtime.Extensions": "4.1.0",
+          "System.Text.Encoding": "4.0.11",
+          "System.Threading": "4.0.11",
+          "System.Xml.ReaderWriter": "4.0.11"
+        },
+        "compile": {
+          "ref/netstandard1.3/_._": {}
+        },
+        "runtime": {
+          "lib/netstandard1.3/System.Xml.XmlDocument.dll": {}
+        }
+      },
+      "System.Xml.XmlSerializer/4.0.11": {
+        "type": "package",
+        "dependencies": {
+          "System.Collections": "4.0.11",
+          "System.Globalization": "4.0.11",
+          "System.IO": "4.1.0",
+          "System.Linq": "4.1.0",
+          "System.Reflection": "4.1.0",
+          "System.Reflection.Emit": "4.0.1",
+          "System.Reflection.Emit.ILGeneration": "4.0.1",
+          "System.Reflection.Extensions": "4.0.1",
+          "System.Reflection.Primitives": "4.0.1",
+          "System.Reflection.TypeExtensions": "4.1.0",
+          "System.Resources.ResourceManager": "4.0.1",
+          "System.Runtime": "4.1.0",
+          "System.Runtime.Extensions": "4.1.0",
+          "System.Text.RegularExpressions": "4.1.0",
+          "System.Threading": "4.0.11",
+          "System.Xml.ReaderWriter": "4.0.11",
+          "System.Xml.XmlDocument": "4.0.1"
+        },
+        "compile": {
+          "ref/netstandard1.3/System.Xml.XmlSerializer.dll": {}
+        },
+        "runtime": {
+          "lib/netstandard1.3/System.Xml.XmlSerializer.dll": {}
+        }
+      },
+      "MediaBrowser.Common/1.0.0": {
+        "type": "project",
+        "framework": ".NETStandard,Version=v1.6",
+        "dependencies": {
+          "MediaBrowser.Model": "1.0.0",
+          "NETStandard.Library": "1.6.0"
+        }
+      },
+      "MediaBrowser.Model/1.0.0": {
+        "type": "project",
+        "framework": ".NETStandard,Version=v1.6",
+        "dependencies": {
+          "NETStandard.Library": "1.6.0"
+        }
+      }
+    }
+  },
+  "libraries": {
+    "Microsoft.NETCore.Platforms/1.0.1": {
+      "sha512": "2G6OjjJzwBfNOO8myRV/nFrbTw5iA+DEm0N+qUqhrOmaVtn4pC77h38I1jsXGw5VH55+dPfQsqHD0We9sCl9FQ==",
+      "type": "package",
+      "path": "Microsoft.NETCore.Platforms/1.0.1",
+      "files": [
+        "Microsoft.NETCore.Platforms.1.0.1.nupkg.sha512",
+        "Microsoft.NETCore.Platforms.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/netstandard1.0/_._",
+        "runtime.json"
+      ]
+    },
+    "Microsoft.NETCore.Targets/1.0.1": {
+      "sha512": "rkn+fKobF/cbWfnnfBOQHKVKIOpxMZBvlSHkqDWgBpwGDcLRduvs3D9OLGeV6GWGvVwNlVi2CBbTjuPmtHvyNw==",
+      "type": "package",
+      "path": "Microsoft.NETCore.Targets/1.0.1",
+      "files": [
+        "Microsoft.NETCore.Targets.1.0.1.nupkg.sha512",
+        "Microsoft.NETCore.Targets.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/netstandard1.0/_._",
+        "runtime.json"
+      ]
+    },
+    "Microsoft.Win32.Primitives/4.0.1": {
+      "sha512": "fQnBHO9DgcmkC9dYSJoBqo6sH1VJwJprUHh8F3hbcRlxiQiBUuTntdk8tUwV490OqC2kQUrinGwZyQHTieuXRA==",
+      "type": "package",
+      "path": "Microsoft.Win32.Primitives/4.0.1",
+      "files": [
+        "Microsoft.Win32.Primitives.4.0.1.nupkg.sha512",
+        "Microsoft.Win32.Primitives.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net46/Microsoft.Win32.Primitives.dll",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net46/Microsoft.Win32.Primitives.dll",
+        "ref/netstandard1.3/Microsoft.Win32.Primitives.dll",
+        "ref/netstandard1.3/Microsoft.Win32.Primitives.xml",
+        "ref/netstandard1.3/de/Microsoft.Win32.Primitives.xml",
+        "ref/netstandard1.3/es/Microsoft.Win32.Primitives.xml",
+        "ref/netstandard1.3/fr/Microsoft.Win32.Primitives.xml",
+        "ref/netstandard1.3/it/Microsoft.Win32.Primitives.xml",
+        "ref/netstandard1.3/ja/Microsoft.Win32.Primitives.xml",
+        "ref/netstandard1.3/ko/Microsoft.Win32.Primitives.xml",
+        "ref/netstandard1.3/ru/Microsoft.Win32.Primitives.xml",
+        "ref/netstandard1.3/zh-hans/Microsoft.Win32.Primitives.xml",
+        "ref/netstandard1.3/zh-hant/Microsoft.Win32.Primitives.xml",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "NETStandard.Library/1.6.0": {
+      "sha512": "ypsCvIdCZ4IoYASJHt6tF2fMo7N30NLgV1EbmC+snO490OMl9FvVxmumw14rhReWU3j3g7BYudG6YCrchwHJlA==",
+      "type": "package",
+      "path": "NETStandard.Library/1.6.0",
+      "files": [
+        "NETStandard.Library.1.6.0.nupkg.sha512",
+        "NETStandard.Library.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt"
+      ]
+    },
+    "runtime.native.System/4.0.0": {
+      "sha512": "QfS/nQI7k/BLgmLrw7qm7YBoULEvgWnPI+cYsbfCVFTW8Aj+i8JhccxcFMu1RWms0YZzF+UHguNBK4Qn89e2Sg==",
+      "type": "package",
+      "path": "runtime.native.System/4.0.0",
+      "files": [
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/netstandard1.0/_._",
+        "runtime.native.System.4.0.0.nupkg.sha512",
+        "runtime.native.System.nuspec"
+      ]
+    },
+    "runtime.native.System.IO.Compression/4.1.0": {
+      "sha512": "Ob7nvnJBox1aaB222zSVZSkf4WrebPG4qFscfK7vmD7P7NxoSxACQLtO7ytWpqXDn2wcd/+45+EAZ7xjaPip8A==",
+      "type": "package",
+      "path": "runtime.native.System.IO.Compression/4.1.0",
+      "files": [
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/netstandard1.0/_._",
+        "runtime.native.System.IO.Compression.4.1.0.nupkg.sha512",
+        "runtime.native.System.IO.Compression.nuspec"
+      ]
+    },
+    "runtime.native.System.Net.Http/4.0.1": {
+      "sha512": "Nh0UPZx2Vifh8r+J+H2jxifZUD3sBrmolgiFWJd2yiNrxO0xTa6bAw3YwRn1VOiSen/tUXMS31ttNItCZ6lKuA==",
+      "type": "package",
+      "path": "runtime.native.System.Net.Http/4.0.1",
+      "files": [
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/netstandard1.0/_._",
+        "runtime.native.System.Net.Http.4.0.1.nupkg.sha512",
+        "runtime.native.System.Net.Http.nuspec"
+      ]
+    },
+    "runtime.native.System.Security.Cryptography/4.0.0": {
+      "sha512": "2CQK0jmO6Eu7ZeMgD+LOFbNJSXHFVQbCJJkEyEwowh1SCgYnrn9W9RykMfpeeVGw7h4IBvYikzpGUlmZTUafJw==",
+      "type": "package",
+      "path": "runtime.native.System.Security.Cryptography/4.0.0",
+      "files": [
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/netstandard1.0/_._",
+        "runtime.native.System.Security.Cryptography.4.0.0.nupkg.sha512",
+        "runtime.native.System.Security.Cryptography.nuspec"
+      ]
+    },
+    "System.AppContext/4.1.0": {
+      "sha512": "3QjO4jNV7PdKkmQAVp9atA+usVnKRwI3Kx1nMwJ93T0LcQfx7pKAYk0nKz5wn1oP5iqlhZuy6RXOFdhr7rDwow==",
+      "type": "package",
+      "path": "System.AppContext/4.1.0",
+      "files": [
+        "System.AppContext.4.1.0.nupkg.sha512",
+        "System.AppContext.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net46/System.AppContext.dll",
+        "lib/net463/System.AppContext.dll",
+        "lib/netcore50/System.AppContext.dll",
+        "lib/netstandard1.6/System.AppContext.dll",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net46/System.AppContext.dll",
+        "ref/net463/System.AppContext.dll",
+        "ref/netstandard/_._",
+        "ref/netstandard1.3/System.AppContext.dll",
+        "ref/netstandard1.3/System.AppContext.xml",
+        "ref/netstandard1.3/de/System.AppContext.xml",
+        "ref/netstandard1.3/es/System.AppContext.xml",
+        "ref/netstandard1.3/fr/System.AppContext.xml",
+        "ref/netstandard1.3/it/System.AppContext.xml",
+        "ref/netstandard1.3/ja/System.AppContext.xml",
+        "ref/netstandard1.3/ko/System.AppContext.xml",
+        "ref/netstandard1.3/ru/System.AppContext.xml",
+        "ref/netstandard1.3/zh-hans/System.AppContext.xml",
+        "ref/netstandard1.3/zh-hant/System.AppContext.xml",
+        "ref/netstandard1.6/System.AppContext.dll",
+        "ref/netstandard1.6/System.AppContext.xml",
+        "ref/netstandard1.6/de/System.AppContext.xml",
+        "ref/netstandard1.6/es/System.AppContext.xml",
+        "ref/netstandard1.6/fr/System.AppContext.xml",
+        "ref/netstandard1.6/it/System.AppContext.xml",
+        "ref/netstandard1.6/ja/System.AppContext.xml",
+        "ref/netstandard1.6/ko/System.AppContext.xml",
+        "ref/netstandard1.6/ru/System.AppContext.xml",
+        "ref/netstandard1.6/zh-hans/System.AppContext.xml",
+        "ref/netstandard1.6/zh-hant/System.AppContext.xml",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._",
+        "runtimes/aot/lib/netcore50/System.AppContext.dll"
+      ]
+    },
+    "System.Buffers/4.0.0": {
+      "sha512": "msXumHfjjURSkvxUjYuq4N2ghHoRi2VpXcKMA7gK6ujQfU3vGpl+B6ld0ATRg+FZFpRyA6PgEPA+VlIkTeNf2w==",
+      "type": "package",
+      "path": "System.Buffers/4.0.0",
+      "files": [
+        "System.Buffers.4.0.0.nupkg.sha512",
+        "System.Buffers.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/netstandard1.1/.xml",
+        "lib/netstandard1.1/System.Buffers.dll"
+      ]
+    },
+    "System.Collections/4.0.11": {
+      "sha512": "YUJGz6eFKqS0V//mLt25vFGrrCvOnsXjlvFQs+KimpwNxug9x0Pzy4PlFMU3Q2IzqAa9G2L4LsK3+9vCBK7oTg==",
+      "type": "package",
+      "path": "System.Collections/4.0.11",
+      "files": [
+        "System.Collections.4.0.11.nupkg.sha512",
+        "System.Collections.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/_._",
+        "lib/portable-net45+win8+wp8+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wp80/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net45/_._",
+        "ref/netcore50/System.Collections.dll",
+        "ref/netcore50/System.Collections.xml",
+        "ref/netcore50/de/System.Collections.xml",
+        "ref/netcore50/es/System.Collections.xml",
+        "ref/netcore50/fr/System.Collections.xml",
+        "ref/netcore50/it/System.Collections.xml",
+        "ref/netcore50/ja/System.Collections.xml",
+        "ref/netcore50/ko/System.Collections.xml",
+        "ref/netcore50/ru/System.Collections.xml",
+        "ref/netcore50/zh-hans/System.Collections.xml",
+        "ref/netcore50/zh-hant/System.Collections.xml",
+        "ref/netstandard1.0/System.Collections.dll",
+        "ref/netstandard1.0/System.Collections.xml",
+        "ref/netstandard1.0/de/System.Collections.xml",
+        "ref/netstandard1.0/es/System.Collections.xml",
+        "ref/netstandard1.0/fr/System.Collections.xml",
+        "ref/netstandard1.0/it/System.Collections.xml",
+        "ref/netstandard1.0/ja/System.Collections.xml",
+        "ref/netstandard1.0/ko/System.Collections.xml",
+        "ref/netstandard1.0/ru/System.Collections.xml",
+        "ref/netstandard1.0/zh-hans/System.Collections.xml",
+        "ref/netstandard1.0/zh-hant/System.Collections.xml",
+        "ref/netstandard1.3/System.Collections.dll",
+        "ref/netstandard1.3/System.Collections.xml",
+        "ref/netstandard1.3/de/System.Collections.xml",
+        "ref/netstandard1.3/es/System.Collections.xml",
+        "ref/netstandard1.3/fr/System.Collections.xml",
+        "ref/netstandard1.3/it/System.Collections.xml",
+        "ref/netstandard1.3/ja/System.Collections.xml",
+        "ref/netstandard1.3/ko/System.Collections.xml",
+        "ref/netstandard1.3/ru/System.Collections.xml",
+        "ref/netstandard1.3/zh-hans/System.Collections.xml",
+        "ref/netstandard1.3/zh-hant/System.Collections.xml",
+        "ref/portable-net45+win8+wp8+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wp80/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Collections.Concurrent/4.0.12": {
+      "sha512": "2gBcbb3drMLgxlI0fBfxMA31ec6AEyYCHygGse4vxceJan8mRIWeKJ24BFzN7+bi/NFTgdIgufzb94LWO5EERQ==",
+      "type": "package",
+      "path": "System.Collections.Concurrent/4.0.12",
+      "files": [
+        "System.Collections.Concurrent.4.0.12.nupkg.sha512",
+        "System.Collections.Concurrent.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/_._",
+        "lib/netcore50/System.Collections.Concurrent.dll",
+        "lib/netstandard1.3/System.Collections.Concurrent.dll",
+        "lib/portable-net45+win8+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net45/_._",
+        "ref/netcore50/System.Collections.Concurrent.dll",
+        "ref/netcore50/System.Collections.Concurrent.xml",
+        "ref/netcore50/de/System.Collections.Concurrent.xml",
+        "ref/netcore50/es/System.Collections.Concurrent.xml",
+        "ref/netcore50/fr/System.Collections.Concurrent.xml",
+        "ref/netcore50/it/System.Collections.Concurrent.xml",
+        "ref/netcore50/ja/System.Collections.Concurrent.xml",
+        "ref/netcore50/ko/System.Collections.Concurrent.xml",
+        "ref/netcore50/ru/System.Collections.Concurrent.xml",
+        "ref/netcore50/zh-hans/System.Collections.Concurrent.xml",
+        "ref/netcore50/zh-hant/System.Collections.Concurrent.xml",
+        "ref/netstandard1.1/System.Collections.Concurrent.dll",
+        "ref/netstandard1.1/System.Collections.Concurrent.xml",
+        "ref/netstandard1.1/de/System.Collections.Concurrent.xml",
+        "ref/netstandard1.1/es/System.Collections.Concurrent.xml",
+        "ref/netstandard1.1/fr/System.Collections.Concurrent.xml",
+        "ref/netstandard1.1/it/System.Collections.Concurrent.xml",
+        "ref/netstandard1.1/ja/System.Collections.Concurrent.xml",
+        "ref/netstandard1.1/ko/System.Collections.Concurrent.xml",
+        "ref/netstandard1.1/ru/System.Collections.Concurrent.xml",
+        "ref/netstandard1.1/zh-hans/System.Collections.Concurrent.xml",
+        "ref/netstandard1.1/zh-hant/System.Collections.Concurrent.xml",
+        "ref/netstandard1.3/System.Collections.Concurrent.dll",
+        "ref/netstandard1.3/System.Collections.Concurrent.xml",
+        "ref/netstandard1.3/de/System.Collections.Concurrent.xml",
+        "ref/netstandard1.3/es/System.Collections.Concurrent.xml",
+        "ref/netstandard1.3/fr/System.Collections.Concurrent.xml",
+        "ref/netstandard1.3/it/System.Collections.Concurrent.xml",
+        "ref/netstandard1.3/ja/System.Collections.Concurrent.xml",
+        "ref/netstandard1.3/ko/System.Collections.Concurrent.xml",
+        "ref/netstandard1.3/ru/System.Collections.Concurrent.xml",
+        "ref/netstandard1.3/zh-hans/System.Collections.Concurrent.xml",
+        "ref/netstandard1.3/zh-hant/System.Collections.Concurrent.xml",
+        "ref/portable-net45+win8+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Console/4.0.0": {
+      "sha512": "qSKUSOIiYA/a0g5XXdxFcUFmv1hNICBD7QZ0QhGYVipPIhvpiydY8VZqr1thmCXvmn8aipMg64zuanB4eotK9A==",
+      "type": "package",
+      "path": "System.Console/4.0.0",
+      "files": [
+        "System.Console.4.0.0.nupkg.sha512",
+        "System.Console.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net46/System.Console.dll",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net46/System.Console.dll",
+        "ref/netstandard1.3/System.Console.dll",
+        "ref/netstandard1.3/System.Console.xml",
+        "ref/netstandard1.3/de/System.Console.xml",
+        "ref/netstandard1.3/es/System.Console.xml",
+        "ref/netstandard1.3/fr/System.Console.xml",
+        "ref/netstandard1.3/it/System.Console.xml",
+        "ref/netstandard1.3/ja/System.Console.xml",
+        "ref/netstandard1.3/ko/System.Console.xml",
+        "ref/netstandard1.3/ru/System.Console.xml",
+        "ref/netstandard1.3/zh-hans/System.Console.xml",
+        "ref/netstandard1.3/zh-hant/System.Console.xml",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Diagnostics.Debug/4.0.11": {
+      "sha512": "w5U95fVKHY4G8ASs/K5iK3J5LY+/dLFd4vKejsnI/ZhBsWS9hQakfx3Zr7lRWKg4tAw9r4iktyvsTagWkqYCiw==",
+      "type": "package",
+      "path": "System.Diagnostics.Debug/4.0.11",
+      "files": [
+        "System.Diagnostics.Debug.4.0.11.nupkg.sha512",
+        "System.Diagnostics.Debug.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/_._",
+        "lib/portable-net45+win8+wp8+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wp80/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net45/_._",
+        "ref/netcore50/System.Diagnostics.Debug.dll",
+        "ref/netcore50/System.Diagnostics.Debug.xml",
+        "ref/netcore50/de/System.Diagnostics.Debug.xml",
+        "ref/netcore50/es/System.Diagnostics.Debug.xml",
+        "ref/netcore50/fr/System.Diagnostics.Debug.xml",
+        "ref/netcore50/it/System.Diagnostics.Debug.xml",
+        "ref/netcore50/ja/System.Diagnostics.Debug.xml",
+        "ref/netcore50/ko/System.Diagnostics.Debug.xml",
+        "ref/netcore50/ru/System.Diagnostics.Debug.xml",
+        "ref/netcore50/zh-hans/System.Diagnostics.Debug.xml",
+        "ref/netcore50/zh-hant/System.Diagnostics.Debug.xml",
+        "ref/netstandard1.0/System.Diagnostics.Debug.dll",
+        "ref/netstandard1.0/System.Diagnostics.Debug.xml",
+        "ref/netstandard1.0/de/System.Diagnostics.Debug.xml",
+        "ref/netstandard1.0/es/System.Diagnostics.Debug.xml",
+        "ref/netstandard1.0/fr/System.Diagnostics.Debug.xml",
+        "ref/netstandard1.0/it/System.Diagnostics.Debug.xml",
+        "ref/netstandard1.0/ja/System.Diagnostics.Debug.xml",
+        "ref/netstandard1.0/ko/System.Diagnostics.Debug.xml",
+        "ref/netstandard1.0/ru/System.Diagnostics.Debug.xml",
+        "ref/netstandard1.0/zh-hans/System.Diagnostics.Debug.xml",
+        "ref/netstandard1.0/zh-hant/System.Diagnostics.Debug.xml",
+        "ref/netstandard1.3/System.Diagnostics.Debug.dll",
+        "ref/netstandard1.3/System.Diagnostics.Debug.xml",
+        "ref/netstandard1.3/de/System.Diagnostics.Debug.xml",
+        "ref/netstandard1.3/es/System.Diagnostics.Debug.xml",
+        "ref/netstandard1.3/fr/System.Diagnostics.Debug.xml",
+        "ref/netstandard1.3/it/System.Diagnostics.Debug.xml",
+        "ref/netstandard1.3/ja/System.Diagnostics.Debug.xml",
+        "ref/netstandard1.3/ko/System.Diagnostics.Debug.xml",
+        "ref/netstandard1.3/ru/System.Diagnostics.Debug.xml",
+        "ref/netstandard1.3/zh-hans/System.Diagnostics.Debug.xml",
+        "ref/netstandard1.3/zh-hant/System.Diagnostics.Debug.xml",
+        "ref/portable-net45+win8+wp8+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wp80/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Diagnostics.DiagnosticSource/4.0.0": {
+      "sha512": "YKglnq4BMTJxfcr6nuT08g+yJ0UxdePIHxosiLuljuHIUR6t4KhFsyaHOaOc1Ofqp0PUvJ0EmcgiEz6T7vEx3w==",
+      "type": "package",
+      "path": "System.Diagnostics.DiagnosticSource/4.0.0",
+      "files": [
+        "System.Diagnostics.DiagnosticSource.4.0.0.nupkg.sha512",
+        "System.Diagnostics.DiagnosticSource.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/net46/System.Diagnostics.DiagnosticSource.dll",
+        "lib/net46/System.Diagnostics.DiagnosticSource.xml",
+        "lib/netstandard1.1/System.Diagnostics.DiagnosticSource.dll",
+        "lib/netstandard1.1/System.Diagnostics.DiagnosticSource.xml",
+        "lib/netstandard1.3/System.Diagnostics.DiagnosticSource.dll",
+        "lib/netstandard1.3/System.Diagnostics.DiagnosticSource.xml",
+        "lib/portable-net45+win8+wpa81/System.Diagnostics.DiagnosticSource.dll",
+        "lib/portable-net45+win8+wpa81/System.Diagnostics.DiagnosticSource.xml"
+      ]
+    },
+    "System.Diagnostics.Tools/4.0.1": {
+      "sha512": "xBfJ8pnd4C17dWaC9FM6aShzbJcRNMChUMD42I6772KGGrqaFdumwhn9OdM68erj1ueNo3xdQ1EwiFjK5k8p0g==",
+      "type": "package",
+      "path": "System.Diagnostics.Tools/4.0.1",
+      "files": [
+        "System.Diagnostics.Tools.4.0.1.nupkg.sha512",
+        "System.Diagnostics.Tools.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/_._",
+        "lib/portable-net45+win8+wp8+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wp80/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net45/_._",
+        "ref/netcore50/System.Diagnostics.Tools.dll",
+        "ref/netcore50/System.Diagnostics.Tools.xml",
+        "ref/netcore50/de/System.Diagnostics.Tools.xml",
+        "ref/netcore50/es/System.Diagnostics.Tools.xml",
+        "ref/netcore50/fr/System.Diagnostics.Tools.xml",
+        "ref/netcore50/it/System.Diagnostics.Tools.xml",
+        "ref/netcore50/ja/System.Diagnostics.Tools.xml",
+        "ref/netcore50/ko/System.Diagnostics.Tools.xml",
+        "ref/netcore50/ru/System.Diagnostics.Tools.xml",
+        "ref/netcore50/zh-hans/System.Diagnostics.Tools.xml",
+        "ref/netcore50/zh-hant/System.Diagnostics.Tools.xml",
+        "ref/netstandard1.0/System.Diagnostics.Tools.dll",
+        "ref/netstandard1.0/System.Diagnostics.Tools.xml",
+        "ref/netstandard1.0/de/System.Diagnostics.Tools.xml",
+        "ref/netstandard1.0/es/System.Diagnostics.Tools.xml",
+        "ref/netstandard1.0/fr/System.Diagnostics.Tools.xml",
+        "ref/netstandard1.0/it/System.Diagnostics.Tools.xml",
+        "ref/netstandard1.0/ja/System.Diagnostics.Tools.xml",
+        "ref/netstandard1.0/ko/System.Diagnostics.Tools.xml",
+        "ref/netstandard1.0/ru/System.Diagnostics.Tools.xml",
+        "ref/netstandard1.0/zh-hans/System.Diagnostics.Tools.xml",
+        "ref/netstandard1.0/zh-hant/System.Diagnostics.Tools.xml",
+        "ref/portable-net45+win8+wp8+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wp80/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Diagnostics.Tracing/4.1.0": {
+      "sha512": "vDN1PoMZCkkdNjvZLql592oYJZgS7URcJzJ7bxeBgGtx5UtR5leNm49VmfHGqIffX4FKacHbI3H6UyNSHQknBg==",
+      "type": "package",
+      "path": "System.Diagnostics.Tracing/4.1.0",
+      "files": [
+        "System.Diagnostics.Tracing.4.1.0.nupkg.sha512",
+        "System.Diagnostics.Tracing.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/_._",
+        "lib/net462/System.Diagnostics.Tracing.dll",
+        "lib/portable-net45+win8+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net45/_._",
+        "ref/net462/System.Diagnostics.Tracing.dll",
+        "ref/netcore50/System.Diagnostics.Tracing.dll",
+        "ref/netcore50/System.Diagnostics.Tracing.xml",
+        "ref/netcore50/de/System.Diagnostics.Tracing.xml",
+        "ref/netcore50/es/System.Diagnostics.Tracing.xml",
+        "ref/netcore50/fr/System.Diagnostics.Tracing.xml",
+        "ref/netcore50/it/System.Diagnostics.Tracing.xml",
+        "ref/netcore50/ja/System.Diagnostics.Tracing.xml",
+        "ref/netcore50/ko/System.Diagnostics.Tracing.xml",
+        "ref/netcore50/ru/System.Diagnostics.Tracing.xml",
+        "ref/netcore50/zh-hans/System.Diagnostics.Tracing.xml",
+        "ref/netcore50/zh-hant/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.1/System.Diagnostics.Tracing.dll",
+        "ref/netstandard1.1/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.1/de/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.1/es/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.1/fr/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.1/it/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.1/ja/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.1/ko/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.1/ru/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.1/zh-hans/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.1/zh-hant/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.2/System.Diagnostics.Tracing.dll",
+        "ref/netstandard1.2/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.2/de/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.2/es/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.2/fr/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.2/it/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.2/ja/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.2/ko/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.2/ru/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.2/zh-hans/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.2/zh-hant/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.3/System.Diagnostics.Tracing.dll",
+        "ref/netstandard1.3/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.3/de/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.3/es/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.3/fr/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.3/it/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.3/ja/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.3/ko/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.3/ru/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.3/zh-hans/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.3/zh-hant/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.5/System.Diagnostics.Tracing.dll",
+        "ref/netstandard1.5/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.5/de/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.5/es/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.5/fr/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.5/it/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.5/ja/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.5/ko/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.5/ru/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.5/zh-hans/System.Diagnostics.Tracing.xml",
+        "ref/netstandard1.5/zh-hant/System.Diagnostics.Tracing.xml",
+        "ref/portable-net45+win8+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Globalization/4.0.11": {
+      "sha512": "B95h0YLEL2oSnwF/XjqSWKnwKOy/01VWkNlsCeMTFJLLabflpGV26nK164eRs5GiaRSBGpOxQ3pKoSnnyZN5pg==",
+      "type": "package",
+      "path": "System.Globalization/4.0.11",
+      "files": [
+        "System.Globalization.4.0.11.nupkg.sha512",
+        "System.Globalization.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/_._",
+        "lib/portable-net45+win8+wp8+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wp80/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net45/_._",
+        "ref/netcore50/System.Globalization.dll",
+        "ref/netcore50/System.Globalization.xml",
+        "ref/netcore50/de/System.Globalization.xml",
+        "ref/netcore50/es/System.Globalization.xml",
+        "ref/netcore50/fr/System.Globalization.xml",
+        "ref/netcore50/it/System.Globalization.xml",
+        "ref/netcore50/ja/System.Globalization.xml",
+        "ref/netcore50/ko/System.Globalization.xml",
+        "ref/netcore50/ru/System.Globalization.xml",
+        "ref/netcore50/zh-hans/System.Globalization.xml",
+        "ref/netcore50/zh-hant/System.Globalization.xml",
+        "ref/netstandard1.0/System.Globalization.dll",
+        "ref/netstandard1.0/System.Globalization.xml",
+        "ref/netstandard1.0/de/System.Globalization.xml",
+        "ref/netstandard1.0/es/System.Globalization.xml",
+        "ref/netstandard1.0/fr/System.Globalization.xml",
+        "ref/netstandard1.0/it/System.Globalization.xml",
+        "ref/netstandard1.0/ja/System.Globalization.xml",
+        "ref/netstandard1.0/ko/System.Globalization.xml",
+        "ref/netstandard1.0/ru/System.Globalization.xml",
+        "ref/netstandard1.0/zh-hans/System.Globalization.xml",
+        "ref/netstandard1.0/zh-hant/System.Globalization.xml",
+        "ref/netstandard1.3/System.Globalization.dll",
+        "ref/netstandard1.3/System.Globalization.xml",
+        "ref/netstandard1.3/de/System.Globalization.xml",
+        "ref/netstandard1.3/es/System.Globalization.xml",
+        "ref/netstandard1.3/fr/System.Globalization.xml",
+        "ref/netstandard1.3/it/System.Globalization.xml",
+        "ref/netstandard1.3/ja/System.Globalization.xml",
+        "ref/netstandard1.3/ko/System.Globalization.xml",
+        "ref/netstandard1.3/ru/System.Globalization.xml",
+        "ref/netstandard1.3/zh-hans/System.Globalization.xml",
+        "ref/netstandard1.3/zh-hant/System.Globalization.xml",
+        "ref/portable-net45+win8+wp8+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wp80/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Globalization.Calendars/4.0.1": {
+      "sha512": "L1c6IqeQ88vuzC1P81JeHmHA8mxq8a18NUBNXnIY/BVb+TCyAaGIFbhpZt60h9FJNmisymoQkHEFSE9Vslja1Q==",
+      "type": "package",
+      "path": "System.Globalization.Calendars/4.0.1",
+      "files": [
+        "System.Globalization.Calendars.4.0.1.nupkg.sha512",
+        "System.Globalization.Calendars.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net46/System.Globalization.Calendars.dll",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net46/System.Globalization.Calendars.dll",
+        "ref/netstandard1.3/System.Globalization.Calendars.dll",
+        "ref/netstandard1.3/System.Globalization.Calendars.xml",
+        "ref/netstandard1.3/de/System.Globalization.Calendars.xml",
+        "ref/netstandard1.3/es/System.Globalization.Calendars.xml",
+        "ref/netstandard1.3/fr/System.Globalization.Calendars.xml",
+        "ref/netstandard1.3/it/System.Globalization.Calendars.xml",
+        "ref/netstandard1.3/ja/System.Globalization.Calendars.xml",
+        "ref/netstandard1.3/ko/System.Globalization.Calendars.xml",
+        "ref/netstandard1.3/ru/System.Globalization.Calendars.xml",
+        "ref/netstandard1.3/zh-hans/System.Globalization.Calendars.xml",
+        "ref/netstandard1.3/zh-hant/System.Globalization.Calendars.xml",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Globalization.Extensions/4.0.1": {
+      "sha512": "KKo23iKeOaIg61SSXwjANN7QYDr/3op3OWGGzDzz7mypx0Za0fZSeG0l6cco8Ntp8YMYkIQcAqlk8yhm5/Uhcg==",
+      "type": "package",
+      "path": "System.Globalization.Extensions/4.0.1",
+      "files": [
+        "System.Globalization.Extensions.4.0.1.nupkg.sha512",
+        "System.Globalization.Extensions.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net46/System.Globalization.Extensions.dll",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net46/System.Globalization.Extensions.dll",
+        "ref/netstandard1.3/System.Globalization.Extensions.dll",
+        "ref/netstandard1.3/System.Globalization.Extensions.xml",
+        "ref/netstandard1.3/de/System.Globalization.Extensions.xml",
+        "ref/netstandard1.3/es/System.Globalization.Extensions.xml",
+        "ref/netstandard1.3/fr/System.Globalization.Extensions.xml",
+        "ref/netstandard1.3/it/System.Globalization.Extensions.xml",
+        "ref/netstandard1.3/ja/System.Globalization.Extensions.xml",
+        "ref/netstandard1.3/ko/System.Globalization.Extensions.xml",
+        "ref/netstandard1.3/ru/System.Globalization.Extensions.xml",
+        "ref/netstandard1.3/zh-hans/System.Globalization.Extensions.xml",
+        "ref/netstandard1.3/zh-hant/System.Globalization.Extensions.xml",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._",
+        "runtimes/unix/lib/netstandard1.3/System.Globalization.Extensions.dll",
+        "runtimes/win/lib/net46/System.Globalization.Extensions.dll",
+        "runtimes/win/lib/netstandard1.3/System.Globalization.Extensions.dll"
+      ]
+    },
+    "System.IO/4.1.0": {
+      "sha512": "3KlTJceQc3gnGIaHZ7UBZO26SHL1SHE4ddrmiwumFnId+CEHP+O8r386tZKaE6zlk5/mF8vifMBzHj9SaXN+mQ==",
+      "type": "package",
+      "path": "System.IO/4.1.0",
+      "files": [
+        "System.IO.4.1.0.nupkg.sha512",
+        "System.IO.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/_._",
+        "lib/net462/System.IO.dll",
+        "lib/portable-net45+win8+wp8+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wp80/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net45/_._",
+        "ref/net462/System.IO.dll",
+        "ref/netcore50/System.IO.dll",
+        "ref/netcore50/System.IO.xml",
+        "ref/netcore50/de/System.IO.xml",
+        "ref/netcore50/es/System.IO.xml",
+        "ref/netcore50/fr/System.IO.xml",
+        "ref/netcore50/it/System.IO.xml",
+        "ref/netcore50/ja/System.IO.xml",
+        "ref/netcore50/ko/System.IO.xml",
+        "ref/netcore50/ru/System.IO.xml",
+        "ref/netcore50/zh-hans/System.IO.xml",
+        "ref/netcore50/zh-hant/System.IO.xml",
+        "ref/netstandard1.0/System.IO.dll",
+        "ref/netstandard1.0/System.IO.xml",
+        "ref/netstandard1.0/de/System.IO.xml",
+        "ref/netstandard1.0/es/System.IO.xml",
+        "ref/netstandard1.0/fr/System.IO.xml",
+        "ref/netstandard1.0/it/System.IO.xml",
+        "ref/netstandard1.0/ja/System.IO.xml",
+        "ref/netstandard1.0/ko/System.IO.xml",
+        "ref/netstandard1.0/ru/System.IO.xml",
+        "ref/netstandard1.0/zh-hans/System.IO.xml",
+        "ref/netstandard1.0/zh-hant/System.IO.xml",
+        "ref/netstandard1.3/System.IO.dll",
+        "ref/netstandard1.3/System.IO.xml",
+        "ref/netstandard1.3/de/System.IO.xml",
+        "ref/netstandard1.3/es/System.IO.xml",
+        "ref/netstandard1.3/fr/System.IO.xml",
+        "ref/netstandard1.3/it/System.IO.xml",
+        "ref/netstandard1.3/ja/System.IO.xml",
+        "ref/netstandard1.3/ko/System.IO.xml",
+        "ref/netstandard1.3/ru/System.IO.xml",
+        "ref/netstandard1.3/zh-hans/System.IO.xml",
+        "ref/netstandard1.3/zh-hant/System.IO.xml",
+        "ref/netstandard1.5/System.IO.dll",
+        "ref/netstandard1.5/System.IO.xml",
+        "ref/netstandard1.5/de/System.IO.xml",
+        "ref/netstandard1.5/es/System.IO.xml",
+        "ref/netstandard1.5/fr/System.IO.xml",
+        "ref/netstandard1.5/it/System.IO.xml",
+        "ref/netstandard1.5/ja/System.IO.xml",
+        "ref/netstandard1.5/ko/System.IO.xml",
+        "ref/netstandard1.5/ru/System.IO.xml",
+        "ref/netstandard1.5/zh-hans/System.IO.xml",
+        "ref/netstandard1.5/zh-hant/System.IO.xml",
+        "ref/portable-net45+win8+wp8+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wp80/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.IO.Compression/4.1.0": {
+      "sha512": "TjnBS6eztThSzeSib+WyVbLzEdLKUcEHN69VtS3u8aAsSc18FU6xCZlNWWsEd8SKcXAE+y1sOu7VbU8sUeM0sg==",
+      "type": "package",
+      "path": "System.IO.Compression/4.1.0",
+      "files": [
+        "System.IO.Compression.4.1.0.nupkg.sha512",
+        "System.IO.Compression.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/_._",
+        "lib/net46/System.IO.Compression.dll",
+        "lib/portable-net45+win8+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net45/_._",
+        "ref/net46/System.IO.Compression.dll",
+        "ref/netcore50/System.IO.Compression.dll",
+        "ref/netcore50/System.IO.Compression.xml",
+        "ref/netcore50/de/System.IO.Compression.xml",
+        "ref/netcore50/es/System.IO.Compression.xml",
+        "ref/netcore50/fr/System.IO.Compression.xml",
+        "ref/netcore50/it/System.IO.Compression.xml",
+        "ref/netcore50/ja/System.IO.Compression.xml",
+        "ref/netcore50/ko/System.IO.Compression.xml",
+        "ref/netcore50/ru/System.IO.Compression.xml",
+        "ref/netcore50/zh-hans/System.IO.Compression.xml",
+        "ref/netcore50/zh-hant/System.IO.Compression.xml",
+        "ref/netstandard1.1/System.IO.Compression.dll",
+        "ref/netstandard1.1/System.IO.Compression.xml",
+        "ref/netstandard1.1/de/System.IO.Compression.xml",
+        "ref/netstandard1.1/es/System.IO.Compression.xml",
+        "ref/netstandard1.1/fr/System.IO.Compression.xml",
+        "ref/netstandard1.1/it/System.IO.Compression.xml",
+        "ref/netstandard1.1/ja/System.IO.Compression.xml",
+        "ref/netstandard1.1/ko/System.IO.Compression.xml",
+        "ref/netstandard1.1/ru/System.IO.Compression.xml",
+        "ref/netstandard1.1/zh-hans/System.IO.Compression.xml",
+        "ref/netstandard1.1/zh-hant/System.IO.Compression.xml",
+        "ref/netstandard1.3/System.IO.Compression.dll",
+        "ref/netstandard1.3/System.IO.Compression.xml",
+        "ref/netstandard1.3/de/System.IO.Compression.xml",
+        "ref/netstandard1.3/es/System.IO.Compression.xml",
+        "ref/netstandard1.3/fr/System.IO.Compression.xml",
+        "ref/netstandard1.3/it/System.IO.Compression.xml",
+        "ref/netstandard1.3/ja/System.IO.Compression.xml",
+        "ref/netstandard1.3/ko/System.IO.Compression.xml",
+        "ref/netstandard1.3/ru/System.IO.Compression.xml",
+        "ref/netstandard1.3/zh-hans/System.IO.Compression.xml",
+        "ref/netstandard1.3/zh-hant/System.IO.Compression.xml",
+        "ref/portable-net45+win8+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._",
+        "runtimes/unix/lib/netstandard1.3/System.IO.Compression.dll",
+        "runtimes/win/lib/net46/System.IO.Compression.dll",
+        "runtimes/win/lib/netstandard1.3/System.IO.Compression.dll"
+      ]
+    },
+    "System.IO.Compression.ZipFile/4.0.1": {
+      "sha512": "hBQYJzfTbQURF10nLhd+az2NHxsU6MU7AB8RUf4IolBP5lOAm4Luho851xl+CqslmhI5ZH/el8BlngEk4lBkaQ==",
+      "type": "package",
+      "path": "System.IO.Compression.ZipFile/4.0.1",
+      "files": [
+        "System.IO.Compression.ZipFile.4.0.1.nupkg.sha512",
+        "System.IO.Compression.ZipFile.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net46/System.IO.Compression.ZipFile.dll",
+        "lib/netstandard1.3/System.IO.Compression.ZipFile.dll",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net46/System.IO.Compression.ZipFile.dll",
+        "ref/netstandard1.3/System.IO.Compression.ZipFile.dll",
+        "ref/netstandard1.3/System.IO.Compression.ZipFile.xml",
+        "ref/netstandard1.3/de/System.IO.Compression.ZipFile.xml",
+        "ref/netstandard1.3/es/System.IO.Compression.ZipFile.xml",
+        "ref/netstandard1.3/fr/System.IO.Compression.ZipFile.xml",
+        "ref/netstandard1.3/it/System.IO.Compression.ZipFile.xml",
+        "ref/netstandard1.3/ja/System.IO.Compression.ZipFile.xml",
+        "ref/netstandard1.3/ko/System.IO.Compression.ZipFile.xml",
+        "ref/netstandard1.3/ru/System.IO.Compression.ZipFile.xml",
+        "ref/netstandard1.3/zh-hans/System.IO.Compression.ZipFile.xml",
+        "ref/netstandard1.3/zh-hant/System.IO.Compression.ZipFile.xml",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.IO.FileSystem/4.0.1": {
+      "sha512": "IBErlVq5jOggAD69bg1t0pJcHaDbJbWNUZTPI96fkYWzwYbN6D9wRHMULLDd9dHsl7C2YsxXL31LMfPI1SWt8w==",
+      "type": "package",
+      "path": "System.IO.FileSystem/4.0.1",
+      "files": [
+        "System.IO.FileSystem.4.0.1.nupkg.sha512",
+        "System.IO.FileSystem.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net46/System.IO.FileSystem.dll",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net46/System.IO.FileSystem.dll",
+        "ref/netstandard1.3/System.IO.FileSystem.dll",
+        "ref/netstandard1.3/System.IO.FileSystem.xml",
+        "ref/netstandard1.3/de/System.IO.FileSystem.xml",
+        "ref/netstandard1.3/es/System.IO.FileSystem.xml",
+        "ref/netstandard1.3/fr/System.IO.FileSystem.xml",
+        "ref/netstandard1.3/it/System.IO.FileSystem.xml",
+        "ref/netstandard1.3/ja/System.IO.FileSystem.xml",
+        "ref/netstandard1.3/ko/System.IO.FileSystem.xml",
+        "ref/netstandard1.3/ru/System.IO.FileSystem.xml",
+        "ref/netstandard1.3/zh-hans/System.IO.FileSystem.xml",
+        "ref/netstandard1.3/zh-hant/System.IO.FileSystem.xml",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.IO.FileSystem.Primitives/4.0.1": {
+      "sha512": "kWkKD203JJKxJeE74p8aF8y4Qc9r9WQx4C0cHzHPrY3fv/L/IhWnyCHaFJ3H1QPOH6A93whlQ2vG5nHlBDvzWQ==",
+      "type": "package",
+      "path": "System.IO.FileSystem.Primitives/4.0.1",
+      "files": [
+        "System.IO.FileSystem.Primitives.4.0.1.nupkg.sha512",
+        "System.IO.FileSystem.Primitives.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net46/System.IO.FileSystem.Primitives.dll",
+        "lib/netstandard1.3/System.IO.FileSystem.Primitives.dll",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net46/System.IO.FileSystem.Primitives.dll",
+        "ref/netstandard1.3/System.IO.FileSystem.Primitives.dll",
+        "ref/netstandard1.3/System.IO.FileSystem.Primitives.xml",
+        "ref/netstandard1.3/de/System.IO.FileSystem.Primitives.xml",
+        "ref/netstandard1.3/es/System.IO.FileSystem.Primitives.xml",
+        "ref/netstandard1.3/fr/System.IO.FileSystem.Primitives.xml",
+        "ref/netstandard1.3/it/System.IO.FileSystem.Primitives.xml",
+        "ref/netstandard1.3/ja/System.IO.FileSystem.Primitives.xml",
+        "ref/netstandard1.3/ko/System.IO.FileSystem.Primitives.xml",
+        "ref/netstandard1.3/ru/System.IO.FileSystem.Primitives.xml",
+        "ref/netstandard1.3/zh-hans/System.IO.FileSystem.Primitives.xml",
+        "ref/netstandard1.3/zh-hant/System.IO.FileSystem.Primitives.xml",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Linq/4.1.0": {
+      "sha512": "bQ0iYFOQI0nuTnt+NQADns6ucV4DUvMdwN6CbkB1yj8i7arTGiTN5eok1kQwdnnNWSDZfIUySQY+J3d5KjWn0g==",
+      "type": "package",
+      "path": "System.Linq/4.1.0",
+      "files": [
+        "System.Linq.4.1.0.nupkg.sha512",
+        "System.Linq.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/_._",
+        "lib/net463/System.Linq.dll",
+        "lib/netcore50/System.Linq.dll",
+        "lib/netstandard1.6/System.Linq.dll",
+        "lib/portable-net45+win8+wp8+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wp80/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net45/_._",
+        "ref/net463/System.Linq.dll",
+        "ref/netcore50/System.Linq.dll",
+        "ref/netcore50/System.Linq.xml",
+        "ref/netcore50/de/System.Linq.xml",
+        "ref/netcore50/es/System.Linq.xml",
+        "ref/netcore50/fr/System.Linq.xml",
+        "ref/netcore50/it/System.Linq.xml",
+        "ref/netcore50/ja/System.Linq.xml",
+        "ref/netcore50/ko/System.Linq.xml",
+        "ref/netcore50/ru/System.Linq.xml",
+        "ref/netcore50/zh-hans/System.Linq.xml",
+        "ref/netcore50/zh-hant/System.Linq.xml",
+        "ref/netstandard1.0/System.Linq.dll",
+        "ref/netstandard1.0/System.Linq.xml",
+        "ref/netstandard1.0/de/System.Linq.xml",
+        "ref/netstandard1.0/es/System.Linq.xml",
+        "ref/netstandard1.0/fr/System.Linq.xml",
+        "ref/netstandard1.0/it/System.Linq.xml",
+        "ref/netstandard1.0/ja/System.Linq.xml",
+        "ref/netstandard1.0/ko/System.Linq.xml",
+        "ref/netstandard1.0/ru/System.Linq.xml",
+        "ref/netstandard1.0/zh-hans/System.Linq.xml",
+        "ref/netstandard1.0/zh-hant/System.Linq.xml",
+        "ref/netstandard1.6/System.Linq.dll",
+        "ref/netstandard1.6/System.Linq.xml",
+        "ref/netstandard1.6/de/System.Linq.xml",
+        "ref/netstandard1.6/es/System.Linq.xml",
+        "ref/netstandard1.6/fr/System.Linq.xml",
+        "ref/netstandard1.6/it/System.Linq.xml",
+        "ref/netstandard1.6/ja/System.Linq.xml",
+        "ref/netstandard1.6/ko/System.Linq.xml",
+        "ref/netstandard1.6/ru/System.Linq.xml",
+        "ref/netstandard1.6/zh-hans/System.Linq.xml",
+        "ref/netstandard1.6/zh-hant/System.Linq.xml",
+        "ref/portable-net45+win8+wp8+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wp80/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Linq.Expressions/4.1.0": {
+      "sha512": "I+y02iqkgmCAyfbqOmSDOgqdZQ5tTj80Akm5BPSS8EeB0VGWdy6X1KCoYe8Pk6pwDoAKZUOdLVxnTJcExiv5zw==",
+      "type": "package",
+      "path": "System.Linq.Expressions/4.1.0",
+      "files": [
+        "System.Linq.Expressions.4.1.0.nupkg.sha512",
+        "System.Linq.Expressions.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/_._",
+        "lib/net463/System.Linq.Expressions.dll",
+        "lib/netcore50/System.Linq.Expressions.dll",
+        "lib/netstandard1.6/System.Linq.Expressions.dll",
+        "lib/portable-net45+win8+wp8+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wp80/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net45/_._",
+        "ref/net463/System.Linq.Expressions.dll",
+        "ref/netcore50/System.Linq.Expressions.dll",
+        "ref/netcore50/System.Linq.Expressions.xml",
+        "ref/netcore50/de/System.Linq.Expressions.xml",
+        "ref/netcore50/es/System.Linq.Expressions.xml",
+        "ref/netcore50/fr/System.Linq.Expressions.xml",
+        "ref/netcore50/it/System.Linq.Expressions.xml",
+        "ref/netcore50/ja/System.Linq.Expressions.xml",
+        "ref/netcore50/ko/System.Linq.Expressions.xml",
+        "ref/netcore50/ru/System.Linq.Expressions.xml",
+        "ref/netcore50/zh-hans/System.Linq.Expressions.xml",
+        "ref/netcore50/zh-hant/System.Linq.Expressions.xml",
+        "ref/netstandard1.0/System.Linq.Expressions.dll",
+        "ref/netstandard1.0/System.Linq.Expressions.xml",
+        "ref/netstandard1.0/de/System.Linq.Expressions.xml",
+        "ref/netstandard1.0/es/System.Linq.Expressions.xml",
+        "ref/netstandard1.0/fr/System.Linq.Expressions.xml",
+        "ref/netstandard1.0/it/System.Linq.Expressions.xml",
+        "ref/netstandard1.0/ja/System.Linq.Expressions.xml",
+        "ref/netstandard1.0/ko/System.Linq.Expressions.xml",
+        "ref/netstandard1.0/ru/System.Linq.Expressions.xml",
+        "ref/netstandard1.0/zh-hans/System.Linq.Expressions.xml",
+        "ref/netstandard1.0/zh-hant/System.Linq.Expressions.xml",
+        "ref/netstandard1.3/System.Linq.Expressions.dll",
+        "ref/netstandard1.3/System.Linq.Expressions.xml",
+        "ref/netstandard1.3/de/System.Linq.Expressions.xml",
+        "ref/netstandard1.3/es/System.Linq.Expressions.xml",
+        "ref/netstandard1.3/fr/System.Linq.Expressions.xml",
+        "ref/netstandard1.3/it/System.Linq.Expressions.xml",
+        "ref/netstandard1.3/ja/System.Linq.Expressions.xml",
+        "ref/netstandard1.3/ko/System.Linq.Expressions.xml",
+        "ref/netstandard1.3/ru/System.Linq.Expressions.xml",
+        "ref/netstandard1.3/zh-hans/System.Linq.Expressions.xml",
+        "ref/netstandard1.3/zh-hant/System.Linq.Expressions.xml",
+        "ref/netstandard1.6/System.Linq.Expressions.dll",
+        "ref/netstandard1.6/System.Linq.Expressions.xml",
+        "ref/netstandard1.6/de/System.Linq.Expressions.xml",
+        "ref/netstandard1.6/es/System.Linq.Expressions.xml",
+        "ref/netstandard1.6/fr/System.Linq.Expressions.xml",
+        "ref/netstandard1.6/it/System.Linq.Expressions.xml",
+        "ref/netstandard1.6/ja/System.Linq.Expressions.xml",
+        "ref/netstandard1.6/ko/System.Linq.Expressions.xml",
+        "ref/netstandard1.6/ru/System.Linq.Expressions.xml",
+        "ref/netstandard1.6/zh-hans/System.Linq.Expressions.xml",
+        "ref/netstandard1.6/zh-hant/System.Linq.Expressions.xml",
+        "ref/portable-net45+win8+wp8+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wp80/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._",
+        "runtimes/aot/lib/netcore50/System.Linq.Expressions.dll"
+      ]
+    },
+    "System.Net.Http/4.1.0": {
+      "sha512": "ULq9g3SOPVuupt+Y3U+A37coXzdNisB1neFCSKzBwo182u0RDddKJF8I5+HfyXqK6OhJPgeoAwWXrbiUXuRDsg==",
+      "type": "package",
+      "path": "System.Net.Http/4.1.0",
+      "files": [
+        "System.Net.Http.4.1.0.nupkg.sha512",
+        "System.Net.Http.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/Xamarinmac20/_._",
+        "lib/monoandroid10/_._",
+        "lib/monotouch10/_._",
+        "lib/net45/_._",
+        "lib/net46/System.Net.Http.dll",
+        "lib/portable-net45+win8+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/Xamarinmac20/_._",
+        "ref/monoandroid10/_._",
+        "ref/monotouch10/_._",
+        "ref/net45/_._",
+        "ref/net46/System.Net.Http.dll",
+        "ref/net46/System.Net.Http.xml",
+        "ref/net46/de/System.Net.Http.xml",
+        "ref/net46/es/System.Net.Http.xml",
+        "ref/net46/fr/System.Net.Http.xml",
+        "ref/net46/it/System.Net.Http.xml",
+        "ref/net46/ja/System.Net.Http.xml",
+        "ref/net46/ko/System.Net.Http.xml",
+        "ref/net46/ru/System.Net.Http.xml",
+        "ref/net46/zh-hans/System.Net.Http.xml",
+        "ref/net46/zh-hant/System.Net.Http.xml",
+        "ref/netcore50/System.Net.Http.dll",
+        "ref/netcore50/System.Net.Http.xml",
+        "ref/netcore50/de/System.Net.Http.xml",
+        "ref/netcore50/es/System.Net.Http.xml",
+        "ref/netcore50/fr/System.Net.Http.xml",
+        "ref/netcore50/it/System.Net.Http.xml",
+        "ref/netcore50/ja/System.Net.Http.xml",
+        "ref/netcore50/ko/System.Net.Http.xml",
+        "ref/netcore50/ru/System.Net.Http.xml",
+        "ref/netcore50/zh-hans/System.Net.Http.xml",
+        "ref/netcore50/zh-hant/System.Net.Http.xml",
+        "ref/netstandard1.1/System.Net.Http.dll",
+        "ref/netstandard1.1/System.Net.Http.xml",
+        "ref/netstandard1.1/de/System.Net.Http.xml",
+        "ref/netstandard1.1/es/System.Net.Http.xml",
+        "ref/netstandard1.1/fr/System.Net.Http.xml",
+        "ref/netstandard1.1/it/System.Net.Http.xml",
+        "ref/netstandard1.1/ja/System.Net.Http.xml",
+        "ref/netstandard1.1/ko/System.Net.Http.xml",
+        "ref/netstandard1.1/ru/System.Net.Http.xml",
+        "ref/netstandard1.1/zh-hans/System.Net.Http.xml",
+        "ref/netstandard1.1/zh-hant/System.Net.Http.xml",
+        "ref/netstandard1.3/System.Net.Http.dll",
+        "ref/netstandard1.3/System.Net.Http.xml",
+        "ref/netstandard1.3/de/System.Net.Http.xml",
+        "ref/netstandard1.3/es/System.Net.Http.xml",
+        "ref/netstandard1.3/fr/System.Net.Http.xml",
+        "ref/netstandard1.3/it/System.Net.Http.xml",
+        "ref/netstandard1.3/ja/System.Net.Http.xml",
+        "ref/netstandard1.3/ko/System.Net.Http.xml",
+        "ref/netstandard1.3/ru/System.Net.Http.xml",
+        "ref/netstandard1.3/zh-hans/System.Net.Http.xml",
+        "ref/netstandard1.3/zh-hant/System.Net.Http.xml",
+        "ref/portable-net45+win8+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._",
+        "runtimes/unix/lib/netstandard1.6/System.Net.Http.dll",
+        "runtimes/win/lib/net46/System.Net.Http.dll",
+        "runtimes/win/lib/netcore50/System.Net.Http.dll",
+        "runtimes/win/lib/netstandard1.3/System.Net.Http.dll"
+      ]
+    },
+    "System.Net.Primitives/4.0.11": {
+      "sha512": "hVvfl4405DRjA2408luZekbPhplJK03j2Y2lSfMlny7GHXlkByw1iLnc9mgKW0GdQn73vvMcWrWewAhylXA4Nw==",
+      "type": "package",
+      "path": "System.Net.Primitives/4.0.11",
+      "files": [
+        "System.Net.Primitives.4.0.11.nupkg.sha512",
+        "System.Net.Primitives.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/_._",
+        "lib/portable-net45+win8+wp8+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wp80/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net45/_._",
+        "ref/netcore50/System.Net.Primitives.dll",
+        "ref/netcore50/System.Net.Primitives.xml",
+        "ref/netcore50/de/System.Net.Primitives.xml",
+        "ref/netcore50/es/System.Net.Primitives.xml",
+        "ref/netcore50/fr/System.Net.Primitives.xml",
+        "ref/netcore50/it/System.Net.Primitives.xml",
+        "ref/netcore50/ja/System.Net.Primitives.xml",
+        "ref/netcore50/ko/System.Net.Primitives.xml",
+        "ref/netcore50/ru/System.Net.Primitives.xml",
+        "ref/netcore50/zh-hans/System.Net.Primitives.xml",
+        "ref/netcore50/zh-hant/System.Net.Primitives.xml",
+        "ref/netstandard1.0/System.Net.Primitives.dll",
+        "ref/netstandard1.0/System.Net.Primitives.xml",
+        "ref/netstandard1.0/de/System.Net.Primitives.xml",
+        "ref/netstandard1.0/es/System.Net.Primitives.xml",
+        "ref/netstandard1.0/fr/System.Net.Primitives.xml",
+        "ref/netstandard1.0/it/System.Net.Primitives.xml",
+        "ref/netstandard1.0/ja/System.Net.Primitives.xml",
+        "ref/netstandard1.0/ko/System.Net.Primitives.xml",
+        "ref/netstandard1.0/ru/System.Net.Primitives.xml",
+        "ref/netstandard1.0/zh-hans/System.Net.Primitives.xml",
+        "ref/netstandard1.0/zh-hant/System.Net.Primitives.xml",
+        "ref/netstandard1.1/System.Net.Primitives.dll",
+        "ref/netstandard1.1/System.Net.Primitives.xml",
+        "ref/netstandard1.1/de/System.Net.Primitives.xml",
+        "ref/netstandard1.1/es/System.Net.Primitives.xml",
+        "ref/netstandard1.1/fr/System.Net.Primitives.xml",
+        "ref/netstandard1.1/it/System.Net.Primitives.xml",
+        "ref/netstandard1.1/ja/System.Net.Primitives.xml",
+        "ref/netstandard1.1/ko/System.Net.Primitives.xml",
+        "ref/netstandard1.1/ru/System.Net.Primitives.xml",
+        "ref/netstandard1.1/zh-hans/System.Net.Primitives.xml",
+        "ref/netstandard1.1/zh-hant/System.Net.Primitives.xml",
+        "ref/netstandard1.3/System.Net.Primitives.dll",
+        "ref/netstandard1.3/System.Net.Primitives.xml",
+        "ref/netstandard1.3/de/System.Net.Primitives.xml",
+        "ref/netstandard1.3/es/System.Net.Primitives.xml",
+        "ref/netstandard1.3/fr/System.Net.Primitives.xml",
+        "ref/netstandard1.3/it/System.Net.Primitives.xml",
+        "ref/netstandard1.3/ja/System.Net.Primitives.xml",
+        "ref/netstandard1.3/ko/System.Net.Primitives.xml",
+        "ref/netstandard1.3/ru/System.Net.Primitives.xml",
+        "ref/netstandard1.3/zh-hans/System.Net.Primitives.xml",
+        "ref/netstandard1.3/zh-hant/System.Net.Primitives.xml",
+        "ref/portable-net45+win8+wp8+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wp80/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Net.Requests/4.0.11": {
+      "sha512": "e7FQ55FBFfztR50qocJdMcwxivKsZw1vcxUXILwdCd1YuGv734JIJuW/jX66/VStDfary3/2+G36A8a3AInpfg==",
+      "type": "package",
+      "path": "System.Net.Requests/4.0.11",
+      "files": [
+        "System.Net.Requests.4.0.11.nupkg.sha512",
+        "System.Net.Requests.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/_._",
+        "lib/portable-net45+win8+wp8+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wp80/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net45/_._",
+        "ref/net46/_._",
+        "ref/netcore50/System.Net.Requests.dll",
+        "ref/netcore50/System.Net.Requests.xml",
+        "ref/netcore50/de/System.Net.Requests.xml",
+        "ref/netcore50/es/System.Net.Requests.xml",
+        "ref/netcore50/fr/System.Net.Requests.xml",
+        "ref/netcore50/it/System.Net.Requests.xml",
+        "ref/netcore50/ja/System.Net.Requests.xml",
+        "ref/netcore50/ko/System.Net.Requests.xml",
+        "ref/netcore50/ru/System.Net.Requests.xml",
+        "ref/netcore50/zh-hans/System.Net.Requests.xml",
+        "ref/netcore50/zh-hant/System.Net.Requests.xml",
+        "ref/netstandard1.0/System.Net.Requests.dll",
+        "ref/netstandard1.0/System.Net.Requests.xml",
+        "ref/netstandard1.0/de/System.Net.Requests.xml",
+        "ref/netstandard1.0/es/System.Net.Requests.xml",
+        "ref/netstandard1.0/fr/System.Net.Requests.xml",
+        "ref/netstandard1.0/it/System.Net.Requests.xml",
+        "ref/netstandard1.0/ja/System.Net.Requests.xml",
+        "ref/netstandard1.0/ko/System.Net.Requests.xml",
+        "ref/netstandard1.0/ru/System.Net.Requests.xml",
+        "ref/netstandard1.0/zh-hans/System.Net.Requests.xml",
+        "ref/netstandard1.0/zh-hant/System.Net.Requests.xml",
+        "ref/netstandard1.1/System.Net.Requests.dll",
+        "ref/netstandard1.1/System.Net.Requests.xml",
+        "ref/netstandard1.1/de/System.Net.Requests.xml",
+        "ref/netstandard1.1/es/System.Net.Requests.xml",
+        "ref/netstandard1.1/fr/System.Net.Requests.xml",
+        "ref/netstandard1.1/it/System.Net.Requests.xml",
+        "ref/netstandard1.1/ja/System.Net.Requests.xml",
+        "ref/netstandard1.1/ko/System.Net.Requests.xml",
+        "ref/netstandard1.1/ru/System.Net.Requests.xml",
+        "ref/netstandard1.1/zh-hans/System.Net.Requests.xml",
+        "ref/netstandard1.1/zh-hant/System.Net.Requests.xml",
+        "ref/netstandard1.3/System.Net.Requests.dll",
+        "ref/netstandard1.3/System.Net.Requests.xml",
+        "ref/netstandard1.3/de/System.Net.Requests.xml",
+        "ref/netstandard1.3/es/System.Net.Requests.xml",
+        "ref/netstandard1.3/fr/System.Net.Requests.xml",
+        "ref/netstandard1.3/it/System.Net.Requests.xml",
+        "ref/netstandard1.3/ja/System.Net.Requests.xml",
+        "ref/netstandard1.3/ko/System.Net.Requests.xml",
+        "ref/netstandard1.3/ru/System.Net.Requests.xml",
+        "ref/netstandard1.3/zh-hans/System.Net.Requests.xml",
+        "ref/netstandard1.3/zh-hant/System.Net.Requests.xml",
+        "ref/portable-net45+win8+wp8+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wp80/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._",
+        "runtimes/unix/lib/netstandard1.3/System.Net.Requests.dll",
+        "runtimes/win/lib/net46/_._",
+        "runtimes/win/lib/netstandard1.3/System.Net.Requests.dll"
+      ]
+    },
+    "System.Net.Sockets/4.1.0": {
+      "sha512": "xAz0N3dAV/aR/9g8r0Y5oEqU1JRsz29F5EGb/WVHmX3jVSLqi2/92M5hTad2aNWovruXrJpJtgZ9fccPMG9uSw==",
+      "type": "package",
+      "path": "System.Net.Sockets/4.1.0",
+      "files": [
+        "System.Net.Sockets.4.1.0.nupkg.sha512",
+        "System.Net.Sockets.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net46/System.Net.Sockets.dll",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net46/System.Net.Sockets.dll",
+        "ref/netstandard1.3/System.Net.Sockets.dll",
+        "ref/netstandard1.3/System.Net.Sockets.xml",
+        "ref/netstandard1.3/de/System.Net.Sockets.xml",
+        "ref/netstandard1.3/es/System.Net.Sockets.xml",
+        "ref/netstandard1.3/fr/System.Net.Sockets.xml",
+        "ref/netstandard1.3/it/System.Net.Sockets.xml",
+        "ref/netstandard1.3/ja/System.Net.Sockets.xml",
+        "ref/netstandard1.3/ko/System.Net.Sockets.xml",
+        "ref/netstandard1.3/ru/System.Net.Sockets.xml",
+        "ref/netstandard1.3/zh-hans/System.Net.Sockets.xml",
+        "ref/netstandard1.3/zh-hant/System.Net.Sockets.xml",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Net.WebHeaderCollection/4.0.1": {
+      "sha512": "Hs0P/pYpYfmKlS+C3djfbMKZhnVhQeZn0R2ETB4a6DZ0lvj3ij+sRtJ4VGXEVRa08DRhKhRlm3Rz3O+f62qzTQ==",
+      "type": "package",
+      "path": "System.Net.WebHeaderCollection/4.0.1",
+      "files": [
+        "System.Net.WebHeaderCollection.4.0.1.nupkg.sha512",
+        "System.Net.WebHeaderCollection.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net46/_._",
+        "lib/netstandard1.3/System.Net.WebHeaderCollection.dll",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net46/_._",
+        "ref/netstandard1.3/System.Net.WebHeaderCollection.dll",
+        "ref/netstandard1.3/System.Net.WebHeaderCollection.xml",
+        "ref/netstandard1.3/de/System.Net.WebHeaderCollection.xml",
+        "ref/netstandard1.3/es/System.Net.WebHeaderCollection.xml",
+        "ref/netstandard1.3/fr/System.Net.WebHeaderCollection.xml",
+        "ref/netstandard1.3/it/System.Net.WebHeaderCollection.xml",
+        "ref/netstandard1.3/ja/System.Net.WebHeaderCollection.xml",
+        "ref/netstandard1.3/ko/System.Net.WebHeaderCollection.xml",
+        "ref/netstandard1.3/ru/System.Net.WebHeaderCollection.xml",
+        "ref/netstandard1.3/zh-hans/System.Net.WebHeaderCollection.xml",
+        "ref/netstandard1.3/zh-hant/System.Net.WebHeaderCollection.xml",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.ObjectModel/4.0.12": {
+      "sha512": "tAgJM1xt3ytyMoW4qn4wIqgJYm7L7TShRZG4+Q4Qsi2PCcj96pXN7nRywS9KkB3p/xDUjc2HSwP9SROyPYDYKQ==",
+      "type": "package",
+      "path": "System.ObjectModel/4.0.12",
+      "files": [
+        "System.ObjectModel.4.0.12.nupkg.sha512",
+        "System.ObjectModel.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/_._",
+        "lib/netcore50/System.ObjectModel.dll",
+        "lib/netstandard1.3/System.ObjectModel.dll",
+        "lib/portable-net45+win8+wp8+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wp80/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net45/_._",
+        "ref/netcore50/System.ObjectModel.dll",
+        "ref/netcore50/System.ObjectModel.xml",
+        "ref/netcore50/de/System.ObjectModel.xml",
+        "ref/netcore50/es/System.ObjectModel.xml",
+        "ref/netcore50/fr/System.ObjectModel.xml",
+        "ref/netcore50/it/System.ObjectModel.xml",
+        "ref/netcore50/ja/System.ObjectModel.xml",
+        "ref/netcore50/ko/System.ObjectModel.xml",
+        "ref/netcore50/ru/System.ObjectModel.xml",
+        "ref/netcore50/zh-hans/System.ObjectModel.xml",
+        "ref/netcore50/zh-hant/System.ObjectModel.xml",
+        "ref/netstandard1.0/System.ObjectModel.dll",
+        "ref/netstandard1.0/System.ObjectModel.xml",
+        "ref/netstandard1.0/de/System.ObjectModel.xml",
+        "ref/netstandard1.0/es/System.ObjectModel.xml",
+        "ref/netstandard1.0/fr/System.ObjectModel.xml",
+        "ref/netstandard1.0/it/System.ObjectModel.xml",
+        "ref/netstandard1.0/ja/System.ObjectModel.xml",
+        "ref/netstandard1.0/ko/System.ObjectModel.xml",
+        "ref/netstandard1.0/ru/System.ObjectModel.xml",
+        "ref/netstandard1.0/zh-hans/System.ObjectModel.xml",
+        "ref/netstandard1.0/zh-hant/System.ObjectModel.xml",
+        "ref/netstandard1.3/System.ObjectModel.dll",
+        "ref/netstandard1.3/System.ObjectModel.xml",
+        "ref/netstandard1.3/de/System.ObjectModel.xml",
+        "ref/netstandard1.3/es/System.ObjectModel.xml",
+        "ref/netstandard1.3/fr/System.ObjectModel.xml",
+        "ref/netstandard1.3/it/System.ObjectModel.xml",
+        "ref/netstandard1.3/ja/System.ObjectModel.xml",
+        "ref/netstandard1.3/ko/System.ObjectModel.xml",
+        "ref/netstandard1.3/ru/System.ObjectModel.xml",
+        "ref/netstandard1.3/zh-hans/System.ObjectModel.xml",
+        "ref/netstandard1.3/zh-hant/System.ObjectModel.xml",
+        "ref/portable-net45+win8+wp8+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wp80/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Reflection/4.1.0": {
+      "sha512": "JCKANJ0TI7kzoQzuwB/OoJANy1Lg338B6+JVacPl4TpUwi3cReg3nMLplMq2uqYfHFQpKIlHAUVAJlImZz/4ng==",
+      "type": "package",
+      "path": "System.Reflection/4.1.0",
+      "files": [
+        "System.Reflection.4.1.0.nupkg.sha512",
+        "System.Reflection.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/_._",
+        "lib/net462/System.Reflection.dll",
+        "lib/portable-net45+win8+wp8+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wp80/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net45/_._",
+        "ref/net462/System.Reflection.dll",
+        "ref/netcore50/System.Reflection.dll",
+        "ref/netcore50/System.Reflection.xml",
+        "ref/netcore50/de/System.Reflection.xml",
+        "ref/netcore50/es/System.Reflection.xml",
+        "ref/netcore50/fr/System.Reflection.xml",
+        "ref/netcore50/it/System.Reflection.xml",
+        "ref/netcore50/ja/System.Reflection.xml",
+        "ref/netcore50/ko/System.Reflection.xml",
+        "ref/netcore50/ru/System.Reflection.xml",
+        "ref/netcore50/zh-hans/System.Reflection.xml",
+        "ref/netcore50/zh-hant/System.Reflection.xml",
+        "ref/netstandard1.0/System.Reflection.dll",
+        "ref/netstandard1.0/System.Reflection.xml",
+        "ref/netstandard1.0/de/System.Reflection.xml",
+        "ref/netstandard1.0/es/System.Reflection.xml",
+        "ref/netstandard1.0/fr/System.Reflection.xml",
+        "ref/netstandard1.0/it/System.Reflection.xml",
+        "ref/netstandard1.0/ja/System.Reflection.xml",
+        "ref/netstandard1.0/ko/System.Reflection.xml",
+        "ref/netstandard1.0/ru/System.Reflection.xml",
+        "ref/netstandard1.0/zh-hans/System.Reflection.xml",
+        "ref/netstandard1.0/zh-hant/System.Reflection.xml",
+        "ref/netstandard1.3/System.Reflection.dll",
+        "ref/netstandard1.3/System.Reflection.xml",
+        "ref/netstandard1.3/de/System.Reflection.xml",
+        "ref/netstandard1.3/es/System.Reflection.xml",
+        "ref/netstandard1.3/fr/System.Reflection.xml",
+        "ref/netstandard1.3/it/System.Reflection.xml",
+        "ref/netstandard1.3/ja/System.Reflection.xml",
+        "ref/netstandard1.3/ko/System.Reflection.xml",
+        "ref/netstandard1.3/ru/System.Reflection.xml",
+        "ref/netstandard1.3/zh-hans/System.Reflection.xml",
+        "ref/netstandard1.3/zh-hant/System.Reflection.xml",
+        "ref/netstandard1.5/System.Reflection.dll",
+        "ref/netstandard1.5/System.Reflection.xml",
+        "ref/netstandard1.5/de/System.Reflection.xml",
+        "ref/netstandard1.5/es/System.Reflection.xml",
+        "ref/netstandard1.5/fr/System.Reflection.xml",
+        "ref/netstandard1.5/it/System.Reflection.xml",
+        "ref/netstandard1.5/ja/System.Reflection.xml",
+        "ref/netstandard1.5/ko/System.Reflection.xml",
+        "ref/netstandard1.5/ru/System.Reflection.xml",
+        "ref/netstandard1.5/zh-hans/System.Reflection.xml",
+        "ref/netstandard1.5/zh-hant/System.Reflection.xml",
+        "ref/portable-net45+win8+wp8+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wp80/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Reflection.Emit/4.0.1": {
+      "sha512": "P2wqAj72fFjpP6wb9nSfDqNBMab+2ovzSDzUZK7MVIm54tBJEPr9jWfSjjoTpPwj1LeKcmX3vr0ttyjSSFM47g==",
+      "type": "package",
+      "path": "System.Reflection.Emit/4.0.1",
+      "files": [
+        "System.Reflection.Emit.4.0.1.nupkg.sha512",
+        "System.Reflection.Emit.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/net45/_._",
+        "lib/netcore50/System.Reflection.Emit.dll",
+        "lib/netstandard1.3/System.Reflection.Emit.dll",
+        "lib/xamarinmac20/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/net45/_._",
+        "ref/netstandard1.1/System.Reflection.Emit.dll",
+        "ref/netstandard1.1/System.Reflection.Emit.xml",
+        "ref/netstandard1.1/de/System.Reflection.Emit.xml",
+        "ref/netstandard1.1/es/System.Reflection.Emit.xml",
+        "ref/netstandard1.1/fr/System.Reflection.Emit.xml",
+        "ref/netstandard1.1/it/System.Reflection.Emit.xml",
+        "ref/netstandard1.1/ja/System.Reflection.Emit.xml",
+        "ref/netstandard1.1/ko/System.Reflection.Emit.xml",
+        "ref/netstandard1.1/ru/System.Reflection.Emit.xml",
+        "ref/netstandard1.1/zh-hans/System.Reflection.Emit.xml",
+        "ref/netstandard1.1/zh-hant/System.Reflection.Emit.xml",
+        "ref/xamarinmac20/_._"
+      ]
+    },
+    "System.Reflection.Emit.ILGeneration/4.0.1": {
+      "sha512": "Ov6dU8Bu15Bc7zuqttgHF12J5lwSWyTf1S+FJouUXVMSqImLZzYaQ+vRr1rQ0OZ0HqsrwWl4dsKHELckQkVpgA==",
+      "type": "package",
+      "path": "System.Reflection.Emit.ILGeneration/4.0.1",
+      "files": [
+        "System.Reflection.Emit.ILGeneration.4.0.1.nupkg.sha512",
+        "System.Reflection.Emit.ILGeneration.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/net45/_._",
+        "lib/netcore50/System.Reflection.Emit.ILGeneration.dll",
+        "lib/netstandard1.3/System.Reflection.Emit.ILGeneration.dll",
+        "lib/portable-net45+wp8/_._",
+        "lib/wp80/_._",
+        "ref/net45/_._",
+        "ref/netstandard1.0/System.Reflection.Emit.ILGeneration.dll",
+        "ref/netstandard1.0/System.Reflection.Emit.ILGeneration.xml",
+        "ref/netstandard1.0/de/System.Reflection.Emit.ILGeneration.xml",
+        "ref/netstandard1.0/es/System.Reflection.Emit.ILGeneration.xml",
+        "ref/netstandard1.0/fr/System.Reflection.Emit.ILGeneration.xml",
+        "ref/netstandard1.0/it/System.Reflection.Emit.ILGeneration.xml",
+        "ref/netstandard1.0/ja/System.Reflection.Emit.ILGeneration.xml",
+        "ref/netstandard1.0/ko/System.Reflection.Emit.ILGeneration.xml",
+        "ref/netstandard1.0/ru/System.Reflection.Emit.ILGeneration.xml",
+        "ref/netstandard1.0/zh-hans/System.Reflection.Emit.ILGeneration.xml",
+        "ref/netstandard1.0/zh-hant/System.Reflection.Emit.ILGeneration.xml",
+        "ref/portable-net45+wp8/_._",
+        "ref/wp80/_._",
+        "runtimes/aot/lib/netcore50/_._"
+      ]
+    },
+    "System.Reflection.Emit.Lightweight/4.0.1": {
+      "sha512": "sSzHHXueZ5Uh0OLpUQprhr+ZYJrLPA2Cmr4gn0wj9+FftNKXx8RIMKvO9qnjk2ebPYUjZ+F2ulGdPOsvj+MEjA==",
+      "type": "package",
+      "path": "System.Reflection.Emit.Lightweight/4.0.1",
+      "files": [
+        "System.Reflection.Emit.Lightweight.4.0.1.nupkg.sha512",
+        "System.Reflection.Emit.Lightweight.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/net45/_._",
+        "lib/netcore50/System.Reflection.Emit.Lightweight.dll",
+        "lib/netstandard1.3/System.Reflection.Emit.Lightweight.dll",
+        "lib/portable-net45+wp8/_._",
+        "lib/wp80/_._",
+        "ref/net45/_._",
+        "ref/netstandard1.0/System.Reflection.Emit.Lightweight.dll",
+        "ref/netstandard1.0/System.Reflection.Emit.Lightweight.xml",
+        "ref/netstandard1.0/de/System.Reflection.Emit.Lightweight.xml",
+        "ref/netstandard1.0/es/System.Reflection.Emit.Lightweight.xml",
+        "ref/netstandard1.0/fr/System.Reflection.Emit.Lightweight.xml",
+        "ref/netstandard1.0/it/System.Reflection.Emit.Lightweight.xml",
+        "ref/netstandard1.0/ja/System.Reflection.Emit.Lightweight.xml",
+        "ref/netstandard1.0/ko/System.Reflection.Emit.Lightweight.xml",
+        "ref/netstandard1.0/ru/System.Reflection.Emit.Lightweight.xml",
+        "ref/netstandard1.0/zh-hans/System.Reflection.Emit.Lightweight.xml",
+        "ref/netstandard1.0/zh-hant/System.Reflection.Emit.Lightweight.xml",
+        "ref/portable-net45+wp8/_._",
+        "ref/wp80/_._",
+        "runtimes/aot/lib/netcore50/_._"
+      ]
+    },
+    "System.Reflection.Extensions/4.0.1": {
+      "sha512": "GYrtRsZcMuHF3sbmRHfMYpvxZoIN2bQGrYGerUiWLEkqdEUQZhH3TRSaC/oI4wO0II1RKBPlpIa1TOMxIcOOzQ==",
+      "type": "package",
+      "path": "System.Reflection.Extensions/4.0.1",
+      "files": [
+        "System.Reflection.Extensions.4.0.1.nupkg.sha512",
+        "System.Reflection.Extensions.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/_._",
+        "lib/portable-net45+win8+wp8+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wp80/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net45/_._",
+        "ref/netcore50/System.Reflection.Extensions.dll",
+        "ref/netcore50/System.Reflection.Extensions.xml",
+        "ref/netcore50/de/System.Reflection.Extensions.xml",
+        "ref/netcore50/es/System.Reflection.Extensions.xml",
+        "ref/netcore50/fr/System.Reflection.Extensions.xml",
+        "ref/netcore50/it/System.Reflection.Extensions.xml",
+        "ref/netcore50/ja/System.Reflection.Extensions.xml",
+        "ref/netcore50/ko/System.Reflection.Extensions.xml",
+        "ref/netcore50/ru/System.Reflection.Extensions.xml",
+        "ref/netcore50/zh-hans/System.Reflection.Extensions.xml",
+        "ref/netcore50/zh-hant/System.Reflection.Extensions.xml",
+        "ref/netstandard1.0/System.Reflection.Extensions.dll",
+        "ref/netstandard1.0/System.Reflection.Extensions.xml",
+        "ref/netstandard1.0/de/System.Reflection.Extensions.xml",
+        "ref/netstandard1.0/es/System.Reflection.Extensions.xml",
+        "ref/netstandard1.0/fr/System.Reflection.Extensions.xml",
+        "ref/netstandard1.0/it/System.Reflection.Extensions.xml",
+        "ref/netstandard1.0/ja/System.Reflection.Extensions.xml",
+        "ref/netstandard1.0/ko/System.Reflection.Extensions.xml",
+        "ref/netstandard1.0/ru/System.Reflection.Extensions.xml",
+        "ref/netstandard1.0/zh-hans/System.Reflection.Extensions.xml",
+        "ref/netstandard1.0/zh-hant/System.Reflection.Extensions.xml",
+        "ref/portable-net45+win8+wp8+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wp80/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Reflection.Primitives/4.0.1": {
+      "sha512": "4inTox4wTBaDhB7V3mPvp9XlCbeGYWVEM9/fXALd52vNEAVisc1BoVWQPuUuD0Ga//dNbA/WeMy9u9mzLxGTHQ==",
+      "type": "package",
+      "path": "System.Reflection.Primitives/4.0.1",
+      "files": [
+        "System.Reflection.Primitives.4.0.1.nupkg.sha512",
+        "System.Reflection.Primitives.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/_._",
+        "lib/portable-net45+win8+wp8+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wp80/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net45/_._",
+        "ref/netcore50/System.Reflection.Primitives.dll",
+        "ref/netcore50/System.Reflection.Primitives.xml",
+        "ref/netcore50/de/System.Reflection.Primitives.xml",
+        "ref/netcore50/es/System.Reflection.Primitives.xml",
+        "ref/netcore50/fr/System.Reflection.Primitives.xml",
+        "ref/netcore50/it/System.Reflection.Primitives.xml",
+        "ref/netcore50/ja/System.Reflection.Primitives.xml",
+        "ref/netcore50/ko/System.Reflection.Primitives.xml",
+        "ref/netcore50/ru/System.Reflection.Primitives.xml",
+        "ref/netcore50/zh-hans/System.Reflection.Primitives.xml",
+        "ref/netcore50/zh-hant/System.Reflection.Primitives.xml",
+        "ref/netstandard1.0/System.Reflection.Primitives.dll",
+        "ref/netstandard1.0/System.Reflection.Primitives.xml",
+        "ref/netstandard1.0/de/System.Reflection.Primitives.xml",
+        "ref/netstandard1.0/es/System.Reflection.Primitives.xml",
+        "ref/netstandard1.0/fr/System.Reflection.Primitives.xml",
+        "ref/netstandard1.0/it/System.Reflection.Primitives.xml",
+        "ref/netstandard1.0/ja/System.Reflection.Primitives.xml",
+        "ref/netstandard1.0/ko/System.Reflection.Primitives.xml",
+        "ref/netstandard1.0/ru/System.Reflection.Primitives.xml",
+        "ref/netstandard1.0/zh-hans/System.Reflection.Primitives.xml",
+        "ref/netstandard1.0/zh-hant/System.Reflection.Primitives.xml",
+        "ref/portable-net45+win8+wp8+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wp80/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Reflection.TypeExtensions/4.1.0": {
+      "sha512": "tsQ/ptQ3H5FYfON8lL4MxRk/8kFyE0A+tGPXmVP967cT/gzLHYxIejIYSxp4JmIeFHVP78g/F2FE1mUUTbDtrg==",
+      "type": "package",
+      "path": "System.Reflection.TypeExtensions/4.1.0",
+      "files": [
+        "System.Reflection.TypeExtensions.4.1.0.nupkg.sha512",
+        "System.Reflection.TypeExtensions.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net46/System.Reflection.TypeExtensions.dll",
+        "lib/net462/System.Reflection.TypeExtensions.dll",
+        "lib/netcore50/System.Reflection.TypeExtensions.dll",
+        "lib/netstandard1.5/System.Reflection.TypeExtensions.dll",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net46/System.Reflection.TypeExtensions.dll",
+        "ref/net462/System.Reflection.TypeExtensions.dll",
+        "ref/netstandard1.3/System.Reflection.TypeExtensions.dll",
+        "ref/netstandard1.3/System.Reflection.TypeExtensions.xml",
+        "ref/netstandard1.3/de/System.Reflection.TypeExtensions.xml",
+        "ref/netstandard1.3/es/System.Reflection.TypeExtensions.xml",
+        "ref/netstandard1.3/fr/System.Reflection.TypeExtensions.xml",
+        "ref/netstandard1.3/it/System.Reflection.TypeExtensions.xml",
+        "ref/netstandard1.3/ja/System.Reflection.TypeExtensions.xml",
+        "ref/netstandard1.3/ko/System.Reflection.TypeExtensions.xml",
+        "ref/netstandard1.3/ru/System.Reflection.TypeExtensions.xml",
+        "ref/netstandard1.3/zh-hans/System.Reflection.TypeExtensions.xml",
+        "ref/netstandard1.3/zh-hant/System.Reflection.TypeExtensions.xml",
+        "ref/netstandard1.5/System.Reflection.TypeExtensions.dll",
+        "ref/netstandard1.5/System.Reflection.TypeExtensions.xml",
+        "ref/netstandard1.5/de/System.Reflection.TypeExtensions.xml",
+        "ref/netstandard1.5/es/System.Reflection.TypeExtensions.xml",
+        "ref/netstandard1.5/fr/System.Reflection.TypeExtensions.xml",
+        "ref/netstandard1.5/it/System.Reflection.TypeExtensions.xml",
+        "ref/netstandard1.5/ja/System.Reflection.TypeExtensions.xml",
+        "ref/netstandard1.5/ko/System.Reflection.TypeExtensions.xml",
+        "ref/netstandard1.5/ru/System.Reflection.TypeExtensions.xml",
+        "ref/netstandard1.5/zh-hans/System.Reflection.TypeExtensions.xml",
+        "ref/netstandard1.5/zh-hant/System.Reflection.TypeExtensions.xml",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._",
+        "runtimes/aot/lib/netcore50/System.Reflection.TypeExtensions.dll"
+      ]
+    },
+    "System.Resources.ResourceManager/4.0.1": {
+      "sha512": "TxwVeUNoTgUOdQ09gfTjvW411MF+w9MBYL7AtNVc+HtBCFlutPLhUCdZjNkjbhj3bNQWMdHboF0KIWEOjJssbA==",
+      "type": "package",
+      "path": "System.Resources.ResourceManager/4.0.1",
+      "files": [
+        "System.Resources.ResourceManager.4.0.1.nupkg.sha512",
+        "System.Resources.ResourceManager.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/_._",
+        "lib/portable-net45+win8+wp8+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wp80/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net45/_._",
+        "ref/netcore50/System.Resources.ResourceManager.dll",
+        "ref/netcore50/System.Resources.ResourceManager.xml",
+        "ref/netcore50/de/System.Resources.ResourceManager.xml",
+        "ref/netcore50/es/System.Resources.ResourceManager.xml",
+        "ref/netcore50/fr/System.Resources.ResourceManager.xml",
+        "ref/netcore50/it/System.Resources.ResourceManager.xml",
+        "ref/netcore50/ja/System.Resources.ResourceManager.xml",
+        "ref/netcore50/ko/System.Resources.ResourceManager.xml",
+        "ref/netcore50/ru/System.Resources.ResourceManager.xml",
+        "ref/netcore50/zh-hans/System.Resources.ResourceManager.xml",
+        "ref/netcore50/zh-hant/System.Resources.ResourceManager.xml",
+        "ref/netstandard1.0/System.Resources.ResourceManager.dll",
+        "ref/netstandard1.0/System.Resources.ResourceManager.xml",
+        "ref/netstandard1.0/de/System.Resources.ResourceManager.xml",
+        "ref/netstandard1.0/es/System.Resources.ResourceManager.xml",
+        "ref/netstandard1.0/fr/System.Resources.ResourceManager.xml",
+        "ref/netstandard1.0/it/System.Resources.ResourceManager.xml",
+        "ref/netstandard1.0/ja/System.Resources.ResourceManager.xml",
+        "ref/netstandard1.0/ko/System.Resources.ResourceManager.xml",
+        "ref/netstandard1.0/ru/System.Resources.ResourceManager.xml",
+        "ref/netstandard1.0/zh-hans/System.Resources.ResourceManager.xml",
+        "ref/netstandard1.0/zh-hant/System.Resources.ResourceManager.xml",
+        "ref/portable-net45+win8+wp8+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wp80/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Runtime/4.1.0": {
+      "sha512": "v6c/4Yaa9uWsq+JMhnOFewrYkgdNHNG2eMKuNqRn8P733rNXeRCGvV5FkkjBXn2dbVkPXOsO0xjsEeM1q2zC0g==",
+      "type": "package",
+      "path": "System.Runtime/4.1.0",
+      "files": [
+        "System.Runtime.4.1.0.nupkg.sha512",
+        "System.Runtime.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/_._",
+        "lib/net462/System.Runtime.dll",
+        "lib/portable-net45+win8+wp80+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wp80/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net45/_._",
+        "ref/net462/System.Runtime.dll",
+        "ref/netcore50/System.Runtime.dll",
+        "ref/netcore50/System.Runtime.xml",
+        "ref/netcore50/de/System.Runtime.xml",
+        "ref/netcore50/es/System.Runtime.xml",
+        "ref/netcore50/fr/System.Runtime.xml",
+        "ref/netcore50/it/System.Runtime.xml",
+        "ref/netcore50/ja/System.Runtime.xml",
+        "ref/netcore50/ko/System.Runtime.xml",
+        "ref/netcore50/ru/System.Runtime.xml",
+        "ref/netcore50/zh-hans/System.Runtime.xml",
+        "ref/netcore50/zh-hant/System.Runtime.xml",
+        "ref/netstandard1.0/System.Runtime.dll",
+        "ref/netstandard1.0/System.Runtime.xml",
+        "ref/netstandard1.0/de/System.Runtime.xml",
+        "ref/netstandard1.0/es/System.Runtime.xml",
+        "ref/netstandard1.0/fr/System.Runtime.xml",
+        "ref/netstandard1.0/it/System.Runtime.xml",
+        "ref/netstandard1.0/ja/System.Runtime.xml",
+        "ref/netstandard1.0/ko/System.Runtime.xml",
+        "ref/netstandard1.0/ru/System.Runtime.xml",
+        "ref/netstandard1.0/zh-hans/System.Runtime.xml",
+        "ref/netstandard1.0/zh-hant/System.Runtime.xml",
+        "ref/netstandard1.2/System.Runtime.dll",
+        "ref/netstandard1.2/System.Runtime.xml",
+        "ref/netstandard1.2/de/System.Runtime.xml",
+        "ref/netstandard1.2/es/System.Runtime.xml",
+        "ref/netstandard1.2/fr/System.Runtime.xml",
+        "ref/netstandard1.2/it/System.Runtime.xml",
+        "ref/netstandard1.2/ja/System.Runtime.xml",
+        "ref/netstandard1.2/ko/System.Runtime.xml",
+        "ref/netstandard1.2/ru/System.Runtime.xml",
+        "ref/netstandard1.2/zh-hans/System.Runtime.xml",
+        "ref/netstandard1.2/zh-hant/System.Runtime.xml",
+        "ref/netstandard1.3/System.Runtime.dll",
+        "ref/netstandard1.3/System.Runtime.xml",
+        "ref/netstandard1.3/de/System.Runtime.xml",
+        "ref/netstandard1.3/es/System.Runtime.xml",
+        "ref/netstandard1.3/fr/System.Runtime.xml",
+        "ref/netstandard1.3/it/System.Runtime.xml",
+        "ref/netstandard1.3/ja/System.Runtime.xml",
+        "ref/netstandard1.3/ko/System.Runtime.xml",
+        "ref/netstandard1.3/ru/System.Runtime.xml",
+        "ref/netstandard1.3/zh-hans/System.Runtime.xml",
+        "ref/netstandard1.3/zh-hant/System.Runtime.xml",
+        "ref/netstandard1.5/System.Runtime.dll",
+        "ref/netstandard1.5/System.Runtime.xml",
+        "ref/netstandard1.5/de/System.Runtime.xml",
+        "ref/netstandard1.5/es/System.Runtime.xml",
+        "ref/netstandard1.5/fr/System.Runtime.xml",
+        "ref/netstandard1.5/it/System.Runtime.xml",
+        "ref/netstandard1.5/ja/System.Runtime.xml",
+        "ref/netstandard1.5/ko/System.Runtime.xml",
+        "ref/netstandard1.5/ru/System.Runtime.xml",
+        "ref/netstandard1.5/zh-hans/System.Runtime.xml",
+        "ref/netstandard1.5/zh-hant/System.Runtime.xml",
+        "ref/portable-net45+win8+wp80+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wp80/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Runtime.Extensions/4.1.0": {
+      "sha512": "CUOHjTT/vgP0qGW22U4/hDlOqXmcPq5YicBaXdUR2UiUoLwBT+olO6we4DVbq57jeX5uXH2uerVZhf0qGj+sVQ==",
+      "type": "package",
+      "path": "System.Runtime.Extensions/4.1.0",
+      "files": [
+        "System.Runtime.Extensions.4.1.0.nupkg.sha512",
+        "System.Runtime.Extensions.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/_._",
+        "lib/net462/System.Runtime.Extensions.dll",
+        "lib/portable-net45+win8+wp8+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wp80/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net45/_._",
+        "ref/net462/System.Runtime.Extensions.dll",
+        "ref/netcore50/System.Runtime.Extensions.dll",
+        "ref/netcore50/System.Runtime.Extensions.xml",
+        "ref/netcore50/de/System.Runtime.Extensions.xml",
+        "ref/netcore50/es/System.Runtime.Extensions.xml",
+        "ref/netcore50/fr/System.Runtime.Extensions.xml",
+        "ref/netcore50/it/System.Runtime.Extensions.xml",
+        "ref/netcore50/ja/System.Runtime.Extensions.xml",
+        "ref/netcore50/ko/System.Runtime.Extensions.xml",
+        "ref/netcore50/ru/System.Runtime.Extensions.xml",
+        "ref/netcore50/zh-hans/System.Runtime.Extensions.xml",
+        "ref/netcore50/zh-hant/System.Runtime.Extensions.xml",
+        "ref/netstandard1.0/System.Runtime.Extensions.dll",
+        "ref/netstandard1.0/System.Runtime.Extensions.xml",
+        "ref/netstandard1.0/de/System.Runtime.Extensions.xml",
+        "ref/netstandard1.0/es/System.Runtime.Extensions.xml",
+        "ref/netstandard1.0/fr/System.Runtime.Extensions.xml",
+        "ref/netstandard1.0/it/System.Runtime.Extensions.xml",
+        "ref/netstandard1.0/ja/System.Runtime.Extensions.xml",
+        "ref/netstandard1.0/ko/System.Runtime.Extensions.xml",
+        "ref/netstandard1.0/ru/System.Runtime.Extensions.xml",
+        "ref/netstandard1.0/zh-hans/System.Runtime.Extensions.xml",
+        "ref/netstandard1.0/zh-hant/System.Runtime.Extensions.xml",
+        "ref/netstandard1.3/System.Runtime.Extensions.dll",
+        "ref/netstandard1.3/System.Runtime.Extensions.xml",
+        "ref/netstandard1.3/de/System.Runtime.Extensions.xml",
+        "ref/netstandard1.3/es/System.Runtime.Extensions.xml",
+        "ref/netstandard1.3/fr/System.Runtime.Extensions.xml",
+        "ref/netstandard1.3/it/System.Runtime.Extensions.xml",
+        "ref/netstandard1.3/ja/System.Runtime.Extensions.xml",
+        "ref/netstandard1.3/ko/System.Runtime.Extensions.xml",
+        "ref/netstandard1.3/ru/System.Runtime.Extensions.xml",
+        "ref/netstandard1.3/zh-hans/System.Runtime.Extensions.xml",
+        "ref/netstandard1.3/zh-hant/System.Runtime.Extensions.xml",
+        "ref/netstandard1.5/System.Runtime.Extensions.dll",
+        "ref/netstandard1.5/System.Runtime.Extensions.xml",
+        "ref/netstandard1.5/de/System.Runtime.Extensions.xml",
+        "ref/netstandard1.5/es/System.Runtime.Extensions.xml",
+        "ref/netstandard1.5/fr/System.Runtime.Extensions.xml",
+        "ref/netstandard1.5/it/System.Runtime.Extensions.xml",
+        "ref/netstandard1.5/ja/System.Runtime.Extensions.xml",
+        "ref/netstandard1.5/ko/System.Runtime.Extensions.xml",
+        "ref/netstandard1.5/ru/System.Runtime.Extensions.xml",
+        "ref/netstandard1.5/zh-hans/System.Runtime.Extensions.xml",
+        "ref/netstandard1.5/zh-hant/System.Runtime.Extensions.xml",
+        "ref/portable-net45+win8+wp8+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wp80/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Runtime.Handles/4.0.1": {
+      "sha512": "nCJvEKguXEvk2ymk1gqj625vVnlK3/xdGzx0vOKicQkoquaTBJTP13AIYkocSUwHCLNBwUbXTqTWGDxBTWpt7g==",
+      "type": "package",
+      "path": "System.Runtime.Handles/4.0.1",
+      "files": [
+        "System.Runtime.Handles.4.0.1.nupkg.sha512",
+        "System.Runtime.Handles.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net46/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net46/_._",
+        "ref/netstandard1.3/System.Runtime.Handles.dll",
+        "ref/netstandard1.3/System.Runtime.Handles.xml",
+        "ref/netstandard1.3/de/System.Runtime.Handles.xml",
+        "ref/netstandard1.3/es/System.Runtime.Handles.xml",
+        "ref/netstandard1.3/fr/System.Runtime.Handles.xml",
+        "ref/netstandard1.3/it/System.Runtime.Handles.xml",
+        "ref/netstandard1.3/ja/System.Runtime.Handles.xml",
+        "ref/netstandard1.3/ko/System.Runtime.Handles.xml",
+        "ref/netstandard1.3/ru/System.Runtime.Handles.xml",
+        "ref/netstandard1.3/zh-hans/System.Runtime.Handles.xml",
+        "ref/netstandard1.3/zh-hant/System.Runtime.Handles.xml",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Runtime.InteropServices/4.1.0": {
+      "sha512": "16eu3kjHS633yYdkjwShDHZLRNMKVi/s0bY8ODiqJ2RfMhDMAwxZaUaWVnZ2P71kr/or+X9o/xFWtNqz8ivieQ==",
+      "type": "package",
+      "path": "System.Runtime.InteropServices/4.1.0",
+      "files": [
+        "System.Runtime.InteropServices.4.1.0.nupkg.sha512",
+        "System.Runtime.InteropServices.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/_._",
+        "lib/net462/System.Runtime.InteropServices.dll",
+        "lib/portable-net45+win8+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net45/_._",
+        "ref/net462/System.Runtime.InteropServices.dll",
+        "ref/netcore50/System.Runtime.InteropServices.dll",
+        "ref/netcore50/System.Runtime.InteropServices.xml",
+        "ref/netcore50/de/System.Runtime.InteropServices.xml",
+        "ref/netcore50/es/System.Runtime.InteropServices.xml",
+        "ref/netcore50/fr/System.Runtime.InteropServices.xml",
+        "ref/netcore50/it/System.Runtime.InteropServices.xml",
+        "ref/netcore50/ja/System.Runtime.InteropServices.xml",
+        "ref/netcore50/ko/System.Runtime.InteropServices.xml",
+        "ref/netcore50/ru/System.Runtime.InteropServices.xml",
+        "ref/netcore50/zh-hans/System.Runtime.InteropServices.xml",
+        "ref/netcore50/zh-hant/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.1/System.Runtime.InteropServices.dll",
+        "ref/netstandard1.1/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.1/de/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.1/es/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.1/fr/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.1/it/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.1/ja/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.1/ko/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.1/ru/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.1/zh-hans/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.1/zh-hant/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.2/System.Runtime.InteropServices.dll",
+        "ref/netstandard1.2/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.2/de/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.2/es/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.2/fr/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.2/it/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.2/ja/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.2/ko/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.2/ru/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.2/zh-hans/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.2/zh-hant/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.3/System.Runtime.InteropServices.dll",
+        "ref/netstandard1.3/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.3/de/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.3/es/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.3/fr/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.3/it/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.3/ja/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.3/ko/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.3/ru/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.3/zh-hans/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.3/zh-hant/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.5/System.Runtime.InteropServices.dll",
+        "ref/netstandard1.5/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.5/de/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.5/es/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.5/fr/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.5/it/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.5/ja/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.5/ko/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.5/ru/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.5/zh-hans/System.Runtime.InteropServices.xml",
+        "ref/netstandard1.5/zh-hant/System.Runtime.InteropServices.xml",
+        "ref/portable-net45+win8+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Runtime.InteropServices.RuntimeInformation/4.0.0": {
+      "sha512": "hWPhJxc453RCa8Z29O91EmfGeZIHX1ZH2A8L6lYQVSaKzku2DfArSfMEb1/MYYzPQRJZeu0c9dmYeJKxW5Fgng==",
+      "type": "package",
+      "path": "System.Runtime.InteropServices.RuntimeInformation/4.0.0",
+      "files": [
+        "System.Runtime.InteropServices.RuntimeInformation.4.0.0.nupkg.sha512",
+        "System.Runtime.InteropServices.RuntimeInformation.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/System.Runtime.InteropServices.RuntimeInformation.dll",
+        "lib/win8/System.Runtime.InteropServices.RuntimeInformation.dll",
+        "lib/wpa81/System.Runtime.InteropServices.RuntimeInformation.dll",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/netstandard1.1/System.Runtime.InteropServices.RuntimeInformation.dll",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._",
+        "runtimes/aot/lib/netcore50/System.Runtime.InteropServices.RuntimeInformation.dll",
+        "runtimes/unix/lib/netstandard1.1/System.Runtime.InteropServices.RuntimeInformation.dll",
+        "runtimes/win/lib/net45/System.Runtime.InteropServices.RuntimeInformation.dll",
+        "runtimes/win/lib/netcore50/System.Runtime.InteropServices.RuntimeInformation.dll",
+        "runtimes/win/lib/netstandard1.1/System.Runtime.InteropServices.RuntimeInformation.dll"
+      ]
+    },
+    "System.Runtime.Numerics/4.0.1": {
+      "sha512": "+XbKFuzdmLP3d1o9pdHu2nxjNr2OEPqGzKeegPLCUMM71a0t50A/rOcIRmGs9wR7a8KuHX6hYs/7/TymIGLNqg==",
+      "type": "package",
+      "path": "System.Runtime.Numerics/4.0.1",
+      "files": [
+        "System.Runtime.Numerics.4.0.1.nupkg.sha512",
+        "System.Runtime.Numerics.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/_._",
+        "lib/netcore50/System.Runtime.Numerics.dll",
+        "lib/netstandard1.3/System.Runtime.Numerics.dll",
+        "lib/portable-net45+win8+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net45/_._",
+        "ref/netcore50/System.Runtime.Numerics.dll",
+        "ref/netcore50/System.Runtime.Numerics.xml",
+        "ref/netcore50/de/System.Runtime.Numerics.xml",
+        "ref/netcore50/es/System.Runtime.Numerics.xml",
+        "ref/netcore50/fr/System.Runtime.Numerics.xml",
+        "ref/netcore50/it/System.Runtime.Numerics.xml",
+        "ref/netcore50/ja/System.Runtime.Numerics.xml",
+        "ref/netcore50/ko/System.Runtime.Numerics.xml",
+        "ref/netcore50/ru/System.Runtime.Numerics.xml",
+        "ref/netcore50/zh-hans/System.Runtime.Numerics.xml",
+        "ref/netcore50/zh-hant/System.Runtime.Numerics.xml",
+        "ref/netstandard1.1/System.Runtime.Numerics.dll",
+        "ref/netstandard1.1/System.Runtime.Numerics.xml",
+        "ref/netstandard1.1/de/System.Runtime.Numerics.xml",
+        "ref/netstandard1.1/es/System.Runtime.Numerics.xml",
+        "ref/netstandard1.1/fr/System.Runtime.Numerics.xml",
+        "ref/netstandard1.1/it/System.Runtime.Numerics.xml",
+        "ref/netstandard1.1/ja/System.Runtime.Numerics.xml",
+        "ref/netstandard1.1/ko/System.Runtime.Numerics.xml",
+        "ref/netstandard1.1/ru/System.Runtime.Numerics.xml",
+        "ref/netstandard1.1/zh-hans/System.Runtime.Numerics.xml",
+        "ref/netstandard1.1/zh-hant/System.Runtime.Numerics.xml",
+        "ref/portable-net45+win8+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Security.Cryptography.Algorithms/4.2.0": {
+      "sha512": "8JQFxbLVdrtIOKMDN38Fn0GWnqYZw/oMlwOUG/qz1jqChvyZlnUmu+0s7wLx7JYua/nAXoESpHA3iw11QFWhXg==",
+      "type": "package",
+      "path": "System.Security.Cryptography.Algorithms/4.2.0",
+      "files": [
+        "System.Security.Cryptography.Algorithms.4.2.0.nupkg.sha512",
+        "System.Security.Cryptography.Algorithms.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net46/System.Security.Cryptography.Algorithms.dll",
+        "lib/net461/System.Security.Cryptography.Algorithms.dll",
+        "lib/net463/System.Security.Cryptography.Algorithms.dll",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net46/System.Security.Cryptography.Algorithms.dll",
+        "ref/net461/System.Security.Cryptography.Algorithms.dll",
+        "ref/net463/System.Security.Cryptography.Algorithms.dll",
+        "ref/netstandard1.3/System.Security.Cryptography.Algorithms.dll",
+        "ref/netstandard1.4/System.Security.Cryptography.Algorithms.dll",
+        "ref/netstandard1.6/System.Security.Cryptography.Algorithms.dll",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._",
+        "runtimes/unix/lib/netstandard1.6/System.Security.Cryptography.Algorithms.dll",
+        "runtimes/win/lib/net46/System.Security.Cryptography.Algorithms.dll",
+        "runtimes/win/lib/net461/System.Security.Cryptography.Algorithms.dll",
+        "runtimes/win/lib/net463/System.Security.Cryptography.Algorithms.dll",
+        "runtimes/win/lib/netcore50/System.Security.Cryptography.Algorithms.dll",
+        "runtimes/win/lib/netstandard1.6/System.Security.Cryptography.Algorithms.dll"
+      ]
+    },
+    "System.Security.Cryptography.Cng/4.2.0": {
+      "sha512": "cUJ2h+ZvONDe28Szw3st5dOHdjndhJzQ2WObDEXAWRPEQBtVItVoxbXM/OEsTthl3cNn2dk2k0I3y45igCQcLw==",
+      "type": "package",
+      "path": "System.Security.Cryptography.Cng/4.2.0",
+      "files": [
+        "System.Security.Cryptography.Cng.4.2.0.nupkg.sha512",
+        "System.Security.Cryptography.Cng.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/net46/System.Security.Cryptography.Cng.dll",
+        "lib/net461/System.Security.Cryptography.Cng.dll",
+        "lib/net463/System.Security.Cryptography.Cng.dll",
+        "ref/net46/System.Security.Cryptography.Cng.dll",
+        "ref/net461/System.Security.Cryptography.Cng.dll",
+        "ref/net463/System.Security.Cryptography.Cng.dll",
+        "ref/netstandard1.3/System.Security.Cryptography.Cng.dll",
+        "ref/netstandard1.4/System.Security.Cryptography.Cng.dll",
+        "ref/netstandard1.6/System.Security.Cryptography.Cng.dll",
+        "runtimes/unix/lib/netstandard1.6/System.Security.Cryptography.Cng.dll",
+        "runtimes/win/lib/net46/System.Security.Cryptography.Cng.dll",
+        "runtimes/win/lib/net461/System.Security.Cryptography.Cng.dll",
+        "runtimes/win/lib/net463/System.Security.Cryptography.Cng.dll",
+        "runtimes/win/lib/netstandard1.4/System.Security.Cryptography.Cng.dll",
+        "runtimes/win/lib/netstandard1.6/System.Security.Cryptography.Cng.dll"
+      ]
+    },
+    "System.Security.Cryptography.Csp/4.0.0": {
+      "sha512": "/i1Usuo4PgAqgbPNC0NjbO3jPW//BoBlTpcWFD1EHVbidH21y4c1ap5bbEMSGAXjAShhMH4abi/K8fILrnu4BQ==",
+      "type": "package",
+      "path": "System.Security.Cryptography.Csp/4.0.0",
+      "files": [
+        "System.Security.Cryptography.Csp.4.0.0.nupkg.sha512",
+        "System.Security.Cryptography.Csp.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net46/System.Security.Cryptography.Csp.dll",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net46/System.Security.Cryptography.Csp.dll",
+        "ref/netstandard1.3/System.Security.Cryptography.Csp.dll",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._",
+        "runtimes/unix/lib/netstandard1.3/System.Security.Cryptography.Csp.dll",
+        "runtimes/win/lib/net46/System.Security.Cryptography.Csp.dll",
+        "runtimes/win/lib/netcore50/_._",
+        "runtimes/win/lib/netstandard1.3/System.Security.Cryptography.Csp.dll"
+      ]
+    },
+    "System.Security.Cryptography.Encoding/4.0.0": {
+      "sha512": "FbKgE5MbxSQMPcSVRgwM6bXN3GtyAh04NkV8E5zKCBE26X0vYW0UtTa2FIgkH33WVqBVxRgxljlVYumWtU+HcQ==",
+      "type": "package",
+      "path": "System.Security.Cryptography.Encoding/4.0.0",
+      "files": [
+        "System.Security.Cryptography.Encoding.4.0.0.nupkg.sha512",
+        "System.Security.Cryptography.Encoding.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net46/System.Security.Cryptography.Encoding.dll",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net46/System.Security.Cryptography.Encoding.dll",
+        "ref/netstandard1.3/System.Security.Cryptography.Encoding.dll",
+        "ref/netstandard1.3/System.Security.Cryptography.Encoding.xml",
+        "ref/netstandard1.3/de/System.Security.Cryptography.Encoding.xml",
+        "ref/netstandard1.3/es/System.Security.Cryptography.Encoding.xml",
+        "ref/netstandard1.3/fr/System.Security.Cryptography.Encoding.xml",
+        "ref/netstandard1.3/it/System.Security.Cryptography.Encoding.xml",
+        "ref/netstandard1.3/ja/System.Security.Cryptography.Encoding.xml",
+        "ref/netstandard1.3/ko/System.Security.Cryptography.Encoding.xml",
+        "ref/netstandard1.3/ru/System.Security.Cryptography.Encoding.xml",
+        "ref/netstandard1.3/zh-hans/System.Security.Cryptography.Encoding.xml",
+        "ref/netstandard1.3/zh-hant/System.Security.Cryptography.Encoding.xml",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._",
+        "runtimes/unix/lib/netstandard1.3/System.Security.Cryptography.Encoding.dll",
+        "runtimes/win/lib/net46/System.Security.Cryptography.Encoding.dll",
+        "runtimes/win/lib/netstandard1.3/System.Security.Cryptography.Encoding.dll"
+      ]
+    },
+    "System.Security.Cryptography.OpenSsl/4.0.0": {
+      "sha512": "HUG/zNUJwEiLkoURDixzkzZdB5yGA5pQhDP93ArOpDPQMteURIGERRNzzoJlmTreLBWr5lkFSjjMSk8ySEpQMw==",
+      "type": "package",
+      "path": "System.Security.Cryptography.OpenSsl/4.0.0",
+      "files": [
+        "System.Security.Cryptography.OpenSsl.4.0.0.nupkg.sha512",
+        "System.Security.Cryptography.OpenSsl.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/netstandard1.6/System.Security.Cryptography.OpenSsl.dll",
+        "ref/netstandard1.6/System.Security.Cryptography.OpenSsl.dll",
+        "runtimes/unix/lib/netstandard1.6/System.Security.Cryptography.OpenSsl.dll"
+      ]
+    },
+    "System.Security.Cryptography.Primitives/4.0.0": {
+      "sha512": "Wkd7QryWYjkQclX0bngpntW5HSlMzeJU24UaLJQ7YTfI8ydAVAaU2J+HXLLABOVJlKTVvAeL0Aj39VeTe7L+oA==",
+      "type": "package",
+      "path": "System.Security.Cryptography.Primitives/4.0.0",
+      "files": [
+        "System.Security.Cryptography.Primitives.4.0.0.nupkg.sha512",
+        "System.Security.Cryptography.Primitives.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net46/System.Security.Cryptography.Primitives.dll",
+        "lib/netstandard1.3/System.Security.Cryptography.Primitives.dll",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net46/System.Security.Cryptography.Primitives.dll",
+        "ref/netstandard1.3/System.Security.Cryptography.Primitives.dll",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Security.Cryptography.X509Certificates/4.1.0": {
+      "sha512": "4HEfsQIKAhA1+ApNn729Gi09zh+lYWwyIuViihoMDWp1vQnEkL2ct7mAbhBlLYm+x/L4Rr/pyGge1lIY635e0w==",
+      "type": "package",
+      "path": "System.Security.Cryptography.X509Certificates/4.1.0",
+      "files": [
+        "System.Security.Cryptography.X509Certificates.4.1.0.nupkg.sha512",
+        "System.Security.Cryptography.X509Certificates.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net46/System.Security.Cryptography.X509Certificates.dll",
+        "lib/net461/System.Security.Cryptography.X509Certificates.dll",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net46/System.Security.Cryptography.X509Certificates.dll",
+        "ref/net461/System.Security.Cryptography.X509Certificates.dll",
+        "ref/netstandard1.3/System.Security.Cryptography.X509Certificates.dll",
+        "ref/netstandard1.3/System.Security.Cryptography.X509Certificates.xml",
+        "ref/netstandard1.3/de/System.Security.Cryptography.X509Certificates.xml",
+        "ref/netstandard1.3/es/System.Security.Cryptography.X509Certificates.xml",
+        "ref/netstandard1.3/fr/System.Security.Cryptography.X509Certificates.xml",
+        "ref/netstandard1.3/it/System.Security.Cryptography.X509Certificates.xml",
+        "ref/netstandard1.3/ja/System.Security.Cryptography.X509Certificates.xml",
+        "ref/netstandard1.3/ko/System.Security.Cryptography.X509Certificates.xml",
+        "ref/netstandard1.3/ru/System.Security.Cryptography.X509Certificates.xml",
+        "ref/netstandard1.3/zh-hans/System.Security.Cryptography.X509Certificates.xml",
+        "ref/netstandard1.3/zh-hant/System.Security.Cryptography.X509Certificates.xml",
+        "ref/netstandard1.4/System.Security.Cryptography.X509Certificates.dll",
+        "ref/netstandard1.4/System.Security.Cryptography.X509Certificates.xml",
+        "ref/netstandard1.4/de/System.Security.Cryptography.X509Certificates.xml",
+        "ref/netstandard1.4/es/System.Security.Cryptography.X509Certificates.xml",
+        "ref/netstandard1.4/fr/System.Security.Cryptography.X509Certificates.xml",
+        "ref/netstandard1.4/it/System.Security.Cryptography.X509Certificates.xml",
+        "ref/netstandard1.4/ja/System.Security.Cryptography.X509Certificates.xml",
+        "ref/netstandard1.4/ko/System.Security.Cryptography.X509Certificates.xml",
+        "ref/netstandard1.4/ru/System.Security.Cryptography.X509Certificates.xml",
+        "ref/netstandard1.4/zh-hans/System.Security.Cryptography.X509Certificates.xml",
+        "ref/netstandard1.4/zh-hant/System.Security.Cryptography.X509Certificates.xml",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._",
+        "runtimes/unix/lib/netstandard1.6/System.Security.Cryptography.X509Certificates.dll",
+        "runtimes/win/lib/net46/System.Security.Cryptography.X509Certificates.dll",
+        "runtimes/win/lib/net461/System.Security.Cryptography.X509Certificates.dll",
+        "runtimes/win/lib/netcore50/System.Security.Cryptography.X509Certificates.dll",
+        "runtimes/win/lib/netstandard1.6/System.Security.Cryptography.X509Certificates.dll"
+      ]
+    },
+    "System.Text.Encoding/4.0.11": {
+      "sha512": "U3gGeMlDZXxCEiY4DwVLSacg+DFWCvoiX+JThA/rvw37Sqrku7sEFeVBBBMBnfB6FeZHsyDx85HlKL19x0HtZA==",
+      "type": "package",
+      "path": "System.Text.Encoding/4.0.11",
+      "files": [
+        "System.Text.Encoding.4.0.11.nupkg.sha512",
+        "System.Text.Encoding.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/_._",
+        "lib/portable-net45+win8+wp8+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wp80/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net45/_._",
+        "ref/netcore50/System.Text.Encoding.dll",
+        "ref/netcore50/System.Text.Encoding.xml",
+        "ref/netcore50/de/System.Text.Encoding.xml",
+        "ref/netcore50/es/System.Text.Encoding.xml",
+        "ref/netcore50/fr/System.Text.Encoding.xml",
+        "ref/netcore50/it/System.Text.Encoding.xml",
+        "ref/netcore50/ja/System.Text.Encoding.xml",
+        "ref/netcore50/ko/System.Text.Encoding.xml",
+        "ref/netcore50/ru/System.Text.Encoding.xml",
+        "ref/netcore50/zh-hans/System.Text.Encoding.xml",
+        "ref/netcore50/zh-hant/System.Text.Encoding.xml",
+        "ref/netstandard1.0/System.Text.Encoding.dll",
+        "ref/netstandard1.0/System.Text.Encoding.xml",
+        "ref/netstandard1.0/de/System.Text.Encoding.xml",
+        "ref/netstandard1.0/es/System.Text.Encoding.xml",
+        "ref/netstandard1.0/fr/System.Text.Encoding.xml",
+        "ref/netstandard1.0/it/System.Text.Encoding.xml",
+        "ref/netstandard1.0/ja/System.Text.Encoding.xml",
+        "ref/netstandard1.0/ko/System.Text.Encoding.xml",
+        "ref/netstandard1.0/ru/System.Text.Encoding.xml",
+        "ref/netstandard1.0/zh-hans/System.Text.Encoding.xml",
+        "ref/netstandard1.0/zh-hant/System.Text.Encoding.xml",
+        "ref/netstandard1.3/System.Text.Encoding.dll",
+        "ref/netstandard1.3/System.Text.Encoding.xml",
+        "ref/netstandard1.3/de/System.Text.Encoding.xml",
+        "ref/netstandard1.3/es/System.Text.Encoding.xml",
+        "ref/netstandard1.3/fr/System.Text.Encoding.xml",
+        "ref/netstandard1.3/it/System.Text.Encoding.xml",
+        "ref/netstandard1.3/ja/System.Text.Encoding.xml",
+        "ref/netstandard1.3/ko/System.Text.Encoding.xml",
+        "ref/netstandard1.3/ru/System.Text.Encoding.xml",
+        "ref/netstandard1.3/zh-hans/System.Text.Encoding.xml",
+        "ref/netstandard1.3/zh-hant/System.Text.Encoding.xml",
+        "ref/portable-net45+win8+wp8+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wp80/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Text.Encoding.Extensions/4.0.11": {
+      "sha512": "jtbiTDtvfLYgXn8PTfWI+SiBs51rrmO4AAckx4KR6vFK9Wzf6tI8kcRdsYQNwriUeQ1+CtQbM1W4cMbLXnj/OQ==",
+      "type": "package",
+      "path": "System.Text.Encoding.Extensions/4.0.11",
+      "files": [
+        "System.Text.Encoding.Extensions.4.0.11.nupkg.sha512",
+        "System.Text.Encoding.Extensions.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/_._",
+        "lib/portable-net45+win8+wp8+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wp80/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net45/_._",
+        "ref/netcore50/System.Text.Encoding.Extensions.dll",
+        "ref/netcore50/System.Text.Encoding.Extensions.xml",
+        "ref/netcore50/de/System.Text.Encoding.Extensions.xml",
+        "ref/netcore50/es/System.Text.Encoding.Extensions.xml",
+        "ref/netcore50/fr/System.Text.Encoding.Extensions.xml",
+        "ref/netcore50/it/System.Text.Encoding.Extensions.xml",
+        "ref/netcore50/ja/System.Text.Encoding.Extensions.xml",
+        "ref/netcore50/ko/System.Text.Encoding.Extensions.xml",
+        "ref/netcore50/ru/System.Text.Encoding.Extensions.xml",
+        "ref/netcore50/zh-hans/System.Text.Encoding.Extensions.xml",
+        "ref/netcore50/zh-hant/System.Text.Encoding.Extensions.xml",
+        "ref/netstandard1.0/System.Text.Encoding.Extensions.dll",
+        "ref/netstandard1.0/System.Text.Encoding.Extensions.xml",
+        "ref/netstandard1.0/de/System.Text.Encoding.Extensions.xml",
+        "ref/netstandard1.0/es/System.Text.Encoding.Extensions.xml",
+        "ref/netstandard1.0/fr/System.Text.Encoding.Extensions.xml",
+        "ref/netstandard1.0/it/System.Text.Encoding.Extensions.xml",
+        "ref/netstandard1.0/ja/System.Text.Encoding.Extensions.xml",
+        "ref/netstandard1.0/ko/System.Text.Encoding.Extensions.xml",
+        "ref/netstandard1.0/ru/System.Text.Encoding.Extensions.xml",
+        "ref/netstandard1.0/zh-hans/System.Text.Encoding.Extensions.xml",
+        "ref/netstandard1.0/zh-hant/System.Text.Encoding.Extensions.xml",
+        "ref/netstandard1.3/System.Text.Encoding.Extensions.dll",
+        "ref/netstandard1.3/System.Text.Encoding.Extensions.xml",
+        "ref/netstandard1.3/de/System.Text.Encoding.Extensions.xml",
+        "ref/netstandard1.3/es/System.Text.Encoding.Extensions.xml",
+        "ref/netstandard1.3/fr/System.Text.Encoding.Extensions.xml",
+        "ref/netstandard1.3/it/System.Text.Encoding.Extensions.xml",
+        "ref/netstandard1.3/ja/System.Text.Encoding.Extensions.xml",
+        "ref/netstandard1.3/ko/System.Text.Encoding.Extensions.xml",
+        "ref/netstandard1.3/ru/System.Text.Encoding.Extensions.xml",
+        "ref/netstandard1.3/zh-hans/System.Text.Encoding.Extensions.xml",
+        "ref/netstandard1.3/zh-hant/System.Text.Encoding.Extensions.xml",
+        "ref/portable-net45+win8+wp8+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wp80/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Text.RegularExpressions/4.1.0": {
+      "sha512": "i88YCXpRTjCnoSQZtdlHkAOx4KNNik4hMy83n0+Ftlb7jvV6ZiZWMpnEZHhjBp6hQVh8gWd/iKNPzlPF7iyA2g==",
+      "type": "package",
+      "path": "System.Text.RegularExpressions/4.1.0",
+      "files": [
+        "System.Text.RegularExpressions.4.1.0.nupkg.sha512",
+        "System.Text.RegularExpressions.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/_._",
+        "lib/net463/System.Text.RegularExpressions.dll",
+        "lib/netcore50/System.Text.RegularExpressions.dll",
+        "lib/netstandard1.6/System.Text.RegularExpressions.dll",
+        "lib/portable-net45+win8+wp8+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wp80/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net45/_._",
+        "ref/net463/System.Text.RegularExpressions.dll",
+        "ref/netcore50/System.Text.RegularExpressions.dll",
+        "ref/netcore50/System.Text.RegularExpressions.xml",
+        "ref/netcore50/de/System.Text.RegularExpressions.xml",
+        "ref/netcore50/es/System.Text.RegularExpressions.xml",
+        "ref/netcore50/fr/System.Text.RegularExpressions.xml",
+        "ref/netcore50/it/System.Text.RegularExpressions.xml",
+        "ref/netcore50/ja/System.Text.RegularExpressions.xml",
+        "ref/netcore50/ko/System.Text.RegularExpressions.xml",
+        "ref/netcore50/ru/System.Text.RegularExpressions.xml",
+        "ref/netcore50/zh-hans/System.Text.RegularExpressions.xml",
+        "ref/netcore50/zh-hant/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.0/System.Text.RegularExpressions.dll",
+        "ref/netstandard1.0/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.0/de/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.0/es/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.0/fr/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.0/it/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.0/ja/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.0/ko/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.0/ru/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.0/zh-hans/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.0/zh-hant/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.3/System.Text.RegularExpressions.dll",
+        "ref/netstandard1.3/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.3/de/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.3/es/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.3/fr/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.3/it/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.3/ja/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.3/ko/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.3/ru/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.3/zh-hans/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.3/zh-hant/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.6/System.Text.RegularExpressions.dll",
+        "ref/netstandard1.6/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.6/de/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.6/es/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.6/fr/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.6/it/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.6/ja/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.6/ko/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.6/ru/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.6/zh-hans/System.Text.RegularExpressions.xml",
+        "ref/netstandard1.6/zh-hant/System.Text.RegularExpressions.xml",
+        "ref/portable-net45+win8+wp8+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wp80/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Threading/4.0.11": {
+      "sha512": "N+3xqIcg3VDKyjwwCGaZ9HawG9aC6cSDI+s7ROma310GQo8vilFZa86hqKppwTHleR/G0sfOzhvgnUxWCR/DrQ==",
+      "type": "package",
+      "path": "System.Threading/4.0.11",
+      "files": [
+        "System.Threading.4.0.11.nupkg.sha512",
+        "System.Threading.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/_._",
+        "lib/netcore50/System.Threading.dll",
+        "lib/netstandard1.3/System.Threading.dll",
+        "lib/portable-net45+win8+wp8+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wp80/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net45/_._",
+        "ref/netcore50/System.Threading.dll",
+        "ref/netcore50/System.Threading.xml",
+        "ref/netcore50/de/System.Threading.xml",
+        "ref/netcore50/es/System.Threading.xml",
+        "ref/netcore50/fr/System.Threading.xml",
+        "ref/netcore50/it/System.Threading.xml",
+        "ref/netcore50/ja/System.Threading.xml",
+        "ref/netcore50/ko/System.Threading.xml",
+        "ref/netcore50/ru/System.Threading.xml",
+        "ref/netcore50/zh-hans/System.Threading.xml",
+        "ref/netcore50/zh-hant/System.Threading.xml",
+        "ref/netstandard1.0/System.Threading.dll",
+        "ref/netstandard1.0/System.Threading.xml",
+        "ref/netstandard1.0/de/System.Threading.xml",
+        "ref/netstandard1.0/es/System.Threading.xml",
+        "ref/netstandard1.0/fr/System.Threading.xml",
+        "ref/netstandard1.0/it/System.Threading.xml",
+        "ref/netstandard1.0/ja/System.Threading.xml",
+        "ref/netstandard1.0/ko/System.Threading.xml",
+        "ref/netstandard1.0/ru/System.Threading.xml",
+        "ref/netstandard1.0/zh-hans/System.Threading.xml",
+        "ref/netstandard1.0/zh-hant/System.Threading.xml",
+        "ref/netstandard1.3/System.Threading.dll",
+        "ref/netstandard1.3/System.Threading.xml",
+        "ref/netstandard1.3/de/System.Threading.xml",
+        "ref/netstandard1.3/es/System.Threading.xml",
+        "ref/netstandard1.3/fr/System.Threading.xml",
+        "ref/netstandard1.3/it/System.Threading.xml",
+        "ref/netstandard1.3/ja/System.Threading.xml",
+        "ref/netstandard1.3/ko/System.Threading.xml",
+        "ref/netstandard1.3/ru/System.Threading.xml",
+        "ref/netstandard1.3/zh-hans/System.Threading.xml",
+        "ref/netstandard1.3/zh-hant/System.Threading.xml",
+        "ref/portable-net45+win8+wp8+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wp80/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._",
+        "runtimes/aot/lib/netcore50/System.Threading.dll"
+      ]
+    },
+    "System.Threading.Tasks/4.0.11": {
+      "sha512": "k1S4Gc6IGwtHGT8188RSeGaX86Qw/wnrgNLshJvsdNUOPP9etMmo8S07c+UlOAx4K/xLuN9ivA1bD0LVurtIxQ==",
+      "type": "package",
+      "path": "System.Threading.Tasks/4.0.11",
+      "files": [
+        "System.Threading.Tasks.4.0.11.nupkg.sha512",
+        "System.Threading.Tasks.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/_._",
+        "lib/portable-net45+win8+wp8+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wp80/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net45/_._",
+        "ref/netcore50/System.Threading.Tasks.dll",
+        "ref/netcore50/System.Threading.Tasks.xml",
+        "ref/netcore50/de/System.Threading.Tasks.xml",
+        "ref/netcore50/es/System.Threading.Tasks.xml",
+        "ref/netcore50/fr/System.Threading.Tasks.xml",
+        "ref/netcore50/it/System.Threading.Tasks.xml",
+        "ref/netcore50/ja/System.Threading.Tasks.xml",
+        "ref/netcore50/ko/System.Threading.Tasks.xml",
+        "ref/netcore50/ru/System.Threading.Tasks.xml",
+        "ref/netcore50/zh-hans/System.Threading.Tasks.xml",
+        "ref/netcore50/zh-hant/System.Threading.Tasks.xml",
+        "ref/netstandard1.0/System.Threading.Tasks.dll",
+        "ref/netstandard1.0/System.Threading.Tasks.xml",
+        "ref/netstandard1.0/de/System.Threading.Tasks.xml",
+        "ref/netstandard1.0/es/System.Threading.Tasks.xml",
+        "ref/netstandard1.0/fr/System.Threading.Tasks.xml",
+        "ref/netstandard1.0/it/System.Threading.Tasks.xml",
+        "ref/netstandard1.0/ja/System.Threading.Tasks.xml",
+        "ref/netstandard1.0/ko/System.Threading.Tasks.xml",
+        "ref/netstandard1.0/ru/System.Threading.Tasks.xml",
+        "ref/netstandard1.0/zh-hans/System.Threading.Tasks.xml",
+        "ref/netstandard1.0/zh-hant/System.Threading.Tasks.xml",
+        "ref/netstandard1.3/System.Threading.Tasks.dll",
+        "ref/netstandard1.3/System.Threading.Tasks.xml",
+        "ref/netstandard1.3/de/System.Threading.Tasks.xml",
+        "ref/netstandard1.3/es/System.Threading.Tasks.xml",
+        "ref/netstandard1.3/fr/System.Threading.Tasks.xml",
+        "ref/netstandard1.3/it/System.Threading.Tasks.xml",
+        "ref/netstandard1.3/ja/System.Threading.Tasks.xml",
+        "ref/netstandard1.3/ko/System.Threading.Tasks.xml",
+        "ref/netstandard1.3/ru/System.Threading.Tasks.xml",
+        "ref/netstandard1.3/zh-hans/System.Threading.Tasks.xml",
+        "ref/netstandard1.3/zh-hant/System.Threading.Tasks.xml",
+        "ref/portable-net45+win8+wp8+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wp80/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Threading.Tasks.Extensions/4.0.0": {
+      "sha512": "pH4FZDsZQ/WmgJtN4LWYmRdJAEeVkyriSwrv2Teoe5FOU0Yxlb6II6GL8dBPOfRmutHGATduj3ooMt7dJ2+i+w==",
+      "type": "package",
+      "path": "System.Threading.Tasks.Extensions/4.0.0",
+      "files": [
+        "System.Threading.Tasks.Extensions.4.0.0.nupkg.sha512",
+        "System.Threading.Tasks.Extensions.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/netstandard1.0/System.Threading.Tasks.Extensions.dll",
+        "lib/netstandard1.0/System.Threading.Tasks.Extensions.xml",
+        "lib/portable-net45+win8+wp8+wpa81/System.Threading.Tasks.Extensions.dll",
+        "lib/portable-net45+win8+wp8+wpa81/System.Threading.Tasks.Extensions.xml"
+      ]
+    },
+    "System.Threading.Timer/4.0.1": {
+      "sha512": "saGfUV8uqVW6LeURiqxcGhZ24PzuRNaUBtbhVeuUAvky1naH395A/1nY0P2bWvrw/BreRtIB/EzTDkGBpqCwEw==",
+      "type": "package",
+      "path": "System.Threading.Timer/4.0.1",
+      "files": [
+        "System.Threading.Timer.4.0.1.nupkg.sha512",
+        "System.Threading.Timer.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net451/_._",
+        "lib/portable-net451+win81+wpa81/_._",
+        "lib/win81/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net451/_._",
+        "ref/netcore50/System.Threading.Timer.dll",
+        "ref/netcore50/System.Threading.Timer.xml",
+        "ref/netcore50/de/System.Threading.Timer.xml",
+        "ref/netcore50/es/System.Threading.Timer.xml",
+        "ref/netcore50/fr/System.Threading.Timer.xml",
+        "ref/netcore50/it/System.Threading.Timer.xml",
+        "ref/netcore50/ja/System.Threading.Timer.xml",
+        "ref/netcore50/ko/System.Threading.Timer.xml",
+        "ref/netcore50/ru/System.Threading.Timer.xml",
+        "ref/netcore50/zh-hans/System.Threading.Timer.xml",
+        "ref/netcore50/zh-hant/System.Threading.Timer.xml",
+        "ref/netstandard1.2/System.Threading.Timer.dll",
+        "ref/netstandard1.2/System.Threading.Timer.xml",
+        "ref/netstandard1.2/de/System.Threading.Timer.xml",
+        "ref/netstandard1.2/es/System.Threading.Timer.xml",
+        "ref/netstandard1.2/fr/System.Threading.Timer.xml",
+        "ref/netstandard1.2/it/System.Threading.Timer.xml",
+        "ref/netstandard1.2/ja/System.Threading.Timer.xml",
+        "ref/netstandard1.2/ko/System.Threading.Timer.xml",
+        "ref/netstandard1.2/ru/System.Threading.Timer.xml",
+        "ref/netstandard1.2/zh-hans/System.Threading.Timer.xml",
+        "ref/netstandard1.2/zh-hant/System.Threading.Timer.xml",
+        "ref/portable-net451+win81+wpa81/_._",
+        "ref/win81/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Xml.ReaderWriter/4.0.11": {
+      "sha512": "ZIiLPsf67YZ9zgr31vzrFaYQqxRPX9cVHjtPSnmx4eN6lbS/yEyYNr2vs1doGDEscF0tjCZFsk9yUg1sC9e8tg==",
+      "type": "package",
+      "path": "System.Xml.ReaderWriter/4.0.11",
+      "files": [
+        "System.Xml.ReaderWriter.4.0.11.nupkg.sha512",
+        "System.Xml.ReaderWriter.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/_._",
+        "lib/netcore50/System.Xml.ReaderWriter.dll",
+        "lib/netstandard1.3/System.Xml.ReaderWriter.dll",
+        "lib/portable-net45+win8+wp8+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wp80/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net45/_._",
+        "ref/netcore50/System.Xml.ReaderWriter.dll",
+        "ref/netcore50/System.Xml.ReaderWriter.xml",
+        "ref/netcore50/de/System.Xml.ReaderWriter.xml",
+        "ref/netcore50/es/System.Xml.ReaderWriter.xml",
+        "ref/netcore50/fr/System.Xml.ReaderWriter.xml",
+        "ref/netcore50/it/System.Xml.ReaderWriter.xml",
+        "ref/netcore50/ja/System.Xml.ReaderWriter.xml",
+        "ref/netcore50/ko/System.Xml.ReaderWriter.xml",
+        "ref/netcore50/ru/System.Xml.ReaderWriter.xml",
+        "ref/netcore50/zh-hans/System.Xml.ReaderWriter.xml",
+        "ref/netcore50/zh-hant/System.Xml.ReaderWriter.xml",
+        "ref/netstandard1.0/System.Xml.ReaderWriter.dll",
+        "ref/netstandard1.0/System.Xml.ReaderWriter.xml",
+        "ref/netstandard1.0/de/System.Xml.ReaderWriter.xml",
+        "ref/netstandard1.0/es/System.Xml.ReaderWriter.xml",
+        "ref/netstandard1.0/fr/System.Xml.ReaderWriter.xml",
+        "ref/netstandard1.0/it/System.Xml.ReaderWriter.xml",
+        "ref/netstandard1.0/ja/System.Xml.ReaderWriter.xml",
+        "ref/netstandard1.0/ko/System.Xml.ReaderWriter.xml",
+        "ref/netstandard1.0/ru/System.Xml.ReaderWriter.xml",
+        "ref/netstandard1.0/zh-hans/System.Xml.ReaderWriter.xml",
+        "ref/netstandard1.0/zh-hant/System.Xml.ReaderWriter.xml",
+        "ref/netstandard1.3/System.Xml.ReaderWriter.dll",
+        "ref/netstandard1.3/System.Xml.ReaderWriter.xml",
+        "ref/netstandard1.3/de/System.Xml.ReaderWriter.xml",
+        "ref/netstandard1.3/es/System.Xml.ReaderWriter.xml",
+        "ref/netstandard1.3/fr/System.Xml.ReaderWriter.xml",
+        "ref/netstandard1.3/it/System.Xml.ReaderWriter.xml",
+        "ref/netstandard1.3/ja/System.Xml.ReaderWriter.xml",
+        "ref/netstandard1.3/ko/System.Xml.ReaderWriter.xml",
+        "ref/netstandard1.3/ru/System.Xml.ReaderWriter.xml",
+        "ref/netstandard1.3/zh-hans/System.Xml.ReaderWriter.xml",
+        "ref/netstandard1.3/zh-hant/System.Xml.ReaderWriter.xml",
+        "ref/portable-net45+win8+wp8+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wp80/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Xml.XDocument/4.0.11": {
+      "sha512": "Mk2mKmPi0nWaoiYeotq1dgeNK1fqWh61+EK+w4Wu8SWuTYLzpUnschb59bJtGywaPq7SmTuPf44wrXRwbIrukg==",
+      "type": "package",
+      "path": "System.Xml.XDocument/4.0.11",
+      "files": [
+        "System.Xml.XDocument.4.0.11.nupkg.sha512",
+        "System.Xml.XDocument.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/_._",
+        "lib/netcore50/System.Xml.XDocument.dll",
+        "lib/netstandard1.3/System.Xml.XDocument.dll",
+        "lib/portable-net45+win8+wp8+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wp80/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net45/_._",
+        "ref/netcore50/System.Xml.XDocument.dll",
+        "ref/netcore50/System.Xml.XDocument.xml",
+        "ref/netcore50/de/System.Xml.XDocument.xml",
+        "ref/netcore50/es/System.Xml.XDocument.xml",
+        "ref/netcore50/fr/System.Xml.XDocument.xml",
+        "ref/netcore50/it/System.Xml.XDocument.xml",
+        "ref/netcore50/ja/System.Xml.XDocument.xml",
+        "ref/netcore50/ko/System.Xml.XDocument.xml",
+        "ref/netcore50/ru/System.Xml.XDocument.xml",
+        "ref/netcore50/zh-hans/System.Xml.XDocument.xml",
+        "ref/netcore50/zh-hant/System.Xml.XDocument.xml",
+        "ref/netstandard1.0/System.Xml.XDocument.dll",
+        "ref/netstandard1.0/System.Xml.XDocument.xml",
+        "ref/netstandard1.0/de/System.Xml.XDocument.xml",
+        "ref/netstandard1.0/es/System.Xml.XDocument.xml",
+        "ref/netstandard1.0/fr/System.Xml.XDocument.xml",
+        "ref/netstandard1.0/it/System.Xml.XDocument.xml",
+        "ref/netstandard1.0/ja/System.Xml.XDocument.xml",
+        "ref/netstandard1.0/ko/System.Xml.XDocument.xml",
+        "ref/netstandard1.0/ru/System.Xml.XDocument.xml",
+        "ref/netstandard1.0/zh-hans/System.Xml.XDocument.xml",
+        "ref/netstandard1.0/zh-hant/System.Xml.XDocument.xml",
+        "ref/netstandard1.3/System.Xml.XDocument.dll",
+        "ref/netstandard1.3/System.Xml.XDocument.xml",
+        "ref/netstandard1.3/de/System.Xml.XDocument.xml",
+        "ref/netstandard1.3/es/System.Xml.XDocument.xml",
+        "ref/netstandard1.3/fr/System.Xml.XDocument.xml",
+        "ref/netstandard1.3/it/System.Xml.XDocument.xml",
+        "ref/netstandard1.3/ja/System.Xml.XDocument.xml",
+        "ref/netstandard1.3/ko/System.Xml.XDocument.xml",
+        "ref/netstandard1.3/ru/System.Xml.XDocument.xml",
+        "ref/netstandard1.3/zh-hans/System.Xml.XDocument.xml",
+        "ref/netstandard1.3/zh-hant/System.Xml.XDocument.xml",
+        "ref/portable-net45+win8+wp8+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wp80/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Xml.XmlDocument/4.0.1": {
+      "sha512": "sDTrZPX5RBEsyGtaNEM48kd2SjfcyF+Nol2SdfrtOVbbjxe3lrJ+EfuidLgzTfd6SZoBi+nI2X8McT/kTp3/RQ==",
+      "type": "package",
+      "path": "System.Xml.XmlDocument/4.0.1",
+      "files": [
+        "System.Xml.XmlDocument.4.0.1.nupkg.sha512",
+        "System.Xml.XmlDocument.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net46/System.Xml.XmlDocument.dll",
+        "lib/netstandard1.3/System.Xml.XmlDocument.dll",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net46/System.Xml.XmlDocument.dll",
+        "ref/netstandard1.3/System.Xml.XmlDocument.dll",
+        "ref/netstandard1.3/System.Xml.XmlDocument.xml",
+        "ref/netstandard1.3/de/System.Xml.XmlDocument.xml",
+        "ref/netstandard1.3/es/System.Xml.XmlDocument.xml",
+        "ref/netstandard1.3/fr/System.Xml.XmlDocument.xml",
+        "ref/netstandard1.3/it/System.Xml.XmlDocument.xml",
+        "ref/netstandard1.3/ja/System.Xml.XmlDocument.xml",
+        "ref/netstandard1.3/ko/System.Xml.XmlDocument.xml",
+        "ref/netstandard1.3/ru/System.Xml.XmlDocument.xml",
+        "ref/netstandard1.3/zh-hans/System.Xml.XmlDocument.xml",
+        "ref/netstandard1.3/zh-hant/System.Xml.XmlDocument.xml",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._"
+      ]
+    },
+    "System.Xml.XmlSerializer/4.0.11": {
+      "sha512": "FrazwwqfIXTfq23mfv4zH+BjqkSFNaNFBtjzu3I9NRmG8EELYyrv/fJnttCIwRMFRR/YKXF1hmsMmMEnl55HGw==",
+      "type": "package",
+      "path": "System.Xml.XmlSerializer/4.0.11",
+      "files": [
+        "System.Xml.XmlSerializer.4.0.11.nupkg.sha512",
+        "System.Xml.XmlSerializer.nuspec",
+        "ThirdPartyNotices.txt",
+        "dotnet_library_license.txt",
+        "lib/MonoAndroid10/_._",
+        "lib/MonoTouch10/_._",
+        "lib/net45/_._",
+        "lib/netcore50/System.Xml.XmlSerializer.dll",
+        "lib/netstandard1.3/System.Xml.XmlSerializer.dll",
+        "lib/portable-net45+win8+wp8+wpa81/_._",
+        "lib/win8/_._",
+        "lib/wp80/_._",
+        "lib/wpa81/_._",
+        "lib/xamarinios10/_._",
+        "lib/xamarinmac20/_._",
+        "lib/xamarintvos10/_._",
+        "lib/xamarinwatchos10/_._",
+        "ref/MonoAndroid10/_._",
+        "ref/MonoTouch10/_._",
+        "ref/net45/_._",
+        "ref/netcore50/System.Xml.XmlSerializer.dll",
+        "ref/netcore50/System.Xml.XmlSerializer.xml",
+        "ref/netcore50/de/System.Xml.XmlSerializer.xml",
+        "ref/netcore50/es/System.Xml.XmlSerializer.xml",
+        "ref/netcore50/fr/System.Xml.XmlSerializer.xml",
+        "ref/netcore50/it/System.Xml.XmlSerializer.xml",
+        "ref/netcore50/ja/System.Xml.XmlSerializer.xml",
+        "ref/netcore50/ko/System.Xml.XmlSerializer.xml",
+        "ref/netcore50/ru/System.Xml.XmlSerializer.xml",
+        "ref/netcore50/zh-hans/System.Xml.XmlSerializer.xml",
+        "ref/netcore50/zh-hant/System.Xml.XmlSerializer.xml",
+        "ref/netstandard1.0/System.Xml.XmlSerializer.dll",
+        "ref/netstandard1.0/System.Xml.XmlSerializer.xml",
+        "ref/netstandard1.0/de/System.Xml.XmlSerializer.xml",
+        "ref/netstandard1.0/es/System.Xml.XmlSerializer.xml",
+        "ref/netstandard1.0/fr/System.Xml.XmlSerializer.xml",
+        "ref/netstandard1.0/it/System.Xml.XmlSerializer.xml",
+        "ref/netstandard1.0/ja/System.Xml.XmlSerializer.xml",
+        "ref/netstandard1.0/ko/System.Xml.XmlSerializer.xml",
+        "ref/netstandard1.0/ru/System.Xml.XmlSerializer.xml",
+        "ref/netstandard1.0/zh-hans/System.Xml.XmlSerializer.xml",
+        "ref/netstandard1.0/zh-hant/System.Xml.XmlSerializer.xml",
+        "ref/netstandard1.3/System.Xml.XmlSerializer.dll",
+        "ref/netstandard1.3/System.Xml.XmlSerializer.xml",
+        "ref/netstandard1.3/de/System.Xml.XmlSerializer.xml",
+        "ref/netstandard1.3/es/System.Xml.XmlSerializer.xml",
+        "ref/netstandard1.3/fr/System.Xml.XmlSerializer.xml",
+        "ref/netstandard1.3/it/System.Xml.XmlSerializer.xml",
+        "ref/netstandard1.3/ja/System.Xml.XmlSerializer.xml",
+        "ref/netstandard1.3/ko/System.Xml.XmlSerializer.xml",
+        "ref/netstandard1.3/ru/System.Xml.XmlSerializer.xml",
+        "ref/netstandard1.3/zh-hans/System.Xml.XmlSerializer.xml",
+        "ref/netstandard1.3/zh-hant/System.Xml.XmlSerializer.xml",
+        "ref/portable-net45+win8+wp8+wpa81/_._",
+        "ref/win8/_._",
+        "ref/wp80/_._",
+        "ref/wpa81/_._",
+        "ref/xamarinios10/_._",
+        "ref/xamarinmac20/_._",
+        "ref/xamarintvos10/_._",
+        "ref/xamarinwatchos10/_._",
+        "runtimes/aot/lib/netcore50/System.Xml.XmlSerializer.dll"
+      ]
+    },
+    "MediaBrowser.Common/1.0.0": {
+      "type": "project",
+      "path": "../MediaBrowser.Common/project.json",
+      "msbuildProject": "../MediaBrowser.Common/MediaBrowser.Common.csproj"
+    },
+    "MediaBrowser.Model/1.0.0": {
+      "type": "project",
+      "path": "../MediaBrowser.Model/project.json",
+      "msbuildProject": "../MediaBrowser.Model/MediaBrowser.Model.csproj"
+    }
+  },
+  "projectFileDependencyGroups": {
+    "": [],
+    ".NETFramework,Version=v4.6": [
+      "MediaBrowser.Common",
+      "MediaBrowser.Model",
+      "System.Collections >= 4.0.0",
+      "System.IO >= 4.0.0",
+      "System.Net >= 4.0.0",
+      "System.Net.Http >= 4.0.0",
+      "System.Net.Http.WebRequest >= 4.0.0",
+      "System.Net.Primitives >= 4.0.0",
+      "System.Runtime >= 4.0.0",
+      "System.Text.Encoding >= 4.0.0",
+      "System.Threading >= 4.0.0",
+      "System.Threading.Tasks >= 4.0.0",
+      "System.Xml >= 4.0.0",
+      "System.Xml.Serialization >= 4.0.0"
+    ],
+    ".NETStandard,Version=v1.6": [
+      "MediaBrowser.Common",
+      "MediaBrowser.Model",
+      "NETStandard.Library >= 1.6.0",
+      "System.Net.Requests >= 4.0.11",
+      "System.Xml.XmlSerializer >= 4.0.11"
+    ]
+  },
+  "tools": {},
+  "projectFileToolGroups": {}
+}

+ 7 - 19
MediaBrowser.Common.Implementations/BaseApplicationHost.cs

@@ -3,7 +3,6 @@ using MediaBrowser.Common.Events;
 using MediaBrowser.Common.Implementations.Devices;
 using MediaBrowser.Common.Implementations.IO;
 using MediaBrowser.Common.Implementations.ScheduledTasks;
-using MediaBrowser.Common.Implementations.Security;
 using MediaBrowser.Common.Implementations.Serialization;
 using MediaBrowser.Common.Implementations.Updates;
 using MediaBrowser.Common.Net;
@@ -31,6 +30,7 @@ using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.Implementations.Cryptography;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Model.Cryptography;
+using MediaBrowser.Model.System;
 using MediaBrowser.Model.Tasks;
 
 namespace MediaBrowser.Common.Implementations
@@ -121,11 +121,6 @@ namespace MediaBrowser.Common.Implementations
         /// <value>The kernel.</value>
         protected ITaskManager TaskManager { get; private set; }
         /// <summary>
-        /// Gets the security manager.
-        /// </summary>
-        /// <value>The security manager.</value>
-        protected ISecurityManager SecurityManager { get; private set; }
-        /// <summary>
         /// Gets the HTTP client.
         /// </summary>
         /// <value>The HTTP client.</value>
@@ -142,16 +137,12 @@ namespace MediaBrowser.Common.Implementations
         /// <value>The configuration manager.</value>
         protected IConfigurationManager ConfigurationManager { get; private set; }
 
-        /// <summary>
-        /// Gets or sets the installation manager.
-        /// </summary>
-        /// <value>The installation manager.</value>
-        protected IInstallationManager InstallationManager { get; private set; }
-
         protected IFileSystem FileSystemManager { get; private set; }
 
         protected IIsoManager IsoManager { get; private set; }
 
+        protected ISystemEvents SystemEvents { get; private set; }
+
         /// <summary>
         /// Gets the name.
         /// </summary>
@@ -221,6 +212,7 @@ namespace MediaBrowser.Common.Implementations
             JsonSerializer = CreateJsonSerializer();
 
             MemoryStreamProvider = CreateMemoryStreamProvider();
+            SystemEvents = CreateSystemEvents();
 
             OnLoggerLoaded(true);
             LogManager.LoggerLoaded += (s, e) => OnLoggerLoaded(false);
@@ -254,6 +246,7 @@ namespace MediaBrowser.Common.Implementations
         }
 
         protected abstract IMemoryStreamProvider CreateMemoryStreamProvider();
+        protected abstract ISystemEvents CreateSystemEvents();
 
         protected virtual void OnLoggerLoaded(bool isFirstLoad)
         {
@@ -473,11 +466,12 @@ namespace MediaBrowser.Common.Implementations
 
             RegisterSingleInstance<IApplicationPaths>(ApplicationPaths);
 
-            TaskManager = new TaskManager(ApplicationPaths, JsonSerializer, LogManager.GetLogger("TaskManager"), FileSystemManager);
+            TaskManager = new TaskManager(ApplicationPaths, JsonSerializer, LogManager.GetLogger("TaskManager"), FileSystemManager, SystemEvents);
 
             RegisterSingleInstance(JsonSerializer);
             RegisterSingleInstance(XmlSerializer);
             RegisterSingleInstance(MemoryStreamProvider);
+            RegisterSingleInstance(SystemEvents);
 
             RegisterSingleInstance(LogManager);
             RegisterSingleInstance(Logger);
@@ -492,12 +486,6 @@ namespace MediaBrowser.Common.Implementations
             NetworkManager = CreateNetworkManager(LogManager.GetLogger("NetworkManager"));
             RegisterSingleInstance(NetworkManager);
 
-            SecurityManager = new PluginSecurityManager(this, HttpClient, JsonSerializer, ApplicationPaths, LogManager);
-            RegisterSingleInstance(SecurityManager);
-
-            InstallationManager = new InstallationManager(LogManager.GetLogger("InstallationManager"), this, ApplicationPaths, HttpClient, JsonSerializer, SecurityManager, ConfigurationManager, FileSystemManager);
-            RegisterSingleInstance(InstallationManager);
-
             IsoManager = new IsoManager();
             RegisterSingleInstance(IsoManager);
 

+ 6 - 6
MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs

@@ -79,7 +79,7 @@ namespace MediaBrowser.Common.Implementations.Configuration
             get
             {
                 // Lazy load
-                LazyInitializer.EnsureInitialized(ref _configuration, ref _configurationLoaded, ref _configurationSyncLock, () => (BaseApplicationConfiguration)ConfigurationHelper.GetXmlConfiguration(ConfigurationType, CommonApplicationPaths.SystemConfigurationFilePath, XmlSerializer));
+                LazyInitializer.EnsureInitialized(ref _configuration, ref _configurationLoaded, ref _configurationSyncLock, () => (BaseApplicationConfiguration)ConfigurationHelper.GetXmlConfiguration(ConfigurationType, CommonApplicationPaths.SystemConfigurationFilePath, XmlSerializer, FileSystem));
                 return _configuration;
             }
             protected set
@@ -126,7 +126,7 @@ namespace MediaBrowser.Common.Implementations.Configuration
             Logger.Info("Saving system configuration");
             var path = CommonApplicationPaths.SystemConfigurationFilePath;
 
-            Directory.CreateDirectory(Path.GetDirectoryName(path));
+            FileSystem.CreateDirectory(Path.GetDirectoryName(path));
 
             lock (_configurationSyncLock)
             {
@@ -196,9 +196,9 @@ namespace MediaBrowser.Common.Implementations.Configuration
                 && !string.Equals(CommonConfiguration.CachePath ?? string.Empty, newPath))
             {
                 // Validate
-                if (!Directory.Exists(newPath))
+                if (!FileSystem.DirectoryExists(newPath))
                 {
-                    throw new DirectoryNotFoundException(string.Format("{0} does not exist.", newPath));
+                    throw new FileNotFoundException(string.Format("{0} does not exist.", newPath));
                 }
 
                 EnsureWriteAccess(newPath);
@@ -253,7 +253,7 @@ namespace MediaBrowser.Common.Implementations.Configuration
             {
                 return Activator.CreateInstance(configurationType);
             }
-            catch (DirectoryNotFoundException)
+            catch (IOException)
             {
                 return Activator.CreateInstance(configurationType);
             }
@@ -293,7 +293,7 @@ namespace MediaBrowser.Common.Implementations.Configuration
             _configurations.AddOrUpdate(key, configuration, (k, v) => configuration);
 
             var path = GetConfigurationFile(key);
-            Directory.CreateDirectory(Path.GetDirectoryName(path));
+            FileSystem.CreateDirectory(Path.GetDirectoryName(path));
 
             lock (_configurationSyncLock)
             {

+ 5 - 4
MediaBrowser.Common.Implementations/Configuration/ConfigurationHelper.cs

@@ -2,6 +2,7 @@
 using System;
 using System.IO;
 using System.Linq;
+using MediaBrowser.Model.IO;
 
 namespace MediaBrowser.Common.Implementations.Configuration
 {
@@ -18,7 +19,7 @@ namespace MediaBrowser.Common.Implementations.Configuration
         /// <param name="path">The path.</param>
         /// <param name="xmlSerializer">The XML serializer.</param>
         /// <returns>System.Object.</returns>
-        public static object GetXmlConfiguration(Type type, string path, IXmlSerializer xmlSerializer)
+        public static object GetXmlConfiguration(Type type, string path, IXmlSerializer xmlSerializer, IFileSystem fileSystem)
         {
             object configuration;
 
@@ -27,7 +28,7 @@ namespace MediaBrowser.Common.Implementations.Configuration
             // Use try/catch to avoid the extra file system lookup using File.Exists
             try
             {
-				buffer = File.ReadAllBytes(path);
+                buffer = fileSystem.ReadAllBytes(path);
 
                 configuration = xmlSerializer.DeserializeFromBytes(type, buffer);
             }
@@ -46,10 +47,10 @@ namespace MediaBrowser.Common.Implementations.Configuration
                 // If the file didn't exist before, or if something has changed, re-save
                 if (buffer == null || !buffer.SequenceEqual(newBytes))
                 {
-					Directory.CreateDirectory(Path.GetDirectoryName(path));
+                    fileSystem.CreateDirectory(Path.GetDirectoryName(path));
 
                     // Save it after load in case we got new items
-					File.WriteAllBytes(path, newBytes);
+                    fileSystem.WriteAllBytes(path, newBytes);
                 }
 
                 return configuration;

+ 10 - 1
MediaBrowser.Common.Implementations/IO/ManagedFileSystem.cs

@@ -3,7 +3,6 @@ using System.Collections.Generic;
 using System.IO;
 using System.Linq;
 using System.Text;
-using MediaBrowser.Common.IO;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Logging;
 
@@ -660,6 +659,11 @@ namespace MediaBrowser.Common.Implementations.IO
             return File.ReadAllText(path);
         }
 
+        public byte[] ReadAllBytes(string path)
+        {
+            return File.ReadAllBytes(path);
+        }
+
         public void WriteAllText(string path, string text, Encoding encoding)
         {
             File.WriteAllText(path, text, encoding);
@@ -670,6 +674,11 @@ namespace MediaBrowser.Common.Implementations.IO
             File.WriteAllText(path, text);
         }
 
+        public void WriteAllBytes(string path, byte[] bytes)
+        {
+            File.WriteAllBytes(path, bytes);
+        }
+
         public string ReadAllText(string path, Encoding encoding)
         {
             return File.ReadAllText(path, encoding);

+ 0 - 6
MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj

@@ -79,14 +79,8 @@
     <Compile Include="ScheduledTasks\Tasks\DeleteLogFileTask.cs" />
     <Compile Include="ScheduledTasks\Tasks\ReloadLoggerFileTask.cs" />
     <Compile Include="ScheduledTasks\WeeklyTrigger.cs" />
-    <Compile Include="Security\MbAdmin.cs" />
-    <Compile Include="Security\MBLicenseFile.cs" />
-    <Compile Include="Security\PluginSecurityManager.cs" />
-    <Compile Include="Security\RegRecord.cs" />
-    <Compile Include="Security\SuppporterInfoResponse.cs" />
     <Compile Include="Serialization\XmlSerializer.cs" />
     <Compile Include="Updates\GithubUpdater.cs" />
-    <Compile Include="Updates\InstallationManager.cs" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj">

+ 4 - 4
MediaBrowser.Common.Implementations/ScheduledTasks/DailyTrigger.cs

@@ -1,11 +1,11 @@
-using MediaBrowser.Model.Events;
-using MediaBrowser.Model.Tasks;
-using System;
+using System;
 using System.Globalization;
 using System.Threading;
+using MediaBrowser.Model.Events;
 using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Tasks;
 
-namespace MediaBrowser.Common.ScheduledTasks
+namespace MediaBrowser.Common.Implementations.ScheduledTasks
 {
     /// <summary>
     /// Represents a task trigger that fires everyday

+ 4 - 4
MediaBrowser.Common.Implementations/ScheduledTasks/IntervalTrigger.cs

@@ -1,11 +1,11 @@
-using MediaBrowser.Model.Events;
-using MediaBrowser.Model.Tasks;
-using System;
+using System;
 using System.Linq;
 using System.Threading;
+using MediaBrowser.Model.Events;
 using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Tasks;
 
-namespace MediaBrowser.Common.ScheduledTasks
+namespace MediaBrowser.Common.Implementations.ScheduledTasks
 {
     /// <summary>
     /// Represents a task trigger that runs repeatedly on an interval

+ 4 - 4
MediaBrowser.Common.Implementations/ScheduledTasks/StartupTrigger.cs

@@ -1,10 +1,10 @@
-using MediaBrowser.Model.Events;
-using MediaBrowser.Model.Tasks;
-using System;
+using System;
 using System.Threading.Tasks;
+using MediaBrowser.Model.Events;
 using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Tasks;
 
-namespace MediaBrowser.Common.ScheduledTasks
+namespace MediaBrowser.Common.Implementations.ScheduledTasks
 {
     /// <summary>
     /// Class StartupTaskTrigger

+ 7 - 10
MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs

@@ -12,6 +12,7 @@ using System.Linq;
 using System.Threading.Tasks;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Model.IO;
+using MediaBrowser.Model.System;
 using Microsoft.Win32;
 
 namespace MediaBrowser.Common.Implementations.ScheduledTasks
@@ -48,6 +49,8 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
         /// <value>The application paths.</value>
         private IApplicationPaths ApplicationPaths { get; set; }
 
+        private readonly ISystemEvents _systemEvents;
+
         /// <summary>
         /// Gets the logger.
         /// </summary>
@@ -81,29 +84,23 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
         /// <param name="jsonSerializer">The json serializer.</param>
         /// <param name="logger">The logger.</param>
         /// <exception cref="System.ArgumentException">kernel</exception>
-        public TaskManager(IApplicationPaths applicationPaths, IJsonSerializer jsonSerializer, ILogger logger, IFileSystem fileSystem)
+        public TaskManager(IApplicationPaths applicationPaths, IJsonSerializer jsonSerializer, ILogger logger, IFileSystem fileSystem, ISystemEvents systemEvents)
         {
             ApplicationPaths = applicationPaths;
             JsonSerializer = jsonSerializer;
             Logger = logger;
             _fileSystem = fileSystem;
+            _systemEvents = systemEvents;
 
             ScheduledTasks = new IScheduledTaskWorker[] { };
         }
 
         private void BindToSystemEvent()
         {
-            try
-            {
-                SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
-            }
-            catch
-            {
-
-            }
+            _systemEvents.Resume += _systemEvents_Resume;
         }
 
-        void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
+        private void _systemEvents_Resume(object sender, EventArgs e)
         {
             foreach (var task in ScheduledTasks)
             {

+ 1 - 1
MediaBrowser.Common.Implementations/ScheduledTasks/WeeklyTrigger.cs

@@ -4,7 +4,7 @@ using MediaBrowser.Model.Events;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Tasks;
 
-namespace MediaBrowser.Common.ScheduledTasks
+namespace MediaBrowser.Common.Implementations.ScheduledTasks
 {
     /// <summary>
     /// Represents a task trigger that fires on a weekly basis

+ 0 - 13
MediaBrowser.Common.Implementations/Security/MbAdmin.cs

@@ -1,13 +0,0 @@
-
-namespace MediaBrowser.Common.Implementations.Security
-{
-    public class MbAdmin
-    {
-        public const string HttpUrl = "https://www.mb3admin.com/admin/";
-        
-        /// <summary>
-        /// Leaving as http for now until we get it squared away
-        /// </summary>
-        public const string HttpsUrl = "https://www.mb3admin.com/admin/";
-    }
-}

+ 0 - 14
MediaBrowser.Common.Implementations/Security/SuppporterInfoResponse.cs

@@ -1,14 +0,0 @@
-
-namespace MediaBrowser.Common.Implementations.Security
-{
-    internal class SuppporterInfoResponse
-    {
-        public string email { get; set; }
-        public string supporterKey { get; set; }
-        public int totalRegs { get; set; }
-        public int totalMachines { get; set; }
-        public string expDate { get; set; }
-        public string regDate { get; set; }
-        public string planType { get; set; }
-    }
-}

+ 4 - 0
MediaBrowser.Model/IO/IFileSystem.cs

@@ -249,6 +249,10 @@ namespace MediaBrowser.Model.IO
         /// <returns>System.String.</returns>
         string ReadAllText(string path);
 
+        byte[] ReadAllBytes(string path);
+
+        void WriteAllBytes(string path, byte[] bytes);
+
         /// <summary>
         /// Writes all text.
         /// </summary>

+ 1 - 0
MediaBrowser.Model/MediaBrowser.Model.csproj

@@ -408,6 +408,7 @@
     <Compile Include="Sync\SyncQualityOption.cs" />
     <Compile Include="Sync\SyncTarget.cs" />
     <Compile Include="System\Architecture.cs" />
+    <Compile Include="System\ISystemEvents.cs" />
     <Compile Include="System\LogFile.cs" />
     <Compile Include="System\PublicSystemInfo.cs" />
     <Compile Include="Tasks\IConfigurableScheduledTask.cs" />

+ 10 - 0
MediaBrowser.Model/System/ISystemEvents.cs

@@ -0,0 +1,10 @@
+using System;
+
+namespace MediaBrowser.Model.System
+{
+    public interface ISystemEvents
+    {
+        event EventHandler Resume;
+        event EventHandler Suspend;
+    }
+}

+ 4 - 0
MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj

@@ -287,6 +287,9 @@
     <Compile Include="Persistence\IDbConnector.cs" />
     <Compile Include="Persistence\MediaStreamColumns.cs" />
     <Compile Include="Reflection\AssemblyInfo.cs" />
+    <Compile Include="Security\MBLicenseFile.cs" />
+    <Compile Include="Security\PluginSecurityManager.cs" />
+    <Compile Include="Security\RegRecord.cs" />
     <Compile Include="Serialization\JsonSerializer.cs" />
     <Compile Include="Social\SharingManager.cs" />
     <Compile Include="Social\SharingRepository.cs" />
@@ -296,6 +299,7 @@
     <Compile Include="Sync\SyncNotificationEntryPoint.cs" />
     <Compile Include="Threading\PeriodicTimer.cs" />
     <Compile Include="TV\SeriesPostScanTask.cs" />
+    <Compile Include="Updates\InstallationManager.cs" />
     <Compile Include="UserViews\CollectionFolderImageProvider.cs" />
     <Compile Include="UserViews\DynamicImageProvider.cs" />
     <Compile Include="News\NewsEntryPoint.cs" />

+ 3 - 3
MediaBrowser.Common.Implementations/Security/MBLicenseFile.cs → MediaBrowser.Server.Implementations/Security/MBLicenseFile.cs

@@ -1,5 +1,4 @@
-using MediaBrowser.Common.Configuration;
-using System;
+using System;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.Globalization;
@@ -7,8 +6,9 @@ using System.IO;
 using System.Linq;
 using System.Security.Cryptography;
 using System.Text;
+using MediaBrowser.Common.Configuration;
 
-namespace MediaBrowser.Common.Implementations.Security
+namespace MediaBrowser.Server.Implementations.Security
 {
     internal class MBLicenseFile
     {

+ 19 - 14
MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs → MediaBrowser.Server.Implementations/Security/PluginSecurityManager.cs

@@ -1,26 +1,29 @@
-using System.IO;
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Common.Security;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Logging;
-using MediaBrowser.Model.Serialization;
-using System;
+using System;
 using System.Collections.Generic;
+using System.IO;
 using System.Linq;
 using System.Net;
 using System.Threading;
 using System.Threading.Tasks;
+using MediaBrowser.Common;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Common.Security;
+using MediaBrowser.Controller;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Net;
+using MediaBrowser.Model.Serialization;
 
-namespace MediaBrowser.Common.Implementations.Security
+namespace MediaBrowser.Server.Implementations.Security
 {
     /// <summary>
     /// Class PluginSecurityManager
     /// </summary>
     public class PluginSecurityManager : ISecurityManager
     {
-        private const string MBValidateUrl = MbAdmin.HttpsUrl + "service/registration/validate";
+        private const string MBValidateUrl = "https://mb3admin.com/admin/service/registration/validate";
         private const string AppstoreRegUrl = /*MbAdmin.HttpsUrl*/ "https://mb3admin.com/admin/service/appstore/register";
 
         /// <summary>
@@ -57,9 +60,10 @@ namespace MediaBrowser.Common.Implementations.Security
 
         private readonly IHttpClient _httpClient;
         private readonly IJsonSerializer _jsonSerializer;
-        private readonly IApplicationHost _appHost;
+        private readonly IServerApplicationHost _appHost;
         private readonly ILogger _logger;
         private readonly IApplicationPaths _appPaths;
+        private readonly IFileSystem _fileSystem;
 
         private IEnumerable<IRequiresRegistration> _registeredEntities;
         protected IEnumerable<IRequiresRegistration> RegisteredEntities
@@ -73,8 +77,8 @@ namespace MediaBrowser.Common.Implementations.Security
         /// <summary>
         /// Initializes a new instance of the <see cref="PluginSecurityManager" /> class.
         /// </summary>
-        public PluginSecurityManager(IApplicationHost appHost, IHttpClient httpClient, IJsonSerializer jsonSerializer,
-            IApplicationPaths appPaths, ILogManager logManager)
+        public PluginSecurityManager(IServerApplicationHost appHost, IHttpClient httpClient, IJsonSerializer jsonSerializer,
+            IApplicationPaths appPaths, ILogManager logManager, IFileSystem fileSystem)
         {
             if (httpClient == null)
             {
@@ -85,6 +89,7 @@ namespace MediaBrowser.Common.Implementations.Security
             _httpClient = httpClient;
             _jsonSerializer = jsonSerializer;
             _appPaths = appPaths;
+            _fileSystem = fileSystem;
             _logger = logManager.GetLogger("SecurityManager");
         }
 
@@ -226,7 +231,7 @@ namespace MediaBrowser.Common.Implementations.Security
 
             try
             {
-                File.WriteAllText(Path.Combine(_appPaths.ProgramDataPath, "apptrans-error.txt"), info);
+                _fileSystem.WriteAllText(Path.Combine(_appPaths.ProgramDataPath, "apptrans-error.txt"), info);
             }
             catch (IOException)
             {

+ 1 - 1
MediaBrowser.Common.Implementations/Security/RegRecord.cs → MediaBrowser.Server.Implementations/Security/RegRecord.cs

@@ -1,6 +1,6 @@
 using System;
 
-namespace MediaBrowser.Common.Implementations.Security
+namespace MediaBrowser.Server.Implementations.Security
 {
     class RegRecord
     {

+ 15 - 16
MediaBrowser.Common.Implementations/Updates/InstallationManager.cs → MediaBrowser.Server.Implementations/Updates/InstallationManager.cs

@@ -1,27 +1,26 @@
-using MediaBrowser.Common.Configuration;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Common;
+using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.Events;
-using MediaBrowser.Common.Implementations.Security;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Common.Plugins;
 using MediaBrowser.Common.Progress;
 using MediaBrowser.Common.Security;
 using MediaBrowser.Common.Updates;
 using MediaBrowser.Model.Events;
+using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Serialization;
 using MediaBrowser.Model.Updates;
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Security.Cryptography;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Common.IO;
-using MediaBrowser.Model.IO;
 
-namespace MediaBrowser.Common.Implementations.Updates
+namespace MediaBrowser.Server.Implementations.Updates
 {
     /// <summary>
     /// Manages all install, uninstall and update operations (both plugins and system)
@@ -164,7 +163,7 @@ namespace MediaBrowser.Common.Implementations.Updates
 
             if (withRegistration)
             {
-                using (var json = await _httpClient.Post(MbAdmin.HttpsUrl + "service/package/retrieveall", data, cancellationToken).ConfigureAwait(false))
+                using (var json = await _httpClient.Post("https://www.mb3admin.com/admin/service/package/retrieveall", data, cancellationToken).ConfigureAwait(false))
                 {
                     cancellationToken.ThrowIfCancellationRequested();
 
@@ -237,7 +236,7 @@ namespace MediaBrowser.Common.Implementations.Updates
 
                 var tempFile = await _httpClient.GetTempFile(new HttpRequestOptions
                 {
-                    Url = MbAdmin.HttpUrl + "service/MB3Packages.json",
+                    Url = "https://www.mb3admin.com/admin/service/MB3Packages.json",
                     CancellationToken = cancellationToken,
                     Progress = new Progress<Double>()
 
@@ -619,7 +618,7 @@ namespace MediaBrowser.Common.Implementations.Updates
                 //If it is an archive - write out a version file so we know what it is
                 if (isArchive)
                 {
-                    File.WriteAllText(target + ".ver", package.versionStr);
+                    _fileSystem.WriteAllText(target + ".ver", package.versionStr);
                 }
             }
             catch (IOException e)

+ 1 - 1
MediaBrowser.Server.Mono/Program.cs

@@ -72,7 +72,7 @@ namespace MediaBrowser.Server.Mono
 
         private static void RunApplication(ServerApplicationPaths appPaths, ILogManager logManager, StartupOptions options)
         {
-            SystemEvents.SessionEnding += SystemEvents_SessionEnding;
+            Microsoft.Win32.SystemEvents.SessionEnding += SystemEvents_SessionEnding;
 
             // Allow all https requests
             ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; });

+ 25 - 1
MediaBrowser.Server.Startup.Common/ApplicationHost.cs

@@ -104,6 +104,8 @@ using MediaBrowser.Common.Implementations.Serialization;
 using MediaBrowser.Common.Implementations.Updates;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Common.Plugins;
+using MediaBrowser.Common.Security;
+using MediaBrowser.Common.Updates;
 using MediaBrowser.Controller.Entities.Audio;
 using MediaBrowser.Controller.Entities.Movies;
 using MediaBrowser.Controller.Entities.TV;
@@ -120,6 +122,7 @@ using MediaBrowser.Model.Xml;
 using MediaBrowser.Server.Implementations.Archiving;
 using MediaBrowser.Server.Implementations.Reflection;
 using MediaBrowser.Server.Implementations.Serialization;
+using MediaBrowser.Server.Implementations.Updates;
 using MediaBrowser.Server.Implementations.Xml;
 using OpenSubtitlesHandler;
 using ServiceStack;
@@ -226,6 +229,17 @@ namespace MediaBrowser.Server.Startup.Common
         private IMediaSourceManager MediaSourceManager { get; set; }
         private IPlaylistManager PlaylistManager { get; set; }
 
+        /// <summary>
+        /// Gets or sets the installation manager.
+        /// </summary>
+        /// <value>The installation manager.</value>
+        protected IInstallationManager InstallationManager { get; private set; }
+        /// <summary>
+        /// Gets the security manager.
+        /// </summary>
+        /// <value>The security manager.</value>
+        protected ISecurityManager SecurityManager { get; private set; }
+
         /// <summary>
         /// Gets or sets the zip client.
         /// </summary>
@@ -405,6 +419,11 @@ namespace MediaBrowser.Server.Startup.Common
             return new MemoryStreamProvider();
         }
 
+        protected override ISystemEvents CreateSystemEvents()
+        {
+            return new SystemEvents(LogManager.GetLogger("SystemEvents"));
+        }
+
         protected override IJsonSerializer CreateJsonSerializer()
         {
             try
@@ -636,7 +655,6 @@ namespace MediaBrowser.Server.Startup.Common
         {
             var migrations = new List<IVersionMigration>
             {
-                new MovieDbEpisodeProviderMigration(ServerConfigurationManager),
                 new DbMigration(ServerConfigurationManager, TaskManager)
             };
 
@@ -660,6 +678,12 @@ namespace MediaBrowser.Server.Startup.Common
         {
             await base.RegisterResources(progress).ConfigureAwait(false);
 
+            SecurityManager = new PluginSecurityManager(this, HttpClient, JsonSerializer, ApplicationPaths, LogManager, FileSystemManager);
+            RegisterSingleInstance(SecurityManager);
+
+            InstallationManager = new InstallationManager(LogManager.GetLogger("InstallationManager"), this, ApplicationPaths, HttpClient, JsonSerializer, SecurityManager, ConfigurationManager, FileSystemManager);
+            RegisterSingleInstance(InstallationManager);
+
             ZipClient = new ZipClient(FileSystemManager);
             RegisterSingleInstance(ZipClient);
 

+ 1 - 1
MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj

@@ -77,11 +77,11 @@
     <Compile Include="MbLinkShortcutHandler.cs" />
     <Compile Include="Migrations\IVersionMigration.cs" />
     <Compile Include="Migrations\DbMigration.cs" />
-    <Compile Include="Migrations\MovieDbEpisodeProviderMigration.cs" />
     <Compile Include="Migrations\UpdateLevelMigration.cs" />
     <Compile Include="NativeEnvironment.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="StartupOptions.cs" />
+    <Compile Include="SystemEvents.cs" />
     <Compile Include="UnhandledExceptionWriter.cs" />
   </ItemGroup>
   <ItemGroup>

+ 0 - 44
MediaBrowser.Server.Startup.Common/Migrations/MovieDbEpisodeProviderMigration.cs

@@ -1,44 +0,0 @@
-using MediaBrowser.Controller.Configuration;
-using System.Linq;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Server.Startup.Common.Migrations
-{
-    class MovieDbEpisodeProviderMigration : IVersionMigration
-    {
-        private readonly IServerConfigurationManager _config;
-        private const string _providerName = "TheMovieDb";
-
-        public MovieDbEpisodeProviderMigration(IServerConfigurationManager config)
-        {
-            _config = config;
-        }
-
-        public async Task Run()
-        {
-            var migrationKey = this.GetType().FullName;
-            var migrationKeyList = _config.Configuration.Migrations.ToList();
-
-            if (!migrationKeyList.Contains(migrationKey))
-            {
-                foreach (var metaDataOption in _config.Configuration.MetadataOptions)
-                {
-                    if (metaDataOption.ItemType == "Episode")
-                    {
-                        var disabledFetchers = metaDataOption.DisabledMetadataFetchers.ToList();
-                        if (!disabledFetchers.Contains(_providerName))
-                        {
-                            disabledFetchers.Add(_providerName);
-                            metaDataOption.DisabledMetadataFetchers = disabledFetchers.ToArray();
-                        }
-                    }
-                }
-
-                migrationKeyList.Add(migrationKey);
-                _config.Configuration.Migrations = migrationKeyList.ToArray();
-                _config.SaveConfiguration();
-            }
-
-        }
-    }
-}

+ 34 - 0
MediaBrowser.Server.Startup.Common/SystemEvents.cs

@@ -0,0 +1,34 @@
+using System;
+using MediaBrowser.Common.Events;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.System;
+
+namespace MediaBrowser.Server.Startup.Common
+{
+    public class SystemEvents : ISystemEvents
+    {
+        public event EventHandler Resume;
+        public event EventHandler Suspend;
+
+        private readonly ILogger _logger;
+
+        public SystemEvents(ILogger logger)
+        {
+            _logger = logger;
+            Microsoft.Win32.SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
+        }
+
+        private void SystemEvents_PowerModeChanged(object sender, Microsoft.Win32.PowerModeChangedEventArgs e)
+        {
+            switch (e.Mode)
+            {
+                case Microsoft.Win32.PowerModes.Resume:
+                    EventHelper.FireEventIfNotNull(Resume, this, EventArgs.Empty, _logger);
+                    break;
+                case Microsoft.Win32.PowerModes.Suspend:
+                    EventHelper.FireEventIfNotNull(Suspend, this, EventArgs.Empty, _logger);
+                    break;
+            }
+        }
+    }
+}

+ 2 - 2
MediaBrowser.ServerApplication/MainStartup.cs

@@ -351,8 +351,8 @@ namespace MediaBrowser.ServerApplication
                 task = InstallVcredist2013IfNeeded(_appHost, _logger);
                 Task.WaitAll(task);
 
-                SystemEvents.SessionEnding += SystemEvents_SessionEnding;
-                SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
+                Microsoft.Win32.SystemEvents.SessionEnding += SystemEvents_SessionEnding;
+                Microsoft.Win32.SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
 
                 HideSplashScreen();