From f27477da26097ab4cca22c64e5f236150975ff47 Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Sat, 30 Mar 2019 15:47:34 -0400 Subject: [PATCH 01/35] Bump version to 10.3.0 and update submodule --- MediaBrowser.WebDashboard/jellyfin-web | 2 +- SharedVersion.cs | 4 ++-- build.yaml | 2 +- deployment/debian-package-x64/pkg-src/changelog | 6 ++++++ deployment/fedora-package-x64/pkg-src/jellyfin.spec | 4 +++- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/MediaBrowser.WebDashboard/jellyfin-web b/MediaBrowser.WebDashboard/jellyfin-web index ec5a3b6e5e..9677981344 160000 --- a/MediaBrowser.WebDashboard/jellyfin-web +++ b/MediaBrowser.WebDashboard/jellyfin-web @@ -1 +1 @@ -Subproject commit ec5a3b6e5efb6041153b92818aee562f20ee994d +Subproject commit 9677981344e57e8f84ca664cad13da1f89f4254f diff --git a/SharedVersion.cs b/SharedVersion.cs index 785ba93018..3a0263bd67 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; -[assembly: AssemblyVersion("10.2.2")] -[assembly: AssemblyFileVersion("10.2.2")] +[assembly: AssemblyVersion("10.3.0")] +[assembly: AssemblyFileVersion("10.3.0")] diff --git a/build.yaml b/build.yaml index 289c1caddc..34d356dacf 100644 --- a/build.yaml +++ b/build.yaml @@ -1,7 +1,7 @@ --- # We just wrap `build` so this is really it name: "jellyfin" -version: "10.2.2" +version: "10.3.0-rc1" packages: - debian-package-x64 - debian-package-armhf diff --git a/deployment/debian-package-x64/pkg-src/changelog b/deployment/debian-package-x64/pkg-src/changelog index 349e8787f6..da9151af1a 100644 --- a/deployment/debian-package-x64/pkg-src/changelog +++ b/deployment/debian-package-x64/pkg-src/changelog @@ -1,3 +1,9 @@ +jellyfin (10.3.0~rc1) unstable; urgency=medium + + * New upstream version 10.3.0-rc1; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.3.0-rc1 + + -- Jellyfin Packaging Team Sat, 30 Mar 2019 15:47:24 -0400 + jellyfin (10.2.2-1) unstable; urgency=medium * jellyfin: diff --git a/deployment/fedora-package-x64/pkg-src/jellyfin.spec b/deployment/fedora-package-x64/pkg-src/jellyfin.spec index e24bd2fcb1..77c291c872 100644 --- a/deployment/fedora-package-x64/pkg-src/jellyfin.spec +++ b/deployment/fedora-package-x64/pkg-src/jellyfin.spec @@ -7,7 +7,7 @@ %endif Name: jellyfin -Version: 10.2.2 +Version: 10.3.0 Release: 1%{?dist} Summary: The Free Software Media Browser License: GPLv2 @@ -140,6 +140,8 @@ fi %systemd_postun_with_restart jellyfin.service %changelog +* Sat Mar 30 2019 Jellyfin Packaging Team +- New upstream version 10.3.0-rc1; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.3.0-rc1 * Thu Feb 28 2019 Jellyfin Packaging Team - jellyfin: - PR968 Release 10.2.z copr autobuild From e37ccd6ec0c5ac58cc2cc39e53cd7fb268ad04de Mon Sep 17 00:00:00 2001 From: LogicalPhallacy <44458166+LogicalPhallacy@users.noreply.github.com> Date: Sun, 31 Mar 2019 10:32:56 -0700 Subject: [PATCH 02/35] Updates windows installer default lib location You can use the emby import to move an existing library this way. --- deployment/windows/install-jellyfin.ps1 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/deployment/windows/install-jellyfin.ps1 b/deployment/windows/install-jellyfin.ps1 index b6e00e0568..689dedb4a9 100644 --- a/deployment/windows/install-jellyfin.ps1 +++ b/deployment/windows/install-jellyfin.ps1 @@ -58,7 +58,7 @@ function Elevate-Window { if($Quiet.IsPresent -or $Quiet -eq $true){ if([string]::IsNullOrEmpty($JellyfinLibraryLocation)){ - $Script:JellyfinDataDir = "$env:AppData\jellyfin\" + $Script:JellyfinDataDir = "$env:LOCALAPPDATA\jellyfin\" }else{ $Script:JellyfinDataDir = $JellyfinLibraryLocation } @@ -82,7 +82,7 @@ if($Quiet.IsPresent -or $Quiet -eq $true){ }else{ $Script:InstallServiceAsUser = $true $Script:UserCredentials = $ServiceUser - $Script:JellyfinDataDir = "C:\Users\$($Script:UserCredentials.UserName)\Appdata\Roaming\jellyfin\"} + $Script:JellyfinDataDir = "$env:HOMEDRIVE\Users\$($Script:UserCredentials.UserName)\Appdata\Roaming\jellyfin\"} if($CreateDesktopShorcut.IsPresent -or $CreateDesktopShorcut -eq $true) {$Script:CreateShortcut = $true}else{$Script:CreateShortcut = $false} if($MigrateEmbyLibrary.IsPresent -or $MigrateEmbyLibrary -eq $true){$Script:MigrateLibrary = $true}else{$Script:MigrateLibrary = $false} if($LaunchJellyfin.IsPresent -or $LaunchJellyfin -eq $true){$Script:StartJellyfin = $true}else{$Script:StartJellyfin = $false} @@ -131,7 +131,7 @@ if($Quiet.IsPresent -or $Quiet -eq $true){ Add-Type -AssemblyName System.Windows.Forms [System.Windows.Forms.Application]::EnableVisualStyles() -$Script:JellyFinDataDir = "$env:AppData\jellyfin\" +$Script:JellyFinDataDir = "$env:LOCALAPPDATA\jellyfin\" $Script:DefaultJellyfinInstallDirectory = "$env:Appdata\jellyfin\" $Script:defaultEmbyDataDir = "$env:Appdata\Emby-Server\" $Script:InstallAsService = $False @@ -392,7 +392,7 @@ $ServiceUserBox.DropDownStyle = [System.Windows.Forms.ComboBoxStyle]::DropDow $GUIElementsCollection += $ServiceUserBox $MigrateLibraryCheck = New-Object system.Windows.Forms.CheckBox -$MigrateLibraryCheck.text = "Import Emby Library" +$MigrateLibraryCheck.text = "Import Emby/Old JF Library" $MigrateLibraryCheck.AutoSize = $false $MigrateLibraryCheck.width = 160 $MigrateLibraryCheck.height = 20 @@ -401,7 +401,7 @@ $MigrateLibraryCheck.Font = 'Microsoft Sans Serif,10' $GUIElementsCollection += $MigrateLibraryCheck $LibraryMigrationLabel = New-Object system.Windows.Forms.Label -$LibraryMigrationLabel.text = "Emby Library Path" +$LibraryMigrationLabel.text = "Emby/Old JF Library Path" $LibraryMigrationLabel.TextAlign = [System.Drawing.ContentAlignment]::MiddleLeft $LibraryMigrationLabel.AutoSize = $false $LibraryMigrationLabel.width = 120 From 816d8a0216989497f6c43da7b9f64539e63bc5bf Mon Sep 17 00:00:00 2001 From: LogicalPhallacy <44458166+LogicalPhallacy@users.noreply.github.com> Date: Sun, 31 Mar 2019 10:34:49 -0700 Subject: [PATCH 03/35] Update install-jellyfin.ps1 --- deployment/windows/install-jellyfin.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deployment/windows/install-jellyfin.ps1 b/deployment/windows/install-jellyfin.ps1 index 689dedb4a9..0cd7f5236f 100644 --- a/deployment/windows/install-jellyfin.ps1 +++ b/deployment/windows/install-jellyfin.ps1 @@ -82,7 +82,7 @@ if($Quiet.IsPresent -or $Quiet -eq $true){ }else{ $Script:InstallServiceAsUser = $true $Script:UserCredentials = $ServiceUser - $Script:JellyfinDataDir = "$env:HOMEDRIVE\Users\$($Script:UserCredentials.UserName)\Appdata\Roaming\jellyfin\"} + $Script:JellyfinDataDir = "$env:HOMEDRIVE\Users\$($Script:UserCredentials.UserName)\Appdata\Local\jellyfin\"} if($CreateDesktopShorcut.IsPresent -or $CreateDesktopShorcut -eq $true) {$Script:CreateShortcut = $true}else{$Script:CreateShortcut = $false} if($MigrateEmbyLibrary.IsPresent -or $MigrateEmbyLibrary -eq $true){$Script:MigrateLibrary = $true}else{$Script:MigrateLibrary = $false} if($LaunchJellyfin.IsPresent -or $LaunchJellyfin -eq $true){$Script:StartJellyfin = $true}else{$Script:StartJellyfin = $false} From 38fcd31917af1d904ea61de0f90918d44122d2e4 Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Tue, 2 Apr 2019 18:19:19 -0400 Subject: [PATCH 04/35] Search all subdirectories for Plugins This was added in #801 which broke the previous plugin install behaviour. Previously plugins could be loaded from subdirectories but this search was only for the highest level. Change it to search all subdirectories instead to restore the previous behaviour. Also modifies the same option from #934, though I'm not 100% sure if this is needed here. --- Emby.Server.Implementations/ApplicationHost.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 41ca2a1025..dbdf246a2d 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1047,7 +1047,7 @@ namespace Emby.Server.Implementations private async void PluginInstalled(object sender, GenericEventArgs args) { string dir = Path.Combine(ApplicationPaths.PluginsPath, Path.GetFileNameWithoutExtension(args.Argument.targetFilename)); - var types = Directory.EnumerateFiles(dir, "*.dll", SearchOption.TopDirectoryOnly) + var types = Directory.EnumerateFiles(dir, "*.dll", SearchOption.AllDirectories) .Select(x => Assembly.LoadFrom(x)) .SelectMany(x => x.ExportedTypes) .Where(x => x.IsClass && !x.IsAbstract && !x.IsInterface && !x.IsGenericType) @@ -1346,7 +1346,7 @@ namespace Emby.Server.Implementations { if (Directory.Exists(ApplicationPaths.PluginsPath)) { - foreach (var file in Directory.EnumerateFiles(ApplicationPaths.PluginsPath, "*.dll", SearchOption.TopDirectoryOnly)) + foreach (var file in Directory.EnumerateFiles(ApplicationPaths.PluginsPath, "*.dll", SearchOption.AllDirectories)) { Logger.LogInformation("Loading assembly {Path}", file); yield return Assembly.LoadFrom(file); From d75324afc93129e9237607eda3d39248ad9719ec Mon Sep 17 00:00:00 2001 From: Andrew Rabert Date: Wed, 3 Apr 2019 01:21:28 -0400 Subject: [PATCH 05/35] Update Dockerfiles * Use new dotnet image paths * Update jellyfin-web to 10.3.0-rc1 --- Dockerfile | 8 ++++---- Dockerfile.arm | 6 +++--- Dockerfile.arm64 | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5794bdde1e..dbbed535f8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ -ARG DOTNET_VERSION=2 +ARG DOTNET_VERSION=2.2 -FROM microsoft/dotnet:${DOTNET_VERSION}-sdk as builder +FROM mcr.microsoft.com/dotnet/core/sdk:${DOTNET_VERSION} as builder WORKDIR /repo COPY . . ENV DOTNET_CLI_TELEMETRY_OPTOUT=1 @@ -8,7 +8,7 @@ RUN bash -c "source deployment/common.build.sh && \ build_jellyfin Jellyfin.Server Release linux-x64 /jellyfin" FROM jellyfin/ffmpeg as ffmpeg -FROM microsoft/dotnet:${DOTNET_VERSION}-runtime +FROM mcr.microsoft.com/dotnet/core/runtime:${DOTNET_VERSION} # libfontconfig1 is required for Skia RUN apt-get update \ && apt-get install --no-install-recommends --no-install-suggests -y \ @@ -21,7 +21,7 @@ RUN apt-get update \ COPY --from=ffmpeg / / COPY --from=builder /jellyfin /jellyfin -ARG JELLYFIN_WEB_VERSION=10.2.2 +ARG JELLYFIN_WEB_VERSION=10.3.0-rc1 RUN curl -L https://github.com/jellyfin/jellyfin-web/archive/v${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \ && rm -rf /jellyfin/jellyfin-web \ && mv jellyfin-web-${JELLYFIN_WEB_VERSION} /jellyfin/jellyfin-web diff --git a/Dockerfile.arm b/Dockerfile.arm index 1497da0ef7..6bd5b576f1 100644 --- a/Dockerfile.arm +++ b/Dockerfile.arm @@ -8,7 +8,7 @@ FROM alpine as qemu_extract COPY --from=qemu /usr/bin qemu-arm-static.tar.gz RUN tar -xzvf qemu-arm-static.tar.gz -FROM microsoft/dotnet:${DOTNET_VERSION}-sdk-stretch as builder +FROM mcr.microsoft.com/dotnet/core/sdk:${DOTNET_VERSION} as builder WORKDIR /repo COPY . . ENV DOTNET_CLI_TELEMETRY_OPTOUT=1 @@ -21,7 +21,7 @@ RUN bash -c "source deployment/common.build.sh && \ build_jellyfin Jellyfin.Server Release linux-arm /jellyfin" -FROM microsoft/dotnet:${DOTNET_VERSION}-runtime-stretch-slim-arm32v7 +FROM mcr.microsoft.com/dotnet/core/runtime:${DOTNET_VERSION}-stretch-slim-arm32v7 COPY --from=qemu_extract qemu-arm-static /usr/bin RUN apt-get update \ && apt-get install --no-install-recommends --no-install-suggests -y ffmpeg \ @@ -30,7 +30,7 @@ RUN apt-get update \ && chmod 777 /cache /config /media COPY --from=builder /jellyfin /jellyfin -ARG JELLYFIN_WEB_VERSION=10.2.2 +ARG JELLYFIN_WEB_VERSION=10.3.0-rc1 RUN curl -L https://github.com/jellyfin/jellyfin-web/archive/v${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \ && rm -rf /jellyfin/jellyfin-web \ && mv jellyfin-web-${JELLYFIN_WEB_VERSION} /jellyfin/jellyfin-web diff --git a/Dockerfile.arm64 b/Dockerfile.arm64 index f4658a055c..3be2fd4f14 100644 --- a/Dockerfile.arm64 +++ b/Dockerfile.arm64 @@ -9,7 +9,7 @@ COPY --from=qemu /usr/bin qemu-aarch64-static.tar.gz RUN tar -xzvf qemu-aarch64-static.tar.gz -FROM microsoft/dotnet:${DOTNET_VERSION}-sdk-stretch as builder +FROM mcr.microsoft.com/dotnet/core/sdk:${DOTNET_VERSION} as builder WORKDIR /repo COPY . . ENV DOTNET_CLI_TELEMETRY_OPTOUT=1 @@ -22,7 +22,7 @@ RUN bash -c "source deployment/common.build.sh && \ build_jellyfin Jellyfin.Server Release linux-arm64 /jellyfin" -FROM microsoft/dotnet:${DOTNET_VERSION}-runtime-stretch-slim-arm64v8 +FROM mcr.microsoft.com/dotnet/core/runtime:${DOTNET_VERSION}-stretch-slim-arm64v8 COPY --from=qemu_extract qemu-aarch64-static /usr/bin RUN apt-get update \ && apt-get install --no-install-recommends --no-install-suggests -y ffmpeg \ @@ -31,7 +31,7 @@ RUN apt-get update \ && chmod 777 /cache /config /media COPY --from=builder /jellyfin /jellyfin -ARG JELLYFIN_WEB_VERSION=10.2.2 +ARG JELLYFIN_WEB_VERSION=10.3.0-rc1 RUN curl -L https://github.com/jellyfin/jellyfin-web/archive/v${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \ && rm -rf /jellyfin/jellyfin-web \ && mv jellyfin-web-${JELLYFIN_WEB_VERSION} /jellyfin/jellyfin-web From 05a4161fd388d7ecda2f1b4a6ec6d02ee7b4488e Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Wed, 3 Apr 2019 19:43:02 -0400 Subject: [PATCH 06/35] Correct the installation and removal of plugins Upgrading plugins was broken for various reasons. There are four fixes and a minor one: 1. Use a directory name based only on the `Name` of the plugin, not the source filename, which contains the version. Avoids strange duplication of the plugin. 2. Use the new directory name for the deletes if it's present, so that installation and removal happen at that directory level and we don't leave empty folders laying around. Ensures we properly remove additional resources in plugins too, not just the main `.dll` file. 3. Ignore the incoming `target` when installing, and always set it ourself to the proper directory, which would matter when reinstalling. 4. Deletes an existing target directory before installing if it exists. Note that not calling any of the plugin removal code is intentional; I suspect that would delete configurations unexpectedly when upgrading which would be annoying. This way, it just replaces the files and then reloads. 5. (Minor) Added some actual debug messages around the plugin download section so failures can be more accurately seen. --- .../ApplicationHost.cs | 2 +- .../Updates/InstallationManager.cs | 41 ++++++++++++++++--- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index dbdf246a2d..05f8a8a5e7 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1046,7 +1046,7 @@ namespace Emby.Server.Implementations private async void PluginInstalled(object sender, GenericEventArgs args) { - string dir = Path.Combine(ApplicationPaths.PluginsPath, Path.GetFileNameWithoutExtension(args.Argument.targetFilename)); + string dir = Path.Combine(ApplicationPaths.PluginsPath, args.Argument.name); var types = Directory.EnumerateFiles(dir, "*.dll", SearchOption.AllDirectories) .Select(x => Assembly.LoadFrom(x)) .SelectMany(x => x.ExportedTypes) diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 7310de55d4..e5ba813a6c 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -85,9 +85,11 @@ namespace Emby.Server.Implementations.Updates private void OnPluginInstalled(PackageVersionInfo package) { _logger.LogInformation("New plugin installed: {0} {1} {2}", package.name, package.versionStr ?? string.Empty, package.classification); + _logger.LogDebug("{String}", package.name); PluginInstalled?.Invoke(this, new GenericEventArgs { Argument = package }); + _logger.LogDebug("{String}", package.name); _applicationHost.NotifyPendingRestart(); } @@ -518,12 +520,12 @@ namespace Emby.Server.Implementations.Updates return; } - if (target == null) - { - target = Path.Combine(_appPaths.PluginsPath, Path.GetFileNameWithoutExtension(package.targetFilename)); - } + // Always override the passed-in target (which is a file) and figure it out again + target = Path.Combine(_appPaths.PluginsPath, package.name); + _logger.LogDebug("Installing plugin to {Filename}.", target); // Download to temporary file so that, if interrupted, it won't destroy the existing installation + _logger.LogDebug("Downloading ZIP."); var tempFile = await _httpClient.GetTempFile(new HttpRequestOptions { Url = package.sourceUrl, @@ -536,9 +538,17 @@ namespace Emby.Server.Implementations.Updates // TODO: Validate with a checksum, *properly* + // Check if the target directory already exists, and remove it if so + if (Directory.Exists(target)) + { + _logger.LogDebug("Deleting existing plugin at {Filename}.", target); + Directory.Delete(target, true); + } + // Success - move it to the real target try { + _logger.LogDebug("Extracting ZIP {TempFile} to {Filename}.", tempFile, target); using (var stream = File.OpenRead(tempFile)) { _zipClient.ExtractAllFromZip(stream, target, true); @@ -552,6 +562,7 @@ namespace Emby.Server.Implementations.Updates try { + _logger.LogDebug("Deleting temporary file {Filename}.", tempFile); _fileSystem.DeleteFile(tempFile); } catch (IOException ex) @@ -574,7 +585,18 @@ namespace Emby.Server.Implementations.Updates _applicationHost.RemovePlugin(plugin); var path = plugin.AssemblyFilePath; - _logger.LogInformation("Deleting plugin file {0}", path); + bool is_path_directory = false; + // Check if we have a plugin directory we should remove too + if (Path.GetDirectoryName(plugin.AssemblyFilePath) != _appPaths.PluginsPath) + { + path = Path.GetDirectoryName(plugin.AssemblyFilePath); + is_path_directory = true; + _logger.LogInformation("Deleting plugin directory {0}", path); + } + else + { + _logger.LogInformation("Deleting plugin file {0}", path); + } // Make this case-insensitive to account for possible incorrect assembly naming var file = _fileSystem.GetFilePaths(Path.GetDirectoryName(path)) @@ -585,7 +607,14 @@ namespace Emby.Server.Implementations.Updates path = file; } - _fileSystem.DeleteFile(path); + if (is_path_directory) + { + Directory.Delete(path, true); + } + else + { + _fileSystem.DeleteFile(path); + } var list = _config.Configuration.UninstalledPlugins.ToList(); var filename = Path.GetFileName(path); From 608fd873de6118198c2ac882b2859da3d0caff72 Mon Sep 17 00:00:00 2001 From: Andrew Rabert Date: Wed, 3 Apr 2019 22:58:52 -0400 Subject: [PATCH 07/35] Optimize images with image_optim --- Emby.Dlna/Images/logo120.png | Bin 7522 -> 6201 bytes Emby.Dlna/Images/logo240.png | Bin 18287 -> 13339 bytes Emby.Dlna/Images/logo48.png | Bin 2554 -> 2263 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/Emby.Dlna/Images/logo120.png b/Emby.Dlna/Images/logo120.png index 321c4772920b3b5e81c61a63f06d5bb2100514f2..14f6c8d5f66010de7b3f132c554e3ab53d49001e 100644 GIT binary patch literal 6201 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 XU2ajqLA}4W00000NkvXXu0mjfyde4m literal 7522 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 diff --git a/Emby.Dlna/Images/logo240.png b/Emby.Dlna/Images/logo240.png index 64c8281299ec62baed2ba1722ae637783272885a..ff50314d44a8d2b9ae1a23690a95c3983293f8a3 100644 GIT binary patch literal 13339 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 diff --git a/Emby.Dlna/Images/logo48.png b/Emby.Dlna/Images/logo48.png index b8fc145647099cc15f8492378c17ab555d4fb163..d6b5fd1df1adedfbd025b73121436668d98cfd2f 100644 GIT binary patch delta 2252 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 Hu0mjf+c4ez From 09505e0988ec53538c3ecc3d243b1d1a5edac8c6 Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Thu, 4 Apr 2019 01:54:31 -0400 Subject: [PATCH 08/35] Apply review feedback Remove a few superfluous/testing log statements, and print the deletion debug messages when it occurs rather than earlier. Use a nicer name for the isDirectory variable. --- .../Updates/InstallationManager.cs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index e5ba813a6c..95fbefe00a 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -85,11 +85,9 @@ namespace Emby.Server.Implementations.Updates private void OnPluginInstalled(PackageVersionInfo package) { _logger.LogInformation("New plugin installed: {0} {1} {2}", package.name, package.versionStr ?? string.Empty, package.classification); - _logger.LogDebug("{String}", package.name); PluginInstalled?.Invoke(this, new GenericEventArgs { Argument = package }); - _logger.LogDebug("{String}", package.name); _applicationHost.NotifyPendingRestart(); } @@ -585,17 +583,12 @@ namespace Emby.Server.Implementations.Updates _applicationHost.RemovePlugin(plugin); var path = plugin.AssemblyFilePath; - bool is_path_directory = false; + bool isDirectory = false; // Check if we have a plugin directory we should remove too if (Path.GetDirectoryName(plugin.AssemblyFilePath) != _appPaths.PluginsPath) { path = Path.GetDirectoryName(plugin.AssemblyFilePath); - is_path_directory = true; - _logger.LogInformation("Deleting plugin directory {0}", path); - } - else - { - _logger.LogInformation("Deleting plugin file {0}", path); + isDirectory = true; } // Make this case-insensitive to account for possible incorrect assembly naming @@ -607,12 +600,14 @@ namespace Emby.Server.Implementations.Updates path = file; } - if (is_path_directory) + if (isDirectory) { + _logger.LogInformation("Deleting plugin directory {0}", path); Directory.Delete(path, true); } else { + _logger.LogInformation("Deleting plugin file {0}", path); _fileSystem.DeleteFile(path); } From 754e76a61bbf4bbda5a4a1073737c07bf28f5f3a Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Thu, 4 Apr 2019 02:34:23 -0400 Subject: [PATCH 09/35] Add TODO to remove string target --- Emby.Server.Implementations/Updates/InstallationManager.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 95fbefe00a..6833c20c3b 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -509,6 +509,8 @@ namespace Emby.Server.Implementations.Updates private async Task PerformPackageInstallation(IProgress progress, string target, PackageVersionInfo package, CancellationToken cancellationToken) { + // TODO: Remove the `string target` argument as it is not used any longer + var extension = Path.GetExtension(package.targetFilename); var isArchive = string.Equals(extension, ".zip", StringComparison.OrdinalIgnoreCase); From f5f7de64de2a15164ef6b62cb8da844dd823067d Mon Sep 17 00:00:00 2001 From: John Taylor Date: Sat, 6 Apr 2019 13:40:19 -0400 Subject: [PATCH 10/35] Use TLS 1.2 to download NSSM --- deployment/windows/build-jellyfin.ps1 | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/deployment/windows/build-jellyfin.ps1 b/deployment/windows/build-jellyfin.ps1 index 2c83f264c2..2999912b3a 100644 --- a/deployment/windows/build-jellyfin.ps1 +++ b/deployment/windows/build-jellyfin.ps1 @@ -26,7 +26,10 @@ function Build-JellyFin { Write-Error "arm only supported with Windows 8 or higher" exit } - dotnet publish -c $BuildType -r "$windowsversion-$Architecture" MediaBrowser.sln -o $InstallLocation -v $DotNetVerbosity + Write-Verbose "windowsversion-Architecture: $windowsversion-$Architecture" + Write-Verbose "InstallLocation: $InstallLocation" + Write-Verbose "DotNetVerbosity: $DotNetVerbosity" + dotnet publish -c $BuildType -r `"$windowsversion-$Architecture`" MediaBrowser.sln -o $InstallLocation -v $DotNetVerbosity } function Install-FFMPEG { @@ -73,6 +76,7 @@ function Install-NSSM { Write-Warning "NSSM will not be installed" }else{ Write-Verbose "Downloading NSSM" + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 Invoke-WebRequest -Uri https://nssm.cc/ci/nssm-2.24-101-g897c7ad.zip -UseBasicParsing -OutFile "$tempdir/nssm.zip" | Write-Verbose } From 1af9c047fbc0283f7abfb4b98918454258dfb348 Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Sun, 7 Apr 2019 19:51:45 -0400 Subject: [PATCH 11/35] Override username with AuthenticationProvider Pass back the Username directive returned by an AuthenticationProvider to the calling code, so we may override the user-provided Username value if the authentication provider passes this back. Useful for instance in an LDAP scenario where what the user types may not necessarily be the "username" that is mapped in the system, e.g. the user providing 'mail' while 'uid' is the "username" value. Could also then be extensible to other authentication providers as well, should they wish to do a similar thing. --- .../Library/UserManager.cs | 44 ++++++++++++++----- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/Emby.Server.Implementations/Library/UserManager.cs b/Emby.Server.Implementations/Library/UserManager.cs index 75c82ca715..952cc6896b 100644 --- a/Emby.Server.Implementations/Library/UserManager.cs +++ b/Emby.Server.Implementations/Library/UserManager.cs @@ -277,24 +277,35 @@ namespace Emby.Server.Implementations.Library .FirstOrDefault(i => string.Equals(username, i.Name, StringComparison.OrdinalIgnoreCase)); var success = false; + string updatedUsername = null; IAuthenticationProvider authenticationProvider = null; if (user != null) { var authResult = await AuthenticateLocalUser(username, password, hashedPassword, user, remoteEndPoint).ConfigureAwait(false); authenticationProvider = authResult.Item1; - success = authResult.Item2; + updatedUsername = authResult.Item2; + success = authResult.Item3; } else { // user is null var authResult = await AuthenticateLocalUser(username, password, hashedPassword, null, remoteEndPoint).ConfigureAwait(false); authenticationProvider = authResult.Item1; - success = authResult.Item2; + updatedUsername = authResult.Item2; + success = authResult.Item3; if (success && authenticationProvider != null && !(authenticationProvider is DefaultAuthenticationProvider)) { - user = await CreateUser(username).ConfigureAwait(false); + // We should trust the user that the authprovider says, not what was typed + if (updatedUsername != username) + { + username = updatedUsername; + } + + // Search the database for the user again; the authprovider might have created it + user = Users + .FirstOrDefault(i => string.Equals(username, i.Name, StringComparison.OrdinalIgnoreCase)); var hasNewUserPolicy = authenticationProvider as IHasNewUserPolicy; if (hasNewUserPolicy != null) @@ -414,32 +425,40 @@ namespace Emby.Server.Implementations.Library return providers; } - private async Task AuthenticateWithProvider(IAuthenticationProvider provider, string username, string password, User resolvedUser) + private async Task> AuthenticateWithProvider(IAuthenticationProvider provider, string username, string password, User resolvedUser) { try { var requiresResolvedUser = provider as IRequiresResolvedUser; + ProviderAuthenticationResult authenticationResult = null; if (requiresResolvedUser != null) { - await requiresResolvedUser.Authenticate(username, password, resolvedUser).ConfigureAwait(false); + authenticationResult = await requiresResolvedUser.Authenticate(username, password, resolvedUser).ConfigureAwait(false); } else { - await provider.Authenticate(username, password).ConfigureAwait(false); + authenticationResult = await provider.Authenticate(username, password).ConfigureAwait(false); + } + + if(authenticationResult.Username != username) + { + _logger.LogDebug("Authentication provider provided updated username {1}", authenticationResult.Username); + username = authenticationResult.Username; } - return true; + return new Tuple(username, true); } catch (Exception ex) { _logger.LogError(ex, "Error authenticating with provider {provider}", provider.Name); - return false; + return new Tuple(username, false); } } - private async Task> AuthenticateLocalUser(string username, string password, string hashedPassword, User user, string remoteEndPoint) + private async Task> AuthenticateLocalUser(string username, string password, string hashedPassword, User user, string remoteEndPoint) { + string updatedUsername = null; bool success = false; IAuthenticationProvider authenticationProvider = null; @@ -458,11 +477,14 @@ namespace Emby.Server.Implementations.Library { foreach (var provider in GetAuthenticationProviders(user)) { - success = await AuthenticateWithProvider(provider, username, password, user).ConfigureAwait(false); + var providerAuthResult = await AuthenticateWithProvider(provider, username, password, user).ConfigureAwait(false); + updatedUsername = providerAuthResult.Item1; + success = providerAuthResult.Item2; if (success) { authenticationProvider = provider; + username = updatedUsername; break; } } @@ -484,7 +506,7 @@ namespace Emby.Server.Implementations.Library } } - return new Tuple(authenticationProvider, success); + return new Tuple(authenticationProvider, username, success); } private void UpdateInvalidLoginAttemptCount(User user, int newValue) From a7e31ef31f0202cefe1fd97a648260c3f4791446 Mon Sep 17 00:00:00 2001 From: Phallacy Date: Thu, 4 Apr 2019 23:04:54 -0700 Subject: [PATCH 12/35] applied changes to just also search jellyfin base dir --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 4867c0f859..b626600fa4 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -230,6 +230,11 @@ namespace MediaBrowser.MediaEncoding.Encoder /// private string ExistsOnSystemPath(string filename) { + string inJellyfinPath = GetEncoderPathFromDirectory(System.AppContext.BaseDirectory, filename); + if (!string.IsNullOrEmpty(inJellyfinPath)) + { + return inJellyfinPath; + } var values = Environment.GetEnvironmentVariable("PATH"); foreach (var path in values.Split(Path.PathSeparator)) From efb14f0b583d570cf73807715ee50956badeaf1d Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Wed, 10 Apr 2019 00:23:39 -0400 Subject: [PATCH 13/35] Bump dockerfile web versions too --- bump_version | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/bump_version b/bump_version index b118af54b9..398caee15c 100755 --- a/bump_version +++ b/bump_version @@ -54,6 +54,7 @@ old_version="$( grep "AssemblyVersion" ${shared_version_file} \ | sed -E 's/\[assembly: ?AssemblyVersion\("([0-9\.]+)"\)\]/\1/' )" +echo $old_version # Set the shared version to the specified new_version old_version_sed="$( sed 's/\./\\./g' <<<"${old_version}" )" # Escape the '.' chars @@ -62,9 +63,11 @@ sed -i "s/${old_version_sed}/${new_version_sed}/g" ${shared_version_file} old_version="$( grep "version:" ${build_file} \ - | sed -E 's/version: "([0-9\.]+)"/\1/' + | sed -E 's/version: "([0-9\.]+[-a-z0-9]*)"/\1/' )" +echo $old_version +# Set the build.yaml version to the specified new_version old_version_sed="$( sed 's/\./\\./g' <<<"${old_version}" )" # Escape the '.' chars sed -i "s/${old_version_sed}/${new_version}/g" ${build_file} @@ -74,6 +77,16 @@ else new_version_deb="${new_version}-1" fi +# Set the Dockerfile web version to the specified new_version +old_version="$( + grep "JELLYFIN_WEB_VERSION=" Dockerfile \ + | sed -E 's/ARG JELLYFIN_WEB_VERSION=([0-9\.]+[-a-z0-9]*)/\1/' +)" +echo $old_version + +old_version_sed="$( sed 's/\./\\./g' <<<"${old_version}" )" # Escape the '.' chars +sed -i "s/${old_version_sed}/${new_version}/g" Dockerfile* + # Write out a temporary Debian changelog with our new stuff appended and some templated formatting debian_changelog_file="deployment/debian-package-x64/pkg-src/changelog" debian_changelog_temp="$( mktemp )" @@ -124,5 +137,5 @@ mv ${fedora_spec_temp} ${fedora_spec_file} rm -rf ${fedora_changelog_temp} ${fedora_spec_temp_dir} # Stage the changed files for commit -git add ${shared_version_file} ${build_file} ${debian_changelog_file} ${fedora_spec_file} +git add ${shared_version_file} ${build_file} ${debian_changelog_file} ${fedora_spec_file} Dockerfile* git status From 65bff1181a3ae739dedbfd647d890630aa2cfba8 Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Wed, 10 Apr 2019 00:51:21 -0400 Subject: [PATCH 14/35] Bump version to 10.3.0-rc2 and update submodule --- Dockerfile | 2 +- Dockerfile.arm | 2 +- Dockerfile.arm64 | 2 +- MediaBrowser.WebDashboard/jellyfin-web | 2 +- build.yaml | 2 +- deployment/debian-package-x64/pkg-src/changelog | 6 ++++++ deployment/fedora-package-x64/pkg-src/jellyfin.spec | 2 ++ 7 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index dbbed535f8..36fc43983e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,7 +21,7 @@ RUN apt-get update \ COPY --from=ffmpeg / / COPY --from=builder /jellyfin /jellyfin -ARG JELLYFIN_WEB_VERSION=10.3.0-rc1 +ARG JELLYFIN_WEB_VERSION=10.3.0-rc2 RUN curl -L https://github.com/jellyfin/jellyfin-web/archive/v${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \ && rm -rf /jellyfin/jellyfin-web \ && mv jellyfin-web-${JELLYFIN_WEB_VERSION} /jellyfin/jellyfin-web diff --git a/Dockerfile.arm b/Dockerfile.arm index 6bd5b576f1..c896d83f27 100644 --- a/Dockerfile.arm +++ b/Dockerfile.arm @@ -30,7 +30,7 @@ RUN apt-get update \ && chmod 777 /cache /config /media COPY --from=builder /jellyfin /jellyfin -ARG JELLYFIN_WEB_VERSION=10.3.0-rc1 +ARG JELLYFIN_WEB_VERSION=10.3.0-rc2 RUN curl -L https://github.com/jellyfin/jellyfin-web/archive/v${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \ && rm -rf /jellyfin/jellyfin-web \ && mv jellyfin-web-${JELLYFIN_WEB_VERSION} /jellyfin/jellyfin-web diff --git a/Dockerfile.arm64 b/Dockerfile.arm64 index 3be2fd4f14..09c9dc12f8 100644 --- a/Dockerfile.arm64 +++ b/Dockerfile.arm64 @@ -31,7 +31,7 @@ RUN apt-get update \ && chmod 777 /cache /config /media COPY --from=builder /jellyfin /jellyfin -ARG JELLYFIN_WEB_VERSION=10.3.0-rc1 +ARG JELLYFIN_WEB_VERSION=10.3.0-rc2 RUN curl -L https://github.com/jellyfin/jellyfin-web/archive/v${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \ && rm -rf /jellyfin/jellyfin-web \ && mv jellyfin-web-${JELLYFIN_WEB_VERSION} /jellyfin/jellyfin-web diff --git a/MediaBrowser.WebDashboard/jellyfin-web b/MediaBrowser.WebDashboard/jellyfin-web index 9677981344..e07edea5bf 160000 --- a/MediaBrowser.WebDashboard/jellyfin-web +++ b/MediaBrowser.WebDashboard/jellyfin-web @@ -1 +1 @@ -Subproject commit 9677981344e57e8f84ca664cad13da1f89f4254f +Subproject commit e07edea5bf22c253fc7ee91f45879d8ee2d1bf17 diff --git a/build.yaml b/build.yaml index 34d356dacf..ccd7ce8f85 100644 --- a/build.yaml +++ b/build.yaml @@ -1,7 +1,7 @@ --- # We just wrap `build` so this is really it name: "jellyfin" -version: "10.3.0-rc1" +version: "10.3.0-rc2" packages: - debian-package-x64 - debian-package-armhf diff --git a/deployment/debian-package-x64/pkg-src/changelog b/deployment/debian-package-x64/pkg-src/changelog index da9151af1a..65880620dc 100644 --- a/deployment/debian-package-x64/pkg-src/changelog +++ b/deployment/debian-package-x64/pkg-src/changelog @@ -1,3 +1,9 @@ +jellyfin (10.3.0~rc2) unstable; urgency=medium + + * New upstream version 10.3.0-rc2; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.3.0-rc2 + + -- Jellyfin Packaging Team Wed, 10 Apr 2019 00:51:14 -0400 + jellyfin (10.3.0~rc1) unstable; urgency=medium * New upstream version 10.3.0-rc1; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.3.0-rc1 diff --git a/deployment/fedora-package-x64/pkg-src/jellyfin.spec b/deployment/fedora-package-x64/pkg-src/jellyfin.spec index 77c291c872..581d926fbf 100644 --- a/deployment/fedora-package-x64/pkg-src/jellyfin.spec +++ b/deployment/fedora-package-x64/pkg-src/jellyfin.spec @@ -140,6 +140,8 @@ fi %systemd_postun_with_restart jellyfin.service %changelog +* Wed Apr 10 2019 Jellyfin Packaging Team +- New upstream version 10.3.0-rc2; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.3.0-rc2 * Sat Mar 30 2019 Jellyfin Packaging Team - New upstream version 10.3.0-rc1; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.3.0-rc1 * Thu Feb 28 2019 Jellyfin Packaging Team From b2f94c0e4015160ba3102cd6617397fc07c6ba35 Mon Sep 17 00:00:00 2001 From: Anthony Lavado Date: Mon, 15 Apr 2019 00:21:14 -0400 Subject: [PATCH 15/35] Remove the old message responders Leaves only an answer to "Who is Jellyfin", removing older ones for EmbyServer and MediaBrowser_v2. --- Emby.Server.Implementations/Udp/UdpServer.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Emby.Server.Implementations/Udp/UdpServer.cs b/Emby.Server.Implementations/Udp/UdpServer.cs index bd86c6cdc8..e7cda2993f 100644 --- a/Emby.Server.Implementations/Udp/UdpServer.cs +++ b/Emby.Server.Implementations/Udp/UdpServer.cs @@ -41,8 +41,6 @@ namespace Emby.Server.Implementations.Udp _socketFactory = socketFactory; AddMessageResponder("who is JellyfinServer?", true, RespondToV2Message); - AddMessageResponder("who is EmbyServer?", true, RespondToV2Message); - AddMessageResponder("who is MediaBrowserServer_v2?", false, RespondToV2Message); } private void AddMessageResponder(string message, bool isSubstring, Func responder) From 34ab99caf18ee862a1dc29a6afb83253db35c219 Mon Sep 17 00:00:00 2001 From: Anthony Lavado Date: Tue, 16 Apr 2019 01:16:02 -0400 Subject: [PATCH 16/35] Move the ProductName to the public endpoint Moves the ProductName field over from the private system/info point to the public one, for easier identification --- Emby.Server.Implementations/ApplicationHost.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 05f8a8a5e7..82042f5ca7 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1425,7 +1425,6 @@ namespace Emby.Server.Implementations HasPendingRestart = HasPendingRestart, IsShuttingDown = IsShuttingDown, Version = ApplicationVersion, - ProductName = ApplicationProductName, WebSocketPortNumber = HttpPort, CompletedInstallations = InstallationManager.CompletedInstallations.ToArray(), Id = SystemId, @@ -1482,6 +1481,7 @@ namespace Emby.Server.Implementations return new PublicSystemInfo { Version = ApplicationVersion, + ProductName = ApplicationProductName, Id = SystemId, OperatingSystem = OperatingSystem.Id.ToString(), WanAddress = wanAddress, From 2f0719a883580b547960904703a39748281bf5e0 Mon Sep 17 00:00:00 2001 From: Anthony Lavado Date: Tue, 16 Apr 2019 01:38:00 -0400 Subject: [PATCH 17/35] Move the definition of ProductName to the correct class Missed moving this from one class to the other. --- MediaBrowser.Model/System/PublicSystemInfo.cs | 5 +++++ MediaBrowser.Model/System/SystemInfo.cs | 4 ---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/MediaBrowser.Model/System/PublicSystemInfo.cs b/MediaBrowser.Model/System/PublicSystemInfo.cs index d97eda3523..d6e031e427 100644 --- a/MediaBrowser.Model/System/PublicSystemInfo.cs +++ b/MediaBrowser.Model/System/PublicSystemInfo.cs @@ -25,6 +25,11 @@ namespace MediaBrowser.Model.System /// /// The version. public string Version { get; set; } + + /// + /// The product name. This is the AssemblyProduct name. + /// + public string ProductName { get; set; } /// /// Gets or sets the operating system. diff --git a/MediaBrowser.Model/System/SystemInfo.cs b/MediaBrowser.Model/System/SystemInfo.cs index 222c10798a..3f73cc4e0b 100644 --- a/MediaBrowser.Model/System/SystemInfo.cs +++ b/MediaBrowser.Model/System/SystemInfo.cs @@ -32,10 +32,6 @@ namespace MediaBrowser.Model.System /// The display name of the operating system. public string OperatingSystemDisplayName { get; set; } - /// - /// The product name. This is the AssemblyProduct name. - /// - public string ProductName { get; set; } /// /// Get or sets the package name. From c7fedfbca388d3e43ca266e7a4a6caccfc4bb5c7 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Wed, 17 Apr 2019 11:41:14 +0200 Subject: [PATCH 18/35] Fix metadata path save --- .../Configuration/ServerConfigurationManager.cs | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs b/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs index 18e279c2f0..c4fa68cac4 100644 --- a/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs +++ b/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs @@ -74,23 +74,14 @@ namespace Emby.Server.Implementations.Configuration /// private void UpdateMetadataPath() { - string metadataPath; - if (string.IsNullOrWhiteSpace(Configuration.MetadataPath)) { - metadataPath = GetInternalMetadataPath(); + ((ServerApplicationPaths)ApplicationPaths).InternalMetadataPath = Path.Combine(ApplicationPaths.ProgramDataPath, "metadata"); } else { - metadataPath = Path.Combine(Configuration.MetadataPath, "metadata"); + ((ServerApplicationPaths)ApplicationPaths).InternalMetadataPath = Configuration.MetadataPath; } - - ((ServerApplicationPaths)ApplicationPaths).InternalMetadataPath = metadataPath; - } - - private string GetInternalMetadataPath() - { - return Path.Combine(ApplicationPaths.ProgramDataPath, "metadata"); } /// From 250e0c75dfaebca54e93be6c11c70cb0d19e589a Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Wed, 17 Apr 2019 22:31:06 -0400 Subject: [PATCH 19/35] Add MethodNotAllowedException with code 405 --- Emby.Server.Implementations/HttpServer/HttpListenerHost.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs index e8d47cad52..831391cee6 100644 --- a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -203,6 +203,7 @@ namespace Emby.Server.Implementations.HttpServer case DirectoryNotFoundException _: case FileNotFoundException _: case ResourceNotFoundException _: return 404; + case MethodNotAllowedException _: return 405; case RemoteServiceUnavailableException _: return 502; default: return 500; } From e790f024c2da2b3104ad698abfbd74fdf273bb9f Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Wed, 17 Apr 2019 22:31:17 -0400 Subject: [PATCH 20/35] Return MethodNotAllowedException if Pw is not set Don't accept pre-hashed (not-plaintext) passwords as the auth provider no longer supports this due to sha1+salting the passwords in the database. --- MediaBrowser.Api/UserService.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs index a6849f75f5..0db62098ca 100644 --- a/MediaBrowser.Api/UserService.cs +++ b/MediaBrowser.Api/UserService.cs @@ -379,6 +379,11 @@ namespace MediaBrowser.Api throw new ResourceNotFoundException("User not found"); } + if (!request.Pw) + { + throw new MethodNotAllowedException("Hashed-only passwords are not valid for this API."); + } + return Post(new AuthenticateUserByName { Username = user.Name, From ca3bb308b3b20327ee96ea914cdaf02fa51374cd Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Wed, 17 Apr 2019 22:46:26 -0400 Subject: [PATCH 21/35] Add the proper Class too --- .../Extensions/ResourceNotFoundException.cs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/MediaBrowser.Common/Extensions/ResourceNotFoundException.cs b/MediaBrowser.Common/Extensions/ResourceNotFoundException.cs index f62c65fd7f..9f70ae7d89 100644 --- a/MediaBrowser.Common/Extensions/ResourceNotFoundException.cs +++ b/MediaBrowser.Common/Extensions/ResourceNotFoundException.cs @@ -26,6 +26,30 @@ namespace MediaBrowser.Common.Extensions } } + /// + /// Class MethodNotAllowedException + /// + public class MethodNotAllowedException : Exception + { + /// + /// Initializes a new instance of the class. + /// + public MethodNotAllowedException() + { + + } + + /// + /// Initializes a new instance of the class. + /// + /// The message. + public MethodNotAllowedException(string message) + : base(message) + { + + } + } + public class RemoteServiceUnavailableException : Exception { public RemoteServiceUnavailableException() From eaa1ac80133e766a1d3ab4e0f5a07bc48619cd44 Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Wed, 17 Apr 2019 22:49:17 -0400 Subject: [PATCH 22/35] Apparently strings can't be !'d --- MediaBrowser.Api/UserService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs index 0db62098ca..119c423e60 100644 --- a/MediaBrowser.Api/UserService.cs +++ b/MediaBrowser.Api/UserService.cs @@ -379,7 +379,7 @@ namespace MediaBrowser.Api throw new ResourceNotFoundException("User not found"); } - if (!request.Pw) + if (request.Pw == "") { throw new MethodNotAllowedException("Hashed-only passwords are not valid for this API."); } From 10f33b027345193f91b91600473222797ae9bef5 Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Thu, 18 Apr 2019 09:31:30 -0400 Subject: [PATCH 23/35] Update conditional to be correct --- MediaBrowser.Api/UserService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs index 119c423e60..7628a2f0fa 100644 --- a/MediaBrowser.Api/UserService.cs +++ b/MediaBrowser.Api/UserService.cs @@ -379,7 +379,7 @@ namespace MediaBrowser.Api throw new ResourceNotFoundException("User not found"); } - if (request.Pw == "") + if (!string.IsNullOrEmpty(request.Password) || string.IsNullOrEmpty(request.Pw)) { throw new MethodNotAllowedException("Hashed-only passwords are not valid for this API."); } From 31ad366aa93e8bc07f6e120320f3abd27d9dfd49 Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Thu, 18 Apr 2019 10:24:08 -0400 Subject: [PATCH 24/35] Implemented suggested conditional --- MediaBrowser.Api/UserService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs index 7628a2f0fa..497800d263 100644 --- a/MediaBrowser.Api/UserService.cs +++ b/MediaBrowser.Api/UserService.cs @@ -379,7 +379,7 @@ namespace MediaBrowser.Api throw new ResourceNotFoundException("User not found"); } - if (!string.IsNullOrEmpty(request.Password) || string.IsNullOrEmpty(request.Pw)) + if (!string.IsNullOrEmpty(request.Password) && string.IsNullOrEmpty(request.Pw)) { throw new MethodNotAllowedException("Hashed-only passwords are not valid for this API."); } @@ -387,7 +387,7 @@ namespace MediaBrowser.Api return Post(new AuthenticateUserByName { Username = user.Name, - Password = request.Password, + Password = null, // This should always be null Pw = request.Pw }); } From 90c04a46403ba158e11c444c7109f5a56f12eff3 Mon Sep 17 00:00:00 2001 From: tinganhsu Date: Fri, 19 Apr 2019 04:32:51 +0000 Subject: [PATCH 25/35] Added translation using Weblate (Chinese (Traditional)) --- Emby.Server.Implementations/Localization/Core/zh_Hant.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 Emby.Server.Implementations/Localization/Core/zh_Hant.json diff --git a/Emby.Server.Implementations/Localization/Core/zh_Hant.json b/Emby.Server.Implementations/Localization/Core/zh_Hant.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/Emby.Server.Implementations/Localization/Core/zh_Hant.json @@ -0,0 +1 @@ +{} From ba684d6d3a4bfc9a0dc3f9de16a3b32bb95da1a1 Mon Sep 17 00:00:00 2001 From: tinganhsu Date: Fri, 19 Apr 2019 04:33:31 +0000 Subject: [PATCH 26/35] Translated using Weblate (Chinese (Traditional)) Currently translated at 96.8% (91 of 94 strings) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/zh_Hant/ --- .../Localization/Core/zh_Hant.json | 94 ++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/zh_Hant.json b/Emby.Server.Implementations/Localization/Core/zh_Hant.json index 0967ef424b..effff5566e 100644 --- a/Emby.Server.Implementations/Localization/Core/zh_Hant.json +++ b/Emby.Server.Implementations/Localization/Core/zh_Hant.json @@ -1 +1,93 @@ -{} +{ + "Albums": "專輯", + "AppDeviceValues": "應用: {0}, 裝置: {1}", + "Application": "應用程式", + "Artists": "演出者", + "AuthenticationSucceededWithUserName": "{0} 成功授權", + "Books": "圖書", + "CameraImageUploadedFrom": "{0} 已經成功上傳一張相片", + "Channels": "頻道", + "ChapterNameValue": "章節 {0}", + "Collections": "合輯", + "DeviceOfflineWithName": "{0} 已經斷線", + "DeviceOnlineWithName": "{0} 已經連線", + "FailedLoginAttemptWithUserName": "來自 {0} 的失敗登入嘗試", + "Favorites": "我的最愛", + "Folders": "資料夾", + "Genres": "風格", + "HeaderAlbumArtists": "專輯演出者", + "HeaderCameraUploads": "相機上傳", + "HeaderContinueWatching": "繼續觀賞", + "HeaderFavoriteAlbums": "最愛專輯", + "HeaderFavoriteArtists": "最愛演出者", + "HeaderFavoriteEpisodes": "最愛級數", + "HeaderFavoriteShows": "最愛節目", + "HeaderFavoriteSongs": "最愛歌曲", + "HeaderLiveTV": "電視直播", + "HeaderNextUp": "接下來", + "HomeVideos": "自製影片", + "ItemAddedWithName": "{0} 已新增至媒體庫", + "ItemRemovedWithName": "{0} 已從媒體庫移除", + "LabelIpAddressValue": "IP 位置: {0}", + "LabelRunningTimeValue": "運行時間: {0}", + "Latest": "最新", + "MessageApplicationUpdated": "Jellyfin Server 已經更新", + "MessageApplicationUpdatedTo": "Jellyfin Server 已經更新至 {0}", + "MessageNamedServerConfigurationUpdatedWithValue": "伺服器設定 {0} 部分已經更新", + "MessageServerConfigurationUpdated": "伺服器設定已經更新", + "MixedContent": "混合內容", + "Movies": "電影", + "Music": "音樂", + "MusicVideos": "音樂MV", + "NameInstallFailed": "{0} 安裝失敗", + "NameSeasonNumber": "第 {0} 季", + "NameSeasonUnknown": "未知季數", + "NewVersionIsAvailable": "新版本的Jellyfin Server 軟體已經推出可供下載。", + "NotificationOptionApplicationUpdateAvailable": "有可用的應用程式更新", + "NotificationOptionApplicationUpdateInstalled": "應用程式已更新", + "NotificationOptionAudioPlayback": "音樂開始播放", + "NotificationOptionAudioPlaybackStopped": "音樂停止播放", + "NotificationOptionCameraImageUploaded": "相機相片已上傳", + "NotificationOptionInstallationFailed": "安裝失敗", + "NotificationOptionNewLibraryContent": "已新增新內容", + "NotificationOptionPluginError": "外掛失敗", + "NotificationOptionPluginInstalled": "外掛已安裝", + "NotificationOptionPluginUninstalled": "外掛已移除", + "NotificationOptionPluginUpdateInstalled": "已更新外掛", + "NotificationOptionServerRestartRequired": "伺服器需要重新啟動", + "NotificationOptionTaskFailed": "排程任務失敗", + "NotificationOptionUserLockedOut": "使用者已鎖定", + "NotificationOptionVideoPlayback": "影片開始播放", + "NotificationOptionVideoPlaybackStopped": "影片停止播放", + "Photos": "相片", + "Playlists": "播放清單", + "Plugin": "外掛", + "PluginInstalledWithName": "{0} 已安裝", + "PluginUninstalledWithName": "{0} 已移除", + "PluginUpdatedWithName": "{0} 已更新", + "ProviderValue": "提供商: {0}", + "ScheduledTaskFailedWithName": "{0} 已失敗", + "ScheduledTaskStartedWithName": "{0} 已開始", + "ServerNameNeedsToBeRestarted": "{0} 需要重新啟動", + "Shows": "節目", + "Songs": "歌曲", + "StartupEmbyServerIsLoading": "Jellyfin Server正在啟動,請稍後再試一次。", + "SubtitlesDownloadedForItem": "已為 {0} 下載字幕", + "Sync": "同步", + "System": "系統", + "TvShows": "電視節目", + "User": "使用者", + "UserCreatedWithName": "使用者 {0} 已建立", + "UserDeletedWithName": "使用者 {0} 已移除", + "UserDownloadingItemWithValues": "{0} 正在下載 {1}", + "UserLockedOutWithName": "使用者 {0} 已鎖定", + "UserOfflineFromDevice": "{0} 已從 {1} 斷線", + "UserOnlineFromDevice": "{0} 已連線,來自 {1}", + "UserPasswordChangedWithName": "使用者 {0} 的密碼已變更", + "UserPolicyUpdatedWithName": "使用者條約已更新為 {0}", + "UserStartedPlayingItemWithValues": "{0}正在使用 {2} 播放 {1}", + "UserStoppedPlayingItemWithValues": "{0} 已停止在 {2} 播放 {1}", + "ValueHasBeenAddedToLibrary": "{0} 已新增至您的媒體庫", + "ValueSpecialEpisodeName": "特典 - {0}", + "VersionNumber": "版本 {0}" +} From d6622818dca410f15764a94c2e19cf9dee1393a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Libor=20Fil=C3=ADpek?= Date: Sat, 13 Apr 2019 12:06:54 +0000 Subject: [PATCH 27/35] Translated using Weblate (Czech) Currently translated at 100.0% (94 of 94 strings) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/cs/ --- .../Localization/Core/cs.json | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/cs.json b/Emby.Server.Implementations/Localization/Core/cs.json index a8b4a44244..c2a101a4da 100644 --- a/Emby.Server.Implementations/Localization/Core/cs.json +++ b/Emby.Server.Implementations/Localization/Core/cs.json @@ -5,7 +5,7 @@ "Artists": "Umělci", "AuthenticationSucceededWithUserName": "{0} úspěšně ověřen", "Books": "Knihy", - "CameraImageUploadedFrom": "A new camera image has been uploaded from {0}", + "CameraImageUploadedFrom": "Z {0} byla nahrána nová fotografie", "Channels": "Kanály", "ChapterNameValue": "Kapitola {0}", "Collections": "Kolekce", @@ -16,14 +16,14 @@ "Folders": "Složky", "Genres": "Žánry", "HeaderAlbumArtists": "Umělci alba", - "HeaderCameraUploads": "Camera Uploads", + "HeaderCameraUploads": "Nahrané fotografie", "HeaderContinueWatching": "Pokračovat ve sledování", "HeaderFavoriteAlbums": "Oblíbená alba", "HeaderFavoriteArtists": "Oblíbení umělci", "HeaderFavoriteEpisodes": "Oblíbené epizody", "HeaderFavoriteShows": "Oblíbené seriály", "HeaderFavoriteSongs": "Oblíbené písně", - "HeaderLiveTV": "Živá TV", + "HeaderLiveTV": "Live TV", "HeaderNextUp": "Nadcházející", "HeaderRecordingGroups": "Skupiny nahrávek", "HomeVideos": "Domáci videa", @@ -34,17 +34,17 @@ "LabelRunningTimeValue": "Délka média: {0}", "Latest": "Nejnovější", "MessageApplicationUpdated": "Jellyfin Server byl aktualizován", - "MessageApplicationUpdatedTo": "Jellyfin Server has been updated to {0}", + "MessageApplicationUpdatedTo": "Jellyfin server byl aktualizován na verzi {0}", "MessageNamedServerConfigurationUpdatedWithValue": "Konfigurace sekce {0} na serveru byla aktualizována", "MessageServerConfigurationUpdated": "Konfigurace serveru aktualizována", "MixedContent": "Smíšený obsah", "Movies": "Filmy", "Music": "Hudba", "MusicVideos": "Hudební klipy", - "NameInstallFailed": "{0} installation failed", + "NameInstallFailed": "Instalace {0} selhala", "NameSeasonNumber": "Sezóna {0}", "NameSeasonUnknown": "Neznámá sezóna", - "NewVersionIsAvailable": "A new version of Jellyfin Server is available for download.", + "NewVersionIsAvailable": "Nová verze Jellyfin serveru je k dispozici ke stažení.", "NotificationOptionApplicationUpdateAvailable": "Dostupná aktualizace aplikace", "NotificationOptionApplicationUpdateInstalled": "Aktualizace aplikace instalována", "NotificationOptionAudioPlayback": "Přehrávání audia zahájeno", @@ -70,12 +70,12 @@ "ProviderValue": "Poskytl: {0}", "ScheduledTaskFailedWithName": "{0} selhalo", "ScheduledTaskStartedWithName": "{0} zahájeno", - "ServerNameNeedsToBeRestarted": "{0} needs to be restarted", + "ServerNameNeedsToBeRestarted": "{0} vyžaduje restart", "Shows": "Seriály", "Songs": "Skladby", "StartupEmbyServerIsLoading": "Jellyfin Server je spouštěn. Zkuste to prosím v brzké době znovu.", "SubtitleDownloadFailureForItem": "Stahování titulků selhalo pro {0}", - "SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}", + "SubtitleDownloadFailureFromForItem": "Stažení titulků pro {1} z {0} selhalo", "SubtitlesDownloadedForItem": "Staženy titulky pro {0}", "Sync": "Synchronizace", "System": "Systém", @@ -88,10 +88,10 @@ "UserOfflineFromDevice": "{0} se odpojil od {1}", "UserOnlineFromDevice": "{0} se připojil z {1}", "UserPasswordChangedWithName": "Provedena změna hesla pro uživatele {0}", - "UserPolicyUpdatedWithName": "User policy has been updated for {0}", + "UserPolicyUpdatedWithName": "Zásady uživatele pro {0} byly aktualizovány", "UserStartedPlayingItemWithValues": "{0} spustil přehrávání {1}", "UserStoppedPlayingItemWithValues": "{0} zastavil přehrávání {1}", - "ValueHasBeenAddedToLibrary": "{0} has been added to your media library", + "ValueHasBeenAddedToLibrary": "{0} byl přidán do vaší knihovny médií", "ValueSpecialEpisodeName": "Speciál - {0}", "VersionNumber": "Verze {0}" } From d31f5229da7049a6cef56c745ae93168f7df24d5 Mon Sep 17 00:00:00 2001 From: Dan Johansen Date: Tue, 9 Apr 2019 07:39:06 +0000 Subject: [PATCH 28/35] Translated using Weblate (Danish) Currently translated at 100.0% (94 of 94 strings) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/da/ --- Emby.Server.Implementations/Localization/Core/da.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/da.json b/Emby.Server.Implementations/Localization/Core/da.json index 9d4d740996..cb8f4576ad 100644 --- a/Emby.Server.Implementations/Localization/Core/da.json +++ b/Emby.Server.Implementations/Localization/Core/da.json @@ -61,8 +61,8 @@ "NotificationOptionUserLockedOut": "Bruger låst ude", "NotificationOptionVideoPlayback": "Videoafspilning påbegyndt", "NotificationOptionVideoPlaybackStopped": "Videoafspilning stoppet", - "Photos": "Fotos", - "Playlists": "Spillelister", + "Photos": "Fotoer", + "Playlists": "Afspilningslister", "Plugin": "Plugin", "PluginInstalledWithName": "{0} blev installeret", "PluginUninstalledWithName": "{0} blev afinstalleret", From 395d2e4917f3c790bb14a1dd43e062b036d98b04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=92=CE=B1=CF=83=CE=AF=CE=BB=CE=B7=CF=82=20=CE=9C=CE=BF?= =?UTF-8?q?=CF=85=CF=81=CE=B1=CF=84=CE=AF=CE=B4=CE=B7=CF=82?= Date: Thu, 18 Apr 2019 09:05:44 +0000 Subject: [PATCH 29/35] Translated using Weblate (Greek) Currently translated at 100.0% (94 of 94 strings) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/el/ --- Emby.Server.Implementations/Localization/Core/el.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/el.json b/Emby.Server.Implementations/Localization/Core/el.json index 91ca34edc2..db7ebb0c01 100644 --- a/Emby.Server.Implementations/Localization/Core/el.json +++ b/Emby.Server.Implementations/Localization/Core/el.json @@ -16,7 +16,7 @@ "Folders": "Φάκελοι", "Genres": "Είδη", "HeaderAlbumArtists": "Άλμπουμ Καλλιτεχνών", - "HeaderCameraUploads": "Camera Uploads", + "HeaderCameraUploads": "Μεταφορτώσεις Κάμερας", "HeaderContinueWatching": "Συνεχίστε να παρακολουθείτε", "HeaderFavoriteAlbums": "Αγαπημένα Άλμπουμ", "HeaderFavoriteArtists": "Αγαπημένοι Καλλιτέχνες", @@ -34,7 +34,7 @@ "LabelRunningTimeValue": "Διάρκεια: {0}", "Latest": "Πρόσφατα", "MessageApplicationUpdated": "Ο Jellyfin Server έχει ενημερωθεί", - "MessageApplicationUpdatedTo": "Jellyfin Server has been updated to {0}", + "MessageApplicationUpdatedTo": "Ο server Jellyfin αναβαθμίστηκε σε έκδοση {0}", "MessageNamedServerConfigurationUpdatedWithValue": "Η ενότητα {0} ρύθμισης παραμέτρων του server έχει ενημερωθεί", "MessageServerConfigurationUpdated": "Η ρύθμιση παραμέτρων του server έχει ενημερωθεί", "MixedContent": "Ανάμεικτο Περιεχόμενο", @@ -49,7 +49,7 @@ "NotificationOptionApplicationUpdateInstalled": "Η ενημέρωση εφαρμογής εγκαταστάθηκε", "NotificationOptionAudioPlayback": "Η αναπαραγωγή ήχου ξεκίνησε", "NotificationOptionAudioPlaybackStopped": "Η αναπαραγωγή ήχου σταμάτησε", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", + "NotificationOptionCameraImageUploaded": "Μεταφορτώθηκε φωτογραφία απο κάμερα", "NotificationOptionInstallationFailed": "Αποτυχία εγκατάστασης", "NotificationOptionNewLibraryContent": "Προστέθηκε νέο περιεχόμενο", "NotificationOptionPluginError": "Αποτυχία του plugin", @@ -75,7 +75,7 @@ "Songs": "Τραγούδια", "StartupEmbyServerIsLoading": "Ο Jellyfin Server φορτώνει. Παρακαλώ δοκιμάστε σε λίγο.", "SubtitleDownloadFailureForItem": "Οι υπότιτλοι απέτυχαν να κατέβουν για {0}", - "SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}", + "SubtitleDownloadFailureFromForItem": "Αποτυχίες μεταφόρτωσης υποτίτλων από {0} για {1}", "SubtitlesDownloadedForItem": "Οι υπότιτλοι κατέβηκαν για {0}", "Sync": "Συγχρονισμός", "System": "Σύστημα", From 8e2827cc39388152ae3d86cf5ec57cc1b4b00753 Mon Sep 17 00:00:00 2001 From: WWWesten Date: Tue, 2 Apr 2019 12:41:49 +0000 Subject: [PATCH 30/35] Translated using Weblate (Kazakh) Currently translated at 100.0% (94 of 94 strings) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/kk/ --- Emby.Server.Implementations/Localization/Core/kk.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/kk.json b/Emby.Server.Implementations/Localization/Core/kk.json index 23841f37d6..cbee711551 100644 --- a/Emby.Server.Implementations/Localization/Core/kk.json +++ b/Emby.Server.Implementations/Localization/Core/kk.json @@ -5,7 +5,7 @@ "Artists": "Oryndaýshylar", "AuthenticationSucceededWithUserName": "{0} túpnusqalyq rastalýy sátti aıaqtaldy", "Books": "Kitaptar", - "CameraImageUploadedFrom": "{0} kamerasynan jańa sýret júktep alyndy", + "CameraImageUploadedFrom": "{0} kamerasynan jańa sýret júktep salyndy", "Channels": "Arnalar", "ChapterNameValue": "{0}-sahna", "Collections": "Jıyntyqtar", @@ -35,8 +35,8 @@ "Latest": "Eń keıingi", "MessageApplicationUpdated": "Jellyfin Serveri jańartyldy", "MessageApplicationUpdatedTo": "Jellyfin Serveri {0} nusqasyna jańartyldy", - "MessageNamedServerConfigurationUpdatedWithValue": "Server teńsheliminiń {0} bólimi jańartyldy", - "MessageServerConfigurationUpdated": "Server teńshelimi jańartyldy", + "MessageNamedServerConfigurationUpdatedWithValue": "Server konfıgýrasýasynyń {0} bólimi jańartyldy", + "MessageServerConfigurationUpdated": "Server konfıgýrasıasy jańartyldy", "MixedContent": "Aralas mazmun", "Movies": "Fılmder", "Music": "Mýzyka", @@ -49,7 +49,7 @@ "NotificationOptionApplicationUpdateInstalled": "Qoldanba jańartýy ornatyldy", "NotificationOptionAudioPlayback": "Dybys oınatýy bastaldy", "NotificationOptionAudioPlaybackStopped": "Dybys oınatýy toqtatyldy", - "NotificationOptionCameraImageUploaded": "Kameradan fotosýret keri qotarylǵan", + "NotificationOptionCameraImageUploaded": "Kameradan fotosýret júktep salynǵan", "NotificationOptionInstallationFailed": "Ornatý sátsizdigi", "NotificationOptionNewLibraryContent": "Jańa mazmun ústelgen", "NotificationOptionPluginError": "Plagın sátsizdigi", From 4886fc467c8cd07fbee2cfc43a2f2c6c71216da1 Mon Sep 17 00:00:00 2001 From: SaddFox Date: Tue, 16 Apr 2019 14:53:26 +0000 Subject: [PATCH 31/35] Translated using Weblate (Slovenian) Currently translated at 100.0% (94 of 94 strings) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/sl/ --- .../Localization/Core/sl-SI.json | 66 +++++++++---------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/sl-SI.json b/Emby.Server.Implementations/Localization/Core/sl-SI.json index b50ff4706e..531dfe51f0 100644 --- a/Emby.Server.Implementations/Localization/Core/sl-SI.json +++ b/Emby.Server.Implementations/Localization/Core/sl-SI.json @@ -9,7 +9,7 @@ "Channels": "Kanali", "ChapterNameValue": "Poglavje {0}", "Collections": "Zbirke", - "DeviceOfflineWithName": "{0} has disconnected", + "DeviceOfflineWithName": "{0} je prekinil povezavo", "DeviceOnlineWithName": "{0} je povezan", "FailedLoginAttemptWithUserName": "Neuspešen poskus prijave z {0}", "Favorites": "Priljubljeni", @@ -33,9 +33,9 @@ "LabelIpAddressValue": "IP naslov: {0}", "LabelRunningTimeValue": "Čas trajanja: {0}", "Latest": "Najnovejše", - "MessageApplicationUpdated": "Jellyfin strežnik je bil posodobljen", - "MessageApplicationUpdatedTo": "Jellyfin strežnik je bil posodobljen na {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", + "MessageApplicationUpdated": "Jellyfin Server je bil posodobljen", + "MessageApplicationUpdatedTo": "Jellyfin Server je bil posodobljen na {0}", + "MessageNamedServerConfigurationUpdatedWithValue": "Oddelek nastavitve strežnika {0} je bil posodobljen", "MessageServerConfigurationUpdated": "Nastavitve strežnika so bile posodobljene", "MixedContent": "Razne vsebine", "Movies": "Filmi", @@ -57,41 +57,41 @@ "NotificationOptionPluginUninstalled": "Dodatek odstranjen", "NotificationOptionPluginUpdateInstalled": "Posodobitev dodatka nameščena", "NotificationOptionServerRestartRequired": "Potreben je ponovni zagon strežnika", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionVideoPlayback": "Video playback started", - "NotificationOptionVideoPlaybackStopped": "Video playback stopped", - "Photos": "Photos", - "Playlists": "Playlists", + "NotificationOptionTaskFailed": "Razporejena naloga neuspešna", + "NotificationOptionUserLockedOut": "Uporabnik zaklenjen", + "NotificationOptionVideoPlayback": "Predvajanje videa se je začelo", + "NotificationOptionVideoPlaybackStopped": "Predvajanje videa se je ustavilo", + "Photos": "Fotografije", + "Playlists": "Seznami predvajanja", "Plugin": "Plugin", - "PluginInstalledWithName": "{0} was installed", - "PluginUninstalledWithName": "{0} was uninstalled", - "PluginUpdatedWithName": "{0} was updated", + "PluginInstalledWithName": "{0} je bil nameščen", + "PluginUninstalledWithName": "{0} je bil odstranjen", + "PluginUpdatedWithName": "{0} je bil posodobljen", "ProviderValue": "Provider: {0}", - "ScheduledTaskFailedWithName": "{0} failed", - "ScheduledTaskStartedWithName": "{0} started", - "ServerNameNeedsToBeRestarted": "{0} needs to be restarted", + "ScheduledTaskFailedWithName": "{0} ni uspelo", + "ScheduledTaskStartedWithName": "{0} začeto", + "ServerNameNeedsToBeRestarted": "{0} mora biti ponovno zagnan", "Shows": "Serije", - "Songs": "Songs", - "StartupEmbyServerIsLoading": "Jellyfin Server is loading. Please try again shortly.", + "Songs": "Pesmi", + "StartupEmbyServerIsLoading": "Jellyfin Server se nalaga. Poskusi ponovno kasneje.", "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "Sync": "Sync", + "SubtitleDownloadFailureFromForItem": "Neuspešen prenos podnapisov iz {0} za {1}", + "SubtitlesDownloadedForItem": "Podnapisi preneseni za {0}", + "Sync": "Sinhroniziraj", "System": "System", - "TvShows": "TV Shows", + "TvShows": "TV serije", "User": "User", - "UserCreatedWithName": "User {0} has been created", - "UserDeletedWithName": "User {0} has been deleted", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserOnlineFromDevice": "{0} is online from {1}", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserPolicyUpdatedWithName": "User policy has been updated for {0}", - "UserStartedPlayingItemWithValues": "{0} is playing {1} on {2}", - "UserStoppedPlayingItemWithValues": "{0} has finished playing {1} on {2}", - "ValueHasBeenAddedToLibrary": "{0} has been added to your media library", + "UserCreatedWithName": "Uporabnik {0} je bil ustvarjen", + "UserDeletedWithName": "Uporabnik {0} je bil izbrisan", + "UserDownloadingItemWithValues": "{0} prenaša {1}", + "UserLockedOutWithName": "Uporabnik {0} je bil zaklenjen", + "UserOfflineFromDevice": "{0} je prekinil povezavo z {1}", + "UserOnlineFromDevice": "{0} je aktiven iz {1}", + "UserPasswordChangedWithName": "Geslo za uporabnika {0} je bilo spremenjeno", + "UserPolicyUpdatedWithName": "Pravilnik uporabe je bil posodobljen za uporabnika {0}", + "UserStartedPlayingItemWithValues": "{0} predvaja {1} na {2}", + "UserStoppedPlayingItemWithValues": "{0} je nehal predvajati {1} na {2}", + "ValueHasBeenAddedToLibrary": "{0} je bil dodan vaši knjižnici", "ValueSpecialEpisodeName": "Special - {0}", "VersionNumber": "Version {0}" } From 10cbdc8e8e624301c2edb1598491cd6493b1644a Mon Sep 17 00:00:00 2001 From: Heldenkrieger01 Date: Tue, 9 Apr 2019 17:16:35 +0000 Subject: [PATCH 32/35] Translated using Weblate (Swiss German) Currently translated at 100.0% (94 of 94 strings) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/gsw/ --- .../Localization/Core/gsw.json | 166 +++++++++--------- 1 file changed, 83 insertions(+), 83 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/gsw.json b/Emby.Server.Implementations/Localization/Core/gsw.json index 728002a560..69c1574014 100644 --- a/Emby.Server.Implementations/Localization/Core/gsw.json +++ b/Emby.Server.Implementations/Localization/Core/gsw.json @@ -1,97 +1,97 @@ { - "Albums": "Albums", - "AppDeviceValues": "App: {0}, Device: {1}", - "Application": "Application", - "Artists": "Artists", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", + "Albums": "Albom", + "AppDeviceValues": "App: {0}, Grät: {1}", + "Application": "Aawändig", + "Artists": "Könstler", + "AuthenticationSucceededWithUserName": "{0} het sech aagmäudet", "Books": "Büecher", - "CameraImageUploadedFrom": "A new camera image has been uploaded from {0}", - "Channels": "Channels", - "ChapterNameValue": "Chapter {0}", - "Collections": "Collections", - "DeviceOfflineWithName": "{0} has disconnected", - "DeviceOnlineWithName": "{0} is connected", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "Favorites": "Favorites", - "Folders": "Folders", + "CameraImageUploadedFrom": "Es nöis Foti esch ufeglade worde vo {0}", + "Channels": "Kanäu", + "ChapterNameValue": "Kapitu {0}", + "Collections": "Sammlige", + "DeviceOfflineWithName": "{0} esch offline gange", + "DeviceOnlineWithName": "{0} esch online cho", + "FailedLoginAttemptWithUserName": "Fäugschlagne Aamäudeversuech vo {0}", + "Favorites": "Favorite", + "Folders": "Ordner", "Genres": "Genres", - "HeaderAlbumArtists": "Albuminterprete", - "HeaderCameraUploads": "Camera Uploads", + "HeaderAlbumArtists": "Albom-Könstler", + "HeaderCameraUploads": "Kamera-Uploads", "HeaderContinueWatching": "Wiiterluege", - "HeaderFavoriteAlbums": "Favorite Albums", - "HeaderFavoriteArtists": "Besti Interpret", - "HeaderFavoriteEpisodes": "Favorite Episodes", - "HeaderFavoriteShows": "Favorite Shows", - "HeaderFavoriteSongs": "Besti Lieder", - "HeaderLiveTV": "Live TV", - "HeaderNextUp": "Next Up", + "HeaderFavoriteAlbums": "Lieblingsalbe", + "HeaderFavoriteArtists": "Lieblings-Interprete", + "HeaderFavoriteEpisodes": "Lieblingsepisode", + "HeaderFavoriteShows": "Lieblingsserie", + "HeaderFavoriteSongs": "Lieblingslieder", + "HeaderLiveTV": "Live-Färnseh", + "HeaderNextUp": "Als nächts", "HeaderRecordingGroups": "Ufnahmegruppe", "HomeVideos": "Heimfilmli", "Inherit": "Hinzuefüege", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "LabelRunningTimeValue": "Running time: {0}", - "Latest": "Letschte", - "MessageApplicationUpdated": "Jellyfin Server has been updated", - "MessageApplicationUpdatedTo": "Jellyfin Server has been updated to {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MixedContent": "Gmischte Inhalt", - "Movies": "Movies", + "ItemAddedWithName": "{0} esch de Bibliothek dezuegfüegt worde", + "ItemRemovedWithName": "{0} esch vo de Bibliothek entfärnt worde", + "LabelIpAddressValue": "IP-Adrässe: {0}", + "LabelRunningTimeValue": "Loufziit: {0}", + "Latest": "Nöischti", + "MessageApplicationUpdated": "Jellyfin Server esch aktualisiert worde", + "MessageApplicationUpdatedTo": "Jellyfin Server esch of Version {0} aktualisiert worde", + "MessageNamedServerConfigurationUpdatedWithValue": "De Serveriistöuigsberiich {0} esch aktualisiert worde", + "MessageServerConfigurationUpdated": "Serveriistöuige send aktualisiert worde", + "MixedContent": "Gmeschti Inhäut", + "Movies": "Film", "Music": "Musig", - "MusicVideos": "Musigfilm", - "NameInstallFailed": "{0} installation failed", - "NameSeasonNumber": "Season {0}", - "NameSeasonUnknown": "Season Unknown", - "NewVersionIsAvailable": "A new version of Jellyfin Server is available for download.", - "NotificationOptionApplicationUpdateAvailable": "Application update available", - "NotificationOptionApplicationUpdateInstalled": "Application update installed", - "NotificationOptionAudioPlayback": "Audio playback started", - "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionInstallationFailed": "Installation failure", - "NotificationOptionNewLibraryContent": "New content added", - "NotificationOptionPluginError": "Plugin failure", - "NotificationOptionPluginInstalled": "Plugin installed", - "NotificationOptionPluginUninstalled": "Plugin uninstalled", - "NotificationOptionPluginUpdateInstalled": "Plugin update installed", - "NotificationOptionServerRestartRequired": "Server restart required", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionVideoPlayback": "Video playback started", - "NotificationOptionVideoPlaybackStopped": "Video playback stopped", + "MusicVideos": "Musigvideos", + "NameInstallFailed": "Installation vo {0} fäugschlage", + "NameSeasonNumber": "Staffle {0}", + "NameSeasonUnknown": "Staffle unbekannt", + "NewVersionIsAvailable": "E nöi Version vo Jellyfin Server esch zom Download parat.", + "NotificationOptionApplicationUpdateAvailable": "Aawändigsupdate verfüegbar", + "NotificationOptionApplicationUpdateInstalled": "Aawändigsupdate installiert", + "NotificationOptionAudioPlayback": "Audiowedergab gstartet", + "NotificationOptionAudioPlaybackStopped": "Audiwedergab gstoppt", + "NotificationOptionCameraImageUploaded": "Foti ueglade", + "NotificationOptionInstallationFailed": "Installationsfäuer", + "NotificationOptionNewLibraryContent": "Nöie Inhaut hinzuegfüegt", + "NotificationOptionPluginError": "Plugin-Fäuer", + "NotificationOptionPluginInstalled": "Plugin installiert", + "NotificationOptionPluginUninstalled": "Plugin deinstalliert", + "NotificationOptionPluginUpdateInstalled": "Pluginupdate installiert", + "NotificationOptionServerRestartRequired": "Serverneustart notwändig", + "NotificationOptionTaskFailed": "Planti Uufgab fäugschlage", + "NotificationOptionUserLockedOut": "Benotzer usgschlosse", + "NotificationOptionVideoPlayback": "Videowedergab gstartet", + "NotificationOptionVideoPlaybackStopped": "Videowedergab gstoppt", "Photos": "Fotis", - "Playlists": "Abspielliste", + "Playlists": "Wedergabeliste", "Plugin": "Plugin", - "PluginInstalledWithName": "{0} was installed", - "PluginUninstalledWithName": "{0} was uninstalled", - "PluginUpdatedWithName": "{0} was updated", - "ProviderValue": "Provider: {0}", - "ScheduledTaskFailedWithName": "{0} failed", - "ScheduledTaskStartedWithName": "{0} started", - "ServerNameNeedsToBeRestarted": "{0} needs to be restarted", - "Shows": "Shows", - "Songs": "Songs", - "StartupEmbyServerIsLoading": "Jellyfin Server is loading. Please try again shortly.", + "PluginInstalledWithName": "{0} esch installiert worde", + "PluginUninstalledWithName": "{0} esch deinstalliert worde", + "PluginUpdatedWithName": "{0} esch updated worde", + "ProviderValue": "Aabieter: {0}", + "ScheduledTaskFailedWithName": "{0} esch fäugschlage", + "ScheduledTaskStartedWithName": "{0} het gstartet", + "ServerNameNeedsToBeRestarted": "{0} mues nöi gstartet wärde", + "Shows": "Serie", + "Songs": "Lieder", + "StartupEmbyServerIsLoading": "Jellyfin Server ladt. Bitte grad noeinisch probiere.", "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "Sync": "Sync", + "SubtitleDownloadFailureFromForItem": "Ondertetle vo {0} för {1} hend ned chönne abeglade wärde", + "SubtitlesDownloadedForItem": "Ondertetle abeglade för {0}", + "Sync": "Synchronisation", "System": "System", - "TvShows": "TV Shows", - "User": "User", - "UserCreatedWithName": "User {0} has been created", - "UserDeletedWithName": "User {0} has been deleted", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserOnlineFromDevice": "{0} is online from {1}", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserPolicyUpdatedWithName": "User policy has been updated for {0}", - "UserStartedPlayingItemWithValues": "{0} is playing {1} on {2}", - "UserStoppedPlayingItemWithValues": "{0} has finished playing {1} on {2}", - "ValueHasBeenAddedToLibrary": "{0} has been added to your media library", - "ValueSpecialEpisodeName": "Spezial - {0}", + "TvShows": "Färnsehserie", + "User": "Benotzer", + "UserCreatedWithName": "Benotzer {0} esch erstöut worde", + "UserDeletedWithName": "Benotzer {0} esch glösche worde", + "UserDownloadingItemWithValues": "{0} ladt {1} abe", + "UserLockedOutWithName": "Benotzer {0} esch usgschlosse worde", + "UserOfflineFromDevice": "{0} esch vo {1} trennt worde", + "UserOnlineFromDevice": "{0} esch online vo {1}", + "UserPasswordChangedWithName": "S'Passwort för Benotzer {0} esch gänderet worde", + "UserPolicyUpdatedWithName": "Benotzerrechtlinie för {0} esch aktualisiert worde", + "UserStartedPlayingItemWithValues": "{0} hed d'Wedergab vo {1} of {2} gstartet", + "UserStoppedPlayingItemWithValues": "{0} het d'Wedergab vo {1} of {2} gstoppt", + "ValueHasBeenAddedToLibrary": "{0} esch dinnere Biblithek hinzuegfüegt worde", + "ValueSpecialEpisodeName": "Extra - {0}", "VersionNumber": "Version {0}" } From 4a6243096afa9215392c4b2671c84e76eaf0d0b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Libor=20Fil=C3=ADpek?= Date: Fri, 19 Apr 2019 17:30:29 +0000 Subject: [PATCH 33/35] Translated using Weblate (Czech) Currently translated at 100.0% (94 of 94 strings) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/cs/ --- Emby.Server.Implementations/Localization/Core/cs.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/cs.json b/Emby.Server.Implementations/Localization/Core/cs.json index c2a101a4da..c19148921b 100644 --- a/Emby.Server.Implementations/Localization/Core/cs.json +++ b/Emby.Server.Implementations/Localization/Core/cs.json @@ -19,10 +19,10 @@ "HeaderCameraUploads": "Nahrané fotografie", "HeaderContinueWatching": "Pokračovat ve sledování", "HeaderFavoriteAlbums": "Oblíbená alba", - "HeaderFavoriteArtists": "Oblíbení umělci", + "HeaderFavoriteArtists": "Oblíbení interpreti", "HeaderFavoriteEpisodes": "Oblíbené epizody", "HeaderFavoriteShows": "Oblíbené seriály", - "HeaderFavoriteSongs": "Oblíbené písně", + "HeaderFavoriteSongs": "Oblíbená hudba", "HeaderLiveTV": "Live TV", "HeaderNextUp": "Nadcházející", "HeaderRecordingGroups": "Skupiny nahrávek", From 9d60cc8c660c47df110d8118975410f86a5a7484 Mon Sep 17 00:00:00 2001 From: Weblate Date: Fri, 19 Apr 2019 13:59:04 -0400 Subject: [PATCH 34/35] Rename Chinese (Traditional) file --- .../Localization/Core/{zh_Hant.json => zh-TW.json} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Emby.Server.Implementations/Localization/Core/{zh_Hant.json => zh-TW.json} (100%) diff --git a/Emby.Server.Implementations/Localization/Core/zh_Hant.json b/Emby.Server.Implementations/Localization/Core/zh-TW.json similarity index 100% rename from Emby.Server.Implementations/Localization/Core/zh_Hant.json rename to Emby.Server.Implementations/Localization/Core/zh-TW.json From 46c37c0ae8d5b5de02ff6f8208a7b91436f54237 Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Fri, 19 Apr 2019 14:25:29 -0400 Subject: [PATCH 35/35] Bump version to 10.3.0 (release) --- Dockerfile | 2 +- Dockerfile.arm | 2 +- Dockerfile.arm64 | 2 +- MediaBrowser.WebDashboard/jellyfin-web | 2 +- build.yaml | 2 +- deployment/debian-package-x64/pkg-src/changelog | 12 +++--------- deployment/fedora-package-x64/pkg-src/jellyfin.spec | 6 ++---- 7 files changed, 10 insertions(+), 18 deletions(-) diff --git a/Dockerfile b/Dockerfile index 36fc43983e..050f8fc49f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,7 +21,7 @@ RUN apt-get update \ COPY --from=ffmpeg / / COPY --from=builder /jellyfin /jellyfin -ARG JELLYFIN_WEB_VERSION=10.3.0-rc2 +ARG JELLYFIN_WEB_VERSION=10.3.0 RUN curl -L https://github.com/jellyfin/jellyfin-web/archive/v${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \ && rm -rf /jellyfin/jellyfin-web \ && mv jellyfin-web-${JELLYFIN_WEB_VERSION} /jellyfin/jellyfin-web diff --git a/Dockerfile.arm b/Dockerfile.arm index c896d83f27..81089b5196 100644 --- a/Dockerfile.arm +++ b/Dockerfile.arm @@ -30,7 +30,7 @@ RUN apt-get update \ && chmod 777 /cache /config /media COPY --from=builder /jellyfin /jellyfin -ARG JELLYFIN_WEB_VERSION=10.3.0-rc2 +ARG JELLYFIN_WEB_VERSION=10.3.0 RUN curl -L https://github.com/jellyfin/jellyfin-web/archive/v${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \ && rm -rf /jellyfin/jellyfin-web \ && mv jellyfin-web-${JELLYFIN_WEB_VERSION} /jellyfin/jellyfin-web diff --git a/Dockerfile.arm64 b/Dockerfile.arm64 index 09c9dc12f8..1ad4dc5a28 100644 --- a/Dockerfile.arm64 +++ b/Dockerfile.arm64 @@ -31,7 +31,7 @@ RUN apt-get update \ && chmod 777 /cache /config /media COPY --from=builder /jellyfin /jellyfin -ARG JELLYFIN_WEB_VERSION=10.3.0-rc2 +ARG JELLYFIN_WEB_VERSION=10.3.0 RUN curl -L https://github.com/jellyfin/jellyfin-web/archive/v${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \ && rm -rf /jellyfin/jellyfin-web \ && mv jellyfin-web-${JELLYFIN_WEB_VERSION} /jellyfin/jellyfin-web diff --git a/MediaBrowser.WebDashboard/jellyfin-web b/MediaBrowser.WebDashboard/jellyfin-web index e07edea5bf..874b51234e 160000 --- a/MediaBrowser.WebDashboard/jellyfin-web +++ b/MediaBrowser.WebDashboard/jellyfin-web @@ -1 +1 @@ -Subproject commit e07edea5bf22c253fc7ee91f45879d8ee2d1bf17 +Subproject commit 874b51234ee4e1f01e2e7410980a1003f316d6a2 diff --git a/build.yaml b/build.yaml index ccd7ce8f85..47ca589f8b 100644 --- a/build.yaml +++ b/build.yaml @@ -1,7 +1,7 @@ --- # We just wrap `build` so this is really it name: "jellyfin" -version: "10.3.0-rc2" +version: "10.3.0" packages: - debian-package-x64 - debian-package-armhf diff --git a/deployment/debian-package-x64/pkg-src/changelog b/deployment/debian-package-x64/pkg-src/changelog index 65880620dc..3908c277b3 100644 --- a/deployment/debian-package-x64/pkg-src/changelog +++ b/deployment/debian-package-x64/pkg-src/changelog @@ -1,14 +1,8 @@ -jellyfin (10.3.0~rc2) unstable; urgency=medium +jellyfin (10.3.0-1) unstable; urgency=medium - * New upstream version 10.3.0-rc2; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.3.0-rc2 + * New upstream version 10.3.0; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.3.0 - -- Jellyfin Packaging Team Wed, 10 Apr 2019 00:51:14 -0400 - -jellyfin (10.3.0~rc1) unstable; urgency=medium - - * New upstream version 10.3.0-rc1; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.3.0-rc1 - - -- Jellyfin Packaging Team Sat, 30 Mar 2019 15:47:24 -0400 + -- Jellyfin Packaging Team Fri, 19 Apr 2019 14:24:29 -0400 jellyfin (10.2.2-1) unstable; urgency=medium diff --git a/deployment/fedora-package-x64/pkg-src/jellyfin.spec b/deployment/fedora-package-x64/pkg-src/jellyfin.spec index 581d926fbf..36fe78c628 100644 --- a/deployment/fedora-package-x64/pkg-src/jellyfin.spec +++ b/deployment/fedora-package-x64/pkg-src/jellyfin.spec @@ -140,10 +140,8 @@ fi %systemd_postun_with_restart jellyfin.service %changelog -* Wed Apr 10 2019 Jellyfin Packaging Team -- New upstream version 10.3.0-rc2; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.3.0-rc2 -* Sat Mar 30 2019 Jellyfin Packaging Team -- New upstream version 10.3.0-rc1; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.3.0-rc1 +* Fri Apr 19 2019 Jellyfin Packaging Team +- New upstream version 10.3.0; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.3.0 * Thu Feb 28 2019 Jellyfin Packaging Team - jellyfin: - PR968 Release 10.2.z copr autobuild