| // | 
| // HttpListenerContext.cs | 
| //    Copied from System.Net.HttpListenerContext | 
| // | 
| // Author: | 
| //    Gonzalo Paniagua Javier (gonzalo@novell.com) | 
| // | 
| // Copyright (c) 2005 Novell, Inc. (http://www.novell.com) | 
| // Copyright (c) 2012 sta.blockhead (sta.blockhead@gmail.com) | 
| // | 
| // Permission is hereby granted, free of charge, to any person obtaining | 
| // a copy of this software and associated documentation files (the | 
| // "Software"), to deal in the Software without restriction, including | 
| // without limitation the rights to use, copy, modify, merge, publish, | 
| // distribute, sublicense, and/or sell copies of the Software, and to | 
| // permit persons to whom the Software is furnished to do so, subject to | 
| // the following conditions: | 
| //  | 
| // The above copyright notice and this permission notice shall be | 
| // included in all copies or substantial portions of the Software. | 
| //  | 
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | 
| // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | 
| // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | 
| // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | 
| // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | 
| // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | 
| // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | 
| // | 
|   | 
| using System; | 
| using System.Collections.Specialized; | 
| using System.IO; | 
| using System.Net; | 
| using System.Security.Principal; | 
| using System.Text; | 
|   | 
| namespace WebSocketSharp.Net { | 
|   | 
|     public sealed class HttpListenerContext { | 
|   | 
|         #region Private Fields | 
|   | 
|         HttpConnection       cnc; | 
|         string               error; | 
|         int                  err_status; | 
|         HttpListenerRequest  request; | 
|         HttpListenerResponse response; | 
|         IPrincipal           user; | 
|   | 
|         #endregion | 
|   | 
|         #region Internal Fields | 
|   | 
|         internal HttpListener Listener; | 
|   | 
|         #endregion | 
|   | 
|         #region Constructor | 
|   | 
|         internal HttpListenerContext (HttpConnection cnc) | 
|         { | 
|             this.cnc   = cnc; | 
|             err_status = 400; | 
|             request    = new HttpListenerRequest (this); | 
|             response   = new HttpListenerResponse (this); | 
|         } | 
|   | 
|         #endregion | 
|   | 
|         #region Internal Properties | 
|   | 
|         internal HttpConnection Connection { | 
|             get { return cnc; } | 
|         } | 
|   | 
|         internal string ErrorMessage { | 
|             get { return error; } | 
|             set { error = value; } | 
|         } | 
|   | 
|         internal int ErrorStatus { | 
|             get { return err_status; } | 
|             set { err_status = value; } | 
|         } | 
|   | 
|         internal bool HaveError { | 
|             get { return (error != null); } | 
|         } | 
|   | 
|         #endregion | 
|   | 
|         #region Public Properties | 
|   | 
|         public HttpListenerRequest Request { | 
|             get { return request; } | 
|         } | 
|   | 
|         public HttpListenerResponse Response { | 
|             get { return response; } | 
|         } | 
|   | 
|         public IPrincipal User { | 
|             get { return user; } | 
|         } | 
|   | 
|         #endregion | 
|   | 
|         #region Internal Methods | 
|   | 
|         internal void ParseAuthentication (AuthenticationSchemes expectedSchemes) | 
|         { | 
|             if (expectedSchemes == AuthenticationSchemes.Anonymous) | 
|                 return; | 
|   | 
|             // TODO: Handle NTLM/Digest modes | 
|             string header = request.Headers ["Authorization"]; | 
|             if (header == null || header.Length < 2) | 
|                 return; | 
|   | 
|             string [] authenticationData = header.Split (new char [] {' '}, 2); | 
|             if (string.Compare (authenticationData [0], "basic", true) == 0) { | 
|                 user = ParseBasicAuthentication (authenticationData [1]); | 
|             } | 
|             // TODO: throw if malformed -> 400 bad request | 
|         } | 
|      | 
|         internal IPrincipal ParseBasicAuthentication (string authData) | 
|         { | 
|             try { | 
|                 // Basic AUTH Data is a formatted Base64 String | 
|                 //string domain = null; | 
|                 string user       = null; | 
|                 string password   = null; | 
|                 int    pos        = -1; | 
|                 string authString = Encoding.Default.GetString (Convert.FromBase64String (authData)); | 
|      | 
|                 // The format is DOMAIN\username:password | 
|                 // Domain is optional | 
|   | 
|                 pos = authString.IndexOf (':'); | 
|      | 
|                 // parse the password off the end | 
|                 password = authString.Substring (pos+1); | 
|                  | 
|                 // discard the password | 
|                 authString = authString.Substring (0, pos); | 
|      | 
|                 // check if there is a domain | 
|                 pos = authString.IndexOf ('\\'); | 
|      | 
|                 if (pos > 0) { | 
|                     //domain = authString.Substring (0, pos); | 
|                     user = authString.Substring (pos); | 
|                 } else { | 
|                     user = authString; | 
|                 } | 
|      | 
|                 HttpListenerBasicIdentity identity = new HttpListenerBasicIdentity (user, password); | 
|                 // TODO: What are the roles MS sets | 
|                 return new GenericPrincipal (identity, new string [0]); | 
|             } catch (Exception) { | 
|                 // Invalid auth data is swallowed silently | 
|                 return null; | 
|             }  | 
|         } | 
|   | 
|         #endregion | 
|   | 
|         #region Public Method | 
|   | 
|         public HttpListenerWebSocketContext AcceptWebSocket () | 
|         { | 
|             return new HttpListenerWebSocketContext (this); | 
|         } | 
|   | 
|         #endregion | 
|     } | 
| } |