Compare commits

...

52 Commits

Author SHA1 Message Date
Joshua Boniface 696a36b4a5 Update submodule for 10.3.1 2019-04-20 15:59:50 -04:00
Joshua Boniface 5fb4922c6f Bump version to 10.3.1 2019-04-20 14:24:40 -04:00
Joshua M. Boniface 3738f95871 Merge pull request #1258 from Bond-009/fixpluginload
Handle exception when loading unsupported assembly
2019-04-20 12:35:57 -04:00
Joshua M. Boniface 6797bdec04 Merge pull request #1264 from jellyfin/fix-empty-pw-migration
Fix comparison for empty password migration
2019-04-20 12:20:22 -04:00
Claus Vium 764c6d5461 Fix comparison for empty password migration 2019-04-20 17:50:34 +02:00
Bond-009 6973182ade Fix more possible exceptions 2019-04-20 17:47:11 +02:00
Bond-009 f62af07381 Handle exception when loading unsupported assembly
Fixes #1256
2019-04-20 17:47:11 +02:00
Joshua Boniface 46c37c0ae8 Bump version to 10.3.0 (release) 2019-04-19 14:25:29 -04:00
Joshua Boniface 4ad71766fc Merge branch 'translations' into release-10.3.z 2019-04-19 14:19:22 -04:00
Weblate 9d60cc8c66 Rename Chinese (Traditional) file 2019-04-19 13:59:04 -04:00
Libor Filípek 4a6243096a 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/
2019-04-19 13:38:32 -04:00
Heldenkrieger01 10cbdc8e8e 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/
2019-04-19 12:09:39 -04:00
SaddFox 4886fc467c 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/
2019-04-19 12:09:38 -04:00
WWWesten 8e2827cc39 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/
2019-04-19 12:09:37 -04:00
Βασίλης Μουρατίδης 395d2e4917 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/
2019-04-19 12:09:37 -04:00
Dan Johansen d31f5229da 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/
2019-04-19 12:09:37 -04:00
Libor Filípek d6622818dc 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/
2019-04-19 12:09:37 -04:00
tinganhsu ba684d6d3a 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/
2019-04-19 12:09:36 -04:00
tinganhsu 90c04a4640 Added translation using Weblate (Chinese (Traditional)) 2019-04-19 00:32:52 -04:00
Joshua M. Boniface 06a1e1f166 Merge pull request #1244 from joshuaboniface/hotfix-authapi
Hotfix authapi
2019-04-18 17:58:54 -04:00
Joshua Boniface 31ad366aa9 Implemented suggested conditional 2019-04-18 10:24:08 -04:00
Joshua Boniface 10f33b0273 Update conditional to be correct 2019-04-18 09:31:30 -04:00
Joshua Boniface eaa1ac8013 Apparently strings can't be !'d 2019-04-17 22:49:17 -04:00
Joshua Boniface ca3bb308b3 Add the proper Class too 2019-04-17 22:46:26 -04:00
Joshua Boniface e790f024c2 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.
2019-04-17 22:33:00 -04:00
Joshua Boniface 250e0c75df Add MethodNotAllowedException with code 405 2019-04-17 22:31:06 -04:00
Joshua M. Boniface cde7375049 Merge pull request #1242 from Bond-009/metadata
Fix metadata path save
2019-04-17 09:26:04 -04:00
Bond_009 c7fedfbca3 Fix metadata path save 2019-04-17 15:09:31 +02:00
Bond-009 f520831025 Merge pull request #1239 from anthonylavado/fix-ident
Clean up UDP responders, and move ProductName to Public endpoint
2019-04-16 11:56:38 +02:00
Anthony Lavado 2f0719a883 Move the definition of ProductName to the correct class
Missed moving this from one class to the other.
2019-04-16 01:38:00 -04:00
Anthony Lavado 34ab99caf1 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
2019-04-16 01:16:02 -04:00
Anthony Lavado b2f94c0e40 Remove the old message responders
Leaves only an answer to "Who is Jellyfin", removing older ones for
EmbyServer and MediaBrowser_v2.
2019-04-15 00:21:14 -04:00
Joshua Boniface 65bff1181a Bump version to 10.3.0-rc2 and update submodule 2019-04-10 00:51:21 -04:00
Joshua Boniface efb14f0b58 Bump dockerfile web versions too 2019-04-10 00:49:33 -04:00
Joshua M. Boniface 75a4f04cce Merge pull request #1209 from joshuaboniface/hotfix-authprovider-create
Override username with AuthenticationProvider
2019-04-10 00:18:08 -04:00
Joshua M. Boniface 007fe34363 Merge pull request #1221 from LogicalPhallacy/ffmpegdetection
Make Jellyfin search its base dir for ffmpeg
2019-04-09 23:57:20 -04:00
Phallacy a7e31ef31f applied changes to just also search jellyfin base dir 2019-04-09 00:27:41 -07:00
Joshua M. Boniface eae0c28e6d Merge pull request #1178 from jellyfin/LogicalPhallacy-patch-1
Updates windows installer default lib location
2019-04-08 18:44:43 -04:00
Joshua M. Boniface 21950382b9 Merge pull request #1188 from joshuaboniface/hotfix-pluginload
Fix problems with plugin installation
2019-04-08 11:24:53 -04:00
Joshua Boniface 1af9c047fb 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.
2019-04-07 19:51:45 -04:00
Joshua M. Boniface 2d19bfa7fb Merge pull request #1199 from jftuga/use_tls12_for_nssm
Use TLS 1.2 to download NSSM
2019-04-07 02:48:59 -04:00
John Taylor f5f7de64de Use TLS 1.2 to download NSSM 2019-04-06 13:40:19 -04:00
Joshua Boniface 754e76a61b Add TODO to remove string target 2019-04-04 02:34:23 -04:00
Joshua Boniface 09505e0988 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.
2019-04-04 01:54:31 -04:00
Anthony Lavado 67e206fa0f Merge pull request #1195 from nvllsvm/optimize
Optimize images with image_optim
2019-04-04 01:16:49 -04:00
Andrew Rabert 608fd873de Optimize images with image_optim 2019-04-03 22:58:52 -04:00
Joshua Boniface 05a4161fd3 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.
2019-04-03 20:05:14 -04:00
Vasily 05040351dc Merge pull request #1190 from jellyfin/updates
Update Dockerfiles
2019-04-03 18:05:59 +03:00
Andrew Rabert d75324afc9 Update Dockerfiles
* Use new dotnet image paths
* Update jellyfin-web to 10.3.0-rc1
2019-04-03 01:21:28 -04:00
Joshua Boniface 38fcd31917 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.
2019-04-02 18:29:14 -04:00
LogicalPhallacy 816d8a0216 Update install-jellyfin.ps1 2019-03-31 10:34:49 -07:00
LogicalPhallacy e37ccd6ec0 Updates windows installer default lib location
You can use the emby import to move an existing library this way.
2019-03-31 10:32:56 -07:00
33 changed files with 437 additions and 213 deletions
+4 -4
View File
@@ -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 WORKDIR /repo
COPY . . COPY . .
ENV DOTNET_CLI_TELEMETRY_OPTOUT=1 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" build_jellyfin Jellyfin.Server Release linux-x64 /jellyfin"
FROM jellyfin/ffmpeg as ffmpeg 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 # libfontconfig1 is required for Skia
RUN apt-get update \ RUN apt-get update \
&& apt-get install --no-install-recommends --no-install-suggests -y \ && apt-get install --no-install-recommends --no-install-suggests -y \
@@ -21,7 +21,7 @@ RUN apt-get update \
COPY --from=ffmpeg / / COPY --from=ffmpeg / /
COPY --from=builder /jellyfin /jellyfin COPY --from=builder /jellyfin /jellyfin
ARG JELLYFIN_WEB_VERSION=10.2.2 ARG JELLYFIN_WEB_VERSION=10.3.1
RUN curl -L https://github.com/jellyfin/jellyfin-web/archive/v${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \ RUN curl -L https://github.com/jellyfin/jellyfin-web/archive/v${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \
&& rm -rf /jellyfin/jellyfin-web \ && rm -rf /jellyfin/jellyfin-web \
&& mv jellyfin-web-${JELLYFIN_WEB_VERSION} /jellyfin/jellyfin-web && mv jellyfin-web-${JELLYFIN_WEB_VERSION} /jellyfin/jellyfin-web
+3 -3
View File
@@ -8,7 +8,7 @@ FROM alpine as qemu_extract
COPY --from=qemu /usr/bin qemu-arm-static.tar.gz COPY --from=qemu /usr/bin qemu-arm-static.tar.gz
RUN tar -xzvf 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 WORKDIR /repo
COPY . . COPY . .
ENV DOTNET_CLI_TELEMETRY_OPTOUT=1 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" 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 COPY --from=qemu_extract qemu-arm-static /usr/bin
RUN apt-get update \ RUN apt-get update \
&& apt-get install --no-install-recommends --no-install-suggests -y ffmpeg \ && apt-get install --no-install-recommends --no-install-suggests -y ffmpeg \
@@ -30,7 +30,7 @@ RUN apt-get update \
&& chmod 777 /cache /config /media && chmod 777 /cache /config /media
COPY --from=builder /jellyfin /jellyfin COPY --from=builder /jellyfin /jellyfin
ARG JELLYFIN_WEB_VERSION=10.2.2 ARG JELLYFIN_WEB_VERSION=10.3.1
RUN curl -L https://github.com/jellyfin/jellyfin-web/archive/v${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \ RUN curl -L https://github.com/jellyfin/jellyfin-web/archive/v${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \
&& rm -rf /jellyfin/jellyfin-web \ && rm -rf /jellyfin/jellyfin-web \
&& mv jellyfin-web-${JELLYFIN_WEB_VERSION} /jellyfin/jellyfin-web && mv jellyfin-web-${JELLYFIN_WEB_VERSION} /jellyfin/jellyfin-web
+3 -3
View File
@@ -9,7 +9,7 @@ COPY --from=qemu /usr/bin qemu-aarch64-static.tar.gz
RUN tar -xzvf 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 WORKDIR /repo
COPY . . COPY . .
ENV DOTNET_CLI_TELEMETRY_OPTOUT=1 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" 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 COPY --from=qemu_extract qemu-aarch64-static /usr/bin
RUN apt-get update \ RUN apt-get update \
&& apt-get install --no-install-recommends --no-install-suggests -y ffmpeg \ && apt-get install --no-install-recommends --no-install-suggests -y ffmpeg \
@@ -31,7 +31,7 @@ RUN apt-get update \
&& chmod 777 /cache /config /media && chmod 777 /cache /config /media
COPY --from=builder /jellyfin /jellyfin COPY --from=builder /jellyfin /jellyfin
ARG JELLYFIN_WEB_VERSION=10.2.2 ARG JELLYFIN_WEB_VERSION=10.3.1
RUN curl -L https://github.com/jellyfin/jellyfin-web/archive/v${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \ RUN curl -L https://github.com/jellyfin/jellyfin-web/archive/v${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \
&& rm -rf /jellyfin/jellyfin-web \ && rm -rf /jellyfin/jellyfin-web \
&& mv jellyfin-web-${JELLYFIN_WEB_VERSION} /jellyfin/jellyfin-web && mv jellyfin-web-${JELLYFIN_WEB_VERSION} /jellyfin/jellyfin-web
Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

