mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-07-09 03:04:24 -04:00
Replace some usage of QueryParamCollection
This commit is contained in:
parent
91afaaf8fe
commit
27e7e792b3
@ -136,7 +136,7 @@ namespace Emby.Dlna.Api
|
|||||||
{
|
{
|
||||||
var url = Request.AbsoluteUri;
|
var url = Request.AbsoluteUri;
|
||||||
var serverAddress = url.Substring(0, url.IndexOf("/dlna/", StringComparison.OrdinalIgnoreCase));
|
var serverAddress = url.Substring(0, url.IndexOf("/dlna/", StringComparison.OrdinalIgnoreCase));
|
||||||
var xml = _dlnaManager.GetServerDescriptionXml(Request.Headers.ToDictionary(), request.UuId, serverAddress);
|
var xml = _dlnaManager.GetServerDescriptionXml(Request.Headers, request.UuId, serverAddress);
|
||||||
|
|
||||||
var cacheLength = TimeSpan.FromDays(1);
|
var cacheLength = TimeSpan.FromDays(1);
|
||||||
var cacheKey = Request.RawUrl.GetMD5();
|
var cacheKey = Request.RawUrl.GetMD5();
|
||||||
@ -147,21 +147,21 @@ namespace Emby.Dlna.Api
|
|||||||
|
|
||||||
public object Get(GetContentDirectory request)
|
public object Get(GetContentDirectory request)
|
||||||
{
|
{
|
||||||
var xml = ContentDirectory.GetServiceXml(Request.Headers.ToDictionary());
|
var xml = ContentDirectory.GetServiceXml();
|
||||||
|
|
||||||
return _resultFactory.GetResult(Request, xml, XMLContentType);
|
return _resultFactory.GetResult(Request, xml, XMLContentType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetMediaReceiverRegistrar request)
|
public object Get(GetMediaReceiverRegistrar request)
|
||||||
{
|
{
|
||||||
var xml = MediaReceiverRegistrar.GetServiceXml(Request.Headers.ToDictionary());
|
var xml = MediaReceiverRegistrar.GetServiceXml();
|
||||||
|
|
||||||
return _resultFactory.GetResult(Request, xml, XMLContentType);
|
return _resultFactory.GetResult(Request, xml, XMLContentType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetConnnectionManager request)
|
public object Get(GetConnnectionManager request)
|
||||||
{
|
{
|
||||||
var xml = ConnectionManager.GetServiceXml(Request.Headers.ToDictionary());
|
var xml = ConnectionManager.GetServiceXml();
|
||||||
|
|
||||||
return _resultFactory.GetResult(Request, xml, XMLContentType);
|
return _resultFactory.GetResult(Request, xml, XMLContentType);
|
||||||
}
|
}
|
||||||
@ -193,7 +193,7 @@ namespace Emby.Dlna.Api
|
|||||||
|
|
||||||
return service.ProcessControlRequest(new ControlRequest
|
return service.ProcessControlRequest(new ControlRequest
|
||||||
{
|
{
|
||||||
Headers = Request.Headers.ToDictionary(),
|
Headers = Request.Headers,
|
||||||
InputXml = requestStream,
|
InputXml = requestStream,
|
||||||
TargetServerUuId = id,
|
TargetServerUuId = id,
|
||||||
RequestedUrl = Request.AbsoluteUri
|
RequestedUrl = Request.AbsoluteUri
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using Emby.Dlna.Service;
|
using Emby.Dlna.Service;
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
@ -24,7 +23,7 @@ namespace Emby.Dlna.ConnectionManager
|
|||||||
XmlReaderSettingsFactory = xmlReaderSettingsFactory;
|
XmlReaderSettingsFactory = xmlReaderSettingsFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetServiceXml(IDictionary<string, string> headers)
|
public string GetServiceXml()
|
||||||
{
|
{
|
||||||
return new ConnectionManagerXmlBuilder().GetXml();
|
return new ConnectionManagerXmlBuilder().GetXml();
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ namespace Emby.Dlna.ContentDirectory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetServiceXml(IDictionary<string, string> headers)
|
public string GetServiceXml()
|
||||||
{
|
{
|
||||||
return new ContentDirectoryXmlBuilder().GetXml();
|
return new ContentDirectoryXmlBuilder().GetXml();
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
namespace Emby.Dlna
|
namespace Emby.Dlna
|
||||||
{
|
{
|
||||||
public class ControlRequest
|
public class ControlRequest
|
||||||
{
|
{
|
||||||
public IDictionary<string, string> Headers { get; set; }
|
public IHeaderDictionary Headers { get; set; }
|
||||||
|
|
||||||
public Stream InputXml { get; set; }
|
public Stream InputXml { get; set; }
|
||||||
|
|
||||||
@ -15,7 +16,7 @@ namespace Emby.Dlna
|
|||||||
|
|
||||||
public ControlRequest()
|
public ControlRequest()
|
||||||
{
|
{
|
||||||
Headers = new Dictionary<string, string>();
|
Headers = new HeaderDictionary();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,9 @@ using MediaBrowser.Model.Drawing;
|
|||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Model.Reflection;
|
using MediaBrowser.Model.Reflection;
|
||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Primitives;
|
||||||
|
|
||||||
namespace Emby.Dlna
|
namespace Emby.Dlna
|
||||||
{
|
{
|
||||||
@ -205,16 +207,13 @@ namespace Emby.Dlna
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeviceProfile GetProfile(IDictionary<string, string> headers)
|
public DeviceProfile GetProfile(IHeaderDictionary headers)
|
||||||
{
|
{
|
||||||
if (headers == null)
|
if (headers == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(headers));
|
throw new ArgumentNullException(nameof(headers));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert to case insensitive
|
|
||||||
headers = new Dictionary<string, string>(headers, StringComparer.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
var profile = GetProfiles().FirstOrDefault(i => i.Identification != null && IsMatch(headers, i.Identification));
|
var profile = GetProfiles().FirstOrDefault(i => i.Identification != null && IsMatch(headers, i.Identification));
|
||||||
|
|
||||||
if (profile != null)
|
if (profile != null)
|
||||||
@ -230,12 +229,12 @@ namespace Emby.Dlna
|
|||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsMatch(IDictionary<string, string> headers, DeviceIdentification profileInfo)
|
private bool IsMatch(IHeaderDictionary headers, DeviceIdentification profileInfo)
|
||||||
{
|
{
|
||||||
return profileInfo.Headers.Any(i => IsMatch(headers, i));
|
return profileInfo.Headers.Any(i => IsMatch(headers, i));
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsMatch(IDictionary<string, string> headers, HttpHeaderInfo header)
|
private bool IsMatch(IHeaderDictionary headers, HttpHeaderInfo header)
|
||||||
{
|
{
|
||||||
// Handle invalid user setup
|
// Handle invalid user setup
|
||||||
if (string.IsNullOrEmpty(header.Name))
|
if (string.IsNullOrEmpty(header.Name))
|
||||||
@ -243,14 +242,14 @@ namespace Emby.Dlna
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (headers.TryGetValue(header.Name, out string value))
|
if (headers.TryGetValue(header.Name, out StringValues value))
|
||||||
{
|
{
|
||||||
switch (header.Match)
|
switch (header.Match)
|
||||||
{
|
{
|
||||||
case HeaderMatchType.Equals:
|
case HeaderMatchType.Equals:
|
||||||
return string.Equals(value, header.Value, StringComparison.OrdinalIgnoreCase);
|
return string.Equals(value, header.Value, StringComparison.OrdinalIgnoreCase);
|
||||||
case HeaderMatchType.Substring:
|
case HeaderMatchType.Substring:
|
||||||
var isMatch = value.IndexOf(header.Value, StringComparison.OrdinalIgnoreCase) != -1;
|
var isMatch = value.ToString().IndexOf(header.Value, StringComparison.OrdinalIgnoreCase) != -1;
|
||||||
//_logger.LogDebug("IsMatch-Substring value: {0} testValue: {1} isMatch: {2}", value, header.Value, isMatch);
|
//_logger.LogDebug("IsMatch-Substring value: {0} testValue: {1} isMatch: {2}", value, header.Value, isMatch);
|
||||||
return isMatch;
|
return isMatch;
|
||||||
case HeaderMatchType.Regex:
|
case HeaderMatchType.Regex:
|
||||||
@ -493,7 +492,7 @@ namespace Emby.Dlna
|
|||||||
internal string Path { get; set; }
|
internal string Path { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetServerDescriptionXml(IDictionary<string, string> headers, string serverUuId, string serverAddress)
|
public string GetServerDescriptionXml(IHeaderDictionary headers, string serverUuId, string serverAddress)
|
||||||
{
|
{
|
||||||
var profile = GetProfile(headers) ??
|
var profile = GetProfile(headers) ??
|
||||||
GetDefaultProfile();
|
GetDefaultProfile();
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Emby.Dlna
|
namespace Emby.Dlna
|
||||||
{
|
{
|
||||||
public interface IUpnpService
|
public interface IUpnpService
|
||||||
@ -7,9 +5,8 @@ namespace Emby.Dlna
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the content directory XML.
|
/// Gets the content directory XML.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="headers">The headers.</param>
|
|
||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
string GetServiceXml(IDictionary<string, string> headers);
|
string GetServiceXml();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Processes the control request.
|
/// Processes the control request.
|
||||||
|
@ -3,6 +3,7 @@ using Emby.Dlna.Service;
|
|||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Model.Xml;
|
using MediaBrowser.Model.Xml;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Emby.Dlna.MediaReceiverRegistrar
|
namespace Emby.Dlna.MediaReceiverRegistrar
|
||||||
@ -19,7 +20,7 @@ namespace Emby.Dlna.MediaReceiverRegistrar
|
|||||||
XmlReaderSettingsFactory = xmlReaderSettingsFactory;
|
XmlReaderSettingsFactory = xmlReaderSettingsFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetServiceXml(IDictionary<string, string> headers)
|
public string GetServiceXml()
|
||||||
{
|
{
|
||||||
return new MediaReceiverRegistrarXmlBuilder().GetXml();
|
return new MediaReceiverRegistrarXmlBuilder().GetXml();
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ using MediaBrowser.Model.Extensions;
|
|||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
using MediaBrowser.Model.Services;
|
using MediaBrowser.Model.Services;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Http.Internal;
|
||||||
using Microsoft.AspNetCore.WebUtilities;
|
using Microsoft.AspNetCore.WebUtilities;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
@ -154,7 +155,7 @@ namespace Emby.Server.Implementations.HttpServer
|
|||||||
{
|
{
|
||||||
OnReceive = ProcessWebSocketMessageReceived,
|
OnReceive = ProcessWebSocketMessageReceived,
|
||||||
Url = e.Url,
|
Url = e.Url,
|
||||||
QueryString = e.QueryString ?? new QueryParamCollection()
|
QueryString = e.QueryString ?? new QueryCollection()
|
||||||
};
|
};
|
||||||
|
|
||||||
connection.Closed += Connection_Closed;
|
connection.Closed += Connection_Closed;
|
||||||
@ -606,8 +607,8 @@ namespace Emby.Server.Implementations.HttpServer
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
httpRes.Close();
|
// TODO
|
||||||
|
httpRes.IsClosed = true;
|
||||||
stopWatch.Stop();
|
stopWatch.Stop();
|
||||||
var elapsed = stopWatch.Elapsed;
|
var elapsed = stopWatch.Elapsed;
|
||||||
if (elapsed.TotalMilliseconds > 500)
|
if (elapsed.TotalMilliseconds > 500)
|
||||||
|
@ -16,6 +16,8 @@ using MediaBrowser.Model.IO;
|
|||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
using MediaBrowser.Model.Services;
|
using MediaBrowser.Model.Services;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Primitives;
|
||||||
|
using Microsoft.Net.Http.Headers;
|
||||||
using IRequest = MediaBrowser.Model.Services.IRequest;
|
using IRequest = MediaBrowser.Model.Services.IRequest;
|
||||||
using MimeTypes = MediaBrowser.Model.Net.MimeTypes;
|
using MimeTypes = MediaBrowser.Model.Net.MimeTypes;
|
||||||
|
|
||||||
@ -246,9 +248,9 @@ namespace Emby.Server.Implementations.HttpServer
|
|||||||
|
|
||||||
private static string GetCompressionType(IRequest request)
|
private static string GetCompressionType(IRequest request)
|
||||||
{
|
{
|
||||||
var acceptEncoding = request.Headers["Accept-Encoding"];
|
var acceptEncoding = request.Headers["Accept-Encoding"].ToString();
|
||||||
|
|
||||||
if (acceptEncoding != null)
|
if (string.IsNullOrEmpty(acceptEncoding))
|
||||||
{
|
{
|
||||||
//if (_brotliCompressor != null && acceptEncoding.IndexOf("br", StringComparison.OrdinalIgnoreCase) != -1)
|
//if (_brotliCompressor != null && acceptEncoding.IndexOf("br", StringComparison.OrdinalIgnoreCase) != -1)
|
||||||
// return "br";
|
// return "br";
|
||||||
@ -424,12 +426,12 @@ namespace Emby.Server.Implementations.HttpServer
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private object GetCachedResult(IRequest requestContext, IDictionary<string, string> responseHeaders, StaticResultOptions options)
|
private object GetCachedResult(IRequest requestContext, IDictionary<string, string> responseHeaders, StaticResultOptions options)
|
||||||
{
|
{
|
||||||
bool noCache = (requestContext.Headers.Get("Cache-Control") ?? string.Empty).IndexOf("no-cache", StringComparison.OrdinalIgnoreCase) != -1;
|
bool noCache = (requestContext.Headers[HeaderNames.CacheControl].ToString()).IndexOf("no-cache", StringComparison.OrdinalIgnoreCase) != -1;
|
||||||
AddCachingHeaders(responseHeaders, options.CacheDuration, noCache, options.DateLastModified);
|
AddCachingHeaders(responseHeaders, options.CacheDuration, noCache, options.DateLastModified);
|
||||||
|
|
||||||
if (!noCache)
|
if (!noCache)
|
||||||
{
|
{
|
||||||
DateTime.TryParse(requestContext.Headers.Get("If-Modified-Since"), out var ifModifiedSinceHeader);
|
DateTime.TryParse(requestContext.Headers[HeaderNames.IfModifiedSince], out var ifModifiedSinceHeader);
|
||||||
|
|
||||||
if (IsNotModified(ifModifiedSinceHeader, options.CacheDuration, options.DateLastModified))
|
if (IsNotModified(ifModifiedSinceHeader, options.CacheDuration, options.DateLastModified))
|
||||||
{
|
{
|
||||||
@ -530,7 +532,7 @@ namespace Emby.Server.Implementations.HttpServer
|
|||||||
options.ResponseHeaders = options.ResponseHeaders ?? new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
options.ResponseHeaders = options.ResponseHeaders ?? new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
var contentType = options.ContentType;
|
var contentType = options.ContentType;
|
||||||
if (!string.IsNullOrEmpty(requestContext.Headers.Get("If-Modified-Since")))
|
if (!StringValues.IsNullOrEmpty(requestContext.Headers[HeaderNames.IfModifiedSince]))
|
||||||
{
|
{
|
||||||
// See if the result is already cached in the browser
|
// See if the result is already cached in the browser
|
||||||
var result = GetCachedResult(requestContext, options.ResponseHeaders, options);
|
var result = GetCachedResult(requestContext, options.ResponseHeaders, options);
|
||||||
@ -548,7 +550,7 @@ namespace Emby.Server.Implementations.HttpServer
|
|||||||
AddCachingHeaders(responseHeaders, options.CacheDuration, false, options.DateLastModified);
|
AddCachingHeaders(responseHeaders, options.CacheDuration, false, options.DateLastModified);
|
||||||
AddAgeHeader(responseHeaders, options.DateLastModified);
|
AddAgeHeader(responseHeaders, options.DateLastModified);
|
||||||
|
|
||||||
var rangeHeader = requestContext.Headers.Get("Range");
|
var rangeHeader = requestContext.Headers["Range"];
|
||||||
|
|
||||||
if (!isHeadRequest && !string.IsNullOrEmpty(options.Path))
|
if (!isHeadRequest && !string.IsNullOrEmpty(options.Path))
|
||||||
{
|
{
|
||||||
@ -609,11 +611,6 @@ namespace Emby.Server.Implementations.HttpServer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The us culture
|
|
||||||
/// </summary>
|
|
||||||
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the caching responseHeaders.
|
/// Adds the caching responseHeaders.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -8,6 +8,7 @@ using MediaBrowser.Controller.Net;
|
|||||||
using MediaBrowser.Model.Net;
|
using MediaBrowser.Model.Net;
|
||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
using MediaBrowser.Model.Services;
|
using MediaBrowser.Model.Services;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using UtfUnknown;
|
using UtfUnknown;
|
||||||
|
|
||||||
@ -67,7 +68,7 @@ namespace Emby.Server.Implementations.HttpServer
|
|||||||
/// Gets or sets the query string.
|
/// Gets or sets the query string.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The query string.</value>
|
/// <value>The query string.</value>
|
||||||
public QueryParamCollection QueryString { get; set; }
|
public IQueryCollection QueryString { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="WebSocketConnection" /> class.
|
/// Initializes a new instance of the <see cref="WebSocketConnection" /> class.
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Net.WebSockets;
|
using System.Net.WebSockets;
|
||||||
using MediaBrowser.Model.Services;
|
using MediaBrowser.Model.Services;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.Net
|
namespace Emby.Server.Implementations.Net
|
||||||
{
|
{
|
||||||
@ -15,7 +16,7 @@ namespace Emby.Server.Implementations.Net
|
|||||||
/// Gets or sets the query string.
|
/// Gets or sets the query string.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The query string.</value>
|
/// <value>The query string.</value>
|
||||||
public QueryParamCollection QueryString { get; set; }
|
public IQueryCollection QueryString { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the web socket.
|
/// Gets or sets the web socket.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -154,7 +154,7 @@ namespace Emby.Server.Implementations.Services
|
|||||||
{
|
{
|
||||||
if (name == null) continue; //thank you ASP.NET
|
if (name == null) continue; //thank you ASP.NET
|
||||||
|
|
||||||
var values = request.QueryString.GetValues(name);
|
var values = request.QueryString[name];
|
||||||
if (values.Count == 1)
|
if (values.Count == 1)
|
||||||
{
|
{
|
||||||
map[name] = values[0];
|
map[name] = values[0];
|
||||||
|
@ -5,6 +5,7 @@ using MediaBrowser.Controller.Session;
|
|||||||
using MediaBrowser.Model.Events;
|
using MediaBrowser.Model.Events;
|
||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
using MediaBrowser.Model.Services;
|
using MediaBrowser.Model.Services;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.Session
|
namespace Emby.Server.Implementations.Session
|
||||||
@ -62,7 +63,7 @@ namespace Emby.Server.Implementations.Session
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private SessionInfo GetSession(QueryParamCollection queryString, string remoteEndpoint)
|
private SessionInfo GetSession(IQueryCollection queryString, string remoteEndpoint)
|
||||||
{
|
{
|
||||||
if (queryString == null)
|
if (queryString == null)
|
||||||
{
|
{
|
||||||
|
@ -118,8 +118,6 @@ namespace Emby.Server.Implementations.SocketSharp
|
|||||||
|
|
||||||
public string Authorization => StringValues.IsNullOrEmpty(request.Headers["Authorization"]) ? null : request.Headers["Authorization"].ToString();
|
public string Authorization => StringValues.IsNullOrEmpty(request.Headers["Authorization"]) ? null : request.Headers["Authorization"].ToString();
|
||||||
|
|
||||||
protected bool validate_cookies { get; set; }
|
|
||||||
protected bool validate_query_string { get; set; }
|
|
||||||
protected bool validate_form { get; set; }
|
protected bool validate_form { get; set; }
|
||||||
protected bool checked_form { get; set; }
|
protected bool checked_form { get; set; }
|
||||||
|
|
||||||
|
@ -52,12 +52,10 @@ using Microsoft.Extensions.Logging;
|
|||||||
var endpoint = ctx.Connection.RemoteIpAddress.ToString();
|
var endpoint = ctx.Connection.RemoteIpAddress.ToString();
|
||||||
var url = ctx.Request.GetDisplayUrl();
|
var url = ctx.Request.GetDisplayUrl();
|
||||||
|
|
||||||
var queryString = new QueryParamCollection(ctx.Request.Query);
|
|
||||||
|
|
||||||
var connectingArgs = new WebSocketConnectingEventArgs
|
var connectingArgs = new WebSocketConnectingEventArgs
|
||||||
{
|
{
|
||||||
Url = url,
|
Url = url,
|
||||||
QueryString = queryString,
|
QueryString = ctx.Request.Query,
|
||||||
Endpoint = endpoint
|
Endpoint = endpoint
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -73,7 +71,7 @@ using Microsoft.Extensions.Logging;
|
|||||||
WebSocketConnected(new WebSocketConnectEventArgs
|
WebSocketConnected(new WebSocketConnectEventArgs
|
||||||
{
|
{
|
||||||
Url = url,
|
Url = url,
|
||||||
QueryString = queryString,
|
QueryString = ctx.Request.Query,
|
||||||
WebSocket = socket,
|
WebSocket = socket,
|
||||||
Endpoint = endpoint
|
Endpoint = endpoint
|
||||||
});
|
});
|
||||||
|
@ -13,7 +13,6 @@ using Microsoft.Extensions.Primitives;
|
|||||||
using Microsoft.Net.Http.Headers;
|
using Microsoft.Net.Http.Headers;
|
||||||
using IHttpFile = MediaBrowser.Model.Services.IHttpFile;
|
using IHttpFile = MediaBrowser.Model.Services.IHttpFile;
|
||||||
using IHttpRequest = MediaBrowser.Model.Services.IHttpRequest;
|
using IHttpRequest = MediaBrowser.Model.Services.IHttpRequest;
|
||||||
using IHttpResponse = MediaBrowser.Model.Services.IHttpResponse;
|
|
||||||
using IResponse = MediaBrowser.Model.Services.IResponse;
|
using IResponse = MediaBrowser.Model.Services.IResponse;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.SocketSharp
|
namespace Emby.Server.Implementations.SocketSharp
|
||||||
@ -21,7 +20,7 @@ namespace Emby.Server.Implementations.SocketSharp
|
|||||||
public partial class WebSocketSharpRequest : IHttpRequest
|
public partial class WebSocketSharpRequest : IHttpRequest
|
||||||
{
|
{
|
||||||
private readonly HttpRequest request;
|
private readonly HttpRequest request;
|
||||||
private readonly IHttpResponse response;
|
private readonly IResponse response;
|
||||||
|
|
||||||
public WebSocketSharpRequest(HttpRequest httpContext, HttpResponse response, string operationName, ILogger logger)
|
public WebSocketSharpRequest(HttpRequest httpContext, HttpResponse response, string operationName, ILogger logger)
|
||||||
{
|
{
|
||||||
@ -34,11 +33,9 @@ namespace Emby.Server.Implementations.SocketSharp
|
|||||||
|
|
||||||
public HttpRequest HttpRequest => request;
|
public HttpRequest HttpRequest => request;
|
||||||
|
|
||||||
public object OriginalRequest => request;
|
|
||||||
|
|
||||||
public IResponse Response => response;
|
public IResponse Response => response;
|
||||||
|
|
||||||
public IHttpResponse HttpResponse => response;
|
public IResponse HttpResponse => response;
|
||||||
|
|
||||||
public string OperationName { get; set; }
|
public string OperationName { get; set; }
|
||||||
|
|
||||||
@ -396,10 +393,9 @@ namespace Emby.Server.Implementations.SocketSharp
|
|||||||
|
|
||||||
public string UserAgent => request.Headers[HeaderNames.UserAgent];
|
public string UserAgent => request.Headers[HeaderNames.UserAgent];
|
||||||
|
|
||||||
public QueryParamCollection Headers => new QueryParamCollection(request.Headers);
|
public IHeaderDictionary Headers => request.Headers;
|
||||||
|
|
||||||
private QueryParamCollection queryString;
|
public IQueryCollection QueryString => request.Query;
|
||||||
public QueryParamCollection QueryString => queryString ?? (queryString = new QueryParamCollection(request.Query));
|
|
||||||
|
|
||||||
public bool IsLocal => string.Equals(request.HttpContext.Connection.LocalIpAddress.ToString(), request.HttpContext.Connection.RemoteIpAddress.ToString());
|
public bool IsLocal => string.Equals(request.HttpContext.Connection.LocalIpAddress.ToString(), request.HttpContext.Connection.RemoteIpAddress.ToString());
|
||||||
|
|
||||||
|
@ -1,23 +1,18 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
|
||||||
using System.Net.Sockets;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Emby.Server.Implementations;
|
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Model.Services;
|
using MediaBrowser.Model.Services;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using IHttpResponse = MediaBrowser.Model.Services.IHttpResponse;
|
|
||||||
using IRequest = MediaBrowser.Model.Services.IRequest;
|
using IRequest = MediaBrowser.Model.Services.IRequest;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.SocketSharp
|
namespace Emby.Server.Implementations.SocketSharp
|
||||||
{
|
{
|
||||||
public class WebSocketSharpResponse : IHttpResponse
|
public class WebSocketSharpResponse : IResponse
|
||||||
{
|
{
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
@ -51,42 +46,7 @@ namespace Emby.Server.Implementations.SocketSharp
|
|||||||
set => _response.ContentType = value;
|
set => _response.ContentType = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public QueryParamCollection Headers => new QueryParamCollection(_response.Headers);
|
public IHeaderDictionary Headers => _response.Headers;
|
||||||
|
|
||||||
private static string AsHeaderValue(Cookie cookie)
|
|
||||||
{
|
|
||||||
DateTime 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}");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cookie.Secure)
|
|
||||||
{
|
|
||||||
sb.Append(";Secure");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cookie.HttpOnly)
|
|
||||||
{
|
|
||||||
sb.Append(";HttpOnly");
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddHeader(string name, string value)
|
public void AddHeader(string name, string value)
|
||||||
{
|
{
|
||||||
@ -111,51 +71,14 @@ namespace Emby.Server.Implementations.SocketSharp
|
|||||||
|
|
||||||
public Stream OutputStream => _response.Body;
|
public Stream OutputStream => _response.Body;
|
||||||
|
|
||||||
public void Close()
|
|
||||||
{
|
|
||||||
if (!this.IsClosed)
|
|
||||||
{
|
|
||||||
this.IsClosed = true;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var response = this._response;
|
|
||||||
|
|
||||||
var outputStream = response.Body;
|
|
||||||
|
|
||||||
// This is needed with compression
|
|
||||||
outputStream.Flush();
|
|
||||||
outputStream.Dispose();
|
|
||||||
}
|
|
||||||
catch (SocketException)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.LogError(ex, "Error in HttpListenerResponseWrapper");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsClosed
|
public bool IsClosed
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
private set;
|
set;
|
||||||
}
|
|
||||||
|
|
||||||
public void SetCookie(Cookie cookie)
|
|
||||||
{
|
|
||||||
var cookieStr = AsHeaderValue(cookie);
|
|
||||||
_response.Headers.Add("Set-Cookie", cookieStr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SendChunked { get; set; }
|
public bool SendChunked { get; set; }
|
||||||
|
|
||||||
public bool KeepAlive { get; set; }
|
|
||||||
|
|
||||||
public void ClearCookies()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
const int StreamCopyToBufferSize = 81920;
|
const int StreamCopyToBufferSize = 81920;
|
||||||
public async Task TransmitFile(string path, long offset, long count, FileShareMode fileShareMode, IFileSystem fileSystem, IStreamHelper streamHelper, CancellationToken cancellationToken)
|
public async Task TransmitFile(string path, long offset, long count, FileShareMode fileShareMode, IFileSystem fileSystem, IStreamHelper streamHelper, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
@ -609,12 +609,12 @@ namespace MediaBrowser.Api.Playback
|
|||||||
{
|
{
|
||||||
foreach (var param in Request.QueryString)
|
foreach (var param in Request.QueryString)
|
||||||
{
|
{
|
||||||
if (char.IsLower(param.Name[0]))
|
if (char.IsLower(param.Key[0]))
|
||||||
{
|
{
|
||||||
// This was probably not parsed initially and should be a StreamOptions
|
// This was probably not parsed initially and should be a StreamOptions
|
||||||
// TODO: This should be incorporated either in the lower framework for parsing requests
|
// TODO: This should be incorporated either in the lower framework for parsing requests
|
||||||
// or the generated URL should correctly serialize it
|
// or the generated URL should correctly serialize it
|
||||||
request.StreamOptions[param.Name] = param.Value;
|
request.StreamOptions[param.Key] = param.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -867,7 +867,7 @@ namespace MediaBrowser.Api.Playback
|
|||||||
|
|
||||||
private void ApplyDeviceProfileSettings(StreamState state)
|
private void ApplyDeviceProfileSettings(StreamState state)
|
||||||
{
|
{
|
||||||
var headers = Request.Headers.ToDictionary();
|
var headers = Request.Headers;
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(state.Request.DeviceProfileId))
|
if (!string.IsNullOrWhiteSpace(state.Request.DeviceProfileId))
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using MediaBrowser.Controller.Drawing;
|
using MediaBrowser.Controller.Drawing;
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Dlna
|
namespace MediaBrowser.Controller.Dlna
|
||||||
{
|
{
|
||||||
@ -17,7 +18,7 @@ namespace MediaBrowser.Controller.Dlna
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="headers">The headers.</param>
|
/// <param name="headers">The headers.</param>
|
||||||
/// <returns>DeviceProfile.</returns>
|
/// <returns>DeviceProfile.</returns>
|
||||||
DeviceProfile GetProfile(IDictionary<string, string> headers);
|
DeviceProfile GetProfile(IHeaderDictionary headers);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the default profile.
|
/// Gets the default profile.
|
||||||
@ -64,7 +65,7 @@ namespace MediaBrowser.Controller.Dlna
|
|||||||
/// <param name="serverUuId">The server uu identifier.</param>
|
/// <param name="serverUuId">The server uu identifier.</param>
|
||||||
/// <param name="serverAddress">The server address.</param>
|
/// <param name="serverAddress">The server address.</param>
|
||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
string GetServerDescriptionXml(IDictionary<string, string> headers, string serverUuId, string serverAddress);
|
string GetServerDescriptionXml(IHeaderDictionary headers, string serverUuId, string serverAddress);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the icon.
|
/// Gets the icon.
|
||||||
|
@ -4,6 +4,7 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Model.Net;
|
using MediaBrowser.Model.Net;
|
||||||
using MediaBrowser.Model.Services;
|
using MediaBrowser.Model.Services;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Net
|
namespace MediaBrowser.Controller.Net
|
||||||
{
|
{
|
||||||
@ -35,7 +36,7 @@ namespace MediaBrowser.Controller.Net
|
|||||||
/// Gets or sets the query string.
|
/// Gets or sets the query string.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The query string.</value>
|
/// <value>The query string.</value>
|
||||||
QueryParamCollection QueryString { get; set; }
|
IQueryCollection QueryString { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the receive action.
|
/// Gets or sets the receive action.
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using MediaBrowser.Model.Services;
|
using MediaBrowser.Model.Services;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Http.Internal;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Net
|
namespace MediaBrowser.Controller.Net
|
||||||
{
|
{
|
||||||
@ -22,7 +24,7 @@ namespace MediaBrowser.Controller.Net
|
|||||||
/// Gets or sets the query string.
|
/// Gets or sets the query string.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The query string.</value>
|
/// <value>The query string.</value>
|
||||||
public QueryParamCollection QueryString { get; set; }
|
public IQueryCollection QueryString { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether [allow connection].
|
/// Gets or sets a value indicating whether [allow connection].
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -31,7 +33,7 @@ namespace MediaBrowser.Controller.Net
|
|||||||
|
|
||||||
public WebSocketConnectingEventArgs()
|
public WebSocketConnectingEventArgs()
|
||||||
{
|
{
|
||||||
QueryString = new QueryParamCollection();
|
QueryString = new QueryCollection();
|
||||||
AllowConnection = true;
|
AllowConnection = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,6 @@ namespace MediaBrowser.Model.Services
|
|||||||
{
|
{
|
||||||
public interface IHttpRequest : IRequest
|
public interface IHttpRequest : IRequest
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// The HttpResponse
|
|
||||||
/// </summary>
|
|
||||||
IHttpResponse HttpResponse { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The HTTP Verb
|
/// The HTTP Verb
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -4,17 +4,5 @@ namespace MediaBrowser.Model.Services
|
|||||||
{
|
{
|
||||||
public interface IHttpResponse : IResponse
|
public interface IHttpResponse : IResponse
|
||||||
{
|
{
|
||||||
//ICookies Cookies { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a new Set-Cookie instruction to Response
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="cookie"></param>
|
|
||||||
void SetCookie(Cookie cookie);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes all pending Set-Cookie instructions
|
|
||||||
/// </summary>
|
|
||||||
void ClearCookies();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,15 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
namespace MediaBrowser.Model.Services
|
namespace MediaBrowser.Model.Services
|
||||||
{
|
{
|
||||||
public interface IRequest
|
public interface IRequest
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// The underlying ASP.NET or HttpListener HttpRequest
|
|
||||||
/// </summary>
|
|
||||||
object OriginalRequest { get; }
|
|
||||||
|
|
||||||
IResponse Response { get; }
|
IResponse Response { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -51,9 +46,9 @@ namespace MediaBrowser.Model.Services
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Dictionary<string, object> Items { get; }
|
Dictionary<string, object> Items { get; }
|
||||||
|
|
||||||
QueryParamCollection Headers { get; }
|
IHeaderDictionary Headers { get; }
|
||||||
|
|
||||||
QueryParamCollection QueryString { get; }
|
IQueryCollection QueryString { get; }
|
||||||
|
|
||||||
Task<QueryParamCollection> GetFormData();
|
Task<QueryParamCollection> GetFormData();
|
||||||
|
|
||||||
@ -122,21 +117,15 @@ namespace MediaBrowser.Model.Services
|
|||||||
|
|
||||||
Stream OutputStream { get; }
|
Stream OutputStream { get; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Signal that this response has been handled and no more processing should be done.
|
|
||||||
/// When used in a request or response filter, no more filters or processing is done on this request.
|
|
||||||
/// </summary>
|
|
||||||
void Close();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether this instance is closed.
|
/// Gets a value indicating whether this instance is closed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool IsClosed { get; }
|
bool IsClosed { get; set; }
|
||||||
|
|
||||||
//Add Metadata to Response
|
//Add Metadata to Response
|
||||||
Dictionary<string, object> Items { get; }
|
Dictionary<string, object> Items { get; }
|
||||||
|
|
||||||
QueryParamCollection Headers { get; }
|
IHeaderDictionary Headers { get; }
|
||||||
|
|
||||||
Task TransmitFile(string path, long offset, long count, FileShareMode fileShareMode, IFileSystem fileSystem, IStreamHelper streamHelper, CancellationToken cancellationToken);
|
Task TransmitFile(string path, long offset, long count, FileShareMode fileShareMode, IFileSystem fileSystem, IStreamHelper streamHelper, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Specialized;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Model.Services
|
namespace MediaBrowser.Model.Services
|
||||||
{
|
{
|
||||||
@ -13,23 +10,6 @@ namespace MediaBrowser.Model.Services
|
|||||||
{
|
{
|
||||||
public QueryParamCollection()
|
public QueryParamCollection()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public QueryParamCollection(IHeaderDictionary headers)
|
|
||||||
{
|
|
||||||
foreach (var pair in headers)
|
|
||||||
{
|
|
||||||
Add(pair.Key, pair.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public QueryParamCollection(IQueryCollection queryCollection)
|
|
||||||
{
|
|
||||||
foreach (var pair in queryCollection)
|
|
||||||
{
|
|
||||||
Add(pair.Key, pair.Value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static StringComparison GetStringComparison()
|
private static StringComparison GetStringComparison()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user