Beispiel #1
0
        /// <summary>
        /// Read in what is basically a text file and return a ResponsePacket with the text UTF8 encoded.
        /// </summary>
        protected ResponsePacket FileLoader(Route routeHandler, Session session, Dictionary <string, object> kvParams, string fullPath, string ext, ExtensionInfo extInfo)
        {
            ResponsePacket ret;

            if (!File.Exists(fullPath))
            {
                ret = new ResponsePacket()
                {
                    Error = Server.ServerError.FileNotFound
                };
                Console.WriteLine("!!! File not found: " + fullPath);
            }
            else
            {
                string text = File.ReadAllText(fullPath);
                ret = new ResponsePacket()
                {
                    Data = Encoding.UTF8.GetBytes(text), ContentType = extInfo.ContentType, Encoding = Encoding.UTF8
                };
            }

            return(ret);
        }
Beispiel #2
0
        /// <summary>
        /// Load an HTML file, taking into account missing extensions and a file-less IP/domain, which should default to index.html.
        /// </summary>
        protected ResponsePacket PageLoader(Route routeHandler, Session session, Dictionary<string, object> kvParams, string fullPath, string ext, ExtensionInfo extInfo)
        {
            ResponsePacket ret;

            if (fullPath == WebsitePath)		// If nothing follows the domain name or IP, then default to loading index.html.
            {
                ret = Route(session, GET, "/index.html", null);
            }
            else
            {
                if (String.IsNullOrEmpty(ext))
                {
                    // No extension, so we make it ".html"
                    fullPath = fullPath + ".html";
                }

                // Inject the "Pages" folder into the path
                // fullPath = WebsitePath +"\\Pages" + fullPath.RightOf(WebsitePath);

                // Custom, for page not found error.
                if (!File.Exists(fullPath))
                {
                    ret = new ResponsePacket() { Error = Server.ServerError.PageNotFound };
                    Console.WriteLine("!!! File not found: " + fullPath);
                }
                else
                {
                    string text = File.ReadAllText(fullPath);

                    // TODO: We put the route custom post process last because of how content is merged in the application's process,
                    // but this might cause problems if the route post processor adds something that the app's post processor needs to replace.
                    // How do we handle this?  A before/after process?  CSRF tokens are a great example!

                    // Do the application global post process replacement.
                    text = server.PostProcess(session, fullPath, text);

                    // If a custom post process callback exists, call it.
                    routeHandler.IfNotNull((r) => r.PostProcess.IfNotNull((p) => text = p(session, kvParams, text)));

                    // Do our default post process to catch any final CSRF stuff in the fully merged document.
                    text = server.DefaultPostProcess(session, fullPath, text);

                    ret = new ResponsePacket() { Data = Encoding.UTF8.GetBytes(text), ContentType = extInfo.ContentType, Encoding = Encoding.UTF8 };
                }
            }

            return ret;
        }
Beispiel #3
0
        /// <summary>
        /// Read in an image file and returns a ResponsePacket with the raw data.
        /// </summary>
        protected ResponsePacket ImageLoader(Route routeHandler, Session session, Dictionary<string, object> kvParams, string fullPath, string ext, ExtensionInfo extInfo)
        {
            ResponsePacket ret;

            if (!File.Exists(fullPath))
            {
                ret = new ResponsePacket() { Error = Server.ServerError.FileNotFound };
                Console.WriteLine("!!! File not found: " + fullPath);
            }
            else
            {
                FileStream fStream = new FileStream(fullPath, FileMode.Open, FileAccess.Read);
                BinaryReader br = new BinaryReader(fStream);
                ret = new ResponsePacket() { Data = br.ReadBytes((int)fStream.Length), ContentType = extInfo.ContentType };
                br.Close();
                fStream.Close();
            }

            return ret;
        }
Beispiel #4
0
        /// <summary>
        /// Read in what is basically a text file and return a ResponsePacket with the text UTF8 encoded.
        /// </summary>
        protected ResponsePacket FileLoader(Route routeHandler, Session session, Dictionary<string, object> kvParams, string fullPath, string ext, ExtensionInfo extInfo)
        {
            ResponsePacket ret;

            if (!File.Exists(fullPath))
            {
                ret = new ResponsePacket() { Error = Server.ServerError.FileNotFound };
                Console.WriteLine("!!! File not found: " + fullPath);
            }
            else
            {
                string text = File.ReadAllText(fullPath);
                ret = new ResponsePacket() { Data = Encoding.UTF8.GetBytes(text), ContentType = extInfo.ContentType, Encoding = Encoding.UTF8 };
            }

            return ret;
        }
Beispiel #5
0
        public ResponsePacket Route(Session session, string verb, string path, Dictionary<string, object> kvParams)
        {
            string ext = path.RightOfRightmostOf('.');
            ExtensionInfo extInfo;
            ResponsePacket ret = null;
            verb = verb.ToLower();
            path = path.ToLower();

            if (extFolderMap.TryGetValue(ext, out extInfo))
            {
                string wpath = path.Substring(1).Replace('/', '\\');			// Strip off leading '/' and reformat as with windows path separator.
                string fullPath = Path.Combine(WebsitePath, wpath);

                Route routeHandler = routes.SingleOrDefault(r => verb == r.Verb.ToLower() && path == r.Path.ToLower());

                if (routeHandler != null)
                {
                    // Application has a handler for this route.
                    ResponsePacket handlerResponse = null;

                    // If a handler exists:
                    routeHandler.Handler.IfNotNull((h) => handlerResponse = h.Handle(session, kvParams));

                    // If multiple handlers exist, see which one, if any, is willing to handle the request.
                    // We stop after the first handler.
                    // This behavior is useful for web services or other types of routes where the data determines the route, not the URL.
                    if (routeHandler.Handlers.Count > 0)
                    {
                        foreach (RouteHandler h in routeHandler.Handlers)
                        {
                            if (h.CanHandle(session, kvParams))
                            {
                                handlerResponse = h.Handle(session, kvParams);
                                break;
                            }
                        }
                    }

                    if (handlerResponse == null)
                    {
                        // Respond with default content loader.
                        ret = extInfo.Loader(routeHandler, session, kvParams, fullPath, ext, extInfo);
                    }
                    else
                    {
                        // Respond with redirect.
                        ret = handlerResponse;
                    }
                }
                else
                {
                    // Attempt default behavior
                    ret = extInfo.Loader(null, session, kvParams, fullPath, ext, extInfo);
                }
            }
            else
            {
                ret = new ResponsePacket() { Error = Server.ServerError.UnknownType };
            }

            return ret;
        }
Beispiel #6
0
        private void Respond(HttpListenerRequest request, HttpListenerResponse response, ResponsePacket resp)
        {
            // Are we redirecting?
            if (String.IsNullOrEmpty(resp.Redirect))
            {
                // No redirect.
                // Do we have a response?
                if (resp.Data != null)
                {
                    // Yes we do.
                    response.ContentType     = resp.ContentType;
                    response.ContentLength64 = resp.Data.Length;
                    response.OutputStream.Write(resp.Data, 0, resp.Data.Length);
                    response.ContentEncoding = resp.Encoding;
                }

                // Whether we do or not, no error occurred, so the response code is OK.
                // For example, we may have just processed an AJAX callback that does not have a data response.
                // Use the status code in the response packet, so the controller has an opportunity to set the response.
                response.StatusCode = (int)resp.StatusCode;
            }
            else
            {
                response.StatusCode = (int)HttpStatusCode.Redirect;

                if (String.IsNullOrEmpty(publicIP))
                {
                    string redirectUrl = request.Url.Scheme + "://" + request.Url.Host + resp.Redirect;
                    response.Redirect(redirectUrl);
                }
                else
                {
                    // response.Redirect("http://" + publicIP + resp.Redirect);
                    string redirectUrl = request.Url.Scheme + "://" + request.Url.Host + resp.Redirect;
                    response.Redirect(redirectUrl);
                }
            }

            response.OutputStream.Close();
        }
Beispiel #7
0
        /// <summary>
        /// Await connections.
        /// </summary>
        private async void StartConnectionListener(HttpListener listener)
        {
            ResponsePacket resp = null;

            // Wait for a connection.  Return to caller while we wait.
            HttpListenerContext context = await listener.GetContextAsync();

            Session session = sessionManager.GetSession(context.Request.RemoteEndPoint);

            OnRequest.IfNotNull(r => r(session, context));

            // Release the semaphore so that another listener can be immediately started up.
            sem.Release();
            Log(context.Request);

            HttpListenerRequest request = context.Request;

            try
            {
                string path  = request.RawUrl.LeftOf("?");                                      // Only the path, not any of the parameters
                string verb  = request.HttpMethod;                                              // get, post, delete, etc.
                string parms = request.RawUrl.RightOf("?");                                     // Params on the URL itself follow the URL and are separated by a ?
                Dictionary <string, object> kvParams = GetKeyValues(parms);                     // Extract into key-value entries.
                string data = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding).ReadToEnd();
                // GetKeyValues(data, kvParams);
                kvParams["Data"] = data;
                Log(kvParams);

                if (!VerifyCsrf(session, verb, kvParams))
                {
                    Console.WriteLine("CSRF did not match.  Terminating connection.");
                    context.Response.OutputStream.Close();
                }
                else
                {
                    resp = router.Route(session, verb, path, kvParams);

                    // Update session last connection after getting the response, as the router itself validates session expiration only on pages requiring authentication.
                    session.UpdateLastConnectionTime();

                    if (resp.Error != ServerError.OK)
                    {
                        resp.Redirect = OnError(resp.Error);
                    }

                    // TODO: Nested exception: is this best?

                    try
                    {
                        Respond(request, context.Response, resp);
                    }
                    catch (Exception reallyBadException)
                    {
                        // The response failed!
                        // TODO: We need to put in some decent logging!
                        Console.WriteLine(reallyBadException.Message);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
                resp = new ResponsePacket()
                {
                    Redirect = OnError(ServerError.ServerError)
                };
            }
        }
Beispiel #8
0
		private void Respond(HttpListenerRequest request, HttpListenerResponse response, ResponsePacket resp)
		{
			// Are we redirecting?
			if (String.IsNullOrEmpty(resp.Redirect))
			{
				// No redirect.
				// Do we have a response?
				if (resp.Data != null)
				{
					// Yes we do.
					response.ContentType = resp.ContentType;
					response.ContentLength64 = resp.Data.Length;
					response.OutputStream.Write(resp.Data, 0, resp.Data.Length);
					response.ContentEncoding = resp.Encoding;
				}

				// Whether we do or not, no error occurred, so the response code is OK.
				// For example, we may have just processed an AJAX callback that does not have a data response.
				// Use the status code in the response packet, so the controller has an opportunity to set the response.
				response.StatusCode = (int)resp.StatusCode;
			}
			else
			{
				response.StatusCode = (int)HttpStatusCode.Redirect;

				if (String.IsNullOrEmpty(publicIP))
				{
					string redirectUrl = request.Url.Scheme + "://" + request.Url.Host + resp.Redirect;
					response.Redirect(redirectUrl);
				}
				else
				{
					// response.Redirect("http://" + publicIP + resp.Redirect);					
					string redirectUrl = request.Url.Scheme + "://" + request.Url.Host + resp.Redirect;
					response.Redirect(redirectUrl);
				}
			}

			response.OutputStream.Close();
		}
Beispiel #9
0
		/// <summary>
		/// Await connections.
		/// </summary>
		private async void StartConnectionListener(HttpListener listener)
		{
			ResponsePacket resp = null;

			// Wait for a connection.  Return to caller while we wait.
			HttpListenerContext context = await listener.GetContextAsync();
			Session session = sessionManager.GetSession(context.Request.RemoteEndPoint);
			OnRequest.IfNotNull(r => r(session, context));

			// Release the semaphore so that another listener can be immediately started up.
			sem.Release();
			Log(context.Request);

			HttpListenerRequest request = context.Request;

			try
			{
				string path = request.RawUrl.LeftOf("?");			// Only the path, not any of the parameters
				string verb = request.HttpMethod;					// get, post, delete, etc.
				string parms = request.RawUrl.RightOf("?");			// Params on the URL itself follow the URL and are separated by a ?
				Dictionary<string, object> kvParams = GetKeyValues(parms);	// Extract into key-value entries.
				string data = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding).ReadToEnd();
				// GetKeyValues(data, kvParams);
				kvParams["Data"] = data;
				Log(kvParams);

				if (!VerifyCsrf(session, verb, kvParams))
				{
					Console.WriteLine("CSRF did not match.  Terminating connection.");
					context.Response.OutputStream.Close();
				}
				else
				{
					resp = router.Route(session, verb, path, kvParams);

					// Update session last connection after getting the response, as the router itself validates session expiration only on pages requiring authentication.
					session.UpdateLastConnectionTime();

					if (resp.Error != ServerError.OK)
					{
						resp.Redirect = OnError(resp.Error);
					}

					// TODO: Nested exception: is this best?

					try
					{
						Respond(request, context.Response, resp);
					}
					catch (Exception reallyBadException)
					{
						// The response failed!
						// TODO: We need to put in some decent logging!
						Console.WriteLine(reallyBadException.Message);
					}
				}
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex.Message);
				Console.WriteLine(ex.StackTrace);
				resp = new ResponsePacket() { Redirect = OnError(ServerError.ServerError) };
			}
		}
