Merge pull request #2277 from MediaBrowser/dev

Dev
This commit is contained in:
Luke 2016-11-08 14:55:32 -05:00 committed by GitHub
commit 82c46a84e4
85 changed files with 1201 additions and 952 deletions

View File

@ -22,7 +22,7 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using MediaBrowser.Model.TextEncoding; using MediaBrowser.Model.Text;
namespace BDInfo namespace BDInfo
{ {
@ -75,7 +75,7 @@ namespace BDInfo
public event OnPlaylistFileScanError PlaylistFileScanError; public event OnPlaylistFileScanError PlaylistFileScanError;
public BDROM( public BDROM(
string path, IFileSystem fileSystem, IEncoding textEncoding) string path, IFileSystem fileSystem, ITextEncoding textEncoding)
{ {
_fileSystem = fileSystem; _fileSystem = fileSystem;
// //

View File

@ -23,14 +23,14 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text; using System.Text;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using MediaBrowser.Model.TextEncoding; using MediaBrowser.Model.Text;
namespace BDInfo namespace BDInfo
{ {
public class TSPlaylistFile public class TSPlaylistFile
{ {
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly IEncoding _textEncoding; private readonly ITextEncoding _textEncoding;
private FileSystemMetadata FileInfo = null; private FileSystemMetadata FileInfo = null;
public string FileType = null; public string FileType = null;
public bool IsInitialized = false; public bool IsInitialized = false;
@ -67,7 +67,7 @@ namespace BDInfo
public TSPlaylistFile( public TSPlaylistFile(
BDROM bdrom, BDROM bdrom,
FileSystemMetadata fileInfo, IFileSystem fileSystem, IEncoding textEncoding) FileSystemMetadata fileInfo, IFileSystem fileSystem, ITextEncoding textEncoding)
{ {
BDROM = bdrom; BDROM = bdrom;
FileInfo = fileInfo; FileInfo = fileInfo;
@ -79,7 +79,7 @@ namespace BDInfo
public TSPlaylistFile( public TSPlaylistFile(
BDROM bdrom, BDROM bdrom,
string name, string name,
List<TSStreamClip> clips, IFileSystem fileSystem, IEncoding textEncoding) List<TSStreamClip> clips, IFileSystem fileSystem, ITextEncoding textEncoding)
{ {
BDROM = bdrom; BDROM = bdrom;
Name = name; Name = name;
@ -1247,7 +1247,7 @@ namespace BDInfo
ref int pos) ref int pos)
{ {
string val = string val =
_textEncoding.GetASCIIString(data, pos, count); _textEncoding.GetASCIIEncoding().GetString(data, pos, count);
pos += count; pos += count;

View File

@ -23,14 +23,14 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text; using System.Text;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using MediaBrowser.Model.TextEncoding; using MediaBrowser.Model.Text;
namespace BDInfo namespace BDInfo
{ {
public class TSStreamClipFile public class TSStreamClipFile
{ {
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly IEncoding _textEncoding; private readonly ITextEncoding _textEncoding;
public FileSystemMetadata FileInfo = null; public FileSystemMetadata FileInfo = null;
public string FileType = null; public string FileType = null;
public bool IsValid = false; public bool IsValid = false;
@ -40,7 +40,7 @@ namespace BDInfo
new Dictionary<ushort,TSStream>(); new Dictionary<ushort,TSStream>();
public TSStreamClipFile( public TSStreamClipFile(
FileSystemMetadata fileInfo, IFileSystem fileSystem, IEncoding textEncoding) FileSystemMetadata fileInfo, IFileSystem fileSystem, ITextEncoding textEncoding)
{ {
FileInfo = fileInfo; FileInfo = fileInfo;
_fileSystem = fileSystem; _fileSystem = fileSystem;
@ -70,7 +70,7 @@ namespace BDInfo
byte[] fileType = new byte[8]; byte[] fileType = new byte[8];
Array.Copy(data, 0, fileType, 0, fileType.Length); Array.Copy(data, 0, fileType, 0, fileType.Length);
FileType = _textEncoding.GetASCIIString(fileType, 0, fileType.Length); FileType = _textEncoding.GetASCIIEncoding().GetString(fileType, 0, fileType.Length);
if (FileType != "HDMV0100" && if (FileType != "HDMV0100" &&
FileType != "HDMV0200") FileType != "HDMV0200")
{ {
@ -167,7 +167,7 @@ namespace BDInfo
Array.Copy(clipData, streamOffset + 3, Array.Copy(clipData, streamOffset + 3,
languageBytes, 0, languageBytes.Length); languageBytes, 0, languageBytes.Length);
string languageCode = string languageCode =
_textEncoding.GetASCIIString(languageBytes, 0, languageBytes.Length); _textEncoding.GetASCIIEncoding().GetString(languageBytes, 0, languageBytes.Length);
TSChannelLayout channelLayout = (TSChannelLayout) TSChannelLayout channelLayout = (TSChannelLayout)
(clipData[streamOffset + 2] >> 4); (clipData[streamOffset + 2] >> 4);
@ -198,7 +198,7 @@ namespace BDInfo
Array.Copy(clipData, streamOffset + 2, Array.Copy(clipData, streamOffset + 2,
languageBytes, 0, languageBytes.Length); languageBytes, 0, languageBytes.Length);
string languageCode = string languageCode =
_textEncoding.GetASCIIString(languageBytes, 0, languageBytes.Length); _textEncoding.GetASCIIEncoding().GetString(languageBytes, 0, languageBytes.Length);
stream = new TSGraphicsStream(); stream = new TSGraphicsStream();
stream.LanguageCode = languageCode; stream.LanguageCode = languageCode;
@ -218,7 +218,7 @@ namespace BDInfo
Array.Copy(clipData, streamOffset + 3, Array.Copy(clipData, streamOffset + 3,
languageBytes, 0, languageBytes.Length); languageBytes, 0, languageBytes.Length);
string languageCode = string languageCode =
_textEncoding.GetASCIIString(languageBytes, 0, languageBytes.Length); _textEncoding.GetASCIIEncoding().GetString(languageBytes, 0, languageBytes.Length);
#if DEBUG #if DEBUG
Debug.WriteLine(string.Format( Debug.WriteLine(string.Format(
"\t{0} {1} {2}", "\t{0} {1} {2}",

View File

@ -170,7 +170,7 @@ namespace Emby.Common.Implementations
/// <value><c>true</c> if this instance is running as service; otherwise, <c>false</c>.</value> /// <value><c>true</c> if this instance is running as service; otherwise, <c>false</c>.</value>
public abstract bool IsRunningAsService { get; } public abstract bool IsRunningAsService { get; }
protected ICryptographyProvider CryptographyProvider = new CryptographyProvider(); protected ICryptoProvider CryptographyProvider = new CryptographyProvider();
protected IEnvironmentInfo EnvironmentInfo = new Emby.Common.Implementations.EnvironmentInfo.EnvironmentInfo(); protected IEnvironmentInfo EnvironmentInfo = new Emby.Common.Implementations.EnvironmentInfo.EnvironmentInfo();
@ -183,7 +183,7 @@ namespace Emby.Common.Implementations
{ {
_deviceId = new DeviceId(ApplicationPaths, LogManager.GetLogger("SystemId"), FileSystemManager); _deviceId = new DeviceId(ApplicationPaths, LogManager.GetLogger("SystemId"), FileSystemManager);
} }
return _deviceId.Value; return _deviceId.Value;
} }
} }
@ -193,7 +193,7 @@ namespace Emby.Common.Implementations
get { return EnvironmentInfo.OperatingSystemName; } get { return EnvironmentInfo.OperatingSystemName; }
} }
public IMemoryStreamProvider MemoryStreamProvider { get; set; } public IMemoryStreamFactory MemoryStreamProvider { get; set; }
/// <summary> /// <summary>
/// The container /// The container
@ -209,7 +209,7 @@ namespace Emby.Common.Implementations
{ {
// hack alert, until common can target .net core // hack alert, until common can target .net core
BaseExtensions.CryptographyProvider = CryptographyProvider; BaseExtensions.CryptographyProvider = CryptographyProvider;
XmlSerializer = new MyXmlSerializer(fileSystem, logManager.GetLogger("XmlSerializer")); XmlSerializer = new MyXmlSerializer(fileSystem, logManager.GetLogger("XmlSerializer"));
FailedAssemblies = new List<string>(); FailedAssemblies = new List<string>();
@ -267,7 +267,7 @@ namespace Emby.Common.Implementations
progress.Report(100); progress.Report(100);
} }
protected abstract IMemoryStreamProvider CreateMemoryStreamProvider(); protected abstract IMemoryStreamFactory CreateMemoryStreamProvider();
protected abstract ISystemEvents CreateSystemEvents(); protected abstract ISystemEvents CreateSystemEvents();
protected virtual void OnLoggerLoaded(bool isFirstLoad) protected virtual void OnLoggerLoaded(bool isFirstLoad)

View File

@ -6,21 +6,14 @@ using MediaBrowser.Model.Cryptography;
namespace Emby.Common.Implementations.Cryptography namespace Emby.Common.Implementations.Cryptography
{ {
public class CryptographyProvider : ICryptographyProvider public class CryptographyProvider : ICryptoProvider
{ {
public Guid GetMD5(string str) public Guid GetMD5(string str)
{ {
return new Guid(GetMD5Bytes(str)); return new Guid(ComputeMD5(Encoding.Unicode.GetBytes(str)));
}
public byte[] GetMD5Bytes(string str)
{
using (var provider = MD5.Create())
{
return provider.ComputeHash(Encoding.Unicode.GetBytes(str));
}
} }
public byte[] GetSHA1Bytes(byte[] bytes) public byte[] ComputeSHA1(byte[] bytes)
{ {
using (var provider = SHA1.Create()) using (var provider = SHA1.Create())
{ {
@ -28,7 +21,7 @@ namespace Emby.Common.Implementations.Cryptography
} }
} }
public byte[] GetMD5Bytes(Stream str) public byte[] ComputeMD5(Stream str)
{ {
using (var provider = MD5.Create()) using (var provider = MD5.Create())
{ {
@ -36,7 +29,7 @@ namespace Emby.Common.Implementations.Cryptography
} }
} }
public byte[] GetMD5Bytes(byte[] bytes) public byte[] ComputeMD5(byte[] bytes)
{ {
using (var provider = MD5.Create()) using (var provider = MD5.Create())
{ {

View File

@ -42,7 +42,7 @@ namespace Emby.Common.Implementations.HttpClientManager
private readonly IApplicationPaths _appPaths; private readonly IApplicationPaths _appPaths;
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly IMemoryStreamProvider _memoryStreamProvider; private readonly IMemoryStreamFactory _memoryStreamProvider;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="HttpClientManager" /> class. /// Initializes a new instance of the <see cref="HttpClientManager" /> class.
@ -53,7 +53,7 @@ namespace Emby.Common.Implementations.HttpClientManager
/// <exception cref="System.ArgumentNullException">appPaths /// <exception cref="System.ArgumentNullException">appPaths
/// or /// or
/// logger</exception> /// logger</exception>
public HttpClientManager(IApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem, IMemoryStreamProvider memoryStreamProvider) public HttpClientManager(IApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem, IMemoryStreamFactory memoryStreamProvider)
{ {
if (appPaths == null) if (appPaths == null)
{ {

View File

@ -0,0 +1,85 @@
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Emby.Common.Implementations.Networking;
using MediaBrowser.Model.Net;
using MediaBrowser.Model.Logging;
namespace Emby.Common.Implementations.Net
{
public class NetSocket : ISocket
{
public Socket Socket { get; private set; }
private readonly ILogger _logger;
public NetSocket(Socket socket, ILogger logger)
{
Socket = socket;
_logger = logger;
}
public IpEndPointInfo LocalEndPoint
{
get
{
return BaseNetworkManager.ToIpEndPointInfo((IPEndPoint)Socket.LocalEndPoint);
}
}
public IpEndPointInfo RemoteEndPoint
{
get
{
return BaseNetworkManager.ToIpEndPointInfo((IPEndPoint)Socket.RemoteEndPoint);
}
}
public void Close()
{
#if NET46
Socket.Close();
#else
Socket.Dispose();
#endif
}
public void Shutdown(bool both)
{
if (both)
{
Socket.Shutdown(SocketShutdown.Both);
}
else
{
// Change interface if ever needed
throw new NotImplementedException();
}
}
public void Listen(int backlog)
{
Socket.Listen(backlog);
}
public void Bind(IpEndPointInfo endpoint)
{
var nativeEndpoint = BaseNetworkManager.ToIPEndPoint(endpoint);
Socket.Bind(nativeEndpoint);
}
private SocketAcceptor _acceptor;
public void StartAccept(Action<ISocket> onAccept, Func<bool> isClosed)
{
_acceptor = new SocketAcceptor(_logger, Socket, onAccept, isClosed);
_acceptor.StartAccept();
}
public void Dispose()
{
Socket.Dispose();
}
}
}

View File

@ -0,0 +1,111 @@
using System;
using System.Net.Sockets;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net;
namespace Emby.Common.Implementations.Net
{
public class SocketAcceptor
{
private readonly ILogger _logger;
private readonly Socket _originalSocket;
private readonly Func<bool> _isClosed;
private readonly Action<ISocket> _onAccept;
public SocketAcceptor(ILogger logger, Socket originalSocket, Action<ISocket> onAccept, Func<bool> isClosed)
{
_logger = logger;
_originalSocket = originalSocket;
_isClosed = isClosed;
_onAccept = onAccept;
}
public void StartAccept()
{
Socket dummy = null;
StartAccept(null, ref dummy);
}
public void StartAccept(SocketAsyncEventArgs acceptEventArg, ref Socket accepted)
{
if (acceptEventArg == null)
{
acceptEventArg = new SocketAsyncEventArgs();
acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(AcceptEventArg_Completed);
}
else
{
// socket must be cleared since the context object is being reused
acceptEventArg.AcceptSocket = null;
}
try
{
bool willRaiseEvent = _originalSocket.AcceptAsync(acceptEventArg);
if (!willRaiseEvent)
{
ProcessAccept(acceptEventArg);
}
}
catch (Exception ex)
{
if (accepted != null)
{
try
{
#if NET46
accepted.Close();
#else
accepted.Dispose();
#endif
}
catch
{
}
accepted = null;
}
}
}
// This method is the callback method associated with Socket.AcceptAsync
// operations and is invoked when an accept operation is complete
//
void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e)
{
ProcessAccept(e);
}
private void ProcessAccept(SocketAsyncEventArgs e)
{
if (_isClosed())
{
return;
}
// http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.acceptasync%28v=vs.110%29.aspx
// Under certain conditions ConnectionReset can occur
// Need to attept to re-accept
if (e.SocketError == SocketError.ConnectionReset)
{
_logger.Error("SocketError.ConnectionReset reported. Attempting to re-accept.");
Socket dummy = null;
StartAccept(e, ref dummy);
return;
}
var acceptSocket = e.AcceptSocket;
if (acceptSocket != null)
{
//ProcessAccept(acceptSocket);
_onAccept(new NetSocket(acceptSocket, _logger));
}
if (_originalSocket != null)
{
// Accept the next connection request
StartAccept(e, ref acceptSocket);
}
}
}
}

View File

@ -4,6 +4,7 @@ using System.Linq;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net; using MediaBrowser.Model.Net;
namespace Emby.Common.Implementations.Net namespace Emby.Common.Implementations.Net
@ -22,16 +23,28 @@ namespace Emby.Common.Implementations.Net
/// </summary> /// </summary>
private IPAddress _LocalIP; private IPAddress _LocalIP;
/// <summary> private ILogger _logger;
/// Default constructor.
/// </summary> public SocketFactory(ILogger logger)
/// <param name="localIP">A string containing the IP address of the local network adapter to bind sockets to. Null or empty string will use <see cref="IPAddress.Any"/>.</param>
public SocketFactory(string localIP)
{ {
if (String.IsNullOrEmpty(localIP)) _logger = logger;
_LocalIP = IPAddress.Any; _LocalIP = IPAddress.Any;
else }
_LocalIP = IPAddress.Parse(localIP);
public ISocket CreateSocket(IpAddressFamily family, MediaBrowser.Model.Net.SocketType socketType, MediaBrowser.Model.Net.ProtocolType protocolType, bool dualMode)
{
var addressFamily = family == IpAddressFamily.InterNetwork
? AddressFamily.InterNetwork
: AddressFamily.InterNetworkV6;
var socket = new Socket(addressFamily, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
if (dualMode)
{
socket.DualMode = true;
}
return new NetSocket(socket, _logger);
} }
#region ISocketFactory Members #region ISocketFactory Members
@ -44,7 +57,7 @@ namespace Emby.Common.Implementations.Net
{ {
if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort"); if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort");
var retVal = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); var retVal = new Socket(AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp);
try try
{ {
retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
@ -68,7 +81,7 @@ namespace Emby.Common.Implementations.Net
{ {
if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort"); if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort");
var retVal = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); var retVal = new Socket(AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp);
try try
{ {
retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
@ -99,7 +112,7 @@ namespace Emby.Common.Implementations.Net
if (multicastTimeToLive <= 0) throw new ArgumentException("multicastTimeToLive cannot be zero or less.", "multicastTimeToLive"); if (multicastTimeToLive <= 0) throw new ArgumentException("multicastTimeToLive cannot be zero or less.", "multicastTimeToLive");
if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort"); if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort");
var retVal = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); var retVal = new Socket(AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp);
try try
{ {

View File

@ -5,6 +5,7 @@ using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Security; using System.Security;
using System.Threading.Tasks; using System.Threading.Tasks;
using Emby.Common.Implementations.Networking;
using MediaBrowser.Model.Net; using MediaBrowser.Model.Net;
namespace Emby.Common.Implementations.Net namespace Emby.Common.Implementations.Net
@ -174,16 +175,7 @@ namespace Emby.Common.Implementations.Net
return null; return null;
} }
return new IpEndPointInfo return BaseNetworkManager.ToIpEndPointInfo(endpoint);
{
IpAddress = new IpAddressInfo
{
Address = endpoint.Address.ToString(),
IsIpv6 = endpoint.AddressFamily == AddressFamily.InterNetworkV6
},
Port = endpoint.Port
};
} }
private void ProcessResponse(IAsyncResult asyncResult) private void ProcessResponse(IAsyncResult asyncResult)

View File

@ -22,14 +22,10 @@ namespace Emby.Common.Implementations.Networking
Logger = logger; Logger = logger;
} }
private List<IPAddress> _localIpAddresses; private List<IpAddressInfo> _localIpAddresses;
private readonly object _localIpAddressSyncLock = new object(); private readonly object _localIpAddressSyncLock = new object();
/// <summary> public IEnumerable<IpAddressInfo> GetLocalIpAddresses()
/// Gets the machine's local ip address
/// </summary>
/// <returns>IPAddress.</returns>
public IEnumerable<IPAddress> GetLocalIpAddresses()
{ {
const int cacheMinutes = 5; const int cacheMinutes = 5;
@ -39,7 +35,7 @@ namespace Emby.Common.Implementations.Networking
if (_localIpAddresses == null || forceRefresh) if (_localIpAddresses == null || forceRefresh)
{ {
var addresses = GetLocalIpAddressesInternal().ToList(); var addresses = GetLocalIpAddressesInternal().Select(ToIpAddressInfo).ToList();
_localIpAddresses = addresses; _localIpAddresses = addresses;
_lastRefresh = DateTime.UtcNow; _lastRefresh = DateTime.UtcNow;
@ -405,18 +401,85 @@ namespace Emby.Common.Implementations.Networking
IPAddress address; IPAddress address;
if (IPAddress.TryParse(ipAddress, out address)) if (IPAddress.TryParse(ipAddress, out address))
{ {
ipAddressInfo = ToIpAddressInfo(address);
ipAddressInfo = new IpAddressInfo
{
Address = address.ToString(),
IsIpv6 = address.AddressFamily == AddressFamily.InterNetworkV6
};
return true; return true;
} }
ipAddressInfo = null; ipAddressInfo = null;
return false; return false;
} }
public static IpEndPointInfo ToIpEndPointInfo(IPEndPoint endpoint)
{
if (endpoint == null)
{
return null;
}
return new IpEndPointInfo(ToIpAddressInfo(endpoint.Address), endpoint.Port);
}
public static IPEndPoint ToIPEndPoint(IpEndPointInfo endpoint)
{
if (endpoint == null)
{
return null;
}
return new IPEndPoint(ToIPAddress(endpoint.IpAddress), endpoint.Port);
}
public static IPAddress ToIPAddress(IpAddressInfo address)
{
if (address.Equals(IpAddressInfo.Any))
{
return IPAddress.Any;
}
if (address.Equals(IpAddressInfo.IPv6Any))
{
return IPAddress.IPv6Any;
}
if (address.Equals(IpAddressInfo.Loopback))
{
return IPAddress.Loopback;
}
if (address.Equals(IpAddressInfo.IPv6Loopback))
{
return IPAddress.IPv6Loopback;
}
return IPAddress.Parse(address.Address);
}
public static IpAddressInfo ToIpAddressInfo(IPAddress address)
{
if (address.Equals(IPAddress.Any))
{
return IpAddressInfo.Any;
}
if (address.Equals(IPAddress.IPv6Any))
{
return IpAddressInfo.IPv6Any;
}
if (address.Equals(IPAddress.Loopback))
{
return IpAddressInfo.Loopback;
}
if (address.Equals(IPAddress.IPv6Loopback))
{
return IpAddressInfo.IPv6Loopback;
}
return new IpAddressInfo
{
Address = address.ToString(),
AddressFamily = address.AddressFamily == AddressFamily.InterNetworkV6 ? IpAddressFamily.InterNetworkV6 : IpAddressFamily.InterNetwork
};
}
public async Task<IpAddressInfo[]> GetHostAddressesAsync(string host)
{
var addresses = await Dns.GetHostAddressesAsync(host).ConfigureAwait(false);
return addresses.Select(ToIpAddressInfo).ToArray();
}
} }
} }

View File

@ -1,10 +1,10 @@
using System.Text; using System.Text;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using MediaBrowser.Model.TextEncoding; using MediaBrowser.Model.Text;
namespace Emby.Common.Implementations.TextEncoding namespace Emby.Common.Implementations.TextEncoding
{ {
public class TextEncoding : IEncoding public class TextEncoding : ITextEncoding
{ {
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
@ -13,14 +13,9 @@ namespace Emby.Common.Implementations.TextEncoding
_fileSystem = fileSystem; _fileSystem = fileSystem;
} }
public byte[] GetASCIIBytes(string text) public Encoding GetASCIIEncoding()
{ {
return Encoding.ASCII.GetBytes(text); return Encoding.ASCII;
}
public string GetASCIIString(byte[] bytes, int startIndex, int length)
{
return Encoding.ASCII.GetString(bytes, 0, bytes.Length);
} }
public Encoding GetFileEncoding(string srcFile) public Encoding GetFileEncoding(string srcFile)

View File

@ -250,14 +250,12 @@ namespace Emby.Dlna.Main
// continue; // continue;
//} //}
var addressString = address.ToString();
var fullService = "urn:schemas-upnp-org:device:MediaServer:1"; var fullService = "urn:schemas-upnp-org:device:MediaServer:1";
_logger.Info("Registering publisher for {0} on {1}", fullService, addressString); _logger.Info("Registering publisher for {0} on {1}", fullService, address.ToString());
var descriptorUri = "/dlna/" + udn + "/description.xml"; var descriptorUri = "/dlna/" + udn + "/description.xml";
var uri = new Uri(_appHost.GetLocalApiUrl(addressString, address.IsIpv6) + descriptorUri); var uri = new Uri(_appHost.GetLocalApiUrl(address) + descriptorUri);
var device = new SsdpRootDevice var device = new SsdpRootDevice
{ {

View File

@ -16,6 +16,7 @@ using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Events; using MediaBrowser.Model.Events;
using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.Net;
using MediaBrowser.Model.Threading; using MediaBrowser.Model.Threading;
namespace Emby.Dlna.PlayTo namespace Emby.Dlna.PlayTo
@ -131,11 +132,11 @@ namespace Emby.Dlna.PlayTo
string serverAddress; string serverAddress;
if (info.LocalIpAddress == null) if (info.LocalIpAddress == null)
{ {
serverAddress = await GetServerAddress(null, false).ConfigureAwait(false); serverAddress = await GetServerAddress(null).ConfigureAwait(false);
} }
else else
{ {
serverAddress = await GetServerAddress(info.LocalIpAddress.Address, info.LocalIpAddress.IsIpv6).ConfigureAwait(false); serverAddress = await GetServerAddress(info.LocalIpAddress).ConfigureAwait(false);
} }
string accessToken = null; string accessToken = null;
@ -189,14 +190,14 @@ namespace Emby.Dlna.PlayTo
} }
} }
private Task<string> GetServerAddress(string ipAddress, bool isIpv6) private Task<string> GetServerAddress(IpAddressInfo address)
{ {
if (string.IsNullOrWhiteSpace(ipAddress)) if (address == null)
{ {
return _appHost.GetLocalApiUrl(); return _appHost.GetLocalApiUrl();
} }
return Task.FromResult(_appHost.GetLocalApiUrl(ipAddress, isIpv6)); return Task.FromResult(_appHost.GetLocalApiUrl(address));
} }
public void Dispose() public void Dispose()

View File

@ -64,7 +64,7 @@ namespace Emby.Server.Implementations.Connect
validIpAddress = await GetIpAddress(ipLookupUrl).ConfigureAwait(false); validIpAddress = await GetIpAddress(ipLookupUrl).ConfigureAwait(false);
// Try to find the ipv4 address, if present // Try to find the ipv4 address, if present
if (!validIpAddress.IsIpv6) if (validIpAddress.AddressFamily != IpAddressFamily.InterNetworkV6)
{ {
break; break;
} }
@ -77,9 +77,9 @@ namespace Emby.Server.Implementations.Connect
_logger.ErrorException("Error getting connection info", ex); _logger.ErrorException("Error getting connection info", ex);
} }
} }
// If this produced an ipv6 address, try again // If this produced an ipv6 address, try again
if (validIpAddress != null && validIpAddress.IsIpv6) if (validIpAddress != null && validIpAddress.AddressFamily == IpAddressFamily.InterNetworkV6)
{ {
foreach (var ipLookupUrl in _ipLookups) foreach (var ipLookupUrl in _ipLookups)
{ {
@ -88,7 +88,7 @@ namespace Emby.Server.Implementations.Connect
var newAddress = await GetIpAddress(ipLookupUrl, true).ConfigureAwait(false); var newAddress = await GetIpAddress(ipLookupUrl, true).ConfigureAwait(false);
// Try to find the ipv4 address, if present // Try to find the ipv4 address, if present
if (!newAddress.IsIpv6) if (newAddress.AddressFamily != IpAddressFamily.InterNetworkV6)
{ {
validIpAddress = newAddress; validIpAddress = newAddress;
break; break;

View File

@ -74,7 +74,7 @@ namespace Emby.Server.Implementations.Connect
if (string.IsNullOrWhiteSpace(address) && DiscoveredWanIpAddress != null) if (string.IsNullOrWhiteSpace(address) && DiscoveredWanIpAddress != null)
{ {
if (DiscoveredWanIpAddress.IsIpv6) if (DiscoveredWanIpAddress.AddressFamily == IpAddressFamily.InterNetworkV6)
{ {
address = "[" + DiscoveredWanIpAddress + "]"; address = "[" + DiscoveredWanIpAddress + "]";
} }

View File

@ -68,11 +68,18 @@
<Compile Include="FileOrganization\OrganizerScheduledTask.cs" /> <Compile Include="FileOrganization\OrganizerScheduledTask.cs" />
<Compile Include="FileOrganization\TvFolderOrganizer.cs" /> <Compile Include="FileOrganization\TvFolderOrganizer.cs" />
<Compile Include="HttpServer\GetSwaggerResource.cs" /> <Compile Include="HttpServer\GetSwaggerResource.cs" />
<Compile Include="HttpServer\LoggerUtils.cs" />
<Compile Include="HttpServer\RangeRequestWriter.cs" />
<Compile Include="HttpServer\ResponseFilter.cs" />
<Compile Include="HttpServer\SocketSharp\Extensions.cs" />
<Compile Include="HttpServer\SocketSharp\HttpUtility.cs" /> <Compile Include="HttpServer\SocketSharp\HttpUtility.cs" />
<Compile Include="HttpServer\IHttpListener.cs" /> <Compile Include="HttpServer\IHttpListener.cs" />
<Compile Include="HttpServer\Security\AuthorizationContext.cs" /> <Compile Include="HttpServer\Security\AuthorizationContext.cs" />
<Compile Include="HttpServer\Security\AuthService.cs" /> <Compile Include="HttpServer\Security\AuthService.cs" />
<Compile Include="HttpServer\Security\SessionContext.cs" /> <Compile Include="HttpServer\Security\SessionContext.cs" />
<Compile Include="HttpServer\SocketSharp\SharpWebSocket.cs" />
<Compile Include="HttpServer\SocketSharp\WebSocketSharpListener.cs" />
<Compile Include="HttpServer\SocketSharp\WebSocketSharpResponse.cs" />
<Compile Include="HttpServer\StreamWriter.cs" /> <Compile Include="HttpServer\StreamWriter.cs" />
<Compile Include="HttpServer\SwaggerService.cs" /> <Compile Include="HttpServer\SwaggerService.cs" />
<Compile Include="Images\BaseDynamicImageProvider.cs" /> <Compile Include="Images\BaseDynamicImageProvider.cs" />
@ -254,6 +261,9 @@
<Project>{442b5058-dcaf-4263-bb6a-f21e31120a1b}</Project> <Project>{442b5058-dcaf-4263-bb6a-f21e31120a1b}</Project>
<Name>MediaBrowser.Providers</Name> <Name>MediaBrowser.Providers</Name>
</ProjectReference> </ProjectReference>
<Reference Include="SocketHttpListener.Portable">
<HintPath>..\ThirdParty\emby\SocketHttpListener.Portable.dll</HintPath>
</Reference>
<Reference Include="UniversalDetector, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="UniversalDetector, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\UniversalDetector.1.0.1\lib\portable-net45+sl4+wp71+win8+wpa81\UniversalDetector.dll</HintPath> <HintPath>..\packages\UniversalDetector.1.0.1\lib\portable-net45+sl4+wp71+win8+wpa81\UniversalDetector.dll</HintPath>
<Private>True</Private> <Private>True</Private>

View File

@ -3,7 +3,7 @@ using System;
using System.Globalization; using System.Globalization;
using SocketHttpListener.Net; using SocketHttpListener.Net;
namespace MediaBrowser.Server.Implementations.HttpServer namespace Emby.Server.Implementations.HttpServer
{ {
public static class LoggerUtils public static class LoggerUtils
{ {

View File

@ -1,5 +1,4 @@
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
using ServiceStack.Web;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
@ -9,7 +8,7 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Model.Services; using MediaBrowser.Model.Services;
namespace MediaBrowser.Server.Implementations.HttpServer namespace Emby.Server.Implementations.HttpServer
{ {
public class RangeRequestWriter : IAsyncStreamWriter, IHttpResult public class RangeRequestWriter : IAsyncStreamWriter, IHttpResult
{ {
@ -41,7 +40,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// </summary> /// </summary>
private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
public Func<IDisposable> ResultScope { get; set; }
public List<Cookie> Cookies { get; private set; } public List<Cookie> Cookies { get; private set; }
/// <summary> /// <summary>
@ -213,8 +211,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer
public object Response { get; set; } public object Response { get; set; }
public IContentTypeWriter ResponseFilter { get; set; }
public int Status { get; set; } public int Status { get; set; }
public HttpStatusCode StatusCode public HttpStatusCode StatusCode
@ -224,7 +220,5 @@ namespace MediaBrowser.Server.Implementations.HttpServer
} }
public string StatusDescription { get; set; } public string StatusDescription { get; set; }
public int PaddingLength { get; set; }
} }
} }

View File

@ -1,12 +1,11 @@
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
using MediaBrowser.Server.Implementations.HttpServer.SocketSharp;
using System; using System;
using System.Globalization; using System.Globalization;
using System.Net;
using System.Text; using System.Text;
using Emby.Server.Implementations.HttpServer.SocketSharp;
using MediaBrowser.Model.Services; using MediaBrowser.Model.Services;
namespace MediaBrowser.Server.Implementations.HttpServer namespace Emby.Server.Implementations.HttpServer
{ {
public class ResponseFilter public class ResponseFilter
{ {
@ -28,6 +27,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer
{ {
// Try to prevent compatibility view // Try to prevent compatibility view
res.AddHeader("X-UA-Compatible", "IE=Edge"); res.AddHeader("X-UA-Compatible", "IE=Edge");
res.AddHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Range, X-MediaBrowser-Token, X-Emby-Authorization");
res.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, PATCH, OPTIONS");
res.AddHeader("Access-Control-Allow-Origin", "*");
var exception = dto as Exception; var exception = dto as Exception;
@ -68,15 +70,15 @@ namespace MediaBrowser.Server.Implementations.HttpServer
{ {
res.SetContentLength(length); res.SetContentLength(length);
var listenerResponse = res.OriginalResponse as HttpListenerResponse; //var listenerResponse = res.OriginalResponse as HttpListenerResponse;
if (listenerResponse != null) //if (listenerResponse != null)
{ //{
// Disable chunked encoding. Technically this is only needed when using Content-Range, but // // Disable chunked encoding. Technically this is only needed when using Content-Range, but
// anytime we know the content length there's no need for it // // anytime we know the content length there's no need for it
listenerResponse.SendChunked = false; // listenerResponse.SendChunked = false;
return; // return;
} //}
if (sharpResponse != null) if (sharpResponse != null)
{ {

View File

@ -0,0 +1,12 @@
using SocketHttpListener.Net;
namespace Emby.Server.Implementations.HttpServer.SocketSharp
{
public static class Extensions
{
public static string GetOperationName(this HttpListenerRequest request)
{
return request.Url.Segments[request.Url.Segments.Length - 1];
}
}
}

View File

@ -6,7 +6,7 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using WebSocketState = MediaBrowser.Model.Net.WebSocketState; using WebSocketState = MediaBrowser.Model.Net.WebSocketState;
namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp namespace Emby.Server.Implementations.HttpServer.SocketSharp
{ {
public class SharpWebSocket : IWebSocket public class SharpWebSocket : IWebSocket
{ {
@ -25,12 +25,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource(); private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
/// <summary>
/// Initializes a new instance of the <see cref="NativeWebSocket" /> class.
/// </summary>
/// <param name="socket">The socket.</param>
/// <param name="logger">The logger.</param>
/// <exception cref="System.ArgumentNullException">socket</exception>
public SharpWebSocket(SocketHttpListener.WebSocket socket, ILogger logger) public SharpWebSocket(SocketHttpListener.WebSocket socket, ILogger logger)
{ {
if (socket == null) if (socket == null)

View File

@ -1,37 +1,51 @@
using System.Collections.Specialized; using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
using SocketHttpListener.Net; using SocketHttpListener.Net;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Emby.Server.Implementations.HttpServer;
using Emby.Server.Implementations.Logging; using Emby.Server.Implementations.Logging;
using MediaBrowser.Common.IO; using MediaBrowser.Common.Net;
using MediaBrowser.Model.Cryptography;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using MediaBrowser.Model.Net;
using MediaBrowser.Model.Services; using MediaBrowser.Model.Services;
using ServiceStack; using MediaBrowser.Model.Text;
using SocketHttpListener.Primitives;
namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp namespace Emby.Server.Implementations.HttpServer.SocketSharp
{ {
public class WebSocketSharpListener : IHttpListener public class WebSocketSharpListener : IHttpListener
{ {
private HttpListener _listener; private HttpListener _listener;
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly string _certificatePath; private readonly ICertificate _certificate;
private readonly IMemoryStreamProvider _memoryStreamProvider; private readonly IMemoryStreamFactory _memoryStreamProvider;
private readonly ITextEncoding _textEncoding;
private readonly INetworkManager _networkManager;
private readonly ISocketFactory _socketFactory;
private readonly ICryptoProvider _cryptoProvider;
private readonly IStreamFactory _streamFactory;
private readonly Func<HttpListenerContext, IHttpRequest> _httpRequestFactory;
private readonly bool _enableDualMode;
public WebSocketSharpListener(ILogger logger, string certificatePath, IMemoryStreamProvider memoryStreamProvider) public WebSocketSharpListener(ILogger logger, ICertificate certificate, IMemoryStreamFactory memoryStreamProvider, ITextEncoding textEncoding, INetworkManager networkManager, ISocketFactory socketFactory, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, bool enableDualMode, Func<HttpListenerContext, IHttpRequest> httpRequestFactory)
{ {
_logger = logger; _logger = logger;
_certificatePath = certificatePath; _certificate = certificate;
_memoryStreamProvider = memoryStreamProvider; _memoryStreamProvider = memoryStreamProvider;
_textEncoding = textEncoding;
_networkManager = networkManager;
_socketFactory = socketFactory;
_cryptoProvider = cryptoProvider;
_streamFactory = streamFactory;
_enableDualMode = enableDualMode;
_httpRequestFactory = httpRequestFactory;
} }
public Action<Exception, IRequest> ErrorHandler { get; set; } public Action<Exception, IRequest> ErrorHandler { get; set; }
public Func<IHttpRequest, Uri, Task> RequestHandler { get; set; } public Func<IHttpRequest, Uri, Task> RequestHandler { get; set; }
public Action<WebSocketConnectingEventArgs> WebSocketConnecting { get; set; } public Action<WebSocketConnectingEventArgs> WebSocketConnecting { get; set; }
@ -41,7 +55,14 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
public void Start(IEnumerable<string> urlPrefixes) public void Start(IEnumerable<string> urlPrefixes)
{ {
if (_listener == null) if (_listener == null)
_listener = new HttpListener(new PatternsLogger(_logger), _certificatePath); _listener = new HttpListener(new PatternsLogger(_logger), _cryptoProvider, _streamFactory, _socketFactory, _networkManager, _textEncoding, _memoryStreamProvider);
_listener.EnableDualMode = _enableDualMode;
if (_certificate != null)
{
_listener.LoadCert(_certificate);
}
foreach (var prefix in urlPrefixes) foreach (var prefix in urlPrefixes)
{ {
@ -59,41 +80,32 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
Task.Factory.StartNew(() => InitTask(context)); Task.Factory.StartNew(() => InitTask(context));
} }
private void InitTask(HttpListenerContext context) private Task InitTask(HttpListenerContext context)
{ {
IHttpRequest httpReq = null;
var request = context.Request;
try try
{ {
var task = this.ProcessRequestAsync(context); if (request.IsWebSocketRequest)
task.ContinueWith(x => HandleError(x.Exception, context), TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.AttachedToParent); {
LoggerUtils.LogRequest(_logger, request);
//if (task.Status == TaskStatus.Created) ProcessWebSocketRequest(context);
//{ return Task.FromResult(true);
// task.RunSynchronously(); }
//}
httpReq = GetRequest(context);
} }
catch (Exception ex) catch (Exception ex)
{ {
HandleError(ex, context); _logger.ErrorException("Error processing request", ex);
}
}
private Task ProcessRequestAsync(HttpListenerContext context) httpReq = httpReq ?? GetRequest(context);
{ ErrorHandler(ex, httpReq);
var request = context.Request;
if (request.IsWebSocketRequest)
{
LoggerUtils.LogRequest(_logger, request);
ProcessWebSocketRequest(context);
return Task.FromResult(true); return Task.FromResult(true);
} }
if (string.IsNullOrEmpty(context.Request.RawUrl))
return ((object)null).AsTaskResult();
var httpReq = GetRequest(context);
return RequestHandler(httpReq, request.Url); return RequestHandler(httpReq, request.Url);
} }
@ -103,19 +115,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
{ {
var endpoint = ctx.Request.RemoteEndPoint.ToString(); var endpoint = ctx.Request.RemoteEndPoint.ToString();
var url = ctx.Request.RawUrl; var url = ctx.Request.RawUrl;
var queryString = ctx.Request.QueryString ?? new NameValueCollection();
var queryParamCollection = new QueryParamCollection();
foreach (var key in queryString.AllKeys)
{
queryParamCollection[key] = queryString[key];
}
var connectingArgs = new WebSocketConnectingEventArgs var connectingArgs = new WebSocketConnectingEventArgs
{ {
Url = url, Url = url,
QueryString = queryParamCollection, QueryString = ctx.Request.QueryString,
Endpoint = endpoint Endpoint = endpoint
}; };
@ -135,7 +139,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
WebSocketConnected(new WebSocketConnectEventArgs WebSocketConnected(new WebSocketConnectEventArgs
{ {
Url = url, Url = url,
QueryString = queryParamCollection, QueryString = ctx.Request.QueryString,
WebSocket = new SharpWebSocket(webSocketContext.WebSocket, _logger), WebSocket = new SharpWebSocket(webSocketContext.WebSocket, _logger),
Endpoint = endpoint Endpoint = endpoint
}); });
@ -158,22 +162,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
private IHttpRequest GetRequest(HttpListenerContext httpContext) private IHttpRequest GetRequest(HttpListenerContext httpContext)
{ {
var operationName = httpContext.Request.GetOperationName(); return _httpRequestFactory(httpContext);
var req = new WebSocketSharpRequest(httpContext, operationName, RequestAttributes.None, _logger, _memoryStreamProvider);
req.RequestAttributes = req.GetAttributes();
return req;
}
private void HandleError(Exception ex, HttpListenerContext context)
{
var httpReq = GetRequest(context);
if (ErrorHandler != null)
{
ErrorHandler(ex, httpReq);
}
} }
public void Stop() public void Stop()
@ -214,4 +203,5 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
} }
} }
} }
} }

View File

@ -2,14 +2,13 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Text;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
using ServiceStack;
using ServiceStack.Host;
using HttpListenerResponse = SocketHttpListener.Net.HttpListenerResponse; using HttpListenerResponse = SocketHttpListener.Net.HttpListenerResponse;
using IHttpResponse = MediaBrowser.Model.Services.IHttpResponse; using IHttpResponse = MediaBrowser.Model.Services.IHttpResponse;
using IRequest = MediaBrowser.Model.Services.IRequest; using IRequest = MediaBrowser.Model.Services.IRequest;
namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp namespace Emby.Server.Implementations.HttpServer.SocketSharp
{ {
public class WebSocketSharpResponse : IHttpResponse public class WebSocketSharpResponse : IHttpResponse
{ {
@ -98,7 +97,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
try try
{ {
this._response.CloseOutputStream(_logger); CloseOutputStream(this._response);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -107,6 +106,20 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
} }
} }
public void CloseOutputStream(HttpListenerResponse response)
{
try
{
response.OutputStream.Flush();
response.OutputStream.Dispose();
response.Close();
}
catch (Exception ex)
{
_logger.ErrorException("Error in HttpListenerResponseWrapper: " + ex.Message, ex);
}
}
public void End() public void End()
{ {
Close(); Close();
@ -133,10 +146,49 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
public void SetCookie(Cookie cookie) public void SetCookie(Cookie cookie)
{ {
var cookieStr = cookie.AsHeaderValue(); var cookieStr = AsHeaderValue(cookie);
_response.Headers.Add(HttpHeaders.SetCookie, cookieStr); _response.Headers.Add("Set-Cookie", cookieStr);
} }
public static string AsHeaderValue(Cookie cookie)
{
var defaultExpires = DateTime.MinValue;
var path = cookie.Expires == defaultExpires
? "/"
: cookie.Path ?? "/";
var sb = new StringBuilder();
sb.Append($"{cookie.Name}={cookie.Value};path={path}");
if (cookie.Expires != defaultExpires)
{
sb.Append($";expires={cookie.Expires:R}");
}
if (!string.IsNullOrEmpty(cookie.Domain))
{
sb.Append($";domain={cookie.Domain}");
}
//else if (restrictAllCookiesToDomain != null)
//{
// sb.Append($";domain={restrictAllCookiesToDomain}");
//}
if (cookie.Secure)
{
sb.Append(";Secure");
}
if (cookie.HttpOnly)
{
sb.Append(";HttpOnly");
}
return sb.ToString();
}
public bool SendChunked public bool SendChunked
{ {
get { return _response.SendChunked; } get { return _response.SendChunked; }

View File

@ -2496,10 +2496,12 @@ namespace Emby.Server.Implementations.Library
}).OrderBy(i => i.Path).ToList(); }).OrderBy(i => i.Path).ToList();
} }
private static readonly string[] ExtrasSubfolderNames = new[] { "extras", "specials", "shorts", "scenes", "featurettes", "behind the scenes", "deleted scenes" };
public IEnumerable<Video> FindExtras(BaseItem owner, List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService) public IEnumerable<Video> FindExtras(BaseItem owner, List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService)
{ {
var files = fileSystemChildren.Where(i => i.IsDirectory) var files = fileSystemChildren.Where(i => i.IsDirectory)
.Where(i => string.Equals(i.Name, "extras", StringComparison.OrdinalIgnoreCase) || string.Equals(i.Name, "specials", StringComparison.OrdinalIgnoreCase)) .Where(i => ExtrasSubfolderNames.Contains(i.Name ?? string.Empty, StringComparer.OrdinalIgnoreCase))
.SelectMany(i => _fileSystem.GetFiles(i.FullName, false)) .SelectMany(i => _fileSystem.GetFiles(i.FullName, false))
.ToList(); .ToList();
@ -2788,7 +2790,7 @@ namespace Emby.Server.Implementations.Library
{ {
var path = Path.Combine(virtualFolderPath, collectionType + ".collection"); var path = Path.Combine(virtualFolderPath, collectionType + ".collection");
_fileSystem.WriteAllBytes(path, new byte[] {}); _fileSystem.WriteAllBytes(path, new byte[] { });
} }
CollectionFolder.SaveLibraryOptions(virtualFolderPath, options); CollectionFolder.SaveLibraryOptions(virtualFolderPath, options);

View File

@ -70,10 +70,10 @@ namespace Emby.Server.Implementations.Library
private readonly Func<IConnectManager> _connectFactory; private readonly Func<IConnectManager> _connectFactory;
private readonly IServerApplicationHost _appHost; private readonly IServerApplicationHost _appHost;
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly ICryptographyProvider _cryptographyProvider; private readonly ICryptoProvider _cryptographyProvider;
private readonly string _defaultUserName; private readonly string _defaultUserName;
public UserManager(ILogger logger, IServerConfigurationManager configurationManager, IUserRepository userRepository, IXmlSerializer xmlSerializer, INetworkManager networkManager, Func<IImageProcessor> imageProcessorFactory, Func<IDtoService> dtoServiceFactory, Func<IConnectManager> connectFactory, IServerApplicationHost appHost, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ICryptographyProvider cryptographyProvider, string defaultUserName) public UserManager(ILogger logger, IServerConfigurationManager configurationManager, IUserRepository userRepository, IXmlSerializer xmlSerializer, INetworkManager networkManager, Func<IImageProcessor> imageProcessorFactory, Func<IDtoService> dtoServiceFactory, Func<IConnectManager> connectFactory, IServerApplicationHost appHost, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ICryptoProvider cryptographyProvider, string defaultUserName)
{ {
_logger = logger; _logger = logger;
UserRepository = userRepository; UserRepository = userRepository;
@ -334,7 +334,7 @@ namespace Emby.Server.Implementations.Library
/// <returns>System.String.</returns> /// <returns>System.String.</returns>
private string GetSha1String(string str) private string GetSha1String(string str)
{ {
return BitConverter.ToString(_cryptographyProvider.GetSHA1Bytes(Encoding.UTF8.GetBytes(str))).Replace("-", string.Empty); return BitConverter.ToString(_cryptographyProvider.ComputeSHA1(Encoding.UTF8.GetBytes(str))).Replace("-", string.Empty);
} }
/// <summary> /// <summary>

View File

@ -15,7 +15,7 @@ namespace Emby.Server.Implementations.Security
{ {
private readonly IApplicationPaths _appPaths; private readonly IApplicationPaths _appPaths;
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly ICryptographyProvider _cryptographyProvider; private readonly ICryptoProvider _cryptographyProvider;
public string RegKey public string RegKey
{ {
@ -43,7 +43,7 @@ namespace Emby.Server.Implementations.Security
private readonly object _fileLock = new object(); private readonly object _fileLock = new object();
private string _regKey; private string _regKey;
public MBLicenseFile(IApplicationPaths appPaths, IFileSystem fileSystem, ICryptographyProvider cryptographyProvider) public MBLicenseFile(IApplicationPaths appPaths, IFileSystem fileSystem, ICryptoProvider cryptographyProvider)
{ {
_appPaths = appPaths; _appPaths = appPaths;
_fileSystem = fileSystem; _fileSystem = fileSystem;
@ -59,7 +59,7 @@ namespace Emby.Server.Implementations.Security
public void AddRegCheck(string featureId) public void AddRegCheck(string featureId)
{ {
var key = new Guid(_cryptographyProvider.GetMD5Bytes(Encoding.Unicode.GetBytes(featureId))); var key = new Guid(_cryptographyProvider.ComputeMD5(Encoding.Unicode.GetBytes(featureId)));
var value = DateTime.UtcNow; var value = DateTime.UtcNow;
SetUpdateRecord(key, value); SetUpdateRecord(key, value);
@ -68,7 +68,7 @@ namespace Emby.Server.Implementations.Security
public void RemoveRegCheck(string featureId) public void RemoveRegCheck(string featureId)
{ {
var key = new Guid(_cryptographyProvider.GetMD5Bytes(Encoding.Unicode.GetBytes(featureId))); var key = new Guid(_cryptographyProvider.ComputeMD5(Encoding.Unicode.GetBytes(featureId)));
DateTime val; DateTime val;
_updateRecords.TryRemove(key, out val); _updateRecords.TryRemove(key, out val);
@ -79,7 +79,7 @@ namespace Emby.Server.Implementations.Security
public DateTime LastChecked(string featureId) public DateTime LastChecked(string featureId)
{ {
DateTime last; DateTime last;
_updateRecords.TryGetValue(new Guid(_cryptographyProvider.GetMD5Bytes(Encoding.Unicode.GetBytes(featureId))), out last); _updateRecords.TryGetValue(new Guid(_cryptographyProvider.ComputeMD5(Encoding.Unicode.GetBytes(featureId))), out last);
// guard agains people just putting a large number in the file // guard agains people just putting a large number in the file
return last < DateTime.UtcNow ? last : DateTime.MinValue; return last < DateTime.UtcNow ? last : DateTime.MinValue;

View File

@ -64,7 +64,7 @@ namespace Emby.Server.Implementations.Security
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IApplicationPaths _appPaths; private readonly IApplicationPaths _appPaths;
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly ICryptographyProvider _cryptographyProvider; private readonly ICryptoProvider _cryptographyProvider;
private IEnumerable<IRequiresRegistration> _registeredEntities; private IEnumerable<IRequiresRegistration> _registeredEntities;
protected IEnumerable<IRequiresRegistration> RegisteredEntities protected IEnumerable<IRequiresRegistration> RegisteredEntities
@ -79,7 +79,7 @@ namespace Emby.Server.Implementations.Security
/// Initializes a new instance of the <see cref="PluginSecurityManager" /> class. /// Initializes a new instance of the <see cref="PluginSecurityManager" /> class.
/// </summary> /// </summary>
public PluginSecurityManager(IServerApplicationHost appHost, IHttpClient httpClient, IJsonSerializer jsonSerializer, public PluginSecurityManager(IServerApplicationHost appHost, IHttpClient httpClient, IJsonSerializer jsonSerializer,
IApplicationPaths appPaths, ILogManager logManager, IFileSystem fileSystem, ICryptographyProvider cryptographyProvider) IApplicationPaths appPaths, ILogManager logManager, IFileSystem fileSystem, ICryptoProvider cryptographyProvider)
{ {
if (httpClient == null) if (httpClient == null)
{ {

View File

@ -15,7 +15,7 @@ using System.Threading.Tasks;
using MediaBrowser.Common.IO; using MediaBrowser.Common.IO;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using MediaBrowser.Model.Services; using MediaBrowser.Model.Services;
using MediaBrowser.Model.TextEncoding; using MediaBrowser.Model.Text;
namespace Emby.Server.Implementations.ServerManager namespace Emby.Server.Implementations.ServerManager
{ {
@ -75,8 +75,8 @@ namespace Emby.Server.Implementations.ServerManager
private readonly List<IWebSocketListener> _webSocketListeners = new List<IWebSocketListener>(); private readonly List<IWebSocketListener> _webSocketListeners = new List<IWebSocketListener>();
private bool _disposed; private bool _disposed;
private readonly IMemoryStreamProvider _memoryStreamProvider; private readonly IMemoryStreamFactory _memoryStreamProvider;
private readonly IEncoding _textEncoding; private readonly ITextEncoding _textEncoding;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ServerManager" /> class. /// Initializes a new instance of the <see cref="ServerManager" /> class.
@ -86,7 +86,7 @@ namespace Emby.Server.Implementations.ServerManager
/// <param name="logger">The logger.</param> /// <param name="logger">The logger.</param>
/// <param name="configurationManager">The configuration manager.</param> /// <param name="configurationManager">The configuration manager.</param>
/// <exception cref="System.ArgumentNullException">applicationHost</exception> /// <exception cref="System.ArgumentNullException">applicationHost</exception>
public ServerManager(IServerApplicationHost applicationHost, IJsonSerializer jsonSerializer, ILogger logger, IServerConfigurationManager configurationManager, IMemoryStreamProvider memoryStreamProvider, IEncoding textEncoding) public ServerManager(IServerApplicationHost applicationHost, IJsonSerializer jsonSerializer, ILogger logger, IServerConfigurationManager configurationManager, IMemoryStreamFactory memoryStreamProvider, ITextEncoding textEncoding)
{ {
if (applicationHost == null) if (applicationHost == null)
{ {

View File

@ -12,7 +12,7 @@ using System.Threading.Tasks;
using MediaBrowser.Common.IO; using MediaBrowser.Common.IO;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using MediaBrowser.Model.Services; using MediaBrowser.Model.Services;
using MediaBrowser.Model.TextEncoding; using MediaBrowser.Model.Text;
using UniversalDetector; using UniversalDetector;
namespace Emby.Server.Implementations.ServerManager namespace Emby.Server.Implementations.ServerManager
@ -77,8 +77,8 @@ namespace Emby.Server.Implementations.ServerManager
/// </summary> /// </summary>
/// <value>The query string.</value> /// <value>The query string.</value>
public QueryParamCollection QueryString { get; set; } public QueryParamCollection QueryString { get; set; }
private readonly IMemoryStreamProvider _memoryStreamProvider; private readonly IMemoryStreamFactory _memoryStreamProvider;
private readonly IEncoding _textEncoding; private readonly ITextEncoding _textEncoding;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="WebSocketConnection" /> class. /// Initializes a new instance of the <see cref="WebSocketConnection" /> class.
@ -88,7 +88,7 @@ namespace Emby.Server.Implementations.ServerManager
/// <param name="jsonSerializer">The json serializer.</param> /// <param name="jsonSerializer">The json serializer.</param>
/// <param name="logger">The logger.</param> /// <param name="logger">The logger.</param>
/// <exception cref="System.ArgumentNullException">socket</exception> /// <exception cref="System.ArgumentNullException">socket</exception>
public WebSocketConnection(IWebSocket socket, string remoteEndPoint, IJsonSerializer jsonSerializer, ILogger logger, IMemoryStreamProvider memoryStreamProvider, IEncoding textEncoding) public WebSocketConnection(IWebSocket socket, string remoteEndPoint, IJsonSerializer jsonSerializer, ILogger logger, IMemoryStreamFactory memoryStreamProvider, ITextEncoding textEncoding)
{ {
if (socket == null) if (socket == null)
{ {
@ -145,7 +145,7 @@ namespace Emby.Server.Implementations.ServerManager
} }
else else
{ {
OnReceiveInternal(_textEncoding.GetASCIIString(bytes, 0, bytes.Length)); OnReceiveInternal(_textEncoding.GetASCIIEncoding().GetString(bytes, 0, bytes.Length));
} }
} }
private string DetectCharset(byte[] bytes) private string DetectCharset(byte[] bytes)

View File

@ -29,12 +29,12 @@ namespace Emby.Server.Implementations.Sync
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly IConfigurationManager _config; private readonly IConfigurationManager _config;
private readonly ICryptographyProvider _cryptographyProvider; private readonly ICryptoProvider _cryptographyProvider;
public const string PathSeparatorString = "/"; public const string PathSeparatorString = "/";
public const char PathSeparatorChar = '/'; public const char PathSeparatorChar = '/';
public MediaSync(ILogger logger, ISyncManager syncManager, IServerApplicationHost appHost, IFileSystem fileSystem, IConfigurationManager config, ICryptographyProvider cryptographyProvider) public MediaSync(ILogger logger, ISyncManager syncManager, IServerApplicationHost appHost, IFileSystem fileSystem, IConfigurationManager config, ICryptoProvider cryptographyProvider)
{ {
_logger = logger; _logger = logger;
_syncManager = syncManager; _syncManager = syncManager;
@ -370,7 +370,7 @@ namespace Emby.Server.Implementations.Sync
private byte[] CreateMd5(byte[] value) private byte[] CreateMd5(byte[] value)
{ {
return _cryptographyProvider.GetMD5Bytes(value); return _cryptographyProvider.ComputeMD5(value);
} }
public LocalItem CreateLocalItem(IServerSyncProvider provider, SyncedItem syncedItem, SyncJob job, SyncTarget target, BaseItemDto libraryItem, string serverId, string serverName, string originalFileName) public LocalItem CreateLocalItem(IServerSyncProvider provider, SyncedItem syncedItem, SyncJob job, SyncTarget target, BaseItemDto libraryItem, string serverId, string serverName, string originalFileName)

View File

@ -23,9 +23,9 @@ namespace Emby.Server.Implementations.Sync
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly IConfigurationManager _config; private readonly IConfigurationManager _config;
private readonly ICryptographyProvider _cryptographyProvider; private readonly ICryptoProvider _cryptographyProvider;
public MultiProviderSync(SyncManager syncManager, IServerApplicationHost appHost, ILogger logger, IFileSystem fileSystem, IConfigurationManager config, ICryptographyProvider cryptographyProvider) public MultiProviderSync(SyncManager syncManager, IServerApplicationHost appHost, ILogger logger, IFileSystem fileSystem, IConfigurationManager config, ICryptoProvider cryptographyProvider)
{ {
_syncManager = syncManager; _syncManager = syncManager;
_appHost = appHost; _appHost = appHost;

View File

@ -20,9 +20,9 @@ namespace Emby.Server.Implementations.Sync
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly IServerApplicationHost _appHost; private readonly IServerApplicationHost _appHost;
private readonly IConfigurationManager _config; private readonly IConfigurationManager _config;
private readonly ICryptographyProvider _cryptographyProvider; private readonly ICryptoProvider _cryptographyProvider;
public ServerSyncScheduledTask(ISyncManager syncManager, ILogger logger, IFileSystem fileSystem, IServerApplicationHost appHost, IConfigurationManager config, ICryptographyProvider cryptographyProvider) public ServerSyncScheduledTask(ISyncManager syncManager, ILogger logger, IFileSystem fileSystem, IServerApplicationHost appHost, IConfigurationManager config, ICryptoProvider cryptographyProvider)
{ {
_syncManager = syncManager; _syncManager = syncManager;
_logger = logger; _logger = logger;

View File

@ -51,7 +51,7 @@ namespace Emby.Server.Implementations.Sync
private readonly Func<IMediaSourceManager> _mediaSourceManager; private readonly Func<IMediaSourceManager> _mediaSourceManager;
private readonly IJsonSerializer _json; private readonly IJsonSerializer _json;
private readonly ITaskManager _taskManager; private readonly ITaskManager _taskManager;
private readonly IMemoryStreamProvider _memoryStreamProvider; private readonly IMemoryStreamFactory _memoryStreamProvider;
private ISyncProvider[] _providers = { }; private ISyncProvider[] _providers = { };
@ -61,7 +61,7 @@ namespace Emby.Server.Implementations.Sync
public event EventHandler<GenericEventArgs<SyncJobItem>> SyncJobItemUpdated; public event EventHandler<GenericEventArgs<SyncJobItem>> SyncJobItemUpdated;
public event EventHandler<GenericEventArgs<SyncJobItem>> SyncJobItemCreated; public event EventHandler<GenericEventArgs<SyncJobItem>> SyncJobItemCreated;
public SyncManager(ILibraryManager libraryManager, ISyncRepository repo, IImageProcessor imageProcessor, ILogger logger, IUserManager userManager, Func<IDtoService> dtoService, IServerApplicationHost appHost, ITVSeriesManager tvSeriesManager, Func<IMediaEncoder> mediaEncoder, IFileSystem fileSystem, Func<ISubtitleEncoder> subtitleEncoder, IConfigurationManager config, IUserDataManager userDataManager, Func<IMediaSourceManager> mediaSourceManager, IJsonSerializer json, ITaskManager taskManager, IMemoryStreamProvider memoryStreamProvider) public SyncManager(ILibraryManager libraryManager, ISyncRepository repo, IImageProcessor imageProcessor, ILogger logger, IUserManager userManager, Func<IDtoService> dtoService, IServerApplicationHost appHost, ITVSeriesManager tvSeriesManager, Func<IMediaEncoder> mediaEncoder, IFileSystem fileSystem, Func<ISubtitleEncoder> subtitleEncoder, IConfigurationManager config, IUserDataManager userDataManager, Func<IMediaSourceManager> mediaSourceManager, IJsonSerializer json, ITaskManager taskManager, IMemoryStreamFactory memoryStreamProvider)
{ {
_libraryManager = libraryManager; _libraryManager = libraryManager;
_repo = repo; _repo = repo;

View File

@ -26,9 +26,9 @@ namespace Emby.Server.Implementations.Sync
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly IApplicationPaths _appPaths; private readonly IApplicationPaths _appPaths;
private readonly IServerApplicationHost _appHost; private readonly IServerApplicationHost _appHost;
private readonly IMemoryStreamProvider _memoryStreamProvider; private readonly IMemoryStreamFactory _memoryStreamProvider;
public TargetDataProvider(IServerSyncProvider provider, SyncTarget target, IServerApplicationHost appHost, ILogger logger, IJsonSerializer json, IFileSystem fileSystem, IApplicationPaths appPaths, IMemoryStreamProvider memoryStreamProvider) public TargetDataProvider(IServerSyncProvider provider, SyncTarget target, IServerApplicationHost appHost, ILogger logger, IJsonSerializer json, IFileSystem fileSystem, IApplicationPaths appPaths, IMemoryStreamFactory memoryStreamProvider)
{ {
_logger = logger; _logger = logger;
_json = json; _json = json;

View File

@ -119,9 +119,9 @@ namespace Emby.Server.Implementations.Updates
/// <value>The application host.</value> /// <value>The application host.</value>
private readonly IApplicationHost _applicationHost; private readonly IApplicationHost _applicationHost;
private readonly ICryptographyProvider _cryptographyProvider; private readonly ICryptoProvider _cryptographyProvider;
public InstallationManager(ILogger logger, IApplicationHost appHost, IApplicationPaths appPaths, IHttpClient httpClient, IJsonSerializer jsonSerializer, ISecurityManager securityManager, IConfigurationManager config, IFileSystem fileSystem, ICryptographyProvider cryptographyProvider) public InstallationManager(ILogger logger, IApplicationHost appHost, IApplicationPaths appPaths, IHttpClient httpClient, IJsonSerializer jsonSerializer, ISecurityManager securityManager, IConfigurationManager config, IFileSystem fileSystem, ICryptoProvider cryptographyProvider)
{ {
if (logger == null) if (logger == null)
{ {
@ -606,7 +606,7 @@ namespace Emby.Server.Implementations.Updates
{ {
using (var stream = _fileSystem.OpenRead(tempFile)) using (var stream = _fileSystem.OpenRead(tempFile))
{ {
var check = Guid.Parse(BitConverter.ToString(_cryptographyProvider.GetMD5Bytes(stream)).Replace("-", String.Empty)); var check = Guid.Parse(BitConverter.ToString(_cryptographyProvider.ComputeMD5(stream)).Replace("-", String.Empty));
if (check != packageChecksum) if (check != packageChecksum)
{ {
throw new Exception(string.Format("Download validation failed for {0}. Probably corrupted during transfer.", package.name)); throw new Exception(string.Format("Download validation failed for {0}. Probably corrupted during transfer.", package.name));

View File

@ -111,9 +111,9 @@ namespace MediaBrowser.Api.Dlna
private readonly IMediaReceiverRegistrar _mediaReceiverRegistrar; private readonly IMediaReceiverRegistrar _mediaReceiverRegistrar;
private const string XMLContentType = "text/xml; charset=UTF-8"; private const string XMLContentType = "text/xml; charset=UTF-8";
private readonly IMemoryStreamProvider _memoryStreamProvider; private readonly IMemoryStreamFactory _memoryStreamProvider;
public DlnaServerService(IDlnaManager dlnaManager, IContentDirectory contentDirectory, IConnectionManager connectionManager, IMediaReceiverRegistrar mediaReceiverRegistrar, IMemoryStreamProvider memoryStreamProvider) public DlnaServerService(IDlnaManager dlnaManager, IContentDirectory contentDirectory, IConnectionManager connectionManager, IMediaReceiverRegistrar mediaReceiverRegistrar, IMemoryStreamFactory memoryStreamProvider)
{ {
_dlnaManager = dlnaManager; _dlnaManager = dlnaManager;
_contentDirectory = contentDirectory; _contentDirectory = contentDirectory;

View File

@ -1263,6 +1263,7 @@ namespace MediaBrowser.Api.Playback
private bool EnableThrottling(StreamState state) private bool EnableThrottling(StreamState state)
{ {
return false;
// do not use throttling with hardware encoders // do not use throttling with hardware encoders
return state.InputProtocol == MediaProtocol.File && return state.InputProtocol == MediaProtocol.File &&
state.RunTimeTicks.HasValue && state.RunTimeTicks.HasValue &&

View File

@ -10,7 +10,7 @@ namespace MediaBrowser.Common.Extensions
/// </summary> /// </summary>
public static class BaseExtensions public static class BaseExtensions
{ {
public static ICryptographyProvider CryptographyProvider { get; set; } public static ICryptoProvider CryptographyProvider { get; set; }
/// <summary> /// <summary>
/// Strips the HTML. /// Strips the HTML.

View File

@ -2,6 +2,7 @@ using MediaBrowser.Model.IO;
using MediaBrowser.Model.Net; using MediaBrowser.Model.Net;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net; using System.Net;
using System.Threading.Tasks;
namespace MediaBrowser.Common.Net namespace MediaBrowser.Common.Net
{ {
@ -46,10 +47,14 @@ namespace MediaBrowser.Common.Net
/// <returns><c>true</c> if [is in local network] [the specified endpoint]; otherwise, <c>false</c>.</returns> /// <returns><c>true</c> if [is in local network] [the specified endpoint]; otherwise, <c>false</c>.</returns>
bool IsInLocalNetwork(string endpoint); bool IsInLocalNetwork(string endpoint);
IEnumerable<IpAddressInfo> GetLocalIpAddresses();
IpAddressInfo ParseIpAddress(string ipAddress); IpAddressInfo ParseIpAddress(string ipAddress);
bool TryParseIpAddress(string ipAddress, out IpAddressInfo ipAddressInfo); bool TryParseIpAddress(string ipAddress, out IpAddressInfo ipAddressInfo);
Task<IpAddressInfo[]> GetHostAddressesAsync(string host);
/// <summary> /// <summary>
/// Generates a self signed certificate at the locatation specified by <paramref name="certificatePath"/>. /// Generates a self signed certificate at the locatation specified by <paramref name="certificatePath"/>.
/// </summary> /// </summary>

View File

@ -85,7 +85,7 @@ namespace MediaBrowser.Controller
/// <summary> /// <summary>
/// Gets the local API URL. /// Gets the local API URL.
/// </summary> /// </summary>
string GetLocalApiUrl(string ipAddress, bool isIpv6); string GetLocalApiUrl(IpAddressInfo address);
void LaunchUrl(string url); void LaunchUrl(string url);

View File

@ -69,7 +69,8 @@ namespace MediaBrowser.Controller.MediaEncoding
// if the audio language is not understood by the user, load their preferred subs, if there are any // if the audio language is not understood by the user, load their preferred subs, if there are any
if (!ContainsOrdinal(preferredLanguages, audioTrackLanguage)) if (!ContainsOrdinal(preferredLanguages, audioTrackLanguage))
{ {
stream = streams.Where(s => !s.IsForced).FirstOrDefault(s => ContainsOrdinal(preferredLanguages, s.Language)); stream = streams.Where(s => !s.IsForced).FirstOrDefault(s => ContainsOrdinal(preferredLanguages, s.Language)) ??
streams.FirstOrDefault(s => ContainsOrdinal(preferredLanguages, s.Language));
} }
} }
else if (mode == SubtitlePlaybackMode.Always) else if (mode == SubtitlePlaybackMode.Always)

View File

@ -7,7 +7,7 @@ namespace MediaBrowser.Controller.Net
{ {
public class AuthenticatedAttribute : Attribute, IHasRequestFilter, IAuthenticationAttributes public class AuthenticatedAttribute : Attribute, IHasRequestFilter, IAuthenticationAttributes
{ {
public IAuthService AuthService { get; set; } public static IAuthService AuthService { get; set; }
/// <summary> /// <summary>
/// Gets or sets the roles. /// Gets or sets the roles.
@ -26,7 +26,7 @@ namespace MediaBrowser.Controller.Net
/// </summary> /// </summary>
/// <value><c>true</c> if [allow before startup wizard]; otherwise, <c>false</c>.</value> /// <value><c>true</c> if [allow before startup wizard]; otherwise, <c>false</c>.</value>
public bool AllowBeforeStartupWizard { get; set; } public bool AllowBeforeStartupWizard { get; set; }
/// <summary> /// <summary>
/// The request filter is executed before the service. /// The request filter is executed before the service.
/// </summary> /// </summary>
@ -40,15 +40,6 @@ namespace MediaBrowser.Controller.Net
AuthService.Authenticate(serviceRequest, this); AuthService.Authenticate(serviceRequest, this);
} }
/// <summary>
/// A new shallow copy of this filter is used on every request.
/// </summary>
/// <returns>IHasRequestFilter.</returns>
public IHasRequestFilter Copy()
{
return this;
}
/// <summary> /// <summary>
/// Order in which Request Filters are executed. /// Order in which Request Filters are executed.
/// &lt;0 Executed before global request filters /// &lt;0 Executed before global request filters
@ -60,7 +51,6 @@ namespace MediaBrowser.Controller.Net
get { return 0; } get { return 0; }
} }
public IEnumerable<string> GetRoles() public IEnumerable<string> GetRoles()
{ {
return (Roles ?? string.Empty).Split(',') return (Roles ?? string.Empty).Split(',')

View File

@ -5,7 +5,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using MediaBrowser.Model.TextEncoding; using MediaBrowser.Model.Text;
namespace MediaBrowser.MediaEncoding.BdInfo namespace MediaBrowser.MediaEncoding.BdInfo
{ {
@ -15,9 +15,9 @@ namespace MediaBrowser.MediaEncoding.BdInfo
public class BdInfoExaminer : IBlurayExaminer public class BdInfoExaminer : IBlurayExaminer
{ {
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly IEncoding _textEncoding; private readonly ITextEncoding _textEncoding;
public BdInfoExaminer(IFileSystem fileSystem, IEncoding textEncoding) public BdInfoExaminer(IFileSystem fileSystem, ITextEncoding textEncoding)
{ {
_fileSystem = fileSystem; _fileSystem = fileSystem;
_textEncoding = textEncoding; _textEncoding = textEncoding;

View File

@ -79,7 +79,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
private readonly IHttpClient _httpClient; private readonly IHttpClient _httpClient;
private readonly IZipClient _zipClient; private readonly IZipClient _zipClient;
private readonly IProcessFactory _processFactory; private readonly IProcessFactory _processFactory;
private readonly IMemoryStreamProvider _memoryStreamProvider; private readonly IMemoryStreamFactory _memoryStreamProvider;
private readonly List<ProcessWrapper> _runningProcesses = new List<ProcessWrapper>(); private readonly List<ProcessWrapper> _runningProcesses = new List<ProcessWrapper>();
private readonly bool _hasExternalEncoder; private readonly bool _hasExternalEncoder;
@ -88,7 +88,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
private readonly int DefaultImageExtractionTimeoutMs; private readonly int DefaultImageExtractionTimeoutMs;
private readonly bool EnableEncoderFontFile; private readonly bool EnableEncoderFontFile;
public MediaEncoder(ILogger logger, IJsonSerializer jsonSerializer, string ffMpegPath, string ffProbePath, bool hasExternalEncoder, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ILiveTvManager liveTvManager, IIsoManager isoManager, ILibraryManager libraryManager, IChannelManager channelManager, ISessionManager sessionManager, Func<ISubtitleEncoder> subtitleEncoder, Func<IMediaSourceManager> mediaSourceManager, IHttpClient httpClient, IZipClient zipClient, IMemoryStreamProvider memoryStreamProvider, IProcessFactory processFactory, public MediaEncoder(ILogger logger, IJsonSerializer jsonSerializer, string ffMpegPath, string ffProbePath, bool hasExternalEncoder, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ILiveTvManager liveTvManager, IIsoManager isoManager, ILibraryManager libraryManager, IChannelManager channelManager, ISessionManager sessionManager, Func<ISubtitleEncoder> subtitleEncoder, Func<IMediaSourceManager> mediaSourceManager, IHttpClient httpClient, IZipClient zipClient, IMemoryStreamFactory memoryStreamProvider, IProcessFactory processFactory,
int defaultImageExtractionTimeoutMs, int defaultImageExtractionTimeoutMs,
bool enableEncoderFontFile) bool enableEncoderFontFile)
{ {

View File

@ -23,9 +23,9 @@ namespace MediaBrowser.MediaEncoding.Probing
private readonly CultureInfo _usCulture = new CultureInfo("en-US"); private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly IMemoryStreamProvider _memoryStreamProvider; private readonly IMemoryStreamFactory _memoryStreamProvider;
public ProbeResultNormalizer(ILogger logger, IFileSystem fileSystem, IMemoryStreamProvider memoryStreamProvider) public ProbeResultNormalizer(ILogger logger, IFileSystem fileSystem, IMemoryStreamFactory memoryStreamProvider)
{ {
_logger = logger; _logger = logger;
_fileSystem = fileSystem; _fileSystem = fileSystem;

View File

@ -19,7 +19,7 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using MediaBrowser.Model.Diagnostics; using MediaBrowser.Model.Diagnostics;
using MediaBrowser.Model.TextEncoding; using MediaBrowser.Model.Text;
using UniversalDetector; using UniversalDetector;
namespace MediaBrowser.MediaEncoding.Subtitles namespace MediaBrowser.MediaEncoding.Subtitles
@ -34,11 +34,11 @@ namespace MediaBrowser.MediaEncoding.Subtitles
private readonly IJsonSerializer _json; private readonly IJsonSerializer _json;
private readonly IHttpClient _httpClient; private readonly IHttpClient _httpClient;
private readonly IMediaSourceManager _mediaSourceManager; private readonly IMediaSourceManager _mediaSourceManager;
private readonly IMemoryStreamProvider _memoryStreamProvider; private readonly IMemoryStreamFactory _memoryStreamProvider;
private readonly IProcessFactory _processFactory; private readonly IProcessFactory _processFactory;
private readonly IEncoding _textEncoding; private readonly ITextEncoding _textEncoding;
public SubtitleEncoder(ILibraryManager libraryManager, ILogger logger, IApplicationPaths appPaths, IFileSystem fileSystem, IMediaEncoder mediaEncoder, IJsonSerializer json, IHttpClient httpClient, IMediaSourceManager mediaSourceManager, IMemoryStreamProvider memoryStreamProvider, IProcessFactory processFactory, IEncoding textEncoding) public SubtitleEncoder(ILibraryManager libraryManager, ILogger logger, IApplicationPaths appPaths, IFileSystem fileSystem, IMediaEncoder mediaEncoder, IJsonSerializer json, IHttpClient httpClient, IMediaSourceManager mediaSourceManager, IMemoryStreamFactory memoryStreamProvider, IProcessFactory processFactory, ITextEncoding textEncoding)
{ {
_libraryManager = libraryManager; _libraryManager = libraryManager;
_logger = logger; _logger = logger;

View File

@ -0,0 +1,13 @@
using System;
using System.IO;
namespace MediaBrowser.Model.Cryptography
{
public interface ICryptoProvider
{
Guid GetMD5(string str);
byte[] ComputeMD5(Stream str);
byte[] ComputeMD5(byte[] bytes);
byte[] ComputeSHA1(byte[] bytes);
}
}

View File

@ -1,14 +0,0 @@
using System;
using System.IO;
namespace MediaBrowser.Model.Cryptography
{
public interface ICryptographyProvider
{
Guid GetMD5(string str);
byte[] GetMD5Bytes(string str);
byte[] GetSHA1Bytes(byte[] bytes);
byte[] GetMD5Bytes(Stream str);
byte[] GetMD5Bytes(byte[] bytes);
}
}

View File

@ -2,10 +2,11 @@
namespace MediaBrowser.Model.IO namespace MediaBrowser.Model.IO
{ {
public interface IMemoryStreamProvider public interface IMemoryStreamFactory
{ {
MemoryStream CreateNew(); MemoryStream CreateNew();
MemoryStream CreateNew(int capacity); MemoryStream CreateNew(int capacity);
MemoryStream CreateNew(byte[] buffer); MemoryStream CreateNew(byte[] buffer);
bool TryGetBuffer(MemoryStream stream, out byte[] buffer);
} }
} }

View File

@ -100,7 +100,7 @@
<Compile Include="Connect\PinExchangeResult.cs" /> <Compile Include="Connect\PinExchangeResult.cs" />
<Compile Include="Connect\PinStatusResult.cs" /> <Compile Include="Connect\PinStatusResult.cs" />
<Compile Include="Connect\UserLinkType.cs" /> <Compile Include="Connect\UserLinkType.cs" />
<Compile Include="Cryptography\ICryptographyProvider.cs" /> <Compile Include="Cryptography\ICryptoProvider.cs" />
<Compile Include="Devices\DeviceOptions.cs" /> <Compile Include="Devices\DeviceOptions.cs" />
<Compile Include="Devices\DeviceQuery.cs" /> <Compile Include="Devices\DeviceQuery.cs" />
<Compile Include="Devices\LocalFileInfo.cs" /> <Compile Include="Devices\LocalFileInfo.cs" />
@ -138,17 +138,19 @@
<Compile Include="Dto\NameIdPair.cs" /> <Compile Include="Dto\NameIdPair.cs" />
<Compile Include="Dto\NameValuePair.cs" /> <Compile Include="Dto\NameValuePair.cs" />
<Compile Include="Net\IpEndPointInfo.cs" /> <Compile Include="Net\IpEndPointInfo.cs" />
<Compile Include="Net\ISocket.cs" />
<Compile Include="Net\ISocketFactory.cs" /> <Compile Include="Net\ISocketFactory.cs" />
<Compile Include="Net\IUdpSocket.cs" /> <Compile Include="Net\IUdpSocket.cs" />
<Compile Include="Net\SocketReceiveResult.cs" /> <Compile Include="Net\SocketReceiveResult.cs" />
<Compile Include="Services\IHttpResult.cs" />
<Compile Include="System\IEnvironmentInfo.cs" /> <Compile Include="System\IEnvironmentInfo.cs" />
<Compile Include="TextEncoding\IEncoding.cs" /> <Compile Include="Text\ITextEncoding.cs" />
<Compile Include="Extensions\LinqExtensions.cs" /> <Compile Include="Extensions\LinqExtensions.cs" />
<Compile Include="FileOrganization\SmartMatchInfo.cs" /> <Compile Include="FileOrganization\SmartMatchInfo.cs" />
<Compile Include="Health\IHealthMonitor.cs" /> <Compile Include="Health\IHealthMonitor.cs" />
<Compile Include="IO\FileSystemMetadata.cs" /> <Compile Include="IO\FileSystemMetadata.cs" />
<Compile Include="IO\IFileSystem.cs" /> <Compile Include="IO\IFileSystem.cs" />
<Compile Include="IO\IMemoryStreamProvider.cs" /> <Compile Include="IO\IMemoryStreamFactory.cs" />
<Compile Include="IO\IShortcutHandler.cs" /> <Compile Include="IO\IShortcutHandler.cs" />
<Compile Include="IO\StreamDefaults.cs" /> <Compile Include="IO\StreamDefaults.cs" />
<Compile Include="Globalization\ILocalizationManager.cs" /> <Compile Include="Globalization\ILocalizationManager.cs" />

View File

@ -0,0 +1,16 @@
using System;
namespace MediaBrowser.Model.Net
{
public interface ISocket : IDisposable
{
IpEndPointInfo LocalEndPoint { get; }
IpEndPointInfo RemoteEndPoint { get; }
void Close();
void Shutdown(bool both);
void Listen(int backlog);
void Bind(IpEndPointInfo endpoint);
void StartAccept(Action<ISocket> onAccept, Func<bool> isClosed);
}
}

View File

@ -27,5 +27,17 @@ namespace MediaBrowser.Model.Net
/// <param name="localPort">The local port to bind to.</param> /// <param name="localPort">The local port to bind to.</param>
/// <returns>A <see cref="IUdpSocket"/> implementation.</returns> /// <returns>A <see cref="IUdpSocket"/> implementation.</returns>
IUdpSocket CreateUdpMulticastSocket(string ipAddress, int multicastTimeToLive, int localPort); IUdpSocket CreateUdpMulticastSocket(string ipAddress, int multicastTimeToLive, int localPort);
}
ISocket CreateSocket(IpAddressFamily family, SocketType socketType, ProtocolType protocolType, bool dualMode);
}
public enum SocketType
{
Stream
}
public enum ProtocolType
{
Tcp
}
} }

View File

@ -4,12 +4,39 @@ namespace MediaBrowser.Model.Net
{ {
public class IpAddressInfo public class IpAddressInfo
{ {
public static IpAddressInfo Any = new IpAddressInfo("0.0.0.0", IpAddressFamily.InterNetwork);
public static IpAddressInfo IPv6Any = new IpAddressInfo("00000000000000000000", IpAddressFamily.InterNetworkV6);
public static IpAddressInfo Loopback = new IpAddressInfo("127.0.0.1", IpAddressFamily.InterNetwork);
public static IpAddressInfo IPv6Loopback = new IpAddressInfo("::1", IpAddressFamily.InterNetworkV6);
public string Address { get; set; } public string Address { get; set; }
public bool IsIpv6 { get; set; } public IpAddressFamily AddressFamily { get; set; }
public IpAddressInfo()
{
}
public IpAddressInfo(string address, IpAddressFamily addressFamily)
{
Address = address;
AddressFamily = addressFamily;
}
public bool Equals(IpAddressInfo address)
{
return string.Equals(address.Address, Address, StringComparison.OrdinalIgnoreCase);
}
public override String ToString() public override String ToString()
{ {
return Address; return Address;
} }
} }
public enum IpAddressFamily
{
InterNetwork,
InterNetworkV6
}
} }

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Globalization;
namespace MediaBrowser.Model.Net namespace MediaBrowser.Model.Net
{ {
@ -8,11 +9,22 @@ namespace MediaBrowser.Model.Net
public int Port { get; set; } public int Port { get; set; }
public IpEndPointInfo()
{
}
public IpEndPointInfo(IpAddressInfo address, int port)
{
IpAddress = address;
Port = port;
}
public override string ToString() public override string ToString()
{ {
var ipAddresString = IpAddress == null ? string.Empty : IpAddress.ToString(); var ipAddresString = IpAddress == null ? string.Empty : IpAddress.ToString();
return ipAddresString + ":" + this.Port.ToString(); return ipAddresString + ":" + Port.ToString(CultureInfo.InvariantCulture);
} }
} }
} }

View File

@ -1,9 +1,4 @@
using System; 
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MediaBrowser.Model.Services namespace MediaBrowser.Model.Services
{ {
public interface IHasRequestFilter public interface IHasRequestFilter
@ -22,11 +17,5 @@ namespace MediaBrowser.Model.Services
/// <param name="res">The http response wrapper</param> /// <param name="res">The http response wrapper</param>
/// <param name="requestDto">The request DTO</param> /// <param name="requestDto">The request DTO</param>
void RequestFilter(IRequest req, IResponse res, object requestDto); void RequestFilter(IRequest req, IResponse res, object requestDto);
/// <summary>
/// A new shallow copy of this filter is used on every request.
/// </summary>
/// <returns></returns>
IHasRequestFilter Copy();
} }
} }

View File

@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace MediaBrowser.Model.Services
{
public interface IHttpResult : IHasHeaders
{
/// <summary>
/// The HTTP Response Status
/// </summary>
int Status { get; set; }
/// <summary>
/// The HTTP Response Status Code
/// </summary>
HttpStatusCode StatusCode { get; set; }
/// <summary>
/// The HTTP Status Description
/// </summary>
string StatusDescription { get; set; }
/// <summary>
/// The HTTP Response ContentType
/// </summary>
string ContentType { get; set; }
/// <summary>
/// Additional HTTP Cookies
/// </summary>
List<Cookie> Cookies { get; }
/// <summary>
/// Response DTO
/// </summary>
object Response { get; set; }
/// <summary>
/// Holds the request call context
/// </summary>
IRequest RequestContext { get; set; }
}
}

View File

@ -60,16 +60,6 @@ namespace MediaBrowser.Model.Services
QueryParamCollection QueryString { get; } QueryParamCollection QueryString { get; }
QueryParamCollection FormData { get; } QueryParamCollection FormData { get; }
/// <summary>
/// Buffer the Request InputStream so it can be re-read
/// </summary>
bool UseBufferedStream { get; set; }
/// <summary>
/// The entire string contents of Request.InputStream
/// </summary>
/// <returns></returns>
string GetRawBody();
string RawUrl { get; } string RawUrl { get; }

View File

@ -9,7 +9,7 @@ namespace MediaBrowser.Model.Services
{ {
public QueryParamCollection() public QueryParamCollection()
{ {
} }
public QueryParamCollection(IDictionary<string, string> headers) public QueryParamCollection(IDictionary<string, string> headers)
@ -30,15 +30,30 @@ namespace MediaBrowser.Model.Services
return StringComparer.OrdinalIgnoreCase; return StringComparer.OrdinalIgnoreCase;
} }
public string GetKey(int index)
{
return this[index].Name;
}
public string Get(int index)
{
return this[index].Value;
}
public virtual string[] GetValues(int index)
{
return new[] { Get(index) };
}
/// <summary> /// <summary>
/// Adds a new query parameter. /// Adds a new query parameter.
/// </summary> /// </summary>
public void Add(string key, string value) public virtual void Add(string key, string value)
{ {
Add(new NameValuePair(key, value)); Add(new NameValuePair(key, value));
} }
public void Set(string key, string value) public virtual void Set(string key, string value)
{ {
if (string.IsNullOrWhiteSpace(value)) if (string.IsNullOrWhiteSpace(value))
{ {
@ -81,17 +96,21 @@ namespace MediaBrowser.Model.Services
/// </summary> /// </summary>
/// <returns>The number of parameters that were removed</returns> /// <returns>The number of parameters that were removed</returns>
/// <exception cref="ArgumentNullException"><paramref name="name" /> is null.</exception> /// <exception cref="ArgumentNullException"><paramref name="name" /> is null.</exception>
public int Remove(string name) public virtual int Remove(string name)
{ {
return RemoveAll(p => p.Name == name); return RemoveAll(p => p.Name == name);
} }
public string Get(string name) public string Get(string name)
{ {
return GetValues(name).FirstOrDefault(); var stringComparison = GetStringComparison();
return this.Where(p => string.Equals(p.Name, name, stringComparison))
.Select(p => p.Value)
.FirstOrDefault();
} }
public string[] GetValues(string name) public virtual string[] GetValues(string name)
{ {
var stringComparison = GetStringComparison(); var stringComparison = GetStringComparison();

View File

@ -0,0 +1,10 @@
using System.Text;
namespace MediaBrowser.Model.Text
{
public interface ITextEncoding
{
Encoding GetASCIIEncoding();
Encoding GetFileEncoding(string path);
}
}

View File

@ -1,12 +0,0 @@
using System.Text;
namespace MediaBrowser.Model.TextEncoding
{
public interface IEncoding
{
byte[] GetASCIIBytes(string text);
string GetASCIIString(byte[] bytes, int startIndex, int length);
Encoding GetFileEncoding(string path);
}
}

View File

@ -40,7 +40,7 @@ namespace MediaBrowser.Providers.Manager
private readonly ILibraryMonitor _libraryMonitor; private readonly ILibraryMonitor _libraryMonitor;
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IMemoryStreamProvider _memoryStreamProvider; private readonly IMemoryStreamFactory _memoryStreamProvider;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ImageSaver" /> class. /// Initializes a new instance of the <see cref="ImageSaver" /> class.
@ -49,7 +49,7 @@ namespace MediaBrowser.Providers.Manager
/// <param name="libraryMonitor">The directory watchers.</param> /// <param name="libraryMonitor">The directory watchers.</param>
/// <param name="fileSystem">The file system.</param> /// <param name="fileSystem">The file system.</param>
/// <param name="logger">The logger.</param> /// <param name="logger">The logger.</param>
public ImageSaver(IServerConfigurationManager config, ILibraryMonitor libraryMonitor, IFileSystem fileSystem, ILogger logger, IMemoryStreamProvider memoryStreamProvider) public ImageSaver(IServerConfigurationManager config, ILibraryMonitor libraryMonitor, IFileSystem fileSystem, ILogger logger, IMemoryStreamFactory memoryStreamProvider)
{ {
_config = config; _config = config;
_libraryMonitor = libraryMonitor; _libraryMonitor = libraryMonitor;

View File

@ -66,7 +66,7 @@ namespace MediaBrowser.Providers.Manager
private IExternalId[] _externalIds; private IExternalId[] _externalIds;
private readonly Func<ILibraryManager> _libraryManagerFactory; private readonly Func<ILibraryManager> _libraryManagerFactory;
private readonly IMemoryStreamProvider _memoryStreamProvider; private readonly IMemoryStreamFactory _memoryStreamProvider;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ProviderManager" /> class. /// Initializes a new instance of the <see cref="ProviderManager" /> class.
@ -76,7 +76,7 @@ namespace MediaBrowser.Providers.Manager
/// <param name="libraryMonitor">The directory watchers.</param> /// <param name="libraryMonitor">The directory watchers.</param>
/// <param name="logManager">The log manager.</param> /// <param name="logManager">The log manager.</param>
/// <param name="fileSystem">The file system.</param> /// <param name="fileSystem">The file system.</param>
public ProviderManager(IHttpClient httpClient, IServerConfigurationManager configurationManager, ILibraryMonitor libraryMonitor, ILogManager logManager, IFileSystem fileSystem, IServerApplicationPaths appPaths, Func<ILibraryManager> libraryManagerFactory, IJsonSerializer json, IMemoryStreamProvider memoryStreamProvider) public ProviderManager(IHttpClient httpClient, IServerConfigurationManager configurationManager, ILibraryMonitor libraryMonitor, ILogManager logManager, IFileSystem fileSystem, IServerApplicationPaths appPaths, Func<ILibraryManager> libraryManagerFactory, IJsonSerializer json, IMemoryStreamFactory memoryStreamProvider)
{ {
_logger = logManager.GetLogger("ProviderManager"); _logger = logManager.GetLogger("ProviderManager");
_httpClient = httpClient; _httpClient = httpClient;

View File

@ -45,6 +45,11 @@ namespace MediaBrowser.Providers.MediaInfo
var codec = Path.GetExtension(fullName).ToLower().TrimStart('.'); var codec = Path.GetExtension(fullName).ToLower().TrimStart('.');
if (string.Equals(codec, "txt", StringComparison.OrdinalIgnoreCase))
{
codec = "srt";
}
// If the subtitle file matches the video file name // If the subtitle file matches the video file name
if (string.Equals(videoFileNameWithoutExtension, fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase)) if (string.Equals(videoFileNameWithoutExtension, fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase))
{ {
@ -74,9 +79,9 @@ namespace MediaBrowser.Providers.MediaInfo
// Try to translate to three character code // Try to translate to three character code
// Be flexible and check against both the full and three character versions // Be flexible and check against both the full and three character versions
var culture = _localization.GetCultures() var culture = _localization.GetCultures()
.FirstOrDefault(i => string.Equals(i.DisplayName, language, StringComparison.OrdinalIgnoreCase) || .FirstOrDefault(i => string.Equals(i.DisplayName, language, StringComparison.OrdinalIgnoreCase) ||
string.Equals(i.Name, language, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Name, language, StringComparison.OrdinalIgnoreCase) ||
string.Equals(i.ThreeLetterISOLanguageName, language, StringComparison.OrdinalIgnoreCase) || string.Equals(i.ThreeLetterISOLanguageName, language, StringComparison.OrdinalIgnoreCase) ||
string.Equals(i.TwoLetterISOLanguageName, language, StringComparison.OrdinalIgnoreCase)); string.Equals(i.TwoLetterISOLanguageName, language, StringComparison.OrdinalIgnoreCase));
if (culture != null) if (culture != null)
@ -119,7 +124,7 @@ namespace MediaBrowser.Providers.MediaInfo
{ {
get get
{ {
return new[] { ".srt", ".ssa", ".ass", ".sub", ".smi", ".sami" }; return new[] { ".srt", ".ssa", ".ass", ".sub", ".smi", ".sami", ".txt" };
} }
} }

View File

@ -40,10 +40,10 @@ namespace MediaBrowser.Providers.TV
private readonly CultureInfo _usCulture = new CultureInfo("en-US"); private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly IMemoryStreamProvider _memoryStreamProvider; private readonly IMemoryStreamFactory _memoryStreamProvider;
private readonly ILocalizationManager _localizationManager; private readonly ILocalizationManager _localizationManager;
public TvdbSeriesProvider(IZipClient zipClient, IHttpClient httpClient, IFileSystem fileSystem, IServerConfigurationManager config, ILogger logger, ILibraryManager libraryManager, IMemoryStreamProvider memoryStreamProvider, IXmlReaderSettingsFactory xmlSettings, ILocalizationManager localizationManager) public TvdbSeriesProvider(IZipClient zipClient, IHttpClient httpClient, IFileSystem fileSystem, IServerConfigurationManager config, ILogger logger, ILibraryManager libraryManager, IMemoryStreamFactory memoryStreamProvider, IXmlReaderSettingsFactory xmlSettings, ILocalizationManager localizationManager)
{ {
_zipClient = zipClient; _zipClient = zipClient;
_httpClient = httpClient; _httpClient = httpClient;

View File

@ -6,7 +6,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// <summary> /// <summary>
/// Class ContainerAdapter /// Class ContainerAdapter
/// </summary> /// </summary>
class ContainerAdapter : IContainerAdapter, IRelease class ContainerAdapter : IContainerAdapter
{ {
/// <summary> /// <summary>
/// The _app host /// The _app host
@ -40,14 +40,5 @@ namespace MediaBrowser.Server.Implementations.HttpServer
{ {
return _appHost.TryResolve<T>(); return _appHost.TryResolve<T>();
} }
/// <summary>
/// Releases the specified instance.
/// </summary>
/// <param name="instance">The instance.</param>
public void Release(object instance)
{
// Leave this empty so SS doesn't try to dispose our objects
}
} }
} }

View File

@ -8,24 +8,31 @@ using MediaBrowser.Server.Implementations.HttpServer.SocketSharp;
using ServiceStack; using ServiceStack;
using ServiceStack.Host; using ServiceStack.Host;
using ServiceStack.Host.Handlers; using ServiceStack.Host.Handlers;
using ServiceStack.Logging;
using ServiceStack.Web; using ServiceStack.Web;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net.Security;
using System.Net.Sockets;
using System.Reflection; using System.Reflection;
using System.Security.Cryptography.X509Certificates;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Emby.Common.Implementations.Net;
using Emby.Server.Implementations.HttpServer; using Emby.Server.Implementations.HttpServer;
using Emby.Server.Implementations.HttpServer.SocketSharp; using Emby.Server.Implementations.HttpServer.SocketSharp;
using MediaBrowser.Common.Net; using MediaBrowser.Common.Net;
using MediaBrowser.Common.Security; using MediaBrowser.Common.Security;
using MediaBrowser.Controller; using MediaBrowser.Controller;
using MediaBrowser.Model.Cryptography;
using MediaBrowser.Model.Extensions; using MediaBrowser.Model.Extensions;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using MediaBrowser.Model.Net;
using MediaBrowser.Model.Services; using MediaBrowser.Model.Services;
using ServiceStack.Api.Swagger; using MediaBrowser.Model.Text;
using SocketHttpListener.Net;
using SocketHttpListener.Primitives;
namespace MediaBrowser.Server.Implementations.HttpServer namespace MediaBrowser.Server.Implementations.HttpServer
{ {
@ -49,21 +56,28 @@ namespace MediaBrowser.Server.Implementations.HttpServer
private readonly IServerConfigurationManager _config; private readonly IServerConfigurationManager _config;
private readonly INetworkManager _networkManager; private readonly INetworkManager _networkManager;
private readonly IMemoryStreamProvider _memoryStreamProvider; private readonly IMemoryStreamFactory _memoryStreamProvider;
private readonly IServerApplicationHost _appHost; private readonly IServerApplicationHost _appHost;
private readonly ITextEncoding _textEncoding;
private readonly ISocketFactory _socketFactory;
private readonly ICryptoProvider _cryptoProvider;
public HttpListenerHost(IServerApplicationHost applicationHost, public HttpListenerHost(IServerApplicationHost applicationHost,
ILogManager logManager, ILogManager logManager,
IServerConfigurationManager config, IServerConfigurationManager config,
string serviceName, string serviceName,
string defaultRedirectPath, INetworkManager networkManager, IMemoryStreamProvider memoryStreamProvider, params Assembly[] assembliesWithServices) string defaultRedirectPath, INetworkManager networkManager, IMemoryStreamFactory memoryStreamProvider, ITextEncoding textEncoding, ISocketFactory socketFactory, ICryptoProvider cryptoProvider)
: base(serviceName, assembliesWithServices) : base(serviceName, new Assembly[] { })
{ {
_appHost = applicationHost; _appHost = applicationHost;
DefaultRedirectPath = defaultRedirectPath; DefaultRedirectPath = defaultRedirectPath;
_networkManager = networkManager; _networkManager = networkManager;
_memoryStreamProvider = memoryStreamProvider; _memoryStreamProvider = memoryStreamProvider;
_textEncoding = textEncoding;
_socketFactory = socketFactory;
_cryptoProvider = cryptoProvider;
_config = config; _config = config;
_logger = logManager.GetLogger("HttpServer"); _logger = logManager.GetLogger("HttpServer");
@ -73,10 +87,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer
public string GlobalResponse { get; set; } public string GlobalResponse { get; set; }
public override void Configure(Container container) public override void Configure()
{ {
HostConfig.Instance.DefaultRedirectPath = DefaultRedirectPath; HostConfig.Instance.DefaultRedirectPath = DefaultRedirectPath;
HostConfig.Instance.LogUnobservedTaskExceptions = false;
HostConfig.Instance.MapExceptionToStatusCode = new Dictionary<Type, int> HostConfig.Instance.MapExceptionToStatusCode = new Dictionary<Type, int>
{ {
@ -93,33 +106,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer
{typeof (NotSupportedException), 500} {typeof (NotSupportedException), 500}
}; };
HostConfig.Instance.GlobalResponseHeaders = new Dictionary<string, string>();
HostConfig.Instance.DebugMode = false;
HostConfig.Instance.LogFactory = LogManager.LogFactory;
HostConfig.Instance.AllowJsonpRequests = false;
// The Markdown feature causes slow startup times (5 mins+) on cold boots for some users // The Markdown feature causes slow startup times (5 mins+) on cold boots for some users
// Custom format allows images // Custom format allows images
HostConfig.Instance.EnableFeatures = Feature.Html | Feature.Json | Feature.Xml | Feature.CustomFormat; HostConfig.Instance.EnableFeatures = Feature.Html | Feature.Json | Feature.Xml | Feature.CustomFormat;
container.Adapter = _containerAdapter; Container.Adapter = _containerAdapter;
Plugins.Add(new SwaggerFeature());
Plugins.Add(new CorsFeature(allowedHeaders: "Content-Type, Authorization, Range, X-MediaBrowser-Token, X-Emby-Authorization"));
//Plugins.Add(new AuthFeature(() => new AuthUserSession(), new IAuthProvider[] {
// new SessionAuthProvider(_containerAdapter.Resolve<ISessionContext>()),
//}));
//PreRequestFilters.Add((httpReq, httpRes) =>
//{
// //Handles Request and closes Responses after emitting global HTTP Headers
// if (string.Equals(httpReq.Verb, "OPTIONS", StringComparison.OrdinalIgnoreCase))
// {
// httpRes.EndRequest(); //add a 'using ServiceStack;'
// }
//});
var requestFilters = _appHost.GetExports<IRequestFilter>().ToList(); var requestFilters = _appHost.GetExports<IRequestFilter>().ToList();
foreach (var filter in requestFilters) foreach (var filter in requestFilters)
@ -130,11 +121,12 @@ namespace MediaBrowser.Server.Implementations.HttpServer
HostContext.GlobalResponseFilters.Add(new ResponseFilter(_logger).FilterResponse); HostContext.GlobalResponseFilters.Add(new ResponseFilter(_logger).FilterResponse);
} }
public override void OnAfterInit() protected override ILogger Logger
{ {
SetAppDomainData(); get
{
base.OnAfterInit(); return _logger;
}
} }
public override void OnConfigLoad() public override void OnConfigLoad()
@ -153,23 +145,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer
return new ServiceController(this, () => types); return new ServiceController(this, () => types);
} }
public virtual void SetAppDomainData()
{
//Required for Mono to resolve VirtualPathUtility and Url.Content urls
var domain = Thread.GetDomain(); // or AppDomain.Current
domain.SetData(".appDomain", "1");
domain.SetData(".appVPath", "/");
domain.SetData(".appPath", domain.BaseDirectory);
if (string.IsNullOrEmpty(domain.GetData(".appId") as string))
{
domain.SetData(".appId", "1");
}
if (string.IsNullOrEmpty(domain.GetData(".domainId") as string))
{
domain.SetData(".domainId", "1");
}
}
public override ServiceStackHost Start(string listeningAtUrlBase) public override ServiceStackHost Start(string listeningAtUrlBase)
{ {
StartListener(); StartListener();
@ -207,7 +182,35 @@ namespace MediaBrowser.Server.Implementations.HttpServer
private IHttpListener GetListener() private IHttpListener GetListener()
{ {
return new WebSocketSharpListener(_logger, CertificatePath, _memoryStreamProvider); var cert = !string.IsNullOrWhiteSpace(CertificatePath) && File.Exists(CertificatePath)
? GetCert(CertificatePath) :
null;
var enableDualMode = Environment.OSVersion.Platform == PlatformID.Win32NT;
return new WebSocketSharpListener(_logger, cert, _memoryStreamProvider, _textEncoding, _networkManager, _socketFactory, _cryptoProvider, new StreamFactory(), enableDualMode, GetRequest);
}
public static ICertificate GetCert(string certificateLocation)
{
X509Certificate2 localCert = new X509Certificate2(certificateLocation);
//localCert.PrivateKey = PrivateKey.CreateFromFile(pvk_file).RSA;
if (localCert.PrivateKey == null)
{
//throw new FileNotFoundException("Secure requested, no private key included", certificateLocation);
return null;
}
return new Certificate(localCert);
}
private IHttpRequest GetRequest(HttpListenerContext httpContext)
{
var operationName = httpContext.Request.GetOperationName();
var req = new WebSocketSharpRequest(httpContext, operationName, _logger, _memoryStreamProvider);
return req;
} }
private void OnWebSocketConnecting(WebSocketConnectingEventArgs args) private void OnWebSocketConnecting(WebSocketConnectingEventArgs args)
@ -259,11 +262,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer
var contentType = httpReq.ResponseContentType; var contentType = httpReq.ResponseContentType;
var serializer = HostContext.ContentTypes.GetResponseSerializer(contentType); var serializer = ContentTypes.Instance.GetResponseSerializer(contentType);
if (serializer == null) if (serializer == null)
{ {
contentType = HostContext.Config.DefaultContentType; contentType = HostContext.Config.DefaultContentType;
serializer = HostContext.ContentTypes.GetResponseSerializer(contentType); serializer = ContentTypes.Instance.GetResponseSerializer(contentType);
} }
var httpError = ex as IHttpError; var httpError = ex as IHttpError;
@ -411,171 +414,170 @@ namespace MediaBrowser.Server.Implementations.HttpServer
protected async Task RequestHandler(IHttpRequest httpReq, Uri url) protected async Task RequestHandler(IHttpRequest httpReq, Uri url)
{ {
var date = DateTime.Now; var date = DateTime.Now;
var httpRes = httpReq.Response; var httpRes = httpReq.Response;
bool enableLog = false;
string urlToLog = null;
string remoteIp = null;
if (_disposed) try
{ {
httpRes.StatusCode = 503; if (_disposed)
httpRes.Close();
return ;
}
if (!ValidateHost(url))
{
httpRes.StatusCode = 400;
httpRes.ContentType = "text/plain";
httpRes.Write("Invalid host");
httpRes.Close();
return;
}
if (string.Equals(httpReq.Verb, "OPTIONS", StringComparison.OrdinalIgnoreCase))
{
httpRes.StatusCode = 200;
httpRes.AddHeader("Access-Control-Allow-Origin", "*");
httpRes.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, PATCH, OPTIONS");
httpRes.AddHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Range, X-MediaBrowser-Token, X-Emby-Authorization");
httpRes.ContentType = "text/html";
httpRes.Close();
}
var operationName = httpReq.OperationName;
var localPath = url.LocalPath;
var urlString = url.OriginalString;
var enableLog = EnableLogging(urlString, localPath);
var urlToLog = urlString;
if (enableLog)
{
urlToLog = GetUrlToLog(urlString);
LoggerUtils.LogRequest(_logger, urlToLog, httpReq.HttpMethod, httpReq.UserAgent);
}
if (string.Equals(localPath, "/emby/", StringComparison.OrdinalIgnoreCase) ||
string.Equals(localPath, "/mediabrowser/", StringComparison.OrdinalIgnoreCase))
{
httpRes.RedirectToUrl(DefaultRedirectPath);
return;
}
if (string.Equals(localPath, "/emby", StringComparison.OrdinalIgnoreCase) ||
string.Equals(localPath, "/mediabrowser", StringComparison.OrdinalIgnoreCase))
{
httpRes.RedirectToUrl("emby/" + DefaultRedirectPath);
return;
}
if (string.Equals(localPath, "/mediabrowser/", StringComparison.OrdinalIgnoreCase) ||
string.Equals(localPath, "/mediabrowser", StringComparison.OrdinalIgnoreCase) ||
localPath.IndexOf("mediabrowser/web", StringComparison.OrdinalIgnoreCase) != -1)
{
httpRes.StatusCode = 200;
httpRes.ContentType = "text/html";
var newUrl = urlString.Replace("mediabrowser", "emby", StringComparison.OrdinalIgnoreCase)
.Replace("/dashboard/", "/web/", StringComparison.OrdinalIgnoreCase);
if (!string.Equals(newUrl, urlString, StringComparison.OrdinalIgnoreCase))
{ {
httpRes.Write("<!doctype html><html><head><title>Emby</title></head><body>Please update your Emby bookmark to <a href=\"" + newUrl + "\">" + newUrl + "</a></body></html>"); httpRes.StatusCode = 503;
httpRes.Close();
return; return;
} }
}
if (localPath.IndexOf("dashboard/", StringComparison.OrdinalIgnoreCase) != -1 && if (!ValidateHost(url))
localPath.IndexOf("web/dashboard", StringComparison.OrdinalIgnoreCase) == -1)
{
httpRes.StatusCode = 200;
httpRes.ContentType = "text/html";
var newUrl = urlString.Replace("mediabrowser", "emby", StringComparison.OrdinalIgnoreCase)
.Replace("/dashboard/", "/web/", StringComparison.OrdinalIgnoreCase);
if (!string.Equals(newUrl, urlString, StringComparison.OrdinalIgnoreCase))
{ {
httpRes.Write("<!doctype html><html><head><title>Emby</title></head><body>Please update your Emby bookmark to <a href=\"" + newUrl + "\">" + newUrl + "</a></body></html>"); httpRes.StatusCode = 400;
httpRes.ContentType = "text/plain";
httpRes.Close(); httpRes.Write("Invalid host");
return; return;
} }
}
if (string.Equals(localPath, "/web", StringComparison.OrdinalIgnoreCase)) if (string.Equals(httpReq.Verb, "OPTIONS", StringComparison.OrdinalIgnoreCase))
{ {
httpRes.RedirectToUrl(DefaultRedirectPath); httpRes.StatusCode = 200;
return; httpRes.AddHeader("Access-Control-Allow-Origin", "*");
} httpRes.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, PATCH, OPTIONS");
if (string.Equals(localPath, "/web/", StringComparison.OrdinalIgnoreCase)) httpRes.AddHeader("Access-Control-Allow-Headers",
{ "Content-Type, Authorization, Range, X-MediaBrowser-Token, X-Emby-Authorization");
httpRes.RedirectToUrl("../" + DefaultRedirectPath); httpRes.ContentType = "text/html";
return; return;
} }
if (string.Equals(localPath, "/", StringComparison.OrdinalIgnoreCase))
{
httpRes.RedirectToUrl(DefaultRedirectPath);
return;
}
if (string.IsNullOrEmpty(localPath))
{
httpRes.RedirectToUrl("/" + DefaultRedirectPath);
return;
}
if (string.Equals(localPath, "/emby/pin", StringComparison.OrdinalIgnoreCase)) var operationName = httpReq.OperationName;
{ var localPath = url.LocalPath;
httpRes.RedirectToUrl("web/pin.html");
return; var urlString = url.OriginalString;
enableLog = EnableLogging(urlString, localPath);
urlToLog = urlString;
if (enableLog)
{
urlToLog = GetUrlToLog(urlString);
remoteIp = httpReq.RemoteIp;
LoggerUtils.LogRequest(_logger, urlToLog, httpReq.HttpMethod, httpReq.UserAgent);
}
if (string.Equals(localPath, "/emby/", StringComparison.OrdinalIgnoreCase) ||
string.Equals(localPath, "/mediabrowser/", StringComparison.OrdinalIgnoreCase))
{
RedirectToUrl(httpRes, DefaultRedirectPath);
return;
}
if (string.Equals(localPath, "/emby", StringComparison.OrdinalIgnoreCase) ||
string.Equals(localPath, "/mediabrowser", StringComparison.OrdinalIgnoreCase))
{
RedirectToUrl(httpRes, "emby/" + DefaultRedirectPath);
return;
}
if (string.Equals(localPath, "/mediabrowser/", StringComparison.OrdinalIgnoreCase) ||
string.Equals(localPath, "/mediabrowser", StringComparison.OrdinalIgnoreCase) ||
localPath.IndexOf("mediabrowser/web", StringComparison.OrdinalIgnoreCase) != -1)
{
httpRes.StatusCode = 200;
httpRes.ContentType = "text/html";
var newUrl = urlString.Replace("mediabrowser", "emby", StringComparison.OrdinalIgnoreCase)
.Replace("/dashboard/", "/web/", StringComparison.OrdinalIgnoreCase);
if (!string.Equals(newUrl, urlString, StringComparison.OrdinalIgnoreCase))
{
httpRes.Write(
"<!doctype html><html><head><title>Emby</title></head><body>Please update your Emby bookmark to <a href=\"" +
newUrl + "\">" + newUrl + "</a></body></html>");
return;
}
}
if (localPath.IndexOf("dashboard/", StringComparison.OrdinalIgnoreCase) != -1 &&
localPath.IndexOf("web/dashboard", StringComparison.OrdinalIgnoreCase) == -1)
{
httpRes.StatusCode = 200;
httpRes.ContentType = "text/html";
var newUrl = urlString.Replace("mediabrowser", "emby", StringComparison.OrdinalIgnoreCase)
.Replace("/dashboard/", "/web/", StringComparison.OrdinalIgnoreCase);
if (!string.Equals(newUrl, urlString, StringComparison.OrdinalIgnoreCase))
{
httpRes.Write(
"<!doctype html><html><head><title>Emby</title></head><body>Please update your Emby bookmark to <a href=\"" +
newUrl + "\">" + newUrl + "</a></body></html>");
return;
}
}
if (string.Equals(localPath, "/web", StringComparison.OrdinalIgnoreCase))
{
RedirectToUrl(httpRes, DefaultRedirectPath);
return;
}
if (string.Equals(localPath, "/web/", StringComparison.OrdinalIgnoreCase))
{
RedirectToUrl(httpRes, "../" + DefaultRedirectPath);
return;
}
if (string.Equals(localPath, "/", StringComparison.OrdinalIgnoreCase))
{
RedirectToUrl(httpRes, DefaultRedirectPath);
return;
}
if (string.IsNullOrEmpty(localPath))
{
RedirectToUrl(httpRes, "/" + DefaultRedirectPath);
return;
}
if (string.Equals(localPath, "/emby/pin", StringComparison.OrdinalIgnoreCase))
{
RedirectToUrl(httpRes, "web/pin.html");
return;
}
if (!string.IsNullOrWhiteSpace(GlobalResponse))
{
httpRes.StatusCode = 503;
httpRes.ContentType = "text/html";
httpRes.Write(GlobalResponse);
return;
}
var handler = HttpHandlerFactory.GetHandler(httpReq);
if (handler != null)
{
await handler.ProcessRequestAsync(httpReq, httpRes, operationName).ConfigureAwait(false);
}
} }
catch (Exception ex)
if (!string.IsNullOrWhiteSpace(GlobalResponse)) {
ErrorHandler(ex, httpReq);
}
finally
{ {
httpRes.StatusCode = 503;
httpRes.ContentType = "text/html";
httpRes.Write(GlobalResponse);
httpRes.Close(); httpRes.Close();
return;
}
var handler = HttpHandlerFactory.GetHandler(httpReq); if (enableLog)
var remoteIp = httpReq.RemoteIp;
var serviceStackHandler = handler as IServiceStackHandler;
if (serviceStackHandler != null)
{
var restHandler = serviceStackHandler as RestHandler;
if (restHandler != null)
{ {
httpReq.OperationName = operationName = restHandler.RestPath.RequestType.GetOperationName();
}
try
{
await serviceStackHandler.ProcessRequestAsync(httpReq, httpRes, operationName).ConfigureAwait(false);
}
finally
{
httpRes.Close();
var statusCode = httpRes.StatusCode; var statusCode = httpRes.StatusCode;
var duration = DateTime.Now - date; var duration = DateTime.Now - date;
if (enableLog) LoggerUtils.LogResponse(_logger, statusCode, urlToLog, remoteIp, duration);
{
LoggerUtils.LogResponse(_logger, statusCode, urlToLog, remoteIp, duration);
}
} }
} }
else
{
httpRes.Close();
}
} }
public static void RedirectToUrl(IResponse httpRes, string url)
{
httpRes.StatusCode = 302;
httpRes.AddHeader(HttpHeaders.Location, url);
httpRes.EndRequest();
}
/// <summary> /// <summary>
/// Adds the rest handlers. /// Adds the rest handlers.
/// </summary> /// </summary>
@ -653,15 +655,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer
return "mediabrowser/" + path; return "mediabrowser/" + path;
} }
/// <summary>
/// Releases the specified instance.
/// </summary>
/// <param name="instance">The instance.</param>
public override void Release(object instance)
{
// Leave this empty so SS doesn't try to dispose our objects
}
private bool _disposed; private bool _disposed;
private readonly object _disposeLock = new object(); private readonly object _disposeLock = new object();
protected virtual void Dispose(bool disposing) protected virtual void Dispose(bool disposing)
@ -696,4 +689,37 @@ namespace MediaBrowser.Server.Implementations.HttpServer
Start(UrlPrefixes.First()); Start(UrlPrefixes.First());
} }
} }
public class StreamFactory : IStreamFactory
{
public Stream CreateNetworkStream(ISocket socket, bool ownsSocket)
{
var netSocket = (NetSocket)socket;
return new NetworkStream(netSocket.Socket, ownsSocket);
}
public Task AuthenticateSslStreamAsServer(Stream stream, ICertificate certificate)
{
var sslStream = (SslStream)stream;
var cert = (Certificate)certificate;
return sslStream.AuthenticateAsServerAsync(cert.X509Certificate);
}
public Stream CreateSslStream(Stream innerStream, bool leaveInnerStreamOpen)
{
return new SslStream(innerStream, leaveInnerStreamOpen);
}
}
public class Certificate : ICertificate
{
public Certificate(X509Certificate x509Certificate)
{
X509Certificate = x509Certificate;
}
public X509Certificate X509Certificate { get; private set; }
}
} }

View File

@ -9,6 +9,7 @@ using System.IO;
using System.Net; using System.Net;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Emby.Server.Implementations.HttpServer;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using MediaBrowser.Model.Services; using MediaBrowser.Model.Services;
using ServiceStack; using ServiceStack;

View File

@ -2,9 +2,11 @@
using MediaBrowser.Controller; using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Cryptography;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
using ServiceStack.Logging; using MediaBrowser.Model.Net;
using MediaBrowser.Model.Text;
namespace MediaBrowser.Server.Implementations.HttpServer namespace MediaBrowser.Server.Implementations.HttpServer
{ {
@ -21,13 +23,14 @@ namespace MediaBrowser.Server.Implementations.HttpServer
ILogManager logManager, ILogManager logManager,
IServerConfigurationManager config, IServerConfigurationManager config,
INetworkManager networkmanager, INetworkManager networkmanager,
IMemoryStreamProvider streamProvider, IMemoryStreamFactory streamProvider,
string serverName, string serverName,
string defaultRedirectpath) string defaultRedirectpath,
ITextEncoding textEncoding,
ISocketFactory socketFactory,
ICryptoProvider cryptoProvider)
{ {
LogManager.LogFactory = new ServerLogFactory(logManager); return new HttpListenerHost(applicationHost, logManager, config, serverName, defaultRedirectpath, networkmanager, streamProvider, textEncoding, socketFactory, cryptoProvider);
return new HttpListenerHost(applicationHost, logManager, config, serverName, defaultRedirectpath, networkmanager, streamProvider);
} }
} }
} }

View File

@ -1,46 +0,0 @@
using System;
using MediaBrowser.Model.Logging;
using ServiceStack.Logging;
namespace MediaBrowser.Server.Implementations.HttpServer
{
/// <summary>
/// Class ServerLogFactory
/// </summary>
public class ServerLogFactory : ILogFactory
{
/// <summary>
/// The _log manager
/// </summary>
private readonly ILogManager _logManager;
/// <summary>
/// Initializes a new instance of the <see cref="ServerLogFactory"/> class.
/// </summary>
/// <param name="logManager">The log manager.</param>
public ServerLogFactory(ILogManager logManager)
{
_logManager = logManager;
}
/// <summary>
/// Gets the logger.
/// </summary>
/// <param name="typeName">Name of the type.</param>
/// <returns>ILog.</returns>
public ILog GetLogger(string typeName)
{
return new ServerLogger(_logManager.GetLogger(typeName));
}
/// <summary>
/// Gets the logger.
/// </summary>
/// <param name="type">The type.</param>
/// <returns>ILog.</returns>
public ILog GetLogger(Type type)
{
return GetLogger(type.Name);
}
}
}

View File

@ -1,194 +0,0 @@
using MediaBrowser.Model.Logging;
using ServiceStack.Logging;
using System;
namespace MediaBrowser.Server.Implementations.HttpServer
{
/// <summary>
/// Class ServerLogger
/// </summary>
public class ServerLogger : ILog
{
/// <summary>
/// The _logger
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Initializes a new instance of the <see cref="ServerLogger"/> class.
/// </summary>
/// <param name="logger">The logger.</param>
public ServerLogger(ILogger logger)
{
_logger = logger;
}
/// <summary>
/// Logs a Debug message and exception.
/// </summary>
/// <param name="message">The message.</param>
/// <param name="exception">The exception.</param>
public void Debug(object message, Exception exception)
{
_logger.ErrorException(GetMesssage(message), exception);
}
/// <summary>
/// Logs a Debug message.
/// </summary>
/// <param name="message">The message.</param>
public void Debug(object message)
{
// Way too verbose. Can always make this configurable if needed again.
//_logger.Debug(GetMesssage(message));
}
/// <summary>
/// Logs a Debug format message.
/// </summary>
/// <param name="format">The format.</param>
/// <param name="args">The args.</param>
public void DebugFormat(string format, params object[] args)
{
// Way too verbose. Can always make this configurable if needed again.
//_logger.Debug(format, args);
}
/// <summary>
/// Logs a Error message and exception.
/// </summary>
/// <param name="message">The message.</param>
/// <param name="exception">The exception.</param>
public void Error(object message, Exception exception)
{
_logger.ErrorException(GetMesssage(message), exception);
}
/// <summary>
/// Logs a Error message.
/// </summary>
/// <param name="message">The message.</param>
public void Error(object message)
{
_logger.Error(GetMesssage(message));
}
/// <summary>
/// Logs a Error format message.
/// </summary>
/// <param name="format">The format.</param>
/// <param name="args">The args.</param>
public void ErrorFormat(string format, params object[] args)
{
_logger.Error(format, args);
}
/// <summary>
/// Logs a Fatal message and exception.
/// </summary>
/// <param name="message">The message.</param>
/// <param name="exception">The exception.</param>
public void Fatal(object message, Exception exception)
{
_logger.FatalException(GetMesssage(message), exception);
}
/// <summary>
/// Logs a Fatal message.
/// </summary>
/// <param name="message">The message.</param>
public void Fatal(object message)
{
_logger.Fatal(GetMesssage(message));
}
/// <summary>
/// Logs a Error format message.
/// </summary>
/// <param name="format">The format.</param>
/// <param name="args">The args.</param>
public void FatalFormat(string format, params object[] args)
{
_logger.Fatal(format, args);
}
/// <summary>
/// Logs an Info message and exception.
/// </summary>
/// <param name="message">The message.</param>
/// <param name="exception">The exception.</param>
public void Info(object message, Exception exception)
{
_logger.ErrorException(GetMesssage(message), exception);
}
/// <summary>
/// Logs an Info message and exception.
/// </summary>
/// <param name="message">The message.</param>
public void Info(object message)
{
_logger.Info(GetMesssage(message));
}
/// <summary>
/// Logs an Info format message.
/// </summary>
/// <param name="format">The format.</param>
/// <param name="args">The args.</param>
public void InfoFormat(string format, params object[] args)
{
_logger.Info(format, args);
}
/// <summary>
/// Gets or sets a value indicating whether this instance is debug enabled.
/// </summary>
/// <value><c>true</c> if this instance is debug enabled; otherwise, <c>false</c>.</value>
public bool IsDebugEnabled
{
get { return true; }
}
/// <summary>
/// Logs a Warning message and exception.
/// </summary>
/// <param name="message">The message.</param>
/// <param name="exception">The exception.</param>
public void Warn(object message, Exception exception)
{
_logger.ErrorException(GetMesssage(message), exception);
}
/// <summary>
/// Logs a Warning message.
/// </summary>
/// <param name="message">The message.</param>
public void Warn(object message)
{
// Hide StringMapTypeDeserializer messages
// _logger.Warn(GetMesssage(message));
}
/// <summary>
/// Logs a Warning format message.
/// </summary>
/// <param name="format">The format.</param>
/// <param name="args">The args.</param>
public void WarnFormat(string format, params object[] args)
{
// Hide StringMapTypeDeserializer messages
// _logger.Warn(format, args);
}
/// <summary>
/// Gets the messsage.
/// </summary>
/// <param name="o">The o.</param>
/// <returns>System.String.</returns>
private string GetMesssage(object o)
{
return o == null ? string.Empty : o.ToString();
}
}
}

View File

@ -1,28 +0,0 @@
using MediaBrowser.Model.Logging;
using SocketHttpListener.Net;
using System;
namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
{
public static class Extensions
{
public static string GetOperationName(this HttpListenerRequest request)
{
return request.Url.Segments[request.Url.Segments.Length - 1];
}
public static void CloseOutputStream(this HttpListenerResponse response, ILogger logger)
{
try
{
response.OutputStream.Flush();
response.OutputStream.Close();
response.Close();
}
catch (Exception ex)
{
logger.ErrorException("Error in HttpListenerResponseWrapper: " + ex.Message, ex);
}
}
}
}

View File

@ -2,11 +2,10 @@
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Net;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web;
using MediaBrowser.Model.Services; using MediaBrowser.Model.Services;
using ServiceStack;
namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
{ {
@ -128,7 +127,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
{ {
get get
{ {
return string.IsNullOrEmpty(request.Headers[HttpHeaders.Accept]) ? null : request.Headers[HttpHeaders.Accept]; return string.IsNullOrEmpty(request.Headers["Accept"]) ? null : request.Headers["Accept"];
} }
} }
@ -136,7 +135,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
{ {
get get
{ {
return string.IsNullOrEmpty(request.Headers[HttpHeaders.Authorization]) ? null : request.Headers[HttpHeaders.Authorization]; return string.IsNullOrEmpty(request.Headers["Authorization"]) ? null : request.Headers["Authorization"];
} }
} }
@ -152,7 +151,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
string msg = String.Format("A potentially dangerous Request.{0} value was " + string msg = String.Format("A potentially dangerous Request.{0} value was " +
"detected from the client ({1}={2}).", name, key, v); "detected from the client ({1}={2}).", name, key, v);
throw new HttpRequestValidationException(msg); throw new Exception(msg);
} }
static void ValidateNameValueCollection(string name, QueryParamCollection coll) static void ValidateNameValueCollection(string name, QueryParamCollection coll)
@ -278,9 +277,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
void AddRawKeyValue(StringBuilder key, StringBuilder value) void AddRawKeyValue(StringBuilder key, StringBuilder value)
{ {
string decodedKey = HttpUtility.UrlDecode(key.ToString(), ContentEncoding); string decodedKey = WebUtility.UrlDecode(key.ToString());
form.Add(decodedKey, form.Add(decodedKey,
HttpUtility.UrlDecode(value.ToString(), ContentEncoding)); WebUtility.UrlDecode(value.ToString()));
key.Length = 0; key.Length = 0;
value.Length = 0; value.Length = 0;

View File

@ -1,17 +1,14 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO; using System.IO;
using System.Text; using System.Text;
using Emby.Server.Implementations.HttpServer.SocketSharp; using Emby.Server.Implementations.HttpServer.SocketSharp;
using Funq; using Funq;
using MediaBrowser.Common.IO;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Services; using MediaBrowser.Model.Services;
using ServiceStack; using ServiceStack;
using ServiceStack.Host; using ServiceStack.Host;
using ServiceStack.Web;
using SocketHttpListener.Net; using SocketHttpListener.Net;
using IHttpFile = MediaBrowser.Model.Services.IHttpFile; using IHttpFile = MediaBrowser.Model.Services.IHttpFile;
using IHttpRequest = MediaBrowser.Model.Services.IHttpRequest; using IHttpRequest = MediaBrowser.Model.Services.IHttpRequest;
@ -25,12 +22,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
public Container Container { get; set; } public Container Container { get; set; }
private readonly HttpListenerRequest request; private readonly HttpListenerRequest request;
private readonly IHttpResponse response; private readonly IHttpResponse response;
private readonly IMemoryStreamProvider _memoryStreamProvider; private readonly IMemoryStreamFactory _memoryStreamProvider;
public WebSocketSharpRequest(HttpListenerContext httpContext, string operationName, RequestAttributes requestAttributes, ILogger logger, IMemoryStreamProvider memoryStreamProvider) public WebSocketSharpRequest(HttpListenerContext httpContext, string operationName, ILogger logger, IMemoryStreamFactory memoryStreamProvider)
{ {
this.OperationName = operationName; this.OperationName = operationName;
this.RequestAttributes = requestAttributes;
_memoryStreamProvider = memoryStreamProvider; _memoryStreamProvider = memoryStreamProvider;
this.request = httpContext.Request; this.request = httpContext.Request;
this.response = new WebSocketSharpResponse(logger, httpContext.Response, this); this.response = new WebSocketSharpResponse(logger, httpContext.Response, this);
@ -56,38 +52,10 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
get { return response; } get { return response; }
} }
public RequestAttributes RequestAttributes { get; set; }
public T TryResolve<T>()
{
if (typeof(T) == typeof(IHttpRequest))
throw new Exception("You don't need to use IHttpRequest.TryResolve<IHttpRequest> to resolve itself");
if (typeof(T) == typeof(IHttpResponse))
throw new Exception("Resolve IHttpResponse with 'Response' property instead of IHttpRequest.TryResolve<IHttpResponse>");
return Container == null
? HostContext.TryResolve<T>()
: Container.TryResolve<T>();
}
public string OperationName { get; set; } public string OperationName { get; set; }
public object Dto { get; set; } public object Dto { get; set; }
public string GetRawBody()
{
if (bufferedStream != null)
{
return bufferedStream.ToArray().FromUtf8Bytes();
}
using (var reader = new StreamReader(InputStream))
{
return reader.ReadToEnd();
}
}
public string RawUrl public string RawUrl
{ {
get { return request.RawUrl; } get { return request.RawUrl; }
@ -107,7 +75,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
{ {
get get
{ {
return String.IsNullOrEmpty(request.Headers[HttpHeaders.XForwardedFor]) ? null : request.Headers[HttpHeaders.XForwardedFor]; return String.IsNullOrEmpty(request.Headers["X-Forwarded-For"]) ? null : request.Headers["X-Forwarded-For"];
} }
} }
@ -115,7 +83,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
{ {
get get
{ {
return string.IsNullOrEmpty(request.Headers[HttpHeaders.XForwardedPort]) ? (int?)null : int.Parse(request.Headers[HttpHeaders.XForwardedPort]); return string.IsNullOrEmpty(request.Headers["X-Forwarded-Port"]) ? (int?)null : int.Parse(request.Headers["X-Forwarded-Port"]);
} }
} }
@ -123,7 +91,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
{ {
get get
{ {
return string.IsNullOrEmpty(request.Headers[HttpHeaders.XForwardedProtocol]) ? null : request.Headers[HttpHeaders.XForwardedProtocol]; return string.IsNullOrEmpty(request.Headers["X-Forwarded-Proto"]) ? null : request.Headers["X-Forwarded-Proto"];
} }
} }
@ -131,7 +99,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
{ {
get get
{ {
return String.IsNullOrEmpty(request.Headers[HttpHeaders.XRealIp]) ? null : request.Headers[HttpHeaders.XRealIp]; return String.IsNullOrEmpty(request.Headers["X-Real-IP"]) ? null : request.Headers["X-Real-IP"];
} }
} }
@ -143,7 +111,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
return remoteIp ?? return remoteIp ??
(remoteIp = (CheckBadChars(XForwardedFor)) ?? (remoteIp = (CheckBadChars(XForwardedFor)) ??
(NormalizeIp(CheckBadChars(XRealIp)) ?? (NormalizeIp(CheckBadChars(XRealIp)) ??
(request.RemoteEndPoint != null ? NormalizeIp(request.RemoteEndPoint.Address.ToString()) : null))); (request.RemoteEndPoint != null ? NormalizeIp(request.RemoteEndPoint.IpAddress.ToString()) : null)));
} }
} }
@ -262,7 +230,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
get get
{ {
return responseContentType return responseContentType
?? (responseContentType = this.GetResponseContentType()); ?? (responseContentType = GetResponseContentType(this));
} }
set set
{ {
@ -271,6 +239,98 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
} }
} }
private static string GetResponseContentType(IRequest httpReq)
{
var specifiedContentType = GetQueryStringContentType(httpReq);
if (!string.IsNullOrEmpty(specifiedContentType)) return specifiedContentType;
var acceptContentTypes = httpReq.AcceptTypes;
var defaultContentType = httpReq.ContentType;
if (httpReq.HasAnyOfContentTypes(MimeTypes.FormUrlEncoded, MimeTypes.MultiPartFormData))
{
defaultContentType = HostContext.Config.DefaultContentType;
}
var customContentTypes = ContentTypes.Instance.ContentTypeFormats.Values;
var preferredContentTypes = new string[] {};
var acceptsAnything = false;
var hasDefaultContentType = !string.IsNullOrEmpty(defaultContentType);
if (acceptContentTypes != null)
{
var hasPreferredContentTypes = new bool[preferredContentTypes.Length];
foreach (var acceptsType in acceptContentTypes)
{
var contentType = ContentFormat.GetRealContentType(acceptsType);
acceptsAnything = acceptsAnything || contentType == "*/*";
for (var i = 0; i < preferredContentTypes.Length; i++)
{
if (hasPreferredContentTypes[i]) continue;
var preferredContentType = preferredContentTypes[i];
hasPreferredContentTypes[i] = contentType.StartsWith(preferredContentType);
//Prefer Request.ContentType if it is also a preferredContentType
if (hasPreferredContentTypes[i] && preferredContentType == defaultContentType)
return preferredContentType;
}
}
for (var i = 0; i < preferredContentTypes.Length; i++)
{
if (hasPreferredContentTypes[i]) return preferredContentTypes[i];
}
if (acceptsAnything)
{
if (hasDefaultContentType)
return defaultContentType;
if (HostContext.Config.DefaultContentType != null)
return HostContext.Config.DefaultContentType;
}
foreach (var contentType in acceptContentTypes)
{
foreach (var customContentType in customContentTypes)
{
if (contentType.StartsWith(customContentType, StringComparison.OrdinalIgnoreCase))
return customContentType;
}
}
}
if (acceptContentTypes == null && httpReq.ContentType == MimeTypes.Soap11)
{
return MimeTypes.Soap11;
}
//We could also send a '406 Not Acceptable', but this is allowed also
return HostContext.Config.DefaultContentType;
}
private static string GetQueryStringContentType(IRequest httpReq)
{
var format = httpReq.QueryString["format"];
if (format == null)
{
const int formatMaxLength = 4;
var pi = httpReq.PathInfo;
if (pi == null || pi.Length <= formatMaxLength) return null;
if (pi[0] == '/') pi = pi.Substring(1);
format = pi.LeftPart('/');
if (format.Length > formatMaxLength) return null;
}
format = format.LeftPart('.').ToLower();
if (format.Contains("json")) return "application/json";
if (format.Contains("xml")) return MimeTypes.Xml;
string contentType;
ContentTypes.Instance.ContentTypeFormats.TryGetValue(format, out contentType);
return contentType;
}
public bool HasExplicitResponseContentType { get; private set; } public bool HasExplicitResponseContentType { get; private set; }
private string pathInfo; private string pathInfo;
@ -286,7 +346,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
if (pos != -1) if (pos != -1)
{ {
var path = request.RawUrl.Substring(0, pos); var path = request.RawUrl.Substring(0, pos);
this.pathInfo = HttpRequestExtensions.GetPathInfo( this.pathInfo = GetPathInfo(
path, path,
mode, mode,
mode ?? ""); mode ?? "");
@ -303,6 +363,55 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
} }
} }
private static string GetPathInfo(string fullPath, string mode, string appPath)
{
var pathInfo = ResolvePathInfoFromMappedPath(fullPath, mode);
if (!string.IsNullOrEmpty(pathInfo)) return pathInfo;
//Wildcard mode relies on this to work out the handlerPath
pathInfo = ResolvePathInfoFromMappedPath(fullPath, appPath);
if (!string.IsNullOrEmpty(pathInfo)) return pathInfo;
return fullPath;
}
private static string ResolvePathInfoFromMappedPath(string fullPath, string mappedPathRoot)
{
if (mappedPathRoot == null) return null;
var sbPathInfo = new StringBuilder();
var fullPathParts = fullPath.Split('/');
var mappedPathRootParts = mappedPathRoot.Split('/');
var fullPathIndexOffset = mappedPathRootParts.Length - 1;
var pathRootFound = false;
for (var fullPathIndex = 0; fullPathIndex < fullPathParts.Length; fullPathIndex++)
{
if (pathRootFound)
{
sbPathInfo.Append("/" + fullPathParts[fullPathIndex]);
}
else if (fullPathIndex - fullPathIndexOffset >= 0)
{
pathRootFound = true;
for (var mappedPathRootIndex = 0; mappedPathRootIndex < mappedPathRootParts.Length; mappedPathRootIndex++)
{
if (!string.Equals(fullPathParts[fullPathIndex - fullPathIndexOffset + mappedPathRootIndex], mappedPathRootParts[mappedPathRootIndex], StringComparison.OrdinalIgnoreCase))
{
pathRootFound = false;
break;
}
}
}
}
if (!pathRootFound) return null;
var path = sbPathInfo.ToString();
return path.Length > 1 ? path.TrimEnd('/') : "/";
}
private Dictionary<string, System.Net.Cookie> cookies; private Dictionary<string, System.Net.Cookie> cookies;
public IDictionary<string, System.Net.Cookie> Cookies public IDictionary<string, System.Net.Cookie> Cookies
{ {
@ -327,10 +436,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
get { return request.UserAgent; } get { return request.UserAgent; }
} }
private QueryParamCollection headers;
public QueryParamCollection Headers public QueryParamCollection Headers
{ {
get { return headers ?? (headers = ToQueryParams(request.Headers)); } get { return request.Headers; }
} }
private QueryParamCollection queryString; private QueryParamCollection queryString;
@ -345,18 +453,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
get { return formData ?? (formData = this.Form); } get { return formData ?? (formData = this.Form); }
} }
private QueryParamCollection ToQueryParams(NameValueCollection collection)
{
var result = new QueryParamCollection();
foreach (var key in collection.AllKeys)
{
result[key] = collection[key];
}
return result;
}
public bool IsLocal public bool IsLocal
{ {
get { return request.IsLocal; } get { return request.IsLocal; }
@ -416,21 +512,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
} }
} }
public bool UseBufferedStream
{
get { return bufferedStream != null; }
set
{
bufferedStream = value
? bufferedStream ?? _memoryStreamProvider.CreateNew(request.InputStream.ReadFully())
: null;
}
}
private MemoryStream bufferedStream;
public Stream InputStream public Stream InputStream
{ {
get { return bufferedStream ?? request.InputStream; } get { return request.InputStream; }
} }
public long ContentLength public long ContentLength
@ -466,7 +550,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
} }
} }
static Stream GetSubStream(Stream stream, IMemoryStreamProvider streamProvider) static Stream GetSubStream(Stream stream, IMemoryStreamFactory streamProvider)
{ {
if (stream is MemoryStream) if (stream is MemoryStream)
{ {
@ -507,4 +591,13 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
return pathInfo; return pathInfo;
} }
} }
public class HttpFile : IHttpFile
{
public string Name { get; set; }
public string FileName { get; set; }
public long ContentLength { get; set; }
public string ContentType { get; set; }
public Stream InputStream { get; set; }
}
} }

View File

@ -4,7 +4,7 @@ using Microsoft.IO;
namespace MediaBrowser.Server.Implementations.IO namespace MediaBrowser.Server.Implementations.IO
{ {
public class RecyclableMemoryStreamProvider : IMemoryStreamProvider public class RecyclableMemoryStreamProvider : IMemoryStreamFactory
{ {
readonly RecyclableMemoryStreamManager _manager = new RecyclableMemoryStreamManager(); readonly RecyclableMemoryStreamManager _manager = new RecyclableMemoryStreamManager();
@ -22,9 +22,15 @@ namespace MediaBrowser.Server.Implementations.IO
{ {
return _manager.GetStream("RecyclableMemoryStream", buffer, 0, buffer.Length); return _manager.GetStream("RecyclableMemoryStream", buffer, 0, buffer.Length);
} }
public bool TryGetBuffer(MemoryStream stream, out byte[] buffer)
{
buffer = stream.GetBuffer();
return true;
}
} }
public class MemoryStreamProvider : IMemoryStreamProvider public class MemoryStreamProvider : IMemoryStreamFactory
{ {
public MemoryStream CreateNew() public MemoryStream CreateNew()
{ {
@ -40,5 +46,11 @@ namespace MediaBrowser.Server.Implementations.IO
{ {
return new MemoryStream(buffer); return new MemoryStream(buffer);
} }
public bool TryGetBuffer(MemoryStream stream, out byte[] buffer)
{
buffer = stream.GetBuffer();
return true;
}
} }
} }

View File

@ -69,16 +69,12 @@
<HintPath>..\packages\Patterns.Logging.1.0.0.6\lib\portable-net45+win8\Patterns.Logging.dll</HintPath> <HintPath>..\packages\Patterns.Logging.1.0.0.6\lib\portable-net45+win8\Patterns.Logging.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="ServiceStack.Api.Swagger">
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Api.Swagger.dll</HintPath>
</Reference>
<Reference Include="SharpCompress, Version=0.10.3.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="SharpCompress, Version=0.10.3.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\ThirdParty\SharpCompress\SharpCompress.dll</HintPath> <HintPath>..\ThirdParty\SharpCompress\SharpCompress.dll</HintPath>
</Reference> </Reference>
<Reference Include="SocketHttpListener, Version=1.0.6154.22657, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="SocketHttpListener.Portable">
<HintPath>..\packages\SocketHttpListener.1.0.0.44\lib\net45\SocketHttpListener.dll</HintPath> <HintPath>..\ThirdParty\emby\SocketHttpListener.Portable.dll</HintPath>
<Private>True</Private>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
@ -88,7 +84,6 @@
<Reference Include="System.Net" /> <Reference Include="System.Net" />
<Reference Include="System.Runtime.Serialization" /> <Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Security" /> <Reference Include="System.Security" />
<Reference Include="System.Web" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="ServiceStack"> <Reference Include="ServiceStack">
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.dll</HintPath> <HintPath>..\ThirdParty\ServiceStack\ServiceStack.dll</HintPath>
@ -119,18 +114,9 @@
<Compile Include="HttpServer\ContainerAdapter.cs" /> <Compile Include="HttpServer\ContainerAdapter.cs" />
<Compile Include="HttpServer\HttpListenerHost.cs" /> <Compile Include="HttpServer\HttpListenerHost.cs" />
<Compile Include="HttpServer\HttpResultFactory.cs" /> <Compile Include="HttpServer\HttpResultFactory.cs" />
<Compile Include="HttpServer\LoggerUtils.cs" />
<Compile Include="HttpServer\RangeRequestWriter.cs" />
<Compile Include="HttpServer\ResponseFilter.cs" />
<Compile Include="HttpServer\ServerFactory.cs" /> <Compile Include="HttpServer\ServerFactory.cs" />
<Compile Include="HttpServer\ServerLogFactory.cs" />
<Compile Include="HttpServer\ServerLogger.cs" />
<Compile Include="HttpServer\SocketSharp\SharpWebSocket.cs" />
<Compile Include="HttpServer\SocketSharp\Extensions.cs" />
<Compile Include="HttpServer\SocketSharp\RequestMono.cs" /> <Compile Include="HttpServer\SocketSharp\RequestMono.cs" />
<Compile Include="HttpServer\SocketSharp\WebSocketSharpListener.cs" />
<Compile Include="HttpServer\SocketSharp\WebSocketSharpRequest.cs" /> <Compile Include="HttpServer\SocketSharp\WebSocketSharpRequest.cs" />
<Compile Include="HttpServer\SocketSharp\WebSocketSharpResponse.cs" />
<Compile Include="IO\LibraryMonitor.cs" /> <Compile Include="IO\LibraryMonitor.cs" />
<Compile Include="IO\MemoryStreamProvider.cs" /> <Compile Include="IO\MemoryStreamProvider.cs" />
<Compile Include="LiveTv\TunerHosts\SatIp\ChannelScan.cs" /> <Compile Include="LiveTv\TunerHosts\SatIp\ChannelScan.cs" />

View File

@ -55,7 +55,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// </summary> /// </summary>
/// <returns>Stream.</returns> /// <returns>Stream.</returns>
/// <exception cref="System.ArgumentNullException">reader</exception> /// <exception cref="System.ArgumentNullException">reader</exception>
public static Stream GetMemoryStream(this IDataReader reader, int ordinal, IMemoryStreamProvider streamProvider) public static Stream GetMemoryStream(this IDataReader reader, int ordinal, IMemoryStreamFactory streamProvider)
{ {
if (reader == null) if (reader == null)
{ {
@ -134,7 +134,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// </summary> /// </summary>
/// <returns>System.Byte[][].</returns> /// <returns>System.Byte[][].</returns>
/// <exception cref="System.ArgumentNullException">obj</exception> /// <exception cref="System.ArgumentNullException">obj</exception>
public static byte[] SerializeToBytes(this IJsonSerializer json, object obj, IMemoryStreamProvider streamProvider) public static byte[] SerializeToBytes(this IJsonSerializer json, object obj, IMemoryStreamFactory streamProvider)
{ {
if (obj == null) if (obj == null)
{ {

View File

@ -20,9 +20,9 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// </summary> /// </summary>
public class SqliteDisplayPreferencesRepository : BaseSqliteRepository, IDisplayPreferencesRepository public class SqliteDisplayPreferencesRepository : BaseSqliteRepository, IDisplayPreferencesRepository
{ {
private readonly IMemoryStreamProvider _memoryStreamProvider; private readonly IMemoryStreamFactory _memoryStreamProvider;
public SqliteDisplayPreferencesRepository(ILogManager logManager, IJsonSerializer jsonSerializer, IApplicationPaths appPaths, IDbConnector dbConnector, IMemoryStreamProvider memoryStreamProvider) public SqliteDisplayPreferencesRepository(ILogManager logManager, IJsonSerializer jsonSerializer, IApplicationPaths appPaths, IDbConnector dbConnector, IMemoryStreamFactory memoryStreamProvider)
: base(logManager, dbConnector) : base(logManager, dbConnector)
{ {
_jsonSerializer = jsonSerializer; _jsonSerializer = jsonSerializer;

View File

@ -99,12 +99,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
private IDbCommand _updateInheritedTagsCommand; private IDbCommand _updateInheritedTagsCommand;
public const int LatestSchemaVersion = 109; public const int LatestSchemaVersion = 109;
private readonly IMemoryStreamProvider _memoryStreamProvider; private readonly IMemoryStreamFactory _memoryStreamProvider;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="SqliteItemRepository"/> class. /// Initializes a new instance of the <see cref="SqliteItemRepository"/> class.
/// </summary> /// </summary>
public SqliteItemRepository(IServerConfigurationManager config, IJsonSerializer jsonSerializer, ILogManager logManager, IDbConnector connector, IMemoryStreamProvider memoryStreamProvider) public SqliteItemRepository(IServerConfigurationManager config, IJsonSerializer jsonSerializer, ILogManager logManager, IDbConnector connector, IMemoryStreamFactory memoryStreamProvider)
: base(logManager, connector) : base(logManager, connector)
{ {
if (config == null) if (config == null)

View File

@ -20,9 +20,9 @@ namespace MediaBrowser.Server.Implementations.Persistence
public class SqliteUserRepository : BaseSqliteRepository, IUserRepository public class SqliteUserRepository : BaseSqliteRepository, IUserRepository
{ {
private readonly IJsonSerializer _jsonSerializer; private readonly IJsonSerializer _jsonSerializer;
private readonly IMemoryStreamProvider _memoryStreamProvider; private readonly IMemoryStreamFactory _memoryStreamProvider;
public SqliteUserRepository(ILogManager logManager, IServerApplicationPaths appPaths, IJsonSerializer jsonSerializer, IDbConnector dbConnector, IMemoryStreamProvider memoryStreamProvider) : base(logManager, dbConnector) public SqliteUserRepository(ILogManager logManager, IServerApplicationPaths appPaths, IJsonSerializer jsonSerializer, IDbConnector dbConnector, IMemoryStreamFactory memoryStreamProvider) : base(logManager, dbConnector)
{ {
_jsonSerializer = jsonSerializer; _jsonSerializer = jsonSerializer;
_memoryStreamProvider = memoryStreamProvider; _memoryStreamProvider = memoryStreamProvider;

View File

@ -5,6 +5,5 @@
<package id="MediaBrowser.Naming" version="1.0.0.59" targetFramework="net46" /> <package id="MediaBrowser.Naming" version="1.0.0.59" targetFramework="net46" />
<package id="Microsoft.IO.RecyclableMemoryStream" version="1.1.0.0" targetFramework="net46" /> <package id="Microsoft.IO.RecyclableMemoryStream" version="1.1.0.0" targetFramework="net46" />
<package id="Patterns.Logging" version="1.0.0.6" targetFramework="net46" /> <package id="Patterns.Logging" version="1.0.0.6" targetFramework="net46" />
<package id="SocketHttpListener" version="1.0.0.44" targetFramework="net46" />
<package id="UniversalDetector" version="1.0.1" targetFramework="net46" /> <package id="UniversalDetector" version="1.0.1" targetFramework="net46" />
</packages> </packages>

View File

@ -126,7 +126,7 @@ using MediaBrowser.Model.Reflection;
using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Services; using MediaBrowser.Model.Services;
using MediaBrowser.Model.Social; using MediaBrowser.Model.Social;
using MediaBrowser.Model.TextEncoding; using MediaBrowser.Model.Text;
using MediaBrowser.Model.Xml; using MediaBrowser.Model.Xml;
using MediaBrowser.Server.Implementations.Archiving; using MediaBrowser.Server.Implementations.Archiving;
using MediaBrowser.Server.Implementations.Serialization; using MediaBrowser.Server.Implementations.Serialization;
@ -252,6 +252,8 @@ namespace MediaBrowser.Server.Startup.Common
/// <value>The zip client.</value> /// <value>The zip client.</value>
protected IZipClient ZipClient { get; private set; } protected IZipClient ZipClient { get; private set; }
protected IAuthService AuthService { get; private set; }
private readonly StartupOptions _startupOptions; private readonly StartupOptions _startupOptions;
private readonly string _releaseAssetFilename; private readonly string _releaseAssetFilename;
@ -410,7 +412,7 @@ namespace MediaBrowser.Server.Startup.Common
LogManager.RemoveConsoleOutput(); LogManager.RemoveConsoleOutput();
} }
protected override IMemoryStreamProvider CreateMemoryStreamProvider() protected override IMemoryStreamFactory CreateMemoryStreamProvider()
{ {
if (Environment.OSVersion.Platform == PlatformID.Win32NT) if (Environment.OSVersion.Platform == PlatformID.Win32NT)
{ {
@ -555,7 +557,7 @@ namespace MediaBrowser.Server.Startup.Common
StringExtensions.LocalizationManager = LocalizationManager; StringExtensions.LocalizationManager = LocalizationManager;
RegisterSingleInstance(LocalizationManager); RegisterSingleInstance(LocalizationManager);
IEncoding textEncoding = new TextEncoding(FileSystemManager); ITextEncoding textEncoding = new TextEncoding(FileSystemManager);
RegisterSingleInstance(textEncoding); RegisterSingleInstance(textEncoding);
Utilities.EncodingHelper = textEncoding; Utilities.EncodingHelper = textEncoding;
RegisterSingleInstance<IBlurayExaminer>(() => new BdInfoExaminer(FileSystemManager, textEncoding)); RegisterSingleInstance<IBlurayExaminer>(() => new BdInfoExaminer(FileSystemManager, textEncoding));
@ -601,7 +603,7 @@ namespace MediaBrowser.Server.Startup.Common
RegisterSingleInstance<ISearchEngine>(() => new SearchEngine(LogManager, LibraryManager, UserManager)); RegisterSingleInstance<ISearchEngine>(() => new SearchEngine(LogManager, LibraryManager, UserManager));
HttpServer = ServerFactory.CreateServer(this, LogManager, ServerConfigurationManager, NetworkManager, MemoryStreamProvider, "Emby", "web/index.html"); HttpServer = ServerFactory.CreateServer(this, LogManager, ServerConfigurationManager, NetworkManager, MemoryStreamProvider, "Emby", "web/index.html", textEncoding, SocketFactory, CryptographyProvider);
HttpServer.GlobalResponse = LocalizationManager.GetLocalizedString("StartupEmbyServerIsLoading"); HttpServer.GlobalResponse = LocalizationManager.GetLocalizedString("StartupEmbyServerIsLoading");
RegisterSingleInstance(HttpServer, false); RegisterSingleInstance(HttpServer, false);
progress.Report(10); progress.Report(10);
@ -702,7 +704,9 @@ namespace MediaBrowser.Server.Startup.Common
var authContext = new AuthorizationContext(AuthenticationRepository, ConnectManager); var authContext = new AuthorizationContext(AuthenticationRepository, ConnectManager);
RegisterSingleInstance<IAuthorizationContext>(authContext); RegisterSingleInstance<IAuthorizationContext>(authContext);
RegisterSingleInstance<ISessionContext>(new SessionContext(UserManager, authContext, SessionManager)); RegisterSingleInstance<ISessionContext>(new SessionContext(UserManager, authContext, SessionManager));
RegisterSingleInstance<IAuthService>(new AuthService(UserManager, authContext, ServerConfigurationManager, ConnectManager, SessionManager, DeviceManager));
AuthService = new AuthService(UserManager, authContext, ServerConfigurationManager, ConnectManager, SessionManager, DeviceManager);
RegisterSingleInstance<IAuthService>(AuthService);
SubtitleEncoder = new SubtitleEncoder(LibraryManager, LogManager.GetLogger("SubtitleEncoder"), ApplicationPaths, FileSystemManager, MediaEncoder, JsonSerializer, HttpClient, MediaSourceManager, MemoryStreamProvider, ProcessFactory, textEncoding); SubtitleEncoder = new SubtitleEncoder(LibraryManager, LogManager.GetLogger("SubtitleEncoder"), ApplicationPaths, FileSystemManager, MediaEncoder, JsonSerializer, HttpClient, MediaSourceManager, MemoryStreamProvider, ProcessFactory, textEncoding);
RegisterSingleInstance(SubtitleEncoder); RegisterSingleInstance(SubtitleEncoder);
@ -900,6 +904,7 @@ namespace MediaBrowser.Server.Startup.Common
BaseStreamingService.AppHost = this; BaseStreamingService.AppHost = this;
BaseStreamingService.HttpClient = HttpClient; BaseStreamingService.HttpClient = HttpClient;
Utilities.CryptographyProvider = CryptographyProvider; Utilities.CryptographyProvider = CryptographyProvider;
AuthenticatedAttribute.AuthService = AuthService;
} }
/// <summary> /// <summary>
@ -1291,7 +1296,7 @@ namespace MediaBrowser.Server.Startup.Common
try try
{ {
// Return the first matched address, if found, or the first known local address // Return the first matched address, if found, or the first known local address
var address = (await GetLocalIpAddressesInternal().ConfigureAwait(false)).FirstOrDefault(i => !IPAddress.IsLoopback(i)); var address = (await GetLocalIpAddresses().ConfigureAwait(false)).FirstOrDefault(i => !i.Equals(IpAddressInfo.Loopback) && !i.Equals(IpAddressInfo.IPv6Loopback));
if (address != null) if (address != null)
{ {
@ -1308,19 +1313,14 @@ namespace MediaBrowser.Server.Startup.Common
return null; return null;
} }
public string GetLocalApiUrl(IPAddress ipAddress) public string GetLocalApiUrl(IpAddressInfo ipAddress)
{ {
return GetLocalApiUrl(ipAddress.ToString(), ipAddress.AddressFamily == AddressFamily.InterNetworkV6); if (ipAddress.AddressFamily == IpAddressFamily.InterNetworkV6)
}
public string GetLocalApiUrl(string ipAddress, bool isIpv6)
{
if (isIpv6)
{ {
return GetLocalApiUrl("[" + ipAddress + "]"); return GetLocalApiUrl("[" + ipAddress.Address + "]");
} }
return GetLocalApiUrl(ipAddress); return GetLocalApiUrl(ipAddress.Address);
} }
public string GetLocalApiUrl(string host) public string GetLocalApiUrl(string host)
@ -1332,23 +1332,8 @@ namespace MediaBrowser.Server.Startup.Common
public async Task<List<IpAddressInfo>> GetLocalIpAddresses() public async Task<List<IpAddressInfo>> GetLocalIpAddresses()
{ {
var list = await GetLocalIpAddressesInternal().ConfigureAwait(false); var addresses = NetworkManager.GetLocalIpAddresses().ToList();
var list = new List<IpAddressInfo>();
return list.Select(i => new IpAddressInfo
{
Address = i.ToString(),
IsIpv6 = i.AddressFamily == AddressFamily.InterNetworkV6
}).ToList();
}
private async Task<List<IPAddress>> GetLocalIpAddressesInternal()
{
// Need to do this until Common will compile with this method
var nativeNetworkManager = (BaseNetworkManager)NetworkManager;
var addresses = nativeNetworkManager.GetLocalIpAddresses().ToList();
var list = new List<IPAddress>();
foreach (var address in addresses) foreach (var address in addresses)
{ {
@ -1364,9 +1349,10 @@ namespace MediaBrowser.Server.Startup.Common
private readonly ConcurrentDictionary<string, bool> _validAddressResults = new ConcurrentDictionary<string, bool>(StringComparer.OrdinalIgnoreCase); private readonly ConcurrentDictionary<string, bool> _validAddressResults = new ConcurrentDictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
private DateTime _lastAddressCacheClear; private DateTime _lastAddressCacheClear;
private async Task<bool> IsIpAddressValidAsync(IPAddress address) private async Task<bool> IsIpAddressValidAsync(IpAddressInfo address)
{ {
if (IPAddress.IsLoopback(address)) if (address.Equals(IpAddressInfo.Loopback) ||
address.Equals(IpAddressInfo.IPv6Loopback))
{ {
return true; return true;
} }

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata> <metadata>
<id>MediaBrowser.Common</id> <id>MediaBrowser.Common</id>
<version>3.0.684</version> <version>3.0.688</version>
<title>Emby.Common</title> <title>Emby.Common</title>
<authors>Emby Team</authors> <authors>Emby Team</authors>
<owners>ebr,Luke,scottisafool</owners> <owners>ebr,Luke,scottisafool</owners>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata> <metadata>
<id>MediaBrowser.Server.Core</id> <id>MediaBrowser.Server.Core</id>
<version>3.0.684</version> <version>3.0.688</version>
<title>Emby.Server.Core</title> <title>Emby.Server.Core</title>
<authors>Emby Team</authors> <authors>Emby Team</authors>
<owners>ebr,Luke,scottisafool</owners> <owners>ebr,Luke,scottisafool</owners>
@ -12,7 +12,7 @@
<description>Contains core components required to build plugins for Emby Server.</description> <description>Contains core components required to build plugins for Emby Server.</description>
<copyright>Copyright © Emby 2013</copyright> <copyright>Copyright © Emby 2013</copyright>
<dependencies> <dependencies>
<dependency id="MediaBrowser.Common" version="3.0.684" /> <dependency id="MediaBrowser.Common" version="3.0.688" />
</dependencies> </dependencies>
</metadata> </metadata>
<files> <files>

View File

@ -24,7 +24,7 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Common.Net; using MediaBrowser.Common.Net;
using MediaBrowser.Model.Cryptography; using MediaBrowser.Model.Cryptography;
using MediaBrowser.Model.TextEncoding; using MediaBrowser.Model.Text;
namespace OpenSubtitlesHandler namespace OpenSubtitlesHandler
{ {
@ -33,9 +33,9 @@ namespace OpenSubtitlesHandler
/// </summary> /// </summary>
public sealed class Utilities public sealed class Utilities
{ {
public static ICryptographyProvider CryptographyProvider { get; set; } public static ICryptoProvider CryptographyProvider { get; set; }
public static IHttpClient HttpClient { get; set; } public static IHttpClient HttpClient { get; set; }
public static IEncoding EncodingHelper { get; set; } public static ITextEncoding EncodingHelper { get; set; }
private const string XML_RPC_SERVER = "https://api.opensubtitles.org/xml-rpc"; private const string XML_RPC_SERVER = "https://api.opensubtitles.org/xml-rpc";
@ -124,13 +124,13 @@ namespace OpenSubtitlesHandler
data.Add((byte)r); data.Add((byte)r);
} }
var bytes = data.ToArray(); var bytes = data.ToArray();
return EncodingHelper.GetASCIIString(bytes, 0, bytes.Length); return EncodingHelper.GetASCIIEncoding().GetString(bytes, 0, bytes.Length);
} }
} }
public static byte[] GetASCIIBytes(string text) public static byte[] GetASCIIBytes(string text)
{ {
return EncodingHelper.GetASCIIBytes(text); return EncodingHelper.GetASCIIEncoding().GetBytes(text);
} }
/// <summary> /// <summary>