Example #1
0
		internal virtual void create_env_vars(StringDictionary env_collection, http_message msg) {

			http_request req = msg.Request;
			http_response res = msg.Response;
			DataAccessLayer d = msg.data_layer;
			String allheader = "";

			//Requirements for POST DATA
			if (req.Header.Verb == "POST" | req.Header.Verb == "PUT")
			{
				env_collection.Add("CONTENT_LENGTH", req.Body.Length.ToString());
				env_collection.Add("CONTENT_TYPE",req.Header.GetValue("Content-Type"));
			}

			// TODO: if you ever implement http authentication or authorization these will need to be adjusted.
			env_collection.Add("AUTH_TYPE", "");
			env_collection.Add("AUTH_USER", "");
			env_collection.Add("REMOTE_USER", "");

			//Setup for "ALL_HTTP"
			foreach(String key in req.Header.Values.Keys)
			{
				allheader += String.Format("{0}: {1}\r\n",
				                           "HTTP_" +key.Replace("-","_").ToUpper(),
				                           req.Header.GetValue(key));
				env_collection.Add("HTTP_" +key.Replace("-","_").ToUpper(),
				                                   req.Header.GetValue(key));
			}
			env_collection.Add("ALL_HTTP",allheader);
			env_collection.Add("ALL_RAW",req.Header.ToString());
			env_collection.Add("REQUEST_METHOD", req.Header.Verb.ToUpper());
			env_collection.Add("REQUEST_URI", req.Header.Target);
			env_collection.Add("SCRIPT_NAME", req.script_name);
			env_collection.Add("REMOTE_ADDR",((IPEndPoint)req.Connection.Client.RemoteEndPoint).Address.ToString());
			env_collection.Add("REMOTE_PORT", ((IPEndPoint)req.Connection.Client.RemoteEndPoint).Port.ToString ());
			env_collection.Add("QUERY_STRING", req.Uri.Query.Replace("?",""));
			// TODO: This is a may not alway produce the proper result. PATH_INFO
			// is intended to be the part of the path that is left over when
			// the scriptname is part of the path i.e https://test.com/index.php/more/path.
			// In this example case /more/path would be the PATH_INFO.
			env_collection.Add("PATH_INFO", req.Uri.AbsolutePath.Replace(req.script_name,""));
			if(msg.ClientStream is SslStream) {
				env_collection.Add("SCHEME", "https");
			} else {
				env_collection.Add("SCHEME", "http");
			}
			env_collection.Add("REDIRECT_STATUS", res.Header.Statuscode);
			env_collection.Add("GATEWAY_INTERFACE","CGI/1.1");
			env_collection.Add("SERVER_PROTOCOL",res.Header.Httpversion);
			env_collection.Add("COOKIES",req.Header.Cookie);
			env_collection.Add("SERVER_PORT",req.Uri.Port.ToString());
			env_collection.Add("SERVER_NAME",req.Header.Host);
			env_collection.Add("SERVER_SOFTWARE",res.Header.Server);
			env_collection.Add("SCRIPT_FILENAME", ((FileDataAccessLayer)d).GetFullPath(req.script_name));
		}
