From 9fff4b060e06569ca77636643901aa42767e318d Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 28 Jul 2019 23:53:19 +0200 Subject: Replace custom code with Asp.Net Core code --- .../SocketSharp/RequestMono.cs | 647 --------------------- .../SocketSharp/WebSocketSharpRequest.cs | 230 +++----- .../SocketSharp/WebSocketSharpResponse.cs | 98 ---- 3 files changed, 93 insertions(+), 882 deletions(-) delete mode 100644 Emby.Server.Implementations/SocketSharp/RequestMono.cs delete mode 100644 Emby.Server.Implementations/SocketSharp/WebSocketSharpResponse.cs (limited to 'Emby.Server.Implementations/SocketSharp') diff --git a/Emby.Server.Implementations/SocketSharp/RequestMono.cs b/Emby.Server.Implementations/SocketSharp/RequestMono.cs deleted file mode 100644 index ec637186f..000000000 --- a/Emby.Server.Implementations/SocketSharp/RequestMono.cs +++ /dev/null @@ -1,647 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Net; -using System.Text; -using System.Threading.Tasks; -using MediaBrowser.Model.Services; -using Microsoft.Extensions.Primitives; -using Microsoft.Net.Http.Headers; - -namespace Emby.Server.Implementations.SocketSharp -{ - public partial class WebSocketSharpRequest : IHttpRequest - { - internal static string GetParameter(ReadOnlySpan header, string attr) - { - int ap = header.IndexOf(attr.AsSpan(), StringComparison.Ordinal); - if (ap == -1) - { - return null; - } - - ap += attr.Length; - if (ap >= header.Length) - { - return null; - } - - char ending = header[ap]; - if (ending != '"') - { - ending = ' '; - } - - var slice = header.Slice(ap + 1); - int end = slice.IndexOf(ending); - if (end == -1) - { - return ending == '"' ? null : header.Slice(ap).ToString(); - } - - return slice.Slice(0, end - ap - 1).ToString(); - } - - private async Task LoadMultiPart(WebROCollection form) - { - string boundary = GetParameter(ContentType.AsSpan(), "; boundary="); - if (boundary == null) - { - return; - } - - using (var requestStream = InputStream) - { - // DB: 30/01/11 - Hack to get around non-seekable stream and received HTTP request - // Not ending with \r\n? - var ms = new MemoryStream(32 * 1024); - await requestStream.CopyToAsync(ms).ConfigureAwait(false); - - var input = ms; - ms.WriteByte((byte)'\r'); - ms.WriteByte((byte)'\n'); - - input.Position = 0; - - // Uncomment to debug - // var content = new StreamReader(ms).ReadToEnd(); - // Console.WriteLine(boundary + "::" + content); - // input.Position = 0; - - var multi_part = new HttpMultipart(input, boundary, ContentEncoding); - - HttpMultipart.Element e; - while ((e = multi_part.ReadNextElement()) != null) - { - if (e.Filename == null) - { - byte[] copy = new byte[e.Length]; - - input.Position = e.Start; - await input.ReadAsync(copy, 0, (int)e.Length).ConfigureAwait(false); - - form.Add(e.Name, (e.Encoding ?? ContentEncoding).GetString(copy, 0, copy.Length)); - } - else - { - // We use a substream, as in 2.x we will support large uploads streamed to disk, - files[e.Name] = new HttpPostedFile(e.Filename, e.ContentType, input, e.Start, e.Length); - } - } - } - } - - public async Task GetFormData() - { - var form = new WebROCollection(); - files = new Dictionary(); - - if (IsContentType("multipart/form-data")) - { - await LoadMultiPart(form).ConfigureAwait(false); - } - else if (IsContentType("application/x-www-form-urlencoded")) - { - await LoadWwwForm(form).ConfigureAwait(false); - } - - if (validate_form && !checked_form) - { - checked_form = true; - ValidateNameValueCollection("Form", form); - } - - return form; - } - - public string Accept => StringValues.IsNullOrEmpty(request.Headers[HeaderNames.Accept]) ? null : request.Headers[HeaderNames.Accept].ToString(); - - public string Authorization => StringValues.IsNullOrEmpty(request.Headers[HeaderNames.Authorization]) ? null : request.Headers[HeaderNames.Authorization].ToString(); - - protected bool validate_form { get; set; } - protected bool checked_form { get; set; } - - private static void ThrowValidationException(string name, string key, string value) - { - string v = "\"" + value + "\""; - if (v.Length > 20) - { - v = v.Substring(0, 16) + "...\""; - } - - string msg = string.Format( - CultureInfo.InvariantCulture, - "A potentially dangerous Request.{0} value was detected from the client ({1}={2}).", - name, - key, - v); - - throw new Exception(msg); - } - - private static void ValidateNameValueCollection(string name, QueryParamCollection coll) - { - if (coll == null) - { - return; - } - - foreach (var pair in coll) - { - var key = pair.Name; - var val = pair.Value; - if (val != null && val.Length > 0 && IsInvalidString(val)) - { - ThrowValidationException(name, key, val); - } - } - } - - internal static bool IsInvalidString(string val) - => IsInvalidString(val, out var validationFailureIndex); - - internal static bool IsInvalidString(string val, out int validationFailureIndex) - { - validationFailureIndex = 0; - - int len = val.Length; - if (len < 2) - { - return false; - } - - char current = val[0]; - for (int idx = 1; idx < len; idx++) - { - char next = val[idx]; - - // See http://secunia.com/advisories/14325 - if (current == '<' || current == '\xff1c') - { - if (next == '!' || next < ' ' - || (next >= 'a' && next <= 'z') - || (next >= 'A' && next <= 'Z')) - { - validationFailureIndex = idx - 1; - return true; - } - } - else if (current == '&' && next == '#') - { - validationFailureIndex = idx - 1; - return true; - } - - current = next; - } - - return false; - } - - private bool IsContentType(string ct) - { - if (ContentType == null) - { - return false; - } - - return ContentType.StartsWith(ct, StringComparison.OrdinalIgnoreCase); - } - - private async Task LoadWwwForm(WebROCollection form) - { - using (var input = InputStream) - { - using (var ms = new MemoryStream()) - { - await input.CopyToAsync(ms).ConfigureAwait(false); - ms.Position = 0; - - using (var s = new StreamReader(ms, ContentEncoding)) - { - var key = new StringBuilder(); - var value = new StringBuilder(); - int c; - - while ((c = s.Read()) != -1) - { - if (c == '=') - { - value.Length = 0; - while ((c = s.Read()) != -1) - { - if (c == '&') - { - AddRawKeyValue(form, key, value); - break; - } - else - { - value.Append((char)c); - } - } - - if (c == -1) - { - AddRawKeyValue(form, key, value); - return; - } - } - else if (c == '&') - { - AddRawKeyValue(form, key, value); - } - else - { - key.Append((char)c); - } - } - - if (c == -1) - { - AddRawKeyValue(form, key, value); - } - } - } - } - } - - private static void AddRawKeyValue(WebROCollection form, StringBuilder key, StringBuilder value) - { - form.Add(WebUtility.UrlDecode(key.ToString()), WebUtility.UrlDecode(value.ToString())); - - key.Length = 0; - value.Length = 0; - } - - private Dictionary files; - - private class WebROCollection : QueryParamCollection - { - public override string ToString() - { - var result = new StringBuilder(); - foreach (var pair in this) - { - if (result.Length > 0) - { - result.Append('&'); - } - - var key = pair.Name; - if (key != null && key.Length > 0) - { - result.Append(key); - result.Append('='); - } - - result.Append(pair.Value); - } - - return result.ToString(); - } - } - private class HttpMultipart - { - - public class Element - { - public string ContentType { get; set; } - - public string Name { get; set; } - - public string Filename { get; set; } - - public Encoding Encoding { get; set; } - - public long Start { get; set; } - - public long Length { get; set; } - - public override string ToString() - { - return "ContentType " + ContentType + ", Name " + Name + ", Filename " + Filename + ", Start " + - Start.ToString(CultureInfo.CurrentCulture) + ", Length " + Length.ToString(CultureInfo.CurrentCulture); - } - } - - private const byte LF = (byte)'\n'; - - private const byte CR = (byte)'\r'; - - private Stream data; - - private string boundary; - - private byte[] boundaryBytes; - - private byte[] buffer; - - private bool atEof; - - private Encoding encoding; - - private StringBuilder sb; - - // See RFC 2046 - // In the case of multipart entities, in which one or more different - // sets of data are combined in a single body, a "multipart" media type - // field must appear in the entity's header. The body must then contain - // one or more body parts, each preceded by a boundary delimiter line, - // and the last one followed by a closing boundary delimiter line. - // After its boundary delimiter line, each body part then consists of a - // header area, a blank line, and a body area. Thus a body part is - // similar to an RFC 822 message in syntax, but different in meaning. - - public HttpMultipart(Stream data, string b, Encoding encoding) - { - this.data = data; - boundary = b; - boundaryBytes = encoding.GetBytes(b); - buffer = new byte[boundaryBytes.Length + 2]; // CRLF or '--' - this.encoding = encoding; - sb = new StringBuilder(); - } - - public Element ReadNextElement() - { - if (atEof || ReadBoundary()) - { - return null; - } - - var elem = new Element(); - ReadOnlySpan header; - while ((header = ReadLine().AsSpan()).Length != 0) - { - if (header.StartsWith("Content-Disposition:".AsSpan(), StringComparison.OrdinalIgnoreCase)) - { - elem.Name = GetContentDispositionAttribute(header, "name"); - elem.Filename = StripPath(GetContentDispositionAttributeWithEncoding(header, "filename")); - } - else if (header.StartsWith("Content-Type:".AsSpan(), StringComparison.OrdinalIgnoreCase)) - { - elem.ContentType = header.Slice("Content-Type:".Length).Trim().ToString(); - elem.Encoding = GetEncoding(elem.ContentType); - } - } - - long start = data.Position; - elem.Start = start; - long pos = MoveToNextBoundary(); - if (pos == -1) - { - return null; - } - - elem.Length = pos - start; - return elem; - } - - private string ReadLine() - { - // CRLF or LF are ok as line endings. - bool got_cr = false; - int b = 0; - sb.Length = 0; - while (true) - { - b = data.ReadByte(); - if (b == -1) - { - return null; - } - - if (b == LF) - { - break; - } - - got_cr = b == CR; - sb.Append((char)b); - } - - if (got_cr) - { - sb.Length--; - } - - return sb.ToString(); - } - - private static string GetContentDispositionAttribute(ReadOnlySpan l, string name) - { - int idx = l.IndexOf((name + "=\"").AsSpan(), StringComparison.Ordinal); - if (idx < 0) - { - return null; - } - - int begin = idx + name.Length + "=\"".Length; - int end = l.Slice(begin).IndexOf('"'); - if (end < 0) - { - return null; - } - - if (begin == end) - { - return string.Empty; - } - - return l.Slice(begin, end - begin).ToString(); - } - - private string GetContentDispositionAttributeWithEncoding(ReadOnlySpan l, string name) - { - int idx = l.IndexOf((name + "=\"").AsSpan(), StringComparison.Ordinal); - if (idx < 0) - { - return null; - } - - int begin = idx + name.Length + "=\"".Length; - int end = l.Slice(begin).IndexOf('"'); - if (end < 0) - { - return null; - } - - if (begin == end) - { - return string.Empty; - } - - ReadOnlySpan temp = l.Slice(begin, end - begin); - byte[] source = new byte[temp.Length]; - for (int i = temp.Length - 1; i >= 0; i--) - { - source[i] = (byte)temp[i]; - } - - return encoding.GetString(source, 0, source.Length); - } - - private bool ReadBoundary() - { - try - { - string line; - do - { - line = ReadLine(); - } - while (line.Length == 0); - - if (line[0] != '-' || line[1] != '-') - { - return false; - } - - if (!line.EndsWith(boundary, StringComparison.Ordinal)) - { - return true; - } - } - catch - { - - } - - return false; - } - - private static bool CompareBytes(byte[] orig, byte[] other) - { - for (int i = orig.Length - 1; i >= 0; i--) - { - if (orig[i] != other[i]) - { - return false; - } - } - - return true; - } - - private long MoveToNextBoundary() - { - long retval = 0; - bool got_cr = false; - - int state = 0; - int c = data.ReadByte(); - while (true) - { - if (c == -1) - { - return -1; - } - - if (state == 0 && c == LF) - { - retval = data.Position - 1; - if (got_cr) - { - retval--; - } - - state = 1; - c = data.ReadByte(); - } - else if (state == 0) - { - got_cr = c == CR; - c = data.ReadByte(); - } - else if (state == 1 && c == '-') - { - c = data.ReadByte(); - if (c == -1) - { - return -1; - } - - if (c != '-') - { - state = 0; - got_cr = false; - continue; // no ReadByte() here - } - - int nread = data.Read(buffer, 0, buffer.Length); - int bl = buffer.Length; - if (nread != bl) - { - return -1; - } - - if (!CompareBytes(boundaryBytes, buffer)) - { - state = 0; - data.Position = retval + 2; - if (got_cr) - { - data.Position++; - got_cr = false; - } - - c = data.ReadByte(); - continue; - } - - if (buffer[bl - 2] == '-' && buffer[bl - 1] == '-') - { - atEof = true; - } - else if (buffer[bl - 2] != CR || buffer[bl - 1] != LF) - { - state = 0; - data.Position = retval + 2; - if (got_cr) - { - data.Position++; - got_cr = false; - } - - c = data.ReadByte(); - continue; - } - - data.Position = retval + 2; - if (got_cr) - { - data.Position++; - } - - break; - } - else - { - // state == 1 - state = 0; // no ReadByte() here - } - } - - return retval; - } - - private static string StripPath(string path) - { - if (path == null || path.Length == 0) - { - return path; - } - - if (path.IndexOf(":\\", StringComparison.Ordinal) != 1 - && !path.StartsWith("\\\\", StringComparison.Ordinal)) - { - return path; - } - - return path.Substring(path.LastIndexOf('\\') + 1); - } - } - } -} diff --git a/Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs b/Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs index 7a630bf10..43f71a69c 100644 --- a/Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs +++ b/Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs @@ -6,7 +6,6 @@ using System.Net; using System.Linq; using System.Text; using MediaBrowser.Common.Net; -using MediaBrowser.Model.Services; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Extensions; using Microsoft.Extensions.Logging; @@ -14,44 +13,49 @@ using Microsoft.Extensions.Primitives; using Microsoft.Net.Http.Headers; using IHttpFile = MediaBrowser.Model.Services.IHttpFile; using IHttpRequest = MediaBrowser.Model.Services.IHttpRequest; -using IResponse = MediaBrowser.Model.Services.IResponse; namespace Emby.Server.Implementations.SocketSharp { public partial class WebSocketSharpRequest : IHttpRequest { - private readonly HttpRequest request; + public const string FormUrlEncoded = "application/x-www-form-urlencoded"; + public const string MultiPartFormData = "multipart/form-data"; + public const string Soap11 = "text/xml; charset=utf-8"; + + private string _remoteIp; + private Dictionary _items; + private string _responseContentType; + private IHttpFile[] _httpFiles; + private Dictionary _files; - public WebSocketSharpRequest(HttpRequest httpContext, HttpResponse response, string operationName, ILogger logger) + public WebSocketSharpRequest(HttpRequest httpRequest, HttpResponse httpResponse, string operationName, ILogger logger) { this.OperationName = operationName; - this.request = httpContext; - this.Response = new WebSocketSharpResponse(logger, response); + this.Request = httpRequest; + this.Response = httpResponse; } - public HttpRequest HttpRequest => request; + public string Accept => StringValues.IsNullOrEmpty(Request.Headers[HeaderNames.Accept]) ? null : Request.Headers[HeaderNames.Accept].ToString(); - public IResponse Response { get; } + public string Authorization => StringValues.IsNullOrEmpty(Request.Headers[HeaderNames.Authorization]) ? null : Request.Headers[HeaderNames.Authorization].ToString(); - public string OperationName { get; set; } + public HttpRequest Request { get; } - public object Dto { get; set; } + public HttpResponse Response { get; } - public string RawUrl => request.GetEncodedPathAndQuery(); + public string OperationName { get; set; } - public string AbsoluteUri => request.GetDisplayUrl().TrimEnd('/'); - // Header[name] returns "" when undefined + public string RawUrl => Request.GetEncodedPathAndQuery(); - private string GetHeader(string name) => request.Headers[name].ToString(); + public string AbsoluteUri => Request.GetDisplayUrl().TrimEnd('/'); - private string remoteIp; public string RemoteIp { get { - if (remoteIp != null) + if (_remoteIp != null) { - return remoteIp; + return _remoteIp; } IPAddress ip; @@ -62,14 +66,84 @@ namespace Emby.Server.Implementations.SocketSharp { if (!IPAddress.TryParse(GetHeader(CustomHeaderNames.XRealIP), out ip)) { - ip = request.HttpContext.Connection.RemoteIpAddress; + ip = Request.HttpContext.Connection.RemoteIpAddress; } } - return remoteIp = NormalizeIp(ip).ToString(); + return _remoteIp = NormalizeIp(ip).ToString(); } } + public string[] AcceptTypes => Request.Headers.GetCommaSeparatedValues(HeaderNames.Accept); + + public Dictionary Items => _items ?? (_items = new Dictionary()); + + public string ResponseContentType + { + get => + _responseContentType + ?? (_responseContentType = GetResponseContentType(Request)); + set => this._responseContentType = value; + } + + public string PathInfo => Request.Path.Value; + + public string UserAgent => Request.Headers[HeaderNames.UserAgent]; + + public IHeaderDictionary Headers => Request.Headers; + + public IQueryCollection QueryString => Request.Query; + + public bool IsLocal => Request.HttpContext.Connection.LocalIpAddress.Equals(Request.HttpContext.Connection.RemoteIpAddress); + + + public string HttpMethod => Request.Method; + + public string Verb => HttpMethod; + + public string ContentType => Request.ContentType; + + public Uri UrlReferrer => Request.GetTypedHeaders().Referer; + + public Stream InputStream => Request.Body; + + public long ContentLength => Request.ContentLength ?? 0; + + + public IHttpFile[] Files + { + get + { + if (_httpFiles != null) + { + return _httpFiles; + } + + if (_files == null) + { + return _httpFiles = Array.Empty(); + } + + var values = _files.Values; + _httpFiles = new IHttpFile[values.Count]; + for (int i = 0; i < values.Count; i++) + { + var reqFile = values.ElementAt(i); + _httpFiles[i] = new HttpFile + { + ContentType = reqFile.ContentType, + ContentLength = reqFile.ContentLength, + FileName = reqFile.FileName, + InputStream = reqFile.InputStream, + }; + } + + return _httpFiles; + } + } + + private string GetHeader(string name) => Request.Headers[name].ToString(); + private static IPAddress NormalizeIp(IPAddress ip) { if (ip.IsIPv4MappedToIPv6) @@ -80,22 +154,6 @@ namespace Emby.Server.Implementations.SocketSharp return ip; } - public string[] AcceptTypes => request.Headers.GetCommaSeparatedValues(HeaderNames.Accept); - - private Dictionary items; - public Dictionary Items => items ?? (items = new Dictionary()); - - private string responseContentType; - public string ResponseContentType - { - get => - responseContentType - ?? (responseContentType = GetResponseContentType(HttpRequest)); - set => this.responseContentType = value; - } - - public const string FormUrlEncoded = "application/x-www-form-urlencoded"; - public const string MultiPartFormData = "multipart/form-data"; public static string GetResponseContentType(HttpRequest httpReq) { var specifiedContentType = GetQueryStringContentType(httpReq); @@ -152,8 +210,6 @@ namespace Emby.Server.Implementations.SocketSharp return serverDefaultContentType; } - public const string Soap11 = "text/xml; charset=utf-8"; - public static bool HasAnyOfContentTypes(HttpRequest request, params string[] contentTypes) { if (contentTypes == null || request.ContentType == null) @@ -224,105 +280,5 @@ namespace Emby.Server.Implementations.SocketSharp var pos = strVal.IndexOf(needle); return pos == -1 ? strVal : strVal.Slice(0, pos); } - - public string PathInfo => this.request.Path.Value; - - public string UserAgent => request.Headers[HeaderNames.UserAgent]; - - public IHeaderDictionary Headers => request.Headers; - - public IQueryCollection QueryString => request.Query; - - public bool IsLocal => string.Equals(request.HttpContext.Connection.LocalIpAddress.ToString(), request.HttpContext.Connection.RemoteIpAddress.ToString()); - - private string httpMethod; - public string HttpMethod => - httpMethod - ?? (httpMethod = request.Method); - - public string Verb => HttpMethod; - - public string ContentType => request.ContentType; - - private Encoding ContentEncoding - { - get - { - // TODO is this necessary? - if (UserAgent != null && CultureInfo.InvariantCulture.CompareInfo.IsPrefix(UserAgent, "UP")) - { - string postDataCharset = Headers["x-up-devcap-post-charset"]; - if (!string.IsNullOrEmpty(postDataCharset)) - { - try - { - return Encoding.GetEncoding(postDataCharset); - } - catch (ArgumentException) - { - } - } - } - - return request.GetTypedHeaders().ContentType.Encoding ?? Encoding.UTF8; - } - } - - public Uri UrlReferrer => request.GetTypedHeaders().Referer; - - public static Encoding GetEncoding(string contentTypeHeader) - { - var param = GetParameter(contentTypeHeader.AsSpan(), "charset="); - if (param == null) - { - return null; - } - - try - { - return Encoding.GetEncoding(param); - } - catch (ArgumentException) - { - return null; - } - } - - public Stream InputStream => request.Body; - - public long ContentLength => request.ContentLength ?? 0; - - private IHttpFile[] httpFiles; - public IHttpFile[] Files - { - get - { - if (httpFiles != null) - { - return httpFiles; - } - - if (files == null) - { - return httpFiles = Array.Empty(); - } - - var values = files.Values; - httpFiles = new IHttpFile[values.Count]; - for (int i = 0; i < values.Count; i++) - { - var reqFile = values.ElementAt(i); - httpFiles[i] = new HttpFile - { - ContentType = reqFile.ContentType, - ContentLength = reqFile.ContentLength, - FileName = reqFile.FileName, - InputStream = reqFile.InputStream, - }; - } - - return httpFiles; - } - } } } diff --git a/Emby.Server.Implementations/SocketSharp/WebSocketSharpResponse.cs b/Emby.Server.Implementations/SocketSharp/WebSocketSharpResponse.cs deleted file mode 100644 index 0f67eaa62..000000000 --- a/Emby.Server.Implementations/SocketSharp/WebSocketSharpResponse.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Runtime.InteropServices; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Services; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Logging; -using IRequest = MediaBrowser.Model.Services.IRequest; - -namespace Emby.Server.Implementations.SocketSharp -{ - public class WebSocketSharpResponse : IResponse - { - private readonly ILogger _logger; - - public WebSocketSharpResponse(ILogger logger, HttpResponse response) - { - _logger = logger; - OriginalResponse = response; - } - - public HttpResponse OriginalResponse { get; } - - public int StatusCode - { - get => OriginalResponse.StatusCode; - set => OriginalResponse.StatusCode = value; - } - - public string StatusDescription { get; set; } - - public string ContentType - { - get => OriginalResponse.ContentType; - set => OriginalResponse.ContentType = value; - } - - public void AddHeader(string name, string value) - { - if (string.Equals(name, "Content-Type", StringComparison.OrdinalIgnoreCase)) - { - ContentType = value; - return; - } - - OriginalResponse.Headers.Add(name, value); - } - - public void Redirect(string url) - { - OriginalResponse.Redirect(url); - } - - public Stream OutputStream => OriginalResponse.Body; - - public bool SendChunked { get; set; } - - const int StreamCopyToBufferSize = 81920; - public async Task TransmitFile(string path, long offset, long count, FileShareMode fileShareMode, IFileSystem fileSystem, IStreamHelper streamHelper, CancellationToken cancellationToken) - { - var allowAsync = !RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - - //if (count <= 0) - //{ - // allowAsync = true; - //} - - var fileOpenOptions = FileOpenOptions.SequentialScan; - - if (allowAsync) - { - fileOpenOptions |= FileOpenOptions.Asynchronous; - } - - // use non-async filestream along with read due to https://github.com/dotnet/corefx/issues/6039 - - using (var fs = fileSystem.GetFileStream(path, FileOpenMode.Open, FileAccessMode.Read, fileShareMode, fileOpenOptions)) - { - if (offset > 0) - { - fs.Position = offset; - } - - if (count > 0) - { - await streamHelper.CopyToAsync(fs, OutputStream, count, cancellationToken).ConfigureAwait(false); - } - else - { - await fs.CopyToAsync(OutputStream, StreamCopyToBufferSize, cancellationToken).ConfigureAwait(false); - } - } - } - } -} -- cgit v1.2.3 From cf7290343ff4a440537c61332cdc76c5fbcbb7e9 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Mon, 29 Jul 2019 00:33:28 +0200 Subject: Fix build --- .../SocketSharp/WebSocketSharpRequest.cs | 38 ---------------------- MediaBrowser.Api/Devices/DeviceService.cs | 15 +++++---- MediaBrowser.Model/Services/IRequest.cs | 8 ----- 3 files changed, 8 insertions(+), 53 deletions(-) (limited to 'Emby.Server.Implementations/SocketSharp') diff --git a/Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs b/Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs index 43f71a69c..332ce3903 100644 --- a/Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs +++ b/Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs @@ -1,17 +1,14 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.IO; using System.Net; using System.Linq; -using System.Text; using MediaBrowser.Common.Net; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Extensions; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Primitives; using Microsoft.Net.Http.Headers; -using IHttpFile = MediaBrowser.Model.Services.IHttpFile; using IHttpRequest = MediaBrowser.Model.Services.IHttpRequest; namespace Emby.Server.Implementations.SocketSharp @@ -25,8 +22,6 @@ namespace Emby.Server.Implementations.SocketSharp private string _remoteIp; private Dictionary _items; private string _responseContentType; - private IHttpFile[] _httpFiles; - private Dictionary _files; public WebSocketSharpRequest(HttpRequest httpRequest, HttpResponse httpResponse, string operationName, ILogger logger) { @@ -109,39 +104,6 @@ namespace Emby.Server.Implementations.SocketSharp public long ContentLength => Request.ContentLength ?? 0; - - public IHttpFile[] Files - { - get - { - if (_httpFiles != null) - { - return _httpFiles; - } - - if (_files == null) - { - return _httpFiles = Array.Empty(); - } - - var values = _files.Values; - _httpFiles = new IHttpFile[values.Count]; - for (int i = 0; i < values.Count; i++) - { - var reqFile = values.ElementAt(i); - _httpFiles[i] = new HttpFile - { - ContentType = reqFile.ContentType, - ContentLength = reqFile.ContentLength, - FileName = reqFile.FileName, - InputStream = reqFile.InputStream, - }; - } - - return _httpFiles; - } - } - private string GetHeader(string name) => Request.Headers[name].ToString(); private static IPAddress NormalizeIp(IPAddress ip) diff --git a/MediaBrowser.Api/Devices/DeviceService.cs b/MediaBrowser.Api/Devices/DeviceService.cs index dc211af6b..697a84f5c 100644 --- a/MediaBrowser.Api/Devices/DeviceService.cs +++ b/MediaBrowser.Api/Devices/DeviceService.cs @@ -133,12 +133,15 @@ namespace MediaBrowser.Api.Devices var album = Request.QueryString["Album"]; var id = Request.QueryString["Id"]; var name = Request.QueryString["Name"]; + var req = Request.Response.HttpContext.Request; - if (Request.ContentType.IndexOf("multi", StringComparison.OrdinalIgnoreCase) == -1) + if (req.HasFormContentType) { - return _deviceManager.AcceptCameraUpload(deviceId, request.RequestStream, new LocalFileInfo + var file = req.Form.Files.Count == 0 ? null : req.Form.Files[0]; + + return _deviceManager.AcceptCameraUpload(deviceId, file.OpenReadStream(), new LocalFileInfo { - MimeType = Request.ContentType, + MimeType = file.ContentType, Album = album, Name = name, Id = id @@ -146,11 +149,9 @@ namespace MediaBrowser.Api.Devices } else { - var file = Request.Files.Length == 0 ? null : Request.Files[0]; - - return _deviceManager.AcceptCameraUpload(deviceId, file.InputStream, new LocalFileInfo + return _deviceManager.AcceptCameraUpload(deviceId, request.RequestStream, new LocalFileInfo { - MimeType = file.ContentType, + MimeType = Request.ContentType, Album = album, Name = name, Id = id diff --git a/MediaBrowser.Model/Services/IRequest.cs b/MediaBrowser.Model/Services/IRequest.cs index 3852b1dd7..7a4152698 100644 --- a/MediaBrowser.Model/Services/IRequest.cs +++ b/MediaBrowser.Model/Services/IRequest.cs @@ -1,9 +1,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Model.IO; using Microsoft.AspNetCore.Http; namespace MediaBrowser.Model.Services @@ -67,11 +64,6 @@ namespace MediaBrowser.Model.Services long ContentLength { get; } - /// - /// Access to the multi-part/formdata files posted on this request - /// - IHttpFile[] Files { get; } - /// /// The value of the Referrer, null if not available /// -- cgit v1.2.3 From dc662beefeb918b6ae967acb9849a2856cfc3672 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Fri, 16 Aug 2019 21:03:45 +0200 Subject: Add analysers to Emby.IsoMounting and enable TreatWarningsAsErrors --- .../Configuration/PluginConfiguration.cs | 3 + Emby.IsoMounting/IsoMounter/IsoMounter.csproj | 12 + Emby.IsoMounting/IsoMounter/LinuxIsoManager.cs | 477 +++++++-------------- Emby.IsoMounting/IsoMounter/LinuxMount.cs | 73 ++-- Emby.IsoMounting/IsoMounter/Plugin.cs | 25 +- Emby.Server.Implementations/IO/IsoManager.cs | 26 +- .../SocketSharp/WebSocketSharpListener.cs | 2 +- MediaBrowser.Model/IO/IIsoManager.cs | 2 +- MediaBrowser.Model/IO/IIsoMounter.cs | 2 +- .../Plugins/BasePluginConfiguration.cs | 2 +- 10 files changed, 215 insertions(+), 409 deletions(-) (limited to 'Emby.Server.Implementations/SocketSharp') diff --git a/Emby.IsoMounting/IsoMounter/Configuration/PluginConfiguration.cs b/Emby.IsoMounting/IsoMounter/Configuration/PluginConfiguration.cs index 4755e4e82..ca6f40cc4 100644 --- a/Emby.IsoMounting/IsoMounter/Configuration/PluginConfiguration.cs +++ b/Emby.IsoMounting/IsoMounter/Configuration/PluginConfiguration.cs @@ -2,6 +2,9 @@ using MediaBrowser.Model.Plugins; namespace IsoMounter.Configuration { + /// + /// Class PluginConfiguration. + /// public class PluginConfiguration : BasePluginConfiguration { } diff --git a/Emby.IsoMounting/IsoMounter/IsoMounter.csproj b/Emby.IsoMounting/IsoMounter/IsoMounter.csproj index 0778b987b..4fa07fbf1 100644 --- a/Emby.IsoMounting/IsoMounter/IsoMounter.csproj +++ b/Emby.IsoMounting/IsoMounter/IsoMounter.csproj @@ -13,6 +13,18 @@ netstandard2.0 false true + true + + + + + + + + + + + ../../jellyfin.ruleset diff --git a/Emby.IsoMounting/IsoMounter/LinuxIsoManager.cs b/Emby.IsoMounting/IsoMounter/LinuxIsoManager.cs index 2f0003be8..48cb2e1d5 100644 --- a/Emby.IsoMounting/IsoMounter/LinuxIsoManager.cs +++ b/Emby.IsoMounting/IsoMounter/LinuxIsoManager.cs @@ -1,9 +1,10 @@ using System; +using System.Diagnostics; +using System.Globalization; using System.IO; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Model.Diagnostics; using MediaBrowser.Model.IO; using MediaBrowser.Model.System; using Microsoft.Extensions.Logging; @@ -11,441 +12,274 @@ using OperatingSystem = MediaBrowser.Common.System.OperatingSystem; namespace IsoMounter { + /// + /// The ISO manager implementation for Linux. + /// public class LinuxIsoManager : IIsoMounter { - [DllImport("libc", SetLastError = true)] - static extern uint getuid(); + private const string MountCommand = "mount"; + private const string UnmountCommand = "umount"; + private const string SudoCommand = "sudo"; - #region Private Fields - - private readonly bool ExecutablesAvailable; private readonly ILogger _logger; - private readonly string MountCommand; - private readonly string MountPointRoot; - private readonly IProcessFactory ProcessFactory; - private readonly string SudoCommand; - private readonly string UmountCommand; - - #endregion + private readonly string _mountPointRoot; - #region Constructor(s) - - public LinuxIsoManager(ILogger logger, IProcessFactory processFactory) + /// + /// Initializes a new instance of the class. + /// + /// The logger. + public LinuxIsoManager(ILogger logger) { _logger = logger; - ProcessFactory = processFactory; - MountPointRoot = Path.DirectorySeparatorChar + "tmp" + Path.DirectorySeparatorChar + "Emby"; + _mountPointRoot = Path.DirectorySeparatorChar + "tmp" + Path.DirectorySeparatorChar + "Emby"; _logger.LogDebug( "[{0}] System PATH is currently set to [{1}].", Name, - Environment.GetEnvironmentVariable("PATH") ?? "" - ); + Environment.GetEnvironmentVariable("PATH") ?? string.Empty); _logger.LogDebug( "[{0}] System path separator is [{1}].", Name, - Path.PathSeparator - ); + Path.PathSeparator); _logger.LogDebug( "[{0}] Mount point root is [{1}].", Name, - MountPointRoot - ); - - // - // Get the location of the executables we need to support mounting/unmounting ISO images. - // - - SudoCommand = GetFullPathForExecutable("sudo"); - - _logger.LogInformation( - "[{0}] Using version of [sudo] located at [{1}].", - Name, - SudoCommand - ); - - MountCommand = GetFullPathForExecutable("mount"); - - _logger.LogInformation( - "[{0}] Using version of [mount] located at [{1}].", - Name, - MountCommand - ); - - UmountCommand = GetFullPathForExecutable("umount"); - - _logger.LogInformation( - "[{0}] Using version of [umount] located at [{1}].", - Name, - UmountCommand - ); - - if (!string.IsNullOrEmpty(SudoCommand) && !string.IsNullOrEmpty(MountCommand) && !string.IsNullOrEmpty(UmountCommand)) - { - ExecutablesAvailable = true; - } - else - { - ExecutablesAvailable = false; - } - + _mountPointRoot); } - #endregion - - #region Interface Implementation for IIsoMounter - - public bool IsInstalled => true; - + /// public string Name => "LinuxMount"; - public bool RequiresInstallation => false; +#pragma warning disable SA1300 +#pragma warning disable SA1400 + [DllImport("libc", SetLastError = true)] + static extern uint getuid(); + +#pragma warning restore SA1300 +#pragma warning restore SA1400 + /// public bool CanMount(string path) { - if (OperatingSystem.Id != OperatingSystemId.Linux) { return false; } + _logger.LogInformation( - "[{0}] Checking we can attempt to mount [{1}], Extension = [{2}], Operating System = [{3}], Executables Available = [{4}].", + "[{0}] Checking we can attempt to mount [{1}], Extension = [{2}], Operating System = [{3}].", Name, path, Path.GetExtension(path), - OperatingSystem.Name, - ExecutablesAvailable - ); + OperatingSystem.Name); - if (ExecutablesAvailable) - { - return string.Equals(Path.GetExtension(path), ".iso", StringComparison.OrdinalIgnoreCase); - } - else - { - return false; - } - } - - public Task Install(CancellationToken cancellationToken) - { - return Task.FromResult(false); + return string.Equals(Path.GetExtension(path), ".iso", StringComparison.OrdinalIgnoreCase); } + /// public Task Mount(string isoPath, CancellationToken cancellationToken) { - if (MountISO(isoPath, out LinuxMount mountedISO)) - { - return Task.FromResult(mountedISO); - } - else + string cmdArguments; + string cmdFilename; + string mountPoint = Path.Combine(_mountPointRoot, Guid.NewGuid().ToString()); + + if (string.IsNullOrEmpty(isoPath)) { - throw new IOException(string.Format( - "An error occurred trying to mount image [$0].", - isoPath - )); + throw new ArgumentNullException(nameof(isoPath)); } - } - #endregion - - #region Interface Implementation for IDisposable - - // Flag: Has Dispose already been called? - private bool disposed = false; - - public void Dispose() - { - - // Dispose of unmanaged resources. - Dispose(true); - - // Suppress finalization. - GC.SuppressFinalize(this); + _logger.LogInformation( + "[{Name}] Attempting to mount [{Path}].", + Name, + isoPath); - } + _logger.LogDebug( + "[{Name}] ISO will be mounted at [{Path}].", + Name, + mountPoint); - protected virtual void Dispose(bool disposing) - { + try + { + Directory.CreateDirectory(mountPoint); + } + catch (UnauthorizedAccessException ex) + { + throw new IOException("Unable to create mount point(Permission denied) for " + isoPath, ex); + } + catch (Exception ex) + { + throw new IOException("Unable to create mount point for " + isoPath, ex); + } - if (disposed) + if (GetUID() == 0) + { + cmdFilename = MountCommand; + cmdArguments = string.Format( + CultureInfo.InvariantCulture, + "\"{0}\" \"{1}\"", + isoPath, + mountPoint); + } + else { - return; + cmdFilename = SudoCommand; + cmdArguments = string.Format( + CultureInfo.InvariantCulture, + "\"{0}\" \"{1}\" \"{2}\"", + MountCommand, + isoPath, + mountPoint); } - _logger.LogInformation( - "[{0}] Disposing [{1}].", + _logger.LogDebug( + "[{0}] Mount command [{1}], mount arguments [{2}].", Name, - disposing - ); + cmdFilename, + cmdArguments); - if (disposing) + int exitcode = ExecuteCommand(cmdFilename, cmdArguments); + if (exitcode == 0) { + _logger.LogInformation( + "[{0}] ISO mount completed successfully.", + Name); - // - // Free managed objects here. - // - + return Task.FromResult(new LinuxMount(this, isoPath, mountPoint)); } - // - // Free any unmanaged objects here. - // - - disposed = true; - - } - - #endregion - - #region Private Methods - - private string GetFullPathForExecutable(string name) - { + _logger.LogInformation( + "[{0}] ISO mount completed with errors.", + Name); - foreach (string test in (Environment.GetEnvironmentVariable("PATH") ?? "").Split(Path.PathSeparator)) + try { - string path = test.Trim(); - - if (!string.IsNullOrEmpty(path) && File.Exists(path = Path.Combine(path, name))) - { - return Path.GetFullPath(path); - } + Directory.Delete(mountPoint, false); + } + catch (Exception ex) + { + _logger.LogError(ex, "[{Name}] Unhandled exception removing mount point.", Name); + throw; } - return string.Empty; + throw new ExternalException("Mount command failed", exitcode); } private uint GetUID() { - var uid = getuid(); _logger.LogDebug( "[{0}] GetUserId() returned [{2}].", Name, - uid - ); + uid); return uid; - } - private bool ExecuteCommand(string cmdFilename, string cmdArguments) + private int ExecuteCommand(string cmdFilename, string cmdArguments) { - - bool processFailed = false; - - var process = ProcessFactory.Create( - new ProcessOptions - { - CreateNoWindow = true, - RedirectStandardOutput = true, - RedirectStandardError = true, - UseShellExecute = false, - FileName = cmdFilename, - Arguments = cmdArguments, - IsHidden = true, - ErrorDialog = false, - EnableRaisingEvents = true - } - ); + var startInfo = new ProcessStartInfo + { + FileName = cmdFilename, + Arguments = cmdArguments, + UseShellExecute = false, + CreateNoWindow = true, + ErrorDialog = false, + RedirectStandardOutput = true, + RedirectStandardError = true + }; + + var process = new Process() + { + StartInfo = startInfo + }; try { process.Start(); - //StreamReader outputReader = process.StandardOutput.; - //StreamReader errorReader = process.StandardError; - _logger.LogDebug( "[{Name}] Standard output from process is [{Error}].", Name, - process.StandardOutput.ReadToEnd() - ); + process.StandardOutput.ReadToEnd()); _logger.LogDebug( "[{Name}] Standard error from process is [{Error}].", Name, - process.StandardError.ReadToEnd() - ); + process.StandardError.ReadToEnd()); + + return process.ExitCode; } catch (Exception ex) { - processFailed = true; _logger.LogDebug(ex, "[{Name}] Unhandled exception executing command.", Name); + throw; } - - if (!processFailed && process.ExitCode == 0) + finally { - return true; + process?.Dispose(); } - else - { - return false; - } - } - private bool MountISO(string isoPath, out LinuxMount mountedISO) + /// + /// Unmounts the specified mount. + /// + /// The mount. + internal void OnUnmount(LinuxMount mount) { - - string cmdArguments; - string cmdFilename; - string mountPoint = Path.Combine(MountPointRoot, Guid.NewGuid().ToString()); - - if (!string.IsNullOrEmpty(isoPath)) - { - - _logger.LogInformation( - "[{Name}] Attempting to mount [{Path}].", - Name, - isoPath - ); - - _logger.LogDebug( - "[{Name}] ISO will be mounted at [{Path}].", - Name, - mountPoint - ); - - } - else + if (mount == null) { - - throw new ArgumentNullException(nameof(isoPath)); - - } - - try - { - Directory.CreateDirectory(mountPoint); - } - catch (UnauthorizedAccessException) - { - throw new IOException("Unable to create mount point(Permission denied) for " + isoPath); - } - catch (Exception) - { - throw new IOException("Unable to create mount point for " + isoPath); - } - - if (GetUID() == 0) - { - cmdFilename = MountCommand; - cmdArguments = string.Format("\"{0}\" \"{1}\"", isoPath, mountPoint); - } - else - { - cmdFilename = SudoCommand; - cmdArguments = string.Format("\"{0}\" \"{1}\" \"{2}\"", MountCommand, isoPath, mountPoint); + throw new ArgumentNullException(nameof(mount)); } - _logger.LogDebug( - "[{0}] Mount command [{1}], mount arguments [{2}].", + _logger.LogInformation( + "[{0}] Attempting to unmount ISO [{1}] mounted on [{2}].", Name, - cmdFilename, - cmdArguments - ); - - if (ExecuteCommand(cmdFilename, cmdArguments)) - { - - _logger.LogInformation( - "[{0}] ISO mount completed successfully.", - Name - ); - - mountedISO = new LinuxMount(this, isoPath, mountPoint); - - } - else - { - - _logger.LogInformation( - "[{0}] ISO mount completed with errors.", - Name - ); - - try - { - Directory.Delete(mountPoint, false); - } - catch (Exception ex) - { - _logger.LogInformation(ex, "[{Name}] Unhandled exception removing mount point.", Name); - } - - mountedISO = null; - - } - - return mountedISO != null; - - } - - private void UnmountISO(LinuxMount mount) - { + mount.IsoPath, + mount.MountedPath); string cmdArguments; string cmdFilename; - if (mount != null) - { - - _logger.LogInformation( - "[{0}] Attempting to unmount ISO [{1}] mounted on [{2}].", - Name, - mount.IsoPath, - mount.MountedPath - ); - - } - else - { - - throw new ArgumentNullException(nameof(mount)); - - } - if (GetUID() == 0) { - cmdFilename = UmountCommand; - cmdArguments = string.Format("\"{0}\"", mount.MountedPath); + cmdFilename = UnmountCommand; + cmdArguments = string.Format( + CultureInfo.InvariantCulture, + "\"{0}\"", + mount.MountedPath); } else { cmdFilename = SudoCommand; - cmdArguments = string.Format("\"{0}\" \"{1}\"", UmountCommand, mount.MountedPath); + cmdArguments = string.Format( + CultureInfo.InvariantCulture, + "\"{0}\" \"{1}\"", + UnmountCommand, + mount.MountedPath); } _logger.LogDebug( "[{0}] Umount command [{1}], umount arguments [{2}].", Name, cmdFilename, - cmdArguments - ); + cmdArguments); - if (ExecuteCommand(cmdFilename, cmdArguments)) + int exitcode = ExecuteCommand(cmdFilename, cmdArguments); + if (exitcode == 0) { - _logger.LogInformation( "[{0}] ISO unmount completed successfully.", - Name - ); - + Name); } else { - _logger.LogInformation( "[{0}] ISO unmount completed with errors.", - Name - ); - + Name); } try @@ -454,24 +288,11 @@ namespace IsoMounter } catch (Exception ex) { - _logger.LogInformation(ex, "[{Name}] Unhandled exception removing mount point.", Name); + _logger.LogError(ex, "[{Name}] Unhandled exception removing mount point.", Name); + throw; } - } - - #endregion - - #region Internal Methods - - internal void OnUnmount(LinuxMount mount) - { - - UnmountISO(mount); + throw new ExternalException("Mount command failed", exitcode); } - - #endregion - } - } - diff --git a/Emby.IsoMounting/IsoMounter/LinuxMount.cs b/Emby.IsoMounting/IsoMounter/LinuxMount.cs index b8636822b..ccad8ce20 100644 --- a/Emby.IsoMounting/IsoMounter/LinuxMount.cs +++ b/Emby.IsoMounting/IsoMounter/LinuxMount.cs @@ -3,81 +3,56 @@ using MediaBrowser.Model.IO; namespace IsoMounter { + /// + /// Class LinuxMount. + /// internal class LinuxMount : IIsoMount { + private readonly LinuxIsoManager _linuxIsoManager; - #region Private Fields - - private readonly LinuxIsoManager linuxIsoManager; - - #endregion - - #region Constructor(s) + private bool _disposed = false; + /// + /// Initializes a new instance of the class. + /// + /// The ISO manager that mounted this ISO file. + /// The path to the ISO file. + /// The folder the ISO is mounted in. internal LinuxMount(LinuxIsoManager isoManager, string isoPath, string mountFolder) { - - linuxIsoManager = isoManager; + _linuxIsoManager = isoManager; IsoPath = isoPath; MountedPath = mountFolder; - } - #endregion - - #region Interface Implementation for IDisposable + /// + public string IsoPath { get; } - // Flag: Has Dispose already been called? - private bool disposed = false; + /// + public string MountedPath { get; } + /// public void Dispose() { - - // Dispose of unmanaged resources. Dispose(true); - - // Suppress finalization. GC.SuppressFinalize(this); - } + /// + /// Releases the unmanaged resources and disposes of the managed resources used. + /// + /// Whether or not the managed resources should be disposed. protected virtual void Dispose(bool disposing) { - - if (disposed) + if (_disposed) { return; } - if (disposing) - { - - // - // Free managed objects here. - // - - linuxIsoManager.OnUnmount(this); - - } - - // - // Free any unmanaged objects here. - // - - disposed = true; + _linuxIsoManager.OnUnmount(this); + _disposed = true; } - - #endregion - - #region Interface Implementation for IIsoMount - - public string IsoPath { get; private set; } - public string MountedPath { get; private set; } - - #endregion - } - } diff --git a/Emby.IsoMounting/IsoMounter/Plugin.cs b/Emby.IsoMounting/IsoMounter/Plugin.cs index f45b39d3e..433294d74 100644 --- a/Emby.IsoMounting/IsoMounter/Plugin.cs +++ b/Emby.IsoMounting/IsoMounter/Plugin.cs @@ -6,25 +6,28 @@ using MediaBrowser.Model.Serialization; namespace IsoMounter { + /// + /// The LinuxMount plugin class. + /// public class Plugin : BasePlugin { - public Plugin(IApplicationPaths applicationPaths, IXmlSerializer xmlSerializer) : base(applicationPaths, xmlSerializer) + /// + /// Initializes a new instance of the class. + /// + /// The application paths. + /// The XML serializer. + public Plugin(IApplicationPaths applicationPaths, IXmlSerializer xmlSerializer) + : base(applicationPaths, xmlSerializer) { } - private Guid _id = new Guid("4682DD4C-A675-4F1B-8E7C-79ADF137A8F8"); - public override Guid Id => _id; + /// + public override Guid Id { get; } = new Guid("4682DD4C-A675-4F1B-8E7C-79ADF137A8F8"); - /// - /// Gets the name of the plugin - /// - /// The name. + /// public override string Name => "Iso Mounter"; - /// - /// Gets the description. - /// - /// The description. + /// public override string Description => "Mount and stream ISO contents"; } } diff --git a/Emby.Server.Implementations/IO/IsoManager.cs b/Emby.Server.Implementations/IO/IsoManager.cs index f0a15097c..94e92c2a6 100644 --- a/Emby.Server.Implementations/IO/IsoManager.cs +++ b/Emby.Server.Implementations/IO/IsoManager.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -8,12 +9,12 @@ using MediaBrowser.Model.IO; namespace Emby.Server.Implementations.IO { /// - /// Class IsoManager + /// Class IsoManager. /// public class IsoManager : IIsoManager { /// - /// The _mounters + /// The _mounters. /// private readonly List _mounters = new List(); @@ -22,9 +23,7 @@ namespace Emby.Server.Implementations.IO /// /// The iso path. /// The cancellation token. - /// IsoMount. - /// isoPath - /// + /// . public Task Mount(string isoPath, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(isoPath)) @@ -36,7 +35,11 @@ namespace Emby.Server.Implementations.IO if (mounter == null) { - throw new ArgumentException(string.Format("No mounters are able to mount {0}", isoPath)); + throw new ArgumentException( + string.Format( + CultureInfo.InvariantCulture, + "No mounters are able to mount {0}", + isoPath)); } return mounter.Mount(isoPath, cancellationToken); @@ -60,16 +63,5 @@ namespace Emby.Server.Implementations.IO { _mounters.AddRange(mounters); } - - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - public void Dispose() - { - foreach (var mounter in _mounters) - { - mounter.Dispose(); - } - } } } diff --git a/Emby.Server.Implementations/SocketSharp/WebSocketSharpListener.cs b/Emby.Server.Implementations/SocketSharp/WebSocketSharpListener.cs index dd313b336..e93bff124 100644 --- a/Emby.Server.Implementations/SocketSharp/WebSocketSharpListener.cs +++ b/Emby.Server.Implementations/SocketSharp/WebSocketSharpListener.cs @@ -117,7 +117,7 @@ namespace Emby.Server.Implementations.SocketSharp /// /// Releases the unmanaged resources and disposes of the managed resources used. /// - /// Whether or not the managed resources should be disposed + /// Whether or not the managed resources should be disposed. protected virtual void Dispose(bool disposing) { if (_disposed) diff --git a/MediaBrowser.Model/IO/IIsoManager.cs b/MediaBrowser.Model/IO/IIsoManager.cs index 24b6e5f05..eb0cb4bfb 100644 --- a/MediaBrowser.Model/IO/IIsoManager.cs +++ b/MediaBrowser.Model/IO/IIsoManager.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Model.IO { - public interface IIsoManager : IDisposable + public interface IIsoManager { /// /// Mounts the specified iso path. diff --git a/MediaBrowser.Model/IO/IIsoMounter.cs b/MediaBrowser.Model/IO/IIsoMounter.cs index f0153a928..766a9e4e6 100644 --- a/MediaBrowser.Model/IO/IIsoMounter.cs +++ b/MediaBrowser.Model/IO/IIsoMounter.cs @@ -5,7 +5,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Model.IO { - public interface IIsoMounter : IDisposable + public interface IIsoMounter { /// /// Mounts the specified iso path. diff --git a/MediaBrowser.Model/Plugins/BasePluginConfiguration.cs b/MediaBrowser.Model/Plugins/BasePluginConfiguration.cs index 39db22133..ac540782c 100644 --- a/MediaBrowser.Model/Plugins/BasePluginConfiguration.cs +++ b/MediaBrowser.Model/Plugins/BasePluginConfiguration.cs @@ -1,7 +1,7 @@ namespace MediaBrowser.Model.Plugins { /// - /// Class BasePluginConfiguration + /// Class BasePluginConfiguration. /// public class BasePluginConfiguration { -- cgit v1.2.3