diff --git a/Dockerfile b/Dockerfile index 5794bdde1e..050f8fc49f 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 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..81089b5196 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 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..1ad4dc5a28 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 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/Emby.Dlna/Images/logo120.png b/Emby.Dlna/Images/logo120.png index 321c477292..14f6c8d5f6 100644 Binary files a/Emby.Dlna/Images/logo120.png and b/Emby.Dlna/Images/logo120.png differ diff --git a/Emby.Dlna/Images/logo240.png b/Emby.Dlna/Images/logo240.png index 64c8281299..ff50314d44 100644 Binary files a/Emby.Dlna/Images/logo240.png and b/Emby.Dlna/Images/logo240.png differ diff --git a/Emby.Dlna/Images/logo48.png b/Emby.Dlna/Images/logo48.png index b8fc145647..d6b5fd1df1 100644 Binary files a/Emby.Dlna/Images/logo48.png and b/Emby.Dlna/Images/logo48.png differ diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 0ebbeea57e..aa0fdde2d8 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1025,8 +1025,8 @@ 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) + 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) .Where(x => x.IsClass && !x.IsAbstract && !x.IsInterface && !x.IsGenericType) @@ -1325,7 +1325,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); @@ -1404,7 +1404,6 @@ namespace Emby.Server.Implementations HasPendingRestart = HasPendingRestart, IsShuttingDown = IsShuttingDown, Version = ApplicationVersion, - ProductName = ApplicationProductName, WebSocketPortNumber = HttpPort, CompletedInstallations = InstallationManager.CompletedInstallations.ToArray(), Id = SystemId, @@ -1461,6 +1460,7 @@ namespace Emby.Server.Implementations return new PublicSystemInfo { Version = ApplicationVersion, + ProductName = ApplicationProductName, Id = SystemId, OperatingSystem = OperatingSystem.Id.ToString(), WanAddress = wanAddress, 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"); } /// diff --git a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs index 79b8f52d78..06d304077d 100644 --- a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -201,6 +201,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; } 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) diff --git a/Emby.Server.Implementations/Localization/Core/cs.json b/Emby.Server.Implementations/Localization/Core/cs.json index a8b4a44244..c19148921b 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", + "HeaderFavoriteArtists": "Oblíbení interpreti", "HeaderFavoriteEpisodes": "Oblíbené epizody", "HeaderFavoriteShows": "Oblíbené seriály", - "HeaderFavoriteSongs": "Oblíbené písně", - "HeaderLiveTV": "Živá TV", + "HeaderFavoriteSongs": "Oblíbená hudba", + "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}" } 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", 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": "Σύστημα", 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}" } 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", 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}" } diff --git a/Emby.Server.Implementations/Localization/Core/zh-TW.json b/Emby.Server.Implementations/Localization/Core/zh-TW.json new file mode 100644 index 0000000000..effff5566e --- /dev/null +++ b/Emby.Server.Implementations/Localization/Core/zh-TW.json @@ -0,0 +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}" +} 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) diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 7310de55d4..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); @@ -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,13 @@ namespace Emby.Server.Implementations.Updates _applicationHost.RemovePlugin(plugin); var path = plugin.AssemblyFilePath; - _logger.LogInformation("Deleting plugin file {0}", path); + 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); + isDirectory = true; + } // Make this case-insensitive to account for possible incorrect assembly naming var file = _fileSystem.GetFilePaths(Path.GetDirectoryName(path)) @@ -585,7 +602,16 @@ namespace Emby.Server.Implementations.Updates path = file; } - _fileSystem.DeleteFile(path); + if (isDirectory) + { + _logger.LogInformation("Deleting plugin directory {0}", path); + Directory.Delete(path, true); + } + else + { + _logger.LogInformation("Deleting plugin file {0}", path); + _fileSystem.DeleteFile(path); + } var list = _config.Configuration.UninstalledPlugins.ToList(); var filename = Path.GetFileName(path); diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs index a6849f75f5..497800d263 100644 --- a/MediaBrowser.Api/UserService.cs +++ b/MediaBrowser.Api/UserService.cs @@ -379,10 +379,15 @@ namespace MediaBrowser.Api throw new ResourceNotFoundException("User not found"); } + if (!string.IsNullOrEmpty(request.Password) && string.IsNullOrEmpty(request.Pw)) + { + throw new MethodNotAllowedException("Hashed-only passwords are not valid for this API."); + } + return Post(new AuthenticateUserByName { Username = user.Name, - Password = request.Password, + Password = null, // This should always be null Pw = request.Pw }); } 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() 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)) 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. diff --git a/MediaBrowser.WebDashboard/jellyfin-web b/MediaBrowser.WebDashboard/jellyfin-web index ec5a3b6e5e..874b51234e 160000 --- a/MediaBrowser.WebDashboard/jellyfin-web +++ b/MediaBrowser.WebDashboard/jellyfin-web @@ -1 +1 @@ -Subproject commit ec5a3b6e5efb6041153b92818aee562f20ee994d +Subproject commit 874b51234ee4e1f01e2e7410980a1003f316d6a2 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..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.2.2" +version: "10.3.0" packages: - debian-package-x64 - debian-package-armhf 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 diff --git a/deployment/debian-package-x64/pkg-src/changelog b/deployment/debian-package-x64/pkg-src/changelog index 349e8787f6..3908c277b3 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-1) unstable; urgency=medium + + * New upstream version 10.3.0; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.3.0 + + -- Jellyfin Packaging Team Fri, 19 Apr 2019 14:24:29 -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..36fe78c628 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 +* 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 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 } diff --git a/deployment/windows/install-jellyfin.ps1 b/deployment/windows/install-jellyfin.ps1 index b6e00e0568..0cd7f5236f 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\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} @@ -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