Example #2
0
        internal virtual void worker_DoWork(Object arg)
        {
			http_message msg = new http_message();
			object[]            args        = (object[])arg;
			connection          cc          = (connection)args[0];
            try
            {
                webserver_plugin_manager scripters   = (webserver_plugin_manager)args[1];

				msg.ClientConnection = cc;
				msg.data_layer = _dataLayer;
				msg.ClientEndpoint = cc.Client.Client.RemoteEndPoint;
				msg.Status = "REQ";
                msg.Request = new http_request();
				msg.Request.Initialize(msg.ClientConnection);
				worker_ProgressChanged(0, msg);

				// Redirect these to fix releative path issues
				if (_dataLayer.DirectoryExists (msg.Request.script_name) && !msg.Request.script_name.EndsWith ("/")) {
					msg.Response = http_response.Create(msg,true);
					msg.Response.Header.Statuscode = "301";
					msg.Response.Header.Statusmessage = "Moved";
					msg.Response.Header.SetValue ("Location", msg.Request.script_name + "/");
					msg.Response.Header.ContentLength = 0;
					msg.Response.Respond(msg.ClientConnection.Client,msg.ClientStream);
					msg.Status = "FIN";
					cc.Processing = false;
					return;
				}
				msg.Status = "DIR";
				msg.Response = http_response.Create(msg,true);
				_directives.process(new object[]{msg.Request,msg.Response,_dataLayer});
				msg.Status = "RAM";
				if(!scripters.process(new object[] {msg})) {
					// If you are here then no "scripter" processed the request so
					// we had better do it.
					msg.Status = "RES";
					msg.Response = http_response.Create(msg, false);
					msg.Response.Respond(msg.ClientConnection.Client, msg.ClientStream);
				}
				msg.Status = "FIN";
                cc.processing = false;
            }
            catch (Exception ex)
            {
				msg.Status = "ERR";
#if DEBUG
				Console.Error.WriteLine(ex.Message);
				Console.Error.WriteLine(ex.StackTrace);
#endif
				if(ex is http_exception) {
					http_exception he = (http_exception)ex;
					msg.Response = he.response;
					try{he.send_response(msg.ClientConnection.Client,msg.ClientStream);}catch{}
					if(he.close_client_connection) {
						msg.ClientConnection.Client.Client.Disconnect(false);
						msg.ClientConnection = null;
					}
				} else {
					if(msg.Request != null) {
						msg.Response = http_response.CreateBasic(msg.Request,500);
						msg.Response.Header.SetValue(
							"Server",
							String.Format("{0}/{1}",Assembly.GetEntryAssembly().GetName().Name,Assembly.GetEntryAssembly().GetName().Version));
						msg.Response.Header.SetValue("ContentType","text/html");
						msg.Response.Header.SetValue("Cache-Control","no-cache");
						msg.Response.Body = new MemoryStream(Encoding.Default.GetBytes(http_function.CreateBasicHTML(ex.ToString())));
						msg.Response.Header.SetValue("Content-Length", msg.Response.Body.Length.ToString());
						http_function.SendBasicHtml(msg.ClientStream,msg.Response);
					} else {
						msg.ClientConnection.Client.Client.Disconnect(false);
						msg.ClientConnection = null;
					}
				}

            }
			cc.processing = false;
        }
