mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-07-21 21:20:39 +02:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
7cde256402
|
@ -37,6 +37,7 @@
|
|||
<PackageReference Include="ServiceStack.Text.Core" Version="5.7.0" />
|
||||
<PackageReference Include="sharpcompress" Version="0.24.0" />
|
||||
<PackageReference Include="SQLitePCL.pretty.netstandard" Version="2.0.1" />
|
||||
<PackageReference Include="System.Interactive.Async" Version="4.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -1 +1,96 @@
|
|||
{}
|
||||
{
|
||||
"Artists": "Kunstenare",
|
||||
"Channels": "Kanale",
|
||||
"Folders": "Fouers",
|
||||
"Favorites": "Gunstelinge",
|
||||
"HeaderFavoriteShows": "Gunsteling Vertonings",
|
||||
"ValueSpecialEpisodeName": "Spesiaal - {0}",
|
||||
"HeaderAlbumArtists": "Album Kunstenaars",
|
||||
"Books": "Boeke",
|
||||
"HeaderNextUp": "Volgende",
|
||||
"Movies": "Rolprente",
|
||||
"Shows": "Program",
|
||||
"HeaderContinueWatching": "Hou Aan Kyk",
|
||||
"HeaderFavoriteEpisodes": "Gunsteling Episodes",
|
||||
"Photos": "Fotos",
|
||||
"Playlists": "Speellysse",
|
||||
"HeaderFavoriteArtists": "Gunsteling Kunstenaars",
|
||||
"HeaderFavoriteAlbums": "Gunsteling Albums",
|
||||
"Sync": "Sinkroniseer",
|
||||
"HeaderFavoriteSongs": "Gunsteling Liedjies",
|
||||
"Songs": "Liedjies",
|
||||
"DeviceOnlineWithName": "{0} is verbind",
|
||||
"DeviceOfflineWithName": "{0} het afgesluit",
|
||||
"Collections": "Versamelings",
|
||||
"Inherit": "Ontvang",
|
||||
"HeaderLiveTV": "Live TV",
|
||||
"Application": "Program",
|
||||
"AppDeviceValues": "App: {0}, Toestel: {1}",
|
||||
"VersionNumber": "Weergawe {0}",
|
||||
"ValueHasBeenAddedToLibrary": "{0} is by jou media biblioteek bygevoeg",
|
||||
"UserStoppedPlayingItemWithValues": "{0} het klaar {1} op {2} gespeel",
|
||||
"UserStartedPlayingItemWithValues": "{0} is besig om {1} op {2} te speel",
|
||||
"UserPolicyUpdatedWithName": "Gebruiker beleid is verander vir {0}",
|
||||
"UserPasswordChangedWithName": "Gebruiker {0} se wagwoord is verander",
|
||||
"UserOnlineFromDevice": "{0} is aanlyn van {1}",
|
||||
"UserOfflineFromDevice": "{0} is ontkoppel van {1}",
|
||||
"UserLockedOutWithName": "Gebruiker {0} is uitgesluit",
|
||||
"UserDownloadingItemWithValues": "{0} is besig om {1} af te laai",
|
||||
"UserDeletedWithName": "Gebruiker {0} is verwyder",
|
||||
"UserCreatedWithName": "Gebruiker {0} is geskep",
|
||||
"User": "Gebruiker",
|
||||
"TvShows": "TV Programme",
|
||||
"System": "Stelsel",
|
||||
"SubtitlesDownloadedForItem": "Ondertitels afgelaai vir {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Ondertitels het misluk om af te laai van {0} vir {1}",
|
||||
"StartupEmbyServerIsLoading": "Jellyfin Bediener is besig om te laai. Probeer weer in 'n kort tyd.",
|
||||
"ServerNameNeedsToBeRestarted": "{0} moet herbegin word",
|
||||
"ScheduledTaskStartedWithName": "{0} het begin",
|
||||
"ScheduledTaskFailedWithName": "{0} het misluk",
|
||||
"ProviderValue": "Voorsiener: {0}",
|
||||
"PluginUpdatedWithName": "{0} was opgedateer",
|
||||
"PluginUninstalledWithName": "{0} was verwyder",
|
||||
"PluginInstalledWithName": "{0} is geïnstalleer",
|
||||
"Plugin": "Inprop module",
|
||||
"NotificationOptionVideoPlaybackStopped": "Video terugspeel het gestop",
|
||||
"NotificationOptionVideoPlayback": "Video terugspeel het begin",
|
||||
"NotificationOptionUserLockedOut": "Gebruiker uitgeslyt",
|
||||
"NotificationOptionTaskFailed": "Geskeduleerde taak het misluk",
|
||||
"NotificationOptionServerRestartRequired": "Bediener herbegin nodig",
|
||||
"NotificationOptionPluginUpdateInstalled": "Nuwe inprop module geïnstalleer",
|
||||
"NotificationOptionPluginUninstalled": "Inprop module verwyder",
|
||||
"NotificationOptionPluginInstalled": "Inprop module geïnstalleer",
|
||||
"NotificationOptionPluginError": "Inprop module het misluk",
|
||||
"NotificationOptionNewLibraryContent": "Nuwe inhoud bygevoeg",
|
||||
"NotificationOptionInstallationFailed": "Installering het misluk",
|
||||
"NotificationOptionCameraImageUploaded": "Kamera foto is opgelaai",
|
||||
"NotificationOptionAudioPlaybackStopped": "Oudio terugspeel het gestop",
|
||||
"NotificationOptionAudioPlayback": "Oudio terugspeel het begin",
|
||||
"NotificationOptionApplicationUpdateInstalled": "Nuwe program weergawe geïnstalleer",
|
||||
"NotificationOptionApplicationUpdateAvailable": "Nuwe program weergawe beskikbaar",
|
||||
"NewVersionIsAvailable": "'n Nuwe Jellyfin Bedienaar weergawe kan afgelaai word.",
|
||||
"NameSeasonUnknown": "Seisoen Onbekend",
|
||||
"NameSeasonNumber": "Seisoen {0}",
|
||||
"NameInstallFailed": "{0} installering het misluk",
|
||||
"MusicVideos": "Musiek videos",
|
||||
"Music": "Musiek",
|
||||
"MixedContent": "Gemengde inhoud",
|
||||
"MessageServerConfigurationUpdated": "Bediener konfigurasie is opgedateer",
|
||||
"MessageNamedServerConfigurationUpdatedWithValue": "Bediener konfigurasie seksie {0} is opgedateer",
|
||||
"MessageApplicationUpdatedTo": "Jellyfin Bediener is opgedateer na {0}",
|
||||
"MessageApplicationUpdated": "Jellyfin Bediener is opgedateer",
|
||||
"Latest": "Nuutste",
|
||||
"LabelRunningTimeValue": "Lopende tyd: {0}",
|
||||
"LabelIpAddressValue": "IP adres: {0}",
|
||||
"ItemRemovedWithName": "{0} is uit versameling verwyder",
|
||||
"ItemAddedWithName": "{0} is in die versameling",
|
||||
"HomeVideos": "Tuis opnames",
|
||||
"HeaderRecordingGroups": "Groep Opnames",
|
||||
"HeaderCameraUploads": "Kamera Oplaai",
|
||||
"Genres": "Genres",
|
||||
"FailedLoginAttemptWithUserName": "Mislukte aansluiting van {0}",
|
||||
"ChapterNameValue": "Hoofstuk",
|
||||
"CameraImageUploadedFrom": "'n Nuwe kamera photo opgelaai van {0}",
|
||||
"AuthenticationSucceededWithUserName": "{0} suksesvol geverifieer",
|
||||
"Albums": "Albums"
|
||||
}
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
"AppDeviceValues": "App: {0}, Gerät: {1}",
|
||||
"Application": "Anwendung",
|
||||
"Artists": "Interpreten",
|
||||
"AuthenticationSucceededWithUserName": "{0} hat sich angemeldet",
|
||||
"AuthenticationSucceededWithUserName": "{0} hat sich erfolgreich angemeldet",
|
||||
"Books": "Bücher",
|
||||
"CameraImageUploadedFrom": "Ein neues Foto wurde hochgeladen von {0}",
|
||||
"Channels": "Kanäle",
|
||||
"ChapterNameValue": "Kapitel {0}",
|
||||
"Collections": "Sammlungen",
|
||||
"DeviceOfflineWithName": "{0} wurde getrennt",
|
||||
"DeviceOnlineWithName": "{0} hat sich verbunden",
|
||||
"DeviceOnlineWithName": "{0} ist verbunden",
|
||||
"FailedLoginAttemptWithUserName": "Fehlgeschlagener Anmeldeversuch von {0}",
|
||||
"Favorites": "Favoriten",
|
||||
"Folders": "Verzeichnisse",
|
||||
|
|
|
@ -8,9 +8,9 @@
|
|||
"CameraImageUploadedFrom": "A new camera image has been uploaded from {0}",
|
||||
"Channels": "Channels",
|
||||
"ChapterNameValue": "Chapter {0}",
|
||||
"Collections": "Versamelings",
|
||||
"DeviceOfflineWithName": "{0} het afgesluit",
|
||||
"DeviceOnlineWithName": "{0} is verbind",
|
||||
"Collections": "Collections",
|
||||
"DeviceOfflineWithName": "{0} has disconnected",
|
||||
"DeviceOnlineWithName": "{0} is connected",
|
||||
"FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
|
||||
"Favorites": "Favorites",
|
||||
"Folders": "Folders",
|
||||
|
|
|
@ -1,41 +1,41 @@
|
|||
{
|
||||
"Albums": "אלבומים",
|
||||
"AppDeviceValues": "App: {0}, Device: {1}",
|
||||
"AppDeviceValues": "יישום: {0}, מכשיר: {1}",
|
||||
"Application": "אפליקציה",
|
||||
"Artists": "אמנים",
|
||||
"AuthenticationSucceededWithUserName": "{0} successfully authenticated",
|
||||
"AuthenticationSucceededWithUserName": "{0} זוהה בהצלחה",
|
||||
"Books": "ספרים",
|
||||
"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": "תמונה חדשה הועלתה מ{0}",
|
||||
"Channels": "ערוצים",
|
||||
"ChapterNameValue": "פרק {0}",
|
||||
"Collections": "קולקציות",
|
||||
"DeviceOfflineWithName": "{0} התנתק",
|
||||
"DeviceOnlineWithName": "{0} מחובר",
|
||||
"FailedLoginAttemptWithUserName": "ניסיון כניסה שגוי מ{0}",
|
||||
"Favorites": "אהובים",
|
||||
"Folders": "תיקיות",
|
||||
"Genres": "ז'אנרים",
|
||||
"HeaderAlbumArtists": "Album Artists",
|
||||
"HeaderCameraUploads": "Camera Uploads",
|
||||
"HeaderContinueWatching": "המשך בצפייה",
|
||||
"HeaderFavoriteAlbums": "Favorite Albums",
|
||||
"HeaderFavoriteArtists": "Favorite Artists",
|
||||
"HeaderFavoriteEpisodes": "Favorite Episodes",
|
||||
"HeaderFavoriteShows": "Favorite Shows",
|
||||
"HeaderFavoriteSongs": "Favorite Songs",
|
||||
"HeaderLiveTV": "Live TV",
|
||||
"HeaderNextUp": "Next Up",
|
||||
"HeaderAlbumArtists": "אמני האלבום",
|
||||
"HeaderCameraUploads": "העלאות ממצלמה",
|
||||
"HeaderContinueWatching": "המשך לצפות",
|
||||
"HeaderFavoriteAlbums": "אלבומים שאהבתי",
|
||||
"HeaderFavoriteArtists": "אמנים שאהבתי",
|
||||
"HeaderFavoriteEpisodes": "פרקים אהובים",
|
||||
"HeaderFavoriteShows": "תוכניות אהובות",
|
||||
"HeaderFavoriteSongs": "שירים שאהבתי",
|
||||
"HeaderLiveTV": "טלוויזיה בשידור חי",
|
||||
"HeaderNextUp": "הבא",
|
||||
"HeaderRecordingGroups": "קבוצות הקלטה",
|
||||
"HomeVideos": "Home videos",
|
||||
"Inherit": "Inherit",
|
||||
"HomeVideos": "סרטונים בייתים",
|
||||
"Inherit": "הורש",
|
||||
"ItemAddedWithName": "{0} was added to the library",
|
||||
"ItemRemovedWithName": "{0} was removed from the library",
|
||||
"LabelIpAddressValue": "Ip address: {0}",
|
||||
"LabelRunningTimeValue": "Running time: {0}",
|
||||
"ItemRemovedWithName": "{0} נמחק מהספרייה",
|
||||
"LabelIpAddressValue": "Ip כתובת: {0}",
|
||||
"LabelRunningTimeValue": "משך צפייה: {0}",
|
||||
"Latest": "אחרון",
|
||||
"MessageApplicationUpdated": "Jellyfin Server has been updated",
|
||||
"MessageApplicationUpdatedTo": "Jellyfin Server has been updated to {0}",
|
||||
"MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
|
||||
"MessageApplicationUpdated": "שרת הJellyfin עודכן",
|
||||
"MessageApplicationUpdatedTo": "שרת הJellyfin עודכן לגרסא {0}",
|
||||
"MessageNamedServerConfigurationUpdatedWithValue": "הגדרת השרת {0} שונתה",
|
||||
"MessageServerConfigurationUpdated": "Server configuration has been updated",
|
||||
"MixedContent": "תוכן מעורב",
|
||||
"Movies": "סרטים",
|
||||
|
@ -50,7 +50,7 @@
|
|||
"NotificationOptionAudioPlayback": "Audio playback started",
|
||||
"NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
|
||||
"NotificationOptionCameraImageUploaded": "Camera image uploaded",
|
||||
"NotificationOptionInstallationFailed": "Installation failure",
|
||||
"NotificationOptionInstallationFailed": "התקנה נכשלה",
|
||||
"NotificationOptionNewLibraryContent": "New content added",
|
||||
"NotificationOptionPluginError": "Plugin failure",
|
||||
"NotificationOptionPluginInstalled": "Plugin installed",
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
"Artists": "Umelci",
|
||||
"AuthenticationSucceededWithUserName": "{0} úspešne overený",
|
||||
"Books": "Knihy",
|
||||
"CameraImageUploadedFrom": "A new camera image has been uploaded from {0}",
|
||||
"CameraImageUploadedFrom": "Z {0} bola nahraná nová fotografia",
|
||||
"Channels": "Kanály",
|
||||
"ChapterNameValue": "Kapitola {0}",
|
||||
"Collections": "Zbierky",
|
||||
|
@ -15,9 +15,9 @@
|
|||
"Favorites": "Obľúbené",
|
||||
"Folders": "Priečinky",
|
||||
"Genres": "Žánre",
|
||||
"HeaderAlbumArtists": "Album Artists",
|
||||
"HeaderAlbumArtists": "Albumy umelcov",
|
||||
"HeaderCameraUploads": "Nahrané fotografie",
|
||||
"HeaderContinueWatching": "Pokračujte v pozeraní",
|
||||
"HeaderContinueWatching": "Pokračovať v pozeraní",
|
||||
"HeaderFavoriteAlbums": "Obľúbené albumy",
|
||||
"HeaderFavoriteArtists": "Obľúbení umelci",
|
||||
"HeaderFavoriteEpisodes": "Obľúbené epizódy",
|
||||
|
|
|
@ -7,8 +7,6 @@ using System.Net.NetworkInformation;
|
|||
using System.Net.Sockets;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Net;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Emby.Server.Implementations.Networking
|
||||
|
@ -55,10 +53,7 @@ namespace Emby.Server.Implementations.Networking
|
|||
_macAddresses = null;
|
||||
}
|
||||
|
||||
if (NetworkChanged != null)
|
||||
{
|
||||
NetworkChanged(this, EventArgs.Empty);
|
||||
}
|
||||
NetworkChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public IPAddress[] GetLocalIpAddresses(bool ignoreVirtualInterface = true)
|
||||
|
@ -261,10 +256,10 @@ namespace Emby.Server.Implementations.Networking
|
|||
return true;
|
||||
}
|
||||
|
||||
if (normalizedSubnet.IndexOf('/') != -1)
|
||||
if (normalizedSubnet.Contains('/', StringComparison.Ordinal))
|
||||
{
|
||||
var ipnetwork = IPNetwork.Parse(normalizedSubnet);
|
||||
if (ipnetwork.Contains(address))
|
||||
var ipNetwork = IPNetwork.Parse(normalizedSubnet);
|
||||
if (ipNetwork.Contains(address))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -455,9 +450,9 @@ namespace Emby.Server.Implementations.Networking
|
|||
|
||||
public bool IsInSameSubnet(IPAddress address1, IPAddress address2, IPAddress subnetMask)
|
||||
{
|
||||
IPAddress network1 = GetNetworkAddress(address1, subnetMask);
|
||||
IPAddress network2 = GetNetworkAddress(address2, subnetMask);
|
||||
return network1.Equals(network2);
|
||||
IPAddress network1 = GetNetworkAddress(address1, subnetMask);
|
||||
IPAddress network2 = GetNetworkAddress(address2, subnetMask);
|
||||
return network1.Equals(network2);
|
||||
}
|
||||
|
||||
private IPAddress GetNetworkAddress(IPAddress address, IPAddress subnetMask)
|
||||
|
@ -473,7 +468,7 @@ namespace Emby.Server.Implementations.Networking
|
|||
byte[] broadcastAddress = new byte[ipAdressBytes.Length];
|
||||
for (int i = 0; i < broadcastAddress.Length; i++)
|
||||
{
|
||||
broadcastAddress[i] = (byte)(ipAdressBytes[i] & (subnetMaskBytes[i]));
|
||||
broadcastAddress[i] = (byte)(ipAdressBytes[i] & subnetMaskBytes[i]);
|
||||
}
|
||||
|
||||
return new IPAddress(broadcastAddress);
|
||||
|
@ -513,24 +508,5 @@ namespace Emby.Server.Implementations.Networking
|
|||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the network shares.
|
||||
/// </summary>
|
||||
/// <param name="path">The path.</param>
|
||||
/// <returns>IEnumerable{NetworkShare}.</returns>
|
||||
public virtual IEnumerable<NetworkShare> GetNetworkShares(string path)
|
||||
{
|
||||
return new List<NetworkShare>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets available devices within the domain
|
||||
/// </summary>
|
||||
/// <returns>PC's in the Domain</returns>
|
||||
public virtual IEnumerable<FileSystemEntryInfo> GetNetworkDevices()
|
||||
{
|
||||
return new List<FileSystemEntryInfo>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,9 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||
{
|
||||
progress.Report(0);
|
||||
|
||||
var packagesToInstall = (await _installationManager.GetAvailablePluginUpdates(cancellationToken).ConfigureAwait(false)).ToList();
|
||||
var packagesToInstall = await _installationManager.GetAvailablePluginUpdates(cancellationToken)
|
||||
.ToListAsync(cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
progress.Report(10);
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Mime;
|
||||
using MediaBrowser.Common.Net;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Extensions;
|
||||
|
@ -14,9 +15,9 @@ namespace Emby.Server.Implementations.SocketSharp
|
|||
{
|
||||
public class WebSocketSharpRequest : IHttpRequest
|
||||
{
|
||||
public const string FormUrlEncoded = "application/x-www-form-urlencoded";
|
||||
public const string MultiPartFormData = "multipart/form-data";
|
||||
public const string Soap11 = "text/xml; charset=utf-8";
|
||||
private const string FormUrlEncoded = "application/x-www-form-urlencoded";
|
||||
private const string MultiPartFormData = "multipart/form-data";
|
||||
private const string Soap11 = "text/xml; charset=utf-8";
|
||||
|
||||
private string _remoteIp;
|
||||
private Dictionary<string, object> _items;
|
||||
|
@ -77,7 +78,7 @@ namespace Emby.Server.Implementations.SocketSharp
|
|||
get =>
|
||||
_responseContentType
|
||||
?? (_responseContentType = GetResponseContentType(Request));
|
||||
set => this._responseContentType = value;
|
||||
set => _responseContentType = value;
|
||||
}
|
||||
|
||||
public string PathInfo => Request.Path.Value;
|
||||
|
@ -90,7 +91,6 @@ namespace Emby.Server.Implementations.SocketSharp
|
|||
|
||||
public bool IsLocal => Request.HttpContext.Connection.LocalIpAddress.Equals(Request.HttpContext.Connection.RemoteIpAddress);
|
||||
|
||||
|
||||
public string HttpMethod => Request.Method;
|
||||
|
||||
public string Verb => HttpMethod;
|
||||
|
@ -123,24 +123,29 @@ namespace Emby.Server.Implementations.SocketSharp
|
|||
return specifiedContentType;
|
||||
}
|
||||
|
||||
const string serverDefaultContentType = "application/json";
|
||||
const string ServerDefaultContentType = MediaTypeNames.Application.Json;
|
||||
|
||||
var acceptContentTypes = httpReq.Headers.GetCommaSeparatedValues(HeaderNames.Accept);
|
||||
string defaultContentType = null;
|
||||
if (HasAnyOfContentTypes(httpReq, FormUrlEncoded, MultiPartFormData))
|
||||
{
|
||||
defaultContentType = serverDefaultContentType;
|
||||
defaultContentType = ServerDefaultContentType;
|
||||
}
|
||||
|
||||
var acceptsAnything = false;
|
||||
var hasDefaultContentType = defaultContentType != null;
|
||||
if (acceptContentTypes != null)
|
||||
{
|
||||
foreach (var acceptsType in acceptContentTypes)
|
||||
foreach (ReadOnlySpan<char> acceptsType in acceptContentTypes)
|
||||
{
|
||||
// TODO: @bond move to Span when Span.Split lands
|
||||
// https://github.com/dotnet/corefx/issues/26528
|
||||
var contentType = acceptsType?.Split(';')[0].Trim();
|
||||
ReadOnlySpan<char> contentType = acceptsType;
|
||||
var index = contentType.IndexOf(';');
|
||||
if (index != -1)
|
||||
{
|
||||
contentType = contentType.Slice(0, index);
|
||||
}
|
||||
|
||||
contentType = contentType.Trim();
|
||||
acceptsAnything = contentType.Equals("*/*", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
if (acceptsAnything)
|
||||
|
@ -157,7 +162,7 @@ namespace Emby.Server.Implementations.SocketSharp
|
|||
}
|
||||
else
|
||||
{
|
||||
return serverDefaultContentType;
|
||||
return ServerDefaultContentType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -168,7 +173,7 @@ namespace Emby.Server.Implementations.SocketSharp
|
|||
}
|
||||
|
||||
// We could also send a '406 Not Acceptable', but this is allowed also
|
||||
return serverDefaultContentType;
|
||||
return ServerDefaultContentType;
|
||||
}
|
||||
|
||||
public static bool HasAnyOfContentTypes(HttpRequest request, params string[] contentTypes)
|
||||
|
@ -196,12 +201,12 @@ namespace Emby.Server.Implementations.SocketSharp
|
|||
|
||||
private static string GetQueryStringContentType(HttpRequest httpReq)
|
||||
{
|
||||
ReadOnlySpan<char> format = httpReq.Query["format"].ToString().AsSpan();
|
||||
ReadOnlySpan<char> format = httpReq.Query["format"].ToString();
|
||||
if (format == null)
|
||||
{
|
||||
const int formatMaxLength = 4;
|
||||
ReadOnlySpan<char> pi = httpReq.Path.ToString().AsSpan();
|
||||
if (pi == null || pi.Length <= formatMaxLength)
|
||||
const int FormatMaxLength = 4;
|
||||
ReadOnlySpan<char> pi = httpReq.Path.ToString();
|
||||
if (pi == null || pi.Length <= FormatMaxLength)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
@ -212,18 +217,18 @@ namespace Emby.Server.Implementations.SocketSharp
|
|||
}
|
||||
|
||||
format = LeftPart(pi, '/');
|
||||
if (format.Length > formatMaxLength)
|
||||
if (format.Length > FormatMaxLength)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
format = LeftPart(format, '.');
|
||||
if (format.Contains("json".AsSpan(), StringComparison.OrdinalIgnoreCase))
|
||||
if (format.Contains("json", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return "application/json";
|
||||
}
|
||||
else if (format.Contains("xml".AsSpan(), StringComparison.OrdinalIgnoreCase))
|
||||
else if (format.Contains("xml", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return "application/xml";
|
||||
}
|
||||
|
|
|
@ -180,7 +180,7 @@ namespace Emby.Server.Implementations.Updates
|
|||
// Package not found.
|
||||
if (package == null)
|
||||
{
|
||||
return null;
|
||||
return Enumerable.Empty<PackageVersionInfo>();
|
||||
}
|
||||
|
||||
return GetCompatibleVersions(
|
||||
|
@ -190,19 +190,23 @@ namespace Emby.Server.Implementations.Updates
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IEnumerable<PackageVersionInfo>> GetAvailablePluginUpdates(CancellationToken cancellationToken = default)
|
||||
public async IAsyncEnumerable<PackageVersionInfo> GetAvailablePluginUpdates(CancellationToken cancellationToken = default)
|
||||
{
|
||||
var catalog = await GetAvailablePackages(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var systemUpdateLevel = _applicationHost.SystemUpdateLevel;
|
||||
|
||||
// Figure out what needs to be installed
|
||||
return _applicationHost.Plugins.Select(x =>
|
||||
foreach (var plugin in _applicationHost.Plugins)
|
||||
{
|
||||
var compatibleversions = GetCompatibleVersions(catalog, x.Name, x.Id, x.Version, systemUpdateLevel);
|
||||
return compatibleversions.FirstOrDefault(y => y.Version > x.Version);
|
||||
}).Where(x => x != null)
|
||||
.Where(x => !CompletedInstallations.Any(y => string.Equals(y.AssemblyGuid, x.guid, StringComparison.OrdinalIgnoreCase)));
|
||||
var compatibleversions = GetCompatibleVersions(catalog, plugin.Name, plugin.Id, plugin.Version, systemUpdateLevel);
|
||||
var version = compatibleversions.FirstOrDefault(y => y.Version > plugin.Version);
|
||||
if (version != null
|
||||
&& !CompletedInstallations.Any(x => string.Equals(x.AssemblyGuid, version.guid, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
yield return version;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
|
@ -52,6 +52,7 @@ namespace MediaBrowser.Api
|
|||
public bool? IsFile { get; set; }
|
||||
}
|
||||
|
||||
[Obsolete]
|
||||
[Route("/Environment/NetworkShares", "GET", Summary = "Gets shares from a network device")]
|
||||
public class GetNetworkShares : IReturn<List<FileSystemEntryInfo>>
|
||||
{
|
||||
|
@ -192,22 +193,18 @@ namespace MediaBrowser.Api
|
|||
|
||||
var networkPrefix = UncSeparatorString + UncSeparatorString;
|
||||
|
||||
if (path.StartsWith(networkPrefix, StringComparison.OrdinalIgnoreCase) && path.LastIndexOf(UncSeparator) == 1)
|
||||
if (path.StartsWith(networkPrefix, StringComparison.OrdinalIgnoreCase)
|
||||
&& path.LastIndexOf(UncSeparator) == 1)
|
||||
{
|
||||
return ToOptimizedResult(GetNetworkShares(path).OrderBy(i => i.Path).ToList());
|
||||
return ToOptimizedResult(Array.Empty<FileSystemEntryInfo>());
|
||||
}
|
||||
|
||||
return ToOptimizedResult(GetFileSystemEntries(request).ToList());
|
||||
}
|
||||
|
||||
[Obsolete]
|
||||
public object Get(GetNetworkShares request)
|
||||
{
|
||||
var path = request.Path;
|
||||
|
||||
var shares = GetNetworkShares(path).OrderBy(i => i.Path).ToList();
|
||||
|
||||
return ToOptimizedResult(shares);
|
||||
}
|
||||
=> ToOptimizedResult(Array.Empty<FileSystemEntryInfo>());
|
||||
|
||||
/// <summary>
|
||||
/// Gets the specified request.
|
||||
|
@ -241,26 +238,7 @@ namespace MediaBrowser.Api
|
|||
/// <param name="request">The request.</param>
|
||||
/// <returns>System.Object.</returns>
|
||||
public object Get(GetNetworkDevices request)
|
||||
{
|
||||
var result = _networkManager.GetNetworkDevices().ToList();
|
||||
|
||||
return ToOptimizedResult(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the network shares.
|
||||
/// </summary>
|
||||
/// <param name="path">The path.</param>
|
||||
/// <returns>IEnumerable{FileSystemEntryInfo}.</returns>
|
||||
private IEnumerable<FileSystemEntryInfo> GetNetworkShares(string path)
|
||||
{
|
||||
return _networkManager.GetNetworkShares(path).Where(s => s.ShareType == NetworkShareType.Disk).Select(c => new FileSystemEntryInfo
|
||||
{
|
||||
Name = c.Name,
|
||||
Path = Path.Combine(path, c.Name),
|
||||
Type = FileSystemEntryType.NetworkShare
|
||||
});
|
||||
}
|
||||
=> ToOptimizedResult(Array.Empty<FileSystemEntryInfo>());
|
||||
|
||||
/// <summary>
|
||||
/// Gets the file system entries.
|
||||
|
|
|
@ -4,8 +4,6 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Net;
|
||||
|
||||
namespace MediaBrowser.Common.Net
|
||||
{
|
||||
|
@ -36,19 +34,6 @@ namespace MediaBrowser.Common.Net
|
|||
/// <returns><c>true</c> if [is in private address space] [the specified endpoint]; otherwise, <c>false</c>.</returns>
|
||||
bool IsInPrivateAddressSpace(string endpoint);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the network shares.
|
||||
/// </summary>
|
||||
/// <param name="path">The path.</param>
|
||||
/// <returns>IEnumerable{NetworkShare}.</returns>
|
||||
IEnumerable<NetworkShare> GetNetworkShares(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Gets available devices within the domain
|
||||
/// </summary>
|
||||
/// <returns>PC's in the Domain</returns>
|
||||
IEnumerable<FileSystemEntryInfo> GetNetworkDevices();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether [is in local network] [the specified endpoint].
|
||||
/// </summary>
|
||||
|
|
|
@ -92,7 +92,7 @@ namespace MediaBrowser.Common.Updates
|
|||
/// </summary>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>The available plugin updates.</returns>
|
||||
Task<IEnumerable<PackageVersionInfo>> GetAvailablePluginUpdates(CancellationToken cancellationToken = default);
|
||||
IAsyncEnumerable<PackageVersionInfo> GetAvailablePluginUpdates(CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Installs the package.
|
||||
|
|
Loading…
Reference in a new issue