+44 -11
View File
@@ -1046,8 +1046,8 @@ namespace Emby.Server.Implementations
private async void PluginInstalled(object sender, GenericEventArgs<PackageVersionInfo> args) private async void PluginInstalled(object sender, GenericEventArgs<PackageVersionInfo> 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.TopDirectoryOnly) var types = Directory.EnumerateFiles(dir, "*.dll", SearchOption.AllDirectories)
.Select(x => Assembly.LoadFrom(x)) .Select(x => Assembly.LoadFrom(x))
.SelectMany(x => x.ExportedTypes) .SelectMany(x => x.ExportedTypes)
.Where(x => x.IsClass && !x.IsAbstract && !x.IsInterface && !x.IsGenericType) .Where(x => x.IsClass && !x.IsAbstract && !x.IsInterface && !x.IsGenericType)
@@ -1167,7 +1167,7 @@ namespace Emby.Server.Implementations
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.LogError(ex, "Error loading plugin {pluginName}", plugin.GetType().FullName); Logger.LogError(ex, "Error loading plugin {PluginName}", plugin.GetType().FullName);
return null; return null;
} }
@@ -1181,10 +1181,32 @@ namespace Emby.Server.Implementations
{ {
Logger.LogInformation("Loading assemblies"); Logger.LogInformation("Loading assemblies");
AllConcreteTypes = GetComposablePartAssemblies() AllConcreteTypes = GetTypes(GetComposablePartAssemblies()).ToArray();
.SelectMany(x => x.ExportedTypes) }
.Where(type => type.IsClass && !type.IsAbstract && !type.IsInterface && !type.IsGenericType)
.ToArray(); private IEnumerable<Type> GetTypes(IEnumerable<Assembly> assemblies)
{
foreach (var ass in assemblies)
{
Type[] exportedTypes;
try
{
exportedTypes = ass.GetExportedTypes();
}
catch (TypeLoadException ex)
{
Logger.LogError(ex, "Error getting exported types from {Assembly}", ass.FullName);
continue;
}
foreach (Type type in exportedTypes)
{
if (type.IsClass && !type.IsAbstract && !type.IsInterface && !type.IsGenericType)
{
yield return type;
}
}
}
} }
private CertificateInfo CertificateInfo { get; set; } private CertificateInfo CertificateInfo { get; set; }
@@ -1346,10 +1368,21 @@ namespace Emby.Server.Implementations
{ {
if (Directory.Exists(ApplicationPaths.PluginsPath)) 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); Assembly plugAss;
yield return Assembly.LoadFrom(file); try
{
plugAss = Assembly.LoadFrom(file);
}
catch (FileLoadException ex)
{
Logger.LogError(ex, "Failed to load assembly {Path}", file);
continue;
}
Logger.LogInformation("Loaded assembly {Assembly} from {Path}", plugAss.FullName, file);
yield return plugAss;
} }
} }
@@ -1425,7 +1458,6 @@ namespace Emby.Server.Implementations
HasPendingRestart = HasPendingRestart, HasPendingRestart = HasPendingRestart,
IsShuttingDown = IsShuttingDown, IsShuttingDown = IsShuttingDown,
Version = ApplicationVersion, Version = ApplicationVersion,
ProductName = ApplicationProductName,
WebSocketPortNumber = HttpPort, WebSocketPortNumber = HttpPort,
CompletedInstallations = InstallationManager.CompletedInstallations.ToArray(), CompletedInstallations = InstallationManager.CompletedInstallations.ToArray(),
Id = SystemId, Id = SystemId,
@@ -1482,6 +1514,7 @@ namespace Emby.Server.Implementations
return new PublicSystemInfo return new PublicSystemInfo
{ {
Version = ApplicationVersion, Version = ApplicationVersion,
ProductName = ApplicationProductName,
Id = SystemId, Id = SystemId,
OperatingSystem = OperatingSystem.Id.ToString(), OperatingSystem = OperatingSystem.Id.ToString(),
WanAddress = wanAddress, WanAddress = wanAddress,
@@ -74,23 +74,14 @@ namespace Emby.Server.Implementations.Configuration
/// </summary> /// </summary>
private void UpdateMetadataPath() private void UpdateMetadataPath()
{ {
string metadataPath;
if (string.IsNullOrWhiteSpace(Configuration.MetadataPath)) if (string.IsNullOrWhiteSpace(Configuration.MetadataPath))
{ {
metadataPath = GetInternalMetadataPath(); ((ServerApplicationPaths)ApplicationPaths).InternalMetadataPath = Path.Combine(ApplicationPaths.ProgramDataPath, "metadata");
} }
else 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");
} }
/// <summary> /// <summary>
@@ -81,7 +81,7 @@ namespace Emby.Server.Implementations.Data
{ {
// If the user password is the sha1 hash of the empty string, remove it // If the user password is the sha1 hash of the empty string, remove it
if (!string.Equals(user.Password, "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709", StringComparison.Ordinal) if (!string.Equals(user.Password, "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709", StringComparison.Ordinal)
|| !string.Equals(user.Password, "$SHA1$DA39A3EE5E6B4B0D3255BFEF95601890AFD80709", StringComparison.Ordinal)) && !string.Equals(user.Password, "$SHA1$DA39A3EE5E6B4B0D3255BFEF95601890AFD80709", StringComparison.Ordinal))
{ {
continue; continue;
} }
@@ -203,6 +203,7 @@ namespace Emby.Server.Implementations.HttpServer
case DirectoryNotFoundException _: case DirectoryNotFoundException _:
case FileNotFoundException _: case FileNotFoundException _:
case ResourceNotFoundException _: return 404; case ResourceNotFoundException _: return 404;
case MethodNotAllowedException _: return 405;
case RemoteServiceUnavailableException _: return 502; case RemoteServiceUnavailableException _: return 502;
default: return 500; default: return 500;
} }
@@ -277,24 +277,35 @@ namespace Emby.Server.Implementations.Library
.FirstOrDefault(i => string.Equals(username, i.Name, StringComparison.OrdinalIgnoreCase)); .FirstOrDefault(i => string.Equals(username, i.Name, StringComparison.OrdinalIgnoreCase));
var success = false; var success = false;
string updatedUsername = null;
IAuthenticationProvider authenticationProvider = null; IAuthenticationProvider authenticationProvider = null;
if (user != null) if (user != null)
{ {
var authResult = await AuthenticateLocalUser(username, password, hashedPassword, user, remoteEndPoint).ConfigureAwait(false); var authResult = await AuthenticateLocalUser(username, password, hashedPassword, user, remoteEndPoint).ConfigureAwait(false);
authenticationProvider = authResult.Item1; authenticationProvider = authResult.Item1;
success = authResult.Item2; updatedUsername = authResult.Item2;
success = authResult.Item3;
} }
else else
{ {
// user is null // user is null
var authResult = await AuthenticateLocalUser(username, password, hashedPassword, null, remoteEndPoint).ConfigureAwait(false); var authResult = await AuthenticateLocalUser(username, password, hashedPassword, null, remoteEndPoint).ConfigureAwait(false);
authenticationProvider = authResult.Item1; authenticationProvider = authResult.Item1;
success = authResult.Item2; updatedUsername = authResult.Item2;
success = authResult.Item3;
if (success && authenticationProvider != null && !(authenticationProvider is DefaultAuthenticationProvider)) 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; var hasNewUserPolicy = authenticationProvider as IHasNewUserPolicy;
if (hasNewUserPolicy != null) if (hasNewUserPolicy != null)
@@ -414,32 +425,40 @@ namespace Emby.Server.Implementations.Library
return providers; return providers;
} }
private async Task<bool> AuthenticateWithProvider(IAuthenticationProvider provider, string username, string password, User resolvedUser) private async Task<Tuple<string, bool>> AuthenticateWithProvider(IAuthenticationProvider provider, string username, string password, User resolvedUser)
{ {
try try
{ {
var requiresResolvedUser = provider as IRequiresResolvedUser; var requiresResolvedUser = provider as IRequiresResolvedUser;
ProviderAuthenticationResult authenticationResult = null;
if (requiresResolvedUser != null) if (requiresResolvedUser != null)
{ {
await requiresResolvedUser.Authenticate(username, password, resolvedUser).ConfigureAwait(false); authenticationResult = await requiresResolvedUser.Authenticate(username, password, resolvedUser).ConfigureAwait(false);
} }
else else
{ {
await provider.Authenticate(username, password).ConfigureAwait(false); authenticationResult = await provider.Authenticate(username, password).ConfigureAwait(false);
} }
return true; if(authenticationResult.Username != username)
{
_logger.LogDebug("Authentication provider provided updated username {1}", authenticationResult.Username);
username = authenticationResult.Username;
}
return new Tuple<string, bool>(username, true);
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Error authenticating with provider {provider}", provider.Name); _logger.LogError(ex, "Error authenticating with provider {provider}", provider.Name);
return false; return new Tuple<string, bool>(username, false);
} }
} }
private async Task<Tuple<IAuthenticationProvider, bool>> AuthenticateLocalUser(string username, string password, string hashedPassword, User user, string remoteEndPoint) private async Task<Tuple<IAuthenticationProvider, string, bool>> AuthenticateLocalUser(string username, string password, string hashedPassword, User user, string remoteEndPoint)
{ {
string updatedUsername = null;
bool success = false; bool success = false;
IAuthenticationProvider authenticationProvider = null; IAuthenticationProvider authenticationProvider = null;
@@ -458,11 +477,14 @@ namespace Emby.Server.Implementations.Library
{ {
foreach (var provider in GetAuthenticationProviders(user)) 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) if (success)
{ {
authenticationProvider = provider; authenticationProvider = provider;
username = updatedUsername;
break; break;
} }
} }
@@ -484,7 +506,7 @@ namespace Emby.Server.Implementations.Library
} }
} }
return new Tuple<IAuthenticationProvider, bool>(authenticationProvider, success); return new Tuple<IAuthenticationProvider, string, bool>(authenticationProvider, username, success);
} }
private void UpdateInvalidLoginAttemptCount(User user, int newValue) private void UpdateInvalidLoginAttemptCount(User user, int newValue)
@@ -5,7 +5,7 @@
"Artists": "Umělci", "Artists": "Umělci",
"AuthenticationSucceededWithUserName": "{0} úspěšně ověřen", "AuthenticationSucceededWithUserName": "{0} úspěšně ověřen",
"Books": "Knihy", "Books": "Knihy",
"CameraImageUploadedFrom": "A new camera image has been uploaded from {0}", "CameraImageUploadedFrom": "Z {0} byla nahrána nová fotografie",
"Channels": "Kanály", "Channels": "Kanály",
"ChapterNameValue": "Kapitola {0}", "ChapterNameValue": "Kapitola {0}",
"Collections": "Kolekce", "Collections": "Kolekce",
@@ -16,14 +16,14 @@
"Folders": "Složky", "Folders": "Složky",
"Genres": "Žánry", "Genres": "Žánry",
"HeaderAlbumArtists": "Umělci alba", "HeaderAlbumArtists": "Umělci alba",
"HeaderCameraUploads": "Camera Uploads", "HeaderCameraUploads": "Nahrané fotografie",
"HeaderContinueWatching": "Pokračovat ve sledování", "HeaderContinueWatching": "Pokračovat ve sledování",
"HeaderFavoriteAlbums": "Oblíbená alba", "HeaderFavoriteAlbums": "Oblíbená alba",
"HeaderFavoriteArtists": "Oblíbení umělci", "HeaderFavoriteArtists": "Oblíbení interpreti",
"HeaderFavoriteEpisodes": "Oblíbené epizody", "HeaderFavoriteEpisodes": "Oblíbené epizody",
"HeaderFavoriteShows": "Oblíbené seriály", "HeaderFavoriteShows": "Oblíbené seriály",
"HeaderFavoriteSongs": "Oblíbené písně", "HeaderFavoriteSongs": "Oblíbená hudba",
"HeaderLiveTV": "Živá TV", "HeaderLiveTV": "Live TV",
"HeaderNextUp": "Nadcházející", "HeaderNextUp": "Nadcházející",
"HeaderRecordingGroups": "Skupiny nahrávek", "HeaderRecordingGroups": "Skupiny nahrávek",
"HomeVideos": "Domáci videa", "HomeVideos": "Domáci videa",
@@ -34,17 +34,17 @@
"LabelRunningTimeValue": "Délka média: {0}", "LabelRunningTimeValue": "Délka média: {0}",
"Latest": "Nejnovější", "Latest": "Nejnovější",
"MessageApplicationUpdated": "Jellyfin Server byl aktualizován", "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", "MessageNamedServerConfigurationUpdatedWithValue": "Konfigurace sekce {0} na serveru byla aktualizována",
"MessageServerConfigurationUpdated": "Konfigurace serveru aktualizována", "MessageServerConfigurationUpdated": "Konfigurace serveru aktualizována",
"MixedContent": "Smíšený obsah", "MixedContent": "Smíšený obsah",
"Movies": "Filmy", "Movies": "Filmy",
"Music": "Hudba", "Music": "Hudba",
"MusicVideos": "Hudební klipy", "MusicVideos": "Hudební klipy",
"NameInstallFailed": "{0} installation failed", "NameInstallFailed": "Instalace {0} selhala",
"NameSeasonNumber": "Sezóna {0}", "NameSeasonNumber": "Sezóna {0}",
"NameSeasonUnknown": "Neznámá sezóna", "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", "NotificationOptionApplicationUpdateAvailable": "Dostupná aktualizace aplikace",
"NotificationOptionApplicationUpdateInstalled": "Aktualizace aplikace instalována", "NotificationOptionApplicationUpdateInstalled": "Aktualizace aplikace instalována",
"NotificationOptionAudioPlayback": "Přehrávání audia zahájeno", "NotificationOptionAudioPlayback": "Přehrávání audia zahájeno",
@@ -70,12 +70,12 @@
"ProviderValue": "Poskytl: {0}", "ProviderValue": "Poskytl: {0}",
"ScheduledTaskFailedWithName": "{0} selhalo", "ScheduledTaskFailedWithName": "{0} selhalo",
"ScheduledTaskStartedWithName": "{0} zahájeno", "ScheduledTaskStartedWithName": "{0} zahájeno",
"ServerNameNeedsToBeRestarted": "{0} needs to be restarted", "ServerNameNeedsToBeRestarted": "{0} vyžaduje restart",
"Shows": "Seriály", "Shows": "Seriály",
"Songs": "Skladby", "Songs": "Skladby",
"StartupEmbyServerIsLoading": "Jellyfin Server je spouštěn. Zkuste to prosím v brzké době znovu.", "StartupEmbyServerIsLoading": "Jellyfin Server je spouštěn. Zkuste to prosím v brzké době znovu.",
"SubtitleDownloadFailureForItem": "Stahování titulků selhalo pro {0}", "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}", "SubtitlesDownloadedForItem": "Staženy titulky pro {0}",
"Sync": "Synchronizace", "Sync": "Synchronizace",
"System": "Systém", "System": "Systém",
@@ -88,10 +88,10 @@
"UserOfflineFromDevice": "{0} se odpojil od {1}", "UserOfflineFromDevice": "{0} se odpojil od {1}",
"UserOnlineFromDevice": "{0} se připojil z {1}", "UserOnlineFromDevice": "{0} se připojil z {1}",
"UserPasswordChangedWithName": "Provedena změna hesla pro uživatele {0}", "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}", "UserStartedPlayingItemWithValues": "{0} spustil přehrávání {1}",
"UserStoppedPlayingItemWithValues": "{0} zastavil 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}", "ValueSpecialEpisodeName": "Speciál - {0}",
"VersionNumber": "Verze {0}" "VersionNumber": "Verze {0}"
} }
@@ -61,8 +61,8 @@
"NotificationOptionUserLockedOut": "Bruger låst ude", "NotificationOptionUserLockedOut": "Bruger låst ude",
"NotificationOptionVideoPlayback": "Videoafspilning påbegyndt", "NotificationOptionVideoPlayback": "Videoafspilning påbegyndt",
"NotificationOptionVideoPlaybackStopped": "Videoafspilning stoppet", "NotificationOptionVideoPlaybackStopped": "Videoafspilning stoppet",
"Photos": "Fotos", "Photos": "Fotoer",
"Playlists": "Spillelister", "Playlists": "Afspilningslister",
"Plugin": "Plugin", "Plugin": "Plugin",
"PluginInstalledWithName": "{0} blev installeret", "PluginInstalledWithName": "{0} blev installeret",
"PluginUninstalledWithName": "{0} blev afinstalleret", "PluginUninstalledWithName": "{0} blev afinstalleret",
@@ -16,7 +16,7 @@
"Folders": "Φάκελοι", "Folders": "Φάκελοι",
"Genres": "Είδη", "Genres": "Είδη",
"HeaderAlbumArtists": "Άλμπουμ Καλλιτεχνών", "HeaderAlbumArtists": "Άλμπουμ Καλλιτεχνών",
"HeaderCameraUploads": "Camera Uploads", "HeaderCameraUploads": "Μεταφορτώσεις Κάμερας",
"HeaderContinueWatching": "Συνεχίστε να παρακολουθείτε", "HeaderContinueWatching": "Συνεχίστε να παρακολουθείτε",
"HeaderFavoriteAlbums": "Αγαπημένα Άλμπουμ", "HeaderFavoriteAlbums": "Αγαπημένα Άλμπουμ",
"HeaderFavoriteArtists": "Αγαπημένοι Καλλιτέχνες", "HeaderFavoriteArtists": "Αγαπημένοι Καλλιτέχνες",
@@ -34,7 +34,7 @@
"LabelRunningTimeValue": "Διάρκεια: {0}", "LabelRunningTimeValue": "Διάρκεια: {0}",
"Latest": "Πρόσφατα", "Latest": "Πρόσφατα",
"MessageApplicationUpdated": "Ο Jellyfin Server έχει ενημερωθεί", "MessageApplicationUpdated": "Ο Jellyfin Server έχει ενημερωθεί",
"MessageApplicationUpdatedTo": "Jellyfin Server has been updated to {0}", "MessageApplicationUpdatedTo": "Ο server Jellyfin αναβαθμίστηκε σε έκδοση {0}",
"MessageNamedServerConfigurationUpdatedWithValue": "Η ενότητα {0} ρύθμισης παραμέτρων του server έχει ενημερωθεί", "MessageNamedServerConfigurationUpdatedWithValue": "Η ενότητα {0} ρύθμισης παραμέτρων του server έχει ενημερωθεί",
"MessageServerConfigurationUpdated": "Η ρύθμιση παραμέτρων του server έχει ενημερωθεί", "MessageServerConfigurationUpdated": "Η ρύθμιση παραμέτρων του server έχει ενημερωθεί",
"MixedContent": "Ανάμεικτο Περιεχόμενο", "MixedContent": "Ανάμεικτο Περιεχόμενο",
@@ -49,7 +49,7 @@
"NotificationOptionApplicationUpdateInstalled": "Η ενημέρωση εφαρμογής εγκαταστάθηκε", "NotificationOptionApplicationUpdateInstalled": "Η ενημέρωση εφαρμογής εγκαταστάθηκε",
"NotificationOptionAudioPlayback": "Η αναπαραγωγή ήχου ξεκίνησε", "NotificationOptionAudioPlayback": "Η αναπαραγωγή ήχου ξεκίνησε",
"NotificationOptionAudioPlaybackStopped": "Η αναπαραγωγή ήχου σταμάτησε", "NotificationOptionAudioPlaybackStopped": "Η αναπαραγωγή ήχου σταμάτησε",
"NotificationOptionCameraImageUploaded": "Camera image uploaded", "NotificationOptionCameraImageUploaded": "Μεταφορτώθηκε φωτογραφία απο κάμερα",
"NotificationOptionInstallationFailed": "Αποτυχία εγκατάστασης", "NotificationOptionInstallationFailed": "Αποτυχία εγκατάστασης",
"NotificationOptionNewLibraryContent": "Προστέθηκε νέο περιεχόμενο", "NotificationOptionNewLibraryContent": "Προστέθηκε νέο περιεχόμενο",
"NotificationOptionPluginError": "Αποτυχία του plugin", "NotificationOptionPluginError": "Αποτυχία του plugin",
@@ -75,7 +75,7 @@
"Songs": "Τραγούδια", "Songs": "Τραγούδια",
"StartupEmbyServerIsLoading": "Ο Jellyfin Server φορτώνει. Παρακαλώ δοκιμάστε σε λίγο.", "StartupEmbyServerIsLoading": "Ο Jellyfin Server φορτώνει. Παρακαλώ δοκιμάστε σε λίγο.",
"SubtitleDownloadFailureForItem": "Οι υπότιτλοι απέτυχαν να κατέβουν για {0}", "SubtitleDownloadFailureForItem": "Οι υπότιτλοι απέτυχαν να κατέβουν για {0}",
"SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}", "SubtitleDownloadFailureFromForItem": "Αποτυχίες μεταφόρτωσης υποτίτλων από {0} για {1}",
"SubtitlesDownloadedForItem": "Οι υπότιτλοι κατέβηκαν για {0}", "SubtitlesDownloadedForItem": "Οι υπότιτλοι κατέβηκαν για {0}",
"Sync": "Συγχρονισμός", "Sync": "Συγχρονισμός",
"System": "Σύστημα", "System": "Σύστημα",
@@ -1,97 +1,97 @@
{ {
"Albums": "Albums", "Albums": "Albom",
"AppDeviceValues": "App: {0}, Device: {1}", "AppDeviceValues": "App: {0}, Grät: {1}",
"Application": "Application", "Application": "Aawändig",
"Artists": "Artists", "Artists": "Könstler",
"AuthenticationSucceededWithUserName": "{0} successfully authenticated", "AuthenticationSucceededWithUserName": "{0} het sech aagmäudet",
"Books": "Büecher", "Books": "Büecher",
"CameraImageUploadedFrom": "A new camera image has been uploaded from {0}", "CameraImageUploadedFrom": "Es nöis Foti esch ufeglade worde vo {0}",
"Channels": "Channels", "Channels": "Kanäu",
"ChapterNameValue": "Chapter {0}", "ChapterNameValue": "Kapitu {0}",
"Collections": "Collections", "Collections": "Sammlige",
"DeviceOfflineWithName": "{0} has disconnected", "DeviceOfflineWithName": "{0} esch offline gange",
"DeviceOnlineWithName": "{0} is connected", "DeviceOnlineWithName": "{0} esch online cho",
"FailedLoginAttemptWithUserName": "Failed login attempt from {0}", "FailedLoginAttemptWithUserName": "Fäugschlagne Aamäudeversuech vo {0}",
"Favorites": "Favorites", "Favorites": "Favorite",
"Folders": "Folders", "Folders": "Ordner",
"Genres": "Genres", "Genres": "Genres",
"HeaderAlbumArtists": "Albuminterprete", "HeaderAlbumArtists": "Albom-Könstler",
"HeaderCameraUploads": "Camera Uploads", "HeaderCameraUploads": "Kamera-Uploads",
"HeaderContinueWatching": "Wiiterluege", "HeaderContinueWatching": "Wiiterluege",
"HeaderFavoriteAlbums": "Favorite Albums", "HeaderFavoriteAlbums": "Lieblingsalbe",
"HeaderFavoriteArtists": "Besti Interpret", "HeaderFavoriteArtists": "Lieblings-Interprete",
"HeaderFavoriteEpisodes": "Favorite Episodes", "HeaderFavoriteEpisodes": "Lieblingsepisode",
"HeaderFavoriteShows": "Favorite Shows", "HeaderFavoriteShows": "Lieblingsserie",
"HeaderFavoriteSongs": "Besti Lieder", "HeaderFavoriteSongs": "Lieblingslieder",
"HeaderLiveTV": "Live TV", "HeaderLiveTV": "Live-Färnseh",
"HeaderNextUp": "Next Up", "HeaderNextUp": "Als nächts",
"HeaderRecordingGroups": "Ufnahmegruppe", "HeaderRecordingGroups": "Ufnahmegruppe",
"HomeVideos": "Heimfilmli", "HomeVideos": "Heimfilmli",
"Inherit": "Hinzuefüege", "Inherit": "Hinzuefüege",
"ItemAddedWithName": "{0} was added to the library", "ItemAddedWithName": "{0} esch de Bibliothek dezuegfüegt worde",
"ItemRemovedWithName": "{0} was removed from the library", "ItemRemovedWithName": "{0} esch vo de Bibliothek entfärnt worde",
"LabelIpAddressValue": "Ip address: {0}", "LabelIpAddressValue": "IP-Adrässe: {0}",
"LabelRunningTimeValue": "Running time: {0}", "LabelRunningTimeValue": "Loufziit: {0}",
"Latest": "Letschte", "Latest": "Nöischti",
"MessageApplicationUpdated": "Jellyfin Server has been updated", "MessageApplicationUpdated": "Jellyfin Server esch aktualisiert worde",
"MessageApplicationUpdatedTo": "Jellyfin Server has been updated to {0}", "MessageApplicationUpdatedTo": "Jellyfin Server esch of Version {0} aktualisiert worde",
"MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", "MessageNamedServerConfigurationUpdatedWithValue": "De Serveriistöuigsberiich {0} esch aktualisiert worde",
"MessageServerConfigurationUpdated": "Server configuration has been updated", "MessageServerConfigurationUpdated": "Serveriistöuige send aktualisiert worde",
"MixedContent": "Gmischte Inhalt", "MixedContent": "Gmeschti Inhäut",
"Movies": "Movies", "Movies": "Film",
"Music": "Musig", "Music": "Musig",
"MusicVideos": "Musigfilm", "MusicVideos": "Musigvideos",
"NameInstallFailed": "{0} installation failed", "NameInstallFailed": "Installation vo {0} fäugschlage",
"NameSeasonNumber": "Season {0}", "NameSeasonNumber": "Staffle {0}",
"NameSeasonUnknown": "Season Unknown", "NameSeasonUnknown": "Staffle unbekannt",
"NewVersionIsAvailable": "A new version of Jellyfin Server is available for download.", "NewVersionIsAvailable": "E nöi Version vo Jellyfin Server esch zom Download parat.",
"NotificationOptionApplicationUpdateAvailable": "Application update available", "NotificationOptionApplicationUpdateAvailable": "Aawändigsupdate verfüegbar",
"NotificationOptionApplicationUpdateInstalled": "Application update installed", "NotificationOptionApplicationUpdateInstalled": "Aawändigsupdate installiert",
"NotificationOptionAudioPlayback": "Audio playback started", "NotificationOptionAudioPlayback": "Audiowedergab gstartet",
"NotificationOptionAudioPlaybackStopped": "Audio playback stopped", "NotificationOptionAudioPlaybackStopped": "Audiwedergab gstoppt",
"NotificationOptionCameraImageUploaded": "Camera image uploaded", "NotificationOptionCameraImageUploaded": "Foti ueglade",
"NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionInstallationFailed": "Installationsfäuer",
"NotificationOptionNewLibraryContent": "New content added", "NotificationOptionNewLibraryContent": "Nöie Inhaut hinzuegfüegt",
"NotificationOptionPluginError": "Plugin failure", "NotificationOptionPluginError": "Plugin-Fäuer",
"NotificationOptionPluginInstalled": "Plugin installed", "NotificationOptionPluginInstalled": "Plugin installiert",
"NotificationOptionPluginUninstalled": "Plugin uninstalled", "NotificationOptionPluginUninstalled": "Plugin deinstalliert",
"NotificationOptionPluginUpdateInstalled": "Plugin update installed", "NotificationOptionPluginUpdateInstalled": "Pluginupdate installiert",
"NotificationOptionServerRestartRequired": "Server restart required", "NotificationOptionServerRestartRequired": "Serverneustart notwändig",
"NotificationOptionTaskFailed": "Scheduled task failure", "NotificationOptionTaskFailed": "Planti Uufgab fäugschlage",
"NotificationOptionUserLockedOut": "User locked out", "NotificationOptionUserLockedOut": "Benotzer usgschlosse",
"NotificationOptionVideoPlayback": "Video playback started", "NotificationOptionVideoPlayback": "Videowedergab gstartet",
"NotificationOptionVideoPlaybackStopped": "Video playback stopped", "NotificationOptionVideoPlaybackStopped": "Videowedergab gstoppt",
"Photos": "Fotis", "Photos": "Fotis",
"Playlists": "Abspielliste", "Playlists": "Wedergabeliste",
"Plugin": "Plugin", "Plugin": "Plugin",
"PluginInstalledWithName": "{0} was installed", "PluginInstalledWithName": "{0} esch installiert worde",
"PluginUninstalledWithName": "{0} was uninstalled", "PluginUninstalledWithName": "{0} esch deinstalliert worde",
"PluginUpdatedWithName": "{0} was updated", "PluginUpdatedWithName": "{0} esch updated worde",
"ProviderValue": "Provider: {0}", "ProviderValue": "Aabieter: {0}",
"ScheduledTaskFailedWithName": "{0} failed", "ScheduledTaskFailedWithName": "{0} esch fäugschlage",
"ScheduledTaskStartedWithName": "{0} started", "ScheduledTaskStartedWithName": "{0} het gstartet",
"ServerNameNeedsToBeRestarted": "{0} needs to be restarted", "ServerNameNeedsToBeRestarted": "{0} mues nöi gstartet wärde",
"Shows": "Shows", "Shows": "Serie",
"Songs": "Songs", "Songs": "Lieder",
"StartupEmbyServerIsLoading": "Jellyfin Server is loading. Please try again shortly.", "StartupEmbyServerIsLoading": "Jellyfin Server ladt. Bitte grad noeinisch probiere.",
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
"SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}", "SubtitleDownloadFailureFromForItem": "Ondertetle vo {0} för {1} hend ned chönne abeglade wärde",
"SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", "SubtitlesDownloadedForItem": "Ondertetle abeglade för {0}",
"Sync": "Sync", "Sync": "Synchronisation",
"System": "System", "System": "System",
"TvShows": "TV Shows", "TvShows": "Färnsehserie",
"User": "User", "User": "Benotzer",
"UserCreatedWithName": "User {0} has been created", "UserCreatedWithName": "Benotzer {0} esch erstöut worde",
"UserDeletedWithName": "User {0} has been deleted", "UserDeletedWithName": "Benotzer {0} esch glösche worde",
"UserDownloadingItemWithValues": "{0} is downloading {1}", "UserDownloadingItemWithValues": "{0} ladt {1} abe",
"UserLockedOutWithName": "User {0} has been locked out", "UserLockedOutWithName": "Benotzer {0} esch usgschlosse worde",
"UserOfflineFromDevice": "{0} has disconnected from {1}", "UserOfflineFromDevice": "{0} esch vo {1} trennt worde",
"UserOnlineFromDevice": "{0} is online from {1}", "UserOnlineFromDevice": "{0} esch online vo {1}",
"UserPasswordChangedWithName": "Password has been changed for user {0}", "UserPasswordChangedWithName": "S'Passwort för Benotzer {0} esch gänderet worde",
"UserPolicyUpdatedWithName": "User policy has been updated for {0}", "UserPolicyUpdatedWithName": "Benotzerrechtlinie för {0} esch aktualisiert worde",
"UserStartedPlayingItemWithValues": "{0} is playing {1} on {2}", "UserStartedPlayingItemWithValues": "{0} hed d'Wedergab vo {1} of {2} gstartet",
"UserStoppedPlayingItemWithValues": "{0} has finished playing {1} on {2}", "UserStoppedPlayingItemWithValues": "{0} het d'Wedergab vo {1} of {2} gstoppt",
"ValueHasBeenAddedToLibrary": "{0} has been added to your media library", "ValueHasBeenAddedToLibrary": "{0} esch dinnere Biblithek hinzuegfüegt worde",
"ValueSpecialEpisodeName": "Spezial - {0}", "ValueSpecialEpisodeName": "Extra - {0}",
"VersionNumber": "Version {0}" "VersionNumber": "Version {0}"
} }
@@ -5,7 +5,7 @@
"Artists": "Oryndaýshylar", "Artists": "Oryndaýshylar",
"AuthenticationSucceededWithUserName": "{0} túpnusqalyq rastalýy sátti aıaqtaldy", "AuthenticationSucceededWithUserName": "{0} túpnusqalyq rastalýy sátti aıaqtaldy",
"Books": "Kitaptar", "Books": "Kitaptar",
"CameraImageUploadedFrom": "{0} kamerasynan jańa sýret júktep alyndy", "CameraImageUploadedFrom": "{0} kamerasynan jańa sýret júktep salyndy",
"Channels": "Arnalar", "Channels": "Arnalar",
"ChapterNameValue": "{0}-sahna", "ChapterNameValue": "{0}-sahna",
"Collections": "Jıyntyqtar", "Collections": "Jıyntyqtar",
@@ -35,8 +35,8 @@
"Latest": "Eń keıingi", "Latest": "Eń keıingi",
"MessageApplicationUpdated": "Jellyfin Serveri jańartyldy", "MessageApplicationUpdated": "Jellyfin Serveri jańartyldy",
"MessageApplicationUpdatedTo": "Jellyfin Serveri {0} nusqasyna jańartyldy", "MessageApplicationUpdatedTo": "Jellyfin Serveri {0} nusqasyna jańartyldy",
"MessageNamedServerConfigurationUpdatedWithValue": "Server teńsheliminiń {0} bólimi jańartyldy", "MessageNamedServerConfigurationUpdatedWithValue": "Server konfıgýrasýasynyń {0} bólimi jańartyldy",
"MessageServerConfigurationUpdated": "Server teńshelimi jańartyldy", "MessageServerConfigurationUpdated": "Server konfıgýrasıasy jańartyldy",
"MixedContent": "Aralas mazmun", "MixedContent": "Aralas mazmun",
"Movies": "Fılmder", "Movies": "Fılmder",
"Music": "Mýzyka", "Music": "Mýzyka",
@@ -49,7 +49,7 @@
"NotificationOptionApplicationUpdateInstalled": "Qoldanba jańartýy ornatyldy", "NotificationOptionApplicationUpdateInstalled": "Qoldanba jańartýy ornatyldy",
"NotificationOptionAudioPlayback": "Dybys oınatýy bastaldy", "NotificationOptionAudioPlayback": "Dybys oınatýy bastaldy",
"NotificationOptionAudioPlaybackStopped": "Dybys oınatýy toqtatyldy", "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", "NotificationOptionInstallationFailed": "Ornatý sátsizdigi",
"NotificationOptionNewLibraryContent": "Jańa mazmun ústelgen", "NotificationOptionNewLibraryContent": "Jańa mazmun ústelgen",
"NotificationOptionPluginError": "Plagın sátsizdigi", "NotificationOptionPluginError": "Plagın sátsizdigi",
@@ -9,7 +9,7 @@
"Channels": "Kanali", "Channels": "Kanali",
"ChapterNameValue": "Poglavje {0}", "ChapterNameValue": "Poglavje {0}",
"Collections": "Zbirke", "Collections": "Zbirke",
"DeviceOfflineWithName": "{0} has disconnected", "DeviceOfflineWithName": "{0} je prekinil povezavo",
"DeviceOnlineWithName": "{0} je povezan", "DeviceOnlineWithName": "{0} je povezan",
"FailedLoginAttemptWithUserName": "Neuspešen poskus prijave z {0}", "FailedLoginAttemptWithUserName": "Neuspešen poskus prijave z {0}",
"Favorites": "Priljubljeni", "Favorites": "Priljubljeni",
@@ -33,9 +33,9 @@
"LabelIpAddressValue": "IP naslov: {0}", "LabelIpAddressValue": "IP naslov: {0}",
"LabelRunningTimeValue": "Čas trajanja: {0}", "LabelRunningTimeValue": "Čas trajanja: {0}",
"Latest": "Najnovejše", "Latest": "Najnovejše",
"MessageApplicationUpdated": "Jellyfin strežnik je bil posodobljen", "MessageApplicationUpdated": "Jellyfin Server je bil posodobljen",
"MessageApplicationUpdatedTo": "Jellyfin strežnik je bil posodobljen na {0}", "MessageApplicationUpdatedTo": "Jellyfin Server je bil posodobljen na {0}",
"MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", "MessageNamedServerConfigurationUpdatedWithValue": "Oddelek nastavitve strežnika {0} je bil posodobljen",
"MessageServerConfigurationUpdated": "Nastavitve strežnika so bile posodobljene", "MessageServerConfigurationUpdated": "Nastavitve strežnika so bile posodobljene",
"MixedContent": "Razne vsebine", "MixedContent": "Razne vsebine",
"Movies": "Filmi", "Movies": "Filmi",
@@ -57,41 +57,41 @@
"NotificationOptionPluginUninstalled": "Dodatek odstranjen", "NotificationOptionPluginUninstalled": "Dodatek odstranjen",
"NotificationOptionPluginUpdateInstalled": "Posodobitev dodatka nameščena", "NotificationOptionPluginUpdateInstalled": "Posodobitev dodatka nameščena",
"NotificationOptionServerRestartRequired": "Potreben je ponovni zagon strežnika", "NotificationOptionServerRestartRequired": "Potreben je ponovni zagon strežnika",
"NotificationOptionTaskFailed": "Scheduled task failure", "NotificationOptionTaskFailed": "Razporejena naloga neuspešna",
"NotificationOptionUserLockedOut": "User locked out", "NotificationOptionUserLockedOut": "Uporabnik zaklenjen",
"NotificationOptionVideoPlayback": "Video playback started", "NotificationOptionVideoPlayback": "Predvajanje videa se je začelo",
"NotificationOptionVideoPlaybackStopped": "Video playback stopped", "NotificationOptionVideoPlaybackStopped": "Predvajanje videa se je ustavilo",
"Photos": "Photos", "Photos": "Fotografije",
"Playlists": "Playlists", "Playlists": "Seznami predvajanja",
"Plugin": "Plugin", "Plugin": "Plugin",
"PluginInstalledWithName": "{0} was installed", "PluginInstalledWithName": "{0} je bil nameščen",
"PluginUninstalledWithName": "{0} was uninstalled", "PluginUninstalledWithName": "{0} je bil odstranjen",
"PluginUpdatedWithName": "{0} was updated", "PluginUpdatedWithName": "{0} je bil posodobljen",
"ProviderValue": "Provider: {0}", "ProviderValue": "Provider: {0}",
"ScheduledTaskFailedWithName": "{0} failed", "ScheduledTaskFailedWithName": "{0} ni uspelo",
"ScheduledTaskStartedWithName": "{0} started", "ScheduledTaskStartedWithName": "{0} začeto",
"ServerNameNeedsToBeRestarted": "{0} needs to be restarted", "ServerNameNeedsToBeRestarted": "{0} mora biti ponovno zagnan",
"Shows": "Serije", "Shows": "Serije",
"Songs": "Songs", "Songs": "Pesmi",
"StartupEmbyServerIsLoading": "Jellyfin Server is loading. Please try again shortly.", "StartupEmbyServerIsLoading": "Jellyfin Server se nalaga. Poskusi ponovno kasneje.",
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
"SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}", "SubtitleDownloadFailureFromForItem": "Neuspešen prenos podnapisov iz {0} za {1}",
"SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", "SubtitlesDownloadedForItem": "Podnapisi preneseni za {0}",
"Sync": "Sync", "Sync": "Sinhroniziraj",
"System": "System", "System": "System",
"TvShows": "TV Shows", "TvShows": "TV serije",
"User": "User", "User": "User",
"UserCreatedWithName": "User {0} has been created", "UserCreatedWithName": "Uporabnik {0} je bil ustvarjen",
"UserDeletedWithName": "User {0} has been deleted", "UserDeletedWithName": "Uporabnik {0} je bil izbrisan",
"UserDownloadingItemWithValues": "{0} is downloading {1}", "UserDownloadingItemWithValues": "{0} prenaša {1}",
"UserLockedOutWithName": "User {0} has been locked out", "UserLockedOutWithName": "Uporabnik {0} je bil zaklenjen",
"UserOfflineFromDevice": "{0} has disconnected from {1}", "UserOfflineFromDevice": "{0} je prekinil povezavo z {1}",
"UserOnlineFromDevice": "{0} is online from {1}", "UserOnlineFromDevice": "{0} je aktiven iz {1}",
"UserPasswordChangedWithName": "Password has been changed for user {0}", "UserPasswordChangedWithName": "Geslo za uporabnika {0} je bilo spremenjeno",
"UserPolicyUpdatedWithName": "User policy has been updated for {0}", "UserPolicyUpdatedWithName": "Pravilnik uporabe je bil posodobljen za uporabnika {0}",
"UserStartedPlayingItemWithValues": "{0} is playing {1} on {2}", "UserStartedPlayingItemWithValues": "{0} predvaja {1} na {2}",
"UserStoppedPlayingItemWithValues": "{0} has finished playing {1} on {2}", "UserStoppedPlayingItemWithValues": "{0} je nehal predvajati {1} na {2}",
"ValueHasBeenAddedToLibrary": "{0} has been added to your media library", "ValueHasBeenAddedToLibrary": "{0} je bil dodan vaši knjižnici",
"ValueSpecialEpisodeName": "Special - {0}", "ValueSpecialEpisodeName": "Special - {0}",
"VersionNumber": "Version {0}" "VersionNumber": "Version {0}"
} }
@@ -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}"
}
@@ -41,8 +41,6 @@ namespace Emby.Server.Implementations.Udp
_socketFactory = socketFactory; _socketFactory = socketFactory;
AddMessageResponder("who is JellyfinServer?", true, RespondToV2Message); 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<string, IpEndPointInfo, Encoding, CancellationToken, Task> responder) private void AddMessageResponder(string message, bool isSubstring, Func<string, IpEndPointInfo, Encoding, CancellationToken, Task> responder)
@@ -509,6 +509,8 @@ namespace Emby.Server.Implementations.Updates
private async Task PerformPackageInstallation(IProgress<double> progress, string target, PackageVersionInfo package, CancellationToken cancellationToken) private async Task PerformPackageInstallation(IProgress<double> 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 extension = Path.GetExtension(package.targetFilename);
var isArchive = string.Equals(extension, ".zip", StringComparison.OrdinalIgnoreCase); var isArchive = string.Equals(extension, ".zip", StringComparison.OrdinalIgnoreCase);
@@ -518,12 +520,12 @@ namespace Emby.Server.Implementations.Updates
return; return;
} }
if (target == null) // Always override the passed-in target (which is a file) and figure it out again
{ target = Path.Combine(_appPaths.PluginsPath, package.name);
target = Path.Combine(_appPaths.PluginsPath, Path.GetFileNameWithoutExtension(package.targetFilename)); _logger.LogDebug("Installing plugin to {Filename}.", target);
}
// Download to temporary file so that, if interrupted, it won't destroy the existing installation // 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 var tempFile = await _httpClient.GetTempFile(new HttpRequestOptions
{ {
Url = package.sourceUrl, Url = package.sourceUrl,
@@ -536,9 +538,17 @@ namespace Emby.Server.Implementations.Updates
// TODO: Validate with a checksum, *properly* // 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 // Success - move it to the real target
try try
{ {
_logger.LogDebug("Extracting ZIP {TempFile} to {Filename}.", tempFile, target);
using (var stream = File.OpenRead(tempFile)) using (var stream = File.OpenRead(tempFile))
{ {
_zipClient.ExtractAllFromZip(stream, target, true); _zipClient.ExtractAllFromZip(stream, target, true);
@@ -552,6 +562,7 @@ namespace Emby.Server.Implementations.Updates
try try
{ {
_logger.LogDebug("Deleting temporary file {Filename}.", tempFile);
_fileSystem.DeleteFile(tempFile); _fileSystem.DeleteFile(tempFile);
} }
catch (IOException ex) catch (IOException ex)
@@ -574,7 +585,13 @@ namespace Emby.Server.Implementations.Updates
_applicationHost.RemovePlugin(plugin); _applicationHost.RemovePlugin(plugin);
var path = plugin.AssemblyFilePath; 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 // Make this case-insensitive to account for possible incorrect assembly naming
var file = _fileSystem.GetFilePaths(Path.GetDirectoryName(path)) var file = _fileSystem.GetFilePaths(Path.GetDirectoryName(path))
@@ -585,7 +602,16 @@ namespace Emby.Server.Implementations.Updates
path = file; 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 list = _config.Configuration.UninstalledPlugins.ToList();
var filename = Path.GetFileName(path); var filename = Path.GetFileName(path);
+6 -1
View File
@@ -379,10 +379,15 @@ namespace MediaBrowser.Api
throw new ResourceNotFoundException("User not found"); 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 return Post(new AuthenticateUserByName
{ {
Username = user.Name, Username = user.Name,
Password = request.Password, Password = null, // This should always be null
Pw = request.Pw Pw = request.Pw
}); });
} }
@@ -26,6 +26,30 @@ namespace MediaBrowser.Common.Extensions
} }
} }
/// <summary>
/// Class MethodNotAllowedException
/// </summary>
public class MethodNotAllowedException : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="MethodNotAllowedException" /> class.
/// </summary>
public MethodNotAllowedException()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="MethodNotAllowedException" /> class.
/// </summary>
/// <param name="message">The message.</param>
public MethodNotAllowedException(string message)
: base(message)
{
}
}
public class RemoteServiceUnavailableException : Exception public class RemoteServiceUnavailableException : Exception
{ {
public RemoteServiceUnavailableException() public RemoteServiceUnavailableException()
@@ -230,6 +230,11 @@ namespace MediaBrowser.MediaEncoding.Encoder
/// <returns></returns> /// <returns></returns>
private string ExistsOnSystemPath(string filename) private string ExistsOnSystemPath(string filename)
{ {
string inJellyfinPath = GetEncoderPathFromDirectory(System.AppContext.BaseDirectory, filename);
if (!string.IsNullOrEmpty(inJellyfinPath))
{
return inJellyfinPath;
}
var values = Environment.GetEnvironmentVariable("PATH"); var values = Environment.GetEnvironmentVariable("PATH");
foreach (var path in values.Split(Path.PathSeparator)) foreach (var path in values.Split(Path.PathSeparator))
@@ -26,6 +26,11 @@ namespace MediaBrowser.Model.System
/// <value>The version.</value> /// <value>The version.</value>
public string Version { get; set; } public string Version { get; set; }
/// <summary>
/// The product name. This is the AssemblyProduct name.
/// </summary>
public string ProductName { get; set; }
/// <summary> /// <summary>
/// Gets or sets the operating system. /// Gets or sets the operating system.
/// </summary> /// </summary>
-4
View File
@@ -32,10 +32,6 @@ namespace MediaBrowser.Model.System
/// <value>The display name of the operating system.</value> /// <value>The display name of the operating system.</value>
public string OperatingSystemDisplayName { get; set; } public string OperatingSystemDisplayName { get; set; }
/// <summary>
/// The product name. This is the AssemblyProduct name.
/// </summary>
public string ProductName { get; set; }
/// <summary> /// <summary>
/// Get or sets the package name. /// Get or sets the package name.
+2 -2
View File
@@ -1,4 +1,4 @@
using System.Reflection; using System.Reflection;
[assembly: AssemblyVersion("10.3.0")] [assembly: AssemblyVersion("10.3.1")]
[assembly: AssemblyFileVersion("10.3.0")] [assembly: AssemblyFileVersion("10.3.1")]
+1 -1
View File
@@ -1,7 +1,7 @@
--- ---
# We just wrap `build` so this is really it # We just wrap `build` so this is really it
name: "jellyfin" name: "jellyfin"
version: "10.3.0-rc1" version: "10.3.1"
packages: packages:
- debian-package-x64 - debian-package-x64
- debian-package-armhf - debian-package-armhf
+15 -2
View File
@@ -54,6 +54,7 @@ old_version="$(
grep "AssemblyVersion" ${shared_version_file} \ grep "AssemblyVersion" ${shared_version_file} \
| sed -E 's/\[assembly: ?AssemblyVersion\("([0-9\.]+)"\)\]/\1/' | sed -E 's/\[assembly: ?AssemblyVersion\("([0-9\.]+)"\)\]/\1/'
)" )"
echo $old_version
# Set the shared version to the specified new_version # Set the shared version to the specified new_version
old_version_sed="$( sed 's/\./\\./g' <<<"${old_version}" )" # Escape the '.' chars 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="$( old_version="$(
grep "version:" ${build_file} \ 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 old_version_sed="$( sed 's/\./\\./g' <<<"${old_version}" )" # Escape the '.' chars
sed -i "s/${old_version_sed}/${new_version}/g" ${build_file} sed -i "s/${old_version_sed}/${new_version}/g" ${build_file}
@@ -74,6 +77,16 @@ else
new_version_deb="${new_version}-1" new_version_deb="${new_version}-1"
fi 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 # 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_file="deployment/debian-package-x64/pkg-src/changelog"
debian_changelog_temp="$( mktemp )" debian_changelog_temp="$( mktemp )"
@@ -124,5 +137,5 @@ mv ${fedora_spec_temp} ${fedora_spec_file}
rm -rf ${fedora_changelog_temp} ${fedora_spec_temp_dir} rm -rf ${fedora_changelog_temp} ${fedora_spec_temp_dir}
# Stage the changed files for commit # 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 git status
@@ -1,8 +1,14 @@
jellyfin (10.3.0~rc1) unstable; urgency=medium jellyfin (10.3.1-1) unstable; urgency=medium
* New upstream version 10.3.0-rc1; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.3.0-rc1 * New upstream version 10.3.1; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.3.1
-- Jellyfin Packaging Team <packaging@jellyfin.org> Sat, 30 Mar 2019 15:47:24 -0400 -- Jellyfin Packaging Team <packaging@jellyfin.org> Sat, 20 Apr 2019 14:24:07 -0400
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 <packaging@jellyfin.org> Fri, 19 Apr 2019 14:24:29 -0400
jellyfin (10.2.2-1) unstable; urgency=medium jellyfin (10.2.2-1) unstable; urgency=medium
@@ -7,7 +7,7 @@
%endif %endif
Name: jellyfin Name: jellyfin
Version: 10.3.0 Version: 10.3.1
Release: 1%{?dist} Release: 1%{?dist}
Summary: The Free Software Media Browser Summary: The Free Software Media Browser
License: GPLv2 License: GPLv2
@@ -140,8 +140,10 @@ fi
%systemd_postun_with_restart jellyfin.service %systemd_postun_with_restart jellyfin.service
%changelog %changelog
* Sat Mar 30 2019 Jellyfin Packaging Team <packaging@jellyfin.org> * Sat Apr 20 2019 Jellyfin Packaging Team <packaging@jellyfin.org>
- New upstream version 10.3.0-rc1; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.3.0-rc1 - New upstream version 10.3.1; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.3.1
* Fri Apr 19 2019 Jellyfin Packaging Team <packaging@jellyfin.org>
- 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 <packaging@jellyfin.org> * Thu Feb 28 2019 Jellyfin Packaging Team <packaging@jellyfin.org>
- jellyfin: - jellyfin:
- PR968 Release 10.2.z copr autobuild - PR968 Release 10.2.z copr autobuild
+5 -1
View File
@@ -26,7 +26,10 @@ function Build-JellyFin {
Write-Error "arm only supported with Windows 8 or higher" Write-Error "arm only supported with Windows 8 or higher"
exit 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 { function Install-FFMPEG {
@@ -73,6 +76,7 @@ function Install-NSSM {
Write-Warning "NSSM will not be installed" Write-Warning "NSSM will not be installed"
}else{ }else{
Write-Verbose "Downloading NSSM" 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 Invoke-WebRequest -Uri https://nssm.cc/ci/nssm-2.24-101-g897c7ad.zip -UseBasicParsing -OutFile "$tempdir/nssm.zip" | Write-Verbose
} }
+5 -5
View File
@@ -58,7 +58,7 @@ function Elevate-Window {
if($Quiet.IsPresent -or $Quiet -eq $true){ if($Quiet.IsPresent -or $Quiet -eq $true){
if([string]::IsNullOrEmpty($JellyfinLibraryLocation)){ if([string]::IsNullOrEmpty($JellyfinLibraryLocation)){
$Script:JellyfinDataDir = "$env:AppData\jellyfin\" $Script:JellyfinDataDir = "$env:LOCALAPPDATA\jellyfin\"
}else{ }else{
$Script:JellyfinDataDir = $JellyfinLibraryLocation $Script:JellyfinDataDir = $JellyfinLibraryLocation
} }
@@ -82,7 +82,7 @@ if($Quiet.IsPresent -or $Quiet -eq $true){
}else{ }else{
$Script:InstallServiceAsUser = $true $Script:InstallServiceAsUser = $true
$Script:UserCredentials = $ServiceUser $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($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($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} 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 Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles() [System.Windows.Forms.Application]::EnableVisualStyles()
$Script:JellyFinDataDir = "$env:AppData\jellyfin\" $Script:JellyFinDataDir = "$env:LOCALAPPDATA\jellyfin\"
$Script:DefaultJellyfinInstallDirectory = "$env:Appdata\jellyfin\" $Script:DefaultJellyfinInstallDirectory = "$env:Appdata\jellyfin\"
$Script:defaultEmbyDataDir = "$env:Appdata\Emby-Server\" $Script:defaultEmbyDataDir = "$env:Appdata\Emby-Server\"
$Script:InstallAsService = $False $Script:InstallAsService = $False
@@ -392,7 +392,7 @@ $ServiceUserBox.DropDownStyle = [System.Windows.Forms.ComboBoxStyle]::DropDow
$GUIElementsCollection += $ServiceUserBox $GUIElementsCollection += $ServiceUserBox
$MigrateLibraryCheck = New-Object system.Windows.Forms.CheckBox $MigrateLibraryCheck = New-Object system.Windows.Forms.CheckBox
$MigrateLibraryCheck.text = "Import Emby Library" $MigrateLibraryCheck.text = "Import Emby/Old JF Library"
$MigrateLibraryCheck.AutoSize = $false $MigrateLibraryCheck.AutoSize = $false
$MigrateLibraryCheck.width = 160 $MigrateLibraryCheck.width = 160
$MigrateLibraryCheck.height = 20 $MigrateLibraryCheck.height = 20
@@ -401,7 +401,7 @@ $MigrateLibraryCheck.Font = 'Microsoft Sans Serif,10'
$GUIElementsCollection += $MigrateLibraryCheck $GUIElementsCollection += $MigrateLibraryCheck
$LibraryMigrationLabel = New-Object system.Windows.Forms.Label $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.TextAlign = [System.Drawing.ContentAlignment]::MiddleLeft
$LibraryMigrationLabel.AutoSize = $false $LibraryMigrationLabel.AutoSize = $false
$LibraryMigrationLabel.width = 120 $LibraryMigrationLabel.width = 120