From 72aaecb27930e04aa356febf35db2372bc417166 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 4 Nov 2016 14:56:47 -0400 Subject: move classes to new server project --- .../Connect/ConnectData.cs | 36 - .../Connect/ConnectEntryPoint.cs | 203 ---- .../Connect/ConnectManager.cs | 1192 -------------------- .../Connect/Responses.cs | 85 -- .../Connect/Validator.cs | 29 - .../EntryPoints/UdpServerEntryPoint.cs | 92 -- .../SocketSharp/WebSocketSharpListener.cs | 2 +- .../IO/FileRefresher.cs | 323 ------ .../IO/LibraryMonitor.cs | 14 +- .../Logging/PatternsLogger.cs | 63 -- .../MediaBrowser.Server.Implementations.csproj | 11 - .../Security/EncryptionManager.cs | 51 - .../Udp/UdpMessageReceivedEventArgs.cs | 21 - .../Udp/UdpServer.cs | 328 ------ 14 files changed, 6 insertions(+), 2444 deletions(-) delete mode 100644 MediaBrowser.Server.Implementations/Connect/ConnectData.cs delete mode 100644 MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs delete mode 100644 MediaBrowser.Server.Implementations/Connect/ConnectManager.cs delete mode 100644 MediaBrowser.Server.Implementations/Connect/Responses.cs delete mode 100644 MediaBrowser.Server.Implementations/Connect/Validator.cs delete mode 100644 MediaBrowser.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs delete mode 100644 MediaBrowser.Server.Implementations/IO/FileRefresher.cs delete mode 100644 MediaBrowser.Server.Implementations/Logging/PatternsLogger.cs delete mode 100644 MediaBrowser.Server.Implementations/Security/EncryptionManager.cs delete mode 100644 MediaBrowser.Server.Implementations/Udp/UdpMessageReceivedEventArgs.cs delete mode 100644 MediaBrowser.Server.Implementations/Udp/UdpServer.cs (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectData.cs b/MediaBrowser.Server.Implementations/Connect/ConnectData.cs deleted file mode 100644 index 5ec0bea22c..0000000000 --- a/MediaBrowser.Server.Implementations/Connect/ConnectData.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace MediaBrowser.Server.Implementations.Connect -{ - public class ConnectData - { - /// - /// Gets or sets the server identifier. - /// - /// The server identifier. - public string ServerId { get; set; } - /// - /// Gets or sets the access key. - /// - /// The access key. - public string AccessKey { get; set; } - - /// - /// Gets or sets the authorizations. - /// - /// The authorizations. - public List PendingAuthorizations { get; set; } - - /// - /// Gets or sets the last authorizations refresh. - /// - /// The last authorizations refresh. - public DateTime LastAuthorizationsRefresh { get; set; } - - public ConnectData() - { - PendingAuthorizations = new List(); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs b/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs deleted file mode 100644 index 565eeb259b..0000000000 --- a/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs +++ /dev/null @@ -1,203 +0,0 @@ -using MediaBrowser.Common; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Connect; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Net; -using System; -using System.IO; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading.Tasks; -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.IO; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Threading; - -namespace MediaBrowser.Server.Implementations.Connect -{ - public class ConnectEntryPoint : IServerEntryPoint - { - private ITimer _timer; - private readonly IHttpClient _httpClient; - private readonly IApplicationPaths _appPaths; - private readonly ILogger _logger; - private readonly IConnectManager _connectManager; - - private readonly INetworkManager _networkManager; - private readonly IApplicationHost _appHost; - private readonly IFileSystem _fileSystem; - private readonly ITimerFactory _timerFactory; - - public ConnectEntryPoint(IHttpClient httpClient, IApplicationPaths appPaths, ILogger logger, INetworkManager networkManager, IConnectManager connectManager, IApplicationHost appHost, IFileSystem fileSystem, ITimerFactory timerFactory) - { - _httpClient = httpClient; - _appPaths = appPaths; - _logger = logger; - _networkManager = networkManager; - _connectManager = connectManager; - _appHost = appHost; - _fileSystem = fileSystem; - _timerFactory = timerFactory; - } - - public void Run() - { - LoadCachedAddress(); - - _timer = _timerFactory.Create(TimerCallback, null, TimeSpan.FromSeconds(5), TimeSpan.FromHours(1)); - ((ConnectManager)_connectManager).Start(); - } - - private readonly string[] _ipLookups = - { - "http://bot.whatismyipaddress.com", - "https://connect.emby.media/service/ip" - }; - - private async void TimerCallback(object state) - { - IPAddress validIpAddress = null; - - foreach (var ipLookupUrl in _ipLookups) - { - try - { - validIpAddress = await GetIpAddress(ipLookupUrl).ConfigureAwait(false); - - // Try to find the ipv4 address, if present - if (validIpAddress.AddressFamily == AddressFamily.InterNetwork) - { - break; - } - } - catch (HttpException) - { - } - catch (Exception ex) - { - _logger.ErrorException("Error getting connection info", ex); - } - } - - // If this produced an ipv6 address, try again - if (validIpAddress != null && validIpAddress.AddressFamily == AddressFamily.InterNetworkV6) - { - foreach (var ipLookupUrl in _ipLookups) - { - try - { - var newAddress = await GetIpAddress(ipLookupUrl, true).ConfigureAwait(false); - - // Try to find the ipv4 address, if present - if (newAddress.AddressFamily == AddressFamily.InterNetwork) - { - validIpAddress = newAddress; - break; - } - } - catch (HttpException) - { - } - catch (Exception ex) - { - _logger.ErrorException("Error getting connection info", ex); - } - } - } - - if (validIpAddress != null) - { - ((ConnectManager)_connectManager).OnWanAddressResolved(validIpAddress); - CacheAddress(validIpAddress); - } - } - - private async Task GetIpAddress(string lookupUrl, bool preferIpv4 = false) - { - // Sometimes whatismyipaddress might fail, but it won't do us any good having users raise alarms over it. - var logErrors = false; - -#if DEBUG - logErrors = true; -#endif - using (var stream = await _httpClient.Get(new HttpRequestOptions - { - Url = lookupUrl, - UserAgent = "Emby/" + _appHost.ApplicationVersion, - LogErrors = logErrors, - - // Seeing block length errors with our server - EnableHttpCompression = false, - PreferIpv4 = preferIpv4, - BufferContent = false - - }).ConfigureAwait(false)) - { - using (var reader = new StreamReader(stream)) - { - var addressString = await reader.ReadToEndAsync().ConfigureAwait(false); - - return IPAddress.Parse(addressString); - } - } - } - - private string CacheFilePath - { - get { return Path.Combine(_appPaths.DataPath, "wan.txt"); } - } - - private void CacheAddress(IPAddress address) - { - var path = CacheFilePath; - - try - { - _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); - _fileSystem.WriteAllText(path, address.ToString(), Encoding.UTF8); - } - catch (Exception ex) - { - _logger.ErrorException("Error saving data", ex); - } - } - - private void LoadCachedAddress() - { - var path = CacheFilePath; - - _logger.Info("Loading data from {0}", path); - - try - { - var endpoint = _fileSystem.ReadAllText(path, Encoding.UTF8); - IPAddress ipAddress; - - if (IPAddress.TryParse(endpoint, out ipAddress)) - { - ((ConnectManager)_connectManager).OnWanAddressResolved(ipAddress); - } - } - catch (IOException) - { - // File isn't there. no biggie - } - catch (Exception ex) - { - _logger.ErrorException("Error loading data", ex); - } - } - - public void Dispose() - { - if (_timer != null) - { - _timer.Dispose(); - _timer = null; - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs deleted file mode 100644 index 27bbfbe82d..0000000000 --- a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs +++ /dev/null @@ -1,1192 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Net; -using MediaBrowser.Common.Security; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Connect; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Controller.Security; -using MediaBrowser.Model.Connect; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Net; -using MediaBrowser.Model.Serialization; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Model.IO; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.IO; - -namespace MediaBrowser.Server.Implementations.Connect -{ - public class ConnectManager : IConnectManager - { - private readonly SemaphoreSlim _operationLock = new SemaphoreSlim(1, 1); - - private readonly ILogger _logger; - private readonly IApplicationPaths _appPaths; - private readonly IJsonSerializer _json; - private readonly IEncryptionManager _encryption; - private readonly IHttpClient _httpClient; - private readonly IServerApplicationHost _appHost; - private readonly IServerConfigurationManager _config; - private readonly IUserManager _userManager; - private readonly IProviderManager _providerManager; - private readonly ISecurityManager _securityManager; - private readonly IFileSystem _fileSystem; - - private ConnectData _data = new ConnectData(); - - public string ConnectServerId - { - get { return _data.ServerId; } - } - public string ConnectAccessKey - { - get { return _data.AccessKey; } - } - - private IPAddress DiscoveredWanIpAddress { get; set; } - - public string WanIpAddress - { - get - { - var address = _config.Configuration.WanDdns; - - if (!string.IsNullOrWhiteSpace(address)) - { - Uri newUri; - - if (Uri.TryCreate(address, UriKind.Absolute, out newUri)) - { - address = newUri.Host; - } - } - - if (string.IsNullOrWhiteSpace(address) && DiscoveredWanIpAddress != null) - { - if (DiscoveredWanIpAddress.AddressFamily == AddressFamily.InterNetworkV6) - { - address = "[" + DiscoveredWanIpAddress + "]"; - } - else - { - address = DiscoveredWanIpAddress.ToString(); - } - } - - return address; - } - } - - public string WanApiAddress - { - get - { - var ip = WanIpAddress; - - if (!string.IsNullOrEmpty(ip)) - { - if (!ip.StartsWith("http://", StringComparison.OrdinalIgnoreCase) && - !ip.StartsWith("https://", StringComparison.OrdinalIgnoreCase)) - { - ip = (_appHost.EnableHttps ? "https://" : "http://") + ip; - } - - ip += ":"; - ip += _appHost.EnableHttps ? _config.Configuration.PublicHttpsPort.ToString(CultureInfo.InvariantCulture) : _config.Configuration.PublicPort.ToString(CultureInfo.InvariantCulture); - - return ip; - } - - return null; - } - } - - private string XApplicationValue - { - get { return _appHost.Name + "/" + _appHost.ApplicationVersion; } - } - - public ConnectManager(ILogger logger, - IApplicationPaths appPaths, - IJsonSerializer json, - IEncryptionManager encryption, - IHttpClient httpClient, - IServerApplicationHost appHost, - IServerConfigurationManager config, IUserManager userManager, IProviderManager providerManager, ISecurityManager securityManager, IFileSystem fileSystem) - { - _logger = logger; - _appPaths = appPaths; - _json = json; - _encryption = encryption; - _httpClient = httpClient; - _appHost = appHost; - _config = config; - _userManager = userManager; - _providerManager = providerManager; - _securityManager = securityManager; - _fileSystem = fileSystem; - - LoadCachedData(); - } - - internal void Start() - { - _config.ConfigurationUpdated += _config_ConfigurationUpdated; - } - - internal void OnWanAddressResolved(IPAddress address) - { - DiscoveredWanIpAddress = address; - - var task = UpdateConnectInfo(); - } - - private async Task UpdateConnectInfo() - { - await _operationLock.WaitAsync().ConfigureAwait(false); - - try - { - await UpdateConnectInfoInternal().ConfigureAwait(false); - } - finally - { - _operationLock.Release(); - } - } - - private async Task UpdateConnectInfoInternal() - { - var wanApiAddress = WanApiAddress; - - if (string.IsNullOrWhiteSpace(wanApiAddress)) - { - _logger.Warn("Cannot update Emby Connect information without a WanApiAddress"); - return; - } - - try - { - var localAddress = await _appHost.GetLocalApiUrl().ConfigureAwait(false); - - var hasExistingRecord = !string.IsNullOrWhiteSpace(ConnectServerId) && - !string.IsNullOrWhiteSpace(ConnectAccessKey); - - var createNewRegistration = !hasExistingRecord; - - if (hasExistingRecord) - { - try - { - await UpdateServerRegistration(wanApiAddress, localAddress).ConfigureAwait(false); - } - catch (HttpException ex) - { - if (!ex.StatusCode.HasValue || !new[] { HttpStatusCode.NotFound, HttpStatusCode.Unauthorized }.Contains(ex.StatusCode.Value)) - { - throw; - } - - createNewRegistration = true; - } - } - - if (createNewRegistration) - { - await CreateServerRegistration(wanApiAddress, localAddress).ConfigureAwait(false); - } - - _lastReportedIdentifier = GetConnectReportingIdentifier(localAddress, wanApiAddress); - - await RefreshAuthorizationsInternal(true, CancellationToken.None).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error registering with Connect", ex); - } - } - - private string _lastReportedIdentifier; - private async Task GetConnectReportingIdentifier() - { - var url = await _appHost.GetLocalApiUrl().ConfigureAwait(false); - return GetConnectReportingIdentifier(url, WanApiAddress); - } - private string GetConnectReportingIdentifier(string localAddress, string remoteAddress) - { - return (remoteAddress ?? string.Empty) + (localAddress ?? string.Empty); - } - - async void _config_ConfigurationUpdated(object sender, EventArgs e) - { - // If info hasn't changed, don't report anything - var connectIdentifier = await GetConnectReportingIdentifier().ConfigureAwait(false); - if (string.Equals(_lastReportedIdentifier, connectIdentifier, StringComparison.OrdinalIgnoreCase)) - { - return; - } - - await UpdateConnectInfo().ConfigureAwait(false); - } - - private async Task CreateServerRegistration(string wanApiAddress, string localAddress) - { - if (string.IsNullOrWhiteSpace(wanApiAddress)) - { - throw new ArgumentNullException("wanApiAddress"); - } - - var url = "Servers"; - url = GetConnectUrl(url); - - var postData = new Dictionary - { - {"name", _appHost.FriendlyName}, - {"url", wanApiAddress}, - {"systemId", _appHost.SystemId} - }; - - if (!string.IsNullOrWhiteSpace(localAddress)) - { - postData["localAddress"] = localAddress; - } - - var options = new HttpRequestOptions - { - Url = url, - CancellationToken = CancellationToken.None, - BufferContent = false - }; - - options.SetPostData(postData); - SetApplicationHeader(options); - - using (var response = await _httpClient.Post(options).ConfigureAwait(false)) - { - var data = _json.DeserializeFromStream(response.Content); - - _data.ServerId = data.Id; - _data.AccessKey = data.AccessKey; - - CacheData(); - } - } - - private async Task UpdateServerRegistration(string wanApiAddress, string localAddress) - { - if (string.IsNullOrWhiteSpace(wanApiAddress)) - { - throw new ArgumentNullException("wanApiAddress"); - } - - if (string.IsNullOrWhiteSpace(ConnectServerId)) - { - throw new ArgumentNullException("ConnectServerId"); - } - - var url = "Servers"; - url = GetConnectUrl(url); - url += "?id=" + ConnectServerId; - - var postData = new Dictionary - { - {"name", _appHost.FriendlyName}, - {"url", wanApiAddress}, - {"systemId", _appHost.SystemId} - }; - - if (!string.IsNullOrWhiteSpace(localAddress)) - { - postData["localAddress"] = localAddress; - } - - var options = new HttpRequestOptions - { - Url = url, - CancellationToken = CancellationToken.None, - BufferContent = false - }; - - options.SetPostData(postData); - - SetServerAccessToken(options); - SetApplicationHeader(options); - - // No need to examine the response - using (var stream = (await _httpClient.Post(options).ConfigureAwait(false)).Content) - { - } - } - - private readonly object _dataFileLock = new object(); - private string CacheFilePath - { - get { return Path.Combine(_appPaths.DataPath, "connect.txt"); } - } - - private void CacheData() - { - var path = CacheFilePath; - - try - { - _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); - - var json = _json.SerializeToString(_data); - - var encrypted = _encryption.EncryptString(json); - - lock (_dataFileLock) - { - _fileSystem.WriteAllText(path, encrypted, Encoding.UTF8); - } - } - catch (Exception ex) - { - _logger.ErrorException("Error saving data", ex); - } - } - - private void LoadCachedData() - { - var path = CacheFilePath; - - _logger.Info("Loading data from {0}", path); - - try - { - lock (_dataFileLock) - { - var encrypted = _fileSystem.ReadAllText(path, Encoding.UTF8); - - var json = _encryption.DecryptString(encrypted); - - _data = _json.DeserializeFromString(json); - } - } - catch (IOException) - { - // File isn't there. no biggie - } - catch (Exception ex) - { - _logger.ErrorException("Error loading data", ex); - } - } - - private User GetUser(string id) - { - var user = _userManager.GetUserById(id); - - if (user == null) - { - throw new ArgumentException("User not found."); - } - - return user; - } - - private string GetConnectUrl(string handler) - { - return "https://connect.emby.media/service/" + handler; - } - - public async Task LinkUser(string userId, string connectUsername) - { - if (string.IsNullOrWhiteSpace(userId)) - { - throw new ArgumentNullException("userId"); - } - if (string.IsNullOrWhiteSpace(connectUsername)) - { - throw new ArgumentNullException("connectUsername"); - } - if (string.IsNullOrWhiteSpace(ConnectServerId)) - { - await UpdateConnectInfo().ConfigureAwait(false); - } - - await _operationLock.WaitAsync().ConfigureAwait(false); - - try - { - return await LinkUserInternal(userId, connectUsername).ConfigureAwait(false); - } - finally - { - _operationLock.Release(); - } - } - - private async Task LinkUserInternal(string userId, string connectUsername) - { - if (string.IsNullOrWhiteSpace(ConnectServerId)) - { - throw new ArgumentNullException("ConnectServerId"); - } - - var connectUser = await GetConnectUser(new ConnectUserQuery - { - NameOrEmail = connectUsername - - }, CancellationToken.None).ConfigureAwait(false); - - if (!connectUser.IsActive) - { - throw new ArgumentException("The Emby account has been disabled."); - } - - var existingUser = _userManager.Users.FirstOrDefault(i => string.Equals(i.ConnectUserId, connectUser.Id) && !string.IsNullOrWhiteSpace(i.ConnectAccessKey)); - if (existingUser != null) - { - throw new InvalidOperationException("This connect user is already linked to local user " + existingUser.Name); - } - - var user = GetUser(userId); - - if (!string.IsNullOrWhiteSpace(user.ConnectUserId)) - { - await RemoveConnect(user, user.ConnectUserId).ConfigureAwait(false); - } - - var url = GetConnectUrl("ServerAuthorizations"); - - var options = new HttpRequestOptions - { - Url = url, - CancellationToken = CancellationToken.None, - BufferContent = false - }; - - var accessToken = Guid.NewGuid().ToString("N"); - - var postData = new Dictionary - { - {"serverId", ConnectServerId}, - {"userId", connectUser.Id}, - {"userType", "Linked"}, - {"accessToken", accessToken} - }; - - options.SetPostData(postData); - - SetServerAccessToken(options); - SetApplicationHeader(options); - - var result = new UserLinkResult(); - - // No need to examine the response - using (var stream = (await _httpClient.Post(options).ConfigureAwait(false)).Content) - { - var response = _json.DeserializeFromStream(stream); - - result.IsPending = string.Equals(response.AcceptStatus, "waiting", StringComparison.OrdinalIgnoreCase); - } - - user.ConnectAccessKey = accessToken; - user.ConnectUserName = connectUser.Name; - user.ConnectUserId = connectUser.Id; - user.ConnectLinkType = UserLinkType.LinkedUser; - - await user.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); - - await _userManager.UpdateConfiguration(user.Id.ToString("N"), user.Configuration); - - await RefreshAuthorizationsInternal(false, CancellationToken.None).ConfigureAwait(false); - - return result; - } - - public async Task InviteUser(ConnectAuthorizationRequest request) - { - if (string.IsNullOrWhiteSpace(ConnectServerId)) - { - await UpdateConnectInfo().ConfigureAwait(false); - } - - await _operationLock.WaitAsync().ConfigureAwait(false); - - try - { - return await InviteUserInternal(request).ConfigureAwait(false); - } - finally - { - _operationLock.Release(); - } - } - - private async Task InviteUserInternal(ConnectAuthorizationRequest request) - { - var connectUsername = request.ConnectUserName; - var sendingUserId = request.SendingUserId; - - if (string.IsNullOrWhiteSpace(connectUsername)) - { - throw new ArgumentNullException("connectUsername"); - } - if (string.IsNullOrWhiteSpace(ConnectServerId)) - { - throw new ArgumentNullException("ConnectServerId"); - } - - var sendingUser = GetUser(sendingUserId); - var requesterUserName = sendingUser.ConnectUserName; - - if (string.IsNullOrWhiteSpace(requesterUserName)) - { - throw new ArgumentException("A Connect account is required in order to send invitations."); - } - - string connectUserId = null; - var result = new UserLinkResult(); - - try - { - var connectUser = await GetConnectUser(new ConnectUserQuery - { - NameOrEmail = connectUsername - - }, CancellationToken.None).ConfigureAwait(false); - - if (!connectUser.IsActive) - { - throw new ArgumentException("The Emby account is not active. Please ensure the account has been activated by following the instructions within the email confirmation."); - } - - connectUserId = connectUser.Id; - result.GuestDisplayName = connectUser.Name; - } - catch (HttpException ex) - { - if (!ex.StatusCode.HasValue) - { - throw; - } - - // If they entered a username, then whatever the error is just throw it, for example, user not found - if (!Validator.EmailIsValid(connectUsername)) - { - if (ex.StatusCode.Value == HttpStatusCode.NotFound) - { - throw new ResourceNotFoundException(); - } - throw; - } - - if (ex.StatusCode.Value != HttpStatusCode.NotFound) - { - throw; - } - } - - if (string.IsNullOrWhiteSpace(connectUserId)) - { - return await SendNewUserInvitation(requesterUserName, connectUsername).ConfigureAwait(false); - } - - var url = GetConnectUrl("ServerAuthorizations"); - - var options = new HttpRequestOptions - { - Url = url, - CancellationToken = CancellationToken.None, - BufferContent = false - }; - - var accessToken = Guid.NewGuid().ToString("N"); - - var postData = new Dictionary - { - {"serverId", ConnectServerId}, - {"userId", connectUserId}, - {"userType", "Guest"}, - {"accessToken", accessToken}, - {"requesterUserName", requesterUserName} - }; - - options.SetPostData(postData); - - SetServerAccessToken(options); - SetApplicationHeader(options); - - // No need to examine the response - using (var stream = (await _httpClient.Post(options).ConfigureAwait(false)).Content) - { - var response = _json.DeserializeFromStream(stream); - - result.IsPending = string.Equals(response.AcceptStatus, "waiting", StringComparison.OrdinalIgnoreCase); - - _data.PendingAuthorizations.Add(new ConnectAuthorizationInternal - { - ConnectUserId = response.UserId, - Id = response.Id, - ImageUrl = response.UserImageUrl, - UserName = response.UserName, - EnabledLibraries = request.EnabledLibraries, - EnabledChannels = request.EnabledChannels, - EnableLiveTv = request.EnableLiveTv, - AccessToken = accessToken - }); - - CacheData(); - } - - await RefreshAuthorizationsInternal(false, CancellationToken.None).ConfigureAwait(false); - - return result; - } - - private async Task SendNewUserInvitation(string fromName, string email) - { - var url = GetConnectUrl("users/invite"); - - var options = new HttpRequestOptions - { - Url = url, - CancellationToken = CancellationToken.None, - BufferContent = false - }; - - var postData = new Dictionary - { - {"email", email}, - {"requesterUserName", fromName} - }; - - options.SetPostData(postData); - SetApplicationHeader(options); - - // No need to examine the response - using (var stream = (await _httpClient.Post(options).ConfigureAwait(false)).Content) - { - } - - return new UserLinkResult - { - IsNewUserInvitation = true, - GuestDisplayName = email - }; - } - - public Task RemoveConnect(string userId) - { - var user = GetUser(userId); - - return RemoveConnect(user, user.ConnectUserId); - } - - private async Task RemoveConnect(User user, string connectUserId) - { - if (!string.IsNullOrWhiteSpace(connectUserId)) - { - await CancelAuthorizationByConnectUserId(connectUserId).ConfigureAwait(false); - } - - user.ConnectAccessKey = null; - user.ConnectUserName = null; - user.ConnectUserId = null; - user.ConnectLinkType = null; - - await user.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); - } - - private async Task GetConnectUser(ConnectUserQuery query, CancellationToken cancellationToken) - { - var url = GetConnectUrl("user"); - - if (!string.IsNullOrWhiteSpace(query.Id)) - { - url = url + "?id=" + WebUtility.UrlEncode(query.Id); - } - else if (!string.IsNullOrWhiteSpace(query.NameOrEmail)) - { - url = url + "?nameOrEmail=" + WebUtility.UrlEncode(query.NameOrEmail); - } - else if (!string.IsNullOrWhiteSpace(query.Name)) - { - url = url + "?name=" + WebUtility.UrlEncode(query.Name); - } - else if (!string.IsNullOrWhiteSpace(query.Email)) - { - url = url + "?name=" + WebUtility.UrlEncode(query.Email); - } - else - { - throw new ArgumentException("Empty ConnectUserQuery supplied"); - } - - var options = new HttpRequestOptions - { - CancellationToken = cancellationToken, - Url = url, - BufferContent = false - }; - - SetServerAccessToken(options); - SetApplicationHeader(options); - - using (var stream = await _httpClient.Get(options).ConfigureAwait(false)) - { - var response = _json.DeserializeFromStream(stream); - - return new ConnectUser - { - Email = response.Email, - Id = response.Id, - Name = response.Name, - IsActive = response.IsActive, - ImageUrl = response.ImageUrl - }; - } - } - - private void SetApplicationHeader(HttpRequestOptions options) - { - options.RequestHeaders.Add("X-Application", XApplicationValue); - } - - private void SetServerAccessToken(HttpRequestOptions options) - { - if (string.IsNullOrWhiteSpace(ConnectAccessKey)) - { - throw new ArgumentNullException("ConnectAccessKey"); - } - - options.RequestHeaders.Add("X-Connect-Token", ConnectAccessKey); - } - - public async Task RefreshAuthorizations(CancellationToken cancellationToken) - { - await _operationLock.WaitAsync(cancellationToken).ConfigureAwait(false); - - try - { - await RefreshAuthorizationsInternal(true, cancellationToken).ConfigureAwait(false); - } - finally - { - _operationLock.Release(); - } - } - - private async Task RefreshAuthorizationsInternal(bool refreshImages, CancellationToken cancellationToken) - { - if (string.IsNullOrWhiteSpace(ConnectServerId)) - { - throw new ArgumentNullException("ConnectServerId"); - } - - var url = GetConnectUrl("ServerAuthorizations"); - - url += "?serverId=" + ConnectServerId; - - var options = new HttpRequestOptions - { - Url = url, - CancellationToken = cancellationToken, - BufferContent = false - }; - - SetServerAccessToken(options); - SetApplicationHeader(options); - - try - { - using (var stream = (await _httpClient.SendAsync(options, "GET").ConfigureAwait(false)).Content) - { - var list = _json.DeserializeFromStream>(stream); - - await RefreshAuthorizations(list, refreshImages).ConfigureAwait(false); - } - } - catch (Exception ex) - { - _logger.ErrorException("Error refreshing server authorizations.", ex); - } - } - - private readonly SemaphoreSlim _connectImageSemaphore = new SemaphoreSlim(5, 5); - private async Task RefreshAuthorizations(List list, bool refreshImages) - { - var users = _userManager.Users.ToList(); - - // Handle existing authorizations that were removed by the Connect server - // Handle existing authorizations whose status may have been updated - foreach (var user in users) - { - if (!string.IsNullOrWhiteSpace(user.ConnectUserId)) - { - var connectEntry = list.FirstOrDefault(i => string.Equals(i.UserId, user.ConnectUserId, StringComparison.OrdinalIgnoreCase)); - - if (connectEntry == null) - { - var deleteUser = user.ConnectLinkType.HasValue && - user.ConnectLinkType.Value == UserLinkType.Guest; - - user.ConnectUserId = null; - user.ConnectAccessKey = null; - user.ConnectUserName = null; - user.ConnectLinkType = null; - - await _userManager.UpdateUser(user).ConfigureAwait(false); - - if (deleteUser) - { - _logger.Debug("Deleting guest user {0}", user.Name); - await _userManager.DeleteUser(user).ConfigureAwait(false); - } - } - else - { - var changed = !string.Equals(user.ConnectAccessKey, connectEntry.AccessToken, StringComparison.OrdinalIgnoreCase); - - if (changed) - { - user.ConnectUserId = connectEntry.UserId; - user.ConnectAccessKey = connectEntry.AccessToken; - - await _userManager.UpdateUser(user).ConfigureAwait(false); - } - } - } - } - - var currentPendingList = _data.PendingAuthorizations.ToList(); - var newPendingList = new List(); - - foreach (var connectEntry in list) - { - if (string.Equals(connectEntry.UserType, "guest", StringComparison.OrdinalIgnoreCase)) - { - var currentPendingEntry = currentPendingList.FirstOrDefault(i => string.Equals(i.Id, connectEntry.Id, StringComparison.OrdinalIgnoreCase)); - - if (string.Equals(connectEntry.AcceptStatus, "accepted", StringComparison.OrdinalIgnoreCase)) - { - var user = _userManager.Users - .FirstOrDefault(i => string.Equals(i.ConnectUserId, connectEntry.UserId, StringComparison.OrdinalIgnoreCase)); - - if (user == null) - { - // Add user - user = await _userManager.CreateUser(_userManager.MakeValidUsername(connectEntry.UserName)).ConfigureAwait(false); - - user.ConnectUserName = connectEntry.UserName; - user.ConnectUserId = connectEntry.UserId; - user.ConnectLinkType = UserLinkType.Guest; - user.ConnectAccessKey = connectEntry.AccessToken; - - await _userManager.UpdateUser(user).ConfigureAwait(false); - - user.Policy.IsHidden = true; - user.Policy.EnableLiveTvManagement = false; - user.Policy.EnableContentDeletion = false; - user.Policy.EnableRemoteControlOfOtherUsers = false; - user.Policy.EnableSharedDeviceControl = false; - user.Policy.IsAdministrator = false; - - if (currentPendingEntry != null) - { - user.Policy.EnabledFolders = currentPendingEntry.EnabledLibraries; - user.Policy.EnableAllFolders = false; - - user.Policy.EnabledChannels = currentPendingEntry.EnabledChannels; - user.Policy.EnableAllChannels = false; - - user.Policy.EnableLiveTvAccess = currentPendingEntry.EnableLiveTv; - } - - await _userManager.UpdateConfiguration(user.Id.ToString("N"), user.Configuration); - } - } - else if (string.Equals(connectEntry.AcceptStatus, "waiting", StringComparison.OrdinalIgnoreCase)) - { - currentPendingEntry = currentPendingEntry ?? new ConnectAuthorizationInternal(); - - currentPendingEntry.ConnectUserId = connectEntry.UserId; - currentPendingEntry.ImageUrl = connectEntry.UserImageUrl; - currentPendingEntry.UserName = connectEntry.UserName; - currentPendingEntry.Id = connectEntry.Id; - currentPendingEntry.AccessToken = connectEntry.AccessToken; - - newPendingList.Add(currentPendingEntry); - } - } - } - - _data.PendingAuthorizations = newPendingList; - CacheData(); - - await RefreshGuestNames(list, refreshImages).ConfigureAwait(false); - } - - private async Task RefreshGuestNames(List list, bool refreshImages) - { - var users = _userManager.Users - .Where(i => !string.IsNullOrEmpty(i.ConnectUserId) && i.ConnectLinkType.HasValue && i.ConnectLinkType.Value == UserLinkType.Guest) - .ToList(); - - foreach (var user in users) - { - var authorization = list.FirstOrDefault(i => string.Equals(i.UserId, user.ConnectUserId, StringComparison.Ordinal)); - - if (authorization == null) - { - _logger.Warn("Unable to find connect authorization record for user {0}", user.Name); - continue; - } - - var syncConnectName = true; - var syncConnectImage = true; - - if (syncConnectName) - { - var changed = !string.Equals(authorization.UserName, user.Name, StringComparison.OrdinalIgnoreCase); - - if (changed) - { - await user.Rename(authorization.UserName).ConfigureAwait(false); - } - } - - if (syncConnectImage) - { - var imageUrl = authorization.UserImageUrl; - - if (!string.IsNullOrWhiteSpace(imageUrl)) - { - var changed = false; - - if (!user.HasImage(ImageType.Primary)) - { - changed = true; - } - else if (refreshImages) - { - using (var response = await _httpClient.SendAsync(new HttpRequestOptions - { - Url = imageUrl, - BufferContent = false - - }, "HEAD").ConfigureAwait(false)) - { - var length = response.ContentLength; - - if (length != _fileSystem.GetFileInfo(user.GetImageInfo(ImageType.Primary, 0).Path).Length) - { - changed = true; - } - } - } - - if (changed) - { - await _providerManager.SaveImage(user, imageUrl, _connectImageSemaphore, ImageType.Primary, null, CancellationToken.None).ConfigureAwait(false); - - await user.RefreshMetadata(new MetadataRefreshOptions(_fileSystem) - { - ForceSave = true, - - }, CancellationToken.None).ConfigureAwait(false); - } - } - } - } - } - - public async Task> GetPendingGuests() - { - var time = DateTime.UtcNow - _data.LastAuthorizationsRefresh; - - if (time.TotalMinutes >= 5) - { - await _operationLock.WaitAsync(CancellationToken.None).ConfigureAwait(false); - - try - { - await RefreshAuthorizationsInternal(false, CancellationToken.None).ConfigureAwait(false); - - _data.LastAuthorizationsRefresh = DateTime.UtcNow; - CacheData(); - } - catch (Exception ex) - { - _logger.ErrorException("Error refreshing authorization", ex); - } - finally - { - _operationLock.Release(); - } - } - - return _data.PendingAuthorizations.Select(i => new ConnectAuthorization - { - ConnectUserId = i.ConnectUserId, - EnableLiveTv = i.EnableLiveTv, - EnabledChannels = i.EnabledChannels, - EnabledLibraries = i.EnabledLibraries, - Id = i.Id, - ImageUrl = i.ImageUrl, - UserName = i.UserName - - }).ToList(); - } - - public async Task CancelAuthorization(string id) - { - await _operationLock.WaitAsync().ConfigureAwait(false); - - try - { - await CancelAuthorizationInternal(id).ConfigureAwait(false); - } - finally - { - _operationLock.Release(); - } - } - - private async Task CancelAuthorizationInternal(string id) - { - var connectUserId = _data.PendingAuthorizations - .First(i => string.Equals(i.Id, id, StringComparison.Ordinal)) - .ConnectUserId; - - await CancelAuthorizationByConnectUserId(connectUserId).ConfigureAwait(false); - - await RefreshAuthorizationsInternal(false, CancellationToken.None).ConfigureAwait(false); - } - - private async Task CancelAuthorizationByConnectUserId(string connectUserId) - { - if (string.IsNullOrWhiteSpace(connectUserId)) - { - throw new ArgumentNullException("connectUserId"); - } - if (string.IsNullOrWhiteSpace(ConnectServerId)) - { - throw new ArgumentNullException("ConnectServerId"); - } - - var url = GetConnectUrl("ServerAuthorizations"); - - var options = new HttpRequestOptions - { - Url = url, - CancellationToken = CancellationToken.None, - BufferContent = false - }; - - var postData = new Dictionary - { - {"serverId", ConnectServerId}, - {"userId", connectUserId} - }; - - options.SetPostData(postData); - - SetServerAccessToken(options); - SetApplicationHeader(options); - - try - { - // No need to examine the response - using (var stream = (await _httpClient.SendAsync(options, "DELETE").ConfigureAwait(false)).Content) - { - } - } - catch (HttpException ex) - { - // If connect says the auth doesn't exist, we can handle that gracefully since this is a remove operation - - if (!ex.StatusCode.HasValue || ex.StatusCode.Value != HttpStatusCode.NotFound) - { - throw; - } - - _logger.Debug("Connect returned a 404 when removing a user auth link. Handling it."); - } - } - - public async Task Authenticate(string username, string passwordMd5) - { - if (string.IsNullOrWhiteSpace(username)) - { - throw new ArgumentNullException("username"); - } - - if (string.IsNullOrWhiteSpace(passwordMd5)) - { - throw new ArgumentNullException("passwordMd5"); - } - - var options = new HttpRequestOptions - { - Url = GetConnectUrl("user/authenticate"), - BufferContent = false - }; - - options.SetPostData(new Dictionary - { - {"userName",username}, - {"password",passwordMd5} - }); - - SetApplicationHeader(options); - - // No need to examine the response - using (var response = (await _httpClient.SendAsync(options, "POST").ConfigureAwait(false)).Content) - { - } - } - - public async Task GetLocalUser(string connectUserId) - { - var user = _userManager.Users - .FirstOrDefault(i => string.Equals(i.ConnectUserId, connectUserId, StringComparison.OrdinalIgnoreCase)); - - if (user == null) - { - await RefreshAuthorizations(CancellationToken.None).ConfigureAwait(false); - } - - return _userManager.Users - .FirstOrDefault(i => string.Equals(i.ConnectUserId, connectUserId, StringComparison.OrdinalIgnoreCase)); - } - - public User GetUserFromExchangeToken(string token) - { - if (string.IsNullOrWhiteSpace(token)) - { - throw new ArgumentNullException("token"); - } - - return _userManager.Users.FirstOrDefault(u => string.Equals(token, u.ConnectAccessKey, StringComparison.OrdinalIgnoreCase)); - } - - public bool IsAuthorizationTokenValid(string token) - { - if (string.IsNullOrWhiteSpace(token)) - { - throw new ArgumentNullException("token"); - } - - return _userManager.Users.Any(u => string.Equals(token, u.ConnectAccessKey, StringComparison.OrdinalIgnoreCase)) || - _data.PendingAuthorizations.Select(i => i.AccessToken).Contains(token, StringComparer.OrdinalIgnoreCase); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Connect/Responses.cs b/MediaBrowser.Server.Implementations/Connect/Responses.cs deleted file mode 100644 index f865278294..0000000000 --- a/MediaBrowser.Server.Implementations/Connect/Responses.cs +++ /dev/null @@ -1,85 +0,0 @@ -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Connect; - -namespace MediaBrowser.Server.Implementations.Connect -{ - public class ServerRegistrationResponse - { - public string Id { get; set; } - public string Url { get; set; } - public string Name { get; set; } - public string AccessKey { get; set; } - } - - public class UpdateServerRegistrationResponse - { - public string Id { get; set; } - public string Url { get; set; } - public string Name { get; set; } - } - - public class GetConnectUserResponse - { - public string Id { get; set; } - public string Name { get; set; } - public string DisplayName { get; set; } - public string Email { get; set; } - public bool IsActive { get; set; } - public string ImageUrl { get; set; } - } - - public class ServerUserAuthorizationResponse - { - public string Id { get; set; } - public string ServerId { get; set; } - public string UserId { get; set; } - public string AccessToken { get; set; } - public string DateCreated { get; set; } - public bool IsActive { get; set; } - public string AcceptStatus { get; set; } - public string UserType { get; set; } - public string UserImageUrl { get; set; } - public string UserName { get; set; } - } - - public class ConnectUserPreferences - { - public string[] PreferredAudioLanguages { get; set; } - public bool PlayDefaultAudioTrack { get; set; } - public string[] PreferredSubtitleLanguages { get; set; } - public SubtitlePlaybackMode SubtitleMode { get; set; } - public bool GroupMoviesIntoBoxSets { get; set; } - - public ConnectUserPreferences() - { - PreferredAudioLanguages = new string[] { }; - PreferredSubtitleLanguages = new string[] { }; - } - - public static ConnectUserPreferences FromUserConfiguration(UserConfiguration config) - { - return new ConnectUserPreferences - { - PlayDefaultAudioTrack = config.PlayDefaultAudioTrack, - SubtitleMode = config.SubtitleMode, - PreferredAudioLanguages = string.IsNullOrWhiteSpace(config.AudioLanguagePreference) ? new string[] { } : new[] { config.AudioLanguagePreference }, - PreferredSubtitleLanguages = string.IsNullOrWhiteSpace(config.SubtitleLanguagePreference) ? new string[] { } : new[] { config.SubtitleLanguagePreference } - }; - } - - public void MergeInto(UserConfiguration config) - { - - } - } - - public class UserPreferencesDto - { - public T data { get; set; } - } - - public class ConnectAuthorizationInternal : ConnectAuthorization - { - public string AccessToken { get; set; } - } -} diff --git a/MediaBrowser.Server.Implementations/Connect/Validator.cs b/MediaBrowser.Server.Implementations/Connect/Validator.cs deleted file mode 100644 index 8cdfc4a6b3..0000000000 --- a/MediaBrowser.Server.Implementations/Connect/Validator.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Text.RegularExpressions; - -namespace MediaBrowser.Server.Implementations.Connect -{ - public static class Validator - { - static readonly Regex ValidEmailRegex = CreateValidEmailRegex(); - - /// - /// Taken from http://haacked.com/archive/2007/08/21/i-knew-how-to-validate-an-email-address-until-i.aspx - /// - /// - private static Regex CreateValidEmailRegex() - { - const string validEmailPattern = @"^(?!\.)(""([^""\r\\]|\\[""\r\\])*""|" - + @"([-a-z0-9!#$%&'*+/=?^_`{|}~]|(? - /// Class UdpServerEntryPoint - /// - public class UdpServerEntryPoint : IServerEntryPoint - { - /// - /// Gets or sets the UDP server. - /// - /// The UDP server. - private UdpServer UdpServer { get; set; } - - /// - /// The _logger - /// - private readonly ILogger _logger; - /// - /// The _network manager - /// - private readonly INetworkManager _networkManager; - private readonly IServerApplicationHost _appHost; - private readonly IJsonSerializer _json; - - public const int PortNumber = 7359; - - /// - /// Initializes a new instance of the class. - /// - /// The logger. - /// The network manager. - /// The application host. - /// The json. - public UdpServerEntryPoint(ILogger logger, INetworkManager networkManager, IServerApplicationHost appHost, IJsonSerializer json) - { - _logger = logger; - _networkManager = networkManager; - _appHost = appHost; - _json = json; - } - - /// - /// Runs this instance. - /// - public void Run() - { - var udpServer = new UdpServer(_logger, _networkManager, _appHost, _json); - - try - { - udpServer.Start(PortNumber); - - UdpServer = udpServer; - } - catch (Exception ex) - { - _logger.ErrorException("Failed to start UDP Server", ex); - } - } - - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - } - - /// - /// Releases unmanaged and - optionally - managed resources. - /// - /// true to release both managed and unmanaged resources; false to release only unmanaged resources. - protected virtual void Dispose(bool dispose) - { - if (dispose) - { - if (UdpServer != null) - { - UdpServer.Dispose(); - } - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs index 20d89d2eb1..5619348543 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs @@ -1,13 +1,13 @@ using System.Collections.Specialized; using MediaBrowser.Controller.Net; using MediaBrowser.Model.Logging; -using MediaBrowser.Server.Implementations.Logging; using SocketHttpListener.Net; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Emby.Server.Implementations.HttpServer; +using Emby.Server.Implementations.Logging; using MediaBrowser.Common.IO; using MediaBrowser.Model.IO; using MediaBrowser.Model.Services; diff --git a/MediaBrowser.Server.Implementations/IO/FileRefresher.cs b/MediaBrowser.Server.Implementations/IO/FileRefresher.cs deleted file mode 100644 index 2742e1a268..0000000000 --- a/MediaBrowser.Server.Implementations/IO/FileRefresher.cs +++ /dev/null @@ -1,323 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Model.IO; -using MediaBrowser.Common.Events; -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.IO; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Extensions; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Tasks; -using MediaBrowser.Model.Threading; - -namespace MediaBrowser.Server.Implementations.IO -{ - public class FileRefresher : IDisposable - { - private ILogger Logger { get; set; } - private ITaskManager TaskManager { get; set; } - private ILibraryManager LibraryManager { get; set; } - private IServerConfigurationManager ConfigurationManager { get; set; } - private readonly IFileSystem _fileSystem; - private readonly List _affectedPaths = new List(); - private ITimer _timer; - private readonly ITimerFactory _timerFactory; - private readonly object _timerLock = new object(); - public string Path { get; private set; } - - public event EventHandler Completed; - - public FileRefresher(string path, IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, ITaskManager taskManager, ILogger logger, ITimerFactory timerFactory) - { - logger.Debug("New file refresher created for {0}", path); - Path = path; - - _fileSystem = fileSystem; - ConfigurationManager = configurationManager; - LibraryManager = libraryManager; - TaskManager = taskManager; - Logger = logger; - _timerFactory = timerFactory; - AddPath(path); - } - - private void AddAffectedPath(string path) - { - if (string.IsNullOrWhiteSpace(path)) - { - throw new ArgumentNullException("path"); - } - - if (!_affectedPaths.Contains(path, StringComparer.Ordinal)) - { - _affectedPaths.Add(path); - } - } - - public void AddPath(string path) - { - if (string.IsNullOrWhiteSpace(path)) - { - throw new ArgumentNullException("path"); - } - - lock (_timerLock) - { - AddAffectedPath(path); - } - RestartTimer(); - } - - public void RestartTimer() - { - if (_disposed) - { - return; - } - - lock (_timerLock) - { - if (_disposed) - { - return; - } - - if (_timer == null) - { - _timer = _timerFactory.Create(OnTimerCallback, null, TimeSpan.FromSeconds(ConfigurationManager.Configuration.LibraryMonitorDelay), TimeSpan.FromMilliseconds(-1)); - } - else - { - _timer.Change(TimeSpan.FromSeconds(ConfigurationManager.Configuration.LibraryMonitorDelay), TimeSpan.FromMilliseconds(-1)); - } - } - } - - public void ResetPath(string path, string affectedFile) - { - lock (_timerLock) - { - Logger.Debug("Resetting file refresher from {0} to {1}", Path, path); - - Path = path; - AddAffectedPath(path); - - if (!string.IsNullOrWhiteSpace(affectedFile)) - { - AddAffectedPath(affectedFile); - } - } - RestartTimer(); - } - - private async void OnTimerCallback(object state) - { - List paths; - - lock (_timerLock) - { - paths = _affectedPaths.ToList(); - } - - // Extend the timer as long as any of the paths are still being written to. - if (paths.Any(IsFileLocked)) - { - Logger.Info("Timer extended."); - RestartTimer(); - return; - } - - Logger.Debug("Timer stopped."); - - DisposeTimer(); - EventHelper.FireEventIfNotNull(Completed, this, EventArgs.Empty, Logger); - - try - { - await ProcessPathChanges(paths.ToList()).ConfigureAwait(false); - } - catch (Exception ex) - { - Logger.ErrorException("Error processing directory changes", ex); - } - } - - private async Task ProcessPathChanges(List paths) - { - var itemsToRefresh = paths - .Distinct(StringComparer.OrdinalIgnoreCase) - .Select(GetAffectedBaseItem) - .Where(item => item != null) - .DistinctBy(i => i.Id) - .ToList(); - - foreach (var p in paths) - { - Logger.Info(p + " reports change."); - } - - // If the root folder changed, run the library task so the user can see it - if (itemsToRefresh.Any(i => i is AggregateFolder)) - { - LibraryManager.ValidateMediaLibrary(new Progress(), CancellationToken.None); - return; - } - - foreach (var item in itemsToRefresh) - { - Logger.Info(item.Name + " (" + item.Path + ") will be refreshed."); - - try - { - await item.ChangedExternally().ConfigureAwait(false); - } - catch (IOException ex) - { - // For now swallow and log. - // Research item: If an IOException occurs, the item may be in a disconnected state (media unavailable) - // Should we remove it from it's parent? - Logger.ErrorException("Error refreshing {0}", ex, item.Name); - } - catch (Exception ex) - { - Logger.ErrorException("Error refreshing {0}", ex, item.Name); - } - } - } - - /// - /// Gets the affected base item. - /// - /// The path. - /// BaseItem. - private BaseItem GetAffectedBaseItem(string path) - { - BaseItem item = null; - - while (item == null && !string.IsNullOrEmpty(path)) - { - item = LibraryManager.FindByPath(path, null); - - path = System.IO.Path.GetDirectoryName(path); - } - - if (item != null) - { - // If the item has been deleted find the first valid parent that still exists - while (!_fileSystem.DirectoryExists(item.Path) && !_fileSystem.FileExists(item.Path)) - { - item = item.GetParent(); - - if (item == null) - { - break; - } - } - } - - return item; - } - - private bool IsFileLocked(string path) - { - if (Environment.OSVersion.Platform != PlatformID.Win32NT) - { - // Causing lockups on linux - return false; - } - - try - { - var data = _fileSystem.GetFileSystemInfo(path); - - if (!data.Exists - || data.IsDirectory - - // Opening a writable stream will fail with readonly files - || data.IsReadOnly) - { - return false; - } - } - catch (IOException) - { - return false; - } - catch (Exception ex) - { - Logger.ErrorException("Error getting file system info for: {0}", ex, path); - return false; - } - - // In order to determine if the file is being written to, we have to request write access - // But if the server only has readonly access, this is going to cause this entire algorithm to fail - // So we'll take a best guess about our access level - var requestedFileAccess = ConfigurationManager.Configuration.SaveLocalMeta - ? FileAccessMode.ReadWrite - : FileAccessMode.Read; - - try - { - using (_fileSystem.GetFileStream(path, FileOpenMode.Open, requestedFileAccess, FileShareMode.ReadWrite)) - { - //file is not locked - return false; - } - } - //catch (DirectoryNotFoundException) - //{ - // // File may have been deleted - // return false; - //} - catch (FileNotFoundException) - { - // File may have been deleted - return false; - } - catch (UnauthorizedAccessException) - { - Logger.Debug("No write permission for: {0}.", path); - return false; - } - catch (IOException) - { - //the file is unavailable because it is: - //still being written to - //or being processed by another thread - //or does not exist (has already been processed) - Logger.Debug("{0} is locked.", path); - return true; - } - catch (Exception ex) - { - Logger.ErrorException("Error determining if file is locked: {0}", ex, path); - return false; - } - } - - private void DisposeTimer() - { - lock (_timerLock) - { - if (_timer != null) - { - _timer.Dispose(); - _timer = null; - } - } - } - - private bool _disposed; - public void Dispose() - { - _disposed = true; - DisposeTimer(); - } - } -} diff --git a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs index 49cb1e75f4..34fc85e7b1 100644 --- a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs +++ b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs @@ -10,13 +10,14 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; +using Emby.Server.Implementations.IO; using MediaBrowser.Common.IO; using MediaBrowser.Model.IO; using MediaBrowser.Controller; using MediaBrowser.Controller.IO; +using MediaBrowser.Model.System; using MediaBrowser.Model.Tasks; using MediaBrowser.Model.Threading; -using Microsoft.Win32; namespace MediaBrowser.Server.Implementations.IO { @@ -142,7 +143,7 @@ namespace MediaBrowser.Server.Implementations.IO /// /// Initializes a new instance of the class. /// - public LibraryMonitor(ILogManager logManager, ITaskManager taskManager, ILibraryManager libraryManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ITimerFactory timerFactory) + public LibraryMonitor(ILogManager logManager, ITaskManager taskManager, ILibraryManager libraryManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ITimerFactory timerFactory, ISystemEvents systemEvents) { if (taskManager == null) { @@ -156,15 +157,10 @@ namespace MediaBrowser.Server.Implementations.IO _fileSystem = fileSystem; _timerFactory = timerFactory; - SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged; + systemEvents.Resume += _systemEvents_Resume; } - /// - /// Handles the PowerModeChanged event of the SystemEvents control. - /// - /// The source of the event. - /// The instance containing the event data. - void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e) + private void _systemEvents_Resume(object sender, EventArgs e) { Restart(); } diff --git a/MediaBrowser.Server.Implementations/Logging/PatternsLogger.cs b/MediaBrowser.Server.Implementations/Logging/PatternsLogger.cs deleted file mode 100644 index 00b6cc5a8b..0000000000 --- a/MediaBrowser.Server.Implementations/Logging/PatternsLogger.cs +++ /dev/null @@ -1,63 +0,0 @@ -using Patterns.Logging; -using System; - -namespace MediaBrowser.Server.Implementations.Logging -{ - public class PatternsLogger : ILogger - { - private readonly Model.Logging.ILogger _logger; - - public PatternsLogger() - : this(new Model.Logging.NullLogger()) - { - } - - public PatternsLogger(Model.Logging.ILogger logger) - { - _logger = logger; - } - - public void Debug(string message, params object[] paramList) - { - _logger.Debug(message, paramList); - } - - public void Error(string message, params object[] paramList) - { - _logger.Error(message, paramList); - } - - public void ErrorException(string message, Exception exception, params object[] paramList) - { - _logger.ErrorException(message, exception, paramList); - } - - public void Fatal(string message, params object[] paramList) - { - _logger.Fatal(message, paramList); - } - - public void FatalException(string message, Exception exception, params object[] paramList) - { - _logger.FatalException(message, exception, paramList); - } - - public void Info(string message, params object[] paramList) - { - _logger.Info(message, paramList); - } - - public void Warn(string message, params object[] paramList) - { - _logger.Warn(message, paramList); - } - - public void Log(LogSeverity severity, string message, params object[] paramList) - { - } - - public void LogMultiline(string message, LogSeverity severity, System.Text.StringBuilder additionalContent) - { - } - } -} diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index d6223c4655..066ee8e306 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -113,15 +113,9 @@ - - - - - - @@ -140,7 +134,6 @@ - @@ -166,7 +159,6 @@ - @@ -180,15 +172,12 @@ - - - diff --git a/MediaBrowser.Server.Implementations/Security/EncryptionManager.cs b/MediaBrowser.Server.Implementations/Security/EncryptionManager.cs deleted file mode 100644 index cd9b9651ec..0000000000 --- a/MediaBrowser.Server.Implementations/Security/EncryptionManager.cs +++ /dev/null @@ -1,51 +0,0 @@ -using MediaBrowser.Controller.Security; -using System; -using System.Text; - -namespace MediaBrowser.Server.Implementations.Security -{ - public class EncryptionManager : IEncryptionManager - { - /// - /// Encrypts the string. - /// - /// The value. - /// System.String. - /// value - public string EncryptString(string value) - { - if (value == null) throw new ArgumentNullException("value"); - - return EncryptStringUniversal(value); - } - - /// - /// Decrypts the string. - /// - /// The value. - /// System.String. - /// value - public string DecryptString(string value) - { - if (value == null) throw new ArgumentNullException("value"); - - return DecryptStringUniversal(value); - } - - private string EncryptStringUniversal(string value) - { - // Yes, this isn't good, but ProtectedData in mono is throwing exceptions, so use this for now - - var bytes = Encoding.UTF8.GetBytes(value); - return Convert.ToBase64String(bytes); - } - - private string DecryptStringUniversal(string value) - { - // Yes, this isn't good, but ProtectedData in mono is throwing exceptions, so use this for now - - var bytes = Convert.FromBase64String(value); - return Encoding.UTF8.GetString(bytes); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Udp/UdpMessageReceivedEventArgs.cs b/MediaBrowser.Server.Implementations/Udp/UdpMessageReceivedEventArgs.cs deleted file mode 100644 index 5c83a13007..0000000000 --- a/MediaBrowser.Server.Implementations/Udp/UdpMessageReceivedEventArgs.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; - -namespace MediaBrowser.Server.Implementations.Udp -{ - /// - /// Class UdpMessageReceivedEventArgs - /// - public class UdpMessageReceivedEventArgs : EventArgs - { - /// - /// Gets or sets the bytes. - /// - /// The bytes. - public byte[] Bytes { get; set; } - /// - /// Gets or sets the remote end point. - /// - /// The remote end point. - public string RemoteEndPoint { get; set; } - } -} diff --git a/MediaBrowser.Server.Implementations/Udp/UdpServer.cs b/MediaBrowser.Server.Implementations/Udp/UdpServer.cs deleted file mode 100644 index c2082f0d2a..0000000000 --- a/MediaBrowser.Server.Implementations/Udp/UdpServer.cs +++ /dev/null @@ -1,328 +0,0 @@ -using MediaBrowser.Common.Net; -using MediaBrowser.Controller; -using MediaBrowser.Model.ApiClient; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Serialization; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading.Tasks; -using Emby.Common.Implementations.Networking; - -namespace MediaBrowser.Server.Implementations.Udp -{ - /// - /// Provides a Udp Server - /// - public class UdpServer : IDisposable - { - /// - /// The _logger - /// - private readonly ILogger _logger; - - /// - /// The _network manager - /// - private readonly INetworkManager _networkManager; - - private bool _isDisposed; - - private readonly List>> _responders = new List>>(); - - private readonly IServerApplicationHost _appHost; - private readonly IJsonSerializer _json; - - /// - /// Initializes a new instance of the class. - /// - /// The logger. - /// The network manager. - /// The application host. - /// The json. - public UdpServer(ILogger logger, INetworkManager networkManager, IServerApplicationHost appHost, IJsonSerializer json) - { - _logger = logger; - _networkManager = networkManager; - _appHost = appHost; - _json = json; - - AddMessageResponder("who is EmbyServer?", true, RespondToV2Message); - AddMessageResponder("who is MediaBrowserServer_v2?", false, RespondToV2Message); - } - - private void AddMessageResponder(string message, bool isSubstring, Func responder) - { - _responders.Add(new Tuple>(message, isSubstring, responder)); - } - - /// - /// Raises the event. - /// - /// The instance containing the event data. - private async void OnMessageReceived(UdpMessageReceivedEventArgs e) - { - var encoding = Encoding.UTF8; - var responder = GetResponder(e.Bytes, encoding); - - if (responder == null) - { - encoding = Encoding.Unicode; - responder = GetResponder(e.Bytes, encoding); - } - - if (responder != null) - { - try - { - await responder.Item2.Item3(responder.Item1, e.RemoteEndPoint, encoding).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error in OnMessageReceived", ex); - } - } - } - - private Tuple>> GetResponder(byte[] bytes, Encoding encoding) - { - var text = encoding.GetString(bytes); - var responder = _responders.FirstOrDefault(i => - { - if (i.Item2) - { - return text.IndexOf(i.Item1, StringComparison.OrdinalIgnoreCase) != -1; - } - return string.Equals(i.Item1, text, StringComparison.OrdinalIgnoreCase); - }); - - if (responder == null) - { - return null; - } - return new Tuple>>(text, responder); - } - - private async Task RespondToV2Message(string messageText, string endpoint, Encoding encoding) - { - var parts = messageText.Split('|'); - - var localUrl = await _appHost.GetLocalApiUrl().ConfigureAwait(false); - - if (!string.IsNullOrEmpty(localUrl)) - { - var response = new ServerDiscoveryInfo - { - Address = localUrl, - Id = _appHost.SystemId, - Name = _appHost.FriendlyName - }; - - await SendAsync(encoding.GetBytes(_json.SerializeToString(response)), endpoint).ConfigureAwait(false); - - if (parts.Length > 1) - { - _appHost.EnableLoopback(parts[1]); - } - } - else - { - _logger.Warn("Unable to respond to udp request because the local ip address could not be determined."); - } - } - - /// - /// The _udp client - /// - private UdpClient _udpClient; - - /// - /// Starts the specified port. - /// - /// The port. - public void Start(int port) - { - _udpClient = new UdpClient(new IPEndPoint(IPAddress.Any, port)); - - _udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); - - Task.Run(() => StartListening()); - } - - private async void StartListening() - { - while (!_isDisposed) - { - try - { - var result = await GetResult().ConfigureAwait(false); - - OnMessageReceived(result); - } - catch (ObjectDisposedException) - { - break; - } - catch (Exception ex) - { - _logger.ErrorException("Error in StartListening", ex); - } - } - } - - private Task GetResult() - { - try - { - return _udpClient.ReceiveAsync(); - } - catch (ObjectDisposedException) - { - return Task.FromResult(new UdpReceiveResult(new byte[] { }, new IPEndPoint(IPAddress.Any, 0))); - } - catch (Exception ex) - { - _logger.ErrorException("Error receiving udp message", ex); - return Task.FromResult(new UdpReceiveResult(new byte[] { }, new IPEndPoint(IPAddress.Any, 0))); - } - } - - /// - /// Called when [message received]. - /// - /// The message. - private void OnMessageReceived(UdpReceiveResult message) - { - if (message.RemoteEndPoint.Port == 0) - { - return; - } - var bytes = message.Buffer; - - try - { - OnMessageReceived(new UdpMessageReceivedEventArgs - { - Bytes = bytes, - RemoteEndPoint = message.RemoteEndPoint.ToString() - }); - } - catch (Exception ex) - { - _logger.ErrorException("Error handling UDP message", ex); - } - } - - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// Stops this instance. - /// - public void Stop() - { - _isDisposed = true; - - if (_udpClient != null) - { - _udpClient.Close(); - } - } - - /// - /// Releases unmanaged and - optionally - managed resources. - /// - /// true to release both managed and unmanaged resources; false to release only unmanaged resources. - protected virtual void Dispose(bool dispose) - { - if (dispose) - { - Stop(); - } - } - - /// - /// Sends the async. - /// - /// The data. - /// The ip address. - /// The port. - /// Task{System.Int32}. - /// data - public Task SendAsync(string data, string ipAddress, int port) - { - return SendAsync(Encoding.UTF8.GetBytes(data), ipAddress, port); - } - - /// - /// Sends the async. - /// - /// The bytes. - /// The ip address. - /// The port. - /// Task{System.Int32}. - /// bytes - public Task SendAsync(byte[] bytes, string ipAddress, int port) - { - if (bytes == null) - { - throw new ArgumentNullException("bytes"); - } - - if (string.IsNullOrEmpty(ipAddress)) - { - throw new ArgumentNullException("ipAddress"); - } - - return _udpClient.SendAsync(bytes, bytes.Length, ipAddress, port); - } - - /// - /// Sends the async. - /// - /// The bytes. - /// The remote end point. - /// Task. - /// - /// bytes - /// or - /// remoteEndPoint - /// - public async Task SendAsync(byte[] bytes, string remoteEndPoint) - { - if (bytes == null) - { - throw new ArgumentNullException("bytes"); - } - - if (string.IsNullOrEmpty(remoteEndPoint)) - { - throw new ArgumentNullException("remoteEndPoint"); - } - - try - { - // Need to do this until Common will compile with this method - var nativeNetworkManager = (BaseNetworkManager) _networkManager; - - await _udpClient.SendAsync(bytes, bytes.Length, nativeNetworkManager.Parse(remoteEndPoint)).ConfigureAwait(false); - - _logger.Info("Udp message sent to {0}", remoteEndPoint); - } - catch (Exception ex) - { - _logger.ErrorException("Error sending message to {0}", ex, remoteEndPoint); - } - } - } - -} -- cgit v1.2.3 From 67ad1db6b77b2c2cb6d81c22808d99564a5f3ebc Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 4 Nov 2016 15:51:59 -0400 Subject: add environment info --- Emby.Common.Implementations/BaseApplicationHost.cs | 17 ++---- .../EnvironmentInfo/EnvironmentInfo.cs | 70 ++++++++++++++++++++++ Emby.Common.Implementations/Net/SocketFactory.cs | 7 +-- Emby.Common.Implementations/Net/UdpSocket.cs | 18 +++--- .../Serialization/XmlSerializer.cs | 17 +++--- Emby.Common.Implementations/project.json | 9 +-- Emby.Dlna/Main/DlnaEntryPoint.cs | 8 ++- Emby.Server.Implementations/IO/FileRefresher.cs | 15 +++-- MediaBrowser.Model/MediaBrowser.Model.csproj | 1 + MediaBrowser.Model/System/IEnvironmentInfo.cs | 22 +++++++ .../IO/LibraryMonitor.cs | 6 +- .../ApplicationHost.cs | 2 +- 12 files changed, 142 insertions(+), 50 deletions(-) create mode 100644 Emby.Common.Implementations/EnvironmentInfo/EnvironmentInfo.cs create mode 100644 MediaBrowser.Model/System/IEnvironmentInfo.cs (limited to 'MediaBrowser.Server.Implementations') diff --git a/Emby.Common.Implementations/BaseApplicationHost.cs b/Emby.Common.Implementations/BaseApplicationHost.cs index bdebe894ef..9585abb2a2 100644 --- a/Emby.Common.Implementations/BaseApplicationHost.cs +++ b/Emby.Common.Implementations/BaseApplicationHost.cs @@ -29,6 +29,7 @@ using MediaBrowser.Common.Extensions; using Emby.Common.Implementations.Cryptography; using Emby.Common.Implementations.Diagnostics; using Emby.Common.Implementations.Net; +using Emby.Common.Implementations.EnvironmentInfo; using Emby.Common.Implementations.Threading; using MediaBrowser.Common; using MediaBrowser.Common.IO; @@ -171,6 +172,8 @@ namespace Emby.Common.Implementations protected ICryptographyProvider CryptographyProvider = new CryptographyProvider(); + protected IEnvironmentInfo EnvironmentInfo = new Emby.Common.Implementations.EnvironmentInfo.EnvironmentInfo(); + private DeviceId _deviceId; public string SystemId { @@ -187,16 +190,7 @@ namespace Emby.Common.Implementations public virtual string OperatingSystemDisplayName { - get - { -#if NET46 - return Environment.OSVersion.VersionString; -#endif -#if NETSTANDARD1_6 - return System.Runtime.InteropServices.RuntimeInformation.OSDescription; -#endif - return "Operating System"; - } + get { return EnvironmentInfo.OperatingSystemName; } } public IMemoryStreamProvider MemoryStreamProvider { get; set; } @@ -216,7 +210,7 @@ namespace Emby.Common.Implementations // hack alert, until common can target .net core BaseExtensions.CryptographyProvider = CryptographyProvider; - XmlSerializer = new XmlSerializer(fileSystem, logManager.GetLogger("XmlSerializer")); + XmlSerializer = new MyXmlSerializer(fileSystem, logManager.GetLogger("XmlSerializer")); FailedAssemblies = new List(); ApplicationPaths = applicationPaths; @@ -534,6 +528,7 @@ return null; RegisterSingleInstance(Logger); RegisterSingleInstance(TaskManager); + RegisterSingleInstance(EnvironmentInfo); RegisterSingleInstance(FileSystemManager); diff --git a/Emby.Common.Implementations/EnvironmentInfo/EnvironmentInfo.cs b/Emby.Common.Implementations/EnvironmentInfo/EnvironmentInfo.cs new file mode 100644 index 0000000000..8cea617eae --- /dev/null +++ b/Emby.Common.Implementations/EnvironmentInfo/EnvironmentInfo.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using MediaBrowser.Model.System; + +namespace Emby.Common.Implementations.EnvironmentInfo +{ + public class EnvironmentInfo : IEnvironmentInfo + { + public MediaBrowser.Model.System.OperatingSystem OperatingSystem + { + get + { +#if NET46 + switch (Environment.OSVersion.Platform) + { + case PlatformID.MacOSX: + return MediaBrowser.Model.System.OperatingSystem.OSX; + case PlatformID.Win32NT: + return MediaBrowser.Model.System.OperatingSystem.Windows; + case PlatformID.Unix: + return MediaBrowser.Model.System.OperatingSystem.Linux; + } +#elif NETSTANDARD1_6 + if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + return OperatingSystem.OSX; + } + if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return OperatingSystem.Windows; + } + if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + return OperatingSystem.Linux; + } +#endif + return MediaBrowser.Model.System.OperatingSystem.Windows; + } + } + + public string OperatingSystemName + { + get + { +#if NET46 + return Environment.OSVersion.Platform.ToString(); +#elif NETSTANDARD1_6 + return System.Runtime.InteropServices.RuntimeInformation.OSDescription; +#endif + return "Operating System"; + } + } + + public string OperatingSystemVersion + { + get + { +#if NET46 + return Environment.OSVersion.Version.ToString() + " " + Environment.OSVersion.ServicePack.ToString(); +#elif NETSTANDARD1_6 + return System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription; +#endif + return "1.0"; + } + } + } +} diff --git a/Emby.Common.Implementations/Net/SocketFactory.cs b/Emby.Common.Implementations/Net/SocketFactory.cs index 6f0ff29961..bb38c72da5 100644 --- a/Emby.Common.Implementations/Net/SocketFactory.cs +++ b/Emby.Common.Implementations/Net/SocketFactory.cs @@ -40,12 +40,11 @@ namespace Emby.Common.Implementations.Net /// Creates a new UDP socket and binds it to the specified local port. /// /// An integer specifying the local port to bind the socket to. - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "The purpose of this method is to create and returns a disposable result, it is up to the caller to dispose it when they are done with it.")] public IUdpSocket CreateUdpSocket(int localPort) { if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort"); - var retVal = new Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp); + var retVal = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); try { retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); @@ -65,12 +64,11 @@ namespace Emby.Common.Implementations.Net /// /// An integer specifying the local port to bind the socket to. /// An implementation of the interface used by RSSDP components to perform socket operations. - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "The purpose of this method is to create and returns a disposable result, it is up to the caller to dispose it when they are done with it.")] public IUdpSocket CreateSsdpUdpSocket(int localPort) { if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort"); - var retVal = new Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp); + var retVal = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); try { retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); @@ -94,7 +92,6 @@ namespace Emby.Common.Implementations.Net /// The multicast time to live value for the socket. /// The number of the local port to bind to. /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "ip"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "The purpose of this method is to create and returns a disposable result, it is up to the caller to dispose it when they are done with it.")] public IUdpSocket CreateUdpMulticastSocket(string ipAddress, int multicastTimeToLive, int localPort) { if (ipAddress == null) throw new ArgumentNullException("ipAddress"); diff --git a/Emby.Common.Implementations/Net/UdpSocket.cs b/Emby.Common.Implementations/Net/UdpSocket.cs index 997d3f25fa..6afb071ae3 100644 --- a/Emby.Common.Implementations/Net/UdpSocket.cs +++ b/Emby.Common.Implementations/Net/UdpSocket.cs @@ -17,14 +17,14 @@ namespace Emby.Common.Implementations.Net #region Fields - private System.Net.Sockets.Socket _Socket; + private Socket _Socket; private int _LocalPort; #endregion #region Constructors - public UdpSocket(System.Net.Sockets.Socket socket, int localPort, IPAddress ip) + public UdpSocket(Socket socket, int localPort, IPAddress ip) { if (socket == null) throw new ArgumentNullException("socket"); @@ -46,12 +46,12 @@ namespace Emby.Common.Implementations.Net var tcs = new TaskCompletionSource(); - System.Net.EndPoint receivedFromEndPoint = new IPEndPoint(IPAddress.Any, 0); + EndPoint receivedFromEndPoint = new IPEndPoint(IPAddress.Any, 0); var state = new AsyncReceiveState(_Socket, receivedFromEndPoint); state.TaskCompletionSource = tcs; #if NETSTANDARD1_6 - _Socket.ReceiveFromAsync(new System.ArraySegment(state.Buffer), System.Net.Sockets.SocketFlags.None, state.EndPoint) + _Socket.ReceiveFromAsync(new ArraySegment(state.Buffer),SocketFlags.None, state.EndPoint) .ContinueWith((task, asyncState) => { if (task.Status != TaskStatus.Faulted) @@ -62,7 +62,7 @@ namespace Emby.Common.Implementations.Net } }, state); #else - _Socket.BeginReceiveFrom(state.Buffer, 0, state.Buffer.Length, System.Net.Sockets.SocketFlags.None, ref state.EndPoint, new AsyncCallback(this.ProcessResponse), state); + _Socket.BeginReceiveFrom(state.Buffer, 0, state.Buffer.Length, SocketFlags.None, ref state.EndPoint, new AsyncCallback(this.ProcessResponse), state); #endif return tcs.Task; @@ -84,7 +84,7 @@ namespace Emby.Common.Implementations.Net buffer = copy; } - _Socket.SendTo(buffer, new System.Net.IPEndPoint(IPAddress.Parse(endPoint.IpAddress.ToString()), endPoint.Port)); + _Socket.SendTo(buffer, new IPEndPoint(IPAddress.Parse(endPoint.IpAddress.ToString()), endPoint.Port)); return Task.FromResult(true); #else var taskSource = new TaskCompletionSource(); @@ -153,7 +153,6 @@ namespace Emby.Common.Implementations.Net #region Private Methods - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exceptions via task methods should be reported by task completion source, so this should be ok.")] private static void ProcessResponse(AsyncReceiveState state, Func receiveData) { try @@ -206,7 +205,6 @@ namespace Emby.Common.Implementations.Net }; } - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exceptions via task methods should be reported by task completion source, so this should be ok.")] private void ProcessResponse(IAsyncResult asyncResult) { #if NET46 @@ -249,7 +247,7 @@ namespace Emby.Common.Implementations.Net private class AsyncReceiveState { - public AsyncReceiveState(System.Net.Sockets.Socket socket, EndPoint endPoint) + public AsyncReceiveState(Socket socket, EndPoint endPoint) { this.Socket = socket; this.EndPoint = endPoint; @@ -258,7 +256,7 @@ namespace Emby.Common.Implementations.Net public EndPoint EndPoint; public byte[] Buffer = new byte[8192]; - public System.Net.Sockets.Socket Socket { get; private set; } + public Socket Socket { get; private set; } public TaskCompletionSource TaskCompletionSource { get; set; } diff --git a/Emby.Common.Implementations/Serialization/XmlSerializer.cs b/Emby.Common.Implementations/Serialization/XmlSerializer.cs index aea63a57e2..3583f998e5 100644 --- a/Emby.Common.Implementations/Serialization/XmlSerializer.cs +++ b/Emby.Common.Implementations/Serialization/XmlSerializer.cs @@ -4,6 +4,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Xml; +using System.Xml.Serialization; using MediaBrowser.Common.IO; using MediaBrowser.Model.IO; using MediaBrowser.Model.Logging; @@ -13,12 +14,12 @@ namespace Emby.Common.Implementations.Serialization /// /// Provides a wrapper around third party xml serialization. /// - public class XmlSerializer : IXmlSerializer + public class MyXmlSerializer : IXmlSerializer { private readonly IFileSystem _fileSystem; private readonly ILogger _logger; - public XmlSerializer(IFileSystem fileSystem, ILogger logger) + public MyXmlSerializer(IFileSystem fileSystem, ILogger logger) { _fileSystem = fileSystem; _logger = logger; @@ -26,18 +27,18 @@ namespace Emby.Common.Implementations.Serialization // Need to cache these // http://dotnetcodebox.blogspot.com/2013/01/xmlserializer-class-may-result-in.html - private readonly Dictionary _serializers = - new Dictionary(); + private readonly Dictionary _serializers = + new Dictionary(); - private System.Xml.Serialization.XmlSerializer GetSerializer(Type type) + private XmlSerializer GetSerializer(Type type) { var key = type.FullName; lock (_serializers) { - System.Xml.Serialization.XmlSerializer serializer; + XmlSerializer serializer; if (!_serializers.TryGetValue(key, out serializer)) { - serializer = new System.Xml.Serialization.XmlSerializer(type); + serializer = new XmlSerializer(type); _serializers[key] = serializer; } return serializer; @@ -80,7 +81,7 @@ namespace Emby.Common.Implementations.Serialization #if NET46 using (var writer = new XmlTextWriter(stream, null)) { - writer.Formatting = System.Xml.Formatting.Indented; + writer.Formatting = Formatting.Indented; SerializeToWriter(obj, writer); } #else diff --git a/Emby.Common.Implementations/project.json b/Emby.Common.Implementations/project.json index dc96f5726c..2b2357e383 100644 --- a/Emby.Common.Implementations/project.json +++ b/Emby.Common.Implementations/project.json @@ -12,15 +12,14 @@ "System.IO": "4.0.0.0", "System.Net": "4.0.0.0", "System.Net.Http": "4.0.0.0", - "System.Net.Http.WebRequest": "4.0.0.0", "System.Net.Primitives": "4.0.0.0", + "System.Net.Http.WebRequest": "4.0.0.0", "System.Runtime": "4.0.0.0", "System.Runtime.Extensions": "4.0.0.0", "System.Text.Encoding": "4.0.0.0", "System.Threading": "4.0.0.0", "System.Threading.Tasks": "4.0.0.0", - "System.Xml": "4.0.0.0", - "System.Xml.Serialization": "4.0.0.0" + "System.Xml.ReaderWriter": "4.0.0" }, "dependencies": { "SimpleInjector": "3.2.4", @@ -30,7 +29,8 @@ }, "MediaBrowser.Common": { "target": "project" - } } + } + } }, "netstandard1.6": { "imports": "dnxcore50", @@ -40,6 +40,7 @@ "System.Diagnostics.Process": "4.1.0", "System.Threading.Timer": "4.0.1", "System.Net.Requests": "4.0.11", + "System.Xml.ReaderWriter": "4.0.11", "System.Xml.XmlSerializer": "4.0.11", "System.Net.Http": "4.1.0", "System.Net.Primitives": "4.0.11", diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs index 14fbbcfa20..bff87bcacc 100644 --- a/Emby.Dlna/Main/DlnaEntryPoint.cs +++ b/Emby.Dlna/Main/DlnaEntryPoint.cs @@ -20,6 +20,7 @@ using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Net; +using MediaBrowser.Model.System; using MediaBrowser.Model.Threading; using Rssdp; using Rssdp.Infrastructure; @@ -52,7 +53,7 @@ namespace Emby.Dlna.Main private readonly ITimerFactory _timerFactory; private readonly ISocketFactory _socketFactory; - + private readonly IEnvironmentInfo _environmentInfo; public DlnaEntryPoint(IServerConfigurationManager config, ILogManager logManager, @@ -66,7 +67,7 @@ namespace Emby.Dlna.Main IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, - IDeviceDiscovery deviceDiscovery, IMediaEncoder mediaEncoder, ISocketFactory socketFactory, ITimerFactory timerFactory) + IDeviceDiscovery deviceDiscovery, IMediaEncoder mediaEncoder, ISocketFactory socketFactory, ITimerFactory timerFactory, IEnvironmentInfo environmentInfo) { _config = config; _appHost = appHost; @@ -83,6 +84,7 @@ namespace Emby.Dlna.Main _mediaEncoder = mediaEncoder; _socketFactory = socketFactory; _timerFactory = timerFactory; + _environmentInfo = environmentInfo; _logger = logManager.GetLogger("Dlna"); } @@ -169,7 +171,7 @@ namespace Emby.Dlna.Main private void StartPublishing() { SsdpDevicePublisherBase.LogFunction = LogMessage; - _Publisher = new SsdpDevicePublisher(_socketFactory, _timerFactory, "Windows", "10"); + _Publisher = new SsdpDevicePublisher(_socketFactory, _timerFactory, _environmentInfo.OperatingSystemName, _environmentInfo.OperatingSystemVersion); } private void StartDeviceDiscovery() diff --git a/Emby.Server.Implementations/IO/FileRefresher.cs b/Emby.Server.Implementations/IO/FileRefresher.cs index 295ecc4651..39033249fd 100644 --- a/Emby.Server.Implementations/IO/FileRefresher.cs +++ b/Emby.Server.Implementations/IO/FileRefresher.cs @@ -13,6 +13,7 @@ using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Extensions; using MediaBrowser.Model.Logging; +using MediaBrowser.Model.System; using MediaBrowser.Model.Tasks; using MediaBrowser.Model.Threading; @@ -32,8 +33,9 @@ namespace Emby.Server.Implementations.IO public string Path { get; private set; } public event EventHandler Completed; + private readonly IEnvironmentInfo _environmentInfo; - public FileRefresher(string path, IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, ITaskManager taskManager, ILogger logger, ITimerFactory timerFactory) + public FileRefresher(string path, IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, ITaskManager taskManager, ILogger logger, ITimerFactory timerFactory, IEnvironmentInfo environmentInfo) { logger.Debug("New file refresher created for {0}", path); Path = path; @@ -44,6 +46,7 @@ namespace Emby.Server.Implementations.IO TaskManager = taskManager; Logger = logger; _timerFactory = timerFactory; + _environmentInfo = environmentInfo; AddPath(path); } @@ -226,11 +229,11 @@ namespace Emby.Server.Implementations.IO private bool IsFileLocked(string path) { - //if (Environment.OSVersion.Platform != PlatformID.Win32NT) - //{ - // // Causing lockups on linux - // return false; - //} + if (_environmentInfo.OperatingSystem != OperatingSystem.Windows) + { + // Causing lockups on linux + return false; + } try { diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index c85b215f2c..52e477b1a0 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -141,6 +141,7 @@ + diff --git a/MediaBrowser.Model/System/IEnvironmentInfo.cs b/MediaBrowser.Model/System/IEnvironmentInfo.cs new file mode 100644 index 0000000000..3fcacb30d4 --- /dev/null +++ b/MediaBrowser.Model/System/IEnvironmentInfo.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MediaBrowser.Model.System +{ + public interface IEnvironmentInfo + { + MediaBrowser.Model.System.OperatingSystem OperatingSystem { get; } + string OperatingSystemName { get; } + string OperatingSystemVersion { get; } + } + + public enum OperatingSystem + { + Windows, + Linux, + OSX + } +} diff --git a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs index 34fc85e7b1..a8363558d5 100644 --- a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs +++ b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs @@ -139,11 +139,12 @@ namespace MediaBrowser.Server.Implementations.IO private readonly IFileSystem _fileSystem; private readonly ITimerFactory _timerFactory; + private readonly IEnvironmentInfo _environmentInfo; /// /// Initializes a new instance of the class. /// - public LibraryMonitor(ILogManager logManager, ITaskManager taskManager, ILibraryManager libraryManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ITimerFactory timerFactory, ISystemEvents systemEvents) + public LibraryMonitor(ILogManager logManager, ITaskManager taskManager, ILibraryManager libraryManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ITimerFactory timerFactory, ISystemEvents systemEvents, IEnvironmentInfo environmentInfo) { if (taskManager == null) { @@ -156,6 +157,7 @@ namespace MediaBrowser.Server.Implementations.IO ConfigurationManager = configurationManager; _fileSystem = fileSystem; _timerFactory = timerFactory; + _environmentInfo = environmentInfo; systemEvents.Resume += _systemEvents_Resume; } @@ -525,7 +527,7 @@ namespace MediaBrowser.Server.Implementations.IO } } - var newRefresher = new FileRefresher(path, _fileSystem, ConfigurationManager, LibraryManager, TaskManager, Logger, _timerFactory); + var newRefresher = new FileRefresher(path, _fileSystem, ConfigurationManager, LibraryManager, TaskManager, Logger, _timerFactory, _environmentInfo); newRefresher.Completed += NewRefresher_Completed; _activeRefreshers.Add(newRefresher); } diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 79f7b5f051..ba04338bb9 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -592,7 +592,7 @@ namespace MediaBrowser.Server.Startup.Common var musicManager = new MusicManager(LibraryManager); RegisterSingleInstance(new MusicManager(LibraryManager)); - LibraryMonitor = new LibraryMonitor(LogManager, TaskManager, LibraryManager, ServerConfigurationManager, FileSystemManager, TimerFactory, SystemEvents); + LibraryMonitor = new LibraryMonitor(LogManager, TaskManager, LibraryManager, ServerConfigurationManager, FileSystemManager, TimerFactory, SystemEvents, EnvironmentInfo); RegisterSingleInstance(LibraryMonitor); ProviderManager = new ProviderManager(HttpClient, ServerConfigurationManager, LibraryMonitor, LogManager, FileSystemManager, ApplicationPaths, () => LibraryManager, JsonSerializer, MemoryStreamProvider); -- cgit v1.2.3 From 3c1447804b5de9a7d840c7158c3cb4e0a27f76e1 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 4 Nov 2016 22:17:18 -0400 Subject: move localization classes --- Emby.Dlna/Didl/DidlBuilder.cs | 8 +- .../Emby.Server.Implementations.csproj | 246 +++++- .../HttpServer/GetSwaggerResource.cs | 17 + .../HttpServer/SocketSharp/HttpUtility.cs | 922 ++++++++++++++++++++ .../HttpServer/SwaggerService.cs | 46 + .../Localization/Core/ar.json | 178 ++++ .../Localization/Core/bg-BG.json | 178 ++++ .../Localization/Core/ca.json | 178 ++++ .../Localization/Core/core.json | 179 ++++ .../Localization/Core/cs.json | 178 ++++ .../Localization/Core/da.json | 178 ++++ .../Localization/Core/de.json | 178 ++++ .../Localization/Core/el.json | 178 ++++ .../Localization/Core/en-GB.json | 178 ++++ .../Localization/Core/en-US.json | 178 ++++ .../Localization/Core/es-AR.json | 178 ++++ .../Localization/Core/es-MX.json | 178 ++++ .../Localization/Core/es.json | 178 ++++ .../Localization/Core/fi.json | 178 ++++ .../Localization/Core/fr-CA.json | 178 ++++ .../Localization/Core/fr.json | 178 ++++ .../Localization/Core/gsw.json | 178 ++++ .../Localization/Core/he.json | 178 ++++ .../Localization/Core/hr.json | 178 ++++ .../Localization/Core/hu.json | 178 ++++ .../Localization/Core/id.json | 178 ++++ .../Localization/Core/it.json | 178 ++++ .../Localization/Core/kk.json | 178 ++++ .../Localization/Core/ko.json | 178 ++++ .../Localization/Core/ms.json | 178 ++++ .../Localization/Core/nb.json | 178 ++++ .../Localization/Core/nl.json | 178 ++++ .../Localization/Core/pl.json | 178 ++++ .../Localization/Core/pt-BR.json | 178 ++++ .../Localization/Core/pt-PT.json | 178 ++++ .../Localization/Core/ro.json | 178 ++++ .../Localization/Core/ru.json | 178 ++++ .../Localization/Core/sl-SI.json | 178 ++++ .../Localization/Core/sv.json | 178 ++++ .../Localization/Core/tr.json | 178 ++++ .../Localization/Core/uk.json | 178 ++++ .../Localization/Core/vi.json | 178 ++++ .../Localization/Core/zh-CN.json | 178 ++++ .../Localization/Core/zh-HK.json | 178 ++++ .../Localization/Core/zh-TW.json | 178 ++++ .../Localization/LocalizationManager.cs | 433 ++++++++++ .../Localization/Ratings/au.txt | 8 + .../Localization/Ratings/be.txt | 6 + .../Localization/Ratings/br.txt | 6 + .../Localization/Ratings/ca.txt | 6 + .../Localization/Ratings/co.txt | 8 + .../Localization/Ratings/de.txt | 10 + .../Localization/Ratings/dk.txt | 4 + .../Localization/Ratings/fr.txt | 5 + .../Localization/Ratings/gb.txt | 7 + .../Localization/Ratings/ie.txt | 6 + .../Localization/Ratings/jp.txt | 4 + .../Localization/Ratings/kz.txt | 6 + .../Localization/Ratings/mx.txt | 6 + .../Localization/Ratings/nl.txt | 6 + .../Localization/Ratings/nz.txt | 10 + .../Localization/Ratings/ru.txt | 5 + .../Localization/Ratings/us.txt | 22 + .../Localization/countries.json | 1 + .../Localization/iso6392.txt | 487 +++++++++++ .../HttpServer/GetSwaggerResource.cs | 17 - .../HttpServer/HttpListenerHost.cs | 1 + .../HttpServer/SocketSharp/HttpUtility.cs | 942 --------------------- .../SocketSharp/WebSocketSharpRequest.cs | 1 + .../HttpServer/SwaggerService.cs | 43 - .../Localization/Core/ar.json | 178 ---- .../Localization/Core/bg-BG.json | 178 ---- .../Localization/Core/ca.json | 178 ---- .../Localization/Core/core.json | 179 ---- .../Localization/Core/cs.json | 178 ---- .../Localization/Core/da.json | 178 ---- .../Localization/Core/de.json | 178 ---- .../Localization/Core/el.json | 178 ---- .../Localization/Core/en-GB.json | 178 ---- .../Localization/Core/en-US.json | 178 ---- .../Localization/Core/es-AR.json | 178 ---- .../Localization/Core/es-MX.json | 178 ---- .../Localization/Core/es.json | 178 ---- .../Localization/Core/fi.json | 178 ---- .../Localization/Core/fr-CA.json | 178 ---- .../Localization/Core/fr.json | 178 ---- .../Localization/Core/gsw.json | 178 ---- .../Localization/Core/he.json | 178 ---- .../Localization/Core/hr.json | 178 ---- .../Localization/Core/hu.json | 178 ---- .../Localization/Core/id.json | 178 ---- .../Localization/Core/it.json | 178 ---- .../Localization/Core/kk.json | 178 ---- .../Localization/Core/ko.json | 178 ---- .../Localization/Core/ms.json | 178 ---- .../Localization/Core/nb.json | 178 ---- .../Localization/Core/nl.json | 178 ---- .../Localization/Core/pl.json | 178 ---- .../Localization/Core/pt-BR.json | 178 ---- .../Localization/Core/pt-PT.json | 178 ---- .../Localization/Core/ro.json | 178 ---- .../Localization/Core/ru.json | 178 ---- .../Localization/Core/sl-SI.json | 178 ---- .../Localization/Core/sv.json | 178 ---- .../Localization/Core/tr.json | 178 ---- .../Localization/Core/uk.json | 178 ---- .../Localization/Core/vi.json | 178 ---- .../Localization/Core/zh-CN.json | 178 ---- .../Localization/Core/zh-HK.json | 178 ---- .../Localization/Core/zh-TW.json | 178 ---- .../Localization/LocalizationManager.cs | 422 --------- .../Localization/Ratings/au.txt | 8 - .../Localization/Ratings/be.txt | 6 - .../Localization/Ratings/br.txt | 6 - .../Localization/Ratings/ca.txt | 6 - .../Localization/Ratings/co.txt | 8 - .../Localization/Ratings/de.txt | 10 - .../Localization/Ratings/dk.txt | 4 - .../Localization/Ratings/fr.txt | 5 - .../Localization/Ratings/gb.txt | 7 - .../Localization/Ratings/ie.txt | 6 - .../Localization/Ratings/jp.txt | 4 - .../Localization/Ratings/kz.txt | 6 - .../Localization/Ratings/mx.txt | 6 - .../Localization/Ratings/nl.txt | 6 - .../Localization/Ratings/nz.txt | 10 - .../Localization/Ratings/ru.txt | 5 - .../Localization/Ratings/us.txt | 22 - .../Localization/countries.json | 1 - .../Localization/iso6392.txt | 487 ----------- .../MediaBrowser.Server.Implementations.csproj | 209 ----- .../ApplicationHost.cs | 9 +- .../MediaBrowser.Server.Startup.Common.csproj | 1 + .../TextLocalizer.cs | 25 + 134 files changed, 9434 insertions(+), 9376 deletions(-) create mode 100644 Emby.Server.Implementations/HttpServer/GetSwaggerResource.cs create mode 100644 Emby.Server.Implementations/HttpServer/SocketSharp/HttpUtility.cs create mode 100644 Emby.Server.Implementations/HttpServer/SwaggerService.cs create mode 100644 Emby.Server.Implementations/Localization/Core/ar.json create mode 100644 Emby.Server.Implementations/Localization/Core/bg-BG.json create mode 100644 Emby.Server.Implementations/Localization/Core/ca.json create mode 100644 Emby.Server.Implementations/Localization/Core/core.json create mode 100644 Emby.Server.Implementations/Localization/Core/cs.json create mode 100644 Emby.Server.Implementations/Localization/Core/da.json create mode 100644 Emby.Server.Implementations/Localization/Core/de.json create mode 100644 Emby.Server.Implementations/Localization/Core/el.json create mode 100644 Emby.Server.Implementations/Localization/Core/en-GB.json create mode 100644 Emby.Server.Implementations/Localization/Core/en-US.json create mode 100644 Emby.Server.Implementations/Localization/Core/es-AR.json create mode 100644 Emby.Server.Implementations/Localization/Core/es-MX.json create mode 100644 Emby.Server.Implementations/Localization/Core/es.json create mode 100644 Emby.Server.Implementations/Localization/Core/fi.json create mode 100644 Emby.Server.Implementations/Localization/Core/fr-CA.json create mode 100644 Emby.Server.Implementations/Localization/Core/fr.json create mode 100644 Emby.Server.Implementations/Localization/Core/gsw.json create mode 100644 Emby.Server.Implementations/Localization/Core/he.json create mode 100644 Emby.Server.Implementations/Localization/Core/hr.json create mode 100644 Emby.Server.Implementations/Localization/Core/hu.json create mode 100644 Emby.Server.Implementations/Localization/Core/id.json create mode 100644 Emby.Server.Implementations/Localization/Core/it.json create mode 100644 Emby.Server.Implementations/Localization/Core/kk.json create mode 100644 Emby.Server.Implementations/Localization/Core/ko.json create mode 100644 Emby.Server.Implementations/Localization/Core/ms.json create mode 100644 Emby.Server.Implementations/Localization/Core/nb.json create mode 100644 Emby.Server.Implementations/Localization/Core/nl.json create mode 100644 Emby.Server.Implementations/Localization/Core/pl.json create mode 100644 Emby.Server.Implementations/Localization/Core/pt-BR.json create mode 100644 Emby.Server.Implementations/Localization/Core/pt-PT.json create mode 100644 Emby.Server.Implementations/Localization/Core/ro.json create mode 100644 Emby.Server.Implementations/Localization/Core/ru.json create mode 100644 Emby.Server.Implementations/Localization/Core/sl-SI.json create mode 100644 Emby.Server.Implementations/Localization/Core/sv.json create mode 100644 Emby.Server.Implementations/Localization/Core/tr.json create mode 100644 Emby.Server.Implementations/Localization/Core/uk.json create mode 100644 Emby.Server.Implementations/Localization/Core/vi.json create mode 100644 Emby.Server.Implementations/Localization/Core/zh-CN.json create mode 100644 Emby.Server.Implementations/Localization/Core/zh-HK.json create mode 100644 Emby.Server.Implementations/Localization/Core/zh-TW.json create mode 100644 Emby.Server.Implementations/Localization/LocalizationManager.cs create mode 100644 Emby.Server.Implementations/Localization/Ratings/au.txt create mode 100644 Emby.Server.Implementations/Localization/Ratings/be.txt create mode 100644 Emby.Server.Implementations/Localization/Ratings/br.txt create mode 100644 Emby.Server.Implementations/Localization/Ratings/ca.txt create mode 100644 Emby.Server.Implementations/Localization/Ratings/co.txt create mode 100644 Emby.Server.Implementations/Localization/Ratings/de.txt create mode 100644 Emby.Server.Implementations/Localization/Ratings/dk.txt create mode 100644 Emby.Server.Implementations/Localization/Ratings/fr.txt create mode 100644 Emby.Server.Implementations/Localization/Ratings/gb.txt create mode 100644 Emby.Server.Implementations/Localization/Ratings/ie.txt create mode 100644 Emby.Server.Implementations/Localization/Ratings/jp.txt create mode 100644 Emby.Server.Implementations/Localization/Ratings/kz.txt create mode 100644 Emby.Server.Implementations/Localization/Ratings/mx.txt create mode 100644 Emby.Server.Implementations/Localization/Ratings/nl.txt create mode 100644 Emby.Server.Implementations/Localization/Ratings/nz.txt create mode 100644 Emby.Server.Implementations/Localization/Ratings/ru.txt create mode 100644 Emby.Server.Implementations/Localization/Ratings/us.txt create mode 100644 Emby.Server.Implementations/Localization/countries.json create mode 100644 Emby.Server.Implementations/Localization/iso6392.txt delete mode 100644 MediaBrowser.Server.Implementations/HttpServer/GetSwaggerResource.cs delete mode 100644 MediaBrowser.Server.Implementations/HttpServer/SocketSharp/HttpUtility.cs delete mode 100644 MediaBrowser.Server.Implementations/HttpServer/SwaggerService.cs delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/ar.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/bg-BG.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/ca.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/core.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/cs.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/da.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/de.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/el.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/en-GB.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/en-US.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/es-AR.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/es-MX.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/es.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/fi.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/fr-CA.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/fr.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/gsw.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/he.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/hr.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/hu.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/id.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/it.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/kk.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/ko.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/ms.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/nb.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/nl.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/pl.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/pt-BR.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/pt-PT.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/ro.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/ru.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/sl-SI.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/sv.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/tr.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/uk.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/vi.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/zh-CN.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/zh-HK.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/Core/zh-TW.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs delete mode 100644 MediaBrowser.Server.Implementations/Localization/Ratings/au.txt delete mode 100644 MediaBrowser.Server.Implementations/Localization/Ratings/be.txt delete mode 100644 MediaBrowser.Server.Implementations/Localization/Ratings/br.txt delete mode 100644 MediaBrowser.Server.Implementations/Localization/Ratings/ca.txt delete mode 100644 MediaBrowser.Server.Implementations/Localization/Ratings/co.txt delete mode 100644 MediaBrowser.Server.Implementations/Localization/Ratings/de.txt delete mode 100644 MediaBrowser.Server.Implementations/Localization/Ratings/dk.txt delete mode 100644 MediaBrowser.Server.Implementations/Localization/Ratings/fr.txt delete mode 100644 MediaBrowser.Server.Implementations/Localization/Ratings/gb.txt delete mode 100644 MediaBrowser.Server.Implementations/Localization/Ratings/ie.txt delete mode 100644 MediaBrowser.Server.Implementations/Localization/Ratings/jp.txt delete mode 100644 MediaBrowser.Server.Implementations/Localization/Ratings/kz.txt delete mode 100644 MediaBrowser.Server.Implementations/Localization/Ratings/mx.txt delete mode 100644 MediaBrowser.Server.Implementations/Localization/Ratings/nl.txt delete mode 100644 MediaBrowser.Server.Implementations/Localization/Ratings/nz.txt delete mode 100644 MediaBrowser.Server.Implementations/Localization/Ratings/ru.txt delete mode 100644 MediaBrowser.Server.Implementations/Localization/Ratings/us.txt delete mode 100644 MediaBrowser.Server.Implementations/Localization/countries.json delete mode 100644 MediaBrowser.Server.Implementations/Localization/iso6392.txt create mode 100644 MediaBrowser.Server.Startup.Common/TextLocalizer.cs (limited to 'MediaBrowser.Server.Implementations') diff --git a/Emby.Dlna/Didl/DidlBuilder.cs b/Emby.Dlna/Didl/DidlBuilder.cs index 50668f5557..ee5c8fecd4 100644 --- a/Emby.Dlna/Didl/DidlBuilder.cs +++ b/Emby.Dlna/Didl/DidlBuilder.cs @@ -104,6 +104,8 @@ namespace Emby.Dlna.Didl writer.WriteStartElement(string.Empty, "item", NS_DIDL); + AddGeneralProperties(item, null, context, writer, filter); + writer.WriteAttributeString("restricted", "1"); writer.WriteAttributeString("id", clientId); @@ -122,8 +124,6 @@ namespace Emby.Dlna.Didl //AddBookmarkInfo(item, user, element); - AddGeneralProperties(item, null, context, writer, filter); - // refID? // storeAttribute(itemNode, object, ClassProperties.REF_ID, false); @@ -501,6 +501,8 @@ namespace Emby.Dlna.Didl { writer.WriteStartElement(string.Empty, "container", NS_DIDL); + AddGeneralProperties(folder, stubType, context, writer, filter); + writer.WriteAttributeString("restricted", "0"); writer.WriteAttributeString("searchable", "1"); writer.WriteAttributeString("childCount", childCount.ToString(_usCulture)); @@ -534,8 +536,6 @@ namespace Emby.Dlna.Didl } } - AddCommonFields(folder, stubType, null, writer, filter); - AddCover(folder, context, stubType, writer); writer.WriteEndElement(); diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 8d13d206ac..33f29d64da 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -67,11 +67,14 @@ + + + @@ -144,6 +147,7 @@ + @@ -230,7 +234,9 @@ - + + + {9142eefa-7570-41e1-bfcc-468bb571af2f} @@ -266,8 +272,246 @@ + + swagger-ui\fonts\droid-sans-v6-latin-700.svg + PreserveNewest + + + swagger-ui\fonts\droid-sans-v6-latin-regular.svg + PreserveNewest + + + swagger-ui\images\explorer_icons.png + PreserveNewest + + + swagger-ui\images\logo_small.png + PreserveNewest + + + swagger-ui\images\pet_store_api.png + PreserveNewest + + + swagger-ui\images\throbber.gif + PreserveNewest + + + swagger-ui\images\wordnik_api.png + PreserveNewest + + + swagger-ui\index.html + PreserveNewest + + + swagger-ui\lib\backbone-min.js + PreserveNewest + + + swagger-ui\lib\handlebars-2.0.0.js + PreserveNewest + + + swagger-ui\lib\highlight.7.3.pack.js + PreserveNewest + + + swagger-ui\lib\jquery-1.8.0.min.js + PreserveNewest + + + swagger-ui\lib\jquery.ba-bbq.min.js + PreserveNewest + + + swagger-ui\lib\jquery.slideto.min.js + PreserveNewest + + + swagger-ui\lib\jquery.wiggle.min.js + PreserveNewest + + + swagger-ui\lib\marked.js + PreserveNewest + + + swagger-ui\lib\shred.bundle.js + PreserveNewest + + + swagger-ui\lib\shred\content.js + PreserveNewest + + + swagger-ui\lib\swagger-client.js + PreserveNewest + + + swagger-ui\lib\swagger-oauth.js + PreserveNewest + + + swagger-ui\lib\underscore-min.js + PreserveNewest + + + swagger-ui\o2c.html + PreserveNewest + + + swagger-ui\patch.js + PreserveNewest + + + swagger-ui\swagger-ui.js + PreserveNewest + + + swagger-ui\swagger-ui.min.js + PreserveNewest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + swagger-ui\fonts\droid-sans-v6-latin-700.eot + PreserveNewest + + + swagger-ui\fonts\droid-sans-v6-latin-700.ttf + PreserveNewest + + + swagger-ui\fonts\droid-sans-v6-latin-700.woff + PreserveNewest + + + swagger-ui\fonts\droid-sans-v6-latin-700.woff2 + PreserveNewest + + + swagger-ui\fonts\droid-sans-v6-latin-regular.eot + PreserveNewest + + + swagger-ui\fonts\droid-sans-v6-latin-regular.ttf + PreserveNewest + + + swagger-ui\fonts\droid-sans-v6-latin-regular.woff + PreserveNewest + + + swagger-ui\fonts\droid-sans-v6-latin-regular.woff2 + PreserveNewest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + swagger-ui\css\reset.css + PreserveNewest + + + swagger-ui\css\screen.css + PreserveNewest + + + swagger-ui\css\typography.css + PreserveNewest + +