2
0

HttpListenerContext.Managed.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. using System;
  2. using System.ComponentModel;
  3. using System.Security.Principal;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using MediaBrowser.Model.Text;
  7. using SocketHttpListener.Net.WebSockets;
  8. namespace SocketHttpListener.Net
  9. {
  10. public sealed unsafe partial class HttpListenerContext
  11. {
  12. private HttpConnection _connection;
  13. internal HttpListenerContext(HttpConnection connection, ITextEncoding textEncoding)
  14. {
  15. _connection = connection;
  16. _response = new HttpListenerResponse(this, textEncoding);
  17. Request = new HttpListenerRequest(this);
  18. ErrorStatus = 400;
  19. }
  20. internal int ErrorStatus { get; set; }
  21. internal string ErrorMessage { get; set; }
  22. internal bool HaveError => ErrorMessage != null;
  23. internal HttpConnection Connection => _connection;
  24. internal void ParseAuthentication(System.Net.AuthenticationSchemes expectedSchemes)
  25. {
  26. if (expectedSchemes == System.Net.AuthenticationSchemes.Anonymous)
  27. return;
  28. string header = Request.Headers["Authorization"];
  29. if (string.IsNullOrEmpty(header))
  30. return;
  31. if (IsBasicHeader(header))
  32. {
  33. _user = ParseBasicAuthentication(header.Substring(AuthenticationTypes.Basic.Length + 1));
  34. }
  35. }
  36. internal IPrincipal ParseBasicAuthentication(string authData) =>
  37. TryParseBasicAuth(authData, out HttpStatusCode errorCode, out string username, out string password) ?
  38. new GenericPrincipal(new HttpListenerBasicIdentity(username, password), Array.Empty<string>()) :
  39. null;
  40. internal static bool IsBasicHeader(string header) =>
  41. header.Length >= 6 &&
  42. header[5] == ' ' &&
  43. string.Compare(header, 0, AuthenticationTypes.Basic, 0, 5, StringComparison.OrdinalIgnoreCase) == 0;
  44. internal static bool TryParseBasicAuth(string headerValue, out HttpStatusCode errorCode, out string username, out string password)
  45. {
  46. errorCode = HttpStatusCode.OK;
  47. username = password = null;
  48. try
  49. {
  50. if (string.IsNullOrWhiteSpace(headerValue))
  51. {
  52. return false;
  53. }
  54. string authString = Encoding.UTF8.GetString(Convert.FromBase64String(headerValue));
  55. int colonPos = authString.IndexOf(':');
  56. if (colonPos < 0)
  57. {
  58. // username must be at least 1 char
  59. errorCode = HttpStatusCode.BadRequest;
  60. return false;
  61. }
  62. username = authString.Substring(0, colonPos);
  63. password = authString.Substring(colonPos + 1);
  64. return true;
  65. }
  66. catch
  67. {
  68. errorCode = HttpStatusCode.InternalServerError;
  69. return false;
  70. }
  71. }
  72. public Task<HttpListenerWebSocketContext> AcceptWebSocketAsync(string subProtocol, int receiveBufferSize, TimeSpan keepAliveInterval)
  73. {
  74. return HttpWebSocket.AcceptWebSocketAsyncCore(this, subProtocol, receiveBufferSize, keepAliveInterval);
  75. }
  76. [EditorBrowsable(EditorBrowsableState.Never)]
  77. public Task<HttpListenerWebSocketContext> AcceptWebSocketAsync(string subProtocol, int receiveBufferSize, TimeSpan keepAliveInterval, ArraySegment<byte> internalBuffer)
  78. {
  79. WebSocketValidate.ValidateArraySegment(internalBuffer, nameof(internalBuffer));
  80. HttpWebSocket.ValidateOptions(subProtocol, receiveBufferSize, HttpWebSocket.MinSendBufferSize, keepAliveInterval);
  81. return HttpWebSocket.AcceptWebSocketAsyncCore(this, subProtocol, receiveBufferSize, keepAliveInterval, internalBuffer);
  82. }
  83. }
  84. }