update portable projects

This commit is contained in:
Luke Pulverenti
2016-11-08 13:44:23 -05:00
parent 05a5ce58a9
commit a8b340cbb2
84 changed files with 1055 additions and 921 deletions

View File

@@ -64,7 +64,7 @@ namespace Emby.Server.Implementations.Connect
validIpAddress = await GetIpAddress(ipLookupUrl).ConfigureAwait(false);
// Try to find the ipv4 address, if present
if (!validIpAddress.IsIpv6)
if (validIpAddress.AddressFamily != IpAddressFamily.InterNetworkV6)
{
break;
}
@@ -77,9 +77,9 @@ namespace Emby.Server.Implementations.Connect
_logger.ErrorException("Error getting connection info", ex);
}
}
// 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)
{
@@ -88,7 +88,7 @@ namespace Emby.Server.Implementations.Connect
var newAddress = await GetIpAddress(ipLookupUrl, true).ConfigureAwait(false);
// Try to find the ipv4 address, if present
if (!newAddress.IsIpv6)
if (newAddress.AddressFamily != IpAddressFamily.InterNetworkV6)
{
validIpAddress = newAddress;
break;

View File

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

View File

@@ -68,11 +68,18 @@
<Compile Include="FileOrganization\OrganizerScheduledTask.cs" />
<Compile Include="FileOrganization\TvFolderOrganizer.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\IHttpListener.cs" />
<Compile Include="HttpServer\Security\AuthorizationContext.cs" />
<Compile Include="HttpServer\Security\AuthService.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\SwaggerService.cs" />
<Compile Include="Images\BaseDynamicImageProvider.cs" />
@@ -254,6 +261,9 @@
<Project>{442b5058-dcaf-4263-bb6a-f21e31120a1b}</Project>
<Name>MediaBrowser.Providers</Name>
</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">
<HintPath>..\packages\UniversalDetector.1.0.1\lib\portable-net45+sl4+wp71+win8+wpa81\UniversalDetector.dll</HintPath>
<Private>True</Private>

View File

@@ -0,0 +1,43 @@
using MediaBrowser.Model.Logging;
using System;
using System.Globalization;
using SocketHttpListener.Net;
namespace Emby.Server.Implementations.HttpServer
{
public static class LoggerUtils
{
/// <summary>
/// Logs the request.
/// </summary>
/// <param name="logger">The logger.</param>
/// <param name="request">The request.</param>
public static void LogRequest(ILogger logger, HttpListenerRequest request)
{
var url = request.Url.ToString();
logger.Info("{0} {1}. UserAgent: {2}", request.IsWebSocketRequest ? "WS" : "HTTP " + request.HttpMethod, url, request.UserAgent ?? string.Empty);
}
public static void LogRequest(ILogger logger, string url, string method, string userAgent)
{
logger.Info("{0} {1}. UserAgent: {2}", "HTTP " + method, url, userAgent ?? string.Empty);
}
/// <summary>
/// Logs the response.
/// </summary>
/// <param name="logger">The logger.</param>
/// <param name="statusCode">The status code.</param>
/// <param name="url">The URL.</param>
/// <param name="endPoint">The end point.</param>
/// <param name="duration">The duration.</param>
public static void LogResponse(ILogger logger, int statusCode, string url, string endPoint, TimeSpan duration)
{
var durationMs = duration.TotalMilliseconds;
var logSuffix = durationMs >= 1000 && durationMs < 60000 ? "ms (slow)" : "ms";
logger.Info("HTTP Response {0} to {1}. Time: {2}{3}. {4}", statusCode, endPoint, Convert.ToInt32(durationMs).ToString(CultureInfo.InvariantCulture), logSuffix, url);
}
}
}

View File

@@ -0,0 +1,224 @@
using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Model.Services;
namespace Emby.Server.Implementations.HttpServer
{
public class RangeRequestWriter : IAsyncStreamWriter, IHttpResult
{
/// <summary>
/// Gets or sets the source stream.
/// </summary>
/// <value>The source stream.</value>
private Stream SourceStream { get; set; }
private string RangeHeader { get; set; }
private bool IsHeadRequest { get; set; }
private long RangeStart { get; set; }
private long RangeEnd { get; set; }
private long RangeLength { get; set; }
private long TotalContentLength { get; set; }
public Action OnComplete { get; set; }
private readonly ILogger _logger;
private const int BufferSize = 81920;
/// <summary>
/// The _options
/// </summary>
private readonly Dictionary<string, string> _options = new Dictionary<string, string>();
/// <summary>
/// The us culture
/// </summary>
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
public List<Cookie> Cookies { get; private set; }
/// <summary>
/// Additional HTTP Headers
/// </summary>
/// <value>The headers.</value>
public IDictionary<string, string> Headers
{
get { return _options; }
}
/// <summary>
/// Initializes a new instance of the <see cref="StreamWriter" /> class.
/// </summary>
/// <param name="rangeHeader">The range header.</param>
/// <param name="source">The source.</param>
/// <param name="contentType">Type of the content.</param>
/// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param>
public RangeRequestWriter(string rangeHeader, Stream source, string contentType, bool isHeadRequest, ILogger logger)
{
if (string.IsNullOrEmpty(contentType))
{
throw new ArgumentNullException("contentType");
}
RangeHeader = rangeHeader;
SourceStream = source;
IsHeadRequest = isHeadRequest;
this._logger = logger;
ContentType = contentType;
Headers["Content-Type"] = contentType;
Headers["Accept-Ranges"] = "bytes";
StatusCode = HttpStatusCode.PartialContent;
Cookies = new List<Cookie>();
SetRangeValues();
}
/// <summary>
/// Sets the range values.
/// </summary>
private void SetRangeValues()
{
var requestedRange = RequestedRanges[0];
TotalContentLength = SourceStream.Length;
// If the requested range is "0-", we can optimize by just doing a stream copy
if (!requestedRange.Value.HasValue)
{
RangeEnd = TotalContentLength - 1;
}
else
{
RangeEnd = requestedRange.Value.Value;
}
RangeStart = requestedRange.Key;
RangeLength = 1 + RangeEnd - RangeStart;
// Content-Length is the length of what we're serving, not the original content
Headers["Content-Length"] = RangeLength.ToString(UsCulture);
Headers["Content-Range"] = string.Format("bytes {0}-{1}/{2}", RangeStart, RangeEnd, TotalContentLength);
if (RangeStart > 0)
{
SourceStream.Position = RangeStart;
}
}
/// <summary>
/// The _requested ranges
/// </summary>
private List<KeyValuePair<long, long?>> _requestedRanges;
/// <summary>
/// Gets the requested ranges.
/// </summary>
/// <value>The requested ranges.</value>
protected List<KeyValuePair<long, long?>> RequestedRanges
{
get
{
if (_requestedRanges == null)
{
_requestedRanges = new List<KeyValuePair<long, long?>>();
// Example: bytes=0-,32-63
var ranges = RangeHeader.Split('=')[1].Split(',');
foreach (var range in ranges)
{
var vals = range.Split('-');
long start = 0;
long? end = null;
if (!string.IsNullOrEmpty(vals[0]))
{
start = long.Parse(vals[0], UsCulture);
}
if (!string.IsNullOrEmpty(vals[1]))
{
end = long.Parse(vals[1], UsCulture);
}
_requestedRanges.Add(new KeyValuePair<long, long?>(start, end));
}
}
return _requestedRanges;
}
}
public async Task WriteToAsync(Stream responseStream, CancellationToken cancellationToken)
{
try
{
// Headers only
if (IsHeadRequest)
{
return;
}
using (var source = SourceStream)
{
// If the requested range is "0-", we can optimize by just doing a stream copy
if (RangeEnd >= TotalContentLength - 1)
{
await source.CopyToAsync(responseStream, BufferSize).ConfigureAwait(false);
}
else
{
await CopyToInternalAsync(source, responseStream, RangeLength).ConfigureAwait(false);
}
}
}
finally
{
if (OnComplete != null)
{
OnComplete();
}
}
}
private async Task CopyToInternalAsync(Stream source, Stream destination, long copyLength)
{
var array = new byte[BufferSize];
int count;
while ((count = await source.ReadAsync(array, 0, array.Length).ConfigureAwait(false)) != 0)
{
var bytesToCopy = Math.Min(count, copyLength);
await destination.WriteAsync(array, 0, Convert.ToInt32(bytesToCopy)).ConfigureAwait(false);
copyLength -= bytesToCopy;
if (copyLength <= 0)
{
break;
}
}
}
public string ContentType { get; set; }
public IRequest RequestContext { get; set; }
public object Response { get; set; }
public int Status { get; set; }
public HttpStatusCode StatusCode
{
get { return (HttpStatusCode)Status; }
set { Status = (int)value; }
}
public string StatusDescription { get; set; }
}
}

View File

@@ -0,0 +1,129 @@
using MediaBrowser.Model.Logging;
using System;
using System.Globalization;
using System.Text;
using Emby.Server.Implementations.HttpServer.SocketSharp;
using MediaBrowser.Model.Services;
namespace Emby.Server.Implementations.HttpServer
{
public class ResponseFilter
{
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
private readonly ILogger _logger;
public ResponseFilter(ILogger logger)
{
_logger = logger;
}
/// <summary>
/// Filters the response.
/// </summary>
/// <param name="req">The req.</param>
/// <param name="res">The res.</param>
/// <param name="dto">The dto.</param>
public void FilterResponse(IRequest req, IResponse res, object dto)
{
// Try to prevent compatibility view
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;
if (exception != null)
{
_logger.ErrorException("Error processing request for {0}", exception, req.RawUrl);
if (!string.IsNullOrEmpty(exception.Message))
{
var error = exception.Message.Replace(Environment.NewLine, " ");
error = RemoveControlCharacters(error);
res.AddHeader("X-Application-Error-Code", error);
}
}
var vary = "Accept-Encoding";
var hasHeaders = dto as IHasHeaders;
var sharpResponse = res as WebSocketSharpResponse;
if (hasHeaders != null)
{
if (!hasHeaders.Headers.ContainsKey("Server"))
{
hasHeaders.Headers["Server"] = "Mono-HTTPAPI/1.1, UPnP/1.0 DLNADOC/1.50";
//hasHeaders.Headers["Server"] = "Mono-HTTPAPI/1.1";
}
// Content length has to be explicitly set on on HttpListenerResponse or it won't be happy
string contentLength;
if (hasHeaders.Headers.TryGetValue("Content-Length", out contentLength) && !string.IsNullOrEmpty(contentLength))
{
var length = long.Parse(contentLength, UsCulture);
if (length > 0)
{
res.SetContentLength(length);
//var listenerResponse = res.OriginalResponse as HttpListenerResponse;
//if (listenerResponse != null)
//{
// // 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
// listenerResponse.SendChunked = false;
// return;
//}
if (sharpResponse != null)
{
sharpResponse.SendChunked = false;
}
}
}
string hasHeadersVary;
if (hasHeaders.Headers.TryGetValue("Vary", out hasHeadersVary))
{
vary = hasHeadersVary;
}
hasHeaders.Headers["Vary"] = vary;
}
//res.KeepAlive = false;
// Per Google PageSpeed
// This instructs the proxies to cache two versions of the resource: one compressed, and one uncompressed.
// The correct version of the resource is delivered based on the client request header.
// This is a good choice for applications that are singly homed and depend on public proxies for user locality.
res.AddHeader("Vary", vary);
}
/// <summary>
/// Removes the control characters.
/// </summary>
/// <param name="inString">The in string.</param>
/// <returns>System.String.</returns>
public static string RemoveControlCharacters(string inString)
{
if (inString == null) return null;
var newString = new StringBuilder();
foreach (var ch in inString)
{
if (!char.IsControl(ch))
{
newString.Append(ch);
}
}
return newString.ToString();
}
}
}

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

@@ -0,0 +1,166 @@
using MediaBrowser.Common.Events;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Logging;
using System;
using System.Threading;
using System.Threading.Tasks;
using WebSocketState = MediaBrowser.Model.Net.WebSocketState;
namespace Emby.Server.Implementations.HttpServer.SocketSharp
{
public class SharpWebSocket : IWebSocket
{
/// <summary>
/// The logger
/// </summary>
private readonly ILogger _logger;
public event EventHandler<EventArgs> Closed;
/// <summary>
/// Gets or sets the web socket.
/// </summary>
/// <value>The web socket.</value>
private SocketHttpListener.WebSocket WebSocket { get; set; }
private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
public SharpWebSocket(SocketHttpListener.WebSocket socket, ILogger logger)
{
if (socket == null)
{
throw new ArgumentNullException("socket");
}
if (logger == null)
{
throw new ArgumentNullException("logger");
}
_logger = logger;
WebSocket = socket;
socket.OnMessage += socket_OnMessage;
socket.OnClose += socket_OnClose;
socket.OnError += socket_OnError;
WebSocket.ConnectAsServer();
}
void socket_OnError(object sender, SocketHttpListener.ErrorEventArgs e)
{
_logger.Error("Error in SharpWebSocket: {0}", e.Message ?? string.Empty);
//EventHelper.FireEventIfNotNull(Closed, this, EventArgs.Empty, _logger);
}
void socket_OnClose(object sender, SocketHttpListener.CloseEventArgs e)
{
EventHelper.FireEventIfNotNull(Closed, this, EventArgs.Empty, _logger);
}
void socket_OnMessage(object sender, SocketHttpListener.MessageEventArgs e)
{
//if (!string.IsNullOrWhiteSpace(e.Data))
//{
// if (OnReceive != null)
// {
// OnReceive(e.Data);
// }
// return;
//}
if (OnReceiveBytes != null)
{
OnReceiveBytes(e.RawData);
}
}
/// <summary>
/// Gets or sets the state.
/// </summary>
/// <value>The state.</value>
public WebSocketState State
{
get
{
WebSocketState commonState;
if (!Enum.TryParse(WebSocket.ReadyState.ToString(), true, out commonState))
{
_logger.Warn("Unrecognized WebSocketState: {0}", WebSocket.ReadyState.ToString());
}
return commonState;
}
}
/// <summary>
/// Sends the async.
/// </summary>
/// <param name="bytes">The bytes.</param>
/// <param name="endOfMessage">if set to <c>true</c> [end of message].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public Task SendAsync(byte[] bytes, bool endOfMessage, CancellationToken cancellationToken)
{
var completionSource = new TaskCompletionSource<bool>();
WebSocket.SendAsync(bytes, res => completionSource.TrySetResult(true));
return completionSource.Task;
}
/// <summary>
/// Sends the asynchronous.
/// </summary>
/// <param name="text">The text.</param>
/// <param name="endOfMessage">if set to <c>true</c> [end of message].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public Task SendAsync(string text, bool endOfMessage, CancellationToken cancellationToken)
{
var completionSource = new TaskCompletionSource<bool>();
WebSocket.SendAsync(text, res => completionSource.TrySetResult(true));
return completionSource.Task;
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
Dispose(true);
}
/// <summary>
/// Releases unmanaged and - optionally - managed resources.
/// </summary>
/// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
protected virtual void Dispose(bool dispose)
{
if (dispose)
{
WebSocket.OnMessage -= socket_OnMessage;
WebSocket.OnClose -= socket_OnClose;
WebSocket.OnError -= socket_OnError;
_cancellationTokenSource.Cancel();
WebSocket.Close();
}
}
/// <summary>
/// Gets or sets the receive action.
/// </summary>
/// <value>The receive action.</value>
public Action<byte[]> OnReceiveBytes { get; set; }
/// <summary>
/// Gets or sets the on receive.
/// </summary>
/// <value>The on receive.</value>
public Action<string> OnReceive { get; set; }
}
}

View File

@@ -0,0 +1,203 @@
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Logging;
using SocketHttpListener.Net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Emby.Server.Implementations.Logging;
using MediaBrowser.Common.Net;
using MediaBrowser.Model.Cryptography;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Net;
using MediaBrowser.Model.Services;
using MediaBrowser.Model.Text;
using SocketHttpListener.Primitives;
namespace Emby.Server.Implementations.HttpServer.SocketSharp
{
public class WebSocketSharpListener : IHttpListener
{
private HttpListener _listener;
private readonly ILogger _logger;
private readonly ICertificate _certificate;
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;
public WebSocketSharpListener(ILogger logger, ICertificate certificate, IMemoryStreamFactory memoryStreamProvider, ITextEncoding textEncoding, INetworkManager networkManager, ISocketFactory socketFactory, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, Func<HttpListenerContext, IHttpRequest> httpRequestFactory)
{
_logger = logger;
_certificate = certificate;
_memoryStreamProvider = memoryStreamProvider;
_textEncoding = textEncoding;
_networkManager = networkManager;
_socketFactory = socketFactory;
_cryptoProvider = cryptoProvider;
_streamFactory = streamFactory;
_httpRequestFactory = httpRequestFactory;
}
public Action<Exception, IRequest> ErrorHandler { get; set; }
public Func<IHttpRequest, Uri, Task> RequestHandler { get; set; }
public Action<WebSocketConnectingEventArgs> WebSocketConnecting { get; set; }
public Action<WebSocketConnectEventArgs> WebSocketConnected { get; set; }
public void Start(IEnumerable<string> urlPrefixes)
{
if (_listener == null)
_listener = new HttpListener(new PatternsLogger(_logger), _cryptoProvider, _streamFactory, _socketFactory, _networkManager, _textEncoding, _memoryStreamProvider);
if (_certificate != null)
{
_listener.LoadCert(_certificate);
}
foreach (var prefix in urlPrefixes)
{
_logger.Info("Adding HttpListener prefix " + prefix);
_listener.Prefixes.Add(prefix);
}
_listener.OnContext = ProcessContext;
_listener.Start();
}
private void ProcessContext(HttpListenerContext context)
{
Task.Factory.StartNew(() => InitTask(context));
}
private Task InitTask(HttpListenerContext context)
{
IHttpRequest httpReq = null;
var request = context.Request;
try
{
if (request.IsWebSocketRequest)
{
LoggerUtils.LogRequest(_logger, request);
ProcessWebSocketRequest(context);
return Task.FromResult(true);
}
httpReq = GetRequest(context);
}
catch (Exception ex)
{
_logger.ErrorException("Error processing request", ex);
httpReq = httpReq ?? GetRequest(context);
ErrorHandler(ex, httpReq);
return Task.FromResult(true);
}
return RequestHandler(httpReq, request.Url);
}
private void ProcessWebSocketRequest(HttpListenerContext ctx)
{
try
{
var endpoint = ctx.Request.RemoteEndPoint.ToString();
var url = ctx.Request.RawUrl;
var connectingArgs = new WebSocketConnectingEventArgs
{
Url = url,
QueryString = ctx.Request.QueryString,
Endpoint = endpoint
};
if (WebSocketConnecting != null)
{
WebSocketConnecting(connectingArgs);
}
if (connectingArgs.AllowConnection)
{
_logger.Debug("Web socket connection allowed");
var webSocketContext = ctx.AcceptWebSocket(null);
if (WebSocketConnected != null)
{
WebSocketConnected(new WebSocketConnectEventArgs
{
Url = url,
QueryString = ctx.Request.QueryString,
WebSocket = new SharpWebSocket(webSocketContext.WebSocket, _logger),
Endpoint = endpoint
});
}
}
else
{
_logger.Warn("Web socket connection not allowed");
ctx.Response.StatusCode = 401;
ctx.Response.Close();
}
}
catch (Exception ex)
{
_logger.ErrorException("AcceptWebSocketAsync error", ex);
ctx.Response.StatusCode = 500;
ctx.Response.Close();
}
}
private IHttpRequest GetRequest(HttpListenerContext httpContext)
{
return _httpRequestFactory(httpContext);
}
public void Stop()
{
if (_listener != null)
{
foreach (var prefix in _listener.Prefixes.ToList())
{
_listener.Prefixes.Remove(prefix);
}
_listener.Close();
}
}
public void Dispose()
{
Dispose(true);
}
private bool _disposed;
private readonly object _disposeLock = new object();
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;
lock (_disposeLock)
{
if (_disposed) return;
if (disposing)
{
Stop();
}
//release unmanaged resources here...
_disposed = true;
}
}
}
}

View File

@@ -0,0 +1,204 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using MediaBrowser.Model.Logging;
using HttpListenerResponse = SocketHttpListener.Net.HttpListenerResponse;
using IHttpResponse = MediaBrowser.Model.Services.IHttpResponse;
using IRequest = MediaBrowser.Model.Services.IRequest;
namespace Emby.Server.Implementations.HttpServer.SocketSharp
{
public class WebSocketSharpResponse : IHttpResponse
{
private readonly ILogger _logger;
private readonly HttpListenerResponse _response;
public WebSocketSharpResponse(ILogger logger, HttpListenerResponse response, IRequest request)
{
_logger = logger;
this._response = response;
Items = new Dictionary<string, object>();
Request = request;
}
public IRequest Request { get; private set; }
public bool UseBufferedStream { get; set; }
public Dictionary<string, object> Items { get; private set; }
public object OriginalResponse
{
get { return _response; }
}
public int StatusCode
{
get { return this._response.StatusCode; }
set { this._response.StatusCode = value; }
}
public string StatusDescription
{
get { return this._response.StatusDescription; }
set { this._response.StatusDescription = value; }
}
public string ContentType
{
get { return _response.ContentType; }
set { _response.ContentType = value; }
}
//public ICookies Cookies { get; set; }
public void AddHeader(string name, string value)
{
if (string.Equals(name, "Content-Type", StringComparison.OrdinalIgnoreCase))
{
ContentType = value;
return;
}
_response.AddHeader(name, value);
}
public string GetHeader(string name)
{
return _response.Headers[name];
}
public void Redirect(string url)
{
_response.Redirect(url);
}
public Stream OutputStream
{
get { return _response.OutputStream; }
}
public object Dto { get; set; }
public void Write(string text)
{
var bOutput = System.Text.Encoding.UTF8.GetBytes(text);
_response.ContentLength64 = bOutput.Length;
var outputStream = _response.OutputStream;
outputStream.Write(bOutput, 0, bOutput.Length);
Close();
}
public void Close()
{
if (!this.IsClosed)
{
this.IsClosed = true;
try
{
CloseOutputStream(this._response);
}
catch (Exception ex)
{
_logger.ErrorException("Error closing HttpListener output stream", ex);
}
}
}
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()
{
Close();
}
public void Flush()
{
_response.OutputStream.Flush();
}
public bool IsClosed
{
get;
private set;
}
public void SetContentLength(long contentLength)
{
//you can happily set the Content-Length header in Asp.Net
//but HttpListener will complain if you do - you have to set ContentLength64 on the response.
//workaround: HttpListener throws "The parameter is incorrect" exceptions when we try to set the Content-Length header
_response.ContentLength64 = contentLength;
}
public void SetCookie(Cookie cookie)
{
var cookieStr = AsHeaderValue(cookie);
_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
{
get { return _response.SendChunked; }
set { _response.SendChunked = value; }
}
public bool KeepAlive { get; set; }
public void ClearCookies()
{
}
}
}

View File

@@ -70,10 +70,10 @@ namespace Emby.Server.Implementations.Library
private readonly Func<IConnectManager> _connectFactory;
private readonly IServerApplicationHost _appHost;
private readonly IFileSystem _fileSystem;
private readonly ICryptographyProvider _cryptographyProvider;
private readonly ICryptoProvider _cryptographyProvider;
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;
UserRepository = userRepository;
@@ -334,7 +334,7 @@ namespace Emby.Server.Implementations.Library
/// <returns>System.String.</returns>
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>

View File

@@ -15,7 +15,7 @@ namespace Emby.Server.Implementations.Security
{
private readonly IApplicationPaths _appPaths;
private readonly IFileSystem _fileSystem;
private readonly ICryptographyProvider _cryptographyProvider;
private readonly ICryptoProvider _cryptographyProvider;
public string RegKey
{
@@ -43,7 +43,7 @@ namespace Emby.Server.Implementations.Security
private readonly object _fileLock = new object();
private string _regKey;
public MBLicenseFile(IApplicationPaths appPaths, IFileSystem fileSystem, ICryptographyProvider cryptographyProvider)
public MBLicenseFile(IApplicationPaths appPaths, IFileSystem fileSystem, ICryptoProvider cryptographyProvider)
{
_appPaths = appPaths;
_fileSystem = fileSystem;
@@ -59,7 +59,7 @@ namespace Emby.Server.Implementations.Security
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;
SetUpdateRecord(key, value);
@@ -68,7 +68,7 @@ namespace Emby.Server.Implementations.Security
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;
_updateRecords.TryRemove(key, out val);
@@ -79,7 +79,7 @@ namespace Emby.Server.Implementations.Security
public DateTime LastChecked(string featureId)
{
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
return last < DateTime.UtcNow ? last : DateTime.MinValue;

View File

@@ -64,7 +64,7 @@ namespace Emby.Server.Implementations.Security
private readonly ILogger _logger;
private readonly IApplicationPaths _appPaths;
private readonly IFileSystem _fileSystem;
private readonly ICryptographyProvider _cryptographyProvider;
private readonly ICryptoProvider _cryptographyProvider;
private 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.
/// </summary>
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)
{

View File

@@ -15,7 +15,7 @@ using System.Threading.Tasks;
using MediaBrowser.Common.IO;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Services;
using MediaBrowser.Model.TextEncoding;
using MediaBrowser.Model.Text;
namespace Emby.Server.Implementations.ServerManager
{
@@ -75,8 +75,8 @@ namespace Emby.Server.Implementations.ServerManager
private readonly List<IWebSocketListener> _webSocketListeners = new List<IWebSocketListener>();
private bool _disposed;
private readonly IMemoryStreamProvider _memoryStreamProvider;
private readonly IEncoding _textEncoding;
private readonly IMemoryStreamFactory _memoryStreamProvider;
private readonly ITextEncoding _textEncoding;
/// <summary>
/// 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="configurationManager">The configuration manager.</param>
/// <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)
{

View File

@@ -12,7 +12,7 @@ using System.Threading.Tasks;
using MediaBrowser.Common.IO;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Services;
using MediaBrowser.Model.TextEncoding;
using MediaBrowser.Model.Text;
using UniversalDetector;
namespace Emby.Server.Implementations.ServerManager
@@ -77,8 +77,8 @@ namespace Emby.Server.Implementations.ServerManager
/// </summary>
/// <value>The query string.</value>
public QueryParamCollection QueryString { get; set; }
private readonly IMemoryStreamProvider _memoryStreamProvider;
private readonly IEncoding _textEncoding;
private readonly IMemoryStreamFactory _memoryStreamProvider;
private readonly ITextEncoding _textEncoding;
/// <summary>
/// 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="logger">The logger.</param>
/// <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)
{
@@ -145,7 +145,7 @@ namespace Emby.Server.Implementations.ServerManager
}
else
{
OnReceiveInternal(_textEncoding.GetASCIIString(bytes, 0, bytes.Length));
OnReceiveInternal(_textEncoding.GetASCIIEncoding().GetString(bytes, 0, bytes.Length));
}
}
private string DetectCharset(byte[] bytes)

View File

@@ -29,12 +29,12 @@ namespace Emby.Server.Implementations.Sync
private readonly ILogger _logger;
private readonly IFileSystem _fileSystem;
private readonly IConfigurationManager _config;
private readonly ICryptographyProvider _cryptographyProvider;
private readonly ICryptoProvider _cryptographyProvider;
public const string PathSeparatorString = "/";
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;
_syncManager = syncManager;
@@ -370,7 +370,7 @@ namespace Emby.Server.Implementations.Sync
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)

View File

@@ -23,9 +23,9 @@ namespace Emby.Server.Implementations.Sync
private readonly ILogger _logger;
private readonly IFileSystem _fileSystem;
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;
_appHost = appHost;

View File

@@ -20,9 +20,9 @@ namespace Emby.Server.Implementations.Sync
private readonly IFileSystem _fileSystem;
private readonly IServerApplicationHost _appHost;
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;
_logger = logger;

View File

@@ -51,7 +51,7 @@ namespace Emby.Server.Implementations.Sync
private readonly Func<IMediaSourceManager> _mediaSourceManager;
private readonly IJsonSerializer _json;
private readonly ITaskManager _taskManager;
private readonly IMemoryStreamProvider _memoryStreamProvider;
private readonly IMemoryStreamFactory _memoryStreamProvider;
private ISyncProvider[] _providers = { };
@@ -61,7 +61,7 @@ namespace Emby.Server.Implementations.Sync
public event EventHandler<GenericEventArgs<SyncJobItem>> SyncJobItemUpdated;
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;
_repo = repo;

View File

@@ -26,9 +26,9 @@ namespace Emby.Server.Implementations.Sync
private readonly IFileSystem _fileSystem;
private readonly IApplicationPaths _appPaths;
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;
_json = json;

View File

@@ -119,9 +119,9 @@ namespace Emby.Server.Implementations.Updates
/// <value>The application host.</value>
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)
{
@@ -606,7 +606,7 @@ namespace Emby.Server.Implementations.Updates
{
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)
{
throw new Exception(string.Format("Download validation failed for {0}. Probably corrupted during transfer.", package.name));