fix some issues in HTTP server and try to implement SSL

This commit is contained in:
Michael Becker 2024-11-07 07:29:16 -05:00
parent 05c3fd5274
commit 0054320a0e
10 changed files with 121 additions and 45 deletions

View File

@ -18,7 +18,7 @@ public class Button : WebControlWithMnemonic
{
if (DropDown != null)
{
return base.GetStyleClasses().Union(["uwt-button-dropdownbutton"]);
return base.GetStyleClasses().Union(new string[] { "uwt-button-dropdownbutton" });
}
return base.GetStyleClasses();
}

View File

@ -4,7 +4,7 @@ namespace MBS.Web.UI.WebControls;
public abstract class ContainerBase : WebControl
{
private IEnumerable<Control> _list = [ ];
private IEnumerable<Control> _list = new Control[0];
protected virtual IEnumerable<Control> GetChildControls()
{
return _list;

View File

@ -47,7 +47,7 @@ public class DockableContainer : Container
public CardinalDirection Position { get; set; } = CardinalDirection.Bottom;
protected override IEnumerable<string> GetStyleClasses()
{
{
string uwtDockPosition = "";
switch (Position)
{
@ -56,7 +56,7 @@ public class DockableContainer : Container
case CardinalDirection.Right: uwtDockPosition = "uwt-dock-right"; break;
case CardinalDirection.Bottom: uwtDockPosition = "uwt-dock-bottom"; break;
}
return base.GetStyleClasses().Union([ "uwt-dockable", uwtDockPosition ]);
return base.GetStyleClasses().Union(new string[] { "uwt-dockable", uwtDockPosition });
}

View File

@ -115,7 +115,7 @@ public class ListView : Container
protected override IEnumerable<string> GetStyleClasses()
{
return [ "uwt-listview" ];
return new string[] { "uwt-listview" };
}
protected override IReadOnlyDictionary<string, string> GetStyleProperties()
{

View File

@ -6,7 +6,7 @@ public class Menu : ContainerBase
protected override string TagName => "ul";
protected override IEnumerable<string> GetStyleClasses()
{
return [ "uwt-menu" ];
return new string[] { "uwt-menu" };
}
private IEnumerable<MenuItem>? _items = null;
@ -25,7 +25,7 @@ public class Menu : ContainerBase
{
return _items;
}
return [];
return new Control[0];
}
}

View File

@ -27,14 +27,14 @@ public abstract class MenuItem : ContainerBase
protected override IEnumerable<string> GetStyleClasses()
{
return base.GetStyleClasses().Union(["uwt-menu-item"]);
return base.GetStyleClasses().Union(new string[] { "uwt-menu-item" });
}
}
public class CommandMenuItem : MenuItem
{
protected override IEnumerable<string> GetStyleClasses()
{
return base.GetStyleClasses().Union(["uwt-menu-item-command"]);
return base.GetStyleClasses().Union(new string[] { "uwt-menu-item-command" });
}
public string Text { get; set; }
@ -55,7 +55,7 @@ public class CommandMenuItem : MenuItem
{
a.TargetUrl = TargetUrl;
}
return [a];
return new Control[] { a };
}
}

View File

@ -39,7 +39,7 @@ public class WebPage : Control
protected virtual IEnumerable<Control> GetHeaderControls()
{
return [ ];
return new Control[0];
}
protected override string TagName => "html";

View File

