diff --git a/.vs/Server Dashboard/DesignTimeBuild/.dtbcache.v2 b/.vs/Server Dashboard/DesignTimeBuild/.dtbcache.v2 index 0982798..b463937 100644 Binary files a/.vs/Server Dashboard/DesignTimeBuild/.dtbcache.v2 and b/.vs/Server Dashboard/DesignTimeBuild/.dtbcache.v2 differ diff --git a/.vs/Server Dashboard/v16/.suo b/.vs/Server Dashboard/v16/.suo index 3d88c30..1aea689 100644 Binary files a/.vs/Server Dashboard/v16/.suo and b/.vs/Server Dashboard/v16/.suo differ diff --git a/Server Dashboard Socket/Channel/ClientChannel.cs b/Server Dashboard Socket/Channel/ClientChannel.cs new file mode 100644 index 0000000..ffb0802 --- /dev/null +++ b/Server Dashboard Socket/Channel/ClientChannel.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading.Tasks; + +namespace Server_Dashboard_Socket { + + /// + /// Client Socket + /// + /// The Protocol type, either JsonMessageProtocol or XmlMessageProtocol + /// The message type, either JObject or XDocument + public class ClientChannel : SocketChannel + where TProtocol : Protocol, new() { + + /// + /// Connect to the socket async + /// + /// An endpoint with an IP address and port + /// + public async Task ConnectAsync(IPEndPoint endpoint) { + //Creates a new Socket + var socket = new Socket(endpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + //Connects to the socket + await socket.ConnectAsync(endpoint).ConfigureAwait(false); + //Attach the socket to a network stream + Attach(socket); + } + } +} \ No newline at end of file diff --git a/Server Dashboard Socket/Channel/SocketChannel.cs b/Server Dashboard Socket/Channel/SocketChannel.cs new file mode 100644 index 0000000..ff210ad --- /dev/null +++ b/Server Dashboard Socket/Channel/SocketChannel.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Server_Dashboard_Socket { + + /// + /// Generic Channel class that handles the connection and message sending / receiving + /// Inherits IDisposable to correctly cut the connection to the server + /// + /// The Protocol type, either JsonMessageProtocol or XmlMessageProtocol + /// The message type, either JObject or XDocument + public abstract class SocketChannel : IDisposable + where TProtocol : Protocol, new() { + protected bool isDisposable = false; + private NetworkStream networkStream; + private readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); + private readonly TProtocol protocol = new TProtocol(); + + private Func messageCallback; + + /// + /// Attaches the socket to a network stream that owns the socket + /// if the network stream goes down it takes the socket with it! + /// + /// A Socket + public void Attach(Socket socket) { + networkStream = new NetworkStream(socket, true); + _ = Task.Run(ReceiveLoop, cancellationTokenSource.Token); + } + + /// + /// Takes a function with a message and sets the private member to the functions value + /// + /// + public void OnMessage(Func callbackHandler) => messageCallback = callbackHandler; + + /// + /// Makes sure to close the socket + /// + public void Close() { + cancellationTokenSource.Cancel(); + networkStream?.Close(); + } + + /// + /// Sends the message async + /// + /// Anything as message, e.g. object or string + /// The message + /// + public async Task SendAsync(T message) => await protocol.SendAsync(networkStream, message).ConfigureAwait(false); + + /// + /// Checks for received messages + /// + /// received message + protected virtual async Task ReceiveLoop() { + while (!cancellationTokenSource.Token.IsCancellationRequested) { + var msg = await protocol.ReceiveAsync(networkStream).ConfigureAwait(false); + await messageCallback(msg).ConfigureAwait(false); + } + } + + /// + /// Deconstructor sets Dispose to false + /// + ~SocketChannel() => Dispose(false); + + /// + /// Sets dispose to true + /// + public void Dispose() => Dispose(true); + + /// + /// Disposes open sockets + /// + /// Is it currently disposing stuff? + protected void Dispose(bool isDisposing) { + //If its not disposable + if (!isDisposable) { + //Set disposable to true + isDisposable = true; + //Close the socket + Close(); + //If its closed, dispose it + networkStream?.Dispose(); + //Wait with the garbage collection until the disposing is done + if (isDisposing) + GC.SuppressFinalize(this); + } + } + } +} \ No newline at end of file diff --git a/Server Dashboard Socket/Client/SocketClient.cs b/Server Dashboard Socket/Client/SocketClient.cs new file mode 100644 index 0000000..ca44d7a --- /dev/null +++ b/Server Dashboard Socket/Client/SocketClient.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Net.Sockets; +using System.Net; +using System.Threading.Tasks; +using System.IO; +using System.Xml.Serialization; +using Server_Dashboard_Socket.Protocol; +using Newtonsoft.Json.Linq; +using System.Xml.Linq; + +namespace Server_Dashboard_Socket { + + public class SocketClient { + + public SocketClient() { + //Starts the echo server for testing purposes + EchoServer echoServer = new EchoServer(); + echoServer.Start(); + //Start the Socket test + Start(); + } + + private async void Start() { + //Creates a new endpoint with the IP address and port + var endpoint = new IPEndPoint(IPAddress.Loopback, 9000); + + //Creates a new Channel for the Json protocol + var channel = new ClientChannel(); + //Creates a new Channel for the XDocument protocol + //var channel = new ClientChannel(); + + //Callback for the message + channel.OnMessage(OnMessage); + + //Connect to the Socket + await channel.ConnectAsync(endpoint).ConfigureAwait(false); + + //Test message + var myMessage = new MyMessage { + IntProperty = 404, + StringProperty = "Hello World!" + }; + //Send the test message + await channel.SendAsync(myMessage).ConfigureAwait(false); + } + + /// + /// When it receives a message it gets converted from Json back to MyMessage + /// + /// The json to be converted back + /// Task completed + private static Task OnMessage(JObject jobject) { + Console.WriteLine(Convert(jobject)); + return Task.CompletedTask; + } + + /// + /// When it receives a message it gets converted from XDocument back to MyMessage + /// + /// The xml to be converted back + /// Task completed + private static Task OnMessage(XDocument xDocument) { + Console.WriteLine(Convert(xDocument)); + return Task.CompletedTask; + } + + /// + /// Converts json to MyMessage + /// + /// The json to be converted + /// MyMessage object + private static MyMessage Convert(JObject jObject) => jObject.ToObject(typeof(MyMessage)) as MyMessage; + + /// + /// Converts XDocument to MyMessage + /// + /// The xml to be converted + /// MyMessage object + private static MyMessage Convert(XDocument xmlDocument) => new XmlSerializer(typeof(MyMessage)).Deserialize(new StringReader(xmlDocument.ToString())) as MyMessage; + } + + /// + /// MyMessage test class + /// Delete later when Sockets are finished + /// + public class MyMessage { + public int IntProperty { get; set; } + public string StringProperty { get; set; } + } +} \ No newline at end of file diff --git a/Server Dashboard Socket/EchoServer.cs b/Server Dashboard Socket/EchoServer.cs index 0d5fade..2d4339b 100644 --- a/Server Dashboard Socket/EchoServer.cs +++ b/Server Dashboard Socket/EchoServer.cs @@ -4,34 +4,56 @@ using System.Net.Sockets; using System.Threading.Tasks; namespace Server_Dashboard_Socket { + /// /// Basic echo server to test the socket connection /// public class EchoServer { - public void Start(int port = 9565) { + + /// + /// Start the socket on 127.0.0.1:9000 + /// + /// A port that is not already in use + public void Start(int port = 9000) { + //Creates a new endpoint on 127.0.0.1 and the port 9000 IPEndPoint endPoint = new IPEndPoint(IPAddress.Loopback, port); + //Creates a new Socket on the given endpoint Socket socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + //Bind the endpoint to the socket socket.Bind(endPoint); + //Define how many Clients you want to have connected max socket.Listen(128); + //Just run the Task forever _ = Task.Run(() => DoEcho(socket)); } + /// + /// Listens for messages and sends them back asap + /// + /// The socket to work with + /// poop private async Task DoEcho(Socket socket) { while (true) { + //Listen for incoming connection requests and accept them Socket clientSocket = await Task.Factory.FromAsync( new Func(socket.BeginAccept), new Func(socket.EndAccept), null).ConfigureAwait(false); - using(NetworkStream stream = new NetworkStream(clientSocket, true)) { - byte[] buffer = new byte[1024]; - while (true) { - int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false); - if (bytesRead == 0) - break; - await stream.WriteAsync(buffer, 0, bytesRead).ConfigureAwait(false); - } + //Create a network stream and make it the owner of the socket + //This will close the socket if the stream is closed and vice verca + await using NetworkStream stream = new NetworkStream(clientSocket, true); + //New buffer for the message in bytes + byte[] buffer = new byte[1024]; + while (true) { + //Read everything that comes in + int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false); + //If its 0 just leave since its a obsolete connection + if (bytesRead == 0) + break; + //Send it back to the sender + await stream.WriteAsync(buffer, 0, bytesRead).ConfigureAwait(false); } } } } -} +} \ No newline at end of file diff --git a/Server Dashboard Socket/Protocol/JsonMessageProtocol.cs b/Server Dashboard Socket/Protocol/JsonMessageProtocol.cs new file mode 100644 index 0000000..e1c67cd --- /dev/null +++ b/Server Dashboard Socket/Protocol/JsonMessageProtocol.cs @@ -0,0 +1,54 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Newtonsoft.Json.Serialization; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace Server_Dashboard_Socket.Protocol { + + /// + /// Json serializer class + /// + public class JsonMessageProtocol : Protocol { + + //The Json serializer and the settings + private static readonly JsonSerializer serializer; + + /// + /// Settings for the Json Serializer + /// + static JsonMessageProtocol() { + //Set the settings + JsonSerializerSettings settings = new JsonSerializerSettings { + Formatting = Formatting.Indented, + DateTimeZoneHandling = DateTimeZoneHandling.Utc, + ContractResolver = new DefaultContractResolver { + NamingStrategy = new CamelCaseNamingStrategy { + ProcessDictionaryKeys = false + } + } + }; + settings.PreserveReferencesHandling = PreserveReferencesHandling.None; + //Creates the serializer with the settings + serializer = JsonSerializer.Create(settings); + } + + //Decode the message, to Json + protected override JObject Decode(byte[] message) => JObject.Parse(Encoding.UTF8.GetString(message)); + + /// + /// Encode the body from Json to bytes + /// + /// The message type e.g. object or string + /// The message to send + /// message as byte[] + protected override byte[] EncodeBody(T message) { + var sb = new StringBuilder(); + var sw = new StringWriter(sb); + serializer.Serialize(sw, message); + return Encoding.UTF8.GetBytes(sb.ToString()); + } + } +} \ No newline at end of file diff --git a/Server Dashboard Socket/Protocol/Protocol.cs b/Server Dashboard Socket/Protocol/Protocol.cs new file mode 100644 index 0000000..0b67e08 --- /dev/null +++ b/Server Dashboard Socket/Protocol/Protocol.cs @@ -0,0 +1,135 @@ +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading.Tasks; + +namespace Server_Dashboard_Socket { + + /// + /// Generic Protocol class for Json and Xml serialization + /// + /// JsonMessageProtocol or XmlMessageProtocol + public abstract class Protocol { + + //Header size is always 4 + private const int HeaderSize = 4; + + /// + /// Gets the message and checks with the header if the message is valid or not + /// important to defend against attacks with infinite long messages + /// + /// A network stream + /// MessageType e.g. Json or Xml + public async Task ReceiveAsync(NetworkStream networkStream) { + //Gets the body length + int bodyLength = await ReadHeader(networkStream).ConfigureAwait(false); + //Validates the length + AssertValidMessageLength(bodyLength); + //Returns the body message type + return await ReadBody(networkStream, bodyLength).ConfigureAwait(false); + } + + /// + /// Sends data Async + /// + /// Message type e.g. object or string + /// Network stream + /// The message + /// + public async Task SendAsync(NetworkStream networkStream, T message) { + //encodes the message to a header and body + var (header, body) = Encode(message); + //Sends the header + await networkStream.WriteAsync(header, 0, header.Length).ConfigureAwait(false); + //Sends the body + await networkStream.WriteAsync(body, 0, body.Length).ConfigureAwait(false); + } + + /// + /// Reads the header and converts it to an integer + /// + /// A network stream + /// Header as Integer + private async Task ReadHeader(NetworkStream networkStream) { + byte[] headerBytes = await ReadAsync(networkStream, HeaderSize).ConfigureAwait(false); + return IPAddress.HostToNetworkOrder(BitConverter.ToInt32(headerBytes)); + } + + /// + /// Reads the body and decodes it to a human readable string + /// + /// A network stream + /// Length of the body + /// Decoded body + private async Task ReadBody(NetworkStream networkStream, int bodyLength) { + //Reads the bytes from the stream into an array + byte[] bodyBytes = await ReadAsync(networkStream, bodyLength).ConfigureAwait(false); + //Decodes it and returns the string + return Decode(bodyBytes); + } + + /// + /// Reads the network stream as long as something is readable + /// + /// A network stream + /// how many bytes there are to read + /// Every byte from the Stream + private async Task ReadAsync(NetworkStream networkStream, int bytesToRead) { + //new buffer that is as big as the content(watch out for buffer overflows) + byte[] buffer = new byte[bytesToRead]; + //keep account of the bytes that are already read + int bytesRead = 0; + //White we still have something to read + while (bytesRead < bytesToRead) { + //Read it from the stream + var bytesReceived = await networkStream.ReadAsync(buffer, bytesRead, (bytesToRead - bytesRead)).ConfigureAwait(false); + //If it happens to be 0 close the socket + if (bytesReceived == 0) + throw new Exception("Socket Closed"); + bytesRead += bytesReceived; + } + return buffer; + } + + /// + /// Encode the message from human readable to bytes for the stream + /// + /// The message as anything e.g. object or string + /// The message to be send + /// The Header and Body as bytes[] + protected (byte[] header, byte[] body) Encode(T message) { + //Creates the body bytes + var bodyBytes = EncodeBody(message); + //Creates the header bytes + var headerBytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(bodyBytes.Length)); + return (headerBytes, bodyBytes); + } + + /// + /// Decode the message with the given type, json or xml + /// + /// The message to decode + /// Decoded message + protected abstract TMessageType Decode(byte[] message); + + /// + /// Validate the message length to combat attacks + /// + /// The message length + protected virtual void AssertValidMessageLength(int messageLength) { + //If its not 0 throw an exception + if (messageLength < 1) + throw new ArgumentOutOfRangeException("Invalid message length"); + } + + /// + /// Encode the message so it can be send via the network stream + /// + /// Message type e.g. object or string + /// The message to be send + /// + protected abstract byte[] EncodeBody(T message); + } +} \ No newline at end of file diff --git a/Server Dashboard Socket/Protocol/XmlMessageProtocol.cs b/Server Dashboard Socket/Protocol/XmlMessageProtocol.cs new file mode 100644 index 0000000..862e322 --- /dev/null +++ b/Server Dashboard Socket/Protocol/XmlMessageProtocol.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Xml; +using System.Xml.Linq; +using System.Xml.Serialization; + +namespace Server_Dashboard_Socket { + /// + /// Xml serialize class + /// + public class XmlMessageProtocol : Protocol { + /// + /// Decodes the message from byte[] to XDocument + /// + /// The message to decode + /// Message as XDocument + protected override XDocument Decode(byte[] message) { + //Reads the data as utf8 string + var xmlData = Encoding.UTF8.GetString(message); + //Creates a new reader + var xmlReader = XmlReader.Create(new StringReader(xmlData), new XmlReaderSettings { DtdProcessing = DtdProcessing.Ignore }); + //Decodes the data to XDocument format + return XDocument.Load(xmlReader); + } + + /// + /// Encode the XDocument to byte[] + /// + /// Message type e.g. object or string + /// The message to encode + /// Message as byte[] + protected override byte[] EncodeBody(T message) { + //new string builder + StringBuilder sb = new StringBuilder(); + //New string writer with the string builder + StringWriter sw = new StringWriter(sb); + //new xml serializer with the same type as the message + XmlSerializer xs = new XmlSerializer(typeof(T)); + //Serialize the message to a regular string + xs.Serialize(sw, message); + //Return as UTF8 encoded byte array + return Encoding.UTF8.GetBytes(sb.ToString()); + } + } +} diff --git a/Server Dashboard Socket/Server Dashboard Socket.csproj b/Server Dashboard Socket/Server Dashboard Socket.csproj index 3f916be..8c74aa7 100644 --- a/Server Dashboard Socket/Server Dashboard Socket.csproj +++ b/Server Dashboard Socket/Server Dashboard Socket.csproj @@ -5,4 +5,8 @@ Server_Dashboard_Socket + + + + diff --git a/Server Dashboard Socket/bin/Debug/netcoreapp3.1/Server Dashboard Socket.deps.json b/Server Dashboard Socket/bin/Debug/netcoreapp3.1/Server Dashboard Socket.deps.json index a59945e..136b03e 100644 --- a/Server Dashboard Socket/bin/Debug/netcoreapp3.1/Server Dashboard Socket.deps.json +++ b/Server Dashboard Socket/bin/Debug/netcoreapp3.1/Server Dashboard Socket.deps.json @@ -7,9 +7,20 @@ "targets": { ".NETCoreApp,Version=v3.1": { "Server Dashboard Socket/1.0.0": { + "dependencies": { + "Newtonsoft.Json": "13.0.1" + }, "runtime": { "Server Dashboard Socket.dll": {} } + }, + "Newtonsoft.Json/13.0.1": { + "runtime": { + "lib/netstandard2.0/Newtonsoft.Json.dll": { + "assemblyVersion": "13.0.0.0", + "fileVersion": "13.0.1.25517" + } + } } } }, @@ -18,6 +29,13 @@ "type": "project", "serviceable": false, "sha512": "" + }, + "Newtonsoft.Json/13.0.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==", + "path": "newtonsoft.json/13.0.1", + "hashPath": "newtonsoft.json.13.0.1.nupkg.sha512" } } } \ No newline at end of file diff --git a/Server Dashboard Socket/bin/Debug/netcoreapp3.1/Server Dashboard Socket.dll b/Server Dashboard Socket/bin/Debug/netcoreapp3.1/Server Dashboard Socket.dll index 691a1a2..1bd2888 100644 Binary files a/Server Dashboard Socket/bin/Debug/netcoreapp3.1/Server Dashboard Socket.dll and b/Server Dashboard Socket/bin/Debug/netcoreapp3.1/Server Dashboard Socket.dll differ diff --git a/Server Dashboard Socket/bin/Debug/netcoreapp3.1/Server Dashboard Socket.pdb b/Server Dashboard Socket/bin/Debug/netcoreapp3.1/Server Dashboard Socket.pdb index d7aa5aa..cfffdd0 100644 Binary files a/Server Dashboard Socket/bin/Debug/netcoreapp3.1/Server Dashboard Socket.pdb and b/Server Dashboard Socket/bin/Debug/netcoreapp3.1/Server Dashboard Socket.pdb differ diff --git a/Server Dashboard Socket/obj/Debug/netcoreapp3.1/Server Dashboard Socket.assets.cache b/Server Dashboard Socket/obj/Debug/netcoreapp3.1/Server Dashboard Socket.assets.cache index 499aecf..ec2c9a1 100644 Binary files a/Server Dashboard Socket/obj/Debug/netcoreapp3.1/Server Dashboard Socket.assets.cache and b/Server Dashboard Socket/obj/Debug/netcoreapp3.1/Server Dashboard Socket.assets.cache differ diff --git a/Server Dashboard Socket/obj/Debug/netcoreapp3.1/Server Dashboard Socket.csproj.CoreCompileInputs.cache b/Server Dashboard Socket/obj/Debug/netcoreapp3.1/Server Dashboard Socket.csproj.CoreCompileInputs.cache index 5c9baf3..9b4fe16 100644 --- a/Server Dashboard Socket/obj/Debug/netcoreapp3.1/Server Dashboard Socket.csproj.CoreCompileInputs.cache +++ b/Server Dashboard Socket/obj/Debug/netcoreapp3.1/Server Dashboard Socket.csproj.CoreCompileInputs.cache @@ -1 +1 @@ -40cb88c995736b43b2440aaa34383fa2c95563ea +8966ab4db41ed1e711f8adec4e833a86df6a665c diff --git a/Server Dashboard Socket/obj/Debug/netcoreapp3.1/Server Dashboard Socket.csprojAssemblyReference.cache b/Server Dashboard Socket/obj/Debug/netcoreapp3.1/Server Dashboard Socket.csprojAssemblyReference.cache index 8a5ef04..262f7ca 100644 Binary files a/Server Dashboard Socket/obj/Debug/netcoreapp3.1/Server Dashboard Socket.csprojAssemblyReference.cache and b/Server Dashboard Socket/obj/Debug/netcoreapp3.1/Server Dashboard Socket.csprojAssemblyReference.cache differ diff --git a/Server Dashboard Socket/obj/Debug/netcoreapp3.1/Server Dashboard Socket.dll b/Server Dashboard Socket/obj/Debug/netcoreapp3.1/Server Dashboard Socket.dll index 691a1a2..1bd2888 100644 Binary files a/Server Dashboard Socket/obj/Debug/netcoreapp3.1/Server Dashboard Socket.dll and b/Server Dashboard Socket/obj/Debug/netcoreapp3.1/Server Dashboard Socket.dll differ diff --git a/Server Dashboard Socket/obj/Debug/netcoreapp3.1/Server Dashboard Socket.pdb b/Server Dashboard Socket/obj/Debug/netcoreapp3.1/Server Dashboard Socket.pdb index d7aa5aa..cfffdd0 100644 Binary files a/Server Dashboard Socket/obj/Debug/netcoreapp3.1/Server Dashboard Socket.pdb and b/Server Dashboard Socket/obj/Debug/netcoreapp3.1/Server Dashboard Socket.pdb differ diff --git a/Server Dashboard Socket/obj/Server Dashboard Socket.csproj.nuget.dgspec.json b/Server Dashboard Socket/obj/Server Dashboard Socket.csproj.nuget.dgspec.json index 81aec51..341d0f4 100644 --- a/Server Dashboard Socket/obj/Server Dashboard Socket.csproj.nuget.dgspec.json +++ b/Server Dashboard Socket/obj/Server Dashboard Socket.csproj.nuget.dgspec.json @@ -43,6 +43,12 @@ "frameworks": { "netcoreapp3.1": { "targetAlias": "netcoreapp3.1", + "dependencies": { + "Newtonsoft.Json": { + "target": "Package", + "version": "[13.0.1, )" + } + }, "imports": [ "net461", "net462", diff --git a/Server Dashboard Socket/obj/project.assets.json b/Server Dashboard Socket/obj/project.assets.json index 21f1ad3..cee09ec 100644 --- a/Server Dashboard Socket/obj/project.assets.json +++ b/Server Dashboard Socket/obj/project.assets.json @@ -1,11 +1,51 @@ { "version": 3, "targets": { - ".NETCoreApp,Version=v3.1": {} + ".NETCoreApp,Version=v3.1": { + "Newtonsoft.Json/13.0.1": { + "type": "package", + "compile": { + "lib/netstandard2.0/Newtonsoft.Json.dll": {} + }, + "runtime": { + "lib/netstandard2.0/Newtonsoft.Json.dll": {} + } + } + } + }, + "libraries": { + "Newtonsoft.Json/13.0.1": { + "sha512": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==", + "type": "package", + "path": "newtonsoft.json/13.0.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.md", + "lib/net20/Newtonsoft.Json.dll", + "lib/net20/Newtonsoft.Json.xml", + "lib/net35/Newtonsoft.Json.dll", + "lib/net35/Newtonsoft.Json.xml", + "lib/net40/Newtonsoft.Json.dll", + "lib/net40/Newtonsoft.Json.xml", + "lib/net45/Newtonsoft.Json.dll", + "lib/net45/Newtonsoft.Json.xml", + "lib/netstandard1.0/Newtonsoft.Json.dll", + "lib/netstandard1.0/Newtonsoft.Json.xml", + "lib/netstandard1.3/Newtonsoft.Json.dll", + "lib/netstandard1.3/Newtonsoft.Json.xml", + "lib/netstandard2.0/Newtonsoft.Json.dll", + "lib/netstandard2.0/Newtonsoft.Json.xml", + "newtonsoft.json.13.0.1.nupkg.sha512", + "newtonsoft.json.nuspec", + "packageIcon.png" + ] + } }, - "libraries": {}, "projectFileDependencyGroups": { - ".NETCoreApp,Version=v3.1": [] + ".NETCoreApp,Version=v3.1": [ + "Newtonsoft.Json >= 13.0.1" + ] }, "packageFolders": { "C:\\Users\\Crylia\\.nuget\\packages\\": {}, @@ -50,6 +90,12 @@ "frameworks": { "netcoreapp3.1": { "targetAlias": "netcoreapp3.1", + "dependencies": { + "Newtonsoft.Json": { + "target": "Package", + "version": "[13.0.1, )" + } + }, "imports": [ "net461", "net462", diff --git a/Server Dashboard Socket/obj/project.nuget.cache b/Server Dashboard Socket/obj/project.nuget.cache index efa6611..58a9d77 100644 --- a/Server Dashboard Socket/obj/project.nuget.cache +++ b/Server Dashboard Socket/obj/project.nuget.cache @@ -1,8 +1,10 @@ { "version": 2, - "dgSpecHash": "TThsag+xtSY7ctBsPwAhUX7uLjuhld1ipCW1nP987HRzxMfYvczqncYfdca/U4IfbiniWP3eJFeh7yA09+/gGA==", + "dgSpecHash": "l9ApM4rx/nIquK7TUSE2VVfvhwnQ4+tycTwd5vMzM9v+MhFzGIKE8eVwCEj+r8Oe9Orh3cE/LeZlJ+t9G9ZaSg==", "success": true, "projectFilePath": "C:\\Users\\Crylia\\Documents\\Git\\Server Dashboard\\Server Dashboard Socket\\Server Dashboard Socket.csproj", - "expectedPackageFiles": [], + "expectedPackageFiles": [ + "C:\\Users\\Crylia\\.nuget\\packages\\newtonsoft.json\\13.0.1\\newtonsoft.json.13.0.1.nupkg.sha512" + ], "logs": [] } \ No newline at end of file diff --git a/Server Dashboard/App.xaml b/Server Dashboard/App.xaml index cf4f5d7..bffe929 100644 --- a/Server Dashboard/App.xaml +++ b/Server Dashboard/App.xaml @@ -4,23 +4,31 @@ xmlns:local="clr-namespace:Server_Dashboard" xmlns:views="clr-namespace:Server_Dashboard.Views.DashboardPages" xmlns:modulescrud="clr-namespace:Server_Dashboard.Views.DashboardPages.ModuleCRUD" + xmlns:dashboardviews="clr-namespace:Server_Dashboard.Views.Dashboard" + xmlns:svgc="http://sharpvectors.codeplex.com/svgc/" StartupUri="LoginWindow.xaml"> - - + + + + + + + + - + - - - + + + - Open Sans + Open Sans - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + - + - + - + - + @@ -330,26 +344,26 @@ - + \ No newline at end of file diff --git a/Server Dashboard/Assets/Images/Docs.png b/Server Dashboard/Assets/Images/Docs.png deleted file mode 100644 index 0828a73..0000000 Binary files a/Server Dashboard/Assets/Images/Docs.png and /dev/null differ diff --git a/Server Dashboard/Assets/Images/Docs.svg b/Server Dashboard/Assets/Images/Docs.svg deleted file mode 100644 index c57424a..0000000 --- a/Server Dashboard/Assets/Images/Docs.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - background - - - - Layer 1 - - - \ No newline at end of file diff --git a/Server Dashboard/Assets/Images/DocsLight.png b/Server Dashboard/Assets/Images/DocsLight.png deleted file mode 100644 index 5c4570c..0000000 Binary files a/Server Dashboard/Assets/Images/DocsLight.png and /dev/null differ diff --git a/Server Dashboard/Assets/Images/GitHub-Mark.svg b/Server Dashboard/Assets/Images/GitHub-Mark.svg deleted file mode 100644 index 8ae40ce..0000000 --- a/Server Dashboard/Assets/Images/GitHub-Mark.svg +++ /dev/null @@ -1,483 +0,0 @@ - -image/svg+xml diff --git a/Server Dashboard/Assets/Images/GitHub.png b/Server Dashboard/Assets/Images/GitHub.png deleted file mode 100644 index ea6ff54..0000000 Binary files a/Server Dashboard/Assets/Images/GitHub.png and /dev/null differ diff --git a/Server Dashboard/Assets/Images/GitHubLight.png b/Server Dashboard/Assets/Images/GitHubLight.png deleted file mode 100644 index 192846a..0000000 Binary files a/Server Dashboard/Assets/Images/GitHubLight.png and /dev/null differ diff --git a/Server Dashboard/Assets/Images/PlaceHolderModule.png b/Server Dashboard/Assets/Images/PlaceHolderModule.png deleted file mode 100644 index d59d243..0000000 Binary files a/Server Dashboard/Assets/Images/PlaceHolderModule.png and /dev/null differ diff --git a/Server Dashboard/Assets/Images/PlaceHolderModuleLight.png b/Server Dashboard/Assets/Images/PlaceHolderModuleLight.png deleted file mode 100644 index 8c74968..0000000 Binary files a/Server Dashboard/Assets/Images/PlaceHolderModuleLight.png and /dev/null differ diff --git a/Server Dashboard/Assets/Images/Settings.svg b/Server Dashboard/Assets/Images/Settings.svg deleted file mode 100644 index b2b9e01..0000000 --- a/Server Dashboard/Assets/Images/Settings.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - background - - - - Layer 1 - - - - \ No newline at end of file diff --git a/Server Dashboard/Assets/Images/User.svg b/Server Dashboard/Assets/Images/User.svg deleted file mode 100644 index 2914906..0000000 --- a/Server Dashboard/Assets/Images/User.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - background - - - - Layer 1 - - - - \ No newline at end of file diff --git a/Server Dashboard/Assets/Images/userlogin.png b/Server Dashboard/Assets/Images/userlogin.png deleted file mode 100644 index 2fd549e..0000000 Binary files a/Server Dashboard/Assets/Images/userlogin.png and /dev/null differ diff --git a/Server Dashboard/Assets/Images/userpasswd.png b/Server Dashboard/Assets/Images/userpasswd.png deleted file mode 100644 index a117ad0..0000000 Binary files a/Server Dashboard/Assets/Images/userpasswd.png and /dev/null differ diff --git a/Server Dashboard/AttachedProperty/BaseAttachedProperty.cs b/Server Dashboard/AttachedProperty/BaseAttachedProperty.cs index 1046070..c50fe4b 100644 --- a/Server Dashboard/AttachedProperty/BaseAttachedProperty.cs +++ b/Server Dashboard/AttachedProperty/BaseAttachedProperty.cs @@ -4,22 +4,30 @@ using System.Text; using System.Windows; namespace Server_Dashboard { + /// /// Attached property base class /// - /// - /// - public abstract class BaseAttachedProperty - where Parent : BaseAttachedProperty, new() { + /// + /// + public abstract class BaseAttachedProperty + where TParent : BaseAttachedProperty, new() { + public event Action ValueChanged = (sender, e) => { }; - public static Parent Instance { get; private set; } = new Parent(); - public static readonly DependencyProperty ValueProperty = DependencyProperty.RegisterAttached("Value", typeof(Property), typeof(BaseAttachedProperty), new PropertyMetadata(new PropertyChangedCallback(OnValuePropertyChanged))); + + public static TParent Instance { get; private set; } = new TParent(); + public static readonly DependencyProperty ValueProperty = DependencyProperty.RegisterAttached("Value", typeof(TProperty), typeof(BaseAttachedProperty), new PropertyMetadata(new PropertyChangedCallback(OnValuePropertyChanged))); + private static void OnValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { Instance.OnValueChanged(d, e); Instance.ValueChanged(d, e); } - public static Property GetValue(DependencyObject d) => (Property)d.GetValue(ValueProperty); - public static void SetValue(DependencyObject d, Property value) => d.SetValue(ValueProperty, value); - public virtual void OnValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { } + + public static TProperty GetValue(DependencyObject d) => (TProperty)d.GetValue(ValueProperty); + + public static void SetValue(DependencyObject d, TProperty value) => d.SetValue(ValueProperty, value); + + public virtual void OnValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { + } } -} +} \ No newline at end of file diff --git a/Server Dashboard/AttachedProperty/HyperlinkProperties.cs b/Server Dashboard/AttachedProperty/HyperlinkProperties.cs index 47d27c6..44055c7 100644 --- a/Server Dashboard/AttachedProperty/HyperlinkProperties.cs +++ b/Server Dashboard/AttachedProperty/HyperlinkProperties.cs @@ -6,7 +6,9 @@ using System.Windows; using System.Windows.Documents; namespace Server_Dashboard { + public static class HyperlinkExtensions { + public static bool GetIsExternal(DependencyObject obj) { return (bool)obj.GetValue(IsExternalProperty); } @@ -14,23 +16,25 @@ namespace Server_Dashboard { public static void SetIsExternal(DependencyObject obj, bool value) { obj.SetValue(IsExternalProperty, value); } + public static readonly DependencyProperty IsExternalProperty = DependencyProperty.RegisterAttached("IsExternal", typeof(bool), typeof(HyperlinkExtensions), new UIPropertyMetadata(false, OnIsExternalChanged)); private static void OnIsExternalChanged(object sender, DependencyPropertyChangedEventArgs args) { var hyperlink = sender as Hyperlink; - if ((bool)args.NewValue) - hyperlink.RequestNavigate += Hyperlink_RequestNavigate; - else + if ((bool)args.NewValue) { + if (hyperlink != null) + hyperlink.RequestNavigate += Hyperlink_RequestNavigate; + } else if (hyperlink != null) hyperlink.RequestNavigate -= Hyperlink_RequestNavigate; } private static void Hyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e) { try { Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri) { UseShellExecute = true }); - } catch { } + } catch (Exception) { } e.Handled = true; } } -} +} \ No newline at end of file diff --git a/Server Dashboard/AttachedProperty/PasswordBoxProperties.cs b/Server Dashboard/AttachedProperty/PasswordBoxProperties.cs index 132d7b6..37fb622 100644 --- a/Server Dashboard/AttachedProperty/PasswordBoxProperties.cs +++ b/Server Dashboard/AttachedProperty/PasswordBoxProperties.cs @@ -2,17 +2,18 @@ using System.Windows.Controls; namespace Server_Dashboard { + public class MonitorPasswordProperty : BaseAttachedProperty { + public override void OnValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { - var passwordBox = sender as PasswordBox; - if (passwordBox == null) + if (!(sender is PasswordBox passwordBox)) return; passwordBox.PasswordChanged -= PasswordBox_PasswordChanged; - if ((bool)e.NewValue) { - HasTextProperty.SetValue(passwordBox); - passwordBox.PasswordChanged += PasswordBox_PasswordChanged; - } + if (!(bool)e.NewValue) + return; + HasTextProperty.SetValue(passwordBox); + passwordBox.PasswordChanged += PasswordBox_PasswordChanged; } private void PasswordBox_PasswordChanged(object sender, RoutedEventArgs e) { @@ -21,8 +22,9 @@ namespace Server_Dashboard { } public class HasTextProperty : BaseAttachedProperty { + public static void SetValue(DependencyObject sender) { SetValue(sender, ((PasswordBox)sender).SecurePassword.Length < 1); } } -} +} \ No newline at end of file diff --git a/Server Dashboard/AttachedProperty/WindowProperties.cs b/Server Dashboard/AttachedProperty/WindowProperties.cs index 68a2709..23e0380 100644 --- a/Server Dashboard/AttachedProperty/WindowProperties.cs +++ b/Server Dashboard/AttachedProperty/WindowProperties.cs @@ -1,7 +1,9 @@ using System.Windows; namespace Server_Dashboard { + public class CloseProperty : BaseAttachedProperty { + public override void OnValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { if (sender is Window window) { window.Loaded += (s, e) => { @@ -14,4 +16,4 @@ namespace Server_Dashboard { } } } -} +} \ No newline at end of file diff --git a/Server Dashboard/Controls/Dashboard/CRUD Popup/CreateModulePopup.xaml b/Server Dashboard/Controls/Dashboard/CRUD Popup/CreateModulePopup.xaml deleted file mode 100644 index 2cadfe9..0000000 --- a/Server Dashboard/Controls/Dashboard/CRUD Popup/CreateModulePopup.xaml +++ /dev/null @@ -1,168 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/Server Dashboard/Controls/ServerModules/ServerModule.xaml.cs b/Server Dashboard/Controls/ServerModules/ServerModule.xaml.cs index 702692a..5a8bd76 100644 --- a/Server Dashboard/Controls/ServerModules/ServerModule.xaml.cs +++ b/Server Dashboard/Controls/ServerModules/ServerModule.xaml.cs @@ -12,12 +12,14 @@ using System.Windows.Navigation; using System.Windows.Shapes; namespace Server_Dashboard.Controls.ServerModules { + /// /// Interaktionslogik für ServerModule.xaml /// public partial class ServerModule : UserControl { + public ServerModule() { InitializeComponent(); } } -} +} \ No newline at end of file diff --git a/Server Dashboard/DashboardModules/NewModuleInformation.cs b/Server Dashboard/DashboardModules/NewModuleInformation.cs deleted file mode 100644 index e820a56..0000000 --- a/Server Dashboard/DashboardModules/NewModuleInformation.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Server_Dashboard.DashboardModules { - /// - /// The Information the user puts into the CreateNewModule form - /// - class NewModuleInformation { - //The Name of the Module - public string ModuleName { get; set; } - //The Name of the Server - public string ServerName { get; set; } - //The Username - public string Username { get; set; } - //IPv4 Adress - public string IPAdress { get; set; } - //Port, defaults to 22 - public int Port { get; set; } - } -} diff --git a/Server Dashboard/DashboardModules/ServerInformation.cs b/Server Dashboard/DashboardModules/ServerInformation.cs deleted file mode 100644 index 74cebbf..0000000 --- a/Server Dashboard/DashboardModules/ServerInformation.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Text; - -namespace Server_Dashboard { - /// - /// Server information class, this will probably scale pretty big later on - /// This will hold all the information the socket will gather - /// - class ServerInformation { - //The ServerName - public string ServerName { get; set; } - //The unix or windows username - public string OSUserName { get; set; } - //Cpu Temp in C - public string CpuTemp { get; set; } - //Gpu Temp in C - public string GpuTemp { get; set; } - //Server uptime - public string Uptime { get; set; } - //When the server was first deployed - public string DeployDate { get; set; } - //Public IPv4 Adress - public string PublicIpAdress { get; set; } - //Private IP adress from the servers network - public string PrivateIpAdress { get; set; } - //GPU usage in % - public string GpuUsage { get; set; } - //CPU usage in % - public string CpuUsage { get; set; } - } -} diff --git a/Server Dashboard/Database/DatabaseHandler.cs b/Server Dashboard/Database/DatabaseHandler.cs index a0b2e19..67737fa 100644 --- a/Server Dashboard/Database/DatabaseHandler.cs +++ b/Server Dashboard/Database/DatabaseHandler.cs @@ -1,17 +1,17 @@ -using Microsoft.Win32; -using System; -using System.Collections.Generic; +using System; using System.Configuration; using System.Data; using System.Data.SqlClient; -using System.Reflection; namespace Server_Dashboard { + /// /// Database class to access the database /// public static class DatabaseHandler { + #region Public Methods + /// /// Checks the user credentials /// @@ -20,136 +20,284 @@ namespace Server_Dashboard { /// [0] is false, [1] is true, [2] connection error public static int CheckLogin(string uname, string passwd) { //Creates the database connection - using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ServerDashboardDB"].ConnectionString)) { - try { - //Open the connection - con.Open(); - //SQL Query - string query = "EXEC ValidateUserLogin @Username = @uname, @Password = @passwd, @Valid = @valid OUTPUT"; - //Creates a new command - using (SqlCommand com = new SqlCommand(query, con)) { - //For security reasons the values are added with this function - //this will avoid SQL Injections - com.Parameters.AddWithValue("@uname", uname); - com.Parameters.AddWithValue("@passwd", passwd); - com.Parameters.Add("@valid", SqlDbType.NVarChar, 250); - com.Parameters["@valid"].Direction = ParameterDirection.Output; - //Execute without a return value - com.ExecuteNonQuery(); - //The Return value from the SQL Stored Procedure will have the answer to life - return Convert.ToInt32(com.Parameters["@Valid"].Value); - } - //Catch any error - } catch (SqlException ex) { - return ex.Number; - } finally { - //Always close the connection - con.Close(); - } + using SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ServerDashboardDB"].ConnectionString); + try { + //Open the connection + con.Open(); + //SQL Query + string query = "EXEC ValidateUserLogin @Username = @uname, @Password = @passwd, @Valid = @valid OUTPUT"; + //Creates a new command + using SqlCommand com = new SqlCommand(query, con);//For security reasons the values are added with this function + //this will avoid SQL Injections + com.Parameters.AddWithValue("@uname", uname); + com.Parameters.AddWithValue("@passwd", passwd); + com.Parameters.Add("@valid", SqlDbType.NVarChar, 250); + com.Parameters["@valid"].Direction = ParameterDirection.Output; + //Execute query and return number of rows affected + com.ExecuteNonQuery(); + //Checks if there are any rows successful + //If the query returns 0 the query wasn't successful + //if its any number above 0 it was successful + return Convert.ToInt32(com.Parameters["@Valid"].Value) == 0 ? 1 : 0; + //Catch any error + } catch (SqlException ex) { + return ex.Number; + } finally { + //Always close the connection + con.Close(); } } + + public static DataTable GetUserData(string username) { + //Creates the database connection + using SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ServerDashboardDB"].ConnectionString); + try { + //Open the connection + con.Open(); + //SQL Query + const string query = "SELECT ID, Username, Email, RegistrationDate FROM UserData WHERE Username = @username"; + //Creates a new command + using SqlCommand com = new SqlCommand(query, con);//For security reasons the values are added with this function + //this will avoid SQL Injections + com.Parameters.AddWithValue("@username", username); + //Execute query and return number of rows affected + DataTable resultTable = new DataTable() { TableName = "Userdata" }; + using SqlDataAdapter sda = new SqlDataAdapter(com); + sda.Fill(resultTable); + return resultTable; + //Checks if there are any rows successful + //If the query returns 0 the query wasn't successful + //if its any number above 0 it was successful + //Catch any error + } catch (SqlException) { + return null; + } finally { + //Always close the connection + con.Close(); + } + } + + public static DataTable GetUserModuleData(int uid) { + //Creates the database connection + using SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ServerDashboardDB"].ConnectionString); + try { + //Open the connection + con.Open(); + //SQL Query + const string query = "SELECT Creator, CreationTime, ModuleName, MI.Image, ModuleData.ID FROM ModuleData LEFT JOIN ModuleIcon MI on ModuleData.ID = MI.Module WHERE UserID = @userID"; + //Creates a new command + using SqlCommand com = new SqlCommand(query, con);//For security reasons the values are added with this function + //this will avoid SQL Injections + com.Parameters.AddWithValue("@userID", uid); + //Execute query and return number of rows affected + DataTable resultTable = new DataTable(); + using SqlDataAdapter sda = new SqlDataAdapter(com); + sda.Fill(resultTable); + return resultTable; + //Checks if there are any rows successful + //If the query returns 0 the query wasn't successful + //if its any number above 0 it was successful + //Catch any error + } catch (SqlException) { + return null; + } finally { + //Always close the connection + con.Close(); + } + } + /// - /// Currently obscolete, would check the Username and Cookie + /// This function will fetch every server data for each module + /// This will need some optimization, for now we just asynchronously + /// fetch the server data for each module + /// + /// ModuleID to fetch the data from + /// + public static DataTable GetServerData(int mid) { + //Creates the database connection + using SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ServerDashboardDB"].ConnectionString); + try { + //Open the connection + con.Open(); + //SQL Query + const string query = "SELECT * FROM ServerData WHERE ModuleID = @mid"; + //Creates a new command + using SqlCommand com = new SqlCommand(query, con);//For security reasons the values are added with this function + //this will avoid SQL Injections + com.Parameters.AddWithValue("@mid", mid); + //Execute query and return number of rows affected + DataTable resultTable = new DataTable(); + using SqlDataAdapter sda = new SqlDataAdapter(com); + sda.Fill(resultTable); + return resultTable; + //Checks if there are any rows successful + //If the query returns 0 the query wasn't successful + //if its any number above 0 it was successful + //Catch any error + } catch (SqlException) { + return null; + } finally { + //Always close the connection + con.Close(); + } + } + + /// + /// Creates a new Module for the current user + /// + /// Server IP Address + /// Module name, default is Module + /// Server name, default is Server + /// Username of the current user + /// module icon as byte[] + /// port, default ist 22 + /// + public static int CreateNewModule(string ipAddress, string moduleName, string serverName, string username, byte[] moduleIcon, string port = "22") { + //Creates the database connection + using SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ServerDashboardDB"].ConnectionString); + try { + //Open the connection + con.Open(); + //SQL Query + const string query = "EXEC AddNewModuleToUser @UserName = @username, @DateTime = @time, @ModuleName = @moduleName, @ServerName = @serverName, @ModuleIcon = @moduleIcon, @IPAddress = @ipAddress, @Port = @port"; + //Creates a new command + using SqlCommand com = new SqlCommand(query, con); + //For security reasons the values are added with this function + //this will avoid SQL Injections + com.Parameters.AddWithValue("@username", username); + com.Parameters.AddWithValue("@time", DateTime.Now); + com.Parameters.AddWithValue("@moduleName", moduleName); + com.Parameters.AddWithValue("@serverName", serverName); + com.Parameters.Add("@moduleIcon", SqlDbType.VarBinary, -1).Value = moduleIcon; + if (moduleIcon == null) + com.Parameters["@moduleIcon"].Value = DBNull.Value; + //com.Parameters.AddWithValue("@moduleIcon", moduleIcon); + com.Parameters.AddWithValue("@ipAddress", ipAddress); + com.Parameters.AddWithValue("@port", port); + //Execute query and return number of rows affected + int sqlResponse = com.ExecuteNonQuery(); + //Checks if there are any rows successful + //If the query returns 0 the query wasn't successful + //if its any number above 0 it was successful + return sqlResponse == 0 ? 1 : 0; + //Catch any error + } catch (SqlException ex) { + return ex.Number; + } finally { + //Always close the connection + con.Close(); + } + } + + /// + /// Currently obsolete, would check the Username and Cookie /// /// Locally stored user cookie /// Locally stored username /// [0] is false, [1] is true, [2] connection error public static int CheckCookie(string cookie, string username) { //Creates the database connection - using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ServerDashboardDB"].ConnectionString)) { - try { - //Open the connection - con.Open(); - //SQL Query - string query = "EXEC CheckUserCookie @Cookie = @cookie, @UserName = @username, @Valid = @valid OUTPUT"; - //Creates a new command - using (SqlCommand com = new SqlCommand(query, con)) { - //For security reasons the values are added with this function - //this will avoid SQL Injections - com.Parameters.AddWithValue("@cookie", cookie); - com.Parameters.AddWithValue("@username", username); - com.Parameters.Add("@valid", SqlDbType.Bit); - com.Parameters["@valid"].Direction = ParameterDirection.Output; - //Execute without a return value - com.ExecuteNonQuery(); - //The Return value from the SQL Stored Procedure will have the answer to life - return Convert.ToInt32(com.Parameters["@Valid"].Value); - } - //Catch any error - } catch (SqlException ex) { - return ex.Number; - } finally { - //Always close the connection - con.Close(); - } + using SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ServerDashboardDB"].ConnectionString); + try { + //Open the connection + con.Open(); + //SQL Query + const string query = "((SELECT Cookie FROM UserData WHERE Username = @username) = @cookie)"; + //Creates a new command + using SqlCommand com = new SqlCommand(query, con); + //For security reasons the values are added with this function + //this will avoid SQL Injections + com.Parameters.AddWithValue("@cookie", cookie); + com.Parameters.AddWithValue("@username", username); + //Execute query and return number of rows affected + int sqlResponse = com.ExecuteNonQuery(); + //Checks if there are any rows successful + //If the query returns 0 the query wasn't successful + //if its any number above 0 it was successfull + return sqlResponse == 0 ? 1 : 0; + //Catch any error + } catch (SqlException ex) { + return ex.Number; + } finally { + //Always close the connection + con.Close(); } } + /// /// Deletes a the cookie from the given user /// /// User who doesnt deserve any delicious cookies :3 - public static void DeleteCookie(string username) { + public static int DeleteCookie(string username) { //Creates the database connection - using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ServerDashboardDB"].ConnectionString)) { - try { - //Open the connection - con.Open(); - //SQL Query - string query = "EXEC DeleteUserCookie @Username = @username, @ResponseMessage = @response OUTPUT"; - //Creates a new command - using (SqlCommand com = new SqlCommand(query, con)) { - //For security reasons the values are added with this function - //this will avoid SQL Injections - com.Parameters.AddWithValue("@username", username); - com.Parameters.Add("@response", SqlDbType.NVarChar, 250); - com.Parameters["@response"].Direction = ParameterDirection.Output; - //Execute without a return value - com.ExecuteNonQuery(); - } - //Catch any error, dont return them, why would you? - } catch { - } finally { - //Always close the connection - con.Close(); - } + using SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ServerDashboardDB"].ConnectionString); + try { + //Open the connection + con.Open(); + //SQL Query + const string query = "UPDATE UserData SET Cookie = null WHERE Username = @username"; + //Creates a new command + using SqlCommand com = new SqlCommand(query, con); + //For security reasons the values are added with this function + //this will avoid SQL Injections + com.Parameters.AddWithValue("@username", username); + //Execute query and return number of rows affected + int sqlResponse = com.ExecuteNonQuery(); + //Checks if there are any rows successful + //If the query returns 0 the query wasn't successful + //if its any number above 0 it was successful + return sqlResponse == 0 ? 1 : 0; + //Catch any error + } catch (SqlException ex) { + return ex.Number; + } finally { + //Always close the connection + con.Close(); } } + /// /// Adds a new Cookie to a user /// /// The delicious locally stored cookie /// The User who deserves a cookie :3 /// [0] is false, [1] is true, [2] connection error - public static int AddCookie(string cookie, string username) { + public static int AddCookie(string username, string cookie) { //Creates the database connection - using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ServerDashboardDB"].ConnectionString)) { - try { - //Open the connection - con.Open(); - //SQL Query - string query = "EXEC AddCookieToUser @Cookie = @cookie, @UserName = @username, @ResponseMessage = @response OUTPUT"; - //Creates a new command - using (SqlCommand com = new SqlCommand(query, con)) { - //For security reasons the values are added with this function - //this will avoid SQL Injections - com.Parameters.AddWithValue("@cookie", cookie); - com.Parameters.AddWithValue("@username", username); - com.Parameters.Add("@response", SqlDbType.NVarChar, 250); - com.Parameters["@response"].Direction = ParameterDirection.Output; - //Execute without a return value - com.ExecuteNonQuery(); - //The Return value from the SQL Stored Procedure will have the answer to life - return Convert.ToInt32(com.Parameters["@ResponseMessage"].Value); - } - //Catch any error - } catch (SqlException ex) { - return ex.Number; - } finally { - //Always close connection - con.Close(); - } + using SqlConnection con = + new SqlConnection(ConfigurationManager.ConnectionStrings["ServerDashboardDB"].ConnectionString); + try { + //Open the connection + con.Open(); + + //SQL Query + const string query = "UPDATE UserData SET Cookie = @cookie WHERE Username = @username"; + + //Creates a new command + using SqlCommand com = new SqlCommand(query, con); + + //For security reasons the values are added with this function + //this will avoid SQL Injections + com.Parameters.Add("@cookie", SqlDbType.NVarChar, -1).Value = cookie; + com.Parameters.AddWithValue("@username", username); + + //Execute query and return number of rows affected + int sqlResponse = com.ExecuteNonQuery(); + + //Checks if there are any rows successful + //If the query returns 0 the query wasn't successful + //if its any number above 0 it was successful + return sqlResponse == 0 ? 1 : 0; + + //Catch any error + } catch (SqlException ex) { + return ex.Number; + } finally { + //Always close the connection + con.Close(); } } - #endregion + + #endregion Public Methods } -} +} \ No newline at end of file diff --git a/Server Dashboard/Interfaces/IHavePassword.cs b/Server Dashboard/Interfaces/IHavePassword.cs index 3ceecd7..bd7689c 100644 --- a/Server Dashboard/Interfaces/IHavePassword.cs +++ b/Server Dashboard/Interfaces/IHavePassword.cs @@ -4,10 +4,11 @@ using System.Security; using System.Text; namespace Server_Dashboard { + /// /// Interface that makes a SecurePassword go one way /// public interface IHavePassword { SecureString SecurePassword { get; } } -} +} \ No newline at end of file diff --git a/Server Dashboard/Interfaces/IWindowHelper.cs b/Server Dashboard/Interfaces/IWindowHelper.cs index defc651..194e829 100644 --- a/Server Dashboard/Interfaces/IWindowHelper.cs +++ b/Server Dashboard/Interfaces/IWindowHelper.cs @@ -3,10 +3,11 @@ using System.Collections.Generic; using System.Text; namespace Server_Dashboard { + /// /// Interface to help close a window with a button /// - interface IWindowHelper { + internal interface IWindowHelper { Action Close { get; set; } } -} +} \ No newline at end of file diff --git a/Server Dashboard/LoginWindow.xaml b/Server Dashboard/LoginWindow.xaml index 6c6aeb0..e32092b 100644 --- a/Server Dashboard/LoginWindow.xaml +++ b/Server Dashboard/LoginWindow.xaml @@ -6,89 +6,99 @@ xmlns:i="http://schemas.microsoft.com/xaml/behaviors" xmlns:local="clr-namespace:Server_Dashboard" xmlns:loading="clr-namespace:Server_Dashboard.Controls" + xmlns:svgc="http://sharpvectors.codeplex.com/svgc/" x:Name="Login" mc:Ignorable="d" Title="Server Dashboard" Height="700" Width="500" WindowStyle="None" Background="Transparent" ResizeMode="CanResize" local:CloseProperty.Value="True"> - + - + - - - - - - - - - - + + + + + + + + + + - - - - - - + - - + + - - - + + - + - + - + - + - - + + - - + + + + + + + + + + - + @@ -97,49 +107,57 @@ - + - - + + - + + + + + + + + + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - - - + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +