예제 #1
0
 public void StartListener()
 {
     _listener = new TcpListener(ListenAddress, Port);
     _listener.Start();
     while (_isActive)
     {
         var s = _listener.AcceptTcpClient();
         var processor = new ClientHttpResponse(s, this);
         Task.Factory.StartNew(processor.ProcessRequest);
     }
 }
 public abstract void SendFileWithMimeType(string path, string wwwroot, ClientHttpResponse response,
     Dictionary<string, string> requestParameters, HTTPMethod method, string postData);
예제 #3
0
 public abstract void HandlePostRequest(ClientHttpResponse response, StreamReader inputData);
예제 #4
0
        private bool RouteDefaultResourcePaths(string requestPath, string wwwroot, ClientHttpResponse response,
            Dictionary<string, string> urlParameters)
        {
            var handled = false;
            switch (requestPath)
            {
                case "/favicon.ico":
                    handled = true;
                    SendBytesWithMimeType(requestPath, wwwroot, response, urlParameters, Resources.logo_ico);
                    break;

                case "/_indexing_style.css":
                    handled = true;
                    SendBytesWithMimeType(requestPath, wwwroot, response, urlParameters,
                        Encoding.UTF8.GetBytes(Resources.defaultindexstyle_css));
                    break;

                default:
                    handled = false;
                    break;
            }
            return handled;
        }
예제 #5
0
 public abstract void HandleGetRequest(ClientHttpResponse response);
예제 #6
0
        public override void HandleGetRequest(ClientHttpResponse response)
        {
            var wwwroot = SelectDocumentRoot(response);
            _currentHookExecutionScope.response = response;
            bool requestHandled = InvokeHook(FireHTTPServerHookType.GetPreHook, _currentHookExecutionScope);
            if (requestHandled)
                return;
            var requestPath = Uri.UnescapeDataString(response.RequestPath);
            var urlParameters = ParseUrlParameters(ref requestPath);
            var handled = RewriteRequestPath(ref requestPath, response, wwwroot);
            if (handled)
                return;

            if (!RouteDefaultResourcePaths(requestPath, wwwroot, response, urlParameters))
                //If default resource router didn't handle it, send the file
            {
                SendFileWithMimeType(requestPath, wwwroot, response, urlParameters, HTTPMethod.Get, null);
            }

            Logger.WriteLine($"GET: {response.RequestPath}");
            InvokeHook(FireHTTPServerHookType.GetPostHook, _currentHookExecutionScope);
            _currentHookExecutionScope = new ExpandoObject(); //reset the execution scope
        }
예제 #7
0
        private bool HandleFAccessConfig(FileSystemInfo requestedFileInfo, DirectoryInfo containingDir,
            FAccessConfig faccess,
            ClientHttpResponse response)
        {
            if (faccess == null)
                return false;
            var forbidden = !faccess.Allow || _denyFileNames.Contains(requestedFileInfo.Name);
            //User-defined access rules:
            var dirAccessRules = faccess.FileAccessRules;
            var requestedFileName = requestedFileInfo.Name;
            switch (dirAccessRules)
            {
                case AccessRules.ExplicitAllow:
                    if (!faccess.AllowedFiles.Contains(requestedFileName))
                    {
                        forbidden = true;
                    }
                    break;

                case AccessRules.ExplicitDeny:
                    if (faccess.DeniedFiles.Contains(requestedFileName))
                    {
                        forbidden = true;
                    }
                    break;
            }
            if (forbidden)
            {
                if (faccess.ErrorDocument403 == null)
                {
                    //Show default 403
                    Logger.WriteLine("403!");
                    response.SendFailure403(); //Send 403 Header
                    response.OutputStream.WriteLine(
                        "403 - You don't have permission to access this path on this server."); //Default 403 body
                    return true; //end the connection
                }
                var errdocFullPath = containingDir.FullName + _dirSep + faccess.ErrorDocument403;
                Logger.WriteLine("403!");
                response.SendFailure403(); //Send 403 Header
                response.OutputStream.WriteLine(File.ReadAllText(errdocFullPath));
                return true; //end the connection
            }
            if (requestedFileInfo.Exists) return false;
            {
                // Default 404
                //Check if it is a missing index, and display dirindex if enabled
                if (requestedFileInfo.Name == "index.html" && faccess.EnableIndexing && containingDir.Exists)
                {
                    response.SendHeader("HTTP/1.1 200 OK");
                    response.SendHeader("Content-Type: text/html");
                    response.SendEndHeaders();
                    response.OutputStream.WriteLine(GenerateDirectoryIndex(containingDir, response)); //Dynamic index
                    Logger.WriteLine("Sent dynamic directory index.");
                    return true; //end the connection
                }
                if (faccess.ErrorDocument404 == null)
                {
                    //Show default 404
                    Logger.WriteLine("404!");
                    response.SendFailure404(); //Send 404 Header
                    response.OutputStream.WriteLine("404 - File not found"); //Default 404 body
                    return true; //end the connection
                }
                var errdocFullPath = containingDir.FullName + _dirSep + faccess.ErrorDocument404;
                Logger.WriteLine("404!");
                response.SendFailure404(); //Send 404 Header
                response.OutputStream.WriteLine(File.ReadAllText(errdocFullPath));
                return true; //end the connection
            }
        }
예제 #8
0
 private static string GenerateDirectoryIndex(DirectoryInfo containingDir, ClientHttpResponse response)
 {
     var indexhtmlbody = "<ul>";
     var fileList = containingDir.GetFiles();
     var dirList = containingDir.GetDirectories();
     foreach (var dir in dirList)
     {
         var targetAddress = response.RequestPath + dir.Name + "/";
         var targetDisplayName = dir.Name + "/";
         indexhtmlbody += "<li><a href=\"" + targetAddress + "\">" + targetDisplayName + "</a><br></li>";
     }
     foreach (var file in fileList)
     {
         var targetAddress = response.RequestPath + file.Name;
         var targetDisplayName = file.Name;
         indexhtmlbody += "<li><a href=\"" + targetAddress + "\">" + targetDisplayName + "</a><br></li>";
     }
     indexhtmlbody += "</ul><p><h5>FireHTTP Server</h5></p>";
     var indexhtml = "<html><head><title>Index of " + response.RequestPath + "</title></head><body>" +
                     indexhtmlbody + "</body></html>";
     return indexhtml;
 }
예제 #9
0
 private static bool RewriteRequestPath(ref string requestPath, ClientHttpResponse response, string wwwroot)
 {
     var path = requestPath.Substring(1); //Remove slash at beginning
     string rqfullPath = null;
     try
     {
         rqfullPath = Path.Combine(wwwroot, path);
     }
     catch (ArgumentException)
     {
         // Invalid path, possibly due to some evil stuff trying to XSS or something
         response.SendFailure404();
         response.OutputStream.WriteLine("404 - The requested resource could not be located.");
         throw new DeadRequestException();
     }
     var finfo = new FileInfo(rqfullPath);
     var dinfo = new DirectoryInfo(rqfullPath);
     if (dinfo.Exists && !requestPath.EndsWith("/"))
     {
         // Permanent redirection
         response.SendHeader("HTTP/1.1 301 Moved Permanently");
         response.SendHeader("Location: " + requestPath + "/");
         response.SendEndHeaders();
     }
     var isDirectory = requestPath.EndsWith("/", StringComparison.CurrentCulture);
     if (isDirectory)
         requestPath += "index.html";
     return false;
 }
예제 #10
0
 public override void SendFileWithMimeType(string path, string wwwroot, ClientHttpResponse response,
     Dictionary<string, string> requestParameters, HTTPMethod method, string postData)
 {
     path = path.Substring(1); //Remove slash at beginning
     var fullPath = Path.Combine(wwwroot, path);
     var fileInfo = new FileInfo(fullPath);
     var containingDir = fileInfo.Directory;
     var configFile = new FileInfo(containingDir?.FullName + _dirSep + CommonVariables.ConfigFileName);
     var faccess = _defaultFAccess;
     var fAccessFound = FindFAccess(ref configFile, wwwroot);
     if (fAccessFound)
     {
         var faccessJson = File.ReadAllText(configFile.FullName);
         faccess = JsonConvert.DeserializeObject<FAccessConfig>(faccessJson);
     }
     var requestHandled = HandleFAccessConfig(fileInfo, containingDir, faccess, response); //Process the FACCESS
     if (requestHandled)
         return;
     var extension = fileInfo.Extension;
     var mimeType = "application/octet-stream";
     if (CommonVariables.MimeTypeMappings.ContainsKey(extension))
     {
         mimeType = CommonVariables.MimeTypeMappings[extension];
     }
     if (!_executableFileTypes.Contains(extension))
     {
         var staticFileHookParameters = new FireHTTPHookParameters
         {
             RequestedDocumentFullPath = fullPath,
             RequestFileName = path,
             RequestMimeType = mimeType,
             RequestedFileExtension = extension
         };
         //Static file; if not executable, send normally
         using (var fs = File.OpenRead(fullPath))
         {
             staticFileHookParameters.RequestFileContentStream = fs;
             bool staticFileHookHandled = InvokeHook(FireHTTPServerHookType.StaticFileSendHook,
                 _currentHookExecutionScope, staticFileHookParameters);
             if (!staticFileHookHandled)
             {
                 SendStreamWithMimeType(fs, mimeType, response);
             }
         }
     }
     else
     {
         //Execute Script
         var executionParameters = new ScriptExecutionParameters();
         ExecuteScript(fullPath, requestParameters, response, extension, mimeType, method, postData, wwwroot,
             executionParameters);
     }
 }
예제 #11
0
 public override void SendStreamWithMimeType(Stream dataStream, string mimeType, ClientHttpResponse response)
 {
     response.SendHeader("HTTP/1.1 200 OK");
     response.SendHeader("Content-Type: " + mimeType);
     //response.SendHeader("Content-Length: "+fs.Length);
     response.SendEndHeaders();
     response.OutputStream.Flush();
     dataStream.CopyTo(response.OutputStream.BaseStream);
 }
예제 #12
0
 public void SendBytesWithMimeType(string path, string wwwroot, ClientHttpResponse response,
     Dictionary<string, string> urlParameters, byte[] bytes)
 {
     path = path.Substring(1);
     var fullPath = Path.Combine(wwwroot, path);
     var fileInfo = new FileInfo(fullPath);
     var extension = fileInfo.Extension;
     var mimeType = "application/octet-stream";
     if (CommonVariables.MimeTypeMappings.ContainsKey(extension))
     {
         mimeType = CommonVariables.MimeTypeMappings[extension];
     }
     using (var fs = new MemoryStream(bytes))
     {
         //Static file
         SendStreamWithMimeType(fs, mimeType, response);
     }
 }
예제 #13
0
 public string SelectDocumentRoot(ClientHttpResponse response)
 {
     if (_serverSettings.SingleInstance)
     {
         //Single instance mode, don't process host header
         return _documentRootCache.Values.ToList()[0];
     }
     var hostHeader = response.GetHostHeader();
     var ipcontents = hostHeader.Split(new[] {':'}, StringSplitOptions.RemoveEmptyEntries);
     var host = ipcontents[0];
     if (ipcontents.Length == 2)
     {
         var hostPort = -1;
         int.TryParse(ipcontents[1], out hostPort);
     }
     var serverNames = _documentRootCache.Keys.ToArray();
     var matches = serverNames.Where(sn => IsWildcardMatch(host, sn)).ToList(); //Get matches
     if (matches.Count != 0) return _documentRootCache[matches[0]]; //return first match.
     Logger.WriteLine("No match found for virtualhost.");
     throw new DeadRequestException();
 }
예제 #14
0
 public override void HandlePostRequest(ClientHttpResponse response, StreamReader postStream)
 {
     var wwwroot = SelectDocumentRoot(response);
     _currentHookExecutionScope.response = response;
     _currentHookExecutionScope.postStream = postStream;
     bool requestHandled = InvokeHook(FireHTTPServerHookType.PostPreHook, _currentHookExecutionScope);
     if (requestHandled)
         return;
     var rawPostDataString = postStream.ReadToEnd();
     var requestPath = Uri.UnescapeDataString(response.RequestPath);
     var postData = ParsePostData(rawPostDataString, response.RequestHttpHeaders["content-type"]);
     var handled = RewriteRequestPath(ref requestPath, response, wwwroot);
     if (handled)
         return;
     SendFileWithMimeType(requestPath, wwwroot, response, postData, HTTPMethod.Post, rawPostDataString);
     Logger.WriteLine($"POST: {response.RequestPath}");
     InvokeHook(FireHTTPServerHookType.PostPostHook, _currentHookExecutionScope);
     _currentHookExecutionScope = new ExpandoObject(); //reset the execution scope
 }
 public abstract void SendStreamWithMimeType(Stream dataStream, string mimeType, ClientHttpResponse response);
예제 #16
0
 private void ExecuteScript(string fullPath, Dictionary<string, string> urlParameters,
     ClientHttpResponse response, string extension, string mimeType, HTTPMethod method, string postData,
     string documentRoot, ScriptExecutionParameters executionParameters)
 {
     //Select launcher
     var launcherProgram = _scriptInterpreterCache[extension];
     launcherProgram.ExecuteScript(fullPath, urlParameters, response, extension, mimeType, method, postData,
         documentRoot, this, executionParameters);
 }
예제 #17
0
        public void ExecuteScript(string fullPath, Dictionary<string, string> urlParameters,
            ClientHttpResponse response, string extension, string mimeType, HTTPMethod method, string postData,
            string documentRoot, dynamic serverHandle, ScriptExecutionParameters executionParameters)
        {
            //Prepare JSScript
            var scriptContents = File.ReadAllText(fullPath);
            var scriptDir = Path.GetDirectoryName(fullPath);
            var jsEngine = new Engine(cfg => cfg.AllowClr());

            var undefined = Undefined.Instance;

            //Inject variables
            if (method == HTTPMethod.Get)
            {
                jsEngine.SetValue("_GET", urlParameters);
                jsEngine.SetValue("_SERVER", response.RequestHttpHeaders);
                jsEngine.SetValue("_POST", undefined);
            }
            if (method == HTTPMethod.Post)
            {
                jsEngine.SetValue("_GET", undefined);
                jsEngine.SetValue("_SERVER", response.RequestHttpHeaders);
                jsEngine.SetValue("_POST", urlParameters);
                jsEngine.SetValue("POST_DATA", postData);
            }

            //Globals
            jsEngine.SetValue("DocumentRoot", documentRoot);
            jsEngine.SetValue("__dirname__", scriptDir);

            switch (extension)
            {
                case ".jscx": //Fully-controlled script
                {
                    try
                    {
                        //Manipulate Scope
                        jsEngine.SetValue("response", response);
                        jsEngine.SetValue("FireHTTPServer", serverHandle);
                        jsEngine.SetValue("_mimeTypeMappings", CommonVariables.MimeTypeMappings);
                        jsEngine.SetValue("dirSep", _dirSep);
                        DefineScriptingApi(jsEngine);
                        jsEngine.Execute(scriptContents);
                        break;
                    }
                    catch (DeadRequestException)
                    {
                        throw; //Don't catch these.
                    }
                    catch (Exception ex)
                    {
                        var level = (int) jsEngine.GetValue("__error_reporting_level").AsNumber();
                        if (level > 0)
                        {
                            if (!response.HasFinishedSendingHeaders)
                            {
                                //If headers not sent, send default headers.
                                response.SendHeader("HTTP/1.1 200 OK");
                                response.SendHeader("Content-Type: text/plain");
                                response.SendEndHeaders();
                            }
                            response.OutputStream.WriteLine("Error in script execution. Stack trace:");
                            response.OutputStream.WriteLine(ex.ToString());
                            break;
                        }
                        throw;
                    }
                }
            }
        }
예제 #18
0
        public void ExecuteScript(string fullPath, Dictionary<string, string> urlParameters,
            ClientHttpResponse response, string extension, string mimeType, HTTPMethod method, string postData,
            string documentRoot, dynamic serverHandle, ScriptExecutionParameters executionParameters)
        {
            //Prepare ExaScript
            var scriptContents = File.ReadAllText(fullPath);
            var scriptDir = Path.GetDirectoryName(fullPath);
            var escLauncher = new ExaScriptLauncher();
            dynamic escExecutionScope = escLauncher.UnderlyingInstance.Scope;
            var escEngine = escLauncher.UnderlyingInstance.Engine;

            //Inject variables
            //Inject code
            if (method == HTTPMethod.Get)
            {
                escExecutionScope._GET = urlParameters;
                escExecutionScope._SERVER = response.RequestHttpHeaders;
                escExecutionScope._POST = null;
            }
            if (method == HTTPMethod.Post)
            {
                escExecutionScope._GET = null;
                escExecutionScope._SERVER = response.RequestHttpHeaders;
                escExecutionScope._POST = urlParameters;
                escExecutionScope.POST_DATA = postData;
            }

            //Globals
            escExecutionScope.DocumentRoot = documentRoot;
            escExecutionScope.__dirname__ = scriptDir;

            switch (extension)
            {
                case ".esc": //Simple executable script
                {
                    //Manipulate Scope

                    //Send Headers
                    response.SendHeader("HTTP/1.1 200 OK");
                    response.SendHeader("Content-Type: " + mimeType);
                    response.SendEndHeaders();

                    escLauncher.LoadCode(scriptContents);
                    var result = escLauncher.RunCode();
                    response.OutputStream.WriteLine(result);
                    break;
                }
                case ".escx": //Fully-controlled script
                {
                    try
                    {
                        //Manipulate Scope
                        escExecutionScope.response = response;
                        escExecutionScope.FireHTTPServer = serverHandle;
                        escExecutionScope._mimeTypeMappings = CommonVariables.MimeTypeMappings;
                        escExecutionScope.dirSep = _dirSep;
                        DefineScriptingApi(escExecutionScope); //Add all the API functions
                        escLauncher.LoadCode(scriptContents);
                        escLauncher.RunCode();
                        break;
                    }
                    catch (DeadRequestException)
                    {
                        throw; //Don't catch these.
                    }
                    catch (Exception ex)
                    {
                        int level = escExecutionScope.__error_reporting_level;
                        if (level <= 0) throw;
                        if (!response.HasFinishedSendingHeaders)
                        {
                            //If headers not sent, send default headers.
                            response.SendHeader("HTTP/1.1 200 OK");
                            response.SendHeader("Content-Type: text/plain");
                            response.SendEndHeaders();
                        }
                        response.OutputStream.WriteLine("Error in script execution. Stack trace:");
                        response.OutputStream.WriteLine(ex.ToString());
                        break;
                    }
                }
            }
        }