| 
														
															@@ -1,8 +1,10 @@ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 #nullable enable 
														 | 
														
														 | 
														
															 #nullable enable 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 using System; 
														 | 
														
														 | 
														
															 using System; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 using System.Collections.Generic; 
														 | 
														
														 | 
														
															 using System.Collections.Generic; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 using System.IO; 
														 | 
														
														 | 
														
															 using System.IO; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 using System.Linq; 
														 | 
														
														 | 
														
															 using System.Linq; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+using System.Net.Http; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 using System.Reflection; 
														 | 
														
														 | 
														
															 using System.Reflection; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 using System.Text; 
														 | 
														
														 | 
														
															 using System.Text; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 using System.Text.Json; 
														 | 
														
														 | 
														
															 using System.Text.Json; 
														 | 
													
												
											
										
											
												
													
														 | 
														
															@@ -11,9 +13,11 @@ using MediaBrowser.Common; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 using MediaBrowser.Common.Extensions; 
														 | 
														
														 | 
														
															 using MediaBrowser.Common.Extensions; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 using MediaBrowser.Common.Json; 
														 | 
														
														 | 
														
															 using MediaBrowser.Common.Json; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 using MediaBrowser.Common.Json.Converters; 
														 | 
														
														 | 
														
															 using MediaBrowser.Common.Json.Converters; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+using MediaBrowser.Common.Net; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 using MediaBrowser.Common.Plugins; 
														 | 
														
														 | 
														
															 using MediaBrowser.Common.Plugins; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 using MediaBrowser.Model.Configuration; 
														 | 
														
														 | 
														
															 using MediaBrowser.Model.Configuration; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 using MediaBrowser.Model.Plugins; 
														 | 
														
														 | 
														
															 using MediaBrowser.Model.Plugins; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+using MediaBrowser.Model.Updates; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 using Microsoft.Extensions.DependencyInjection; 
														 | 
														
														 | 
														
															 using Microsoft.Extensions.DependencyInjection; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 using Microsoft.Extensions.Logging; 
														 | 
														
														 | 
														
															 using Microsoft.Extensions.Logging; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
										
											
												
													
														 | 
														
															@@ -33,6 +37,21 @@ namespace Emby.Server.Implementations.Plugins 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         private readonly IList<LocalPlugin> _plugins; 
														 | 
														
														 | 
														
															         private readonly IList<LocalPlugin> _plugins; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         private readonly Version _minimumVersion; 
														 | 
														
														 | 
														
															         private readonly Version _minimumVersion; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        private IHttpClientFactory? _httpClientFactory; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        private IHttpClientFactory HttpClientFactory 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        { 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            get 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            { 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                if (_httpClientFactory == null) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                { 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                    _httpClientFactory = _appHost.Resolve<IHttpClientFactory>(); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                } 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                return _httpClientFactory; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            } 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        } 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         /// <summary> 
														 | 
														
														 | 
														
															         /// <summary> 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         /// Initializes a new instance of the <see cref="PluginManager"/> class. 
														 | 
														
														 | 
														
															         /// Initializes a new instance of the <see cref="PluginManager"/> class. 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         /// </summary> 
														 | 
														
														 | 
														
															         /// </summary> 
														 | 
													
												
											
										
											
												
													
														 | 
														
															@@ -332,32 +351,74 @@ namespace Emby.Server.Implementations.Plugins 
														 | 
													
												
											
												
													
														| 
														 | 
														
															             ChangePluginState(plugin, PluginStatus.Malfunctioned); 
														 | 
														
														 | 
														
															             ChangePluginState(plugin, PluginStatus.Malfunctioned); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         } 
														 | 
														
														 | 
														
															         } 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        /// <summary> 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        /// Saves the manifest back to disk. 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        /// </summary> 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        /// <param name="manifest">The <see cref="PluginManifest"/> to save.</param> 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        /// <param name="path">The path where to save the manifest.</param> 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        /// <returns>True if successful.</returns> 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        /// <inheritdoc/> 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         public bool SaveManifest(PluginManifest manifest, string path) 
														 | 
														
														 | 
														
															         public bool SaveManifest(PluginManifest manifest, string path) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         { 
														 | 
														
														 | 
														
															         { 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-            if (manifest == null) 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-            { 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-                return false; 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-            } 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															- 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															             try 
														 | 
														
														 | 
														
															             try 
														 | 
													
												
											
												
													
														| 
														 | 
														
															             { 
														 | 
														
														 | 
														
															             { 
														 | 
													
												
											
												
													
														| 
														 | 
														
															                 var data = JsonSerializer.Serialize(manifest, _jsonOptions); 
														 | 
														
														 | 
														
															                 var data = JsonSerializer.Serialize(manifest, _jsonOptions); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															                 File.WriteAllText(Path.Combine(path, "meta.json"), data); 
														 | 
														
														 | 
														
															                 File.WriteAllText(Path.Combine(path, "meta.json"), data); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															                 return true; 
														 | 
														
														 | 
														
															                 return true; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															             } 
														 | 
														
														 | 
														
															             } 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-#pragma warning disable CA1031 // Do not catch general exception types 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-            catch (Exception e) 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-#pragma warning restore CA1031 // Do not catch general exception types 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            catch (ArgumentException e) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            { 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                _logger.LogWarning(e, "Unable to save plugin manifest due to invalid value. {Path}", path); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                return false; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            } 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        } 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        /// <inheritdoc/> 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        public async Task<bool> GenerateManifest(PackageInfo packageInfo, Version version, string path) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        { 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            if (packageInfo == null) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															             { 
														 | 
														
														 | 
														
															             { 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-                _logger.LogWarning(e, "Unable to save plugin manifest. {Path}", path); 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															                 return false; 
														 | 
														
														 | 
														
															                 return false; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															             } 
														 | 
														
														 | 
														
															             } 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            var versionInfo = packageInfo.Versions.First(v => v.Version == version.ToString()); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            var imagePath = string.Empty; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            if (!string.IsNullOrEmpty(packageInfo.ImageUrl)) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            { 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                var url = new Uri(packageInfo.ImageUrl); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                imagePath = Path.Join(path, url.Segments[^1]); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                await using var fileStream = File.OpenWrite(imagePath); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                try 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                { 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                    await using var downloadStream = await HttpClientFactory 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                        .CreateClient(NamedClient.Default) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                        .GetStreamAsync(url) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                        .ConfigureAwait(false); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                    await downloadStream.CopyToAsync(fileStream).ConfigureAwait(false); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                } 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                catch (HttpRequestException ex) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                { 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                    _logger.LogError(ex, "Failed to download image to path {Path} on disk.", imagePath); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                    imagePath = string.Empty; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                } 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            } 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            var manifest = new PluginManifest 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            { 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                Category = packageInfo.Category, 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                Changelog = versionInfo.Changelog ?? string.Empty, 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                Description = packageInfo.Description, 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                Id = new Guid(packageInfo.Id), 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                Name = packageInfo.Name, 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                Overview = packageInfo.Overview, 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                Owner = packageInfo.Owner, 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                TargetAbi = versionInfo.TargetAbi ?? string.Empty, 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                Timestamp = string.IsNullOrEmpty(versionInfo.Timestamp) ? DateTime.MinValue : DateTime.Parse(versionInfo.Timestamp), 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                Version = versionInfo.Version, 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                Status = PluginStatus.Active, 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                AutoUpdate = true, 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                ImagePath = imagePath 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            }; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            return SaveManifest(manifest, path); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         } 
														 | 
														
														 | 
														
															         } 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															         /// <summary> 
														 | 
														
														 | 
														
															         /// <summary> 
														 | 
													
												
											
										
											
												
													
														 | 
														
															@@ -410,7 +471,7 @@ namespace Emby.Server.Implementations.Plugins 
														 | 
													
												
											
												
													
														| 
														 | 
														
															                 if (plugin == null) 
														 | 
														
														 | 
														
															                 if (plugin == null) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															                 { 
														 | 
														
														 | 
														
															                 { 
														 | 
													
												
											
												
													
														| 
														 | 
														
															                     // Create a dummy record for the providers. 
														 | 
														
														 | 
														
															                     // Create a dummy record for the providers. 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-                    // TODO: remove this code, if all provided have been released as separate plugins. 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                    // TODO: remove this code once all provided have been released as separate plugins. 
														 | 
													
												
											
												
													
														| 
														 | 
														
															                     plugin = new LocalPlugin( 
														 | 
														
														 | 
														
															                     plugin = new LocalPlugin( 
														 | 
													
												
											
												
													
														| 
														 | 
														
															                         instance.AssemblyFilePath, 
														 | 
														
														 | 
														
															                         instance.AssemblyFilePath, 
														 | 
													
												
											
												
													
														| 
														 | 
														
															                         true, 
														 | 
														
														 | 
														
															                         true, 
														 |