Example #3
0
        public static http_response Create(http_message msg, Boolean basic)
        {
			http_request req = msg.Request;
            http_response res = CreateBasic(req,200);
			DataAccessLayer d = msg.data_layer;
            String targetfile = HttpUtility.UrlDecode(req.Uri.AbsolutePath);

			if (basic)
				return res;

			// TODO: Support these as test cases come up...
			if (req.Header.Verb == "CONNECT" || req.Header.Verb == "OPTIONS" || 
				req.Header.Verb == "DELETE" || req.Header.Verb == "PUT" || req.Header.Verb == "TRACE" || req.Header.Verb == "POST" ) {
#if DEBUG

				Console.Error.WriteLine("Unsupported Method: " + req.Header.Verb);
#endif
				res = CreateBasic(req,501);
				res.Header.ContentType = "text/plain; charset=" + Encoding.Default.WebName.ToUpper();
				byte[] body = Encoding.Default.GetBytes (res.Header.Statusmessage);
				res.Body.Write (body, 0, body.Length);
				res.Header.ContentLength = Convert.ToInt32 (res.Body.Length);
				return res;
			}

			if (d.DirectoryExists (targetfile)) {
				foreach (string index_file in _index_files) {
					if (d.FileExists (d.PathCombine (targetfile, index_file))) {
						req.Uri = new HttpUri (HttpUtility.UrlDecode (req.Uri.OriginalString).Replace (targetfile, d.URLPathCombine (req.Uri.AbsolutePath, index_file)));
						if(msg.ClientStream is SslStream)
							req.Header.Referer = "https://" + req.Header.Host + targetfile;
						else
							req.Header.Referer = "http://" + req.Header.Host + targetfile;
						targetfile = HttpUtility.UrlDecode (req.Uri.AbsolutePath);
						req.Header.Target = targetfile;
						break;
					}
				}
			}

			if (d.DirectoryExists(targetfile))
			{
				if (_allow_directory_browsing) {
					res.Header.Statuscode = "200";
					res.Header.Statusmessage = "OK";
					res.Header.SetValue("Cache-Control","no-cache");
					res.Header.SetValue ("Content-Type", "text/html; charset=" + Encoding.Default.WebName.ToUpper());
					String body = "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=" + 
						Encoding.Default.WebName + "\" />\n</head>\n<body>\n";
					String[] files = d.GetFiles (targetfile);
					String scheme = "http://";
					if(msg.ClientStream is SslStream)
						scheme = "https://";
					foreach (String file in files) {
						body += String.Format ("<a href=\"{0}\">{1}</a><br>\n", scheme + req.Header.Host + "/" + HttpUtility.UrlEncode (d.URLPathCombine("",file)).Replace ("%2f", "/"), Path.GetFileName (file));
					}
					body += "\n</body>\n</html>";
					byte[] bytes = Encoding.Default.GetBytes (body);
					res.Header.SetValue ("Content-Length", bytes.Length.ToString ());
					res.Body.Write (bytes, 0, (int)bytes.Length);
					res.End = (int)bytes.Length;
				} else {
					throw new http_exception(req,"Direcotry browsing is not permitted.",null,403);
				}

			}
			else if(d.FileExists(targetfile)) {

				if(!_disable_cache && req.Header.Values.ContainsKey("If-Modified-Since") &&
				    	DateTime.Parse(req.Header.GetValue("If-Modified-Since")).ToUniversalTime() ==
				    	d.GetFileDate(targetfile)) {
					res.Header.Statuscode = "304";
					res.Header.Statusmessage = "Not Modified";
					res.Header.SetValue("Expires", DateTime.Now.AddDays(1).ToString("r"));
					res.Header.SetValue("Cache-Control","public must-revalidate max-age=3600");
					res.Header.SetValue("Last-Modified",d.GetFileDate(targetfile).ToString("r"));
					res.Header.ContentLength = 0;
				}
				else if (req.Header.Values.ContainsKey ("Range")) {
					res.Body = d.GetFile(targetfile);
					res.Header.Statuscode = "206";
					res.Header.Statusmessage = "Partial Content";
					string range = req.Header.GetValue ("Range");
					string[] rangesplit = range.Split (new string[] { "=", "-" }, StringSplitOptions.RemoveEmptyEntries);
					if (rangesplit.Length > 0 && rangesplit [0].ToLower () != "bytes")
						throw new http_exception (req,"Range only accepted in bytes!",null,406);

					if (rangesplit.Length > 1 && rangesplit [1] != null)
						res.Start = Convert.ToInt32 (rangesplit [1]);

					if (rangesplit.Length > 2 && rangesplit [2] != null) {
						res.End = Convert.ToInt32 (rangesplit [2]);
					}
					else {
						res.End = res.Body.Length;
					}

					res.Header.ContentLength = Convert.ToInt32 (res.End - res.Start);

					res.Header.SetValue("Content-Range", 
					                    String.Format("bytes {0}-{1}/{2}",res.Start, res.End -1,res.End));
						                         
				} 
				else {
					res.Body = d.GetFile(targetfile);
					if(res.Body.Length > 1024 * 1024) {
						res.Header.SetValue("Accept-Ranges","bytes");
					}
					res.Header.Statuscode = "200";
					res.Header.Statusmessage = "OK";
					if(!_disable_cache) {
						res.Header.SetValue("Expires", DateTime.Now.AddDays(1).ToString("r"));
						res.Header.SetValue("Cache-Control","public must-revalidate max-age=3600");
						res.Header.SetValue("Last-Modified",d.GetFileDate(targetfile).ToString("r"));
					}
					else
						res.Header.SetValue("Cache-Control","no-cache");
					res.End = res.Body.Length;
					res.Header.ContentLength = Convert.ToInt32(res.Body.Length);
				}
				string ext = Path.GetExtension(req.Uri.AbsolutePath);
				res.Header.ContentType = mime_types.GetMimeType(ext);
			}
			else
            {
                throw new http_exception(
					req,
					String.Format("{0} was not found on this server",req.Header.Target),
					null,404);
            }
            return res;
        }