Beispiel #10
0
		/// <summary>
		/// Return a ResponsePacket with the specified URL and an optional (singular) parameter.
		/// </summary>
		public ResponsePacket Redirect(string url, string parm = null)
		{
			ResponsePacket ret = new ResponsePacket() { Redirect = url };
			parm.IfNotNull((p) => ret.Redirect += "?" + p);

			return ret;
		}
Beispiel #11
0
        public ResponsePacket Route(Session session, string verb, string path, Dictionary <string, object> kvParams)
        {
            string         ext = path.RightOfRightmostOf('.');
            ExtensionInfo  extInfo;
            ResponsePacket ret = null;

            verb = verb.ToLower();
            path = path.ToLower();

            if (extFolderMap.TryGetValue(ext, out extInfo))
            {
                string wpath    = path.Substring(1).Replace('/', '\\');                                 // Strip off leading '/' and reformat as with windows path separator.
                string fullPath = Path.Combine(WebsitePath, wpath);

                Route routeHandler = routes.SingleOrDefault(r => verb == r.Verb.ToLower() && path == r.Path.ToLower());

                if (routeHandler != null)
                {
                    // Application has a handler for this route.
                    ResponsePacket handlerResponse = null;

                    // If a handler exists:
                    routeHandler.Handler.IfNotNull((h) => handlerResponse = h.Handle(session, kvParams));

                    // If multiple handlers exist, see which one, if any, is willing to handle the request.
                    // We stop after the first handler.
                    // This behavior is useful for web services or other types of routes where the data determines the route, not the URL.
                    if (routeHandler.Handlers.Count > 0)
                    {
                        foreach (RouteHandler h in routeHandler.Handlers)
                        {
                            if (h.CanHandle(session, kvParams))
                            {
                                handlerResponse = h.Handle(session, kvParams);
                                break;
                            }
                        }
                    }

                    if (handlerResponse == null)
                    {
                        // Respond with default content loader.
                        ret = extInfo.Loader(routeHandler, session, kvParams, fullPath, ext, extInfo);
                    }
                    else
                    {
                        // Respond with redirect.
                        ret = handlerResponse;
                    }
                }
                else
                {
                    // Attempt default behavior
                    ret = extInfo.Loader(null, session, kvParams, fullPath, ext, extInfo);
                }
            }
            else
            {
                ret = new ResponsePacket()
                {
                    Error = Server.ServerError.UnknownType
                };
            }

            return(ret);
        }