@ -24,7 +24,7 @@ public abstract class WebApplication : Application
ProcessRequest?.Invoke(this, e);
}
private void server_OnProcessRequest(object sender, WebServerProcessRequestEventArgs e)
private void server_OnProcessRequest(object? sender, WebServerProcessRequestEventArgs e)
{
OnProcessRequest(e);
}
@ -35,11 +35,16 @@ public abstract class WebApplication : Application
ServerCreated?.Invoke(this, e);
}
protected virtual WebServer CreateWebServer()
{
return new WebServer(new IPEndPoint(IPAddress.Any, DefaultPort));
}
protected override void OnStartup(EventArgs e)
{
base.OnStartup(e);
WebServer server = new WebServer(new IPEndPoint(IPAddress.Any, DefaultPort));
WebServer server = CreateWebServer();
Console.WriteLine("attempting to start server listening on port {0}", DefaultPort);
OnServerCreated(new WebServerCreatedEventArgs(server));

View File

@ -1,6 +1,7 @@
using System.Collections.ObjectModel;
using System.Data.SqlTypes;
using System.Net;
using MBS.Core;
namespace MBS.Web;
@ -31,12 +32,12 @@ public class WebRequest
int queryStringIndex = path.IndexOf('?');
if (queryStringIndex > -1)
{
Path = path.Substring(0, queryStringIndex);
Path = path.Substring(0, queryStringIndex).UrlDecode();
QueryString = path.Substring(queryStringIndex + 1);
}
else
{
Path = path;
Path = path.UrlDecode();
}
PathParts = Path.Split(new char[] { '/' });
@ -44,17 +45,18 @@ public class WebRequest
foreach (string queryStringPart in queryStringParts)
{
string[] nameValue = queryStringPart.Split(new char[] { '=' });
string key = nameValue[0].UrlDecode();
if (nameValue.Length > 1)
{
if (!Query.ContainsKey(nameValue[0]))
if (!Query.ContainsKey(key))
{
Query[nameValue[0]] = new List<string>();
Query[key] = new List<string>();
}
Query[nameValue[0]].Add(nameValue[1]);
Query[key].Add(nameValue[1].UrlDecode());
}
else
{
Query[nameValue[0]] = new List<string>();
Query[key] = new List<string>();
}
}

View File

@ -1,5 +1,7 @@
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using MBS.Core;
@ -160,6 +162,9 @@ public class WebServer
private Dictionary<string, Dictionary<string, object>> _sessions = new Dictionary<string, Dictionary<string, object>>();
public string? SSLCertificateFile = null;
public string? SSLCertificateKeyFile = null;
private void HandleClient(System.Net.Sockets.TcpClient client)
{
// WebServerProcessRequestEventArgs e = new WebServerProcessRequestEventArgs();
@ -174,9 +179,40 @@ public class WebServer
// client.ReceiveTimeout = 5000;
// client.SendTimeout = 5000;
NetworkStream st = client.GetStream();
Stream st = client.GetStream();
if (ServerCertificate != null)
{
SslStream ssl = new SslStream(client.GetStream(), false);
try
{
ssl.AuthenticateAsServer(ServerCertificate, false, SslProtocols.None, false);
}
catch (AuthenticationException ex)
{
Console.Error.WriteLine("AuthenticationException: {0}", ex.Message);
}
st = ssl;
}
else
{
Console.WriteLine("MBS.Web.WebServer: !! NOT using SSL !!");
}
StreamReader sr = new StreamReader(st);
/*
byte[] buffer = new byte[4096];
int len = st.Read(buffer, 0, buffer.Length);
Array.Resize<byte>(ref buffer, len);
string text = System.Text.Encoding.UTF8.GetString(buffer);
Console.WriteLine(text);
*/
string line = sr.ReadLine();
Console.Error.WriteLine(line);
if (line == null)
{
Console.Error.WriteLine("unexpected NULL line from client");
@ -186,7 +222,7 @@ public class WebServer
string[] lineParts = line.Split(new char[] { ' ' });
if (lineParts.Length != 3)
{
Console.Error.WriteLine("unexpected request from client:\n----> {0}", line);
Console.Error.WriteLine("unexpected request from client");
client.Close();
return;
}
@ -224,18 +260,21 @@ public class WebServer
if (contentLength != "")
{
int contentLengthInt = Int32.Parse(contentLength);
Console.Error.WriteLine("Content-Length: {0}", contentLengthInt);
char[] buffer = new char[contentLengthInt];
sr.ReadBlock(buffer, 0, contentLengthInt);
string content = new string(buffer);
Console.Error.WriteLine(content);
if (!String.IsNullOrEmpty(content))
{
string[] kvps = content.Split(new char[] { '&' });
foreach (string kvp in kvps)
{
string[] pv = kvp.Split(new char[] { '=' });
form[pv[0]] = pv[1].Replace('+', ' ');
form[pv[0].UrlDecode()] = pv[1].UrlDecode().Replace('+', ' ');
}
}
}
@ -328,34 +367,39 @@ public class WebServer
client.Close();
}
private void tClientThread_ParameterizedThreadStart(object parm)
private void tClientThread_ParameterizedThreadStart(object? parm)
{
System.Net.Sockets.TcpClient client = (System.Net.Sockets.TcpClient)parm;
Console.WriteLine("Client connected");
if (parm is System.Net.Sockets.TcpClient client)
{
Console.WriteLine("Client connected");
try
{
HandleClient(client);
try
{
HandleClient(client);
}
catch (System.Net.Sockets.SocketException ex)
{
Console.Error.WriteLine("caught SocketException; ignoring");
Console.Error.WriteLine(ex.Message);
}
catch (System.IO.IOException ex)
{
Console.Error.WriteLine("caught IOException; ignoring");
Console.Error.WriteLine(ex.Message);
}
catch (Exception ex)
{
Console.Error.WriteLine("caught exception of type {0}", ex.GetType().FullName);
Console.Error.WriteLine(ex.Message);
Console.Error.WriteLine(ex.StackTrace);
}
client.Close();
}
catch (System.Net.Sockets.SocketException ex)
{
Console.Error.WriteLine("caught SocketException; ignoring");
Console.Error.WriteLine(ex.Message);
}
catch (System.IO.IOException ex)
{
Console.Error.WriteLine("caught IOException; ignoring");
Console.Error.WriteLine(ex.Message);
}
catch (Exception ex)
{
Console.Error.WriteLine("caught exception of type {0}", ex.GetType().FullName);
Console.Error.WriteLine(ex.Message);
}
client.Close();
}
public X509Certificate? ServerCertificate { get; private set; } = null;
private bool _Stopping = false;
private Thread? tServer = null;
public void Start()
@ -365,6 +409,31 @@ public class WebServer
_Stopping = false;
if (SSLCertificateFile != null && SSLCertificateKeyFile != null)
{
Console.WriteLine("MBS.Web.WebServer: using SSL :)");
if (!System.IO.File.Exists(SSLCertificateFile))
{
Console.Error.WriteLine("SSLCertificateFile not found: {0}", SSLCertificateFile);
}
else if (!System.IO.File.Exists(SSLCertificateKeyFile))
{
Console.Error.WriteLine("SSLCertificateKeyFile not found: {0}", SSLCertificateKeyFile);
}
else
{
// assuming an 509 certificate has been loaded before in an init method of some sort
// X509Certificate serverCertificate = X509Certificate2.CreateFromCertFile(SSLCertificateFile);
ServerCertificate = X509Certificate2.CreateFromPemFile(SSLCertificateFile, SSLCertificateKeyFile);
}
}
else
{
Console.WriteLine("MBS.Web.WebServer: !! NOT using SSL !!");
}
tServer = new Thread(tServer_ThreadStart);
tServer.Start();
}