private byte[] OKResponse (OSHttpResponse httpResponse) { httpResponse.AddHeader ("X-Handlers-Provided", m_HandlersType); httpResponse.StatusCode = (int)HttpStatusCode.OK; httpResponse.StatusDescription = "OK"; return new byte[0]; }
/// <summary> /// Invoked by OSHttpRequestPump. /// </summary> public override OSHttpHandlerResult Process(OSHttpRequest request) { // call handler method Hashtable responseData = _handler(request.Query); int responseCode = (int)responseData["int_response_code"]; string responseString = (string)responseData["str_response_string"]; string contentType = (string)responseData["content_type"]; //Even though only one other part of the entire code uses HTTPHandlers, we shouldn't expect this //and should check for NullReferenceExceptions if (string.IsNullOrEmpty(contentType)) { contentType = "text/html"; } OSHttpResponse response = new OSHttpResponse(request); // We're forgoing the usual error status codes here because the client // ignores anything but 200 and 301 response.StatusCode = (int)OSHttpStatusCode.SuccessOk; if (responseCode == (int)OSHttpStatusCode.RedirectMovedPermanently) { response.RedirectLocation = (string)responseData["str_redirect_location"]; response.StatusCode = responseCode; } response.AddHeader("Content-type", contentType); byte[] buffer; if (!contentType.Contains("image")) { buffer = Encoding.UTF8.GetBytes(responseString); } else { buffer = Convert.FromBase64String(responseString); } response.SendChunked = false; response.ContentLength64 = buffer.Length; response.ContentEncoding = Encoding.UTF8; try { response.Body.Write(buffer, 0, buffer.Length); } catch (Exception ex) { _log.ErrorFormat("[OSHttp Http Handler]: Error: {0}", ex.Message); } finally { response.Send(); } return(OSHttpHandlerResult.Done); }
byte[] OptionsHandler(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) { httpResponse.AddHeader("DAV", "2"); httpResponse.AddHeader("MS-Author-Via", "DAV"); //This now gets all the events that have handler from the dav listener string allowString = server.GetAvailableMethods(); //Add this information to both, Public and Allow. We currently have no way of separating these two httpResponse.AddHeader("Public", allowString); httpResponse.AddHeader("Allow", allowString); //Preserving the old headers as reference. These should be removed when method is mature enough //response.AddHeader("Public", "COPY, DELETE, GET, HEAD, MKCOL, MOVE, OPTIONS, PROPFIND, PROPPATCH, PUT"); //response.AddHeader("Allow", "COPY, DELETE, GET, HEAD, MKCOL, MOVE, OPTIONS, PROPFIND, PROPPATCH, PUT"); return OpenMetaverse.Utils.EmptyBytes; }
private void WriteTextureData(OSHttpRequest request, OSHttpResponse response, AssetBase texture, string format) { string range = request.Headers.GetOne("Range"); //m_log.DebugFormat("[GETTEXTURE]: Range {0}", range); if (!String.IsNullOrEmpty(range)) // JP2's only { // Range request int start, end; if (TryParseRange(range, out start, out end)) { // Before clamping start make sure we can satisfy it in order to avoid // sending back the last byte instead of an error status if (start >= texture.Data.Length) { response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable; return; } end = Utils.Clamp(end, 0, texture.Data.Length - 1); start = Utils.Clamp(start, 0, end); int len = end - start + 1; //m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID); if (len < texture.Data.Length) response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent; response.ContentLength = len; response.ContentType = texture.Metadata.ContentType; response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length)); response.Body.Write(texture.Data, start, len); } else { m_log.Warn("[GETTEXTURE]: Malformed Range header: " + range); response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest; } } else // JP2's or other formats { // Full content request response.StatusCode = (int)System.Net.HttpStatusCode.OK; response.ContentLength = texture.Data.Length; if (format == DefaultFormat) response.ContentType = texture.Metadata.ContentType; else response.ContentType = "image/" + format; response.Body.Write(texture.Data, 0, texture.Data.Length); } }
public byte[] Handle(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) { byte[] assetData = null; UUID assetID; // Split the URL up into an AssetID and a method string[] rawUrl = httpRequest.Url.PathAndQuery.Split('/'); if (rawUrl.Length >= 3 && UUID.TryParse(rawUrl[1], out assetID)) { UUID authToken = Utils.GetAuthToken(httpRequest); if (m_server.AuthorizationProvider.IsDataAuthorized(authToken, assetID)) { BackendResponse storageResponse = m_server.StorageProvider.TryFetchData(assetID, out assetData); if (storageResponse == BackendResponse.Success) { httpResponse.StatusCode = (int) HttpStatusCode.OK; httpResponse.ContentType = "application/octet-stream"; httpResponse.AddHeader("Content-Disposition", "attachment; filename=" + assetID.ToString()); httpResponse.ContentLength = assetData.Length; httpResponse.Body.Write(assetData, 0, assetData.Length); } else if (storageResponse == BackendResponse.NotFound) { httpResponse.StatusCode = (int) HttpStatusCode.NotFound; } else { httpResponse.StatusCode = (int) HttpStatusCode.InternalServerError; } } else { httpResponse.StatusCode = (int) HttpStatusCode.Forbidden; } return assetData; } httpResponse.StatusCode = (int) HttpStatusCode.BadRequest; return assetData; }
internal void DoHTTPGruntWork(Hashtable responsedata, OSHttpResponse response) { //m_log.Info("[BASE HTTP SERVER]: Doing HTTP Grunt work with response"); int responsecode = (int)responsedata["int_response_code"]; string responseString = (string)responsedata["str_response_string"]; string contentType = (string)responsedata["content_type"]; if (responsedata.ContainsKey("error_status_text")) { response.StatusDescription = (string)responsedata["error_status_text"]; } if (responsedata.ContainsKey("http_protocol_version")) { response.ProtocolVersion = (string)responsedata["http_protocol_version"]; } if (responsedata.ContainsKey("keepalive")) { bool keepalive = (bool)responsedata["keepalive"]; response.KeepAlive = keepalive; } if (responsedata.ContainsKey("reusecontext")) response.ReuseContext = (bool) responsedata["reusecontext"]; // Cross-Origin Resource Sharing with simple requests if (responsedata.ContainsKey("access_control_allow_origin")) response.AddHeader("Access-Control-Allow-Origin", (string)responsedata["access_control_allow_origin"]); //Even though only one other part of the entire code uses HTTPHandlers, we shouldn't expect this //and should check for NullReferenceExceptions if (string.IsNullOrEmpty(contentType)) { contentType = "text/html"; } // The client ignores anything but 200 here for web login, so ensure that this is 200 for that response.StatusCode = responsecode; if (responsecode == (int)OSHttpStatusCode.RedirectMovedPermanently) { response.RedirectLocation = (string)responsedata["str_redirect_location"]; response.StatusCode = responsecode; } response.AddHeader("Content-Type", contentType); byte[] buffer; if (!(contentType.Contains("image") || contentType.Contains("x-shockwave-flash") || contentType.Contains("application/x-oar") || contentType.Contains("application/vnd.ll.mesh"))) { // Text buffer = Encoding.UTF8.GetBytes(responseString); } else { // Binary! buffer = Convert.FromBase64String(responseString); } response.SendChunked = false; response.ContentLength64 = buffer.Length; response.ContentEncoding = Encoding.UTF8; try { response.OutputStream.Write(buffer, 0, buffer.Length); } catch (Exception ex) { m_log.Warn("[HTTPD]: Error - " + ex.Message); } finally { //response.OutputStream.Close(); try { response.OutputStream.Flush(); response.Send(); //if (!response.KeepAlive && response.ReuseContext) // response.FreeContext(); } catch (SocketException e) { // This has to be here to prevent a Linux/Mono crash m_log.WarnFormat("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e); } catch (IOException e) { m_log.Warn("[BASE HTTP SERVER]: XmlRpcRequest issue: " + e.Message); } } }
internal byte[] DoHTTPGruntWork(Hashtable responsedata, OSHttpResponse response) { //m_log.Info("[BASE HTTP SERVER]: Doing HTTP Grunt work with response"); int responsecode = (int)responsedata["int_response_code"]; string responseString = (string)responsedata["str_response_string"]; string contentType = (string)responsedata["content_type"]; if (responsedata.ContainsKey("error_status_text")) { response.StatusDescription = (string)responsedata["error_status_text"]; } if (responsedata.ContainsKey("http_protocol_version")) { response.ProtocolVersion = (string)responsedata["http_protocol_version"]; } if (responsedata.ContainsKey("keepalive")) { bool keepalive = (bool)responsedata["keepalive"]; response.KeepAlive = keepalive; } if (responsedata.ContainsKey("reusecontext")) response.ReuseContext = (bool) responsedata["reusecontext"]; // Cross-Origin Resource Sharing with simple requests if (responsedata.ContainsKey("access_control_allow_origin")) response.AddHeader("Access-Control-Allow-Origin", (string)responsedata["access_control_allow_origin"]); //Even though only one other part of the entire code uses HTTPHandlers, we shouldn't expect this //and should check for NullReferenceExceptions if (string.IsNullOrEmpty(contentType)) { contentType = "text/html"; } // The client ignores anything but 200 here for web login, so ensure that this is 200 for that response.StatusCode = responsecode; if (responsecode == (int)OSHttpStatusCode.RedirectMovedPermanently) { response.RedirectLocation = (string)responsedata["str_redirect_location"]; response.StatusCode = responsecode; } response.AddHeader("Content-Type", contentType); byte[] buffer; if (!(contentType.Contains("image") || contentType.Contains("x-shockwave-flash") || contentType.Contains("application/x-oar") || contentType.Contains("application/vnd.ll.mesh"))) { // Text buffer = Encoding.UTF8.GetBytes(responseString); } else { // Binary! buffer = Convert.FromBase64String(responseString); } response.SendChunked = false; response.ContentLength64 = buffer.Length; response.ContentEncoding = Encoding.UTF8; return buffer; }
public byte[] SendHTML500(OSHttpResponse response) { response.StatusCode = (int)OSHttpStatusCode.ServerErrorInternalError; response.AddHeader("Content-type", "text/html"); string responseString = GetHTTP500(); byte[] buffer = Encoding.UTF8.GetBytes(responseString); response.SendChunked = false; response.ContentLength64 = buffer.Length; response.ContentEncoding = Encoding.UTF8; return buffer; }
public byte[] DoHTTPGruntWork(Hashtable responsedata, OSHttpRequest request, OSHttpResponse response) { //m_log.Info("[BASE HTTP SERVER]: Doing HTTP Grunt work with response"); int responsecode = (int)responsedata["int_response_code"]; string responseString = (string)responsedata["str_response_string"]; string contentType = (string)responsedata["content_type"]; byte[] responseBinary = responsedata.Contains("response_binary") ? (byte[])responsedata["response_binary"] : null; if (responsedata.ContainsKey("error_status_text")) { response.StatusDescription = (string)responsedata["error_status_text"]; } if (responsedata.ContainsKey("http_protocol_version")) { response.ProtocolVersion = new System.Version((string)responsedata["http_protocol_version"]); } if (responsedata.ContainsKey("keepalive")) { bool keepalive = (bool)responsedata["keepalive"]; response.KeepAlive = keepalive; } // Cross-Origin Resource Sharing with simple requests if (responsedata.ContainsKey("access_control_allow_origin")) response.AddHeader("Access-Control-Allow-Origin", (string)responsedata["access_control_allow_origin"]); // The client ignores anything but 200 here for web login, so ensure that this is 200 for that response.StatusCode = responsecode; if (responsecode == (int)OSHttpStatusCode.RedirectMovedPermanently) { response.RedirectLocation = (string)responsedata["str_redirect_location"]; response.StatusCode = responsecode; } if (string.IsNullOrEmpty(contentType)) contentType = "text/html"; response.AddHeader("Content-Type", contentType); byte[] buffer; if (responseBinary != null) { buffer = responseBinary; } else { if (!(contentType.Contains("image") || contentType.Contains("x-shockwave-flash") || contentType.Contains("application/x-oar") || contentType.Contains("application/vnd.ll.mesh"))) { // Text buffer = Encoding.UTF8.GetBytes(responseString); } else { // Binary! buffer = Convert.FromBase64String(responseString); } } response.SendChunked = false; response.ContentLength64 = buffer.LongLength; response.ContentEncoding = System.Text.Encoding.UTF8; return buffer; }
public static void OpenAuthResponseToHttp(OSHttpResponse httpResponse, OutgoingWebResponse openAuthResponse) { httpResponse.StatusCode = (int)openAuthResponse.Status; foreach (string key in openAuthResponse.Headers.Keys) httpResponse.AddHeader(key, openAuthResponse.Headers[key]); if (!String.IsNullOrEmpty(openAuthResponse.Body)) AddToBody(httpResponse, openAuthResponse.Body); }
/*public static void OpenAuthResponseToHttp(OSHttpResponse httpResponse, OutgoingWebResponse openAuthResponse) { httpResponse.StatusCode = (int)openAuthResponse.Status; foreach (string key in openAuthResponse.Headers.Keys) httpResponse.AddHeader(key, openAuthResponse.Headers[key]); if (!String.IsNullOrEmpty(openAuthResponse.Body)) AddToBody(httpResponse, openAuthResponse.Body); }*/ public static byte[] MakeOpenAuthResponse(OSHttpResponse httpResponse, OutgoingWebResponse openAuthResponse) { httpResponse.StatusCode = (int)openAuthResponse.Status; foreach (string key in openAuthResponse.Headers.Keys) httpResponse.AddHeader(key, openAuthResponse.Headers[key]); if (!String.IsNullOrEmpty(openAuthResponse.Body)) return Encoding.UTF8.GetBytes(openAuthResponse.Body); else return Utils.EmptyBytes; }
/// <summary> /// Returns information about a mumble server via a REST Request /// </summary> /// <param name="request"></param> /// <param name="path"></param> /// <param name="param">A string representing the sim's UUID</param> /// <param name="httpRequest">HTTP request header object</param> /// <param name="httpResponse">HTTP response header object</param> /// <returns>Information about the mumble server in http response headers</returns> public string RestGetMumbleServerInfo(Scene scene, string request, string path, string param, OSHttpRequest httpRequest, OSHttpResponse httpResponse) { if (m_murmurd_host == null) { httpResponse.StatusCode = 404; httpResponse.StatusDescription = "Not Found"; string message = "[MurmurVoice]: Server info request from " + httpRequest.RemoteIPEndPoint.Address + ". Cannot send response, module is not configured properly."; m_log.Warn(message); return "Mumble server info is not available."; } if (httpRequest.Headers.GetValues("avatar_uuid") == null) { httpResponse.StatusCode = 400; httpResponse.StatusDescription = "Bad Request"; string message = "[MurmurVoice]: Invalid server info request from " + httpRequest.RemoteIPEndPoint.Address + ""; m_log.Warn(message); return "avatar_uuid header is missing"; } string avatar_uuid = httpRequest.Headers.GetValues("avatar_uuid")[0]; string responseBody = String.Empty; UUID avatarId; if (UUID.TryParse(avatar_uuid, out avatarId)) { if (scene == null) throw new Exception("[MurmurVoice] Invalid scene."); ServerManager manager = GetServerManager(scene); Agent agent = manager.Agent.GetOrCreate(avatarId, scene); string channel_uri; ScenePresence avatar = scene.GetScenePresence(avatarId); // get channel_uri: check first whether estate // settings allow voice, then whether parcel allows // voice, if all do retrieve or obtain the parcel // voice channel LandData land = scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); if (null == land) throw new Exception(String.Format("region \"{0}\": avatar \"{1}\": land data not yet available", scene.RegionInfo.RegionName, avatar.Name)); m_log.DebugFormat("[MurmurVoice] region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}", scene.RegionInfo.RegionName, land.Name, land.LocalID, avatar.Name, request, path, param); if (((land.Flags & (uint)ParcelFlags.AllowVoiceChat) > 0) && scene.RegionInfo.EstateSettings.AllowVoice) { agent.channel = manager.Channel.GetOrCreate(ChannelName(scene, land)); // Host/port pair for voice server channel_uri = String.Format("{0}:{1}", m_murmurd_host, m_murmurd_port); if (agent.session > 0) { Murmur.User state = manager.Server.getState(agent.session); GetServerCallback(scene).AddUserToChan(state, agent.channel); } m_log.InfoFormat("[MurmurVoice] {0}", channel_uri); } else { m_log.DebugFormat("[MurmurVoice] Voice not enabled."); channel_uri = ""; } string m_context = "Mumble voice system"; httpResponse.AddHeader("Mumble-Server", m_murmurd_host); httpResponse.AddHeader("Mumble-Version", m_server_version); httpResponse.AddHeader("Mumble-Channel", channel_uri); httpResponse.AddHeader("Mumble-User", avatar_uuid); httpResponse.AddHeader("Mumble-Password", agent.pass); httpResponse.AddHeader("Mumble-Avatar-Id", avatar_uuid); httpResponse.AddHeader("Mumble-Context-Id", m_context); responseBody += "Mumble-Server: " + m_murmurd_host + "\n"; responseBody += "Mumble-Version: " + m_server_version + "\n"; responseBody += "Mumble-Channel: " + channel_uri + "\n"; responseBody += "Mumble-User: "******"\n"; responseBody += "Mumble-Password: "******"\n"; responseBody += "Mumble-Avatar-Id: " + avatar_uuid + "\n"; responseBody += "Mumble-Context-Id: " + m_context + "\n"; string log_message = "[MurmurVoice]: Server info request handled for " + httpRequest.RemoteIPEndPoint.Address + ""; m_log.Info(log_message); } else { httpResponse.StatusCode = 400; httpResponse.StatusDescription = "Bad Request"; m_log.Warn("[MurmurVoice]: Could not parse avatar uuid from request"); return "could not parse avatar_uuid header"; } return responseBody; }
byte[] LockHandler(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) { string username; if (server.AuthenticateRequest(httpRequest, httpResponse, out username)) { WebDAVLockRequest lockRequest = ParseRequest(httpRequest); WebDAVLockResponse lockResponse = server.OnLockConnector(lockRequest); if (lockResponse == null) { httpResponse.StatusCode = (int)HttpStatusCode.InternalServerError; return OpenMetaverse.Utils.EmptyBytes; } if (lockResponse.HttpStatusCode == HttpStatusCode.OK || lockResponse.HttpStatusCode == HttpStatusCode.Created) { using (MemoryStream responseStream = new MemoryStream()) { using (XmlTextWriter xmlWriter = new XmlTextWriter(responseStream, Encoding.ASCII)) { xmlWriter.Formatting = Formatting.Indented; xmlWriter.IndentChar = '\t'; xmlWriter.Indentation = 1; xmlWriter.WriteStartDocument(); xmlWriter.WriteStartElement("D", "prop", "DAV:"); xmlWriter.WriteStartElement("lockdiscovery", "DAV:"); xmlWriter.WriteStartElement("activelock", "DAV:"); xmlWriter.WriteStartElement("locktype", "DAV:"); xmlWriter.WriteElementString(Enum.GetName(typeof(LockType), lockResponse.LockType), "DAV:", String.Empty); //only legal value available. future extensions might support others xmlWriter.WriteEndElement(); //locktype xmlWriter.WriteStartElement("lockscope", "DAV:"); xmlWriter.WriteElementString(Enum.GetName(typeof(LockScope), lockResponse.LockScope), "DAV:", String.Empty); //possible values "exclusive" or "shared" xmlWriter.WriteEndElement(); //lockscope xmlWriter.WriteStartElement("depth", "DAV:"); xmlWriter.WriteValue(lockResponse.Depth); xmlWriter.WriteEndElement(); //depth //The server must save this identifier and return it in the lockdiscovery property so that other users and other client software can see some information about the lock creator. xmlWriter.WriteStartElement("owner", "DAV:"); if (lockResponse.OwnerNamespaceUri != null && lockResponse.OwnerNamespaceUri != String.Empty) { xmlWriter.WriteAttributeString("xmlns:a", lockResponse.OwnerNamespaceUri); } if (lockResponse.OwnerValue != null && lockResponse.OwnerValue != String.Empty) { xmlWriter.WriteValue(lockResponse.OwnerValue); } else { foreach (KeyValuePair<string, string> kvp in lockResponse.OwnerValues) { xmlWriter.WriteElementString(kvp.Key, "DAV:", kvp.Value); } } //xmlWriter.WriteElementString("lock-user", "DAV:", username); //xmlWriter.WriteElementString("created-by", "DAV:", "Some user"); xmlWriter.WriteEndElement(); //owner xmlWriter.WriteElementString("timeout", "DAV:", lockResponse.Timeout); xmlWriter.WriteStartElement("locktoken", "DAV:"); xmlWriter.WriteElementString("href", "DAV:", lockResponse.LockToken); xmlWriter.WriteEndElement(); httpResponse.AddHeader("Lock-Token", lockResponse.LockToken); //add lock token also to header xmlWriter.WriteEndElement(); //activelock xmlWriter.WriteEndElement(); //lockdiscovery xmlWriter.WriteEndElement(); //prop xmlWriter.WriteEndDocument(); xmlWriter.Flush(); httpResponse.StatusCode = (int)lockResponse.HttpStatusCode; byte[] bytes = responseStream.ToArray(); httpResponse.ContentLength = bytes.Length; return bytes; } } } else { httpResponse.StatusCode = (int)lockResponse.HttpStatusCode; return OpenMetaverse.Utils.EmptyBytes; } } return OpenMetaverse.Utils.EmptyBytes; }
internal byte[] srvDoHTTPGruntWork(Hashtable responsedata, OSHttpResponse response) { int responsecode; string responseString = String.Empty; byte[] responseData = null; string contentType; if (responsedata == null) { responsecode = 500; responseString = "No response could be obtained"; contentType = "text/plain"; responsedata = new Hashtable(); } else { try { //m_log.Info("[BASE HTTP SERVER]: Doing HTTP Grunt work with response"); responsecode = (int)responsedata["int_response_code"]; if (responsedata["bin_response_data"] != null) { responseData = (byte[])responsedata["bin_response_data"]; } else { responseString = (string)responsedata["str_response_string"]; } contentType = (string)responsedata["content_type"]; if (responseString == null) { responseString = String.Empty; } } catch { responsecode = 500; responseString = "No response could be obtained"; contentType = "text/plain"; responsedata = new Hashtable(); } } if (responsedata.ContainsKey("error_status_text")) { response.StatusDescription = (string)responsedata["error_status_text"]; } if (responsedata.ContainsKey("http_protocol_version")) { response.ProtocolVersion = (string)responsedata["http_protocol_version"]; } if (responsedata.ContainsKey("keepalive")) { bool keepalive = (bool)responsedata["keepalive"]; response.KeepAlive = keepalive; } // Cross-Origin Resource Sharing with simple requests if (responsedata.ContainsKey("access_control_allow_origin")) { response.AddHeader("Access-Control-Allow-Origin", (string)responsedata["access_control_allow_origin"]); } //Even though only one other part of the entire code uses HTTPHandlers, we shouldn't expect this //and should check for NullReferenceExceptions if (string.IsNullOrEmpty(contentType)) { contentType = "text/html"; } // The client ignores anything but 200 here for web login, so ensure that this is 200 for that response.StatusCode = responsecode; if (responsecode == (int)OSHttpStatusCode.RedirectMovedPermanently) { response.RedirectLocation = (string)responsedata["str_redirect_location"]; response.StatusCode = responsecode; } response.AddHeader("Content-Type", contentType); if (responsedata.ContainsKey("headers")) { Hashtable headerdata = (Hashtable)responsedata["headers"]; foreach (string header in headerdata.Keys) { response.AddHeader(header, headerdata[header].ToString()); } } byte[] buffer; if (responseData != null) { buffer = responseData; } else { if (!(contentType.Contains("image") || contentType.Contains("x-shockwave-flash") || contentType.Contains("application/x-oar") || contentType.Contains("application/vnd.ll.mesh"))) { // Text buffer = Encoding.UTF8.GetBytes(responseString); } else { // Binary! buffer = Convert.FromBase64String(responseString); } response.SendChunked = false; response.ContentLength64 = buffer.Length; response.ContentEncoding = Encoding.UTF8; } return(buffer); }
void OpenIDLoginGetHandler(OSHttpRequest httpRequest, OSHttpResponse httpResponse) { if (httpRequest.Url.AbsolutePath.EndsWith("openid_callback")) { #region OpenID Callback IAuthenticationResponse authResponse = CableBeachState.RelyingParty.GetResponse(OpenAuthHelper.GetRequestInfo(httpRequest)); if (authResponse != null) { if (authResponse.Status == AuthenticationStatus.Authenticated) { // OpenID authentication succeeded Uri identity = new Uri(authResponse.ClaimedIdentifier.ToString()); // Check if this identity is authorized for access. This check is done here for the second time // because the ClaimedIdentifier after authentication has finished is not necessarily the original // OpenID URL entered into the login form if (CableBeachState.IsIdentityAuthorized(identity)) { string firstName = null, lastName = null, email = null; // Get the Simple Registration attributes the IDP returned, if any ClaimsResponse sreg = authResponse.GetExtension<ClaimsResponse>(); if (sreg != null) { if (!String.IsNullOrEmpty(sreg.FullName)) { string[] firstLast = sreg.FullName.Split(' '); if (firstLast.Length == 2) { firstName = firstLast[0]; lastName = firstLast[1]; } } email = sreg.Email; } CableBeachState.StartLogin(httpRequest, httpResponse, identity, firstName, lastName, email, CableBeachAuthMethods.OPENID); } else { CableBeachState.SendLoginTemplate(httpResponse, null, identity + " is not authorized to access this world"); } } else { // Parse an error message out of authResponse string errorMsg = (authResponse.Exception != null) ? authResponse.Exception.Message : authResponse.Status.ToString(); CableBeachState.SendLoginTemplate(httpResponse, null, errorMsg); } } else { httpResponse.StatusCode = (int)HttpStatusCode.BadRequest; OpenAuthHelper.AddToBody(httpResponse, "Invalid or missing OpenID callback data"); } #endregion OpenID Callback } else if (httpRequest.Url.AbsolutePath.EndsWith("oauth_callback")) { #region OAuth Callback ServiceRequestsData stateData; string requestToken = OpenAuthHelper.GetQueryValue(httpRequest.Url.Query, "oauth_token"); if (!String.IsNullOrEmpty(requestToken) && CableBeachState.CurrentServiceRequests.TryGetValue(requestToken, out stateData)) { ServiceIdentifier serviceIdentifier = CableBeachState.GetCurrentService(stateData.ServiceRequirements); Service service; CapabilityRequirements capRequirements; if (serviceIdentifier != null) { if (stateData.Services.TryGetValue(serviceIdentifier, out service) && stateData.ServiceRequirements.TryGetValue(serviceIdentifier, out capRequirements)) { try { OAuthConsumer consumer = new OAuthConsumer(OpenAuthHelper.CreateServiceProviderDescription(service), CableBeachState.OAuthTokenManager); AuthorizedTokenResponse tokenResponse = consumer.ProcessUserAuthorization(OpenAuthHelper.GetRequestInfo(httpRequest)); // We actually don't need the access token at all since the capabilities should be in this response. // Parse the capabilities out of ExtraData CapabilityRequirements newCaps = new CapabilityRequirements(); foreach (KeyValuePair<string, string> capability in tokenResponse.ExtraData) { Uri capIdentifier, capUri; if (Uri.TryCreate(capability.Key, UriKind.Absolute, out capIdentifier) && Uri.TryCreate(capability.Value, UriKind.Absolute, out capUri)) { newCaps[capIdentifier] = capUri; } } m_log.Info("[CABLE BEACH LOGIN]: Fetched " + newCaps.Count + " capabilities through OAuth from " + service.OAuthGetAccessToken); // Update the capabilities for this service stateData.ServiceRequirements[serviceIdentifier] = newCaps; } catch (Exception ex) { m_log.Error("[CABLE BEACH LOGIN]: Failed to exchange request token for capabilities at " + service.OAuthGetAccessToken + ": " + ex.Message); CableBeachState.SendLoginTemplate(httpResponse, null, "OAuth request to " + service.OAuthGetAccessToken + " failed: " + ex.Message); return; } } else { m_log.Error("[CABLE BEACH LOGIN]: OAuth state data corrupted, could not find service or service requirements for " + serviceIdentifier); CableBeachState.SendLoginTemplate(httpResponse, null, "OAuth state data corrupted, please try again"); return; } } else { m_log.Warn("[CABLE BEACH LOGIN]: OAuth callback fired but there are no unfulfilled services. Could be a browser refresh"); } // Check if we need to continue the cap requesting process CableBeachState.GetCapabilitiesOrCompleteLogin(httpRequest, httpResponse, stateData, requestToken); } else { // A number of different things could lead here (incomplete login sequence, browser refresh of a completed sequence). // Safest thing to do would be to redirect back to the login screen httpResponse.StatusCode = (int)HttpStatusCode.Found; httpResponse.AddHeader("Location", new Uri(CableBeachState.UserServerUrl, "/login/").ToString()); } #endregion OAuth Callback } else { // Make sure we are starting from the correct URL if (httpRequest.Url.Authority != CableBeachState.UserServerUrl.Authority) { m_log.Debug("[CABLE BEACH LOGIN]: Redirecting from " + httpRequest.Url + " to " + CableBeachState.UserServerUrl); httpResponse.StatusCode = (int)HttpStatusCode.Redirect; httpResponse.RedirectLocation = new Uri(CableBeachState.UserServerUrl, "/login/").ToString(); } else if (httpRequest.Query.ContainsKey("openid_identifier")) { OpenIDLoginFormHandler(httpRequest, httpResponse, httpRequest.Query["openid_identifier"] as string); } else { // TODO: Check for a client cookie with an authenticated session CableBeachState.SendLoginTemplate(httpResponse, null, null); } } }
byte[] PropFindHandler(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) { string username; if (server.AuthenticateRequest(httpRequest, httpResponse, out username)) { //PropertyRequestType requestType = PropertyRequestType.AllProperties; List<string> davProperties = new List<string>(); List<string> validProperties = new List<string>(); List<string> invalidProperties = new List<string>(); if (httpRequest.ContentLength != 0) { XPathNavigator requestNavigator = new XPathDocument(httpRequest.InputStream).CreateNavigator(); XPathNodeIterator propNodeIterator = requestNavigator.SelectDescendants("prop", "DAV:", false); if (propNodeIterator.MoveNext()) { XPathNodeIterator nodeChildren = propNodeIterator.Current.SelectChildren(XPathNodeType.All); while (nodeChildren.MoveNext()) { XPathNavigator currentNode = nodeChildren.Current; if (currentNode.NodeType == XPathNodeType.Element) davProperties.Add(currentNode.LocalName.ToLower()); } } } using (MemoryStream responseStream = new MemoryStream()) { using (XmlTextWriter xmlWriter = new XmlTextWriter(responseStream, Encoding.ASCII)) { xmlWriter.Formatting = Formatting.Indented; xmlWriter.IndentChar = '\t'; xmlWriter.Indentation = 1; xmlWriter.WriteStartDocument(); xmlWriter.WriteStartElement("D", "multistatus", "DAV:"); // Microsoft cruft (joy) xmlWriter.WriteAttributeString("xmlns:b", "urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882"); xmlWriter.WriteAttributeString("xmlns:c", "urn:schemas-microsoft-com:office:office"); DepthHeader depth = Depth.ParseDepth(httpRequest); IList<IWebDAVResource> resources = server.OnPropFindConnector(username, httpRequest.Url.AbsolutePath, depth); if (resources.Count > 0) { for (int i = 0; i < resources.Count; i++) XmlResponse.WriteResponse(xmlWriter, davProperties, resources[i]); } xmlWriter.WriteEndElement(); // multistatus xmlWriter.WriteEndDocument(); xmlWriter.Flush(); httpResponse.KeepAlive = httpRequest.KeepAlive; httpResponse.ContentType = "text/xml"; httpResponse.ContentEncoding = Encoding.UTF8; httpResponse.AddHeader("DAV", "1"); httpResponse.AddHeader("MS-Author-Via", "DAV"); httpResponse.AddHeader("Cache-Control", "no-cache"); if (resources.Count > 0) { httpResponse.StatusCode = 207; // Multistatus byte[] bytes = responseStream.ToArray(); httpResponse.ContentLength = bytes.Length; return bytes; } else { //eventually this should be the same that is defined in HttpListener.Set404Handler() //that however needs some work in HttpServer httpResponse.StatusCode = (int)HttpStatusCode.NotFound; httpResponse.StatusDescription = "Not Found"; string notFoundResponse = "<html><head><title>Page Not Found</title></head><body><h3>" + httpResponse.StatusDescription + "</h3></body></html>"; byte[] buffer = System.Text.Encoding.UTF8.GetBytes(notFoundResponse); httpResponse.ContentLength = buffer.Length; return buffer; } } } } return OpenMetaverse.Utils.EmptyBytes; }
/// <summary> /// Handles all GET and POST requests for Facebook Connect logins /// </summary> public void Handle(string requestPath, Stream request, Stream response, OSHttpRequest httpRequest, OSHttpResponse httpResponse) { if (!CanHandle(httpRequest.Url)) { httpResponse.StatusCode = (int)HttpStatusCode.NotFound; OpenAuthHelper.AddToBody(httpResponse, "File not found"); return; } try { string path = GetPath(httpRequest.Url); string extension = GetFileExtension(path); if (extension == null) { httpResponse.StatusCode = (int)HttpStatusCode.UnsupportedMediaType; OpenAuthHelper.AddToBody(httpResponse, "Unsupported media type"); return; } if (m_mimeTypes.ContainsKey(extension)) { httpResponse.ContentType = m_mimeTypes[extension]; } else { httpResponse.StatusCode = (int)HttpStatusCode.UnsupportedMediaType; OpenAuthHelper.AddToBody(httpResponse, "Unsupported media type"); return; } using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { if (!String.IsNullOrEmpty(httpRequest.Headers["if-modified-since"])) { DateTime lastRequest = DateTime.Parse(httpRequest.Headers["if-modified-since"]); if (lastRequest.CompareTo(File.GetLastWriteTime(path)) <= 0) httpResponse.StatusCode = (int)HttpStatusCode.NotModified; } httpResponse.AddHeader("Last-modified", File.GetLastWriteTime(path).ToString("r")); httpResponse.ContentLength = stream.Length; if (!httpRequest.HttpMethod.Equals("HEADERS", StringComparison.InvariantCultureIgnoreCase) && httpResponse.StatusCode != (int)HttpStatusCode.NotModified) { OpenAuthHelper.CopyTo(stream, httpResponse.OutputStream, (int)stream.Length); } } } catch (FileNotFoundException) { httpResponse.StatusCode = (int)HttpStatusCode.NotFound; OpenAuthHelper.AddToBody(httpResponse, "File not found"); } }
private void WriteTextureData(OSHttpRequest request, OSHttpResponse response, AssetBase texture, string format) { m_service.Registry.RequestModuleInterface<ISimulationBase>().EventManager.FireGenericEventHandler( "AssetRequested", new object[] {m_service.Registry, texture, m_service.AgentID}); string range = request.Headers.GetOne("Range"); //MainConsole.Instance.DebugFormat("[GETTEXTURE]: Range {0}", range); if (!String.IsNullOrEmpty(range)) // JP2's only { // Range request int start, end; if (TryParseRange(range, out start, out end)) { // Before clamping start make sure we can satisfy it in order to avoid // sending back the last byte instead of an error status if (start >= texture.Data.Length) { response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable; } else { end = Utils.Clamp(end, 0, texture.Data.Length - 1); start = Utils.Clamp(start, 0, end); int len = end - start + 1; //MainConsole.Instance.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID); if (len < texture.Data.Length) response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent; else response.StatusCode = (int)System.Net.HttpStatusCode.OK; response.ContentLength = len; response.ContentType = texture.TypeString; response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length)); response.Body.Write(texture.Data, start, len); } } else { MainConsole.Instance.Warn("[GETTEXTURE]: Malformed Range header: " + range); response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest; } } else // JP2's or other formats { // Full content request response.StatusCode = (int)System.Net.HttpStatusCode.OK; response.ContentLength = texture.Data.Length; response.ContentType = texture.TypeString; if (format == DefaultFormat) response.ContentType = texture.TypeString; else response.ContentType = "image/" + format; response.Body.Write(texture.Data, 0, texture.Data.Length); } }
public byte[] SendHTML404(OSHttpResponse response) { response.StatusCode = 404; response.AddHeader("Content-type", "text/html"); string responseString = GetHTTP404(); byte[] buffer = Encoding.UTF8.GetBytes(responseString); response.SendChunked = false; response.ContentLength64 = buffer.Length; response.ContentEncoding = Encoding.UTF8; return buffer; }
private void SendChunk(OSHttpRequest request, OSHttpResponse response, int X, int Y) { string range = request.Headers.GetOne("Range"); //m_log.DebugFormat("[GETTEXTURE]: Range {0}", range); byte[] chunk = m_scene.Voxels.GetChunk(X, Y); if (!String.IsNullOrEmpty(range)) { // Range request int start, end; if (TryParseRange(range, out start, out end)) { // Before clamping start make sure we can satisfy it in order to avoid // sending back the last byte instead of an error status if (start >= chunk.Length) { response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable; return; } end = Utils.Clamp(end, 0, chunk.Length - 1); start = Utils.Clamp(start, 0, end); int len = end - start + 1; //m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID); if (len < chunk.Length) response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent; response.ContentLength = len; response.ContentType = "application/octet-stream"; response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, chunk.Length)); response.Body.Write(chunk, start, len); } else { m_log.Warn("Malformed Range header: " + range); response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest; } } else { // Full content request response.ContentLength = chunk.Length; response.ContentType = "application/octet-stream"; response.Body.Write(chunk, 0, chunk.Length); } }
public void SendResponse(OSHttpRequest request, OSHttpResponse response, IRequestHandler requestHandler, byte[] buffer) { try { request.InputStream.Close(); // Do not include the time taken to actually send the response to the caller in the measurement // time. This is to avoid logging when it's the client that is slow to process rather than the // server request.EndTime = Environment.TickCount; // Every month or so this will wrap and give bad numbers, not really a problem // since its just for reporting int tickdiff = request.EndTime - request.StartTime; // Dont log EQG messages. They always run long due to the way the queue works if ((tickdiff > 3000) && (request.Url.AbsolutePath.StartsWith("/CAPS/EQG") == false)) { m_log.InfoFormat( "[BASE HTTP SERVER]: Slow handling of {0} {1} {2} {3} {4} from {5} took {6}ms", request.SeqNo, request.HttpMethod, request.Url.AbsolutePath, requestHandler != null ? requestHandler.Name : "", requestHandler != null ? requestHandler.Description : "", request.RemoteIPEndPoint, tickdiff); } else if (DebugLevel >= 4) { m_log.DebugFormat( "[BASE HTTP SERVER]: HTTP IN {0} :{1} took {2}ms", request.SeqNo, Port, tickdiff); } if (buffer != null) { //find the accept encoding key string acceptEncodingKey = null; foreach (string key in request.Headers.AllKeys) { if (key.ToLower() == "accept-encoding") { acceptEncodingKey = request.Headers[key]; } } // GZip compress the response if the client says they can handle that if (acceptEncodingKey != null && request.Headers["accept-encoding"].Contains("gzip")) { using (MemoryStream ms = new MemoryStream()) { using (GZipStream gs = new GZipStream(ms, CompressionMode.Compress)) { gs.Write(buffer, 0, buffer.Length); } buffer = ms.ToArray(); } response.AddHeader("Content-Encoding", "gzip"); } if (!response.SendChunked) response.ContentLength64 = buffer.LongLength; response.OutputStream.BeginWrite(buffer, 0, buffer.Length, ResponseWriteFinished, Tuple.Create(request, response, requestHandler)); } } catch (Exception e) { //fill out request end time to get an actual count in case the exception is thrown in response.Write request.EndTime = Environment.TickCount; int tickdiff = request.EndTime - request.StartTime; m_log.ErrorFormat( "[BASE HTTP SERVER]: HandleRequest() threw {0} while processing {1} {2} {3} {4} {5} took {6}ms", e, request.SeqNo, request.HttpMethod, request.Url.AbsolutePath, requestHandler != null ? requestHandler.Name : "", requestHandler != null ? requestHandler.Description : "", tickdiff); // note that request.RemoteIPEndPoint is often disposed when we reach here (e.g. remote end has crashed) } }
public void SendHTML404(OSHttpResponse response, string host) { // I know this statuscode is dumb, but the client doesn't respond to 404s and 500s //MSIE doesn't allow for 400 pages to show... so we send 200 for now response.StatusCode = 200; //response.StatusCode = 400; response.AddHeader("Content-type", "text/html"); string responseString = GetHTTP404(host); byte[] buffer = Encoding.UTF8.GetBytes(responseString); response.SendChunked = false; response.ContentLength64 = buffer.Length; response.ContentEncoding = Encoding.UTF8; try { response.OutputStream.Write(buffer, 0, buffer.Length); } catch (Exception ex) { m_log.Warn("[BASE HTTP SERVER]: Error - " + ex.ToString()); } finally { //response.OutputStream.Close(); try { response.Send(); //response.FreeContext(); } catch (SocketException e) { // This has to be here to prevent a Linux/Mono crash m_log.WarnFormat("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e); } } }
public byte[] SendHTML500(OSHttpResponse response) { // I know this statuscode is dumb, but the client doesn't respond to 404s and 500s response.StatusCode = (int)OSHttpStatusCode.SuccessOk; response.AddHeader("Content-type", "text/html"); string responseString = GetHTTP500(); byte[] buffer = Encoding.UTF8.GetBytes(responseString); response.SendChunked = false; response.ContentLength64 = buffer.Length; response.ContentEncoding = Encoding.UTF8; return buffer; }
public override byte[] Handle(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) { Uri xrdUrl = new Uri(CableBeachServerState.ServiceUrl, "/xrd"); httpResponse.AddHeader("link", String.Format("<{0}>; rel=\"describedby\"; type=\"application/xrd+xml\"", xrdUrl)); httpResponse.ContentType = "text/html"; return CableBeachServerState.BuildServiceRootPageTemplate(xrdUrl.ToString()); }
internal void DoHTTPGruntWork(Hashtable responsedata) { if (Request.Body.CanRead) { Request.Body.Dispose(); } if (responsedata.Contains("h")) { OSHttpResponse r = (OSHttpResponse)responsedata["h"]; try { r.Send(); } catch { } PollServiceArgs.RequestsHandled++; return; } OSHttpResponse response = new OSHttpResponse(new HttpResponse(Request)); if (responsedata == null) { SendNoContentError(response); return; } int responsecode = 200; string responseString = String.Empty; string contentType; byte[] buffer = null; int rangeStart = 0; int rangeLen = -1; try { //m_log.Info("[BASE HTTP SERVER]: Doing HTTP Grunt work with response"); if (responsedata["int_response_code"] != null) { responsecode = (int)responsedata["int_response_code"]; } if (responsedata["bin_response_data"] != null) { buffer = (byte[])responsedata["bin_response_data"]; responsedata["bin_response_data"] = null; if (responsedata["bin_start"] != null) { rangeStart = (int)responsedata["bin_start"]; } if (responsedata["int_bytes"] != null) { rangeLen = (int)responsedata["int_bytes"]; } } else { responseString = (string)responsedata["str_response_string"]; } contentType = (string)responsedata["content_type"]; if (responseString == null) { responseString = String.Empty; } } catch { SendNoContentError(response); return; } response.StatusCode = responsecode; if (responsecode == (int)HttpStatusCode.Moved) { response.AddHeader("Location", (string)responsedata["str_redirect_location"]); response.KeepAlive = false; PollServiceArgs.RequestsHandled++; response.Send(); return; } if (responsedata.ContainsKey("http_protocol_version")) { response.ProtocolVersion = (string)responsedata["http_protocol_version"]; } if (responsedata.ContainsKey("keepalive")) { response.KeepAlive = (bool)responsedata["keepalive"]; } if (responsedata.ContainsKey("keepaliveTimeout")) { response.KeepAliveTimeout = (int)responsedata["keepaliveTimeout"]; } if (responsedata.ContainsKey("prio")) { response.Priority = (int)responsedata["prio"]; } if (responsedata.ContainsKey("error_status_text")) { response.StatusDescription = (string)responsedata["error_status_text"]; } // Cross-Origin Resource Sharing with simple requests if (responsedata.ContainsKey("access_control_allow_origin")) { response.AddHeader("Access-Control-Allow-Origin", (string)responsedata["access_control_allow_origin"]); } if (string.IsNullOrEmpty(contentType)) { response.AddHeader("Content-Type", "text/html"); } else { response.AddHeader("Content-Type", contentType); } if (responsedata.ContainsKey("headers")) { Hashtable headerdata = (Hashtable)responsedata["headers"]; foreach (string header in headerdata.Keys) { response.AddHeader(header, headerdata[header].ToString()); } } if (buffer == null) { if (contentType != null && (!(contentType.Contains("image") || contentType.Contains("x-shockwave-flash") || contentType.Contains("application/x-oar") || contentType.Contains("application/vnd.ll.mesh")))) { // Text buffer = Encoding.UTF8.GetBytes(responseString); } else { // Binary! buffer = Convert.FromBase64String(responseString); } response.ContentEncoding = Encoding.UTF8; } if (rangeStart < 0 || rangeStart > buffer.Length) { rangeStart = 0; } if (rangeLen < 0) { rangeLen = buffer.Length; } else if (rangeLen + rangeStart > buffer.Length) { rangeLen = buffer.Length - rangeStart; } response.ContentLength64 = rangeLen; try { if (rangeLen > 0) { response.RawBufferStart = rangeStart; response.RawBufferLen = rangeLen; response.RawBuffer = buffer; //response.OutputStream.Write(buffer, rangeStart, rangeLen); } buffer = null; response.Send(); } catch (Exception ex) { if (ex is System.Net.Sockets.SocketException) { // only mute connection reset by peer so we are not totally blind for now if (((System.Net.Sockets.SocketException)ex).SocketErrorCode != System.Net.Sockets.SocketError.ConnectionReset) { m_log.Warn("[POLL SERVICE WORKER THREAD]: Error ", ex); } } else { m_log.Warn("[POLL SERVICE WORKER THREAD]: Error ", ex); } } PollServiceArgs.RequestsHandled++; }
/// <summary> /// Invoked by OSHttpRequestPump. /// </summary> public override OSHttpHandlerResult Process(OSHttpRequest request) { // call handler method Hashtable responseData = _handler(request.Query); int responseCode = (int)responseData["int_response_code"]; string responseString = (string)responseData["str_response_string"]; string contentType = (string)responseData["content_type"]; //Even though only one other part of the entire code uses HTTPHandlers, we shouldn't expect this //and should check for NullReferenceExceptions if (string.IsNullOrEmpty(contentType)) { contentType = "text/html"; } OSHttpResponse response = new OSHttpResponse(request); // We're forgoing the usual error status codes here because the client // ignores anything but 200 and 301 response.StatusCode = (int)OSHttpStatusCode.SuccessOk; if (responseCode == (int)OSHttpStatusCode.RedirectMovedPermanently) { response.RedirectLocation = (string)responseData["str_redirect_location"]; response.StatusCode = responseCode; } response.AddHeader("Content-type", contentType); byte[] buffer; if (!contentType.Contains("image")) { buffer = Encoding.UTF8.GetBytes(responseString); } else { buffer = Convert.FromBase64String(responseString); } response.SendChunked = false; response.ContentLength64 = buffer.Length; response.ContentEncoding = Encoding.UTF8; try { response.Body.Write(buffer, 0, buffer.Length); } catch (Exception ex) { _log.ErrorFormat("[OSHttpHttpHandler]: Error: {0}", ex.Message); } finally { response.Send(); } return OSHttpHandlerResult.Done; }
public void SendHTML500(OSHttpResponse response) { // I know this statuscode is dumb, but the client doesn't respond to 404s and 500s response.StatusCode = (int)OSHttpStatusCode.SuccessOk; response.AddHeader("Content-type", "text/html"); string responseString = GetHTTP500(); byte[] buffer = Encoding.UTF8.GetBytes(responseString); response.SendChunked = false; response.ContentLength64 = buffer.Length; response.ContentEncoding = Encoding.UTF8; try { response.OutputStream.Write(buffer, 0, buffer.Length); } catch (Exception ex) { m_log.Warn("[BASE HTTP SERVER]: Error - " + ex.Message); } finally { //response.OutputStream.Close(); try { response.Send(); //response.FreeContext(); } catch (SocketException e) { // This has to be here to prevent a Linux/Mono crash m_log.WarnFormat("[BASE HTTP SERVER] XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e); } } }
internal bool AuthenticateRequest(OSHttpRequest request, OSHttpResponse response, out string username) { username = String.Empty; bool authSuccess = true; if (Authentication != AuthenticationType.None) { authSuccess = false; string[] authHeaderValues = request.Headers.GetValues("Authorization"); string authHeader = (authHeaderValues != null && authHeaderValues.Length > 0) ? authHeader = authHeaderValues[0] : authHeader = String.Empty; switch (Authentication) { case AuthenticationType.Basic: if (authHeader.StartsWith("Basic")) { string basicStr = Encoding.ASCII.GetString(Convert.FromBase64String(authHeader.Substring(6))); int colonPos = basicStr.LastIndexOf(':'); if (colonPos > -1) { username = basicStr.Substring(0, colonPos); string password = basicStr.Substring(colonPos + 1); if (OnBasicAuthenticate != null) authSuccess = OnBasicAuthenticate(username, password); } } break; case AuthenticationType.Digest: authHeader = authHeader.Trim(); if (authHeader.StartsWith("Digest")) { Dictionary<string, string> digestives = new Dictionary<string, string>(); digestives = GetHeaderParts(authHeader); if (digestives["uri"] != HttpUtility.UrlPathEncode(request.Url.PathAndQuery)) { response.StatusCode = (int)HttpStatusCode.BadRequest; return false; } string passwd = null; PasswordFormat format; if (OnDigestAuthenticate != null) { if (!OnDigestAuthenticate(digestives["username"], out format, out passwd)) { authSuccess = false; //failed to find password break; } } else { //no password request handler response.StatusCode = (int)HttpStatusCode.InternalServerError; return false; } string ha1 = null; username = digestives["username"]; //For some unknown horrible reason, windows vista client gives username in format DOMAIN\USER, but //calculates the MD5 hash with format DOMAIN\USER. To prevent it from failing well need to convert //the username to proper format. For more info //see: http://www.webdavsystem.com/server/documentation/authentication/digest_vista_xp_2003 if (request.Headers["User-Agent"] != null && request.Headers["User-Agent"].StartsWith("Microsoft-WebDAV-MiniRedir/6") && username.Contains("\\\\")) { string[] usernameParts = username.Split('\\'); username = usernameParts[0] + "\\" + usernameParts[2]; } if (format == PasswordFormat.Plain) ha1 = MD5HashString(username + ":" + digestives["realm"] + ":" + passwd); else ha1 = passwd; string ha2 = null; if (digestives["qop"] != null && digestives["qop"] == "auth-int") { string entityHash = MD5HashString(request.InputStream.ToString()); ha2 = MD5HashString(request.HttpMethod + ":" + digestives["uri"] + ":" + entityHash); } else ha2 = MD5HashString(request.HttpMethod + ":" + digestives["uri"]); string myResponse = null; if (digestives["qop"] != null && (digestives["qop"] == "auth-int" || digestives["qop"] == "auth")) myResponse = MD5HashString( ha1 + ":" + digestives["nonce"] + ":" + digestives["nc"] + ":" + digestives["cnonce"] + ":" + digestives["qop"] + ":" + ha2); else myResponse = MD5HashString(ha1 + ":" + digestives["nonce"] + ":" + ha2); if (myResponse == digestives["response"] && IsValidNonce(digestives["nonce"])) authSuccess = true; else authSuccess = false; break; } authSuccess = false; break; } } if (authSuccess) { return true; } else { byte[] responseData = Encoding.UTF8.GetBytes("401 Access Denied"); response.StatusCode = (int)HttpStatusCode.Unauthorized; response.StatusDescription = "Access Denied"; response.ContentLength = responseData.Length; response.Body.Write(responseData, 0, responseData.Length); if (Authentication == AuthenticationType.Digest) { string realm = request.Url.Host; string nonce = GenerateNonce(); //qop indicates that the server is merely looking for the client to authenticate //may ask for message integrity as well (qop=auth-int) string qop = "auth"; //advices if the client on whether it's appropriate to prompt the user for the password again or use a cached value bool stale = false; //send stale=true when it needs the client to rechallenge the user. //construct the digest header value string digest = "Digest realm=\"" + realm + "\","; digest += " stale=" + stale.ToString() + ","; digest += " nonce=\"" + nonce + "\","; digest += " qop=\"" + qop + "\", algorithm=\"MD5\""; response.AddHeader("WWW-Authenticate", digest); } else { response.AddHeader("WWW-Authenticate", "Basic Realm=\"\""); } return false; } }